Commit 776ad806 authored by Jesse Barnes's avatar Jesse Barnes Committed by Chris Wilson

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: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
parent d5bb081b
...@@ -398,6 +398,50 @@ static void gen6_pm_irq_handler(struct drm_device *dev) ...@@ -398,6 +398,50 @@ static void gen6_pm_irq_handler(struct drm_device *dev)
I915_WRITE(GEN6_PMIIR, pm_iir); I915_WRITE(GEN6_PMIIR, pm_iir);
} }
static void pch_irq_handler(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
u32 pch_iir;
pch_iir = I915_READ(SDEIIR);
if (pch_iir & SDE_AUDIO_POWER_MASK)
DRM_DEBUG_DRIVER("PCH audio power change on port %d\n",
(pch_iir & SDE_AUDIO_POWER_MASK) >>
SDE_AUDIO_POWER_SHIFT);
if (pch_iir & SDE_GMBUS)
DRM_DEBUG_DRIVER("PCH GMBUS interrupt\n");
if (pch_iir & SDE_AUDIO_HDCP_MASK)
DRM_DEBUG_DRIVER("PCH HDCP audio interrupt\n");
if (pch_iir & SDE_AUDIO_TRANS_MASK)
DRM_DEBUG_DRIVER("PCH transcoder audio interrupt\n");
if (pch_iir & SDE_POISON)
DRM_ERROR("PCH poison interrupt\n");
if (pch_iir & SDE_FDI_MASK) {
u32 fdia, fdib;
fdia = I915_READ(FDI_RXA_IIR);
fdib = I915_READ(FDI_RXB_IIR);
DRM_DEBUG_DRIVER("PCH FDI RX interrupt; FDI RXA IIR: 0x%08x, FDI RXB IIR: 0x%08x\n", fdia, fdib);
}
if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE))
DRM_DEBUG_DRIVER("PCH transcoder CRC done interrupt\n");
if (pch_iir & (SDE_TRANSB_CRC_ERR | SDE_TRANSA_CRC_ERR))
DRM_DEBUG_DRIVER("PCH transcoder CRC error interrupt\n");
if (pch_iir & SDE_TRANSB_FIFO_UNDER)
DRM_DEBUG_DRIVER("PCH transcoder B underrun interrupt\n");
if (pch_iir & SDE_TRANSA_FIFO_UNDER)
DRM_DEBUG_DRIVER("PCH transcoder A underrun interrupt\n");
}
static irqreturn_t ironlake_irq_handler(struct drm_device *dev) static irqreturn_t ironlake_irq_handler(struct drm_device *dev)
{ {
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 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,8 +509,11 @@ static irqreturn_t ironlake_irq_handler(struct drm_device *dev)
drm_handle_vblank(dev, 1); drm_handle_vblank(dev, 1);
/* check event from PCH */ /* check event from PCH */
if ((de_iir & DE_PCH_EVENT) && (pch_iir & hotplug_mask)) if (de_iir & DE_PCH_EVENT) {
queue_work(dev_priv->wq, &dev_priv->hotplug_work); if (pch_iir & hotplug_mask)
queue_work(dev_priv->wq, &dev_priv->hotplug_work);
pch_irq_handler(dev);
}
if (de_iir & DE_PCU_EVENT) { if (de_iir & DE_PCU_EVENT) {
I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS)); I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS));
...@@ -1656,6 +1703,9 @@ static int ironlake_irq_postinstall(struct drm_device *dev) ...@@ -1656,6 +1703,9 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
} else { } else {
hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG | hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG |
SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG; SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG;
hotplug_mask |= SDE_AUX_MASK | SDE_FDI_MASK | SDE_TRANS_MASK;
I915_WRITE(FDI_RXA_IMR, 0);
I915_WRITE(FDI_RXB_IMR, 0);
} }
dev_priv->pch_irq_mask = ~hotplug_mask; dev_priv->pch_irq_mask = ~hotplug_mask;
......
...@@ -2778,12 +2778,41 @@ ...@@ -2778,12 +2778,41 @@
/* PCH */ /* PCH */
/* south display engine interrupt */ /* south display engine interrupt */
#define SDE_AUDIO_POWER_D (1 << 27)
#define SDE_AUDIO_POWER_C (1 << 26)
#define SDE_AUDIO_POWER_B (1 << 25)
#define SDE_AUDIO_POWER_SHIFT (25)
#define SDE_AUDIO_POWER_MASK (7 << SDE_AUDIO_POWER_SHIFT)
#define SDE_GMBUS (1 << 24)
#define SDE_AUDIO_HDCP_TRANSB (1 << 23)
#define SDE_AUDIO_HDCP_TRANSA (1 << 22)
#define SDE_AUDIO_HDCP_MASK (3 << 22)
#define SDE_AUDIO_TRANSB (1 << 21)
#define SDE_AUDIO_TRANSA (1 << 20)
#define SDE_AUDIO_TRANS_MASK (3 << 20)
#define SDE_POISON (1 << 19)
/* 18 reserved */
#define SDE_FDI_RXB (1 << 17)
#define SDE_FDI_RXA (1 << 16)
#define SDE_FDI_MASK (3 << 16)
#define SDE_AUXD (1 << 15)
#define SDE_AUXC (1 << 14)
#define SDE_AUXB (1 << 13)
#define SDE_AUX_MASK (7 << 13)
/* 12 reserved */
#define SDE_CRT_HOTPLUG (1 << 11) #define SDE_CRT_HOTPLUG (1 << 11)
#define SDE_PORTD_HOTPLUG (1 << 10) #define SDE_PORTD_HOTPLUG (1 << 10)
#define SDE_PORTC_HOTPLUG (1 << 9) #define SDE_PORTC_HOTPLUG (1 << 9)
#define SDE_PORTB_HOTPLUG (1 << 8) #define SDE_PORTB_HOTPLUG (1 << 8)
#define SDE_SDVOB_HOTPLUG (1 << 6) #define SDE_SDVOB_HOTPLUG (1 << 6)
#define SDE_HOTPLUG_MASK (0xf << 8) #define SDE_HOTPLUG_MASK (0xf << 8)
#define SDE_TRANSB_CRC_DONE (1 << 5)
#define SDE_TRANSB_CRC_ERR (1 << 4)
#define SDE_TRANSB_FIFO_UNDER (1 << 3)
#define SDE_TRANSA_CRC_DONE (1 << 2)
#define SDE_TRANSA_CRC_ERR (1 << 1)
#define SDE_TRANSA_FIFO_UNDER (1 << 0)
#define SDE_TRANS_MASK (0x3f)
/* CPT */ /* CPT */
#define SDE_CRT_HOTPLUG_CPT (1 << 19) #define SDE_CRT_HOTPLUG_CPT (1 << 19)
#define SDE_PORTD_HOTPLUG_CPT (1 << 23) #define SDE_PORTD_HOTPLUG_CPT (1 << 23)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment