From 531f25cfe9d0319f78fe58260bfed08d5e3e8bcc Mon Sep 17 00:00:00 2001
From: Jesse Barnes <jbarnes@nietzche.virtuousgeek.org>
Date: Tue, 22 Jan 2008 15:16:01 -0800
Subject: Correct vblank count value

The frame count registers don't increment until the start of the next
frame, so make sure we return an incremented count if called during the
actual vblank period.
---
 shared-core/i915_drv.h |  6 ++++++
 shared-core/i915_irq.c | 15 +++++++++++++--
 2 files changed, 19 insertions(+), 2 deletions(-)

(limited to 'shared-core')

diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h
index b8d027d7..2c1f2c2e 100644
--- a/shared-core/i915_drv.h
+++ b/shared-core/i915_drv.h
@@ -471,6 +471,9 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 #define I915REG_INT_ENABLE_R	0x020a0
 #define I915REG_INSTPM	        0x020c0
 
+#define PIPEADSL		0x70000
+#define PIPEBDSL		0x71000
+
 #define I915REG_PIPEASTAT	0x70024
 #define I915REG_PIPEBSTAT	0x71024
 /*
@@ -790,6 +793,9 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 #define BCLRPAT_B	0x61020
 #define VSYNCSHIFT_B	0x61028
 
+#define HACTIVE_MASK	0x00000fff
+#define VBLANK_START_MASK 0x00001fff
+
 #define PP_STATUS	0x61200
 # define PP_ON					(1 << 31)
 /**
diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c
index bef73b62..7ad21a97 100644
--- a/shared-core/i915_irq.c
+++ b/shared-core/i915_irq.c
@@ -69,8 +69,6 @@ i915_get_pipe(struct drm_device *dev, int plane)
 static int
 i915_get_plane(struct drm_device *dev, int pipe)
 {
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-
 	if (i915_get_pipe(dev, 0) == pipe)
 		return 0;
 	return 1;
@@ -349,12 +347,16 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	unsigned long high_frame;
 	unsigned long low_frame;
+	unsigned long pipedsl, vblank, htotal;
 	u32 high1, high2, low, count;
 	int pipe;
 
 	pipe = i915_get_pipe(dev, plane);
 	high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
 	low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
+	pipedsl = pipe ? PIPEBDSL : PIPEADSL;
+	vblank = pipe ? VBLANK_B : VBLANK_A;
+	htotal = pipe ? HTOTAL_B : HTOTAL_A;
 
 	if (!i915_pipe_enabled(dev, pipe)) {
 	    printk(KERN_ERR "trying to get vblank count for disabled "
@@ -378,6 +380,15 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
 
 	count = (high1 << 8) | low;
 
+	/*
+	 * If we're in the middle of the vblank period, the
+	 * above regs won't have been updated yet, so return
+	 * an incremented count to stay accurate
+	 */
+	if ((I915_READ(pipedsl) >= (I915_READ(vblank) & VBLANK_START_MASK)) ||
+	    (I915_READ(pipedsl) < (I915_READ(htotal) & HACTIVE_MASK)))
+		count++;
+
 	return count;
 }
 
-- 
cgit v1.2.3