drm/radeon: add dpm UVD handling for sumo asics
authorAlex Deucher <alexander.deucher@amd.com>
Wed, 5 Dec 2012 20:59:11 +0000 (15:59 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 27 Jun 2013 23:15:48 +0000 (19:15 -0400)
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/radeon/sumo_dpm.c
drivers/gpu/drm/radeon/sumod.h

index 69792e4ac1cede89995a32acf315edccdd7a5905..7bd3fca175decd84f43555ba592177c249c5c654 100644 (file)
@@ -811,6 +811,40 @@ static void sumo_program_bootup_state(struct radeon_device *rdev)
                sumo_power_level_enable(rdev, i, false);
 }
 
+static void sumo_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev)
+{
+       struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+       struct sumo_ps *current_ps = sumo_get_ps(rdev->pm.dpm.current_ps);
+
+       if ((rdev->pm.dpm.requested_ps->vclk == rdev->pm.dpm.current_ps->vclk) &&
+           (rdev->pm.dpm.requested_ps->dclk == rdev->pm.dpm.current_ps->dclk))
+               return;
+
+       if (new_ps->levels[new_ps->num_levels - 1].sclk >=
+           current_ps->levels[current_ps->num_levels - 1].sclk)
+               return;
+
+       radeon_set_uvd_clocks(rdev, rdev->pm.dpm.requested_ps->vclk,
+                             rdev->pm.dpm.requested_ps->dclk);
+}
+
+static void sumo_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev)
+{
+       struct sumo_ps *new_ps = sumo_get_ps(rdev->pm.dpm.requested_ps);
+       struct sumo_ps *current_ps = sumo_get_ps(rdev->pm.dpm.current_ps);
+
+       if ((rdev->pm.dpm.requested_ps->vclk == rdev->pm.dpm.current_ps->vclk) &&
+           (rdev->pm.dpm.requested_ps->dclk == rdev->pm.dpm.current_ps->dclk))
+               return;
+
+       if (new_ps->levels[new_ps->num_levels - 1].sclk <
+           current_ps->levels[current_ps->num_levels - 1].sclk)
+               return;
+
+       radeon_set_uvd_clocks(rdev, rdev->pm.dpm.requested_ps->vclk,
+                             rdev->pm.dpm.requested_ps->dclk);
+}
+
 void sumo_take_smu_control(struct radeon_device *rdev, bool enable)
 {
 /* This bit selects who handles display phy powergating.
@@ -1096,6 +1130,22 @@ static void sumo_cleanup_asic(struct radeon_device *rdev)
        sumo_take_smu_control(rdev, false);
 }
 
+static void sumo_uvd_init(struct radeon_device *rdev)
+{
+       u32 tmp;
+
+       tmp = RREG32(CG_VCLK_CNTL);
+       tmp &= ~VCLK_DIR_CNTL_EN;
+       WREG32(CG_VCLK_CNTL, tmp);
+
+       tmp = RREG32(CG_DCLK_CNTL);
+       tmp &= ~DCLK_DIR_CNTL_EN;
+       WREG32(CG_DCLK_CNTL, tmp);
+
+       /* 100 Mhz */
+       radeon_set_uvd_clocks(rdev, 10000, 10000);
+}
+
 static int sumo_set_thermal_temperature_range(struct radeon_device *rdev,
                                              int min_temp, int max_temp)
 {
@@ -1188,6 +1238,8 @@ int sumo_dpm_set_power_state(struct radeon_device *rdev)
 
        if (pi->enable_dynamic_patch_ps)
                sumo_apply_state_adjust_rules(rdev);
+       if (pi->enable_dpm)
+               sumo_set_uvd_clock_before_set_eng_clock(rdev);
        sumo_update_current_power_levels(rdev);
        if (pi->enable_boost) {
                sumo_enable_boost(rdev, false);
@@ -1211,6 +1263,8 @@ int sumo_dpm_set_power_state(struct radeon_device *rdev)
        }
        if (pi->enable_boost)
                sumo_enable_boost(rdev, true);
+       if (pi->enable_dpm)
+               sumo_set_uvd_clock_after_set_eng_clock(rdev);
 
        return 0;
 }
@@ -1237,6 +1291,7 @@ void sumo_dpm_setup_asic(struct radeon_device *rdev)
        sumo_program_acpi_power_level(rdev);
        sumo_enable_acpi_pm(rdev);
        sumo_take_smu_control(rdev, true);
+       sumo_uvd_init(rdev);
 }
 
 void sumo_dpm_display_configuration_changed(struct radeon_device *rdev)
index a5deba6ebf2b005b4a5c3652a63847b5e7d9b84a..7c9c2d4b86c086d2b52ca8e8425c994a71d3c0ba 100644 (file)
 #define CG_SCLK_STATUS                                  0x604
 #       define SCLK_OVERCLK_DETECT                      (1 << 2)
 
+#define CG_DCLK_CNTL                                    0x610
+#       define DCLK_DIVIDER_MASK                        0x7f
+#       define DCLK_DIR_CNTL_EN                         (1 << 8)
+#define CG_DCLK_STATUS                                  0x614
+#       define DCLK_STATUS                              (1 << 0)
+#define CG_VCLK_CNTL                                    0x618
+#       define VCLK_DIVIDER_MASK                        0x7f
+#       define VCLK_DIR_CNTL_EN                         (1 << 8)
+#define CG_VCLK_STATUS                                  0x61c
+
 #define GENERAL_PWRMGT                                  0x63c
 #       define STATIC_PM_EN                             (1 << 1)