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 <alexander.deucher@amd.com>
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_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 @@
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 @@
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_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 @@
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 @@
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 @@
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 @@
return ret;
}
#endif
- kv_update_uvd_dpm(rdev, false);
kv_update_sclk_t(rdev);
}
} else {
@@ -1740,7 +1749,6 @@
return ret;
}
#endif
- kv_update_uvd_dpm(rdev, false);
kv_update_sclk_t(rdev);
kv_enable_nb_dpm(rdev);
}
@@ -2502,7 +2510,7 @@
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 @@
.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 @@
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