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