From 77df508a98834d8e2fe4c7c4e1089a1ce66ccaa1 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 9 Aug 2013 10:02:40 -0400 Subject: [PATCH] drm/radeon/dpm: implement UVD powergating for KB/KV Powergate the UVD block when not in use to save power. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 4 ++-- drivers/gpu/drm/radeon/kv_dpm.c | 22 +++++++++++++++------- drivers/gpu/drm/radeon/radeon_asic.c | 1 + drivers/gpu/drm/radeon/radeon_asic.h | 1 + 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 59b866a..e661aec 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -69,7 +69,7 @@ static void cik_pcie_gen3_enable(struct radeon_device *rdev); static void cik_program_aspm(struct radeon_device *rdev); static void cik_init_pg(struct radeon_device *rdev); static void cik_init_cg(struct radeon_device *rdev); -static void cik_uvd_resume(struct radeon_device *rdev); +void cik_uvd_resume(struct radeon_device *rdev); /* get temperature in millidegrees */ int ci_get_temp(struct radeon_device *rdev) @@ -8600,7 +8600,7 @@ int cik_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) return r; } -static void cik_uvd_resume(struct radeon_device *rdev) +void cik_uvd_resume(struct radeon_device *rdev) { uint64_t addr; uint32_t size; diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c index c26c4e3..3e232a4 100644 --- a/drivers/gpu/drm/radeon/kv_dpm.c +++ b/drivers/gpu/drm/radeon/kv_dpm.c @@ -49,7 +49,7 @@ static int kv_set_thermal_temperature_range(struct radeon_device *rdev, int min_temp, int max_temp); static int kv_init_fps_limits(struct radeon_device *rdev); -static void kv_dpm_powergate_uvd(struct radeon_device *rdev, bool gate); +void kv_dpm_powergate_uvd(struct radeon_device *rdev, bool gate); static void kv_dpm_powergate_vce(struct radeon_device *rdev, bool gate); static void kv_dpm_powergate_samu(struct radeon_device *rdev, bool gate); static void kv_dpm_powergate_acp(struct radeon_device *rdev, bool gate); @@ -59,6 +59,10 @@ extern void cik_exit_rlc_safe_mode(struct radeon_device *rdev); extern void cik_update_cg(struct radeon_device *rdev, u32 block, bool enable); +extern void cik_uvd_resume(struct radeon_device *rdev); +extern int r600_uvd_init(struct radeon_device *rdev, bool ring_test); +extern void r600_do_uvd_stop(struct radeon_device *rdev); + static const struct kv_lcac_config_values sx_local_cac_cfg_kv[] = { { 0, 4, 1 }, @@ -1201,6 +1205,7 @@ int kv_dpm_enable(struct radeon_device *rdev) kv_dpm_powergate_acp(rdev, true); kv_dpm_powergate_samu(rdev, true); kv_dpm_powergate_vce(rdev, true); + kv_dpm_powergate_uvd(rdev, true); kv_update_current_ps(rdev, rdev->pm.dpm.boot_ps); @@ -1458,7 +1463,7 @@ static int kv_update_acp_dpm(struct radeon_device *rdev, bool gate) return kv_enable_acp_dpm(rdev, !gate); } -static void kv_dpm_powergate_uvd(struct radeon_device *rdev, bool gate) +void kv_dpm_powergate_uvd(struct radeon_device *rdev, bool gate) { struct kv_power_info *pi = kv_get_pi(rdev); @@ -1468,13 +1473,18 @@ static void kv_dpm_powergate_uvd(struct radeon_device *rdev, bool gate) pi->uvd_power_gated = gate; if (gate) { - kv_update_uvd_dpm(rdev, true); + r600_do_uvd_stop(rdev); + cik_update_cg(rdev, RADEON_CG_BLOCK_UVD, false); + kv_update_uvd_dpm(rdev, gate); if (pi->caps_uvd_pg) kv_notify_message_to_smu(rdev, PPSMC_MSG_UVDPowerOFF); } else { if (pi->caps_uvd_pg) kv_notify_message_to_smu(rdev, PPSMC_MSG_UVDPowerON); - kv_update_uvd_dpm(rdev, false); + cik_uvd_resume(rdev); + r600_uvd_init(rdev, false); + cik_update_cg(rdev, RADEON_CG_BLOCK_UVD, true); + kv_update_uvd_dpm(rdev, gate); } } @@ -1714,7 +1724,6 @@ int kv_dpm_set_power_state(struct radeon_device *rdev) return ret; } #endif - kv_update_uvd_dpm(rdev, false); kv_update_sclk_t(rdev); } } else { @@ -1740,7 +1749,6 @@ int kv_dpm_set_power_state(struct radeon_device *rdev) return ret; } #endif - kv_update_uvd_dpm(rdev, false); kv_update_sclk_t(rdev); kv_enable_nb_dpm(rdev); } @@ -2502,7 +2510,7 @@ int kv_dpm_init(struct radeon_device *rdev) pi->voltage_drop_t = 0; pi->caps_sclk_throttle_low_notification = false; pi->caps_fps = false; /* true? */ - pi->caps_uvd_pg = false; /* XXX */ + pi->caps_uvd_pg = true; pi->caps_uvd_dpm = true; pi->caps_vce_pg = false; pi->caps_samu_pg = false; diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 1dad80c..63b6aae 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -2642,6 +2642,7 @@ static struct radeon_asic kv_asic = { .print_power_state = &kv_dpm_print_power_state, .debugfs_print_current_performance_level = &kv_dpm_debugfs_print_current_performance_level, .force_performance_level = &kv_dpm_force_performance_level, + .powergate_uvd = &kv_dpm_powergate_uvd, }, .pflip = { .pre_page_flip = &evergreen_pre_page_flip, diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 3570817..9060757 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -784,5 +784,6 @@ void kv_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, struct seq_file *m); int kv_dpm_force_performance_level(struct radeon_device *rdev, enum radeon_dpm_forced_level level); +void kv_dpm_powergate_uvd(struct radeon_device *rdev, bool gate); #endif -- 2.7.4