aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915
diff options
context:
space:
mode:
authorZhenyu Wang <zhenyuw@linux.intel.com>2009-11-03 13:57:21 -0500
committerEric Anholt <eric@anholt.net>2009-11-05 17:49:37 -0500
commitc650156af34bffa3d3a62c9fe26eee595aab3fd1 (patch)
tree7b5e322e49fa39a3dd11e4dc0511188eb9ec9d91 /drivers/gpu/drm/i915
parent01c66889c14aa163c49355b3be2ccfb214500599 (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')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h2
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c35
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h1
3 files changed, 34 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 210d0f690dbb..835625ba7c9c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -214,6 +214,8 @@ typedef struct drm_i915_private {
214 u32 gt_irq_mask_reg; 214 u32 gt_irq_mask_reg;
215 u32 gt_irq_enable_reg; 215 u32 gt_irq_enable_reg;
216 u32 de_irq_enable_reg; 216 u32 de_irq_enable_reg;
217 u32 pch_irq_mask_reg;
218 u32 pch_irq_enable_reg;
217 219
218 u32 hotplug_supported_mask; 220 u32 hotplug_supported_mask;
219 struct work_struct hotplug_work; 221 struct work_struct hotplug_work;
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index ce337be4bbcd..024fb954db37 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)
270{ 270{
271 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 271 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
272 int ret = IRQ_NONE; 272 int ret = IRQ_NONE;
273 u32 de_iir, gt_iir; 273 u32 de_iir, gt_iir, pch_iir;
274 u32 new_de_iir, new_gt_iir; 274 u32 new_de_iir, new_gt_iir, new_pch_iir;
275 struct drm_i915_master_private *master_priv; 275 struct drm_i915_master_private *master_priv;
276 276
277 de_iir = I915_READ(DEIIR); 277 de_iir = I915_READ(DEIIR);
278 gt_iir = I915_READ(GTIIR); 278 gt_iir = I915_READ(GTIIR);
279 pch_iir = I915_READ(SDEIIR);
279 280
280 for (;;) { 281 for (;;) {
281 if (de_iir == 0 && gt_iir == 0) 282 if (de_iir == 0 && gt_iir == 0 && pch_iir == 0)
282 break; 283 break;
283 284
284 ret = IRQ_HANDLED; 285 ret = IRQ_HANDLED;
285 286
287 /* should clear PCH hotplug event before clear CPU irq */
288 I915_WRITE(SDEIIR, pch_iir);
289 new_pch_iir = I915_READ(SDEIIR);
290
286 I915_WRITE(DEIIR, de_iir); 291 I915_WRITE(DEIIR, de_iir);
287 new_de_iir = I915_READ(DEIIR); 292 new_de_iir = I915_READ(DEIIR);
288 I915_WRITE(GTIIR, gt_iir); 293 I915_WRITE(GTIIR, gt_iir);
@@ -305,8 +310,15 @@ irqreturn_t igdng_irq_handler(struct drm_device *dev)
305 if (de_iir & DE_GSE) 310 if (de_iir & DE_GSE)
306 ironlake_opregion_gse_intr(dev); 311 ironlake_opregion_gse_intr(dev);
307 312
313 /* check event from PCH */
314 if ((de_iir & DE_PCH_EVENT) &&
315 (pch_iir & SDE_HOTPLUG_MASK)) {
316 queue_work(dev_priv->wq, &dev_priv->hotplug_work);
317 }
318
308 de_iir = new_de_iir; 319 de_iir = new_de_iir;
309 gt_iir = new_gt_iir; 320 gt_iir = new_gt_iir;
321 pch_iir = new_pch_iir;
310 } 322 }
311 323
312 return ret; 324 return ret;
@@ -1003,14 +1015,21 @@ static void igdng_irq_preinstall(struct drm_device *dev)
1003 I915_WRITE(GTIMR, 0xffffffff); 1015 I915_WRITE(GTIMR, 0xffffffff);
1004 I915_WRITE(GTIER, 0x0); 1016 I915_WRITE(GTIER, 0x0);
1005 (void) I915_READ(GTIER); 1017 (void) I915_READ(GTIER);
1018
1019 /* south display irq */
1020 I915_WRITE(SDEIMR, 0xffffffff);
1021 I915_WRITE(SDEIER, 0x0);
1022 (void) I915_READ(SDEIER);
1006} 1023}
1007 1024
1008static int igdng_irq_postinstall(struct drm_device *dev) 1025static int igdng_irq_postinstall(struct drm_device *dev)
1009{ 1026{
1010 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 1027 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
1011 /* enable kind of interrupts always enabled */ 1028 /* enable kind of interrupts always enabled */
1012 u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE /*| DE_PCH_EVENT */; 1029 u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT;
1013 u32 render_mask = GT_USER_INTERRUPT; 1030 u32 render_mask = GT_USER_INTERRUPT;
1031 u32 hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG |
1032 SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG;
1014 1033
1015 dev_priv->irq_mask_reg = ~display_mask; 1034 dev_priv->irq_mask_reg = ~display_mask;
1016 dev_priv->de_irq_enable_reg = display_mask; 1035 dev_priv->de_irq_enable_reg = display_mask;
@@ -1030,6 +1049,14 @@ static int igdng_irq_postinstall(struct drm_device *dev)
1030 I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg); 1049 I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg);
1031 (void) I915_READ(GTIER); 1050 (void) I915_READ(GTIER);
1032 1051
1052 dev_priv->pch_irq_mask_reg = ~hotplug_mask;
1053 dev_priv->pch_irq_enable_reg = hotplug_mask;
1054
1055 I915_WRITE(SDEIIR, I915_READ(SDEIIR));
1056 I915_WRITE(SDEIMR, dev_priv->pch_irq_mask_reg);
1057 I915_WRITE(SDEIER, dev_priv->pch_irq_enable_reg);
1058 (void) I915_READ(SDEIER);
1059
1033 return 0; 1060 return 0;
1034} 1061}
1035 1062
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index e8c6d00cde97..b11a682a4cff 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2126,6 +2126,7 @@
2126#define SDE_PORTC_HOTPLUG (1 << 9) 2126#define SDE_PORTC_HOTPLUG (1 << 9)
2127#define SDE_PORTB_HOTPLUG (1 << 8) 2127#define SDE_PORTB_HOTPLUG (1 << 8)
2128#define SDE_SDVOB_HOTPLUG (1 << 6) 2128#define SDE_SDVOB_HOTPLUG (1 << 6)
2129#define SDE_HOTPLUG_MASK (0xf << 8)
2129 2130
2130#define SDEISR 0xc4000 2131#define SDEISR 0xc4000
2131#define SDEIMR 0xc4004 2132#define SDEIMR 0xc4004