based on the engine activity read from smu, driver will
notify smu to adjust the behaviour of natural DPM.

Change-Id: I951390cae82eeacfdaea3917eb570aa57216cbd7
Signed-off-by: Rex Zhu <rex....@amd.com>
---
 drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 65 +++++++++++++++++++++-
 drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h | 11 +++-
 2 files changed, 73 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c 
b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
index 22a42c9..2336f1f 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
@@ -766,7 +766,7 @@ static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
        vega10_set_default_registry_data(hwmgr);
 
        data->disable_dpm_mask = 0xff;
-       data->workload_mask = 0xff;
+       data->workload_index = 0xff;
 
        /* need to set voltage control types before EVV patching */
        data->vddc_control = VEGA10_VOLTAGE_CONTROL_NONE;
@@ -4942,6 +4942,67 @@ static int vega10_set_power_profile_mode(struct pp_hwmgr 
*hwmgr, long *input, ui
        return 0;
 }
 
+static void vega10_start_auto_wattman(struct pp_hwmgr *hwmgr, bool en)
+{
+       if (en)
+               schedule_delayed_work(&hwmgr->wattman_update_work, 
WATTMAM_SAMPLE_PERIOD);
+       else
+               cancel_delayed_work_sync(&hwmgr->wattman_update_work);
+}
+
+static void vega10_auto_wattman_get_data(struct pp_hwmgr *hwmgr)
+{
+       struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
+       uint32_t activity_percent;
+
+       smum_send_msg_to_smc_with_parameter(hwmgr, 
PPSMC_MSG_GetAverageGfxActivity, 0);
+       vega10_read_arg_from_smc(hwmgr, &activity_percent);
+       data->wattman_data.average_sclk_busy = activity_percent > 100 ? 100 : 
activity_percent;
+
+       pr_debug("average sclk busy: %d\n", 
data->wattman_data.average_sclk_busy);
+
+       return;
+}
+
+#define Vega10_AutoWattMan_Setting_Max 5
+
+uint32_t Vega10_AutoWattMan_Setting[Vega10_AutoWattMan_Setting_Max] = {
+                               PP_SMC_POWER_PROFILE_POWERSAVING,
+                               PP_SMC_POWER_PROFILE_VIDEO,
+                               PP_SMC_POWER_PROFILE_FULLSCREEN3D,
+                               PP_SMC_POWER_PROFILE_VR,
+                               PP_SMC_POWER_PROFILE_COMPUTE};
+
+static void vega10_auto_wattman_algorithm(struct pp_hwmgr *hwmgr)
+{
+       struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
+       uint32_t threshold = AutoWattmanAlgorithmThreshold;
+
+       if (data->wattman_data.average_sclk_busy < threshold){
+               if (data->workload_index > 0)
+                       data->workload_index -= 1;
+       } else {
+               if (data->workload_index < (Vega10_AutoWattMan_Setting_Max - 1))
+                       data->workload_index += 1;
+       }
+}
+
+static int vega10_update_auto_wattman(struct pp_hwmgr *hwmgr)
+{
+       struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
+
+       vega10_auto_wattman_get_data(hwmgr);
+       vega10_auto_wattman_algorithm(hwmgr);
+
+       if (hwmgr->power_profile_mode != 
Vega10_AutoWattMan_Setting[data->workload_index]) {
+               hwmgr->power_profile_mode = 
Vega10_AutoWattMan_Setting[data->workload_index];
+               smum_send_msg_to_smc_with_parameter(hwmgr, 
PPSMC_MSG_SetWorkloadMask,
+                                               1<<hwmgr->power_profile_mode);
+       }
+
+       return 0;
+}
+
 static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
        .backend_init = vega10_hwmgr_backend_init,
        .backend_fini = vega10_hwmgr_backend_fini,
@@ -5000,6 +5061,8 @@ static int vega10_set_power_profile_mode(struct pp_hwmgr 
*hwmgr, long *input, ui
        .get_power_profile_mode = vega10_get_power_profile_mode,
        .set_power_profile_mode = vega10_set_power_profile_mode,
        .set_power_limit = vega10_set_power_limit,
+       .update_auto_wattman = vega10_update_auto_wattman,
+       .start_auto_wattman = vega10_start_auto_wattman,
 };
 
 int vega10_hwmgr_init(struct pp_hwmgr *hwmgr)
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h 
b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h
index ab3e879..a12c170 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h
@@ -36,6 +36,8 @@
 #define WaterMarksExist  1
 #define WaterMarksLoaded 2
 
+#define AutoWattmanAlgorithmThreshold 80
+
 enum {
        GNLD_DPM_PREFETCHER = 0,
        GNLD_DPM_GFXCLK,
@@ -299,6 +301,11 @@ struct vega10_odn_fan_table {
        uint32_t        min_fan_limit;
 };
 
+struct vega10_auto_wattman_data {
+       uint32_t   average_sclk_busy;
+       uint32_t   average_mclk_busy;
+};
+
 struct vega10_hwmgr {
        struct vega10_dpm_table                 dpm_table;
        struct vega10_dpm_table                 golden_dpm_table;
@@ -374,8 +381,8 @@ struct vega10_hwmgr {
        uint32_t                       apply_overdrive_next_settings_mask;
 
        /* ---- Workload Mask ---- */
-       uint32_t                       workload_mask;
-
+       uint32_t                       workload_index;
+       struct vega10_auto_wattman_data         wattman_data;
        /* ---- SMU9 ---- */
        struct smu_features            smu_features[GNLD_FEATURES_MAX];
        struct vega10_smc_state_table  smc_state_table;
-- 
1.9.1

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

Reply via email to