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->virtual_width, 356 target->virtual_height); 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->virtual_width, target->virtual_height); 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.virtual_width == target->virtual_width 576 && hardwareTarget.virtual_height == target->virtual_height) { 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.virtual_width, hardwareTarget.virtual_height); 584 585 hardwareTarget.space = target->space; 586 // FIXME we should also get the refresh frequency from the target 587 // mode, and then "sanitize" the resulting mode we made up. 588 589 needsScaling = true; 590 } 591 } else { 592 TRACE("Setting LVDS mode without VBT info or on unhandled hardware " 593 "generation, scaling may not work\n"); 594 // We don't have VBT data, try to set the requested mode directly 595 // and hope for the best 596 hardwareTarget = *target; 597 } 598 599 // Setup PanelFitter and Train FDI if it exists 600 PanelFitter* fitter = fPipe->PFT(); 601 if (fitter != NULL) 602 fitter->Enable(hardwareTarget); 603 FDILink* link = fPipe->FDI(); 604 if (link != NULL) 605 link->Train(&hardwareTarget); 606 607 pll_divisors divisors; 608 compute_pll_divisors(&hardwareTarget, &divisors, true); 609 610 uint32 lvds = read32(_PortRegister()) 611 | LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; 612 613 if (gInfo->shared_info->device_type.Generation() == 4) { 614 // LVDS_A3_POWER_UP == 24bpp 615 // otherwise, 18bpp 616 if ((lvds & LVDS_A3_POWER_MASK) != LVDS_A3_POWER_UP) 617 lvds |= LVDS_18BIT_DITHER; 618 } 619 620 // LVDS on PCH needs set before display enable 621 if (gInfo->shared_info->pch_info == INTEL_PCH_CPT) { 622 lvds &= ~PORT_TRANS_SEL_MASK; 623 if (fPipe->Index() == INTEL_PIPE_A) 624 lvds |= PORT_TRANS_A_SEL_CPT; 625 else 626 lvds |= PORT_TRANS_B_SEL_CPT; 627 } 628 629 // Set the B0-B3 data pairs corresponding to whether we're going to 630 // set the DPLLs for dual-channel mode or not. 631 if (divisors.p2 == 5 || divisors.p2 == 7) { 632 TRACE("LVDS: dual channel\n"); 633 lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; 634 } else { 635 TRACE("LVDS: single channel\n"); 636 lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); 637 } 638 639 // LVDS port control moves polarity bits because Intel hates you. 640 // Set LVDS sync polarity 641 lvds &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY); 642 643 // set on - polarity. 644 if ((target->timing.flags & B_POSITIVE_HSYNC) == 0) 645 lvds |= LVDS_HSYNC_POLARITY; 646 if ((target->timing.flags & B_POSITIVE_VSYNC) == 0) 647 lvds |= LVDS_VSYNC_POLARITY; 648 649 TRACE("%s: LVDS Write: 0x%" B_PRIx32 "\n", __func__, lvds); 650 write32(_PortRegister(), lvds); 651 read32(_PortRegister()); 652 653 uint32 extraPLLFlags = 0; 654 655 // DPLL mode LVDS for i915+ 656 if (gInfo->shared_info->device_type.Generation() >= 3) 657 extraPLLFlags |= DISPLAY_PLL_MODE_LVDS | DISPLAY_PLL_2X_CLOCK; 658 659 // Program general pipe config 660 fPipe->Configure(target); 661 662 // Program pipe PLL's (using the hardware mode timings, since that's what 663 // the PLL is used for) 664 fPipe->ConfigureClocks(divisors, hardwareTarget.timing.pixel_clock, 665 extraPLLFlags); 666 667 if (gInfo->shared_info->device_type.Generation() != 4) { 668 // G45: no need to power the panel off 669 // Power on Panel 670 write32(panelControl, 671 read32(panelControl) | PANEL_CONTROL_POWER_TARGET_ON); 672 read32(panelControl); 673 674 if (!wait_for_set(panelStatus, PANEL_STATUS_POWER_ON, 1000)) { 675 ERROR("%s: %s didn't power on within 1000ms!\n", __func__, 676 PortName()); 677 } 678 } 679 680 // Program target display mode 681 fPipe->ConfigureTimings(target, !needsScaling); 682 683 if (needsScaling) { 684 if (gInfo->shared_info->device_type.Generation() <= 4) { 685 // Enable panel fitter in automatic mode. It will figure out 686 // the scaling ratios automatically. 687 uint32 panelFitterControl = read32(INTEL_PANEL_FIT_CONTROL); 688 panelFitterControl |= PANEL_FITTER_ENABLED; 689 panelFitterControl &= ~(PANEL_FITTER_SCALING_MODE_MASK 690 | PANEL_FITTER_PIPE_MASK); 691 panelFitterControl |= PANEL_FITTER_PIPE_B; 692 // LVDS is always on pipe B. 693 write32(INTEL_PANEL_FIT_CONTROL, panelFitterControl); 694 } 695 // TODO do we need to do anything on later generations? 696 } else { 697 if (gInfo->shared_info->device_type.Generation() == 4 698 || gInfo->shared_info->device_type.Generation() == 3) { 699 // Bypass the panel fitter 700 uint32 panelFitterControl = read32(INTEL_PANEL_FIT_CONTROL); 701 panelFitterControl &= ~PANEL_FITTER_ENABLED; 702 write32(INTEL_PANEL_FIT_CONTROL, panelFitterControl); 703 } else { 704 // We don't need to do anything more for later generations, the 705 // scaling is handled at the transcoder level. We may want to 706 // configure dithering, but the code below ignores the previous 707 // value in the register and may mess things up so we should do 708 // this in a safeer way. For now, assume the BIOS did the right 709 // thing. 710 #if 0 711 // Disable panel fitting, but enable 8 to 6-bit dithering 712 write32(INTEL_PANEL_FIT_CONTROL, 0x4); 713 // TODO: do not do this if the connected panel is 24-bit 714 // (I don't know how to detect that) 715 #endif 716 } 717 } 718 719 // Set fCurrentMode to our set display mode 720 memcpy(&fCurrentMode, target, sizeof(display_mode)); 721 722 return B_OK; 723 } 724 725 726 // #pragma mark - DVI/SDVO/generic 727 728 729 DigitalPort::DigitalPort(port_index index, const char* baseName) 730 : 731 Port(index, baseName) 732 { 733 } 734 735 736 bool 737 DigitalPort::IsConnected() 738 { 739 TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), 740 _PortRegister()); 741 742 // As this port overlaps with pretty much everything, this must be called 743 // after having ruled out all other port types. 744 return HasEDID(); 745 } 746 747 748 addr_t 749 DigitalPort::_DDCRegister() 750 { 751 //TODO: IS BROXTON, B = B, C = C, D = NIL 752 switch (PortIndex()) { 753 case INTEL_PORT_B: 754 return INTEL_I2C_IO_E; 755 case INTEL_PORT_C: 756 return INTEL_I2C_IO_D; 757 case INTEL_PORT_D: 758 return INTEL_I2C_IO_F; 759 default: 760 return 0; 761 } 762 763 return 0; 764 } 765 766 767 addr_t 768 DigitalPort::_PortRegister() 769 { 770 switch (PortIndex()) { 771 case INTEL_PORT_A: 772 return INTEL_DIGITAL_PORT_A; 773 case INTEL_PORT_B: 774 return INTEL_DIGITAL_PORT_B; 775 case INTEL_PORT_C: 776 return INTEL_DIGITAL_PORT_C; 777 default: 778 return 0; 779 } 780 return 0; 781 } 782 783 784 status_t 785 DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode) 786 { 787 CALLED(); 788 TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width, 789 target->virtual_height); 790 791 if (fPipe == NULL) { 792 ERROR("%s: Setting display mode without assigned pipe!\n", __func__); 793 return B_ERROR; 794 } 795 796 // Setup PanelFitter and Train FDI if it exists 797 PanelFitter* fitter = fPipe->PFT(); 798 if (fitter != NULL) 799 fitter->Enable(*target); 800 FDILink* link = fPipe->FDI(); 801 if (link != NULL) 802 link->Train(target); 803 804 pll_divisors divisors; 805 compute_pll_divisors(target, &divisors, false); 806 807 uint32 extraPLLFlags = 0; 808 if (gInfo->shared_info->device_type.Generation() >= 3) 809 extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL | DISPLAY_PLL_2X_CLOCK; 810 811 // Program general pipe config 812 fPipe->Configure(target); 813 814 // Program pipe PLL's 815 fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags); 816 817 // Program target display mode 818 fPipe->ConfigureTimings(target); 819 820 // Set fCurrentMode to our set display mode 821 memcpy(&fCurrentMode, target, sizeof(display_mode)); 822 823 return B_OK; 824 } 825 826 827 // #pragma mark - LVDS Panel 828 // #pragma mark - HDMI 829 830 831 HDMIPort::HDMIPort(port_index index) 832 : 833 DigitalPort(index, "HDMI") 834 { 835 } 836 837 838 bool 839 HDMIPort::IsConnected() 840 { 841 if (!gInfo->shared_info->device_type.SupportsHDMI()) 842 return false; 843 844 addr_t portRegister = _PortRegister(); 845 TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), 846 portRegister); 847 848 if (portRegister == 0) 849 return false; 850 851 //Notes: 852 //- DISPLAY_MONITOR_PORT_DETECTED does only tell you *some* sort of digital display is 853 // connected to the port *if* you have the AUX channel stuff under power. It does not 854 // tell you which -type- of digital display is connected. 855 //- Since we rely on the BIOS anyway, let's just use the conclusions it made for us :) 856 // Beware though: set_display_power_mode() uses this DISPLAY_MONITOR_PORT_ENABLED bit 857 // for DPMS as well. So we should better buffer our findings here for i.e. possible 858 // accelerant clones starting up. For DPMS there's currently no problem as this bit 859 // is only programmed for LVDS, DVI and VGA while we detect presence only for DP and HDMI. 860 // 861 //if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0) 862 if ((read32(portRegister) & DISPLAY_MONITOR_PORT_ENABLED) == 0) 863 return false; 864 865 return HasEDID(); 866 } 867 868 869 addr_t 870 HDMIPort::_PortRegister() 871 { 872 // on PCH there's an additional port sandwiched in 873 bool hasPCH = (gInfo->shared_info->pch_info != INTEL_PCH_NONE); 874 bool fourthGen = gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV); 875 876 switch (PortIndex()) { 877 case INTEL_PORT_B: 878 if (fourthGen) 879 return GEN4_HDMI_PORT_B; 880 return hasPCH ? PCH_HDMI_PORT_B : INTEL_HDMI_PORT_B; 881 case INTEL_PORT_C: 882 if (fourthGen) 883 return GEN4_HDMI_PORT_C; 884 return hasPCH ? PCH_HDMI_PORT_C : INTEL_HDMI_PORT_C; 885 case INTEL_PORT_D: 886 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) 887 return CHV_HDMI_PORT_D; 888 return hasPCH ? PCH_HDMI_PORT_D : 0; 889 default: 890 return 0; 891 } 892 893 return 0; 894 } 895 896 897 // #pragma mark - DisplayPort 898 899 900 DisplayPort::DisplayPort(port_index index, const char* baseName) 901 : 902 Port(index, baseName) 903 { 904 } 905 906 907 pipe_index 908 DisplayPort::PipePreference() 909 { 910 CALLED(); 911 if (gInfo->shared_info->device_type.Generation() <= 4) 912 return INTEL_PIPE_ANY; 913 914 // Notes: 915 // - The BIOSes seen sofar do not use PIPE C by default. 916 // - Looks like BIOS selected Transcoder (A,B,C) is not always same as selected Pipe (A,B,C) 917 // so these should probably be handled seperately. For now this is OK as we don't touch 918 // the pipe for DisplayPort, only the transcoder.. 919 uint32 TranscoderPort = INTEL_TRANS_DP_PORT_NONE; 920 switch (PortIndex()) { 921 case INTEL_PORT_A: 922 return INTEL_PIPE_ANY; 923 case INTEL_PORT_B: 924 TranscoderPort = INTEL_TRANS_DP_PORT_B; 925 break; 926 case INTEL_PORT_C: 927 TranscoderPort = INTEL_TRANS_DP_PORT_C; 928 break; 929 case INTEL_PORT_D: 930 TranscoderPort = INTEL_TRANS_DP_PORT_D; 931 break; 932 default: 933 return INTEL_PIPE_ANY; 934 } 935 936 for (uint32 Transcoder = 0; Transcoder < 3; Transcoder++) { 937 if ((read32(INTEL_TRANSCODER_A_DP_CTL + (Transcoder << 12)) & INTEL_TRANS_DP_PORT_MASK) == 938 INTEL_TRANS_DP_PORT(TranscoderPort)) { 939 switch (Transcoder) { 940 case 0: 941 return INTEL_PIPE_A; 942 case 1: 943 return INTEL_PIPE_B; 944 case 2: 945 return INTEL_PIPE_C; 946 } 947 } 948 } 949 950 return INTEL_PIPE_ANY; 951 } 952 953 954 bool 955 DisplayPort::IsConnected() 956 { 957 addr_t portRegister = _PortRegister(); 958 959 TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), 960 portRegister); 961 962 if (portRegister == 0) 963 return false; 964 965 //Notes: 966 //- DISPLAY_MONITOR_PORT_DETECTED does only tell you *some* sort of digital display is 967 // connected to the port *if* you have the AUX channel stuff under power. It does not 968 // tell you which -type- of digital display is connected. 969 //- Since we rely on the BIOS anyway, let's just use the conclusions it made for us :) 970 // Beware though: set_display_power_mode() uses this DISPLAY_MONITOR_PORT_ENABLED bit 971 // for DPMS as well. So we should better buffer our findings here for i.e. possible 972 // accelerant clones starting up. For DPMS there's currently no problem as this bit 973 // is only programmed for LVDS, DVI and VGA while we detect presence only for DP and HDMI. 974 // 975 //if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0) { 976 if ((read32(portRegister) & DISPLAY_MONITOR_PORT_ENABLED) == 0) { 977 TRACE("%s: %s link not detected\n", __func__, PortName()); 978 return false; 979 } 980 981 //since EDID is not correctly implemented yet for this connection type we'll do without it for now 982 //return HasEDID(); 983 TRACE("%s: %s link detected\n", __func__, PortName()); 984 return true; 985 } 986 987 988 addr_t 989 DisplayPort::_DDCRegister() 990 { 991 // TODO: Do VLV + CHV use the VLV_DP_AUX_CTL_B + VLV_DP_AUX_CTL_C? 992 switch (PortIndex()) { 993 case INTEL_PORT_A: 994 return INTEL_DP_AUX_CTL_A; 995 case INTEL_PORT_B: 996 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) 997 return VLV_DP_AUX_CTL_B; 998 return INTEL_DP_AUX_CTL_B; 999 case INTEL_PORT_C: 1000 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) 1001 return VLV_DP_AUX_CTL_C; 1002 return INTEL_DP_AUX_CTL_C; 1003 case INTEL_PORT_D: 1004 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) 1005 return CHV_DP_AUX_CTL_D; 1006 else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) 1007 return 0; 1008 return INTEL_DP_AUX_CTL_D; 1009 default: 1010 return 0; 1011 } 1012 1013 return 0; 1014 } 1015 1016 1017 addr_t 1018 DisplayPort::_PortRegister() 1019 { 1020 // There are 6000 lines of intel linux code probing DP registers 1021 // to properly detect DP vs eDP to then in-turn properly figure out 1022 // what is DP and what is HDMI. It only takes 3 lines to 1023 // ignore DisplayPort on ValleyView / CherryView 1024 1025 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV) 1026 || gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) { 1027 ERROR("TODO: DisplayPort on ValleyView / CherryView"); 1028 return 0; 1029 } 1030 1031 // Intel, are humans even involved anymore? 1032 // This is a lot more complex than this code makes it look. (see defines) 1033 // INTEL_DISPLAY_PORT_X moves around a lot based on PCH 1034 // except on ValleyView and CherryView. 1035 switch (PortIndex()) { 1036 case INTEL_PORT_A: 1037 return INTEL_DISPLAY_PORT_A; 1038 case INTEL_PORT_B: 1039 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) 1040 return VLV_DISPLAY_PORT_B; 1041 return INTEL_DISPLAY_PORT_B; 1042 case INTEL_PORT_C: 1043 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) 1044 return VLV_DISPLAY_PORT_C; 1045 return INTEL_DISPLAY_PORT_C; 1046 case INTEL_PORT_D: 1047 if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_CHV)) 1048 return CHV_DISPLAY_PORT_D; 1049 else if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_VLV)) 1050 return 0; 1051 return INTEL_DISPLAY_PORT_D; 1052 default: 1053 return 0; 1054 } 1055 1056 return 0; 1057 } 1058 1059 1060 status_t 1061 DisplayPort::_SetPortLinkGen4(display_mode* target) 1062 { 1063 // Khz / 10. ( each output octet encoded as 10 bits. 1064 //uint32 linkBandwidth = gInfo->shared_info->fdi_link_frequency * 1000 / 10; //=270000 khz 1065 //fixme: always so? 1066 uint32 linkBandwidth = 270000; //khz 1067 uint32 fPipeOffset = 0; 1068 if (fPipe->Index() == INTEL_PIPE_B) 1069 fPipeOffset = 0x1000; 1070 1071 TRACE("%s: DP M1 data before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_DATA_M + fPipeOffset)); 1072 TRACE("%s: DP N1 data before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_DATA_N + fPipeOffset)); 1073 TRACE("%s: DP M1 link before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_LINK_M + fPipeOffset)); 1074 TRACE("%s: DP N1 link before: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_LINK_N + fPipeOffset)); 1075 1076 uint32 bitsPerPixel = 24; //fixme: always so? 1077 uint32 lanes = 4; //fixme: always so? 1078 1079 //Setup Data M/N 1080 uint64 linkspeed = lanes * linkBandwidth * 8; 1081 uint64 ret_n = 1; 1082 while(ret_n < linkspeed) { 1083 ret_n *= 2; 1084 } 1085 if (ret_n > 0x800000) { 1086 ret_n = 0x800000; 1087 } 1088 uint64 ret_m = target->timing.pixel_clock * ret_n * bitsPerPixel / linkspeed; 1089 while ((ret_n > 0xffffff) || (ret_m > 0xffffff)) { 1090 ret_m >>= 1; 1091 ret_n >>= 1; 1092 } 1093 //Set TU size bits (to default, max) before link training so that error detection works 1094 write32(INTEL_PIPE_A_DATA_M + fPipeOffset, ret_m | FDI_PIPE_MN_TU_SIZE_MASK); 1095 write32(INTEL_PIPE_A_DATA_N + fPipeOffset, ret_n); 1096 1097 //Setup Link M/N 1098 linkspeed = linkBandwidth; 1099 ret_n = 1; 1100 while(ret_n < linkspeed) { 1101 ret_n *= 2; 1102 } 1103 if (ret_n > 0x800000) { 1104 ret_n = 0x800000; 1105 } 1106 ret_m = target->timing.pixel_clock * ret_n / linkspeed; 1107 while ((ret_n > 0xffffff) || (ret_m > 0xffffff)) { 1108 ret_m >>= 1; 1109 ret_n >>= 1; 1110 } 1111 write32(INTEL_PIPE_A_LINK_M + fPipeOffset, ret_m); 1112 //Writing Link N triggers all four registers to be activated also (on next VBlank) 1113 write32(INTEL_PIPE_A_LINK_N + fPipeOffset, ret_n); 1114 1115 TRACE("%s: DP M1 data after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_DATA_M + fPipeOffset)); 1116 TRACE("%s: DP N1 data after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_DATA_N + fPipeOffset)); 1117 TRACE("%s: DP M1 link after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_LINK_M + fPipeOffset)); 1118 TRACE("%s: DP N1 link after: 0x%" B_PRIx32 "\n", __func__, read32(INTEL_PIPE_A_LINK_N + fPipeOffset)); 1119 1120 return B_OK; 1121 } 1122 1123 1124 status_t 1125 DisplayPort::SetDisplayMode(display_mode* target, uint32 colorMode) 1126 { 1127 CALLED(); 1128 TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width, 1129 target->virtual_height); 1130 1131 if (fPipe == NULL) { 1132 ERROR("%s: Setting display mode without assigned pipe!\n", __func__); 1133 return B_ERROR; 1134 } 1135 1136 status_t result = B_OK; 1137 if (gInfo->shared_info->device_type.Generation() <= 4) { 1138 fPipe->ConfigureTimings(target); 1139 result = _SetPortLinkGen4(target); 1140 } else { 1141 //fixme: doesn't work yet. For now just scale to native mode. 1142 #if 0 1143 // Setup PanelFitter and Train FDI if it exists 1144 PanelFitter* fitter = fPipe->PFT(); 1145 if (fitter != NULL) 1146 fitter->Enable(*target); 1147 FDILink* link = fPipe->FDI(); 1148 if (link != NULL) 1149 link->Train(target); 1150 1151 pll_divisors divisors; 1152 compute_pll_divisors(target, &divisors, false); 1153 1154 uint32 extraPLLFlags = 0; 1155 if (gInfo->shared_info->device_type.Generation() >= 3) 1156 extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL | DISPLAY_PLL_2X_CLOCK; 1157 1158 // Program general pipe config 1159 fPipe->Configure(target); 1160 1161 // Program pipe PLL's 1162 fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags); 1163 1164 // Program target display mode 1165 fPipe->ConfigureTimings(target); 1166 #endif 1167 1168 // Keep monitor at native mode and scale image to that 1169 fPipe->ConfigureScalePos(target); 1170 } 1171 1172 // Set fCurrentMode to our set display mode 1173 memcpy(&fCurrentMode, target, sizeof(display_mode)); 1174 1175 return result; 1176 } 1177 1178 1179 // #pragma mark - Embedded DisplayPort 1180 1181 1182 EmbeddedDisplayPort::EmbeddedDisplayPort() 1183 : 1184 DisplayPort(INTEL_PORT_A, "Embedded DisplayPort") 1185 { 1186 } 1187 1188 1189 bool 1190 EmbeddedDisplayPort::IsConnected() 1191 { 1192 addr_t portRegister = _PortRegister(); 1193 1194 TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), 1195 portRegister); 1196 1197 if (!gInfo->shared_info->device_type.IsMobile()) { 1198 TRACE("%s: skipping eDP on non-mobile GPU\n", __func__); 1199 return false; 1200 } 1201 1202 if ((read32(portRegister) & DISPLAY_MONITOR_PORT_DETECTED) == 0) { 1203 TRACE("%s: %s link not detected\n", __func__, PortName()); 1204 return false; 1205 } 1206 1207 HasEDID(); 1208 1209 // If eDP has EDID, awesome. We use it. 1210 // No EDID? The modesetting code falls back to VBIOS panel_mode 1211 return true; 1212 } 1213 1214 1215 // #pragma mark - Digital Display Port 1216 1217 1218 DigitalDisplayInterface::DigitalDisplayInterface(port_index index, 1219 const char* baseName) 1220 : 1221 Port(index, baseName) 1222 { 1223 // As of Haswell, Intel decided to change eDP ports to a "DDI" bus... 1224 // on a dare because the hardware engineers were drunk one night. 1225 } 1226 1227 1228 addr_t 1229 DigitalDisplayInterface::_PortRegister() 1230 { 1231 // TODO: Linux does a DDI_BUF_CTL(INTEL_PORT_A) which is cleaner 1232 // (but we have to ensure the offsets + region base is correct) 1233 switch (PortIndex()) { 1234 case INTEL_PORT_A: 1235 return DDI_BUF_CTL_A; 1236 case INTEL_PORT_B: 1237 return DDI_BUF_CTL_B; 1238 case INTEL_PORT_C: 1239 return DDI_BUF_CTL_C; 1240 case INTEL_PORT_D: 1241 return DDI_BUF_CTL_D; 1242 case INTEL_PORT_E: 1243 return DDI_BUF_CTL_E; 1244 default: 1245 return 0; 1246 } 1247 return 0; 1248 } 1249 1250 1251 addr_t 1252 DigitalDisplayInterface::_DDCRegister() 1253 { 1254 // TODO: No idea, does DDI have DDC? 1255 return 0; 1256 } 1257 1258 1259 status_t 1260 DigitalDisplayInterface::Power(bool enabled) 1261 { 1262 TRACE("%s: %s DDI enabled: %s\n", __func__, PortName(), 1263 enabled ? "true" : "false"); 1264 1265 fPipe->Enable(enabled); 1266 1267 addr_t portRegister = _PortRegister(); 1268 uint32 state = read32(portRegister); 1269 write32(portRegister, 1270 enabled ? (state | DDI_BUF_CTL_ENABLE) : (state & ~DDI_BUF_CTL_ENABLE)); 1271 read32(portRegister); 1272 1273 return B_OK; 1274 } 1275 1276 1277 bool 1278 DigitalDisplayInterface::IsConnected() 1279 { 1280 addr_t portRegister = _PortRegister(); 1281 1282 TRACE("%s: %s PortRegister: 0x%" B_PRIxADDR "\n", __func__, PortName(), 1283 portRegister); 1284 1285 if (portRegister == 0) 1286 return false; 1287 1288 if ((read32(portRegister) & DDI_INIT_DISPLAY_DETECTED) == 0) { 1289 TRACE("%s: %s link not detected\n", __func__, PortName()); 1290 return false; 1291 } 1292 1293 // Probe a little port info. 1294 if ((read32(DDI_BUF_CTL_A) & DDI_A_4_LANES) != 0) { 1295 switch (PortIndex()) { 1296 case INTEL_PORT_A: 1297 fMaxLanes = 4; 1298 break; 1299 case INTEL_PORT_E: 1300 fMaxLanes = 0; 1301 break; 1302 default: 1303 fMaxLanes = 4; 1304 break; 1305 } 1306 } else { 1307 switch (PortIndex()) { 1308 case INTEL_PORT_A: 1309 fMaxLanes = 2; 1310 break; 1311 case INTEL_PORT_E: 1312 fMaxLanes = 2; 1313 break; 1314 default: 1315 fMaxLanes = 4; 1316 break; 1317 } 1318 } 1319 1320 TRACE("%s: %s Maximum Lanes: %" B_PRId8 "\n", __func__, 1321 PortName(), fMaxLanes); 1322 1323 //since EDID is not correctly implemented yet for this connection type we'll do without it for now 1324 //return HasEDID(); 1325 TRACE("%s: %s link detected\n", __func__, PortName()); 1326 return true; 1327 } 1328 1329 1330 status_t 1331 DigitalDisplayInterface::SetDisplayMode(display_mode* target, uint32 colorMode) 1332 { 1333 CALLED(); 1334 TRACE("%s: %s %dx%d\n", __func__, PortName(), target->virtual_width, 1335 target->virtual_height); 1336 1337 if (fPipe == NULL) { 1338 ERROR("%s: Setting display mode without assigned pipe!\n", __func__); 1339 return B_ERROR; 1340 } 1341 1342 // Setup PanelFitter and Train FDI if it exists 1343 PanelFitter* fitter = fPipe->PFT(); 1344 if (fitter != NULL) 1345 fitter->Enable(*target); 1346 // Skip FDI if we have a CPU connected display 1347 if (PortIndex() != INTEL_PORT_A) { 1348 FDILink* link = fPipe->FDI(); 1349 if (link != NULL) 1350 link->Train(target); 1351 } 1352 1353 pll_divisors divisors; 1354 compute_pll_divisors(target, &divisors, false); 1355 1356 uint32 extraPLLFlags = 0; 1357 if (gInfo->shared_info->device_type.Generation() >= 3) 1358 extraPLLFlags |= DISPLAY_PLL_MODE_NORMAL | DISPLAY_PLL_2X_CLOCK; 1359 1360 // Program general pipe config 1361 fPipe->Configure(target); 1362 1363 // Program pipe PLL's 1364 fPipe->ConfigureClocks(divisors, target->timing.pixel_clock, extraPLLFlags); 1365 1366 // Program target display mode 1367 fPipe->ConfigureTimings(target); 1368 1369 // Set fCurrentMode to our set display mode 1370 memcpy(&fCurrentMode, target, sizeof(display_mode)); 1371 1372 return B_OK; 1373 } 1374