This patch adds get_max_sustainable_clock function for smu11.

Signed-off-by: Huang Rui <[email protected]>
Reviewed-by: Kevin Wang <[email protected]>
---
 drivers/gpu/drm/amd/powerplay/amdgpu_smu.c     |   9 ++
 drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h |   4 +
 drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h  |   8 ++
 drivers/gpu/drm/amd/powerplay/smu_v11_0.c      | 114 +++++++++++++++++++++++++
 4 files changed, 135 insertions(+)

diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c 
b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
index b225cf8..cd04369 100644
--- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
@@ -393,6 +393,10 @@ static int smu_smc_table_hw_init(struct smu_context *smu)
        if (ret)
                return ret;
 
+       ret = smu_init_max_sustainable_clocks(smu);
+       if (ret)
+               return ret;
+
        ret = smu_populate_umd_state_clk(smu);
        if (ret)
                return ret;
@@ -539,6 +543,11 @@ static int smu_hw_fini(void *handle)
                return -EINVAL;
        kfree(table_context->driver_pptable);
 
+       if (table_context->max_sustainable_clocks) {
+               kfree(table_context->max_sustainable_clocks);
+               table_context->max_sustainable_clocks = NULL;
+       }
+
        ret = smu_fini_fb_allocations(smu);
        if (ret)
                return ret;
diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h 
b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
index a3c8b73..a68519e 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
@@ -158,6 +158,7 @@ struct smu_table_context
        void                            *power_play_table;
        uint32_t                        power_play_table_size;
 
+       void                            *max_sustainable_clocks;
        struct smu_bios_boot_up_values  boot_values;
        void                            *driver_pptable;
        struct smu_table                *tables;
@@ -253,6 +254,7 @@ struct smu_funcs
        int (*notify_display_change)(struct smu_context *smu);
        int (*get_power_limit)(struct smu_context *smu);
        int (*get_current_clk_freq)(struct smu_context *smu, uint32_t clk_id, 
uint32_t *value);
+       int (*init_max_sustainable_clocks)(struct smu_context *smu);
 };
 
 #define smu_init_microcode(smu) \
@@ -297,6 +299,8 @@ struct smu_funcs
        ((smu)->funcs->set_last_dcef_min_deep_sleep_clk ? 
(smu)->funcs->set_last_dcef_min_deep_sleep_clk((smu)) : 0)
 #define smu_system_features_control(smu, en) \
        ((smu)->funcs->system_features_control ? 
(smu)->funcs->system_features_control((smu), (en)) : 0)
+#define smu_init_max_sustainable_clocks(smu) \
+       ((smu)->funcs->init_max_sustainable_clocks ? 
(smu)->funcs->init_max_sustainable_clocks((smu)) : 0)
 #define smu_send_smc_msg(smu, msg) \
        ((smu)->funcs->send_smc_msg? (smu)->funcs->send_smc_msg((smu), (msg)) : 
0)
 #define smu_send_smc_msg_with_param(smu, msg, param) \
diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h 
b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h
index 2853ab7..aa8d81f 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h
@@ -36,6 +36,14 @@
 #define smnMP0_FW_INTF                 0x30101c0
 #define smnMP1_PUB_CTRL                        0x3010b14
 
+struct smu_11_0_max_sustainable_clocks {
+       uint32_t display_clock;
+       uint32_t phy_clock;
+       uint32_t pixel_clock;
+       uint32_t uclock;
+       uint32_t dcef_clock;
+       uint32_t soc_clock;
+};
 
 struct smu_11_0_dpm_table {
        uint32_t    min;        /* MHz */
diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c 
b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
index def64f5..129d2b1 100644
--- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
+++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c
@@ -738,6 +738,119 @@ static int smu_v11_0_notify_display_change(struct 
smu_context *smu)
        return ret;
 }
 
+static int
+smu_v11_0_get_max_sustainable_clock(struct smu_context *smu, uint32_t *clock,
+                                   PPCLK_e clock_select)
+{
+       int ret = 0;
+
+       ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetDcModeMaxDpmFreq,
+                                         clock_select << 16);
+       if (ret) {
+               pr_err("[GetMaxSustainableClock] Failed to get max DC clock 
from SMC!");
+               return ret;
+       }
+
+       ret = smu_read_smc_arg(smu, clock);
+       if (ret)
+               return ret;
+
+       if (*clock != 0)
+               return 0;
+
+       /* if DC limit is zero, return AC limit */
+       ret = smu_send_smc_msg_with_param(smu, SMU_MSG_GetMaxDpmFreq,
+                                         clock_select << 16);
+       if (ret) {
+               pr_err("[GetMaxSustainableClock] failed to get max AC clock 
from SMC!");
+               return ret;
+       }
+
+       ret = smu_read_smc_arg(smu, clock);
+
+       return ret;
+}
+
+static int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu)
+{
+       struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks;
+       int ret = 0;
+
+       max_sustainable_clocks = kzalloc(sizeof(struct 
smu_11_0_max_sustainable_clocks),
+                                        GFP_KERNEL);
+       smu->smu_table.max_sustainable_clocks = (void *)max_sustainable_clocks;
+
+       max_sustainable_clocks->uclock = smu->smu_table.boot_values.uclk / 100;
+       max_sustainable_clocks->soc_clock = smu->smu_table.boot_values.socclk / 
100;
+       max_sustainable_clocks->dcef_clock = smu->smu_table.boot_values.dcefclk 
/ 100;
+       max_sustainable_clocks->display_clock = 0xFFFFFFFF;
+       max_sustainable_clocks->phy_clock = 0xFFFFFFFF;
+       max_sustainable_clocks->pixel_clock = 0xFFFFFFFF;
+
+       if (smu_feature_is_enabled(smu, FEATURE_DPM_UCLK_BIT)) {
+               ret = smu_v11_0_get_max_sustainable_clock(smu,
+                                                         
&(max_sustainable_clocks->uclock),
+                                                         PPCLK_UCLK);
+               if (ret) {
+                       pr_err("[%s] failed to get max UCLK from SMC!",
+                              __func__);
+                       return ret;
+               }
+       }
+
+       if (smu_feature_is_enabled(smu, FEATURE_DPM_SOCCLK_BIT)) {
+               ret = smu_v11_0_get_max_sustainable_clock(smu,
+                                                         
&(max_sustainable_clocks->soc_clock),
+                                                         PPCLK_SOCCLK);
+               if (ret) {
+                       pr_err("[%s] failed to get max SOCCLK from SMC!",
+                              __func__);
+                       return ret;
+               }
+       }
+
+       if (smu_feature_is_enabled(smu, FEATURE_DPM_DCEFCLK_BIT)) {
+               ret = smu_v11_0_get_max_sustainable_clock(smu,
+                                                         
&(max_sustainable_clocks->dcef_clock),
+                                                         PPCLK_DCEFCLK);
+               if (ret) {
+                       pr_err("[%s] failed to get max DCEFCLK from SMC!",
+                              __func__);
+                       return ret;
+               }
+
+               ret = smu_v11_0_get_max_sustainable_clock(smu,
+                                                         
&(max_sustainable_clocks->display_clock),
+                                                         PPCLK_DISPCLK);
+               if (ret) {
+                       pr_err("[%s] failed to get max DISPCLK from SMC!",
+                              __func__);
+                       return ret;
+               }
+               ret = smu_v11_0_get_max_sustainable_clock(smu,
+                                                         
&(max_sustainable_clocks->phy_clock),
+                                                         PPCLK_PHYCLK);
+               if (ret) {
+                       pr_err("[%s] failed to get max PHYCLK from SMC!",
+                              __func__);
+                       return ret;
+               }
+               ret = smu_v11_0_get_max_sustainable_clock(smu,
+                                                         
&(max_sustainable_clocks->pixel_clock),
+                                                         PPCLK_PIXCLK);
+               if (ret) {
+                       pr_err("[%s] failed to get max PIXCLK from SMC!",
+                              __func__);
+                       return ret;
+               }
+       }
+
+       if (max_sustainable_clocks->soc_clock < max_sustainable_clocks->uclock)
+               max_sustainable_clocks->uclock = 
max_sustainable_clocks->soc_clock;
+
+       return 0;
+}
+
 static int smu_v11_0_get_power_limit(struct smu_context *smu)
 {
        int ret;
@@ -810,6 +923,7 @@ static const struct smu_funcs smu_v11_0_funcs = {
        .notify_display_change = smu_v11_0_notify_display_change,
        .get_power_limit = smu_v11_0_get_power_limit,
        .get_current_clk_freq = smu_v11_0_get_current_clk_freq,
+       .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks,
 };
 
 void smu_v11_0_set_smu_funcs(struct smu_context *smu)
-- 
2.7.4

_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to