Commit c16df976 authored by Likun Gao's avatar Likun Gao Committed by Alex Deucher

drm/amd/powerplay: adjust power state when set od_clk

Expose the function of adjust_power_state_dynamic to make it common to
other functions.
Add the operate of adjust powet state when set od percentage or
overdrive commit dpm table.
Signed-off-by: default avatarLikun Gao <Likun.Gao@amd.com>
Reviewed-by: default avatarHuang Rui <ray.huang@amd.com>
Reviewed-by: default avatarKevin Wang <kevin1.wang@amd.com>
Acked-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent e388cc47
...@@ -1764,44 +1764,35 @@ static enum amd_dpm_forced_level vega20_get_performance_level(struct smu_context ...@@ -1764,44 +1764,35 @@ static enum amd_dpm_forced_level vega20_get_performance_level(struct smu_context
return smu_dpm_ctx->dpm_level; return smu_dpm_ctx->dpm_level;
} }
static int static int vega20_adjust_power_state_dynamic(struct smu_context *smu,
vega20_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level) enum amd_dpm_forced_level level)
{ {
int ret = 0; int ret = 0;
int index = 0; int index = 0;
int i = 0;
uint32_t sclk_mask, mclk_mask, soc_mask; uint32_t sclk_mask, mclk_mask, soc_mask;
long workload; long workload;
struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
if (!smu_dpm_ctx->dpm_context)
return -EINVAL;
for (i = 0; i < smu->adev->num_ip_blocks; i++) {
if (smu->adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC)
break;
}
mutex_lock(&smu->mutex);
smu->adev->ip_blocks[i].version->funcs->enable_umd_pstate(smu, &level);
ret = vega20_display_config_changed(smu); ret = vega20_display_config_changed(smu);
if (ret) { if (ret) {
pr_err("Failed to change display config!"); pr_err("Failed to change display config!");
goto failed; return ret;
} }
ret = vega20_apply_clocks_adjust_rules(smu); ret = vega20_apply_clocks_adjust_rules(smu);
if (ret) { if (ret) {
pr_err("Failed to apply clocks adjust rules!"); pr_err("Failed to apply clocks adjust rules!");
goto failed; return ret;
} }
ret = vega20_notify_smc_dispaly_config(smu); ret = vega20_notify_smc_dispaly_config(smu);
if (ret) { if (ret) {
pr_err("Failed to notify smc display config!"); pr_err("Failed to notify smc display config!");
goto failed; return ret;
} }
switch (level) { switch (level) {
case AMD_DPM_FORCED_LEVEL_HIGH: case AMD_DPM_FORCED_LEVEL_HIGH:
ret = vega20_force_dpm_highest(smu); ret = vega20_force_dpm_highest(smu);
break; break;
case AMD_DPM_FORCED_LEVEL_LOW: case AMD_DPM_FORCED_LEVEL_LOW:
ret = vega20_force_dpm_lowest(smu); ret = vega20_force_dpm_lowest(smu);
break; break;
...@@ -1819,7 +1810,7 @@ vega20_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_leve ...@@ -1819,7 +1810,7 @@ vega20_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_leve
&mclk_mask, &mclk_mask,
&soc_mask); &soc_mask);
if (ret) if (ret)
goto failed; return ret;
vega20_force_clk_levels(smu, PP_SCLK, 1 << sclk_mask); vega20_force_clk_levels(smu, PP_SCLK, 1 << sclk_mask);
vega20_force_clk_levels(smu, PP_MCLK, 1 << mclk_mask); vega20_force_clk_levels(smu, PP_MCLK, 1 << mclk_mask);
break; break;
...@@ -1842,8 +1833,31 @@ vega20_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_leve ...@@ -1842,8 +1833,31 @@ vega20_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_leve
smu->funcs->set_power_profile_mode(smu, &workload, 0); smu->funcs->set_power_profile_mode(smu, &workload, 0);
} }
failed: return ret;
}
static int
vega20_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
{
int ret = 0;
int i;
struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
if (!smu_dpm_ctx->dpm_context)
return -EINVAL;
for (i = 0; i < smu->adev->num_ip_blocks; i++) {
if (smu->adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC)
break;
}
mutex_lock(&smu->mutex);
smu->adev->ip_blocks[i].version->funcs->enable_umd_pstate(smu, &level);
ret = vega20_adjust_power_state_dynamic(smu, level);
mutex_unlock(&smu->mutex); mutex_unlock(&smu->mutex);
return ret; return ret;
} }
...@@ -1934,9 +1948,12 @@ static int vega20_set_od_percentage(struct smu_context *smu, ...@@ -1934,9 +1948,12 @@ static int vega20_set_od_percentage(struct smu_context *smu,
struct vega20_single_dpm_table *single_dpm_table; struct vega20_single_dpm_table *single_dpm_table;
struct vega20_single_dpm_table *golden_dpm_table; struct vega20_single_dpm_table *golden_dpm_table;
uint32_t od_clk, index; uint32_t od_clk, index;
int ret, feature_enabled; int ret = 0;
int feature_enabled;
PPCLK_e clk_id; PPCLK_e clk_id;
mutex_lock(&(smu->mutex));
dpm_table = smu_dpm->dpm_context; dpm_table = smu_dpm->dpm_context;
golden_table = smu_dpm->golden_dpm_context; golden_table = smu_dpm->golden_dpm_context;
...@@ -1956,10 +1973,13 @@ static int vega20_set_od_percentage(struct smu_context *smu, ...@@ -1956,10 +1973,13 @@ static int vega20_set_od_percentage(struct smu_context *smu,
index = OD8_SETTING_UCLK_FMAX; index = OD8_SETTING_UCLK_FMAX;
break; break;
default: default:
return -EINVAL; ret = -EINVAL;
break; break;
} }
if (ret)
goto set_od_failed;
od_clk = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value * value; od_clk = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value * value;
od_clk /= 100; od_clk /= 100;
od_clk += golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value; od_clk += golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value;
...@@ -1967,7 +1987,7 @@ static int vega20_set_od_percentage(struct smu_context *smu, ...@@ -1967,7 +1987,7 @@ static int vega20_set_od_percentage(struct smu_context *smu,
ret = smu_update_od8_settings(smu, index, od_clk); ret = smu_update_od8_settings(smu, index, od_clk);
if (ret) { if (ret) {
pr_err("[Setoverdrive] failed to set od clk!\n"); pr_err("[Setoverdrive] failed to set od clk!\n");
return ret; goto set_od_failed;
} }
if (feature_enabled) { if (feature_enabled) {
...@@ -1975,14 +1995,19 @@ static int vega20_set_od_percentage(struct smu_context *smu, ...@@ -1975,14 +1995,19 @@ static int vega20_set_od_percentage(struct smu_context *smu,
clk_id); clk_id);
if (ret) { if (ret) {
pr_err("[Setoverdrive] failed to refresh dpm table!\n"); pr_err("[Setoverdrive] failed to refresh dpm table!\n");
return ret; goto set_od_failed;
} }
} else { } else {
single_dpm_table->count = 1; single_dpm_table->count = 1;
single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100;
} }
return 0; ret = vega20_adjust_power_state_dynamic(smu, smu_dpm->dpm_level);
set_od_failed:
mutex_unlock(&(smu->mutex));
return ret;
} }
static int vega20_odn_edit_dpm_table(struct smu_context *smu, static int vega20_odn_edit_dpm_table(struct smu_context *smu,
...@@ -1999,7 +2024,8 @@ static int vega20_odn_edit_dpm_table(struct smu_context *smu, ...@@ -1999,7 +2024,8 @@ static int vega20_odn_edit_dpm_table(struct smu_context *smu,
(struct vega20_od8_settings *)table_context->od8_settings; (struct vega20_od8_settings *)table_context->od8_settings;
struct pp_clock_levels_with_latency clocks; struct pp_clock_levels_with_latency clocks;
int32_t input_index, input_clk, input_vol, i; int32_t input_index, input_clk, input_vol, i;
int od8_id, ret; int od8_id;
int ret = 0;
dpm_table = smu_dpm->dpm_context; dpm_table = smu_dpm->dpm_context;
...@@ -2204,7 +2230,13 @@ static int vega20_odn_edit_dpm_table(struct smu_context *smu, ...@@ -2204,7 +2230,13 @@ static int vega20_odn_edit_dpm_table(struct smu_context *smu,
return -EINVAL; return -EINVAL;
} }
return 0; if (type == PP_OD_COMMIT_DPM_TABLE) {
mutex_lock(&(smu->mutex));
ret = vega20_adjust_power_state_dynamic(smu, smu_dpm->dpm_level);
mutex_unlock(&(smu->mutex));
}
return ret;
} }
static const struct pptable_funcs vega20_ppt_funcs = { static const struct pptable_funcs vega20_ppt_funcs = {
......
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