drm/radeon/pm: fix multi-head profile handling on BTC+ (v2)
authorAlex Deucher <alexander.deucher@amd.com>
Mon, 1 Oct 2012 23:25:11 +0000 (19:25 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 2 Oct 2012 14:27:51 +0000 (10:27 -0400)
Starting on BTC, there are no longer separate states for
single head and multi-head, we just use the high mclk/voltage
for all states for multi-head.

Fixes:
https://bugs.freedesktop.org/show_bug.cgi?id=49981

v2: fix typo

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

index ef47879..c4ded39 100644 (file)
@@ -326,6 +326,64 @@ void sumo_pm_init_profile(struct radeon_device *rdev)
 }
 
 /**
+ * btc_pm_init_profile - Initialize power profiles callback.
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Initialize the power states used in profile mode
+ * (BTC, cayman).
+ * Used for profile mode only.
+ */
+void btc_pm_init_profile(struct radeon_device *rdev)
+{
+       int idx;
+
+       /* default */
+       rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
+       rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
+       rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 2;
+       /* starting with BTC, there is one state that is used for both
+        * MH and SH.  Difference is that we always use the high clock index for
+        * mclk.
+        */
+       if (rdev->flags & RADEON_IS_MOBILITY)
+               idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
+       else
+               idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+       /* low sh */
+       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+       /* mid sh */
+       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
+       /* high sh */
+       rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2;
+       /* low mh */
+       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+       /* mid mh */
+       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
+       /* high mh */
+       rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2;
+}
+
+/**
  * evergreen_pm_misc - set additional pm hw parameters callback.
  *
  * @rdev: radeon_device pointer
index 6225e19..0f31c43 100644 (file)
@@ -1357,7 +1357,7 @@ static struct radeon_asic btc_asic = {
                .misc = &evergreen_pm_misc,
                .prepare = &evergreen_pm_prepare,
                .finish = &evergreen_pm_finish,
-               .init_profile = &r600_pm_init_profile,
+               .init_profile = &btc_pm_init_profile,
                .get_dynpm_state = &r600_pm_get_dynpm_state,
                .get_engine_clock = &radeon_atom_get_engine_clock,
                .set_engine_clock = &radeon_atom_set_engine_clock,
@@ -1462,7 +1462,7 @@ static struct radeon_asic cayman_asic = {
                .misc = &evergreen_pm_misc,
                .prepare = &evergreen_pm_prepare,
                .finish = &evergreen_pm_finish,
-               .init_profile = &r600_pm_init_profile,
+               .init_profile = &btc_pm_init_profile,
                .get_dynpm_state = &r600_pm_get_dynpm_state,
                .get_engine_clock = &radeon_atom_get_engine_clock,
                .set_engine_clock = &radeon_atom_set_engine_clock,
index 9a71f44..f158c11 100644 (file)
@@ -420,6 +420,7 @@ extern void evergreen_pm_misc(struct radeon_device *rdev);
 extern void evergreen_pm_prepare(struct radeon_device *rdev);
 extern void evergreen_pm_finish(struct radeon_device *rdev);
 extern void sumo_pm_init_profile(struct radeon_device *rdev);
+extern void btc_pm_init_profile(struct radeon_device *rdev);
 extern void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc);
 extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
 extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc);
index 8d64138..bc2e705 100644 (file)
@@ -167,8 +167,21 @@ static void radeon_set_power_state(struct radeon_device *rdev)
                if (sclk > rdev->pm.default_sclk)
                        sclk = rdev->pm.default_sclk;
 
-               mclk = rdev->pm.power_state[rdev->pm.requested_power_state_index].
-                       clock_info[rdev->pm.requested_clock_mode_index].mclk;
+               /* starting with BTC, there is one state that is used for both
+                * MH and SH.  Difference is that we always use the high clock index for
+                * mclk.
+                */
+               if ((rdev->pm.pm_method == PM_METHOD_PROFILE) &&
+                   (rdev->family >= CHIP_BARTS) &&
+                   rdev->pm.active_crtc_count &&
+                   ((rdev->pm.profile_index == PM_PROFILE_MID_MH_IDX) ||
+                    (rdev->pm.profile_index == PM_PROFILE_LOW_MH_IDX)))
+                       mclk = rdev->pm.power_state[rdev->pm.requested_power_state_index].
+                               clock_info[rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx].mclk;
+               else
+                       mclk = rdev->pm.power_state[rdev->pm.requested_power_state_index].
+                               clock_info[rdev->pm.requested_clock_mode_index].mclk;
+
                if (mclk > rdev->pm.default_mclk)
                        mclk = rdev->pm.default_mclk;