diff options
author | Zhenyu Wang <zhenyuw@linux.intel.com> | 2009-11-03 18:57:21 +0000 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2009-11-05 14:49:37 -0800 |
commit | c650156af34bffa3d3a62c9fe26eee595aab3fd1 (patch) | |
tree | 7b5e322e49fa39a3dd11e4dc0511188eb9ec9d91 /drivers/gpu/drm/i915/i915_irq.c | |
parent | 01c66889c14aa163c49355b3be2ccfb214500599 (diff) |
drm/i915: Add display hotplug event on Ironlake
Enable display hotplug irqs from Ibex Peak (PCH).
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_irq.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 35 |
1 files changed, 31 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index ce337be4bbc..024fb954db3 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -270,19 +270,24 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int ret = IRQ_NONE; - u32 de_iir, gt_iir; - u32 new_de_iir, new_gt_iir; + u32 de_iir, gt_iir, pch_iir; + u32 new_de_iir, new_gt_iir, new_pch_iir; struct drm_i915_master_private *master_priv; de_iir = I915_READ(DEIIR); gt_iir = I915_READ(GTIIR); + pch_iir = I915_READ(SDEIIR); for (;;) { - if (de_iir == 0 && gt_iir == 0) + if (de_iir == 0 && gt_iir == 0 && pch_iir == 0) break; ret = IRQ_HANDLED; + /* should clear PCH hotplug event before clear CPU irq */ + I915_WRITE(SDEIIR, pch_iir); + new_pch_iir = I915_READ(SDEIIR); + I915_WRITE(DEIIR, de_iir); new_de_iir = I915_READ(DEIIR); I915_WRITE(GTIIR, gt_iir); @@ -305,8 +310,15 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev) if (de_iir & DE_GSE) ironlake_opregion_gse_intr(dev); + /* check event from PCH */ + if ((de_iir & DE_PCH_EVENT) && + (pch_iir & SDE_HOTPLUG_MASK)) { + queue_work(dev_priv->wq, &dev_priv->hotplug_work); + } + de_iir = new_de_iir; gt_iir = new_gt_iir; + pch_iir = new_pch_iir; } return ret; @@ -1003,14 +1015,21 @@ static void igdng_irq_preinstall(struct drm_device *dev) I915_WRITE(GTIMR, 0xffffffff); I915_WRITE(GTIER, 0x0); (void) I915_READ(GTIER); + + /* south display irq */ + I915_WRITE(SDEIMR, 0xffffffff); + I915_WRITE(SDEIER, 0x0); + (void) I915_READ(SDEIER); } static int igdng_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; /* enable kind of interrupts always enabled */ - u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE /*| DE_PCH_EVENT */; + u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT; u32 render_mask = GT_USER_INTERRUPT; + u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG | + SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG; dev_priv->irq_mask_reg = ~display_mask; dev_priv->de_irq_enable_reg = display_mask; @@ -1030,6 +1049,14 @@ static int igdng_irq_postinstall(struct drm_device *dev) I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg); (void) I915_READ(GTIER); + dev_priv->pch_irq_mask_reg = ~hotplug_mask; + dev_priv->pch_irq_enable_reg = hotplug_mask; + + I915_WRITE(SDEIIR, I915_READ(SDEIIR)); + I915_WRITE(SDEIMR, dev_priv->pch_irq_mask_reg); + I915_WRITE(SDEIER, dev_priv->pch_irq_enable_reg); + (void) I915_READ(SDEIER); + return 0; } |