diff options
author | Alex Deucher <alexdeucher@gmail.com> | 2010-05-03 01:13:14 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-05-18 04:21:50 -0400 |
commit | d7311171c4cc8d6231427f7ac5056b939a184b80 (patch) | |
tree | bbe3db53048b12ccf1e480261e69121f095226d7 /drivers | |
parent | ca2af92311eee95820f3b48c35045e5f56bc1477 (diff) |
drm/radeon/kms/pm: add support for no display power states
The lowest power states often cause display problems, so only enable
them when all displays are off.
Signed-off-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/radeon/atombios_crtc.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r100.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/r600.c | 20 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_atombios.c | 37 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_combios.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 9 | ||||
-rw-r--r-- | 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 4151ad8affed..03dd6c41dc19 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) | |||
245 | 245 | ||
246 | switch (mode) { | 246 | switch (mode) { |
247 | case DRM_MODE_DPMS_ON: | 247 | case DRM_MODE_DPMS_ON: |
248 | radeon_crtc->enabled = true; | ||
249 | /* adjust pm to dpms changes BEFORE enabling crtcs */ | ||
250 | radeon_pm_compute_clocks(rdev); | ||
248 | atombios_enable_crtc(crtc, ATOM_ENABLE); | 251 | atombios_enable_crtc(crtc, ATOM_ENABLE); |
249 | if (ASIC_IS_DCE3(rdev)) | 252 | if (ASIC_IS_DCE3(rdev)) |
250 | atombios_enable_crtc_memreq(crtc, ATOM_ENABLE); | 253 | atombios_enable_crtc_memreq(crtc, ATOM_ENABLE); |
251 | atombios_blank_crtc(crtc, ATOM_DISABLE); | 254 | atombios_blank_crtc(crtc, ATOM_DISABLE); |
252 | drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); | 255 | drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); |
253 | radeon_crtc_load_lut(crtc); | 256 | radeon_crtc_load_lut(crtc); |
254 | radeon_crtc->enabled = true; | ||
255 | break; | 257 | break; |
256 | case DRM_MODE_DPMS_STANDBY: | 258 | case DRM_MODE_DPMS_STANDBY: |
257 | case DRM_MODE_DPMS_SUSPEND: | 259 | case DRM_MODE_DPMS_SUSPEND: |
@@ -262,11 +264,10 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
262 | atombios_enable_crtc_memreq(crtc, ATOM_DISABLE); | 264 | atombios_enable_crtc_memreq(crtc, ATOM_DISABLE); |
263 | atombios_enable_crtc(crtc, ATOM_DISABLE); | 265 | atombios_enable_crtc(crtc, ATOM_DISABLE); |
264 | radeon_crtc->enabled = false; | 266 | radeon_crtc->enabled = false; |
267 | /* adjust pm to dpms changes AFTER disabling crtcs */ | ||
268 | radeon_pm_compute_clocks(rdev); | ||
265 | break; | 269 | break; |
266 | } | 270 | } |
267 | |||
268 | /* adjust pm to dpms change */ | ||
269 | radeon_pm_compute_clocks(rdev); | ||
270 | } | 271 | } |
271 | 272 | ||
272 | static void | 273 | static void |
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 14b7541df38a..4161a35dd3d3 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, | |||
87 | } else { | 87 | } else { |
88 | if (rdev->pm.active_crtc_count > 1) { | 88 | if (rdev->pm.active_crtc_count > 1) { |
89 | for (i = 0; i < rdev->pm.num_power_states; i++) { | 89 | for (i = 0; i < rdev->pm.num_power_states; i++) { |
90 | if (rdev->pm.power_state[i].flags & RADEON_PM_SINGLE_DISPLAY_ONLY) | 90 | if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) |
91 | continue; | 91 | continue; |
92 | else if (i >= rdev->pm.current_power_state_index) { | 92 | else if (i >= rdev->pm.current_power_state_index) { |
93 | rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index; | 93 | 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, | |||
101 | rdev->pm.requested_power_state_index = | 101 | rdev->pm.requested_power_state_index = |
102 | rdev->pm.current_power_state_index - 1; | 102 | rdev->pm.current_power_state_index - 1; |
103 | } | 103 | } |
104 | /* don't use the power state if crtcs are active and no display flag is set */ | ||
105 | if ((rdev->pm.active_crtc_count > 0) && | ||
106 | (rdev->pm.power_state[rdev->pm.requested_power_state_index].clock_info[0].flags & | ||
107 | RADEON_PM_MODE_NO_DISPLAY)) { | ||
108 | rdev->pm.requested_power_state_index++; | ||
109 | } | ||
104 | break; | 110 | break; |
105 | case PM_ACTION_UPCLOCK: | 111 | case PM_ACTION_UPCLOCK: |
106 | if (rdev->pm.current_power_state_index == (rdev->pm.num_power_states - 1)) { | 112 | 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, | |||
109 | } else { | 115 | } else { |
110 | if (rdev->pm.active_crtc_count > 1) { | 116 | if (rdev->pm.active_crtc_count > 1) { |
111 | for (i = (rdev->pm.num_power_states - 1); i >= 0; i--) { | 117 | for (i = (rdev->pm.num_power_states - 1); i >= 0; i--) { |
112 | if (rdev->pm.power_state[i].flags & RADEON_PM_SINGLE_DISPLAY_ONLY) | 118 | if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) |
113 | continue; | 119 | continue; |
114 | else if (i <= rdev->pm.current_power_state_index) { | 120 | else if (i <= rdev->pm.current_power_state_index) { |
115 | rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index; | 121 | 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) | |||
215 | rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index; | 221 | rdev->pm.current_power_state_index = rdev->pm.requested_power_state_index; |
216 | rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index; | 222 | rdev->pm.current_clock_mode_index = rdev->pm.requested_clock_mode_index; |
217 | } else | 223 | } else |
218 | DRM_INFO("GUI not idle!!!\n"); | 224 | DRM_INFO("pm: GUI not idle!!!\n"); |
219 | } | 225 | } |
220 | 226 | ||
221 | void r100_pm_misc(struct radeon_device *rdev) | 227 | 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 75c825cb8790..08a328c4165a 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, | |||
120 | } else { | 120 | } else { |
121 | if (rdev->pm.active_crtc_count > 1) { | 121 | if (rdev->pm.active_crtc_count > 1) { |
122 | for (i = 0; i < rdev->pm.num_power_states; i++) { | 122 | for (i = 0; i < rdev->pm.num_power_states; i++) { |
123 | if (rdev->pm.power_state[i].flags & RADEON_PM_SINGLE_DISPLAY_ONLY) | 123 | if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) |
124 | continue; | 124 | continue; |
125 | else if (i >= rdev->pm.current_power_state_index) { | 125 | else if (i >= rdev->pm.current_power_state_index) { |
126 | rdev->pm.requested_power_state_index = | 126 | rdev->pm.requested_power_state_index = |
@@ -136,6 +136,13 @@ void r600_get_power_state(struct radeon_device *rdev, | |||
136 | rdev->pm.current_power_state_index - 1; | 136 | rdev->pm.current_power_state_index - 1; |
137 | } | 137 | } |
138 | rdev->pm.requested_clock_mode_index = 0; | 138 | rdev->pm.requested_clock_mode_index = 0; |
139 | /* don't use the power state if crtcs are active and no display flag is set */ | ||
140 | if ((rdev->pm.active_crtc_count > 0) && | ||
141 | (rdev->pm.power_state[rdev->pm.requested_power_state_index]. | ||
142 | clock_info[rdev->pm.requested_clock_mode_index].flags & | ||
143 | RADEON_PM_MODE_NO_DISPLAY)) { | ||
144 | rdev->pm.requested_power_state_index++; | ||
145 | } | ||
139 | break; | 146 | break; |
140 | case PM_ACTION_UPCLOCK: | 147 | case PM_ACTION_UPCLOCK: |
141 | if (rdev->pm.current_power_state_index == (rdev->pm.num_power_states - 1)) { | 148 | 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, | |||
144 | } else { | 151 | } else { |
145 | if (rdev->pm.active_crtc_count > 1) { | 152 | if (rdev->pm.active_crtc_count > 1) { |
146 | for (i = (rdev->pm.num_power_states - 1); i >= 0; i--) { | 153 | for (i = (rdev->pm.num_power_states - 1); i >= 0; i--) { |
147 | if (rdev->pm.power_state[i].flags & RADEON_PM_SINGLE_DISPLAY_ONLY) | 154 | if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) |
148 | continue; | 155 | continue; |
149 | else if (i <= rdev->pm.current_power_state_index) { | 156 | else if (i <= rdev->pm.current_power_state_index) { |
150 | rdev->pm.requested_power_state_index = | 157 | rdev->pm.requested_power_state_index = |
@@ -179,7 +186,7 @@ void r600_get_power_state(struct radeon_device *rdev, | |||
179 | rdev->pm.requested_power_state_index = -1; | 186 | rdev->pm.requested_power_state_index = -1; |
180 | /* start at 1 as we don't want the default mode */ | 187 | /* start at 1 as we don't want the default mode */ |
181 | for (i = 1; i < rdev->pm.num_power_states; i++) { | 188 | for (i = 1; i < rdev->pm.num_power_states; i++) { |
182 | if (rdev->pm.power_state[i].flags & RADEON_PM_SINGLE_DISPLAY_ONLY) | 189 | if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) |
183 | continue; | 190 | continue; |
184 | else if ((rdev->pm.power_state[i].type == POWER_STATE_TYPE_PERFORMANCE) || | 191 | else if ((rdev->pm.power_state[i].type == POWER_STATE_TYPE_PERFORMANCE) || |
185 | (rdev->pm.power_state[i].type == POWER_STATE_TYPE_BATTERY)) { | 192 | (rdev->pm.power_state[i].type == POWER_STATE_TYPE_BATTERY)) { |
@@ -210,6 +217,13 @@ void r600_get_power_state(struct radeon_device *rdev, | |||
210 | rdev->pm.requested_clock_mode_index = 0; | 217 | rdev->pm.requested_clock_mode_index = 0; |
211 | rdev->pm.can_downclock = false; | 218 | rdev->pm.can_downclock = false; |
212 | } | 219 | } |
220 | /* don't use the power state if crtcs are active and no display flag is set */ | ||
221 | if ((rdev->pm.active_crtc_count > 0) && | ||
222 | (rdev->pm.power_state[rdev->pm.requested_power_state_index]. | ||
223 | clock_info[rdev->pm.requested_clock_mode_index].flags & | ||
224 | RADEON_PM_MODE_NO_DISPLAY)) { | ||
225 | rdev->pm.requested_clock_mode_index++; | ||
226 | } | ||
213 | break; | 227 | break; |
214 | case PM_ACTION_UPCLOCK: | 228 | case PM_ACTION_UPCLOCK: |
215 | if (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index) { | 229 | 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 e39e2b4ec979..480a83ff54d5 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -658,6 +658,9 @@ struct radeon_voltage { | |||
658 | u32 voltage; | 658 | u32 voltage; |
659 | }; | 659 | }; |
660 | 660 | ||
661 | /* clock mode flags */ | ||
662 | #define RADEON_PM_MODE_NO_DISPLAY (1 << 0) | ||
663 | |||
661 | struct radeon_pm_clock_info { | 664 | struct radeon_pm_clock_info { |
662 | /* memory clock */ | 665 | /* memory clock */ |
663 | u32 mclk; | 666 | u32 mclk; |
@@ -665,12 +668,12 @@ struct radeon_pm_clock_info { | |||
665 | u32 sclk; | 668 | u32 sclk; |
666 | /* voltage info */ | 669 | /* voltage info */ |
667 | struct radeon_voltage voltage; | 670 | struct radeon_voltage voltage; |
668 | /* standardized clock flags - not sure we'll need these */ | 671 | /* standardized clock flags */ |
669 | u32 flags; | 672 | u32 flags; |
670 | }; | 673 | }; |
671 | 674 | ||
672 | /* state flags */ | 675 | /* state flags */ |
673 | #define RADEON_PM_SINGLE_DISPLAY_ONLY (1 << 0) | 676 | #define RADEON_PM_STATE_SINGLE_DISPLAY_ONLY (1 << 0) |
674 | 677 | ||
675 | struct radeon_power_state { | 678 | struct radeon_power_state { |
676 | enum radeon_pm_state_type type; | 679 | 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 c29ac74a1d20..9149e4a3af0f 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) | |||
1549 | rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = | 1549 | rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = |
1550 | power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex; | 1550 | power_info->info.asPowerPlayInfo[i].ucVoltageDropIndex; |
1551 | } | 1551 | } |
1552 | rdev->pm.power_state[state_index].flags = RADEON_PM_SINGLE_DISPLAY_ONLY; | 1552 | rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; |
1553 | rdev->pm.power_state[state_index].misc = misc; | 1553 | rdev->pm.power_state[state_index].misc = misc; |
1554 | /* order matters! */ | 1554 | /* order matters! */ |
1555 | if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE) | 1555 | if (misc & ATOM_PM_MISCINFO_POWER_SAVING_MODE) |
@@ -1568,7 +1568,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) | |||
1568 | rdev->pm.power_state[state_index].type = | 1568 | rdev->pm.power_state[state_index].type = |
1569 | POWER_STATE_TYPE_PERFORMANCE; | 1569 | POWER_STATE_TYPE_PERFORMANCE; |
1570 | rdev->pm.power_state[state_index].flags &= | 1570 | rdev->pm.power_state[state_index].flags &= |
1571 | ~RADEON_PM_SINGLE_DISPLAY_ONLY; | 1571 | ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; |
1572 | } | 1572 | } |
1573 | if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) { | 1573 | if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) { |
1574 | rdev->pm.power_state[state_index].type = | 1574 | rdev->pm.power_state[state_index].type = |
@@ -1577,7 +1577,10 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) | |||
1577 | rdev->pm.power_state[state_index].default_clock_mode = | 1577 | rdev->pm.power_state[state_index].default_clock_mode = |
1578 | &rdev->pm.power_state[state_index].clock_info[0]; | 1578 | &rdev->pm.power_state[state_index].clock_info[0]; |
1579 | rdev->pm.power_state[state_index].flags &= | 1579 | rdev->pm.power_state[state_index].flags &= |
1580 | ~RADEON_PM_SINGLE_DISPLAY_ONLY; | 1580 | ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; |
1581 | } else if (state_index == 0) { | ||
1582 | rdev->pm.power_state[state_index].clock_info[0].flags |= | ||
1583 | RADEON_PM_MODE_NO_DISPLAY; | ||
1581 | } | 1584 | } |
1582 | state_index++; | 1585 | state_index++; |
1583 | break; | 1586 | break; |
@@ -1613,7 +1616,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) | |||
1613 | rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = | 1616 | rdev->pm.power_state[state_index].clock_info[0].voltage.vddc_id = |
1614 | power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex; | 1617 | power_info->info_2.asPowerPlayInfo[i].ucVoltageDropIndex; |
1615 | } | 1618 | } |
1616 | rdev->pm.power_state[state_index].flags = RADEON_PM_SINGLE_DISPLAY_ONLY; | 1619 | rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; |
1617 | rdev->pm.power_state[state_index].misc = misc; | 1620 | rdev->pm.power_state[state_index].misc = misc; |
1618 | rdev->pm.power_state[state_index].misc2 = misc2; | 1621 | rdev->pm.power_state[state_index].misc2 = misc2; |
1619 | /* order matters! */ | 1622 | /* order matters! */ |
@@ -1633,14 +1636,14 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) | |||
1633 | rdev->pm.power_state[state_index].type = | 1636 | rdev->pm.power_state[state_index].type = |
1634 | POWER_STATE_TYPE_PERFORMANCE; | 1637 | POWER_STATE_TYPE_PERFORMANCE; |
1635 | rdev->pm.power_state[state_index].flags &= | 1638 | rdev->pm.power_state[state_index].flags &= |
1636 | ~RADEON_PM_SINGLE_DISPLAY_ONLY; | 1639 | ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; |
1637 | } | 1640 | } |
1638 | if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE) | 1641 | if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE) |
1639 | rdev->pm.power_state[state_index].type = | 1642 | rdev->pm.power_state[state_index].type = |
1640 | POWER_STATE_TYPE_BALANCED; | 1643 | POWER_STATE_TYPE_BALANCED; |
1641 | if (misc2 & ATOM_PM_MISCINFO2_MULTI_DISPLAY_SUPPORT) | 1644 | if (misc2 & ATOM_PM_MISCINFO2_MULTI_DISPLAY_SUPPORT) |
1642 | rdev->pm.power_state[state_index].flags &= | 1645 | rdev->pm.power_state[state_index].flags &= |
1643 | ~RADEON_PM_SINGLE_DISPLAY_ONLY; | 1646 | ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; |
1644 | if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) { | 1647 | if (misc & ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE) { |
1645 | rdev->pm.power_state[state_index].type = | 1648 | rdev->pm.power_state[state_index].type = |
1646 | POWER_STATE_TYPE_DEFAULT; | 1649 | POWER_STATE_TYPE_DEFAULT; |
@@ -1648,7 +1651,10 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) | |||
1648 | rdev->pm.power_state[state_index].default_clock_mode = | 1651 | rdev->pm.power_state[state_index].default_clock_mode = |
1649 | &rdev->pm.power_state[state_index].clock_info[0]; | 1652 | &rdev->pm.power_state[state_index].clock_info[0]; |
1650 | rdev->pm.power_state[state_index].flags &= | 1653 | rdev->pm.power_state[state_index].flags &= |
1651 | ~RADEON_PM_SINGLE_DISPLAY_ONLY; | 1654 | ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; |
1655 | } else if (state_index == 0) { | ||
1656 | rdev->pm.power_state[state_index].clock_info[0].flags |= | ||
1657 | RADEON_PM_MODE_NO_DISPLAY; | ||
1652 | } | 1658 | } |
1653 | state_index++; | 1659 | state_index++; |
1654 | break; | 1660 | break; |
@@ -1690,7 +1696,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) | |||
1690 | power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex; | 1696 | power_info->info_3.asPowerPlayInfo[i].ucVDDCI_VoltageDropIndex; |
1691 | } | 1697 | } |
1692 | } | 1698 | } |
1693 | rdev->pm.power_state[state_index].flags = RADEON_PM_SINGLE_DISPLAY_ONLY; | 1699 | rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; |
1694 | rdev->pm.power_state[state_index].misc = misc; | 1700 | rdev->pm.power_state[state_index].misc = misc; |
1695 | rdev->pm.power_state[state_index].misc2 = misc2; | 1701 | rdev->pm.power_state[state_index].misc2 = misc2; |
1696 | /* order matters! */ | 1702 | /* order matters! */ |
@@ -1710,7 +1716,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) | |||
1710 | rdev->pm.power_state[state_index].type = | 1716 | rdev->pm.power_state[state_index].type = |
1711 | POWER_STATE_TYPE_PERFORMANCE; | 1717 | POWER_STATE_TYPE_PERFORMANCE; |
1712 | rdev->pm.power_state[state_index].flags &= | 1718 | rdev->pm.power_state[state_index].flags &= |
1713 | ~RADEON_PM_SINGLE_DISPLAY_ONLY; | 1719 | ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; |
1714 | } | 1720 | } |
1715 | if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE) | 1721 | if (misc2 & ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE) |
1716 | rdev->pm.power_state[state_index].type = | 1722 | rdev->pm.power_state[state_index].type = |
@@ -1721,6 +1727,9 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) | |||
1721 | rdev->pm.default_power_state_index = state_index; | 1727 | rdev->pm.default_power_state_index = state_index; |
1722 | rdev->pm.power_state[state_index].default_clock_mode = | 1728 | rdev->pm.power_state[state_index].default_clock_mode = |
1723 | &rdev->pm.power_state[state_index].clock_info[0]; | 1729 | &rdev->pm.power_state[state_index].clock_info[0]; |
1730 | } else if (state_index == 0) { | ||
1731 | rdev->pm.power_state[state_index].clock_info[0].flags |= | ||
1732 | RADEON_PM_MODE_NO_DISPLAY; | ||
1724 | } | 1733 | } |
1725 | state_index++; | 1734 | state_index++; |
1726 | break; | 1735 | break; |
@@ -1734,7 +1743,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) | |||
1734 | rdev->pm.power_state[state_index - 1].default_clock_mode = | 1743 | rdev->pm.power_state[state_index - 1].default_clock_mode = |
1735 | &rdev->pm.power_state[state_index - 1].clock_info[0]; | 1744 | &rdev->pm.power_state[state_index - 1].clock_info[0]; |
1736 | rdev->pm.power_state[state_index].flags &= | 1745 | rdev->pm.power_state[state_index].flags &= |
1737 | ~RADEON_PM_SINGLE_DISPLAY_ONLY; | 1746 | ~RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; |
1738 | rdev->pm.power_state[state_index].misc = 0; | 1747 | rdev->pm.power_state[state_index].misc = 0; |
1739 | rdev->pm.power_state[state_index].misc2 = 0; | 1748 | rdev->pm.power_state[state_index].misc2 = 0; |
1740 | } | 1749 | } |
@@ -1881,7 +1890,7 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) | |||
1881 | rdev->pm.power_state[state_index].flags = 0; | 1890 | rdev->pm.power_state[state_index].flags = 0; |
1882 | if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) | 1891 | if (misc & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) |
1883 | rdev->pm.power_state[state_index].flags |= | 1892 | rdev->pm.power_state[state_index].flags |= |
1884 | RADEON_PM_SINGLE_DISPLAY_ONLY; | 1893 | RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; |
1885 | if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) { | 1894 | if (misc2 & ATOM_PPLIB_CLASSIFICATION_BOOT) { |
1886 | rdev->pm.power_state[state_index].type = | 1895 | rdev->pm.power_state[state_index].type = |
1887 | POWER_STATE_TYPE_DEFAULT; | 1896 | POWER_STATE_TYPE_DEFAULT; |
@@ -1892,6 +1901,12 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) | |||
1892 | state_index++; | 1901 | state_index++; |
1893 | } | 1902 | } |
1894 | } | 1903 | } |
1904 | /* if multiple clock modes, mark the lowest as no display */ | ||
1905 | for (i = 0; i < state_index; i++) { | ||
1906 | if (rdev->pm.power_state[i].num_clock_modes > 1) | ||
1907 | rdev->pm.power_state[i].clock_info[0].flags |= | ||
1908 | RADEON_PM_MODE_NO_DISPLAY; | ||
1909 | } | ||
1895 | /* first mode is usually default */ | 1910 | /* first mode is usually default */ |
1896 | if (rdev->pm.default_power_state_index == -1) { | 1911 | if (rdev->pm.default_power_state_index == -1) { |
1897 | rdev->pm.power_state[0].type = | 1912 | 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 c22344b7fc58..93f18bbf744a 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c | |||
@@ -2437,7 +2437,7 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev) | |||
2437 | if (rev > 6) | 2437 | if (rev > 6) |
2438 | rdev->pm.power_state[state_index].pcie_lanes = | 2438 | rdev->pm.power_state[state_index].pcie_lanes = |
2439 | RBIOS8(offset + 0x5 + 0x10); | 2439 | RBIOS8(offset + 0x5 + 0x10); |
2440 | rdev->pm.power_state[state_index].flags = RADEON_PM_SINGLE_DISPLAY_ONLY; | 2440 | rdev->pm.power_state[state_index].flags = RADEON_PM_STATE_SINGLE_DISPLAY_ONLY; |
2441 | state_index++; | 2441 | state_index++; |
2442 | } else { | 2442 | } else { |
2443 | /* XXX figure out some good default low power mode for mobility cards w/out power tables */ | 2443 | /* 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 7701d42c4804..e1e5255396ac 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) | |||
314 | 314 | ||
315 | switch (mode) { | 315 | switch (mode) { |
316 | case DRM_MODE_DPMS_ON: | 316 | case DRM_MODE_DPMS_ON: |
317 | radeon_crtc->enabled = true; | ||
318 | /* adjust pm to dpms changes BEFORE enabling crtcs */ | ||
319 | radeon_pm_compute_clocks(rdev); | ||
317 | if (radeon_crtc->crtc_id) | 320 | if (radeon_crtc->crtc_id) |
318 | WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~(RADEON_CRTC2_EN | mask)); | 321 | WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~(RADEON_CRTC2_EN | mask)); |
319 | else { | 322 | else { |
@@ -323,7 +326,6 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
323 | } | 326 | } |
324 | drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); | 327 | drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); |
325 | radeon_crtc_load_lut(crtc); | 328 | radeon_crtc_load_lut(crtc); |
326 | radeon_crtc->enabled = true; | ||
327 | break; | 329 | break; |
328 | case DRM_MODE_DPMS_STANDBY: | 330 | case DRM_MODE_DPMS_STANDBY: |
329 | case DRM_MODE_DPMS_SUSPEND: | 331 | case DRM_MODE_DPMS_SUSPEND: |
@@ -337,11 +339,10 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
337 | WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask); | 339 | WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask); |
338 | } | 340 | } |
339 | radeon_crtc->enabled = false; | 341 | radeon_crtc->enabled = false; |
342 | /* adjust pm to dpms changes AFTER disabling crtcs */ | ||
343 | radeon_pm_compute_clocks(rdev); | ||
340 | break; | 344 | break; |
341 | } | 345 | } |
342 | |||
343 | /* adjust pm to dpms change */ | ||
344 | radeon_pm_compute_clocks(rdev); | ||
345 | } | 346 | } |
346 | 347 | ||
347 | int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, | 348 | 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 1ee7fc9918ac..0dfa508fe5f2 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) | |||
58 | { | 58 | { |
59 | int i; | 59 | int i; |
60 | 60 | ||
61 | if (!static_switch) | 61 | if (rdev->pm.state != PM_STATE_DISABLED) |
62 | radeon_get_power_state(rdev, rdev->pm.planned_action); | 62 | radeon_get_power_state(rdev, rdev->pm.planned_action); |
63 | 63 | ||
64 | mutex_lock(&rdev->ddev->struct_mutex); | 64 | mutex_lock(&rdev->ddev->struct_mutex); |
@@ -147,8 +147,11 @@ static ssize_t radeon_set_power_state_static(struct device *dev, | |||
147 | mutex_lock(&rdev->pm.mutex); | 147 | mutex_lock(&rdev->pm.mutex); |
148 | if ((ps >= 0) && (ps < rdev->pm.num_power_states) && | 148 | if ((ps >= 0) && (ps < rdev->pm.num_power_states) && |
149 | (cm >= 0) && (cm < rdev->pm.power_state[ps].num_clock_modes)) { | 149 | (cm >= 0) && (cm < rdev->pm.power_state[ps].num_clock_modes)) { |
150 | if ((rdev->pm.active_crtc_count > 1) && | 150 | if ((rdev->pm.active_crtc_count > 0) && |
151 | (rdev->pm.power_state[ps].flags & RADEON_PM_SINGLE_DISPLAY_ONLY)) { | 151 | (rdev->pm.power_state[ps].clock_info[cm].flags & RADEON_PM_MODE_NO_DISPLAY)) { |
152 | DRM_ERROR("Invalid power state for display: %d.%d\n", ps, cm); | ||
153 | } else if ((rdev->pm.active_crtc_count > 1) && | ||
154 | (rdev->pm.power_state[ps].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY)) { | ||
152 | DRM_ERROR("Invalid power state for multi-head: %d.%d\n", ps, cm); | 155 | DRM_ERROR("Invalid power state for multi-head: %d.%d\n", ps, cm); |
153 | } else { | 156 | } else { |
154 | /* disable dynpm */ | 157 | /* disable dynpm */ |
@@ -248,7 +251,7 @@ static void radeon_print_power_mode_info(struct radeon_device *rdev) | |||
248 | is_default ? "(default)" : ""); | 251 | is_default ? "(default)" : ""); |
249 | if ((rdev->flags & RADEON_IS_PCIE) && !(rdev->flags & RADEON_IS_IGP)) | 252 | if ((rdev->flags & RADEON_IS_PCIE) && !(rdev->flags & RADEON_IS_IGP)) |
250 | DRM_INFO("\t%d PCIE Lanes\n", rdev->pm.power_state[i].pcie_lanes); | 253 | DRM_INFO("\t%d PCIE Lanes\n", rdev->pm.power_state[i].pcie_lanes); |
251 | if (rdev->pm.power_state[i].flags & RADEON_PM_SINGLE_DISPLAY_ONLY) | 254 | if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) |
252 | DRM_INFO("\tSingle display only\n"); | 255 | DRM_INFO("\tSingle display only\n"); |
253 | DRM_INFO("\t%d Clock Mode(s)\n", rdev->pm.power_state[i].num_clock_modes); | 256 | DRM_INFO("\t%d Clock Mode(s)\n", rdev->pm.power_state[i].num_clock_modes); |
254 | for (j = 0; j < rdev->pm.power_state[i].num_clock_modes; j++) { | 257 | 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) | |||
261 | j, | 264 | j, |
262 | rdev->pm.power_state[i].clock_info[j].sclk * 10, | 265 | rdev->pm.power_state[i].clock_info[j].sclk * 10, |
263 | rdev->pm.power_state[i].clock_info[j].mclk * 10); | 266 | rdev->pm.power_state[i].clock_info[j].mclk * 10); |
267 | if (rdev->pm.power_state[i].clock_info[j].flags & RADEON_PM_MODE_NO_DISPLAY) | ||
268 | DRM_INFO("\t\tNo display only\n"); | ||
264 | } | 269 | } |
265 | } | 270 | } |
266 | } | 271 | } |
@@ -318,7 +323,7 @@ void radeon_pm_fini(struct radeon_device *rdev) | |||
318 | /* reset default clocks */ | 323 | /* reset default clocks */ |
319 | rdev->pm.state = PM_STATE_DISABLED; | 324 | rdev->pm.state = PM_STATE_DISABLED; |
320 | rdev->pm.planned_action = PM_ACTION_DEFAULT; | 325 | rdev->pm.planned_action = PM_ACTION_DEFAULT; |
321 | radeon_pm_set_clocks(rdev, false); | 326 | radeon_pm_set_clocks(rdev, true); |
322 | } else if ((rdev->pm.current_power_state_index != | 327 | } else if ((rdev->pm.current_power_state_index != |
323 | rdev->pm.default_power_state_index) || | 328 | rdev->pm.default_power_state_index) || |
324 | (rdev->pm.current_clock_mode_index != 0)) { | 329 | (rdev->pm.current_clock_mode_index != 0)) { |
@@ -342,9 +347,6 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev) | |||
342 | struct drm_crtc *crtc; | 347 | struct drm_crtc *crtc; |
343 | struct radeon_crtc *radeon_crtc; | 348 | struct radeon_crtc *radeon_crtc; |
344 | 349 | ||
345 | if (rdev->pm.state == PM_STATE_DISABLED) | ||
346 | return; | ||
347 | |||
348 | mutex_lock(&rdev->pm.mutex); | 350 | mutex_lock(&rdev->pm.mutex); |
349 | 351 | ||
350 | rdev->pm.active_crtcs = 0; | 352 | rdev->pm.active_crtcs = 0; |
@@ -358,13 +360,22 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev) | |||
358 | } | 360 | } |
359 | } | 361 | } |
360 | 362 | ||
363 | if (rdev->pm.state == PM_STATE_DISABLED) { | ||
364 | mutex_unlock(&rdev->pm.mutex); | ||
365 | return; | ||
366 | } | ||
367 | |||
368 | /* Note, radeon_pm_set_clocks is called with static_switch set | ||
369 | * to true since we always want to statically set the clocks, | ||
370 | * not wait for vbl. | ||
371 | */ | ||
361 | if (rdev->pm.active_crtc_count > 1) { | 372 | if (rdev->pm.active_crtc_count > 1) { |
362 | if (rdev->pm.state == PM_STATE_ACTIVE) { | 373 | if (rdev->pm.state == PM_STATE_ACTIVE) { |
363 | cancel_delayed_work(&rdev->pm.idle_work); | 374 | cancel_delayed_work(&rdev->pm.idle_work); |
364 | 375 | ||
365 | rdev->pm.state = PM_STATE_PAUSED; | 376 | rdev->pm.state = PM_STATE_PAUSED; |
366 | rdev->pm.planned_action = PM_ACTION_UPCLOCK; | 377 | rdev->pm.planned_action = PM_ACTION_DEFAULT; |
367 | radeon_pm_set_clocks(rdev, false); | 378 | radeon_pm_set_clocks(rdev, true); |
368 | 379 | ||
369 | DRM_DEBUG("radeon: dynamic power management deactivated\n"); | 380 | DRM_DEBUG("radeon: dynamic power management deactivated\n"); |
370 | } | 381 | } |
@@ -374,7 +385,7 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev) | |||
374 | if (rdev->pm.state == PM_STATE_MINIMUM) { | 385 | if (rdev->pm.state == PM_STATE_MINIMUM) { |
375 | rdev->pm.state = PM_STATE_ACTIVE; | 386 | rdev->pm.state = PM_STATE_ACTIVE; |
376 | rdev->pm.planned_action = PM_ACTION_UPCLOCK; | 387 | rdev->pm.planned_action = PM_ACTION_UPCLOCK; |
377 | radeon_pm_set_clocks(rdev, false); | 388 | radeon_pm_set_clocks(rdev, true); |
378 | 389 | ||
379 | queue_delayed_work(rdev->wq, &rdev->pm.idle_work, | 390 | queue_delayed_work(rdev->wq, &rdev->pm.idle_work, |
380 | msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); | 391 | msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); |
@@ -390,7 +401,7 @@ void radeon_pm_compute_clocks(struct radeon_device *rdev) | |||
390 | 401 | ||
391 | rdev->pm.state = PM_STATE_MINIMUM; | 402 | rdev->pm.state = PM_STATE_MINIMUM; |
392 | rdev->pm.planned_action = PM_ACTION_MINIMUM; | 403 | rdev->pm.planned_action = PM_ACTION_MINIMUM; |
393 | radeon_pm_set_clocks(rdev, false); | 404 | radeon_pm_set_clocks(rdev, true); |
394 | } | 405 | } |
395 | } | 406 | } |
396 | 407 | ||
@@ -526,6 +537,9 @@ static void radeon_pm_idle_work_handler(struct work_struct *work) | |||
526 | } | 537 | } |
527 | } | 538 | } |
528 | 539 | ||
540 | /* Note, radeon_pm_set_clocks is called with static_switch set | ||
541 | * to false since we want to wait for vbl to avoid flicker. | ||
542 | */ | ||
529 | if (rdev->pm.planned_action != PM_ACTION_NONE && | 543 | if (rdev->pm.planned_action != PM_ACTION_NONE && |
530 | jiffies > rdev->pm.action_timeout) { | 544 | jiffies > rdev->pm.action_timeout) { |
531 | radeon_pm_set_clocks(rdev, false); | 545 | radeon_pm_set_clocks(rdev, false); |