[PATCH 13/16] drm: Move ->get_scanout_position() to struct drm_crtc_funcs

Daniel Vetter daniel at ffwll.ch
Thu Sep 24 11:22:05 PDT 2015


On Thu, Sep 24, 2015 at 06:35:35PM +0200, Thierry Reding wrote:
> From: Thierry Reding <treding at 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 at intel.com>
> Cc: Jani Nikula <jani.nikula at linux.intel.com>
> Cc: Ben Skeggs <bskeggs at redhat.com>
> Cc: Alex Deucher <alexander.deucher at amd.com>
> Cc: Christian König <christian.koenig at amd.com>
> Signed-off-by: Thierry Reding <treding at 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",
> +			  crtc->base.id);
>  		return -EAGAIN;
>  	}
>  
> @@ -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",
> +		  crtc->base.id, vbl_status, hpos, vpos,
>  		  (long)tv_etime.tv_sec, (long)tv_etime.tv_usec,
>  		  (long)vblank_time->tv_sec, (long)vblank_time->tv_usec,
>  		  duration_ns/1000, i);
> 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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch


More information about the dri-devel mailing list