From d54e9e70f5e86e510eac888a683587136455444e Mon Sep 17 00:00:00 2001 From: Xiaomeng Hou Date: Mon, 22 Feb 2021 16:44:30 +0800 Subject: drm/amd/pm: add the fine grain tuning function for yellow carp Use the pp_od_clk_voltage sysfs file to configure the min and max value of gfx clock frequency or to restore the default values. 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 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: 600Mhz OD_RANGE: SCLK: 200MHz 600MHz 2) use "s" -- set command to configure the min or max sclk frequency $ echo "s 0 300" > pp_od_clk_voltage $ echo "s 1 500" > pp_od_clk_voltage $ echo "c" > pp_od_clk_voltage $ cat pp_od_clk_voltage OD_SCLK: 0: 300Mhz 1: 500Mhz OD_RANGE: SCLK: 200MHz 600MHz 3) use "r" -- reset command to restore the min and max sclk frequency $ echo "r" > pp_od_clk_voltage $ echo "c" > pp_od_clk_voltage $ cat pp_od_clk_voltage OD_SCLK: 0: 200Mhz 1: 600Mhz OD_RANGE: SCLK: 200MHz 600MHz v2: modify the description of reset command usage - need to do "commit" after set the restore command Signed-off-by: Xiaomeng Hou Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- .../gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c | 116 +++++++++++++++++++++ 1 file changed, 116 insertions(+) (limited to 'drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c') 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 71ebdaba029f..fa871df86d86 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 @@ -382,6 +382,119 @@ static int yellow_carp_set_watermarks_table(struct smu_context *smu, return 0; } +static int yellow_carp_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type, + long input[], uint32_t size) +{ + int ret = 0; + + 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 minimum 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 maximum 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; + } + 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; +} + +static int yellow_carp_print_clk_levels(struct smu_context *smu, + enum smu_clk_type clk_type, char *buf) +{ + int size = 0; + + switch (clk_type) { + case SMU_OD_SCLK: + 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: + 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 yellow_carp_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 yellow_carp_ppt_funcs = { .check_fw_status = smu_v13_0_1_check_fw_status, .check_fw_version = smu_v13_0_1_check_fw_version, @@ -400,6 +513,9 @@ static const struct pptable_funcs yellow_carp_ppt_funcs = { .set_driver_table_location = smu_v13_0_1_set_driver_table_location, .gfx_off_control = smu_v13_0_1_gfx_off_control, .post_init = yellow_carp_post_smu_init, + .od_edit_dpm_table = yellow_carp_od_edit_dpm_table, + .print_clk_levels = yellow_carp_print_clk_levels, + .set_fine_grain_gfx_freq_parameters = yellow_carp_set_fine_grain_gfx_freq_parameters, }; void yellow_carp_set_ppt_funcs(struct smu_context *smu) -- cgit