diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2011-01-04 18:09:39 -0500 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-01-11 15:44:01 -0500 |
commit | 776ad8062bb77697b8728a9794e3a394b28cf885 (patch) | |
tree | 049e99bbdb92533dce7c528bc435ed864e4f1132 /drivers/gpu | |
parent | d5bb081b027b520f9e59b4fb8faea83a136ec15e (diff) |
drm/i915: detect & report PCH display error interrupts
FDI and the transcoders can fail for various reasons, so detect those
conditions and report on them.
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 54 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 29 |
2 files changed, 81 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index c9adcdd6ad6a..d431fc4fb84b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -398,6 +398,50 @@ static void gen6_pm_irq_handler(struct drm_device *dev) | |||
398 | I915_WRITE(GEN6_PMIIR, pm_iir); | 398 | I915_WRITE(GEN6_PMIIR, pm_iir); |
399 | } | 399 | } |
400 | 400 | ||
401 | static void pch_irq_handler(struct drm_device *dev) | ||
402 | { | ||
403 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
404 | u32 pch_iir; | ||
405 | |||
406 | pch_iir = I915_READ(SDEIIR); | ||
407 | |||
408 | if (pch_iir & SDE_AUDIO_POWER_MASK) | ||
409 | DRM_DEBUG_DRIVER("PCH audio power change on port %d\n", | ||
410 | (pch_iir & SDE_AUDIO_POWER_MASK) >> | ||
411 | SDE_AUDIO_POWER_SHIFT); | ||
412 | |||
413 | if (pch_iir & SDE_GMBUS) | ||
414 | DRM_DEBUG_DRIVER("PCH GMBUS interrupt\n"); | ||
415 | |||
416 | if (pch_iir & SDE_AUDIO_HDCP_MASK) | ||
417 | DRM_DEBUG_DRIVER("PCH HDCP audio interrupt\n"); | ||
418 | |||
419 | if (pch_iir & SDE_AUDIO_TRANS_MASK) | ||
420 | DRM_DEBUG_DRIVER("PCH transcoder audio interrupt\n"); | ||
421 | |||
422 | if (pch_iir & SDE_POISON) | ||
423 | DRM_ERROR("PCH poison interrupt\n"); | ||
424 | |||
425 | if (pch_iir & SDE_FDI_MASK) { | ||
426 | u32 fdia, fdib; | ||
427 | |||
428 | fdia = I915_READ(FDI_RXA_IIR); | ||
429 | fdib = I915_READ(FDI_RXB_IIR); | ||
430 | DRM_DEBUG_DRIVER("PCH FDI RX interrupt; FDI RXA IIR: 0x%08x, FDI RXB IIR: 0x%08x\n", fdia, fdib); | ||
431 | } | ||
432 | |||
433 | if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE)) | ||
434 | DRM_DEBUG_DRIVER("PCH transcoder CRC done interrupt\n"); | ||
435 | |||
436 | if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR)) | ||
437 | DRM_DEBUG_DRIVER("PCH transcoder CRC error interrupt\n"); | ||
438 | |||
439 | if (pch_iir & SDE_TRANSB_FIFO_UNDER) | ||
440 | DRM_DEBUG_DRIVER("PCH transcoder B underrun interrupt\n"); | ||
441 | if (pch_iir & SDE_TRANSA_FIFO_UNDER) | ||
442 | DRM_DEBUG_DRIVER("PCH transcoder A underrun interrupt\n"); | ||
443 | } | ||
444 | |||
401 | static irqreturn_t ironlake_irq_handler(struct drm_device *dev) | 445 | static irqreturn_t ironlake_irq_handler(struct drm_device *dev) |
402 | { | 446 | { |
403 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 447 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
@@ -465,8 +509,11 @@ static irqreturn_t ironlake_irq_handler(struct drm_device *dev) | |||
465 | drm_handle_vblank(dev, 1); | 509 | drm_handle_vblank(dev, 1); |
466 | 510 | ||
467 | /* check event from PCH */ | 511 | /* check event from PCH */ |
468 | if ((de_iir & DE_PCH_EVENT) && (pch_iir & hotplug_mask)) | 512 | if (de_iir & DE_PCH_EVENT) { |
469 | queue_work(dev_priv->wq, &dev_priv->hotplug_work); | 513 | if (pch_iir & hotplug_mask) |
514 | queue_work(dev_priv->wq, &dev_priv->hotplug_work); | ||
515 | pch_irq_handler(dev); | ||
516 | } | ||
470 | 517 | ||
471 | if (de_iir & DE_PCU_EVENT) { | 518 | if (de_iir & DE_PCU_EVENT) { |
472 | I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS)); | 519 | I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS)); |
@@ -1656,6 +1703,9 @@ static int ironlake_irq_postinstall(struct drm_device *dev) | |||
1656 | } else { | 1703 | } else { |
1657 | hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG | | 1704 | hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG | |
1658 | SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG; | 1705 | SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG; |
1706 | hotplug_mask |= SDE_AUX_MASK | SDE_FDI_MASK | SDE_TRANS_MASK; | ||
1707 | I915_WRITE(FDI_RXA_IMR, 0); | ||
1708 | I915_WRITE(FDI_RXB_IMR, 0); | ||
1659 | } | 1709 | } |
1660 | 1710 | ||
1661 | dev_priv->pch_irq_mask = ~hotplug_mask; | 1711 | dev_priv->pch_irq_mask = ~hotplug_mask; |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 33ddf3120f2f..40a407f41f61 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -2778,12 +2778,41 @@ | |||
2778 | /* PCH */ | 2778 | /* PCH */ |
2779 | 2779 | ||
2780 | /* south display engine interrupt */ | 2780 | /* south display engine interrupt */ |
2781 | #define SDE_AUDIO_POWER_D (1 << 27) | ||
2782 | #define SDE_AUDIO_POWER_C (1 << 26) | ||
2783 | #define SDE_AUDIO_POWER_B (1 << 25) | ||
2784 | #define SDE_AUDIO_POWER_SHIFT (25) | ||
2785 | #define SDE_AUDIO_POWER_MASK (7 << SDE_AUDIO_POWER_SHIFT) | ||
2786 | #define SDE_GMBUS (1 << 24) | ||
2787 | #define SDE_AUDIO_HDCP_TRANSB (1 << 23) | ||
2788 | #define SDE_AUDIO_HDCP_TRANSA (1 << 22) | ||
2789 | #define SDE_AUDIO_HDCP_MASK (3 << 22) | ||
2790 | #define SDE_AUDIO_TRANSB (1 << 21) | ||
2791 | #define SDE_AUDIO_TRANSA (1 << 20) | ||
2792 | #define SDE_AUDIO_TRANS_MASK (3 << 20) | ||
2793 | #define SDE_POISON (1 << 19) | ||
2794 | /* 18 reserved */ | ||
2795 | #define SDE_FDI_RXB (1 << 17) | ||
2796 | #define SDE_FDI_RXA (1 << 16) | ||
2797 | #define SDE_FDI_MASK (3 << 16) | ||
2798 | #define SDE_AUXD (1 << 15) | ||
2799 | #define SDE_AUXC (1 << 14) | ||
2800 | #define SDE_AUXB (1 << 13) | ||
2801 | #define SDE_AUX_MASK (7 << 13) | ||
2802 | /* 12 reserved */ | ||
2781 | #define SDE_CRT_HOTPLUG (1 << 11) | 2803 | #define SDE_CRT_HOTPLUG (1 << 11) |
2782 | #define SDE_PORTD_HOTPLUG (1 << 10) | 2804 | #define SDE_PORTD_HOTPLUG (1 << 10) |
2783 | #define SDE_PORTC_HOTPLUG (1 << 9) | 2805 | #define SDE_PORTC_HOTPLUG (1 << 9) |
2784 | #define SDE_PORTB_HOTPLUG (1 << 8) | 2806 | #define SDE_PORTB_HOTPLUG (1 << 8) |
2785 | #define SDE_SDVOB_HOTPLUG (1 << 6) | 2807 | #define SDE_SDVOB_HOTPLUG (1 << 6) |
2786 | #define SDE_HOTPLUG_MASK (0xf << 8) | 2808 | #define SDE_HOTPLUG_MASK (0xf << 8) |
2809 | #define SDE_TRANSB_CRC_DONE (1 << 5) | ||
2810 | #define SDE_TRANSB_CRC_ERR (1 << 4) | ||
2811 | #define SDE_TRANSB_FIFO_UNDER (1 << 3) | ||
2812 | #define SDE_TRANSA_CRC_DONE (1 << 2) | ||
2813 | #define SDE_TRANSA_CRC_ERR (1 << 1) | ||
2814 | #define SDE_TRANSA_FIFO_UNDER (1 << 0) | ||
2815 | #define SDE_TRANS_MASK (0x3f) | ||
2787 | /* CPT */ | 2816 | /* CPT */ |
2788 | #define SDE_CRT_HOTPLUG_CPT (1 << 19) | 2817 | #define SDE_CRT_HOTPLUG_CPT (1 << 19) |
2789 | #define SDE_PORTD_HOTPLUG_CPT (1 << 23) | 2818 | #define SDE_PORTD_HOTPLUG_CPT (1 << 23) |