| From 29aa390c3c262376a3396bc0f6649065641ad98f Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> |
| Date: Fri, 11 Oct 2013 19:10:32 +0300 |
| Subject: drm/i915: Fix scanoutpos calculations |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| |
| 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.kleiner@tuebingen.mpg.de> |
| Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> |
| Reviewed-by: mario.kleiner.de@gmail.com |
| Tested-by: mario.kleiner.de@gmail.com |
| Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> |
| (cherry picked from commit 3aa18df8f22f24ab6ccd4155cb34ef6bff2f2a1c) |
| Signed-off-by: Darren Hart <dvhart@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 cc35d52f0166..a923dea245ac 100644 |
| --- a/drivers/gpu/drm/i915/i915_irq.c |
| +++ b/drivers/gpu/drm/i915/i915_irq.c |
| @@ -599,7 +599,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; |
| @@ -621,13 +621,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 |
| @@ -635,15 +629,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; |
| + |
| + /* |
| + * 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; |
| |
| - /* Inside "upper part" of vblank area? Apply corrective offset: */ |
| - if (in_vbl && (*vpos >= vbl_start)) |
| - *vpos = *vpos - vtotal; |
| + 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.5.rc3 |
| |