diff options
Diffstat (limited to 'drivers/gpu/drm/drm_irq.c')
| -rw-r--r-- | drivers/gpu/drm/drm_irq.c | 164 | 
1 files changed, 40 insertions, 124 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index b969a64a1514..273625a85036 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -93,7 +93,7 @@ static void store_vblank(struct drm_device *dev, unsigned int pipe,   * Reset the stored timestamp for the current vblank count to correspond   * to the last vblank occurred.   * - * Only to be called from drm_vblank_on(). + * Only to be called from drm_crtc_vblank_on().   *   * Note: caller must hold dev->vbl_lock since this reads & writes   * device vblank fields. @@ -234,6 +234,16 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,  	store_vblank(dev, pipe, diff, &t_vblank, cur_vblank);  } +static u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe) +{ +	struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + +	if (WARN_ON(pipe >= dev->num_crtcs)) +		return 0; + +	return vblank->count; +} +  /**   * drm_accurate_vblank_count - retrieve the master vblank counter   * @crtc: which counter to retrieve @@ -296,7 +306,7 @@ static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe)  	 * Always update the count and timestamp to maintain the  	 * appearance that the counter has been ticking all along until  	 * this time. This makes the count account for the entire time -	 * between drm_vblank_on() and drm_vblank_off(). +	 * between drm_crtc_vblank_on() and drm_crtc_vblank_off().  	 */  	drm_update_vblank_count(dev, pipe, 0); @@ -888,31 +898,6 @@ drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,  }  /** - * drm_vblank_count - retrieve "cooked" vblank counter value - * @dev: DRM device - * @pipe: index of CRTC for which to retrieve the counter - * - * Fetches the "cooked" vblank count value that represents the number of - * vblank events since the system was booted, including lost events due to - * modesetting activity. - * - * This is the legacy version of drm_crtc_vblank_count(). - * - * Returns: - * The software vblank counter. - */ -u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe) -{ -	struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; - -	if (WARN_ON(pipe >= dev->num_crtcs)) -		return 0; - -	return vblank->count; -} -EXPORT_SYMBOL(drm_vblank_count); - -/**   * drm_crtc_vblank_count - retrieve "cooked" vblank counter value   * @crtc: which counter to retrieve   * @@ -920,8 +905,6 @@ EXPORT_SYMBOL(drm_vblank_count);   * vblank events since the system was booted, including lost events due to   * modesetting activity.   * - * This is the native KMS version of drm_vblank_count(). - *   * Returns:   * The software vblank counter.   */ @@ -952,8 +935,10 @@ static u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,  	u32 vblank_count;  	unsigned int seq; -	if (WARN_ON(pipe >= dev->num_crtcs)) +	if (WARN_ON(pipe >= dev->num_crtcs)) { +		*vblanktime = (struct timeval) { 0 };  		return 0; +	}  	do {  		seq = read_seqbegin(&vblank->seqlock); @@ -1270,21 +1255,20 @@ void drm_crtc_wait_one_vblank(struct drm_crtc *crtc)  EXPORT_SYMBOL(drm_crtc_wait_one_vblank);  /** - * drm_vblank_off - disable vblank events on a CRTC - * @dev: DRM device - * @pipe: CRTC index + * drm_crtc_vblank_off - disable vblank events on a CRTC + * @crtc: CRTC in question   *   * Drivers can use this function to shut down the vblank interrupt handling when   * disabling a crtc. This function ensures that the latest vblank frame count is - * stored so that drm_vblank_on() can restore it again. + * stored so that drm_vblank_on can restore it again.   *   * Drivers must use this function when the hardware vblank counter can get   * reset, e.g. when suspending. - * - * This is the legacy version of drm_crtc_vblank_off().   */ -void drm_vblank_off(struct drm_device *dev, unsigned int pipe) +void drm_crtc_vblank_off(struct drm_crtc *crtc)  { +	struct drm_device *dev = crtc->dev; +	unsigned int pipe = drm_crtc_index(crtc);  	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];  	struct drm_pending_vblank_event *e, *t;  	struct timeval now; @@ -1300,7 +1284,8 @@ void drm_vblank_off(struct drm_device *dev, unsigned int pipe)  	DRM_DEBUG_VBL("crtc %d, vblank enabled %d, inmodeset %d\n",  		      pipe, vblank->enabled, vblank->inmodeset); -	/* Avoid redundant vblank disables without previous drm_vblank_on(). */ +	/* Avoid redundant vblank disables without previous +	 * drm_crtc_vblank_on(). */  	if (drm_core_check_feature(dev, DRIVER_ATOMIC) || !vblank->inmodeset)  		vblank_disable_and_save(dev, pipe); @@ -1331,25 +1316,6 @@ void drm_vblank_off(struct drm_device *dev, unsigned int pipe)  	}  	spin_unlock_irqrestore(&dev->event_lock, irqflags);  } -EXPORT_SYMBOL(drm_vblank_off); - -/** - * drm_crtc_vblank_off - disable vblank events on a CRTC - * @crtc: CRTC in question - * - * Drivers can use this function to shut down the vblank interrupt handling when - * disabling a crtc. This function ensures that the latest vblank frame count is - * stored so that drm_vblank_on can restore it again. - * - * Drivers must use this function when the hardware vblank counter can get - * reset, e.g. when suspending. - * - * This is the native kms version of drm_vblank_off(). - */ -void drm_crtc_vblank_off(struct drm_crtc *crtc) -{ -	drm_vblank_off(crtc->dev, drm_crtc_index(crtc)); -}  EXPORT_SYMBOL(drm_crtc_vblank_off);  /** @@ -1385,19 +1351,18 @@ void drm_crtc_vblank_reset(struct drm_crtc *crtc)  EXPORT_SYMBOL(drm_crtc_vblank_reset);  /** - * drm_vblank_on - enable vblank events on a CRTC - * @dev: DRM device - * @pipe: CRTC index + * drm_crtc_vblank_on - enable vblank events on a CRTC + * @crtc: CRTC in question   *   * This functions restores the vblank interrupt state captured with - * drm_vblank_off() again. Note that calls to drm_vblank_on() and - * drm_vblank_off() can be unbalanced and so can also be unconditionally called + * drm_crtc_vblank_off() again. Note that calls to drm_crtc_vblank_on() and + * drm_crtc_vblank_off() can be unbalanced and so can also be unconditionally called   * in driver load code to reflect the current hardware state of the crtc. - * - * This is the legacy version of drm_crtc_vblank_on().   */ -void drm_vblank_on(struct drm_device *dev, unsigned int pipe) +void drm_crtc_vblank_on(struct drm_crtc *crtc)  { +	struct drm_device *dev = crtc->dev; +	unsigned int pipe = drm_crtc_index(crtc);  	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];  	unsigned long irqflags; @@ -1424,49 +1389,10 @@ void drm_vblank_on(struct drm_device *dev, unsigned int pipe)  		WARN_ON(drm_vblank_enable(dev, pipe));  	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);  } -EXPORT_SYMBOL(drm_vblank_on); - -/** - * drm_crtc_vblank_on - enable vblank events on a CRTC - * @crtc: CRTC in question - * - * This functions restores the vblank interrupt state captured with - * drm_vblank_off() again. Note that calls to drm_vblank_on() and - * drm_vblank_off() can be unbalanced and so can also be unconditionally called - * in driver load code to reflect the current hardware state of the crtc. - * - * This is the native kms version of drm_vblank_on(). - */ -void drm_crtc_vblank_on(struct drm_crtc *crtc) -{ -	drm_vblank_on(crtc->dev, drm_crtc_index(crtc)); -}  EXPORT_SYMBOL(drm_crtc_vblank_on); -/** - * drm_vblank_pre_modeset - account for vblanks across mode sets - * @dev: DRM device - * @pipe: CRTC index - * - * Account for vblank events across mode setting events, which will likely - * reset the hardware frame counter. - * - * This is done by grabbing a temporary vblank reference to ensure that the - * vblank interrupt keeps running across the modeset sequence. With this the - * software-side vblank frame counting will ensure that there are no jumps or - * discontinuities. - * - * Unfortunately this approach is racy and also doesn't work when the vblank - * interrupt stops running, e.g. across system suspend resume. It is therefore - * highly recommended that drivers use the newer drm_vblank_off() and - * drm_vblank_on() instead. drm_vblank_pre_modeset() only works correctly when - * using "cooked" software vblank frame counters and not relying on any hardware - * counters. - * - * Drivers must call drm_vblank_post_modeset() when re-enabling the same crtc - * again. - */ -void drm_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe) +static void drm_legacy_vblank_pre_modeset(struct drm_device *dev, +					  unsigned int pipe)  {  	struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; @@ -1490,17 +1416,9 @@ void drm_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe)  			vblank->inmodeset |= 0x2;  	}  } -EXPORT_SYMBOL(drm_vblank_pre_modeset); -/** - * drm_vblank_post_modeset - undo drm_vblank_pre_modeset changes - * @dev: DRM device - * @pipe: CRTC index - * - * This function again drops the temporary vblank reference acquired in - * drm_vblank_pre_modeset. - */ -void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe) +static void drm_legacy_vblank_post_modeset(struct drm_device *dev, +					   unsigned int pipe)  {  	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];  	unsigned long irqflags; @@ -1523,7 +1441,6 @@ void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe)  		vblank->inmodeset = 0;  	}  } -EXPORT_SYMBOL(drm_vblank_post_modeset);  /*   * drm_modeset_ctl - handle vblank event counter changes across mode switch @@ -1556,10 +1473,10 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,  	switch (modeset->cmd) {  	case _DRM_PRE_MODESET: -		drm_vblank_pre_modeset(dev, pipe); +		drm_legacy_vblank_pre_modeset(dev, pipe);  		break;  	case _DRM_POST_MODESET: -		drm_vblank_post_modeset(dev, pipe); +		drm_legacy_vblank_post_modeset(dev, pipe);  		break;  	default:  		return -EINVAL; @@ -1594,11 +1511,10 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,  	spin_lock_irqsave(&dev->event_lock, flags);  	/* -	 * drm_vblank_off() might have been called after we called -	 * drm_vblank_get(). drm_vblank_off() holds event_lock -	 * around the vblank disable, so no need for further locking. -	 * The reference from drm_vblank_get() protects against -	 * vblank disable from another source. +	 * drm_crtc_vblank_off() might have been called after we called +	 * drm_vblank_get(). drm_crtc_vblank_off() holds event_lock around the +	 * vblank disable, so no need for further locking.  The reference from +	 * drm_vblank_get() protects against vblank disable from another source.  	 */  	if (!vblank->enabled) {  		ret = -EINVAL;  |