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