On Thu, Sep 24, 2015 at 06:35:35PM +0200, Thierry Reding wrote:
From: Thierry Reding treding@nvidia.com
None of the drivers use this in legacy mode, so it can be converted to use struct drm_crtc * directly. While at it, also make the sole user of the callback, drm_calc_vbltimestamp_from_scanoutpos(), pass through the CRTC directly.
v2: use standard [CRTC:%u] format
I very much like this as a first small step towards untangling drm_irq.c. Two comments below.
Cc: Daniel Vetter daniel.vetter@intel.com Cc: Jani Nikula jani.nikula@linux.intel.com Cc: Ben Skeggs bskeggs@redhat.com Cc: Alex Deucher alexander.deucher@amd.com Cc: Christian König christian.koenig@amd.com Signed-off-by: Thierry Reding treding@nvidia.com
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 4a5dee5cd327..525bd82ab514 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -653,8 +653,7 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
/**
- drm_calc_vbltimestamp_from_scanoutpos - precise vblank timestamp helper
- @dev: DRM device
- @pipe: index of CRTC whose vblank timestamp to retrieve
- @crtc: CRTC whose vblank timestamp to retrieve
- @max_error: Desired maximum allowable error in timestamps (nanosecs)
On return contains true maximum error of timestamp
- @vblank_time: Pointer to struct timeval which should receive the timestamp
@@ -696,13 +695,13 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
- DRM_VBLANKTIME_INVBL - Timestamp taken while scanout was in vblank interval.
*/ -int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
unsigned int pipe,
+int drm_calc_vbltimestamp_from_scanoutpos(struct drm_crtc *crtc, int *max_error, struct timeval *vblank_time, unsigned flags, const struct drm_display_mode *mode)
This function is actually more a helper, since if you use some hardware vblank timestamp register you don't really need it at all. Hence I think we should fix this properly and instead move this function into a new drm_irq_helper.c (part of drm_kms_helper.ko) - there will be more once drm_irq.c is untangled. And also push the callback into the corresponding helper funcs sturctures.
{
- const struct drm_crtc_funcs *funcs = crtc->funcs; struct timeval tv_etime; ktime_t stime, etime; unsigned int vbl_status;
@@ -710,22 +709,16 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int vpos, hpos, i; int delta_ns, duration_ns;
- if (pipe >= dev->num_crtcs) {
DRM_ERROR("Invalid crtc %u\n", pipe);
return -EINVAL;
- }
- /* Scanout position query not supported? Should not happen. */
- if (!dev->driver->get_scanout_position) {
DRM_ERROR("Called from driver w/o get_scanout_position()!?\n");
return -EIO;
- }
if (WARN_ON(funcs->get_scanout_position == NULL))
return -ENOSYS;
/* If mode timing undefined, just return as no-op:
- Happens during initial modesetting of a crtc.
*/ if (mode->crtc_clock == 0) {
DRM_DEBUG("crtc %u: Noop due to uninitialized mode.\n", pipe);
DRM_DEBUG("[CRTC:%u] Noop due to uninitialized mode.\n",
return -EAGAIN; }crtc->base.id);
@@ -741,15 +734,14 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, * Get vertical and horizontal scanout position vpos, hpos, * and bounding timestamps stime, etime, pre/post query. */
vbl_status = dev->driver->get_scanout_position(dev, pipe, flags,
&vpos, &hpos,
&stime, &etime,
mode);
vbl_status = funcs->get_scanout_position(crtc, flags, &vpos,
&hpos, &stime, &etime,
mode);
/* Return as no-op if scanout query unsupported or failed. */ if (!(vbl_status & DRM_SCANOUTPOS_VALID)) {
DRM_DEBUG("crtc %u : scanoutpos query failed [0x%x].\n",
pipe, vbl_status);
DRM_DEBUG("[CRTC:%u] scanoutpos query failed [%d].\n",
}crtc->base.id, vbl_status); return -EIO;
@@ -763,8 +755,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
/* Noisy system timing? */ if (i == DRM_TIMESTAMP_MAXRETRIES) {
DRM_DEBUG("crtc %u: Noisy timestamp %d us > %d us [%d reps].\n",
pipe, duration_ns/1000, *max_error/1000, i);
DRM_DEBUG("[CRTC:%u] Noisy timestamp %d us > %d us [%d reps].\n",
crtc->base.id, duration_ns/1000, *max_error/1000, i);
}
/* Return upper bound of timestamp precision error. */
@@ -799,8 +791,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, etime = ktime_sub_ns(etime, delta_ns); *vblank_time = ktime_to_timeval(etime);
- DRM_DEBUG("crtc %u : v 0x%x p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n",
pipe, vbl_status, hpos, vpos,
- DRM_DEBUG("[CRTC:%u] v 0x%x p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n",
(long)tv_etime.tv_sec, (long)tv_etime.tv_usec, (long)vblank_time->tv_sec, (long)vblank_time->tv_usec, duration_ns/1000, i);crtc->base.id, vbl_status, hpos, vpos,
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 7b3aeb0f8056..6eec529b3a5b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -767,14 +767,15 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc) return (position + crtc->scanline_offset) % vtotal; }
-static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
unsigned int flags, int *vpos, int *hpos,
ktime_t *stime, ktime_t *etime,
const struct drm_display_mode *mode)
+int i915_get_crtc_scanoutpos(struct drm_crtc *crtc, unsigned int flags,
int *vpos, int *hpos, ktime_t *stime,
ktime_t *etime,
const struct drm_display_mode *mode)
{
- struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private;
- struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- enum pipe pipe = intel_crtc->pipe; int position; int vbl_start, vbl_end, hsync_start, htotal, vtotal; bool in_vbl = true;
@@ -929,7 +930,7 @@ static int i915_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe, }
/* Helper routine in DRM core does all the work: */
- return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error,
- return drm_calc_vbltimestamp_from_scanoutpos(crtc, max_error, vblank_time, flags, &crtc->hwmode);
} @@ -4387,7 +4388,6 @@ void intel_irq_init(struct drm_i915_private *dev_priv) dev->vblank_disable_immediate = true;
dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp;
dev->driver->get_scanout_position = i915_get_crtc_scanoutpos;
if (IS_CHERRYVIEW(dev_priv)) { dev->driver->irq_handler = cherryview_irq_handler;
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 683f1421a825..c5c9e316251a 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -307,6 +307,11 @@ struct drm_crtc_state { struct drm_atomic_state *state; };
+/* get_scanout_position() return flags */ +#define DRM_SCANOUTPOS_VALID (1 << 0) +#define DRM_SCANOUTPOS_IN_VBLANK (1 << 1) +#define DRM_SCANOUTPOS_ACCURATE (1 << 2)
/**
- struct drm_crtc_funcs - control CRTCs for a given device
- @save: save CRTC state
@@ -326,6 +331,7 @@ struct drm_crtc_state {
- (do not call directly, use drm_atomic_crtc_set_property())
- @atomic_get_property: get a property on an atomic state for this CRTC
- (do not call directly, use drm_atomic_crtc_get_property())
- @get_scanout_position: return the current scanout position
- The drm_crtc_funcs structure is the central CRTC management structure
- in the DRM. Each CRTC controls one or more connectors (note that the name
@@ -389,6 +395,40 @@ struct drm_crtc_funcs { const struct drm_crtc_state *state, struct drm_property *property, uint64_t *val);
- /**
Please use the new inline structure documentation layout for this (merged into 4.3): Just drop the @get_scanout_position: from the top-level comment and add that here. -Daniel
* Called by vblank timestamping code.
*
* Return the current display scanout position from a crtc, and an
* optional accurate ktime_get timestamp of when position was measured.
*
* \param crtc CRTC to query.
* \param flags Flags from the caller (DRM_CALLED_FROM_VBLIRQ or 0).
* \param *vpos Target location for current vertical scanout position.
* \param *hpos Target location for current horizontal scanout position.
* \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.
* \param mode Current display timings.
*
* Returns vpos as a positive number while in active scanout area.
* Returns vpos as a negative number inside vblank, counting the number
* of scanlines to go until end of vblank, e.g., -1 means "one scanline
* until start of active scanout / end of vblank."
*
* \return Flags, or'ed together as follows:
*
* DRM_SCANOUTPOS_VALID = Query successful.
* DRM_SCANOUTPOS_INVBL = Inside vblank.
* DRM_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of
* this flag means that returned position may be offset by a constant
* but unknown small number of scanlines wrt. real scanout position.
*/
- int (*get_scanout_position)(struct drm_crtc *crtc, unsigned int flags,
int *vpos, int *hpos, ktime_t *stime,
ktime_t *etime,
const struct drm_display_mode *mode);
};
/** @@ -1194,6 +1234,12 @@ extern int drm_crtc_init_with_planes(struct drm_device *dev, extern void drm_crtc_cleanup(struct drm_crtc *crtc); extern unsigned int drm_crtc_index(struct drm_crtc *crtc);
+extern int drm_calc_vbltimestamp_from_scanoutpos(struct drm_crtc *crtc,
int *max_error,
struct timeval *vblank_time,
unsigned flags,
const struct drm_display_mode *mode);
/**
- drm_crtc_mask - find the mask of a registered CRTC
- @crtc: CRTC to find mask for
-- 2.5.0
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel