drm/amdgpu/swsmu: add automatic parameter to set_soft_freq_range
authorAlex Deucher <alexander.deucher@amd.com>
Tue, 1 Oct 2024 14:31:26 +0000 (10:31 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 15 Oct 2024 15:27:08 +0000 (11:27 -0400)
On chips that support it, you can specificy 0 and 0xffff for
min and max and the PMFW will use that to determine the optimal
min and max.  This enables optimal performance when the
user manually switches between performance levels using sysfs.
Previously we'd set soft min/max which could limit performance.

Reviewed-by: Kenneth Feng <kenneth.feng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
21 files changed:
drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v11_0.h
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v12_0.h
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c
drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c
drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c

index 0bd8821..82b8832 100644 (file)
@@ -140,7 +140,8 @@ int smu_set_soft_freq_range(struct smu_context *smu,
                ret = smu->ppt_funcs->set_soft_freq_limited_range(smu,
                                                                  clk_type,
                                                                  min,
-                                                                 max);
+                                                                 max,
+                                                                 false);
 
        return ret;
 }
index 727da0c..8bb32b3 100644 (file)
@@ -1255,7 +1255,8 @@ struct pptable_funcs {
         * @set_soft_freq_limited_range: Set the soft frequency range of a clock
         *                               domain in MHz.
         */
-       int (*set_soft_freq_limited_range)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t min, uint32_t max);
+       int (*set_soft_freq_limited_range)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t min, uint32_t max,
+                                          bool automatic);
 
        /**
         * @set_power_source: Notify the SMU of the current power source.
index c2ab336..ed8304d 100644 (file)
@@ -255,7 +255,7 @@ int smu_v11_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type c
                                                 uint32_t *min, uint32_t *max);
 
 int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_type clk_type,
-                           uint32_t min, uint32_t max);
+                                         uint32_t min, uint32_t max, bool automatic);
 
 int smu_v11_0_set_hard_freq_limited_range(struct smu_context *smu,
                                          enum smu_clk_type clk_type,
index 1ad2dff..0886d8c 100644 (file)
@@ -56,7 +56,7 @@ int smu_v12_0_set_default_dpm_tables(struct smu_context *smu);
 int smu_v12_0_mode2_reset(struct smu_context *smu);
 
 int smu_v12_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_type clk_type,
-                           uint32_t min, uint32_t max);
+                                         uint32_t min, uint32_t max, bool automatic);
 
 int smu_v12_0_set_driver_table_location(struct smu_context *smu);
 
index e58220a..044d689 100644 (file)
@@ -219,7 +219,7 @@ int smu_v13_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type c
                                    uint32_t *min, uint32_t *max);
 
 int smu_v13_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_type clk_type,
-                                         uint32_t min, uint32_t max);
+                                         uint32_t min, uint32_t max, bool automatic);
 
 int smu_v13_0_set_hard_freq_limited_range(struct smu_context *smu,
                                          enum smu_clk_type clk_type,
index 46b4565..6cada19 100644 (file)
@@ -186,7 +186,7 @@ int smu_v14_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type c
                                    uint32_t *min, uint32_t *max);
 
 int smu_v14_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_type clk_type,
-                                         uint32_t min, uint32_t max);
+                                         uint32_t min, uint32_t max, bool automatic);
 
 int smu_v14_0_set_hard_freq_limited_range(struct smu_context *smu,
                                          enum smu_clk_type clk_type,
index 16af1a3..9fa305b 100644 (file)
@@ -1689,7 +1689,7 @@ static int navi10_force_clk_levels(struct smu_context *smu,
                if (ret)
                        return 0;
 
-               ret = smu_v11_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq);
+               ret = smu_v11_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq, false);
                if (ret)
                        return 0;
                break;
index 3b29cb7..77e58eb 100644 (file)
@@ -1469,7 +1469,7 @@ static int sienna_cichlid_force_clk_levels(struct smu_context *smu,
                if (ret)
                        goto forec_level_out;
 
-               ret = smu_v11_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq);
+               ret = smu_v11_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq, false);
                if (ret)
                        goto forec_level_out;
                break;
index 8981302..480cf3c 100644 (file)
@@ -1764,7 +1764,8 @@ failed:
 int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu,
                                          enum smu_clk_type clk_type,
                                          uint32_t min,
-                                         uint32_t max)
+                                         uint32_t max,
+                                         bool automatic)
 {
        int ret = 0, clk_id = 0;
        uint32_t param;
@@ -1779,7 +1780,10 @@ int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu,
                return clk_id;
 
        if (max > 0) {
-               param = (uint32_t)((clk_id << 16) | (max & 0xffff));
+               if (automatic)
+                       param = (uint32_t)((clk_id << 16) | 0xffff);
+               else
+                       param = (uint32_t)((clk_id << 16) | (max & 0xffff));
                ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxByFreq,
                                                  param, NULL);
                if (ret)
@@ -1787,7 +1791,10 @@ int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu,
        }
 
        if (min > 0) {
-               param = (uint32_t)((clk_id << 16) | (min & 0xffff));
+               if (automatic)
+                       param = (uint32_t)((clk_id << 16) | 0);
+               else
+                       param = (uint32_t)((clk_id << 16) | (min & 0xffff));
                ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMinByFreq,
                                                  param, NULL);
                if (ret)
@@ -1855,6 +1862,7 @@ int smu_v11_0_set_performance_level(struct smu_context *smu,
        uint32_t mclk_min = 0, mclk_max = 0;
        uint32_t socclk_min = 0, socclk_max = 0;
        int ret = 0;
+       bool auto_level = false;
 
        switch (level) {
        case AMD_DPM_FORCED_LEVEL_HIGH:
@@ -1874,6 +1882,7 @@ int smu_v11_0_set_performance_level(struct smu_context *smu,
                mclk_max = mem_table->max;
                socclk_min = soc_table->min;
                socclk_max = soc_table->max;
+               auto_level = true;
                break;
        case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
                sclk_min = sclk_max = pstate_table->gfxclk_pstate.standard;
@@ -1906,13 +1915,15 @@ int smu_v11_0_set_performance_level(struct smu_context *smu,
        if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(11, 0, 2)) {
                mclk_min = mclk_max = 0;
                socclk_min = socclk_max = 0;
+               auto_level = false;
        }
 
        if (sclk_min && sclk_max) {
                ret = smu_v11_0_set_soft_freq_limited_range(smu,
                                                            SMU_GFXCLK,
                                                            sclk_min,
-                                                           sclk_max);
+                                                           sclk_max,
+                                                           auto_level);
                if (ret)
                        return ret;
        }
@@ -1921,7 +1932,8 @@ int smu_v11_0_set_performance_level(struct smu_context *smu,
                ret = smu_v11_0_set_soft_freq_limited_range(smu,
                                                            SMU_MCLK,
                                                            mclk_min,
-                                                           mclk_max);
+                                                           mclk_max,
+                                                           auto_level);
                if (ret)
                        return ret;
        }
@@ -1930,7 +1942,8 @@ int smu_v11_0_set_performance_level(struct smu_context *smu,
                ret = smu_v11_0_set_soft_freq_limited_range(smu,
                                                            SMU_SOCCLK,
                                                            socclk_min,
-                                                           socclk_max);
+                                                           socclk_max,
+                                                           auto_level);
                if (ret)
                        return ret;
        }
index 22737b1..a333ab8 100644 (file)
@@ -1091,9 +1091,10 @@ static int vangogh_set_power_profile_mode(struct smu_context *smu, long *input,
 }
 
 static int vangogh_set_soft_freq_limited_range(struct smu_context *smu,
-                                         enum smu_clk_type clk_type,
-                                         uint32_t min,
-                                         uint32_t max)
+                                              enum smu_clk_type clk_type,
+                                              uint32_t min,
+                                              uint32_t max,
+                                              bool automatic)
 {
        int ret = 0;
 
@@ -1299,7 +1300,7 @@ static int vangogh_force_dpm_limit_value(struct smu_context *smu, bool highest)
                        return ret;
 
                force_freq = highest ? max_freq : min_freq;
-               ret = vangogh_set_soft_freq_limited_range(smu, clk_type, force_freq, force_freq);
+               ret = vangogh_set_soft_freq_limited_range(smu, clk_type, force_freq, force_freq, false);
                if (ret)
                        return ret;
        }
@@ -1335,7 +1336,7 @@ static int vangogh_unforce_dpm_levels(struct smu_context *smu)
                if (ret)
                        return ret;
 
-               ret = vangogh_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq);
+               ret = vangogh_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq, false);
 
                if (ret)
                        return ret;
@@ -1354,7 +1355,7 @@ static int vangogh_set_peak_clock_by_device(struct smu_context *smu)
        if (ret)
                return ret;
 
-       ret = vangogh_set_soft_freq_limited_range(smu, SMU_FCLK, fclk_freq, fclk_freq);
+       ret = vangogh_set_soft_freq_limited_range(smu, SMU_FCLK, fclk_freq, fclk_freq, false);
        if (ret)
                return ret;
 
@@ -1362,7 +1363,7 @@ static int vangogh_set_peak_clock_by_device(struct smu_context *smu)
        if (ret)
                return ret;
 
-       ret = vangogh_set_soft_freq_limited_range(smu, SMU_SOCCLK, socclk_freq, socclk_freq);
+       ret = vangogh_set_soft_freq_limited_range(smu, SMU_SOCCLK, socclk_freq, socclk_freq, false);
        if (ret)
                return ret;
 
@@ -1370,7 +1371,7 @@ static int vangogh_set_peak_clock_by_device(struct smu_context *smu)
        if (ret)
                return ret;
 
-       ret = vangogh_set_soft_freq_limited_range(smu, SMU_VCLK, vclk_freq, vclk_freq);
+       ret = vangogh_set_soft_freq_limited_range(smu, SMU_VCLK, vclk_freq, vclk_freq, false);
        if (ret)
                return ret;
 
@@ -1378,7 +1379,7 @@ static int vangogh_set_peak_clock_by_device(struct smu_context *smu)
        if (ret)
                return ret;
 
-       ret = vangogh_set_soft_freq_limited_range(smu, SMU_DCLK, dclk_freq, dclk_freq);
+       ret = vangogh_set_soft_freq_limited_range(smu, SMU_DCLK, dclk_freq, dclk_freq, false);
        if (ret)
                return ret;
 
index cc0504b..0b210b1 100644 (file)
@@ -707,7 +707,7 @@ static int renoir_force_dpm_limit_value(struct smu_context *smu, bool highest)
                        return ret;
 
                force_freq = highest ? max_freq : min_freq;
-               ret = smu_v12_0_set_soft_freq_limited_range(smu, clk_type, force_freq, force_freq);
+               ret = smu_v12_0_set_soft_freq_limited_range(smu, clk_type, force_freq, force_freq, false);
                if (ret)
                        return ret;
        }
@@ -740,7 +740,7 @@ static int renoir_unforce_dpm_levels(struct smu_context *smu) {
                if (ret)
                        return ret;
 
-               ret = smu_v12_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq);
+               ret = smu_v12_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq, false);
                if (ret)
                        return ret;
        }
@@ -911,7 +911,7 @@ static int renoir_set_peak_clock_by_device(struct smu_context *smu)
        if (ret)
                return ret;
 
-       ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_SCLK, sclk_freq, sclk_freq);
+       ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_SCLK, sclk_freq, sclk_freq, false);
        if (ret)
                return ret;
 
@@ -919,7 +919,7 @@ static int renoir_set_peak_clock_by_device(struct smu_context *smu)
        if (ret)
                return ret;
 
-       ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_UCLK, uclk_freq, uclk_freq);
+       ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_UCLK, uclk_freq, uclk_freq, false);
        if (ret)
                return ret;
 
@@ -961,13 +961,13 @@ static int renior_set_dpm_profile_freq(struct smu_context *smu,
        }
 
        if (sclk)
-               ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_SCLK, sclk, sclk);
+               ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_SCLK, sclk, sclk, false);
 
        if (socclk)
-               ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_SOCCLK, socclk, socclk);
+               ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_SOCCLK, socclk, socclk, false);
 
        if (fclk)
-               ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_FCLK, fclk, fclk);
+               ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_FCLK, fclk, fclk, false);
 
        return ret;
 }
index ed15f5a..3d3cd54 100644 (file)
@@ -211,7 +211,7 @@ int smu_v12_0_mode2_reset(struct smu_context *smu)
 }
 
 int smu_v12_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_type clk_type,
-                           uint32_t min, uint32_t max)
+                                         uint32_t min, uint32_t max, bool automatic)
 {
        int ret = 0;
 
index 2c35eb3..f6b0293 100644 (file)
@@ -1297,9 +1297,10 @@ static int aldebaran_set_performance_level(struct smu_context *smu,
 }
 
 static int aldebaran_set_soft_freq_limited_range(struct smu_context *smu,
-                                         enum smu_clk_type clk_type,
-                                         uint32_t min,
-                                         uint32_t max)
+                                                enum smu_clk_type clk_type,
+                                                uint32_t min,
+                                                uint32_t max,
+                                                bool automatic)
 {
        struct smu_dpm_context *smu_dpm = &(smu->smu_dpm);
        struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
@@ -1328,7 +1329,7 @@ static int aldebaran_set_soft_freq_limited_range(struct smu_context *smu,
                        return 0;
 
                ret = smu_v13_0_set_soft_freq_limited_range(smu, SMU_GFXCLK,
-                                                           min, max);
+                                                           min, max, false);
                if (!ret) {
                        pstate_table->gfxclk_pstate.curr.min = min;
                        pstate_table->gfxclk_pstate.curr.max = max;
@@ -1348,7 +1349,7 @@ static int aldebaran_set_soft_freq_limited_range(struct smu_context *smu,
                /* Restore default min/max clocks and enable determinism */
                min_clk = dpm_context->dpm_tables.gfx_table.min;
                max_clk = dpm_context->dpm_tables.gfx_table.max;
-               ret = smu_v13_0_set_soft_freq_limited_range(smu, SMU_GFXCLK, min_clk, max_clk);
+               ret = smu_v13_0_set_soft_freq_limited_range(smu, SMU_GFXCLK, min_clk, max_clk, false);
                if (!ret) {
                        usleep_range(500, 1000);
                        ret = smu_cmn_send_smc_msg_with_param(smu,
@@ -1422,7 +1423,7 @@ static int aldebaran_usr_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_
                        min_clk = dpm_context->dpm_tables.gfx_table.min;
                        max_clk = dpm_context->dpm_tables.gfx_table.max;
 
-                       return aldebaran_set_soft_freq_limited_range(smu, SMU_GFXCLK, min_clk, max_clk);
+                       return aldebaran_set_soft_freq_limited_range(smu, SMU_GFXCLK, min_clk, max_clk, false);
                }
                break;
        case PP_OD_COMMIT_DPM_TABLE:
@@ -1441,7 +1442,7 @@ static int aldebaran_usr_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_
                        min_clk = pstate_table->gfxclk_pstate.custom.min;
                        max_clk = pstate_table->gfxclk_pstate.custom.max;
 
-                       return aldebaran_set_soft_freq_limited_range(smu, SMU_GFXCLK, min_clk, max_clk);
+                       return aldebaran_set_soft_freq_limited_range(smu, SMU_GFXCLK, min_clk, max_clk, false);
                }
                break;
        default:
index e17466c..6cfd663 100644 (file)
@@ -1608,7 +1608,8 @@ failed:
 int smu_v13_0_set_soft_freq_limited_range(struct smu_context *smu,
                                          enum smu_clk_type clk_type,
                                          uint32_t min,
-                                         uint32_t max)
+                                         uint32_t max,
+                                         bool automatic)
 {
        int ret = 0, clk_id = 0;
        uint32_t param;
@@ -1623,7 +1624,10 @@ int smu_v13_0_set_soft_freq_limited_range(struct smu_context *smu,
                return clk_id;
 
        if (max > 0) {
-               param = (uint32_t)((clk_id << 16) | (max & 0xffff));
+               if (automatic)
+                       param = (uint32_t)((clk_id << 16) | 0xffff);
+               else
+                       param = (uint32_t)((clk_id << 16) | (max & 0xffff));
                ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxByFreq,
                                                      param, NULL);
                if (ret)
@@ -1631,7 +1635,10 @@ int smu_v13_0_set_soft_freq_limited_range(struct smu_context *smu,
        }
 
        if (min > 0) {
-               param = (uint32_t)((clk_id << 16) | (min & 0xffff));
+               if (automatic)
+                       param = (uint32_t)((clk_id << 16) | 0);
+               else
+                       param = (uint32_t)((clk_id << 16) | (min & 0xffff));
                ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMinByFreq,
                                                      param, NULL);
                if (ret)
@@ -1708,6 +1715,7 @@ int smu_v13_0_set_performance_level(struct smu_context *smu,
        uint32_t dclk_min = 0, dclk_max = 0;
        uint32_t fclk_min = 0, fclk_max = 0;
        int ret = 0, i;
+       bool auto_level = false;
 
        switch (level) {
        case AMD_DPM_FORCED_LEVEL_HIGH:
@@ -1739,6 +1747,7 @@ int smu_v13_0_set_performance_level(struct smu_context *smu,
                dclk_max = dclk_table->max;
                fclk_min = fclk_table->min;
                fclk_max = fclk_table->max;
+               auto_level = true;
                break;
        case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
                sclk_min = sclk_max = pstate_table->gfxclk_pstate.standard;
@@ -1780,13 +1789,15 @@ int smu_v13_0_set_performance_level(struct smu_context *smu,
                vclk_min = vclk_max = 0;
                dclk_min = dclk_max = 0;
                fclk_min = fclk_max = 0;
+               auto_level = false;
        }
 
        if (sclk_min && sclk_max) {
                ret = smu_v13_0_set_soft_freq_limited_range(smu,
                                                            SMU_GFXCLK,
                                                            sclk_min,
-                                                           sclk_max);
+                                                           sclk_max,
+                                                           auto_level);
                if (ret)
                        return ret;
 
@@ -1798,7 +1809,8 @@ int smu_v13_0_set_performance_level(struct smu_context *smu,
                ret = smu_v13_0_set_soft_freq_limited_range(smu,
                                                            SMU_MCLK,
                                                            mclk_min,
-                                                           mclk_max);
+                                                           mclk_max,
+                                                           auto_level);
                if (ret)
                        return ret;
 
@@ -1810,7 +1822,8 @@ int smu_v13_0_set_performance_level(struct smu_context *smu,
                ret = smu_v13_0_set_soft_freq_limited_range(smu,
                                                            SMU_SOCCLK,
                                                            socclk_min,
-                                                           socclk_max);
+                                                           socclk_max,
+                                                           auto_level);
                if (ret)
                        return ret;
 
@@ -1825,7 +1838,8 @@ int smu_v13_0_set_performance_level(struct smu_context *smu,
                        ret = smu_v13_0_set_soft_freq_limited_range(smu,
                                                                    i ? SMU_VCLK1 : SMU_VCLK,
                                                                    vclk_min,
-                                                                   vclk_max);
+                                                                   vclk_max,
+                                                                   auto_level);
                        if (ret)
                                return ret;
                }
@@ -1840,7 +1854,8 @@ int smu_v13_0_set_performance_level(struct smu_context *smu,
                        ret = smu_v13_0_set_soft_freq_limited_range(smu,
                                                                    i ? SMU_DCLK1 : SMU_DCLK,
                                                                    dclk_min,
-                                                                   dclk_max);
+                                                                   dclk_max,
+                                                                   auto_level);
                        if (ret)
                                return ret;
                }
@@ -1852,7 +1867,8 @@ int smu_v13_0_set_performance_level(struct smu_context *smu,
                ret = smu_v13_0_set_soft_freq_limited_range(smu,
                                                            SMU_FCLK,
                                                            fclk_min,
-                                                           fclk_max);
+                                                           fclk_max,
+                                                           auto_level);
                if (ret)
                        return ret;
 
index 4e658ab..3e2277a 100644 (file)
@@ -1962,7 +1962,8 @@ static int smu_v13_0_0_force_clk_levels(struct smu_context *smu,
                ret = smu_v13_0_set_soft_freq_limited_range(smu,
                                                            clk_type,
                                                            min_freq,
-                                                           max_freq);
+                                                           max_freq,
+                                                           false);
                break;
        case SMU_DCEFCLK:
        case SMU_PCIE:
index 9c2c43b..a71b7c0 100644 (file)
@@ -811,9 +811,10 @@ failed:
 }
 
 static int smu_v13_0_5_set_soft_freq_limited_range(struct smu_context *smu,
-                                                       enum smu_clk_type clk_type,
-                                                       uint32_t min,
-                                                       uint32_t max)
+                                                  enum smu_clk_type clk_type,
+                                                  uint32_t min,
+                                                  uint32_t max,
+                                                  bool automatic)
 {
        enum smu_message_type msg_set_min, msg_set_max;
        uint32_t min_clk = min;
@@ -950,7 +951,7 @@ static int smu_v13_0_5_force_clk_levels(struct smu_context *smu,
                if (ret)
                        goto force_level_out;
 
-               ret = smu_v13_0_5_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq);
+               ret = smu_v13_0_5_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq, false);
                if (ret)
                        goto force_level_out;
                break;
@@ -1046,9 +1047,10 @@ static int smu_v13_0_5_set_performance_level(struct smu_context *smu,
 
        if (sclk_min && sclk_max) {
                ret = smu_v13_0_5_set_soft_freq_limited_range(smu,
-                                                           SMU_SCLK,
-                                                           sclk_min,
-                                                           sclk_max);
+                                                             SMU_SCLK,
+                                                             sclk_min,
+                                                             sclk_max,
+                                                             false);
                if (ret)
                        return ret;
 
@@ -1060,7 +1062,8 @@ static int smu_v13_0_5_set_performance_level(struct smu_context *smu,
                ret = smu_v13_0_5_set_soft_freq_limited_range(smu,
                                                              SMU_VCLK,
                                                              vclk_min,
-                                                             vclk_max);
+                                                             vclk_max,
+                                                             false);
                if (ret)
                        return ret;
        }
@@ -1069,7 +1072,8 @@ static int smu_v13_0_5_set_performance_level(struct smu_context *smu,
                ret = smu_v13_0_5_set_soft_freq_limited_range(smu,
                                                              SMU_DCLK,
                                                              dclk_min,
-                                                             dclk_max);
+                                                             dclk_max,
+                                                             false);
                if (ret)
                        return ret;
        }
index 9129759..7ebb675 100644 (file)
@@ -1758,7 +1758,7 @@ static int smu_v13_0_6_set_performance_level(struct smu_context *smu,
                if (uclk_table->max != pstate_table->uclk_pstate.curr.max) {
                        /* Min UCLK is not expected to be changed */
                        ret = smu_v13_0_set_soft_freq_limited_range(
-                               smu, SMU_UCLK, 0, uclk_table->max);
+                               smu, SMU_UCLK, 0, uclk_table->max, false);
                        if (ret)
                                return ret;
                        pstate_table->uclk_pstate.curr.max = uclk_table->max;
@@ -1777,7 +1777,8 @@ static int smu_v13_0_6_set_performance_level(struct smu_context *smu,
 
 static int smu_v13_0_6_set_soft_freq_limited_range(struct smu_context *smu,
                                                   enum smu_clk_type clk_type,
-                                                  uint32_t min, uint32_t max)
+                                                  uint32_t min, uint32_t max,
+                                                  bool automatic)
 {
        struct smu_dpm_context *smu_dpm = &(smu->smu_dpm);
        struct smu_13_0_dpm_context *dpm_context = smu_dpm->dpm_context;
@@ -1825,7 +1826,7 @@ static int smu_v13_0_6_set_soft_freq_limited_range(struct smu_context *smu,
                                return -EOPNOTSUPP;
                        /* Only max clock limiting is allowed for UCLK */
                        ret = smu_v13_0_set_soft_freq_limited_range(
-                               smu, SMU_UCLK, 0, max);
+                               smu, SMU_UCLK, 0, max, false);
                        if (!ret)
                                pstate_table->uclk_pstate.curr.max = max;
                }
@@ -1965,7 +1966,7 @@ static int smu_v13_0_6_usr_edit_dpm_table(struct smu_context *smu,
                        max_clk = dpm_context->dpm_tables.gfx_table.max;
 
                        ret = smu_v13_0_6_set_soft_freq_limited_range(
-                               smu, SMU_GFXCLK, min_clk, max_clk);
+                               smu, SMU_GFXCLK, min_clk, max_clk, false);
 
                        if (ret)
                                return ret;
@@ -1973,7 +1974,7 @@ static int smu_v13_0_6_usr_edit_dpm_table(struct smu_context *smu,
                        min_clk = dpm_context->dpm_tables.uclk_table.min;
                        max_clk = dpm_context->dpm_tables.uclk_table.max;
                        ret = smu_v13_0_6_set_soft_freq_limited_range(
-                               smu, SMU_UCLK, min_clk, max_clk);
+                               smu, SMU_UCLK, min_clk, max_clk, false);
                        if (ret)
                                return ret;
                        pstate_table->uclk_pstate.custom.max = 0;
@@ -1997,7 +1998,7 @@ static int smu_v13_0_6_usr_edit_dpm_table(struct smu_context *smu,
                        max_clk = pstate_table->gfxclk_pstate.custom.max;
 
                        ret = smu_v13_0_6_set_soft_freq_limited_range(
-                               smu, SMU_GFXCLK, min_clk, max_clk);
+                               smu, SMU_GFXCLK, min_clk, max_clk, false);
 
                        if (ret)
                                return ret;
@@ -2008,7 +2009,7 @@ static int smu_v13_0_6_usr_edit_dpm_table(struct smu_context *smu,
                        min_clk = pstate_table->uclk_pstate.curr.min;
                        max_clk = pstate_table->uclk_pstate.custom.max;
                        return smu_v13_0_6_set_soft_freq_limited_range(
-                               smu, SMU_UCLK, min_clk, max_clk);
+                               smu, SMU_UCLK, min_clk, max_clk, false);
                }
                break;
        default:
index f7d7cae..23f1338 100644 (file)
@@ -1951,7 +1951,8 @@ static int smu_v13_0_7_force_clk_levels(struct smu_context *smu,
                ret = smu_v13_0_set_soft_freq_limited_range(smu,
                                                            clk_type,
                                                            min_freq,
-                                                           max_freq);
+                                                           max_freq,
+                                                           false);
                break;
        case SMU_DCEFCLK:
        case SMU_PCIE:
index 260c339..71d58c8 100644 (file)
@@ -945,9 +945,10 @@ failed:
 }
 
 static int yellow_carp_set_soft_freq_limited_range(struct smu_context *smu,
-                                                       enum smu_clk_type clk_type,
-                                                       uint32_t min,
-                                                       uint32_t max)
+                                                  enum smu_clk_type clk_type,
+                                                  uint32_t min,
+                                                  uint32_t max,
+                                                  bool automatic)
 {
        enum smu_message_type msg_set_min, msg_set_max;
        uint32_t min_clk = min;
@@ -1134,7 +1135,7 @@ static int yellow_carp_force_clk_levels(struct smu_context *smu,
                if (ret)
                        goto force_level_out;
 
-               ret = yellow_carp_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq);
+               ret = yellow_carp_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq, false);
                if (ret)
                        goto force_level_out;
                break;
@@ -1254,9 +1255,10 @@ static int yellow_carp_set_performance_level(struct smu_context *smu,
 
        if (sclk_min && sclk_max) {
                ret = yellow_carp_set_soft_freq_limited_range(smu,
-                                                           SMU_SCLK,
-                                                           sclk_min,
-                                                           sclk_max);
+                                                             SMU_SCLK,
+                                                             sclk_min,
+                                                             sclk_max,
+                                                             false);
                if (ret)
                        return ret;
 
@@ -1266,18 +1268,20 @@ static int yellow_carp_set_performance_level(struct smu_context *smu,
 
        if (fclk_min && fclk_max) {
                ret = yellow_carp_set_soft_freq_limited_range(smu,
-                                                           SMU_FCLK,
-                                                           fclk_min,
-                                                           fclk_max);
+                                                             SMU_FCLK,
+                                                             fclk_min,
+                                                             fclk_max,
+                                                             false);
                if (ret)
                        return ret;
        }
 
        if (socclk_min && socclk_max) {
                ret = yellow_carp_set_soft_freq_limited_range(smu,
-                                                           SMU_SOCCLK,
-                                                           socclk_min,
-                                                           socclk_max);
+                                                             SMU_SOCCLK,
+                                                             socclk_min,
+                                                             socclk_max,
+                                                             false);
                if (ret)
                        return ret;
        }
@@ -1286,7 +1290,8 @@ static int yellow_carp_set_performance_level(struct smu_context *smu,
                ret = yellow_carp_set_soft_freq_limited_range(smu,
                                                              SMU_VCLK,
                                                              vclk_min,
-                                                             vclk_max);
+                                                             vclk_max,
+                                                             false);
                if (ret)
                        return ret;
        }
@@ -1295,7 +1300,8 @@ static int yellow_carp_set_performance_level(struct smu_context *smu,
                ret = yellow_carp_set_soft_freq_limited_range(smu,
                                                              SMU_DCLK,
                                                              dclk_min,
-                                                             dclk_max);
+                                                             dclk_max,
+                                                             false);
                if (ret)
                        return ret;
        }
index 865e916..f7745ea 100644 (file)
@@ -1102,7 +1102,8 @@ failed:
 int smu_v14_0_set_soft_freq_limited_range(struct smu_context *smu,
                                          enum smu_clk_type clk_type,
                                          uint32_t min,
-                                         uint32_t max)
+                                         uint32_t max,
+                                         bool automatic)
 {
        int ret = 0, clk_id = 0;
        uint32_t param;
@@ -1117,7 +1118,10 @@ int smu_v14_0_set_soft_freq_limited_range(struct smu_context *smu,
                return clk_id;
 
        if (max > 0) {
-               param = (uint32_t)((clk_id << 16) | (max & 0xffff));
+               if (automatic)
+                       param = (uint32_t)((clk_id << 16) | 0xffff);
+               else
+                       param = (uint32_t)((clk_id << 16) | (max & 0xffff));
                ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxByFreq,
                                                      param, NULL);
                if (ret)
@@ -1125,7 +1129,10 @@ int smu_v14_0_set_soft_freq_limited_range(struct smu_context *smu,
        }
 
        if (min > 0) {
-               param = (uint32_t)((clk_id << 16) | (min & 0xffff));
+               if (automatic)
+                       param = (uint32_t)((clk_id << 16) | 0);
+               else
+                       param = (uint32_t)((clk_id << 16) | (min & 0xffff));
                ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMinByFreq,
                                                      param, NULL);
                if (ret)
@@ -1202,6 +1209,7 @@ int smu_v14_0_set_performance_level(struct smu_context *smu,
        uint32_t dclk_min = 0, dclk_max = 0;
        uint32_t fclk_min = 0, fclk_max = 0;
        int ret = 0, i;
+       bool auto_level = false;
 
        switch (level) {
        case AMD_DPM_FORCED_LEVEL_HIGH:
@@ -1233,6 +1241,7 @@ int smu_v14_0_set_performance_level(struct smu_context *smu,
                dclk_max = dclk_table->max;
                fclk_min = fclk_table->min;
                fclk_max = fclk_table->max;
+               auto_level = true;
                break;
        case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
                sclk_min = sclk_max = pstate_table->gfxclk_pstate.standard;
@@ -1268,7 +1277,8 @@ int smu_v14_0_set_performance_level(struct smu_context *smu,
                ret = smu_v14_0_set_soft_freq_limited_range(smu,
                                                            SMU_GFXCLK,
                                                            sclk_min,
-                                                           sclk_max);
+                                                           sclk_max,
+                                                           auto_level);
                if (ret)
                        return ret;
 
@@ -1280,7 +1290,8 @@ int smu_v14_0_set_performance_level(struct smu_context *smu,
                ret = smu_v14_0_set_soft_freq_limited_range(smu,
                                                            SMU_MCLK,
                                                            mclk_min,
-                                                           mclk_max);
+                                                           mclk_max,
+                                                           auto_level);
                if (ret)
                        return ret;
 
@@ -1292,7 +1303,8 @@ int smu_v14_0_set_performance_level(struct smu_context *smu,
                ret = smu_v14_0_set_soft_freq_limited_range(smu,
                                                            SMU_SOCCLK,
                                                            socclk_min,
-                                                           socclk_max);
+                                                           socclk_max,
+                                                           auto_level);
                if (ret)
                        return ret;
 
@@ -1307,7 +1319,8 @@ int smu_v14_0_set_performance_level(struct smu_context *smu,
                        ret = smu_v14_0_set_soft_freq_limited_range(smu,
                                                                    i ? SMU_VCLK1 : SMU_VCLK,
                                                                    vclk_min,
-                                                                   vclk_max);
+                                                                   vclk_max,
+                                                                   auto_level);
                        if (ret)
                                return ret;
                }
@@ -1322,7 +1335,8 @@ int smu_v14_0_set_performance_level(struct smu_context *smu,
                        ret = smu_v14_0_set_soft_freq_limited_range(smu,
                                                                    i ? SMU_DCLK1 : SMU_DCLK,
                                                                    dclk_min,
-                                                                   dclk_max);
+                                                                   dclk_max,
+                                                                   auto_level);
                        if (ret)
                                return ret;
                }
@@ -1334,7 +1348,8 @@ int smu_v14_0_set_performance_level(struct smu_context *smu,
                ret = smu_v14_0_set_soft_freq_limited_range(smu,
                                                            SMU_FCLK,
                                                            fclk_min,
-                                                           fclk_max);
+                                                           fclk_max,
+                                                           auto_level);
                if (ret)
                        return ret;
 
index ade3ee3..27f4e0c 100644 (file)
@@ -1503,7 +1503,8 @@ static int smu_v14_0_2_force_clk_levels(struct smu_context *smu,
                ret = smu_v14_0_set_soft_freq_limited_range(smu,
                                                            clk_type,
                                                            min_freq,
-                                                           max_freq);
+                                                           max_freq,
+                                                           false);
                break;
        case SMU_DCEFCLK:
        case SMU_PCIE: