On Mon, Sep 28, 2020 at 03:15:30PM +0800, Du, Xiaojian wrote:
> From: Xiaojian Du <[email protected]>
> 
> From: Xiaojian Du <[email protected]>
> 
> 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 <[email protected]>

Reviewed-by: Huang Rui <[email protected]>

> ---
>  .../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
> 
_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to