Correct vblank count value
authorJesse Barnes <jbarnes@nietzche.virtuousgeek.org>
Tue, 22 Jan 2008 23:16:01 +0000 (15:16 -0800)
committerJesse Barnes <jbarnes@nietzche.virtuousgeek.org>
Tue, 22 Jan 2008 23:16:01 +0000 (15:16 -0800)
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
shared-core/i915_irq.c

index b8d027d..2c1f2c2 100644 (file)
@@ -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)
 /**
index bef73b6..7ad21a9 100644 (file)
@@ -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;
 }