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); |
