aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r100.c
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2010-04-22 12:52:11 -0400
committerDave Airlie <airlied@redhat.com>2010-05-18 04:20:49 -0400
commit2031f77ca9c17133869b265210418959a909d259 (patch)
tree21fc2aedea8f3c80c4de1d7b1168479bc7a1ce98 /drivers/gpu/drm/radeon/r100.c
parentdef9ba9cf6a8266ee1ffd72556db002c3a2663db (diff)
drm/radeon/kms: add support for gui idle interrupts (v4)
Useful for certain power management operations. You need to wait for the GUI engine (2D, 3D, CP, etc.) to be idle before changing clocks or adjusting engine parameters. (v2) Fix gui idle enable on pre-r6xx asics (v3) The gui idle interrrupt status bit is permanently asserted on pre-r6xx chips, but the interrrupt is still generated. workaround it in the driver. (v4) Add support for evergreen Signed-off-by: Alex Deucher <alexdeucher@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/r100.c')
-rw-r--r--drivers/gpu/drm/radeon/r100.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index e62116e222a0..d35298684f30 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -262,6 +262,9 @@ int r100_irq_set(struct radeon_device *rdev)
262 if (rdev->irq.sw_int) { 262 if (rdev->irq.sw_int) {
263 tmp |= RADEON_SW_INT_ENABLE; 263 tmp |= RADEON_SW_INT_ENABLE;
264 } 264 }
265 if (rdev->irq.gui_idle) {
266 tmp |= RADEON_GUI_IDLE_MASK;
267 }
265 if (rdev->irq.crtc_vblank_int[0]) { 268 if (rdev->irq.crtc_vblank_int[0]) {
266 tmp |= RADEON_CRTC_VBLANK_MASK; 269 tmp |= RADEON_CRTC_VBLANK_MASK;
267 } 270 }
@@ -296,6 +299,12 @@ static inline uint32_t r100_irq_ack(struct radeon_device *rdev)
296 RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT | 299 RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT |
297 RADEON_FP_DETECT_STAT | RADEON_FP2_DETECT_STAT; 300 RADEON_FP_DETECT_STAT | RADEON_FP2_DETECT_STAT;
298 301
302 /* the interrupt works, but the status bit is permanently asserted */
303 if (rdev->irq.gui_idle && radeon_gui_idle(rdev)) {
304 if (!rdev->irq.gui_idle_acked)
305 irq_mask |= RADEON_GUI_IDLE_STAT;
306 }
307
299 if (irqs) { 308 if (irqs) {
300 WREG32(RADEON_GEN_INT_STATUS, irqs); 309 WREG32(RADEON_GEN_INT_STATUS, irqs);
301 } 310 }
@@ -307,6 +316,9 @@ int r100_irq_process(struct radeon_device *rdev)
307 uint32_t status, msi_rearm; 316 uint32_t status, msi_rearm;
308 bool queue_hotplug = false; 317 bool queue_hotplug = false;
309 318
319 /* reset gui idle ack. the status bit is broken */
320 rdev->irq.gui_idle_acked = false;
321
310 status = r100_irq_ack(rdev); 322 status = r100_irq_ack(rdev);
311 if (!status) { 323 if (!status) {
312 return IRQ_NONE; 324 return IRQ_NONE;
@@ -319,6 +331,12 @@ int r100_irq_process(struct radeon_device *rdev)
319 if (status & RADEON_SW_INT_TEST) { 331 if (status & RADEON_SW_INT_TEST) {
320 radeon_fence_process(rdev); 332 radeon_fence_process(rdev);
321 } 333 }
334 /* gui idle interrupt */
335 if (status & RADEON_GUI_IDLE_STAT) {
336 rdev->irq.gui_idle_acked = true;
337 rdev->pm.gui_idle = true;
338 wake_up(&rdev->irq.idle_queue);
339 }
322 /* Vertical blank interrupts */ 340 /* Vertical blank interrupts */
323 if (status & RADEON_CRTC_VBLANK_STAT) { 341 if (status & RADEON_CRTC_VBLANK_STAT) {
324 drm_handle_vblank(rdev->ddev, 0); 342 drm_handle_vblank(rdev->ddev, 0);
@@ -340,6 +358,8 @@ int r100_irq_process(struct radeon_device *rdev)
340 } 358 }
341 status = r100_irq_ack(rdev); 359 status = r100_irq_ack(rdev);
342 } 360 }
361 /* reset gui idle ack. the status bit is broken */
362 rdev->irq.gui_idle_acked = false;
343 if (queue_hotplug) 363 if (queue_hotplug)
344 queue_work(rdev->wq, &rdev->hotplug_work); 364 queue_work(rdev->wq, &rdev->hotplug_work);
345 if (rdev->msi_enabled) { 365 if (rdev->msi_enabled) {