summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/powerplay
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/powerplay')
-rw-r--r--drivers/gpu/drm/amd/powerplay/amd_powerplay.c32
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c16
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c11
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c6
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c8
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h3
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/hwmgr.h5
7 files changed, 63 insertions, 18 deletions
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
index a8705b5ad264..b989bf3542d6 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 aea107643859..4b6cf795243c 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 ed3bd1502c0d..d0ef8f9c1361 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 58e2e0a10b3d..d8c205cf8f12 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 d90a0f1dbb55..f23861f2c685 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 de3219fff2db..8f6c2cb962da 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 65224dbb550d..94df6eed5384 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 {