From ba0c9427cda0810ac8d42163b41836c94dab5205 Mon Sep 17 00:00:00 2001 From: Rudolf Cornelissen Date: Sun, 30 Jan 2022 00:21:32 +0000 Subject: [PATCH] intel_extreme: for Ivy/SandyBridge added eDP programming for laptops. --- .../graphics/intel_extreme/intel_extreme.h | 2 +- .../FlexibleDisplayInterface.cpp | 3 +- .../accelerants/intel_extreme/Ports.cpp | 56 ++++++++++++++++--- .../accelerants/intel_extreme/accelerant.cpp | 3 + 4 files changed, 53 insertions(+), 11 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 9ca3f3512e..224e7f2140 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -1248,7 +1248,7 @@ struct intel_free_graphics_memory { #define FDI_LINK_TRAIN_PRE_EMPHASIS_2X (2 << 22) #define FDI_LINK_TRAIN_PRE_EMPHASIS_3X (3 << 22) -//FDI PIPE M/N DATA AND LINK VALUES (refreshrate) +//(FDI) PIPE M/N DATA AND LINK VALUES (refreshrate) #define PCH_FDI_PIPE_A_DATA_M1 0x0030 #define PCH_FDI_PIPE_A_DATA_M2 0x0038 #define PCH_FDI_PIPE_B_DATA_M1 0x1030 diff --git a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp index 54e0eaf31c..b062c0e314 100644 --- a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp +++ b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp @@ -250,7 +250,7 @@ FDILink::FDILink(pipe_index pipeIndex) status_t -FDILink::Train(display_timing* target) +FDILink::Train(display_timing* target) // fixme: seperate FDI training and PIPE M/N programming.. { CALLED(); @@ -282,6 +282,7 @@ FDILink::Train(display_timing* target) TRACE("%s: FDI Link Colordepth: %" B_PRIu32 "\n", __func__, bitsPerPixel); // Khz / 10. ( each output octet encoded as 10 bits. + // note: if used for eDP (PORT_A) might be we should check reg. DP_CTL (0x64000), bit 16-17 (Ivy). uint32 linkBandwidth = gInfo->shared_info->fdi_link_frequency * 1000 / 10; //Reserving 5% bandwidth for possible spread spectrum clock use uint32 bps = target->pixel_clock * bitsPerPixel * 21 / 20; diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 6e5c6040a4..5ad4d25415 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -1301,18 +1301,56 @@ DisplayPort::SetDisplayMode(display_mode* target, uint32 colorMode) fPipe->ConfigureTimings(target); result = _SetPortLinkGen4(target->timing); } else { - result = _SetPortLinkGen6(target->timing); + display_timing hardwareTarget = target->timing; + bool needsScaling = false; + if ((PortIndex() == INTEL_PORT_A) && gInfo->shared_info->device_type.IsMobile()) { + // For internal panels, we may need to set the timings according to the panel + // native video mode, and let the panel fitter do the scaling. + // note: upto/including generation 5 laptop panels are still LVDS types, handled elsewhere. + + if (gInfo->shared_info->got_vbt) { + // Set vbios hardware panel mode as base + hardwareTarget = gInfo->shared_info->panel_timing; + + if (hardwareTarget.h_display == target->timing.h_display + && hardwareTarget.v_display == target->timing.v_display) { + // We are setting the native video mode, nothing special to do + // Note: this means refresh and timing might vary according to requested mode. + hardwareTarget = target->timing; + TRACE("%s: Setting internal panel to native resolution at %" B_PRIu32 "Hz\n", __func__, + hardwareTarget.pixel_clock * 1000 / (hardwareTarget.h_total * hardwareTarget.v_total)); + } else { + // We need to enable the panel fitter + TRACE("%s: Hardware mode will actually be %dx%d at %" B_PRIu32 "Hz\n", __func__, + hardwareTarget.h_display, hardwareTarget.v_display, + hardwareTarget.pixel_clock * 1000 / (hardwareTarget.h_total * hardwareTarget.v_total)); + + // FIXME we should also get the refresh frequency from the target + // mode, and then "sanitize" the resulting mode we made up. + needsScaling = true; + } + } else { + TRACE("%s: Setting internal panel mode without VBT info generation, scaling may not work\n", + __func__); + // We don't have VBT data, try to set the requested mode directly + // and hope for the best + hardwareTarget = target->timing; + } + } + + result = B_OK; + if (PortIndex() != INTEL_PORT_A) + result = _SetPortLinkGen6(hardwareTarget); + if (result == B_OK) { // Setup PanelFitter and Train FDI if it exists PanelFitter* fitter = fPipe->PFT(); if (fitter != NULL) - fitter->Enable(target->timing); - // skip FDI if it doesn't exist or we don't use it (eDP) - if ((gInfo->shared_info->device_type.Generation() <= 8) && (PortIndex() != INTEL_PORT_A)) { - FDILink* link = fPipe->FDI(); - if (link != NULL) - link->Train(&target->timing); - } + fitter->Enable(hardwareTarget); + // we should skip FDI if PORT_A, but need pipe M/N programming (is eDP link), so call always for now + FDILink* link = fPipe->FDI(); + if (link != NULL) + link->Train(&target->timing); // Program general pipe config fPipe->Configure(target); @@ -1320,7 +1358,7 @@ DisplayPort::SetDisplayMode(display_mode* target, uint32 colorMode) // Pll programming is not needed for (e)DP.. // Program target display mode - fPipe->ConfigureTimings(target); + fPipe->ConfigureTimings(target, !needsScaling); } else { TRACE("%s: Setting display mode via fallback: using scaling!\n", __func__); // Keep monitor at native mode and scale image to that diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index 967e185e40..4e290f95a0 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -306,6 +306,8 @@ probe_ports() } } +#if 0 + // never execute this as the 'standard' DisplayPort class called above already handles it. if (!gInfo->shared_info->device_type.HasDDI()) { // Ensure DP_A isn't already taken TRACE("Probing eDP\n"); @@ -320,6 +322,7 @@ probe_ports() delete eDPPort; } } +#endif if (!gInfo->shared_info->device_type.HasDDI()) { for (int i = INTEL_PORT_B; i <= INTEL_PORT_D; i++) {