From: Ville Syrjälä <ville.syrj...@linux.intel.com>

The reported scanout position must be relative to the end of vblank.
Currently we manage to fumble that in a few ways.

First we don't consider the case when vtotal != vbl_end. While that
isn't very common (happens maybe only w/ old panel fitting hardware),
we can fix it easily enough.

The second issue is that on pre-CTG hardware we convert the pixel count
to horizontal/vertical components at the very beginning, and then forget
to adjust the horizontal component to be relative to vbl_end. So instead
we should keep our numbers in the pixel count domain while we're
adjusting the position to be relative to vbl_end. Then when we do the
conversion in the end, both vertical _and_ horizontal components will
come out correct.

v2: Change position to int from u32 to avoid sign issues

Cc: Mario Kleiner <mario.klei...@tuebingen.mpg.de>
Signed-off-by: Ville Syrjälä <ville.syrj...@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_irq.c | 39 +++++++++++++++++++++++++--------------
 1 file changed, 25 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 92a37ee..c9d2ab7 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -574,7 +574,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, 
int pipe,
        struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        const struct drm_display_mode *mode = &intel_crtc->config.adjusted_mode;
-       u32 position;
+       int position;
        int vbl_start, vbl_end, htotal, vtotal;
        bool in_vbl = true;
        int ret = 0;
@@ -596,13 +596,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device 
*dev, int pipe,
                /* No obvious pixelcount register. Only query vertical
                 * scanout position from Display scan line register.
                 */
-               position = I915_READ(PIPEDSL(pipe));
-
-               /* Decode into vertical scanout position. Don't have
-                * horizontal scanout position.
-                */
-               *vpos = position & 0x1fff;
-               *hpos = 0;
+               position = I915_READ(PIPEDSL(pipe)) & 0x1fff;
        } else {
                /* Have access to pixelcount since start of frame.
                 * We can split this into vertical and horizontal
@@ -610,15 +604,32 @@ static int i915_get_crtc_scanoutpos(struct drm_device 
*dev, int pipe,
                 */
                position = (I915_READ(PIPEFRAMEPIXEL(pipe)) & PIPE_PIXEL_MASK) 
>> PIPE_PIXEL_SHIFT;
 
-               *vpos = position / htotal;
-               *hpos = position - (*vpos * htotal);
+               /* convert to pixel counts */
+               vbl_start *= htotal;
+               vbl_end *= htotal;
+               vtotal *= htotal;
        }
 
-       in_vbl = *vpos >= vbl_start && *vpos < vbl_end;
+       in_vbl = position >= vbl_start && position < vbl_end;
 
-       /* Inside "upper part" of vblank area? Apply corrective offset: */
-       if (in_vbl && (*vpos >= vbl_start))
-               *vpos = *vpos - vtotal;
+       /*
+        * While in vblank, position will be negative
+        * counting up towards 0 at vbl_end. And outside
+        * vblank, position will be positive counting
+        * up since vbl_end.
+        */
+       if (position >= vbl_start)
+               position -= vbl_end;
+       else
+               position += vtotal - vbl_end;
+
+       if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) {
+               *vpos = position;
+               *hpos = 0;
+       } else {
+               *vpos = position / htotal;
+               *hpos = position - (*vpos * htotal);
+       }
 
        /* In vblank? */
        if (in_vbl)
-- 
1.8.1.5

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to