[PATCH] i915: make vbl interrupts work properly on i965g/gm

From: Dave Airlie
Date: Thu Sep 27 2007 - 22:05:55 EST



Hi Linus,

The attached patch is to fix a bug reported on 965gm chipsets (lots of new laptops), I think distros will all have to patch this in to fix it, so can we get it into the 2.6.23 final?

(Otherwise I'll wait until stable..)

Dave.From 14e53712e5e2ccc72dac1131de78e590e9a9d451 Mon Sep 17 00:00:00 2001
From: Dave Airlie <airlied@xxxxxxxx>
Date: Fri, 28 Sep 2007 11:46:28 +1000
Subject: [PATCH] i915: make vbl interrupts work properly on i965g/gm hw.

This code is ported from the DRM git tree and allows the vblank interrupts
to function on the i965 hw. It also requires a change in Mesa's 965 driver
to actually use them.

Signed-off-by: Dave Airlie <airlied@xxxxxxxx>
---
drivers/char/drm/i915_drv.h | 6 ++++++
drivers/char/drm/i915_irq.c | 12 ++++++++++++
2 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index 737088b..28b9873 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -210,6 +210,12 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define I915REG_INT_MASK_R 0x020a8
#define I915REG_INT_ENABLE_R 0x020a0

+#define I915REG_PIPEASTAT 0x70024
+#define I915REG_PIPEBSTAT 0x71024
+
+#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17)
+#define I915_VBLANK_CLEAR (1UL<<1)
+
#define SRX_INDEX 0x3c4
#define SRX_DATA 0x3c5
#define SR01 1
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index 4b4b2ce..bb8e9e9 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -214,6 +214,10 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
struct drm_device *dev = (struct drm_device *) arg;
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
u16 temp;
+ u32 pipea_stats, pipeb_stats;
+
+ pipea_stats = I915_READ(I915REG_PIPEASTAT);
+ pipeb_stats = I915_READ(I915REG_PIPEBSTAT);

temp = I915_READ16(I915REG_INT_IDENTITY_R);

@@ -225,6 +229,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
return IRQ_NONE;

I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+ (void) I915_READ16(I915REG_INT_IDENTITY_R);
+ DRM_READMEMORYBARRIER();

dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);

@@ -252,6 +258,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)

if (dev_priv->swaps_pending > 0)
drm_locked_tasklet(dev, i915_vblank_tasklet);
+ I915_WRITE(I915REG_PIPEASTAT,
+ pipea_stats|I915_VBLANK_INTERRUPT_ENABLE|
+ I915_VBLANK_CLEAR);
+ I915_WRITE(I915REG_PIPEBSTAT,
+ pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE|
+ I915_VBLANK_CLEAR);
}

return IRQ_HANDLED;
--
1.5.3.1