diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index 9c373f8f465c..643d008410c6 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 e482daf394d3..15bd0f9acf73 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 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 {