From e9c5b46e3c50f58403aeca6d6419b9235d2518b2 Mon Sep 17 00:00:00 2001 From: Likun Gao Date: Fri, 18 Jan 2019 16:15:14 +0800 Subject: [PATCH] drm/amd/powerplay: add sys interface for set sclk_od/mclk_od for smu Add sys interface for set pp_sclk_od and pp_mclk_od for smu. Signed-off-by: Likun Gao Reviewed-by: Huang Rui Reviewed-by: Kevin Wang Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 34 ++++++---- .../gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 5 ++ drivers/gpu/drm/amd/powerplay/vega20_ppt.c | 62 +++++++++++++++++++ 3 files changed, 89 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 52cb63030b9a..eb17ab94e4bf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -1069,14 +1069,19 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, count = -EINVAL; goto fail; } - if (adev->powerplay.pp_funcs->set_sclk_od) - amdgpu_dpm_set_sclk_od(adev, (uint32_t)value); - if (adev->powerplay.pp_funcs->dispatch_tasks) { - amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL); + if (is_support_sw_smu(adev)) { + value = smu_set_od_percentage(&(adev->smu), OD_SCLK, (uint32_t)value); } else { - adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; - amdgpu_pm_compute_clocks(adev); + if (adev->powerplay.pp_funcs->set_sclk_od) + amdgpu_dpm_set_sclk_od(adev, (uint32_t)value); + + if (adev->powerplay.pp_funcs->dispatch_tasks) { + amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL); + } else { + adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; + amdgpu_pm_compute_clocks(adev); + } } fail: @@ -1115,14 +1120,19 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, count = -EINVAL; goto fail; } - if (adev->powerplay.pp_funcs->set_mclk_od) - amdgpu_dpm_set_mclk_od(adev, (uint32_t)value); - if (adev->powerplay.pp_funcs->dispatch_tasks) { - amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL); + if (is_support_sw_smu(adev)) { + value = smu_set_od_percentage(&(adev->smu), OD_MCLK, (uint32_t)value); } else { - adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; - amdgpu_pm_compute_clocks(adev); + if (adev->powerplay.pp_funcs->set_mclk_od) + amdgpu_dpm_set_mclk_od(adev, (uint32_t)value); + + if (adev->powerplay.pp_funcs->dispatch_tasks) { + amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL); + } else { + adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; + amdgpu_pm_compute_clocks(adev); + } } fail: diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h index d824739f7408..c3bc9a7e3f48 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h @@ -414,6 +414,9 @@ struct pptable_funcs { uint32_t index, uint32_t value); int (*get_od_percentage)(struct smu_context *smu, enum pp_clock_type type); + int (*set_od_percentage)(struct smu_context *smu, + enum pp_clock_type type, + uint32_t value); int (*get_clock_by_type_with_latency)(struct smu_context *smu, enum amd_pp_clock_type type, struct @@ -598,6 +601,8 @@ struct smu_funcs ((smu)->ppt_funcs->force_clk_levels ? (smu)->ppt_funcs->force_clk_levels((smu), (type), (level)) : 0) #define smu_get_od_percentage(smu, type) \ ((smu)->ppt_funcs->get_od_percentage ? (smu)->ppt_funcs->get_od_percentage((smu), (type)) : 0) +#define smu_set_od_percentage(smu, type, value) \ + ((smu)->ppt_funcs->set_od_percentage ? (smu)->ppt_funcs->set_od_percentage((smu), (type), (value)) : 0) #define smu_start_thermal_control(smu) \ ((smu)->funcs->start_thermal_control? (smu)->funcs->start_thermal_control((smu)) : 0) #define smu_read_sensor(smu, sensor, data, size) \ diff --git a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c index d5469fccfffc..d025f54285ed 100644 --- a/drivers/gpu/drm/amd/powerplay/vega20_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/vega20_ppt.c @@ -1924,6 +1924,67 @@ static int vega20_update_specified_od8_value(struct smu_context *smu, return 0; } +static int vega20_set_od_percentage(struct smu_context *smu, + enum pp_clock_type type, + uint32_t value) +{ + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; + struct vega20_dpm_table *dpm_table = NULL; + struct vega20_dpm_table *golden_table = NULL; + struct vega20_single_dpm_table *single_dpm_table; + struct vega20_single_dpm_table *golden_dpm_table; + uint32_t od_clk, index; + int ret, feature_enabled; + PPCLK_e clk_id; + + dpm_table = smu_dpm->dpm_context; + golden_table = smu_dpm->golden_dpm_context; + + switch (type) { + case OD_SCLK: + single_dpm_table = &(dpm_table->gfx_table); + golden_dpm_table = &(golden_table->gfx_table); + feature_enabled = smu_feature_is_enabled(smu, FEATURE_DPM_GFXCLK_BIT); + clk_id = PPCLK_GFXCLK; + index = OD8_SETTING_GFXCLK_FMAX; + break; + case OD_MCLK: + single_dpm_table = &(dpm_table->mem_table); + golden_dpm_table = &(golden_table->mem_table); + feature_enabled = smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT); + clk_id = PPCLK_UCLK; + index = OD8_SETTING_UCLK_FMAX; + break; + default: + return -EINVAL; + break; + } + + od_clk = golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value * value; + od_clk /= 100; + od_clk += golden_dpm_table->dpm_levels[golden_dpm_table->count - 1].value; + + ret = smu_update_od8_settings(smu, index, od_clk); + if (ret) { + pr_err("[Setoverdrive] failed to set od clk!\n"); + return ret; + } + + if (feature_enabled) { + ret = vega20_set_single_dpm_table(smu, single_dpm_table, + clk_id); + if (ret) { + pr_err("[Setoverdrive] failed to refresh dpm table!\n"); + return ret; + } + } else { + single_dpm_table->count = 1; + single_dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; + } + + return 0; +} + static const struct pptable_funcs vega20_ppt_funcs = { .alloc_dpm_context = vega20_allocate_dpm_context, .store_powerplay_table = vega20_store_powerplay_table, @@ -1944,6 +2005,7 @@ static const struct pptable_funcs vega20_ppt_funcs = { .get_performance_level = vega20_get_performance_level, .force_performance_level = vega20_force_performance_level, .update_specified_od8_value = vega20_update_specified_od8_value, + .set_od_percentage = vega20_set_od_percentage, }; void vega20_set_ppt_funcs(struct smu_context *smu) -- 2.30.2