diff options
author | Lijo Lazar <lijo.lazar@amd.com> | 2024-01-29 11:36:31 +0300 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2024-02-15 01:15:58 +0300 |
commit | b7a9003445463bcd57850e8cd88aca0827e92837 (patch) | |
tree | f81d023c3a0c87bd31bef6ac4c516388527df4dc | |
parent | efe0f34c2bd037a0b01465323d52a7bbd8b5e888 (diff) | |
download | linux-b7a9003445463bcd57850e8cd88aca0827e92837.tar.xz |
drm/amd/pm: Allow setting max UCLK on SMU v13.0.6
Allow reducing max UCLK in MANUAL performance level. New UCLK value
should be less than the max DPM level UCLK level value.
Ex:
echo manual > "/sys/bus/pci/devices/.../power_dpm_force_performance_level"
echo m 1 900 > "/sys/bus/pci/devices/.../pp_od_clk_voltage”
echo c > "/sys/bus/pci/devices/.../pp_od_clk_voltage”
Signed-off-by: Lijo Lazar <lijo.lazar@amd.com>
Reviewed-by: Asad Kamal <asad.kamal@amd.com>
Tested-by: Asad Kamal <asad.kamal@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c | 122 |
1 files changed, 102 insertions, 20 deletions
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c index 626f73f147de..29c102fe650d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c @@ -1579,6 +1579,8 @@ static int smu_v13_0_6_set_performance_level(struct smu_context *smu, struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context; struct smu_13_0_dpm_table *gfx_table = &dpm_context->dpm_tables.gfx_table; + struct smu_13_0_dpm_table *uclk_table = + &dpm_context->dpm_tables.uclk_table; struct smu_umd_pstate_table *pstate_table = &smu->pstate_table; int ret; @@ -1594,17 +1596,27 @@ static int smu_v13_0_6_set_performance_level(struct smu_context *smu, return 0; case AMD_DPM_FORCED_LEVEL_AUTO: - if ((gfx_table->min == pstate_table->gfxclk_pstate.curr.min) && - (gfx_table->max == pstate_table->gfxclk_pstate.curr.max)) - return 0; + if ((gfx_table->min != pstate_table->gfxclk_pstate.curr.min) || + (gfx_table->max != pstate_table->gfxclk_pstate.curr.max)) { + ret = smu_v13_0_6_set_gfx_soft_freq_limited_range( + smu, gfx_table->min, gfx_table->max); + if (ret) + return ret; - ret = smu_v13_0_6_set_gfx_soft_freq_limited_range( - smu, gfx_table->min, gfx_table->max); - if (ret) - return ret; + pstate_table->gfxclk_pstate.curr.min = gfx_table->min; + pstate_table->gfxclk_pstate.curr.max = gfx_table->max; + } + + if (uclk_table->max != pstate_table->uclk_pstate.curr.max) { + /* Min UCLK is not expected to be changed */ + ret = smu_v13_0_set_soft_freq_limited_range( + smu, SMU_UCLK, 0, uclk_table->max); + if (ret) + return ret; + pstate_table->uclk_pstate.curr.max = uclk_table->max; + } + pstate_table->uclk_pstate.custom.max = 0; - pstate_table->gfxclk_pstate.curr.min = gfx_table->min; - pstate_table->gfxclk_pstate.curr.max = gfx_table->max; return 0; case AMD_DPM_FORCED_LEVEL_MANUAL: return 0; @@ -1627,7 +1639,8 @@ static int smu_v13_0_6_set_soft_freq_limited_range(struct smu_context *smu, uint32_t max_clk; int ret = 0; - if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) + if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK && + clk_type != SMU_UCLK) return -EINVAL; if ((smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) && @@ -1637,18 +1650,31 @@ static int smu_v13_0_6_set_soft_freq_limited_range(struct smu_context *smu, if (smu_dpm->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) { if (min >= max) { dev_err(smu->adev->dev, - "Minimum GFX clk should be less than the maximum allowed clock\n"); + "Minimum clk should be less than the maximum allowed clock\n"); return -EINVAL; } - if ((min == pstate_table->gfxclk_pstate.curr.min) && - (max == pstate_table->gfxclk_pstate.curr.max)) - return 0; + if (clk_type == SMU_GFXCLK) { + if ((min == pstate_table->gfxclk_pstate.curr.min) && + (max == pstate_table->gfxclk_pstate.curr.max)) + return 0; - ret = smu_v13_0_6_set_gfx_soft_freq_limited_range(smu, min, max); - if (!ret) { - pstate_table->gfxclk_pstate.curr.min = min; - pstate_table->gfxclk_pstate.curr.max = max; + ret = smu_v13_0_6_set_gfx_soft_freq_limited_range( + smu, min, max); + if (!ret) { + pstate_table->gfxclk_pstate.curr.min = min; + pstate_table->gfxclk_pstate.curr.max = max; + } + } + + if (clk_type == SMU_UCLK) { + if (max == pstate_table->uclk_pstate.curr.max) + return 0; + /* Only max clock limiting is allowed for UCLK */ + ret = smu_v13_0_set_soft_freq_limited_range( + smu, SMU_UCLK, 0, max); + if (!ret) + pstate_table->uclk_pstate.curr.max = max; } return ret; @@ -1741,6 +1767,40 @@ static int smu_v13_0_6_usr_edit_dpm_table(struct smu_context *smu, return -EINVAL; } break; + case PP_OD_EDIT_MCLK_VDDC_TABLE: + if (size != 2) { + dev_err(smu->adev->dev, + "Input parameter number not correct\n"); + return -EINVAL; + } + + if (!smu_cmn_feature_is_enabled(smu, + SMU_FEATURE_DPM_UCLK_BIT)) { + dev_warn(smu->adev->dev, + "UCLK_LIMITS setting not supported!\n"); + return -EOPNOTSUPP; + } + + if (input[0] == 0) { + dev_info(smu->adev->dev, + "Setting min UCLK level is not supported"); + return -EINVAL; + } else if (input[0] == 1) { + if (input[1] > dpm_context->dpm_tables.uclk_table.max) { + dev_warn( + smu->adev->dev, + "Maximum UCLK (%ld) MHz specified is greater than the maximum allowed (%d) MHz\n", + input[1], + dpm_context->dpm_tables.uclk_table.max); + pstate_table->uclk_pstate.custom.max = + pstate_table->uclk_pstate.curr.max; + return -EINVAL; + } + + pstate_table->uclk_pstate.custom.max = input[1]; + } + break; + case PP_OD_RESTORE_DEFAULT_TABLE: if (size != 0) { dev_err(smu->adev->dev, @@ -1751,8 +1811,19 @@ static int smu_v13_0_6_usr_edit_dpm_table(struct smu_context *smu, min_clk = dpm_context->dpm_tables.gfx_table.min; max_clk = dpm_context->dpm_tables.gfx_table.max; - return smu_v13_0_6_set_soft_freq_limited_range( + ret = smu_v13_0_6_set_soft_freq_limited_range( smu, SMU_GFXCLK, min_clk, max_clk); + + if (ret) + return ret; + + min_clk = dpm_context->dpm_tables.uclk_table.min; + max_clk = dpm_context->dpm_tables.uclk_table.max; + ret = smu_v13_0_6_set_soft_freq_limited_range( + smu, SMU_UCLK, min_clk, max_clk); + if (ret) + return ret; + pstate_table->uclk_pstate.custom.max = 0; } break; case PP_OD_COMMIT_DPM_TABLE: @@ -1772,8 +1843,19 @@ static int smu_v13_0_6_usr_edit_dpm_table(struct smu_context *smu, min_clk = pstate_table->gfxclk_pstate.custom.min; max_clk = pstate_table->gfxclk_pstate.custom.max; - return smu_v13_0_6_set_soft_freq_limited_range( + ret = smu_v13_0_6_set_soft_freq_limited_range( smu, SMU_GFXCLK, min_clk, max_clk); + + if (ret) + return ret; + + if (!pstate_table->uclk_pstate.custom.max) + return 0; + + min_clk = pstate_table->uclk_pstate.curr.min; + max_clk = pstate_table->uclk_pstate.custom.max; + return smu_v13_0_6_set_soft_freq_limited_range( + smu, SMU_UCLK, min_clk, max_clk); } break; default: |