diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/rs600.c')
-rw-r--r-- | drivers/gpu/drm/radeon/rs600.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 5e3f21861f45..b312b72d76ce 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c | |||
@@ -382,6 +382,9 @@ int rs600_irq_set(struct radeon_device *rdev) | |||
382 | if (rdev->irq.sw_int) { | 382 | if (rdev->irq.sw_int) { |
383 | tmp |= S_000040_SW_INT_EN(1); | 383 | tmp |= S_000040_SW_INT_EN(1); |
384 | } | 384 | } |
385 | if (rdev->irq.gui_idle) { | ||
386 | tmp |= S_000040_GUI_IDLE(1); | ||
387 | } | ||
385 | if (rdev->irq.crtc_vblank_int[0]) { | 388 | if (rdev->irq.crtc_vblank_int[0]) { |
386 | mode_int |= S_006540_D1MODE_VBLANK_INT_MASK(1); | 389 | mode_int |= S_006540_D1MODE_VBLANK_INT_MASK(1); |
387 | } | 390 | } |
@@ -404,9 +407,15 @@ int rs600_irq_set(struct radeon_device *rdev) | |||
404 | static inline uint32_t rs600_irq_ack(struct radeon_device *rdev, u32 *r500_disp_int) | 407 | static inline uint32_t rs600_irq_ack(struct radeon_device *rdev, u32 *r500_disp_int) |
405 | { | 408 | { |
406 | uint32_t irqs = RREG32(R_000044_GEN_INT_STATUS); | 409 | uint32_t irqs = RREG32(R_000044_GEN_INT_STATUS); |
407 | uint32_t irq_mask = ~C_000044_SW_INT; | 410 | uint32_t irq_mask = S_000044_SW_INT(1); |
408 | u32 tmp; | 411 | u32 tmp; |
409 | 412 | ||
413 | /* the interrupt works, but the status bit is permanently asserted */ | ||
414 | if (rdev->irq.gui_idle && radeon_gui_idle(rdev)) { | ||
415 | if (!rdev->irq.gui_idle_acked) | ||
416 | irq_mask |= S_000044_GUI_IDLE_STAT(1); | ||
417 | } | ||
418 | |||
410 | if (G_000044_DISPLAY_INT_STAT(irqs)) { | 419 | if (G_000044_DISPLAY_INT_STAT(irqs)) { |
411 | *r500_disp_int = RREG32(R_007EDC_DISP_INTERRUPT_STATUS); | 420 | *r500_disp_int = RREG32(R_007EDC_DISP_INTERRUPT_STATUS); |
412 | if (G_007EDC_LB_D1_VBLANK_INTERRUPT(*r500_disp_int)) { | 421 | if (G_007EDC_LB_D1_VBLANK_INTERRUPT(*r500_disp_int)) { |
@@ -454,6 +463,9 @@ int rs600_irq_process(struct radeon_device *rdev) | |||
454 | uint32_t r500_disp_int; | 463 | uint32_t r500_disp_int; |
455 | bool queue_hotplug = false; | 464 | bool queue_hotplug = false; |
456 | 465 | ||
466 | /* reset gui idle ack. the status bit is broken */ | ||
467 | rdev->irq.gui_idle_acked = false; | ||
468 | |||
457 | status = rs600_irq_ack(rdev, &r500_disp_int); | 469 | status = rs600_irq_ack(rdev, &r500_disp_int); |
458 | if (!status && !r500_disp_int) { | 470 | if (!status && !r500_disp_int) { |
459 | return IRQ_NONE; | 471 | return IRQ_NONE; |
@@ -462,6 +474,12 @@ int rs600_irq_process(struct radeon_device *rdev) | |||
462 | /* SW interrupt */ | 474 | /* SW interrupt */ |
463 | if (G_000044_SW_INT(status)) | 475 | if (G_000044_SW_INT(status)) |
464 | radeon_fence_process(rdev); | 476 | radeon_fence_process(rdev); |
477 | /* GUI idle */ | ||
478 | if (G_000040_GUI_IDLE(status)) { | ||
479 | rdev->irq.gui_idle_acked = true; | ||
480 | rdev->pm.gui_idle = true; | ||
481 | wake_up(&rdev->irq.idle_queue); | ||
482 | } | ||
465 | /* Vertical blank interrupts */ | 483 | /* Vertical blank interrupts */ |
466 | if (G_007EDC_LB_D1_VBLANK_INTERRUPT(r500_disp_int)) { | 484 | if (G_007EDC_LB_D1_VBLANK_INTERRUPT(r500_disp_int)) { |
467 | drm_handle_vblank(rdev->ddev, 0); | 485 | drm_handle_vblank(rdev->ddev, 0); |
@@ -483,6 +501,8 @@ int rs600_irq_process(struct radeon_device *rdev) | |||
483 | } | 501 | } |
484 | status = rs600_irq_ack(rdev, &r500_disp_int); | 502 | status = rs600_irq_ack(rdev, &r500_disp_int); |
485 | } | 503 | } |
504 | /* reset gui idle ack. the status bit is broken */ | ||
505 | rdev->irq.gui_idle_acked = false; | ||
486 | if (queue_hotplug) | 506 | if (queue_hotplug) |
487 | queue_work(rdev->wq, &rdev->hotplug_work); | 507 | queue_work(rdev->wq, &rdev->hotplug_work); |
488 | if (rdev->msi_enabled) { | 508 | if (rdev->msi_enabled) { |