From: Samson Tam <samson....@amd.com>

[Why]
For individual feature testing, PMFW may not report all clock
values back. Driver will default them to 0 but this will
cause the BB table to be skipped and default to one state
with max clocks.

[How]
Add helper function to scan through initial clock values and
populate them with default clock limits so that BB table
can be built.
Add dpm_enabled flag to check when DPM is not enabled and
to trigger helper function.

Reviewed-by: Jun Lei <jun....@amd.com>
Acked-by: Jasdeep Dhillon <jdhil...@amd.com>
Signed-off-by: Samson Tam <samson....@amd.com>
---
 .../display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c  | 14 +++++++
 .../drm/amd/display/dc/dml/dcn32/dcn32_fpu.c  | 39 +++++++++++++++++++
 .../drm/amd/display/dc/dml/dcn32/dcn32_fpu.h  |  2 +
 .../amd/display/dc/inc/hw/clk_mgr_internal.h  |  2 +
 4 files changed, 57 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c 
b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
index c6785969eb1a..f0f3f66629cc 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
@@ -156,12 +156,14 @@ 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;
 
        memset(&(clk_mgr_base->clks), 0, sizeof(struct dc_clocks));
        clk_mgr_base->clks.p_state_change_support = true;
        clk_mgr_base->clks.prev_p_state_change_support = true;
        clk_mgr_base->clks.fclk_prev_p_state_change_support = true;
        clk_mgr->smu_present = false;
+       clk_mgr->dpm_present = false;
 
        if (!clk_mgr_base->bw_params)
                return;
@@ -179,6 +181,7 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
        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;
 
        /* SOCCLK */
        dcn32_init_single_clock(clk_mgr, PPCLK_SOCCLK,
@@ -189,11 +192,16 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base)
                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;
 
        /* 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;
+
+       if (num_dcfclk_levels && num_dtbclk_levels && num_dispclk_levels)
+               clk_mgr->dpm_present = true;
 
        if (clk_mgr_base->ctx->dc->debug.min_disp_clk_khz) {
                unsigned int i;
@@ -658,6 +666,12 @@ static void dcn32_get_memclk_states_from_smu(struct 
clk_mgr *clk_mgr_base)
                        &num_levels);
        clk_mgr_base->bw_params->clk_table.num_entries = num_levels ? 
num_levels : 1;
 
+       if (clk_mgr->dpm_present && !num_levels)
+               clk_mgr->dpm_present = false;
+
+       if (!clk_mgr->dpm_present)
+               dcn32_patch_dpm_table(clk_mgr_base->bw_params);
+
        DC_FP_START();
        /* Refresh bounding box */
        clk_mgr_base->ctx->dc->res_pool->funcs->update_bw_bounding_box(
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c 
b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
index cb97afbee097..4484a7ece4b4 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c
@@ -2044,6 +2044,45 @@ static void remove_entry_from_table_at_index(struct 
_vcs_dpi_voltage_scaling_st
        memset(&table[--(*num_entries)], 0, sizeof(struct 
_vcs_dpi_voltage_scaling_st));
 }
 
+void dcn32_patch_dpm_table(struct clk_bw_params *bw_params)
+{
+       int i;
+       unsigned int max_dcfclk_mhz = 0, max_dispclk_mhz = 0, max_dppclk_mhz = 
0,
+                       max_phyclk_mhz = 0, max_dtbclk_mhz = 0, max_fclk_mhz = 
0, max_uclk_mhz = 0;
+
+       for (i = 0; i < MAX_NUM_DPM_LVL; i++) {
+               if (bw_params->clk_table.entries[i].dcfclk_mhz > max_dcfclk_mhz)
+                       max_dcfclk_mhz = 
bw_params->clk_table.entries[i].dcfclk_mhz;
+               if (bw_params->clk_table.entries[i].fclk_mhz > max_fclk_mhz)
+                       max_fclk_mhz = bw_params->clk_table.entries[i].fclk_mhz;
+               if (bw_params->clk_table.entries[i].memclk_mhz > max_uclk_mhz)
+                       max_uclk_mhz = 
bw_params->clk_table.entries[i].memclk_mhz;
+               if (bw_params->clk_table.entries[i].dispclk_mhz > 
max_dispclk_mhz)
+                       max_dispclk_mhz = 
bw_params->clk_table.entries[i].dispclk_mhz;
+               if (bw_params->clk_table.entries[i].dppclk_mhz > max_dppclk_mhz)
+                       max_dppclk_mhz = 
bw_params->clk_table.entries[i].dppclk_mhz;
+               if (bw_params->clk_table.entries[i].phyclk_mhz > max_phyclk_mhz)
+                       max_phyclk_mhz = 
bw_params->clk_table.entries[i].phyclk_mhz;
+               if (bw_params->clk_table.entries[i].dtbclk_mhz > max_dtbclk_mhz)
+                       max_dtbclk_mhz = 
bw_params->clk_table.entries[i].dtbclk_mhz;
+       }
+
+       /* Scan through clock values we currently have and if they are 0,
+        *  then populate it with dcn3_2_soc.clock_limits[] value.
+        *
+        * Do it for DCFCLK, DISPCLK, DTBCLK and UCLK as any of those being
+        *  0, will cause it to skip building the clock table.
+        */
+       if (max_dcfclk_mhz == 0)
+               bw_params->clk_table.entries[0].dcfclk_mhz = 
dcn3_2_soc.clock_limits[0].dcfclk_mhz;
+       if (max_dispclk_mhz == 0)
+               bw_params->clk_table.entries[0].dispclk_mhz = 
dcn3_2_soc.clock_limits[0].dispclk_mhz;
+       if (max_dtbclk_mhz == 0)
+               bw_params->clk_table.entries[0].dtbclk_mhz = 
dcn3_2_soc.clock_limits[0].dtbclk_mhz;
+       if (max_uclk_mhz == 0)
+               bw_params->clk_table.entries[0].memclk_mhz = 
dcn3_2_soc.clock_limits[0].dram_speed_mts / 16;
+}
+
 static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
                struct _vcs_dpi_voltage_scaling_st *table, unsigned int 
*num_entries)
 {
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h 
b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h
index 732ed7fadb8a..3a3dc2ce4c73 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h
@@ -71,4 +71,6 @@ int 
dcn32_find_dummy_latency_index_for_fw_based_mclk_switch(struct dc *dc,
                                                            int pipe_cnt,
                                                            int vlevel);
 
+void dcn32_patch_dpm_table(struct clk_bw_params *bw_params);
+
 #endif
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h 
b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
index 68c2ed434d2c..cff5fd55a0ad 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h
@@ -340,6 +340,8 @@ struct clk_mgr_internal {
        bool smu_present;
        void *wm_range_table;
        long long wm_range_table_addr;
+
+       bool dpm_present;
 };
 
 struct clk_mgr_internal_funcs {
-- 
2.25.1

Reply via email to