The lowest power states often cause display problems, so only enable
them when all displays are off.

Signed-off-by: Alex Deucher <alexdeucher at gmail.com>
---
 drivers/gpu/drm/radeon/atombios_crtc.c      |    9 +++---
 drivers/gpu/drm/radeon/r100.c               |   12 ++++++--
 drivers/gpu/drm/radeon/r600.c               |   20 ++++++++++++--
 drivers/gpu/drm/radeon/radeon.h             |    7 +++-
 drivers/gpu/drm/radeon/radeon_atombios.c    |   37 ++++++++++++++++++--------
 drivers/gpu/drm/radeon/radeon_combios.c     |    2 +-
 drivers/gpu/drm/radeon/radeon_legacy_crtc.c |    9 +++---
 drivers/gpu/drm/radeon/radeon_pm.c          |   38 ++++++++++++++++++--------
 8 files changed, 94 insertions(+), 40 deletions(-)

diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c 
b/drivers/gpu/drm/radeon/atombios_crtc.c
index 4151ad8..03dd6c4 100644
--- a/drivers/gpu/drm/radeon/atombios_crtc.c
+++ b/drivers/gpu/drm/radeon/atombios_crtc.c
@@ -245,13 +245,15 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)

        switch (mode) {
        case DRM_MODE_DPMS_ON:
+               radeon_crtc->enabled = true;
+               /* adjust pm to dpms changes BEFORE enabling crtcs */
+               radeon_pm_compute_clocks(rdev);
                atombios_enable_crtc(crtc, ATOM_ENABLE);
                if (ASIC_IS_DCE3(rdev))
                        atombios_enable_crtc_memreq(crtc, ATOM_ENABLE);
                atombios_blank_crtc(crtc, ATOM_DISABLE);
                drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
                radeon_crtc_load_lut(crtc);
-               radeon_crtc->enabled = true;
                break;
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
@@ -262,11 +264,10 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
                        atombios_enable_crtc_memreq(crtc, ATOM_DISABLE);
                atombios_enable_crtc(crtc, ATOM_DISABLE);
                radeon_crtc->enabled = false;
+               /* adjust pm to dpms changes AFTER disabling crtcs */
+               radeon_pm_compute_clocks(rdev);
                break;
        }
-
-       /* adjust pm to dpms change */
-       radeon_pm_compute_clocks(rdev);
 }

 static void
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 14b7541..4161a35 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -87,7 +87,7 @@ void r100_get_power_state(struct radeon_device *rdev,
                } else {
                        if (rdev->pm.active_crtc_count > 1) {
                                for (i = 0; i < rdev->pm.num_power_states; i++) 
{
-                                       if (rdev->pm.power_state[i].flags & 
RADEON_PM_SINGLE_DISPLAY_ONLY)
+                                       if (rdev->pm.power_state[i].flags & 
RADEON_PM_STATE_SINGLE_DISPLAY_ONLY)
                                                continue;
                                        else if (i >= 
rdev->pm.current_power_state_index) {
                                                
rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
@@ -101,6 +101,12 @@ void r100_get_power_state(struct radeon_device *rdev,
                                rdev->pm.requested_power_state_index =
                                        rdev->pm.current_power_state_index - 1;
                }
+               /* don't use the power state if crtcs are active and no display 
flag is set */
+               if ((rdev->pm.active_crtc_count > 0) &&
+                   
(rdev->pm.power_state[rdev->pm.requested_power_state_index].clock_info[0].flags 
&
+                    RADEON_PM_MODE_NO_DISPLAY)) {
+                       rdev->pm.requested_power_state_index++;
+               }
                break;
        case PM_ACTION_UPCLOCK:
                if (rdev->pm.current_power_state_index == 
(rdev->pm.num_power_states - 1)) {
@@ -109,7 +115,7 @@ void r100_get_power_state(struct radeon_device *rdev,
                } else {
                        if (rdev->pm.active_crtc_count > 1) {
                                for (i = (rdev->pm.num_power_states - 1); i >= 
0; i--) {
-                                       if (rdev->pm.power_state[i].flags & 
RADEON_PM_SINGLE_DISPLAY_ONLY)
+                                       if (rdev->pm.power_state[i].flags & 
RADEON_PM_STATE_SINGLE_DISPLAY_ONLY)
                                                continue;
                                        else if (i <= 
rdev->pm.current_power_state_index) {
                                                
rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index;
@@ -215,7 +221,7 @@ void r100_set_power_state(struct radeon_device *rdev, bool 
static_switch)
                rdev->pm.current_power_state_index = 
rdev->pm.requested_power_state_index;
                rdev->pm.current_clock_mode_index = 
rdev->pm.requested_clock_mode_index;
        } else
-               DRM_INFO("GUI not idle!!!\n");
+               DRM_INFO("pm: GUI not idle!!!\n");
 }

 void r100_pm_misc(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 75c825c..08a328c 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -120,7 +120,7 @@ void r600_get_power_state(struct radeon_device *rdev,
                        } else {
                                if (rdev->pm.active_crtc_count > 1) {
                                        for (i = 0; i < 
rdev->pm.num_power_states; i++) {
-                                               if 
(rdev->pm.power_state[i].flags & RADEON_PM_SINGLE_DISPLAY_ONLY)
+                                               if 
(rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY)
                                                        continue;
                                                else if (i >= 
rdev->pm.current_power_state_index) {
                                                        
rdev->pm.requested_power_state_index =
@@ -136,6 +136,13 @@ void r600_get_power_state(struct radeon_device *rdev,
                                                
rdev->pm.current_power_state_index - 1;
                        }
                        rdev->pm.requested_clock_mode_index = 0;
+                       /* don't use the power state if crtcs are active and no 
display flag is set */
+                       if ((rdev->pm.active_crtc_count > 0) &&
+                           
(rdev->pm.power_state[rdev->pm.requested_power_state_index].
+                            
clock_info[rdev->pm.requested_clock_mode_index].flags &
+                            RADEON_PM_MODE_NO_DISPLAY)) {
+                               rdev->pm.requested_power_state_index++;
+                       }
                        break;
                case PM_ACTION_UPCLOCK:
                        if (rdev->pm.current_power_state_index == 
(rdev->pm.num_power_states - 1)) {
@@ -144,7 +151,7 @@ void r600_get_power_state(struct radeon_device *rdev,
                        } else {
                                if (rdev->pm.active_crtc_count > 1) {
                                        for (i = (rdev->pm.num_power_states - 
1); i >= 0; i--) {
-                                               if 
(rdev->pm.power_state[i].flags & RADEON_PM_SINGLE_DISPLAY_ONLY)
+                                               if 
(rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY)
                                                        continue;
                                                else if (i <= 
rdev->pm.current_power_state_index) {
                                                        
rdev->pm.requested_power_state_index =
@@ -179,7 +186,7 @@ void r600_get_power_state(struct radeon_device *rdev,
                        rdev->pm.requested_power_state_index = -1;
                        /* start at 1 as we don't want the default mode */
                        for (i = 1; i < rdev->pm.num_power_states; i++) {
-                               if (rdev->pm.power_state[i].flags & 
RADEON_PM_SINGLE_DISPLAY_ONLY)
+                               if (rdev->pm.power_state[i].flags & 
RADEON_PM_STATE_SINGLE_DISPLAY_ONLY)
                                        continue;
                                else if ((rdev->pm.power_state[i].type == 
POWER_STATE_TYPE_PERFORMANCE) ||
                                         (rdev->pm.power_state[i].type == 
POWER_STATE_TYPE_BATTERY)) {
@@ -210,6 +217,13 @@ void r600_get_power_state(struct radeon_device *rdev,
                                rdev->pm.requested_clock_mode_index = 0;
                                rdev->pm.can_downclock = false;
                        }
+                       /* don't use the power state if crtcs are active and no 
display flag is set */
+                       if ((rdev->pm.active_crtc_count > 0) &&
+                           
(rdev->pm.power_state[rdev->pm.requested_power_state_index].
+                            
clock_info[rdev->pm.requested_clock_mode_index].flags &
+                            RADEON_PM_MODE_NO_DISPLAY)) {
+                               rdev->pm.requested_clock_mode_index++;
+                       }
                        break;
                case PM_ACTION_UPCLOCK:
                        if (rdev->pm.requested_power_state_index == 
rdev->pm.current_power_state_index) {
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index e39e2b4..480a83f 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -658,6 +658,9 @@ struct radeon_voltage {
        u32 voltage;
 };

+/* clock mode flags */
+#define RADEON_PM_MODE_NO_DISPLAY          (1 << 0)
+
 struct radeon_pm_clock_info {
        /* memory clock */
        u32 mclk;
@@ -665,12 +668,12 @@ struct radeon_pm_clock_info {
        u32 sclk;
        /* voltage info */
        struct radeon_voltage voltage;
-       /* standardized clock flags - not sure we'll need these */
+       /* standardized clock flags */
        u32 flags;
 };

 /* state flags */
-#define RADEON_PM_SINGLE_DISPLAY_ONLY (1 << 0)
+#define RADEON_PM_STATE_SINGLE_DISPLAY_ONLY (1 << 0)

 struct radeon_power_state {
        enum radeon_pm_state_type type;
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c 
b/drivers/gpu/drm/radeon/radeon_atombios.c
index 7968d61..78e53d1 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -1549,7 +1549,7 @@ void radeon_atombios_get_power_modes(struct radeon_device 
*rdev)
                                                
rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
                                                        
power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex;
                                        }
-                                       rdev->pm.power_state[state_index].flags 
= RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                       rdev->pm.power_state[state_index].flags 
= RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
                                        rdev->pm.power_state[state_index].misc 
= misc;
                                        /* order matters! */
                                        if (misc & 
ATOM_PM_MISCINFO_POWER_SAVING_MODE)
@@ -1568,7 +1568,7 @@ void radeon_atombios_get_power_modes(struct radeon_device 
*rdev)
                                                
rdev->pm.power_state[state_index].type =
                                                        
POWER_STATE_TYPE_PERFORMANCE;
                                                
rdev->pm.power_state[state_index].flags &=
-                                                       
~RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                                       
~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
                                        }
                                        if (misc & 
ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
                                                
rdev->pm.power_state[state_index].type =
@@ -1577,7 +1577,10 @@ void radeon_atombios_get_power_modes(struct 
radeon_device *rdev)
                                                
rdev->pm.power_state[state_index].default_clock_mode =
                                                        
&rdev->pm.power_state[state_index].clock_info[0];
                                                
rdev->pm.power_state[state_index].flags &=
-                                                       
~RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                                       
~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
+                                       } else if (state_index == 0) {
+                                               
rdev->pm.power_state[state_index].clock_info[0].flags |=
+                                                       
RADEON_PM_MODE_NO_DISPLAY;
                                        }
                                        state_index++;
                                        break;
@@ -1613,7 +1616,7 @@ void radeon_atombios_get_power_modes(struct radeon_device 
*rdev)
                                                
rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id =
                                                        
power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex;
                                        }
-                                       rdev->pm.power_state[state_index].flags 
= RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                       rdev->pm.power_state[state_index].flags 
= RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
                                        rdev->pm.power_state[state_index].misc 
= misc;
                                        rdev->pm.power_state[state_index].misc2 
= misc2;
                                        /* order matters! */
@@ -1633,14 +1636,14 @@ void radeon_atombios_get_power_modes(struct 
radeon_device *rdev)
                                                
rdev->pm.power_state[state_index].type =
                                                        
POWER_STATE_TYPE_PERFORMANCE;
                                                
rdev->pm.power_state[state_index].flags &=
-                                                       
~RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                                       
~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
                                        }
                                        if (misc2 & 
ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
                                                
rdev->pm.power_state[state_index].type =
                                                        
POWER_STATE_TYPE_BALANCED;
                                        if (misc2 & 
ATOM_PM_MISCINFO2_MULTI_DISPLAY_SUPPORT)
                                                
rdev->pm.power_state[state_index].flags &=
-                                                       
~RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                                       
~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
                                        if (misc & 
ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) {
                                                
rdev->pm.power_state[state_index].type =
                                                        
POWER_STATE_TYPE_DEFAULT;
@@ -1648,7 +1651,10 @@ void radeon_atombios_get_power_modes(struct 
radeon_device *rdev)
                                                
rdev->pm.power_state[state_index].default_clock_mode =
                                                        
&rdev->pm.power_state[state_index].clock_info[0];
                                                
rdev->pm.power_state[state_index].flags &=
-                                                       
~RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                                       
~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
+                                       } else if (state_index == 0) {
+                                               
rdev->pm.power_state[state_index].clock_info[0].flags |=
+                                                       
RADEON_PM_MODE_NO_DISPLAY;
                                        }
                                        state_index++;
                                        break;
@@ -1690,7 +1696,7 @@ void radeon_atombios_get_power_modes(struct radeon_device 
*rdev)
                                                        
power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex;
                                                }
                                        }
-                                       rdev->pm.power_state[state_index].flags 
= RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                       rdev->pm.power_state[state_index].flags 
= RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
                                        rdev->pm.power_state[state_index].misc 
= misc;
                                        rdev->pm.power_state[state_index].misc2 
= misc2;
                                        /* order matters! */
@@ -1710,7 +1716,7 @@ void radeon_atombios_get_power_modes(struct radeon_device 
*rdev)
                                                
rdev->pm.power_state[state_index].type =
                                                        
POWER_STATE_TYPE_PERFORMANCE;
                                                
rdev->pm.power_state[state_index].flags &=
-                                                       
~RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                                       
~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
                                        }
                                        if (misc2 & 
ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE)
                                                
rdev->pm.power_state[state_index].type =
@@ -1721,6 +1727,9 @@ void radeon_atombios_get_power_modes(struct radeon_device 
*rdev)
                                                
rdev->pm.default_power_state_index = state_index;
                                                
rdev->pm.power_state[state_index].default_clock_mode =
                                                        
&rdev->pm.power_state[state_index].clock_info[0];
+                                       } else if (state_index == 0) {
+                                               
rdev->pm.power_state[state_index].clock_info[0].flags |=
+                                                       
RADEON_PM_MODE_NO_DISPLAY;
                                        }
                                        state_index++;
                                        break;
@@ -1734,7 +1743,7 @@ void radeon_atombios_get_power_modes(struct radeon_device 
*rdev)
                                rdev->pm.power_state[state_index - 
1].default_clock_mode =
                                        &rdev->pm.power_state[state_index - 
1].clock_info[0];
                                rdev->pm.power_state[state_index].flags &=
-                                       ~RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                       ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
                                rdev->pm.power_state[state_index].misc = 0;
                                rdev->pm.power_state[state_index].misc2 = 0;
                        }
@@ -1881,7 +1890,7 @@ void radeon_atombios_get_power_modes(struct radeon_device 
*rdev)
                                        rdev->pm.power_state[state_index].flags 
= 0;
                                        if (misc & 
ATOM_PPLIB_SINGLE_DISPLAY_ONLY)
                                                
rdev->pm.power_state[state_index].flags |=
-                                                       
RADEON_PM_SINGLE_DISPLAY_ONLY;
+                                                       
RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
                                        if (misc2 & 
ATOM_PPLIB_CLASSIFICATION_BOOT) {
                                                
rdev->pm.power_state[state_index].type =
                                                        
POWER_STATE_TYPE_DEFAULT;
@@ -1892,6 +1901,12 @@ void radeon_atombios_get_power_modes(struct 
radeon_device *rdev)
                                        state_index++;
                                }
                        }
+                       /* if multiple clock modes, mark the lowest as no 
display */
+                       for (i = 0; i < state_index; i++) {
+                               if (rdev->pm.power_state[i].num_clock_modes > 1)
+                                       
rdev->pm.power_state[i].clock_info[0].flags |=
+                                               RADEON_PM_MODE_NO_DISPLAY;
+                       }
                        /* first mode is usually default */
                        if (rdev->pm.default_power_state_index == -1) {
                                rdev->pm.power_state[0].type =
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c 
b/drivers/gpu/drm/radeon/radeon_combios.c
index b0d58a7..ea34ec5 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -2435,7 +2435,7 @@ void radeon_combios_get_power_modes(struct radeon_device 
*rdev)
                        if (rev > 6)
                                rdev->pm.power_state[state_index].pcie_lanes =
                                        RBIOS8(offset + 0x5 + 0x10);
-                       rdev->pm.power_state[state_index].flags = 
RADEON_PM_SINGLE_DISPLAY_ONLY;
+                       rdev->pm.power_state[state_index].flags = 
RADEON_PM_STATE_SINGLE_DISPLAY_ONLY;
                        state_index++;
                } else {
                        /* XXX figure out some good default low power mode for 
mobility cards w/out power tables */
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c 
b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
index 7701d42..e1e5255 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
@@ -314,6 +314,9 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)

        switch (mode) {
        case DRM_MODE_DPMS_ON:
+               radeon_crtc->enabled = true;
+               /* adjust pm to dpms changes BEFORE enabling crtcs */
+               radeon_pm_compute_clocks(rdev);
                if (radeon_crtc->crtc_id)
                        WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, 
~(RADEON_CRTC2_EN | mask));
                else {
@@ -323,7 +326,6 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
                }
                drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
                radeon_crtc_load_lut(crtc);
-               radeon_crtc->enabled = true;
                break;
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
@@ -337,11 +339,10 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
                        WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask);
                }
                radeon_crtc->enabled = false;
+               /* adjust pm to dpms changes AFTER disabling crtcs */
+               radeon_pm_compute_clocks(rdev);
                break;
        }
-
-       /* adjust pm to dpms change */
-       radeon_pm_compute_clocks(rdev);
 }

 int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c 
b/drivers/gpu/drm/radeon/radeon_pm.c
index 1ee7fc9..0dfa508 100644
--- a/drivers/gpu/drm/radeon/radeon_pm.c
+++ b/drivers/gpu/drm/radeon/radeon_pm.c
@@ -58,7 +58,7 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev, 
int static_switch)
 {
        int i;

-       if (!static_switch)
+       if (rdev->pm.state != PM_STATE_DISABLED)
                radeon_get_power_state(rdev, rdev->pm.planned_action);

        mutex_lock(&rdev->ddev->struct_mutex);
@@ -147,8 +147,11 @@ static ssize_t radeon_set_power_state_static(struct device 
*dev,
        mutex_lock(&rdev->pm.mutex);
        if ((ps >= 0) && (ps < rdev->pm.num_power_states) &&
            (cm >= 0) && (cm < rdev->pm.power_state[ps].num_clock_modes)) {
-               if ((rdev->pm.active_crtc_count > 1) &&
-                   (rdev->pm.power_state[ps].flags & 
RADEON_PM_SINGLE_DISPLAY_ONLY)) {
+               if ((rdev->pm.active_crtc_count > 0) &&
+                   (rdev->pm.power_state[ps].clock_info[cm].flags & 
RADEON_PM_MODE_NO_DISPLAY)) {
+                       DRM_ERROR("Invalid power state for display: %d.%d\n", 
ps, cm);
+               } else if ((rdev->pm.active_crtc_count > 1) &&
+                          (rdev->pm.power_state[ps].flags & 
RADEON_PM_STATE_SINGLE_DISPLAY_ONLY)) {
                        DRM_ERROR("Invalid power state for multi-head: 
%d.%d\n", ps, cm);
                } else {
                        /* disable dynpm */
@@ -248,7 +251,7 @@ static void radeon_print_power_mode_info(struct 
radeon_device *rdev)
                         is_default ? "(default)" : "");
                if ((rdev->flags & RADEON_IS_PCIE) && !(rdev->flags & 
RADEON_IS_IGP))
                        DRM_INFO("\t%d PCIE Lanes\n", 
rdev->pm.power_state[i].pcie_lanes);
-               if (rdev->pm.power_state[i].flags & 
RADEON_PM_SINGLE_DISPLAY_ONLY)
+               if (rdev->pm.power_state[i].flags & 
RADEON_PM_STATE_SINGLE_DISPLAY_ONLY)
                        DRM_INFO("\tSingle display only\n");
                DRM_INFO("\t%d Clock Mode(s)\n", 
rdev->pm.power_state[i].num_clock_modes);
                for (j = 0; j < rdev->pm.power_state[i].num_clock_modes; j++) {
@@ -261,6 +264,8 @@ static void radeon_print_power_mode_info(struct 
radeon_device *rdev)
                                         j,
                                         
rdev->pm.power_state[i].clock_info[j].sclk * 10,
                                         
rdev->pm.power_state[i].clock_info[j].mclk * 10);
+                       if (rdev->pm.power_state[i].clock_info[j].flags & 
RADEON_PM_MODE_NO_DISPLAY)
+                               DRM_INFO("\t\tNo display only\n");
                }
        }
 }
@@ -318,7 +323,7 @@ void radeon_pm_fini(struct radeon_device *rdev)
                /* reset default clocks */
                rdev->pm.state = PM_STATE_DISABLED;
                rdev->pm.planned_action = PM_ACTION_DEFAULT;
-               radeon_pm_set_clocks(rdev, false);
+               radeon_pm_set_clocks(rdev, true);
        } else if ((rdev->pm.current_power_state_index !=
                    rdev->pm.default_power_state_index) ||
                   (rdev->pm.current_clock_mode_index != 0)) {
@@ -342,9 +347,6 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev)
        struct drm_crtc *crtc;
        struct radeon_crtc *radeon_crtc;

-       if (rdev->pm.state == PM_STATE_DISABLED)
-               return;
-
        mutex_lock(&rdev->pm.mutex);

        rdev->pm.active_crtcs = 0;
@@ -358,13 +360,22 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev)
                }
        }

+       if (rdev->pm.state == PM_STATE_DISABLED) {
+               mutex_unlock(&rdev->pm.mutex);
+               return;
+       }
+
+       /* Note, radeon_pm_set_clocks is called with static_switch set
+        * to true since we always want to statically set the clocks,
+        * not wait for vbl.
+        */
        if (rdev->pm.active_crtc_count > 1) {
                if (rdev->pm.state == PM_STATE_ACTIVE) {
                        cancel_delayed_work(&rdev->pm.idle_work);

                        rdev->pm.state = PM_STATE_PAUSED;
-                       rdev->pm.planned_action = PM_ACTION_UPCLOCK;
-                       radeon_pm_set_clocks(rdev, false);
+                       rdev->pm.planned_action = PM_ACTION_DEFAULT;
+                       radeon_pm_set_clocks(rdev, true);

                        DRM_DEBUG("radeon: dynamic power management 
deactivated\n");
                }
@@ -374,7 +385,7 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev)
                if (rdev->pm.state == PM_STATE_MINIMUM) {
                        rdev->pm.state = PM_STATE_ACTIVE;
                        rdev->pm.planned_action = PM_ACTION_UPCLOCK;
-                       radeon_pm_set_clocks(rdev, false);
+                       radeon_pm_set_clocks(rdev, true);

                        queue_delayed_work(rdev->wq, &rdev->pm.idle_work,
                                msecs_to_jiffies(RADEON_IDLE_LOOP_MS));
@@ -390,7 +401,7 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev)

                        rdev->pm.state = PM_STATE_MINIMUM;
                        rdev->pm.planned_action = PM_ACTION_MINIMUM;
-                       radeon_pm_set_clocks(rdev, false);
+                       radeon_pm_set_clocks(rdev, true);
                }
        }

@@ -526,6 +537,9 @@ static void radeon_pm_idle_work_handler(struct work_struct 
*work)
                        }
                }

+               /* Note, radeon_pm_set_clocks is called with static_switch set
+                * to false since we want to wait for vbl to avoid flicker.
+                */
                if (rdev->pm.planned_action != PM_ACTION_NONE &&
                    jiffies > rdev->pm.action_timeout) {
                        radeon_pm_set_clocks(rdev, false);
-- 
1.5.6.3

Reply via email to