[Intel-gfx] [PATCH 8/5] drm/i915: Fix gen2 scanline counter

ville.syrjala at linux.intel.com ville.syrjala at linux.intel.com
Tue Feb 18 13:04:20 CET 2014


From: Ville Syrjälä <ville.syrjala at linux.intel.com>

On gen2 the scanline counter behaves a bit differently from the
later generations. Instead of adding one to the raw scanline
counter value, we must subtract one.

I've not yet verified which way gen3 works. My suspicion is that
it behaves like gen4 since for the most part the other timing
related registers are similar to gen4. The one similarity to gen2
that gen3 shares is the lack of the "start of vblank" interrupt.
The event is there internally even on gen2 (that's where the
registers get latched) but the PIPESTAT status bit and the actual
interrupt are not available to the driver.

Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
---
 drivers/gpu/drm/i915/i915_irq.c | 36 +++++++++++++++++++++++-------------
 1 file changed, 23 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index fc49fb6..bec9af8 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -724,26 +724,36 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	const struct drm_display_mode *mode = &crtc->config.adjusted_mode;
 	enum pipe pipe = crtc->pipe;
-	int vtotal = mode->crtc_vtotal;
-	int position;
+	int position, vtotal;
 
+	vtotal = mode->crtc_vtotal;
 	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
 		vtotal /= 2;
 
+	/*
+	 * The scanline counter increments at the leading edge of hsync.
+	 *
+	 * On most platforms it starts counting from vtotal-1 on the
+	 * first active line. That means the scanline counter value is
+	 * always one less than what we would expect. Ie. just after
+	 * start of vblank, which also occurs at start of hsync (on the
+	 * last active line), the scanline counter will read vblank_start-1.
+	 *
+	 * Gen2 is the exception as the scanline counter starts counting
+	 * from 1 instead of vtotal-1, so we have to subtract one (or
+	 * rather add vtotal-1 to keep the value positive), instead of
+	 * adding one.
+	 *
+	 * FIXME which way does gen3 work? Gen4 is for sure in the +1 camp.
+	 */
 	if (IS_GEN2(dev))
-		position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN2;
+		position = (__raw_i915_read32(dev_priv, PIPEDSL(pipe)) &
+			    DSL_LINEMASK_GEN2) + vtotal - 1;
 	else
-		position = __raw_i915_read32(dev_priv, PIPEDSL(pipe)) & DSL_LINEMASK_GEN3;
+		position = (__raw_i915_read32(dev_priv, PIPEDSL(pipe)) &
+			    DSL_LINEMASK_GEN3) + 1;
 
-	/*
-	 * Scanline counter increments at leading edge of hsync, and
-	 * it starts counting from vtotal-1 on the first active line.
-	 * That means the scanline counter value is always one less
-	 * than what we would expect. Ie. just after start of vblank,
-	 * which also occurs at start of hsync (on the last active line),
-	 * the scanline counter will read vblank_start-1.
-	 */
-	return (position + 1) % vtotal;
+	return position % vtotal;
 }
 
 static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
-- 
1.8.3.2




More information about the Intel-gfx mailing list