Commit b7a90034 authored by Lijo Lazar's avatar Lijo Lazar Committed by Alex Deucher

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: default avatarLijo Lazar <lijo.lazar@amd.com>
Reviewed-by: default avatarAsad Kamal <asad.kamal@amd.com>
Tested-by: default avatarAsad Kamal <asad.kamal@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent efe0f34c
...@@ -1579,6 +1579,8 @@ static int smu_v13_0_6_set_performance_level(struct smu_context *smu, ...@@ -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_context *dpm_context = smu_dpm->dpm_context;
struct smu_13_0_dpm_table *gfx_table = struct smu_13_0_dpm_table *gfx_table =
&dpm_context->dpm_tables.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; struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
int ret; int ret;
...@@ -1594,17 +1596,27 @@ static int smu_v13_0_6_set_performance_level(struct smu_context *smu, ...@@ -1594,17 +1596,27 @@ static int smu_v13_0_6_set_performance_level(struct smu_context *smu,
return 0; return 0;
case AMD_DPM_FORCED_LEVEL_AUTO: case AMD_DPM_FORCED_LEVEL_AUTO:
if ((gfx_table->min == pstate_table->gfxclk_pstate.curr.min) && if ((gfx_table->min != pstate_table->gfxclk_pstate.curr.min) ||
(gfx_table->max == pstate_table->gfxclk_pstate.curr.max)) (gfx_table->max != pstate_table->gfxclk_pstate.curr.max)) {
return 0; 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( pstate_table->gfxclk_pstate.curr.min = gfx_table->min;
smu, gfx_table->min, gfx_table->max); pstate_table->gfxclk_pstate.curr.max = gfx_table->max;
if (ret) }
return ret;
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; return 0;
case AMD_DPM_FORCED_LEVEL_MANUAL: case AMD_DPM_FORCED_LEVEL_MANUAL:
return 0; return 0;
...@@ -1627,7 +1639,8 @@ static int smu_v13_0_6_set_soft_freq_limited_range(struct smu_context *smu, ...@@ -1627,7 +1639,8 @@ static int smu_v13_0_6_set_soft_freq_limited_range(struct smu_context *smu,
uint32_t max_clk; uint32_t max_clk;
int ret = 0; 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; return -EINVAL;
if ((smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) && 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, ...@@ -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 (smu_dpm->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
if (min >= max) { if (min >= max) {
dev_err(smu->adev->dev, 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; return -EINVAL;
} }
if ((min == pstate_table->gfxclk_pstate.curr.min) && if (clk_type == SMU_GFXCLK) {
(max == pstate_table->gfxclk_pstate.curr.max)) if ((min == pstate_table->gfxclk_pstate.curr.min) &&
return 0; (max == pstate_table->gfxclk_pstate.curr.max))
return 0;
ret = smu_v13_0_6_set_gfx_soft_freq_limited_range(smu, min, max); ret = smu_v13_0_6_set_gfx_soft_freq_limited_range(
if (!ret) { smu, min, max);
pstate_table->gfxclk_pstate.curr.min = min; if (!ret) {
pstate_table->gfxclk_pstate.curr.max = max; 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; return ret;
...@@ -1741,6 +1767,40 @@ static int smu_v13_0_6_usr_edit_dpm_table(struct smu_context *smu, ...@@ -1741,6 +1767,40 @@ static int smu_v13_0_6_usr_edit_dpm_table(struct smu_context *smu,
return -EINVAL; return -EINVAL;
} }
break; 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: case PP_OD_RESTORE_DEFAULT_TABLE:
if (size != 0) { if (size != 0) {
dev_err(smu->adev->dev, dev_err(smu->adev->dev,
...@@ -1751,8 +1811,19 @@ static int smu_v13_0_6_usr_edit_dpm_table(struct smu_context *smu, ...@@ -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; min_clk = dpm_context->dpm_tables.gfx_table.min;
max_clk = dpm_context->dpm_tables.gfx_table.max; 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); 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; break;
case PP_OD_COMMIT_DPM_TABLE: case PP_OD_COMMIT_DPM_TABLE:
...@@ -1772,8 +1843,19 @@ static int smu_v13_0_6_usr_edit_dpm_table(struct smu_context *smu, ...@@ -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; min_clk = pstate_table->gfxclk_pstate.custom.min;
max_clk = pstate_table->gfxclk_pstate.custom.max; 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); 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; break;
default: default:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment