[Intel-gfx] [PATCH 2/3] drm/i915: Fix scanoutpos calculations

Mario Kleiner mario.kleiner.de at gmail.com
Fri Oct 11 16:31:38 CEST 2013


Daniel, Ville,

i tested Ville's patch series for the scanoutpos improvements on a 
GMA-950, on top of airlied's current drm-next branch.

There's one issue: The variable "position" in i915_get_crtc_scanoutpos() 
must be turned from a u32 into a int, otherwise funny sign errors happen 
and we end up with *vpos being off by multiple million scanlines and 
timestamps being off by over 60 seconds.

Other than that looks good. Execution time is now better:

Before uncore.lock addition: 3-4 usecs execution time for the scanoutpos 
query on my machine. After uncore.lock addition (3.12.0-rc3) 9-20 usecs, 
sometimes repetition of the timing loop triggered. After Ville's patches 
down to typically 3-8 usecs, occassionally spiking to almost 20 usecs.

I'll make my patches for the realtime kernel + increased accuracy on top 
of drm-next + Ville's patches.

thanks,
-mario

On 09/23/2013 12:02 PM, ville.syrjala at linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala at 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.
>
> Cc: Mario Kleiner <mario.kleiner at tuebingen.mpg.de>
> Signed-off-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
> ---
>   drivers/gpu/drm/i915/i915_irq.c | 37 ++++++++++++++++++++++++-------------
>   1 file changed, 24 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
> index 697d62c..4f74f0c 100644
> --- a/drivers/gpu/drm/i915/i915_irq.c
> +++ b/drivers/gpu/drm/i915/i915_irq.c
> @@ -615,13 +615,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
> @@ -629,15 +623,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)




More information about the Intel-gfx mailing list