Commit 8072bfa6 authored by Ville Syrjälä's avatar Ville Syrjälä

drm/radeon: Move the early vblank IRQ fixup to radeon_get_crtc_scanoutpos()

i915 doesn't need this kludge for most platforms. Although we do
appear to need something similar on certain platforms, but we can
be more accurate when we apply the adjustment since we know exactly
why the scanline counter doesn't always quite match the vblank
status.

Also the current code doesn't handle interlaced modes correctly,
and we already deal with interlaced modes in i915 code.

So let's just move the current code to radeon_get_crtc_scanoutpos()
since that's why it was added. For i915 we'll add a more finely
targeted variant.

v2: Fix vpos vs. *vpos bug (Mario)

Reviewed-by: mario.kleiner.de@gmail.com
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
parent abca9e45
...@@ -542,7 +542,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, ...@@ -542,7 +542,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
{ {
ktime_t stime, etime, mono_time_offset; ktime_t stime, etime, mono_time_offset;
struct timeval tv_etime; struct timeval tv_etime;
int vbl_status, vtotal, vdisplay; int vbl_status;
int vpos, hpos, i; int vpos, hpos, i;
int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns; int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns;
bool invbl; bool invbl;
...@@ -558,9 +558,6 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, ...@@ -558,9 +558,6 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
return -EIO; return -EIO;
} }
vtotal = mode->crtc_vtotal;
vdisplay = mode->crtc_vdisplay;
/* Durations of frames, lines, pixels in nanoseconds. */ /* Durations of frames, lines, pixels in nanoseconds. */
framedur_ns = refcrtc->framedur_ns; framedur_ns = refcrtc->framedur_ns;
linedur_ns = refcrtc->linedur_ns; linedur_ns = refcrtc->linedur_ns;
...@@ -569,7 +566,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, ...@@ -569,7 +566,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
/* If mode timing undefined, just return as no-op: /* If mode timing undefined, just return as no-op:
* Happens during initial modesetting of a crtc. * Happens during initial modesetting of a crtc.
*/ */
if (vtotal <= 0 || vdisplay <= 0 || framedur_ns == 0) { if (framedur_ns == 0) {
DRM_DEBUG("crtc %d: Noop due to uninitialized mode.\n", crtc); DRM_DEBUG("crtc %d: Noop due to uninitialized mode.\n", crtc);
return -EAGAIN; return -EAGAIN;
} }
...@@ -633,24 +630,6 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, ...@@ -633,24 +630,6 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
*/ */
delta_ns = vpos * linedur_ns + hpos * pixeldur_ns; delta_ns = vpos * linedur_ns + hpos * pixeldur_ns;
/* Is vpos outside nominal vblank area, but less than
* 1/100 of a frame height away from start of vblank?
* If so, assume this isn't a massively delayed vblank
* interrupt, but a vblank interrupt that fired a few
* microseconds before true start of vblank. Compensate
* by adding a full frame duration to the final timestamp.
* Happens, e.g., on ATI R500, R600.
*
* We only do this if DRM_CALLED_FROM_VBLIRQ.
*/
if ((flags & DRM_CALLED_FROM_VBLIRQ) && !invbl &&
((vdisplay - vpos) < vtotal / 100)) {
delta_ns = delta_ns - framedur_ns;
/* Signal this correction as "applied". */
vbl_status |= 0x8;
}
if (!drm_timestamp_monotonic) if (!drm_timestamp_monotonic)
etime = ktime_sub(etime, mono_time_offset); etime = ktime_sub(etime, mono_time_offset);
......
...@@ -1775,5 +1775,27 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl ...@@ -1775,5 +1775,27 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int fl
if (in_vbl) if (in_vbl)
ret |= DRM_SCANOUTPOS_INVBL; ret |= DRM_SCANOUTPOS_INVBL;
/* Is vpos outside nominal vblank area, but less than
* 1/100 of a frame height away from start of vblank?
* If so, assume this isn't a massively delayed vblank
* interrupt, but a vblank interrupt that fired a few
* microseconds before true start of vblank. Compensate
* by adding a full frame duration to the final timestamp.
* Happens, e.g., on ATI R500, R600.
*
* We only do this if DRM_CALLED_FROM_VBLIRQ.
*/
if ((flags & DRM_CALLED_FROM_VBLIRQ) && !in_vbl) {
vbl_start = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vdisplay;
vtotal = rdev->mode_info.crtcs[crtc]->base.hwmode.crtc_vtotal;
if (vbl_start - *vpos < vtotal / 100) {
*vpos -= vtotal;
/* Signal this correction as "applied". */
ret |= 0x8;
}
}
return ret; return ret;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment