drm/amd/display: Allow DTBCLK disable for DCN35
authorNicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Tue, 14 Nov 2023 16:22:09 +0000 (11:22 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 29 Nov 2023 23:11:03 +0000 (18:11 -0500)
[Why]
DTBCLK is enabled on idle and it will burn power.

[How]
There's a few issues here:
- Always enabling DTBCLK on clock manager init
- Setting refclk when DTBCLK is supposed to be disabled
- Not applying the correct calculated version refclk, but instead the
  base value which might be zero

On dtbclk_en change we'll message PMFW to enable or disable the clock
accordingly.

The DTBDTO will be then based on refclk, but it will be set to the
default fixed value if there was nothing calculated in DML despite the
clock being considered enabled.

Reviewed-by: Charlene Liu <charlene.liu@amd.com>
Acked-by: Tom Chung <chiahsuan.chung@amd.com>
Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c

index 63a0b885b6f03484b14f5a4e8edcbd8d256ea62d..d5fde7d23fbf8e273e349a1bfdfb58fdfad3de7d 100644 (file)
@@ -232,6 +232,10 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
        if (dc->work_arounds.skip_clock_update)
                return;
 
+       /* DTBCLK is fixed, so set a default if unspecified. */
+       if (new_clocks->dtbclk_en && !new_clocks->ref_dtbclk_khz)
+               new_clocks->ref_dtbclk_khz = 600000;
+
        /*
         * if it is safe to lower, but we are already in the lower state, we don't have to do anything
         * also if safe to lower is false, we just go in the higher state
@@ -265,8 +269,10 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
 
                if (!clk_mgr_base->clks.dtbclk_en && new_clocks->dtbclk_en) {
                        dcn35_smu_set_dtbclk(clk_mgr, true);
-                       dcn35_update_clocks_update_dtb_dto(clk_mgr, context, clk_mgr_base->clks.ref_dtbclk_khz);
                        clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en;
+
+                       dcn35_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz);
+                       clk_mgr_base->clks.ref_dtbclk_khz = new_clocks->ref_dtbclk_khz;
                }
 
                /* check that we're not already in D0 */
@@ -314,17 +320,12 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base,
                update_dispclk = true;
        }
 
-       if (!new_clocks->dtbclk_en) {
-               new_clocks->ref_dtbclk_khz = 600000;
-       }
-
        /* clock limits are received with MHz precision, divide by 1000 to prevent setting clocks at every call */
        if (!dc->debug.disable_dtb_ref_clk_switch &&
-                       should_set_clock(safe_to_lower, new_clocks->ref_dtbclk_khz / 1000, clk_mgr_base->clks.ref_dtbclk_khz / 1000)) {
-               /* DCCG requires KHz precision for DTBCLK */
-               dcn35_smu_set_dtbclk(clk_mgr, true);
-
-               dcn35_update_clocks_update_dtb_dto(clk_mgr, context, clk_mgr_base->clks.ref_dtbclk_khz);
+           should_set_clock(safe_to_lower, new_clocks->ref_dtbclk_khz / 1000,
+                            clk_mgr_base->clks.ref_dtbclk_khz / 1000)) {
+               dcn35_update_clocks_update_dtb_dto(clk_mgr, context, new_clocks->ref_dtbclk_khz);
+               clk_mgr_base->clks.ref_dtbclk_khz = new_clocks->ref_dtbclk_khz;
        }
 
        if (dpp_clock_lowered) {
@@ -1048,12 +1049,8 @@ void dcn35_clk_mgr_construct(
        dcn35_dump_clk_registers(&clk_mgr->base.base.boot_snapshot, &clk_mgr->base.base, &log_info);
 
        clk_mgr->base.base.dprefclk_khz = dcn35_smu_get_dprefclk(&clk_mgr->base);
-       clk_mgr->base.base.clks.ref_dtbclk_khz = dcn35_smu_get_dtbclk(&clk_mgr->base);
-
-       if (!clk_mgr->base.base.clks.ref_dtbclk_khz)
-               dcn35_smu_set_dtbclk(&clk_mgr->base, true);
+       clk_mgr->base.base.clks.ref_dtbclk_khz = 600000;
 
-       clk_mgr->base.base.clks.dtbclk_en = true;
        dce_clock_read_ss_info(&clk_mgr->base);
        /*when clk src is from FCH, it could have ss, same clock src as DPREF clk*/