From: Asad Kamal <[email protected]>

Add set_performance_support for smu_v15_0_8

v2: Skip Gl2clk/fclk (Lijo)

Signed-off-by: Asad Kamal <[email protected]>
Signed-off-by: Yang Wang <[email protected]>
Reviewed-by: Lijo Lazar <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
---
 .../drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c  | 141 +++++++++++++++++-
 drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c        |  10 ++
 drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h        |   1 +
 3 files changed, 151 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
index f3378e73b6ccb..435798388b012 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu15/smu_v15_0_8_ppt.c
@@ -1391,6 +1391,144 @@ static int smu_v15_0_8_populate_umd_state_clk(struct 
smu_context *smu)
        return 0;
 }
 
+static int smu_v15_0_8_set_gfx_soft_freq_limited_range(struct smu_context *smu,
+                                                      uint32_t min,
+                                                      uint32_t max)
+{
+       int ret;
+
+       ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk,
+                                             max & 0xffff, NULL);
+       if (ret)
+               return ret;
+
+       ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMinGfxclk,
+                                             min & 0xffff, NULL);
+
+       return ret;
+}
+
+static int smu_v15_0_8_set_performance_level(struct smu_context *smu,
+                                            enum amd_dpm_forced_level level)
+{
+       struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
+       struct smu_15_0_dpm_context *dpm_context = smu_dpm->dpm_context;
+       struct smu_dpm_table *gfx_table = &dpm_context->dpm_tables.gfx_table;
+       struct smu_dpm_table *uclk_table = &dpm_context->dpm_tables.uclk_table;
+       struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
+       int ret;
+
+       switch (level) {
+       case AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM:
+               /* Determinism not supported on SMU v15.0.8 */
+               ret = -EOPNOTSUPP;
+               break;
+
+       case AMD_DPM_FORCED_LEVEL_AUTO:
+               /* Restore GFXCLK to default range */
+               if ((SMU_DPM_TABLE_MIN(gfx_table) !=
+                    pstate_table->gfxclk_pstate.curr.min) ||
+                   (SMU_DPM_TABLE_MAX(gfx_table) !=
+                    pstate_table->gfxclk_pstate.curr.max)) {
+                       ret = smu_v15_0_8_set_gfx_soft_freq_limited_range(
+                               smu, SMU_DPM_TABLE_MIN(gfx_table),
+                               SMU_DPM_TABLE_MAX(gfx_table));
+                       if (ret)
+                               goto out;
+
+                       pstate_table->gfxclk_pstate.curr.min =
+                               SMU_DPM_TABLE_MIN(gfx_table);
+                       pstate_table->gfxclk_pstate.curr.max =
+                               SMU_DPM_TABLE_MAX(gfx_table);
+               }
+
+               /* Restore UCLK to default max */
+               if (SMU_DPM_TABLE_MAX(uclk_table) !=
+                   pstate_table->uclk_pstate.curr.max) {
+                       /* Min UCLK is not expected to be changed */
+                       ret = smu_v15_0_set_soft_freq_limited_range(smu,
+                                                                   SMU_UCLK, 0,
+                                                                   
SMU_DPM_TABLE_MAX(uclk_table),
+                                                                   false);
+                       if (ret)
+                               goto out;
+
+                       pstate_table->uclk_pstate.curr.max =
+                               SMU_DPM_TABLE_MAX(uclk_table);
+               }
+
+               if (ret)
+                       goto out;
+
+               smu_cmn_reset_custom_level(smu);
+
+               break;
+       case AMD_DPM_FORCED_LEVEL_MANUAL:
+               ret = 0;
+               break;
+       default:
+               ret = -EOPNOTSUPP;
+               break;
+       }
+
+out:
+       return ret;
+}
+
+static int smu_v15_0_8_set_soft_freq_limited_range(struct smu_context *smu,
+                                                  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_umd_pstate_table *pstate_table = &smu->pstate_table;
+       int ret = 0;
+
+       if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK &&
+           clk_type != SMU_UCLK)
+               return -EINVAL;
+
+       if (smu_dpm->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
+               return -EINVAL;
+
+       if (smu_dpm->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) {
+               if (min >= max) {
+                       dev_err(smu->adev->dev,
+                               "Minimum clk should be less than the maximum 
allowed clock\n");
+                       return -EINVAL;
+               }
+
+               if (clk_type == SMU_GFXCLK || clk_type == SMU_SCLK) {
+                       if ((min == pstate_table->gfxclk_pstate.curr.min) &&
+                           (max == pstate_table->gfxclk_pstate.curr.max))
+                               return 0;
+
+                       ret = smu_v15_0_8_set_gfx_soft_freq_limited_range(smu,
+                                                                         min, 
max);
+                       if (!ret) {
+                               pstate_table->gfxclk_pstate.curr.min = min;
+                               pstate_table->gfxclk_pstate.curr.max = max;
+                       }
+               }
+
+               if (clk_type == SMU_UCLK) {
+                       if (max == pstate_table->uclk_pstate.curr.max)
+                               return 0;
+
+                       ret = smu_v15_0_set_soft_freq_limited_range(smu,
+                                                                   SMU_UCLK,
+                                                                   0, max,
+                                                                   false);
+                       if (!ret)
+                               pstate_table->uclk_pstate.curr.max = max;
+               }
+
+               return ret;
+       }
+
+       return 0;
+}
+
 static const struct pptable_funcs smu_v15_0_8_ppt_funcs = {
        .init_allowed_features = smu_v15_0_8_init_allowed_features,
        .set_default_dpm_table = smu_v15_0_8_set_default_dpm_table,
@@ -1420,7 +1558,8 @@ static const struct pptable_funcs smu_v15_0_8_ppt_funcs = 
{
        .set_power_limit = smu_v15_0_set_power_limit,
        .emit_clk_levels = smu_v15_0_8_emit_clk_levels,
        .populate_umd_state_clk = smu_v15_0_8_populate_umd_state_clk,
-       };
+       .set_performance_level = smu_v15_0_8_set_performance_level,
+};
 
 static void smu_v15_0_8_init_msg_ctl(struct smu_context *smu,
                                     const struct cmn2asic_msg_mapping 
*message_map)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
index a644579903f40..09b486ed3f1ee 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
@@ -1305,6 +1305,16 @@ void smu_cmn_get_backend_workload_mask(struct 
smu_context *smu,
        }
 }
 
+void smu_cmn_reset_custom_level(struct smu_context *smu)
+{
+       struct smu_umd_pstate_table *pstate_table = &smu->pstate_table;
+
+       pstate_table->gfxclk_pstate.custom.min = 0;
+       pstate_table->gfxclk_pstate.custom.max = 0;
+       pstate_table->uclk_pstate.custom.min = 0;
+       pstate_table->uclk_pstate.custom.max = 0;
+}
+
 static inline bool smu_cmn_freqs_match(uint32_t freq1, uint32_t freq2)
 {
        /* Frequencies within 25 MHz are considered equal */
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h 
b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
index e4d282d8bcae3..b76e86df5da78 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
@@ -204,6 +204,7 @@ int smu_cmn_print_pcie_levels(struct smu_context *smu,
                               struct smu_pcie_table *pcie_table,
                               uint32_t cur_gen, uint32_t cur_lane,
                               char *buf, int *offset);
+void smu_cmn_reset_custom_level(struct smu_context *smu);
 
 int smu_cmn_dpm_pcie_gen_idx(int gen);
 int smu_cmn_dpm_pcie_width_idx(int width);
-- 
2.53.0

Reply via email to