From 3c50a78b274e666c83fdc929bf68328ae17964bb Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 9 May 2019 16:11:56 +0800 Subject: [PATCH 1/2] drm/amd/powerplay: update SMU7 fast uclk switch settings Clean up the fast uclk switch settings on SMU7 asics. Change-Id: I3bde78b3caa13078b67c1e2500aa44269c9c7350 Signed-off-by: Evan Quan --- .../gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 81 ++++++++++++------- .../gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.h | 14 ++++ 2 files changed, 65 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index 6870dc0572b5..b5ca29100387 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -2891,6 +2891,7 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, struct PP_Clocks minimum_clocks = {0}; bool disable_mclk_switching; bool disable_mclk_switching_for_frame_lock; + bool disable_mclk_switching_for_display; const struct phm_clock_and_voltage_limits *max_limits; uint32_t i; struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); @@ -2898,9 +2899,12 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, (struct phm_ppt_v1_information *)(hwmgr->pptable); int32_t count; int32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0; + uint32_t latency; + int latency_allowed = 0; data->battery_state = (PP_StateUILabel_Battery == request_ps->classification.ui_label); + data->mclk_ignore_signal = false; PP_ASSERT_WITH_CODE(smu7_ps->performance_level_count == 2, "VI should always have 2 performance levels", @@ -2947,25 +2951,20 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, minimum_clocks.memoryClock = stable_pstate_mclk; } + if (hwmgr->display_config->num_display == 0) + data->mclk_ignore_signal = true; + disable_mclk_switching_for_frame_lock = phm_cap_enabled( hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMclkSwitchingForFrameLock); - - - if (hwmgr->display_config->num_display == 0) - disable_mclk_switching = false; - else - disable_mclk_switching = ((1 < hwmgr->display_config->num_display) || - disable_mclk_switching_for_frame_lock || - smu7_vblank_too_short(hwmgr, hwmgr->display_config->min_vblank_time)); + disable_mclk_switching_for_display = (((1 < hwmgr->display_config->num_display) && + !hwmgr->display_config->multi_monitor_in_sync) || + smu7_vblank_too_short(hwmgr, hwmgr->display_config->min_vblank_time)); + disable_mclk_switching = disable_mclk_switching_for_display || disable_mclk_switching_for_frame_lock; sclk = smu7_ps->performance_levels[0].engine_clock; mclk = smu7_ps->performance_levels[0].memory_clock; - if (disable_mclk_switching) - mclk = smu7_ps->performance_levels - [smu7_ps->performance_level_count - 1].memory_clock; - if (sclk < minimum_clocks.engineClock) sclk = (minimum_clocks.engineClock > max_limits->sclk) ? max_limits->sclk : minimum_clocks.engineClock; @@ -2987,8 +2986,27 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, if (mclk < smu7_ps->performance_levels[1].memory_clock) mclk = smu7_ps->performance_levels[1].memory_clock; + if (disable_mclk_switching_for_display) { + latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency; + for (i = 0; i < data->mclk_latency_table.count; i++) { + if (data->mclk_latency_table.entries[i].latency <= latency) { + latency_allowed = 1; + + if ((data->mclk_latency_table.entries[i].frequency >= smu7_ps->performance_levels[0].memory_clock) && + (data->mclk_latency_table.entries[i].frequency <= smu7_ps->performance_levels[1].memory_clock)) { + mclk = data->mclk_latency_table.entries[i].frequency; + break; + } + } + } + + if ((i >= data->mclk_latency_table.count) && !latency_allowed) + data->mclk_ignore_signal = true; + else + data->mclk_ignore_signal = false; + } + smu7_ps->performance_levels[0].memory_clock = mclk; - smu7_ps->performance_levels[1].memory_clock = mclk; } else { if (smu7_ps->performance_levels[1].memory_clock < smu7_ps->performance_levels[0].memory_clock) @@ -3925,9 +3943,20 @@ static int smu7_notify_link_speed_change_after_state_change( return 0; } +static int +smu7_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display) +{ + PPSMC_Msg msg = has_display ? (PPSMC_Msg)PPSMC_HasDisplay : (PPSMC_Msg)PPSMC_NoDisplay; + + return (smum_send_msg_to_smc(hwmgr, msg) == 0) ? 0 : -1; +} + static int smu7_notify_smc_display(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (data->mclk_ignore_signal) + return (smu7_notify_smc_display_change(hwmgr, false) == 0) ? 0 : -EINVAL; if (hwmgr->feature_mask & PP_VBI_TIME_SUPPORT_MASK) { if (hwmgr->chip_id == CHIP_VEGAM) @@ -3940,8 +3965,9 @@ static int smu7_notify_smc_display(struct pp_hwmgr *hwmgr) else smum_send_msg_to_smc_with_parameter(hwmgr, (PPSMC_Msg)PPSMC_MSG_SetVBITimeout, data->frame_time_x2); + data->last_sent_vbi_timeout = data->frame_time_x2; } - return (smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_HasDisplay) == 0) ? 0 : -EINVAL; + return (smu7_notify_smc_display_change(hwmgr, true) == 0) ? 0 : -EINVAL; } static int smu7_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input) @@ -4023,21 +4049,10 @@ static int smu7_set_max_fan_pwm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_f PPSMC_MSG_SetFanPwmMax, us_max_fan_pwm); } -static int -smu7_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display) -{ - PPSMC_Msg msg = has_display ? (PPSMC_Msg)PPSMC_HasDisplay : (PPSMC_Msg)PPSMC_NoDisplay; - - return (smum_send_msg_to_smc(hwmgr, msg) == 0) ? 0 : -1; -} static int smu7_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr) { - if (hwmgr->display_config->num_display > 1 && - !hwmgr->display_config->multi_monitor_in_sync) - smu7_notify_smc_display_change(hwmgr, false); - return 0; } @@ -4151,7 +4166,7 @@ smu7_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) is_update_required = true; - if (data->display_timing.vrefresh != hwmgr->display_config->vrefresh) + if (data->last_sent_vbi_timeout != data->frame_time_x2) is_update_required = true; if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) { @@ -4668,20 +4683,26 @@ static uint32_t smu7_get_mem_latency(struct pp_hwmgr *hwmgr, uint32_t clk) static int smu7_get_mclks(struct pp_hwmgr *hwmgr, struct amd_pp_clocks *clocks) { + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); struct phm_ppt_v1_information *table_info = (struct phm_ppt_v1_information *)hwmgr->pptable; struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table; int i; struct phm_clock_voltage_dependency_table *mclk_table; + data->mclk_latency_table.count = 0; if (hwmgr->pp_table_version == PP_TABLE_V1) { if (table_info == NULL) return -EINVAL; dep_mclk_table = table_info->vdd_dep_on_mclk; for (i = 0; i < dep_mclk_table->count; i++) { clocks->clock[i] = dep_mclk_table->entries[i].clk * 10; - clocks->latency[i] = smu7_get_mem_latency(hwmgr, + data->mclk_latency_table.entries[i].frequency = + dep_mclk_table->entries[i].clk; + clocks->latency[i] = data->mclk_latency_table.entries[i].latency = + smu7_get_mem_latency(hwmgr, dep_mclk_table->entries[i].clk); + data->mclk_latency_table.count++; } clocks->count = dep_mclk_table->count; } else if (hwmgr->pp_table_version == PP_TABLE_V0) { diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.h index 69d361f8dfca..6883ffd55b2b 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.h @@ -200,6 +200,16 @@ struct profile_mode_setting { uint16_t mclk_activity; }; +struct smu7_mclk_latency_entries { + uint32_t frequency; + uint32_t latency; +}; + +struct smu7_mclk_latency_table { + uint32_t count; + struct smu7_mclk_latency_entries entries[8]; +}; + struct smu7_hwmgr { struct smu7_dpm_table dpm_table; struct smu7_dpm_table golden_dpm_table; @@ -328,6 +338,10 @@ struct smu7_hwmgr { uint16_t mem_latency_low; uint32_t vr_config; struct profile_mode_setting current_profile_setting; + + bool mclk_ignore_signal; + struct smu7_mclk_latency_table mclk_latency_table; + uint32_t last_sent_vbi_timeout; }; /* To convert to Q8.8 format for firmware */ -- 2.21.0