summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/pm/swsmu/smu13
diff options
context:
space:
mode:
authorXiaomeng Hou <Xiaomeng.Hou@amd.com>2021-04-08 09:44:02 +0800
committerAlex Deucher <alexander.deucher@amd.com>2021-06-04 16:03:24 -0400
commit6c83a0151b8f028eedd51f618a17cb838c11d217 (patch)
tree694efdb70b142040491c0cb88a18519c8d78dda5 /drivers/gpu/drm/amd/pm/swsmu/smu13
parent0cf6faafc43d46b4b3714159c7a9e8ecd2b11bd6 (diff)
drm/amd/pm: add set_performance_level function for yellow carp
This patch enables editing sysfs file power_dpm_force_performance_level for yellow carp. User could thus adjust the dpm forced level. v2: enable fine grain control of GFXCLK only when in manual performance level mode. In other mode, the min/max range of GFXCLK will be reset to corresponding values. Ex: To enable min 300MHz / max 600MHz gfx clocks 1) echo manual > /sys/bus/pci/devices/.../power_dpm_force_performance_level 2) echo s 0 300 > /sys/bus/pci/devices/.../pp_od_clk_voltage 3) echo s 1 600 > /sys/bus/pci/devices/.../pp_od_clk_voltage 4) echo c > /sys/bus/pci/devices/.../pp_od_clk_voltage Signed-off-by: Xiaomeng Hou <Xiaomeng.Hou@amd.com> Acked-by: Huang Rui <ray.huang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/pm/swsmu/smu13')
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
index 24dbd4ce4938..ddf56b31a403 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
@@ -602,8 +602,13 @@ static ssize_t yellow_carp_get_gpu_metrics(struct smu_context *smu,
static int yellow_carp_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type,
long input[], uint32_t size)
{
+ struct smu_dpm_context *smu_dpm = &(smu->smu_dpm);
int ret = 0;
+ /* Only allowed in manual mode */
+ if (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
+ return -EINVAL;
+
switch (type) {
case PP_OD_EDIT_SCLK_VDDC_TABLE:
if (size != 2) {
@@ -1049,6 +1054,84 @@ force_level_out:
return ret;
}
+static int yellow_carp_set_performance_level(struct smu_context *smu,
+ enum amd_dpm_forced_level level)
+{
+ struct amdgpu_device *adev = smu->adev;
+ uint32_t sclk_min = 0, sclk_max = 0;
+ uint32_t mclk_min = 0, mclk_max = 0;
+ uint32_t socclk_min = 0, socclk_max = 0;
+ int ret = 0;
+
+ switch (level) {
+ case AMD_DPM_FORCED_LEVEL_HIGH:
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk_max);
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_MCLK, NULL, &mclk_max);
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &socclk_max);
+ sclk_min = sclk_max;
+ mclk_min = mclk_max;
+ socclk_min = socclk_max;
+ break;
+ case AMD_DPM_FORCED_LEVEL_LOW:
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, NULL);
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_MCLK, &mclk_min, NULL);
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, NULL);
+ sclk_max = sclk_min;
+ mclk_max = mclk_min;
+ socclk_max = socclk_min;
+ break;
+ case AMD_DPM_FORCED_LEVEL_AUTO:
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, &sclk_max);
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_MCLK, &mclk_min, &mclk_max);
+ yellow_carp_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, &socclk_max);
+ break;
+ case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
+ case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
+ case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
+ case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
+ /* Temporarily do nothing since the optimal clocks haven't been provided yet */
+ break;
+ case AMD_DPM_FORCED_LEVEL_MANUAL:
+ case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
+ return 0;
+ default:
+ dev_err(adev->dev, "Invalid performance level %d\n", level);
+ return -EINVAL;
+ }
+
+ if (sclk_min && sclk_max) {
+ ret = yellow_carp_set_soft_freq_limited_range(smu,
+ SMU_SCLK,
+ sclk_min,
+ sclk_max);
+ if (ret)
+ return ret;
+
+ smu->gfx_actual_hard_min_freq = sclk_min;
+ smu->gfx_actual_soft_max_freq = sclk_max;
+ }
+
+ if (mclk_min && mclk_max) {
+ ret = yellow_carp_set_soft_freq_limited_range(smu,
+ SMU_MCLK,
+ mclk_min,
+ mclk_max);
+ if (ret)
+ return ret;
+ }
+
+ if (socclk_min && socclk_max) {
+ ret = yellow_carp_set_soft_freq_limited_range(smu,
+ SMU_SOCCLK,
+ socclk_min,
+ socclk_max);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
static int yellow_carp_set_fine_grain_gfx_freq_parameters(struct smu_context *smu)
{
DpmClocks_t *clk_table = smu->smu_table.clocks_table;
@@ -1088,6 +1171,7 @@ static const struct pptable_funcs yellow_carp_ppt_funcs = {
.od_edit_dpm_table = yellow_carp_od_edit_dpm_table,
.print_clk_levels = yellow_carp_print_clk_levels,
.force_clk_levels = yellow_carp_force_clk_levels,
+ .set_performance_level = yellow_carp_set_performance_level,
.set_fine_grain_gfx_freq_parameters = yellow_carp_set_fine_grain_gfx_freq_parameters,
};