xref: /openbmc/linux/drivers/gpu/drm/drm_vblank.c (revision 6f1ccbf0)
13ed4351aSDaniel Vetter /*
23ed4351aSDaniel Vetter  * drm_irq.c IRQ and vblank support
33ed4351aSDaniel Vetter  *
43ed4351aSDaniel Vetter  * \author Rickard E. (Rik) Faith <faith@valinux.com>
53ed4351aSDaniel Vetter  * \author Gareth Hughes <gareth@valinux.com>
63ed4351aSDaniel Vetter  *
73ed4351aSDaniel Vetter  * Permission is hereby granted, free of charge, to any person obtaining a
83ed4351aSDaniel Vetter  * copy of this software and associated documentation files (the "Software"),
93ed4351aSDaniel Vetter  * to deal in the Software without restriction, including without limitation
103ed4351aSDaniel Vetter  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
113ed4351aSDaniel Vetter  * and/or sell copies of the Software, and to permit persons to whom the
123ed4351aSDaniel Vetter  * Software is furnished to do so, subject to the following conditions:
133ed4351aSDaniel Vetter  *
143ed4351aSDaniel Vetter  * The above copyright notice and this permission notice (including the next
153ed4351aSDaniel Vetter  * paragraph) shall be included in all copies or substantial portions of the
163ed4351aSDaniel Vetter  * Software.
173ed4351aSDaniel Vetter  *
183ed4351aSDaniel Vetter  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
193ed4351aSDaniel Vetter  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
203ed4351aSDaniel Vetter  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
213ed4351aSDaniel Vetter  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
223ed4351aSDaniel Vetter  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
233ed4351aSDaniel Vetter  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
243ed4351aSDaniel Vetter  * OTHER DEALINGS IN THE SOFTWARE.
253ed4351aSDaniel Vetter  */
263ed4351aSDaniel Vetter 
273ed4351aSDaniel Vetter #include <linux/export.h>
285e6c2b4fSLyude Paul #include <linux/kthread.h>
290500c04eSSam Ravnborg #include <linux/moduleparam.h>
303ed4351aSDaniel Vetter 
310500c04eSSam Ravnborg #include <drm/drm_crtc.h>
320500c04eSSam Ravnborg #include <drm/drm_drv.h>
330500c04eSSam Ravnborg #include <drm/drm_framebuffer.h>
34c23d686fSDaniel Vetter #include <drm/drm_managed.h>
35f1e2b637SThomas Zimmermann #include <drm/drm_modeset_helper_vtables.h>
360500c04eSSam Ravnborg #include <drm/drm_print.h>
370500c04eSSam Ravnborg #include <drm/drm_vblank.h>
380500c04eSSam Ravnborg 
393ed4351aSDaniel Vetter #include "drm_internal.h"
400500c04eSSam Ravnborg #include "drm_trace.h"
413ed4351aSDaniel Vetter 
4257d30230SDaniel Vetter /**
4357d30230SDaniel Vetter  * DOC: vblank handling
4457d30230SDaniel Vetter  *
4556b165feSSam Ravnborg  * From the computer's perspective, every time the monitor displays
4656b165feSSam Ravnborg  * a new frame the scanout engine has "scanned out" the display image
4756b165feSSam Ravnborg  * from top to bottom, one row of pixels at a time. The current row
4856b165feSSam Ravnborg  * of pixels is referred to as the current scanline.
4956b165feSSam Ravnborg  *
5056b165feSSam Ravnborg  * In addition to the display's visible area, there's usually a couple of
5156b165feSSam Ravnborg  * extra scanlines which aren't actually displayed on the screen.
5256b165feSSam Ravnborg  * These extra scanlines don't contain image data and are occasionally used
5356b165feSSam Ravnborg  * for features like audio and infoframes. The region made up of these
5456b165feSSam Ravnborg  * scanlines is referred to as the vertical blanking region, or vblank for
5556b165feSSam Ravnborg  * short.
5656b165feSSam Ravnborg  *
5756b165feSSam Ravnborg  * For historical reference, the vertical blanking period was designed to
5856b165feSSam Ravnborg  * give the electron gun (on CRTs) enough time to move back to the top of
5956b165feSSam Ravnborg  * the screen to start scanning out the next frame. Similar for horizontal
6056b165feSSam Ravnborg  * blanking periods. They were designed to give the electron gun enough
6156b165feSSam Ravnborg  * time to move back to the other side of the screen to start scanning the
6256b165feSSam Ravnborg  * next scanline.
6356b165feSSam Ravnborg  *
6456b165feSSam Ravnborg  * ::
6556b165feSSam Ravnborg  *
6656b165feSSam Ravnborg  *
6756b165feSSam Ravnborg  *    physical →   ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽
6856b165feSSam Ravnborg  *    top of      |                                        |
6956b165feSSam Ravnborg  *    display     |                                        |
7056b165feSSam Ravnborg  *                |               New frame                |
7156b165feSSam Ravnborg  *                |                                        |
7256b165feSSam Ravnborg  *                |↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓|
7356b165feSSam Ravnborg  *                |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| ← Scanline,
7456b165feSSam Ravnborg  *                |↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓|   updates the
7556b165feSSam Ravnborg  *                |                                        |   frame as it
7656b165feSSam Ravnborg  *                |                                        |   travels down
778323c625SSumera Priyadarsini  *                |                                        |   ("scan out")
7856b165feSSam Ravnborg  *                |               Old frame                |
7956b165feSSam Ravnborg  *                |                                        |
8056b165feSSam Ravnborg  *                |                                        |
8156b165feSSam Ravnborg  *                |                                        |
8256b165feSSam Ravnborg  *                |                                        |   physical
8356b165feSSam Ravnborg  *                |                                        |   bottom of
8456b165feSSam Ravnborg  *    vertical    |⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽| ← display
8556b165feSSam Ravnborg  *    blanking    ┆xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx┆
8656b165feSSam Ravnborg  *    region   →  ┆xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx┆
8756b165feSSam Ravnborg  *                ┆xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx┆
8856b165feSSam Ravnborg  *    start of →   ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽
8956b165feSSam Ravnborg  *    new frame
9056b165feSSam Ravnborg  *
9156b165feSSam Ravnborg  * "Physical top of display" is the reference point for the high-precision/
9256b165feSSam Ravnborg  * corrected timestamp.
9356b165feSSam Ravnborg  *
9456b165feSSam Ravnborg  * On a lot of display hardware, programming needs to take effect during the
9556b165feSSam Ravnborg  * vertical blanking period so that settings like gamma, the image buffer
9656b165feSSam Ravnborg  * buffer to be scanned out, etc. can safely be changed without showing
9756b165feSSam Ravnborg  * any visual artifacts on the screen. In some unforgiving hardware, some of
9856b165feSSam Ravnborg  * this programming has to both start and end in the same vblank. To help
9956b165feSSam Ravnborg  * with the timing of the hardware programming, an interrupt is usually
10056b165feSSam Ravnborg  * available to notify the driver when it can start the updating of registers.
10156b165feSSam Ravnborg  * The interrupt is in this context named the vblank interrupt.
10256b165feSSam Ravnborg  *
10356b165feSSam Ravnborg  * The vblank interrupt may be fired at different points depending on the
10456b165feSSam Ravnborg  * hardware. Some hardware implementations will fire the interrupt when the
10556b165feSSam Ravnborg  * new frame start, other implementations will fire the interrupt at different
10656b165feSSam Ravnborg  * points in time.
10756b165feSSam Ravnborg  *
10857d30230SDaniel Vetter  * Vertical blanking plays a major role in graphics rendering. To achieve
10957d30230SDaniel Vetter  * tear-free display, users must synchronize page flips and/or rendering to
11057d30230SDaniel Vetter  * vertical blanking. The DRM API offers ioctls to perform page flips
11157d30230SDaniel Vetter  * synchronized to vertical blanking and wait for vertical blanking.
11257d30230SDaniel Vetter  *
11357d30230SDaniel Vetter  * The DRM core handles most of the vertical blanking management logic, which
11457d30230SDaniel Vetter  * involves filtering out spurious interrupts, keeping race-free blanking
11557d30230SDaniel Vetter  * counters, coping with counter wrap-around and resets and keeping use counts.
11657d30230SDaniel Vetter  * It relies on the driver to generate vertical blanking interrupts and
11757d30230SDaniel Vetter  * optionally provide a hardware vertical blanking counter.
11857d30230SDaniel Vetter  *
11957d30230SDaniel Vetter  * Drivers must initialize the vertical blanking handling core with a call to
12057d30230SDaniel Vetter  * drm_vblank_init(). Minimally, a driver needs to implement
12157d30230SDaniel Vetter  * &drm_crtc_funcs.enable_vblank and &drm_crtc_funcs.disable_vblank plus call
1221e55a53aSMatt Roper  * drm_crtc_handle_vblank() in its vblank interrupt handler for working vblank
12357d30230SDaniel Vetter  * support.
12457d30230SDaniel Vetter  *
12557d30230SDaniel Vetter  * Vertical blanking interrupts can be enabled by the DRM core or by drivers
12657d30230SDaniel Vetter  * themselves (for instance to handle page flipping operations).  The DRM core
12757d30230SDaniel Vetter  * maintains a vertical blanking use count to ensure that the interrupts are not
12857d30230SDaniel Vetter  * disabled while a user still needs them. To increment the use count, drivers
12957d30230SDaniel Vetter  * call drm_crtc_vblank_get() and release the vblank reference again with
13057d30230SDaniel Vetter  * drm_crtc_vblank_put(). In between these two calls vblank interrupts are
13157d30230SDaniel Vetter  * guaranteed to be enabled.
13257d30230SDaniel Vetter  *
13357d30230SDaniel Vetter  * On many hardware disabling the vblank interrupt cannot be done in a race-free
13457d30230SDaniel Vetter  * manner, see &drm_driver.vblank_disable_immediate and
13557d30230SDaniel Vetter  * &drm_driver.max_vblank_count. In that case the vblank core only disables the
13657d30230SDaniel Vetter  * vblanks after a timer has expired, which can be configured through the
13757d30230SDaniel Vetter  * ``vblankoffdelay`` module parameter.
1387beb691fSThomas Zimmermann  *
1397beb691fSThomas Zimmermann  * Drivers for hardware without support for vertical-blanking interrupts
1407beb691fSThomas Zimmermann  * must not call drm_vblank_init(). For such drivers, atomic helpers will
1417beb691fSThomas Zimmermann  * automatically generate fake vblank events as part of the display update.
1427beb691fSThomas Zimmermann  * This functionality also can be controlled by the driver by enabling and
1437beb691fSThomas Zimmermann  * disabling struct drm_crtc_state.no_vblank.
14457d30230SDaniel Vetter  */
14557d30230SDaniel Vetter 
1463ed4351aSDaniel Vetter /* Retry timestamp calculation up to 3 times to satisfy
1473ed4351aSDaniel Vetter  * drm_timestamp_precision before giving up.
1483ed4351aSDaniel Vetter  */
1493ed4351aSDaniel Vetter #define DRM_TIMESTAMP_MAXRETRIES 3
1503ed4351aSDaniel Vetter 
1513ed4351aSDaniel Vetter /* Threshold in nanoseconds for detection of redundant
1523ed4351aSDaniel Vetter  * vblank irq in drm_handle_vblank(). 1 msec should be ok.
1533ed4351aSDaniel Vetter  */
1543ed4351aSDaniel Vetter #define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000
1553ed4351aSDaniel Vetter 
1563ed4351aSDaniel Vetter static bool
1573ed4351aSDaniel Vetter drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
15867680d3cSArnd Bergmann 			  ktime_t *tvblank, bool in_vblank_irq);
1593ed4351aSDaniel Vetter 
1603ed4351aSDaniel Vetter static unsigned int drm_timestamp_precision = 20;  /* Default to 20 usecs. */
1613ed4351aSDaniel Vetter 
1623ed4351aSDaniel Vetter static int drm_vblank_offdelay = 5000;    /* Default to 5000 msecs. */
1633ed4351aSDaniel Vetter 
1643ed4351aSDaniel Vetter module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
1653ed4351aSDaniel Vetter module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
1663ed4351aSDaniel Vetter MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs] (0: never disable, <0: disable immediately)");
1673ed4351aSDaniel Vetter MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
1683ed4351aSDaniel Vetter 
store_vblank(struct drm_device * dev,unsigned int pipe,u32 vblank_count_inc,ktime_t t_vblank,u32 last)1693ed4351aSDaniel Vetter static void store_vblank(struct drm_device *dev, unsigned int pipe,
1703ed4351aSDaniel Vetter 			 u32 vblank_count_inc,
17167680d3cSArnd Bergmann 			 ktime_t t_vblank, u32 last)
1723ed4351aSDaniel Vetter {
1733ed4351aSDaniel Vetter 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
1743ed4351aSDaniel Vetter 
1753ed4351aSDaniel Vetter 	assert_spin_locked(&dev->vblank_time_lock);
1763ed4351aSDaniel Vetter 
1773ed4351aSDaniel Vetter 	vblank->last = last;
1783ed4351aSDaniel Vetter 
1793ed4351aSDaniel Vetter 	write_seqlock(&vblank->seqlock);
18067680d3cSArnd Bergmann 	vblank->time = t_vblank;
181bd7e3f3bSDaniel Vetter 	atomic64_add(vblank_count_inc, &vblank->count);
1823ed4351aSDaniel Vetter 	write_sequnlock(&vblank->seqlock);
1833ed4351aSDaniel Vetter }
1843ed4351aSDaniel Vetter 
drm_max_vblank_count(struct drm_device * dev,unsigned int pipe)185ed20151aSVille Syrjälä static u32 drm_max_vblank_count(struct drm_device *dev, unsigned int pipe)
186ed20151aSVille Syrjälä {
187ed20151aSVille Syrjälä 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
188ed20151aSVille Syrjälä 
189ed20151aSVille Syrjälä 	return vblank->max_vblank_count ?: dev->max_vblank_count;
190ed20151aSVille Syrjälä }
191ed20151aSVille Syrjälä 
1923ed4351aSDaniel Vetter /*
1933ed4351aSDaniel Vetter  * "No hw counter" fallback implementation of .get_vblank_counter() hook,
1940ae865efSCai Huoqing  * if there is no usable hardware frame counter available.
1953ed4351aSDaniel Vetter  */
drm_vblank_no_hw_counter(struct drm_device * dev,unsigned int pipe)1963ed4351aSDaniel Vetter static u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe)
1973ed4351aSDaniel Vetter {
1985a4784f4SSam Ravnborg 	drm_WARN_ON_ONCE(dev, drm_max_vblank_count(dev, pipe) != 0);
1993ed4351aSDaniel Vetter 	return 0;
2003ed4351aSDaniel Vetter }
2013ed4351aSDaniel Vetter 
__get_vblank_counter(struct drm_device * dev,unsigned int pipe)2023ed4351aSDaniel Vetter static u32 __get_vblank_counter(struct drm_device *dev, unsigned int pipe)
2033ed4351aSDaniel Vetter {
2043ed4351aSDaniel Vetter 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
2053ed4351aSDaniel Vetter 		struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
2063ed4351aSDaniel Vetter 
2075a4784f4SSam Ravnborg 		if (drm_WARN_ON(dev, !crtc))
2084ffb8deeSJoe Moriarty 			return 0;
2094ffb8deeSJoe Moriarty 
2103ed4351aSDaniel Vetter 		if (crtc->funcs->get_vblank_counter)
2113ed4351aSDaniel Vetter 			return crtc->funcs->get_vblank_counter(crtc);
21257bb1ee6SDaniel Vetter 	}
21357bb1ee6SDaniel Vetter #ifdef CONFIG_DRM_LEGACY
21457bb1ee6SDaniel Vetter 	else if (dev->driver->get_vblank_counter) {
2153ed4351aSDaniel Vetter 		return dev->driver->get_vblank_counter(dev, pipe);
216f397d66bSThomas Zimmermann 	}
21757bb1ee6SDaniel Vetter #endif
2183ed4351aSDaniel Vetter 
2193ed4351aSDaniel Vetter 	return drm_vblank_no_hw_counter(dev, pipe);
2203ed4351aSDaniel Vetter }
2213ed4351aSDaniel Vetter 
2223ed4351aSDaniel Vetter /*
2233ed4351aSDaniel Vetter  * Reset the stored timestamp for the current vblank count to correspond
2243ed4351aSDaniel Vetter  * to the last vblank occurred.
2253ed4351aSDaniel Vetter  *
2263ed4351aSDaniel Vetter  * Only to be called from drm_crtc_vblank_on().
2273ed4351aSDaniel Vetter  *
2283ed4351aSDaniel Vetter  * Note: caller must hold &drm_device.vbl_lock since this reads & writes
2293ed4351aSDaniel Vetter  * device vblank fields.
2303ed4351aSDaniel Vetter  */
drm_reset_vblank_timestamp(struct drm_device * dev,unsigned int pipe)2313ed4351aSDaniel Vetter static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe)
2323ed4351aSDaniel Vetter {
2333ed4351aSDaniel Vetter 	u32 cur_vblank;
2343ed4351aSDaniel Vetter 	bool rc;
23567680d3cSArnd Bergmann 	ktime_t t_vblank;
2363ed4351aSDaniel Vetter 	int count = DRM_TIMESTAMP_MAXRETRIES;
2373ed4351aSDaniel Vetter 
2383ed4351aSDaniel Vetter 	spin_lock(&dev->vblank_time_lock);
2393ed4351aSDaniel Vetter 
2403ed4351aSDaniel Vetter 	/*
2413ed4351aSDaniel Vetter 	 * sample the current counter to avoid random jumps
2423ed4351aSDaniel Vetter 	 * when drm_vblank_enable() applies the diff
2433ed4351aSDaniel Vetter 	 */
2443ed4351aSDaniel Vetter 	do {
2453ed4351aSDaniel Vetter 		cur_vblank = __get_vblank_counter(dev, pipe);
2463ed4351aSDaniel Vetter 		rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, false);
2473ed4351aSDaniel Vetter 	} while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
2483ed4351aSDaniel Vetter 
2493ed4351aSDaniel Vetter 	/*
2503ed4351aSDaniel Vetter 	 * Only reinitialize corresponding vblank timestamp if high-precision query
2513ed4351aSDaniel Vetter 	 * available and didn't fail. Otherwise reinitialize delayed at next vblank
2523ed4351aSDaniel Vetter 	 * interrupt and assign 0 for now, to mark the vblanktimestamp as invalid.
2533ed4351aSDaniel Vetter 	 */
2543ed4351aSDaniel Vetter 	if (!rc)
25567680d3cSArnd Bergmann 		t_vblank = 0;
2563ed4351aSDaniel Vetter 
2573ed4351aSDaniel Vetter 	/*
2583ed4351aSDaniel Vetter 	 * +1 to make sure user will never see the same
2593ed4351aSDaniel Vetter 	 * vblank counter value before and after a modeset
2603ed4351aSDaniel Vetter 	 */
26167680d3cSArnd Bergmann 	store_vblank(dev, pipe, 1, t_vblank, cur_vblank);
2623ed4351aSDaniel Vetter 
2633ed4351aSDaniel Vetter 	spin_unlock(&dev->vblank_time_lock);
2643ed4351aSDaniel Vetter }
2653ed4351aSDaniel Vetter 
2663ed4351aSDaniel Vetter /*
2673ed4351aSDaniel Vetter  * Call back into the driver to update the appropriate vblank counter
2683ed4351aSDaniel Vetter  * (specified by @pipe).  Deal with wraparound, if it occurred, and
2693ed4351aSDaniel Vetter  * update the last read value so we can deal with wraparound on the next
2703ed4351aSDaniel Vetter  * call if necessary.
2713ed4351aSDaniel Vetter  *
2723ed4351aSDaniel Vetter  * Only necessary when going from off->on, to account for frames we
2733ed4351aSDaniel Vetter  * didn't get an interrupt for.
2743ed4351aSDaniel Vetter  *
2753ed4351aSDaniel Vetter  * Note: caller must hold &drm_device.vbl_lock since this reads & writes
2763ed4351aSDaniel Vetter  * device vblank fields.
2773ed4351aSDaniel Vetter  */
drm_update_vblank_count(struct drm_device * dev,unsigned int pipe,bool in_vblank_irq)2783ed4351aSDaniel Vetter static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
2793ed4351aSDaniel Vetter 				    bool in_vblank_irq)
2803ed4351aSDaniel Vetter {
2813ed4351aSDaniel Vetter 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
2823ed4351aSDaniel Vetter 	u32 cur_vblank, diff;
2833ed4351aSDaniel Vetter 	bool rc;
28467680d3cSArnd Bergmann 	ktime_t t_vblank;
2853ed4351aSDaniel Vetter 	int count = DRM_TIMESTAMP_MAXRETRIES;
2863ed4351aSDaniel Vetter 	int framedur_ns = vblank->framedur_ns;
287ed20151aSVille Syrjälä 	u32 max_vblank_count = drm_max_vblank_count(dev, pipe);
2883ed4351aSDaniel Vetter 
2893ed4351aSDaniel Vetter 	/*
2903ed4351aSDaniel Vetter 	 * Interrupts were disabled prior to this call, so deal with counter
2913ed4351aSDaniel Vetter 	 * wrap if needed.
2923ed4351aSDaniel Vetter 	 * NOTE!  It's possible we lost a full dev->max_vblank_count + 1 events
2933ed4351aSDaniel Vetter 	 * here if the register is small or we had vblank interrupts off for
2943ed4351aSDaniel Vetter 	 * a long time.
2953ed4351aSDaniel Vetter 	 *
2963ed4351aSDaniel Vetter 	 * We repeat the hardware vblank counter & timestamp query until
2973ed4351aSDaniel Vetter 	 * we get consistent results. This to prevent races between gpu
2983ed4351aSDaniel Vetter 	 * updating its hardware counter while we are retrieving the
2993ed4351aSDaniel Vetter 	 * corresponding vblank timestamp.
3003ed4351aSDaniel Vetter 	 */
3013ed4351aSDaniel Vetter 	do {
3023ed4351aSDaniel Vetter 		cur_vblank = __get_vblank_counter(dev, pipe);
3033ed4351aSDaniel Vetter 		rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, in_vblank_irq);
3043ed4351aSDaniel Vetter 	} while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
3053ed4351aSDaniel Vetter 
306ed20151aSVille Syrjälä 	if (max_vblank_count) {
3073ed4351aSDaniel Vetter 		/* trust the hw counter when it's around */
308ed20151aSVille Syrjälä 		diff = (cur_vblank - vblank->last) & max_vblank_count;
3093ed4351aSDaniel Vetter 	} else if (rc && framedur_ns) {
31067680d3cSArnd Bergmann 		u64 diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time));
3113ed4351aSDaniel Vetter 
3123ed4351aSDaniel Vetter 		/*
3133ed4351aSDaniel Vetter 		 * Figure out how many vblanks we've missed based
3143ed4351aSDaniel Vetter 		 * on the difference in the timestamps and the
3153ed4351aSDaniel Vetter 		 * frame/field duration.
3163ed4351aSDaniel Vetter 		 */
31741ff5bd8SOleg Vasilev 
31802149a76SSam Ravnborg 		drm_dbg_vbl(dev, "crtc %u: Calculating number of vblanks."
31941ff5bd8SOleg Vasilev 			    " diff_ns = %lld, framedur_ns = %d)\n",
32041ff5bd8SOleg Vasilev 			    pipe, (long long)diff_ns, framedur_ns);
32141ff5bd8SOleg Vasilev 
3223ed4351aSDaniel Vetter 		diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns);
3233ed4351aSDaniel Vetter 
3243ed4351aSDaniel Vetter 		if (diff == 0 && in_vblank_irq)
32502149a76SSam Ravnborg 			drm_dbg_vbl(dev, "crtc %u: Redundant vblirq ignored\n",
32641ff5bd8SOleg Vasilev 				    pipe);
3273ed4351aSDaniel Vetter 	} else {
3283ed4351aSDaniel Vetter 		/* some kind of default for drivers w/o accurate vbl timestamping */
3293ed4351aSDaniel Vetter 		diff = in_vblank_irq ? 1 : 0;
3303ed4351aSDaniel Vetter 	}
3313ed4351aSDaniel Vetter 
3323ed4351aSDaniel Vetter 	/*
3333ed4351aSDaniel Vetter 	 * Within a drm_vblank_pre_modeset - drm_vblank_post_modeset
3343ed4351aSDaniel Vetter 	 * interval? If so then vblank irqs keep running and it will likely
3353ed4351aSDaniel Vetter 	 * happen that the hardware vblank counter is not trustworthy as it
3363ed4351aSDaniel Vetter 	 * might reset at some point in that interval and vblank timestamps
3373ed4351aSDaniel Vetter 	 * are not trustworthy either in that interval. Iow. this can result
3383ed4351aSDaniel Vetter 	 * in a bogus diff >> 1 which must be avoided as it would cause
3393ed4351aSDaniel Vetter 	 * random large forward jumps of the software vblank counter.
3403ed4351aSDaniel Vetter 	 */
3413ed4351aSDaniel Vetter 	if (diff > 1 && (vblank->inmodeset & 0x2)) {
34202149a76SSam Ravnborg 		drm_dbg_vbl(dev,
34302149a76SSam Ravnborg 			    "clamping vblank bump to 1 on crtc %u: diffr=%u"
3443ed4351aSDaniel Vetter 			    " due to pre-modeset.\n", pipe, diff);
3453ed4351aSDaniel Vetter 		diff = 1;
3463ed4351aSDaniel Vetter 	}
3473ed4351aSDaniel Vetter 
34802149a76SSam Ravnborg 	drm_dbg_vbl(dev, "updating vblank count on crtc %u:"
349570e8696SKeith Packard 		    " current=%llu, diff=%u, hw=%u hw_last=%u\n",
3509d81fe17SLyude Paul 		    pipe, (unsigned long long)atomic64_read(&vblank->count),
3519d81fe17SLyude Paul 		    diff, cur_vblank, vblank->last);
3523ed4351aSDaniel Vetter 
3533ed4351aSDaniel Vetter 	if (diff == 0) {
3545a4784f4SSam Ravnborg 		drm_WARN_ON_ONCE(dev, cur_vblank != vblank->last);
3553ed4351aSDaniel Vetter 		return;
3563ed4351aSDaniel Vetter 	}
3573ed4351aSDaniel Vetter 
3583ed4351aSDaniel Vetter 	/*
3593ed4351aSDaniel Vetter 	 * Only reinitialize corresponding vblank timestamp if high-precision query
3603ed4351aSDaniel Vetter 	 * available and didn't fail, or we were called from the vblank interrupt.
3613ed4351aSDaniel Vetter 	 * Otherwise reinitialize delayed at next vblank interrupt and assign 0
3623ed4351aSDaniel Vetter 	 * for now, to mark the vblanktimestamp as invalid.
3633ed4351aSDaniel Vetter 	 */
364138b87faSLaurent Pinchart 	if (!rc && !in_vblank_irq)
36567680d3cSArnd Bergmann 		t_vblank = 0;
3663ed4351aSDaniel Vetter 
36767680d3cSArnd Bergmann 	store_vblank(dev, pipe, diff, t_vblank, cur_vblank);
3683ed4351aSDaniel Vetter }
3693ed4351aSDaniel Vetter 
drm_vblank_count(struct drm_device * dev,unsigned int pipe)3705e6c2b4fSLyude Paul u64 drm_vblank_count(struct drm_device *dev, unsigned int pipe)
3713ed4351aSDaniel Vetter {
3723ed4351aSDaniel Vetter 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
373bd7e3f3bSDaniel Vetter 	u64 count;
3743ed4351aSDaniel Vetter 
3755a4784f4SSam Ravnborg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
3763ed4351aSDaniel Vetter 		return 0;
3773ed4351aSDaniel Vetter 
378bd7e3f3bSDaniel Vetter 	count = atomic64_read(&vblank->count);
379bd7e3f3bSDaniel Vetter 
380bd7e3f3bSDaniel Vetter 	/*
381bd7e3f3bSDaniel Vetter 	 * This read barrier corresponds to the implicit write barrier of the
382bd7e3f3bSDaniel Vetter 	 * write seqlock in store_vblank(). Note that this is the only place
383bd7e3f3bSDaniel Vetter 	 * where we need an explicit barrier, since all other access goes
384bd7e3f3bSDaniel Vetter 	 * through drm_vblank_count_and_time(), which already has the required
385bd7e3f3bSDaniel Vetter 	 * read barrier curtesy of the read seqlock.
386bd7e3f3bSDaniel Vetter 	 */
387bd7e3f3bSDaniel Vetter 	smp_rmb();
388bd7e3f3bSDaniel Vetter 
389bd7e3f3bSDaniel Vetter 	return count;
3903ed4351aSDaniel Vetter }
3913ed4351aSDaniel Vetter 
3923ed4351aSDaniel Vetter /**
393ca814b25SDaniel Vetter  * drm_crtc_accurate_vblank_count - retrieve the master vblank counter
3943ed4351aSDaniel Vetter  * @crtc: which counter to retrieve
3953ed4351aSDaniel Vetter  *
39657d30230SDaniel Vetter  * This function is similar to drm_crtc_vblank_count() but this function
39757d30230SDaniel Vetter  * interpolates to handle a race with vblank interrupts using the high precision
39857d30230SDaniel Vetter  * timestamping support.
3993ed4351aSDaniel Vetter  *
40057d30230SDaniel Vetter  * This is mostly useful for hardware that can obtain the scanout position, but
40157d30230SDaniel Vetter  * doesn't have a hardware frame counter.
4023ed4351aSDaniel Vetter  */
drm_crtc_accurate_vblank_count(struct drm_crtc * crtc)4033b765c0bSDhinakaran Pandiyan u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc)
4043ed4351aSDaniel Vetter {
4053ed4351aSDaniel Vetter 	struct drm_device *dev = crtc->dev;
4063ed4351aSDaniel Vetter 	unsigned int pipe = drm_crtc_index(crtc);
4073b765c0bSDhinakaran Pandiyan 	u64 vblank;
4083ed4351aSDaniel Vetter 	unsigned long flags;
4093ed4351aSDaniel Vetter 
4105a4784f4SSam Ravnborg 	drm_WARN_ONCE(dev, drm_debug_enabled(DRM_UT_VBL) &&
411f397d66bSThomas Zimmermann 		      !crtc->funcs->get_vblank_timestamp,
4123ed4351aSDaniel Vetter 		      "This function requires support for accurate vblank timestamps.");
4133ed4351aSDaniel Vetter 
4143ed4351aSDaniel Vetter 	spin_lock_irqsave(&dev->vblank_time_lock, flags);
4153ed4351aSDaniel Vetter 
4163ed4351aSDaniel Vetter 	drm_update_vblank_count(dev, pipe, false);
4173ed4351aSDaniel Vetter 	vblank = drm_vblank_count(dev, pipe);
4183ed4351aSDaniel Vetter 
4193ed4351aSDaniel Vetter 	spin_unlock_irqrestore(&dev->vblank_time_lock, flags);
4203ed4351aSDaniel Vetter 
4213ed4351aSDaniel Vetter 	return vblank;
4223ed4351aSDaniel Vetter }
423ca814b25SDaniel Vetter EXPORT_SYMBOL(drm_crtc_accurate_vblank_count);
4243ed4351aSDaniel Vetter 
__disable_vblank(struct drm_device * dev,unsigned int pipe)4253ed4351aSDaniel Vetter static void __disable_vblank(struct drm_device *dev, unsigned int pipe)
4263ed4351aSDaniel Vetter {
4273ed4351aSDaniel Vetter 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
4283ed4351aSDaniel Vetter 		struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
4293ed4351aSDaniel Vetter 
4305a4784f4SSam Ravnborg 		if (drm_WARN_ON(dev, !crtc))
4314ffb8deeSJoe Moriarty 			return;
4324ffb8deeSJoe Moriarty 
433f397d66bSThomas Zimmermann 		if (crtc->funcs->disable_vblank)
4343ed4351aSDaniel Vetter 			crtc->funcs->disable_vblank(crtc);
43557bb1ee6SDaniel Vetter 	}
43657bb1ee6SDaniel Vetter #ifdef CONFIG_DRM_LEGACY
43757bb1ee6SDaniel Vetter 	else {
4383ed4351aSDaniel Vetter 		dev->driver->disable_vblank(dev, pipe);
4393ed4351aSDaniel Vetter 	}
44057bb1ee6SDaniel Vetter #endif
441f397d66bSThomas Zimmermann }
4423ed4351aSDaniel Vetter 
4433ed4351aSDaniel Vetter /*
4443ed4351aSDaniel Vetter  * Disable vblank irq's on crtc, make sure that last vblank count
4453ed4351aSDaniel Vetter  * of hardware and corresponding consistent software vblank counter
4463ed4351aSDaniel Vetter  * are preserved, even if there are any spurious vblank irq's after
4473ed4351aSDaniel Vetter  * disable.
4483ed4351aSDaniel Vetter  */
drm_vblank_disable_and_save(struct drm_device * dev,unsigned int pipe)4493ed4351aSDaniel Vetter void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe)
4503ed4351aSDaniel Vetter {
4513ed4351aSDaniel Vetter 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
4523ed4351aSDaniel Vetter 	unsigned long irqflags;
4533ed4351aSDaniel Vetter 
4543ed4351aSDaniel Vetter 	assert_spin_locked(&dev->vbl_lock);
4553ed4351aSDaniel Vetter 
4563ed4351aSDaniel Vetter 	/* Prevent vblank irq processing while disabling vblank irqs,
4573ed4351aSDaniel Vetter 	 * so no updates of timestamps or count can happen after we've
4583ed4351aSDaniel Vetter 	 * disabled. Needed to prevent races in case of delayed irq's.
4593ed4351aSDaniel Vetter 	 */
4603ed4351aSDaniel Vetter 	spin_lock_irqsave(&dev->vblank_time_lock, irqflags);
4613ed4351aSDaniel Vetter 
4623ed4351aSDaniel Vetter 	/*
46368036b08SDhinakaran Pandiyan 	 * Update vblank count and disable vblank interrupts only if the
46468036b08SDhinakaran Pandiyan 	 * interrupts were enabled. This avoids calling the ->disable_vblank()
46568036b08SDhinakaran Pandiyan 	 * operation in atomic context with the hardware potentially runtime
46668036b08SDhinakaran Pandiyan 	 * suspended.
4673ed4351aSDaniel Vetter 	 */
46868036b08SDhinakaran Pandiyan 	if (!vblank->enabled)
46968036b08SDhinakaran Pandiyan 		goto out;
4703ed4351aSDaniel Vetter 
4713ed4351aSDaniel Vetter 	/*
47268036b08SDhinakaran Pandiyan 	 * Update the count and timestamp to maintain the
4733ed4351aSDaniel Vetter 	 * appearance that the counter has been ticking all along until
4743ed4351aSDaniel Vetter 	 * this time. This makes the count account for the entire time
4753ed4351aSDaniel Vetter 	 * between drm_crtc_vblank_on() and drm_crtc_vblank_off().
4763ed4351aSDaniel Vetter 	 */
4773ed4351aSDaniel Vetter 	drm_update_vblank_count(dev, pipe, false);
47868036b08SDhinakaran Pandiyan 	__disable_vblank(dev, pipe);
47968036b08SDhinakaran Pandiyan 	vblank->enabled = false;
4803ed4351aSDaniel Vetter 
48168036b08SDhinakaran Pandiyan out:
4823ed4351aSDaniel Vetter 	spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
4833ed4351aSDaniel Vetter }
4843ed4351aSDaniel Vetter 
vblank_disable_fn(struct timer_list * t)485e99e88a9SKees Cook static void vblank_disable_fn(struct timer_list *t)
4863ed4351aSDaniel Vetter {
487e99e88a9SKees Cook 	struct drm_vblank_crtc *vblank = from_timer(vblank, t, disable_timer);
4883ed4351aSDaniel Vetter 	struct drm_device *dev = vblank->dev;
4893ed4351aSDaniel Vetter 	unsigned int pipe = vblank->pipe;
4903ed4351aSDaniel Vetter 	unsigned long irqflags;
4913ed4351aSDaniel Vetter 
4923ed4351aSDaniel Vetter 	spin_lock_irqsave(&dev->vbl_lock, irqflags);
4933ed4351aSDaniel Vetter 	if (atomic_read(&vblank->refcount) == 0 && vblank->enabled) {
49402149a76SSam Ravnborg 		drm_dbg_core(dev, "disabling vblank on crtc %u\n", pipe);
4953ed4351aSDaniel Vetter 		drm_vblank_disable_and_save(dev, pipe);
4963ed4351aSDaniel Vetter 	}
4973ed4351aSDaniel Vetter 	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
4983ed4351aSDaniel Vetter }
4993ed4351aSDaniel Vetter 
drm_vblank_init_release(struct drm_device * dev,void * ptr)500c23d686fSDaniel Vetter static void drm_vblank_init_release(struct drm_device *dev, void *ptr)
5013ed4351aSDaniel Vetter {
502a7e5e06dSLyude Paul 	struct drm_vblank_crtc *vblank = ptr;
5033ed4351aSDaniel Vetter 
5045a4784f4SSam Ravnborg 	drm_WARN_ON(dev, READ_ONCE(vblank->enabled) &&
5053ed4351aSDaniel Vetter 		    drm_core_check_feature(dev, DRIVER_MODESET));
5063ed4351aSDaniel Vetter 
5075e6c2b4fSLyude Paul 	drm_vblank_destroy_worker(vblank);
5083ed4351aSDaniel Vetter 	del_timer_sync(&vblank->disable_timer);
5093ed4351aSDaniel Vetter }
5103ed4351aSDaniel Vetter 
5113ed4351aSDaniel Vetter /**
5123ed4351aSDaniel Vetter  * drm_vblank_init - initialize vblank support
5133ed4351aSDaniel Vetter  * @dev: DRM device
5143ed4351aSDaniel Vetter  * @num_crtcs: number of CRTCs supported by @dev
5153ed4351aSDaniel Vetter  *
5163ed4351aSDaniel Vetter  * This function initializes vblank support for @num_crtcs display pipelines.
517c23d686fSDaniel Vetter  * Cleanup is handled automatically through a cleanup function added with
518a7e5e06dSLyude Paul  * drmm_add_action_or_reset().
5193ed4351aSDaniel Vetter  *
5203ed4351aSDaniel Vetter  * Returns:
5213ed4351aSDaniel Vetter  * Zero on success or a negative error code on failure.
5223ed4351aSDaniel Vetter  */
drm_vblank_init(struct drm_device * dev,unsigned int num_crtcs)5233ed4351aSDaniel Vetter int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs)
5243ed4351aSDaniel Vetter {
525c23d686fSDaniel Vetter 	int ret;
5263ed4351aSDaniel Vetter 	unsigned int i;
5273ed4351aSDaniel Vetter 
5283ed4351aSDaniel Vetter 	spin_lock_init(&dev->vbl_lock);
5293ed4351aSDaniel Vetter 	spin_lock_init(&dev->vblank_time_lock);
5303ed4351aSDaniel Vetter 
531c23d686fSDaniel Vetter 	dev->vblank = drmm_kcalloc(dev, num_crtcs, sizeof(*dev->vblank), GFP_KERNEL);
532c23d686fSDaniel Vetter 	if (!dev->vblank)
533c23d686fSDaniel Vetter 		return -ENOMEM;
534c23d686fSDaniel Vetter 
5353ed4351aSDaniel Vetter 	dev->num_crtcs = num_crtcs;
5363ed4351aSDaniel Vetter 
5373ed4351aSDaniel Vetter 	for (i = 0; i < num_crtcs; i++) {
5383ed4351aSDaniel Vetter 		struct drm_vblank_crtc *vblank = &dev->vblank[i];
5393ed4351aSDaniel Vetter 
5403ed4351aSDaniel Vetter 		vblank->dev = dev;
5413ed4351aSDaniel Vetter 		vblank->pipe = i;
5423ed4351aSDaniel Vetter 		init_waitqueue_head(&vblank->queue);
543e99e88a9SKees Cook 		timer_setup(&vblank->disable_timer, vblank_disable_fn, 0);
5443ed4351aSDaniel Vetter 		seqlock_init(&vblank->seqlock);
545a7e5e06dSLyude Paul 
546a7e5e06dSLyude Paul 		ret = drmm_add_action_or_reset(dev, drm_vblank_init_release,
547a7e5e06dSLyude Paul 					       vblank);
548a7e5e06dSLyude Paul 		if (ret)
549a7e5e06dSLyude Paul 			return ret;
5505e6c2b4fSLyude Paul 
5515e6c2b4fSLyude Paul 		ret = drm_vblank_worker_init(vblank);
5525e6c2b4fSLyude Paul 		if (ret)
5535e6c2b4fSLyude Paul 			return ret;
5543ed4351aSDaniel Vetter 	}
5553ed4351aSDaniel Vetter 
5563ed4351aSDaniel Vetter 	return 0;
5573ed4351aSDaniel Vetter }
5583ed4351aSDaniel Vetter EXPORT_SYMBOL(drm_vblank_init);
5593ed4351aSDaniel Vetter 
5603ed4351aSDaniel Vetter /**
5617beb691fSThomas Zimmermann  * drm_dev_has_vblank - test if vblanking has been initialized for
5627beb691fSThomas Zimmermann  *                      a device
5637beb691fSThomas Zimmermann  * @dev: the device
5647beb691fSThomas Zimmermann  *
5657beb691fSThomas Zimmermann  * Drivers may call this function to test if vblank support is
5667beb691fSThomas Zimmermann  * initialized for a device. For most hardware this means that vblanking
5677beb691fSThomas Zimmermann  * can also be enabled.
5687beb691fSThomas Zimmermann  *
5697beb691fSThomas Zimmermann  * Atomic helpers use this function to initialize
5707beb691fSThomas Zimmermann  * &drm_crtc_state.no_vblank. See also drm_atomic_helper_check_modeset().
5717beb691fSThomas Zimmermann  *
5727beb691fSThomas Zimmermann  * Returns:
5737beb691fSThomas Zimmermann  * True if vblanking has been initialized for the given device, false
5747beb691fSThomas Zimmermann  * otherwise.
5757beb691fSThomas Zimmermann  */
drm_dev_has_vblank(const struct drm_device * dev)5767beb691fSThomas Zimmermann bool drm_dev_has_vblank(const struct drm_device *dev)
5777beb691fSThomas Zimmermann {
5787beb691fSThomas Zimmermann 	return dev->num_crtcs != 0;
5797beb691fSThomas Zimmermann }
5807beb691fSThomas Zimmermann EXPORT_SYMBOL(drm_dev_has_vblank);
5817beb691fSThomas Zimmermann 
5827beb691fSThomas Zimmermann /**
5833ed4351aSDaniel Vetter  * drm_crtc_vblank_waitqueue - get vblank waitqueue for the CRTC
5843ed4351aSDaniel Vetter  * @crtc: which CRTC's vblank waitqueue to retrieve
5853ed4351aSDaniel Vetter  *
5863ed4351aSDaniel Vetter  * This function returns a pointer to the vblank waitqueue for the CRTC.
5873ed4351aSDaniel Vetter  * Drivers can use this to implement vblank waits using wait_event() and related
5883ed4351aSDaniel Vetter  * functions.
5893ed4351aSDaniel Vetter  */
drm_crtc_vblank_waitqueue(struct drm_crtc * crtc)5903ed4351aSDaniel Vetter wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc)
5913ed4351aSDaniel Vetter {
5923ed4351aSDaniel Vetter 	return &crtc->dev->vblank[drm_crtc_index(crtc)].queue;
5933ed4351aSDaniel Vetter }
5943ed4351aSDaniel Vetter EXPORT_SYMBOL(drm_crtc_vblank_waitqueue);
5953ed4351aSDaniel Vetter 
5963ed4351aSDaniel Vetter 
5973ed4351aSDaniel Vetter /**
5983ed4351aSDaniel Vetter  * drm_calc_timestamping_constants - calculate vblank timestamp constants
5993ed4351aSDaniel Vetter  * @crtc: drm_crtc whose timestamp constants should be updated.
6003ed4351aSDaniel Vetter  * @mode: display mode containing the scanout timings
6013ed4351aSDaniel Vetter  *
60257d30230SDaniel Vetter  * Calculate and store various constants which are later needed by vblank and
60357d30230SDaniel Vetter  * swap-completion timestamping, e.g, by
6047fe3f0d1SThomas Zimmermann  * drm_crtc_vblank_helper_get_vblank_timestamp(). They are derived from
6057fe3f0d1SThomas Zimmermann  * CRTC's true scanout timing, so they take things like panel scaling or
6067fe3f0d1SThomas Zimmermann  * other adjustments into account.
6073ed4351aSDaniel Vetter  */
drm_calc_timestamping_constants(struct drm_crtc * crtc,const struct drm_display_mode * mode)6083ed4351aSDaniel Vetter void drm_calc_timestamping_constants(struct drm_crtc *crtc,
6093ed4351aSDaniel Vetter 				     const struct drm_display_mode *mode)
6103ed4351aSDaniel Vetter {
6113ed4351aSDaniel Vetter 	struct drm_device *dev = crtc->dev;
6123ed4351aSDaniel Vetter 	unsigned int pipe = drm_crtc_index(crtc);
6133ed4351aSDaniel Vetter 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
6143ed4351aSDaniel Vetter 	int linedur_ns = 0, framedur_ns = 0;
6153ed4351aSDaniel Vetter 	int dotclock = mode->crtc_clock;
6163ed4351aSDaniel Vetter 
6176015002eSDaniel Vetter 	if (!drm_dev_has_vblank(dev))
6183ed4351aSDaniel Vetter 		return;
6193ed4351aSDaniel Vetter 
6205a4784f4SSam Ravnborg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
6213ed4351aSDaniel Vetter 		return;
6223ed4351aSDaniel Vetter 
6233ed4351aSDaniel Vetter 	/* Valid dotclock? */
6243ed4351aSDaniel Vetter 	if (dotclock > 0) {
6253ed4351aSDaniel Vetter 		int frame_size = mode->crtc_htotal * mode->crtc_vtotal;
6263ed4351aSDaniel Vetter 
6273ed4351aSDaniel Vetter 		/*
6283ed4351aSDaniel Vetter 		 * Convert scanline length in pixels and video
6293ed4351aSDaniel Vetter 		 * dot clock to line duration and frame duration
6303ed4351aSDaniel Vetter 		 * in nanoseconds:
6313ed4351aSDaniel Vetter 		 */
6323ed4351aSDaniel Vetter 		linedur_ns  = div_u64((u64) mode->crtc_htotal * 1000000, dotclock);
6333ed4351aSDaniel Vetter 		framedur_ns = div_u64((u64) frame_size * 1000000, dotclock);
6343ed4351aSDaniel Vetter 
6353ed4351aSDaniel Vetter 		/*
6363ed4351aSDaniel Vetter 		 * Fields of interlaced scanout modes are only half a frame duration.
6373ed4351aSDaniel Vetter 		 */
6383ed4351aSDaniel Vetter 		if (mode->flags & DRM_MODE_FLAG_INTERLACE)
6393ed4351aSDaniel Vetter 			framedur_ns /= 2;
64002149a76SSam Ravnborg 	} else {
64102149a76SSam Ravnborg 		drm_err(dev, "crtc %u: Can't calculate constants, dotclock = 0!\n",
6423ed4351aSDaniel Vetter 			crtc->base.id);
64302149a76SSam Ravnborg 	}
6443ed4351aSDaniel Vetter 
6453ed4351aSDaniel Vetter 	vblank->linedur_ns  = linedur_ns;
6463ed4351aSDaniel Vetter 	vblank->framedur_ns = framedur_ns;
647a3342f4dSVille Syrjälä 	drm_mode_copy(&vblank->hwmode, mode);
6483ed4351aSDaniel Vetter 
64902149a76SSam Ravnborg 	drm_dbg_core(dev,
65002149a76SSam Ravnborg 		     "crtc %u: hwmode: htotal %d, vtotal %d, vdisplay %d\n",
6513ed4351aSDaniel Vetter 		     crtc->base.id, mode->crtc_htotal,
6523ed4351aSDaniel Vetter 		     mode->crtc_vtotal, mode->crtc_vdisplay);
65302149a76SSam Ravnborg 	drm_dbg_core(dev, "crtc %u: clock %d kHz framedur %d linedur %d\n",
6543ed4351aSDaniel Vetter 		     crtc->base.id, dotclock, framedur_ns, linedur_ns);
6553ed4351aSDaniel Vetter }
6563ed4351aSDaniel Vetter EXPORT_SYMBOL(drm_calc_timestamping_constants);
6573ed4351aSDaniel Vetter 
6583ed4351aSDaniel Vetter /**
659f1e2b637SThomas Zimmermann  * drm_crtc_vblank_helper_get_vblank_timestamp_internal - precise vblank
660f1e2b637SThomas Zimmermann  *                                                        timestamp helper
661099d705dSThomas Zimmermann  * @crtc: CRTC whose vblank timestamp to retrieve
662f1e2b637SThomas Zimmermann  * @max_error: Desired maximum allowable error in timestamps (nanosecs)
663f1e2b637SThomas Zimmermann  *             On return contains true maximum error of timestamp
664f1e2b637SThomas Zimmermann  * @vblank_time: Pointer to time which should receive the timestamp
665f1e2b637SThomas Zimmermann  * @in_vblank_irq:
666f1e2b637SThomas Zimmermann  *     True when called from drm_crtc_handle_vblank().  Some drivers
667f1e2b637SThomas Zimmermann  *     need to apply some workarounds for gpu-specific vblank irq quirks
668f1e2b637SThomas Zimmermann  *     if flag is set.
669f1e2b637SThomas Zimmermann  * @get_scanout_position:
670f1e2b637SThomas Zimmermann  *     Callback function to retrieve the scanout position. See
671f1e2b637SThomas Zimmermann  *     @struct drm_crtc_helper_funcs.get_scanout_position.
672f1e2b637SThomas Zimmermann  *
673f1e2b637SThomas Zimmermann  * Implements calculation of exact vblank timestamps from given drm_display_mode
674f1e2b637SThomas Zimmermann  * timings and current video scanout position of a CRTC.
675f1e2b637SThomas Zimmermann  *
676f1e2b637SThomas Zimmermann  * The current implementation only handles standard video modes. For double scan
677f1e2b637SThomas Zimmermann  * and interlaced modes the driver is supposed to adjust the hardware mode
678f1e2b637SThomas Zimmermann  * (taken from &drm_crtc_state.adjusted mode for atomic modeset drivers) to
679f1e2b637SThomas Zimmermann  * match the scanout position reported.
680f1e2b637SThomas Zimmermann  *
681f1e2b637SThomas Zimmermann  * Note that atomic drivers must call drm_calc_timestamping_constants() before
682f1e2b637SThomas Zimmermann  * enabling a CRTC. The atomic helpers already take care of that in
683441959ebSVille Syrjälä  * drm_atomic_helper_calc_timestamping_constants().
684f1e2b637SThomas Zimmermann  *
685f1e2b637SThomas Zimmermann  * Returns:
686f1e2b637SThomas Zimmermann  *
687f1e2b637SThomas Zimmermann  * Returns true on success, and false on failure, i.e. when no accurate
688f1e2b637SThomas Zimmermann  * timestamp could be acquired.
689f1e2b637SThomas Zimmermann  */
690f1e2b637SThomas Zimmermann bool
drm_crtc_vblank_helper_get_vblank_timestamp_internal(struct drm_crtc * crtc,int * max_error,ktime_t * vblank_time,bool in_vblank_irq,drm_vblank_get_scanout_position_func get_scanout_position)691f1e2b637SThomas Zimmermann drm_crtc_vblank_helper_get_vblank_timestamp_internal(
692f1e2b637SThomas Zimmermann 	struct drm_crtc *crtc, int *max_error, ktime_t *vblank_time,
693f1e2b637SThomas Zimmermann 	bool in_vblank_irq,
69448e67807SThomas Zimmermann 	drm_vblank_get_scanout_position_func get_scanout_position)
695f1e2b637SThomas Zimmermann {
696f1e2b637SThomas Zimmermann 	struct drm_device *dev = crtc->dev;
697f1e2b637SThomas Zimmermann 	unsigned int pipe = crtc->index;
698f1e2b637SThomas Zimmermann 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
699f1e2b637SThomas Zimmermann 	struct timespec64 ts_etime, ts_vblank_time;
700f1e2b637SThomas Zimmermann 	ktime_t stime, etime;
701f1e2b637SThomas Zimmermann 	bool vbl_status;
702f1e2b637SThomas Zimmermann 	const struct drm_display_mode *mode;
703f1e2b637SThomas Zimmermann 	int vpos, hpos, i;
704f1e2b637SThomas Zimmermann 	int delta_ns, duration_ns;
705f1e2b637SThomas Zimmermann 
706f1e2b637SThomas Zimmermann 	if (pipe >= dev->num_crtcs) {
70702149a76SSam Ravnborg 		drm_err(dev, "Invalid crtc %u\n", pipe);
7083ed4351aSDaniel Vetter 		return false;
7093ed4351aSDaniel Vetter 	}
7103ed4351aSDaniel Vetter 
7113ed4351aSDaniel Vetter 	/* Scanout position query not supported? Should not happen. */
71248e67807SThomas Zimmermann 	if (!get_scanout_position) {
71302149a76SSam Ravnborg 		drm_err(dev, "Called from CRTC w/o get_scanout_position()!?\n");
7143ed4351aSDaniel Vetter 		return false;
7153ed4351aSDaniel Vetter 	}
7163ed4351aSDaniel Vetter 
7173ed4351aSDaniel Vetter 	if (drm_drv_uses_atomic_modeset(dev))
7183ed4351aSDaniel Vetter 		mode = &vblank->hwmode;
7193ed4351aSDaniel Vetter 	else
7203ed4351aSDaniel Vetter 		mode = &crtc->hwmode;
7213ed4351aSDaniel Vetter 
7223ed4351aSDaniel Vetter 	/* If mode timing undefined, just return as no-op:
7233ed4351aSDaniel Vetter 	 * Happens during initial modesetting of a crtc.
7243ed4351aSDaniel Vetter 	 */
7253ed4351aSDaniel Vetter 	if (mode->crtc_clock == 0) {
72602149a76SSam Ravnborg 		drm_dbg_core(dev, "crtc %u: Noop due to uninitialized mode.\n",
72702149a76SSam Ravnborg 			     pipe);
7285a4784f4SSam Ravnborg 		drm_WARN_ON_ONCE(dev, drm_drv_uses_atomic_modeset(dev));
7293ed4351aSDaniel Vetter 		return false;
7303ed4351aSDaniel Vetter 	}
7313ed4351aSDaniel Vetter 
7323ed4351aSDaniel Vetter 	/* Get current scanout position with system timestamp.
7333ed4351aSDaniel Vetter 	 * Repeat query up to DRM_TIMESTAMP_MAXRETRIES times
7343ed4351aSDaniel Vetter 	 * if single query takes longer than max_error nanoseconds.
7353ed4351aSDaniel Vetter 	 *
7363ed4351aSDaniel Vetter 	 * This guarantees a tight bound on maximum error if
7373ed4351aSDaniel Vetter 	 * code gets preempted or delayed for some reason.
7383ed4351aSDaniel Vetter 	 */
7393ed4351aSDaniel Vetter 	for (i = 0; i < DRM_TIMESTAMP_MAXRETRIES; i++) {
7403ed4351aSDaniel Vetter 		/*
7413ed4351aSDaniel Vetter 		 * Get vertical and horizontal scanout position vpos, hpos,
7423ed4351aSDaniel Vetter 		 * and bounding timestamps stime, etime, pre/post query.
7433ed4351aSDaniel Vetter 		 */
74448e67807SThomas Zimmermann 		vbl_status = get_scanout_position(crtc, in_vblank_irq,
7453ed4351aSDaniel Vetter 						  &vpos, &hpos,
7463ed4351aSDaniel Vetter 						  &stime, &etime,
7473ed4351aSDaniel Vetter 						  mode);
7483ed4351aSDaniel Vetter 
7493ed4351aSDaniel Vetter 		/* Return as no-op if scanout query unsupported or failed. */
7503ed4351aSDaniel Vetter 		if (!vbl_status) {
75102149a76SSam Ravnborg 			drm_dbg_core(dev,
75202149a76SSam Ravnborg 				     "crtc %u : scanoutpos query failed.\n",
7533ed4351aSDaniel Vetter 				     pipe);
7543ed4351aSDaniel Vetter 			return false;
7553ed4351aSDaniel Vetter 		}
7563ed4351aSDaniel Vetter 
7573ed4351aSDaniel Vetter 		/* Compute uncertainty in timestamp of scanout position query. */
7583ed4351aSDaniel Vetter 		duration_ns = ktime_to_ns(etime) - ktime_to_ns(stime);
7593ed4351aSDaniel Vetter 
7603ed4351aSDaniel Vetter 		/* Accept result with <  max_error nsecs timing uncertainty. */
7613ed4351aSDaniel Vetter 		if (duration_ns <= *max_error)
7623ed4351aSDaniel Vetter 			break;
7633ed4351aSDaniel Vetter 	}
7643ed4351aSDaniel Vetter 
7653ed4351aSDaniel Vetter 	/* Noisy system timing? */
7663ed4351aSDaniel Vetter 	if (i == DRM_TIMESTAMP_MAXRETRIES) {
76702149a76SSam Ravnborg 		drm_dbg_core(dev,
76802149a76SSam Ravnborg 			     "crtc %u: Noisy timestamp %d us > %d us [%d reps].\n",
7693ed4351aSDaniel Vetter 			     pipe, duration_ns / 1000, *max_error / 1000, i);
7703ed4351aSDaniel Vetter 	}
7713ed4351aSDaniel Vetter 
7723ed4351aSDaniel Vetter 	/* Return upper bound of timestamp precision error. */
7733ed4351aSDaniel Vetter 	*max_error = duration_ns;
7743ed4351aSDaniel Vetter 
7753ed4351aSDaniel Vetter 	/* Convert scanout position into elapsed time at raw_time query
7763ed4351aSDaniel Vetter 	 * since start of scanout at first display scanline. delta_ns
7773ed4351aSDaniel Vetter 	 * can be negative if start of scanout hasn't happened yet.
7783ed4351aSDaniel Vetter 	 */
7793ed4351aSDaniel Vetter 	delta_ns = div_s64(1000000LL * (vpos * mode->crtc_htotal + hpos),
7803ed4351aSDaniel Vetter 			   mode->crtc_clock);
7813ed4351aSDaniel Vetter 
7823ed4351aSDaniel Vetter 	/* Subtract time delta from raw timestamp to get final
7833ed4351aSDaniel Vetter 	 * vblank_time timestamp for end of vblank.
7843ed4351aSDaniel Vetter 	 */
785bcbec31cSVille Syrjälä 	*vblank_time = ktime_sub_ns(etime, delta_ns);
786bcbec31cSVille Syrjälä 
787f0a8f533SJani Nikula 	if (!drm_debug_enabled(DRM_UT_VBL))
788bcbec31cSVille Syrjälä 		return true;
789bcbec31cSVille Syrjälä 
790bcbec31cSVille Syrjälä 	ts_etime = ktime_to_timespec64(etime);
791bcbec31cSVille Syrjälä 	ts_vblank_time = ktime_to_timespec64(*vblank_time);
7923ed4351aSDaniel Vetter 
79302149a76SSam Ravnborg 	drm_dbg_vbl(dev,
79402149a76SSam Ravnborg 		    "crtc %u : v p(%d,%d)@ %lld.%06ld -> %lld.%06ld [e %d us, %d rep]\n",
7953ed4351aSDaniel Vetter 		    pipe, hpos, vpos,
79667680d3cSArnd Bergmann 		    (u64)ts_etime.tv_sec, ts_etime.tv_nsec / 1000,
79767680d3cSArnd Bergmann 		    (u64)ts_vblank_time.tv_sec, ts_vblank_time.tv_nsec / 1000,
7983ed4351aSDaniel Vetter 		    duration_ns / 1000, i);
7993ed4351aSDaniel Vetter 
8003ed4351aSDaniel Vetter 	return true;
8013ed4351aSDaniel Vetter }
802f1e2b637SThomas Zimmermann EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp_internal);
8033ed4351aSDaniel Vetter 
8043ed4351aSDaniel Vetter /**
8057fe3f0d1SThomas Zimmermann  * drm_crtc_vblank_helper_get_vblank_timestamp - precise vblank timestamp
8067fe3f0d1SThomas Zimmermann  *                                               helper
8077fe3f0d1SThomas Zimmermann  * @crtc: CRTC whose vblank timestamp to retrieve
8087fe3f0d1SThomas Zimmermann  * @max_error: Desired maximum allowable error in timestamps (nanosecs)
8097fe3f0d1SThomas Zimmermann  *             On return contains true maximum error of timestamp
8107fe3f0d1SThomas Zimmermann  * @vblank_time: Pointer to time which should receive the timestamp
8117fe3f0d1SThomas Zimmermann  * @in_vblank_irq:
8127fe3f0d1SThomas Zimmermann  *     True when called from drm_crtc_handle_vblank().  Some drivers
8137fe3f0d1SThomas Zimmermann  *     need to apply some workarounds for gpu-specific vblank irq quirks
8147fe3f0d1SThomas Zimmermann  *     if flag is set.
8157fe3f0d1SThomas Zimmermann  *
8167fe3f0d1SThomas Zimmermann  * Implements calculation of exact vblank timestamps from given drm_display_mode
8177fe3f0d1SThomas Zimmermann  * timings and current video scanout position of a CRTC. This can be directly
8187fe3f0d1SThomas Zimmermann  * used as the &drm_crtc_funcs.get_vblank_timestamp implementation of a kms
8197fe3f0d1SThomas Zimmermann  * driver if &drm_crtc_helper_funcs.get_scanout_position is implemented.
8207fe3f0d1SThomas Zimmermann  *
8217fe3f0d1SThomas Zimmermann  * The current implementation only handles standard video modes. For double scan
8227fe3f0d1SThomas Zimmermann  * and interlaced modes the driver is supposed to adjust the hardware mode
8237fe3f0d1SThomas Zimmermann  * (taken from &drm_crtc_state.adjusted mode for atomic modeset drivers) to
8247fe3f0d1SThomas Zimmermann  * match the scanout position reported.
8257fe3f0d1SThomas Zimmermann  *
8267fe3f0d1SThomas Zimmermann  * Note that atomic drivers must call drm_calc_timestamping_constants() before
8277fe3f0d1SThomas Zimmermann  * enabling a CRTC. The atomic helpers already take care of that in
828441959ebSVille Syrjälä  * drm_atomic_helper_calc_timestamping_constants().
8297fe3f0d1SThomas Zimmermann  *
8307fe3f0d1SThomas Zimmermann  * Returns:
8317fe3f0d1SThomas Zimmermann  *
8327fe3f0d1SThomas Zimmermann  * Returns true on success, and false on failure, i.e. when no accurate
8337fe3f0d1SThomas Zimmermann  * timestamp could be acquired.
8347fe3f0d1SThomas Zimmermann  */
drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc * crtc,int * max_error,ktime_t * vblank_time,bool in_vblank_irq)8357fe3f0d1SThomas Zimmermann bool drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc *crtc,
8367fe3f0d1SThomas Zimmermann 						 int *max_error,
8377fe3f0d1SThomas Zimmermann 						 ktime_t *vblank_time,
8387fe3f0d1SThomas Zimmermann 						 bool in_vblank_irq)
8397fe3f0d1SThomas Zimmermann {
8407fe3f0d1SThomas Zimmermann 	return drm_crtc_vblank_helper_get_vblank_timestamp_internal(
8417fe3f0d1SThomas Zimmermann 		crtc, max_error, vblank_time, in_vblank_irq,
84248e67807SThomas Zimmermann 		crtc->helper_private->get_scanout_position);
8437fe3f0d1SThomas Zimmermann }
8447fe3f0d1SThomas Zimmermann EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp);
8457fe3f0d1SThomas Zimmermann 
8467fe3f0d1SThomas Zimmermann /**
847b2c077d0SRob Clark  * drm_crtc_get_last_vbltimestamp - retrieve raw timestamp for the most
848b2c077d0SRob Clark  *                                  recent vblank interval
849b2c077d0SRob Clark  * @crtc: CRTC whose vblank timestamp to retrieve
85067680d3cSArnd Bergmann  * @tvblank: Pointer to target time which should receive the timestamp
8513ed4351aSDaniel Vetter  * @in_vblank_irq:
8523ed4351aSDaniel Vetter  *     True when called from drm_crtc_handle_vblank().  Some drivers
8533ed4351aSDaniel Vetter  *     need to apply some workarounds for gpu-specific vblank irq quirks
8543ed4351aSDaniel Vetter  *     if flag is set.
8553ed4351aSDaniel Vetter  *
8563ed4351aSDaniel Vetter  * Fetches the system timestamp corresponding to the time of the most recent
8573ed4351aSDaniel Vetter  * vblank interval on specified CRTC. May call into kms-driver to
8583ed4351aSDaniel Vetter  * compute the timestamp with a high-precision GPU specific method.
8593ed4351aSDaniel Vetter  *
8603ed4351aSDaniel Vetter  * Returns zero if timestamp originates from uncorrected do_gettimeofday()
8613ed4351aSDaniel Vetter  * call, i.e., it isn't very precisely locked to the true vblank.
8623ed4351aSDaniel Vetter  *
8633ed4351aSDaniel Vetter  * Returns:
8643ed4351aSDaniel Vetter  * True if timestamp is considered to be very precise, false otherwise.
8653ed4351aSDaniel Vetter  */
8663ed4351aSDaniel Vetter static bool
drm_crtc_get_last_vbltimestamp(struct drm_crtc * crtc,ktime_t * tvblank,bool in_vblank_irq)867b2c077d0SRob Clark drm_crtc_get_last_vbltimestamp(struct drm_crtc *crtc, ktime_t *tvblank,
868b2c077d0SRob Clark 			       bool in_vblank_irq)
8693ed4351aSDaniel Vetter {
8703ed4351aSDaniel Vetter 	bool ret = false;
8713ed4351aSDaniel Vetter 
8723ed4351aSDaniel Vetter 	/* Define requested maximum error on timestamps (nanoseconds). */
8733ed4351aSDaniel Vetter 	int max_error = (int) drm_timestamp_precision * 1000;
8743ed4351aSDaniel Vetter 
8753ed4351aSDaniel Vetter 	/* Query driver if possible and precision timestamping enabled. */
8767fe3f0d1SThomas Zimmermann 	if (crtc && crtc->funcs->get_vblank_timestamp && max_error > 0) {
8777fe3f0d1SThomas Zimmermann 		ret = crtc->funcs->get_vblank_timestamp(crtc, &max_error,
8787fe3f0d1SThomas Zimmermann 							tvblank, in_vblank_irq);
8797fe3f0d1SThomas Zimmermann 	}
8803ed4351aSDaniel Vetter 
8813ed4351aSDaniel Vetter 	/* GPU high precision timestamp query unsupported or failed.
8823ed4351aSDaniel Vetter 	 * Return current monotonic/gettimeofday timestamp as best estimate.
8833ed4351aSDaniel Vetter 	 */
8843ed4351aSDaniel Vetter 	if (!ret)
88525e1a798SArnd Bergmann 		*tvblank = ktime_get();
8863ed4351aSDaniel Vetter 
8873ed4351aSDaniel Vetter 	return ret;
8883ed4351aSDaniel Vetter }
8893ed4351aSDaniel Vetter 
890b2c077d0SRob Clark static bool
drm_get_last_vbltimestamp(struct drm_device * dev,unsigned int pipe,ktime_t * tvblank,bool in_vblank_irq)891b2c077d0SRob Clark drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
892b2c077d0SRob Clark 			  ktime_t *tvblank, bool in_vblank_irq)
893b2c077d0SRob Clark {
894b2c077d0SRob Clark 	struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
895b2c077d0SRob Clark 
896b2c077d0SRob Clark 	return drm_crtc_get_last_vbltimestamp(crtc, tvblank, in_vblank_irq);
897b2c077d0SRob Clark }
898b2c077d0SRob Clark 
8993ed4351aSDaniel Vetter /**
9003ed4351aSDaniel Vetter  * drm_crtc_vblank_count - retrieve "cooked" vblank counter value
9013ed4351aSDaniel Vetter  * @crtc: which counter to retrieve
9023ed4351aSDaniel Vetter  *
9033ed4351aSDaniel Vetter  * Fetches the "cooked" vblank count value that represents the number of
9043ed4351aSDaniel Vetter  * vblank events since the system was booted, including lost events due to
90557d30230SDaniel Vetter  * modesetting activity. Note that this timer isn't correct against a racing
90657d30230SDaniel Vetter  * vblank interrupt (since it only reports the software vblank counter), see
907ca814b25SDaniel Vetter  * drm_crtc_accurate_vblank_count() for such use-cases.
9083ed4351aSDaniel Vetter  *
909bd7e3f3bSDaniel Vetter  * Note that for a given vblank counter value drm_crtc_handle_vblank()
910bd7e3f3bSDaniel Vetter  * and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time()
911bd7e3f3bSDaniel Vetter  * provide a barrier: Any writes done before calling
912bd7e3f3bSDaniel Vetter  * drm_crtc_handle_vblank() will be visible to callers of the later
9130ae865efSCai Huoqing  * functions, if the vblank count is the same or a later one.
914bd7e3f3bSDaniel Vetter  *
915bd7e3f3bSDaniel Vetter  * See also &drm_vblank_crtc.count.
916bd7e3f3bSDaniel Vetter  *
9173ed4351aSDaniel Vetter  * Returns:
9183ed4351aSDaniel Vetter  * The software vblank counter.
9193ed4351aSDaniel Vetter  */
drm_crtc_vblank_count(struct drm_crtc * crtc)920570e8696SKeith Packard u64 drm_crtc_vblank_count(struct drm_crtc *crtc)
9213ed4351aSDaniel Vetter {
9223ed4351aSDaniel Vetter 	return drm_vblank_count(crtc->dev, drm_crtc_index(crtc));
9233ed4351aSDaniel Vetter }
9243ed4351aSDaniel Vetter EXPORT_SYMBOL(drm_crtc_vblank_count);
9253ed4351aSDaniel Vetter 
926570e8696SKeith Packard /**
927570e8696SKeith Packard  * drm_vblank_count_and_time - retrieve "cooked" vblank counter value and the
928570e8696SKeith Packard  *     system timestamp corresponding to that vblank counter value.
929570e8696SKeith Packard  * @dev: DRM device
930570e8696SKeith Packard  * @pipe: index of CRTC whose counter to retrieve
931570e8696SKeith Packard  * @vblanktime: Pointer to ktime_t to receive the vblank timestamp.
932570e8696SKeith Packard  *
933570e8696SKeith Packard  * Fetches the "cooked" vblank count value that represents the number of
934570e8696SKeith Packard  * vblank events since the system was booted, including lost events due to
935570e8696SKeith Packard  * modesetting activity. Returns corresponding system timestamp of the time
936570e8696SKeith Packard  * of the vblank interval that corresponds to the current vblank counter value.
937570e8696SKeith Packard  *
938570e8696SKeith Packard  * This is the legacy version of drm_crtc_vblank_count_and_time().
939570e8696SKeith Packard  */
drm_vblank_count_and_time(struct drm_device * dev,unsigned int pipe,ktime_t * vblanktime)940570e8696SKeith Packard static u64 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
94167680d3cSArnd Bergmann 				     ktime_t *vblanktime)
9423ed4351aSDaniel Vetter {
9433ed4351aSDaniel Vetter 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
944570e8696SKeith Packard 	u64 vblank_count;
9453ed4351aSDaniel Vetter 	unsigned int seq;
9463ed4351aSDaniel Vetter 
9475a4784f4SSam Ravnborg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) {
94867680d3cSArnd Bergmann 		*vblanktime = 0;
9493ed4351aSDaniel Vetter 		return 0;
9503ed4351aSDaniel Vetter 	}
9513ed4351aSDaniel Vetter 
9523ed4351aSDaniel Vetter 	do {
9533ed4351aSDaniel Vetter 		seq = read_seqbegin(&vblank->seqlock);
954bd7e3f3bSDaniel Vetter 		vblank_count = atomic64_read(&vblank->count);
9553ed4351aSDaniel Vetter 		*vblanktime = vblank->time;
9563ed4351aSDaniel Vetter 	} while (read_seqretry(&vblank->seqlock, seq));
9573ed4351aSDaniel Vetter 
9583ed4351aSDaniel Vetter 	return vblank_count;
9593ed4351aSDaniel Vetter }
9603ed4351aSDaniel Vetter 
9613ed4351aSDaniel Vetter /**
9623ed4351aSDaniel Vetter  * drm_crtc_vblank_count_and_time - retrieve "cooked" vblank counter value
9633ed4351aSDaniel Vetter  *     and the system timestamp corresponding to that vblank counter value
9643ed4351aSDaniel Vetter  * @crtc: which counter to retrieve
96567680d3cSArnd Bergmann  * @vblanktime: Pointer to time to receive the vblank timestamp.
9663ed4351aSDaniel Vetter  *
9673ed4351aSDaniel Vetter  * Fetches the "cooked" vblank count value that represents the number of
9683ed4351aSDaniel Vetter  * vblank events since the system was booted, including lost events due to
9693ed4351aSDaniel Vetter  * modesetting activity. Returns corresponding system timestamp of the time
9703ed4351aSDaniel Vetter  * of the vblank interval that corresponds to the current vblank counter value.
971bd7e3f3bSDaniel Vetter  *
972bd7e3f3bSDaniel Vetter  * Note that for a given vblank counter value drm_crtc_handle_vblank()
973bd7e3f3bSDaniel Vetter  * and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time()
974bd7e3f3bSDaniel Vetter  * provide a barrier: Any writes done before calling
975bd7e3f3bSDaniel Vetter  * drm_crtc_handle_vblank() will be visible to callers of the later
9760ae865efSCai Huoqing  * functions, if the vblank count is the same or a later one.
977bd7e3f3bSDaniel Vetter  *
978bd7e3f3bSDaniel Vetter  * See also &drm_vblank_crtc.count.
9793ed4351aSDaniel Vetter  */
drm_crtc_vblank_count_and_time(struct drm_crtc * crtc,ktime_t * vblanktime)980570e8696SKeith Packard u64 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc,
98167680d3cSArnd Bergmann 				   ktime_t *vblanktime)
9823ed4351aSDaniel Vetter {
9833ed4351aSDaniel Vetter 	return drm_vblank_count_and_time(crtc->dev, drm_crtc_index(crtc),
9843ed4351aSDaniel Vetter 					 vblanktime);
9853ed4351aSDaniel Vetter }
9863ed4351aSDaniel Vetter EXPORT_SYMBOL(drm_crtc_vblank_count_and_time);
9873ed4351aSDaniel Vetter 
988b2c077d0SRob Clark /**
989b2c077d0SRob Clark  * drm_crtc_next_vblank_start - calculate the time of the next vblank
990b2c077d0SRob Clark  * @crtc: the crtc for which to calculate next vblank time
991b2c077d0SRob Clark  * @vblanktime: pointer to time to receive the next vblank timestamp.
992b2c077d0SRob Clark  *
993b2c077d0SRob Clark  * Calculate the expected time of the start of the next vblank period,
994b2c077d0SRob Clark  * based on time of previous vblank and frame duration
995b2c077d0SRob Clark  */
drm_crtc_next_vblank_start(struct drm_crtc * crtc,ktime_t * vblanktime)996b2c077d0SRob Clark int drm_crtc_next_vblank_start(struct drm_crtc *crtc, ktime_t *vblanktime)
997b2c077d0SRob Clark {
998b2c077d0SRob Clark 	unsigned int pipe = drm_crtc_index(crtc);
999*6f1ccbf0SRob Clark 	struct drm_vblank_crtc *vblank;
1000*6f1ccbf0SRob Clark 	struct drm_display_mode *mode;
1001b2c077d0SRob Clark 	u64 vblank_start;
1002b2c077d0SRob Clark 
1003*6f1ccbf0SRob Clark 	if (!drm_dev_has_vblank(crtc->dev))
1004*6f1ccbf0SRob Clark 		return -EINVAL;
1005*6f1ccbf0SRob Clark 
1006*6f1ccbf0SRob Clark 	vblank = &crtc->dev->vblank[pipe];
1007*6f1ccbf0SRob Clark 	mode = &vblank->hwmode;
1008*6f1ccbf0SRob Clark 
1009b2c077d0SRob Clark 	if (!vblank->framedur_ns || !vblank->linedur_ns)
1010b2c077d0SRob Clark 		return -EINVAL;
1011b2c077d0SRob Clark 
1012b2c077d0SRob Clark 	if (!drm_crtc_get_last_vbltimestamp(crtc, vblanktime, false))
1013b2c077d0SRob Clark 		return -EINVAL;
1014b2c077d0SRob Clark 
1015b2c077d0SRob Clark 	vblank_start = DIV_ROUND_DOWN_ULL(
1016b2c077d0SRob Clark 			(u64)vblank->framedur_ns * mode->crtc_vblank_start,
1017b2c077d0SRob Clark 			mode->crtc_vtotal);
1018b2c077d0SRob Clark 	*vblanktime  = ktime_add(*vblanktime, ns_to_ktime(vblank_start));
1019b2c077d0SRob Clark 
1020b2c077d0SRob Clark 	return 0;
1021b2c077d0SRob Clark }
1022b2c077d0SRob Clark EXPORT_SYMBOL(drm_crtc_next_vblank_start);
1023b2c077d0SRob Clark 
send_vblank_event(struct drm_device * dev,struct drm_pending_vblank_event * e,u64 seq,ktime_t now)10243ed4351aSDaniel Vetter static void send_vblank_event(struct drm_device *dev,
10253ed4351aSDaniel Vetter 		struct drm_pending_vblank_event *e,
1026570e8696SKeith Packard 		u64 seq, ktime_t now)
10273ed4351aSDaniel Vetter {
1028bd386e51SKeith Packard 	struct timespec64 tv;
102967680d3cSArnd Bergmann 
1030bd386e51SKeith Packard 	switch (e->event.base.type) {
1031bd386e51SKeith Packard 	case DRM_EVENT_VBLANK:
1032bd386e51SKeith Packard 	case DRM_EVENT_FLIP_COMPLETE:
1033bd386e51SKeith Packard 		tv = ktime_to_timespec64(now);
1034bd386e51SKeith Packard 		e->event.vbl.sequence = seq;
103567680d3cSArnd Bergmann 		/*
103667680d3cSArnd Bergmann 		 * e->event is a user space structure, with hardcoded unsigned
103725e1a798SArnd Bergmann 		 * 32-bit seconds/microseconds. This is safe as we always use
103825e1a798SArnd Bergmann 		 * monotonic timestamps since linux-4.15
103967680d3cSArnd Bergmann 		 */
1040bd386e51SKeith Packard 		e->event.vbl.tv_sec = tv.tv_sec;
1041bd386e51SKeith Packard 		e->event.vbl.tv_usec = tv.tv_nsec / 1000;
1042bd386e51SKeith Packard 		break;
10433064abfaSKeith Packard 	case DRM_EVENT_CRTC_SEQUENCE:
10443064abfaSKeith Packard 		if (seq)
10453064abfaSKeith Packard 			e->event.seq.sequence = seq;
10463064abfaSKeith Packard 		e->event.seq.time_ns = ktime_to_ns(now);
10473064abfaSKeith Packard 		break;
1048bd386e51SKeith Packard 	}
1049bd386e51SKeith Packard 	trace_drm_vblank_event_delivered(e->base.file_priv, e->pipe, seq);
1050a78e7a51SVeera Sundaram Sankaran 	/*
1051a78e7a51SVeera Sundaram Sankaran 	 * Use the same timestamp for any associated fence signal to avoid
1052a78e7a51SVeera Sundaram Sankaran 	 * mismatch in timestamps for vsync & fence events triggered by the
1053a78e7a51SVeera Sundaram Sankaran 	 * same HW event. Frameworks like SurfaceFlinger in Android expects the
1054a78e7a51SVeera Sundaram Sankaran 	 * retire-fence timestamp to match exactly with HW vsync as it uses it
1055a78e7a51SVeera Sundaram Sankaran 	 * for its software vsync modeling.
1056a78e7a51SVeera Sundaram Sankaran 	 */
1057a78e7a51SVeera Sundaram Sankaran 	drm_send_event_timestamp_locked(dev, &e->base, now);
10583ed4351aSDaniel Vetter }
10593ed4351aSDaniel Vetter 
10603ed4351aSDaniel Vetter /**
10613ed4351aSDaniel Vetter  * drm_crtc_arm_vblank_event - arm vblank event after pageflip
10623ed4351aSDaniel Vetter  * @crtc: the source CRTC of the vblank event
10633ed4351aSDaniel Vetter  * @e: the event to send
10643ed4351aSDaniel Vetter  *
10653ed4351aSDaniel Vetter  * A lot of drivers need to generate vblank events for the very next vblank
10663ed4351aSDaniel Vetter  * interrupt. For example when the page flip interrupt happens when the page
10673ed4351aSDaniel Vetter  * flip gets armed, but not when it actually executes within the next vblank
10683ed4351aSDaniel Vetter  * period. This helper function implements exactly the required vblank arming
10693ed4351aSDaniel Vetter  * behaviour.
10703ed4351aSDaniel Vetter  *
10713ed4351aSDaniel Vetter  * NOTE: Drivers using this to send out the &drm_crtc_state.event as part of an
10723ed4351aSDaniel Vetter  * atomic commit must ensure that the next vblank happens at exactly the same
10733ed4351aSDaniel Vetter  * time as the atomic commit is committed to the hardware. This function itself
1074e13a0583SDaniel Vetter  * does **not** protect against the next vblank interrupt racing with either this
10753ed4351aSDaniel Vetter  * function call or the atomic commit operation. A possible sequence could be:
10763ed4351aSDaniel Vetter  *
10773ed4351aSDaniel Vetter  * 1. Driver commits new hardware state into vblank-synchronized registers.
10783ed4351aSDaniel Vetter  * 2. A vblank happens, committing the hardware state. Also the corresponding
10793ed4351aSDaniel Vetter  *    vblank interrupt is fired off and fully processed by the interrupt
10803ed4351aSDaniel Vetter  *    handler.
10813ed4351aSDaniel Vetter  * 3. The atomic commit operation proceeds to call drm_crtc_arm_vblank_event().
10823ed4351aSDaniel Vetter  * 4. The event is only send out for the next vblank, which is wrong.
10833ed4351aSDaniel Vetter  *
10843ed4351aSDaniel Vetter  * An equivalent race can happen when the driver calls
10853ed4351aSDaniel Vetter  * drm_crtc_arm_vblank_event() before writing out the new hardware state.
10863ed4351aSDaniel Vetter  *
10873ed4351aSDaniel Vetter  * The only way to make this work safely is to prevent the vblank from firing
10883ed4351aSDaniel Vetter  * (and the hardware from committing anything else) until the entire atomic
10893ed4351aSDaniel Vetter  * commit sequence has run to completion. If the hardware does not have such a
10903ed4351aSDaniel Vetter  * feature (e.g. using a "go" bit), then it is unsafe to use this functions.
10913ed4351aSDaniel Vetter  * Instead drivers need to manually send out the event from their interrupt
10923ed4351aSDaniel Vetter  * handler by calling drm_crtc_send_vblank_event() and make sure that there's no
10933ed4351aSDaniel Vetter  * possible race with the hardware committing the atomic update.
10943ed4351aSDaniel Vetter  *
1095e750218dSStefan Agner  * Caller must hold a vblank reference for the event @e acquired by a
1096e750218dSStefan Agner  * drm_crtc_vblank_get(), which will be dropped when the next vblank arrives.
10973ed4351aSDaniel Vetter  */
drm_crtc_arm_vblank_event(struct drm_crtc * crtc,struct drm_pending_vblank_event * e)10983ed4351aSDaniel Vetter void drm_crtc_arm_vblank_event(struct drm_crtc *crtc,
10993ed4351aSDaniel Vetter 			       struct drm_pending_vblank_event *e)
11003ed4351aSDaniel Vetter {
11013ed4351aSDaniel Vetter 	struct drm_device *dev = crtc->dev;
11023ed4351aSDaniel Vetter 	unsigned int pipe = drm_crtc_index(crtc);
11033ed4351aSDaniel Vetter 
11043ed4351aSDaniel Vetter 	assert_spin_locked(&dev->event_lock);
11053ed4351aSDaniel Vetter 
11063ed4351aSDaniel Vetter 	e->pipe = pipe;
1107570e8696SKeith Packard 	e->sequence = drm_crtc_accurate_vblank_count(crtc) + 1;
11083ed4351aSDaniel Vetter 	list_add_tail(&e->base.link, &dev->vblank_event_list);
11093ed4351aSDaniel Vetter }
11103ed4351aSDaniel Vetter EXPORT_SYMBOL(drm_crtc_arm_vblank_event);
11113ed4351aSDaniel Vetter 
11123ed4351aSDaniel Vetter /**
11133ed4351aSDaniel Vetter  * drm_crtc_send_vblank_event - helper to send vblank event after pageflip
11143ed4351aSDaniel Vetter  * @crtc: the source CRTC of the vblank event
11153ed4351aSDaniel Vetter  * @e: the event to send
11163ed4351aSDaniel Vetter  *
11173ed4351aSDaniel Vetter  * Updates sequence # and timestamp on event for the most recently processed
11183ed4351aSDaniel Vetter  * vblank, and sends it to userspace.  Caller must hold event lock.
11193ed4351aSDaniel Vetter  *
11203ed4351aSDaniel Vetter  * See drm_crtc_arm_vblank_event() for a helper which can be used in certain
11213ed4351aSDaniel Vetter  * situation, especially to send out events for atomic commit operations.
11223ed4351aSDaniel Vetter  */
drm_crtc_send_vblank_event(struct drm_crtc * crtc,struct drm_pending_vblank_event * e)11233ed4351aSDaniel Vetter void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
11243ed4351aSDaniel Vetter 				struct drm_pending_vblank_event *e)
11253ed4351aSDaniel Vetter {
11263ed4351aSDaniel Vetter 	struct drm_device *dev = crtc->dev;
1127570e8696SKeith Packard 	u64 seq;
1128570e8696SKeith Packard 	unsigned int pipe = drm_crtc_index(crtc);
112967680d3cSArnd Bergmann 	ktime_t now;
11303ed4351aSDaniel Vetter 
11316015002eSDaniel Vetter 	if (drm_dev_has_vblank(dev)) {
11323ed4351aSDaniel Vetter 		seq = drm_vblank_count_and_time(dev, pipe, &now);
11333ed4351aSDaniel Vetter 	} else {
11343ed4351aSDaniel Vetter 		seq = 0;
11353ed4351aSDaniel Vetter 
113625e1a798SArnd Bergmann 		now = ktime_get();
11373ed4351aSDaniel Vetter 	}
11383ed4351aSDaniel Vetter 	e->pipe = pipe;
113967680d3cSArnd Bergmann 	send_vblank_event(dev, e, seq, now);
11403ed4351aSDaniel Vetter }
11413ed4351aSDaniel Vetter EXPORT_SYMBOL(drm_crtc_send_vblank_event);
11423ed4351aSDaniel Vetter 
__enable_vblank(struct drm_device * dev,unsigned int pipe)11433ed4351aSDaniel Vetter static int __enable_vblank(struct drm_device *dev, unsigned int pipe)
11443ed4351aSDaniel Vetter {
11453ed4351aSDaniel Vetter 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
11463ed4351aSDaniel Vetter 		struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
11473ed4351aSDaniel Vetter 
11485a4784f4SSam Ravnborg 		if (drm_WARN_ON(dev, !crtc))
11494ffb8deeSJoe Moriarty 			return 0;
11504ffb8deeSJoe Moriarty 
11513ed4351aSDaniel Vetter 		if (crtc->funcs->enable_vblank)
11523ed4351aSDaniel Vetter 			return crtc->funcs->enable_vblank(crtc);
115357bb1ee6SDaniel Vetter 	}
115457bb1ee6SDaniel Vetter #ifdef CONFIG_DRM_LEGACY
115557bb1ee6SDaniel Vetter 	else if (dev->driver->enable_vblank) {
1156f397d66bSThomas Zimmermann 		return dev->driver->enable_vblank(dev, pipe);
11573ed4351aSDaniel Vetter 	}
115857bb1ee6SDaniel Vetter #endif
11593ed4351aSDaniel Vetter 
1160f397d66bSThomas Zimmermann 	return -EINVAL;
11613ed4351aSDaniel Vetter }
11623ed4351aSDaniel Vetter 
drm_vblank_enable(struct drm_device * dev,unsigned int pipe)11633ed4351aSDaniel Vetter static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe)
11643ed4351aSDaniel Vetter {
11653ed4351aSDaniel Vetter 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
11663ed4351aSDaniel Vetter 	int ret = 0;
11673ed4351aSDaniel Vetter 
11683ed4351aSDaniel Vetter 	assert_spin_locked(&dev->vbl_lock);
11693ed4351aSDaniel Vetter 
11703ed4351aSDaniel Vetter 	spin_lock(&dev->vblank_time_lock);
11713ed4351aSDaniel Vetter 
11723ed4351aSDaniel Vetter 	if (!vblank->enabled) {
11733ed4351aSDaniel Vetter 		/*
11743ed4351aSDaniel Vetter 		 * Enable vblank irqs under vblank_time_lock protection.
11753ed4351aSDaniel Vetter 		 * All vblank count & timestamp updates are held off
11763ed4351aSDaniel Vetter 		 * until we are done reinitializing master counter and
11773ed4351aSDaniel Vetter 		 * timestamps. Filtercode in drm_handle_vblank() will
11783ed4351aSDaniel Vetter 		 * prevent double-accounting of same vblank interval.
11793ed4351aSDaniel Vetter 		 */
11803ed4351aSDaniel Vetter 		ret = __enable_vblank(dev, pipe);
118102149a76SSam Ravnborg 		drm_dbg_core(dev, "enabling vblank on crtc %u, ret: %d\n",
118202149a76SSam Ravnborg 			     pipe, ret);
11833ed4351aSDaniel Vetter 		if (ret) {
11843ed4351aSDaniel Vetter 			atomic_dec(&vblank->refcount);
11853ed4351aSDaniel Vetter 		} else {
11863ed4351aSDaniel Vetter 			drm_update_vblank_count(dev, pipe, 0);
11873ed4351aSDaniel Vetter 			/* drm_update_vblank_count() includes a wmb so we just
11883ed4351aSDaniel Vetter 			 * need to ensure that the compiler emits the write
11893ed4351aSDaniel Vetter 			 * to mark the vblank as enabled after the call
11903ed4351aSDaniel Vetter 			 * to drm_update_vblank_count().
11913ed4351aSDaniel Vetter 			 */
11923ed4351aSDaniel Vetter 			WRITE_ONCE(vblank->enabled, true);
11933ed4351aSDaniel Vetter 		}
11943ed4351aSDaniel Vetter 	}
11953ed4351aSDaniel Vetter 
11963ed4351aSDaniel Vetter 	spin_unlock(&dev->vblank_time_lock);
11973ed4351aSDaniel Vetter 
11983ed4351aSDaniel Vetter 	return ret;
11993ed4351aSDaniel Vetter }
12003ed4351aSDaniel Vetter 
drm_vblank_get(struct drm_device * dev,unsigned int pipe)12015e6c2b4fSLyude Paul int drm_vblank_get(struct drm_device *dev, unsigned int pipe)
12023ed4351aSDaniel Vetter {
12033ed4351aSDaniel Vetter 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
12043ed4351aSDaniel Vetter 	unsigned long irqflags;
12053ed4351aSDaniel Vetter 	int ret = 0;
12063ed4351aSDaniel Vetter 
12076015002eSDaniel Vetter 	if (!drm_dev_has_vblank(dev))
12083ed4351aSDaniel Vetter 		return -EINVAL;
12093ed4351aSDaniel Vetter 
12105a4784f4SSam Ravnborg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
12113ed4351aSDaniel Vetter 		return -EINVAL;
12123ed4351aSDaniel Vetter 
12133ed4351aSDaniel Vetter 	spin_lock_irqsave(&dev->vbl_lock, irqflags);
12143ed4351aSDaniel Vetter 	/* Going from 0->1 means we have to enable interrupts again */
12153ed4351aSDaniel Vetter 	if (atomic_add_return(1, &vblank->refcount) == 1) {
12163ed4351aSDaniel Vetter 		ret = drm_vblank_enable(dev, pipe);
12173ed4351aSDaniel Vetter 	} else {
12183ed4351aSDaniel Vetter 		if (!vblank->enabled) {
12193ed4351aSDaniel Vetter 			atomic_dec(&vblank->refcount);
12203ed4351aSDaniel Vetter 			ret = -EINVAL;
12213ed4351aSDaniel Vetter 		}
12223ed4351aSDaniel Vetter 	}
12233ed4351aSDaniel Vetter 	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
12243ed4351aSDaniel Vetter 
12253ed4351aSDaniel Vetter 	return ret;
12263ed4351aSDaniel Vetter }
12273ed4351aSDaniel Vetter 
12283ed4351aSDaniel Vetter /**
12293ed4351aSDaniel Vetter  * drm_crtc_vblank_get - get a reference count on vblank events
12303ed4351aSDaniel Vetter  * @crtc: which CRTC to own
12313ed4351aSDaniel Vetter  *
12323ed4351aSDaniel Vetter  * Acquire a reference count on vblank events to avoid having them disabled
12333ed4351aSDaniel Vetter  * while in use.
12343ed4351aSDaniel Vetter  *
12353ed4351aSDaniel Vetter  * Returns:
12363ed4351aSDaniel Vetter  * Zero on success or a negative error code on failure.
12373ed4351aSDaniel Vetter  */
drm_crtc_vblank_get(struct drm_crtc * crtc)12383ed4351aSDaniel Vetter int drm_crtc_vblank_get(struct drm_crtc *crtc)
12393ed4351aSDaniel Vetter {
12403ed4351aSDaniel Vetter 	return drm_vblank_get(crtc->dev, drm_crtc_index(crtc));
12413ed4351aSDaniel Vetter }
12423ed4351aSDaniel Vetter EXPORT_SYMBOL(drm_crtc_vblank_get);
12433ed4351aSDaniel Vetter 
drm_vblank_put(struct drm_device * dev,unsigned int pipe)12445e6c2b4fSLyude Paul void drm_vblank_put(struct drm_device *dev, unsigned int pipe)
12453ed4351aSDaniel Vetter {
12463ed4351aSDaniel Vetter 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
12473ed4351aSDaniel Vetter 
12485a4784f4SSam Ravnborg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
12493ed4351aSDaniel Vetter 		return;
12503ed4351aSDaniel Vetter 
12515a4784f4SSam Ravnborg 	if (drm_WARN_ON(dev, atomic_read(&vblank->refcount) == 0))
12523ed4351aSDaniel Vetter 		return;
12533ed4351aSDaniel Vetter 
12543ed4351aSDaniel Vetter 	/* Last user schedules interrupt disable */
12553ed4351aSDaniel Vetter 	if (atomic_dec_and_test(&vblank->refcount)) {
12563ed4351aSDaniel Vetter 		if (drm_vblank_offdelay == 0)
12573ed4351aSDaniel Vetter 			return;
12583ed4351aSDaniel Vetter 		else if (drm_vblank_offdelay < 0)
1259e99e88a9SKees Cook 			vblank_disable_fn(&vblank->disable_timer);
12603ed4351aSDaniel Vetter 		else if (!dev->vblank_disable_immediate)
12613ed4351aSDaniel Vetter 			mod_timer(&vblank->disable_timer,
12623ed4351aSDaniel Vetter 				  jiffies + ((drm_vblank_offdelay * HZ)/1000));
12633ed4351aSDaniel Vetter 	}
12643ed4351aSDaniel Vetter }
12653ed4351aSDaniel Vetter 
12663ed4351aSDaniel Vetter /**
12673ed4351aSDaniel Vetter  * drm_crtc_vblank_put - give up ownership of vblank events
12683ed4351aSDaniel Vetter  * @crtc: which counter to give up
12693ed4351aSDaniel Vetter  *
12703ed4351aSDaniel Vetter  * Release ownership of a given vblank counter, turning off interrupts
12713ed4351aSDaniel Vetter  * if possible. Disable interrupts after drm_vblank_offdelay milliseconds.
12723ed4351aSDaniel Vetter  */
drm_crtc_vblank_put(struct drm_crtc * crtc)12733ed4351aSDaniel Vetter void drm_crtc_vblank_put(struct drm_crtc *crtc)
12743ed4351aSDaniel Vetter {
12753ed4351aSDaniel Vetter 	drm_vblank_put(crtc->dev, drm_crtc_index(crtc));
12763ed4351aSDaniel Vetter }
12773ed4351aSDaniel Vetter EXPORT_SYMBOL(drm_crtc_vblank_put);
12783ed4351aSDaniel Vetter 
12793ed4351aSDaniel Vetter /**
12803ed4351aSDaniel Vetter  * drm_wait_one_vblank - wait for one vblank
12813ed4351aSDaniel Vetter  * @dev: DRM device
12823ed4351aSDaniel Vetter  * @pipe: CRTC index
12833ed4351aSDaniel Vetter  *
12843ed4351aSDaniel Vetter  * This waits for one vblank to pass on @pipe, using the irq driver interfaces.
12853ed4351aSDaniel Vetter  * It is a failure to call this when the vblank irq for @pipe is disabled, e.g.
12863ed4351aSDaniel Vetter  * due to lack of driver support or because the crtc is off.
128757d30230SDaniel Vetter  *
128857d30230SDaniel Vetter  * This is the legacy version of drm_crtc_wait_one_vblank().
12893ed4351aSDaniel Vetter  */
drm_wait_one_vblank(struct drm_device * dev,unsigned int pipe)12903ed4351aSDaniel Vetter void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe)
12913ed4351aSDaniel Vetter {
12923ed4351aSDaniel Vetter 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
12933ed4351aSDaniel Vetter 	int ret;
12943b765c0bSDhinakaran Pandiyan 	u64 last;
12953ed4351aSDaniel Vetter 
12965a4784f4SSam Ravnborg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
12973ed4351aSDaniel Vetter 		return;
12983ed4351aSDaniel Vetter 
12993ed4351aSDaniel Vetter 	ret = drm_vblank_get(dev, pipe);
13005a4784f4SSam Ravnborg 	if (drm_WARN(dev, ret, "vblank not available on crtc %i, ret=%i\n",
13015a4784f4SSam Ravnborg 		     pipe, ret))
13023ed4351aSDaniel Vetter 		return;
13033ed4351aSDaniel Vetter 
13043ed4351aSDaniel Vetter 	last = drm_vblank_count(dev, pipe);
13053ed4351aSDaniel Vetter 
13063ed4351aSDaniel Vetter 	ret = wait_event_timeout(vblank->queue,
13073ed4351aSDaniel Vetter 				 last != drm_vblank_count(dev, pipe),
13083ed4351aSDaniel Vetter 				 msecs_to_jiffies(100));
13093ed4351aSDaniel Vetter 
13105a4784f4SSam Ravnborg 	drm_WARN(dev, ret == 0, "vblank wait timed out on crtc %i\n", pipe);
13113ed4351aSDaniel Vetter 
13123ed4351aSDaniel Vetter 	drm_vblank_put(dev, pipe);
13133ed4351aSDaniel Vetter }
13143ed4351aSDaniel Vetter EXPORT_SYMBOL(drm_wait_one_vblank);
13153ed4351aSDaniel Vetter 
13163ed4351aSDaniel Vetter /**
13173ed4351aSDaniel Vetter  * drm_crtc_wait_one_vblank - wait for one vblank
13183ed4351aSDaniel Vetter  * @crtc: DRM crtc
13193ed4351aSDaniel Vetter  *
13203ed4351aSDaniel Vetter  * This waits for one vblank to pass on @crtc, using the irq driver interfaces.
13213ed4351aSDaniel Vetter  * It is a failure to call this when the vblank irq for @crtc is disabled, e.g.
13223ed4351aSDaniel Vetter  * due to lack of driver support or because the crtc is off.
13233ed4351aSDaniel Vetter  */
drm_crtc_wait_one_vblank(struct drm_crtc * crtc)13243ed4351aSDaniel Vetter void drm_crtc_wait_one_vblank(struct drm_crtc *crtc)
13253ed4351aSDaniel Vetter {
13263ed4351aSDaniel Vetter 	drm_wait_one_vblank(crtc->dev, drm_crtc_index(crtc));
13273ed4351aSDaniel Vetter }
13283ed4351aSDaniel Vetter EXPORT_SYMBOL(drm_crtc_wait_one_vblank);
13293ed4351aSDaniel Vetter 
13303ed4351aSDaniel Vetter /**
13313ed4351aSDaniel Vetter  * drm_crtc_vblank_off - disable vblank events on a CRTC
13323ed4351aSDaniel Vetter  * @crtc: CRTC in question
13333ed4351aSDaniel Vetter  *
13343ed4351aSDaniel Vetter  * Drivers can use this function to shut down the vblank interrupt handling when
13353ed4351aSDaniel Vetter  * disabling a crtc. This function ensures that the latest vblank frame count is
13363ed4351aSDaniel Vetter  * stored so that drm_vblank_on can restore it again.
13373ed4351aSDaniel Vetter  *
13383ed4351aSDaniel Vetter  * Drivers must use this function when the hardware vblank counter can get
133957d30230SDaniel Vetter  * reset, e.g. when suspending or disabling the @crtc in general.
13403ed4351aSDaniel Vetter  */
drm_crtc_vblank_off(struct drm_crtc * crtc)13413ed4351aSDaniel Vetter void drm_crtc_vblank_off(struct drm_crtc *crtc)
13423ed4351aSDaniel Vetter {
13433ed4351aSDaniel Vetter 	struct drm_device *dev = crtc->dev;
13443ed4351aSDaniel Vetter 	unsigned int pipe = drm_crtc_index(crtc);
13453ed4351aSDaniel Vetter 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
13463ed4351aSDaniel Vetter 	struct drm_pending_vblank_event *e, *t;
134767680d3cSArnd Bergmann 	ktime_t now;
1348570e8696SKeith Packard 	u64 seq;
13493ed4351aSDaniel Vetter 
13505a4784f4SSam Ravnborg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
13513ed4351aSDaniel Vetter 		return;
13523ed4351aSDaniel Vetter 
13535e6c2b4fSLyude Paul 	/*
13545e6c2b4fSLyude Paul 	 * Grab event_lock early to prevent vblank work from being scheduled
13555e6c2b4fSLyude Paul 	 * while we're in the middle of shutting down vblank interrupts
13565e6c2b4fSLyude Paul 	 */
1357a7e3ad5fSLyude Paul 	spin_lock_irq(&dev->event_lock);
13583ed4351aSDaniel Vetter 
13593ed4351aSDaniel Vetter 	spin_lock(&dev->vbl_lock);
136002149a76SSam Ravnborg 	drm_dbg_vbl(dev, "crtc %d, vblank enabled %d, inmodeset %d\n",
13613ed4351aSDaniel Vetter 		    pipe, vblank->enabled, vblank->inmodeset);
13623ed4351aSDaniel Vetter 
13633ed4351aSDaniel Vetter 	/* Avoid redundant vblank disables without previous
13643ed4351aSDaniel Vetter 	 * drm_crtc_vblank_on(). */
13653ed4351aSDaniel Vetter 	if (drm_core_check_feature(dev, DRIVER_ATOMIC) || !vblank->inmodeset)
13663ed4351aSDaniel Vetter 		drm_vblank_disable_and_save(dev, pipe);
13673ed4351aSDaniel Vetter 
13683ed4351aSDaniel Vetter 	wake_up(&vblank->queue);
13693ed4351aSDaniel Vetter 
13703ed4351aSDaniel Vetter 	/*
13713ed4351aSDaniel Vetter 	 * Prevent subsequent drm_vblank_get() from re-enabling
13723ed4351aSDaniel Vetter 	 * the vblank interrupt by bumping the refcount.
13733ed4351aSDaniel Vetter 	 */
13743ed4351aSDaniel Vetter 	if (!vblank->inmodeset) {
13753ed4351aSDaniel Vetter 		atomic_inc(&vblank->refcount);
13763ed4351aSDaniel Vetter 		vblank->inmodeset = 1;
13773ed4351aSDaniel Vetter 	}
13783ed4351aSDaniel Vetter 	spin_unlock(&dev->vbl_lock);
13793ed4351aSDaniel Vetter 
13803ed4351aSDaniel Vetter 	/* Send any queued vblank events, lest the natives grow disquiet */
13813ed4351aSDaniel Vetter 	seq = drm_vblank_count_and_time(dev, pipe, &now);
13823ed4351aSDaniel Vetter 
13833ed4351aSDaniel Vetter 	list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
13843ed4351aSDaniel Vetter 		if (e->pipe != pipe)
13853ed4351aSDaniel Vetter 			continue;
138602149a76SSam Ravnborg 		drm_dbg_core(dev, "Sending premature vblank event on disable: "
1387570e8696SKeith Packard 			     "wanted %llu, current %llu\n",
1388570e8696SKeith Packard 			     e->sequence, seq);
13893ed4351aSDaniel Vetter 		list_del(&e->base.link);
13903ed4351aSDaniel Vetter 		drm_vblank_put(dev, pipe);
139167680d3cSArnd Bergmann 		send_vblank_event(dev, e, seq, now);
13923ed4351aSDaniel Vetter 	}
13935e6c2b4fSLyude Paul 
13945e6c2b4fSLyude Paul 	/* Cancel any leftover pending vblank work */
13955e6c2b4fSLyude Paul 	drm_vblank_cancel_pending_works(vblank);
13965e6c2b4fSLyude Paul 
1397a7e3ad5fSLyude Paul 	spin_unlock_irq(&dev->event_lock);
13983ed4351aSDaniel Vetter 
13993ed4351aSDaniel Vetter 	/* Will be reset by the modeset helpers when re-enabling the crtc by
14003ed4351aSDaniel Vetter 	 * calling drm_calc_timestamping_constants(). */
14013ed4351aSDaniel Vetter 	vblank->hwmode.crtc_clock = 0;
14025e6c2b4fSLyude Paul 
14035e6c2b4fSLyude Paul 	/* Wait for any vblank work that's still executing to finish */
14045e6c2b4fSLyude Paul 	drm_vblank_flush_worker(vblank);
14053ed4351aSDaniel Vetter }
14063ed4351aSDaniel Vetter EXPORT_SYMBOL(drm_crtc_vblank_off);
14073ed4351aSDaniel Vetter 
14083ed4351aSDaniel Vetter /**
14093ed4351aSDaniel Vetter  * drm_crtc_vblank_reset - reset vblank state to off on a CRTC
14103ed4351aSDaniel Vetter  * @crtc: CRTC in question
14113ed4351aSDaniel Vetter  *
14123ed4351aSDaniel Vetter  * Drivers can use this function to reset the vblank state to off at load time.
14133ed4351aSDaniel Vetter  * Drivers should use this together with the drm_crtc_vblank_off() and
14143ed4351aSDaniel Vetter  * drm_crtc_vblank_on() functions. The difference compared to
14153ed4351aSDaniel Vetter  * drm_crtc_vblank_off() is that this function doesn't save the vblank counter
14163ed4351aSDaniel Vetter  * and hence doesn't need to call any driver hooks.
141757d30230SDaniel Vetter  *
141857d30230SDaniel Vetter  * This is useful for recovering driver state e.g. on driver load, or on resume.
14193ed4351aSDaniel Vetter  */
drm_crtc_vblank_reset(struct drm_crtc * crtc)14203ed4351aSDaniel Vetter void drm_crtc_vblank_reset(struct drm_crtc *crtc)
14213ed4351aSDaniel Vetter {
14223ed4351aSDaniel Vetter 	struct drm_device *dev = crtc->dev;
14233ed4351aSDaniel Vetter 	unsigned int pipe = drm_crtc_index(crtc);
14243ed4351aSDaniel Vetter 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
14253ed4351aSDaniel Vetter 
1426fbc678e8SLyude Paul 	spin_lock_irq(&dev->vbl_lock);
14273ed4351aSDaniel Vetter 	/*
14283ed4351aSDaniel Vetter 	 * Prevent subsequent drm_vblank_get() from enabling the vblank
14293ed4351aSDaniel Vetter 	 * interrupt by bumping the refcount.
14303ed4351aSDaniel Vetter 	 */
14313ed4351aSDaniel Vetter 	if (!vblank->inmodeset) {
14323ed4351aSDaniel Vetter 		atomic_inc(&vblank->refcount);
14333ed4351aSDaniel Vetter 		vblank->inmodeset = 1;
14343ed4351aSDaniel Vetter 	}
1435fbc678e8SLyude Paul 	spin_unlock_irq(&dev->vbl_lock);
14363ed4351aSDaniel Vetter 
14375a4784f4SSam Ravnborg 	drm_WARN_ON(dev, !list_empty(&dev->vblank_event_list));
14385e6c2b4fSLyude Paul 	drm_WARN_ON(dev, !list_empty(&vblank->pending_work));
14393ed4351aSDaniel Vetter }
14403ed4351aSDaniel Vetter EXPORT_SYMBOL(drm_crtc_vblank_reset);
14413ed4351aSDaniel Vetter 
14423ed4351aSDaniel Vetter /**
1443ed20151aSVille Syrjälä  * drm_crtc_set_max_vblank_count - configure the hw max vblank counter value
1444ed20151aSVille Syrjälä  * @crtc: CRTC in question
1445ed20151aSVille Syrjälä  * @max_vblank_count: max hardware vblank counter value
1446ed20151aSVille Syrjälä  *
1447ed20151aSVille Syrjälä  * Update the maximum hardware vblank counter value for @crtc
1448ed20151aSVille Syrjälä  * at runtime. Useful for hardware where the operation of the
1449ed20151aSVille Syrjälä  * hardware vblank counter depends on the currently active
1450ed20151aSVille Syrjälä  * display configuration.
1451ed20151aSVille Syrjälä  *
1452ed20151aSVille Syrjälä  * For example, if the hardware vblank counter does not work
1453ed20151aSVille Syrjälä  * when a specific connector is active the maximum can be set
1454ed20151aSVille Syrjälä  * to zero. And when that specific connector isn't active the
1455ed20151aSVille Syrjälä  * maximum can again be set to the appropriate non-zero value.
1456ed20151aSVille Syrjälä  *
1457ed20151aSVille Syrjälä  * If used, must be called before drm_vblank_on().
1458ed20151aSVille Syrjälä  */
drm_crtc_set_max_vblank_count(struct drm_crtc * crtc,u32 max_vblank_count)1459ed20151aSVille Syrjälä void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc,
1460ed20151aSVille Syrjälä 				   u32 max_vblank_count)
1461ed20151aSVille Syrjälä {
1462ed20151aSVille Syrjälä 	struct drm_device *dev = crtc->dev;
1463ed20151aSVille Syrjälä 	unsigned int pipe = drm_crtc_index(crtc);
1464ed20151aSVille Syrjälä 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
1465ed20151aSVille Syrjälä 
14665a4784f4SSam Ravnborg 	drm_WARN_ON(dev, dev->max_vblank_count);
14675a4784f4SSam Ravnborg 	drm_WARN_ON(dev, !READ_ONCE(vblank->inmodeset));
1468ed20151aSVille Syrjälä 
1469ed20151aSVille Syrjälä 	vblank->max_vblank_count = max_vblank_count;
1470ed20151aSVille Syrjälä }
1471ed20151aSVille Syrjälä EXPORT_SYMBOL(drm_crtc_set_max_vblank_count);
1472ed20151aSVille Syrjälä 
1473ed20151aSVille Syrjälä /**
14743ed4351aSDaniel Vetter  * drm_crtc_vblank_on - enable vblank events on a CRTC
14753ed4351aSDaniel Vetter  * @crtc: CRTC in question
14763ed4351aSDaniel Vetter  *
14773ed4351aSDaniel Vetter  * This functions restores the vblank interrupt state captured with
147857d30230SDaniel Vetter  * drm_crtc_vblank_off() again and is generally called when enabling @crtc. Note
147957d30230SDaniel Vetter  * that calls to drm_crtc_vblank_on() and drm_crtc_vblank_off() can be
148057d30230SDaniel Vetter  * unbalanced and so can also be unconditionally called in driver load code to
148157d30230SDaniel Vetter  * reflect the current hardware state of the crtc.
14823ed4351aSDaniel Vetter  */
drm_crtc_vblank_on(struct drm_crtc * crtc)14833ed4351aSDaniel Vetter void drm_crtc_vblank_on(struct drm_crtc *crtc)
14843ed4351aSDaniel Vetter {
14853ed4351aSDaniel Vetter 	struct drm_device *dev = crtc->dev;
14863ed4351aSDaniel Vetter 	unsigned int pipe = drm_crtc_index(crtc);
14873ed4351aSDaniel Vetter 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
14883ed4351aSDaniel Vetter 
14895a4784f4SSam Ravnborg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
14903ed4351aSDaniel Vetter 		return;
14913ed4351aSDaniel Vetter 
149292cc68e3SLyude Paul 	spin_lock_irq(&dev->vbl_lock);
149302149a76SSam Ravnborg 	drm_dbg_vbl(dev, "crtc %d, vblank enabled %d, inmodeset %d\n",
14943ed4351aSDaniel Vetter 		    pipe, vblank->enabled, vblank->inmodeset);
14953ed4351aSDaniel Vetter 
14963ed4351aSDaniel Vetter 	/* Drop our private "prevent drm_vblank_get" refcount */
14973ed4351aSDaniel Vetter 	if (vblank->inmodeset) {
14983ed4351aSDaniel Vetter 		atomic_dec(&vblank->refcount);
14993ed4351aSDaniel Vetter 		vblank->inmodeset = 0;
15003ed4351aSDaniel Vetter 	}
15013ed4351aSDaniel Vetter 
15023ed4351aSDaniel Vetter 	drm_reset_vblank_timestamp(dev, pipe);
15033ed4351aSDaniel Vetter 
15043ed4351aSDaniel Vetter 	/*
15053ed4351aSDaniel Vetter 	 * re-enable interrupts if there are users left, or the
15063ed4351aSDaniel Vetter 	 * user wishes vblank interrupts to be enabled all the time.
15073ed4351aSDaniel Vetter 	 */
15083ed4351aSDaniel Vetter 	if (atomic_read(&vblank->refcount) != 0 || drm_vblank_offdelay == 0)
15095a4784f4SSam Ravnborg 		drm_WARN_ON(dev, drm_vblank_enable(dev, pipe));
151092cc68e3SLyude Paul 	spin_unlock_irq(&dev->vbl_lock);
15113ed4351aSDaniel Vetter }
15123ed4351aSDaniel Vetter EXPORT_SYMBOL(drm_crtc_vblank_on);
15133ed4351aSDaniel Vetter 
drm_vblank_restore(struct drm_device * dev,unsigned int pipe)1514f66aaab8SDaniel Vetter static void drm_vblank_restore(struct drm_device *dev, unsigned int pipe)
1515d0bb96b4SDhinakaran Pandiyan {
1516d0bb96b4SDhinakaran Pandiyan 	ktime_t t_vblank;
1517d0bb96b4SDhinakaran Pandiyan 	struct drm_vblank_crtc *vblank;
1518d0bb96b4SDhinakaran Pandiyan 	int framedur_ns;
1519d0bb96b4SDhinakaran Pandiyan 	u64 diff_ns;
1520d0bb96b4SDhinakaran Pandiyan 	u32 cur_vblank, diff = 1;
1521d0bb96b4SDhinakaran Pandiyan 	int count = DRM_TIMESTAMP_MAXRETRIES;
1522167b4002SVille Syrjälä 	u32 max_vblank_count = drm_max_vblank_count(dev, pipe);
1523d0bb96b4SDhinakaran Pandiyan 
15245a4784f4SSam Ravnborg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
1525d0bb96b4SDhinakaran Pandiyan 		return;
1526d0bb96b4SDhinakaran Pandiyan 
1527d0bb96b4SDhinakaran Pandiyan 	assert_spin_locked(&dev->vbl_lock);
1528d0bb96b4SDhinakaran Pandiyan 	assert_spin_locked(&dev->vblank_time_lock);
1529d0bb96b4SDhinakaran Pandiyan 
1530d0bb96b4SDhinakaran Pandiyan 	vblank = &dev->vblank[pipe];
15315a4784f4SSam Ravnborg 	drm_WARN_ONCE(dev,
15325a4784f4SSam Ravnborg 		      drm_debug_enabled(DRM_UT_VBL) && !vblank->framedur_ns,
1533d0bb96b4SDhinakaran Pandiyan 		      "Cannot compute missed vblanks without frame duration\n");
1534d0bb96b4SDhinakaran Pandiyan 	framedur_ns = vblank->framedur_ns;
1535d0bb96b4SDhinakaran Pandiyan 
1536d0bb96b4SDhinakaran Pandiyan 	do {
1537d0bb96b4SDhinakaran Pandiyan 		cur_vblank = __get_vblank_counter(dev, pipe);
1538d0bb96b4SDhinakaran Pandiyan 		drm_get_last_vbltimestamp(dev, pipe, &t_vblank, false);
1539d0bb96b4SDhinakaran Pandiyan 	} while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
1540d0bb96b4SDhinakaran Pandiyan 
1541d0bb96b4SDhinakaran Pandiyan 	diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time));
1542d0bb96b4SDhinakaran Pandiyan 	if (framedur_ns)
1543d0bb96b4SDhinakaran Pandiyan 		diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns);
1544d0bb96b4SDhinakaran Pandiyan 
1545d0bb96b4SDhinakaran Pandiyan 
154602149a76SSam Ravnborg 	drm_dbg_vbl(dev,
154702149a76SSam Ravnborg 		    "missed %d vblanks in %lld ns, frame duration=%d ns, hw_diff=%d\n",
1548d0bb96b4SDhinakaran Pandiyan 		    diff, diff_ns, framedur_ns, cur_vblank - vblank->last);
1549167b4002SVille Syrjälä 	vblank->last = (cur_vblank - diff) & max_vblank_count;
1550d0bb96b4SDhinakaran Pandiyan }
1551d0bb96b4SDhinakaran Pandiyan 
1552d0bb96b4SDhinakaran Pandiyan /**
1553ea3f0ef3SDhinakaran Pandiyan  * drm_crtc_vblank_restore - estimate missed vblanks and update vblank count.
1554ea3f0ef3SDhinakaran Pandiyan  * @crtc: CRTC in question
1555ea3f0ef3SDhinakaran Pandiyan  *
1556d0bb96b4SDhinakaran Pandiyan  * Power manamement features can cause frame counter resets between vblank
1557ea3f0ef3SDhinakaran Pandiyan  * disable and enable. Drivers can use this function in their
1558ea3f0ef3SDhinakaran Pandiyan  * &drm_crtc_funcs.enable_vblank implementation to estimate missed vblanks since
1559ea3f0ef3SDhinakaran Pandiyan  * the last &drm_crtc_funcs.disable_vblank using timestamps and update the
1560ea3f0ef3SDhinakaran Pandiyan  * vblank counter.
1561f66aaab8SDaniel Vetter  *
1562f66aaab8SDaniel Vetter  * Note that drivers must have race-free high-precision timestamping support,
1563f66aaab8SDaniel Vetter  * i.e.  &drm_crtc_funcs.get_vblank_timestamp must be hooked up and
1564f66aaab8SDaniel Vetter  * &drm_driver.vblank_disable_immediate must be set to indicate the
1565f66aaab8SDaniel Vetter  * time-stamping functions are race-free against vblank hardware counter
1566f66aaab8SDaniel Vetter  * increments.
1567d0bb96b4SDhinakaran Pandiyan  */
drm_crtc_vblank_restore(struct drm_crtc * crtc)1568d0bb96b4SDhinakaran Pandiyan void drm_crtc_vblank_restore(struct drm_crtc *crtc)
1569d0bb96b4SDhinakaran Pandiyan {
1570f66aaab8SDaniel Vetter 	WARN_ON_ONCE(!crtc->funcs->get_vblank_timestamp);
1571f66aaab8SDaniel Vetter 	WARN_ON_ONCE(!crtc->dev->vblank_disable_immediate);
1572f66aaab8SDaniel Vetter 
1573d0bb96b4SDhinakaran Pandiyan 	drm_vblank_restore(crtc->dev, drm_crtc_index(crtc));
1574d0bb96b4SDhinakaran Pandiyan }
1575d0bb96b4SDhinakaran Pandiyan EXPORT_SYMBOL(drm_crtc_vblank_restore);
1576d0bb96b4SDhinakaran Pandiyan 
drm_legacy_vblank_pre_modeset(struct drm_device * dev,unsigned int pipe)15773ed4351aSDaniel Vetter static void drm_legacy_vblank_pre_modeset(struct drm_device *dev,
15783ed4351aSDaniel Vetter 					  unsigned int pipe)
15793ed4351aSDaniel Vetter {
15803ed4351aSDaniel Vetter 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
15813ed4351aSDaniel Vetter 
15823ed4351aSDaniel Vetter 	/* vblank is not initialized (IRQ not installed ?), or has been freed */
15836015002eSDaniel Vetter 	if (!drm_dev_has_vblank(dev))
15843ed4351aSDaniel Vetter 		return;
15853ed4351aSDaniel Vetter 
15865a4784f4SSam Ravnborg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
15873ed4351aSDaniel Vetter 		return;
15883ed4351aSDaniel Vetter 
15893ed4351aSDaniel Vetter 	/*
15903ed4351aSDaniel Vetter 	 * To avoid all the problems that might happen if interrupts
15913ed4351aSDaniel Vetter 	 * were enabled/disabled around or between these calls, we just
15923ed4351aSDaniel Vetter 	 * have the kernel take a reference on the CRTC (just once though
15933ed4351aSDaniel Vetter 	 * to avoid corrupting the count if multiple, mismatch calls occur),
15943ed4351aSDaniel Vetter 	 * so that interrupts remain enabled in the interim.
15953ed4351aSDaniel Vetter 	 */
15963ed4351aSDaniel Vetter 	if (!vblank->inmodeset) {
15973ed4351aSDaniel Vetter 		vblank->inmodeset = 0x1;
15983ed4351aSDaniel Vetter 		if (drm_vblank_get(dev, pipe) == 0)
15993ed4351aSDaniel Vetter 			vblank->inmodeset |= 0x2;
16003ed4351aSDaniel Vetter 	}
16013ed4351aSDaniel Vetter }
16023ed4351aSDaniel Vetter 
drm_legacy_vblank_post_modeset(struct drm_device * dev,unsigned int pipe)16033ed4351aSDaniel Vetter static void drm_legacy_vblank_post_modeset(struct drm_device *dev,
16043ed4351aSDaniel Vetter 					   unsigned int pipe)
16053ed4351aSDaniel Vetter {
16063ed4351aSDaniel Vetter 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
16073ed4351aSDaniel Vetter 
16083ed4351aSDaniel Vetter 	/* vblank is not initialized (IRQ not installed ?), or has been freed */
16096015002eSDaniel Vetter 	if (!drm_dev_has_vblank(dev))
16103ed4351aSDaniel Vetter 		return;
16113ed4351aSDaniel Vetter 
16125a4784f4SSam Ravnborg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
16133ed4351aSDaniel Vetter 		return;
16143ed4351aSDaniel Vetter 
16153ed4351aSDaniel Vetter 	if (vblank->inmodeset) {
1616eb2ee0efSLyude Paul 		spin_lock_irq(&dev->vbl_lock);
16173ed4351aSDaniel Vetter 		drm_reset_vblank_timestamp(dev, pipe);
1618eb2ee0efSLyude Paul 		spin_unlock_irq(&dev->vbl_lock);
16193ed4351aSDaniel Vetter 
16203ed4351aSDaniel Vetter 		if (vblank->inmodeset & 0x2)
16213ed4351aSDaniel Vetter 			drm_vblank_put(dev, pipe);
16223ed4351aSDaniel Vetter 
16233ed4351aSDaniel Vetter 		vblank->inmodeset = 0;
16243ed4351aSDaniel Vetter 	}
16253ed4351aSDaniel Vetter }
16263ed4351aSDaniel Vetter 
drm_legacy_modeset_ctl_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)1627b6dcaaacSDaniel Vetter int drm_legacy_modeset_ctl_ioctl(struct drm_device *dev, void *data,
16283ed4351aSDaniel Vetter 				 struct drm_file *file_priv)
16293ed4351aSDaniel Vetter {
16303ed4351aSDaniel Vetter 	struct drm_modeset_ctl *modeset = data;
16313ed4351aSDaniel Vetter 	unsigned int pipe;
16323ed4351aSDaniel Vetter 
16333ed4351aSDaniel Vetter 	/* If drm_vblank_init() hasn't been called yet, just no-op */
16346015002eSDaniel Vetter 	if (!drm_dev_has_vblank(dev))
16353ed4351aSDaniel Vetter 		return 0;
16363ed4351aSDaniel Vetter 
16373ed4351aSDaniel Vetter 	/* KMS drivers handle this internally */
16383ed4351aSDaniel Vetter 	if (!drm_core_check_feature(dev, DRIVER_LEGACY))
16393ed4351aSDaniel Vetter 		return 0;
16403ed4351aSDaniel Vetter 
16413ed4351aSDaniel Vetter 	pipe = modeset->crtc;
16423ed4351aSDaniel Vetter 	if (pipe >= dev->num_crtcs)
16433ed4351aSDaniel Vetter 		return -EINVAL;
16443ed4351aSDaniel Vetter 
16453ed4351aSDaniel Vetter 	switch (modeset->cmd) {
16463ed4351aSDaniel Vetter 	case _DRM_PRE_MODESET:
16473ed4351aSDaniel Vetter 		drm_legacy_vblank_pre_modeset(dev, pipe);
16483ed4351aSDaniel Vetter 		break;
16493ed4351aSDaniel Vetter 	case _DRM_POST_MODESET:
16503ed4351aSDaniel Vetter 		drm_legacy_vblank_post_modeset(dev, pipe);
16513ed4351aSDaniel Vetter 		break;
16523ed4351aSDaniel Vetter 	default:
16533ed4351aSDaniel Vetter 		return -EINVAL;
16543ed4351aSDaniel Vetter 	}
16553ed4351aSDaniel Vetter 
16563ed4351aSDaniel Vetter 	return 0;
16573ed4351aSDaniel Vetter }
16583ed4351aSDaniel Vetter 
drm_queue_vblank_event(struct drm_device * dev,unsigned int pipe,u64 req_seq,union drm_wait_vblank * vblwait,struct drm_file * file_priv)16593ed4351aSDaniel Vetter static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
1660570e8696SKeith Packard 				  u64 req_seq,
16613ed4351aSDaniel Vetter 				  union drm_wait_vblank *vblwait,
16623ed4351aSDaniel Vetter 				  struct drm_file *file_priv)
16633ed4351aSDaniel Vetter {
16643ed4351aSDaniel Vetter 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
16653ed4351aSDaniel Vetter 	struct drm_pending_vblank_event *e;
166667680d3cSArnd Bergmann 	ktime_t now;
1667570e8696SKeith Packard 	u64 seq;
16683ed4351aSDaniel Vetter 	int ret;
16693ed4351aSDaniel Vetter 
16703ed4351aSDaniel Vetter 	e = kzalloc(sizeof(*e), GFP_KERNEL);
16713ed4351aSDaniel Vetter 	if (e == NULL) {
16723ed4351aSDaniel Vetter 		ret = -ENOMEM;
16733ed4351aSDaniel Vetter 		goto err_put;
16743ed4351aSDaniel Vetter 	}
16753ed4351aSDaniel Vetter 
16763ed4351aSDaniel Vetter 	e->pipe = pipe;
16773ed4351aSDaniel Vetter 	e->event.base.type = DRM_EVENT_VBLANK;
1678bd386e51SKeith Packard 	e->event.base.length = sizeof(e->event.vbl);
1679bd386e51SKeith Packard 	e->event.vbl.user_data = vblwait->request.signal;
1680bd386e51SKeith Packard 	e->event.vbl.crtc_id = 0;
1681bd386e51SKeith Packard 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
1682bd386e51SKeith Packard 		struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
1683948de842SSuraj Upadhyay 
1684bd386e51SKeith Packard 		if (crtc)
1685bd386e51SKeith Packard 			e->event.vbl.crtc_id = crtc->base.id;
1686bd386e51SKeith Packard 	}
16873ed4351aSDaniel Vetter 
16887f07c35fSLyude Paul 	spin_lock_irq(&dev->event_lock);
16893ed4351aSDaniel Vetter 
16903ed4351aSDaniel Vetter 	/*
16913ed4351aSDaniel Vetter 	 * drm_crtc_vblank_off() might have been called after we called
16923ed4351aSDaniel Vetter 	 * drm_vblank_get(). drm_crtc_vblank_off() holds event_lock around the
16933ed4351aSDaniel Vetter 	 * vblank disable, so no need for further locking.  The reference from
16943ed4351aSDaniel Vetter 	 * drm_vblank_get() protects against vblank disable from another source.
16953ed4351aSDaniel Vetter 	 */
16963ed4351aSDaniel Vetter 	if (!READ_ONCE(vblank->enabled)) {
16973ed4351aSDaniel Vetter 		ret = -EINVAL;
16983ed4351aSDaniel Vetter 		goto err_unlock;
16993ed4351aSDaniel Vetter 	}
17003ed4351aSDaniel Vetter 
17013ed4351aSDaniel Vetter 	ret = drm_event_reserve_init_locked(dev, file_priv, &e->base,
17023ed4351aSDaniel Vetter 					    &e->event.base);
17033ed4351aSDaniel Vetter 
17043ed4351aSDaniel Vetter 	if (ret)
17053ed4351aSDaniel Vetter 		goto err_unlock;
17063ed4351aSDaniel Vetter 
17073ed4351aSDaniel Vetter 	seq = drm_vblank_count_and_time(dev, pipe, &now);
17083ed4351aSDaniel Vetter 
170902149a76SSam Ravnborg 	drm_dbg_core(dev, "event on vblank count %llu, current %llu, crtc %u\n",
1710570e8696SKeith Packard 		     req_seq, seq, pipe);
17113ed4351aSDaniel Vetter 
1712570e8696SKeith Packard 	trace_drm_vblank_event_queued(file_priv, pipe, req_seq);
17133ed4351aSDaniel Vetter 
1714570e8696SKeith Packard 	e->sequence = req_seq;
17155e6c2b4fSLyude Paul 	if (drm_vblank_passed(seq, req_seq)) {
17163ed4351aSDaniel Vetter 		drm_vblank_put(dev, pipe);
171767680d3cSArnd Bergmann 		send_vblank_event(dev, e, seq, now);
17183ed4351aSDaniel Vetter 		vblwait->reply.sequence = seq;
17193ed4351aSDaniel Vetter 	} else {
17203ed4351aSDaniel Vetter 		/* drm_handle_vblank_events will call drm_vblank_put */
17213ed4351aSDaniel Vetter 		list_add_tail(&e->base.link, &dev->vblank_event_list);
1722570e8696SKeith Packard 		vblwait->reply.sequence = req_seq;
17233ed4351aSDaniel Vetter 	}
17243ed4351aSDaniel Vetter 
17257f07c35fSLyude Paul 	spin_unlock_irq(&dev->event_lock);
17263ed4351aSDaniel Vetter 
17273ed4351aSDaniel Vetter 	return 0;
17283ed4351aSDaniel Vetter 
17293ed4351aSDaniel Vetter err_unlock:
17307f07c35fSLyude Paul 	spin_unlock_irq(&dev->event_lock);
17313ed4351aSDaniel Vetter 	kfree(e);
17323ed4351aSDaniel Vetter err_put:
17333ed4351aSDaniel Vetter 	drm_vblank_put(dev, pipe);
17343ed4351aSDaniel Vetter 	return ret;
17353ed4351aSDaniel Vetter }
17363ed4351aSDaniel Vetter 
drm_wait_vblank_is_query(union drm_wait_vblank * vblwait)17373ed4351aSDaniel Vetter static bool drm_wait_vblank_is_query(union drm_wait_vblank *vblwait)
17383ed4351aSDaniel Vetter {
17393ed4351aSDaniel Vetter 	if (vblwait->request.sequence)
17403ed4351aSDaniel Vetter 		return false;
17413ed4351aSDaniel Vetter 
17423ed4351aSDaniel Vetter 	return _DRM_VBLANK_RELATIVE ==
17433ed4351aSDaniel Vetter 		(vblwait->request.type & (_DRM_VBLANK_TYPES_MASK |
17443ed4351aSDaniel Vetter 					  _DRM_VBLANK_EVENT |
17453ed4351aSDaniel Vetter 					  _DRM_VBLANK_NEXTONMISS));
17463ed4351aSDaniel Vetter }
17473ed4351aSDaniel Vetter 
1748570e8696SKeith Packard /*
1749570e8696SKeith Packard  * Widen a 32-bit param to 64-bits.
1750570e8696SKeith Packard  *
1751570e8696SKeith Packard  * \param narrow 32-bit value (missing upper 32 bits)
1752570e8696SKeith Packard  * \param near 64-bit value that should be 'close' to near
1753570e8696SKeith Packard  *
1754570e8696SKeith Packard  * This function returns a 64-bit value using the lower 32-bits from
1755570e8696SKeith Packard  * 'narrow' and constructing the upper 32-bits so that the result is
1756570e8696SKeith Packard  * as close as possible to 'near'.
1757570e8696SKeith Packard  */
1758570e8696SKeith Packard 
widen_32_to_64(u32 narrow,u64 near)1759570e8696SKeith Packard static u64 widen_32_to_64(u32 narrow, u64 near)
1760570e8696SKeith Packard {
1761570e8696SKeith Packard 	return near + (s32) (narrow - near);
1762570e8696SKeith Packard }
1763570e8696SKeith Packard 
drm_wait_vblank_reply(struct drm_device * dev,unsigned int pipe,struct drm_wait_vblank_reply * reply)176467680d3cSArnd Bergmann static void drm_wait_vblank_reply(struct drm_device *dev, unsigned int pipe,
176567680d3cSArnd Bergmann 				  struct drm_wait_vblank_reply *reply)
176667680d3cSArnd Bergmann {
176767680d3cSArnd Bergmann 	ktime_t now;
176867680d3cSArnd Bergmann 	struct timespec64 ts;
176967680d3cSArnd Bergmann 
177067680d3cSArnd Bergmann 	/*
177167680d3cSArnd Bergmann 	 * drm_wait_vblank_reply is a UAPI structure that uses 'long'
177225e1a798SArnd Bergmann 	 * to store the seconds. This is safe as we always use monotonic
177325e1a798SArnd Bergmann 	 * timestamps since linux-4.15.
177467680d3cSArnd Bergmann 	 */
177567680d3cSArnd Bergmann 	reply->sequence = drm_vblank_count_and_time(dev, pipe, &now);
177667680d3cSArnd Bergmann 	ts = ktime_to_timespec64(now);
177767680d3cSArnd Bergmann 	reply->tval_sec = (u32)ts.tv_sec;
177867680d3cSArnd Bergmann 	reply->tval_usec = ts.tv_nsec / 1000;
177967680d3cSArnd Bergmann }
178067680d3cSArnd Bergmann 
drm_wait_vblank_supported(struct drm_device * dev)17811e4cd78eSThomas Zimmermann static bool drm_wait_vblank_supported(struct drm_device *dev)
17821e4cd78eSThomas Zimmermann {
1783c1736b90SThomas Zimmermann #if IS_ENABLED(CONFIG_DRM_LEGACY)
17841e4cd78eSThomas Zimmermann 	if (unlikely(drm_core_check_feature(dev, DRIVER_LEGACY)))
17851e4cd78eSThomas Zimmermann 		return dev->irq_enabled;
1786c1736b90SThomas Zimmermann #endif
17871e4cd78eSThomas Zimmermann 	return drm_dev_has_vblank(dev);
17881e4cd78eSThomas Zimmermann }
17891e4cd78eSThomas Zimmermann 
drm_wait_vblank_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)1790b6dcaaacSDaniel Vetter int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
17913ed4351aSDaniel Vetter 			  struct drm_file *file_priv)
17923ed4351aSDaniel Vetter {
17937de440dbSKeith Packard 	struct drm_crtc *crtc;
17943ed4351aSDaniel Vetter 	struct drm_vblank_crtc *vblank;
17953ed4351aSDaniel Vetter 	union drm_wait_vblank *vblwait = data;
17963ed4351aSDaniel Vetter 	int ret;
1797570e8696SKeith Packard 	u64 req_seq, seq;
17987de440dbSKeith Packard 	unsigned int pipe_index;
1799570e8696SKeith Packard 	unsigned int flags, pipe, high_pipe;
18003ed4351aSDaniel Vetter 
18011e4cd78eSThomas Zimmermann 	if (!drm_wait_vblank_supported(dev))
1802aed6105bSRodrigo Siqueira 		return -EOPNOTSUPP;
18033ed4351aSDaniel Vetter 
18043ed4351aSDaniel Vetter 	if (vblwait->request.type & _DRM_VBLANK_SIGNAL)
18053ed4351aSDaniel Vetter 		return -EINVAL;
18063ed4351aSDaniel Vetter 
18073ed4351aSDaniel Vetter 	if (vblwait->request.type &
18083ed4351aSDaniel Vetter 	    ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK |
18093ed4351aSDaniel Vetter 	      _DRM_VBLANK_HIGH_CRTC_MASK)) {
181002149a76SSam Ravnborg 		drm_dbg_core(dev,
181102149a76SSam Ravnborg 			     "Unsupported type value 0x%x, supported mask 0x%x\n",
18123ed4351aSDaniel Vetter 			     vblwait->request.type,
18133ed4351aSDaniel Vetter 			     (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK |
18143ed4351aSDaniel Vetter 			      _DRM_VBLANK_HIGH_CRTC_MASK));
18153ed4351aSDaniel Vetter 		return -EINVAL;
18163ed4351aSDaniel Vetter 	}
18173ed4351aSDaniel Vetter 
18183ed4351aSDaniel Vetter 	flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
18193ed4351aSDaniel Vetter 	high_pipe = (vblwait->request.type & _DRM_VBLANK_HIGH_CRTC_MASK);
18203ed4351aSDaniel Vetter 	if (high_pipe)
18217de440dbSKeith Packard 		pipe_index = high_pipe >> _DRM_VBLANK_HIGH_CRTC_SHIFT;
18223ed4351aSDaniel Vetter 	else
18237de440dbSKeith Packard 		pipe_index = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
18247de440dbSKeith Packard 
18257de440dbSKeith Packard 	/* Convert lease-relative crtc index into global crtc index */
18267de440dbSKeith Packard 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
18277de440dbSKeith Packard 		pipe = 0;
18287de440dbSKeith Packard 		drm_for_each_crtc(crtc, dev) {
18297de440dbSKeith Packard 			if (drm_lease_held(file_priv, crtc->base.id)) {
18307de440dbSKeith Packard 				if (pipe_index == 0)
18317de440dbSKeith Packard 					break;
18327de440dbSKeith Packard 				pipe_index--;
18337de440dbSKeith Packard 			}
18347de440dbSKeith Packard 			pipe++;
18357de440dbSKeith Packard 		}
18367de440dbSKeith Packard 	} else {
18377de440dbSKeith Packard 		pipe = pipe_index;
18387de440dbSKeith Packard 	}
18397de440dbSKeith Packard 
18403ed4351aSDaniel Vetter 	if (pipe >= dev->num_crtcs)
18413ed4351aSDaniel Vetter 		return -EINVAL;
18423ed4351aSDaniel Vetter 
18433ed4351aSDaniel Vetter 	vblank = &dev->vblank[pipe];
18443ed4351aSDaniel Vetter 
18453ed4351aSDaniel Vetter 	/* If the counter is currently enabled and accurate, short-circuit
18463ed4351aSDaniel Vetter 	 * queries to return the cached timestamp of the last vblank.
18473ed4351aSDaniel Vetter 	 */
18483ed4351aSDaniel Vetter 	if (dev->vblank_disable_immediate &&
18493ed4351aSDaniel Vetter 	    drm_wait_vblank_is_query(vblwait) &&
18503ed4351aSDaniel Vetter 	    READ_ONCE(vblank->enabled)) {
185167680d3cSArnd Bergmann 		drm_wait_vblank_reply(dev, pipe, &vblwait->reply);
18523ed4351aSDaniel Vetter 		return 0;
18533ed4351aSDaniel Vetter 	}
18543ed4351aSDaniel Vetter 
18553ed4351aSDaniel Vetter 	ret = drm_vblank_get(dev, pipe);
18563ed4351aSDaniel Vetter 	if (ret) {
185702149a76SSam Ravnborg 		drm_dbg_core(dev,
185802149a76SSam Ravnborg 			     "crtc %d failed to acquire vblank counter, %d\n",
185902149a76SSam Ravnborg 			     pipe, ret);
18603ed4351aSDaniel Vetter 		return ret;
18613ed4351aSDaniel Vetter 	}
18623ed4351aSDaniel Vetter 	seq = drm_vblank_count(dev, pipe);
18633ed4351aSDaniel Vetter 
18643ed4351aSDaniel Vetter 	switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
18653ed4351aSDaniel Vetter 	case _DRM_VBLANK_RELATIVE:
1866570e8696SKeith Packard 		req_seq = seq + vblwait->request.sequence;
1867570e8696SKeith Packard 		vblwait->request.sequence = req_seq;
18683ed4351aSDaniel Vetter 		vblwait->request.type &= ~_DRM_VBLANK_RELATIVE;
1869570e8696SKeith Packard 		break;
18703ed4351aSDaniel Vetter 	case _DRM_VBLANK_ABSOLUTE:
1871570e8696SKeith Packard 		req_seq = widen_32_to_64(vblwait->request.sequence, seq);
18723ed4351aSDaniel Vetter 		break;
18733ed4351aSDaniel Vetter 	default:
18743ed4351aSDaniel Vetter 		ret = -EINVAL;
18753ed4351aSDaniel Vetter 		goto done;
18763ed4351aSDaniel Vetter 	}
18773ed4351aSDaniel Vetter 
18783ed4351aSDaniel Vetter 	if ((flags & _DRM_VBLANK_NEXTONMISS) &&
18795e6c2b4fSLyude Paul 	    drm_vblank_passed(seq, req_seq)) {
1880570e8696SKeith Packard 		req_seq = seq + 1;
1881570e8696SKeith Packard 		vblwait->request.type &= ~_DRM_VBLANK_NEXTONMISS;
1882570e8696SKeith Packard 		vblwait->request.sequence = req_seq;
1883570e8696SKeith Packard 	}
18843ed4351aSDaniel Vetter 
18853ed4351aSDaniel Vetter 	if (flags & _DRM_VBLANK_EVENT) {
18863ed4351aSDaniel Vetter 		/* must hold on to the vblank ref until the event fires
18873ed4351aSDaniel Vetter 		 * drm_vblank_put will be called asynchronously
18883ed4351aSDaniel Vetter 		 */
1889570e8696SKeith Packard 		return drm_queue_vblank_event(dev, pipe, req_seq, vblwait, file_priv);
18903ed4351aSDaniel Vetter 	}
18913ed4351aSDaniel Vetter 
1892570e8696SKeith Packard 	if (req_seq != seq) {
189305103ea9SSam Ravnborg 		int wait;
189405103ea9SSam Ravnborg 
189502149a76SSam Ravnborg 		drm_dbg_core(dev, "waiting on vblank count %llu, crtc %u\n",
1896570e8696SKeith Packard 			     req_seq, pipe);
189705103ea9SSam Ravnborg 		wait = wait_event_interruptible_timeout(vblank->queue,
18985e6c2b4fSLyude Paul 			drm_vblank_passed(drm_vblank_count(dev, pipe), req_seq) ||
189905103ea9SSam Ravnborg 				      !READ_ONCE(vblank->enabled),
190005103ea9SSam Ravnborg 			msecs_to_jiffies(3000));
190105103ea9SSam Ravnborg 
190205103ea9SSam Ravnborg 		switch (wait) {
190305103ea9SSam Ravnborg 		case 0:
190405103ea9SSam Ravnborg 			/* timeout */
190505103ea9SSam Ravnborg 			ret = -EBUSY;
190605103ea9SSam Ravnborg 			break;
190705103ea9SSam Ravnborg 		case -ERESTARTSYS:
190805103ea9SSam Ravnborg 			/* interrupted by signal */
190905103ea9SSam Ravnborg 			ret = -EINTR;
191005103ea9SSam Ravnborg 			break;
191105103ea9SSam Ravnborg 		default:
191205103ea9SSam Ravnborg 			ret = 0;
191305103ea9SSam Ravnborg 			break;
191405103ea9SSam Ravnborg 		}
19153ed4351aSDaniel Vetter 	}
19163ed4351aSDaniel Vetter 
19173ed4351aSDaniel Vetter 	if (ret != -EINTR) {
191867680d3cSArnd Bergmann 		drm_wait_vblank_reply(dev, pipe, &vblwait->reply);
19193ed4351aSDaniel Vetter 
192002149a76SSam Ravnborg 		drm_dbg_core(dev, "crtc %d returning %u to client\n",
19213ed4351aSDaniel Vetter 			     pipe, vblwait->reply.sequence);
19223ed4351aSDaniel Vetter 	} else {
192302149a76SSam Ravnborg 		drm_dbg_core(dev, "crtc %d vblank wait interrupted by signal\n",
192402149a76SSam Ravnborg 			     pipe);
19253ed4351aSDaniel Vetter 	}
19263ed4351aSDaniel Vetter 
19273ed4351aSDaniel Vetter done:
19283ed4351aSDaniel Vetter 	drm_vblank_put(dev, pipe);
19293ed4351aSDaniel Vetter 	return ret;
19303ed4351aSDaniel Vetter }
19313ed4351aSDaniel Vetter 
drm_handle_vblank_events(struct drm_device * dev,unsigned int pipe)19323ed4351aSDaniel Vetter static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe)
19333ed4351aSDaniel Vetter {
19347fe3f0d1SThomas Zimmermann 	struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
19357fe3f0d1SThomas Zimmermann 	bool high_prec = false;
19363ed4351aSDaniel Vetter 	struct drm_pending_vblank_event *e, *t;
193767680d3cSArnd Bergmann 	ktime_t now;
1938570e8696SKeith Packard 	u64 seq;
19393ed4351aSDaniel Vetter 
19403ed4351aSDaniel Vetter 	assert_spin_locked(&dev->event_lock);
19413ed4351aSDaniel Vetter 
19423ed4351aSDaniel Vetter 	seq = drm_vblank_count_and_time(dev, pipe, &now);
19433ed4351aSDaniel Vetter 
19443ed4351aSDaniel Vetter 	list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
19453ed4351aSDaniel Vetter 		if (e->pipe != pipe)
19463ed4351aSDaniel Vetter 			continue;
19475e6c2b4fSLyude Paul 		if (!drm_vblank_passed(seq, e->sequence))
19483ed4351aSDaniel Vetter 			continue;
19493ed4351aSDaniel Vetter 
195002149a76SSam Ravnborg 		drm_dbg_core(dev, "vblank event on %llu, current %llu\n",
1951570e8696SKeith Packard 			     e->sequence, seq);
19523ed4351aSDaniel Vetter 
19533ed4351aSDaniel Vetter 		list_del(&e->base.link);
19543ed4351aSDaniel Vetter 		drm_vblank_put(dev, pipe);
195567680d3cSArnd Bergmann 		send_vblank_event(dev, e, seq, now);
19563ed4351aSDaniel Vetter 	}
19573ed4351aSDaniel Vetter 
19587fe3f0d1SThomas Zimmermann 	if (crtc && crtc->funcs->get_vblank_timestamp)
19597fe3f0d1SThomas Zimmermann 		high_prec = true;
19607fe3f0d1SThomas Zimmermann 
19617fe3f0d1SThomas Zimmermann 	trace_drm_vblank_event(pipe, seq, now, high_prec);
19623ed4351aSDaniel Vetter }
19633ed4351aSDaniel Vetter 
19643ed4351aSDaniel Vetter /**
19653ed4351aSDaniel Vetter  * drm_handle_vblank - handle a vblank event
19663ed4351aSDaniel Vetter  * @dev: DRM device
19673ed4351aSDaniel Vetter  * @pipe: index of CRTC where this event occurred
19683ed4351aSDaniel Vetter  *
19693ed4351aSDaniel Vetter  * Drivers should call this routine in their vblank interrupt handlers to
19703ed4351aSDaniel Vetter  * update the vblank counter and send any signals that may be pending.
19713ed4351aSDaniel Vetter  *
19723ed4351aSDaniel Vetter  * This is the legacy version of drm_crtc_handle_vblank().
19733ed4351aSDaniel Vetter  */
drm_handle_vblank(struct drm_device * dev,unsigned int pipe)19743ed4351aSDaniel Vetter bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe)
19753ed4351aSDaniel Vetter {
19763ed4351aSDaniel Vetter 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
19773ed4351aSDaniel Vetter 	unsigned long irqflags;
19783ed4351aSDaniel Vetter 	bool disable_irq;
19793ed4351aSDaniel Vetter 
19805a4784f4SSam Ravnborg 	if (drm_WARN_ON_ONCE(dev, !drm_dev_has_vblank(dev)))
19813ed4351aSDaniel Vetter 		return false;
19823ed4351aSDaniel Vetter 
19835a4784f4SSam Ravnborg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
19843ed4351aSDaniel Vetter 		return false;
19853ed4351aSDaniel Vetter 
19863ed4351aSDaniel Vetter 	spin_lock_irqsave(&dev->event_lock, irqflags);
19873ed4351aSDaniel Vetter 
19883ed4351aSDaniel Vetter 	/* Need timestamp lock to prevent concurrent execution with
19893ed4351aSDaniel Vetter 	 * vblank enable/disable, as this would cause inconsistent
19903ed4351aSDaniel Vetter 	 * or corrupted timestamps and vblank counts.
19913ed4351aSDaniel Vetter 	 */
19923ed4351aSDaniel Vetter 	spin_lock(&dev->vblank_time_lock);
19933ed4351aSDaniel Vetter 
19943ed4351aSDaniel Vetter 	/* Vblank irq handling disabled. Nothing to do. */
19953ed4351aSDaniel Vetter 	if (!vblank->enabled) {
19963ed4351aSDaniel Vetter 		spin_unlock(&dev->vblank_time_lock);
19973ed4351aSDaniel Vetter 		spin_unlock_irqrestore(&dev->event_lock, irqflags);
19983ed4351aSDaniel Vetter 		return false;
19993ed4351aSDaniel Vetter 	}
20003ed4351aSDaniel Vetter 
20013ed4351aSDaniel Vetter 	drm_update_vblank_count(dev, pipe, true);
20023ed4351aSDaniel Vetter 
20033ed4351aSDaniel Vetter 	spin_unlock(&dev->vblank_time_lock);
20043ed4351aSDaniel Vetter 
20053ed4351aSDaniel Vetter 	wake_up(&vblank->queue);
20063ed4351aSDaniel Vetter 
20073ed4351aSDaniel Vetter 	/* With instant-off, we defer disabling the interrupt until after
20083ed4351aSDaniel Vetter 	 * we finish processing the following vblank after all events have
20093ed4351aSDaniel Vetter 	 * been signaled. The disable has to be last (after
20103ed4351aSDaniel Vetter 	 * drm_handle_vblank_events) so that the timestamp is always accurate.
20113ed4351aSDaniel Vetter 	 */
20123ed4351aSDaniel Vetter 	disable_irq = (dev->vblank_disable_immediate &&
20133ed4351aSDaniel Vetter 		       drm_vblank_offdelay > 0 &&
20143ed4351aSDaniel Vetter 		       !atomic_read(&vblank->refcount));
20153ed4351aSDaniel Vetter 
20163ed4351aSDaniel Vetter 	drm_handle_vblank_events(dev, pipe);
20175e6c2b4fSLyude Paul 	drm_handle_vblank_works(vblank);
20183ed4351aSDaniel Vetter 
20193ed4351aSDaniel Vetter 	spin_unlock_irqrestore(&dev->event_lock, irqflags);
20203ed4351aSDaniel Vetter 
20213ed4351aSDaniel Vetter 	if (disable_irq)
2022e99e88a9SKees Cook 		vblank_disable_fn(&vblank->disable_timer);
20233ed4351aSDaniel Vetter 
20243ed4351aSDaniel Vetter 	return true;
20253ed4351aSDaniel Vetter }
20263ed4351aSDaniel Vetter EXPORT_SYMBOL(drm_handle_vblank);
20273ed4351aSDaniel Vetter 
20283ed4351aSDaniel Vetter /**
20293ed4351aSDaniel Vetter  * drm_crtc_handle_vblank - handle a vblank event
20303ed4351aSDaniel Vetter  * @crtc: where this event occurred
20313ed4351aSDaniel Vetter  *
20323ed4351aSDaniel Vetter  * Drivers should call this routine in their vblank interrupt handlers to
20333ed4351aSDaniel Vetter  * update the vblank counter and send any signals that may be pending.
20343ed4351aSDaniel Vetter  *
20353ed4351aSDaniel Vetter  * This is the native KMS version of drm_handle_vblank().
20363ed4351aSDaniel Vetter  *
2037bd7e3f3bSDaniel Vetter  * Note that for a given vblank counter value drm_crtc_handle_vblank()
2038bd7e3f3bSDaniel Vetter  * and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time()
2039bd7e3f3bSDaniel Vetter  * provide a barrier: Any writes done before calling
2040bd7e3f3bSDaniel Vetter  * drm_crtc_handle_vblank() will be visible to callers of the later
20410ae865efSCai Huoqing  * functions, if the vblank count is the same or a later one.
2042bd7e3f3bSDaniel Vetter  *
2043bd7e3f3bSDaniel Vetter  * See also &drm_vblank_crtc.count.
2044bd7e3f3bSDaniel Vetter  *
20453ed4351aSDaniel Vetter  * Returns:
20463ed4351aSDaniel Vetter  * True if the event was successfully handled, false on failure.
20473ed4351aSDaniel Vetter  */
drm_crtc_handle_vblank(struct drm_crtc * crtc)20483ed4351aSDaniel Vetter bool drm_crtc_handle_vblank(struct drm_crtc *crtc)
20493ed4351aSDaniel Vetter {
20503ed4351aSDaniel Vetter 	return drm_handle_vblank(crtc->dev, drm_crtc_index(crtc));
20513ed4351aSDaniel Vetter }
20523ed4351aSDaniel Vetter EXPORT_SYMBOL(drm_crtc_handle_vblank);
20533064abfaSKeith Packard 
20543064abfaSKeith Packard /*
20553064abfaSKeith Packard  * Get crtc VBLANK count.
20563064abfaSKeith Packard  *
20573064abfaSKeith Packard  * \param dev DRM device
20580ae865efSCai Huoqing  * \param data user argument, pointing to a drm_crtc_get_sequence structure.
20593064abfaSKeith Packard  * \param file_priv drm file private for the user's open file descriptor
20603064abfaSKeith Packard  */
20613064abfaSKeith Packard 
drm_crtc_get_sequence_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)20623064abfaSKeith Packard int drm_crtc_get_sequence_ioctl(struct drm_device *dev, void *data,
20633064abfaSKeith Packard 				struct drm_file *file_priv)
20643064abfaSKeith Packard {
20653064abfaSKeith Packard 	struct drm_crtc *crtc;
20663064abfaSKeith Packard 	struct drm_vblank_crtc *vblank;
20673064abfaSKeith Packard 	int pipe;
20683064abfaSKeith Packard 	struct drm_crtc_get_sequence *get_seq = data;
20693064abfaSKeith Packard 	ktime_t now;
20703064abfaSKeith Packard 	bool vblank_enabled;
20713064abfaSKeith Packard 	int ret;
20723064abfaSKeith Packard 
20733064abfaSKeith Packard 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
207469fdf420SChris Wilson 		return -EOPNOTSUPP;
20753064abfaSKeith Packard 
20761e4cd78eSThomas Zimmermann 	if (!drm_dev_has_vblank(dev))
2077aed6105bSRodrigo Siqueira 		return -EOPNOTSUPP;
20783064abfaSKeith Packard 
20793064abfaSKeith Packard 	crtc = drm_crtc_find(dev, file_priv, get_seq->crtc_id);
20803064abfaSKeith Packard 	if (!crtc)
20813064abfaSKeith Packard 		return -ENOENT;
20823064abfaSKeith Packard 
20833064abfaSKeith Packard 	pipe = drm_crtc_index(crtc);
20843064abfaSKeith Packard 
20853064abfaSKeith Packard 	vblank = &dev->vblank[pipe];
20863064abfaSKeith Packard 	vblank_enabled = dev->vblank_disable_immediate && READ_ONCE(vblank->enabled);
20873064abfaSKeith Packard 
20883064abfaSKeith Packard 	if (!vblank_enabled) {
20893064abfaSKeith Packard 		ret = drm_crtc_vblank_get(crtc);
20903064abfaSKeith Packard 		if (ret) {
209102149a76SSam Ravnborg 			drm_dbg_core(dev,
209202149a76SSam Ravnborg 				     "crtc %d failed to acquire vblank counter, %d\n",
209302149a76SSam Ravnborg 				     pipe, ret);
20943064abfaSKeith Packard 			return ret;
20953064abfaSKeith Packard 		}
20963064abfaSKeith Packard 	}
20973064abfaSKeith Packard 	drm_modeset_lock(&crtc->mutex, NULL);
20983064abfaSKeith Packard 	if (crtc->state)
20993064abfaSKeith Packard 		get_seq->active = crtc->state->enable;
21003064abfaSKeith Packard 	else
21013064abfaSKeith Packard 		get_seq->active = crtc->enabled;
21023064abfaSKeith Packard 	drm_modeset_unlock(&crtc->mutex);
21033064abfaSKeith Packard 	get_seq->sequence = drm_vblank_count_and_time(dev, pipe, &now);
21043064abfaSKeith Packard 	get_seq->sequence_ns = ktime_to_ns(now);
21053064abfaSKeith Packard 	if (!vblank_enabled)
21063064abfaSKeith Packard 		drm_crtc_vblank_put(crtc);
21073064abfaSKeith Packard 	return 0;
21083064abfaSKeith Packard }
21093064abfaSKeith Packard 
21103064abfaSKeith Packard /*
21113064abfaSKeith Packard  * Queue a event for VBLANK sequence
21123064abfaSKeith Packard  *
21133064abfaSKeith Packard  * \param dev DRM device
21140ae865efSCai Huoqing  * \param data user argument, pointing to a drm_crtc_queue_sequence structure.
21153064abfaSKeith Packard  * \param file_priv drm file private for the user's open file descriptor
21163064abfaSKeith Packard  */
21173064abfaSKeith Packard 
drm_crtc_queue_sequence_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)21183064abfaSKeith Packard int drm_crtc_queue_sequence_ioctl(struct drm_device *dev, void *data,
21193064abfaSKeith Packard 				  struct drm_file *file_priv)
21203064abfaSKeith Packard {
21213064abfaSKeith Packard 	struct drm_crtc *crtc;
21223064abfaSKeith Packard 	struct drm_vblank_crtc *vblank;
21233064abfaSKeith Packard 	int pipe;
21243064abfaSKeith Packard 	struct drm_crtc_queue_sequence *queue_seq = data;
21253064abfaSKeith Packard 	ktime_t now;
21263064abfaSKeith Packard 	struct drm_pending_vblank_event *e;
21273064abfaSKeith Packard 	u32 flags;
21283064abfaSKeith Packard 	u64 seq;
21293064abfaSKeith Packard 	u64 req_seq;
21303064abfaSKeith Packard 	int ret;
21313064abfaSKeith Packard 
21323064abfaSKeith Packard 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
213369fdf420SChris Wilson 		return -EOPNOTSUPP;
21343064abfaSKeith Packard 
21351e4cd78eSThomas Zimmermann 	if (!drm_dev_has_vblank(dev))
2136aed6105bSRodrigo Siqueira 		return -EOPNOTSUPP;
21373064abfaSKeith Packard 
21383064abfaSKeith Packard 	crtc = drm_crtc_find(dev, file_priv, queue_seq->crtc_id);
21393064abfaSKeith Packard 	if (!crtc)
21403064abfaSKeith Packard 		return -ENOENT;
21413064abfaSKeith Packard 
21423064abfaSKeith Packard 	flags = queue_seq->flags;
21433064abfaSKeith Packard 	/* Check valid flag bits */
21443064abfaSKeith Packard 	if (flags & ~(DRM_CRTC_SEQUENCE_RELATIVE|
21453064abfaSKeith Packard 		      DRM_CRTC_SEQUENCE_NEXT_ON_MISS))
21463064abfaSKeith Packard 		return -EINVAL;
21473064abfaSKeith Packard 
21483064abfaSKeith Packard 	pipe = drm_crtc_index(crtc);
21493064abfaSKeith Packard 
21503064abfaSKeith Packard 	vblank = &dev->vblank[pipe];
21513064abfaSKeith Packard 
21523064abfaSKeith Packard 	e = kzalloc(sizeof(*e), GFP_KERNEL);
21533064abfaSKeith Packard 	if (e == NULL)
21543064abfaSKeith Packard 		return -ENOMEM;
21553064abfaSKeith Packard 
21563064abfaSKeith Packard 	ret = drm_crtc_vblank_get(crtc);
21573064abfaSKeith Packard 	if (ret) {
215802149a76SSam Ravnborg 		drm_dbg_core(dev,
215902149a76SSam Ravnborg 			     "crtc %d failed to acquire vblank counter, %d\n",
216002149a76SSam Ravnborg 			     pipe, ret);
21613064abfaSKeith Packard 		goto err_free;
21623064abfaSKeith Packard 	}
21633064abfaSKeith Packard 
21643064abfaSKeith Packard 	seq = drm_vblank_count_and_time(dev, pipe, &now);
21653064abfaSKeith Packard 	req_seq = queue_seq->sequence;
21663064abfaSKeith Packard 
21673064abfaSKeith Packard 	if (flags & DRM_CRTC_SEQUENCE_RELATIVE)
21683064abfaSKeith Packard 		req_seq += seq;
21693064abfaSKeith Packard 
21705e6c2b4fSLyude Paul 	if ((flags & DRM_CRTC_SEQUENCE_NEXT_ON_MISS) && drm_vblank_passed(seq, req_seq))
21713064abfaSKeith Packard 		req_seq = seq + 1;
21723064abfaSKeith Packard 
21733064abfaSKeith Packard 	e->pipe = pipe;
21743064abfaSKeith Packard 	e->event.base.type = DRM_EVENT_CRTC_SEQUENCE;
21753064abfaSKeith Packard 	e->event.base.length = sizeof(e->event.seq);
21763064abfaSKeith Packard 	e->event.seq.user_data = queue_seq->user_data;
21773064abfaSKeith Packard 
21785887a2adSLyude Paul 	spin_lock_irq(&dev->event_lock);
21793064abfaSKeith Packard 
21803064abfaSKeith Packard 	/*
21813064abfaSKeith Packard 	 * drm_crtc_vblank_off() might have been called after we called
21823064abfaSKeith Packard 	 * drm_crtc_vblank_get(). drm_crtc_vblank_off() holds event_lock around the
21833064abfaSKeith Packard 	 * vblank disable, so no need for further locking.  The reference from
21843064abfaSKeith Packard 	 * drm_crtc_vblank_get() protects against vblank disable from another source.
21853064abfaSKeith Packard 	 */
21863064abfaSKeith Packard 	if (!READ_ONCE(vblank->enabled)) {
21873064abfaSKeith Packard 		ret = -EINVAL;
21883064abfaSKeith Packard 		goto err_unlock;
21893064abfaSKeith Packard 	}
21903064abfaSKeith Packard 
21913064abfaSKeith Packard 	ret = drm_event_reserve_init_locked(dev, file_priv, &e->base,
21923064abfaSKeith Packard 					    &e->event.base);
21933064abfaSKeith Packard 
21943064abfaSKeith Packard 	if (ret)
21953064abfaSKeith Packard 		goto err_unlock;
21963064abfaSKeith Packard 
21973064abfaSKeith Packard 	e->sequence = req_seq;
21983064abfaSKeith Packard 
21995e6c2b4fSLyude Paul 	if (drm_vblank_passed(seq, req_seq)) {
22003064abfaSKeith Packard 		drm_crtc_vblank_put(crtc);
22013064abfaSKeith Packard 		send_vblank_event(dev, e, seq, now);
22023064abfaSKeith Packard 		queue_seq->sequence = seq;
22033064abfaSKeith Packard 	} else {
22043064abfaSKeith Packard 		/* drm_handle_vblank_events will call drm_vblank_put */
22053064abfaSKeith Packard 		list_add_tail(&e->base.link, &dev->vblank_event_list);
22063064abfaSKeith Packard 		queue_seq->sequence = req_seq;
22073064abfaSKeith Packard 	}
22083064abfaSKeith Packard 
22095887a2adSLyude Paul 	spin_unlock_irq(&dev->event_lock);
22103064abfaSKeith Packard 	return 0;
22113064abfaSKeith Packard 
22123064abfaSKeith Packard err_unlock:
22135887a2adSLyude Paul 	spin_unlock_irq(&dev->event_lock);
22143064abfaSKeith Packard 	drm_crtc_vblank_put(crtc);
22153064abfaSKeith Packard err_free:
22163064abfaSKeith Packard 	kfree(e);
22173064abfaSKeith Packard 	return ret;
22183064abfaSKeith Packard }
22195e6c2b4fSLyude Paul 
2220