From: Lijo Lazar Date: Tue, 25 Nov 2025 10:23:25 +0000 (+0530) Subject: drm/amd/pm: Use generic dpm table for SMUv14 SOCs X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b4742a9e7fd42c011cf805e3441dd188f22e325c;p=thirdparty%2Fkernel%2Flinux.git drm/amd/pm: Use generic dpm table for SMUv14 SOCs Use the generic dpm table structure instead of SMUv14 specific table. Signed-off-by: Lijo Lazar Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h index 29a4583db873..5b6fa8fdce2d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h @@ -43,7 +43,6 @@ #define smnMP1_FIRMWARE_FLAGS 0x3010024 #define smnMP1_PUB_CTRL 0x3010d10 -#define MAX_DPM_LEVELS 16 #define MAX_PCIE_CONF 3 #define SMU14_TOOL_SIZE 0x19000 @@ -67,19 +66,6 @@ struct smu_14_0_max_sustainable_clocks { uint32_t soc_clock; }; -struct smu_14_0_dpm_clk_level { - bool enabled; - uint32_t value; -}; - -struct smu_14_0_dpm_table { - uint32_t min; /* MHz */ - uint32_t max; /* MHz */ - uint32_t count; - bool is_fine_grained; - struct smu_14_0_dpm_clk_level dpm_levels[MAX_DPM_LEVELS]; -}; - struct smu_14_0_pcie_table { uint8_t pcie_gen[MAX_PCIE_CONF]; uint8_t pcie_lane[MAX_PCIE_CONF]; @@ -88,17 +74,17 @@ struct smu_14_0_pcie_table { }; struct smu_14_0_dpm_tables { - struct smu_14_0_dpm_table soc_table; - struct smu_14_0_dpm_table gfx_table; - struct smu_14_0_dpm_table uclk_table; - struct smu_14_0_dpm_table eclk_table; - struct smu_14_0_dpm_table vclk_table; - struct smu_14_0_dpm_table dclk_table; - struct smu_14_0_dpm_table dcef_table; - struct smu_14_0_dpm_table pixel_table; - struct smu_14_0_dpm_table display_table; - struct smu_14_0_dpm_table phy_table; - struct smu_14_0_dpm_table fclk_table; + struct smu_dpm_table soc_table; + struct smu_dpm_table gfx_table; + struct smu_dpm_table uclk_table; + struct smu_dpm_table eclk_table; + struct smu_dpm_table vclk_table; + struct smu_dpm_table dclk_table; + struct smu_dpm_table dcef_table; + struct smu_dpm_table pixel_table; + struct smu_dpm_table display_table; + struct smu_dpm_table phy_table; + struct smu_dpm_table fclk_table; struct smu_14_0_pcie_table pcie_table; }; @@ -201,7 +187,7 @@ int smu_v14_0_set_power_source(struct smu_context *smu, int smu_v14_0_set_single_dpm_table(struct smu_context *smu, enum smu_clk_type clk_type, - struct smu_14_0_dpm_table *single_dpm_table); + struct smu_dpm_table *single_dpm_table); int smu_v14_0_gfx_ulv_control(struct smu_context *smu, bool enablement); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c index f9b0938c57ea..7db1161c0c05 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c @@ -1247,18 +1247,12 @@ int smu_v14_0_set_performance_level(struct smu_context *smu, { struct smu_14_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; - struct smu_14_0_dpm_table *gfx_table = - &dpm_context->dpm_tables.gfx_table; - struct smu_14_0_dpm_table *mem_table = - &dpm_context->dpm_tables.uclk_table; - struct smu_14_0_dpm_table *soc_table = - &dpm_context->dpm_tables.soc_table; - struct smu_14_0_dpm_table *vclk_table = - &dpm_context->dpm_tables.vclk_table; - struct smu_14_0_dpm_table *dclk_table = - &dpm_context->dpm_tables.dclk_table; - struct smu_14_0_dpm_table *fclk_table = - &dpm_context->dpm_tables.fclk_table; + struct smu_dpm_table *gfx_table = &dpm_context->dpm_tables.gfx_table; + struct smu_dpm_table *mem_table = &dpm_context->dpm_tables.uclk_table; + struct smu_dpm_table *soc_table = &dpm_context->dpm_tables.soc_table; + struct smu_dpm_table *vclk_table = &dpm_context->dpm_tables.vclk_table; + struct smu_dpm_table *dclk_table = &dpm_context->dpm_tables.dclk_table; + struct smu_dpm_table *fclk_table = &dpm_context->dpm_tables.fclk_table; struct smu_umd_pstate_table *pstate_table = &smu->pstate_table; struct amdgpu_device *adev = smu->adev; @@ -1273,34 +1267,34 @@ int smu_v14_0_set_performance_level(struct smu_context *smu, switch (level) { case AMD_DPM_FORCED_LEVEL_HIGH: - sclk_min = sclk_max = gfx_table->max; - mclk_min = mclk_max = mem_table->max; - socclk_min = socclk_max = soc_table->max; - vclk_min = vclk_max = vclk_table->max; - dclk_min = dclk_max = dclk_table->max; - fclk_min = fclk_max = fclk_table->max; + sclk_min = sclk_max = SMU_DPM_TABLE_MAX(gfx_table); + mclk_min = mclk_max = SMU_DPM_TABLE_MAX(mem_table); + socclk_min = socclk_max = SMU_DPM_TABLE_MAX(soc_table); + vclk_min = vclk_max = SMU_DPM_TABLE_MAX(vclk_table); + dclk_min = dclk_max = SMU_DPM_TABLE_MAX(dclk_table); + fclk_min = fclk_max = SMU_DPM_TABLE_MAX(fclk_table); break; case AMD_DPM_FORCED_LEVEL_LOW: - sclk_min = sclk_max = gfx_table->min; - mclk_min = mclk_max = mem_table->min; - socclk_min = socclk_max = soc_table->min; - vclk_min = vclk_max = vclk_table->min; - dclk_min = dclk_max = dclk_table->min; - fclk_min = fclk_max = fclk_table->min; + sclk_min = sclk_max = SMU_DPM_TABLE_MIN(gfx_table); + mclk_min = mclk_max = SMU_DPM_TABLE_MIN(mem_table); + socclk_min = socclk_max = SMU_DPM_TABLE_MIN(soc_table); + vclk_min = vclk_max = SMU_DPM_TABLE_MIN(vclk_table); + dclk_min = dclk_max = SMU_DPM_TABLE_MIN(dclk_table); + fclk_min = fclk_max = SMU_DPM_TABLE_MIN(fclk_table); break; case AMD_DPM_FORCED_LEVEL_AUTO: - sclk_min = gfx_table->min; - sclk_max = gfx_table->max; - mclk_min = mem_table->min; - mclk_max = mem_table->max; - socclk_min = soc_table->min; - socclk_max = soc_table->max; - vclk_min = vclk_table->min; - vclk_max = vclk_table->max; - dclk_min = dclk_table->min; - dclk_max = dclk_table->max; - fclk_min = fclk_table->min; - fclk_max = fclk_table->max; + sclk_min = SMU_DPM_TABLE_MIN(gfx_table); + sclk_max = SMU_DPM_TABLE_MAX(gfx_table); + mclk_min = SMU_DPM_TABLE_MIN(mem_table); + mclk_max = SMU_DPM_TABLE_MAX(mem_table); + socclk_min = SMU_DPM_TABLE_MIN(soc_table); + socclk_max = SMU_DPM_TABLE_MAX(soc_table); + vclk_min = SMU_DPM_TABLE_MIN(vclk_table); + vclk_max = SMU_DPM_TABLE_MAX(vclk_table); + dclk_min = SMU_DPM_TABLE_MIN(dclk_table); + dclk_max = SMU_DPM_TABLE_MAX(dclk_table); + fclk_min = SMU_DPM_TABLE_MIN(fclk_table); + fclk_max = SMU_DPM_TABLE_MAX(fclk_table); auto_level = true; break; case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: @@ -1522,11 +1516,12 @@ static int smu_v14_0_get_fine_grained_status(struct smu_context *smu, int smu_v14_0_set_single_dpm_table(struct smu_context *smu, enum smu_clk_type clk_type, - struct smu_14_0_dpm_table *single_dpm_table) + struct smu_dpm_table *single_dpm_table) { int ret = 0; uint32_t clk; int i; + bool is_fine_grained; ret = smu_v14_0_get_dpm_level_count(smu, clk_type, @@ -1536,13 +1531,14 @@ int smu_v14_0_set_single_dpm_table(struct smu_context *smu, return ret; } - ret = smu_v14_0_get_fine_grained_status(smu, - clk_type, - &single_dpm_table->is_fine_grained); + ret = smu_v14_0_get_fine_grained_status(smu, clk_type, + &is_fine_grained); if (ret) { dev_err(smu->adev->dev, "[%s] failed to get fine grained status!\n", __func__); return ret; } + if (is_fine_grained) + single_dpm_table->flags |= SMU_DPM_TABLE_FINE_GRAINED; for (i = 0; i < single_dpm_table->count; i++) { ret = smu_v14_0_get_dpm_freq_by_index(smu, @@ -1556,11 +1552,6 @@ int smu_v14_0_set_single_dpm_table(struct smu_context *smu, single_dpm_table->dpm_levels[i].value = clk; single_dpm_table->dpm_levels[i].enabled = true; - - if (i == 0) - single_dpm_table->min = clk; - else if (i == single_dpm_table->count - 1) - single_dpm_table->max = clk; } return 0; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c index ab57bb2e5dcf..daa51364cb24 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c @@ -501,11 +501,12 @@ static int smu_v14_0_2_set_default_dpm_table(struct smu_context *smu) struct smu_table_context *table_context = &smu->smu_table; PPTable_t *pptable = table_context->driver_pptable; SkuTable_t *skutable = &pptable->SkuTable; - struct smu_14_0_dpm_table *dpm_table; + struct smu_dpm_table *dpm_table; int ret = 0; /* socclk dpm table setup */ dpm_table = &dpm_context->dpm_tables.soc_table; + dpm_table->clk_type = SMU_SOCCLK; if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { ret = smu_v14_0_set_single_dpm_table(smu, SMU_SOCCLK, @@ -516,12 +517,11 @@ static int smu_v14_0_2_set_default_dpm_table(struct smu_context *smu) dpm_table->count = 1; dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100; dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; } /* gfxclk dpm table setup */ dpm_table = &dpm_context->dpm_tables.gfx_table; + dpm_table->clk_type = SMU_GFXCLK; if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) { ret = smu_v14_0_set_single_dpm_table(smu, SMU_GFXCLK, @@ -543,18 +543,16 @@ static int smu_v14_0_2_set_default_dpm_table(struct smu_context *smu) skutable->DriverReportedClocks.GameClockAc)) { dpm_table->dpm_levels[dpm_table->count - 1].value = skutable->DriverReportedClocks.GameClockAc; - dpm_table->max = skutable->DriverReportedClocks.GameClockAc; } } else { dpm_table->count = 1; dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; } /* uclk dpm table setup */ dpm_table = &dpm_context->dpm_tables.uclk_table; + dpm_table->clk_type = SMU_UCLK; if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { ret = smu_v14_0_set_single_dpm_table(smu, SMU_UCLK, @@ -565,12 +563,11 @@ static int smu_v14_0_2_set_default_dpm_table(struct smu_context *smu) dpm_table->count = 1; dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100; dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; } /* fclk dpm table setup */ dpm_table = &dpm_context->dpm_tables.fclk_table; + dpm_table->clk_type = SMU_FCLK; if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT)) { ret = smu_v14_0_set_single_dpm_table(smu, SMU_FCLK, @@ -581,12 +578,11 @@ static int smu_v14_0_2_set_default_dpm_table(struct smu_context *smu) dpm_table->count = 1; dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.fclk / 100; dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; } /* vclk dpm table setup */ dpm_table = &dpm_context->dpm_tables.vclk_table; + dpm_table->clk_type = SMU_VCLK; if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_VCLK_BIT)) { ret = smu_v14_0_set_single_dpm_table(smu, SMU_VCLK, @@ -597,12 +593,11 @@ static int smu_v14_0_2_set_default_dpm_table(struct smu_context *smu) dpm_table->count = 1; dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100; dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; } /* dclk dpm table setup */ dpm_table = &dpm_context->dpm_tables.dclk_table; + dpm_table->clk_type = SMU_DCLK; if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCLK_BIT)) { ret = smu_v14_0_set_single_dpm_table(smu, SMU_DCLK, @@ -613,12 +608,11 @@ static int smu_v14_0_2_set_default_dpm_table(struct smu_context *smu) dpm_table->count = 1; dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100; dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; } /* dcefclk dpm table setup */ dpm_table = &dpm_context->dpm_tables.dcef_table; + dpm_table->clk_type = SMU_DCEFCLK; if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCN_BIT)) { ret = smu_v14_0_set_single_dpm_table(smu, SMU_DCEFCLK, @@ -629,8 +623,6 @@ static int smu_v14_0_2_set_default_dpm_table(struct smu_context *smu) dpm_table->count = 1; dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; } return 0; @@ -794,7 +786,7 @@ static int smu_v14_0_2_get_dpm_ultimate_freq(struct smu_context *smu, { struct smu_14_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; - struct smu_14_0_dpm_table *dpm_table; + struct smu_dpm_table *dpm_table; switch (clk_type) { case SMU_MCLK: @@ -831,9 +823,9 @@ static int smu_v14_0_2_get_dpm_ultimate_freq(struct smu_context *smu, } if (min) - *min = dpm_table->min; + *min = SMU_DPM_TABLE_MIN(dpm_table); if (max) - *max = dpm_table->max; + *max = SMU_DPM_TABLE_MAX(dpm_table); return 0; } @@ -1053,7 +1045,7 @@ static int smu_v14_0_2_emit_clk_levels(struct smu_context *smu, struct smu_14_0_dpm_context *dpm_context = smu_dpm->dpm_context; OverDriveTableExternal_t *od_table = (OverDriveTableExternal_t *)smu->smu_table.overdrive_table; - struct smu_14_0_dpm_table *single_dpm_table; + struct smu_dpm_table *single_dpm_table; struct smu_14_0_pcie_table *pcie_table; uint32_t gen_speed, lane_width; int i, curr_freq, size = *offset, start_offset = *offset; @@ -1109,7 +1101,7 @@ static int smu_v14_0_2_emit_clk_levels(struct smu_context *smu, return ret; } - if (single_dpm_table->is_fine_grained) { + if (single_dpm_table->flags & SMU_DPM_TABLE_FINE_GRAINED) { /* * For fine grained dpms, there are only two dpm levels: * - level 0 -> min clock freq @@ -1383,7 +1375,7 @@ static int smu_v14_0_2_force_clk_levels(struct smu_context *smu, { struct smu_dpm_context *smu_dpm = &smu->smu_dpm; struct smu_14_0_dpm_context *dpm_context = smu_dpm->dpm_context; - struct smu_14_0_dpm_table *single_dpm_table; + struct smu_dpm_table *single_dpm_table; uint32_t soft_min_level, soft_max_level; uint32_t min_freq, max_freq; int ret = 0; @@ -1429,7 +1421,7 @@ static int smu_v14_0_2_force_clk_levels(struct smu_context *smu, case SMU_VCLK1: case SMU_DCLK: case SMU_DCLK1: - if (single_dpm_table->is_fine_grained) { + if (single_dpm_table->flags & SMU_DPM_TABLE_FINE_GRAINED) { /* There is only 2 levels for fine grained DPM */ soft_max_level = (soft_max_level >= 1 ? 1 : 0); soft_min_level = (soft_min_level >= 1 ? 1 : 0); @@ -1582,18 +1574,12 @@ static int smu_v14_0_2_populate_umd_state_clk(struct smu_context *smu) { struct smu_14_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; - struct smu_14_0_dpm_table *gfx_table = - &dpm_context->dpm_tables.gfx_table; - struct smu_14_0_dpm_table *mem_table = - &dpm_context->dpm_tables.uclk_table; - struct smu_14_0_dpm_table *soc_table = - &dpm_context->dpm_tables.soc_table; - struct smu_14_0_dpm_table *vclk_table = - &dpm_context->dpm_tables.vclk_table; - struct smu_14_0_dpm_table *dclk_table = - &dpm_context->dpm_tables.dclk_table; - struct smu_14_0_dpm_table *fclk_table = - &dpm_context->dpm_tables.fclk_table; + struct smu_dpm_table *gfx_table = &dpm_context->dpm_tables.gfx_table; + struct smu_dpm_table *mem_table = &dpm_context->dpm_tables.uclk_table; + struct smu_dpm_table *soc_table = &dpm_context->dpm_tables.soc_table; + struct smu_dpm_table *vclk_table = &dpm_context->dpm_tables.vclk_table; + struct smu_dpm_table *dclk_table = &dpm_context->dpm_tables.dclk_table; + struct smu_dpm_table *fclk_table = &dpm_context->dpm_tables.fclk_table; struct smu_umd_pstate_table *pstate_table = &smu->pstate_table; struct smu_table_context *table_context = &smu->smu_table; @@ -1601,38 +1587,39 @@ static int smu_v14_0_2_populate_umd_state_clk(struct smu_context *smu) DriverReportedClocks_t driver_clocks = pptable->SkuTable.DriverReportedClocks; - pstate_table->gfxclk_pstate.min = gfx_table->min; + pstate_table->gfxclk_pstate.min = SMU_DPM_TABLE_MIN(gfx_table); if (driver_clocks.GameClockAc && - (driver_clocks.GameClockAc < gfx_table->max)) + (driver_clocks.GameClockAc < SMU_DPM_TABLE_MAX(gfx_table))) pstate_table->gfxclk_pstate.peak = driver_clocks.GameClockAc; else - pstate_table->gfxclk_pstate.peak = gfx_table->max; + pstate_table->gfxclk_pstate.peak = SMU_DPM_TABLE_MAX(gfx_table); - pstate_table->uclk_pstate.min = mem_table->min; - pstate_table->uclk_pstate.peak = mem_table->max; + pstate_table->uclk_pstate.min = SMU_DPM_TABLE_MIN(mem_table); + pstate_table->uclk_pstate.peak = SMU_DPM_TABLE_MAX(mem_table); - pstate_table->socclk_pstate.min = soc_table->min; - pstate_table->socclk_pstate.peak = soc_table->max; + pstate_table->socclk_pstate.min = SMU_DPM_TABLE_MIN(soc_table); + pstate_table->socclk_pstate.peak = SMU_DPM_TABLE_MAX(soc_table); - pstate_table->vclk_pstate.min = vclk_table->min; - pstate_table->vclk_pstate.peak = vclk_table->max; + pstate_table->vclk_pstate.min = SMU_DPM_TABLE_MIN(vclk_table); + pstate_table->vclk_pstate.peak = SMU_DPM_TABLE_MAX(vclk_table); - pstate_table->dclk_pstate.min = dclk_table->min; - pstate_table->dclk_pstate.peak = dclk_table->max; + pstate_table->dclk_pstate.min = SMU_DPM_TABLE_MIN(dclk_table); + pstate_table->dclk_pstate.peak = SMU_DPM_TABLE_MAX(dclk_table); - pstate_table->fclk_pstate.min = fclk_table->min; - pstate_table->fclk_pstate.peak = fclk_table->max; + pstate_table->fclk_pstate.min = SMU_DPM_TABLE_MIN(fclk_table); + pstate_table->fclk_pstate.peak = SMU_DPM_TABLE_MAX(fclk_table); if (driver_clocks.BaseClockAc && - driver_clocks.BaseClockAc < gfx_table->max) + driver_clocks.BaseClockAc < SMU_DPM_TABLE_MAX(gfx_table)) pstate_table->gfxclk_pstate.standard = driver_clocks.BaseClockAc; else - pstate_table->gfxclk_pstate.standard = gfx_table->max; - pstate_table->uclk_pstate.standard = mem_table->max; - pstate_table->socclk_pstate.standard = soc_table->min; - pstate_table->vclk_pstate.standard = vclk_table->min; - pstate_table->dclk_pstate.standard = dclk_table->min; - pstate_table->fclk_pstate.standard = fclk_table->min; + pstate_table->gfxclk_pstate.standard = + SMU_DPM_TABLE_MAX(gfx_table); + pstate_table->uclk_pstate.standard = SMU_DPM_TABLE_MAX(mem_table); + pstate_table->socclk_pstate.standard = SMU_DPM_TABLE_MIN(soc_table); + pstate_table->vclk_pstate.standard = SMU_DPM_TABLE_MIN(vclk_table); + pstate_table->dclk_pstate.standard = SMU_DPM_TABLE_MIN(dclk_table); + pstate_table->fclk_pstate.standard = SMU_DPM_TABLE_MIN(fclk_table); return 0; }