| From db44332141213f6ff471847d0cdbb20a502c8ef0 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 4 Mar 2025 23:15:56 +0800 |
| Subject: drm/amd/display: Guard against setting dispclk low for dcn31x |
| |
| From: Jing Zhou <Jing.Zhou@amd.com> |
| |
| [ Upstream commit 9c2f4ae64bb6f6d83a54d88b9ee0f369cdbb9fa8 ] |
| |
| [WHY] |
| We should never apply a minimum dispclk value while in |
| prepare_bandwidth or while displays are active. This is |
| always an optimizaiton for when all displays are disabled. |
| |
| [HOW] |
| Defer dispclk optimization until safe_to_lower = true |
| and display_count reaches 0. |
| |
| Since 0 has a special value in this logic (ie. no dispclk |
| required) we also need adjust the logic that clamps it for |
| the actual request to PMFW. |
| |
| Reviewed-by: Charlene Liu <charlene.liu@amd.com> |
| Reviewed-by: Chris Park <chris.park@amd.com> |
| Reviewed-by: Eric Yang <eric.yang@amd.com> |
| Signed-off-by: Jing Zhou <Jing.Zhou@amd.com> |
| Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> |
| Signed-off-by: Alex Hung <alex.hung@amd.com> |
| Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> |
| Signed-off-by: Alex Deucher <alexander.deucher@amd.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| .../dc/clk_mgr/dcn315/dcn315_clk_mgr.c | 20 +++++++++++-------- |
| .../dc/clk_mgr/dcn316/dcn316_clk_mgr.c | 13 +++++++++--- |
| 2 files changed, 22 insertions(+), 11 deletions(-) |
| |
| diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c |
| index d4d3f58a613f7..ebeb969ee180b 100644 |
| --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c |
| +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c |
| @@ -130,7 +130,7 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base, |
| struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); |
| struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk; |
| struct dc *dc = clk_mgr_base->ctx->dc; |
| - int display_count; |
| + int display_count = 0; |
| bool update_dppclk = false; |
| bool update_dispclk = false; |
| bool dpp_clock_lowered = false; |
| @@ -204,15 +204,19 @@ static void dcn315_update_clocks(struct clk_mgr *clk_mgr_base, |
| update_dppclk = true; |
| } |
| |
| - if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { |
| - /* No need to apply the w/a if we haven't taken over from bios yet */ |
| - if (clk_mgr_base->clks.dispclk_khz) |
| - dcn315_disable_otg_wa(clk_mgr_base, context, true); |
| + if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) && |
| + (new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) { |
| + int requested_dispclk_khz = new_clocks->dispclk_khz; |
| |
| + dcn315_disable_otg_wa(clk_mgr_base, context, true); |
| + |
| + /* Clamp the requested clock to PMFW based on their limit. */ |
| + if (dc->debug.min_disp_clk_khz > 0 && requested_dispclk_khz < dc->debug.min_disp_clk_khz) |
| + requested_dispclk_khz = dc->debug.min_disp_clk_khz; |
| + |
| + dcn315_smu_set_dispclk(clk_mgr, requested_dispclk_khz); |
| clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; |
| - dcn315_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); |
| - if (clk_mgr_base->clks.dispclk_khz) |
| - dcn315_disable_otg_wa(clk_mgr_base, context, false); |
| + dcn315_disable_otg_wa(clk_mgr_base, context, false); |
| |
| update_dispclk = true; |
| } |
| diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c |
| index a13ead3d21e31..6f1785715dfb7 100644 |
| --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c |
| +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c |
| @@ -140,7 +140,7 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base, |
| struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); |
| struct dc_clocks *new_clocks = &context->bw_ctx.bw.dcn.clk; |
| struct dc *dc = clk_mgr_base->ctx->dc; |
| - int display_count; |
| + int display_count = 0; |
| bool update_dppclk = false; |
| bool update_dispclk = false; |
| bool dpp_clock_lowered = false; |
| @@ -211,11 +211,18 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base, |
| update_dppclk = true; |
| } |
| |
| - if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { |
| + if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) && |
| + (new_clocks->dispclk_khz > 0 || (safe_to_lower && display_count == 0))) { |
| + int requested_dispclk_khz = new_clocks->dispclk_khz; |
| + |
| dcn316_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true); |
| |
| + /* Clamp the requested clock to PMFW based on their limit. */ |
| + if (dc->debug.min_disp_clk_khz > 0 && requested_dispclk_khz < dc->debug.min_disp_clk_khz) |
| + requested_dispclk_khz = dc->debug.min_disp_clk_khz; |
| + |
| + dcn316_smu_set_dispclk(clk_mgr, requested_dispclk_khz); |
| clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; |
| - dcn316_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); |
| dcn316_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false); |
| |
| update_dispclk = true; |
| -- |
| 2.39.5 |
| |