xref: /openbsd-src/sys/dev/pci/drm/drm_vblank.c (revision f005ef32267c16bdb134f0e9fa4477dbe07c263a)
17f4dd379Sjsg /*
27f4dd379Sjsg  * drm_irq.c IRQ and vblank support
37f4dd379Sjsg  *
47f4dd379Sjsg  * \author Rickard E. (Rik) Faith <faith@valinux.com>
57f4dd379Sjsg  * \author Gareth Hughes <gareth@valinux.com>
67f4dd379Sjsg  *
77f4dd379Sjsg  * Permission is hereby granted, free of charge, to any person obtaining a
87f4dd379Sjsg  * copy of this software and associated documentation files (the "Software"),
97f4dd379Sjsg  * to deal in the Software without restriction, including without limitation
107f4dd379Sjsg  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
117f4dd379Sjsg  * and/or sell copies of the Software, and to permit persons to whom the
127f4dd379Sjsg  * Software is furnished to do so, subject to the following conditions:
137f4dd379Sjsg  *
147f4dd379Sjsg  * The above copyright notice and this permission notice (including the next
157f4dd379Sjsg  * paragraph) shall be included in all copies or substantial portions of the
167f4dd379Sjsg  * Software.
177f4dd379Sjsg  *
187f4dd379Sjsg  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
197f4dd379Sjsg  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
207f4dd379Sjsg  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
217f4dd379Sjsg  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
227f4dd379Sjsg  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
237f4dd379Sjsg  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
247f4dd379Sjsg  * OTHER DEALINGS IN THE SOFTWARE.
257f4dd379Sjsg  */
267f4dd379Sjsg 
277f4dd379Sjsg #include <linux/export.h>
28ad8b1aafSjsg #include <linux/kthread.h>
29c349dbc7Sjsg #include <linux/moduleparam.h>
307f4dd379Sjsg 
31c349dbc7Sjsg #include <drm/drm_crtc.h>
32c349dbc7Sjsg #include <drm/drm_drv.h>
33c349dbc7Sjsg #include <drm/drm_framebuffer.h>
34ad8b1aafSjsg #include <drm/drm_managed.h>
35c349dbc7Sjsg #include <drm/drm_modeset_helper_vtables.h>
36c349dbc7Sjsg #include <drm/drm_print.h>
37c349dbc7Sjsg #include <drm/drm_vblank.h>
38c349dbc7Sjsg 
397f4dd379Sjsg #include "drm_internal.h"
40c349dbc7Sjsg #include "drm_trace.h"
417f4dd379Sjsg 
427f4dd379Sjsg /**
437f4dd379Sjsg  * DOC: vblank handling
447f4dd379Sjsg  *
45ad8b1aafSjsg  * From the computer's perspective, every time the monitor displays
46ad8b1aafSjsg  * a new frame the scanout engine has "scanned out" the display image
47ad8b1aafSjsg  * from top to bottom, one row of pixels at a time. The current row
48ad8b1aafSjsg  * of pixels is referred to as the current scanline.
49ad8b1aafSjsg  *
50ad8b1aafSjsg  * In addition to the display's visible area, there's usually a couple of
51ad8b1aafSjsg  * extra scanlines which aren't actually displayed on the screen.
52ad8b1aafSjsg  * These extra scanlines don't contain image data and are occasionally used
53ad8b1aafSjsg  * for features like audio and infoframes. The region made up of these
54ad8b1aafSjsg  * scanlines is referred to as the vertical blanking region, or vblank for
55ad8b1aafSjsg  * short.
56ad8b1aafSjsg  *
57ad8b1aafSjsg  * For historical reference, the vertical blanking period was designed to
58ad8b1aafSjsg  * give the electron gun (on CRTs) enough time to move back to the top of
59ad8b1aafSjsg  * the screen to start scanning out the next frame. Similar for horizontal
60ad8b1aafSjsg  * blanking periods. They were designed to give the electron gun enough
61ad8b1aafSjsg  * time to move back to the other side of the screen to start scanning the
62ad8b1aafSjsg  * next scanline.
63ad8b1aafSjsg  *
64ad8b1aafSjsg  * ::
65ad8b1aafSjsg  *
66ad8b1aafSjsg  *
67ad8b1aafSjsg  *    physical →   ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽
68ad8b1aafSjsg  *    top of      |                                        |
69ad8b1aafSjsg  *    display     |                                        |
70ad8b1aafSjsg  *                |               New frame                |
71ad8b1aafSjsg  *                |                                        |
72ad8b1aafSjsg  *                |↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓|
73ad8b1aafSjsg  *                |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| ← Scanline,
74ad8b1aafSjsg  *                |↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓|   updates the
75ad8b1aafSjsg  *                |                                        |   frame as it
76ad8b1aafSjsg  *                |                                        |   travels down
775ca02815Sjsg  *                |                                        |   ("scan out")
78ad8b1aafSjsg  *                |               Old frame                |
79ad8b1aafSjsg  *                |                                        |
80ad8b1aafSjsg  *                |                                        |
81ad8b1aafSjsg  *                |                                        |
82ad8b1aafSjsg  *                |                                        |   physical
83ad8b1aafSjsg  *                |                                        |   bottom of
84ad8b1aafSjsg  *    vertical    |⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽| ← display
85ad8b1aafSjsg  *    blanking    ┆xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx┆
86ad8b1aafSjsg  *    region   →  ┆xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx┆
87ad8b1aafSjsg  *                ┆xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx┆
88ad8b1aafSjsg  *    start of →   ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽
89ad8b1aafSjsg  *    new frame
90ad8b1aafSjsg  *
91ad8b1aafSjsg  * "Physical top of display" is the reference point for the high-precision/
92ad8b1aafSjsg  * corrected timestamp.
93ad8b1aafSjsg  *
94ad8b1aafSjsg  * On a lot of display hardware, programming needs to take effect during the
95ad8b1aafSjsg  * vertical blanking period so that settings like gamma, the image buffer
96ad8b1aafSjsg  * buffer to be scanned out, etc. can safely be changed without showing
97ad8b1aafSjsg  * any visual artifacts on the screen. In some unforgiving hardware, some of
98ad8b1aafSjsg  * this programming has to both start and end in the same vblank. To help
99ad8b1aafSjsg  * with the timing of the hardware programming, an interrupt is usually
100ad8b1aafSjsg  * available to notify the driver when it can start the updating of registers.
101ad8b1aafSjsg  * The interrupt is in this context named the vblank interrupt.
102ad8b1aafSjsg  *
103ad8b1aafSjsg  * The vblank interrupt may be fired at different points depending on the
104ad8b1aafSjsg  * hardware. Some hardware implementations will fire the interrupt when the
105ad8b1aafSjsg  * new frame start, other implementations will fire the interrupt at different
106ad8b1aafSjsg  * points in time.
107ad8b1aafSjsg  *
1087f4dd379Sjsg  * Vertical blanking plays a major role in graphics rendering. To achieve
1097f4dd379Sjsg  * tear-free display, users must synchronize page flips and/or rendering to
1107f4dd379Sjsg  * vertical blanking. The DRM API offers ioctls to perform page flips
1117f4dd379Sjsg  * synchronized to vertical blanking and wait for vertical blanking.
1127f4dd379Sjsg  *
1137f4dd379Sjsg  * The DRM core handles most of the vertical blanking management logic, which
1147f4dd379Sjsg  * involves filtering out spurious interrupts, keeping race-free blanking
1157f4dd379Sjsg  * counters, coping with counter wrap-around and resets and keeping use counts.
1167f4dd379Sjsg  * It relies on the driver to generate vertical blanking interrupts and
1177f4dd379Sjsg  * optionally provide a hardware vertical blanking counter.
1187f4dd379Sjsg  *
1197f4dd379Sjsg  * Drivers must initialize the vertical blanking handling core with a call to
1207f4dd379Sjsg  * drm_vblank_init(). Minimally, a driver needs to implement
1217f4dd379Sjsg  * &drm_crtc_funcs.enable_vblank and &drm_crtc_funcs.disable_vblank plus call
122c349dbc7Sjsg  * drm_crtc_handle_vblank() in its vblank interrupt handler for working vblank
1237f4dd379Sjsg  * support.
1247f4dd379Sjsg  *
1257f4dd379Sjsg  * Vertical blanking interrupts can be enabled by the DRM core or by drivers
1267f4dd379Sjsg  * themselves (for instance to handle page flipping operations).  The DRM core
1277f4dd379Sjsg  * maintains a vertical blanking use count to ensure that the interrupts are not
1287f4dd379Sjsg  * disabled while a user still needs them. To increment the use count, drivers
1297f4dd379Sjsg  * call drm_crtc_vblank_get() and release the vblank reference again with
1307f4dd379Sjsg  * drm_crtc_vblank_put(). In between these two calls vblank interrupts are
1317f4dd379Sjsg  * guaranteed to be enabled.
1327f4dd379Sjsg  *
1337f4dd379Sjsg  * On many hardware disabling the vblank interrupt cannot be done in a race-free
1347f4dd379Sjsg  * manner, see &drm_driver.vblank_disable_immediate and
1357f4dd379Sjsg  * &drm_driver.max_vblank_count. In that case the vblank core only disables the
1367f4dd379Sjsg  * vblanks after a timer has expired, which can be configured through the
1377f4dd379Sjsg  * ``vblankoffdelay`` module parameter.
138c349dbc7Sjsg  *
139c349dbc7Sjsg  * Drivers for hardware without support for vertical-blanking interrupts
140c349dbc7Sjsg  * must not call drm_vblank_init(). For such drivers, atomic helpers will
141c349dbc7Sjsg  * automatically generate fake vblank events as part of the display update.
142c349dbc7Sjsg  * This functionality also can be controlled by the driver by enabling and
143c349dbc7Sjsg  * disabling struct drm_crtc_state.no_vblank.
1447f4dd379Sjsg  */
1457f4dd379Sjsg 
1467f4dd379Sjsg /* Retry timestamp calculation up to 3 times to satisfy
1477f4dd379Sjsg  * drm_timestamp_precision before giving up.
1487f4dd379Sjsg  */
1497f4dd379Sjsg #define DRM_TIMESTAMP_MAXRETRIES 3
1507f4dd379Sjsg 
1517f4dd379Sjsg /* Threshold in nanoseconds for detection of redundant
1527f4dd379Sjsg  * vblank irq in drm_handle_vblank(). 1 msec should be ok.
1537f4dd379Sjsg  */
1547f4dd379Sjsg #define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000
1557f4dd379Sjsg 
1567f4dd379Sjsg static bool
1577f4dd379Sjsg drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
1587f4dd379Sjsg 			  ktime_t *tvblank, bool in_vblank_irq);
1597f4dd379Sjsg 
1607f4dd379Sjsg static unsigned int drm_timestamp_precision = 20;  /* Default to 20 usecs. */
1617f4dd379Sjsg 
1627f4dd379Sjsg static int drm_vblank_offdelay = 5000;    /* Default to 5000 msecs. */
1637f4dd379Sjsg 
1647f4dd379Sjsg module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
1657f4dd379Sjsg module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
1667f4dd379Sjsg MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs] (0: never disable, <0: disable immediately)");
1677f4dd379Sjsg MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
1687f4dd379Sjsg 
store_vblank(struct drm_device * dev,unsigned int pipe,u32 vblank_count_inc,ktime_t t_vblank,u32 last)1697f4dd379Sjsg static void store_vblank(struct drm_device *dev, unsigned int pipe,
1707f4dd379Sjsg 			 u32 vblank_count_inc,
1717f4dd379Sjsg 			 ktime_t t_vblank, u32 last)
1727f4dd379Sjsg {
1737f4dd379Sjsg 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
1747f4dd379Sjsg 
1757f4dd379Sjsg 	assert_spin_locked(&dev->vblank_time_lock);
1767f4dd379Sjsg 
1777f4dd379Sjsg 	vblank->last = last;
1787f4dd379Sjsg 
1797f4dd379Sjsg 	write_seqlock(&vblank->seqlock);
1807f4dd379Sjsg 	vblank->time = t_vblank;
181c349dbc7Sjsg 	atomic64_add(vblank_count_inc, &vblank->count);
1827f4dd379Sjsg 	write_sequnlock(&vblank->seqlock);
1837f4dd379Sjsg }
1847f4dd379Sjsg 
drm_max_vblank_count(struct drm_device * dev,unsigned int pipe)1851b040800Sjsg static u32 drm_max_vblank_count(struct drm_device *dev, unsigned int pipe)
1861b040800Sjsg {
1871b040800Sjsg 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
1881b040800Sjsg 
1891b040800Sjsg 	return vblank->max_vblank_count ?: dev->max_vblank_count;
1901b040800Sjsg }
1911b040800Sjsg 
1927f4dd379Sjsg /*
1937f4dd379Sjsg  * "No hw counter" fallback implementation of .get_vblank_counter() hook,
1945ca02815Sjsg  * if there is no usable hardware frame counter available.
1957f4dd379Sjsg  */
drm_vblank_no_hw_counter(struct drm_device * dev,unsigned int pipe)1967f4dd379Sjsg static u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe)
1977f4dd379Sjsg {
198ad8b1aafSjsg 	drm_WARN_ON_ONCE(dev, drm_max_vblank_count(dev, pipe) != 0);
1997f4dd379Sjsg 	return 0;
2007f4dd379Sjsg }
2017f4dd379Sjsg 
__get_vblank_counter(struct drm_device * dev,unsigned int pipe)2027f4dd379Sjsg static u32 __get_vblank_counter(struct drm_device *dev, unsigned int pipe)
2037f4dd379Sjsg {
2047f4dd379Sjsg 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
2057f4dd379Sjsg 		struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
2067f4dd379Sjsg 
207ad8b1aafSjsg 		if (drm_WARN_ON(dev, !crtc))
2087f4dd379Sjsg 			return 0;
2097f4dd379Sjsg 
2107f4dd379Sjsg 		if (crtc->funcs->get_vblank_counter)
2117f4dd379Sjsg 			return crtc->funcs->get_vblank_counter(crtc);
2125ca02815Sjsg 	}
2135ca02815Sjsg #ifdef CONFIG_DRM_LEGACY
2145ca02815Sjsg 	else if (dev->driver->get_vblank_counter) {
2157f4dd379Sjsg 		return dev->driver->get_vblank_counter(dev, pipe);
216c349dbc7Sjsg 	}
2175ca02815Sjsg #endif
2187f4dd379Sjsg 
2197f4dd379Sjsg 	return drm_vblank_no_hw_counter(dev, pipe);
2207f4dd379Sjsg }
2217f4dd379Sjsg 
2227f4dd379Sjsg /*
2237f4dd379Sjsg  * Reset the stored timestamp for the current vblank count to correspond
2247f4dd379Sjsg  * to the last vblank occurred.
2257f4dd379Sjsg  *
2267f4dd379Sjsg  * Only to be called from drm_crtc_vblank_on().
2277f4dd379Sjsg  *
2287f4dd379Sjsg  * Note: caller must hold &drm_device.vbl_lock since this reads & writes
2297f4dd379Sjsg  * device vblank fields.
2307f4dd379Sjsg  */
drm_reset_vblank_timestamp(struct drm_device * dev,unsigned int pipe)2317f4dd379Sjsg static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe)
2327f4dd379Sjsg {
2337f4dd379Sjsg 	u32 cur_vblank;
2347f4dd379Sjsg 	bool rc;
2357f4dd379Sjsg 	ktime_t t_vblank;
2367f4dd379Sjsg 	int count = DRM_TIMESTAMP_MAXRETRIES;
2377f4dd379Sjsg 
2387f4dd379Sjsg 	spin_lock(&dev->vblank_time_lock);
2397f4dd379Sjsg 
2407f4dd379Sjsg 	/*
2417f4dd379Sjsg 	 * sample the current counter to avoid random jumps
2427f4dd379Sjsg 	 * when drm_vblank_enable() applies the diff
2437f4dd379Sjsg 	 */
2447f4dd379Sjsg 	do {
2457f4dd379Sjsg 		cur_vblank = __get_vblank_counter(dev, pipe);
2467f4dd379Sjsg 		rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, false);
2477f4dd379Sjsg 	} while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
2487f4dd379Sjsg 
2497f4dd379Sjsg 	/*
2507f4dd379Sjsg 	 * Only reinitialize corresponding vblank timestamp if high-precision query
2517f4dd379Sjsg 	 * available and didn't fail. Otherwise reinitialize delayed at next vblank
2527f4dd379Sjsg 	 * interrupt and assign 0 for now, to mark the vblanktimestamp as invalid.
2537f4dd379Sjsg 	 */
2547f4dd379Sjsg 	if (!rc)
2550df1b8f9Sjsg 		t_vblank = 0;
2567f4dd379Sjsg 
2577f4dd379Sjsg 	/*
2587f4dd379Sjsg 	 * +1 to make sure user will never see the same
2597f4dd379Sjsg 	 * vblank counter value before and after a modeset
2607f4dd379Sjsg 	 */
2617f4dd379Sjsg 	store_vblank(dev, pipe, 1, t_vblank, cur_vblank);
2627f4dd379Sjsg 
2637f4dd379Sjsg 	spin_unlock(&dev->vblank_time_lock);
2647f4dd379Sjsg }
2657f4dd379Sjsg 
2667f4dd379Sjsg /*
2677f4dd379Sjsg  * Call back into the driver to update the appropriate vblank counter
2687f4dd379Sjsg  * (specified by @pipe).  Deal with wraparound, if it occurred, and
2697f4dd379Sjsg  * update the last read value so we can deal with wraparound on the next
2707f4dd379Sjsg  * call if necessary.
2717f4dd379Sjsg  *
2727f4dd379Sjsg  * Only necessary when going from off->on, to account for frames we
2737f4dd379Sjsg  * didn't get an interrupt for.
2747f4dd379Sjsg  *
2757f4dd379Sjsg  * Note: caller must hold &drm_device.vbl_lock since this reads & writes
2767f4dd379Sjsg  * device vblank fields.
2777f4dd379Sjsg  */
drm_update_vblank_count(struct drm_device * dev,unsigned int pipe,bool in_vblank_irq)2787f4dd379Sjsg static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
2797f4dd379Sjsg 				    bool in_vblank_irq)
2807f4dd379Sjsg {
2817f4dd379Sjsg 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
2827f4dd379Sjsg 	u32 cur_vblank, diff;
2837f4dd379Sjsg 	bool rc;
2847f4dd379Sjsg 	ktime_t t_vblank;
2857f4dd379Sjsg 	int count = DRM_TIMESTAMP_MAXRETRIES;
2867f4dd379Sjsg 	int framedur_ns = vblank->framedur_ns;
2871b040800Sjsg 	u32 max_vblank_count = drm_max_vblank_count(dev, pipe);
2887f4dd379Sjsg 
2897f4dd379Sjsg 	/*
2907f4dd379Sjsg 	 * Interrupts were disabled prior to this call, so deal with counter
2917f4dd379Sjsg 	 * wrap if needed.
2927f4dd379Sjsg 	 * NOTE!  It's possible we lost a full dev->max_vblank_count + 1 events
2937f4dd379Sjsg 	 * here if the register is small or we had vblank interrupts off for
2947f4dd379Sjsg 	 * a long time.
2957f4dd379Sjsg 	 *
2967f4dd379Sjsg 	 * We repeat the hardware vblank counter & timestamp query until
2977f4dd379Sjsg 	 * we get consistent results. This to prevent races between gpu
2987f4dd379Sjsg 	 * updating its hardware counter while we are retrieving the
2997f4dd379Sjsg 	 * corresponding vblank timestamp.
3007f4dd379Sjsg 	 */
3017f4dd379Sjsg 	do {
3027f4dd379Sjsg 		cur_vblank = __get_vblank_counter(dev, pipe);
3037f4dd379Sjsg 		rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, in_vblank_irq);
3047f4dd379Sjsg 	} while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
3057f4dd379Sjsg 
3061b040800Sjsg 	if (max_vblank_count) {
3077f4dd379Sjsg 		/* trust the hw counter when it's around */
3081b040800Sjsg 		diff = (cur_vblank - vblank->last) & max_vblank_count;
3097f4dd379Sjsg 	} else if (rc && framedur_ns) {
3107f4dd379Sjsg 		u64 diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time));
3117f4dd379Sjsg 
3127f4dd379Sjsg 		/*
3137f4dd379Sjsg 		 * Figure out how many vblanks we've missed based
3147f4dd379Sjsg 		 * on the difference in the timestamps and the
3157f4dd379Sjsg 		 * frame/field duration.
3167f4dd379Sjsg 		 */
317c349dbc7Sjsg 
318ad8b1aafSjsg 		drm_dbg_vbl(dev, "crtc %u: Calculating number of vblanks."
319c349dbc7Sjsg 			    " diff_ns = %lld, framedur_ns = %d)\n",
320c349dbc7Sjsg 			    pipe, (long long)diff_ns, framedur_ns);
321c349dbc7Sjsg 
3227f4dd379Sjsg 		diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns);
3237f4dd379Sjsg 
3247f4dd379Sjsg 		if (diff == 0 && in_vblank_irq)
325ad8b1aafSjsg 			drm_dbg_vbl(dev, "crtc %u: Redundant vblirq ignored\n",
326c349dbc7Sjsg 				    pipe);
3277f4dd379Sjsg 	} else {
3287f4dd379Sjsg 		/* some kind of default for drivers w/o accurate vbl timestamping */
3297f4dd379Sjsg 		diff = in_vblank_irq ? 1 : 0;
3307f4dd379Sjsg 	}
3317f4dd379Sjsg 
3327f4dd379Sjsg 	/*
3337f4dd379Sjsg 	 * Within a drm_vblank_pre_modeset - drm_vblank_post_modeset
3347f4dd379Sjsg 	 * interval? If so then vblank irqs keep running and it will likely
3357f4dd379Sjsg 	 * happen that the hardware vblank counter is not trustworthy as it
3367f4dd379Sjsg 	 * might reset at some point in that interval and vblank timestamps
3377f4dd379Sjsg 	 * are not trustworthy either in that interval. Iow. this can result
3387f4dd379Sjsg 	 * in a bogus diff >> 1 which must be avoided as it would cause
3397f4dd379Sjsg 	 * random large forward jumps of the software vblank counter.
3407f4dd379Sjsg 	 */
3417f4dd379Sjsg 	if (diff > 1 && (vblank->inmodeset & 0x2)) {
342ad8b1aafSjsg 		drm_dbg_vbl(dev,
343ad8b1aafSjsg 			    "clamping vblank bump to 1 on crtc %u: diffr=%u"
3447f4dd379Sjsg 			    " due to pre-modeset.\n", pipe, diff);
3457f4dd379Sjsg 		diff = 1;
3467f4dd379Sjsg 	}
3477f4dd379Sjsg 
348ad8b1aafSjsg 	drm_dbg_vbl(dev, "updating vblank count on crtc %u:"
3497f4dd379Sjsg 		    " current=%llu, diff=%u, hw=%u hw_last=%u\n",
350ad8b1aafSjsg 		    pipe, (unsigned long long)atomic64_read(&vblank->count),
351ad8b1aafSjsg 		    diff, cur_vblank, vblank->last);
3527f4dd379Sjsg 
3537f4dd379Sjsg 	if (diff == 0) {
354ad8b1aafSjsg 		drm_WARN_ON_ONCE(dev, cur_vblank != vblank->last);
3557f4dd379Sjsg 		return;
3567f4dd379Sjsg 	}
3577f4dd379Sjsg 
3587f4dd379Sjsg 	/*
3597f4dd379Sjsg 	 * Only reinitialize corresponding vblank timestamp if high-precision query
3607f4dd379Sjsg 	 * available and didn't fail, or we were called from the vblank interrupt.
3617f4dd379Sjsg 	 * Otherwise reinitialize delayed at next vblank interrupt and assign 0
3627f4dd379Sjsg 	 * for now, to mark the vblanktimestamp as invalid.
3637f4dd379Sjsg 	 */
3647f4dd379Sjsg 	if (!rc && !in_vblank_irq)
3650df1b8f9Sjsg 		t_vblank = 0;
3667f4dd379Sjsg 
3677f4dd379Sjsg 	store_vblank(dev, pipe, diff, t_vblank, cur_vblank);
3687f4dd379Sjsg }
3697f4dd379Sjsg 
drm_vblank_count(struct drm_device * dev,unsigned int pipe)370ad8b1aafSjsg u64 drm_vblank_count(struct drm_device *dev, unsigned int pipe)
3717f4dd379Sjsg {
3727f4dd379Sjsg 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
373c349dbc7Sjsg 	u64 count;
3747f4dd379Sjsg 
375ad8b1aafSjsg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
3767f4dd379Sjsg 		return 0;
3777f4dd379Sjsg 
378c349dbc7Sjsg 	count = atomic64_read(&vblank->count);
379c349dbc7Sjsg 
380c349dbc7Sjsg 	/*
381c349dbc7Sjsg 	 * This read barrier corresponds to the implicit write barrier of the
382c349dbc7Sjsg 	 * write seqlock in store_vblank(). Note that this is the only place
383c349dbc7Sjsg 	 * where we need an explicit barrier, since all other access goes
384c349dbc7Sjsg 	 * through drm_vblank_count_and_time(), which already has the required
385c349dbc7Sjsg 	 * read barrier curtesy of the read seqlock.
386c349dbc7Sjsg 	 */
387c349dbc7Sjsg 	smp_rmb();
388c349dbc7Sjsg 
389c349dbc7Sjsg 	return count;
3907f4dd379Sjsg }
3917f4dd379Sjsg 
3927f4dd379Sjsg /**
3937f4dd379Sjsg  * drm_crtc_accurate_vblank_count - retrieve the master vblank counter
3947f4dd379Sjsg  * @crtc: which counter to retrieve
3957f4dd379Sjsg  *
3967f4dd379Sjsg  * This function is similar to drm_crtc_vblank_count() but this function
3977f4dd379Sjsg  * interpolates to handle a race with vblank interrupts using the high precision
3987f4dd379Sjsg  * timestamping support.
3997f4dd379Sjsg  *
4007f4dd379Sjsg  * This is mostly useful for hardware that can obtain the scanout position, but
4017f4dd379Sjsg  * doesn't have a hardware frame counter.
4027f4dd379Sjsg  */
drm_crtc_accurate_vblank_count(struct drm_crtc * crtc)4037f4dd379Sjsg u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc)
4047f4dd379Sjsg {
4057f4dd379Sjsg 	struct drm_device *dev = crtc->dev;
4067f4dd379Sjsg 	unsigned int pipe = drm_crtc_index(crtc);
4077f4dd379Sjsg 	u64 vblank;
4087f4dd379Sjsg 	unsigned long flags;
4097f4dd379Sjsg 
410ad8b1aafSjsg 	drm_WARN_ONCE(dev, drm_debug_enabled(DRM_UT_VBL) &&
411c349dbc7Sjsg 		      !crtc->funcs->get_vblank_timestamp,
4127f4dd379Sjsg 		      "This function requires support for accurate vblank timestamps.");
4137f4dd379Sjsg 
4147f4dd379Sjsg 	spin_lock_irqsave(&dev->vblank_time_lock, flags);
4157f4dd379Sjsg 
4167f4dd379Sjsg 	drm_update_vblank_count(dev, pipe, false);
4177f4dd379Sjsg 	vblank = drm_vblank_count(dev, pipe);
4187f4dd379Sjsg 
4197f4dd379Sjsg 	spin_unlock_irqrestore(&dev->vblank_time_lock, flags);
4207f4dd379Sjsg 
4217f4dd379Sjsg 	return vblank;
4227f4dd379Sjsg }
4237f4dd379Sjsg EXPORT_SYMBOL(drm_crtc_accurate_vblank_count);
4247f4dd379Sjsg 
__disable_vblank(struct drm_device * dev,unsigned int pipe)4257f4dd379Sjsg static void __disable_vblank(struct drm_device *dev, unsigned int pipe)
4267f4dd379Sjsg {
4277f4dd379Sjsg 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
4287f4dd379Sjsg 		struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
4297f4dd379Sjsg 
430ad8b1aafSjsg 		if (drm_WARN_ON(dev, !crtc))
4317f4dd379Sjsg 			return;
4327f4dd379Sjsg 
433c349dbc7Sjsg 		if (crtc->funcs->disable_vblank)
4347f4dd379Sjsg 			crtc->funcs->disable_vblank(crtc);
4355ca02815Sjsg 	}
4365ca02815Sjsg #ifdef CONFIG_DRM_LEGACY
4375ca02815Sjsg 	else {
4387f4dd379Sjsg 		dev->driver->disable_vblank(dev, pipe);
4397f4dd379Sjsg 	}
4405ca02815Sjsg #endif
441c349dbc7Sjsg }
4427f4dd379Sjsg 
4437f4dd379Sjsg /*
4447f4dd379Sjsg  * Disable vblank irq's on crtc, make sure that last vblank count
4457f4dd379Sjsg  * of hardware and corresponding consistent software vblank counter
4467f4dd379Sjsg  * are preserved, even if there are any spurious vblank irq's after
4477f4dd379Sjsg  * disable.
4487f4dd379Sjsg  */
drm_vblank_disable_and_save(struct drm_device * dev,unsigned int pipe)4497f4dd379Sjsg void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe)
4507f4dd379Sjsg {
4517f4dd379Sjsg 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
4527f4dd379Sjsg 	unsigned long irqflags;
4537f4dd379Sjsg 
4547f4dd379Sjsg 	assert_spin_locked(&dev->vbl_lock);
4557f4dd379Sjsg 
4567f4dd379Sjsg 	/* Prevent vblank irq processing while disabling vblank irqs,
4577f4dd379Sjsg 	 * so no updates of timestamps or count can happen after we've
4587f4dd379Sjsg 	 * disabled. Needed to prevent races in case of delayed irq's.
4597f4dd379Sjsg 	 */
4607f4dd379Sjsg 	spin_lock_irqsave(&dev->vblank_time_lock, irqflags);
4617f4dd379Sjsg 
4627f4dd379Sjsg 	/*
4637f4dd379Sjsg 	 * Update vblank count and disable vblank interrupts only if the
4647f4dd379Sjsg 	 * interrupts were enabled. This avoids calling the ->disable_vblank()
4657f4dd379Sjsg 	 * operation in atomic context with the hardware potentially runtime
4667f4dd379Sjsg 	 * suspended.
4677f4dd379Sjsg 	 */
4687f4dd379Sjsg 	if (!vblank->enabled)
4697f4dd379Sjsg 		goto out;
4707f4dd379Sjsg 
4717f4dd379Sjsg 	/*
4727f4dd379Sjsg 	 * Update the count and timestamp to maintain the
4737f4dd379Sjsg 	 * appearance that the counter has been ticking all along until
4747f4dd379Sjsg 	 * this time. This makes the count account for the entire time
4757f4dd379Sjsg 	 * between drm_crtc_vblank_on() and drm_crtc_vblank_off().
4767f4dd379Sjsg 	 */
4777f4dd379Sjsg 	drm_update_vblank_count(dev, pipe, false);
4787f4dd379Sjsg 	__disable_vblank(dev, pipe);
4797f4dd379Sjsg 	vblank->enabled = false;
4807f4dd379Sjsg 
4817f4dd379Sjsg out:
4827f4dd379Sjsg 	spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
4837f4dd379Sjsg }
4847f4dd379Sjsg 
vblank_disable_fn(void * arg)485bbf6708cSjsg static void vblank_disable_fn(void *arg)
4867f4dd379Sjsg {
487bbf6708cSjsg 	struct drm_vblank_crtc *vblank = arg;
4887f4dd379Sjsg 	struct drm_device *dev = vblank->dev;
4897f4dd379Sjsg 	unsigned int pipe = vblank->pipe;
4907f4dd379Sjsg 	unsigned long irqflags;
4917f4dd379Sjsg 
4927f4dd379Sjsg 	spin_lock_irqsave(&dev->vbl_lock, irqflags);
4937f4dd379Sjsg 	if (atomic_read(&vblank->refcount) == 0 && vblank->enabled) {
494ad8b1aafSjsg 		drm_dbg_core(dev, "disabling vblank on crtc %u\n", pipe);
4957f4dd379Sjsg 		drm_vblank_disable_and_save(dev, pipe);
4967f4dd379Sjsg 	}
4977f4dd379Sjsg 	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
4987f4dd379Sjsg }
4997f4dd379Sjsg 
drm_vblank_init_release(struct drm_device * dev,void * ptr)500ad8b1aafSjsg static void drm_vblank_init_release(struct drm_device *dev, void *ptr)
5017f4dd379Sjsg {
502ad8b1aafSjsg 	struct drm_vblank_crtc *vblank = ptr;
5037f4dd379Sjsg 
504ad8b1aafSjsg 	drm_WARN_ON(dev, READ_ONCE(vblank->enabled) &&
5057f4dd379Sjsg 		    drm_core_check_feature(dev, DRIVER_MODESET));
5067f4dd379Sjsg 
507ad8b1aafSjsg 	drm_vblank_destroy_worker(vblank);
5087f4dd379Sjsg 	del_timer_sync(&vblank->disable_timer);
5097f4dd379Sjsg }
5107f4dd379Sjsg 
5117f4dd379Sjsg /**
5127f4dd379Sjsg  * drm_vblank_init - initialize vblank support
5137f4dd379Sjsg  * @dev: DRM device
5147f4dd379Sjsg  * @num_crtcs: number of CRTCs supported by @dev
5157f4dd379Sjsg  *
5167f4dd379Sjsg  * This function initializes vblank support for @num_crtcs display pipelines.
517ad8b1aafSjsg  * Cleanup is handled automatically through a cleanup function added with
518ad8b1aafSjsg  * drmm_add_action_or_reset().
5197f4dd379Sjsg  *
5207f4dd379Sjsg  * Returns:
5217f4dd379Sjsg  * Zero on success or a negative error code on failure.
5227f4dd379Sjsg  */
drm_vblank_init(struct drm_device * dev,unsigned int num_crtcs)5237f4dd379Sjsg int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs)
5247f4dd379Sjsg {
525ad8b1aafSjsg 	int ret;
5267f4dd379Sjsg 	unsigned int i;
5277f4dd379Sjsg 
5287f4dd379Sjsg 	mtx_init(&dev->vbl_lock, IPL_TTY);
5297f4dd379Sjsg 	mtx_init(&dev->vblank_time_lock, IPL_TTY);
5307f4dd379Sjsg 
531ad8b1aafSjsg 	dev->vblank = drmm_kcalloc(dev, num_crtcs, sizeof(*dev->vblank), GFP_KERNEL);
5327f4dd379Sjsg 	if (!dev->vblank)
533ad8b1aafSjsg 		return -ENOMEM;
534ad8b1aafSjsg 
535ad8b1aafSjsg 	dev->num_crtcs = num_crtcs;
5367f4dd379Sjsg 
5377f4dd379Sjsg 	for (i = 0; i < num_crtcs; i++) {
5387f4dd379Sjsg 		struct drm_vblank_crtc *vblank = &dev->vblank[i];
5397f4dd379Sjsg 
5407f4dd379Sjsg 		vblank->dev = dev;
5417f4dd379Sjsg 		vblank->pipe = i;
5427f4dd379Sjsg 		init_waitqueue_head(&vblank->queue);
543bbf6708cSjsg #ifdef __linux__
544bbf6708cSjsg 		timer_setup(&vblank->disable_timer, vblank_disable_fn, 0);
545bbf6708cSjsg #else
546bbf6708cSjsg 		timeout_set(&vblank->disable_timer, vblank_disable_fn, vblank);
547bbf6708cSjsg #endif
548b69c1869Sjsg 		seqlock_init(&vblank->seqlock, IPL_TTY);
549ad8b1aafSjsg 
550ad8b1aafSjsg 		ret = drmm_add_action_or_reset(dev, drm_vblank_init_release,
551ad8b1aafSjsg 					       vblank);
552ad8b1aafSjsg 		if (ret)
553ad8b1aafSjsg 			return ret;
554ad8b1aafSjsg 
555ad8b1aafSjsg 		ret = drm_vblank_worker_init(vblank);
556ad8b1aafSjsg 		if (ret)
557ad8b1aafSjsg 			return ret;
5587f4dd379Sjsg 	}
5597f4dd379Sjsg 
5607f4dd379Sjsg 	return 0;
5617f4dd379Sjsg }
5627f4dd379Sjsg EXPORT_SYMBOL(drm_vblank_init);
5637f4dd379Sjsg 
5647f4dd379Sjsg /**
565c349dbc7Sjsg  * drm_dev_has_vblank - test if vblanking has been initialized for
566c349dbc7Sjsg  *                      a device
567c349dbc7Sjsg  * @dev: the device
568c349dbc7Sjsg  *
569c349dbc7Sjsg  * Drivers may call this function to test if vblank support is
570c349dbc7Sjsg  * initialized for a device. For most hardware this means that vblanking
571c349dbc7Sjsg  * can also be enabled.
572c349dbc7Sjsg  *
573c349dbc7Sjsg  * Atomic helpers use this function to initialize
574c349dbc7Sjsg  * &drm_crtc_state.no_vblank. See also drm_atomic_helper_check_modeset().
575c349dbc7Sjsg  *
576c349dbc7Sjsg  * Returns:
577c349dbc7Sjsg  * True if vblanking has been initialized for the given device, false
578c349dbc7Sjsg  * otherwise.
579c349dbc7Sjsg  */
drm_dev_has_vblank(const struct drm_device * dev)580c349dbc7Sjsg bool drm_dev_has_vblank(const struct drm_device *dev)
581c349dbc7Sjsg {
582c349dbc7Sjsg 	return dev->num_crtcs != 0;
583c349dbc7Sjsg }
584c349dbc7Sjsg EXPORT_SYMBOL(drm_dev_has_vblank);
585c349dbc7Sjsg 
586c349dbc7Sjsg /**
5877f4dd379Sjsg  * drm_crtc_vblank_waitqueue - get vblank waitqueue for the CRTC
5887f4dd379Sjsg  * @crtc: which CRTC's vblank waitqueue to retrieve
5897f4dd379Sjsg  *
5907f4dd379Sjsg  * This function returns a pointer to the vblank waitqueue for the CRTC.
5917f4dd379Sjsg  * Drivers can use this to implement vblank waits using wait_event() and related
5927f4dd379Sjsg  * functions.
5937f4dd379Sjsg  */
drm_crtc_vblank_waitqueue(struct drm_crtc * crtc)5947f4dd379Sjsg wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc)
5957f4dd379Sjsg {
5967f4dd379Sjsg 	return &crtc->dev->vblank[drm_crtc_index(crtc)].queue;
5977f4dd379Sjsg }
5987f4dd379Sjsg EXPORT_SYMBOL(drm_crtc_vblank_waitqueue);
5997f4dd379Sjsg 
6007f4dd379Sjsg 
6017f4dd379Sjsg /**
6027f4dd379Sjsg  * drm_calc_timestamping_constants - calculate vblank timestamp constants
6037f4dd379Sjsg  * @crtc: drm_crtc whose timestamp constants should be updated.
6047f4dd379Sjsg  * @mode: display mode containing the scanout timings
6057f4dd379Sjsg  *
6067f4dd379Sjsg  * Calculate and store various constants which are later needed by vblank and
6077f4dd379Sjsg  * swap-completion timestamping, e.g, by
608c349dbc7Sjsg  * drm_crtc_vblank_helper_get_vblank_timestamp(). They are derived from
609c349dbc7Sjsg  * CRTC's true scanout timing, so they take things like panel scaling or
610c349dbc7Sjsg  * other adjustments into account.
6117f4dd379Sjsg  */
drm_calc_timestamping_constants(struct drm_crtc * crtc,const struct drm_display_mode * mode)6127f4dd379Sjsg void drm_calc_timestamping_constants(struct drm_crtc *crtc,
6137f4dd379Sjsg 				     const struct drm_display_mode *mode)
6147f4dd379Sjsg {
6157f4dd379Sjsg 	struct drm_device *dev = crtc->dev;
6167f4dd379Sjsg 	unsigned int pipe = drm_crtc_index(crtc);
6177f4dd379Sjsg 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
6187f4dd379Sjsg 	int linedur_ns = 0, framedur_ns = 0;
6197f4dd379Sjsg 	int dotclock = mode->crtc_clock;
6207f4dd379Sjsg 
621ad8b1aafSjsg 	if (!drm_dev_has_vblank(dev))
6227f4dd379Sjsg 		return;
6237f4dd379Sjsg 
624ad8b1aafSjsg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
6257f4dd379Sjsg 		return;
6267f4dd379Sjsg 
6277f4dd379Sjsg 	/* Valid dotclock? */
6287f4dd379Sjsg 	if (dotclock > 0) {
6297f4dd379Sjsg 		int frame_size = mode->crtc_htotal * mode->crtc_vtotal;
6307f4dd379Sjsg 
6317f4dd379Sjsg 		/*
6327f4dd379Sjsg 		 * Convert scanline length in pixels and video
6337f4dd379Sjsg 		 * dot clock to line duration and frame duration
6347f4dd379Sjsg 		 * in nanoseconds:
6357f4dd379Sjsg 		 */
6367f4dd379Sjsg 		linedur_ns  = div_u64((u64) mode->crtc_htotal * 1000000, dotclock);
6377f4dd379Sjsg 		framedur_ns = div_u64((u64) frame_size * 1000000, dotclock);
6387f4dd379Sjsg 
6397f4dd379Sjsg 		/*
6407f4dd379Sjsg 		 * Fields of interlaced scanout modes are only half a frame duration.
6417f4dd379Sjsg 		 */
6427f4dd379Sjsg 		if (mode->flags & DRM_MODE_FLAG_INTERLACE)
6437f4dd379Sjsg 			framedur_ns /= 2;
644ad8b1aafSjsg 	} else {
645ad8b1aafSjsg 		drm_err(dev, "crtc %u: Can't calculate constants, dotclock = 0!\n",
6467f4dd379Sjsg 			crtc->base.id);
647ad8b1aafSjsg 	}
6487f4dd379Sjsg 
6497f4dd379Sjsg 	vblank->linedur_ns  = linedur_ns;
6507f4dd379Sjsg 	vblank->framedur_ns = framedur_ns;
6511bb76ff1Sjsg 	drm_mode_copy(&vblank->hwmode, mode);
6527f4dd379Sjsg 
653ad8b1aafSjsg 	drm_dbg_core(dev,
654ad8b1aafSjsg 		     "crtc %u: hwmode: htotal %d, vtotal %d, vdisplay %d\n",
6557f4dd379Sjsg 		     crtc->base.id, mode->crtc_htotal,
6567f4dd379Sjsg 		     mode->crtc_vtotal, mode->crtc_vdisplay);
657ad8b1aafSjsg 	drm_dbg_core(dev, "crtc %u: clock %d kHz framedur %d linedur %d\n",
6587f4dd379Sjsg 		     crtc->base.id, dotclock, framedur_ns, linedur_ns);
6597f4dd379Sjsg }
6607f4dd379Sjsg EXPORT_SYMBOL(drm_calc_timestamping_constants);
6617f4dd379Sjsg 
6627f4dd379Sjsg /**
663c349dbc7Sjsg  * drm_crtc_vblank_helper_get_vblank_timestamp_internal - precise vblank
664c349dbc7Sjsg  *                                                        timestamp helper
665c349dbc7Sjsg  * @crtc: CRTC whose vblank timestamp to retrieve
6667f4dd379Sjsg  * @max_error: Desired maximum allowable error in timestamps (nanosecs)
6677f4dd379Sjsg  *             On return contains true maximum error of timestamp
6687f4dd379Sjsg  * @vblank_time: Pointer to time which should receive the timestamp
6697f4dd379Sjsg  * @in_vblank_irq:
6707f4dd379Sjsg  *     True when called from drm_crtc_handle_vblank().  Some drivers
6717f4dd379Sjsg  *     need to apply some workarounds for gpu-specific vblank irq quirks
6727f4dd379Sjsg  *     if flag is set.
673c349dbc7Sjsg  * @get_scanout_position:
674c349dbc7Sjsg  *     Callback function to retrieve the scanout position. See
675c349dbc7Sjsg  *     @struct drm_crtc_helper_funcs.get_scanout_position.
6767f4dd379Sjsg  *
6777f4dd379Sjsg  * Implements calculation of exact vblank timestamps from given drm_display_mode
678c349dbc7Sjsg  * timings and current video scanout position of a CRTC.
6797f4dd379Sjsg  *
6807f4dd379Sjsg  * The current implementation only handles standard video modes. For double scan
6817f4dd379Sjsg  * and interlaced modes the driver is supposed to adjust the hardware mode
6827f4dd379Sjsg  * (taken from &drm_crtc_state.adjusted mode for atomic modeset drivers) to
6837f4dd379Sjsg  * match the scanout position reported.
6847f4dd379Sjsg  *
6857f4dd379Sjsg  * Note that atomic drivers must call drm_calc_timestamping_constants() before
6867f4dd379Sjsg  * enabling a CRTC. The atomic helpers already take care of that in
687ad8b1aafSjsg  * drm_atomic_helper_calc_timestamping_constants().
6887f4dd379Sjsg  *
6897f4dd379Sjsg  * Returns:
6907f4dd379Sjsg  *
6917f4dd379Sjsg  * Returns true on success, and false on failure, i.e. when no accurate
6927f4dd379Sjsg  * timestamp could be acquired.
6937f4dd379Sjsg  */
694c349dbc7Sjsg 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)695c349dbc7Sjsg drm_crtc_vblank_helper_get_vblank_timestamp_internal(
696c349dbc7Sjsg 	struct drm_crtc *crtc, int *max_error, ktime_t *vblank_time,
697c349dbc7Sjsg 	bool in_vblank_irq,
698c349dbc7Sjsg 	drm_vblank_get_scanout_position_func get_scanout_position)
6997f4dd379Sjsg {
700c349dbc7Sjsg 	struct drm_device *dev = crtc->dev;
701c349dbc7Sjsg 	unsigned int pipe = crtc->index;
702c349dbc7Sjsg 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
7037f4dd379Sjsg 	struct timespec64 ts_etime, ts_vblank_time;
7047f4dd379Sjsg 	ktime_t stime, etime;
7057f4dd379Sjsg 	bool vbl_status;
7067f4dd379Sjsg 	const struct drm_display_mode *mode;
7077f4dd379Sjsg 	int vpos, hpos, i;
7087f4dd379Sjsg 	int delta_ns, duration_ns;
7097f4dd379Sjsg 
710c349dbc7Sjsg 	if (pipe >= dev->num_crtcs) {
711ad8b1aafSjsg 		drm_err(dev, "Invalid crtc %u\n", pipe);
7127f4dd379Sjsg 		return false;
7137f4dd379Sjsg 	}
7147f4dd379Sjsg 
7157f4dd379Sjsg 	/* Scanout position query not supported? Should not happen. */
716c349dbc7Sjsg 	if (!get_scanout_position) {
717ad8b1aafSjsg 		drm_err(dev, "Called from CRTC w/o get_scanout_position()!?\n");
7187f4dd379Sjsg 		return false;
7197f4dd379Sjsg 	}
7207f4dd379Sjsg 
7217f4dd379Sjsg 	if (drm_drv_uses_atomic_modeset(dev))
7227f4dd379Sjsg 		mode = &vblank->hwmode;
7237f4dd379Sjsg 	else
7247f4dd379Sjsg 		mode = &crtc->hwmode;
7257f4dd379Sjsg 
7267f4dd379Sjsg 	/* If mode timing undefined, just return as no-op:
7277f4dd379Sjsg 	 * Happens during initial modesetting of a crtc.
7287f4dd379Sjsg 	 */
7297f4dd379Sjsg 	if (mode->crtc_clock == 0) {
730ad8b1aafSjsg 		drm_dbg_core(dev, "crtc %u: Noop due to uninitialized mode.\n",
731ad8b1aafSjsg 			     pipe);
732ad8b1aafSjsg 		drm_WARN_ON_ONCE(dev, drm_drv_uses_atomic_modeset(dev));
7337f4dd379Sjsg 		return false;
7347f4dd379Sjsg 	}
7357f4dd379Sjsg 
7367f4dd379Sjsg 	/* Get current scanout position with system timestamp.
7377f4dd379Sjsg 	 * Repeat query up to DRM_TIMESTAMP_MAXRETRIES times
7387f4dd379Sjsg 	 * if single query takes longer than max_error nanoseconds.
7397f4dd379Sjsg 	 *
7407f4dd379Sjsg 	 * This guarantees a tight bound on maximum error if
7417f4dd379Sjsg 	 * code gets preempted or delayed for some reason.
7427f4dd379Sjsg 	 */
7437f4dd379Sjsg 	for (i = 0; i < DRM_TIMESTAMP_MAXRETRIES; i++) {
7447f4dd379Sjsg 		/*
7457f4dd379Sjsg 		 * Get vertical and horizontal scanout position vpos, hpos,
7467f4dd379Sjsg 		 * and bounding timestamps stime, etime, pre/post query.
7477f4dd379Sjsg 		 */
748c349dbc7Sjsg 		vbl_status = get_scanout_position(crtc, in_vblank_irq,
7497f4dd379Sjsg 						  &vpos, &hpos,
7507f4dd379Sjsg 						  &stime, &etime,
7517f4dd379Sjsg 						  mode);
7527f4dd379Sjsg 
7537f4dd379Sjsg 		/* Return as no-op if scanout query unsupported or failed. */
7547f4dd379Sjsg 		if (!vbl_status) {
755ad8b1aafSjsg 			drm_dbg_core(dev,
756ad8b1aafSjsg 				     "crtc %u : scanoutpos query failed.\n",
7577f4dd379Sjsg 				     pipe);
7587f4dd379Sjsg 			return false;
7597f4dd379Sjsg 		}
7607f4dd379Sjsg 
7617f4dd379Sjsg 		/* Compute uncertainty in timestamp of scanout position query. */
7627f4dd379Sjsg 		duration_ns = ktime_to_ns(etime) - ktime_to_ns(stime);
7637f4dd379Sjsg 
7647f4dd379Sjsg 		/* Accept result with <  max_error nsecs timing uncertainty. */
7657f4dd379Sjsg 		if (duration_ns <= *max_error)
7667f4dd379Sjsg 			break;
7677f4dd379Sjsg 	}
7687f4dd379Sjsg 
7697f4dd379Sjsg 	/* Noisy system timing? */
7707f4dd379Sjsg 	if (i == DRM_TIMESTAMP_MAXRETRIES) {
771ad8b1aafSjsg 		drm_dbg_core(dev,
772ad8b1aafSjsg 			     "crtc %u: Noisy timestamp %d us > %d us [%d reps].\n",
7737f4dd379Sjsg 			     pipe, duration_ns / 1000, *max_error / 1000, i);
7747f4dd379Sjsg 	}
7757f4dd379Sjsg 
7767f4dd379Sjsg 	/* Return upper bound of timestamp precision error. */
7777f4dd379Sjsg 	*max_error = duration_ns;
7787f4dd379Sjsg 
7797f4dd379Sjsg 	/* Convert scanout position into elapsed time at raw_time query
7807f4dd379Sjsg 	 * since start of scanout at first display scanline. delta_ns
7817f4dd379Sjsg 	 * can be negative if start of scanout hasn't happened yet.
7827f4dd379Sjsg 	 */
7837f4dd379Sjsg 	delta_ns = div_s64(1000000LL * (vpos * mode->crtc_htotal + hpos),
7847f4dd379Sjsg 			   mode->crtc_clock);
7857f4dd379Sjsg 
7867f4dd379Sjsg 	/* Subtract time delta from raw timestamp to get final
7877f4dd379Sjsg 	 * vblank_time timestamp for end of vblank.
7887f4dd379Sjsg 	 */
7897f4dd379Sjsg 	*vblank_time = ktime_sub_ns(etime, delta_ns);
7907f4dd379Sjsg 
791c349dbc7Sjsg 	if (!drm_debug_enabled(DRM_UT_VBL))
7927f4dd379Sjsg 		return true;
7937f4dd379Sjsg 
7947f4dd379Sjsg 	ts_etime = ktime_to_timespec64(etime);
7957f4dd379Sjsg 	ts_vblank_time = ktime_to_timespec64(*vblank_time);
7967f4dd379Sjsg 
797ad8b1aafSjsg 	drm_dbg_vbl(dev,
798ad8b1aafSjsg 		    "crtc %u : v p(%d,%d)@ %lld.%06ld -> %lld.%06ld [e %d us, %d rep]\n",
7997f4dd379Sjsg 		    pipe, hpos, vpos,
8007f4dd379Sjsg 		    (u64)ts_etime.tv_sec, ts_etime.tv_nsec / 1000,
8017f4dd379Sjsg 		    (u64)ts_vblank_time.tv_sec, ts_vblank_time.tv_nsec / 1000,
8027f4dd379Sjsg 		    duration_ns / 1000, i);
8037f4dd379Sjsg 
8047f4dd379Sjsg 	return true;
8057f4dd379Sjsg }
806c349dbc7Sjsg EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp_internal);
807c349dbc7Sjsg 
808c349dbc7Sjsg /**
809c349dbc7Sjsg  * drm_crtc_vblank_helper_get_vblank_timestamp - precise vblank timestamp
810c349dbc7Sjsg  *                                               helper
811c349dbc7Sjsg  * @crtc: CRTC whose vblank timestamp to retrieve
812c349dbc7Sjsg  * @max_error: Desired maximum allowable error in timestamps (nanosecs)
813c349dbc7Sjsg  *             On return contains true maximum error of timestamp
814c349dbc7Sjsg  * @vblank_time: Pointer to time which should receive the timestamp
815c349dbc7Sjsg  * @in_vblank_irq:
816c349dbc7Sjsg  *     True when called from drm_crtc_handle_vblank().  Some drivers
817c349dbc7Sjsg  *     need to apply some workarounds for gpu-specific vblank irq quirks
818c349dbc7Sjsg  *     if flag is set.
819c349dbc7Sjsg  *
820c349dbc7Sjsg  * Implements calculation of exact vblank timestamps from given drm_display_mode
821c349dbc7Sjsg  * timings and current video scanout position of a CRTC. This can be directly
822c349dbc7Sjsg  * used as the &drm_crtc_funcs.get_vblank_timestamp implementation of a kms
823c349dbc7Sjsg  * driver if &drm_crtc_helper_funcs.get_scanout_position is implemented.
824c349dbc7Sjsg  *
825c349dbc7Sjsg  * The current implementation only handles standard video modes. For double scan
826c349dbc7Sjsg  * and interlaced modes the driver is supposed to adjust the hardware mode
827c349dbc7Sjsg  * (taken from &drm_crtc_state.adjusted mode for atomic modeset drivers) to
828c349dbc7Sjsg  * match the scanout position reported.
829c349dbc7Sjsg  *
830c349dbc7Sjsg  * Note that atomic drivers must call drm_calc_timestamping_constants() before
831c349dbc7Sjsg  * enabling a CRTC. The atomic helpers already take care of that in
832ad8b1aafSjsg  * drm_atomic_helper_calc_timestamping_constants().
833c349dbc7Sjsg  *
834c349dbc7Sjsg  * Returns:
835c349dbc7Sjsg  *
836c349dbc7Sjsg  * Returns true on success, and false on failure, i.e. when no accurate
837c349dbc7Sjsg  * timestamp could be acquired.
838c349dbc7Sjsg  */
drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc * crtc,int * max_error,ktime_t * vblank_time,bool in_vblank_irq)839c349dbc7Sjsg bool drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc *crtc,
840c349dbc7Sjsg 						 int *max_error,
841c349dbc7Sjsg 						 ktime_t *vblank_time,
842c349dbc7Sjsg 						 bool in_vblank_irq)
843c349dbc7Sjsg {
844c349dbc7Sjsg 	return drm_crtc_vblank_helper_get_vblank_timestamp_internal(
845c349dbc7Sjsg 		crtc, max_error, vblank_time, in_vblank_irq,
846c349dbc7Sjsg 		crtc->helper_private->get_scanout_position);
847c349dbc7Sjsg }
848c349dbc7Sjsg EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp);
8497f4dd379Sjsg 
8507f4dd379Sjsg /**
851*f005ef32Sjsg  * drm_crtc_get_last_vbltimestamp - retrieve raw timestamp for the most
852*f005ef32Sjsg  *                                  recent vblank interval
853*f005ef32Sjsg  * @crtc: CRTC whose vblank timestamp to retrieve
8547f4dd379Sjsg  * @tvblank: Pointer to target time which should receive the timestamp
8557f4dd379Sjsg  * @in_vblank_irq:
8567f4dd379Sjsg  *     True when called from drm_crtc_handle_vblank().  Some drivers
8577f4dd379Sjsg  *     need to apply some workarounds for gpu-specific vblank irq quirks
8587f4dd379Sjsg  *     if flag is set.
8597f4dd379Sjsg  *
8607f4dd379Sjsg  * Fetches the system timestamp corresponding to the time of the most recent
8617f4dd379Sjsg  * vblank interval on specified CRTC. May call into kms-driver to
8627f4dd379Sjsg  * compute the timestamp with a high-precision GPU specific method.
8637f4dd379Sjsg  *
8647f4dd379Sjsg  * Returns zero if timestamp originates from uncorrected do_gettimeofday()
8657f4dd379Sjsg  * call, i.e., it isn't very precisely locked to the true vblank.
8667f4dd379Sjsg  *
8677f4dd379Sjsg  * Returns:
8687f4dd379Sjsg  * True if timestamp is considered to be very precise, false otherwise.
8697f4dd379Sjsg  */
8707f4dd379Sjsg static bool
drm_crtc_get_last_vbltimestamp(struct drm_crtc * crtc,ktime_t * tvblank,bool in_vblank_irq)871*f005ef32Sjsg drm_crtc_get_last_vbltimestamp(struct drm_crtc *crtc, ktime_t *tvblank,
872*f005ef32Sjsg 			       bool in_vblank_irq)
8737f4dd379Sjsg {
8747f4dd379Sjsg 	bool ret = false;
8757f4dd379Sjsg 
8767f4dd379Sjsg 	/* Define requested maximum error on timestamps (nanoseconds). */
8777f4dd379Sjsg 	int max_error = (int) drm_timestamp_precision * 1000;
8787f4dd379Sjsg 
8797f4dd379Sjsg 	/* Query driver if possible and precision timestamping enabled. */
880c349dbc7Sjsg 	if (crtc && crtc->funcs->get_vblank_timestamp && max_error > 0) {
881c349dbc7Sjsg 		ret = crtc->funcs->get_vblank_timestamp(crtc, &max_error,
8827f4dd379Sjsg 							tvblank, in_vblank_irq);
883c349dbc7Sjsg 	}
8847f4dd379Sjsg 
8857f4dd379Sjsg 	/* GPU high precision timestamp query unsupported or failed.
8867f4dd379Sjsg 	 * Return current monotonic/gettimeofday timestamp as best estimate.
8877f4dd379Sjsg 	 */
8887f4dd379Sjsg 	if (!ret)
8897f4dd379Sjsg 		*tvblank = ktime_get();
8907f4dd379Sjsg 
8917f4dd379Sjsg 	return ret;
8927f4dd379Sjsg }
8937f4dd379Sjsg 
894*f005ef32Sjsg static bool
drm_get_last_vbltimestamp(struct drm_device * dev,unsigned int pipe,ktime_t * tvblank,bool in_vblank_irq)895*f005ef32Sjsg drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
896*f005ef32Sjsg 			  ktime_t *tvblank, bool in_vblank_irq)
897*f005ef32Sjsg {
898*f005ef32Sjsg 	struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
899*f005ef32Sjsg 
900*f005ef32Sjsg 	return drm_crtc_get_last_vbltimestamp(crtc, tvblank, in_vblank_irq);
901*f005ef32Sjsg }
902*f005ef32Sjsg 
9037f4dd379Sjsg /**
9047f4dd379Sjsg  * drm_crtc_vblank_count - retrieve "cooked" vblank counter value
9057f4dd379Sjsg  * @crtc: which counter to retrieve
9067f4dd379Sjsg  *
9077f4dd379Sjsg  * Fetches the "cooked" vblank count value that represents the number of
9087f4dd379Sjsg  * vblank events since the system was booted, including lost events due to
9097f4dd379Sjsg  * modesetting activity. Note that this timer isn't correct against a racing
9107f4dd379Sjsg  * vblank interrupt (since it only reports the software vblank counter), see
9117f4dd379Sjsg  * drm_crtc_accurate_vblank_count() for such use-cases.
9127f4dd379Sjsg  *
913c349dbc7Sjsg  * Note that for a given vblank counter value drm_crtc_handle_vblank()
914c349dbc7Sjsg  * and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time()
915c349dbc7Sjsg  * provide a barrier: Any writes done before calling
916c349dbc7Sjsg  * drm_crtc_handle_vblank() will be visible to callers of the later
9175ca02815Sjsg  * functions, if the vblank count is the same or a later one.
918c349dbc7Sjsg  *
919c349dbc7Sjsg  * See also &drm_vblank_crtc.count.
920c349dbc7Sjsg  *
9217f4dd379Sjsg  * Returns:
9227f4dd379Sjsg  * The software vblank counter.
9237f4dd379Sjsg  */
drm_crtc_vblank_count(struct drm_crtc * crtc)9247f4dd379Sjsg u64 drm_crtc_vblank_count(struct drm_crtc *crtc)
9257f4dd379Sjsg {
9267f4dd379Sjsg 	return drm_vblank_count(crtc->dev, drm_crtc_index(crtc));
9277f4dd379Sjsg }
9287f4dd379Sjsg EXPORT_SYMBOL(drm_crtc_vblank_count);
9297f4dd379Sjsg 
9307f4dd379Sjsg /**
9317f4dd379Sjsg  * drm_vblank_count_and_time - retrieve "cooked" vblank counter value and the
9327f4dd379Sjsg  *     system timestamp corresponding to that vblank counter value.
9337f4dd379Sjsg  * @dev: DRM device
9347f4dd379Sjsg  * @pipe: index of CRTC whose counter to retrieve
9357f4dd379Sjsg  * @vblanktime: Pointer to ktime_t to receive the vblank timestamp.
9367f4dd379Sjsg  *
9377f4dd379Sjsg  * Fetches the "cooked" vblank count value that represents the number of
9387f4dd379Sjsg  * vblank events since the system was booted, including lost events due to
9397f4dd379Sjsg  * modesetting activity. Returns corresponding system timestamp of the time
9407f4dd379Sjsg  * of the vblank interval that corresponds to the current vblank counter value.
9417f4dd379Sjsg  *
9427f4dd379Sjsg  * This is the legacy version of drm_crtc_vblank_count_and_time().
9437f4dd379Sjsg  */
drm_vblank_count_and_time(struct drm_device * dev,unsigned int pipe,ktime_t * vblanktime)9447f4dd379Sjsg static u64 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
9457f4dd379Sjsg 				     ktime_t *vblanktime)
9467f4dd379Sjsg {
9477f4dd379Sjsg 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
9487f4dd379Sjsg 	u64 vblank_count;
9497f4dd379Sjsg 	unsigned int seq;
9507f4dd379Sjsg 
951ad8b1aafSjsg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) {
9520df1b8f9Sjsg 		*vblanktime = 0;
9537f4dd379Sjsg 		return 0;
9547f4dd379Sjsg 	}
9557f4dd379Sjsg 
9567f4dd379Sjsg 	do {
9577f4dd379Sjsg 		seq = read_seqbegin(&vblank->seqlock);
958c349dbc7Sjsg 		vblank_count = atomic64_read(&vblank->count);
9597f4dd379Sjsg 		*vblanktime = vblank->time;
9607f4dd379Sjsg 	} while (read_seqretry(&vblank->seqlock, seq));
9617f4dd379Sjsg 
9627f4dd379Sjsg 	return vblank_count;
9637f4dd379Sjsg }
9647f4dd379Sjsg 
9657f4dd379Sjsg /**
9667f4dd379Sjsg  * drm_crtc_vblank_count_and_time - retrieve "cooked" vblank counter value
9677f4dd379Sjsg  *     and the system timestamp corresponding to that vblank counter value
9687f4dd379Sjsg  * @crtc: which counter to retrieve
9697f4dd379Sjsg  * @vblanktime: Pointer to time to receive the vblank timestamp.
9707f4dd379Sjsg  *
9717f4dd379Sjsg  * Fetches the "cooked" vblank count value that represents the number of
9727f4dd379Sjsg  * vblank events since the system was booted, including lost events due to
9737f4dd379Sjsg  * modesetting activity. Returns corresponding system timestamp of the time
9747f4dd379Sjsg  * of the vblank interval that corresponds to the current vblank counter value.
975c349dbc7Sjsg  *
976c349dbc7Sjsg  * Note that for a given vblank counter value drm_crtc_handle_vblank()
977c349dbc7Sjsg  * and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time()
978c349dbc7Sjsg  * provide a barrier: Any writes done before calling
979c349dbc7Sjsg  * drm_crtc_handle_vblank() will be visible to callers of the later
9805ca02815Sjsg  * functions, if the vblank count is the same or a later one.
981c349dbc7Sjsg  *
982c349dbc7Sjsg  * See also &drm_vblank_crtc.count.
9837f4dd379Sjsg  */
drm_crtc_vblank_count_and_time(struct drm_crtc * crtc,ktime_t * vblanktime)9847f4dd379Sjsg u64 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc,
9857f4dd379Sjsg 				   ktime_t *vblanktime)
9867f4dd379Sjsg {
9877f4dd379Sjsg 	return drm_vblank_count_and_time(crtc->dev, drm_crtc_index(crtc),
9887f4dd379Sjsg 					 vblanktime);
9897f4dd379Sjsg }
9907f4dd379Sjsg EXPORT_SYMBOL(drm_crtc_vblank_count_and_time);
9917f4dd379Sjsg 
992*f005ef32Sjsg /**
993*f005ef32Sjsg  * drm_crtc_next_vblank_start - calculate the time of the next vblank
994*f005ef32Sjsg  * @crtc: the crtc for which to calculate next vblank time
995*f005ef32Sjsg  * @vblanktime: pointer to time to receive the next vblank timestamp.
996*f005ef32Sjsg  *
997*f005ef32Sjsg  * Calculate the expected time of the start of the next vblank period,
998*f005ef32Sjsg  * based on time of previous vblank and frame duration
999*f005ef32Sjsg  */
drm_crtc_next_vblank_start(struct drm_crtc * crtc,ktime_t * vblanktime)1000*f005ef32Sjsg int drm_crtc_next_vblank_start(struct drm_crtc *crtc, ktime_t *vblanktime)
1001*f005ef32Sjsg {
1002*f005ef32Sjsg 	unsigned int pipe = drm_crtc_index(crtc);
1003*f005ef32Sjsg 	struct drm_vblank_crtc *vblank;
1004*f005ef32Sjsg 	struct drm_display_mode *mode;
1005*f005ef32Sjsg 	u64 vblank_start;
1006*f005ef32Sjsg 
1007*f005ef32Sjsg 	if (!drm_dev_has_vblank(crtc->dev))
1008*f005ef32Sjsg 		return -EINVAL;
1009*f005ef32Sjsg 
1010*f005ef32Sjsg 	vblank = &crtc->dev->vblank[pipe];
1011*f005ef32Sjsg 	mode = &vblank->hwmode;
1012*f005ef32Sjsg 
1013*f005ef32Sjsg 	if (!vblank->framedur_ns || !vblank->linedur_ns)
1014*f005ef32Sjsg 		return -EINVAL;
1015*f005ef32Sjsg 
1016*f005ef32Sjsg 	if (!drm_crtc_get_last_vbltimestamp(crtc, vblanktime, false))
1017*f005ef32Sjsg 		return -EINVAL;
1018*f005ef32Sjsg 
1019*f005ef32Sjsg 	vblank_start = DIV_ROUND_DOWN_ULL(
1020*f005ef32Sjsg 			(u64)vblank->framedur_ns * mode->crtc_vblank_start,
1021*f005ef32Sjsg 			mode->crtc_vtotal);
1022*f005ef32Sjsg 	*vblanktime  = ktime_add(*vblanktime, ns_to_ktime(vblank_start));
1023*f005ef32Sjsg 
1024*f005ef32Sjsg 	return 0;
1025*f005ef32Sjsg }
1026*f005ef32Sjsg EXPORT_SYMBOL(drm_crtc_next_vblank_start);
1027*f005ef32Sjsg 
send_vblank_event(struct drm_device * dev,struct drm_pending_vblank_event * e,u64 seq,ktime_t now)10287f4dd379Sjsg static void send_vblank_event(struct drm_device *dev,
10297f4dd379Sjsg 		struct drm_pending_vblank_event *e,
10307f4dd379Sjsg 		u64 seq, ktime_t now)
10317f4dd379Sjsg {
10327f4dd379Sjsg 	struct timespec64 tv;
10337f4dd379Sjsg 
10347f4dd379Sjsg 	switch (e->event.base.type) {
10357f4dd379Sjsg 	case DRM_EVENT_VBLANK:
10367f4dd379Sjsg 	case DRM_EVENT_FLIP_COMPLETE:
10377f4dd379Sjsg 		tv = ktime_to_timespec64(now);
10387f4dd379Sjsg 		e->event.vbl.sequence = seq;
10397f4dd379Sjsg 		/*
10407f4dd379Sjsg 		 * e->event is a user space structure, with hardcoded unsigned
10417f4dd379Sjsg 		 * 32-bit seconds/microseconds. This is safe as we always use
10427f4dd379Sjsg 		 * monotonic timestamps since linux-4.15
10437f4dd379Sjsg 		 */
10447f4dd379Sjsg 		e->event.vbl.tv_sec = tv.tv_sec;
10457f4dd379Sjsg 		e->event.vbl.tv_usec = tv.tv_nsec / 1000;
10467f4dd379Sjsg 		break;
10477f4dd379Sjsg 	case DRM_EVENT_CRTC_SEQUENCE:
10487f4dd379Sjsg 		if (seq)
10497f4dd379Sjsg 			e->event.seq.sequence = seq;
10507f4dd379Sjsg 		e->event.seq.time_ns = ktime_to_ns(now);
10517f4dd379Sjsg 		break;
10527f4dd379Sjsg 	}
10537f4dd379Sjsg 	trace_drm_vblank_event_delivered(e->base.file_priv, e->pipe, seq);
10545ca02815Sjsg 	/*
10555ca02815Sjsg 	 * Use the same timestamp for any associated fence signal to avoid
10565ca02815Sjsg 	 * mismatch in timestamps for vsync & fence events triggered by the
10575ca02815Sjsg 	 * same HW event. Frameworks like SurfaceFlinger in Android expects the
10585ca02815Sjsg 	 * retire-fence timestamp to match exactly with HW vsync as it uses it
10595ca02815Sjsg 	 * for its software vsync modeling.
10605ca02815Sjsg 	 */
10615ca02815Sjsg 	drm_send_event_timestamp_locked(dev, &e->base, now);
10627f4dd379Sjsg }
10637f4dd379Sjsg 
10647f4dd379Sjsg /**
10657f4dd379Sjsg  * drm_crtc_arm_vblank_event - arm vblank event after pageflip
10667f4dd379Sjsg  * @crtc: the source CRTC of the vblank event
10677f4dd379Sjsg  * @e: the event to send
10687f4dd379Sjsg  *
10697f4dd379Sjsg  * A lot of drivers need to generate vblank events for the very next vblank
10707f4dd379Sjsg  * interrupt. For example when the page flip interrupt happens when the page
10717f4dd379Sjsg  * flip gets armed, but not when it actually executes within the next vblank
10727f4dd379Sjsg  * period. This helper function implements exactly the required vblank arming
10737f4dd379Sjsg  * behaviour.
10747f4dd379Sjsg  *
10757f4dd379Sjsg  * NOTE: Drivers using this to send out the &drm_crtc_state.event as part of an
10767f4dd379Sjsg  * atomic commit must ensure that the next vblank happens at exactly the same
10777f4dd379Sjsg  * time as the atomic commit is committed to the hardware. This function itself
10787f4dd379Sjsg  * does **not** protect against the next vblank interrupt racing with either this
10797f4dd379Sjsg  * function call or the atomic commit operation. A possible sequence could be:
10807f4dd379Sjsg  *
10817f4dd379Sjsg  * 1. Driver commits new hardware state into vblank-synchronized registers.
10827f4dd379Sjsg  * 2. A vblank happens, committing the hardware state. Also the corresponding
10837f4dd379Sjsg  *    vblank interrupt is fired off and fully processed by the interrupt
10847f4dd379Sjsg  *    handler.
10857f4dd379Sjsg  * 3. The atomic commit operation proceeds to call drm_crtc_arm_vblank_event().
10867f4dd379Sjsg  * 4. The event is only send out for the next vblank, which is wrong.
10877f4dd379Sjsg  *
10887f4dd379Sjsg  * An equivalent race can happen when the driver calls
10897f4dd379Sjsg  * drm_crtc_arm_vblank_event() before writing out the new hardware state.
10907f4dd379Sjsg  *
10917f4dd379Sjsg  * The only way to make this work safely is to prevent the vblank from firing
10927f4dd379Sjsg  * (and the hardware from committing anything else) until the entire atomic
10937f4dd379Sjsg  * commit sequence has run to completion. If the hardware does not have such a
10947f4dd379Sjsg  * feature (e.g. using a "go" bit), then it is unsafe to use this functions.
10957f4dd379Sjsg  * Instead drivers need to manually send out the event from their interrupt
10967f4dd379Sjsg  * handler by calling drm_crtc_send_vblank_event() and make sure that there's no
10977f4dd379Sjsg  * possible race with the hardware committing the atomic update.
10987f4dd379Sjsg  *
1099c349dbc7Sjsg  * Caller must hold a vblank reference for the event @e acquired by a
1100c349dbc7Sjsg  * drm_crtc_vblank_get(), which will be dropped when the next vblank arrives.
11017f4dd379Sjsg  */
drm_crtc_arm_vblank_event(struct drm_crtc * crtc,struct drm_pending_vblank_event * e)11027f4dd379Sjsg void drm_crtc_arm_vblank_event(struct drm_crtc *crtc,
11037f4dd379Sjsg 			       struct drm_pending_vblank_event *e)
11047f4dd379Sjsg {
11057f4dd379Sjsg 	struct drm_device *dev = crtc->dev;
11067f4dd379Sjsg 	unsigned int pipe = drm_crtc_index(crtc);
11077f4dd379Sjsg 
11087f4dd379Sjsg 	assert_spin_locked(&dev->event_lock);
11097f4dd379Sjsg 
11107f4dd379Sjsg 	e->pipe = pipe;
11117f4dd379Sjsg 	e->sequence = drm_crtc_accurate_vblank_count(crtc) + 1;
11127f4dd379Sjsg 	list_add_tail(&e->base.link, &dev->vblank_event_list);
11137f4dd379Sjsg }
11147f4dd379Sjsg EXPORT_SYMBOL(drm_crtc_arm_vblank_event);
11157f4dd379Sjsg 
11167f4dd379Sjsg /**
11177f4dd379Sjsg  * drm_crtc_send_vblank_event - helper to send vblank event after pageflip
11187f4dd379Sjsg  * @crtc: the source CRTC of the vblank event
11197f4dd379Sjsg  * @e: the event to send
11207f4dd379Sjsg  *
11217f4dd379Sjsg  * Updates sequence # and timestamp on event for the most recently processed
11227f4dd379Sjsg  * vblank, and sends it to userspace.  Caller must hold event lock.
11237f4dd379Sjsg  *
11247f4dd379Sjsg  * See drm_crtc_arm_vblank_event() for a helper which can be used in certain
11257f4dd379Sjsg  * situation, especially to send out events for atomic commit operations.
11267f4dd379Sjsg  */
drm_crtc_send_vblank_event(struct drm_crtc * crtc,struct drm_pending_vblank_event * e)11277f4dd379Sjsg void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
11287f4dd379Sjsg 				struct drm_pending_vblank_event *e)
11297f4dd379Sjsg {
11307f4dd379Sjsg 	struct drm_device *dev = crtc->dev;
11317f4dd379Sjsg 	u64 seq;
11327f4dd379Sjsg 	unsigned int pipe = drm_crtc_index(crtc);
11337f4dd379Sjsg 	ktime_t now;
11347f4dd379Sjsg 
1135ad8b1aafSjsg 	if (drm_dev_has_vblank(dev)) {
11367f4dd379Sjsg 		seq = drm_vblank_count_and_time(dev, pipe, &now);
11377f4dd379Sjsg 	} else {
11387f4dd379Sjsg 		seq = 0;
11397f4dd379Sjsg 
11407f4dd379Sjsg 		now = ktime_get();
11417f4dd379Sjsg 	}
11427f4dd379Sjsg 	e->pipe = pipe;
11437f4dd379Sjsg 	send_vblank_event(dev, e, seq, now);
11447f4dd379Sjsg }
11457f4dd379Sjsg EXPORT_SYMBOL(drm_crtc_send_vblank_event);
11467f4dd379Sjsg 
__enable_vblank(struct drm_device * dev,unsigned int pipe)11477f4dd379Sjsg static int __enable_vblank(struct drm_device *dev, unsigned int pipe)
11487f4dd379Sjsg {
11497f4dd379Sjsg 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
11507f4dd379Sjsg 		struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
11517f4dd379Sjsg 
1152ad8b1aafSjsg 		if (drm_WARN_ON(dev, !crtc))
11537f4dd379Sjsg 			return 0;
11547f4dd379Sjsg 
11557f4dd379Sjsg 		if (crtc->funcs->enable_vblank)
11567f4dd379Sjsg 			return crtc->funcs->enable_vblank(crtc);
11575ca02815Sjsg 	}
11585ca02815Sjsg #ifdef CONFIG_DRM_LEGACY
11595ca02815Sjsg 	else if (dev->driver->enable_vblank) {
1160c349dbc7Sjsg 		return dev->driver->enable_vblank(dev, pipe);
11617f4dd379Sjsg 	}
11625ca02815Sjsg #endif
11637f4dd379Sjsg 
1164c349dbc7Sjsg 	return -EINVAL;
11657f4dd379Sjsg }
11667f4dd379Sjsg 
drm_vblank_enable(struct drm_device * dev,unsigned int pipe)11677f4dd379Sjsg static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe)
11687f4dd379Sjsg {
11697f4dd379Sjsg 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
11707f4dd379Sjsg 	int ret = 0;
11717f4dd379Sjsg 
11727f4dd379Sjsg 	assert_spin_locked(&dev->vbl_lock);
11737f4dd379Sjsg 
11747f4dd379Sjsg 	spin_lock(&dev->vblank_time_lock);
11757f4dd379Sjsg 
11767f4dd379Sjsg 	if (!vblank->enabled) {
11777f4dd379Sjsg 		/*
11787f4dd379Sjsg 		 * Enable vblank irqs under vblank_time_lock protection.
11797f4dd379Sjsg 		 * All vblank count & timestamp updates are held off
11807f4dd379Sjsg 		 * until we are done reinitializing master counter and
11817f4dd379Sjsg 		 * timestamps. Filtercode in drm_handle_vblank() will
11827f4dd379Sjsg 		 * prevent double-accounting of same vblank interval.
11837f4dd379Sjsg 		 */
11847f4dd379Sjsg 		ret = __enable_vblank(dev, pipe);
1185ad8b1aafSjsg 		drm_dbg_core(dev, "enabling vblank on crtc %u, ret: %d\n",
1186ad8b1aafSjsg 			     pipe, ret);
11877f4dd379Sjsg 		if (ret) {
11887f4dd379Sjsg 			atomic_dec(&vblank->refcount);
11897f4dd379Sjsg 		} else {
11907f4dd379Sjsg 			drm_update_vblank_count(dev, pipe, 0);
11917f4dd379Sjsg 			/* drm_update_vblank_count() includes a wmb so we just
11927f4dd379Sjsg 			 * need to ensure that the compiler emits the write
11937f4dd379Sjsg 			 * to mark the vblank as enabled after the call
11947f4dd379Sjsg 			 * to drm_update_vblank_count().
11957f4dd379Sjsg 			 */
11967f4dd379Sjsg 			WRITE_ONCE(vblank->enabled, true);
11977f4dd379Sjsg 		}
11987f4dd379Sjsg 	}
11997f4dd379Sjsg 
12007f4dd379Sjsg 	spin_unlock(&dev->vblank_time_lock);
12017f4dd379Sjsg 
12027f4dd379Sjsg 	return ret;
12037f4dd379Sjsg }
12047f4dd379Sjsg 
drm_vblank_get(struct drm_device * dev,unsigned int pipe)1205ad8b1aafSjsg int drm_vblank_get(struct drm_device *dev, unsigned int pipe)
12067f4dd379Sjsg {
12077f4dd379Sjsg 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
12087f4dd379Sjsg 	unsigned long irqflags;
12097f4dd379Sjsg 	int ret = 0;
12107f4dd379Sjsg 
1211ad8b1aafSjsg 	if (!drm_dev_has_vblank(dev))
12127f4dd379Sjsg 		return -EINVAL;
12137f4dd379Sjsg 
1214ad8b1aafSjsg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
12157f4dd379Sjsg 		return -EINVAL;
12167f4dd379Sjsg 
12177f4dd379Sjsg 	spin_lock_irqsave(&dev->vbl_lock, irqflags);
12187f4dd379Sjsg 	/* Going from 0->1 means we have to enable interrupts again */
12197f4dd379Sjsg 	if (atomic_add_return(1, &vblank->refcount) == 1) {
12207f4dd379Sjsg 		ret = drm_vblank_enable(dev, pipe);
12217f4dd379Sjsg 	} else {
12227f4dd379Sjsg 		if (!vblank->enabled) {
12237f4dd379Sjsg 			atomic_dec(&vblank->refcount);
12247f4dd379Sjsg 			ret = -EINVAL;
12257f4dd379Sjsg 		}
12267f4dd379Sjsg 	}
12277f4dd379Sjsg 	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
12287f4dd379Sjsg 
12297f4dd379Sjsg 	return ret;
12307f4dd379Sjsg }
12317f4dd379Sjsg 
12327f4dd379Sjsg /**
12337f4dd379Sjsg  * drm_crtc_vblank_get - get a reference count on vblank events
12347f4dd379Sjsg  * @crtc: which CRTC to own
12357f4dd379Sjsg  *
12367f4dd379Sjsg  * Acquire a reference count on vblank events to avoid having them disabled
12377f4dd379Sjsg  * while in use.
12387f4dd379Sjsg  *
12397f4dd379Sjsg  * Returns:
12407f4dd379Sjsg  * Zero on success or a negative error code on failure.
12417f4dd379Sjsg  */
drm_crtc_vblank_get(struct drm_crtc * crtc)12427f4dd379Sjsg int drm_crtc_vblank_get(struct drm_crtc *crtc)
12437f4dd379Sjsg {
12447f4dd379Sjsg 	return drm_vblank_get(crtc->dev, drm_crtc_index(crtc));
12457f4dd379Sjsg }
12467f4dd379Sjsg EXPORT_SYMBOL(drm_crtc_vblank_get);
12477f4dd379Sjsg 
drm_vblank_put(struct drm_device * dev,unsigned int pipe)1248ad8b1aafSjsg void drm_vblank_put(struct drm_device *dev, unsigned int pipe)
12497f4dd379Sjsg {
12507f4dd379Sjsg 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
12517f4dd379Sjsg 
1252ad8b1aafSjsg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
12537f4dd379Sjsg 		return;
12547f4dd379Sjsg 
1255ad8b1aafSjsg 	if (drm_WARN_ON(dev, atomic_read(&vblank->refcount) == 0))
12567f4dd379Sjsg 		return;
12577f4dd379Sjsg 
12587f4dd379Sjsg 	/* Last user schedules interrupt disable */
12597f4dd379Sjsg 	if (atomic_dec_and_test(&vblank->refcount)) {
12607f4dd379Sjsg 		if (drm_vblank_offdelay == 0)
12617f4dd379Sjsg 			return;
12627f4dd379Sjsg 		else if (drm_vblank_offdelay < 0)
1263bbf6708cSjsg 			vblank_disable_fn(vblank);
12647f4dd379Sjsg 		else if (!dev->vblank_disable_immediate)
12657f4dd379Sjsg 			mod_timer(&vblank->disable_timer,
12667f4dd379Sjsg 				  jiffies + ((drm_vblank_offdelay * HZ)/1000));
12677f4dd379Sjsg 	}
12687f4dd379Sjsg }
12697f4dd379Sjsg 
12707f4dd379Sjsg /**
12717f4dd379Sjsg  * drm_crtc_vblank_put - give up ownership of vblank events
12727f4dd379Sjsg  * @crtc: which counter to give up
12737f4dd379Sjsg  *
12747f4dd379Sjsg  * Release ownership of a given vblank counter, turning off interrupts
12757f4dd379Sjsg  * if possible. Disable interrupts after drm_vblank_offdelay milliseconds.
12767f4dd379Sjsg  */
drm_crtc_vblank_put(struct drm_crtc * crtc)12777f4dd379Sjsg void drm_crtc_vblank_put(struct drm_crtc *crtc)
12787f4dd379Sjsg {
12797f4dd379Sjsg 	drm_vblank_put(crtc->dev, drm_crtc_index(crtc));
12807f4dd379Sjsg }
12817f4dd379Sjsg EXPORT_SYMBOL(drm_crtc_vblank_put);
12827f4dd379Sjsg 
12837f4dd379Sjsg /**
12847f4dd379Sjsg  * drm_wait_one_vblank - wait for one vblank
12857f4dd379Sjsg  * @dev: DRM device
12867f4dd379Sjsg  * @pipe: CRTC index
12877f4dd379Sjsg  *
12887f4dd379Sjsg  * This waits for one vblank to pass on @pipe, using the irq driver interfaces.
12897f4dd379Sjsg  * It is a failure to call this when the vblank irq for @pipe is disabled, e.g.
12907f4dd379Sjsg  * due to lack of driver support or because the crtc is off.
12917f4dd379Sjsg  *
12927f4dd379Sjsg  * This is the legacy version of drm_crtc_wait_one_vblank().
12937f4dd379Sjsg  */
drm_wait_one_vblank(struct drm_device * dev,unsigned int pipe)12947f4dd379Sjsg void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe)
12957f4dd379Sjsg {
12967f4dd379Sjsg 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
12977f4dd379Sjsg 	int ret;
12987f4dd379Sjsg 	u64 last;
12997f4dd379Sjsg 
1300ad8b1aafSjsg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
13017f4dd379Sjsg 		return;
13027f4dd379Sjsg 
13037f4dd379Sjsg #ifdef __OpenBSD__
13047f4dd379Sjsg 	/*
13057f4dd379Sjsg 	 * If we're cold, vblank interrupts won't happen even if
13067f4dd379Sjsg 	 * they're turned on by the driver.  Just stall long enough
13077f4dd379Sjsg 	 * for a vblank to pass.  This assumes a vrefresh of at least
13087f4dd379Sjsg 	 * 25 Hz.
13097f4dd379Sjsg 	 */
13107f4dd379Sjsg 	if (cold) {
13117f4dd379Sjsg 		delay(40000);
13127f4dd379Sjsg 		return;
13137f4dd379Sjsg 	}
13147f4dd379Sjsg #endif
13157f4dd379Sjsg 
13167f4dd379Sjsg 	ret = drm_vblank_get(dev, pipe);
1317ad8b1aafSjsg 	if (drm_WARN(dev, ret, "vblank not available on crtc %i, ret=%i\n",
1318ad8b1aafSjsg 		     pipe, ret))
13197f4dd379Sjsg 		return;
13207f4dd379Sjsg 
13217f4dd379Sjsg 	last = drm_vblank_count(dev, pipe);
13227f4dd379Sjsg 
13237f4dd379Sjsg 	ret = wait_event_timeout(vblank->queue,
13247f4dd379Sjsg 				 last != drm_vblank_count(dev, pipe),
13257f4dd379Sjsg 				 msecs_to_jiffies(100));
13267f4dd379Sjsg 
1327ad8b1aafSjsg 	drm_WARN(dev, ret == 0, "vblank wait timed out on crtc %i\n", pipe);
13287f4dd379Sjsg 
13297f4dd379Sjsg 	drm_vblank_put(dev, pipe);
13307f4dd379Sjsg }
13317f4dd379Sjsg EXPORT_SYMBOL(drm_wait_one_vblank);
13327f4dd379Sjsg 
13337f4dd379Sjsg /**
13347f4dd379Sjsg  * drm_crtc_wait_one_vblank - wait for one vblank
13357f4dd379Sjsg  * @crtc: DRM crtc
13367f4dd379Sjsg  *
13377f4dd379Sjsg  * This waits for one vblank to pass on @crtc, using the irq driver interfaces.
13387f4dd379Sjsg  * It is a failure to call this when the vblank irq for @crtc is disabled, e.g.
13397f4dd379Sjsg  * due to lack of driver support or because the crtc is off.
13407f4dd379Sjsg  */
drm_crtc_wait_one_vblank(struct drm_crtc * crtc)13417f4dd379Sjsg void drm_crtc_wait_one_vblank(struct drm_crtc *crtc)
13427f4dd379Sjsg {
13437f4dd379Sjsg 	drm_wait_one_vblank(crtc->dev, drm_crtc_index(crtc));
13447f4dd379Sjsg }
13457f4dd379Sjsg EXPORT_SYMBOL(drm_crtc_wait_one_vblank);
13467f4dd379Sjsg 
13477f4dd379Sjsg /**
13487f4dd379Sjsg  * drm_crtc_vblank_off - disable vblank events on a CRTC
13497f4dd379Sjsg  * @crtc: CRTC in question
13507f4dd379Sjsg  *
13517f4dd379Sjsg  * Drivers can use this function to shut down the vblank interrupt handling when
13527f4dd379Sjsg  * disabling a crtc. This function ensures that the latest vblank frame count is
13537f4dd379Sjsg  * stored so that drm_vblank_on can restore it again.
13547f4dd379Sjsg  *
13557f4dd379Sjsg  * Drivers must use this function when the hardware vblank counter can get
13567f4dd379Sjsg  * reset, e.g. when suspending or disabling the @crtc in general.
13577f4dd379Sjsg  */
drm_crtc_vblank_off(struct drm_crtc * crtc)13587f4dd379Sjsg void drm_crtc_vblank_off(struct drm_crtc *crtc)
13597f4dd379Sjsg {
13607f4dd379Sjsg 	struct drm_device *dev = crtc->dev;
13617f4dd379Sjsg 	unsigned int pipe = drm_crtc_index(crtc);
13627f4dd379Sjsg 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
13637f4dd379Sjsg 	struct drm_pending_vblank_event *e, *t;
13647f4dd379Sjsg 	ktime_t now;
13657f4dd379Sjsg 	u64 seq;
13667f4dd379Sjsg 
1367ad8b1aafSjsg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
13687f4dd379Sjsg 		return;
13697f4dd379Sjsg 
1370ad8b1aafSjsg 	/*
1371ad8b1aafSjsg 	 * Grab event_lock early to prevent vblank work from being scheduled
1372ad8b1aafSjsg 	 * while we're in the middle of shutting down vblank interrupts
1373ad8b1aafSjsg 	 */
1374ad8b1aafSjsg 	spin_lock_irq(&dev->event_lock);
13757f4dd379Sjsg 
13767f4dd379Sjsg 	spin_lock(&dev->vbl_lock);
1377ad8b1aafSjsg 	drm_dbg_vbl(dev, "crtc %d, vblank enabled %d, inmodeset %d\n",
13787f4dd379Sjsg 		    pipe, vblank->enabled, vblank->inmodeset);
13797f4dd379Sjsg 
13807f4dd379Sjsg 	/* Avoid redundant vblank disables without previous
13817f4dd379Sjsg 	 * drm_crtc_vblank_on(). */
13827f4dd379Sjsg 	if (drm_core_check_feature(dev, DRIVER_ATOMIC) || !vblank->inmodeset)
13837f4dd379Sjsg 		drm_vblank_disable_and_save(dev, pipe);
13847f4dd379Sjsg 
13857f4dd379Sjsg 	wake_up(&vblank->queue);
13867f4dd379Sjsg 
13877f4dd379Sjsg 	/*
13887f4dd379Sjsg 	 * Prevent subsequent drm_vblank_get() from re-enabling
13897f4dd379Sjsg 	 * the vblank interrupt by bumping the refcount.
13907f4dd379Sjsg 	 */
13917f4dd379Sjsg 	if (!vblank->inmodeset) {
13927f4dd379Sjsg 		atomic_inc(&vblank->refcount);
13937f4dd379Sjsg 		vblank->inmodeset = 1;
13947f4dd379Sjsg 	}
13957f4dd379Sjsg 	spin_unlock(&dev->vbl_lock);
13967f4dd379Sjsg 
13977f4dd379Sjsg 	/* Send any queued vblank events, lest the natives grow disquiet */
13987f4dd379Sjsg 	seq = drm_vblank_count_and_time(dev, pipe, &now);
13997f4dd379Sjsg 
14007f4dd379Sjsg 	list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
14017f4dd379Sjsg 		if (e->pipe != pipe)
14027f4dd379Sjsg 			continue;
1403ad8b1aafSjsg 		drm_dbg_core(dev, "Sending premature vblank event on disable: "
14047f4dd379Sjsg 			     "wanted %llu, current %llu\n",
14057f4dd379Sjsg 			     e->sequence, seq);
14067f4dd379Sjsg 		list_del(&e->base.link);
14077f4dd379Sjsg 		drm_vblank_put(dev, pipe);
14087f4dd379Sjsg 		send_vblank_event(dev, e, seq, now);
14097f4dd379Sjsg 	}
1410ad8b1aafSjsg 
1411ad8b1aafSjsg 	/* Cancel any leftover pending vblank work */
1412ad8b1aafSjsg 	drm_vblank_cancel_pending_works(vblank);
1413ad8b1aafSjsg 
1414ad8b1aafSjsg 	spin_unlock_irq(&dev->event_lock);
14157f4dd379Sjsg 
14167f4dd379Sjsg 	/* Will be reset by the modeset helpers when re-enabling the crtc by
14177f4dd379Sjsg 	 * calling drm_calc_timestamping_constants(). */
14187f4dd379Sjsg 	vblank->hwmode.crtc_clock = 0;
1419ad8b1aafSjsg 
1420ad8b1aafSjsg 	/* Wait for any vblank work that's still executing to finish */
1421ad8b1aafSjsg 	drm_vblank_flush_worker(vblank);
14227f4dd379Sjsg }
14237f4dd379Sjsg EXPORT_SYMBOL(drm_crtc_vblank_off);
14247f4dd379Sjsg 
14257f4dd379Sjsg /**
14267f4dd379Sjsg  * drm_crtc_vblank_reset - reset vblank state to off on a CRTC
14277f4dd379Sjsg  * @crtc: CRTC in question
14287f4dd379Sjsg  *
14297f4dd379Sjsg  * Drivers can use this function to reset the vblank state to off at load time.
14307f4dd379Sjsg  * Drivers should use this together with the drm_crtc_vblank_off() and
14317f4dd379Sjsg  * drm_crtc_vblank_on() functions. The difference compared to
14327f4dd379Sjsg  * drm_crtc_vblank_off() is that this function doesn't save the vblank counter
14337f4dd379Sjsg  * and hence doesn't need to call any driver hooks.
14347f4dd379Sjsg  *
14357f4dd379Sjsg  * This is useful for recovering driver state e.g. on driver load, or on resume.
14367f4dd379Sjsg  */
drm_crtc_vblank_reset(struct drm_crtc * crtc)14377f4dd379Sjsg void drm_crtc_vblank_reset(struct drm_crtc *crtc)
14387f4dd379Sjsg {
14397f4dd379Sjsg 	struct drm_device *dev = crtc->dev;
14407f4dd379Sjsg 	unsigned int pipe = drm_crtc_index(crtc);
14417f4dd379Sjsg 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
14427f4dd379Sjsg 
1443ad8b1aafSjsg 	spin_lock_irq(&dev->vbl_lock);
14447f4dd379Sjsg 	/*
14457f4dd379Sjsg 	 * Prevent subsequent drm_vblank_get() from enabling the vblank
14467f4dd379Sjsg 	 * interrupt by bumping the refcount.
14477f4dd379Sjsg 	 */
14487f4dd379Sjsg 	if (!vblank->inmodeset) {
14497f4dd379Sjsg 		atomic_inc(&vblank->refcount);
14507f4dd379Sjsg 		vblank->inmodeset = 1;
14517f4dd379Sjsg 	}
1452ad8b1aafSjsg 	spin_unlock_irq(&dev->vbl_lock);
14537f4dd379Sjsg 
1454ad8b1aafSjsg 	drm_WARN_ON(dev, !list_empty(&dev->vblank_event_list));
1455ad8b1aafSjsg 	drm_WARN_ON(dev, !list_empty(&vblank->pending_work));
14567f4dd379Sjsg }
14577f4dd379Sjsg EXPORT_SYMBOL(drm_crtc_vblank_reset);
14587f4dd379Sjsg 
14597f4dd379Sjsg /**
14601b040800Sjsg  * drm_crtc_set_max_vblank_count - configure the hw max vblank counter value
14611b040800Sjsg  * @crtc: CRTC in question
14621b040800Sjsg  * @max_vblank_count: max hardware vblank counter value
14631b040800Sjsg  *
14641b040800Sjsg  * Update the maximum hardware vblank counter value for @crtc
14651b040800Sjsg  * at runtime. Useful for hardware where the operation of the
14661b040800Sjsg  * hardware vblank counter depends on the currently active
14671b040800Sjsg  * display configuration.
14681b040800Sjsg  *
14691b040800Sjsg  * For example, if the hardware vblank counter does not work
14701b040800Sjsg  * when a specific connector is active the maximum can be set
14711b040800Sjsg  * to zero. And when that specific connector isn't active the
14721b040800Sjsg  * maximum can again be set to the appropriate non-zero value.
14731b040800Sjsg  *
14741b040800Sjsg  * If used, must be called before drm_vblank_on().
14751b040800Sjsg  */
drm_crtc_set_max_vblank_count(struct drm_crtc * crtc,u32 max_vblank_count)14761b040800Sjsg void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc,
14771b040800Sjsg 				   u32 max_vblank_count)
14781b040800Sjsg {
14791b040800Sjsg 	struct drm_device *dev = crtc->dev;
14801b040800Sjsg 	unsigned int pipe = drm_crtc_index(crtc);
14811b040800Sjsg 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
14821b040800Sjsg 
1483ad8b1aafSjsg 	drm_WARN_ON(dev, dev->max_vblank_count);
1484ad8b1aafSjsg 	drm_WARN_ON(dev, !READ_ONCE(vblank->inmodeset));
14851b040800Sjsg 
14861b040800Sjsg 	vblank->max_vblank_count = max_vblank_count;
14871b040800Sjsg }
14881b040800Sjsg EXPORT_SYMBOL(drm_crtc_set_max_vblank_count);
14891b040800Sjsg 
14901b040800Sjsg /**
14917f4dd379Sjsg  * drm_crtc_vblank_on - enable vblank events on a CRTC
14927f4dd379Sjsg  * @crtc: CRTC in question
14937f4dd379Sjsg  *
14947f4dd379Sjsg  * This functions restores the vblank interrupt state captured with
14957f4dd379Sjsg  * drm_crtc_vblank_off() again and is generally called when enabling @crtc. Note
14967f4dd379Sjsg  * that calls to drm_crtc_vblank_on() and drm_crtc_vblank_off() can be
14977f4dd379Sjsg  * unbalanced and so can also be unconditionally called in driver load code to
14987f4dd379Sjsg  * reflect the current hardware state of the crtc.
14997f4dd379Sjsg  */
drm_crtc_vblank_on(struct drm_crtc * crtc)15007f4dd379Sjsg void drm_crtc_vblank_on(struct drm_crtc *crtc)
15017f4dd379Sjsg {
15027f4dd379Sjsg 	struct drm_device *dev = crtc->dev;
15037f4dd379Sjsg 	unsigned int pipe = drm_crtc_index(crtc);
15047f4dd379Sjsg 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
15057f4dd379Sjsg 
1506ad8b1aafSjsg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
15077f4dd379Sjsg 		return;
15087f4dd379Sjsg 
1509ad8b1aafSjsg 	spin_lock_irq(&dev->vbl_lock);
1510ad8b1aafSjsg 	drm_dbg_vbl(dev, "crtc %d, vblank enabled %d, inmodeset %d\n",
15117f4dd379Sjsg 		    pipe, vblank->enabled, vblank->inmodeset);
15127f4dd379Sjsg 
15137f4dd379Sjsg 	/* Drop our private "prevent drm_vblank_get" refcount */
15147f4dd379Sjsg 	if (vblank->inmodeset) {
15157f4dd379Sjsg 		atomic_dec(&vblank->refcount);
15167f4dd379Sjsg 		vblank->inmodeset = 0;
15177f4dd379Sjsg 	}
15187f4dd379Sjsg 
15197f4dd379Sjsg 	drm_reset_vblank_timestamp(dev, pipe);
15207f4dd379Sjsg 
15217f4dd379Sjsg 	/*
15227f4dd379Sjsg 	 * re-enable interrupts if there are users left, or the
15237f4dd379Sjsg 	 * user wishes vblank interrupts to be enabled all the time.
15247f4dd379Sjsg 	 */
15257f4dd379Sjsg 	if (atomic_read(&vblank->refcount) != 0 || drm_vblank_offdelay == 0)
1526ad8b1aafSjsg 		drm_WARN_ON(dev, drm_vblank_enable(dev, pipe));
1527ad8b1aafSjsg 	spin_unlock_irq(&dev->vbl_lock);
15287f4dd379Sjsg }
15297f4dd379Sjsg EXPORT_SYMBOL(drm_crtc_vblank_on);
15307f4dd379Sjsg 
drm_vblank_restore(struct drm_device * dev,unsigned int pipe)15315ca02815Sjsg static void drm_vblank_restore(struct drm_device *dev, unsigned int pipe)
15327f4dd379Sjsg {
15337f4dd379Sjsg 	ktime_t t_vblank;
15347f4dd379Sjsg 	struct drm_vblank_crtc *vblank;
15357f4dd379Sjsg 	int framedur_ns;
15367f4dd379Sjsg 	u64 diff_ns;
15377f4dd379Sjsg 	u32 cur_vblank, diff = 1;
15387f4dd379Sjsg 	int count = DRM_TIMESTAMP_MAXRETRIES;
15395ca02815Sjsg 	u32 max_vblank_count = drm_max_vblank_count(dev, pipe);
15407f4dd379Sjsg 
1541ad8b1aafSjsg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
15427f4dd379Sjsg 		return;
15437f4dd379Sjsg 
15447f4dd379Sjsg 	assert_spin_locked(&dev->vbl_lock);
15457f4dd379Sjsg 	assert_spin_locked(&dev->vblank_time_lock);
15467f4dd379Sjsg 
15477f4dd379Sjsg 	vblank = &dev->vblank[pipe];
1548ad8b1aafSjsg 	drm_WARN_ONCE(dev,
1549ad8b1aafSjsg 		      drm_debug_enabled(DRM_UT_VBL) && !vblank->framedur_ns,
15507f4dd379Sjsg 		      "Cannot compute missed vblanks without frame duration\n");
15517f4dd379Sjsg 	framedur_ns = vblank->framedur_ns;
15527f4dd379Sjsg 
15537f4dd379Sjsg 	do {
15547f4dd379Sjsg 		cur_vblank = __get_vblank_counter(dev, pipe);
15557f4dd379Sjsg 		drm_get_last_vbltimestamp(dev, pipe, &t_vblank, false);
15567f4dd379Sjsg 	} while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
15577f4dd379Sjsg 
15587f4dd379Sjsg 	diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time));
15597f4dd379Sjsg 	if (framedur_ns)
15607f4dd379Sjsg 		diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns);
15617f4dd379Sjsg 
15627f4dd379Sjsg 
1563ad8b1aafSjsg 	drm_dbg_vbl(dev,
1564ad8b1aafSjsg 		    "missed %d vblanks in %lld ns, frame duration=%d ns, hw_diff=%d\n",
15657f4dd379Sjsg 		    diff, diff_ns, framedur_ns, cur_vblank - vblank->last);
15665ca02815Sjsg 	vblank->last = (cur_vblank - diff) & max_vblank_count;
15677f4dd379Sjsg }
15687f4dd379Sjsg 
15697f4dd379Sjsg /**
15707f4dd379Sjsg  * drm_crtc_vblank_restore - estimate missed vblanks and update vblank count.
15717f4dd379Sjsg  * @crtc: CRTC in question
15727f4dd379Sjsg  *
15737f4dd379Sjsg  * Power manamement features can cause frame counter resets between vblank
15747f4dd379Sjsg  * disable and enable. Drivers can use this function in their
15757f4dd379Sjsg  * &drm_crtc_funcs.enable_vblank implementation to estimate missed vblanks since
15767f4dd379Sjsg  * the last &drm_crtc_funcs.disable_vblank using timestamps and update the
15777f4dd379Sjsg  * vblank counter.
15785ca02815Sjsg  *
15795ca02815Sjsg  * Note that drivers must have race-free high-precision timestamping support,
15805ca02815Sjsg  * i.e.  &drm_crtc_funcs.get_vblank_timestamp must be hooked up and
15815ca02815Sjsg  * &drm_driver.vblank_disable_immediate must be set to indicate the
15825ca02815Sjsg  * time-stamping functions are race-free against vblank hardware counter
15835ca02815Sjsg  * increments.
15847f4dd379Sjsg  */
drm_crtc_vblank_restore(struct drm_crtc * crtc)15857f4dd379Sjsg void drm_crtc_vblank_restore(struct drm_crtc *crtc)
15867f4dd379Sjsg {
15875ca02815Sjsg 	WARN_ON_ONCE(!crtc->funcs->get_vblank_timestamp);
15885ca02815Sjsg 	WARN_ON_ONCE(!crtc->dev->vblank_disable_immediate);
15895ca02815Sjsg 
15907f4dd379Sjsg 	drm_vblank_restore(crtc->dev, drm_crtc_index(crtc));
15917f4dd379Sjsg }
15927f4dd379Sjsg EXPORT_SYMBOL(drm_crtc_vblank_restore);
15937f4dd379Sjsg 
drm_legacy_vblank_pre_modeset(struct drm_device * dev,unsigned int pipe)15947f4dd379Sjsg static void drm_legacy_vblank_pre_modeset(struct drm_device *dev,
15957f4dd379Sjsg 					  unsigned int pipe)
15967f4dd379Sjsg {
15977f4dd379Sjsg 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
15987f4dd379Sjsg 
15997f4dd379Sjsg 	/* vblank is not initialized (IRQ not installed ?), or has been freed */
1600ad8b1aafSjsg 	if (!drm_dev_has_vblank(dev))
16017f4dd379Sjsg 		return;
16027f4dd379Sjsg 
1603ad8b1aafSjsg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
16047f4dd379Sjsg 		return;
16057f4dd379Sjsg 
16067f4dd379Sjsg 	/*
16077f4dd379Sjsg 	 * To avoid all the problems that might happen if interrupts
16087f4dd379Sjsg 	 * were enabled/disabled around or between these calls, we just
16097f4dd379Sjsg 	 * have the kernel take a reference on the CRTC (just once though
16107f4dd379Sjsg 	 * to avoid corrupting the count if multiple, mismatch calls occur),
16117f4dd379Sjsg 	 * so that interrupts remain enabled in the interim.
16127f4dd379Sjsg 	 */
16137f4dd379Sjsg 	if (!vblank->inmodeset) {
16147f4dd379Sjsg 		vblank->inmodeset = 0x1;
16157f4dd379Sjsg 		if (drm_vblank_get(dev, pipe) == 0)
16167f4dd379Sjsg 			vblank->inmodeset |= 0x2;
16177f4dd379Sjsg 	}
16187f4dd379Sjsg }
16197f4dd379Sjsg 
drm_legacy_vblank_post_modeset(struct drm_device * dev,unsigned int pipe)16207f4dd379Sjsg static void drm_legacy_vblank_post_modeset(struct drm_device *dev,
16217f4dd379Sjsg 					   unsigned int pipe)
16227f4dd379Sjsg {
16237f4dd379Sjsg 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
16247f4dd379Sjsg 
16257f4dd379Sjsg 	/* vblank is not initialized (IRQ not installed ?), or has been freed */
1626ad8b1aafSjsg 	if (!drm_dev_has_vblank(dev))
16277f4dd379Sjsg 		return;
16287f4dd379Sjsg 
1629ad8b1aafSjsg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
16307f4dd379Sjsg 		return;
16317f4dd379Sjsg 
16327f4dd379Sjsg 	if (vblank->inmodeset) {
1633ad8b1aafSjsg 		spin_lock_irq(&dev->vbl_lock);
16347f4dd379Sjsg 		drm_reset_vblank_timestamp(dev, pipe);
1635ad8b1aafSjsg 		spin_unlock_irq(&dev->vbl_lock);
16367f4dd379Sjsg 
16377f4dd379Sjsg 		if (vblank->inmodeset & 0x2)
16387f4dd379Sjsg 			drm_vblank_put(dev, pipe);
16397f4dd379Sjsg 
16407f4dd379Sjsg 		vblank->inmodeset = 0;
16417f4dd379Sjsg 	}
16427f4dd379Sjsg }
16437f4dd379Sjsg 
drm_legacy_modeset_ctl_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)16447f4dd379Sjsg int drm_legacy_modeset_ctl_ioctl(struct drm_device *dev, void *data,
16457f4dd379Sjsg 				 struct drm_file *file_priv)
16467f4dd379Sjsg {
16477f4dd379Sjsg 	struct drm_modeset_ctl *modeset = data;
16487f4dd379Sjsg 	unsigned int pipe;
16497f4dd379Sjsg 
16507f4dd379Sjsg 	/* If drm_vblank_init() hasn't been called yet, just no-op */
1651ad8b1aafSjsg 	if (!drm_dev_has_vblank(dev))
16527f4dd379Sjsg 		return 0;
16537f4dd379Sjsg 
16547f4dd379Sjsg 	/* KMS drivers handle this internally */
16557f4dd379Sjsg 	if (!drm_core_check_feature(dev, DRIVER_LEGACY))
16567f4dd379Sjsg 		return 0;
16577f4dd379Sjsg 
16587f4dd379Sjsg 	pipe = modeset->crtc;
16597f4dd379Sjsg 	if (pipe >= dev->num_crtcs)
16607f4dd379Sjsg 		return -EINVAL;
16617f4dd379Sjsg 
16627f4dd379Sjsg 	switch (modeset->cmd) {
16637f4dd379Sjsg 	case _DRM_PRE_MODESET:
16647f4dd379Sjsg 		drm_legacy_vblank_pre_modeset(dev, pipe);
16657f4dd379Sjsg 		break;
16667f4dd379Sjsg 	case _DRM_POST_MODESET:
16677f4dd379Sjsg 		drm_legacy_vblank_post_modeset(dev, pipe);
16687f4dd379Sjsg 		break;
16697f4dd379Sjsg 	default:
16707f4dd379Sjsg 		return -EINVAL;
16717f4dd379Sjsg 	}
16727f4dd379Sjsg 
16737f4dd379Sjsg 	return 0;
16747f4dd379Sjsg }
16757f4dd379Sjsg 
drm_queue_vblank_event(struct drm_device * dev,unsigned int pipe,u64 req_seq,union drm_wait_vblank * vblwait,struct drm_file * file_priv)16767f4dd379Sjsg static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
16777f4dd379Sjsg 				  u64 req_seq,
16787f4dd379Sjsg 				  union drm_wait_vblank *vblwait,
16797f4dd379Sjsg 				  struct drm_file *file_priv)
16807f4dd379Sjsg {
16817f4dd379Sjsg 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
16827f4dd379Sjsg 	struct drm_pending_vblank_event *e;
16837f4dd379Sjsg 	ktime_t now;
16847f4dd379Sjsg 	u64 seq;
16857f4dd379Sjsg 	int ret;
16867f4dd379Sjsg 
16877f4dd379Sjsg 	e = kzalloc(sizeof(*e), GFP_KERNEL);
16887f4dd379Sjsg 	if (e == NULL) {
16897f4dd379Sjsg 		ret = -ENOMEM;
16907f4dd379Sjsg 		goto err_put;
16917f4dd379Sjsg 	}
16927f4dd379Sjsg 
16937f4dd379Sjsg 	e->pipe = pipe;
16947f4dd379Sjsg 	e->event.base.type = DRM_EVENT_VBLANK;
16957f4dd379Sjsg 	e->event.base.length = sizeof(e->event.vbl);
16967f4dd379Sjsg 	e->event.vbl.user_data = vblwait->request.signal;
16977f4dd379Sjsg 	e->event.vbl.crtc_id = 0;
16987f4dd379Sjsg 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
16997f4dd379Sjsg 		struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
1700ad8b1aafSjsg 
17017f4dd379Sjsg 		if (crtc)
17027f4dd379Sjsg 			e->event.vbl.crtc_id = crtc->base.id;
17037f4dd379Sjsg 	}
17047f4dd379Sjsg 
1705ad8b1aafSjsg 	spin_lock_irq(&dev->event_lock);
17067f4dd379Sjsg 
17077f4dd379Sjsg 	/*
17087f4dd379Sjsg 	 * drm_crtc_vblank_off() might have been called after we called
17097f4dd379Sjsg 	 * drm_vblank_get(). drm_crtc_vblank_off() holds event_lock around the
17107f4dd379Sjsg 	 * vblank disable, so no need for further locking.  The reference from
17117f4dd379Sjsg 	 * drm_vblank_get() protects against vblank disable from another source.
17127f4dd379Sjsg 	 */
17137f4dd379Sjsg 	if (!READ_ONCE(vblank->enabled)) {
17147f4dd379Sjsg 		ret = -EINVAL;
17157f4dd379Sjsg 		goto err_unlock;
17167f4dd379Sjsg 	}
17177f4dd379Sjsg 
17187f4dd379Sjsg 	ret = drm_event_reserve_init_locked(dev, file_priv, &e->base,
17197f4dd379Sjsg 					    &e->event.base);
17207f4dd379Sjsg 
17217f4dd379Sjsg 	if (ret)
17227f4dd379Sjsg 		goto err_unlock;
17237f4dd379Sjsg 
17247f4dd379Sjsg 	seq = drm_vblank_count_and_time(dev, pipe, &now);
17257f4dd379Sjsg 
1726ad8b1aafSjsg 	drm_dbg_core(dev, "event on vblank count %llu, current %llu, crtc %u\n",
17277f4dd379Sjsg 		     req_seq, seq, pipe);
17287f4dd379Sjsg 
17297f4dd379Sjsg 	trace_drm_vblank_event_queued(file_priv, pipe, req_seq);
17307f4dd379Sjsg 
17317f4dd379Sjsg 	e->sequence = req_seq;
1732ad8b1aafSjsg 	if (drm_vblank_passed(seq, req_seq)) {
17337f4dd379Sjsg 		drm_vblank_put(dev, pipe);
17347f4dd379Sjsg 		send_vblank_event(dev, e, seq, now);
17357f4dd379Sjsg 		vblwait->reply.sequence = seq;
17367f4dd379Sjsg 	} else {
17377f4dd379Sjsg 		/* drm_handle_vblank_events will call drm_vblank_put */
17387f4dd379Sjsg 		list_add_tail(&e->base.link, &dev->vblank_event_list);
17397f4dd379Sjsg 		vblwait->reply.sequence = req_seq;
17407f4dd379Sjsg 	}
17417f4dd379Sjsg 
1742ad8b1aafSjsg 	spin_unlock_irq(&dev->event_lock);
17437f4dd379Sjsg 
17447f4dd379Sjsg 	return 0;
17457f4dd379Sjsg 
17467f4dd379Sjsg err_unlock:
1747ad8b1aafSjsg 	spin_unlock_irq(&dev->event_lock);
17487f4dd379Sjsg 	kfree(e);
17497f4dd379Sjsg err_put:
17507f4dd379Sjsg 	drm_vblank_put(dev, pipe);
17517f4dd379Sjsg 	return ret;
17527f4dd379Sjsg }
17537f4dd379Sjsg 
drm_wait_vblank_is_query(union drm_wait_vblank * vblwait)17547f4dd379Sjsg static bool drm_wait_vblank_is_query(union drm_wait_vblank *vblwait)
17557f4dd379Sjsg {
17567f4dd379Sjsg 	if (vblwait->request.sequence)
17577f4dd379Sjsg 		return false;
17587f4dd379Sjsg 
17597f4dd379Sjsg 	return _DRM_VBLANK_RELATIVE ==
17607f4dd379Sjsg 		(vblwait->request.type & (_DRM_VBLANK_TYPES_MASK |
17617f4dd379Sjsg 					  _DRM_VBLANK_EVENT |
17627f4dd379Sjsg 					  _DRM_VBLANK_NEXTONMISS));
17637f4dd379Sjsg }
17647f4dd379Sjsg 
17657f4dd379Sjsg /*
17667f4dd379Sjsg  * Widen a 32-bit param to 64-bits.
17677f4dd379Sjsg  *
17687f4dd379Sjsg  * \param narrow 32-bit value (missing upper 32 bits)
17697f4dd379Sjsg  * \param near 64-bit value that should be 'close' to near
17707f4dd379Sjsg  *
17717f4dd379Sjsg  * This function returns a 64-bit value using the lower 32-bits from
17727f4dd379Sjsg  * 'narrow' and constructing the upper 32-bits so that the result is
17737f4dd379Sjsg  * as close as possible to 'near'.
17747f4dd379Sjsg  */
17757f4dd379Sjsg 
widen_32_to_64(u32 narrow,u64 near)17767f4dd379Sjsg static u64 widen_32_to_64(u32 narrow, u64 near)
17777f4dd379Sjsg {
17787f4dd379Sjsg 	return near + (s32) (narrow - near);
17797f4dd379Sjsg }
17807f4dd379Sjsg 
drm_wait_vblank_reply(struct drm_device * dev,unsigned int pipe,struct drm_wait_vblank_reply * reply)17817f4dd379Sjsg static void drm_wait_vblank_reply(struct drm_device *dev, unsigned int pipe,
17827f4dd379Sjsg 				  struct drm_wait_vblank_reply *reply)
17837f4dd379Sjsg {
17847f4dd379Sjsg 	ktime_t now;
17857f4dd379Sjsg 	struct timespec64 ts;
17867f4dd379Sjsg 
17877f4dd379Sjsg 	/*
17887f4dd379Sjsg 	 * drm_wait_vblank_reply is a UAPI structure that uses 'long'
17897f4dd379Sjsg 	 * to store the seconds. This is safe as we always use monotonic
17907f4dd379Sjsg 	 * timestamps since linux-4.15.
17917f4dd379Sjsg 	 */
17927f4dd379Sjsg 	reply->sequence = drm_vblank_count_and_time(dev, pipe, &now);
17937f4dd379Sjsg 	ts = ktime_to_timespec64(now);
17947f4dd379Sjsg 	reply->tval_sec = (u32)ts.tv_sec;
17957f4dd379Sjsg 	reply->tval_usec = ts.tv_nsec / 1000;
17967f4dd379Sjsg }
17977f4dd379Sjsg 
drm_wait_vblank_supported(struct drm_device * dev)17985ca02815Sjsg static bool drm_wait_vblank_supported(struct drm_device *dev)
17995ca02815Sjsg {
18005ca02815Sjsg #if IS_ENABLED(CONFIG_DRM_LEGACY)
18015ca02815Sjsg 	if (unlikely(drm_core_check_feature(dev, DRIVER_LEGACY)))
18025ca02815Sjsg 		return dev->irq_enabled;
18035ca02815Sjsg #endif
18045ca02815Sjsg 	return drm_dev_has_vblank(dev);
18055ca02815Sjsg }
18065ca02815Sjsg 
drm_wait_vblank_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)18077f4dd379Sjsg int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
18087f4dd379Sjsg 			  struct drm_file *file_priv)
18097f4dd379Sjsg {
18107f4dd379Sjsg 	struct drm_crtc *crtc;
18117f4dd379Sjsg 	struct drm_vblank_crtc *vblank;
18127f4dd379Sjsg 	union drm_wait_vblank *vblwait = data;
18137f4dd379Sjsg 	int ret;
18147f4dd379Sjsg 	u64 req_seq, seq;
18157f4dd379Sjsg 	unsigned int pipe_index;
18167f4dd379Sjsg 	unsigned int flags, pipe, high_pipe;
18177f4dd379Sjsg 
18185ca02815Sjsg 	if (!drm_wait_vblank_supported(dev))
181964ce7eeaSjsg 		return -EOPNOTSUPP;
18207f4dd379Sjsg 
18217f4dd379Sjsg 	if (vblwait->request.type & _DRM_VBLANK_SIGNAL)
18227f4dd379Sjsg 		return -EINVAL;
18237f4dd379Sjsg 
18247f4dd379Sjsg 	if (vblwait->request.type &
18257f4dd379Sjsg 	    ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK |
18267f4dd379Sjsg 	      _DRM_VBLANK_HIGH_CRTC_MASK)) {
1827ad8b1aafSjsg 		drm_dbg_core(dev,
1828ad8b1aafSjsg 			     "Unsupported type value 0x%x, supported mask 0x%x\n",
18297f4dd379Sjsg 			     vblwait->request.type,
18307f4dd379Sjsg 			     (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK |
18317f4dd379Sjsg 			      _DRM_VBLANK_HIGH_CRTC_MASK));
18327f4dd379Sjsg 		return -EINVAL;
18337f4dd379Sjsg 	}
18347f4dd379Sjsg 
18357f4dd379Sjsg 	flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
18367f4dd379Sjsg 	high_pipe = (vblwait->request.type & _DRM_VBLANK_HIGH_CRTC_MASK);
18377f4dd379Sjsg 	if (high_pipe)
18387f4dd379Sjsg 		pipe_index = high_pipe >> _DRM_VBLANK_HIGH_CRTC_SHIFT;
18397f4dd379Sjsg 	else
18407f4dd379Sjsg 		pipe_index = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
18417f4dd379Sjsg 
18427f4dd379Sjsg 	/* Convert lease-relative crtc index into global crtc index */
18437f4dd379Sjsg 	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
18447f4dd379Sjsg 		pipe = 0;
18457f4dd379Sjsg 		drm_for_each_crtc(crtc, dev) {
18467f4dd379Sjsg 			if (drm_lease_held(file_priv, crtc->base.id)) {
18477f4dd379Sjsg 				if (pipe_index == 0)
18487f4dd379Sjsg 					break;
18497f4dd379Sjsg 				pipe_index--;
18507f4dd379Sjsg 			}
18517f4dd379Sjsg 			pipe++;
18527f4dd379Sjsg 		}
18537f4dd379Sjsg 	} else {
18547f4dd379Sjsg 		pipe = pipe_index;
18557f4dd379Sjsg 	}
18567f4dd379Sjsg 
18577f4dd379Sjsg 	if (pipe >= dev->num_crtcs)
18587f4dd379Sjsg 		return -EINVAL;
18597f4dd379Sjsg 
18607f4dd379Sjsg 	vblank = &dev->vblank[pipe];
18617f4dd379Sjsg 
18627f4dd379Sjsg 	/* If the counter is currently enabled and accurate, short-circuit
18637f4dd379Sjsg 	 * queries to return the cached timestamp of the last vblank.
18647f4dd379Sjsg 	 */
18657f4dd379Sjsg 	if (dev->vblank_disable_immediate &&
18667f4dd379Sjsg 	    drm_wait_vblank_is_query(vblwait) &&
18677f4dd379Sjsg 	    READ_ONCE(vblank->enabled)) {
18687f4dd379Sjsg 		drm_wait_vblank_reply(dev, pipe, &vblwait->reply);
18697f4dd379Sjsg 		return 0;
18707f4dd379Sjsg 	}
18717f4dd379Sjsg 
18727f4dd379Sjsg 	ret = drm_vblank_get(dev, pipe);
18737f4dd379Sjsg 	if (ret) {
1874ad8b1aafSjsg 		drm_dbg_core(dev,
1875ad8b1aafSjsg 			     "crtc %d failed to acquire vblank counter, %d\n",
1876ad8b1aafSjsg 			     pipe, ret);
18777f4dd379Sjsg 		return ret;
18787f4dd379Sjsg 	}
18797f4dd379Sjsg 	seq = drm_vblank_count(dev, pipe);
18807f4dd379Sjsg 
18817f4dd379Sjsg 	switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
18827f4dd379Sjsg 	case _DRM_VBLANK_RELATIVE:
18837f4dd379Sjsg 		req_seq = seq + vblwait->request.sequence;
18847f4dd379Sjsg 		vblwait->request.sequence = req_seq;
18857f4dd379Sjsg 		vblwait->request.type &= ~_DRM_VBLANK_RELATIVE;
18867f4dd379Sjsg 		break;
18877f4dd379Sjsg 	case _DRM_VBLANK_ABSOLUTE:
18887f4dd379Sjsg 		req_seq = widen_32_to_64(vblwait->request.sequence, seq);
18897f4dd379Sjsg 		break;
18907f4dd379Sjsg 	default:
18917f4dd379Sjsg 		ret = -EINVAL;
18927f4dd379Sjsg 		goto done;
18937f4dd379Sjsg 	}
18947f4dd379Sjsg 
18957f4dd379Sjsg 	if ((flags & _DRM_VBLANK_NEXTONMISS) &&
1896ad8b1aafSjsg 	    drm_vblank_passed(seq, req_seq)) {
18977f4dd379Sjsg 		req_seq = seq + 1;
18987f4dd379Sjsg 		vblwait->request.type &= ~_DRM_VBLANK_NEXTONMISS;
18997f4dd379Sjsg 		vblwait->request.sequence = req_seq;
19007f4dd379Sjsg 	}
19017f4dd379Sjsg 
19027f4dd379Sjsg 	if (flags & _DRM_VBLANK_EVENT) {
19037f4dd379Sjsg 		/* must hold on to the vblank ref until the event fires
19047f4dd379Sjsg 		 * drm_vblank_put will be called asynchronously
19057f4dd379Sjsg 		 */
19067f4dd379Sjsg 		return drm_queue_vblank_event(dev, pipe, req_seq, vblwait, file_priv);
19077f4dd379Sjsg 	}
19087f4dd379Sjsg 
19097f4dd379Sjsg 	if (req_seq != seq) {
1910c349dbc7Sjsg 		int wait;
1911c349dbc7Sjsg 
1912ad8b1aafSjsg 		drm_dbg_core(dev, "waiting on vblank count %llu, crtc %u\n",
19137f4dd379Sjsg 			     req_seq, pipe);
1914c349dbc7Sjsg 		wait = wait_event_interruptible_timeout(vblank->queue,
1915ad8b1aafSjsg 			drm_vblank_passed(drm_vblank_count(dev, pipe), req_seq) ||
1916c349dbc7Sjsg 				      !READ_ONCE(vblank->enabled),
1917c349dbc7Sjsg 			msecs_to_jiffies(3000));
1918c349dbc7Sjsg 
1919c349dbc7Sjsg 		switch (wait) {
1920c349dbc7Sjsg 		case 0:
1921c349dbc7Sjsg 			/* timeout */
1922c349dbc7Sjsg 			ret = -EBUSY;
1923c349dbc7Sjsg 			break;
1924c349dbc7Sjsg 		case -ERESTARTSYS:
1925c349dbc7Sjsg 			/* interrupted by signal */
1926c349dbc7Sjsg 			ret = -EINTR;
1927c349dbc7Sjsg 			break;
1928c349dbc7Sjsg 		default:
1929c349dbc7Sjsg 			ret = 0;
1930c349dbc7Sjsg 			break;
1931c349dbc7Sjsg 		}
19327f4dd379Sjsg 	}
19337f4dd379Sjsg 
19347f4dd379Sjsg 	if (ret != -EINTR) {
19357f4dd379Sjsg 		drm_wait_vblank_reply(dev, pipe, &vblwait->reply);
19367f4dd379Sjsg 
1937ad8b1aafSjsg 		drm_dbg_core(dev, "crtc %d returning %u to client\n",
19387f4dd379Sjsg 			     pipe, vblwait->reply.sequence);
19397f4dd379Sjsg 	} else {
1940ad8b1aafSjsg 		drm_dbg_core(dev, "crtc %d vblank wait interrupted by signal\n",
1941ad8b1aafSjsg 			     pipe);
19427f4dd379Sjsg 	}
19437f4dd379Sjsg 
19447f4dd379Sjsg done:
19457f4dd379Sjsg 	drm_vblank_put(dev, pipe);
19467f4dd379Sjsg 	return ret;
19477f4dd379Sjsg }
19487f4dd379Sjsg 
drm_handle_vblank_events(struct drm_device * dev,unsigned int pipe)19497f4dd379Sjsg static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe)
19507f4dd379Sjsg {
1951c349dbc7Sjsg 	struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
1952c349dbc7Sjsg 	bool high_prec = false;
19537f4dd379Sjsg 	struct drm_pending_vblank_event *e, *t;
19547f4dd379Sjsg 	ktime_t now;
19557f4dd379Sjsg 	u64 seq;
19567f4dd379Sjsg 
19577f4dd379Sjsg 	assert_spin_locked(&dev->event_lock);
19587f4dd379Sjsg 
19597f4dd379Sjsg 	seq = drm_vblank_count_and_time(dev, pipe, &now);
19607f4dd379Sjsg 
19617f4dd379Sjsg 	list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
19627f4dd379Sjsg 		if (e->pipe != pipe)
19637f4dd379Sjsg 			continue;
1964ad8b1aafSjsg 		if (!drm_vblank_passed(seq, e->sequence))
19657f4dd379Sjsg 			continue;
19667f4dd379Sjsg 
1967ad8b1aafSjsg 		drm_dbg_core(dev, "vblank event on %llu, current %llu\n",
19687f4dd379Sjsg 			     e->sequence, seq);
19697f4dd379Sjsg 
19707f4dd379Sjsg 		list_del(&e->base.link);
19717f4dd379Sjsg 		drm_vblank_put(dev, pipe);
19727f4dd379Sjsg 		send_vblank_event(dev, e, seq, now);
19737f4dd379Sjsg 	}
19747f4dd379Sjsg 
1975c349dbc7Sjsg 	if (crtc && crtc->funcs->get_vblank_timestamp)
1976c349dbc7Sjsg 		high_prec = true;
1977c349dbc7Sjsg 
1978c349dbc7Sjsg 	trace_drm_vblank_event(pipe, seq, now, high_prec);
19797f4dd379Sjsg }
19807f4dd379Sjsg 
19817f4dd379Sjsg /**
19827f4dd379Sjsg  * drm_handle_vblank - handle a vblank event
19837f4dd379Sjsg  * @dev: DRM device
19847f4dd379Sjsg  * @pipe: index of CRTC where this event occurred
19857f4dd379Sjsg  *
19867f4dd379Sjsg  * Drivers should call this routine in their vblank interrupt handlers to
19877f4dd379Sjsg  * update the vblank counter and send any signals that may be pending.
19887f4dd379Sjsg  *
19897f4dd379Sjsg  * This is the legacy version of drm_crtc_handle_vblank().
19907f4dd379Sjsg  */
drm_handle_vblank(struct drm_device * dev,unsigned int pipe)19917f4dd379Sjsg bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe)
19927f4dd379Sjsg {
19937f4dd379Sjsg 	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
19947f4dd379Sjsg 	unsigned long irqflags;
19957f4dd379Sjsg 	bool disable_irq;
19967f4dd379Sjsg 
1997ad8b1aafSjsg 	if (drm_WARN_ON_ONCE(dev, !drm_dev_has_vblank(dev)))
19987f4dd379Sjsg 		return false;
19997f4dd379Sjsg 
2000ad8b1aafSjsg 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
20017f4dd379Sjsg 		return false;
20027f4dd379Sjsg 
20037f4dd379Sjsg 	spin_lock_irqsave(&dev->event_lock, irqflags);
20047f4dd379Sjsg 
20057f4dd379Sjsg 	/* Need timestamp lock to prevent concurrent execution with
20067f4dd379Sjsg 	 * vblank enable/disable, as this would cause inconsistent
20077f4dd379Sjsg 	 * or corrupted timestamps and vblank counts.
20087f4dd379Sjsg 	 */
20097f4dd379Sjsg 	spin_lock(&dev->vblank_time_lock);
20107f4dd379Sjsg 
20117f4dd379Sjsg 	/* Vblank irq handling disabled. Nothing to do. */
20127f4dd379Sjsg 	if (!vblank->enabled) {
20137f4dd379Sjsg 		spin_unlock(&dev->vblank_time_lock);
20147f4dd379Sjsg 		spin_unlock_irqrestore(&dev->event_lock, irqflags);
20157f4dd379Sjsg 		return false;
20167f4dd379Sjsg 	}
20177f4dd379Sjsg 
20187f4dd379Sjsg 	drm_update_vblank_count(dev, pipe, true);
20197f4dd379Sjsg 
20207f4dd379Sjsg 	spin_unlock(&dev->vblank_time_lock);
20217f4dd379Sjsg 
20227f4dd379Sjsg 	wake_up(&vblank->queue);
20237f4dd379Sjsg 
20247f4dd379Sjsg 	/* With instant-off, we defer disabling the interrupt until after
20257f4dd379Sjsg 	 * we finish processing the following vblank after all events have
20267f4dd379Sjsg 	 * been signaled. The disable has to be last (after
20277f4dd379Sjsg 	 * drm_handle_vblank_events) so that the timestamp is always accurate.
20287f4dd379Sjsg 	 */
20297f4dd379Sjsg 	disable_irq = (dev->vblank_disable_immediate &&
20307f4dd379Sjsg 		       drm_vblank_offdelay > 0 &&
20317f4dd379Sjsg 		       !atomic_read(&vblank->refcount));
20327f4dd379Sjsg 
20337f4dd379Sjsg 	drm_handle_vblank_events(dev, pipe);
2034ad8b1aafSjsg 	drm_handle_vblank_works(vblank);
20357f4dd379Sjsg 
20367f4dd379Sjsg 	spin_unlock_irqrestore(&dev->event_lock, irqflags);
20377f4dd379Sjsg 
20387f4dd379Sjsg 	if (disable_irq)
2039bbf6708cSjsg 		vblank_disable_fn(vblank);
20407f4dd379Sjsg 
20417f4dd379Sjsg 	return true;
20427f4dd379Sjsg }
20437f4dd379Sjsg EXPORT_SYMBOL(drm_handle_vblank);
20447f4dd379Sjsg 
20457f4dd379Sjsg /**
20467f4dd379Sjsg  * drm_crtc_handle_vblank - handle a vblank event
20477f4dd379Sjsg  * @crtc: where this event occurred
20487f4dd379Sjsg  *
20497f4dd379Sjsg  * Drivers should call this routine in their vblank interrupt handlers to
20507f4dd379Sjsg  * update the vblank counter and send any signals that may be pending.
20517f4dd379Sjsg  *
20527f4dd379Sjsg  * This is the native KMS version of drm_handle_vblank().
20537f4dd379Sjsg  *
2054c349dbc7Sjsg  * Note that for a given vblank counter value drm_crtc_handle_vblank()
2055c349dbc7Sjsg  * and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time()
2056c349dbc7Sjsg  * provide a barrier: Any writes done before calling
2057c349dbc7Sjsg  * drm_crtc_handle_vblank() will be visible to callers of the later
20585ca02815Sjsg  * functions, if the vblank count is the same or a later one.
2059c349dbc7Sjsg  *
2060c349dbc7Sjsg  * See also &drm_vblank_crtc.count.
2061c349dbc7Sjsg  *
20627f4dd379Sjsg  * Returns:
20637f4dd379Sjsg  * True if the event was successfully handled, false on failure.
20647f4dd379Sjsg  */
drm_crtc_handle_vblank(struct drm_crtc * crtc)20657f4dd379Sjsg bool drm_crtc_handle_vblank(struct drm_crtc *crtc)
20667f4dd379Sjsg {
20677f4dd379Sjsg 	return drm_handle_vblank(crtc->dev, drm_crtc_index(crtc));
20687f4dd379Sjsg }
20697f4dd379Sjsg EXPORT_SYMBOL(drm_crtc_handle_vblank);
20707f4dd379Sjsg 
20717f4dd379Sjsg /*
20727f4dd379Sjsg  * Get crtc VBLANK count.
20737f4dd379Sjsg  *
20747f4dd379Sjsg  * \param dev DRM device
20755ca02815Sjsg  * \param data user argument, pointing to a drm_crtc_get_sequence structure.
20767f4dd379Sjsg  * \param file_priv drm file private for the user's open file descriptor
20777f4dd379Sjsg  */
20787f4dd379Sjsg 
drm_crtc_get_sequence_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)20797f4dd379Sjsg int drm_crtc_get_sequence_ioctl(struct drm_device *dev, void *data,
20807f4dd379Sjsg 				struct drm_file *file_priv)
20817f4dd379Sjsg {
20827f4dd379Sjsg 	struct drm_crtc *crtc;
20837f4dd379Sjsg 	struct drm_vblank_crtc *vblank;
20847f4dd379Sjsg 	int pipe;
20857f4dd379Sjsg 	struct drm_crtc_get_sequence *get_seq = data;
20867f4dd379Sjsg 	ktime_t now;
20877f4dd379Sjsg 	bool vblank_enabled;
20887f4dd379Sjsg 	int ret;
20897f4dd379Sjsg 
20907f4dd379Sjsg 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
2091c349dbc7Sjsg 		return -EOPNOTSUPP;
20927f4dd379Sjsg 
20935ca02815Sjsg 	if (!drm_dev_has_vblank(dev))
209464ce7eeaSjsg 		return -EOPNOTSUPP;
20957f4dd379Sjsg 
20967f4dd379Sjsg 	crtc = drm_crtc_find(dev, file_priv, get_seq->crtc_id);
20977f4dd379Sjsg 	if (!crtc)
20987f4dd379Sjsg 		return -ENOENT;
20997f4dd379Sjsg 
21007f4dd379Sjsg 	pipe = drm_crtc_index(crtc);
21017f4dd379Sjsg 
21027f4dd379Sjsg 	vblank = &dev->vblank[pipe];
21037f4dd379Sjsg 	vblank_enabled = dev->vblank_disable_immediate && READ_ONCE(vblank->enabled);
21047f4dd379Sjsg 
21057f4dd379Sjsg 	if (!vblank_enabled) {
21067f4dd379Sjsg 		ret = drm_crtc_vblank_get(crtc);
21077f4dd379Sjsg 		if (ret) {
2108ad8b1aafSjsg 			drm_dbg_core(dev,
2109ad8b1aafSjsg 				     "crtc %d failed to acquire vblank counter, %d\n",
2110ad8b1aafSjsg 				     pipe, ret);
21117f4dd379Sjsg 			return ret;
21127f4dd379Sjsg 		}
21137f4dd379Sjsg 	}
21147f4dd379Sjsg 	drm_modeset_lock(&crtc->mutex, NULL);
21157f4dd379Sjsg 	if (crtc->state)
21167f4dd379Sjsg 		get_seq->active = crtc->state->enable;
21177f4dd379Sjsg 	else
21187f4dd379Sjsg 		get_seq->active = crtc->enabled;
21197f4dd379Sjsg 	drm_modeset_unlock(&crtc->mutex);
21207f4dd379Sjsg 	get_seq->sequence = drm_vblank_count_and_time(dev, pipe, &now);
21217f4dd379Sjsg 	get_seq->sequence_ns = ktime_to_ns(now);
21227f4dd379Sjsg 	if (!vblank_enabled)
21237f4dd379Sjsg 		drm_crtc_vblank_put(crtc);
21247f4dd379Sjsg 	return 0;
21257f4dd379Sjsg }
21267f4dd379Sjsg 
21277f4dd379Sjsg /*
21287f4dd379Sjsg  * Queue a event for VBLANK sequence
21297f4dd379Sjsg  *
21307f4dd379Sjsg  * \param dev DRM device
21315ca02815Sjsg  * \param data user argument, pointing to a drm_crtc_queue_sequence structure.
21327f4dd379Sjsg  * \param file_priv drm file private for the user's open file descriptor
21337f4dd379Sjsg  */
21347f4dd379Sjsg 
drm_crtc_queue_sequence_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)21357f4dd379Sjsg int drm_crtc_queue_sequence_ioctl(struct drm_device *dev, void *data,
21367f4dd379Sjsg 				  struct drm_file *file_priv)
21377f4dd379Sjsg {
21387f4dd379Sjsg 	struct drm_crtc *crtc;
21397f4dd379Sjsg 	struct drm_vblank_crtc *vblank;
21407f4dd379Sjsg 	int pipe;
21417f4dd379Sjsg 	struct drm_crtc_queue_sequence *queue_seq = data;
21427f4dd379Sjsg 	ktime_t now;
21437f4dd379Sjsg 	struct drm_pending_vblank_event *e;
21447f4dd379Sjsg 	u32 flags;
21457f4dd379Sjsg 	u64 seq;
21467f4dd379Sjsg 	u64 req_seq;
21477f4dd379Sjsg 	int ret;
21487f4dd379Sjsg 
21497f4dd379Sjsg 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
2150c349dbc7Sjsg 		return -EOPNOTSUPP;
21517f4dd379Sjsg 
21525ca02815Sjsg 	if (!drm_dev_has_vblank(dev))
215364ce7eeaSjsg 		return -EOPNOTSUPP;
21547f4dd379Sjsg 
21557f4dd379Sjsg 	crtc = drm_crtc_find(dev, file_priv, queue_seq->crtc_id);
21567f4dd379Sjsg 	if (!crtc)
21577f4dd379Sjsg 		return -ENOENT;
21587f4dd379Sjsg 
21597f4dd379Sjsg 	flags = queue_seq->flags;
21607f4dd379Sjsg 	/* Check valid flag bits */
21617f4dd379Sjsg 	if (flags & ~(DRM_CRTC_SEQUENCE_RELATIVE|
21627f4dd379Sjsg 		      DRM_CRTC_SEQUENCE_NEXT_ON_MISS))
21637f4dd379Sjsg 		return -EINVAL;
21647f4dd379Sjsg 
21657f4dd379Sjsg 	pipe = drm_crtc_index(crtc);
21667f4dd379Sjsg 
21677f4dd379Sjsg 	vblank = &dev->vblank[pipe];
21687f4dd379Sjsg 
21697f4dd379Sjsg 	e = kzalloc(sizeof(*e), GFP_KERNEL);
21707f4dd379Sjsg 	if (e == NULL)
21717f4dd379Sjsg 		return -ENOMEM;
21727f4dd379Sjsg 
21737f4dd379Sjsg 	ret = drm_crtc_vblank_get(crtc);
21747f4dd379Sjsg 	if (ret) {
2175ad8b1aafSjsg 		drm_dbg_core(dev,
2176ad8b1aafSjsg 			     "crtc %d failed to acquire vblank counter, %d\n",
2177ad8b1aafSjsg 			     pipe, ret);
21787f4dd379Sjsg 		goto err_free;
21797f4dd379Sjsg 	}
21807f4dd379Sjsg 
21817f4dd379Sjsg 	seq = drm_vblank_count_and_time(dev, pipe, &now);
21827f4dd379Sjsg 	req_seq = queue_seq->sequence;
21837f4dd379Sjsg 
21847f4dd379Sjsg 	if (flags & DRM_CRTC_SEQUENCE_RELATIVE)
21857f4dd379Sjsg 		req_seq += seq;
21867f4dd379Sjsg 
2187ad8b1aafSjsg 	if ((flags & DRM_CRTC_SEQUENCE_NEXT_ON_MISS) && drm_vblank_passed(seq, req_seq))
21887f4dd379Sjsg 		req_seq = seq + 1;
21897f4dd379Sjsg 
21907f4dd379Sjsg 	e->pipe = pipe;
21917f4dd379Sjsg 	e->event.base.type = DRM_EVENT_CRTC_SEQUENCE;
21927f4dd379Sjsg 	e->event.base.length = sizeof(e->event.seq);
21937f4dd379Sjsg 	e->event.seq.user_data = queue_seq->user_data;
21947f4dd379Sjsg 
2195ad8b1aafSjsg 	spin_lock_irq(&dev->event_lock);
21967f4dd379Sjsg 
21977f4dd379Sjsg 	/*
21987f4dd379Sjsg 	 * drm_crtc_vblank_off() might have been called after we called
21997f4dd379Sjsg 	 * drm_crtc_vblank_get(). drm_crtc_vblank_off() holds event_lock around the
22007f4dd379Sjsg 	 * vblank disable, so no need for further locking.  The reference from
22017f4dd379Sjsg 	 * drm_crtc_vblank_get() protects against vblank disable from another source.
22027f4dd379Sjsg 	 */
22037f4dd379Sjsg 	if (!READ_ONCE(vblank->enabled)) {
22047f4dd379Sjsg 		ret = -EINVAL;
22057f4dd379Sjsg 		goto err_unlock;
22067f4dd379Sjsg 	}
22077f4dd379Sjsg 
22087f4dd379Sjsg 	ret = drm_event_reserve_init_locked(dev, file_priv, &e->base,
22097f4dd379Sjsg 					    &e->event.base);
22107f4dd379Sjsg 
22117f4dd379Sjsg 	if (ret)
22127f4dd379Sjsg 		goto err_unlock;
22137f4dd379Sjsg 
22147f4dd379Sjsg 	e->sequence = req_seq;
22157f4dd379Sjsg 
2216ad8b1aafSjsg 	if (drm_vblank_passed(seq, req_seq)) {
22177f4dd379Sjsg 		drm_crtc_vblank_put(crtc);
22187f4dd379Sjsg 		send_vblank_event(dev, e, seq, now);
22197f4dd379Sjsg 		queue_seq->sequence = seq;
22207f4dd379Sjsg 	} else {
22217f4dd379Sjsg 		/* drm_handle_vblank_events will call drm_vblank_put */
22227f4dd379Sjsg 		list_add_tail(&e->base.link, &dev->vblank_event_list);
22237f4dd379Sjsg 		queue_seq->sequence = req_seq;
22247f4dd379Sjsg 	}
22257f4dd379Sjsg 
2226ad8b1aafSjsg 	spin_unlock_irq(&dev->event_lock);
22277f4dd379Sjsg 	return 0;
22287f4dd379Sjsg 
22297f4dd379Sjsg err_unlock:
2230ad8b1aafSjsg 	spin_unlock_irq(&dev->event_lock);
22317f4dd379Sjsg 	drm_crtc_vblank_put(crtc);
22327f4dd379Sjsg err_free:
22337f4dd379Sjsg 	kfree(e);
22347f4dd379Sjsg 	return ret;
22357f4dd379Sjsg }
2236ad8b1aafSjsg 
2237