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 #include "PanelFitter.h" 25 26 #include <new> 27 28 29 #undef TRACE 30 #define TRACE_PORTS 31 #ifdef TRACE_PORTS 32 # define TRACE(x...) _sPrintf("intel_extreme: " x) 33 #else 34 # define TRACE(x...) 35 #endif 36 37 #define ERROR(x...) _sPrintf("intel_extreme: " x) 38 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) 39 40 41 static bool 42 wait_for_set(addr_t address, uint32 mask, uint32 timeout) 43 { 44 int interval = 50; 45 uint32 i = 0; 46 for(i = 0; i <= timeout; i += interval) { 47 spin(interval); 48 if ((read32(address) & mask) != 0) 49 return true; 50 } 51 return false; 52 } 53 54 55 static bool 56 wait_for_clear(addr_t address, uint32 mask, uint32 timeout) 57 { 58 int interval = 50; 59 uint32 i = 0; 60 for(i = 0; i <= timeout; i += interval) { 61 spin(interval); 62 if ((read32(address) & mask) == 0) 63 return true; 64 } 65 return false; 66 } 67 68 69 Port::Port(port_index index, const char* baseName) 70 : 71 fPipe(NULL), 72 fEDIDState(B_NO_INIT), 73 fPortIndex(index), 74 fPortName(NULL) 75 { 76 char portID[2]; 77 portID[0] = 'A' + index - INTEL_PORT_A; 78 portID[1] = 0; 79 80 char buffer[32]; 81 buffer[0] = 0; 82 83 strlcat(buffer, baseName, sizeof(buffer)); 84 strlcat(buffer, " ", sizeof(buffer)); 85 strlcat(buffer, portID, sizeof(buffer)); 86 fPortName = strdup(buffer); 87 } 88 89 90 Port::~Port() 91 { 92 free(fPortName); 93 } 94 95 96 bool 97 Port::HasEDID() 98 { 99 if (fEDIDState == B_NO_INIT) 100 GetEDID(NULL); 101 102 return fEDIDState == B_OK; 103 } 104 105 106 status_t 107 Port::SetPipe(Pipe* pipe) 108 { 109 CALLED(); 110 111 if (pipe == NULL) { 112 ERROR("%s: Invalid pipe provided!\n", __func__); 113 return B_ERROR; 114 } 115 116 uint32 portRegister = _PortRegister(); 117 if (portRegister == 0) { 118 ERROR("%s: Invalid PortRegister ((0x%" B_PRIx32 ") for %s\n", __func__, 119 portRegister, PortName()); 120 return B_ERROR; 121 } 122 123 // TODO: UnAssignPipe? This likely needs reworked a little 124 if (fPipe != NULL) { 125 ERROR("%s: Can't reassign display pipe (yet)\n", __func__); 126 return B_ERROR; 127 } 128 129 TRACE("%s: Assigning %s (0x%" B_PRIx32 ") to pipe %s\n", __func__, 130 PortName(), portRegister, (pipe->Index() == INTEL_PIPE_A) ? "A" : "B"); 131 132 uint32 portState = read32(portRegister); 133 134 // FIXME is the use of PORT_TRANS_* constants correct for Sandy Bridge / 135 // Cougar Point? Or is it only for Ivy Bridge / Panther point onwards? 136 if (gInfo->shared_info->pch_info == INTEL_PCH_CPT) { 137 portState &= ~PORT_TRANS_SEL_MASK; 138 if (pipe->Index() == INTEL_PIPE_A) 139 write32(portRegister, portState | PORT_TRANS_A_SEL_CPT); 140 else 141 write32(portRegister, portState | PORT_TRANS_B_SEL_CPT); 142 } else { 143 if (pipe->Index() == INTEL_PIPE_A) 144 write32(portRegister, portState & ~DISPLAY_MONITOR_PIPE_B); 145 else 146 write32(portRegister, portState | DISPLAY_MONITOR_PIPE_B); 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 if (fPipe == NULL) { 167 ERROR("%s: Setting power mode without assigned pipe!\n", __func__); 168 return B_ERROR; 169 } 170 171 fPipe->Enable(enabled); 172 173 return B_OK; 174 } 175 176 177 status_t 178 Port::GetEDID(edid1_info* edid, bool forceRead) 179 { 180 CALLED(); 181 182 if (fEDIDState == B_NO_INIT || forceRead) { 183 TRACE("%s: trying to read EDID\n", PortName()); 184 185 addr_t ddcRegister = _DDCRegister(); 186 if (ddcRegister == 0) { 187 TRACE("%s: no DDC register found\n", PortName()); 188 fEDIDState = B_ERROR; 189 return fEDIDState; 190 } 191 192 TRACE("%s: using ddc @ 0x%" B_PRIxADDR "\n", PortName(), ddcRegister); 193 194 i2c_bus bus; 195 bus.cookie = (void*)ddcRegister; 196 bus.set_signals = &_SetI2CSignals; 197 bus.get_signals = &_GetI2CSignals; 198 ddc2_init_timing(&bus); 199 200 fEDIDState = ddc2_read_edid1(&bus, &fEDIDInfo, NULL, NULL); 201 202 if (fEDIDState == B_OK) { 203 TRACE("%s: found EDID information!\n", PortName()); 204 edid_dump(&fEDIDInfo); 205 } 206 } 207 208 if (fEDIDState != B_OK) { 209 TRACE("%s: no EDID information found.\n", PortName()); 210 return fEDIDState; 211 } 212 213 if (edid != NULL) 214 memcpy(edid, &fEDIDInfo, sizeof(edid1_info)); 215 216 return B_OK; 217 } 218 219 220 status_t 221 Port::GetPLLLimits(pll_limits& limits) 222 { 223 return B_ERROR; 224 } 225 226 227 pipe_index 228 Port::PipePreference() 229 { 230 CALLED(); 231 // Ideally we could just return INTEL_PIPE_ANY for all devices by default, but 232 // this doesn't quite work yet. We need to use the BIOS presetup pipes for now. 233 if (gInfo->shared_info->device_type.Generation() < 4) 234 return INTEL_PIPE_ANY; 235 236 // Notes: 237 // - The BIOSes seen sofar do not use PIPE C by default. 238 // - The BIOSes seen sofar program transcoder A to PIPE A, etc. 239 // - Later devices add a pipe C alongside the added transcoder C. 240 241 // FIXME How's this setup in newer gens? Currently return INTEL_PIPE_ANY there.. 242 if ((gInfo->shared_info->device_type.Generation() <= 7) && 243 (!gInfo->shared_info->device_type.HasDDI())) { 244 uint32 portState = read32(_PortRegister()); 245 if (gInfo->shared_info->pch_info == INTEL_PCH_CPT) { 246 portState &= PORT_TRANS_SEL_MASK; 247 if (portState == PORT_TRANS_B_SEL_CPT) 248 return INTEL_PIPE_B; 249 else 250 return INTEL_PIPE_A; 251 } else { 252 if (portState & DISPLAY_MONITOR_PIPE_B) 253 return INTEL_PIPE_B; 254 else 255 return INTEL_PIPE_A; 256 } 257 } 258 259 if (gInfo->shared_info->device_type.HasDDI()) { 260 //fixme implement detection via PIPE_DDI_FUNC_CTL_x scan.. 261 } 262 263 return INTEL_PIPE_ANY; 264 } 265 266 267 status_t 268 Port::_GetI2CSignals(void* cookie, int* _clock, int* _data) 269 { 270 addr_t ioRegister = (addr_t)cookie; 271 uint32 value = read32(ioRegister); 272 273 *_clock = (value & I2C_CLOCK_VALUE_IN) != 0; 274 *_data = (value & I2C_DATA_VALUE_IN) != 0; 275 276 return B_OK; 277 } 278 279 280 status_t 281 Port::_SetI2CSignals(void* cookie, int clock, int data) 282 { 283 addr_t ioRegister = (addr_t)cookie; 284 uint32 value; 285 286 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_83x)) { 287 // on these chips, the reserved values are fixed 288 value = 0; 289 } else { 290 // on all others, we have to preserve them manually 291 value = read32(ioRegister) & I2C_RESERVED; 292 } 293 294 if (data != 0) 295 value |= I2C_DATA_DIRECTION_MASK; 296 else { 297 value |= I2C_DATA_DIRECTION_MASK | I2C_DATA_DIRECTION_OUT 298 | I2C_DATA_VALUE_MASK; 299 } 300 301 if (clock != 0) 302 value |= I2C_CLOCK_DIRECTION_MASK; 303 else { 304 value |= I2C_CLOCK_DIRECTION_MASK | I2C_CLOCK_DIRECTION_OUT 305 | I2C_CLOCK_VALUE_MASK; 306 } 307 308 write32(ioRegister, value); 309 read32(ioRegister); 310 // make sure the PCI bus has flushed the write 311 312 return B_OK; 313 } 314 315 316 // #pragma mark - Analog Port 317 318 319 AnalogPort::AnalogPort() 320 : 321 Port(INTEL_PORT_A, "Analog") 322 { 323 } 324 325 326 bool 327 AnalogPort::IsConnected() 328 { 329 TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), 330 _PortRegister()); 331 return HasEDID(); 332 } 333 334 335 addr_t 336 AnalogPort::_DDCRegister() 337 { 338 // always fixed 339 return INTEL_I2C_IO_A; 340 } 341 342 343 addr_t 344 AnalogPort::_PortRegister() 345 { 346 // always fixed 347 return INTEL_ANALOG_PORT; 348 } 349 350 351 status_t 352 AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) 353 { 354 CALLED(); 355 TRACE("%s: %s %dx%d\n", __func__, PortName(), target->timing.h_display, 356 target->timing.v_display); 357 358 if (fPipe == NULL) { 359 ERROR("%s: Setting display mode without assigned pipe!\n", __func__); 360 return B_ERROR; 361 } 362 363 // Setup PanelFitter and Train FDI if it exists 364 PanelFitter* fitter = fPipe->PFT(); 365 if (fitter != NULL) 366 fitter->Enable(*target); 367 FDILink* link = fPipe->FDI(); 368 if (link != NULL) 369 link->Train(target); 370 371 pll_divisors divisors; 372 compute_pll_divisors(target, &divisors, false); 373 374 uint32 extraPLLFlags = 0; 375 if (gInfo->shared_info->device_type.Generation() >= 3) 376 extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL; 377 378 // Program general pipe config 379 fPipe->Configure(target); 380 381 // Program pipe PLL's 382 fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags); 383 384 write32(_PortRegister(), (read32(_PortRegister()) 385 & ~(DISPLAY_MONITOR_POLARITY_MASK | DISPLAY_MONITOR_VGA_POLARITY)) 386 | ((target->timing.flags & B_POSITIVE_HSYNC) != 0 387 ? DISPLAY_MONITOR_POSITIVE_HSYNC : 0) 388 | ((target->timing.flags & B_POSITIVE_VSYNC) != 0 389 ? DISPLAY_MONITOR_POSITIVE_VSYNC : 0)); 390 391 // Program target display mode 392 fPipe->ConfigureTimings(target); 393 394 // Set fCurrentMode to our set display mode 395 memcpy(&fCurrentMode, target, sizeof(display_mode)); 396 397 return B_OK; 398 } 399 400 401 // #pragma mark - LVDS Panel 402 403 404 LVDSPort::LVDSPort() 405 : 406 Port(INTEL_PORT_C, "LVDS") 407 { 408 // Always unlock LVDS port as soon as we start messing with it. 409 uint32 panelControl = INTEL_PANEL_CONTROL; 410 if (gInfo->shared_info->pch_info != INTEL_PCH_NONE) { 411 // FIXME writing there results in black screen on SandyBridge 412 return; 413 // panelControl = PCH_PANEL_CONTROL; 414 } 415 write32(panelControl, read32(panelControl) | PANEL_REGISTER_UNLOCK); 416 } 417 418 419 pipe_index 420 LVDSPort::PipePreference() 421 { 422 CALLED(); 423 // Older devices have hardcoded pipe/port mappings, so just use that 424 if (gInfo->shared_info->device_type.Generation() < 4) 425 return INTEL_PIPE_B; 426 427 // Ideally we could just return INTEL_PIPE_ANY for the newer devices, but 428 // this doesn't quite work yet. 429 430 // On SandyBridge and later, there is a transcoder C. On SandyBridge at least 431 // that can't be used by the LVDS port (but A and B would be fine). 432 // On Ibex Point, SandyBridge and IvyBridge (tested) changing pipes does not 433 // work yet. 434 // Notes: 435 // - Switching Pipes only works reliably when a 'full modeswitch' is executed 436 // (FDI training) so we have to reuse the BIOS preset setup always for now. 437 // - The BIOSes seen sofar do not use PIPE C by default. 438 // - The BIOSes seen sofar program transcoder A to PIPE A, etc. 439 // - Later devices add a pipe C alongside the added transcoder C. 440 441 // FIXME How's this setup in newer gens? Currently return Pipe B fixed there.. 442 if (gInfo->shared_info->device_type.Generation() <= 7) { 443 uint32 portState = read32(_PortRegister()); 444 if (gInfo->shared_info->pch_info == INTEL_PCH_CPT) { 445 portState &= PORT_TRANS_SEL_MASK; 446 if (portState == PORT_TRANS_B_SEL_CPT) 447 return INTEL_PIPE_B; 448 else 449 return INTEL_PIPE_A; 450 } else { 451 if (portState & DISPLAY_MONITOR_PIPE_B) 452 return INTEL_PIPE_B; 453 else 454 return INTEL_PIPE_A; 455 } 456 } 457 458 return INTEL_PIPE_B; 459 } 460 461 462 bool 463 LVDSPort::IsConnected() 464 { 465 TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), 466 _PortRegister()); 467 468 if (gInfo->shared_info->pch_info != INTEL_PCH_NONE) { 469 uint32 registerValue = read32(_PortRegister()); 470 // there's a detection bit we can use 471 if ((registerValue & PCH_LVDS_DETECTED) == 0) { 472 TRACE("LVDS: Not detected\n"); 473 return false; 474 } 475 // TODO: Skip if eDP support 476 } else if (gInfo->shared_info->device_type.Generation() <= 4) { 477 // Older generations don't have LVDS detection. If not mobile skip. 478 if (!gInfo->shared_info->device_type.IsMobile()) { 479 TRACE("LVDS: Skipping LVDS detection due to gen and not mobile\n"); 480 return false; 481 } 482 // If mobile, try to grab EDID 483 // Linux seems to look at lid status for LVDS port detection 484 // If we don't get EDID, we can use vbios native mode or vesa? 485 if (!HasEDID()) { 486 if (gInfo->shared_info->has_vesa_edid_info) { 487 TRACE("LVDS: Using VESA edid info\n"); 488 memcpy(&fEDIDInfo, &gInfo->shared_info->vesa_edid_info, 489 sizeof(edid1_info)); 490 fEDIDState = B_OK; 491 // HasEDID now true 492 } else if (gInfo->shared_info->got_vbt) { 493 TRACE("LVDS: No EDID, but force enabled as we have a VBT\n"); 494 return true; 495 } else { 496 TRACE("LVDS: Couldn't find any valid EDID!\n"); 497 return false; 498 } 499 } 500 } 501 502 // Try getting EDID, as the LVDS port doesn't overlap with anything else, 503 // we don't run the risk of getting someone else's data. 504 return HasEDID(); 505 } 506 507 508 addr_t 509 LVDSPort::_DDCRegister() 510 { 511 // always fixed 512 return INTEL_I2C_IO_C; 513 } 514 515 516 addr_t 517 LVDSPort::_PortRegister() 518 { 519 // always fixed 520 return INTEL_DIGITAL_LVDS_PORT; 521 } 522 523 524 status_t 525 LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) 526 { 527 CALLED(); 528 if (target == NULL) { 529 ERROR("%s: Invalid target mode passed!\n", __func__); 530 return B_ERROR; 531 } 532 533 TRACE("%s: %s-%d %dx%d\n", __func__, PortName(), PortIndex(), 534 target->timing.h_display, target->timing.v_display); 535 536 if (fPipe == NULL) { 537 ERROR("%s: Setting display mode without assigned pipe!\n", __func__); 538 return B_ERROR; 539 } 540 541 addr_t panelControl = INTEL_PANEL_CONTROL; 542 addr_t panelStatus = INTEL_PANEL_STATUS; 543 if (gInfo->shared_info->pch_info != INTEL_PCH_NONE) { 544 panelControl = PCH_PANEL_CONTROL; 545 panelStatus = PCH_PANEL_STATUS; 546 } 547 548 if (gInfo->shared_info->device_type.Generation() != 4) { 549 // TODO not needed on any generation if we are using the panel fitter 550 // Power off Panel 551 write32(panelControl, 552 read32(panelControl) & ~PANEL_CONTROL_POWER_TARGET_ON); 553 read32(panelControl); 554 555 if (!wait_for_clear(panelStatus, PANEL_STATUS_POWER_ON, 1000)) { 556 ERROR("%s: %s didn't power off within 1000ms!\n", __func__, 557 PortName()); 558 } 559 } 560 561 // For LVDS panels, we may need to set the timings according to the panel 562 // native video mode, and let the panel fitter do the scaling. But the 563 // place where the scaling happens varies accross generations of devices. 564 display_mode hardwareTarget; 565 bool needsScaling = false; 566 567 // TODO figure out how it's done (or if we need to configure something at 568 // all) for other generations 569 if (gInfo->shared_info->device_type.Generation() <= 6 570 && gInfo->shared_info->device_type.Generation() >= 3 571 && gInfo->shared_info->got_vbt) { 572 // Set vbios hardware panel mode as base 573 hardwareTarget = gInfo->shared_info->panel_mode; 574 575 if (hardwareTarget.timing.h_display == target->timing.h_display 576 && hardwareTarget.timing.v_display == target->timing.v_display) { 577 // We are setting the native video mode, nothing special to do 578 TRACE("Setting LVDS to native mode\n"); 579 hardwareTarget = *target; 580 } else { 581 // We need to enable the panel fitter 582 TRACE("%s: hardware mode will actually be %dx%d\n", __func__, 583 hardwareTarget.timing.h_display, hardwareTarget.timing.v_display); 584 585 hardwareTarget.space = target->space; 586 // retain requested virtual size 587 hardwareTarget.virtual_width = target->virtual_width; 588 hardwareTarget.virtual_height = target->virtual_height; 589 // FIXME we should also get the refresh frequency from the target 590 // mode, and then "sanitize" the resulting mode we made up. 591 592 needsScaling = true; 593 } 594 } else { 595 TRACE("Setting LVDS mode without VBT info or on unhandled hardware " 596 "generation, scaling may not work\n"); 597 // We don't have VBT data, try to set the requested mode directly 598 // and hope for the best 599 hardwareTarget = *target; 600 } 601 602 // Setup PanelFitter and Train FDI if it exists 603 PanelFitter* fitter = fPipe->PFT(); 604 if (fitter != NULL) 605 fitter->Enable(hardwareTarget); 606 FDILink* link = fPipe->FDI(); 607 if (link != NULL) 608 link->Train(&hardwareTarget); 609 610 pll_divisors divisors; 611 compute_pll_divisors(&hardwareTarget, &divisors, true); 612 613 uint32 lvds = read32(_PortRegister()) 614 | LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; 615 616 if (gInfo->shared_info->device_type.Generation() == 4) { 617 // LVDS_A3_POWER_UP == 24bpp 618 // otherwise, 18bpp 619 if ((lvds & LVDS_A3_POWER_MASK) != LVDS_A3_POWER_UP) 620 lvds |= LVDS_18BIT_DITHER; 621 } 622 623 // LVDS on PCH needs set before display enable 624 if (gInfo->shared_info->pch_info == INTEL_PCH_CPT) { 625 lvds &= ~PORT_TRANS_SEL_MASK; 626 if (fPipe->Index() == INTEL_PIPE_A) 627 lvds |= PORT_TRANS_A_SEL_CPT; 628 else 629 lvds |= PORT_TRANS_B_SEL_CPT; 630 } 631 632 // Set the B0-B3 data pairs corresponding to whether we're going to 633 // set the DPLLs for dual-channel mode or not. 634 if (divisors.p2 == 5 || divisors.p2 == 7) { 635 TRACE("LVDS: dual channel\n"); 636 lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; 637 } else { 638 TRACE("LVDS: single channel\n"); 639 lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); 640 } 641 642 // LVDS port control moves polarity bits because Intel hates you. 643 // Set LVDS sync polarity 644 lvds &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY); 645 646 // set on - polarity. 647 if ((target->timing.flags & B_POSITIVE_HSYNC) == 0) 648 lvds |= LVDS_HSYNC_POLARITY; 649 if ((target->timing.flags & B_POSITIVE_VSYNC) == 0) 650 lvds |= LVDS_VSYNC_POLARITY; 651 652 TRACE("%s: LVDS Write: 0x%" B_PRIx32 "\n", __func__, lvds); 653 write32(_PortRegister(), lvds); 654 read32(_PortRegister()); 655 656 uint32 extraPLLFlags = 0; 657 658 // DPLL mode LVDS for i915+ 659 if (gInfo->shared_info->device_type.Generation() >= 3) 660 extraPLLFlags |= DISPLAY_PLL_MODE_LVDS | DISPLAY_PLL_2X_CLOCK; 661 662 // Program general pipe config 663 fPipe->Configure(target); 664 665 // Program pipe PLL's (using the hardware mode timings, since that's what 666 // the PLL is used for) 667 fPipe->ConfigureClocks(divisors, hardwareTarget.timing.pixel_clock, 668 extraPLLFlags); 669 670 if (gInfo->shared_info->device_type.Generation() != 4) { 671 // G45: no need to power the panel off 672 // Power on Panel 673 write32(panelControl, 674 read32(panelControl) | PANEL_CONTROL_POWER_TARGET_ON); 675 read32(panelControl); 676 677 if (!wait_for_set(panelStatus, PANEL_STATUS_POWER_ON, 1000)) { 678 ERROR("%s: %s didn't power on within 1000ms!\n", __func__, 679 PortName()); 680 } 681 } 682 683 // Program target display mode 684 fPipe->ConfigureTimings(target, !needsScaling); 685 686 if (needsScaling) { 687 if (gInfo->shared_info->device_type.Generation() <= 4) { 688 // Enable panel fitter in automatic mode. It will figure out 689 // the scaling ratios automatically. 690 uint32 panelFitterControl = read32(INTEL_PANEL_FIT_CONTROL); 691 panelFitterControl |= PANEL_FITTER_ENABLED; 692 panelFitterControl &= ~(PANEL_FITTER_SCALING_MODE_MASK 693 | PANEL_FITTER_PIPE_MASK); 694 panelFitterControl |= PANEL_FITTER_PIPE_B; 695 // LVDS is always on pipe B. 696 write32(INTEL_PANEL_FIT_CONTROL, panelFitterControl); 697 } 698 // TODO do we need to do anything on later generations? 699 } else { 700 if (gInfo->shared_info->device_type.Generation() == 4 701 || gInfo->shared_info->device_type.Generation() == 3) { 702 // Bypass the panel fitter 703 uint32 panelFitterControl = read32(INTEL_PANEL_FIT_CONTROL); 704 panelFitterControl &= ~PANEL_FITTER_ENABLED; 705 write32(INTEL_PANEL_FIT_CONTROL, panelFitterControl); 706 } else { 707 // We don't need to do anything more for later generations, the 708 // scaling is handled at the transcoder level. We may want to 709 // configure dithering, but the code below ignores the previous 710 // value in the register and may mess things up so we should do 711 // this in a safeer way. For now, assume the BIOS did the right 712 // thing. 713 #if 0 714 // Disable panel fitting, but enable 8 to 6-bit dithering 715 write32(INTEL_PANEL_FIT_CONTROL, 0x4); 716 // TODO: do not do this if the connected panel is 24-bit 717 // (I don't know how to detect that) 718 #endif 719 } 720 } 721 722 // Set fCurrentMode to our set display mode 723 memcpy(&fCurrentMode, target, sizeof(display_mode)); 724 725 return B_OK; 726 } 727 728 729 // #pragma mark - DVI/SDVO/generic 730 731 732 DigitalPort::DigitalPort(port_index index, const char* baseName) 733 : 734 Port(index, baseName) 735 { 736 } 737 738 739 bool 740 DigitalPort::IsConnected() 741 { 742 TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), 743 _PortRegister()); 744 745 // As this port overlaps with pretty much everything, this must be called 746 // after having ruled out all other port types. 747 return HasEDID(); 748 } 749 750 751 addr_t 752 DigitalPort::_DDCRegister() 753 { 754 //TODO: IS BROXTON, B = B, C = C, D = NIL 755 switch (PortIndex()) { 756 case INTEL_PORT_B: 757 return INTEL_I2C_IO_E; 758 case INTEL_PORT_C: 759 return INTEL_I2C_IO_D; 760 case INTEL_PORT_D: 761 return INTEL_I2C_IO_F; 762 default: 763 return 0; 764 } 765 766 return 0; 767 } 768 769 770 addr_t 771 DigitalPort::_PortRegister() 772 { 773 switch (PortIndex()) { 774 case INTEL_PORT_A: 775 return INTEL_DIGITAL_PORT_A; 776 case INTEL_PORT_B: 777 return INTEL_DIGITAL_PORT_B; 778 case INTEL_PORT_C: 779 return INTEL_DIGITAL_PORT_C; 780 default: 781 return 0; 782 } 783 return 0; 784 } 785 786 787 status_t 788 DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode) 789 { 790 CALLED(); 791 TRACE("%s: %s %dx%d\n", __func__, PortName(), target->timing.h_display, 792 target->timing.v_display); 793 794 if (fPipe == NULL) { 795 ERROR("%s: Setting display mode without assigned pipe!\n", __func__); 796 return B_ERROR; 797 } 798 799 // Setup PanelFitter and Train FDI if it exists 800 PanelFitter* fitter = fPipe->PFT(); 801 if (fitter != NULL) 802 fitter->Enable(*target); 803 FDILink* link = fPipe->FDI(); 804 if (link != NULL) 805 link->Train(target); 806 807 pll_divisors divisors; 808 compute_pll_divisors(target, &divisors, false); 809 810 uint32 extraPLLFlags = 0; 811 if (gInfo->shared_info->device_type.Generation() >= 3) 812 extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL | DISPLAY_PLL_2X_CLOCK; 813 814 // Program general pipe config 815 fPipe->Configure(target); 816 817 // Program pipe PLL's 818 fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags); 819 820 // Program target display mode 821 fPipe->ConfigureTimings(target); 822 823 // Set fCurrentMode to our set display mode 824 memcpy(&fCurrentMode, target, sizeof(display_mode)); 825 826 return B_OK; 827 } 828 829 830 // #pragma mark - LVDS Panel 831 // #pragma mark - HDMI 832 833 834 HDMIPort::HDMIPort(port_index index) 835 : 836 DigitalPort(index, "HDMI") 837 { 838 } 839 840 841 bool 842 HDMIPort::IsConnected() 843 { 844 if (!gInfo->shared_info->device_type.SupportsHDMI()) 845 return false; 846 847 addr_t portRegister = _PortRegister(); 848 TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), 849 portRegister); 850 851 if (portRegister == 0) 852 return false; 853 854 //Notes: 855 //- DISPLAY_MONITOR_PORT_DETECTED does only tell you *some* sort of digital display is 856 // connected to the port *if* you have the AUX channel stuff under power. It does not 857 // tell you which -type- of digital display is connected. 858 //- Since we rely on the BIOS anyway, let's just use the conclusions it made for us :) 859 // Beware though: set_display_power_mode() uses this DISPLAY_MONITOR_PORT_ENABLED bit 860 // for DPMS as well. So we should better buffer our findings here for i.e. possible 861 // accelerant clones starting up. For DPMS there's currently no problem as this bit 862 // is only programmed for LVDS, DVI and VGA while we detect presence only for DP and HDMI. 863 // 864 //if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0) 865 if ((read32(portRegister) & DISPLAY_MONITOR_PORT_ENABLED) == 0) 866 return false; 867 868 return HasEDID(); 869 } 870 871 872 addr_t 873 HDMIPort::_PortRegister() 874 { 875 // on PCH there's an additional port sandwiched in 876 bool hasPCH = (gInfo->shared_info->pch_info != INTEL_PCH_NONE); 877 bool fourthGen = gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV); 878 879 switch (PortIndex()) { 880 case INTEL_PORT_B: 881 if (fourthGen) 882 return GEN4_HDMI_PORT_B; 883 return hasPCH ? PCH_HDMI_PORT_B : INTEL_HDMI_PORT_B; 884 case INTEL_PORT_C: 885 if (fourthGen) 886 return GEN4_HDMI_PORT_C; 887 return hasPCH ? PCH_HDMI_PORT_C : INTEL_HDMI_PORT_C; 888 case INTEL_PORT_D: 889 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) 890 return CHV_HDMI_PORT_D; 891 return hasPCH ? PCH_HDMI_PORT_D : 0; 892 default: 893 return 0; 894 } 895 896 return 0; 897 } 898 899 900 // #pragma mark - DisplayPort 901 902 903 DisplayPort::DisplayPort(port_index index, const char* baseName) 904 : 905 Port(index, baseName) 906 { 907 } 908 909 910 pipe_index 911 DisplayPort::PipePreference() 912 { 913 CALLED(); 914 if (gInfo->shared_info->device_type.Generation() <= 4) 915 return INTEL_PIPE_ANY; 916 917 // Notes: 918 // - The BIOSes seen sofar do not use PIPE C by default. 919 // - Looks like BIOS selected Transcoder (A,B,C) is not always same as selected Pipe (A,B,C) 920 // so these should probably be handled seperately. For now this is OK as we don't touch 921 // the pipe for DisplayPort, only the transcoder.. 922 uint32 TranscoderPort = INTEL_TRANS_DP_PORT_NONE; 923 switch (PortIndex()) { 924 case INTEL_PORT_A: 925 return INTEL_PIPE_ANY; 926 case INTEL_PORT_B: 927 TranscoderPort = INTEL_TRANS_DP_PORT_B; 928 break; 929 case INTEL_PORT_C: 930 TranscoderPort = INTEL_TRANS_DP_PORT_C; 931 break; 932 case INTEL_PORT_D: 933 TranscoderPort = INTEL_TRANS_DP_PORT_D; 934 break; 935 default: 936 return INTEL_PIPE_ANY; 937 } 938 939 for (uint32 Transcoder = 0; Transcoder < 3; Transcoder++) { 940 if ((read32(INTEL_TRANSCODER_A_DP_CTL + (Transcoder << 12)) & INTEL_TRANS_DP_PORT_MASK) == 941 INTEL_TRANS_DP_PORT(TranscoderPort)) { 942 switch (Transcoder) { 943 case 0: 944 return INTEL_PIPE_A; 945 case 1: 946 return INTEL_PIPE_B; 947 case 2: 948 return INTEL_PIPE_C; 949 } 950 } 951 } 952 953 return INTEL_PIPE_ANY; 954 } 955 956 957 bool 958 DisplayPort::IsConnected() 959 { 960 addr_t portRegister = _PortRegister(); 961 962 TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), 963 portRegister); 964 965 if (portRegister == 0) 966 return false; 967 968 //Notes: 969 //- DISPLAY_MONITOR_PORT_DETECTED does only tell you *some* sort of digital display is 970 // connected to the port *if* you have the AUX channel stuff under power. It does not 971 // tell you which -type- of digital display is connected. 972 //- Since we rely on the BIOS anyway, let's just use the conclusions it made for us :) 973 // Beware though: set_display_power_mode() uses this DISPLAY_MONITOR_PORT_ENABLED bit 974 // for DPMS as well. So we should better buffer our findings here for i.e. possible 975 // accelerant clones starting up. For DPMS there's currently no problem as this bit 976 // is only programmed for LVDS, DVI and VGA while we detect presence only for DP and HDMI. 977 // 978 //if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0) { 979 if ((read32(portRegister) & DISPLAY_MONITOR_PORT_ENABLED) == 0) { 980 TRACE("%s: %s link not detected\n", __func__, PortName()); 981 return false; 982 } 983 984 //since EDID is not correctly implemented yet for this connection type we'll do without it for now 985 //return HasEDID(); 986 TRACE("%s: %s link detected\n", __func__, PortName()); 987 return true; 988 } 989 990 991 addr_t 992 DisplayPort::_DDCRegister() 993 { 994 // TODO: Do VLV + CHV use the VLV_DP_AUX_CTL_B + VLV_DP_AUX_CTL_C? 995 switch (PortIndex()) { 996 case INTEL_PORT_A: 997 return INTEL_DP_AUX_CTL_A; 998 case INTEL_PORT_B: 999 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) 1000 return VLV_DP_AUX_CTL_B; 1001 return INTEL_DP_AUX_CTL_B; 1002 case INTEL_PORT_C: 1003 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) 1004 return VLV_DP_AUX_CTL_C; 1005 return INTEL_DP_AUX_CTL_C; 1006 case INTEL_PORT_D: 1007 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) 1008 return CHV_DP_AUX_CTL_D; 1009 else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) 1010 return 0; 1011 return INTEL_DP_AUX_CTL_D; 1012 default: 1013 return 0; 1014 } 1015 1016 return 0; 1017 } 1018 1019 1020 addr_t 1021 DisplayPort::_PortRegister() 1022 { 1023 // There are 6000 lines of intel linux code probing DP registers 1024 // to properly detect DP vs eDP to then in-turn properly figure out 1025 // what is DP and what is HDMI. It only takes 3 lines to 1026 // ignore DisplayPort on ValleyView / CherryView 1027 1028 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV) 1029 || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) { 1030 ERROR("TODO: DisplayPort on ValleyView / CherryView"); 1031 return 0; 1032 } 1033 1034 // Intel, are humans even involved anymore? 1035 // This is a lot more complex than this code makes it look. (see defines) 1036 // INTEL_DISPLAY_PORT_X moves around a lot based on PCH 1037 // except on ValleyView and CherryView. 1038 switch (PortIndex()) { 1039 case INTEL_PORT_A: 1040 return INTEL_DISPLAY_PORT_A; 1041 case INTEL_PORT_B: 1042 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) 1043 return VLV_DISPLAY_PORT_B; 1044 return INTEL_DISPLAY_PORT_B; 1045 case INTEL_PORT_C: 1046 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) 1047 return VLV_DISPLAY_PORT_C; 1048 return INTEL_DISPLAY_PORT_C; 1049 case INTEL_PORT_D: 1050 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) 1051 return CHV_DISPLAY_PORT_D; 1052 else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) 1053 return 0; 1054 return INTEL_DISPLAY_PORT_D; 1055 default: 1056 return 0; 1057 } 1058 1059 return 0; 1060 } 1061 1062 1063 status_t 1064 DisplayPort::_SetPortLinkGen4(display_mode* target) 1065 { 1066 // Khz / 10. ( each output octet encoded as 10 bits. 1067 //uint32 linkBandwidth = gInfo->shared_info->fdi_link_frequency * 1000 / 10; //=270000 khz 1068 //fixme: always so? 1069 uint32 linkBandwidth = 270000; //khz 1070 uint32 fPipeOffset = 0; 1071 if (fPipe->Index() == INTEL_PIPE_B) 1072 fPipeOffset = 0x1000; 1073 1074 TRACE("%s: DP M1 data before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_DATA_M + fPipeOffset)); 1075 TRACE("%s: DP N1 data before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_DATA_N + fPipeOffset)); 1076 TRACE("%s: DP M1 link before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_LINK_M + fPipeOffset)); 1077 TRACE("%s: DP N1 link before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_LINK_N + fPipeOffset)); 1078 1079 uint32 bitsPerPixel = 24; //fixme: always so? 1080 uint32 lanes = 4; //fixme: always so? 1081 1082 //Setup Data M/N 1083 uint64 linkspeed = lanes * linkBandwidth * 8; 1084 uint64 ret_n = 1; 1085 while(ret_n < linkspeed) { 1086 ret_n *= 2; 1087 } 1088 if (ret_n > 0x800000) { 1089 ret_n = 0x800000; 1090 } 1091 uint64 ret_m = target->timing.pixel_clock * ret_n * bitsPerPixel / linkspeed; 1092 while ((ret_n > 0xffffff) || (ret_m > 0xffffff)) { 1093 ret_m >>= 1; 1094 ret_n >>= 1; 1095 } 1096 //Set TU size bits (to default, max) before link training so that error detection works 1097 write32(INTEL_PIPE_A_DATA_M + fPipeOffset, ret_m | FDI_PIPE_MN_TU_SIZE_MASK); 1098 write32(INTEL_PIPE_A_DATA_N + fPipeOffset, ret_n); 1099 1100 //Setup Link M/N 1101 linkspeed = linkBandwidth; 1102 ret_n = 1; 1103 while(ret_n < linkspeed) { 1104 ret_n *= 2; 1105 } 1106 if (ret_n > 0x800000) { 1107 ret_n = 0x800000; 1108 } 1109 ret_m = target->timing.pixel_clock * ret_n / linkspeed; 1110 while ((ret_n > 0xffffff) || (ret_m > 0xffffff)) { 1111 ret_m >>= 1; 1112 ret_n >>= 1; 1113 } 1114 write32(INTEL_PIPE_A_LINK_M + fPipeOffset, ret_m); 1115 //Writing Link N triggers all four registers to be activated also (on next VBlank) 1116 write32(INTEL_PIPE_A_LINK_N + fPipeOffset, ret_n); 1117 1118 TRACE("%s: DP M1 data after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_DATA_M + fPipeOffset)); 1119 TRACE("%s: DP N1 data after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_DATA_N + fPipeOffset)); 1120 TRACE("%s: DP M1 link after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_LINK_M + fPipeOffset)); 1121 TRACE("%s: DP N1 link after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_LINK_N + fPipeOffset)); 1122 1123 return B_OK; 1124 } 1125 1126 1127 status_t 1128 DisplayPort::SetDisplayMode(display_mode* target, uint32 colorMode) 1129 { 1130 CALLED(); 1131 TRACE("%s: %s %dx%d\n", __func__, PortName(), target->timing.h_display, 1132 target->timing.v_display); 1133 1134 if (fPipe == NULL) { 1135 ERROR("%s: Setting display mode without assigned pipe!\n", __func__); 1136 return B_ERROR; 1137 } 1138 1139 status_t result = B_OK; 1140 if (gInfo->shared_info->device_type.Generation() <= 4) { 1141 fPipe->ConfigureTimings(target); 1142 result = _SetPortLinkGen4(target); 1143 } else { 1144 //fixme: doesn't work yet. For now just scale to native mode. 1145 #if 0 1146 // Setup PanelFitter and Train FDI if it exists 1147 PanelFitter* fitter = fPipe->PFT(); 1148 if (fitter != NULL) 1149 fitter->Enable(*target); 1150 FDILink* link = fPipe->FDI(); 1151 if (link != NULL) 1152 link->Train(target); 1153 1154 pll_divisors divisors; 1155 compute_pll_divisors(target, &divisors, false); 1156 1157 uint32 extraPLLFlags = 0; 1158 if (gInfo->shared_info->device_type.Generation() >= 3) 1159 extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL | DISPLAY_PLL_2X_CLOCK; 1160 1161 // Program general pipe config 1162 fPipe->Configure(target); 1163 1164 // Program pipe PLL's 1165 fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags); 1166 1167 // Program target display mode 1168 fPipe->ConfigureTimings(target); 1169 #endif 1170 1171 // Keep monitor at native mode and scale image to that 1172 fPipe->ConfigureScalePos(target); 1173 } 1174 1175 // Set fCurrentMode to our set display mode 1176 memcpy(&fCurrentMode, target, sizeof(display_mode)); 1177 1178 return result; 1179 } 1180 1181 1182 // #pragma mark - Embedded DisplayPort 1183 1184 1185 EmbeddedDisplayPort::EmbeddedDisplayPort() 1186 : 1187 DisplayPort(INTEL_PORT_A, "Embedded DisplayPort") 1188 { 1189 } 1190 1191 1192 bool 1193 EmbeddedDisplayPort::IsConnected() 1194 { 1195 addr_t portRegister = _PortRegister(); 1196 1197 TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), 1198 portRegister); 1199 1200 if (!gInfo->shared_info->device_type.IsMobile()) { 1201 TRACE("%s: skipping eDP on non-mobile GPU\n", __func__); 1202 return false; 1203 } 1204 1205 if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0) { 1206 TRACE("%s: %s link not detected\n", __func__, PortName()); 1207 return false; 1208 } 1209 1210 HasEDID(); 1211 1212 // If eDP has EDID, awesome. We use it. 1213 // No EDID? The modesetting code falls back to VBIOS panel_mode 1214 return true; 1215 } 1216 1217 1218 // #pragma mark - Digital Display Port 1219 1220 1221 DigitalDisplayInterface::DigitalDisplayInterface(port_index index, 1222 const char* baseName) 1223 : 1224 Port(index, baseName) 1225 { 1226 // As of Haswell, Intel decided to change eDP ports to a "DDI" bus... 1227 // on a dare because the hardware engineers were drunk one night. 1228 } 1229 1230 1231 addr_t 1232 DigitalDisplayInterface::_PortRegister() 1233 { 1234 // TODO: Linux does a DDI_BUF_CTL(INTEL_PORT_A) which is cleaner 1235 // (but we have to ensure the offsets + region base is correct) 1236 switch (PortIndex()) { 1237 case INTEL_PORT_A: 1238 return DDI_BUF_CTL_A; 1239 case INTEL_PORT_B: 1240 return DDI_BUF_CTL_B; 1241 case INTEL_PORT_C: 1242 return DDI_BUF_CTL_C; 1243 case INTEL_PORT_D: 1244 return DDI_BUF_CTL_D; 1245 case INTEL_PORT_E: 1246 return DDI_BUF_CTL_E; 1247 default: 1248 return 0; 1249 } 1250 return 0; 1251 } 1252 1253 1254 addr_t 1255 DigitalDisplayInterface::_DDCRegister() 1256 { 1257 // TODO: No idea, does DDI have DDC? 1258 return 0; 1259 } 1260 1261 1262 status_t 1263 DigitalDisplayInterface::Power(bool enabled) 1264 { 1265 TRACE("%s: %s DDI enabled: %s\n", __func__, PortName(), 1266 enabled ? "true" : "false"); 1267 1268 fPipe->Enable(enabled); 1269 1270 addr_t portRegister = _PortRegister(); 1271 uint32 state = read32(portRegister); 1272 write32(portRegister, 1273 enabled ? (state | DDI_BUF_CTL_ENABLE) : (state & ~DDI_BUF_CTL_ENABLE)); 1274 read32(portRegister); 1275 1276 return B_OK; 1277 } 1278 1279 1280 bool 1281 DigitalDisplayInterface::IsConnected() 1282 { 1283 addr_t portRegister = _PortRegister(); 1284 1285 TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), 1286 portRegister); 1287 1288 if (portRegister == 0) 1289 return false; 1290 1291 if ((read32(portRegister) & DDI_INIT_DISPLAY_DETECTED) == 0) { 1292 TRACE("%s: %s link not detected\n", __func__, PortName()); 1293 return false; 1294 } 1295 1296 // Probe a little port info. 1297 if ((read32(DDI_BUF_CTL_A) & DDI_A_4_LANES) != 0) { 1298 switch (PortIndex()) { 1299 case INTEL_PORT_A: 1300 fMaxLanes = 4; 1301 break; 1302 case INTEL_PORT_E: 1303 fMaxLanes = 0; 1304 break; 1305 default: 1306 fMaxLanes = 4; 1307 break; 1308 } 1309 } else { 1310 switch (PortIndex()) { 1311 case INTEL_PORT_A: 1312 fMaxLanes = 2; 1313 break; 1314 case INTEL_PORT_E: 1315 fMaxLanes = 2; 1316 break; 1317 default: 1318 fMaxLanes = 4; 1319 break; 1320 } 1321 } 1322 1323 TRACE("%s: %s Maximum Lanes: %" B_PRId8 "\n", __func__, 1324 PortName(), fMaxLanes); 1325 1326 //since EDID is not correctly implemented yet for this connection type we'll do without it for now 1327 //return HasEDID(); 1328 TRACE("%s: %s link detected\n", __func__, PortName()); 1329 return true; 1330 } 1331 1332 1333 status_t 1334 DigitalDisplayInterface::SetDisplayMode(display_mode* target, uint32 colorMode) 1335 { 1336 CALLED(); 1337 TRACE("%s: %s %dx%d\n", __func__, PortName(), target->timing.h_display, 1338 target->timing.v_display); 1339 1340 if (fPipe == NULL) { 1341 ERROR("%s: Setting display mode without assigned pipe!\n", __func__); 1342 return B_ERROR; 1343 } 1344 1345 // Setup PanelFitter and Train FDI if it exists 1346 PanelFitter* fitter = fPipe->PFT(); 1347 if (fitter != NULL) 1348 fitter->Enable(*target); 1349 // Skip FDI if we have a CPU connected display 1350 if (PortIndex() != INTEL_PORT_A) { 1351 FDILink* link = fPipe->FDI(); 1352 if (link != NULL) 1353 link->Train(target); 1354 } 1355 1356 pll_divisors divisors; 1357 compute_pll_divisors(target, &divisors, false); 1358 1359 uint32 extraPLLFlags = 0; 1360 if (gInfo->shared_info->device_type.Generation() >= 3) 1361 extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL | DISPLAY_PLL_2X_CLOCK; 1362 1363 // Program general pipe config 1364 fPipe->Configure(target); 1365 1366 // Program pipe PLL's 1367 fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags); 1368 1369 // Program target display mode 1370 fPipe->ConfigureTimings(target); 1371 1372 // Set fCurrentMode to our set display mode 1373 memcpy(&fCurrentMode, target, sizeof(display_mode)); 1374 1375 return B_OK; 1376 } 1377