aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhenyu Wang <zhenyuw@linux.intel.com>2009-06-08 02:40:19 -0400
committerEric Anholt <eric@anholt.net>2009-06-09 14:15:27 -0400
commit036a4a7d9272582fc7370359515d807393e2f728 (patch)
tree1f6be44c18dd9823155e60d9bc53260a41b40630
parentd765898970f35acef960581f678b9da9d5c779fa (diff)
drm/i915: handle interrupt on new chipset
Update interrupt handling methods for IGDNG with new registers for display and graphics interrupt functions. As we won't use irq-based vblank sync in dri2, so display interrupt on new chip will be used for hotplug only in future. Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com> Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c2
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h5
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c5
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c186
4 files changed, 190 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 68e882cd9651..6bc716d13a52 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1162,7 +1162,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
1162 1162
1163 dev->driver->get_vblank_counter = i915_get_vblank_counter; 1163 dev->driver->get_vblank_counter = i915_get_vblank_counter;
1164 dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ 1164 dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
1165 if (IS_G4X(dev)) { 1165 if (IS_G4X(dev) || IS_IGDNG(dev)) {
1166 dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */ 1166 dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
1167 dev->driver->get_vblank_counter = gm45_get_vblank_counter; 1167 dev->driver->get_vblank_counter = gm45_get_vblank_counter;
1168 } 1168 }
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 6a471458d61a..8ef6bcec211b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -167,6 +167,11 @@ typedef struct drm_i915_private {
167 /** Cached value of IMR to avoid reads in updating the bitfield */ 167 /** Cached value of IMR to avoid reads in updating the bitfield */
168 u32 irq_mask_reg; 168 u32 irq_mask_reg;
169 u32 pipestat[2]; 169 u32 pipestat[2];
170 /** splitted irq regs for graphics and display engine on IGDNG,
171 irq_mask_reg is still used for display irq. */
172 u32 gt_irq_mask_reg;
173 u32 gt_irq_enable_reg;
174 u32 de_irq_enable_reg;
170 175
171 u32 hotplug_supported_mask; 176 u32 hotplug_supported_mask;
172 struct work_struct hotplug_work; 177 struct work_struct hotplug_work;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 3fbd8a0c40d1..38e0f8301a14 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1714,7 +1714,10 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno)
1714 BUG_ON(seqno == 0); 1714 BUG_ON(seqno == 0);
1715 1715
1716 if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) { 1716 if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
1717 ier = I915_READ(IER); 1717 if (IS_IGDNG(dev))
1718 ier = I915_READ(DEIER) | I915_READ(GTIER);
1719 else
1720 ier = I915_READ(IER);
1718 if (!ier) { 1721 if (!ier) {
1719 DRM_ERROR("something (likely vbetool) disabled " 1722 DRM_ERROR("something (likely vbetool) disabled "
1720 "interrupts, re-enabling\n"); 1723 "interrupts, re-enabling\n");
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 701d6809deb7..b86b7b7130c6 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -58,6 +58,47 @@
58 DRM_I915_VBLANK_PIPE_B) 58 DRM_I915_VBLANK_PIPE_B)
59 59
60void 60void
61igdng_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
62{
63 if ((dev_priv->gt_irq_mask_reg & mask) != 0) {
64 dev_priv->gt_irq_mask_reg &= ~mask;
65 I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
66 (void) I915_READ(GTIMR);
67 }
68}
69
70static inline void
71igdng_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
72{
73 if ((dev_priv->gt_irq_mask_reg & mask) != mask) {
74 dev_priv->gt_irq_mask_reg |= mask;
75 I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
76 (void) I915_READ(GTIMR);
77 }
78}
79
80/* For display hotplug interrupt */
81void
82igdng_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
83{
84 if ((dev_priv->irq_mask_reg & mask) != 0) {
85 dev_priv->irq_mask_reg &= ~mask;
86 I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
87 (void) I915_READ(DEIMR);
88 }
89}
90
91static inline void
92igdng_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
93{
94 if ((dev_priv->irq_mask_reg & mask) != mask) {
95 dev_priv->irq_mask_reg |= mask;
96 I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
97 (void) I915_READ(DEIMR);
98 }
99}
100
101void
61i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask) 102i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
62{ 103{
63 if ((dev_priv->irq_mask_reg & mask) != 0) { 104 if ((dev_priv->irq_mask_reg & mask) != 0) {
@@ -196,6 +237,47 @@ static void i915_hotplug_work_func(struct work_struct *work)
196 drm_sysfs_hotplug_event(dev); 237 drm_sysfs_hotplug_event(dev);
197} 238}
198 239
240irqreturn_t igdng_irq_handler(struct drm_device *dev)
241{
242 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
243 int ret = IRQ_NONE;
244 u32 de_iir, gt_iir;
245 u32 new_de_iir, new_gt_iir;
246 struct drm_i915_master_private *master_priv;
247
248 de_iir = I915_READ(DEIIR);
249 gt_iir = I915_READ(GTIIR);
250
251 for (;;) {
252 if (de_iir == 0 && gt_iir == 0)
253 break;
254
255 ret = IRQ_HANDLED;
256
257 I915_WRITE(DEIIR, de_iir);
258 new_de_iir = I915_READ(DEIIR);
259 I915_WRITE(GTIIR, gt_iir);
260 new_gt_iir = I915_READ(GTIIR);
261
262 if (dev->primary->master) {
263 master_priv = dev->primary->master->driver_priv;
264 if (master_priv->sarea_priv)
265 master_priv->sarea_priv->last_dispatch =
266 READ_BREADCRUMB(dev_priv);
267 }
268
269 if (gt_iir & GT_USER_INTERRUPT) {
270 dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
271 DRM_WAKEUP(&dev_priv->irq_queue);
272 }
273
274 de_iir = new_de_iir;
275 gt_iir = new_gt_iir;
276 }
277
278 return ret;
279}
280
199irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) 281irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
200{ 282{
201 struct drm_device *dev = (struct drm_device *) arg; 283 struct drm_device *dev = (struct drm_device *) arg;
@@ -212,6 +294,9 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
212 294
213 atomic_inc(&dev_priv->irq_received); 295 atomic_inc(&dev_priv->irq_received);
214 296
297 if (IS_IGDNG(dev))
298 return igdng_irq_handler(dev);
299
215 iir = I915_READ(IIR); 300 iir = I915_READ(IIR);
216 301
217 if (IS_I965G(dev)) { 302 if (IS_I965G(dev)) {
@@ -349,8 +434,12 @@ void i915_user_irq_get(struct drm_device *dev)
349 unsigned long irqflags; 434 unsigned long irqflags;
350 435
351 spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); 436 spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
352 if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) 437 if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) {
353 i915_enable_irq(dev_priv, I915_USER_INTERRUPT); 438 if (IS_IGDNG(dev))
439 igdng_enable_graphics_irq(dev_priv, GT_USER_INTERRUPT);
440 else
441 i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
442 }
354 spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); 443 spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
355} 444}
356 445
@@ -361,8 +450,12 @@ void i915_user_irq_put(struct drm_device *dev)
361 450
362 spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); 451 spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
363 BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0); 452 BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
364 if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) 453 if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
365 i915_disable_irq(dev_priv, I915_USER_INTERRUPT); 454 if (IS_IGDNG(dev))
455 igdng_disable_graphics_irq(dev_priv, GT_USER_INTERRUPT);
456 else
457 i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
458 }
366 spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags); 459 spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
367} 460}
368 461
@@ -455,6 +548,9 @@ int i915_enable_vblank(struct drm_device *dev, int pipe)
455 if (!(pipeconf & PIPEACONF_ENABLE)) 548 if (!(pipeconf & PIPEACONF_ENABLE))
456 return -EINVAL; 549 return -EINVAL;
457 550
551 if (IS_IGDNG(dev))
552 return 0;
553
458 spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); 554 spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
459 if (IS_I965G(dev)) 555 if (IS_I965G(dev))
460 i915_enable_pipestat(dev_priv, pipe, 556 i915_enable_pipestat(dev_priv, pipe,
@@ -474,6 +570,9 @@ void i915_disable_vblank(struct drm_device *dev, int pipe)
474 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 570 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
475 unsigned long irqflags; 571 unsigned long irqflags;
476 572
573 if (IS_IGDNG(dev))
574 return;
575
477 spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags); 576 spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
478 i915_disable_pipestat(dev_priv, pipe, 577 i915_disable_pipestat(dev_priv, pipe,
479 PIPE_VBLANK_INTERRUPT_ENABLE | 578 PIPE_VBLANK_INTERRUPT_ENABLE |
@@ -547,12 +646,65 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
547 646
548/* drm_dma.h hooks 647/* drm_dma.h hooks
549*/ 648*/
649static void igdng_irq_preinstall(struct drm_device *dev)
650{
651 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
652
653 I915_WRITE(HWSTAM, 0xeffe);
654
655 /* XXX hotplug from PCH */
656
657 I915_WRITE(DEIMR, 0xffffffff);
658 I915_WRITE(DEIER, 0x0);
659 (void) I915_READ(DEIER);
660
661 /* and GT */
662 I915_WRITE(GTIMR, 0xffffffff);
663 I915_WRITE(GTIER, 0x0);
664 (void) I915_READ(GTIER);
665}
666
667static int igdng_irq_postinstall(struct drm_device *dev)
668{
669 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
670 /* enable kind of interrupts always enabled */
671 u32 display_mask = DE_MASTER_IRQ_CONTROL /*| DE_PCH_EVENT */;
672 u32 render_mask = GT_USER_INTERRUPT;
673
674 dev_priv->irq_mask_reg = ~display_mask;
675 dev_priv->de_irq_enable_reg = display_mask;
676
677 /* should always can generate irq */
678 I915_WRITE(DEIIR, I915_READ(DEIIR));
679 I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
680 I915_WRITE(DEIER, dev_priv->de_irq_enable_reg);
681 (void) I915_READ(DEIER);
682
683 /* user interrupt should be enabled, but masked initial */
684 dev_priv->gt_irq_mask_reg = 0xffffffff;
685 dev_priv->gt_irq_enable_reg = render_mask;
686
687 I915_WRITE(GTIIR, I915_READ(GTIIR));
688 I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
689 I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg);
690 (void) I915_READ(GTIER);
691
692 return 0;
693}
694
550void i915_driver_irq_preinstall(struct drm_device * dev) 695void i915_driver_irq_preinstall(struct drm_device * dev)
551{ 696{
552 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 697 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
553 698
554 atomic_set(&dev_priv->irq_received, 0); 699 atomic_set(&dev_priv->irq_received, 0);
555 700
701 INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
702
703 if (IS_IGDNG(dev)) {
704 igdng_irq_preinstall(dev);
705 return;
706 }
707
556 if (I915_HAS_HOTPLUG(dev)) { 708 if (I915_HAS_HOTPLUG(dev)) {
557 I915_WRITE(PORT_HOTPLUG_EN, 0); 709 I915_WRITE(PORT_HOTPLUG_EN, 0);
558 I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); 710 I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
@@ -564,7 +716,6 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
564 I915_WRITE(IMR, 0xffffffff); 716 I915_WRITE(IMR, 0xffffffff);
565 I915_WRITE(IER, 0x0); 717 I915_WRITE(IER, 0x0);
566 (void) I915_READ(IER); 718 (void) I915_READ(IER);
567 INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
568} 719}
569 720
570int i915_driver_irq_postinstall(struct drm_device *dev) 721int i915_driver_irq_postinstall(struct drm_device *dev)
@@ -572,8 +723,13 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
572 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 723 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
573 u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR; 724 u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;
574 725
726 DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
727
575 dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; 728 dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;
576 729
730 if (IS_IGDNG(dev))
731 return igdng_irq_postinstall(dev);
732
577 /* Unmask the interrupts that we always want on. */ 733 /* Unmask the interrupts that we always want on. */
578 dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX; 734 dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX;
579 735
@@ -613,11 +769,24 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
613 (void) I915_READ(IER); 769 (void) I915_READ(IER);
614 770
615 opregion_enable_asle(dev); 771 opregion_enable_asle(dev);
616 DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
617 772
618 return 0; 773 return 0;
619} 774}
620 775
776static void igdng_irq_uninstall(struct drm_device *dev)
777{
778 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
779 I915_WRITE(HWSTAM, 0xffffffff);
780
781 I915_WRITE(DEIMR, 0xffffffff);
782 I915_WRITE(DEIER, 0x0);
783 I915_WRITE(DEIIR, I915_READ(DEIIR));
784
785 I915_WRITE(GTIMR, 0xffffffff);
786 I915_WRITE(GTIER, 0x0);
787 I915_WRITE(GTIIR, I915_READ(GTIIR));
788}
789
621void i915_driver_irq_uninstall(struct drm_device * dev) 790void i915_driver_irq_uninstall(struct drm_device * dev)
622{ 791{
623 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 792 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -627,6 +796,11 @@ void i915_driver_irq_uninstall(struct drm_device * dev)
627 796
628 dev_priv->vblank_pipe = 0; 797 dev_priv->vblank_pipe = 0;
629 798
799 if (IS_IGDNG(dev)) {
800 igdng_irq_uninstall(dev);
801 return;
802 }
803
630 if (I915_HAS_HOTPLUG(dev)) { 804 if (I915_HAS_HOTPLUG(dev)) {
631 I915_WRITE(PORT_HOTPLUG_EN, 0); 805 I915_WRITE(PORT_HOTPLUG_EN, 0);
632 I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); 806 I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));