[PATCH] drm/amd/powerplay: add one sysfs file -- "pp_od_clk_voltage" to support the feature to modify gfx engine clock(Mhz units) on Raven/Raven2/Picasso APU.
Huang Rui
ray.huang at amd.com
Mon Sep 28 09:15:56 UTC 2020
On Mon, Sep 28, 2020 at 03:15:30PM +0800, Du, Xiaojian wrote:
> From: Xiaojian Du <xiaojian.du at amd.com>
>
> From: Xiaojian Du <Xiaojian.Du at amd.com>
>
> 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 at amd.com>
Reviewed-by: Huang Rui <ray.huang at amd.com>
> ---
> .../gpu/drm/amd/include/kgd_pp_interface.h | 1 +
> drivers/gpu/drm/amd/pm/amdgpu_pm.c | 12 +++
> drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 4 +
> drivers/gpu/drm/amd/pm/inc/hwmgr.h | 5 ++
> .../gpu/drm/amd/pm/powerplay/amd_powerplay.c | 17 +++-
> .../drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c | 79 +++++++++++++++++++
> 6 files changed, 117 insertions(+), 1 deletion(-)
>
> 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 b5d2f30043ad..fe0de00f56e2 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..bb8d077d3f05 100644
> --- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
> +++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
> @@ -911,6 +911,20 @@ 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 +934,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 +1659,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 9ee8cf8267c8..791db107d51a 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,8 @@ 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;
>
> + hwmgr->od_enabled = 1; /*enable the pp_od_clk_voltage sysfs file*/
> +
> return result;
> }
>
> @@ -947,6 +977,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;
> }
> @@ -1348,6 +1398,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,
> @@ -1388,9 +1464,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)
> --
> 2.17.1
>
More information about the amd-gfx
mailing list