From 4492fde7bf7c5e9bfeb1a6d71de9da3a0dfbf6ae Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Wed, 27 Oct 2021 14:46:04 +0200 Subject: [PATCH] intel_extreme: reduce use of display_mode where display_timing is enough In most cases we don't need to use the complete display_mode struct and we just need the timings. This will avoid future confusion between the virtual width/height and the actual display timings, if we implement scrolling someday. Change-Id: I6c4430b84130b956a47ea0a01afb0843f5a34fd2 Reviewed-on: https://review.haiku-os.org/c/haiku/+/4665 Reviewed-by: waddlesplash --- .../graphics/intel_extreme/intel_extreme.h | 2 +- .../FlexibleDisplayInterface.cpp | 8 +- .../intel_extreme/FlexibleDisplayInterface.h | 2 +- .../accelerants/intel_extreme/PanelFitter.cpp | 4 +- .../accelerants/intel_extreme/PanelFitter.h | 2 +- .../accelerants/intel_extreme/Ports.cpp | 39 ++++----- .../accelerants/intel_extreme/mode.cpp | 16 +++- src/add-ons/accelerants/intel_extreme/pll.cpp | 18 ++-- src/add-ons/accelerants/intel_extreme/pll.h | 2 +- .../drivers/graphics/intel_extreme/bios.cpp | 87 ++++++------------- .../graphics/intel_extreme/intel_extreme.cpp | 2 +- .../intel_extreme/intel_extreme_private.h | 2 +- 12 files changed, 77 insertions(+), 107 deletions(-) diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 99dc9eaa09..75de2cfd43 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -249,7 +249,7 @@ struct intel_shared_info { uint32 mode_count; display_mode current_mode; // pretty much a hack until per-display modes - display_mode panel_mode; // VBIOS VBT panel mode + display_timing panel_timing; // Hardware timings of the LVDS panel, extracted from BIOS uint32 bytes_per_row; uint32 bits_per_pixel; uint32 dpms_mode; diff --git a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.cpp index f627d212b1..54e0eaf31c 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_mode* target) +FDILink::Train(display_timing* target) { CALLED(); @@ -284,7 +284,7 @@ FDILink::Train(display_mode* target) // Khz / 10. ( each output octet encoded as 10 bits. uint32 linkBandwidth = gInfo->shared_info->fdi_link_frequency * 1000 / 10; //Reserving 5% bandwidth for possible spread spectrum clock use - uint32 bps = target->timing.pixel_clock * bitsPerPixel * 21 / 20; + uint32 bps = target->pixel_clock * bitsPerPixel * 21 / 20; //use DIV_ROUND_UP: uint32 lanes = (bps + (linkBandwidth * 8) - 1) / (linkBandwidth * 8); @@ -338,7 +338,7 @@ FDILink::Train(display_mode* target) if (ret_n > 0x800000) { ret_n = 0x800000; } - uint64 ret_m = target->timing.pixel_clock * ret_n * bitsPerPixel / linkspeed; + uint64 ret_m = target->pixel_clock * ret_n * bitsPerPixel / linkspeed; while ((ret_n > 0xffffff) || (ret_m > 0xffffff)) { ret_m >>= 1; ret_n >>= 1; @@ -356,7 +356,7 @@ FDILink::Train(display_mode* target) if (ret_n > 0x800000) { ret_n = 0x800000; } - ret_m = target->timing.pixel_clock * ret_n / linkspeed; + ret_m = target->pixel_clock * ret_n / linkspeed; while ((ret_n > 0xffffff) || (ret_m > 0xffffff)) { ret_m >>= 1; ret_n >>= 1; diff --git a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h index d6220ca6f2..aac632fec8 100644 --- a/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h +++ b/src/add-ons/accelerants/intel_extreme/FlexibleDisplayInterface.h @@ -65,7 +65,7 @@ public: FDIReceiver& Receiver() { return fReceiver; }; - status_t Train(display_mode* target); + status_t Train(display_timing* target); private: status_t _NormalTrain(uint32 lanes); diff --git a/src/add-ons/accelerants/intel_extreme/PanelFitter.cpp b/src/add-ons/accelerants/intel_extreme/PanelFitter.cpp index d6959628a7..4d15f31905 100644 --- a/src/add-ons/accelerants/intel_extreme/PanelFitter.cpp +++ b/src/add-ons/accelerants/intel_extreme/PanelFitter.cpp @@ -59,7 +59,7 @@ PanelFitter::IsEnabled() void -PanelFitter::Enable(const display_mode& mode) +PanelFitter::Enable(const display_timing& timing) { _Enable(true); @@ -69,7 +69,7 @@ PanelFitter::Enable(const display_mode& mode) TRACE("%s: PCH_PANEL_FITTER_WINDOW_POS, 0x%" B_PRIx32 "\n", __func__, read32(fRegisterBase + PCH_PANEL_FITTER_WINDOW_POS)); // Window size _must_ be the last register programmed as it 'arms'/unlocks all the other ones.. - write32(fRegisterBase + PCH_PANEL_FITTER_WINDOW_SIZE, (mode.timing.h_display << 16) | mode.timing.v_display); + write32(fRegisterBase + PCH_PANEL_FITTER_WINDOW_SIZE, (timing.h_display << 16) | timing.v_display); } diff --git a/src/add-ons/accelerants/intel_extreme/PanelFitter.h b/src/add-ons/accelerants/intel_extreme/PanelFitter.h index 8d2ce11009..2f1267fe2d 100644 --- a/src/add-ons/accelerants/intel_extreme/PanelFitter.h +++ b/src/add-ons/accelerants/intel_extreme/PanelFitter.h @@ -17,7 +17,7 @@ public: virtual ~PanelFitter(); bool IsEnabled(); - void Enable(const display_mode& mode); + void Enable(const display_timing& timing); void Disable(); private: diff --git a/src/add-ons/accelerants/intel_extreme/Ports.cpp b/src/add-ons/accelerants/intel_extreme/Ports.cpp index 9447ae73f1..f6c1e26d7b 100644 --- a/src/add-ons/accelerants/intel_extreme/Ports.cpp +++ b/src/add-ons/accelerants/intel_extreme/Ports.cpp @@ -363,13 +363,13 @@ AnalogPort::SetDisplayMode(display_mode* target, uint32 colorMode) // Setup PanelFitter and Train FDI if it exists PanelFitter* fitter = fPipe->PFT(); if (fitter != NULL) - fitter->Enable(*target); + fitter->Enable(target->timing); FDILink* link = fPipe->FDI(); if (link != NULL) - link->Train(target); + link->Train(&target->timing); pll_divisors divisors; - compute_pll_divisors(target, &divisors, false); + compute_pll_divisors(&target->timing, &divisors, false); uint32 extraPLLFlags = 0; if (gInfo->shared_info->device_type.Generation() >= 3) @@ -561,7 +561,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) // For LVDS panels, we may need to set the timings according to the panel // native video mode, and let the panel fitter do the scaling. But the // place where the scaling happens varies accross generations of devices. - display_mode hardwareTarget; + display_timing hardwareTarget; bool needsScaling = false; // TODO figure out how it's done (or if we need to configure something at @@ -570,25 +570,20 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) && gInfo->shared_info->device_type.Generation() >= 3 && gInfo->shared_info->got_vbt) { // Set vbios hardware panel mode as base - hardwareTarget = gInfo->shared_info->panel_mode; + hardwareTarget = gInfo->shared_info->panel_timing; - if (hardwareTarget.timing.h_display == target->timing.h_display - && hardwareTarget.timing.v_display == target->timing.v_display) { + 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 TRACE("Setting LVDS to native mode\n"); - hardwareTarget = *target; + hardwareTarget = target->timing; } else { // We need to enable the panel fitter TRACE("%s: hardware mode will actually be %dx%d\n", __func__, - hardwareTarget.timing.h_display, hardwareTarget.timing.v_display); + hardwareTarget.h_display, hardwareTarget.v_display); - hardwareTarget.space = target->space; - // retain requested virtual size - hardwareTarget.virtual_width = target->virtual_width; - hardwareTarget.virtual_height = target->virtual_height; // FIXME we should also get the refresh frequency from the target // mode, and then "sanitize" the resulting mode we made up. - needsScaling = true; } } else { @@ -596,7 +591,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) "generation, scaling may not work\n"); // We don't have VBT data, try to set the requested mode directly // and hope for the best - hardwareTarget = *target; + hardwareTarget = target->timing; } // Setup PanelFitter and Train FDI if it exists @@ -664,7 +659,7 @@ LVDSPort::SetDisplayMode(display_mode* target, uint32 colorMode) // Program pipe PLL's (using the hardware mode timings, since that's what // the PLL is used for) - fPipe->ConfigureClocks(divisors, hardwareTarget.timing.pixel_clock, + fPipe->ConfigureClocks(divisors, hardwareTarget.pixel_clock, extraPLLFlags); if (gInfo->shared_info->device_type.Generation() != 4) { @@ -799,13 +794,13 @@ DigitalPort::SetDisplayMode(display_mode* target, uint32 colorMode) // Setup PanelFitter and Train FDI if it exists PanelFitter* fitter = fPipe->PFT(); if (fitter != NULL) - fitter->Enable(*target); + fitter->Enable(target->timing); FDILink* link = fPipe->FDI(); if (link != NULL) - link->Train(target); + link->Train(&target->timing); pll_divisors divisors; - compute_pll_divisors(target, &divisors, false); + compute_pll_divisors(&target->timing, &divisors, false); uint32 extraPLLFlags = 0; if (gInfo->shared_info->device_type.Generation() >= 3) @@ -1345,16 +1340,16 @@ DigitalDisplayInterface::SetDisplayMode(display_mode* target, uint32 colorMode) // Setup PanelFitter and Train FDI if it exists PanelFitter* fitter = fPipe->PFT(); if (fitter != NULL) - fitter->Enable(*target); + fitter->Enable(target->timing); // Skip FDI if we have a CPU connected display if (PortIndex() != INTEL_PORT_A) { FDILink* link = fPipe->FDI(); if (link != NULL) - link->Train(target); + link->Train(&target->timing); } pll_divisors divisors; - compute_pll_divisors(target, &divisors, false); + compute_pll_divisors(&target->timing, &divisors, false); uint32 extraPLLFlags = 0; if (gInfo->shared_info->device_type.Generation() >= 3) diff --git a/src/add-ons/accelerants/intel_extreme/mode.cpp b/src/add-ons/accelerants/intel_extreme/mode.cpp index a1a23decfb..1937fdc53e 100644 --- a/src/add-ons/accelerants/intel_extreme/mode.cpp +++ b/src/add-ons/accelerants/intel_extreme/mode.cpp @@ -179,9 +179,9 @@ limit_modes_for_gen3_lvds(display_mode* mode) // display. // FIXME do this only for that display. The whole display mode logic // needs to be adjusted to know which display we're talking about. - if (gInfo->shared_info->panel_mode.timing.h_display < mode->timing.h_display) + if (gInfo->shared_info->panel_timing.h_display < mode->timing.h_display) return false; - if (gInfo->shared_info->panel_mode.timing.v_display < mode->timing.v_display) + if (gInfo->shared_info->panel_timing.v_display < mode->timing.v_display) return false; return true; @@ -230,9 +230,17 @@ create_mode_list(void) if (gInfo->shared_info->device_type.Generation() < 4) limitModes = limit_modes_for_gen3_lvds; + display_mode mode; + mode.timing = gInfo->shared_info->panel_timing; + mode.space = B_RGB32; + mode.virtual_width = mode.timing.h_display; + mode.virtual_height = mode.timing.v_display; + mode.h_display_start = 0; + mode.v_display_start = 0; + mode.flags = 0; + // TODO: support lower modes via scaling and windowing - gInfo->mode_list_area = create_display_modes("intel extreme modes", - NULL, &gInfo->shared_info->panel_mode, 1, + gInfo->mode_list_area = create_display_modes("intel extreme modes", NULL, &mode, 1, supportedSpaces, colorSpaceCount, limitModes, &list, &count); } else { // Otherwise return the 'real' list of modes diff --git a/src/add-ons/accelerants/intel_extreme/pll.cpp b/src/add-ons/accelerants/intel_extreme/pll.cpp index 3260009576..8e887035dc 100644 --- a/src/add-ons/accelerants/intel_extreme/pll.cpp +++ b/src/add-ons/accelerants/intel_extreme/pll.cpp @@ -184,9 +184,9 @@ static pll_limits kLimitsPinLvds = { static bool -lvds_dual_link(display_mode* current) +lvds_dual_link(display_timing* current) { - float requestedPixelClock = current->timing.pixel_clock / 1000.0f; + float requestedPixelClock = current->pixel_clock / 1000.0f; if (requestedPixelClock > 112.999) return true; @@ -215,7 +215,7 @@ valid_pll_divisors(pll_divisors* divisors, pll_limits* limits) static void -compute_pll_p2(display_mode* current, pll_divisors* divisors, +compute_pll_p2(display_timing* current, pll_divisors* divisors, pll_limits* limits, bool isLVDS) { if (isLVDS) { @@ -227,7 +227,7 @@ compute_pll_p2(display_mode* current, pll_divisors* divisors, divisors->p2 = limits->max.p2; } } else { - if (current->timing.pixel_clock < limits->dot_limit) { + if (current->pixel_clock < limits->dot_limit) { // slow DAC timing divisors->p2 = limits->max.p2; } else { @@ -269,9 +269,9 @@ compute_pll_p(pll_divisors* divisors) static void -compute_dpll_g4x(display_mode* current, pll_divisors* divisors, bool isLVDS) +compute_dpll_g4x(display_timing* current, pll_divisors* divisors, bool isLVDS) { - float requestedPixelClock = current->timing.pixel_clock / 1000.0f; + float requestedPixelClock = current->pixel_clock / 1000.0f; float referenceClock = gInfo->shared_info->pll_info.reference_frequency / 1000.0f; @@ -363,9 +363,9 @@ compute_dpll_g4x(display_mode* current, pll_divisors* divisors, bool isLVDS) static void -compute_dpll_9xx(display_mode* current, pll_divisors* divisors, bool isLVDS) +compute_dpll_9xx(display_timing* current, pll_divisors* divisors, bool isLVDS) { - float requestedPixelClock = current->timing.pixel_clock / 1000.0f; + float requestedPixelClock = current->pixel_clock / 1000.0f; float referenceClock = gInfo->shared_info->pll_info.reference_frequency / 1000.0f; @@ -447,7 +447,7 @@ compute_dpll_9xx(display_mode* current, pll_divisors* divisors, bool isLVDS) void -compute_pll_divisors(display_mode* current, pll_divisors* divisors, bool isLVDS) +compute_pll_divisors(display_timing* current, pll_divisors* divisors, bool isLVDS) { if (gInfo->shared_info->device_type.InGroup(INTEL_GROUP_G4x) || (gInfo->shared_info->pch_info != INTEL_PCH_NONE)) { diff --git a/src/add-ons/accelerants/intel_extreme/pll.h b/src/add-ons/accelerants/intel_extreme/pll.h index d30edd2c46..57373925aa 100644 --- a/src/add-ons/accelerants/intel_extreme/pll.h +++ b/src/add-ons/accelerants/intel_extreme/pll.h @@ -33,7 +33,7 @@ struct pll_limits { bool valid_pll_divisors(pll_divisors* divisors, pll_limits* limits); -void compute_pll_divisors(display_mode* current, pll_divisors* divisors, +void compute_pll_divisors(display_timing* current, pll_divisors* divisors, bool isLVDS); void refclk_activate_ilk(bool hasPanel); diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/bios.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/bios.cpp index 41395bc2ec..4889c0f706 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/bios.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/bios.cpp @@ -102,16 +102,6 @@ struct lvds_bdb2_lfp_info { static struct vbios { area_id area; uint8* memory; - display_mode* shared_info; - struct { - uint16 hsync_start; - uint16 hsync_end; - uint16 hsync_total; - uint16 vsync_start; - uint16 vsync_end; - uint16 vsync_total; - } timings_common; - uint16_t ReadWord(off_t address) { return memory[address] | memory[address + 1] << 8; @@ -160,57 +150,37 @@ get_bios(void) } -static bool -feed_shared_info(uint8* data) +static void +sanitize_panel_timing(display_timing& timing) { bool bogus = false; /* handle bogus h/vtotal values, if got such */ - if (vbios.timings_common.hsync_end > vbios.timings_common.hsync_total) { - vbios.timings_common.hsync_total = vbios.timings_common.hsync_end + 1; + if (timing.h_sync_end > timing.h_total) { + timing.h_total = timing.h_sync_end + 1; bogus = true; TRACE((DEVICE_NAME": got bogus htotal. Fixing\n")); } - if (vbios.timings_common.vsync_end > vbios.timings_common.vsync_total) { - vbios.timings_common.vsync_total = vbios.timings_common.vsync_end + 1; + if (timing.v_sync_end > timing.v_total) { + timing.v_total = timing.v_sync_end + 1; bogus = true; TRACE((DEVICE_NAME": got bogus vtotal. Fixing\n")); } if (bogus) { - TRACE((DEVICE_NAME": adjusted LFP modeline: x%d Hz,\t" + TRACE((DEVICE_NAME": adjusted LFP modeline: %" B_PRIu32 " KHz,\t" "%d %d %d %d %d %d %d %d\n", - _PIXEL_CLOCK(data) / ((_H_ACTIVE(data) + _H_BLANK(data)) - * (_V_ACTIVE(data) + _V_BLANK(data))), - _H_ACTIVE(data), vbios.timings_common.hsync_start, - vbios.timings_common.hsync_end, vbios.timings_common.hsync_total, - _V_ACTIVE(data), vbios.timings_common.vsync_start, - vbios.timings_common.vsync_end, vbios.timings_common.vsync_total)); + timing.pixel_clock / (timing.h_total * timing.v_total), + timing.h_display, timing.h_sync_start, + timing.h_sync_end, timing.h_total, + timing.v_display, timing.v_sync_start, + timing.v_sync_end, timing.v_total)); } - - /* TODO: add retrieved info to edid info struct, not fixed mode struct */ - - /* struct display_timing is not packed, so we have to set elements - individually */ - vbios.shared_info->timing.pixel_clock = _PIXEL_CLOCK(data) / 1000; - vbios.shared_info->timing.h_display = vbios.shared_info->virtual_width - = _H_ACTIVE(data); - vbios.shared_info->timing.h_sync_start = vbios.timings_common.hsync_start; - vbios.shared_info->timing.h_sync_end = vbios.timings_common.hsync_end; - vbios.shared_info->timing.h_total = vbios.timings_common.hsync_total; - vbios.shared_info->timing.v_display = vbios.shared_info->virtual_height - = _V_ACTIVE(data); - vbios.shared_info->timing.v_sync_start = vbios.timings_common.vsync_start; - vbios.shared_info->timing.v_sync_end = vbios.timings_common.vsync_end; - vbios.shared_info->timing.v_total = vbios.timings_common.vsync_total; - - delete_area(vbios.area); - return true; } bool -get_lvds_mode_from_bios(display_mode* sharedInfo) +get_lvds_mode_from_bios(display_timing* panelTiming) { if (!get_bios()) return false; @@ -276,27 +246,24 @@ get_lvds_mode_from_bios(display_mode* sharedInfo) "in BIOS VBT tables\n", lvds2_lfp_info->x_res, lvds2_lfp_info->y_res)); - vbios.timings_common.hsync_start = _H_ACTIVE(timing_data) - + _H_SYNC_OFF(timing_data); - vbios.timings_common.hsync_end - = vbios.timings_common.hsync_start - + _H_SYNC_WIDTH(timing_data); - vbios.timings_common.hsync_total = _H_ACTIVE(timing_data) - + _H_BLANK(timing_data); - vbios.timings_common.vsync_start = _V_ACTIVE(timing_data) - + _V_SYNC_OFF(timing_data); - vbios.timings_common.vsync_end - = vbios.timings_common.vsync_start - + _V_SYNC_WIDTH(timing_data); - vbios.timings_common.vsync_total = _V_ACTIVE(timing_data) - + _V_BLANK(timing_data); + panelTiming->pixel_clock = _PIXEL_CLOCK(timing_data) / 1000; + panelTiming->h_sync_start = _H_ACTIVE(timing_data) + _H_SYNC_OFF(timing_data); + panelTiming->h_sync_end = panelTiming->h_sync_start + _H_SYNC_WIDTH(timing_data); + panelTiming->h_total = _H_ACTIVE(timing_data) + _H_BLANK(timing_data); + panelTiming->h_display = _H_ACTIVE(timing_data); + panelTiming->v_sync_start = _V_ACTIVE(timing_data) + _V_SYNC_OFF(timing_data); + panelTiming->v_sync_end = panelTiming->v_sync_start + _V_SYNC_WIDTH(timing_data); + panelTiming->v_total = _V_ACTIVE(timing_data) + _V_BLANK(timing_data); + panelTiming->v_display = _V_ACTIVE(timing_data); + panelTiming->flags = 0; - vbios.shared_info = sharedInfo; - return feed_shared_info(timing_data); + sanitize_panel_timing(*panelTiming); + delete_area(vbios.area); + return true; } } } delete_area(vbios.area); - return true; + return false; } diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp index 1136cd1aba..a49eb23c10 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp @@ -446,7 +446,7 @@ intel_extreme_init(intel_info &info) // Pull VBIOS panel mode for later use info.shared_info->got_vbt = get_lvds_mode_from_bios( - &info.shared_info->panel_mode); + &info.shared_info->panel_timing); /* at least 855gm can't drive more than one head at time */ if (info.device_type.InFamily(INTEL_FAMILY_8xx)) diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme_private.h b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme_private.h index 3c4a0b48d0..94fc955981 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme_private.h +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme_private.h @@ -72,7 +72,7 @@ find_reg(const intel_info& info, uint32 target) } -extern bool get_lvds_mode_from_bios(display_mode *mode); +extern bool get_lvds_mode_from_bios(display_timing *timing); extern status_t intel_free_memory(intel_info& info, addr_t offset); extern status_t intel_allocate_memory(intel_info& info, size_t size, size_t alignment, uint32 flags, addr_t* _offset,