Commit b840e4d5 authored by Kevin Wang's avatar Kevin Wang Committed by Alex Deucher

drm/amd/powerplay: custom peak clock freq for navi10

v2:
add function smu_default_set_performance_level as default dpm level handler.
change function name smu_set_performance_level to smu_asic_set_performance_level

v1:
1.NAVI10_PEAK_SCLK_XTX    1830 Mhz
2.NAVI10_PEAK_SCLK_XT     1755 Mhz
3.NAVI10_PEAK_SCLK_XL     1625 Mhz
Signed-off-by: default avatarKevin Wang <kevin1.wang@amd.com>
Reviewed-by: default avatarHuang Rui <ray.huang@amd.com>
Reviewed-by: default avatarKenneth Feng <kenneth.feng@amd.com>
Reviewed-by: default avatarEvan Quan <evan.quan@amd.com>
Reviewed-by: default avatarJack Gui <Jack.Gui@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent b7066693
...@@ -1374,13 +1374,49 @@ static int smu_enable_umd_pstate(void *handle, ...@@ -1374,13 +1374,49 @@ static int smu_enable_umd_pstate(void *handle,
return 0; return 0;
} }
static int smu_default_set_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
{
int ret = 0;
uint32_t sclk_mask, mclk_mask, soc_mask;
switch (level) {
case AMD_DPM_FORCED_LEVEL_HIGH:
ret = smu_force_dpm_limit_value(smu, true);
break;
case AMD_DPM_FORCED_LEVEL_LOW:
ret = smu_force_dpm_limit_value(smu, false);
break;
case AMD_DPM_FORCED_LEVEL_AUTO:
case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
ret = smu_unforce_dpm_levels(smu);
break;
case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
ret = smu_get_profiling_clk_mask(smu, level,
&sclk_mask,
&mclk_mask,
&soc_mask);
if (ret)
return ret;
smu_force_clk_levels(smu, SMU_SCLK, 1 << sclk_mask);
smu_force_clk_levels(smu, SMU_MCLK, 1 << mclk_mask);
smu_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask);
break;
case AMD_DPM_FORCED_LEVEL_MANUAL:
case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
default:
break;
}
return ret;
}
int smu_adjust_power_state_dynamic(struct smu_context *smu, int smu_adjust_power_state_dynamic(struct smu_context *smu,
enum amd_dpm_forced_level level, enum amd_dpm_forced_level level,
bool skip_display_settings) bool skip_display_settings)
{ {
int ret = 0; int ret = 0;
int index = 0; int index = 0;
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);
...@@ -1411,39 +1447,10 @@ int smu_adjust_power_state_dynamic(struct smu_context *smu, ...@@ -1411,39 +1447,10 @@ int smu_adjust_power_state_dynamic(struct smu_context *smu,
} }
if (smu_dpm_ctx->dpm_level != level) { if (smu_dpm_ctx->dpm_level != level) {
switch (level) { ret = smu_asic_set_performance_level(smu, level);
case AMD_DPM_FORCED_LEVEL_HIGH: if (ret) {
ret = smu_force_dpm_limit_value(smu, true); ret = smu_default_set_performance_level(smu, level);
break;
case AMD_DPM_FORCED_LEVEL_LOW:
ret = smu_force_dpm_limit_value(smu, false);
break;
case AMD_DPM_FORCED_LEVEL_AUTO:
case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
ret = smu_unforce_dpm_levels(smu);
break;
case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
ret = smu_get_profiling_clk_mask(smu, level,
&sclk_mask,
&mclk_mask,
&soc_mask);
if (ret)
return ret;
smu_force_clk_levels(smu, SMU_SCLK, 1 << sclk_mask);
smu_force_clk_levels(smu, SMU_MCLK, 1 << mclk_mask);
smu_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask);
break;
case AMD_DPM_FORCED_LEVEL_MANUAL:
case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
default:
break;
} }
if (!ret) if (!ret)
smu_dpm_ctx->dpm_level = level; smu_dpm_ctx->dpm_level = level;
} }
......
...@@ -621,6 +621,7 @@ struct pptable_funcs { ...@@ -621,6 +621,7 @@ struct pptable_funcs {
int (*get_thermal_temperature_range)(struct smu_context *smu, struct smu_temperature_range *range); int (*get_thermal_temperature_range)(struct smu_context *smu, struct smu_temperature_range *range);
int (*get_uclk_dpm_states)(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states); int (*get_uclk_dpm_states)(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states);
int (*set_default_od_settings)(struct smu_context *smu, bool initialize); int (*set_default_od_settings)(struct smu_context *smu, bool initialize);
int (*set_performance_level)(struct smu_context *smu, enum amd_dpm_forced_level level);
}; };
struct smu_funcs struct smu_funcs
...@@ -918,6 +919,9 @@ struct smu_funcs ...@@ -918,6 +919,9 @@ struct smu_funcs
((smu)->funcs->baco_get_state? (smu)->funcs->baco_get_state((smu), (state)) : 0) ((smu)->funcs->baco_get_state? (smu)->funcs->baco_get_state((smu), (state)) : 0)
#define smu_baco_reset(smu) \ #define smu_baco_reset(smu) \
((smu)->funcs->baco_reset? (smu)->funcs->baco_reset((smu)) : 0) ((smu)->funcs->baco_reset? (smu)->funcs->baco_reset((smu)) : 0)
#define smu_asic_set_performance_level(smu, level) \
((smu)->ppt_funcs->set_performance_level? (smu)->ppt_funcs->set_performance_level((smu), (level)) : -EINVAL);
extern int smu_get_atom_data_table(struct smu_context *smu, uint32_t table, extern int smu_get_atom_data_table(struct smu_context *smu, uint32_t table,
uint16_t *size, uint8_t *frev, uint8_t *crev, uint16_t *size, uint8_t *frev, uint8_t *crev,
......
...@@ -1565,6 +1565,60 @@ static int navi10_set_ppfeature_status(struct smu_context *smu, ...@@ -1565,6 +1565,60 @@ static int navi10_set_ppfeature_status(struct smu_context *smu,
return 0; return 0;
} }
static int navi10_set_peak_clock_by_device(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
int ret = 0;
uint32_t sclk_freq = 0, uclk_freq = 0;
uint32_t uclk_level = 0;
switch (adev->rev_id) {
case 0xf0: /* XTX */
case 0xc0:
sclk_freq = NAVI10_PEAK_SCLK_XTX;
break;
case 0xf1: /* XT */
case 0xc1:
sclk_freq = NAVI10_PEAK_SCLK_XT;
break;
default: /* XL */
sclk_freq = NAVI10_PEAK_SCLK_XL;
break;
}
ret = smu_get_dpm_level_count(smu, SMU_UCLK, &uclk_level);
if (ret)
return ret;
ret = smu_get_dpm_freq_by_index(smu, SMU_UCLK, uclk_level - 1, &uclk_freq);
if (ret)
return ret;
ret = smu_set_soft_freq_range(smu, SMU_SCLK, sclk_freq, sclk_freq);
if (ret)
return ret;
ret = smu_set_soft_freq_range(smu, SMU_UCLK, uclk_freq, uclk_freq);
if (ret)
return ret;
return ret;
}
static int navi10_set_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level)
{
int ret = 0;
switch (level) {
case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
ret = navi10_set_peak_clock_by_device(smu);
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
static const struct pptable_funcs navi10_ppt_funcs = { static const struct pptable_funcs navi10_ppt_funcs = {
.tables_init = navi10_tables_init, .tables_init = navi10_tables_init,
.alloc_dpm_context = navi10_allocate_dpm_context, .alloc_dpm_context = navi10_allocate_dpm_context,
...@@ -1600,6 +1654,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { ...@@ -1600,6 +1654,7 @@ static const struct pptable_funcs navi10_ppt_funcs = {
.get_uclk_dpm_states = navi10_get_uclk_dpm_states, .get_uclk_dpm_states = navi10_get_uclk_dpm_states,
.get_ppfeature_status = navi10_get_ppfeature_status, .get_ppfeature_status = navi10_get_ppfeature_status,
.set_ppfeature_status = navi10_set_ppfeature_status, .set_ppfeature_status = navi10_set_ppfeature_status,
.set_performance_level = navi10_set_performance_level,
}; };
void navi10_set_ppt_funcs(struct smu_context *smu) void navi10_set_ppt_funcs(struct smu_context *smu)
......
...@@ -23,6 +23,10 @@ ...@@ -23,6 +23,10 @@
#ifndef __NAVI10_PPT_H__ #ifndef __NAVI10_PPT_H__
#define __NAVI10_PPT_H__ #define __NAVI10_PPT_H__
#define NAVI10_PEAK_SCLK_XTX (1830)
#define NAVI10_PEAK_SCLK_XT (1755)
#define NAVI10_PEAK_SCLK_XL (1625)
extern void navi10_set_ppt_funcs(struct smu_context *smu); extern void navi10_set_ppt_funcs(struct smu_context *smu);
#endif #endif
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