[PATCH 08/10] drm/amd/pp: Implement AutoWattman feature on Vega10

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.Zhu at 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



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux