drm/amd/display: Acquire FCLK DPM levels on DCN32
authorDillon Varone <Dillon.Varone@amd.com>
Wed, 28 Sep 2022 19:44:38 +0000 (15:44 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Mon, 10 Oct 2022 21:32:55 +0000 (17:32 -0400)
[Why & How]
Acquire FCLK DPM levels to properly construct DML clock limits. Further
add new logic to keep number of indices for each clock in clk_mgr.

Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Reviewed-by: Jun Lei <Jun.Lei@amd.com>
Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com>
Signed-off-by: Dillon Varone <Dillon.Varone@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h

index 96d5e0d5b3ce03f2b3b0a01af025faf88d30488b..99ae3255dcb91f60c4d80a8dfdca31337afeaff7 100644 (file)
@@ -156,7 +156,7 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
 {
        struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
        unsigned int num_levels;
-       unsigned int num_dcfclk_levels, num_dtbclk_levels, num_dispclk_levels;
+       struct clk_limit_num_entries *num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk;
 
        memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks));
        clk_mgr_base->clks.p_state_change_support = true;
@@ -180,27 +180,28 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
        /* DCFCLK */
        dcn32_init_single_clock(clk_mgr, PPCLK_DCFCLK,
                        &clk_mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz,
-                       &num_levels);
-       num_dcfclk_levels = num_levels;
+                       &num_entries_per_clk->num_dcfclk_levels);
 
        /* SOCCLK */
        dcn32_init_single_clock(clk_mgr, PPCLK_SOCCLK,
                                        &clk_mgr_base->bw_params->clk_table.entries[0].socclk_mhz,
-                                       &num_levels);
+                                       &num_entries_per_clk->num_socclk_levels);
+
        /* DTBCLK */
        if (!clk_mgr->base.ctx->dc->debug.disable_dtb_ref_clk_switch)
                dcn32_init_single_clock(clk_mgr, PPCLK_DTBCLK,
                                &clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz,
-                               &num_levels);
-       num_dtbclk_levels = num_levels;
+                               &num_entries_per_clk->num_dtbclk_levels);
 
        /* DISPCLK */
        dcn32_init_single_clock(clk_mgr, PPCLK_DISPCLK,
                        &clk_mgr_base->bw_params->clk_table.entries[0].dispclk_mhz,
-                       &num_levels);
-       num_dispclk_levels = num_levels;
+                       &num_entries_per_clk->num_dispclk_levels);
+       num_levels = num_entries_per_clk->num_dispclk_levels;
 
-       if (num_dcfclk_levels && num_dtbclk_levels && num_dispclk_levels)
+       if (num_entries_per_clk->num_dcfclk_levels &&
+                       num_entries_per_clk->num_dtbclk_levels &&
+                       num_entries_per_clk->num_dispclk_levels)
                clk_mgr->dpm_present = true;
 
        if (clk_mgr_base->ctx->dc->debug.min_disp_clk_khz) {
@@ -383,7 +384,7 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
                        /* to disable P-State switching, set UCLK min = max */
                        if (!clk_mgr_base->clks.p_state_change_support)
                                dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
-                                               clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries - 1].memclk_mhz);
+                                               clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_memclk_levels - 1].memclk_mhz);
                }
 
                /* Always update saved value, even if new value not set due to P-State switching unsupported. Also check safe_to_lower for FCLK */
@@ -634,7 +635,7 @@ static void dcn32_set_hard_min_memclk(struct clk_mgr *clk_mgr_base, bool current
                                        khz_to_mhz_ceil(clk_mgr_base->clks.dramclk_khz));
                else
                        dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
-                                       clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries - 1].memclk_mhz);
+                                       clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_memclk_levels - 1].memclk_mhz);
        } else {
                dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_UCLK,
                                clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz);
@@ -650,22 +651,34 @@ static void dcn32_set_hard_max_memclk(struct clk_mgr *clk_mgr_base)
                return;
 
        dcn30_smu_set_hard_max_by_freq(clk_mgr, PPCLK_UCLK,
-                       clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries - 1].memclk_mhz);
+                       clk_mgr_base->bw_params->clk_table.entries[clk_mgr_base->bw_params->clk_table.num_entries_per_clk.num_memclk_levels - 1].memclk_mhz);
 }
 
 /* Get current memclk states, update bounding box */
 static void dcn32_get_memclk_states_from_smu(struct clk_mgr *clk_mgr_base)
 {
        struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+       struct clk_limit_num_entries *num_entries_per_clk = &clk_mgr_base->bw_params->clk_table.num_entries_per_clk;
        unsigned int num_levels;
 
        if (!clk_mgr->smu_present)
                return;
 
-       /* Refresh memclk states */
+       /* Refresh memclk and fclk states */
        dcn32_init_single_clock(clk_mgr, PPCLK_UCLK,
                        &clk_mgr_base->bw_params->clk_table.entries[0].memclk_mhz,
-                       &num_levels);
+                       &num_entries_per_clk->num_memclk_levels);
+
+       dcn32_init_single_clock(clk_mgr, PPCLK_FCLK,
+                       &clk_mgr_base->bw_params->clk_table.entries[0].fclk_mhz,
+                       &num_entries_per_clk->num_fclk_levels);
+
+       if (num_entries_per_clk->num_memclk_levels >= num_entries_per_clk->num_fclk_levels) {
+               num_levels = num_entries_per_clk->num_memclk_levels;
+       } else {
+               num_levels = num_entries_per_clk->num_fclk_levels;
+       }
+
        clk_mgr_base->bw_params->clk_table.num_entries = num_levels ? num_levels : 1;
 
        if (clk_mgr->dpm_present && !num_levels)
index d9f1b0a4fbd4ab5874ab9a0f6b14dca6a06073c2..591ab1389e3b3d5a9bfe6ff42c03a08f1e851c00 100644 (file)
@@ -95,10 +95,23 @@ struct clk_limit_table_entry {
        unsigned int wck_ratio;
 };
 
+struct clk_limit_num_entries {
+       unsigned int num_dcfclk_levels;
+       unsigned int num_fclk_levels;
+       unsigned int num_memclk_levels;
+       unsigned int num_socclk_levels;
+       unsigned int num_dtbclk_levels;
+       unsigned int num_dispclk_levels;
+       unsigned int num_dppclk_levels;
+       unsigned int num_phyclk_levels;
+       unsigned int num_phyclk_d18_levels;
+};
+
 /* This table is contiguous */
 struct clk_limit_table {
        struct clk_limit_table_entry entries[MAX_NUM_DPM_LVL];
-       unsigned int num_entries;
+       struct clk_limit_num_entries num_entries_per_clk;
+       unsigned int num_entries; /* highest populated dpm level for back compatibility */
 };
 
 struct wm_range_table_entry {