diff options
author | Xiaojian Du <Xiaojian.Du@amd.com> | 2020-09-27 12:07:02 +0300 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2020-09-29 23:12:16 +0300 |
commit | 12a6727dee5d1119fc1556b870848f511414bf5d (patch) | |
tree | 934fd1c5b055c08048c53e890e7b12bac3754d40 /drivers/gpu | |
parent | 72e71a82d6986b2259168575b1cea7fb78f9da32 (diff) | |
download | linux-12a6727dee5d1119fc1556b870848f511414bf5d.tar.xz |
drm/amd/powerplay: add one sysfs file to support the feature to modify gfx clock on Raven/Raven2/Picasso APU.
This patch is to add one sysfs file -- "pp_od_clk_voltage" for
Raven/Raven2/Picasso APU, which is only used by dGPU like VEGA10.
This sysfs file supports the feature to modify gfx engine clock(Mhz units), it can
be used to configure the min value and the max value for gfx clock limited in the
safe range.
Command guide:
echo "s level clock" > pp_od_clk_voltage
s - adjust teh sclk level
level - 0 or 1, "0" represents the min value, "1" represents the max value
clock - the clock value(Mhz units), like 400, 800 or 1200, the value must be within the
OD_RANGE limits.
Example:
$ cat pp_od_clk_voltage
OD_SCLK:
0: 200Mhz
1: 1400Mhz
OD_RANGE:
SCLK: 200MHz 1400MHz
$ echo "s 0 600" > pp_od_clk_voltage
$ echo "s 1 1000" > pp_od_clk_voltage
$ cat pp_od_clk_voltage
OD_SCLK:
0: 600Mhz
1: 1000Mhz
OD_RANGE:
SCLK: 200MHz 1400MHz
Signed-off-by: Xiaojian Du <Xiaojian.Du@amd.com>
Reviewed-by: Kevin Wang <kevin1.wang@amd.com>
Reviewed-by: Huang Rui <ray.huang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/amd/include/kgd_pp_interface.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/amdgpu_pm.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/inc/hwmgr.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c | 80 | ||||
-rw-r--r-- | drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h | 2 |
7 files changed, 118 insertions, 2 deletions
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index 0aec28fda058..94132c70d7af 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -281,6 +281,7 @@ struct amd_pm_funcs { int (*get_power_limit)(void *handle, uint32_t *limit, bool default_limit); int (*get_power_profile_mode)(void *handle, char *buf); int (*set_power_profile_mode)(void *handle, long *input, uint32_t size); + int (*set_fine_grain_clk_vol)(void *handle, uint32_t type, long *input, uint32_t size); int (*odn_edit_dpm_table)(void *handle, uint32_t type, long *input, uint32_t size); int (*set_mp1_state)(void *handle, enum pp_mp1_state mp1_state); int (*smu_i2c_bus_access)(void *handle, bool acquire); diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 2d924e88a215..529816637c73 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -827,6 +827,18 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, return -EINVAL; } } else { + + if (adev->powerplay.pp_funcs->set_fine_grain_clk_vol) { + ret = amdgpu_dpm_set_fine_grain_clk_vol(adev, type, + parameter, + parameter_size); + if (ret) { + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return -EINVAL; + } + } + if (adev->powerplay.pp_funcs->odn_edit_dpm_table) { ret = amdgpu_dpm_odn_edit_dpm_table(adev, type, parameter, parameter_size); diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h index dff4a5f99bb0..f6e0e7d8a007 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -349,6 +349,10 @@ enum amdgpu_pcie_gen { ((adev)->powerplay.pp_funcs->set_power_profile_mode(\ (adev)->powerplay.pp_handle, parameter, size)) +#define amdgpu_dpm_set_fine_grain_clk_vol(adev, type, parameter, size) \ + ((adev)->powerplay.pp_funcs->set_fine_grain_clk_vol(\ + (adev)->powerplay.pp_handle, type, parameter, size)) + #define amdgpu_dpm_odn_edit_dpm_table(adev, type, parameter, size) \ ((adev)->powerplay.pp_funcs->odn_edit_dpm_table(\ (adev)->powerplay.pp_handle, type, parameter, size)) diff --git a/drivers/gpu/drm/amd/pm/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/inc/hwmgr.h index 1b3529efc91e..3898a95ec28b 100644 --- a/drivers/gpu/drm/amd/pm/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/pm/inc/hwmgr.h @@ -340,6 +340,9 @@ struct pp_hwmgr_func { int (*odn_edit_dpm_table)(struct pp_hwmgr *hwmgr, enum PP_OD_DPM_TABLE_COMMAND type, long *input, uint32_t size); + int (*set_fine_grain_clk_vol)(struct pp_hwmgr *hwmgr, + enum PP_OD_DPM_TABLE_COMMAND type, + long *input, uint32_t size); int (*set_power_limit)(struct pp_hwmgr *hwmgr, uint32_t n); int (*powergate_mmhub)(struct pp_hwmgr *hwmgr); int (*smus_notify_pwe)(struct pp_hwmgr *hwmgr); @@ -347,6 +350,8 @@ struct pp_hwmgr_func { int (*enable_mgpu_fan_boost)(struct pp_hwmgr *hwmgr); int (*set_hard_min_dcefclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock); int (*set_hard_min_fclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock); + int (*set_hard_min_gfxclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock); + int (*set_soft_max_gfxclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock); int (*get_asic_baco_capability)(struct pp_hwmgr *hwmgr, bool *cap); int (*get_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE *state); int (*set_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE state); diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c index a6321f2063c1..eab9768029c1 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c @@ -911,6 +911,19 @@ static int pp_set_power_profile_mode(void *handle, long *input, uint32_t size) return ret; } +static int pp_set_fine_grain_clk_vol(void *handle, uint32_t type, long *input, uint32_t size) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->set_fine_grain_clk_vol == NULL) + return 0; + + return hwmgr->hwmgr_func->set_fine_grain_clk_vol(hwmgr, type, input, size); +} + static int pp_odn_edit_dpm_table(void *handle, uint32_t type, long *input, uint32_t size) { struct pp_hwmgr *hwmgr = handle; @@ -920,7 +933,7 @@ static int pp_odn_edit_dpm_table(void *handle, uint32_t type, long *input, uint3 if (hwmgr->hwmgr_func->odn_edit_dpm_table == NULL) { pr_info_ratelimited("%s was not implemented.\n", __func__); - return -EINVAL; + return 0; } return hwmgr->hwmgr_func->odn_edit_dpm_table(hwmgr, type, input, size); @@ -1645,6 +1658,7 @@ static const struct amd_pm_funcs pp_dpm_funcs = { .set_powergating_by_smu = pp_set_powergating_by_smu, .get_power_profile_mode = pp_get_power_profile_mode, .set_power_profile_mode = pp_set_power_profile_mode, + .set_fine_grain_clk_vol = pp_set_fine_grain_clk_vol, .odn_edit_dpm_table = pp_odn_edit_dpm_table, .set_mp1_state = pp_dpm_set_mp1_state, .set_power_limit = pp_set_power_limit, diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c index e0ac54608e88..cf60f3992303 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c @@ -242,6 +242,34 @@ static int smu10_set_hard_min_fclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t cloc return 0; } +static int smu10_set_hard_min_gfxclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock) +{ + struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); + + if (clock && smu10_data->gfx_actual_soft_min_freq != clock) { + smu10_data->gfx_actual_soft_min_freq = clock; + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinGfxClk, + smu10_data->gfx_actual_soft_min_freq, + NULL); + } + return 0; +} + +static int smu10_set_soft_max_gfxclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock) +{ + struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); + + if (clock && smu10_data->gfx_max_freq_limit != (clock * 100)) { + smu10_data->gfx_max_freq_limit = clock * 100; + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxGfxClk, + clock, + NULL); + } + return 0; +} + static int smu10_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count) { struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); @@ -527,6 +555,9 @@ static int smu10_hwmgr_backend_init(struct pp_hwmgr *hwmgr) hwmgr->pstate_sclk = SMU10_UMD_PSTATE_GFXCLK * 100; hwmgr->pstate_mclk = SMU10_UMD_PSTATE_FCLK * 100; + /* enable the pp_od_clk_voltage sysfs file */ + hwmgr->od_enabled = 1; + return result; } @@ -949,6 +980,26 @@ static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr, ((mclk_table->entries[i].clk / 100) == now) ? "*" : ""); break; + case OD_SCLK: + if (hwmgr->od_enabled) { + size = sprintf(buf, "%s:\n", "OD_SCLK"); + + size += sprintf(buf + size, "0: %10uMhz\n", + (data->gfx_actual_soft_min_freq > 0) ? data->gfx_actual_soft_min_freq : data->gfx_min_freq_limit/100); + size += sprintf(buf + size, "1: %10uMhz\n", data->gfx_max_freq_limit/100); + } + break; + case OD_RANGE: + if (hwmgr->od_enabled) { + uint32_t min_freq, max_freq = 0; + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMinGfxclkFrequency, &min_freq); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxGfxclkFrequency, &max_freq); + + size = sprintf(buf, "%s:\n", "OD_RANGE"); + size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n", + min_freq, max_freq); + } + break; default: break; } @@ -1361,6 +1412,32 @@ static int smu10_asic_reset(struct pp_hwmgr *hwmgr, enum SMU_ASIC_RESET_MODE mod NULL); } +static int smu10_set_fine_grain_clk_vol(struct pp_hwmgr *hwmgr, + enum PP_OD_DPM_TABLE_COMMAND type, + long *input, uint32_t size) +{ + if (!hwmgr->od_enabled) { + pr_err("Fine grain not support\n"); + return -EINVAL; + } + + if (size != 2) { + pr_err("Input parameter number not correct\n"); + return -EINVAL; + } + + if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) { + if (input[0] == 0) + smu10_set_hard_min_gfxclk_by_freq(hwmgr, input[1]); + else if (input[0] == 1) + smu10_set_soft_max_gfxclk_by_freq(hwmgr, input[1]); + else + return -EINVAL; + } + + return 0; +} + static const struct pp_hwmgr_func smu10_hwmgr_funcs = { .backend_init = smu10_hwmgr_backend_init, .backend_fini = smu10_hwmgr_backend_fini, @@ -1401,9 +1478,12 @@ static const struct pp_hwmgr_func smu10_hwmgr_funcs = { .powergate_sdma = smu10_powergate_sdma, .set_hard_min_dcefclk_by_freq = smu10_set_hard_min_dcefclk_by_freq, .set_hard_min_fclk_by_freq = smu10_set_hard_min_fclk_by_freq, + .set_hard_min_gfxclk_by_freq = smu10_set_hard_min_gfxclk_by_freq, + .set_soft_max_gfxclk_by_freq = smu10_set_soft_max_gfxclk_by_freq, .get_power_profile_mode = smu10_get_power_profile_mode, .set_power_profile_mode = smu10_set_power_profile_mode, .asic_reset = smu10_asic_reset, + .set_fine_grain_clk_vol = smu10_set_fine_grain_clk_vol, }; int smu10_init_function_pointers(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h index ee0c9591620b..6c9b5f060902 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h @@ -284,7 +284,7 @@ struct smu10_hwmgr { uint32_t dclk_soft_min; uint32_t gfx_actual_soft_min_freq; uint32_t gfx_min_freq_limit; - uint32_t gfx_max_freq_limit; + uint32_t gfx_max_freq_limit; /* in 10Khz*/ bool vcn_power_gated; bool vcn_dpg_mode; |