drm/radeon/dpm: implement UVD powergating for KB/KV
authorAlex Deucher <alexander.deucher@amd.com>
Fri, 9 Aug 2013 14:02:40 +0000 (10:02 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 30 Aug 2013 20:30:35 +0000 (16:30 -0400)
Powergate the UVD block when not in use to save power.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/kv_dpm.c
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_asic.h

index 59b866aa08d9b3029672493bb7cb30cdd4560b1e..e661aec734b241494b04aae2c92cd1bf1b83628e 100644 (file)
@@ -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;
index c26c4e3005e744c8b0d4006c05194c730f673d4b..3e232a4d3f4c10ef234abc2a679f5a7e8c101ef2 100644 (file)
@@ -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;
index 1dad80c0e17f00f0c1a9b2e669e832eba57ad670..63b6aae66236b840a53a087310f3557cceed7ac7 100644 (file)
@@ -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,
index 3570817a5847c0a1297f14c5f61a6acc41a7b67f..9060757e4dc1008002cd6835215cb1964027f612 100644 (file)
@@ -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