public inbox for intel-gfx@lists.freedesktop.org
 help / color / mirror / Atom feed
From: Mario Kleiner <mario.kleiner.de@gmail.com>
To: "Ville Syrjälä" <ville.syrjala@linux.intel.com>
Cc: intel-gfx@lists.freedesktop.org,
	Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
Subject: Re: [PATCH 3/3] drm/i915: Improve the accuracy of get_scanout_pos on CTG+
Date: Thu, 26 Sep 2013 19:04:05 +0200	[thread overview]
Message-ID: <52446905.1080109@gmail.com> (raw)
In-Reply-To: <20130925081130.GJ4531@intel.com>

On 25.09.13 10:11, Ville Syrjälä wrote:
> On Wed, Sep 25, 2013 at 05:12:54AM +0200, Mario Kleiner wrote:
>>
>>
>> On 23.09.13 12:02, ville.syrjala@linux.intel.com wrote:
>>> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>>
>>> The DSL register increments at the start of horizontal sync, so it
>>> manages to miss the entire active portion of the current line.
>>>
>>> Improve the get_scanoutpos accuracy a bit when the scanout position is
>>> close to the start or end of vblank. We can do that by double checking
>>> the DSL value against the vblank status bit from ISR.
>>>
>>> Cc: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
>>> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
>>> ---
>>>    drivers/gpu/drm/i915/i915_irq.c | 53 +++++++++++++++++++++++++++++++++++++++++
>>>    1 file changed, 53 insertions(+)
>>>
>>> diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
>>> index 4f74f0c..14b42d9 100644
>>> --- a/drivers/gpu/drm/i915/i915_irq.c
>>> +++ b/drivers/gpu/drm/i915/i915_irq.c
>>> @@ -567,6 +567,47 @@ static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
>>>    	return I915_READ(reg);
>>>    }
>>>
>>> +static bool g4x_pipe_in_vblank(struct drm_device *dev, enum pipe pipe)
>>> +{
>>> +	struct drm_i915_private *dev_priv = dev->dev_private;
>>> +	uint32_t status;
>>> +
>>> +	if (IS_VALLEYVIEW(dev)) {
>>> +		status = pipe == PIPE_A ?
>>> +			I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT :
>>> +			I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
>>> +
>>> +		return I915_READ(VLV_ISR) & status;
>>> +	} else if (IS_G4X(dev)) {
>>> +		status = pipe == PIPE_A ?
>>> +			I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT :
>>> +			I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT;
>>> +
>>> +		return I915_READ(ISR) & status;
>>> +	} else if (INTEL_INFO(dev)->gen < 7) {
>>> +		status = pipe == PIPE_A ?
>>> +			DE_PIPEA_VBLANK :
>>> +			DE_PIPEB_VBLANK;
>>> +
>>> +		return I915_READ(DEISR) & status;
>>> +	} else {
>>> +		switch (pipe) {
>>> +		default:
>>> +		case PIPE_A:
>>> +			status = DE_PIPEA_VBLANK_IVB;
>>> +			break;
>>> +		case PIPE_B:
>>> +			status = DE_PIPEB_VBLANK_IVB;
>>> +			break;
>>> +		case PIPE_C:
>>> +			status = DE_PIPEC_VBLANK_IVB;
>>> +			break;
>>> +		}
>>> +
>>> +		return I915_READ(DEISR) & status;
>>> +	}
>>> +}
>>> +
>>>    static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
>>>    			     int *vpos, int *hpos)
>>>    {
>>> @@ -616,6 +657,18 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,
>>>    		 * scanout position from Display scan line register.
>>>    		 */
>>>    		position = I915_READ(PIPEDSL(pipe)) & 0x1fff;
>>> +
>>> +		/*
>>> +		 * The scanline counter increments at the leading edge
>>> +		 * of hsync, ie. it completely misses the active portion
>>> +		 * of the line. Fix up the counter at both edges of vblank
>>> +		 * to get a more accurate picture whether we're in vblank
>>> +		 * or not.
>>> +		 */
>>> +		in_vbl = g4x_pipe_in_vblank(dev, pipe);
>>> +		if ((in_vbl && position == vbl_start - 1) ||
>>> +		    (!in_vbl && position == vbl_end - 1))
>>> +			position = (position + 1) % vtotal;
>>>    	} else {
>>>    		/* Have access to pixelcount since start of frame.
>>>    		 * We can split this into vertical and horizontal
>>>
>>
>> This one i don't know. I think i can't follow the logic, but i don't
>> know enough about the way the intel hw counts.
>>
>> Do you mean the counter increments when the scanline is over, instead of
>> when it begins?
>
> Let me draw a picture of the scanline (not to scale):
>
>   |XXXXXXXXXXXXX|-----|___________|---|
>    horiz. active       horiz. sync
>   ^                   ^
>   |                   |
>   first pixel         this is where the
>   of the line         scanline counter increments
>
>> With this correction by +1 at the edges of vblank, the scanlines at
>> vbl_start and vbl_end would be reported twice, for two successive
>> scanline durations, that seems a bit weird and asymmetric to the rest of
>> the scanline positions. Wouldn't it make more sense to simply always add
>> 1 for a smaller overall error, given that hblank is shorter than the
>> active scanout part of a scanline?
>
> Since the counter increments too late, drm_handle_vblank()
> may get the wrong idea ie. something like this may happen:
>
> 1. vblank irq triggered
> 2. drm_handle_vblank() gets called
> 3. i915_get_crtc_scanoutpos() returns vbl_start-1 as the scanline
> 4. delta_ns calculation gets confused and tries to correct for it
>
> Now, the correction you do for delta_ns should handle this, but
> I don't like having such kludges in common code, and we can handle
> it in the driver as I've demonstrated. But yeah, I suppose it can
> make the error slightly less stable.
>

The kludges are also needed for other drivers, especially some radeon 
gpu's which can fire their vblank interrupts multiple scanlines before 
the vblank, and iirc nouveau with the prototype patches we had. I like 
that catch-all for robustness, especially on gpu's whose behaviour is 
not that well documented as in case of intel, but of course it's better 
if a driver does the right thing from the start.

> For some other uses (atomic page flip stuff) of the scanline position,
> I definitely want this correction since I need accurate information
> whether the position has passed vblank start.
>

Ok, i can live with that.

>> Also it adds back one lock protected, therefore potentially slow,
>> register read into the time critical code.
>
> I don't think a single register read should be _that_ slow even
> with all the extra junk we do. And of course we can fix that problem.
>

Ja. If you make g4x_pipe_in_vblank() or maybe a helper to just return 
the register and status mask, we can do the actual register read also as 
a __raw read together with the raw read of scanout position regs, inside 
that ktime_get() enclosed section. Then it's cheap and rt compatible and 
done with that one uncore.lock lock/unlock and everybody's happy.

-mario

      parent reply	other threads:[~2013-09-26 17:04 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-09-23 10:02 [PATCH 0/3] drm/i915: i915_get_crtc_scanoutpos improvements ville.syrjala
2013-09-23 10:02 ` [PATCH 1/3] drm/i915: Skip register reads in i915_get_crtc_scanoutpos() ville.syrjala
2013-09-23 10:30   ` Chris Wilson
2013-09-23 11:48     ` [PATCH v2 " ville.syrjala
2013-09-24  9:11       ` Daniel Vetter
2013-09-25  4:45         ` Mario Kleiner
2013-09-25  7:52           ` Daniel Vetter
2013-09-25  2:35       ` Mario Kleiner
2013-09-25  8:14         ` Ville Syrjälä
2013-09-26 16:12           ` Mario Kleiner
2013-09-23 10:02 ` [PATCH 2/3] drm/i915: Fix scanoutpos calculations ville.syrjala
2013-09-25  2:39   ` Mario Kleiner
2013-10-11 14:31   ` Mario Kleiner
2013-10-11 16:10     ` [PATCH v2 " ville.syrjala
2013-10-11 23:19     ` [PATCH " Daniel Vetter
2013-10-11 23:22       ` Mario Kleiner
2013-10-14 15:13         ` Daniel Vetter
2013-09-23 10:02 ` [PATCH 3/3] drm/i915: Improve the accuracy of get_scanout_pos on CTG+ ville.syrjala
2013-09-25  3:12   ` Mario Kleiner
2013-09-25  8:11     ` Ville Syrjälä
2013-09-25  8:46       ` Daniel Vetter
2013-09-26 17:04       ` Mario Kleiner [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=52446905.1080109@gmail.com \
    --to=mario.kleiner.de@gmail.com \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=mario.kleiner@tuebingen.mpg.de \
    --cc=ville.syrjala@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox