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