diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
index 9c373f8f465c0cedf9d3364b7a8a9c4594200bb1..643d008410c654ee8b871c093d10281421b60715 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
@@ -341,9 +341,9 @@ enum amdgpu_pcie_gen {
 		((adev)->powerplay.pp_funcs->reset_power_profile_state(\
 			(adev)->powerplay.pp_handle, request))
 
-#define amdgpu_dpm_switch_power_profile(adev, type) \
+#define amdgpu_dpm_switch_power_profile(adev, type, en) \
 		((adev)->powerplay.pp_funcs->switch_power_profile(\
-			(adev)->powerplay.pp_handle, type))
+			(adev)->powerplay.pp_handle, type, en))
 
 #define amdgpu_dpm_set_clockgating_by_smu(adev, msg_id) \
 		((adev)->powerplay.pp_funcs->set_clockgating_by_smu(\
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index e482daf394d3ba35e83e7c57b6744d4833daff3c..15bd0f9acf73a992502b2415f0f270bc14780cdf 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -83,20 +83,6 @@ enum amd_vce_level {
 	AMD_VCE_LEVEL_DC_GP_HIGH = 5, /* DC, general purpose queue, 1080 >= res > 720 */
 };
 
-enum amd_pp_profile_type {
-	AMD_PP_GFX_PROFILE,
-	AMD_PP_COMPUTE_PROFILE,
-};
-
-struct amd_pp_profile {
-	enum amd_pp_profile_type type;
-	uint32_t min_sclk;
-	uint32_t min_mclk;
-	uint16_t activity_threshold;
-	uint8_t up_hyst;
-	uint8_t down_hyst;
-};
-
 enum amd_fan_ctrl_mode {
 	AMD_FAN_CTRL_NONE = 0,
 	AMD_FAN_CTRL_MANUAL = 1,
@@ -143,7 +129,6 @@ enum PP_SMC_POWER_PROFILE {
 	PP_SMC_POWER_PROFILE_VR           = 0x3,
 	PP_SMC_POWER_PROFILE_COMPUTE      = 0x4,
 	PP_SMC_POWER_PROFILE_CUSTOM       = 0x5,
-	PP_SMC_POWER_PROFILE_AUTO         = 0x6,
 };
 
 enum {
@@ -252,8 +237,7 @@ struct amd_pm_funcs {
 	int (*get_pp_table)(void *handle, char **table);
 	int (*set_pp_table)(void *handle, const char *buf, size_t size);
 	void (*debugfs_print_current_performance_level)(void *handle, struct seq_file *m);
-	int (*switch_power_profile)(void *handle,
-			enum amd_pp_profile_type type);
+	int (*switch_power_profile)(void *handle, enum PP_SMC_POWER_PROFILE type, bool en);
 /* export to amdgpu */
 	void (*powergate_uvd)(void *handle, bool gate);
 	void (*powergate_vce)(void *handle, bool gate);
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
index a8705b5ad264aec10b23cbad73507bdcb49833a8..b989bf3542d606a68b098d6f84e432bb27f77802 100644
--- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
+++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
@@ -1077,22 +1077,44 @@ static int pp_odn_edit_dpm_table(void *handle, uint32_t type, long *input, uint3
 }
 
 static int pp_dpm_switch_power_profile(void *handle,
-		enum amd_pp_profile_type type)
+		enum PP_SMC_POWER_PROFILE type, bool en)
 {
 	struct pp_hwmgr *hwmgr;
-	struct amd_pp_profile request = {0};
 	struct pp_instance *pp_handle = (struct pp_instance *)handle;
+	long workload;
+	uint32_t index;
 
 	if (pp_check(pp_handle))
 		return -EINVAL;
 
 	hwmgr = pp_handle->hwmgr;
 
-	if (hwmgr->current_power_profile != type) {
-		request.type = type;
-		pp_dpm_set_power_profile_state(handle, &request);
+	if (hwmgr->hwmgr_func->set_power_profile_mode == NULL) {
+		pr_info("%s was not implemented.\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!(type < PP_SMC_POWER_PROFILE_CUSTOM))
+		return -EINVAL;
+
+	mutex_lock(&pp_handle->pp_lock);
+
+	if (!en) {
+		hwmgr->workload_mask &= ~(1 << hwmgr->workload_prority[type]);
+		index = fls(hwmgr->workload_mask);
+		index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0;
+		workload = hwmgr->workload_setting[index];
+	} else {
+		hwmgr->workload_mask |= (1 << hwmgr->workload_prority[type]);
+		index = fls(hwmgr->workload_mask);
+		index = index <= Workload_Policy_Max ? index - 1 : 0;
+		workload = hwmgr->workload_setting[index];
 	}
 
+	if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL)
+		hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, &workload, 0);
+	mutex_unlock(&pp_handle->pp_lock);
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
index aea107643859fe7bf64bcb15c677d1622b4e132c..4b6cf795243c8d0a9abe651f25fe6d9626d5d31d 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
@@ -125,6 +125,21 @@ static const struct cgs_irq_src_funcs thermal_irq_src[3] = {
 	{ .handler = phm_ctf_irq }
 };
 
+static void hwmgr_init_workload_prority(struct pp_hwmgr *hwmgr)
+{
+	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 2;
+	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 0;
+	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 1;
+	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VR] = 3;
+	hwmgr->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 4;
+
+	hwmgr->workload_setting[0] = PP_SMC_POWER_PROFILE_POWERSAVING;
+	hwmgr->workload_setting[1] = PP_SMC_POWER_PROFILE_VIDEO;
+	hwmgr->workload_setting[2] = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
+	hwmgr->workload_setting[3] = PP_SMC_POWER_PROFILE_VR;
+	hwmgr->workload_setting[4] = PP_SMC_POWER_PROFILE_COMPUTE;
+}
+
 int hwmgr_early_init(struct pp_instance *handle)
 {
 	struct pp_hwmgr *hwmgr;
@@ -151,6 +166,7 @@ int hwmgr_early_init(struct pp_instance *handle)
 	hwmgr_set_user_specify_caps(hwmgr);
 	hwmgr->fan_ctrl_is_in_default_mode = true;
 	hwmgr->reload_fw = 1;
+	hwmgr_init_workload_prority(hwmgr);
 
 	switch (hwmgr->chip_family) {
 	case AMDGPU_FAMILY_CI:
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c
index ed3bd1502c0db3056868a88dbcf121dc35f8583b..d0ef8f9c1361c98c6e0c3905c54bbd15ca36a8d7 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c
@@ -220,6 +220,8 @@ int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip,
 	struct pp_power_state *pcurrent;
 	struct pp_power_state *requested;
 	bool equal;
+	uint32_t index;
+	long workload;
 
 	if (skip)
 		return 0;
@@ -247,6 +249,15 @@ int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip,
 	if (!phm_force_dpm_levels(hwmgr, hwmgr->request_dpm_level))
 		hwmgr->dpm_level = hwmgr->request_dpm_level;
 
+	if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) {
+		index = fls(hwmgr->workload_mask);
+		index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0;
+		workload = hwmgr->workload_setting[index];
+
+		if (hwmgr->power_profile_mode != workload && hwmgr->hwmgr_func->set_power_profile_mode)
+			hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, &workload, 0);
+	}
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
index 58e2e0a10b3d08ce39b93960b33f1c4ab925a512..d8c205cf8f124643d4611071b614fd8c76467f9c 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
@@ -1510,6 +1510,9 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
 	data->current_profile_setting.mclk_up_hyst = 0;
 	data->current_profile_setting.mclk_down_hyst = 100;
 	data->current_profile_setting.mclk_activity = SMU7_MCLK_TARGETACTIVITY_DFLT;
+	hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D];
+	hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
+	hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
 
 	if (hwmgr->chip_id == CHIP_POLARIS12 || hwmgr->is_kicker) {
 		uint8_t tmp1, tmp2;
@@ -2466,9 +2469,6 @@ static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
 	smu7_patch_voltage_workaround(hwmgr);
 	smu7_init_dpm_defaults(hwmgr);
 
-	hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
-	hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
-
 	/* Get leakage voltage based on leakage ID. */
 	if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
 			PHM_PlatformCaps_EVV)) {
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
index d90a0f1dbb5557a1d31bc9759f22596a7590b2b0..f23861f2c6855b67117e710585e639193bc532a7 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
@@ -766,13 +766,12 @@ static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
 
 	hwmgr->backend = data;
 
+	hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO];
 	hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
 	hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
 
 	vega10_set_default_registry_data(hwmgr);
-
 	data->disable_dpm_mask = 0xff;
-	data->workload_mask = 0xff;
 
 	/* need to set voltage control types before EVV patching */
 	data->vddc_control = VEGA10_VOLTAGE_CONTROL_NONE;
@@ -4187,11 +4186,6 @@ static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
 		break;
 	case AMD_DPM_FORCED_LEVEL_AUTO:
 		ret = vega10_unforce_dpm_levels(hwmgr);
-		if (hwmgr->default_power_profile_mode != hwmgr->power_profile_mode) {
-				smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask,
-						1 << hwmgr->default_power_profile_mode);
-				hwmgr->power_profile_mode = hwmgr->default_power_profile_mode;
-		}
 		break;
 	case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
 	case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h
index de3219fff2db561f3b91e361c5a9fce054ba4637..8f6c2cb962da105a800590669433d72fbc399cba 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h
@@ -374,9 +374,6 @@ struct vega10_hwmgr {
 	/* ---- Overdrive next setting ---- */
 	uint32_t                       apply_overdrive_next_settings_mask;
 
-	/* ---- Workload Mask ---- */
-	uint32_t                       workload_mask;
-
 	/* ---- SMU9 ---- */
 	struct smu_features            smu_features[GNLD_FEATURES_MAX];
 	struct vega10_smc_state_table  smc_state_table;
diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
index 65224dbb550dac1406c47c70e0452a3c0ea05fb9..94df6eed5384d3f5e9a085f4d585fb38f2a1c107 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
@@ -696,6 +696,8 @@ enum PP_TABLE_VERSION {
 /**
  * The main hardware manager structure.
  */
+#define Workload_Policy_Max 5
+
 struct pp_hwmgr {
 	void *adev;
 	uint32_t chip_family;
@@ -757,6 +759,9 @@ struct pp_hwmgr {
 	bool od_enabled;
 	uint32_t power_limit;
 	uint32_t default_power_limit;
+	uint32_t workload_mask;
+	uint32_t workload_prority[Workload_Policy_Max];
+	uint32_t workload_setting[Workload_Policy_Max];
 };
 
 struct cgs_irq_src_funcs {