OSDN Git Service

drm/amd/powerplay: add sys interface for set sclk_od/mclk_od for smu
authorLikun Gao <Likun.Gao@amd.com>
Fri, 18 Jan 2019 08:15:14 +0000 (16:15 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 19 Mar 2019 20:04:00 +0000 (15:04 -0500)
Add sys interface for set pp_sclk_od and pp_mclk_od for smu.

Signed-off-by: Likun Gao <Likun.Gao@amd.com>
Reviewed-by: Huang Rui <ray.huang@amd.com>
Reviewed-by: Kevin Wang <kevin1.wang@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
drivers/gpu/drm/amd/powerplay/vega20_ppt.c

index 52cb630..eb17ab9 100644 (file)
@@ -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:
index d824739..c3bc9a7 100644 (file)
@@ -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) \
index d5469fc..d025f54 100644 (file)
@@ -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)