summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@nietzche.virtuousgeek.org>2008-01-22 15:16:01 -0800
committerJesse Barnes <jbarnes@nietzche.virtuousgeek.org>2008-01-22 15:16:01 -0800
commit531f25cfe9d0319f78fe58260bfed08d5e3e8bcc (patch)
treef1e9e1957b016fcccbeb9fc4f97f1c44a0230e92
parent893e311999d1565943899d73c56c674fc9b6e502 (diff)
Correct vblank count valuevblank-rework
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.
-rw-r--r--shared-core/i915_drv.h6
-rw-r--r--shared-core/i915_irq.c15
2 files changed, 19 insertions, 2 deletions
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;
}