Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 84e35483 authored by Shawn Guo's avatar Shawn Guo Committed by Daniel Vetter
Browse files

drm: add vblank hooks to struct drm_crtc_funcs



The vblank is mostly CRTC specific and implemented as part of CRTC
driver.  Let's keep the vblank hooks struct drm_driver for legacy
drivers, and add corresponding hooks in struct drm_crtc_funcs.  These
hooks take struct drm_crtc pointer as argument, and will be called by
core vblank handling code for DRIVER_MODESET drivers.

The new hooks get plugged into core by adding wrapper functions for
vblank handling code.  The .get_vblank_counter hook is effectively
optional, as we provide drm_vblank_no_hw_counter() as the default
fallback in the wrapper function.

Signed-off-by: default avatarShawn Guo <shawn.guo@linaro.org>
Reviewed-by: default avatarAndrzej Hajda <a.hajda@samsung.com>
Acked-by: default avatarThierry Reding <treding@nvidia.com>
Reviewed-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Link: http://patchwork.freedesktop.org/patch/msgid/1486458995-31018-2-git-send-email-shawnguo@kernel.org
parent da7bdda2
Loading
Loading
Loading
Loading
+47 −6
Original line number Original line Diff line number Diff line
@@ -89,6 +89,21 @@ static void store_vblank(struct drm_device *dev, unsigned int pipe,
	write_sequnlock(&vblank->seqlock);
	write_sequnlock(&vblank->seqlock);
}
}


static u32 __get_vblank_counter(struct drm_device *dev, unsigned int pipe)
{
	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
		struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);

		if (crtc->funcs->get_vblank_counter)
			return crtc->funcs->get_vblank_counter(crtc);
	}

	if (dev->driver->get_vblank_counter)
		return dev->driver->get_vblank_counter(dev, pipe);

	return drm_vblank_no_hw_counter(dev, pipe);
}

/*
/*
 * Reset the stored timestamp for the current vblank count to correspond
 * Reset the stored timestamp for the current vblank count to correspond
 * to the last vblank occurred.
 * to the last vblank occurred.
@@ -112,9 +127,9 @@ static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe
	 * when drm_vblank_enable() applies the diff
	 * when drm_vblank_enable() applies the diff
	 */
	 */
	do {
	do {
		cur_vblank = dev->driver->get_vblank_counter(dev, pipe);
		cur_vblank = __get_vblank_counter(dev, pipe);
		rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, 0);
		rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, 0);
	} while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe) && --count > 0);
	} while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);


	/*
	/*
	 * Only reinitialize corresponding vblank timestamp if high-precision query
	 * Only reinitialize corresponding vblank timestamp if high-precision query
@@ -168,9 +183,9 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
	 * corresponding vblank timestamp.
	 * corresponding vblank timestamp.
	 */
	 */
	do {
	do {
		cur_vblank = dev->driver->get_vblank_counter(dev, pipe);
		cur_vblank = __get_vblank_counter(dev, pipe);
		rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, flags);
		rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, flags);
	} while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe) && --count > 0);
	} while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);


	if (dev->max_vblank_count != 0) {
	if (dev->max_vblank_count != 0) {
		/* trust the hw counter when it's around */
		/* trust the hw counter when it's around */
@@ -275,6 +290,20 @@ u32 drm_accurate_vblank_count(struct drm_crtc *crtc)
}
}
EXPORT_SYMBOL(drm_accurate_vblank_count);
EXPORT_SYMBOL(drm_accurate_vblank_count);


static void __disable_vblank(struct drm_device *dev, unsigned int pipe)
{
	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
		struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);

		if (crtc->funcs->disable_vblank) {
			crtc->funcs->disable_vblank(crtc);
			return;
		}
	}

	dev->driver->disable_vblank(dev, pipe);
}

/*
/*
 * Disable vblank irq's on crtc, make sure that last vblank count
 * Disable vblank irq's on crtc, make sure that last vblank count
 * of hardware and corresponding consistent software vblank counter
 * of hardware and corresponding consistent software vblank counter
@@ -298,7 +327,7 @@ static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe)
	 * hardware potentially runtime suspended.
	 * hardware potentially runtime suspended.
	 */
	 */
	if (vblank->enabled) {
	if (vblank->enabled) {
		dev->driver->disable_vblank(dev, pipe);
		__disable_vblank(dev, pipe);
		vblank->enabled = false;
		vblank->enabled = false;
	}
	}


@@ -1027,6 +1056,18 @@ void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
}
}
EXPORT_SYMBOL(drm_crtc_send_vblank_event);
EXPORT_SYMBOL(drm_crtc_send_vblank_event);


static int __enable_vblank(struct drm_device *dev, unsigned int pipe)
{
	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
		struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);

		if (crtc->funcs->enable_vblank)
			return crtc->funcs->enable_vblank(crtc);
	}

	return dev->driver->enable_vblank(dev, pipe);
}

/**
/**
 * drm_vblank_enable - enable the vblank interrupt on a CRTC
 * drm_vblank_enable - enable the vblank interrupt on a CRTC
 * @dev: DRM device
 * @dev: DRM device
@@ -1052,7 +1093,7 @@ static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe)
		 * timestamps. Filtercode in drm_handle_vblank() will
		 * timestamps. Filtercode in drm_handle_vblank() will
		 * prevent double-accounting of same vblank interval.
		 * prevent double-accounting of same vblank interval.
		 */
		 */
		ret = dev->driver->enable_vblank(dev, pipe);
		ret = __enable_vblank(dev, pipe);
		DRM_DEBUG("enabling vblank on crtc %u, ret: %d\n", pipe, ret);
		DRM_DEBUG("enabling vblank on crtc %u, ret: %d\n", pipe, ret);
		if (ret)
		if (ret)
			atomic_dec(&vblank->refcount);
			atomic_dec(&vblank->refcount);
+44 −0
Original line number Original line Diff line number Diff line
@@ -608,6 +608,50 @@ struct drm_crtc_funcs {
	 */
	 */
	void (*atomic_print_state)(struct drm_printer *p,
	void (*atomic_print_state)(struct drm_printer *p,
				   const struct drm_crtc_state *state);
				   const struct drm_crtc_state *state);

	/**
	 * @get_vblank_counter:
	 *
	 * Driver callback for fetching a raw hardware vblank counter for the
	 * CRTC. It's meant to be used by new drivers as the replacement of
	 * &drm_driver.get_vblank_counter hook.
	 *
	 * This callback is optional. If a device doesn't have a hardware
	 * counter, the driver can simply leave the hook as NULL. The DRM core
	 * will account for missed vblank events while interrupts where disabled
	 * based on system timestamps.
	 *
	 * Wraparound handling and loss of events due to modesetting is dealt
	 * with in the DRM core code, as long as drivers call
	 * drm_crtc_vblank_off() and drm_crtc_vblank_on() when disabling or
	 * enabling a CRTC.
	 *
	 * Returns:
	 *
	 * Raw vblank counter value.
	 */
	u32 (*get_vblank_counter)(struct drm_crtc *crtc);

	/**
	 * @enable_vblank:
	 *
	 * Enable vblank interrupts for the CRTC. It's meant to be used by
	 * new drivers as the replacement of &drm_driver.enable_vblank hook.
	 *
	 * Returns:
	 *
	 * Zero on success, appropriate errno if the vblank interrupt cannot
	 * be enabled.
	 */
	int (*enable_vblank)(struct drm_crtc *crtc);

	/**
	 * @disable_vblank:
	 *
	 * Disable vblank interrupts for the CRTC. It's meant to be used by
	 * new drivers as the replacement of &drm_driver.disable_vblank hook.
	 */
	void (*disable_vblank)(struct drm_crtc *crtc);
};
};


/**
/**
+9 −0
Original line number Original line Diff line number Diff line
@@ -130,6 +130,9 @@ struct drm_driver {
	 * drm_crtc_vblank_off() and drm_crtc_vblank_on() when disabling or
	 * drm_crtc_vblank_off() and drm_crtc_vblank_on() when disabling or
	 * enabling a CRTC.
	 * enabling a CRTC.
	 *
	 *
	 * This is deprecated and should not be used by new drivers.
	 * Use &drm_crtc_funcs.get_vblank_counter instead.
	 *
	 * Returns:
	 * Returns:
	 *
	 *
	 * Raw vblank counter value.
	 * Raw vblank counter value.
@@ -142,6 +145,9 @@ struct drm_driver {
	 * Enable vblank interrupts for the CRTC specified with the pipe
	 * Enable vblank interrupts for the CRTC specified with the pipe
	 * argument.
	 * argument.
	 *
	 *
	 * This is deprecated and should not be used by new drivers.
	 * Use &drm_crtc_funcs.enable_vblank instead.
	 *
	 * Returns:
	 * Returns:
	 *
	 *
	 * Zero on success, appropriate errno if the given @crtc's vblank
	 * Zero on success, appropriate errno if the given @crtc's vblank
@@ -154,6 +160,9 @@ struct drm_driver {
	 *
	 *
	 * Disable vblank interrupts for the CRTC specified with the pipe
	 * Disable vblank interrupts for the CRTC specified with the pipe
	 * argument.
	 * argument.
	 *
	 * This is deprecated and should not be used by new drivers.
	 * Use &drm_crtc_funcs.disable_vblank instead.
	 */
	 */
	void (*disable_vblank) (struct drm_device *dev, unsigned int pipe);
	void (*disable_vblank) (struct drm_device *dev, unsigned int pipe);