diff options
| author | Alvin Lee <Alvin.Lee2@amd.com> | 2026-08-26 13:49:58 -0400 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2026-09-10 12:02:13 -0400 |
| commit | 00eaae7bca217987fda68795d2fa61d5b9f5931e (patch) | |
| tree | 3aa87d017906f0831ae4ecfb03b09c709aeac59c | |
| parent | 606dc2492b8ca657118b4c4b1443a20a2bfa9a7c (diff) | |
| download | linux-next-00eaae7bca217987fda68795d2fa61d5b9f5931e.tar.gz linux-next-00eaae7bca217987fda68795d2fa61d5b9f5931e.zip | |
drm/amd/display: Add override capability for UTM table params
[Why & How]
Add calls for overriding UTM table params from PMFW. This is for
debug and test purposes only when PMFW has not yet populated the table
values correctly.
Reviewed-by: Wenjing Liu <wenjing.liu@amd.com>
Signed-off-by: Alvin Lee <Alvin.Lee2@amd.com>
Signed-off-by: Ray Wu <ray.wu@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
3 files changed, 88 insertions, 28 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dalsmc.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dalsmc.h index 6954a54dad89..9b109959bd7f 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dalsmc.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dalsmc.h @@ -112,7 +112,7 @@ typedef struct { * TABLE_DAL_INIT - Full TABLE_DAL_INIT payload transferred from SMU to DRAM. */ #define TABLE_DAL_INIT 0xD -#define MAX_PPCLK_COUNT 20 +#define MAX_PPCLK_COUNT 22 #define DPM_CLOCK_OFFSET(Ppclk) \ (sizeof(DalInitHeader_t) + (Ppclk) * sizeof(DpmClock_t)) #define UTM_TABLE_OFFSET \ diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c index 83989b4b1fdd..2b7740b82161 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_clk_mgr.c @@ -479,6 +479,39 @@ static int dcn60_get_dtb_ref_freq_khz(struct clk_mgr *clk_mgr_base) return dtb_ref_clk_khz; } +/** + * dcn60_override_dc_mode_limit - Override DC mode limits from the clock table. + * @dc_limit: output DC mode limit to populate + * @clk_table: clock table already populated (and possibly overridden) + * + * Sets the DC mode max frequency for each clock to the highest populated DPM + * level in the clock table. Deriving the limit from the clock table (rather + * than the raw DAL init table) ensures any overrides applied to the clock + * levels are respected. + */ +static void dcn60_override_dc_mode_limit( + struct clk_limit_table_entry *dc_limit, + const struct clk_limit_table *clk_table) +{ + const struct clk_limit_table_entry *entries = clk_table->entries; + const struct clk_limit_num_entries *num_entries = &clk_table->num_entries_per_clk; + + dc_limit->dcfclk_mhz = num_entries->num_dcfclk_levels ? + entries[num_entries->num_dcfclk_levels - 1].dcfclk_mhz : 0; + dc_limit->socclk_mhz = num_entries->num_socclk_levels ? + entries[num_entries->num_socclk_levels - 1].socclk_mhz : 0; + dc_limit->dtbclk_mhz = num_entries->num_dtbclk_levels ? + entries[num_entries->num_dtbclk_levels - 1].dtbclk_mhz : 0; + dc_limit->dispclk_mhz = num_entries->num_dispclk_levels ? + entries[num_entries->num_dispclk_levels - 1].dispclk_mhz : 0; + dc_limit->dppclk_mhz = num_entries->num_dppclk_levels ? + entries[num_entries->num_dppclk_levels - 1].dppclk_mhz : 0; + dc_limit->memclk_mhz = num_entries->num_memclk_levels ? + entries[num_entries->num_memclk_levels - 1].memclk_mhz : 0; + dc_limit->fclk_mhz = num_entries->num_fclk_levels ? + entries[num_entries->num_fclk_levels - 1].fclk_mhz : 0; +} + static unsigned int dcn60_get_dc_mode_limit_mhz(const DpmClock_t *dpm_clk) { if (dpm_clk->NumClocks @@ -495,8 +528,10 @@ static unsigned int dcn60_get_dc_mode_limit_mhz(const DpmClock_t *dpm_clk) * * Sets the DC mode max frequency for each clock. If DcMaxClock equals the * highest DPM level, the limit is set to 0 (no DC-specific cap). + * + * Temporarily unused. */ -static void dcn60_populate_dc_mode_limit( +static void __maybe_unused dcn60_populate_dc_mode_limit( struct clk_limit_table_entry *dc_limit, const DalInitTable_t *init_table) { @@ -578,6 +613,20 @@ static void dcn60_populate_clk_table(struct clk_mgr_internal *clk_mgr, clk_table->num_entries = 1; } +/** + * dcn60_override_clk_table - Override the clock table with hardcoded values. + * @clk_table: clock table to override + * + * Temporary debug/bring-up override that replaces the DPM clock levels + * populated from the DAL init table (see dcn60_populate_clk_table) with a + * fixed set of hardcoded values. Implement any override as needed. + */ +static void dcn60_override_clk_table(struct clk_limit_table *clk_table) +{ + /* Override as needed */ + (void)clk_table; +} + static void dcn60_override_bw_params(struct clk_mgr_internal *clk_mgr, struct clk_bw_params *bw_params) { @@ -605,12 +654,17 @@ static void dcn60_override_bw_params(struct clk_mgr_internal *clk_mgr, bw_params->dc_mode_softmax_memclk = bw_params->dc_mode_limit.memclk_mhz; - /* The qos model stores dchub_v3 as a const view of a mutable table, so - * cast away const to apply the override. - */ - if (bw_params->utm_qos_model && bw_params->utm_qos_model->dchub_v3) + /* Override as needed - temporary for debug only. */ + if (bw_params->utm_qos_model && bw_params->utm_qos_model->dchub_v3) { + dcn6_test_initialize_utm_qos_model_v3( + (struct utm_qos_model *)bw_params->utm_qos_model, + (struct utm_qos_model_dchub_v3 *)bw_params->utm_qos_model->dchub_v3); + + // Override for lsdma here is redundant with the above call, but this may need to outlive + // the test_initialize call for debug purposes so keep it here for now. dcn6_test_override_lsdma_bandwidth_v3( (struct utm_qos_model_dchub_v3 *)bw_params->utm_qos_model->dchub_v3); + } } /** @@ -685,7 +739,9 @@ static bool dcn60_fetch_dal_init_table(struct clk_mgr_internal *clk_mgr) clk_mgr->smu_ver = init_table->Header.SmuVersion; dcn60_populate_clk_table(clk_mgr, &bw_params->clk_table, init_table); - dcn60_populate_dc_mode_limit(&bw_params->dc_mode_limit, init_table); + // Comment out for now - DC mode limit is not yet used in DCN6 and the current + // population from init table will cause undefined behaviors. + //dcn60_populate_dc_mode_limit(&bw_params->dc_mode_limit, init_table); bw_params->num_channels = init_table->MemoryConfig.NumUmcChannels; bw_params->dram_channel_width_bytes = @@ -694,6 +750,8 @@ static bool dcn60_fetch_dal_init_table(struct clk_mgr_internal *clk_mgr) dcn60_populate_utm_qos_model(clk_mgr, &bw_params->utm_qos_model, init_table); dcn60_override_bw_params(clk_mgr, bw_params); + dcn60_override_clk_table(&bw_params->clk_table); + dcn60_override_dc_mode_limit(&bw_params->dc_mode_limit, &bw_params->clk_table); return true; } diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_smu_driver_if.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_smu_driver_if.h index 3e101fa87cfd..ca23518d88b9 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_smu_driver_if.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn60/dcn60_smu_driver_if.h @@ -9,27 +9,29 @@ //Only Clks that have DPM descriptors are listed here // This should be the same order as DPM_e typedef enum { - PPCLK_GFXCLK = 0, - PPCLK_BTNCLK = 1, - PPCLK_LCLK = 2, - PPCLK_UCLK = 3, - PPCLK_FCLK = 4, - PPCLK_G7FCLK = 5, - PPCLK_SOCCLK = 6, - PPCLK_ACLK = 7, - PPCLK_DCFCLK = 8, - PPCLK_VPECLK = 9, - PPCLK_DISPCLK = 10, - PPCLK_DPPCLK = 11, - PPCLK_DPREFCLK = 12, - PPCLK_CFPUCLK = 13, - PPCLK_LOGANCLK = 14, - PPCLK_MSPCLK = 15, - PPCLK_MOVADCLK = 16, - PPCLK_DTBCLK = 17, - PPCLK_DCLK_0 = 18, - PPCLK_VCLK_0 = 19, - PPCLK_COUNT = 20, + PPCLK_GFXCLK = 0, + PPCLK_NVECLK1, + PPCLK_NVECLK2, + PPCLK_NVECLK3, + PPCLK_LCLK, + PPCLK_UCLK, + PPCLK_FCLK, + PPCLK_G7FCLK, + PPCLK_SOCCLK, + PPCLK_ACLK, + PPCLK_DCFCLK, + PPCLK_VPECLK, + PPCLK_DISPCLK, + PPCLK_DPPCLK, + PPCLK_DPREFCLK, + PPCLK_CFPUCLK, + PPCLK_LOGANCLK, + PPCLK_MSPHCLK, + PPCLK_MSPLCLK, + PPCLK_MSPEDECLK, + PPCLK_MOVADCLK, + PPCLK_DTBCLK, + PPCLK_COUNT, } PPCLK_e; typedef struct { |
