This patch is to add the fine grain tuning function for vangogh.
This function uses the pp_od_clk_voltage sysfs file to configure the min
and max value of gfx clock frequency or restore the default value.

Command guide:
echo "s level value" > pp_od_clk_voltage
        "s" - set the sclk frequency
        "level" - 0 or 1, "0" represents the min value,  "1" represents
        the max value
        "value" - the target value of sclk frequency, it should be
        limited in the
        safe range.
echo "r" > pp_od_clk_voltage
        "r" - reset the sclk frequency, restore the default value
echo "c" > pp_od_clk_voltage
        "c" - commit the min and max value of sclk frequency to the system.
        only after the commit command, the target values will take
        effect.
Example:
1)check the default sclk frequency
        $ cat pp_od_clk_voltage
        OD_SCLK:
        0:        200Mhz
        1:       1400Mhz
        OD_RANGE:
        SCLK:     200MHz       1400MHz
2)use "s" -- set command to configure the min or max sclk frequency
        $ echo "s 0 600" > pp_od_clk_voltage
        $ echo "s 1 1000" > pp_od_clk_voltage
        $ echo "c" > pp_od_clk_voltage
        $ cat pp_od_clk_voltage
        OD_SCLK:
        0:        600Mhz
        1:       1000Mhz
        OD_RANGE:
        SCLK:     200MHz       1400MHz
3)use "r" -- reset command to restore the min and max sclk frequency
        $ echo "r" > pp_od_clk_voltage
        & echo "c" > pp_od_clk_voltage
        $ cat pp_od_clk_voltage
        OD_SCLK:
        0:        200Mhz
        1:       1400Mhz
        OD_RANGE:
        SCLK:     200MHz       1400MHz

Signed-off-by: Xiaojian Du <xiaojian...@amd.com>
---
 drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h       |   6 +
 .../gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c    |   2 +
 .../gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c  | 135 ++++++++++++++++++
 drivers/gpu/drm/amd/pm/swsmu/smu_internal.h   |   1 +
 4 files changed, 144 insertions(+)

diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h 
b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
index ae8ff7b07932..7550757cc059 100644
--- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h
@@ -459,6 +459,11 @@ struct smu_context
 
        unsigned fan_max_rpm;
        unsigned manual_fan_speed_rpm;
+
+       uint32_t gfx_default_hard_min_freq;
+       uint32_t gfx_default_soft_max_freq;
+       uint32_t gfx_actual_hard_min_freq;
+       uint32_t gfx_actual_soft_max_freq;
 };
 
 struct i2c_adapter;
@@ -577,6 +582,7 @@ struct pptable_funcs {
        void (*interrupt_work)(struct smu_context *smu);
        int (*gpo_control)(struct smu_context *smu, bool enablement);
        int (*gfx_state_change_set)(struct smu_context *smu, uint32_t state);
+       int (*set_fine_grain_gfx_freq_parameters)(struct smu_context *smu);
 };
 
 typedef enum {
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
index b880c72c322c..b23311096467 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
@@ -438,11 +438,13 @@ int smu_v11_0_fini_smc_tables(struct smu_context *smu)
        kfree(smu_table->overdrive_table);
        kfree(smu_table->max_sustainable_clocks);
        kfree(smu_table->driver_pptable);
+       kfree(smu_table->clocks_table);
        smu_table->gpu_metrics_table = NULL;
        smu_table->boot_overdrive_table = NULL;
        smu_table->overdrive_table = NULL;
        smu_table->max_sustainable_clocks = NULL;
        smu_table->driver_pptable = NULL;
+       smu_table->clocks_table = NULL;
        kfree(smu_table->hardcode_pptable);
        smu_table->hardcode_pptable = NULL;
 
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
index cbcbcd8514f0..299ad695f607 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
@@ -200,8 +200,14 @@ static int vangogh_tables_init(struct smu_context *smu)
        if (!smu_table->watermarks_table)
                goto err2_out;
 
+       smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL);
+       if (!smu_table->clocks_table)
+               goto err3_out;
+
        return 0;
 
+err3_out:
+       kfree(smu_table->clocks_table);
 err2_out:
        kfree(smu_table->gpu_metrics_table);
 err1_out:
@@ -477,6 +483,35 @@ static int vangogh_get_current_clk_freq_by_table(struct 
smu_context *smu,
                                           value);
 }
 
+static int vangogh_print_fine_grain_clk(struct smu_context *smu,
+                       enum smu_clk_type clk_type, char *buf)
+{
+       int size = 0;
+
+       switch (clk_type) {
+       case SMU_OD_SCLK:
+               if (smu->od_enabled) {
+                       size = sprintf(buf, "%s:\n", "OD_SCLK");
+                       size += sprintf(buf + size, "0: %10uMhz\n",
+                       (smu->gfx_actual_hard_min_freq > 0) ? 
smu->gfx_actual_hard_min_freq : smu->gfx_default_hard_min_freq);
+                       size += sprintf(buf + size, "1: %10uMhz\n",
+                       (smu->gfx_actual_soft_max_freq > 0) ? 
smu->gfx_actual_soft_max_freq : smu->gfx_default_soft_max_freq);
+               }
+               break;
+       case SMU_OD_RANGE:
+               if (smu->od_enabled) {
+                       size = sprintf(buf, "%s:\n", "OD_RANGE");
+                       size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n",
+                               smu->gfx_default_hard_min_freq, 
smu->gfx_default_soft_max_freq);
+               }
+               break;
+       default:
+               break;
+       }
+
+       return size;
+}
+
 static int vangogh_read_sensor(struct smu_context *smu,
                                 enum amd_pp_sensors sensor,
                                 void *data, uint32_t *size)
@@ -635,6 +670,102 @@ static ssize_t vangogh_get_gpu_metrics(struct smu_context 
*smu,
        return sizeof(struct gpu_metrics_v2_0);
 }
 
+static int vangogh_od_edit_dpm_table(struct smu_context *smu, enum 
PP_OD_DPM_TABLE_COMMAND type,
+                                                       long input[], uint32_t 
size)
+{
+       int ret = 0;
+
+       if (!smu->od_enabled) {
+               dev_warn(smu->adev->dev, "Fine grain is not enabled!\n");
+               return -EINVAL;
+       }
+
+       switch (type) {
+       case PP_OD_EDIT_SCLK_VDDC_TABLE:
+               if (size != 2) {
+                       dev_err(smu->adev->dev, "Input parameter number not 
correct\n");
+                       return -EINVAL;
+               }
+
+               if (input[0] == 0) {
+                       if (input[1] < smu->gfx_default_hard_min_freq) {
+                               dev_warn(smu->adev->dev, "Fine grain setting 
minimun sclk (%ld) MHz is less than the minimum allowed (%d) MHz\n",
+                                       input[1], 
smu->gfx_default_hard_min_freq);
+                               return -EINVAL;
+                       }
+                       smu->gfx_actual_hard_min_freq = input[1];
+               } else if (input[0] == 1) {
+                       if (input[1] > smu->gfx_default_soft_max_freq) {
+                               dev_warn(smu->adev->dev, "Fine grain setting 
maximun sclk (%ld) MHz is greater than the maximum allowed (%d) MHz\n",
+                                       input[1], 
smu->gfx_default_soft_max_freq);
+                               return -EINVAL;
+                       }
+                       smu->gfx_actual_soft_max_freq = input[1];
+               } else {
+                       return -EINVAL;
+               }
+               break;
+       case PP_OD_RESTORE_DEFAULT_TABLE:
+               if (size != 0) {
+                       dev_err(smu->adev->dev, "Input parameter number not 
correct\n");
+                       return -EINVAL;
+               } else {
+                       smu->gfx_actual_hard_min_freq = 
smu->gfx_default_hard_min_freq;
+                       smu->gfx_actual_soft_max_freq = 
smu->gfx_default_soft_max_freq;
+               }
+               break;
+       case PP_OD_COMMIT_DPM_TABLE:
+               if (size != 0) {
+                       dev_err(smu->adev->dev, "Input parameter number not 
correct\n");
+                       return -EINVAL;
+               } else {
+                       if (smu->gfx_actual_hard_min_freq > 
smu->gfx_actual_soft_max_freq) {
+                               dev_err(smu->adev->dev, "The setting minimun 
sclk (%d) MHz is greater than the setting maximum sclk (%d) MHz\n",
+                               smu->gfx_actual_hard_min_freq, 
smu->gfx_actual_soft_max_freq);
+                               return -EINVAL;
+                       }
+
+                       ret = smu_cmn_send_smc_msg_with_param(smu, 
SMU_MSG_SetHardMinGfxClk,
+                                                                       
smu->gfx_actual_hard_min_freq, NULL);
+                       if (ret) {
+                               dev_err(smu->adev->dev, "Set hard min sclk 
failed!");
+                               return ret;
+                       }
+
+                       ret = smu_cmn_send_smc_msg_with_param(smu, 
SMU_MSG_SetSoftMaxGfxClk,
+                                                                       
smu->gfx_actual_soft_max_freq, NULL);
+                       if (ret) {
+                               dev_err(smu->adev->dev, "Set soft max sclk 
failed!");
+                               return ret;
+                       }
+               }
+               break;
+       default:
+               return -ENOSYS;
+       }
+
+       return ret;
+}
+
+int vangogh_set_default_dpm_tables(struct smu_context *smu)
+{
+       struct smu_table_context *smu_table = &smu->smu_table;
+
+       return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0, 
smu_table->clocks_table, false);
+}
+
+static int vangogh_set_fine_grain_gfx_freq_parameters(struct smu_context *smu)
+{
+       DpmClocks_t *clk_table = smu->smu_table.clocks_table;
+
+       smu->gfx_default_hard_min_freq = clk_table->MinGfxClk;
+       smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk;
+       smu->gfx_actual_hard_min_freq = 0;
+       smu->gfx_actual_soft_max_freq = 0;
+
+       return 0;
+}
+
 static const struct pptable_funcs vangogh_ppt_funcs = {
 
        .check_fw_status = smu_v11_0_check_fw_status,
@@ -659,6 +790,10 @@ static const struct pptable_funcs vangogh_ppt_funcs = {
        .disable_all_features_with_exception = 
smu_cmn_disable_all_features_with_exception,
        .interrupt_work = smu_v11_0_interrupt_work,
        .get_gpu_metrics = vangogh_get_gpu_metrics,
+       .od_edit_dpm_table = vangogh_od_edit_dpm_table,
+       .print_clk_levels = vangogh_print_fine_grain_clk,
+       .set_default_dpm_table = vangogh_set_default_dpm_tables,
+       .set_fine_grain_gfx_freq_parameters = 
vangogh_set_fine_grain_gfx_freq_parameters,
 };
 
 void vangogh_set_ppt_funcs(struct smu_context *smu)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h 
b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
index f7be2d1a0ff2..68d9464ababc 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
@@ -90,6 +90,7 @@
 #define smu_get_fan_parameters(smu)                                    
smu_ppt_funcs(get_fan_parameters, 0, smu)
 #define smu_post_init(smu)                                             
smu_ppt_funcs(post_init, 0, smu)
 #define smu_gpo_control(smu, enablement)                               
smu_ppt_funcs(gpo_control, 0, smu, enablement)
+#define smu_set_fine_grain_gfx_freq_parameters(smu)                            
        smu_ppt_funcs(set_fine_grain_gfx_freq_parameters, 0, smu)
 
 #endif
 #endif
-- 
2.17.1

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to