1 /* 2 * Copyright 2006-2015, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 * Michael Lotz, mmlr@mlotz.ch 8 * Alexander von Gluck IV, kallisti5@unixzen.com 9 */ 10 11 12 #include "Ports.h" 13 14 #include <ddc.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include <Debug.h> 18 #include <KernelExport.h> 19 20 #include "accelerant.h" 21 #include "accelerant_protos.h" 22 #include "FlexibleDisplayInterface.h" 23 #include "intel_extreme.h" 24 25 #include <new> 26 27 28 #undef TRACE 29 #define TRACE_PORTS 30 #ifdef TRACE_PORTS 31 # define TRACE(x...) _sPrintf("intel_extreme: " x) 32 #else 33 # define TRACE(x...) 34 #endif 35 36 #define ERROR(x...) _sPrintf("intel_extreme: " x) 37 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) 38 39 40 static bool 41 wait_for_set(addr_t address, uint32 mask, uint32 timeout) 42 { 43 int interval = 50; 44 uint32 i = 0; 45 for(i = 0; i <= timeout; i += interval) { 46 spin(interval); 47 if ((read32(address) & mask) != 0) 48 return true; 49 } 50 return false; 51 } 52 53 54 static bool 55 wait_for_clear(addr_t address, uint32 mask, uint32 timeout) 56 { 57 int interval = 50; 58 uint32 i = 0; 59 for(i = 0; i <= timeout; i += interval) { 60 spin(interval); 61 if ((read32(address) & mask) == 0) 62 return true; 63 } 64 return false; 65 } 66 67 68 Port::Port(port_index index, const char* baseName) 69 : 70 fPipe(NULL), 71 fEDIDState(B_NO_INIT), 72 fPortIndex(index), 73 fPortName(NULL) 74 { 75 char portID[2]; 76 portID[0] = 'A' + index - INTEL_PORT_A; 77 portID[1] = 0; 78 79 char buffer[32]; 80 buffer[0] = 0; 81 82 strlcat(buffer, baseName, sizeof(buffer)); 83 strlcat(buffer, " ", sizeof(buffer)); 84 strlcat(buffer, portID, sizeof(buffer)); 85 fPortName = strdup(buffer); 86 } 87 88 89 Port::~Port() 90 { 91 free(fPortName); 92 } 93 94 95 bool 96 Port::HasEDID() 97 { 98 if (fEDIDState == B_NO_INIT) 99 GetEDID(NULL); 100 101 return fEDIDState == B_OK; 102 } 103 104 105 status_t 106 Port::SetPipe(Pipe* pipe) 107 { 108 CALLED(); 109 110 if (pipe == NULL) { 111 ERROR("%s: Invalid pipe provided!\n", __func__); 112 return B_ERROR; 113 } 114 115 uint32 portRegister = _PortRegister(); 116 if (portRegister == 0) { 117 ERROR("%s: Invalid PortRegister ((0x%" B_PRIx32 ") for %s\n", __func__, 118 portRegister, PortName()); 119 return B_ERROR; 120 } 121 122 // TODO: UnAssignPipe? This likely needs reworked a little 123 if (fPipe != NULL) { 124 ERROR("%s: Can't reassign display pipe (yet)\n", __func__); 125 return B_ERROR; 126 } 127 128 TRACE("%s: Assigning %s (0x%" B_PRIx32 ") to pipe %s\n", __func__, 129 PortName(), portRegister, (pipe->Index() == INTEL_PIPE_A) ? "A" : "B"); 130 131 uint32 portState = read32(portRegister); 132 133 if (gInfo->shared_info->pch_info == INTEL_PCH_CPT) { 134 portState &= PORT_TRANS_SEL_MASK; 135 if (pipe->Index() == INTEL_PIPE_A) 136 write32(portRegister, portState | PORT_TRANS_A_SEL_CPT); 137 else 138 write32(portRegister, portState | PORT_TRANS_B_SEL_CPT); 139 } else { 140 if (pipe->Index() == INTEL_PIPE_A) 141 write32(portRegister, portState & ~DISPLAY_MONITOR_PIPE_B); 142 else 143 write32(portRegister, portState | DISPLAY_MONITOR_PIPE_B); 144 } 145 146 fPipe = pipe; 147 148 if (fPipe == NULL) 149 return B_NO_MEMORY; 150 151 // Disable display pipe until modesetting enables it 152 if (fPipe->IsEnabled()) 153 fPipe->Enable(false); 154 155 read32(portRegister); 156 157 return B_OK; 158 } 159 160 161 status_t 162 Port::Power(bool enabled) 163 { 164 fPipe->Enable(enabled); 165 166 return B_OK; 167 } 168 169 170 status_t 171 Port::GetEDID(edid1_info* edid, bool forceRead) 172 { 173 CALLED(); 174 175 if (fEDIDState == B_NO_INIT || forceRead) { 176 TRACE("%s: trying to read EDID\n", PortName()); 177 178 addr_t ddcRegister = _DDCRegister(); 179 if (ddcRegister == 0) { 180 TRACE("%s: no DDC register found\n", PortName()); 181 fEDIDState = B_ERROR; 182 return fEDIDState; 183 } 184 185 TRACE("%s: using ddc @ 0x%" B_PRIxADDR "\n", PortName(), ddcRegister); 186 187 i2c_bus bus; 188 bus.cookie = (void*)ddcRegister; 189 bus.set_signals = &_SetI2CSignals; 190 bus.get_signals = &_GetI2CSignals; 191 ddc2_init_timing(&bus); 192 193 fEDIDState = ddc2_read_edid1(&bus, &fEDIDInfo, NULL, NULL); 194 195 if (fEDIDState == B_OK) { 196 TRACE("%s: found EDID information!\n", PortName()); 197 edid_dump(&fEDIDInfo); 198 } 199 } 200 201 if (fEDIDState != B_OK) { 202 TRACE("%s: no EDID information found.\n", PortName()); 203 return fEDIDState; 204 } 205 206 if (edid != NULL) 207 memcpy(edid, &fEDIDInfo, sizeof(edid1_info)); 208 209 return B_OK; 210 } 211 212 213 status_t 214 Port::GetPLLLimits(pll_limits& limits) 215 { 216 return B_ERROR; 217 } 218 219 220 status_t 221 Port::_GetI2CSignals(void* cookie, int* _clock, int* _data) 222 { 223 addr_t ioRegister = (addr_t)cookie; 224 uint32 value = read32(ioRegister); 225 226 *_clock = (value & I2C_CLOCK_VALUE_IN) != 0; 227 *_data = (value & I2C_DATA_VALUE_IN) != 0; 228 229 return B_OK; 230 } 231 232 233 status_t 234 Port::_SetI2CSignals(void* cookie, int clock, int data) 235 { 236 addr_t ioRegister = (addr_t)cookie; 237 uint32 value; 238 239 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_83x)) { 240 // on these chips, the reserved values are fixed 241 value = 0; 242 } else { 243 // on all others, we have to preserve them manually 244 value = read32(ioRegister) & I2C_RESERVED; 245 } 246 247 if (data != 0) 248 value |= I2C_DATA_DIRECTION_MASK; 249 else { 250 value |= I2C_DATA_DIRECTION_MASK | I2C_DATA_DIRECTION_OUT 251 | I2C_DATA_VALUE_MASK; 252 } 253 254 if (clock != 0) 255 value |= I2C_CLOCK_DIRECTION_MASK; 256 else { 257 value |= I2C_CLOCK_DIRECTION_MASK | I2C_CLOCK_DIRECTION_OUT 258 | I2C_CLOCK_VALUE_MASK; 259 } 260 261 write32(ioRegister, value); 262 read32(ioRegister); 263 // make sure the PCI bus has flushed the write 264 265 return B_OK; 266 } 267 268 269 // #pragma mark - Analog Port 270 271 272 AnalogPort::AnalogPort() 273 : 274 Port(INTEL_PORT_A, "Analog") 275 { 276 } 277 278 279 bool 280 AnalogPort::IsConnected() 281 { 282 TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), 283 _PortRegister()); 284 return HasEDID(); 285 } 286 287 288 addr_t 289 AnalogPort::_DDCRegister() 290 { 291 // always fixed 292 return INTEL_I2C_IO_A; 293 } 294 295 296 addr_t 297 AnalogPort::_PortRegister() 298 { 299 // always fixed 300 return INTEL_ANALOG_PORT; 301 } 302 303 304 status_t 305 AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) 306 { 307 TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width, 308 target->virtual_height); 309 310 if (fPipe == NULL) { 311 ERROR("%s: Setting display mode without assigned pipe!\n", __func__); 312 return B_ERROR; 313 } 314 315 // Train FDI if it exists 316 FDILink* link = fPipe->FDI(); 317 if (link != NULL) 318 link->Train(target); 319 320 pll_divisors divisors; 321 compute_pll_divisors(target, &divisors, false); 322 323 uint32 extraPLLFlags = 0; 324 if (gInfo->shared_info->device_type.Generation() >= 3) 325 extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL; 326 327 // Program general pipe config 328 fPipe->Configure(target); 329 330 // Program pipe PLL's 331 fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags); 332 333 write32(_PortRegister(), (read32(_PortRegister()) 334 & ~(DISPLAY_MONITOR_POLARITY_MASK | DISPLAY_MONITOR_VGA_POLARITY)) 335 | ((target->timing.flags & B_POSITIVE_HSYNC) != 0 336 ? DISPLAY_MONITOR_POSITIVE_HSYNC : 0) 337 | ((target->timing.flags & B_POSITIVE_VSYNC) != 0 338 ? DISPLAY_MONITOR_POSITIVE_VSYNC : 0)); 339 340 // Program target display mode 341 fPipe->ConfigureTimings(target); 342 343 // Set fCurrentMode to our set display mode 344 memcpy(&fCurrentMode, target, sizeof(display_mode)); 345 346 return B_OK; 347 } 348 349 350 // #pragma mark - LVDS Panel 351 352 353 LVDSPort::LVDSPort() 354 : 355 Port(INTEL_PORT_C, "LVDS") 356 { 357 // Always unlock LVDS port as soon as we start messing with it. 358 uint32 panelControl = INTEL_PANEL_CONTROL; 359 if (gInfo->shared_info->pch_info != INTEL_PCH_NONE) { 360 // FIXME writing there results in black screen on SandyBridge 361 return; 362 // panelControl = PCH_PANEL_CONTROL; 363 } 364 write32(panelControl, read32(panelControl) | PANEL_REGISTER_UNLOCK); 365 } 366 367 368 pipe_index 369 LVDSPort::PipePreference() 370 { 371 // TODO: Technically INTEL_PIPE_B is only required on < gen 4 372 // otherwise we can use INTEL_PIPE_ANY, however it seems to break 373 // modesetting atm. (likely due to a bug on our end) 374 //if (gInfo->shared_info->device_type.Generation() < 4) 375 // return INTEL_PIPE_B; 376 377 return INTEL_PIPE_B; 378 } 379 380 381 bool 382 LVDSPort::IsConnected() 383 { 384 TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), 385 _PortRegister()); 386 387 if (gInfo->shared_info->pch_info != INTEL_PCH_NONE) { 388 uint32 registerValue = read32(_PortRegister()); 389 // there's a detection bit we can use 390 if ((registerValue & PCH_LVDS_DETECTED) == 0) { 391 TRACE("LVDS: Not detected\n"); 392 return false; 393 } 394 // TODO: Skip if eDP support 395 } else if (gInfo->shared_info->device_type.Generation() <= 4) { 396 // Older generations don't have LVDS detection. If not mobile skip. 397 if (!gInfo->shared_info->device_type.IsMobile()) { 398 TRACE("LVDS: Skipping LVDS detection due to gen and not mobile\n"); 399 return false; 400 } 401 // If mobile, try to grab EDID 402 // Linux seems to look at lid status for LVDS port detection 403 // If we don't get EDID, we can use vbios native mode or vesa? 404 if (!HasEDID()) { 405 #if 0 406 if (gInfo->shared_info->got_vbt) { 407 // TODO: Fake EDID from vbios native mode? 408 // I feel like this would be more accurate 409 } else if... 410 #endif 411 if (gInfo->shared_info->has_vesa_edid_info) { 412 TRACE("LVDS: Using VESA edid info\n"); 413 memcpy(&fEDIDInfo, &gInfo->shared_info->vesa_edid_info, 414 sizeof(edid1_info)); 415 fEDIDState = B_OK; 416 // HasEDID now true 417 } else { 418 TRACE("LVDS: Couldn't find any valid EDID!\n"); 419 return false; 420 } 421 } 422 } 423 424 // Try getting EDID, as the LVDS port doesn't overlap with anything else, 425 // we don't run the risk of getting someone else's data. 426 return HasEDID(); 427 } 428 429 430 addr_t 431 LVDSPort::_DDCRegister() 432 { 433 // always fixed 434 return INTEL_I2C_IO_C; 435 } 436 437 438 addr_t 439 LVDSPort::_PortRegister() 440 { 441 // always fixed 442 return INTEL_DIGITAL_LVDS_PORT; 443 } 444 445 446 status_t 447 LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) 448 { 449 CALLED(); 450 if (target == NULL) { 451 ERROR("%s: Invalid target mode passed!\n", __func__); 452 return B_ERROR; 453 } 454 455 TRACE("%s: %s-%d %dx%d\n", __func__, PortName(), PortIndex(), 456 target->virtual_width, target->virtual_height); 457 458 if (fPipe == NULL) { 459 ERROR("%s: Setting display mode without assigned pipe!\n", __func__); 460 return B_ERROR; 461 } 462 463 addr_t panelControl = INTEL_PANEL_CONTROL; 464 addr_t panelStatus = INTEL_PANEL_STATUS; 465 if (gInfo->shared_info->pch_info != INTEL_PCH_NONE) { 466 panelControl = PCH_PANEL_CONTROL; 467 panelStatus = PCH_PANEL_STATUS; 468 } 469 470 // Power off Panel 471 write32(panelControl, read32(panelControl) & ~PANEL_CONTROL_POWER_TARGET_ON); 472 read32(panelControl); 473 474 if (!wait_for_clear(panelStatus, PANEL_STATUS_POWER_ON, 1000)) 475 ERROR("%s: %s didn't power off within 1000ms!\n", __func__, PortName()); 476 477 // Train FDI if it exists 478 FDILink* link = fPipe->FDI(); 479 if (link != NULL) 480 link->Train(target); 481 482 #if 0 483 // Disable PanelFitter for now 484 addr_t panelFitterControl = PCH_PANEL_FITTER_BASE_REGISTER 485 + PCH_PANEL_FITTER_CONTROL; 486 if (fPipe->Index() == INTEL_PIPE_B) 487 panelFitterControl += PCH_PANEL_FITTER_PIPE_OFFSET; 488 write32(panelFitterControl, (read32(panelFitterControl) & ~PANEL_FITTER_ENABLED)); 489 read32(panelFitterControl); 490 #endif 491 492 // For LVDS panels, we actually always set the native mode in hardware 493 // Then we use the panel fitter to scale the picture to that. 494 display_mode hardwareTarget; 495 bool needsScaling = false; 496 // Try to get the panel preferred screen mode from EDID info 497 498 if (gInfo->shared_info->got_vbt) { 499 // Set vbios hardware panel mode as base 500 memcpy(&hardwareTarget, &gInfo->shared_info->panel_mode, 501 sizeof(display_mode)); 502 hardwareTarget.space = target->space; 503 504 if ((hardwareTarget.virtual_width <= target->virtual_width 505 && hardwareTarget.virtual_height <= target->virtual_height 506 && hardwareTarget.space <= target->space) 507 || intel_propose_display_mode(&hardwareTarget, target, target)) { 508 hardwareTarget = *target; 509 } else 510 needsScaling = true; 511 512 TRACE("%s: hardware mode will actually be %dx%d (%s)\n", __func__, 513 hardwareTarget.virtual_width, hardwareTarget.virtual_height, 514 needsScaling ? "scaled" : "unscaled"); 515 } else { 516 // We don't have EDID data, try to set the requested mode directly 517 hardwareTarget = *target; 518 } 519 520 pll_divisors divisors; 521 if (needsScaling) 522 compute_pll_divisors(&hardwareTarget, &divisors, true); 523 else 524 compute_pll_divisors(target, &divisors, true); 525 526 uint32 lvds = read32(_PortRegister()) 527 | LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; 528 529 if (gInfo->shared_info->device_type.Generation() == 4) { 530 // LVDS_A3_POWER_UP == 24bpp 531 // otherwise, 18bpp 532 if ((lvds & LVDS_A3_POWER_MASK) != LVDS_A3_POWER_UP) 533 lvds |= LVDS_18BIT_DITHER; 534 } 535 536 // LVDS on PCH needs set before display enable 537 if (gInfo->shared_info->pch_info == INTEL_PCH_CPT) { 538 lvds &= PORT_TRANS_SEL_MASK; 539 if (fPipe->Index() == INTEL_PIPE_A) 540 lvds |= PORT_TRANS_A_SEL_CPT; 541 else 542 lvds |= PORT_TRANS_B_SEL_CPT; 543 } 544 545 // Set the B0-B3 data pairs corresponding to whether we're going to 546 // set the DPLLs for dual-channel mode or not. 547 if (divisors.p2 == 5 || divisors.p2 == 7) { 548 TRACE("LVDS: dual channel\n"); 549 lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; 550 } else { 551 TRACE("LVDS: single channel\n"); 552 lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); 553 } 554 555 // LVDS port control moves polarity bits because Intel hates you. 556 // Set LVDS sync polarity 557 lvds &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY); 558 559 // set on - polarity. 560 if ((target->timing.flags & B_POSITIVE_HSYNC) == 0) 561 lvds |= LVDS_HSYNC_POLARITY; 562 if ((target->timing.flags & B_POSITIVE_VSYNC) == 0) 563 lvds |= LVDS_VSYNC_POLARITY; 564 565 TRACE("%s: LVDS Write: 0x%" B_PRIx32 "\n", __func__, lvds); 566 write32(_PortRegister(), lvds); 567 read32(_PortRegister()); 568 569 uint32 extraPLLFlags = 0; 570 571 // DPLL mode LVDS for i915+ 572 if (gInfo->shared_info->device_type.Generation() >= 3) 573 extraPLLFlags |= DISPLAY_PLL_MODE_LVDS; 574 575 // Program general pipe config 576 fPipe->Configure(target); 577 578 // Program pipe PLL's (pixel_clock is *always* the hardware pixel clock) 579 fPipe->ConfigureClocks(divisors, hardwareTarget.timing.pixel_clock, 580 extraPLLFlags); 581 582 // Disable panel fitting, but enable 8 to 6-bit dithering 583 write32(INTEL_PANEL_FIT_CONTROL, 0x4); 584 // TODO: do not do this if the connected panel is 24-bit 585 // (I don't know how to detect that) 586 587 // Power on Panel 588 write32(panelControl, read32(panelControl) | PANEL_CONTROL_POWER_TARGET_ON); 589 read32(panelControl); 590 591 if (!wait_for_set(panelStatus, PANEL_STATUS_POWER_ON, 1000)) 592 ERROR("%s: %s didn't power on within 1000ms!\n", __func__, PortName()); 593 594 // Program target display mode 595 fPipe->ConfigureTimings(target); 596 597 #if 0 598 // update timing parameters 599 if (needsScaling) { 600 // TODO: Alternatively, it should be possible to use the panel 601 // fitter and scale the picture. 602 603 // TODO: Perform some sanity check, for example if the target is 604 // wider than the hardware mode we end up with negative borders and 605 // broken timings 606 uint32 borderWidth = hardwareTarget.timing.h_display 607 - target->timing.h_display; 608 609 uint32 syncWidth = hardwareTarget.timing.h_sync_end 610 - hardwareTarget.timing.h_sync_start; 611 612 uint32 syncCenter = target->timing.h_display 613 + (hardwareTarget.timing.h_total 614 - target->timing.h_display) / 2; 615 616 write32(INTEL_DISPLAY_B_HTOTAL, 617 ((uint32)(hardwareTarget.timing.h_total - 1) << 16) 618 | ((uint32)target->timing.h_display - 1)); 619 write32(INTEL_DISPLAY_B_HBLANK, 620 ((uint32)(hardwareTarget.timing.h_total - borderWidth / 2 - 1) 621 << 16) 622 | ((uint32)target->timing.h_display + borderWidth / 2 - 1)); 623 write32(INTEL_DISPLAY_B_HSYNC, 624 ((uint32)(syncCenter + syncWidth / 2 - 1) << 16) 625 | ((uint32)syncCenter - syncWidth / 2 - 1)); 626 627 uint32 borderHeight = hardwareTarget.timing.v_display 628 - target->timing.v_display; 629 630 uint32 syncHeight = hardwareTarget.timing.v_sync_end 631 - hardwareTarget.timing.v_sync_start; 632 633 syncCenter = target->timing.v_display 634 + (hardwareTarget.timing.v_total 635 - target->timing.v_display) / 2; 636 637 write32(INTEL_DISPLAY_B_VTOTAL, 638 ((uint32)(hardwareTarget.timing.v_total - 1) << 16) 639 | ((uint32)target->timing.v_display - 1)); 640 write32(INTEL_DISPLAY_B_VBLANK, 641 ((uint32)(hardwareTarget.timing.v_total - borderHeight / 2 - 1) 642 << 16) 643 | ((uint32)target->timing.v_display 644 + borderHeight / 2 - 1)); 645 write32(INTEL_DISPLAY_B_VSYNC, 646 ((uint32)(syncCenter + syncHeight / 2 - 1) << 16) 647 | ((uint32)syncCenter - syncHeight / 2 - 1)); 648 649 // This is useful for debugging: it sets the border to red, so you 650 // can see what is border and what is porch (black area around the 651 // sync) 652 // write32(0x61020, 0x00FF0000); 653 } else { 654 write32(INTEL_DISPLAY_B_HTOTAL, 655 ((uint32)(target->timing.h_total - 1) << 16) 656 | ((uint32)target->timing.h_display - 1)); 657 write32(INTEL_DISPLAY_B_HBLANK, 658 ((uint32)(target->timing.h_total - 1) << 16) 659 | ((uint32)target->timing.h_display - 1)); 660 write32(INTEL_DISPLAY_B_HSYNC, 661 ((uint32)(target->timing.h_sync_end - 1) << 16) 662 | ((uint32)target->timing.h_sync_start - 1)); 663 664 write32(INTEL_DISPLAY_B_VTOTAL, 665 ((uint32)(target->timing.v_total - 1) << 16) 666 | ((uint32)target->timing.v_display - 1)); 667 write32(INTEL_DISPLAY_B_VBLANK, 668 ((uint32)(target->timing.v_total - 1) << 16) 669 | ((uint32)target->timing.v_display - 1)); 670 write32(INTEL_DISPLAY_B_VSYNC, ( 671 (uint32)(target->timing.v_sync_end - 1) << 16) 672 | ((uint32)target->timing.v_sync_start - 1)); 673 } 674 #endif 675 676 // Set fCurrentMode to our set display mode 677 memcpy(&fCurrentMode, target, sizeof(display_mode)); 678 679 return B_OK; 680 } 681 682 683 // #pragma mark - DVI/SDVO/generic 684 685 686 DigitalPort::DigitalPort(port_index index, const char* baseName) 687 : 688 Port(index, baseName) 689 { 690 } 691 692 693 bool 694 DigitalPort::IsConnected() 695 { 696 TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), 697 _PortRegister()); 698 699 // As this port overlaps with pretty much everything, this must be called 700 // after having ruled out all other port types. 701 return HasEDID(); 702 } 703 704 705 addr_t 706 DigitalPort::_DDCRegister() 707 { 708 //TODO: IS BROXTON, B = B, C = C, D = NIL 709 switch (PortIndex()) { 710 case INTEL_PORT_B: 711 return INTEL_I2C_IO_E; 712 case INTEL_PORT_C: 713 return INTEL_I2C_IO_D; 714 case INTEL_PORT_D: 715 return INTEL_I2C_IO_F; 716 default: 717 return 0; 718 } 719 720 return 0; 721 } 722 723 724 addr_t 725 DigitalPort::_PortRegister() 726 { 727 switch (PortIndex()) { 728 case INTEL_PORT_A: 729 return INTEL_DIGITAL_PORT_A; 730 case INTEL_PORT_B: 731 return INTEL_DIGITAL_PORT_B; 732 case INTEL_PORT_C: 733 return INTEL_DIGITAL_PORT_C; 734 default: 735 return 0; 736 } 737 return 0; 738 } 739 740 741 status_t 742 DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode) 743 { 744 TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width, 745 target->virtual_height); 746 747 if (fPipe == NULL) { 748 ERROR("%s: Setting display mode without assigned pipe!\n", __func__); 749 return B_ERROR; 750 } 751 752 // Train FDI if it exists 753 FDILink* link = fPipe->FDI(); 754 if (link != NULL) 755 link->Train(target); 756 757 pll_divisors divisors; 758 compute_pll_divisors(target, &divisors, false); 759 760 uint32 extraPLLFlags = 0; 761 if (gInfo->shared_info->device_type.Generation() >= 3) 762 extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL; 763 764 // Program general pipe config 765 fPipe->Configure(target); 766 767 // Program pipe PLL's 768 fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags); 769 770 // Program target display mode 771 fPipe->ConfigureTimings(target); 772 773 // Set fCurrentMode to our set display mode 774 memcpy(&fCurrentMode, target, sizeof(display_mode)); 775 776 return B_OK; 777 } 778 779 780 // #pragma mark - LVDS Panel 781 // #pragma mark - HDMI 782 783 784 HDMIPort::HDMIPort(port_index index) 785 : 786 DigitalPort(index, "HDMI") 787 { 788 } 789 790 791 bool 792 HDMIPort::IsConnected() 793 { 794 if (!gInfo->shared_info->device_type.SupportsHDMI()) 795 return false; 796 797 addr_t portRegister = _PortRegister(); 798 TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), 799 portRegister); 800 801 if (portRegister == 0) 802 return false; 803 804 bool hasPCH = (gInfo->shared_info->pch_info != INTEL_PCH_NONE); 805 if (!hasPCH && PortIndex() == INTEL_PORT_C) { 806 // there's no detection bit on this port 807 } else if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0) 808 return false; 809 810 return HasEDID(); 811 } 812 813 814 addr_t 815 HDMIPort::_PortRegister() 816 { 817 // on PCH there's an additional port sandwiched in 818 bool hasPCH = (gInfo->shared_info->pch_info != INTEL_PCH_NONE); 819 bool fourthGen = gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV); 820 821 switch (PortIndex()) { 822 case INTEL_PORT_B: 823 if (fourthGen) 824 return GEN4_HDMI_PORT_B; 825 return hasPCH ? PCH_HDMI_PORT_B : INTEL_HDMI_PORT_B; 826 case INTEL_PORT_C: 827 if (fourthGen) 828 return GEN4_HDMI_PORT_C; 829 return hasPCH ? PCH_HDMI_PORT_C : INTEL_HDMI_PORT_C; 830 case INTEL_PORT_D: 831 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) 832 return CHV_HDMI_PORT_D; 833 return hasPCH ? PCH_HDMI_PORT_D : 0; 834 default: 835 return 0; 836 } 837 838 return 0; 839 } 840 841 842 // #pragma mark - DisplayPort 843 844 845 DisplayPort::DisplayPort(port_index index, const char* baseName) 846 : 847 Port(index, baseName) 848 { 849 } 850 851 852 bool 853 DisplayPort::IsConnected() 854 { 855 addr_t portRegister = _PortRegister(); 856 857 TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), 858 portRegister); 859 860 if (portRegister == 0) 861 return false; 862 863 if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0) { 864 TRACE("%s: %s link not detected\n", __func__, PortName()); 865 return false; 866 } 867 868 return HasEDID(); 869 } 870 871 872 addr_t 873 DisplayPort::_DDCRegister() 874 { 875 // TODO: Do VLV + CHV use the VLV_DP_AUX_CTL_B + VLV_DP_AUX_CTL_C? 876 switch (PortIndex()) { 877 case INTEL_PORT_A: 878 return INTEL_DP_AUX_CTL_A; 879 case INTEL_PORT_B: 880 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) 881 return VLV_DP_AUX_CTL_B; 882 return INTEL_DP_AUX_CTL_B; 883 case INTEL_PORT_C: 884 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) 885 return VLV_DP_AUX_CTL_C; 886 return INTEL_DP_AUX_CTL_C; 887 case INTEL_PORT_D: 888 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) 889 return CHV_DP_AUX_CTL_D; 890 else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) 891 return 0; 892 return INTEL_DP_AUX_CTL_D; 893 default: 894 return 0; 895 } 896 897 return 0; 898 } 899 900 901 addr_t 902 DisplayPort::_PortRegister() 903 { 904 // There are 6000 lines of intel linux code probing DP registers 905 // to properly detect DP vs eDP to then in-turn properly figure out 906 // what is DP and what is HDMI. It only takes 3 lines to 907 // ignore DisplayPort on ValleyView / CherryView 908 909 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV) 910 || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) { 911 ERROR("TODO: DisplayPort on ValleyView / CherryView"); 912 return 0; 913 } 914 915 // Intel, are humans even involved anymore? 916 // This is a lot more complex than this code makes it look. (see defines) 917 // INTEL_DISPLAY_PORT_X moves around a lot based on PCH 918 // except on ValleyView and CherryView. 919 switch (PortIndex()) { 920 case INTEL_PORT_A: 921 return INTEL_DISPLAY_PORT_A; 922 case INTEL_PORT_B: 923 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) 924 return VLV_DISPLAY_PORT_B; 925 return INTEL_DISPLAY_PORT_B; 926 case INTEL_PORT_C: 927 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) 928 return VLV_DISPLAY_PORT_C; 929 return INTEL_DISPLAY_PORT_C; 930 case INTEL_PORT_D: 931 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) 932 return CHV_DISPLAY_PORT_D; 933 else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) 934 return 0; 935 return INTEL_DISPLAY_PORT_D; 936 default: 937 return 0; 938 } 939 940 return 0; 941 } 942 943 944 status_t 945 DisplayPort::SetDisplayMode(display_mode* target, uint32 colorMode) 946 { 947 TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width, 948 target->virtual_height); 949 950 ERROR("TODO: DisplayPort\n"); 951 return B_ERROR; 952 } 953 954 955 // #pragma mark - Embedded DisplayPort 956 957 958 EmbeddedDisplayPort::EmbeddedDisplayPort() 959 : 960 DisplayPort(INTEL_PORT_A, "Embedded DisplayPort") 961 { 962 } 963 964 965 bool 966 EmbeddedDisplayPort::IsConnected() 967 { 968 addr_t portRegister = _PortRegister(); 969 970 TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), 971 portRegister); 972 973 if (!gInfo->shared_info->device_type.IsMobile()) { 974 TRACE("%s: skipping eDP on non-mobile GPU\n", __func__); 975 return false; 976 } 977 978 if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0) { 979 TRACE("%s: %s link not detected\n", __func__, PortName()); 980 return false; 981 } 982 983 HasEDID(); 984 985 // If eDP has EDID, awesome. We use it. 986 // No EDID? The modesetting code falls back to VBIOS panel_mode 987 return true; 988 } 989 990 991 // #pragma mark - Digital Display Port 992 993 994 DigitalDisplayInterface::DigitalDisplayInterface(port_index index, 995 const char* baseName) 996 : 997 Port(index, baseName) 998 { 999 // As of Haswell, Intel decided to change eDP ports to a "DDI" bus... 1000 // on a dare because the hardware engineers were drunk one night. 1001 } 1002 1003 1004 addr_t 1005 DigitalDisplayInterface::_PortRegister() 1006 { 1007 // TODO: Linux does a DDI_BUF_CTL(INTEL_PORT_A) which is cleaner 1008 // (but we have to ensure the offsets + region base is correct) 1009 switch (PortIndex()) { 1010 case INTEL_PORT_A: 1011 return DDI_BUF_CTL_A; 1012 case INTEL_PORT_B: 1013 return DDI_BUF_CTL_B; 1014 case INTEL_PORT_C: 1015 return DDI_BUF_CTL_C; 1016 case INTEL_PORT_D: 1017 return DDI_BUF_CTL_D; 1018 case INTEL_PORT_E: 1019 return DDI_BUF_CTL_E; 1020 default: 1021 return 0; 1022 } 1023 return 0; 1024 } 1025 1026 1027 addr_t 1028 DigitalDisplayInterface::_DDCRegister() 1029 { 1030 // TODO: No idea, does DDI have DDC? 1031 return 0; 1032 } 1033 1034 1035 status_t 1036 DigitalDisplayInterface::Power(bool enabled) 1037 { 1038 TRACE("%s: %s DDI enabled: %s\n", __func__, PortName(), 1039 enabled ? "true" : "false"); 1040 1041 fPipe->Enable(enabled); 1042 1043 addr_t portRegister = _PortRegister(); 1044 uint32 state = read32(portRegister); 1045 write32(portRegister, 1046 enabled ? (state | DDI_BUF_CTL_ENABLE) : (state & ~DDI_BUF_CTL_ENABLE)); 1047 read32(portRegister); 1048 1049 return B_OK; 1050 } 1051 1052 1053 bool 1054 DigitalDisplayInterface::IsConnected() 1055 { 1056 addr_t portRegister = _PortRegister(); 1057 1058 TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), 1059 portRegister); 1060 1061 if (portRegister == 0) 1062 return false; 1063 1064 if ((read32(portRegister) & DDI_INIT_DISPLAY_DETECTED) == 0) { 1065 TRACE("%s: %s link not detected\n", __func__, PortName()); 1066 return false; 1067 } 1068 1069 // Probe a little port info. 1070 if ((read32(DDI_BUF_CTL_A) & DDI_A_4_LANES) != 0) { 1071 switch (PortIndex()) { 1072 case INTEL_PORT_A: 1073 fMaxLanes = 4; 1074 break; 1075 case INTEL_PORT_E: 1076 fMaxLanes = 0; 1077 break; 1078 default: 1079 fMaxLanes = 4; 1080 break; 1081 } 1082 } else { 1083 switch (PortIndex()) { 1084 case INTEL_PORT_A: 1085 fMaxLanes = 2; 1086 break; 1087 case INTEL_PORT_E: 1088 fMaxLanes = 2; 1089 break; 1090 default: 1091 fMaxLanes = 4; 1092 break; 1093 } 1094 } 1095 1096 TRACE("%s: %s Maximum Lanes: %" B_PRId8 "\n", __func__, 1097 PortName(), fMaxLanes); 1098 1099 HasEDID(); 1100 1101 return true; 1102 } 1103 1104 1105 status_t 1106 DigitalDisplayInterface::SetDisplayMode(display_mode* target, uint32 colorMode) 1107 { 1108 TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width, 1109 target->virtual_height); 1110 1111 if (fPipe == NULL) { 1112 ERROR("%s: Setting display mode without assigned pipe!\n", __func__); 1113 return B_ERROR; 1114 } 1115 1116 // Train FDI if it exists 1117 FDILink* link = fPipe->FDI(); 1118 if (link != NULL) 1119 link->Train(target); 1120 1121 pll_divisors divisors; 1122 compute_pll_divisors(target, &divisors, false); 1123 1124 uint32 extraPLLFlags = 0; 1125 if (gInfo->shared_info->device_type.Generation() >= 3) 1126 extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL; 1127 1128 // Program general pipe config 1129 fPipe->Configure(target); 1130 1131 // Program pipe PLL's 1132 fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags); 1133 1134 // Program target display mode 1135 fPipe->ConfigureTimings(target); 1136 1137 // Set fCurrentMode to our set display mode 1138 memcpy(&fCurrentMode, target, sizeof(display_mode)); 1139 1140 return B_OK; 1141 } 1142