Commit c650156a authored by Zhenyu Wang's avatar Zhenyu Wang Committed by Eric Anholt

drm/i915: Add display hotplug event on Ironlake

Enable display hotplug irqs from Ibex Peak (PCH).
Signed-off-by: default avatarZhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: default avatarEric Anholt <eric@anholt.net>
parent 01c66889
...@@ -214,6 +214,8 @@ typedef struct drm_i915_private { ...@@ -214,6 +214,8 @@ typedef struct drm_i915_private {
u32 gt_irq_mask_reg; u32 gt_irq_mask_reg;
u32 gt_irq_enable_reg; u32 gt_irq_enable_reg;
u32 de_irq_enable_reg; u32 de_irq_enable_reg;
u32 pch_irq_mask_reg;
u32 pch_irq_enable_reg;
u32 hotplug_supported_mask; u32 hotplug_supported_mask;
struct work_struct hotplug_work; struct work_struct hotplug_work;
......
...@@ -270,19 +270,24 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev) ...@@ -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; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
int ret = IRQ_NONE; int ret = IRQ_NONE;
u32 de_iir, gt_iir; u32 de_iir, gt_iir, pch_iir;
u32 new_de_iir, new_gt_iir; u32 new_de_iir, new_gt_iir, new_pch_iir;
struct drm_i915_master_private *master_priv; struct drm_i915_master_private *master_priv;
de_iir = I915_READ(DEIIR); de_iir = I915_READ(DEIIR);
gt_iir = I915_READ(GTIIR); gt_iir = I915_READ(GTIIR);
pch_iir = I915_READ(SDEIIR);
for (;;) { for (;;) {
if (de_iir == 0 && gt_iir == 0) if (de_iir == 0 && gt_iir == 0 && pch_iir == 0)
break; break;
ret = IRQ_HANDLED; 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); I915_WRITE(DEIIR, de_iir);
new_de_iir = I915_READ(DEIIR); new_de_iir = I915_READ(DEIIR);
I915_WRITE(GTIIR, gt_iir); I915_WRITE(GTIIR, gt_iir);
...@@ -305,8 +310,15 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev) ...@@ -305,8 +310,15 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev)
if (de_iir & DE_GSE) if (de_iir & DE_GSE)
ironlake_opregion_gse_intr(dev); 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; de_iir = new_de_iir;
gt_iir = new_gt_iir; gt_iir = new_gt_iir;
pch_iir = new_pch_iir;
} }
return ret; return ret;
...@@ -1003,14 +1015,21 @@ static void igdng_irq_preinstall(struct drm_device *dev) ...@@ -1003,14 +1015,21 @@ static void igdng_irq_preinstall(struct drm_device *dev)
I915_WRITE(GTIMR, 0xffffffff); I915_WRITE(GTIMR, 0xffffffff);
I915_WRITE(GTIER, 0x0); I915_WRITE(GTIER, 0x0);
(void) I915_READ(GTIER); (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) static int igdng_irq_postinstall(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;
/* enable kind of interrupts always enabled */ /* 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 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->irq_mask_reg = ~display_mask;
dev_priv->de_irq_enable_reg = display_mask; dev_priv->de_irq_enable_reg = display_mask;
...@@ -1030,6 +1049,14 @@ static int igdng_irq_postinstall(struct drm_device *dev) ...@@ -1030,6 +1049,14 @@ static int igdng_irq_postinstall(struct drm_device *dev)
I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg); I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg);
(void) I915_READ(GTIER); (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; return 0;
} }
......
...@@ -2126,6 +2126,7 @@ ...@@ -2126,6 +2126,7 @@
#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 SDEISR 0xc4000 #define SDEISR 0xc4000
#define SDEIMR 0xc4004 #define SDEIMR 0xc4004
......
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