]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/amd/display: Guard against setting dispclk low for dcn31x
authorJing Zhou <Jing.Zhou@amd.com>
Tue, 4 Mar 2025 15:15:56 +0000 (23:15 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 29 May 2025 09:12:36 +0000 (11:12 +0200)
[ 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>
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c

index a0fb4481d2f1b10224daf3b0113f8d068a233e6a..827b24b3442adb00f624423cbd6a214cd51723e9 100644 (file)
@@ -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;
        }
index c3e50c3aaa609ee5798f291d2d150deef88a1f2d..37c39756fece4ee4e7b27980b7371eb9ad813dfc 100644 (file)
@@ -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;