mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 11:19:37 +00:00
drm/amd/pm: add the fine grain tuning function for vangogh
This patch is to add the fine grain tuning function for vangogh. This function uses the pp_od_clk_voltage sysfs file to configure the min and max value of gfx clock frequency or restore the default value. Command guide: echo "s level value" > pp_od_clk_voltage "s" - set the sclk frequency "level" - 0 or 1, "0" represents the min value, "1" represents the max value "value" - the target value of sclk frequency, it should be limited in the safe range echo "r" > pp_od_clk_voltage "r" - reset the sclk frequency, restore the default value instantly echo "c" > pp_od_clk_voltage "c" - commit the min and max value of sclk frequency to the system only after the commit command, the setting target values by "s" command will take effect. Example: 1)check the default sclk frequency $ cat pp_od_clk_voltage OD_SCLK: 0: 200Mhz 1: 1400Mhz OD_RANGE: SCLK: 200MHz 1400MHz 2)use "s" -- set command to configure the min or max sclk frequency $ echo "s 0 600" > pp_od_clk_voltage $ echo "s 1 1000" > pp_od_clk_voltage $ echo "c" > pp_od_clk_voltage $ cat pp_od_clk_voltage OD_SCLK: 0: 600Mhz 1: 1000Mhz OD_RANGE: SCLK: 200MHz 1400MHz 3)use "r" -- reset command to restore the min and max sclk frequency $ echo "r" > pp_od_clk_voltage $ cat pp_od_clk_voltage OD_SCLK: 0: 200Mhz 1: 1400Mhz OD_RANGE: SCLK: 200MHz 1400MHz Signed-off-by: Xiaojian Du <Xiaojian.Du@amd.com> Reviewed-by: Evan Quan <evan.quan@amd.com> Reviewed-by: Huang Rui <ray.huang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
5fe6b98ae0
commit
c98ee89736
4 changed files with 158 additions and 0 deletions
|
@ -459,6 +459,11 @@ struct smu_context
|
|||
|
||||
unsigned fan_max_rpm;
|
||||
unsigned manual_fan_speed_rpm;
|
||||
|
||||
uint32_t gfx_default_hard_min_freq;
|
||||
uint32_t gfx_default_soft_max_freq;
|
||||
uint32_t gfx_actual_hard_min_freq;
|
||||
uint32_t gfx_actual_soft_max_freq;
|
||||
};
|
||||
|
||||
struct i2c_adapter;
|
||||
|
@ -577,6 +582,7 @@ struct pptable_funcs {
|
|||
void (*interrupt_work)(struct smu_context *smu);
|
||||
int (*gpo_control)(struct smu_context *smu, bool enablement);
|
||||
int (*gfx_state_change_set)(struct smu_context *smu, uint32_t state);
|
||||
int (*set_fine_grain_gfx_freq_parameters)(struct smu_context *smu);
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -438,11 +438,13 @@ int smu_v11_0_fini_smc_tables(struct smu_context *smu)
|
|||
kfree(smu_table->overdrive_table);
|
||||
kfree(smu_table->max_sustainable_clocks);
|
||||
kfree(smu_table->driver_pptable);
|
||||
kfree(smu_table->clocks_table);
|
||||
smu_table->gpu_metrics_table = NULL;
|
||||
smu_table->boot_overdrive_table = NULL;
|
||||
smu_table->overdrive_table = NULL;
|
||||
smu_table->max_sustainable_clocks = NULL;
|
||||
smu_table->driver_pptable = NULL;
|
||||
smu_table->clocks_table = NULL;
|
||||
kfree(smu_table->hardcode_pptable);
|
||||
smu_table->hardcode_pptable = NULL;
|
||||
|
||||
|
|
|
@ -200,8 +200,14 @@ static int vangogh_tables_init(struct smu_context *smu)
|
|||
if (!smu_table->watermarks_table)
|
||||
goto err2_out;
|
||||
|
||||
smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL);
|
||||
if (!smu_table->clocks_table)
|
||||
goto err3_out;
|
||||
|
||||
return 0;
|
||||
|
||||
err3_out:
|
||||
kfree(smu_table->clocks_table);
|
||||
err2_out:
|
||||
kfree(smu_table->gpu_metrics_table);
|
||||
err1_out:
|
||||
|
@ -477,6 +483,35 @@ static int vangogh_get_current_clk_freq_by_table(struct smu_context *smu,
|
|||
value);
|
||||
}
|
||||
|
||||
static int vangogh_print_fine_grain_clk(struct smu_context *smu,
|
||||
enum smu_clk_type clk_type, char *buf)
|
||||
{
|
||||
int size = 0;
|
||||
|
||||
switch (clk_type) {
|
||||
case SMU_OD_SCLK:
|
||||
if (smu->od_enabled) {
|
||||
size = sprintf(buf, "%s:\n", "OD_SCLK");
|
||||
size += sprintf(buf + size, "0: %10uMhz\n",
|
||||
(smu->gfx_actual_hard_min_freq > 0) ? smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq);
|
||||
size += sprintf(buf + size, "1: %10uMhz\n",
|
||||
(smu->gfx_actual_soft_max_freq > 0) ? smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq);
|
||||
}
|
||||
break;
|
||||
case SMU_OD_RANGE:
|
||||
if (smu->od_enabled) {
|
||||
size = sprintf(buf, "%s:\n", "OD_RANGE");
|
||||
size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
|
||||
smu->gfx_default_hard_min_freq, smu->gfx_default_soft_max_freq);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static int vangogh_read_sensor(struct smu_context *smu,
|
||||
enum amd_pp_sensors sensor,
|
||||
void *data, uint32_t *size)
|
||||
|
@ -635,6 +670,116 @@ static ssize_t vangogh_get_gpu_metrics(struct smu_context *smu,
|
|||
return sizeof(struct gpu_metrics_v2_0);
|
||||
}
|
||||
|
||||
static int vangogh_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type,
|
||||
long input[], uint32_t size)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!smu->od_enabled) {
|
||||
dev_warn(smu->adev->dev, "Fine grain is not enabled!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case PP_OD_EDIT_SCLK_VDDC_TABLE:
|
||||
if (size != 2) {
|
||||
dev_err(smu->adev->dev, "Input parameter number not correct\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (input[0] == 0) {
|
||||
if (input[1] < smu->gfx_default_hard_min_freq) {
|
||||
dev_warn(smu->adev->dev, "Fine grain setting minimun sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n",
|
||||
input[1], smu->gfx_default_hard_min_freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
smu->gfx_actual_hard_min_freq = input[1];
|
||||
} else if (input[0] == 1) {
|
||||
if (input[1] > smu->gfx_default_soft_max_freq) {
|
||||
dev_warn(smu->adev->dev, "Fine grain setting maximun sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n",
|
||||
input[1], smu->gfx_default_soft_max_freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
smu->gfx_actual_soft_max_freq = input[1];
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case PP_OD_RESTORE_DEFAULT_TABLE:
|
||||
if (size != 0) {
|
||||
dev_err(smu->adev->dev, "Input parameter number not correct\n");
|
||||
return -EINVAL;
|
||||
} else {
|
||||
smu->gfx_actual_hard_min_freq = smu->gfx_default_hard_min_freq;
|
||||
smu->gfx_actual_soft_max_freq = smu->gfx_default_soft_max_freq;
|
||||
|
||||
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
|
||||
smu->gfx_actual_hard_min_freq, NULL);
|
||||
if (ret) {
|
||||
dev_err(smu->adev->dev, "Restore the default hard min sclk failed!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
|
||||
smu->gfx_actual_soft_max_freq, NULL);
|
||||
if (ret) {
|
||||
dev_err(smu->adev->dev, "Restore the default soft max sclk failed!");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PP_OD_COMMIT_DPM_TABLE:
|
||||
if (size != 0) {
|
||||
dev_err(smu->adev->dev, "Input parameter number not correct\n");
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (smu->gfx_actual_hard_min_freq > smu->gfx_actual_soft_max_freq) {
|
||||
dev_err(smu->adev->dev, "The setting minimun sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n",
|
||||
smu->gfx_actual_hard_min_freq, smu->gfx_actual_soft_max_freq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk,
|
||||
smu->gfx_actual_hard_min_freq, NULL);
|
||||
if (ret) {
|
||||
dev_err(smu->adev->dev, "Set hard min sclk failed!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
|
||||
smu->gfx_actual_soft_max_freq, NULL);
|
||||
if (ret) {
|
||||
dev_err(smu->adev->dev, "Set soft max sclk failed!");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int vangogh_set_default_dpm_tables(struct smu_context *smu)
|
||||
{
|
||||
struct smu_table_context *smu_table = &smu->smu_table;
|
||||
|
||||
return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0, smu_table->clocks_table, false);
|
||||
}
|
||||
|
||||
static int vangogh_set_fine_grain_gfx_freq_parameters(struct smu_context *smu)
|
||||
{
|
||||
DpmClocks_t *clk_table = smu->smu_table.clocks_table;
|
||||
|
||||
smu->gfx_default_hard_min_freq = clk_table->MinGfxClk;
|
||||
smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk;
|
||||
smu->gfx_actual_hard_min_freq = 0;
|
||||
smu->gfx_actual_soft_max_freq = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pptable_funcs vangogh_ppt_funcs = {
|
||||
|
||||
.check_fw_status = smu_v11_0_check_fw_status,
|
||||
|
@ -659,6 +804,10 @@ static const struct pptable_funcs vangogh_ppt_funcs = {
|
|||
.disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception,
|
||||
.interrupt_work = smu_v11_0_interrupt_work,
|
||||
.get_gpu_metrics = vangogh_get_gpu_metrics,
|
||||
.od_edit_dpm_table = vangogh_od_edit_dpm_table,
|
||||
.print_clk_levels = vangogh_print_fine_grain_clk,
|
||||
.set_default_dpm_table = vangogh_set_default_dpm_tables,
|
||||
.set_fine_grain_gfx_freq_parameters = vangogh_set_fine_grain_gfx_freq_parameters,
|
||||
};
|
||||
|
||||
void vangogh_set_ppt_funcs(struct smu_context *smu)
|
||||
|
|
|
@ -90,6 +90,7 @@
|
|||
#define smu_get_fan_parameters(smu) smu_ppt_funcs(get_fan_parameters, 0, smu)
|
||||
#define smu_post_init(smu) smu_ppt_funcs(post_init, 0, smu)
|
||||
#define smu_gpo_control(smu, enablement) smu_ppt_funcs(gpo_control, 0, smu, enablement)
|
||||
#define smu_set_fine_grain_gfx_freq_parameters(smu) smu_ppt_funcs(set_fine_grain_gfx_freq_parameters, 0, smu)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue