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/gpu/drm/radeon/radeon_pm.c | |
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/gpu/drm/radeon/radeon_pm.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_pm.c | 38 |
1 files changed, 26 insertions, 12 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 1ee7fc9918a..0dfa508fe5f 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); |