[PATCH 26/34] drm/amd/display: Force FreeSync range minimum on quirky panels
Tom Chung <[email protected]> Wed, 5 Aug 2026 14:36:38 +0800
| Newsgroups | org.freedesktop.lists.amd-gfx |
|---|---|
| Message-ID | <[email protected]> |
From: Fangzhi Zuo <[email protected]> [why] Some panels advertise a FreeSync range minimum that does not operate reliably at the low end: - X34GS (EDID panel id ACR 0x08AF) reports a minimum that can flicker or drop out when the refresh rate approaches the reported minimum. - 34w-30 (EDID panel id LEN 0x66F1) reports a 48 Hz minimum over DisplayPort, but the panel fails to light up at that minimum, resulting in a black screen. Forcing the minimum to 60 Hz avoids the black screen and lets the display light up normally. [how] - Add a force_freesync_min_hz field to struct dc_panel_patch. - Add apply_edid_quirks() cases keyed on the affected panel ids that set force_freesync_min_hz (55 Hz for the X34GS, 60 Hz for the G34w-30). - In amdgpu_dm_update_freesync_caps(), when the quirk is set and the sink is otherwise FreeSync capable, clamp the reported VRR range minimum (min_vfreq and monitor_range.min_vfreq) to the quirked value. - Add a KUnit test covering the new quirk. Reviewed-by: George Zhang <[email protected]> Signed-off-by: Fangzhi Zuo <[email protected]> Signed-off-by: Tom Chung <[email protected]> --- .../display/amdgpu_dm/amdgpu_dm_connector.c | 12 ++++++++++++ .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 18 ++++++++++++++++++ .../amdgpu_dm/tests/amdgpu_dm_helpers_test.c | 17 +++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc_types.h | 1 + 4 files changed, 48 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c index 4304520d2484..2cc3734c992b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_connector.c @@ -3880,6 +3880,18 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, } } + /* + * Apply per-monitor FreeSync range quirks. Some panels report a + * VRR minimum that does not operate reliably; force it when the + * monitor is quirked (see apply_edid_quirks()). + */ + if (sink->edid_caps.panel_patch.force_freesync_min_hz && freesync_capable) { + amdgpu_dm_connector->min_vfreq = + sink->edid_caps.panel_patch.force_freesync_min_hz; + connector->display_info.monitor_range.min_vfreq = + amdgpu_dm_connector->min_vfreq; + } + /* Handle MCCS */ if (do_mccs) dm_helpers_read_mccs_caps(adev->dm.dc->ctx, amdgpu_dm_connector->dc_link, sink); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index d451082552e8..b05455498cbf 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -147,6 +147,24 @@ STATIC_IFN_KUNIT void apply_edid_quirks(struct dc_link *link, struct edid *edid, drm_dbg_driver(dev, "Hiding secondary tile on panel id %X\n", panel_id); edid_caps->panel_patch.disable_second_tile = true; break; + /* + * Workaround for the Acer Predator X34GS which reports a FreeSync + * minimum refresh rate that does not operate reliably. Force the + * FreeSync range minimum to 55 Hz. + */ + case drm_edid_encode_panel_id('A', 'C', 'R', 0x08AF): + drm_dbg_driver(dev, "Force FreeSync min to 55 Hz on panel id %X\n", panel_id); + edid_caps->panel_patch.force_freesync_min_hz = 55; + break; + /* + * Workaround for the Lenovo G34w-30 which reports a FreeSync + * minimum refresh rate (48 Hz) that fails to light up over DP. + * Force the FreeSync range minimum to 60 Hz. + */ + case drm_edid_encode_panel_id('L', 'E', 'N', 0x66F1): + drm_dbg_driver(dev, "Force FreeSync min to 60 Hz on panel id %X\n", panel_id); + edid_caps->panel_patch.force_freesync_min_hz = 60; + break; default: return; } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c index 058e1ad15dfe..5de697ca0fcc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c @@ -186,6 +186,22 @@ static void dm_test_apply_edid_quirks_skip_phy_ssc(struct kunit *test) KUNIT_EXPECT_TRUE(test, link->wa_flags.skip_phy_ssc_reduction); } +/** + * dm_test_apply_edid_quirks_force_freesync_min - Test ACR 0x08AF FreeSync min quirk + * @test: The KUnit test context + */ +static void dm_test_apply_edid_quirks_force_freesync_min(struct kunit *test) +{ + struct dc_edid_caps edid_caps = {0}; + struct dc_link *link = dm_test_quirk_link(test); + struct edid *edid = dm_test_edid_with_panel_id(test, + drm_edid_encode_panel_id('A', 'C', 'R', 0x08AF)); + + apply_edid_quirks(link, edid, &edid_caps); + + KUNIT_EXPECT_EQ(test, edid_caps.panel_patch.force_freesync_min_hz, 55U); +} + /** * dm_test_apply_edid_quirks_unknown_noop - Test unknown panel id is a no-op * @test: The KUnit test context @@ -3724,6 +3740,7 @@ static struct kunit_case amdgpu_dm_helpers_test_cases[] = { KUNIT_CASE(dm_test_apply_edid_quirks_remove_sink_ext_caps), KUNIT_CASE(dm_test_apply_edid_quirks_disable_colorimetry), KUNIT_CASE(dm_test_apply_edid_quirks_skip_phy_ssc), + KUNIT_CASE(dm_test_apply_edid_quirks_force_freesync_min), KUNIT_CASE(dm_test_apply_edid_quirks_unknown_noop), /* dm_helpers_parse_edid_caps */ KUNIT_CASE(dm_test_parse_edid_caps_null_edid), diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 7da673111ed9..64b4adee36c4 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -194,6 +194,7 @@ struct dc_panel_patch { bool oled_optimize_display_on; unsigned int force_mst_blocked_discovery; unsigned int wait_after_dpcd_poweroff_ms; + unsigned int force_freesync_min_hz; }; /** -- 2.43.0