|
@@ -307,7 +307,7 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id)
|
|
|
*/
|
|
|
if (update_pending &&
|
|
|
(DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id,
|
|
|
- &vpos, &hpos)) &&
|
|
|
+ &vpos, &hpos, NULL, NULL)) &&
|
|
|
((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) ||
|
|
|
(vpos < 0 && !ASIC_IS_AVIVO(rdev)))) {
|
|
|
/* crtc didn't flip in this target vblank interval,
|
|
@@ -1596,12 +1596,17 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * Retrieve current video scanout position of crtc on a given gpu.
|
|
|
+ * Retrieve current video scanout position of crtc on a given gpu, and
|
|
|
+ * an optional accurate timestamp of when query happened.
|
|
|
*
|
|
|
* \param dev Device to query.
|
|
|
* \param crtc Crtc to query.
|
|
|
* \param *vpos Location where vertical scanout position should be stored.
|
|
|
* \param *hpos Location where horizontal scanout position should go.
|
|
|
+ * \param *stime Target location for timestamp taken immediately before
|
|
|
+ * scanout position query. Can be NULL to skip timestamp.
|
|
|
+ * \param *etime Target location for timestamp taken immediately after
|
|
|
+ * scanout position query. Can be NULL to skip timestamp.
|
|
|
*
|
|
|
* Returns vpos as a positive number while in active scanout area.
|
|
|
* Returns vpos as a negative number inside vblank, counting the number
|
|
@@ -1617,7 +1622,8 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
|
|
|
* unknown small number of scanlines wrt. real scanout position.
|
|
|
*
|
|
|
*/
|
|
|
-int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, int *vpos, int *hpos)
|
|
|
+int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, int *vpos, int *hpos,
|
|
|
+ ktime_t *stime, ktime_t *etime)
|
|
|
{
|
|
|
u32 stat_crtc = 0, vbl = 0, position = 0;
|
|
|
int vbl_start, vbl_end, vtotal, ret = 0;
|
|
@@ -1625,6 +1631,12 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, int *vpos, int
|
|
|
|
|
|
struct radeon_device *rdev = dev->dev_private;
|
|
|
|
|
|
+ /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */
|
|
|
+
|
|
|
+ /* Get optional system timestamp before query. */
|
|
|
+ if (stime)
|
|
|
+ *stime = ktime_get();
|
|
|
+
|
|
|
if (ASIC_IS_DCE4(rdev)) {
|
|
|
if (crtc == 0) {
|
|
|
vbl = RREG32(EVERGREEN_CRTC_V_BLANK_START_END +
|
|
@@ -1707,6 +1719,12 @@ int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, int *vpos, int
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /* Get optional system timestamp after query. */
|
|
|
+ if (etime)
|
|
|
+ *etime = ktime_get();
|
|
|
+
|
|
|
+ /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */
|
|
|
+
|
|
|
/* Decode into vertical and horizontal scanout position. */
|
|
|
*vpos = position & 0x1fff;
|
|
|
*hpos = (position >> 16) & 0x1fff;
|