1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * drm_irq.c IRQ and vblank support
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * \author Rickard E. (Rik) Faith <faith@valinux.com>
5*4882a593Smuzhiyun * \author Gareth Hughes <gareth@valinux.com>
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Permission is hereby granted, free of charge, to any person obtaining a
8*4882a593Smuzhiyun * copy of this software and associated documentation files (the "Software"),
9*4882a593Smuzhiyun * to deal in the Software without restriction, including without limitation
10*4882a593Smuzhiyun * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11*4882a593Smuzhiyun * and/or sell copies of the Software, and to permit persons to whom the
12*4882a593Smuzhiyun * Software is furnished to do so, subject to the following conditions:
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * The above copyright notice and this permission notice (including the next
15*4882a593Smuzhiyun * paragraph) shall be included in all copies or substantial portions of the
16*4882a593Smuzhiyun * Software.
17*4882a593Smuzhiyun *
18*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19*4882a593Smuzhiyun * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20*4882a593Smuzhiyun * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21*4882a593Smuzhiyun * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22*4882a593Smuzhiyun * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23*4882a593Smuzhiyun * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24*4882a593Smuzhiyun * OTHER DEALINGS IN THE SOFTWARE.
25*4882a593Smuzhiyun */
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #include <linux/export.h>
28*4882a593Smuzhiyun #include <linux/kthread.h>
29*4882a593Smuzhiyun #include <linux/moduleparam.h>
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun #include <drm/drm_crtc.h>
32*4882a593Smuzhiyun #include <drm/drm_drv.h>
33*4882a593Smuzhiyun #include <drm/drm_framebuffer.h>
34*4882a593Smuzhiyun #include <drm/drm_managed.h>
35*4882a593Smuzhiyun #include <drm/drm_modeset_helper_vtables.h>
36*4882a593Smuzhiyun #include <drm/drm_print.h>
37*4882a593Smuzhiyun #include <drm/drm_vblank.h>
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #include "drm_internal.h"
40*4882a593Smuzhiyun #include "drm_trace.h"
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun /**
43*4882a593Smuzhiyun * DOC: vblank handling
44*4882a593Smuzhiyun *
45*4882a593Smuzhiyun * From the computer's perspective, every time the monitor displays
46*4882a593Smuzhiyun * a new frame the scanout engine has "scanned out" the display image
47*4882a593Smuzhiyun * from top to bottom, one row of pixels at a time. The current row
48*4882a593Smuzhiyun * of pixels is referred to as the current scanline.
49*4882a593Smuzhiyun *
50*4882a593Smuzhiyun * In addition to the display's visible area, there's usually a couple of
51*4882a593Smuzhiyun * extra scanlines which aren't actually displayed on the screen.
52*4882a593Smuzhiyun * These extra scanlines don't contain image data and are occasionally used
53*4882a593Smuzhiyun * for features like audio and infoframes. The region made up of these
54*4882a593Smuzhiyun * scanlines is referred to as the vertical blanking region, or vblank for
55*4882a593Smuzhiyun * short.
56*4882a593Smuzhiyun *
57*4882a593Smuzhiyun * For historical reference, the vertical blanking period was designed to
58*4882a593Smuzhiyun * give the electron gun (on CRTs) enough time to move back to the top of
59*4882a593Smuzhiyun * the screen to start scanning out the next frame. Similar for horizontal
60*4882a593Smuzhiyun * blanking periods. They were designed to give the electron gun enough
61*4882a593Smuzhiyun * time to move back to the other side of the screen to start scanning the
62*4882a593Smuzhiyun * next scanline.
63*4882a593Smuzhiyun *
64*4882a593Smuzhiyun * ::
65*4882a593Smuzhiyun *
66*4882a593Smuzhiyun *
67*4882a593Smuzhiyun * physical → ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽
68*4882a593Smuzhiyun * top of | |
69*4882a593Smuzhiyun * display | |
70*4882a593Smuzhiyun * | New frame |
71*4882a593Smuzhiyun * | |
72*4882a593Smuzhiyun * |↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓|
73*4882a593Smuzhiyun * |~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| ← Scanline,
74*4882a593Smuzhiyun * |↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓| updates the
75*4882a593Smuzhiyun * | | frame as it
76*4882a593Smuzhiyun * | | travels down
77*4882a593Smuzhiyun * | | ("sacn out")
78*4882a593Smuzhiyun * | Old frame |
79*4882a593Smuzhiyun * | |
80*4882a593Smuzhiyun * | |
81*4882a593Smuzhiyun * | |
82*4882a593Smuzhiyun * | | physical
83*4882a593Smuzhiyun * | | bottom of
84*4882a593Smuzhiyun * vertical |⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽| ← display
85*4882a593Smuzhiyun * blanking ┆xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx┆
86*4882a593Smuzhiyun * region → ┆xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx┆
87*4882a593Smuzhiyun * ┆xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx┆
88*4882a593Smuzhiyun * start of → ⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽⎽
89*4882a593Smuzhiyun * new frame
90*4882a593Smuzhiyun *
91*4882a593Smuzhiyun * "Physical top of display" is the reference point for the high-precision/
92*4882a593Smuzhiyun * corrected timestamp.
93*4882a593Smuzhiyun *
94*4882a593Smuzhiyun * On a lot of display hardware, programming needs to take effect during the
95*4882a593Smuzhiyun * vertical blanking period so that settings like gamma, the image buffer
96*4882a593Smuzhiyun * buffer to be scanned out, etc. can safely be changed without showing
97*4882a593Smuzhiyun * any visual artifacts on the screen. In some unforgiving hardware, some of
98*4882a593Smuzhiyun * this programming has to both start and end in the same vblank. To help
99*4882a593Smuzhiyun * with the timing of the hardware programming, an interrupt is usually
100*4882a593Smuzhiyun * available to notify the driver when it can start the updating of registers.
101*4882a593Smuzhiyun * The interrupt is in this context named the vblank interrupt.
102*4882a593Smuzhiyun *
103*4882a593Smuzhiyun * The vblank interrupt may be fired at different points depending on the
104*4882a593Smuzhiyun * hardware. Some hardware implementations will fire the interrupt when the
105*4882a593Smuzhiyun * new frame start, other implementations will fire the interrupt at different
106*4882a593Smuzhiyun * points in time.
107*4882a593Smuzhiyun *
108*4882a593Smuzhiyun * Vertical blanking plays a major role in graphics rendering. To achieve
109*4882a593Smuzhiyun * tear-free display, users must synchronize page flips and/or rendering to
110*4882a593Smuzhiyun * vertical blanking. The DRM API offers ioctls to perform page flips
111*4882a593Smuzhiyun * synchronized to vertical blanking and wait for vertical blanking.
112*4882a593Smuzhiyun *
113*4882a593Smuzhiyun * The DRM core handles most of the vertical blanking management logic, which
114*4882a593Smuzhiyun * involves filtering out spurious interrupts, keeping race-free blanking
115*4882a593Smuzhiyun * counters, coping with counter wrap-around and resets and keeping use counts.
116*4882a593Smuzhiyun * It relies on the driver to generate vertical blanking interrupts and
117*4882a593Smuzhiyun * optionally provide a hardware vertical blanking counter.
118*4882a593Smuzhiyun *
119*4882a593Smuzhiyun * Drivers must initialize the vertical blanking handling core with a call to
120*4882a593Smuzhiyun * drm_vblank_init(). Minimally, a driver needs to implement
121*4882a593Smuzhiyun * &drm_crtc_funcs.enable_vblank and &drm_crtc_funcs.disable_vblank plus call
122*4882a593Smuzhiyun * drm_crtc_handle_vblank() in its vblank interrupt handler for working vblank
123*4882a593Smuzhiyun * support.
124*4882a593Smuzhiyun *
125*4882a593Smuzhiyun * Vertical blanking interrupts can be enabled by the DRM core or by drivers
126*4882a593Smuzhiyun * themselves (for instance to handle page flipping operations). The DRM core
127*4882a593Smuzhiyun * maintains a vertical blanking use count to ensure that the interrupts are not
128*4882a593Smuzhiyun * disabled while a user still needs them. To increment the use count, drivers
129*4882a593Smuzhiyun * call drm_crtc_vblank_get() and release the vblank reference again with
130*4882a593Smuzhiyun * drm_crtc_vblank_put(). In between these two calls vblank interrupts are
131*4882a593Smuzhiyun * guaranteed to be enabled.
132*4882a593Smuzhiyun *
133*4882a593Smuzhiyun * On many hardware disabling the vblank interrupt cannot be done in a race-free
134*4882a593Smuzhiyun * manner, see &drm_driver.vblank_disable_immediate and
135*4882a593Smuzhiyun * &drm_driver.max_vblank_count. In that case the vblank core only disables the
136*4882a593Smuzhiyun * vblanks after a timer has expired, which can be configured through the
137*4882a593Smuzhiyun * ``vblankoffdelay`` module parameter.
138*4882a593Smuzhiyun *
139*4882a593Smuzhiyun * Drivers for hardware without support for vertical-blanking interrupts
140*4882a593Smuzhiyun * must not call drm_vblank_init(). For such drivers, atomic helpers will
141*4882a593Smuzhiyun * automatically generate fake vblank events as part of the display update.
142*4882a593Smuzhiyun * This functionality also can be controlled by the driver by enabling and
143*4882a593Smuzhiyun * disabling struct drm_crtc_state.no_vblank.
144*4882a593Smuzhiyun */
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun /* Retry timestamp calculation up to 3 times to satisfy
147*4882a593Smuzhiyun * drm_timestamp_precision before giving up.
148*4882a593Smuzhiyun */
149*4882a593Smuzhiyun #define DRM_TIMESTAMP_MAXRETRIES 3
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun /* Threshold in nanoseconds for detection of redundant
152*4882a593Smuzhiyun * vblank irq in drm_handle_vblank(). 1 msec should be ok.
153*4882a593Smuzhiyun */
154*4882a593Smuzhiyun #define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun static bool
157*4882a593Smuzhiyun drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
158*4882a593Smuzhiyun ktime_t *tvblank, bool in_vblank_irq);
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun static unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun static int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
165*4882a593Smuzhiyun module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600);
166*4882a593Smuzhiyun MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs] (0: never disable, <0: disable immediately)");
167*4882a593Smuzhiyun MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
168*4882a593Smuzhiyun
store_vblank(struct drm_device * dev,unsigned int pipe,u32 vblank_count_inc,ktime_t t_vblank,u32 last)169*4882a593Smuzhiyun static void store_vblank(struct drm_device *dev, unsigned int pipe,
170*4882a593Smuzhiyun u32 vblank_count_inc,
171*4882a593Smuzhiyun ktime_t t_vblank, u32 last)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun assert_spin_locked(&dev->vblank_time_lock);
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun vblank->last = last;
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun write_seqlock(&vblank->seqlock);
180*4882a593Smuzhiyun vblank->time = t_vblank;
181*4882a593Smuzhiyun atomic64_add(vblank_count_inc, &vblank->count);
182*4882a593Smuzhiyun write_sequnlock(&vblank->seqlock);
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
drm_max_vblank_count(struct drm_device * dev,unsigned int pipe)185*4882a593Smuzhiyun static u32 drm_max_vblank_count(struct drm_device *dev, unsigned int pipe)
186*4882a593Smuzhiyun {
187*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun return vblank->max_vblank_count ?: dev->max_vblank_count;
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun /*
193*4882a593Smuzhiyun * "No hw counter" fallback implementation of .get_vblank_counter() hook,
194*4882a593Smuzhiyun * if there is no useable hardware frame counter available.
195*4882a593Smuzhiyun */
drm_vblank_no_hw_counter(struct drm_device * dev,unsigned int pipe)196*4882a593Smuzhiyun static u32 drm_vblank_no_hw_counter(struct drm_device *dev, unsigned int pipe)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun drm_WARN_ON_ONCE(dev, drm_max_vblank_count(dev, pipe) != 0);
199*4882a593Smuzhiyun return 0;
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun
__get_vblank_counter(struct drm_device * dev,unsigned int pipe)202*4882a593Smuzhiyun static u32 __get_vblank_counter(struct drm_device *dev, unsigned int pipe)
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun if (drm_core_check_feature(dev, DRIVER_MODESET)) {
205*4882a593Smuzhiyun struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun if (drm_WARN_ON(dev, !crtc))
208*4882a593Smuzhiyun return 0;
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun if (crtc->funcs->get_vblank_counter)
211*4882a593Smuzhiyun return crtc->funcs->get_vblank_counter(crtc);
212*4882a593Smuzhiyun } else if (dev->driver->get_vblank_counter) {
213*4882a593Smuzhiyun return dev->driver->get_vblank_counter(dev, pipe);
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun return drm_vblank_no_hw_counter(dev, pipe);
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun /*
220*4882a593Smuzhiyun * Reset the stored timestamp for the current vblank count to correspond
221*4882a593Smuzhiyun * to the last vblank occurred.
222*4882a593Smuzhiyun *
223*4882a593Smuzhiyun * Only to be called from drm_crtc_vblank_on().
224*4882a593Smuzhiyun *
225*4882a593Smuzhiyun * Note: caller must hold &drm_device.vbl_lock since this reads & writes
226*4882a593Smuzhiyun * device vblank fields.
227*4882a593Smuzhiyun */
drm_reset_vblank_timestamp(struct drm_device * dev,unsigned int pipe)228*4882a593Smuzhiyun static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun u32 cur_vblank;
231*4882a593Smuzhiyun bool rc;
232*4882a593Smuzhiyun ktime_t t_vblank;
233*4882a593Smuzhiyun int count = DRM_TIMESTAMP_MAXRETRIES;
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun spin_lock(&dev->vblank_time_lock);
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun /*
238*4882a593Smuzhiyun * sample the current counter to avoid random jumps
239*4882a593Smuzhiyun * when drm_vblank_enable() applies the diff
240*4882a593Smuzhiyun */
241*4882a593Smuzhiyun do {
242*4882a593Smuzhiyun cur_vblank = __get_vblank_counter(dev, pipe);
243*4882a593Smuzhiyun rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, false);
244*4882a593Smuzhiyun } while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun /*
247*4882a593Smuzhiyun * Only reinitialize corresponding vblank timestamp if high-precision query
248*4882a593Smuzhiyun * available and didn't fail. Otherwise reinitialize delayed at next vblank
249*4882a593Smuzhiyun * interrupt and assign 0 for now, to mark the vblanktimestamp as invalid.
250*4882a593Smuzhiyun */
251*4882a593Smuzhiyun if (!rc)
252*4882a593Smuzhiyun t_vblank = 0;
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun /*
255*4882a593Smuzhiyun * +1 to make sure user will never see the same
256*4882a593Smuzhiyun * vblank counter value before and after a modeset
257*4882a593Smuzhiyun */
258*4882a593Smuzhiyun store_vblank(dev, pipe, 1, t_vblank, cur_vblank);
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun spin_unlock(&dev->vblank_time_lock);
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun /*
264*4882a593Smuzhiyun * Call back into the driver to update the appropriate vblank counter
265*4882a593Smuzhiyun * (specified by @pipe). Deal with wraparound, if it occurred, and
266*4882a593Smuzhiyun * update the last read value so we can deal with wraparound on the next
267*4882a593Smuzhiyun * call if necessary.
268*4882a593Smuzhiyun *
269*4882a593Smuzhiyun * Only necessary when going from off->on, to account for frames we
270*4882a593Smuzhiyun * didn't get an interrupt for.
271*4882a593Smuzhiyun *
272*4882a593Smuzhiyun * Note: caller must hold &drm_device.vbl_lock since this reads & writes
273*4882a593Smuzhiyun * device vblank fields.
274*4882a593Smuzhiyun */
drm_update_vblank_count(struct drm_device * dev,unsigned int pipe,bool in_vblank_irq)275*4882a593Smuzhiyun static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
276*4882a593Smuzhiyun bool in_vblank_irq)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
279*4882a593Smuzhiyun u32 cur_vblank, diff;
280*4882a593Smuzhiyun bool rc;
281*4882a593Smuzhiyun ktime_t t_vblank;
282*4882a593Smuzhiyun int count = DRM_TIMESTAMP_MAXRETRIES;
283*4882a593Smuzhiyun int framedur_ns = vblank->framedur_ns;
284*4882a593Smuzhiyun u32 max_vblank_count = drm_max_vblank_count(dev, pipe);
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun /*
287*4882a593Smuzhiyun * Interrupts were disabled prior to this call, so deal with counter
288*4882a593Smuzhiyun * wrap if needed.
289*4882a593Smuzhiyun * NOTE! It's possible we lost a full dev->max_vblank_count + 1 events
290*4882a593Smuzhiyun * here if the register is small or we had vblank interrupts off for
291*4882a593Smuzhiyun * a long time.
292*4882a593Smuzhiyun *
293*4882a593Smuzhiyun * We repeat the hardware vblank counter & timestamp query until
294*4882a593Smuzhiyun * we get consistent results. This to prevent races between gpu
295*4882a593Smuzhiyun * updating its hardware counter while we are retrieving the
296*4882a593Smuzhiyun * corresponding vblank timestamp.
297*4882a593Smuzhiyun */
298*4882a593Smuzhiyun do {
299*4882a593Smuzhiyun cur_vblank = __get_vblank_counter(dev, pipe);
300*4882a593Smuzhiyun rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, in_vblank_irq);
301*4882a593Smuzhiyun } while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun if (max_vblank_count) {
304*4882a593Smuzhiyun /* trust the hw counter when it's around */
305*4882a593Smuzhiyun diff = (cur_vblank - vblank->last) & max_vblank_count;
306*4882a593Smuzhiyun } else if (rc && framedur_ns) {
307*4882a593Smuzhiyun u64 diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time));
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun /*
310*4882a593Smuzhiyun * Figure out how many vblanks we've missed based
311*4882a593Smuzhiyun * on the difference in the timestamps and the
312*4882a593Smuzhiyun * frame/field duration.
313*4882a593Smuzhiyun */
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun drm_dbg_vbl(dev, "crtc %u: Calculating number of vblanks."
316*4882a593Smuzhiyun " diff_ns = %lld, framedur_ns = %d)\n",
317*4882a593Smuzhiyun pipe, (long long)diff_ns, framedur_ns);
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns);
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun if (diff == 0 && in_vblank_irq)
322*4882a593Smuzhiyun drm_dbg_vbl(dev, "crtc %u: Redundant vblirq ignored\n",
323*4882a593Smuzhiyun pipe);
324*4882a593Smuzhiyun } else {
325*4882a593Smuzhiyun /* some kind of default for drivers w/o accurate vbl timestamping */
326*4882a593Smuzhiyun diff = in_vblank_irq ? 1 : 0;
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun /*
330*4882a593Smuzhiyun * Within a drm_vblank_pre_modeset - drm_vblank_post_modeset
331*4882a593Smuzhiyun * interval? If so then vblank irqs keep running and it will likely
332*4882a593Smuzhiyun * happen that the hardware vblank counter is not trustworthy as it
333*4882a593Smuzhiyun * might reset at some point in that interval and vblank timestamps
334*4882a593Smuzhiyun * are not trustworthy either in that interval. Iow. this can result
335*4882a593Smuzhiyun * in a bogus diff >> 1 which must be avoided as it would cause
336*4882a593Smuzhiyun * random large forward jumps of the software vblank counter.
337*4882a593Smuzhiyun */
338*4882a593Smuzhiyun if (diff > 1 && (vblank->inmodeset & 0x2)) {
339*4882a593Smuzhiyun drm_dbg_vbl(dev,
340*4882a593Smuzhiyun "clamping vblank bump to 1 on crtc %u: diffr=%u"
341*4882a593Smuzhiyun " due to pre-modeset.\n", pipe, diff);
342*4882a593Smuzhiyun diff = 1;
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun drm_dbg_vbl(dev, "updating vblank count on crtc %u:"
346*4882a593Smuzhiyun " current=%llu, diff=%u, hw=%u hw_last=%u\n",
347*4882a593Smuzhiyun pipe, (unsigned long long)atomic64_read(&vblank->count),
348*4882a593Smuzhiyun diff, cur_vblank, vblank->last);
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun if (diff == 0) {
351*4882a593Smuzhiyun drm_WARN_ON_ONCE(dev, cur_vblank != vblank->last);
352*4882a593Smuzhiyun return;
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun /*
356*4882a593Smuzhiyun * Only reinitialize corresponding vblank timestamp if high-precision query
357*4882a593Smuzhiyun * available and didn't fail, or we were called from the vblank interrupt.
358*4882a593Smuzhiyun * Otherwise reinitialize delayed at next vblank interrupt and assign 0
359*4882a593Smuzhiyun * for now, to mark the vblanktimestamp as invalid.
360*4882a593Smuzhiyun */
361*4882a593Smuzhiyun if (!rc && !in_vblank_irq)
362*4882a593Smuzhiyun t_vblank = 0;
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun store_vblank(dev, pipe, diff, t_vblank, cur_vblank);
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun
drm_vblank_count(struct drm_device * dev,unsigned int pipe)367*4882a593Smuzhiyun u64 drm_vblank_count(struct drm_device *dev, unsigned int pipe)
368*4882a593Smuzhiyun {
369*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
370*4882a593Smuzhiyun u64 count;
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
373*4882a593Smuzhiyun return 0;
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun count = atomic64_read(&vblank->count);
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun /*
378*4882a593Smuzhiyun * This read barrier corresponds to the implicit write barrier of the
379*4882a593Smuzhiyun * write seqlock in store_vblank(). Note that this is the only place
380*4882a593Smuzhiyun * where we need an explicit barrier, since all other access goes
381*4882a593Smuzhiyun * through drm_vblank_count_and_time(), which already has the required
382*4882a593Smuzhiyun * read barrier curtesy of the read seqlock.
383*4882a593Smuzhiyun */
384*4882a593Smuzhiyun smp_rmb();
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun return count;
387*4882a593Smuzhiyun }
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun /**
390*4882a593Smuzhiyun * drm_crtc_accurate_vblank_count - retrieve the master vblank counter
391*4882a593Smuzhiyun * @crtc: which counter to retrieve
392*4882a593Smuzhiyun *
393*4882a593Smuzhiyun * This function is similar to drm_crtc_vblank_count() but this function
394*4882a593Smuzhiyun * interpolates to handle a race with vblank interrupts using the high precision
395*4882a593Smuzhiyun * timestamping support.
396*4882a593Smuzhiyun *
397*4882a593Smuzhiyun * This is mostly useful for hardware that can obtain the scanout position, but
398*4882a593Smuzhiyun * doesn't have a hardware frame counter.
399*4882a593Smuzhiyun */
drm_crtc_accurate_vblank_count(struct drm_crtc * crtc)400*4882a593Smuzhiyun u64 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc)
401*4882a593Smuzhiyun {
402*4882a593Smuzhiyun struct drm_device *dev = crtc->dev;
403*4882a593Smuzhiyun unsigned int pipe = drm_crtc_index(crtc);
404*4882a593Smuzhiyun u64 vblank;
405*4882a593Smuzhiyun unsigned long flags;
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun drm_WARN_ONCE(dev, drm_debug_enabled(DRM_UT_VBL) &&
408*4882a593Smuzhiyun !crtc->funcs->get_vblank_timestamp,
409*4882a593Smuzhiyun "This function requires support for accurate vblank timestamps.");
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun spin_lock_irqsave(&dev->vblank_time_lock, flags);
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun drm_update_vblank_count(dev, pipe, false);
414*4882a593Smuzhiyun vblank = drm_vblank_count(dev, pipe);
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->vblank_time_lock, flags);
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun return vblank;
419*4882a593Smuzhiyun }
420*4882a593Smuzhiyun EXPORT_SYMBOL(drm_crtc_accurate_vblank_count);
421*4882a593Smuzhiyun
__disable_vblank(struct drm_device * dev,unsigned int pipe)422*4882a593Smuzhiyun static void __disable_vblank(struct drm_device *dev, unsigned int pipe)
423*4882a593Smuzhiyun {
424*4882a593Smuzhiyun if (drm_core_check_feature(dev, DRIVER_MODESET)) {
425*4882a593Smuzhiyun struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun if (drm_WARN_ON(dev, !crtc))
428*4882a593Smuzhiyun return;
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun if (crtc->funcs->disable_vblank)
431*4882a593Smuzhiyun crtc->funcs->disable_vblank(crtc);
432*4882a593Smuzhiyun } else {
433*4882a593Smuzhiyun dev->driver->disable_vblank(dev, pipe);
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun /*
438*4882a593Smuzhiyun * Disable vblank irq's on crtc, make sure that last vblank count
439*4882a593Smuzhiyun * of hardware and corresponding consistent software vblank counter
440*4882a593Smuzhiyun * are preserved, even if there are any spurious vblank irq's after
441*4882a593Smuzhiyun * disable.
442*4882a593Smuzhiyun */
drm_vblank_disable_and_save(struct drm_device * dev,unsigned int pipe)443*4882a593Smuzhiyun void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe)
444*4882a593Smuzhiyun {
445*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
446*4882a593Smuzhiyun unsigned long irqflags;
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun assert_spin_locked(&dev->vbl_lock);
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun /* Prevent vblank irq processing while disabling vblank irqs,
451*4882a593Smuzhiyun * so no updates of timestamps or count can happen after we've
452*4882a593Smuzhiyun * disabled. Needed to prevent races in case of delayed irq's.
453*4882a593Smuzhiyun */
454*4882a593Smuzhiyun spin_lock_irqsave(&dev->vblank_time_lock, irqflags);
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun /*
457*4882a593Smuzhiyun * Update vblank count and disable vblank interrupts only if the
458*4882a593Smuzhiyun * interrupts were enabled. This avoids calling the ->disable_vblank()
459*4882a593Smuzhiyun * operation in atomic context with the hardware potentially runtime
460*4882a593Smuzhiyun * suspended.
461*4882a593Smuzhiyun */
462*4882a593Smuzhiyun if (!vblank->enabled)
463*4882a593Smuzhiyun goto out;
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun /*
466*4882a593Smuzhiyun * Update the count and timestamp to maintain the
467*4882a593Smuzhiyun * appearance that the counter has been ticking all along until
468*4882a593Smuzhiyun * this time. This makes the count account for the entire time
469*4882a593Smuzhiyun * between drm_crtc_vblank_on() and drm_crtc_vblank_off().
470*4882a593Smuzhiyun */
471*4882a593Smuzhiyun drm_update_vblank_count(dev, pipe, false);
472*4882a593Smuzhiyun __disable_vblank(dev, pipe);
473*4882a593Smuzhiyun vblank->enabled = false;
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun out:
476*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
477*4882a593Smuzhiyun }
478*4882a593Smuzhiyun
vblank_disable_fn(struct timer_list * t)479*4882a593Smuzhiyun static void vblank_disable_fn(struct timer_list *t)
480*4882a593Smuzhiyun {
481*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = from_timer(vblank, t, disable_timer);
482*4882a593Smuzhiyun struct drm_device *dev = vblank->dev;
483*4882a593Smuzhiyun unsigned int pipe = vblank->pipe;
484*4882a593Smuzhiyun unsigned long irqflags;
485*4882a593Smuzhiyun
486*4882a593Smuzhiyun spin_lock_irqsave(&dev->vbl_lock, irqflags);
487*4882a593Smuzhiyun if (atomic_read(&vblank->refcount) == 0 && vblank->enabled) {
488*4882a593Smuzhiyun drm_dbg_core(dev, "disabling vblank on crtc %u\n", pipe);
489*4882a593Smuzhiyun drm_vblank_disable_and_save(dev, pipe);
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun
drm_vblank_init_release(struct drm_device * dev,void * ptr)494*4882a593Smuzhiyun static void drm_vblank_init_release(struct drm_device *dev, void *ptr)
495*4882a593Smuzhiyun {
496*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = ptr;
497*4882a593Smuzhiyun
498*4882a593Smuzhiyun drm_WARN_ON(dev, READ_ONCE(vblank->enabled) &&
499*4882a593Smuzhiyun drm_core_check_feature(dev, DRIVER_MODESET));
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun drm_vblank_destroy_worker(vblank);
502*4882a593Smuzhiyun del_timer_sync(&vblank->disable_timer);
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun /**
506*4882a593Smuzhiyun * drm_vblank_init - initialize vblank support
507*4882a593Smuzhiyun * @dev: DRM device
508*4882a593Smuzhiyun * @num_crtcs: number of CRTCs supported by @dev
509*4882a593Smuzhiyun *
510*4882a593Smuzhiyun * This function initializes vblank support for @num_crtcs display pipelines.
511*4882a593Smuzhiyun * Cleanup is handled automatically through a cleanup function added with
512*4882a593Smuzhiyun * drmm_add_action_or_reset().
513*4882a593Smuzhiyun *
514*4882a593Smuzhiyun * Returns:
515*4882a593Smuzhiyun * Zero on success or a negative error code on failure.
516*4882a593Smuzhiyun */
drm_vblank_init(struct drm_device * dev,unsigned int num_crtcs)517*4882a593Smuzhiyun int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs)
518*4882a593Smuzhiyun {
519*4882a593Smuzhiyun int ret;
520*4882a593Smuzhiyun unsigned int i;
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun spin_lock_init(&dev->vbl_lock);
523*4882a593Smuzhiyun spin_lock_init(&dev->vblank_time_lock);
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun dev->vblank = drmm_kcalloc(dev, num_crtcs, sizeof(*dev->vblank), GFP_KERNEL);
526*4882a593Smuzhiyun if (!dev->vblank)
527*4882a593Smuzhiyun return -ENOMEM;
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun dev->num_crtcs = num_crtcs;
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun for (i = 0; i < num_crtcs; i++) {
532*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[i];
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun vblank->dev = dev;
535*4882a593Smuzhiyun vblank->pipe = i;
536*4882a593Smuzhiyun init_waitqueue_head(&vblank->queue);
537*4882a593Smuzhiyun timer_setup(&vblank->disable_timer, vblank_disable_fn, 0);
538*4882a593Smuzhiyun seqlock_init(&vblank->seqlock);
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun ret = drmm_add_action_or_reset(dev, drm_vblank_init_release,
541*4882a593Smuzhiyun vblank);
542*4882a593Smuzhiyun if (ret)
543*4882a593Smuzhiyun return ret;
544*4882a593Smuzhiyun
545*4882a593Smuzhiyun ret = drm_vblank_worker_init(vblank);
546*4882a593Smuzhiyun if (ret)
547*4882a593Smuzhiyun return ret;
548*4882a593Smuzhiyun }
549*4882a593Smuzhiyun
550*4882a593Smuzhiyun return 0;
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun EXPORT_SYMBOL(drm_vblank_init);
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun /**
555*4882a593Smuzhiyun * drm_dev_has_vblank - test if vblanking has been initialized for
556*4882a593Smuzhiyun * a device
557*4882a593Smuzhiyun * @dev: the device
558*4882a593Smuzhiyun *
559*4882a593Smuzhiyun * Drivers may call this function to test if vblank support is
560*4882a593Smuzhiyun * initialized for a device. For most hardware this means that vblanking
561*4882a593Smuzhiyun * can also be enabled.
562*4882a593Smuzhiyun *
563*4882a593Smuzhiyun * Atomic helpers use this function to initialize
564*4882a593Smuzhiyun * &drm_crtc_state.no_vblank. See also drm_atomic_helper_check_modeset().
565*4882a593Smuzhiyun *
566*4882a593Smuzhiyun * Returns:
567*4882a593Smuzhiyun * True if vblanking has been initialized for the given device, false
568*4882a593Smuzhiyun * otherwise.
569*4882a593Smuzhiyun */
drm_dev_has_vblank(const struct drm_device * dev)570*4882a593Smuzhiyun bool drm_dev_has_vblank(const struct drm_device *dev)
571*4882a593Smuzhiyun {
572*4882a593Smuzhiyun return dev->num_crtcs != 0;
573*4882a593Smuzhiyun }
574*4882a593Smuzhiyun EXPORT_SYMBOL(drm_dev_has_vblank);
575*4882a593Smuzhiyun
576*4882a593Smuzhiyun /**
577*4882a593Smuzhiyun * drm_crtc_vblank_waitqueue - get vblank waitqueue for the CRTC
578*4882a593Smuzhiyun * @crtc: which CRTC's vblank waitqueue to retrieve
579*4882a593Smuzhiyun *
580*4882a593Smuzhiyun * This function returns a pointer to the vblank waitqueue for the CRTC.
581*4882a593Smuzhiyun * Drivers can use this to implement vblank waits using wait_event() and related
582*4882a593Smuzhiyun * functions.
583*4882a593Smuzhiyun */
drm_crtc_vblank_waitqueue(struct drm_crtc * crtc)584*4882a593Smuzhiyun wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc)
585*4882a593Smuzhiyun {
586*4882a593Smuzhiyun return &crtc->dev->vblank[drm_crtc_index(crtc)].queue;
587*4882a593Smuzhiyun }
588*4882a593Smuzhiyun EXPORT_SYMBOL(drm_crtc_vblank_waitqueue);
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun /**
592*4882a593Smuzhiyun * drm_calc_timestamping_constants - calculate vblank timestamp constants
593*4882a593Smuzhiyun * @crtc: drm_crtc whose timestamp constants should be updated.
594*4882a593Smuzhiyun * @mode: display mode containing the scanout timings
595*4882a593Smuzhiyun *
596*4882a593Smuzhiyun * Calculate and store various constants which are later needed by vblank and
597*4882a593Smuzhiyun * swap-completion timestamping, e.g, by
598*4882a593Smuzhiyun * drm_crtc_vblank_helper_get_vblank_timestamp(). They are derived from
599*4882a593Smuzhiyun * CRTC's true scanout timing, so they take things like panel scaling or
600*4882a593Smuzhiyun * other adjustments into account.
601*4882a593Smuzhiyun */
drm_calc_timestamping_constants(struct drm_crtc * crtc,const struct drm_display_mode * mode)602*4882a593Smuzhiyun void drm_calc_timestamping_constants(struct drm_crtc *crtc,
603*4882a593Smuzhiyun const struct drm_display_mode *mode)
604*4882a593Smuzhiyun {
605*4882a593Smuzhiyun struct drm_device *dev = crtc->dev;
606*4882a593Smuzhiyun unsigned int pipe = drm_crtc_index(crtc);
607*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
608*4882a593Smuzhiyun int linedur_ns = 0, framedur_ns = 0;
609*4882a593Smuzhiyun int dotclock = mode->crtc_clock;
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun if (!drm_dev_has_vblank(dev))
612*4882a593Smuzhiyun return;
613*4882a593Smuzhiyun
614*4882a593Smuzhiyun if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
615*4882a593Smuzhiyun return;
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun /* Valid dotclock? */
618*4882a593Smuzhiyun if (dotclock > 0) {
619*4882a593Smuzhiyun int frame_size = mode->crtc_htotal * mode->crtc_vtotal;
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun /*
622*4882a593Smuzhiyun * Convert scanline length in pixels and video
623*4882a593Smuzhiyun * dot clock to line duration and frame duration
624*4882a593Smuzhiyun * in nanoseconds:
625*4882a593Smuzhiyun */
626*4882a593Smuzhiyun linedur_ns = div_u64((u64) mode->crtc_htotal * 1000000, dotclock);
627*4882a593Smuzhiyun framedur_ns = div_u64((u64) frame_size * 1000000, dotclock);
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun /*
630*4882a593Smuzhiyun * Fields of interlaced scanout modes are only half a frame duration.
631*4882a593Smuzhiyun */
632*4882a593Smuzhiyun if (mode->flags & DRM_MODE_FLAG_INTERLACE)
633*4882a593Smuzhiyun framedur_ns /= 2;
634*4882a593Smuzhiyun } else {
635*4882a593Smuzhiyun drm_err(dev, "crtc %u: Can't calculate constants, dotclock = 0!\n",
636*4882a593Smuzhiyun crtc->base.id);
637*4882a593Smuzhiyun }
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun vblank->linedur_ns = linedur_ns;
640*4882a593Smuzhiyun vblank->framedur_ns = framedur_ns;
641*4882a593Smuzhiyun vblank->hwmode = *mode;
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun drm_dbg_core(dev,
644*4882a593Smuzhiyun "crtc %u: hwmode: htotal %d, vtotal %d, vdisplay %d\n",
645*4882a593Smuzhiyun crtc->base.id, mode->crtc_htotal,
646*4882a593Smuzhiyun mode->crtc_vtotal, mode->crtc_vdisplay);
647*4882a593Smuzhiyun drm_dbg_core(dev, "crtc %u: clock %d kHz framedur %d linedur %d\n",
648*4882a593Smuzhiyun crtc->base.id, dotclock, framedur_ns, linedur_ns);
649*4882a593Smuzhiyun }
650*4882a593Smuzhiyun EXPORT_SYMBOL(drm_calc_timestamping_constants);
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun /**
653*4882a593Smuzhiyun * drm_crtc_vblank_helper_get_vblank_timestamp_internal - precise vblank
654*4882a593Smuzhiyun * timestamp helper
655*4882a593Smuzhiyun * @crtc: CRTC whose vblank timestamp to retrieve
656*4882a593Smuzhiyun * @max_error: Desired maximum allowable error in timestamps (nanosecs)
657*4882a593Smuzhiyun * On return contains true maximum error of timestamp
658*4882a593Smuzhiyun * @vblank_time: Pointer to time which should receive the timestamp
659*4882a593Smuzhiyun * @in_vblank_irq:
660*4882a593Smuzhiyun * True when called from drm_crtc_handle_vblank(). Some drivers
661*4882a593Smuzhiyun * need to apply some workarounds for gpu-specific vblank irq quirks
662*4882a593Smuzhiyun * if flag is set.
663*4882a593Smuzhiyun * @get_scanout_position:
664*4882a593Smuzhiyun * Callback function to retrieve the scanout position. See
665*4882a593Smuzhiyun * @struct drm_crtc_helper_funcs.get_scanout_position.
666*4882a593Smuzhiyun *
667*4882a593Smuzhiyun * Implements calculation of exact vblank timestamps from given drm_display_mode
668*4882a593Smuzhiyun * timings and current video scanout position of a CRTC.
669*4882a593Smuzhiyun *
670*4882a593Smuzhiyun * The current implementation only handles standard video modes. For double scan
671*4882a593Smuzhiyun * and interlaced modes the driver is supposed to adjust the hardware mode
672*4882a593Smuzhiyun * (taken from &drm_crtc_state.adjusted mode for atomic modeset drivers) to
673*4882a593Smuzhiyun * match the scanout position reported.
674*4882a593Smuzhiyun *
675*4882a593Smuzhiyun * Note that atomic drivers must call drm_calc_timestamping_constants() before
676*4882a593Smuzhiyun * enabling a CRTC. The atomic helpers already take care of that in
677*4882a593Smuzhiyun * drm_atomic_helper_calc_timestamping_constants().
678*4882a593Smuzhiyun *
679*4882a593Smuzhiyun * Returns:
680*4882a593Smuzhiyun *
681*4882a593Smuzhiyun * Returns true on success, and false on failure, i.e. when no accurate
682*4882a593Smuzhiyun * timestamp could be acquired.
683*4882a593Smuzhiyun */
684*4882a593Smuzhiyun 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)685*4882a593Smuzhiyun drm_crtc_vblank_helper_get_vblank_timestamp_internal(
686*4882a593Smuzhiyun struct drm_crtc *crtc, int *max_error, ktime_t *vblank_time,
687*4882a593Smuzhiyun bool in_vblank_irq,
688*4882a593Smuzhiyun drm_vblank_get_scanout_position_func get_scanout_position)
689*4882a593Smuzhiyun {
690*4882a593Smuzhiyun struct drm_device *dev = crtc->dev;
691*4882a593Smuzhiyun unsigned int pipe = crtc->index;
692*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
693*4882a593Smuzhiyun struct timespec64 ts_etime, ts_vblank_time;
694*4882a593Smuzhiyun ktime_t stime, etime;
695*4882a593Smuzhiyun bool vbl_status;
696*4882a593Smuzhiyun const struct drm_display_mode *mode;
697*4882a593Smuzhiyun int vpos, hpos, i;
698*4882a593Smuzhiyun int delta_ns, duration_ns;
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun if (pipe >= dev->num_crtcs) {
701*4882a593Smuzhiyun drm_err(dev, "Invalid crtc %u\n", pipe);
702*4882a593Smuzhiyun return false;
703*4882a593Smuzhiyun }
704*4882a593Smuzhiyun
705*4882a593Smuzhiyun /* Scanout position query not supported? Should not happen. */
706*4882a593Smuzhiyun if (!get_scanout_position) {
707*4882a593Smuzhiyun drm_err(dev, "Called from CRTC w/o get_scanout_position()!?\n");
708*4882a593Smuzhiyun return false;
709*4882a593Smuzhiyun }
710*4882a593Smuzhiyun
711*4882a593Smuzhiyun if (drm_drv_uses_atomic_modeset(dev))
712*4882a593Smuzhiyun mode = &vblank->hwmode;
713*4882a593Smuzhiyun else
714*4882a593Smuzhiyun mode = &crtc->hwmode;
715*4882a593Smuzhiyun
716*4882a593Smuzhiyun /* If mode timing undefined, just return as no-op:
717*4882a593Smuzhiyun * Happens during initial modesetting of a crtc.
718*4882a593Smuzhiyun */
719*4882a593Smuzhiyun if (mode->crtc_clock == 0) {
720*4882a593Smuzhiyun drm_dbg_core(dev, "crtc %u: Noop due to uninitialized mode.\n",
721*4882a593Smuzhiyun pipe);
722*4882a593Smuzhiyun drm_WARN_ON_ONCE(dev, drm_drv_uses_atomic_modeset(dev));
723*4882a593Smuzhiyun return false;
724*4882a593Smuzhiyun }
725*4882a593Smuzhiyun
726*4882a593Smuzhiyun /* Get current scanout position with system timestamp.
727*4882a593Smuzhiyun * Repeat query up to DRM_TIMESTAMP_MAXRETRIES times
728*4882a593Smuzhiyun * if single query takes longer than max_error nanoseconds.
729*4882a593Smuzhiyun *
730*4882a593Smuzhiyun * This guarantees a tight bound on maximum error if
731*4882a593Smuzhiyun * code gets preempted or delayed for some reason.
732*4882a593Smuzhiyun */
733*4882a593Smuzhiyun for (i = 0; i < DRM_TIMESTAMP_MAXRETRIES; i++) {
734*4882a593Smuzhiyun /*
735*4882a593Smuzhiyun * Get vertical and horizontal scanout position vpos, hpos,
736*4882a593Smuzhiyun * and bounding timestamps stime, etime, pre/post query.
737*4882a593Smuzhiyun */
738*4882a593Smuzhiyun vbl_status = get_scanout_position(crtc, in_vblank_irq,
739*4882a593Smuzhiyun &vpos, &hpos,
740*4882a593Smuzhiyun &stime, &etime,
741*4882a593Smuzhiyun mode);
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun /* Return as no-op if scanout query unsupported or failed. */
744*4882a593Smuzhiyun if (!vbl_status) {
745*4882a593Smuzhiyun drm_dbg_core(dev,
746*4882a593Smuzhiyun "crtc %u : scanoutpos query failed.\n",
747*4882a593Smuzhiyun pipe);
748*4882a593Smuzhiyun return false;
749*4882a593Smuzhiyun }
750*4882a593Smuzhiyun
751*4882a593Smuzhiyun /* Compute uncertainty in timestamp of scanout position query. */
752*4882a593Smuzhiyun duration_ns = ktime_to_ns(etime) - ktime_to_ns(stime);
753*4882a593Smuzhiyun
754*4882a593Smuzhiyun /* Accept result with < max_error nsecs timing uncertainty. */
755*4882a593Smuzhiyun if (duration_ns <= *max_error)
756*4882a593Smuzhiyun break;
757*4882a593Smuzhiyun }
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun /* Noisy system timing? */
760*4882a593Smuzhiyun if (i == DRM_TIMESTAMP_MAXRETRIES) {
761*4882a593Smuzhiyun drm_dbg_core(dev,
762*4882a593Smuzhiyun "crtc %u: Noisy timestamp %d us > %d us [%d reps].\n",
763*4882a593Smuzhiyun pipe, duration_ns / 1000, *max_error / 1000, i);
764*4882a593Smuzhiyun }
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun /* Return upper bound of timestamp precision error. */
767*4882a593Smuzhiyun *max_error = duration_ns;
768*4882a593Smuzhiyun
769*4882a593Smuzhiyun /* Convert scanout position into elapsed time at raw_time query
770*4882a593Smuzhiyun * since start of scanout at first display scanline. delta_ns
771*4882a593Smuzhiyun * can be negative if start of scanout hasn't happened yet.
772*4882a593Smuzhiyun */
773*4882a593Smuzhiyun delta_ns = div_s64(1000000LL * (vpos * mode->crtc_htotal + hpos),
774*4882a593Smuzhiyun mode->crtc_clock);
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun /* Subtract time delta from raw timestamp to get final
777*4882a593Smuzhiyun * vblank_time timestamp for end of vblank.
778*4882a593Smuzhiyun */
779*4882a593Smuzhiyun *vblank_time = ktime_sub_ns(etime, delta_ns);
780*4882a593Smuzhiyun
781*4882a593Smuzhiyun if (!drm_debug_enabled(DRM_UT_VBL))
782*4882a593Smuzhiyun return true;
783*4882a593Smuzhiyun
784*4882a593Smuzhiyun ts_etime = ktime_to_timespec64(etime);
785*4882a593Smuzhiyun ts_vblank_time = ktime_to_timespec64(*vblank_time);
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun drm_dbg_vbl(dev,
788*4882a593Smuzhiyun "crtc %u : v p(%d,%d)@ %lld.%06ld -> %lld.%06ld [e %d us, %d rep]\n",
789*4882a593Smuzhiyun pipe, hpos, vpos,
790*4882a593Smuzhiyun (u64)ts_etime.tv_sec, ts_etime.tv_nsec / 1000,
791*4882a593Smuzhiyun (u64)ts_vblank_time.tv_sec, ts_vblank_time.tv_nsec / 1000,
792*4882a593Smuzhiyun duration_ns / 1000, i);
793*4882a593Smuzhiyun
794*4882a593Smuzhiyun return true;
795*4882a593Smuzhiyun }
796*4882a593Smuzhiyun EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp_internal);
797*4882a593Smuzhiyun
798*4882a593Smuzhiyun /**
799*4882a593Smuzhiyun * drm_crtc_vblank_helper_get_vblank_timestamp - precise vblank timestamp
800*4882a593Smuzhiyun * helper
801*4882a593Smuzhiyun * @crtc: CRTC whose vblank timestamp to retrieve
802*4882a593Smuzhiyun * @max_error: Desired maximum allowable error in timestamps (nanosecs)
803*4882a593Smuzhiyun * On return contains true maximum error of timestamp
804*4882a593Smuzhiyun * @vblank_time: Pointer to time which should receive the timestamp
805*4882a593Smuzhiyun * @in_vblank_irq:
806*4882a593Smuzhiyun * True when called from drm_crtc_handle_vblank(). Some drivers
807*4882a593Smuzhiyun * need to apply some workarounds for gpu-specific vblank irq quirks
808*4882a593Smuzhiyun * if flag is set.
809*4882a593Smuzhiyun *
810*4882a593Smuzhiyun * Implements calculation of exact vblank timestamps from given drm_display_mode
811*4882a593Smuzhiyun * timings and current video scanout position of a CRTC. This can be directly
812*4882a593Smuzhiyun * used as the &drm_crtc_funcs.get_vblank_timestamp implementation of a kms
813*4882a593Smuzhiyun * driver if &drm_crtc_helper_funcs.get_scanout_position is implemented.
814*4882a593Smuzhiyun *
815*4882a593Smuzhiyun * The current implementation only handles standard video modes. For double scan
816*4882a593Smuzhiyun * and interlaced modes the driver is supposed to adjust the hardware mode
817*4882a593Smuzhiyun * (taken from &drm_crtc_state.adjusted mode for atomic modeset drivers) to
818*4882a593Smuzhiyun * match the scanout position reported.
819*4882a593Smuzhiyun *
820*4882a593Smuzhiyun * Note that atomic drivers must call drm_calc_timestamping_constants() before
821*4882a593Smuzhiyun * enabling a CRTC. The atomic helpers already take care of that in
822*4882a593Smuzhiyun * drm_atomic_helper_calc_timestamping_constants().
823*4882a593Smuzhiyun *
824*4882a593Smuzhiyun * Returns:
825*4882a593Smuzhiyun *
826*4882a593Smuzhiyun * Returns true on success, and false on failure, i.e. when no accurate
827*4882a593Smuzhiyun * timestamp could be acquired.
828*4882a593Smuzhiyun */
drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc * crtc,int * max_error,ktime_t * vblank_time,bool in_vblank_irq)829*4882a593Smuzhiyun bool drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc *crtc,
830*4882a593Smuzhiyun int *max_error,
831*4882a593Smuzhiyun ktime_t *vblank_time,
832*4882a593Smuzhiyun bool in_vblank_irq)
833*4882a593Smuzhiyun {
834*4882a593Smuzhiyun return drm_crtc_vblank_helper_get_vblank_timestamp_internal(
835*4882a593Smuzhiyun crtc, max_error, vblank_time, in_vblank_irq,
836*4882a593Smuzhiyun crtc->helper_private->get_scanout_position);
837*4882a593Smuzhiyun }
838*4882a593Smuzhiyun EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp);
839*4882a593Smuzhiyun
840*4882a593Smuzhiyun /**
841*4882a593Smuzhiyun * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent
842*4882a593Smuzhiyun * vblank interval
843*4882a593Smuzhiyun * @dev: DRM device
844*4882a593Smuzhiyun * @pipe: index of CRTC whose vblank timestamp to retrieve
845*4882a593Smuzhiyun * @tvblank: Pointer to target time which should receive the timestamp
846*4882a593Smuzhiyun * @in_vblank_irq:
847*4882a593Smuzhiyun * True when called from drm_crtc_handle_vblank(). Some drivers
848*4882a593Smuzhiyun * need to apply some workarounds for gpu-specific vblank irq quirks
849*4882a593Smuzhiyun * if flag is set.
850*4882a593Smuzhiyun *
851*4882a593Smuzhiyun * Fetches the system timestamp corresponding to the time of the most recent
852*4882a593Smuzhiyun * vblank interval on specified CRTC. May call into kms-driver to
853*4882a593Smuzhiyun * compute the timestamp with a high-precision GPU specific method.
854*4882a593Smuzhiyun *
855*4882a593Smuzhiyun * Returns zero if timestamp originates from uncorrected do_gettimeofday()
856*4882a593Smuzhiyun * call, i.e., it isn't very precisely locked to the true vblank.
857*4882a593Smuzhiyun *
858*4882a593Smuzhiyun * Returns:
859*4882a593Smuzhiyun * True if timestamp is considered to be very precise, false otherwise.
860*4882a593Smuzhiyun */
861*4882a593Smuzhiyun static bool
drm_get_last_vbltimestamp(struct drm_device * dev,unsigned int pipe,ktime_t * tvblank,bool in_vblank_irq)862*4882a593Smuzhiyun drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
863*4882a593Smuzhiyun ktime_t *tvblank, bool in_vblank_irq)
864*4882a593Smuzhiyun {
865*4882a593Smuzhiyun struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
866*4882a593Smuzhiyun bool ret = false;
867*4882a593Smuzhiyun
868*4882a593Smuzhiyun /* Define requested maximum error on timestamps (nanoseconds). */
869*4882a593Smuzhiyun int max_error = (int) drm_timestamp_precision * 1000;
870*4882a593Smuzhiyun
871*4882a593Smuzhiyun /* Query driver if possible and precision timestamping enabled. */
872*4882a593Smuzhiyun if (crtc && crtc->funcs->get_vblank_timestamp && max_error > 0) {
873*4882a593Smuzhiyun struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
874*4882a593Smuzhiyun
875*4882a593Smuzhiyun ret = crtc->funcs->get_vblank_timestamp(crtc, &max_error,
876*4882a593Smuzhiyun tvblank, in_vblank_irq);
877*4882a593Smuzhiyun }
878*4882a593Smuzhiyun
879*4882a593Smuzhiyun /* GPU high precision timestamp query unsupported or failed.
880*4882a593Smuzhiyun * Return current monotonic/gettimeofday timestamp as best estimate.
881*4882a593Smuzhiyun */
882*4882a593Smuzhiyun if (!ret)
883*4882a593Smuzhiyun *tvblank = ktime_get();
884*4882a593Smuzhiyun
885*4882a593Smuzhiyun return ret;
886*4882a593Smuzhiyun }
887*4882a593Smuzhiyun
888*4882a593Smuzhiyun /**
889*4882a593Smuzhiyun * drm_crtc_vblank_count - retrieve "cooked" vblank counter value
890*4882a593Smuzhiyun * @crtc: which counter to retrieve
891*4882a593Smuzhiyun *
892*4882a593Smuzhiyun * Fetches the "cooked" vblank count value that represents the number of
893*4882a593Smuzhiyun * vblank events since the system was booted, including lost events due to
894*4882a593Smuzhiyun * modesetting activity. Note that this timer isn't correct against a racing
895*4882a593Smuzhiyun * vblank interrupt (since it only reports the software vblank counter), see
896*4882a593Smuzhiyun * drm_crtc_accurate_vblank_count() for such use-cases.
897*4882a593Smuzhiyun *
898*4882a593Smuzhiyun * Note that for a given vblank counter value drm_crtc_handle_vblank()
899*4882a593Smuzhiyun * and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time()
900*4882a593Smuzhiyun * provide a barrier: Any writes done before calling
901*4882a593Smuzhiyun * drm_crtc_handle_vblank() will be visible to callers of the later
902*4882a593Smuzhiyun * functions, iff the vblank count is the same or a later one.
903*4882a593Smuzhiyun *
904*4882a593Smuzhiyun * See also &drm_vblank_crtc.count.
905*4882a593Smuzhiyun *
906*4882a593Smuzhiyun * Returns:
907*4882a593Smuzhiyun * The software vblank counter.
908*4882a593Smuzhiyun */
drm_crtc_vblank_count(struct drm_crtc * crtc)909*4882a593Smuzhiyun u64 drm_crtc_vblank_count(struct drm_crtc *crtc)
910*4882a593Smuzhiyun {
911*4882a593Smuzhiyun return drm_vblank_count(crtc->dev, drm_crtc_index(crtc));
912*4882a593Smuzhiyun }
913*4882a593Smuzhiyun EXPORT_SYMBOL(drm_crtc_vblank_count);
914*4882a593Smuzhiyun
915*4882a593Smuzhiyun /**
916*4882a593Smuzhiyun * drm_vblank_count_and_time - retrieve "cooked" vblank counter value and the
917*4882a593Smuzhiyun * system timestamp corresponding to that vblank counter value.
918*4882a593Smuzhiyun * @dev: DRM device
919*4882a593Smuzhiyun * @pipe: index of CRTC whose counter to retrieve
920*4882a593Smuzhiyun * @vblanktime: Pointer to ktime_t to receive the vblank timestamp.
921*4882a593Smuzhiyun *
922*4882a593Smuzhiyun * Fetches the "cooked" vblank count value that represents the number of
923*4882a593Smuzhiyun * vblank events since the system was booted, including lost events due to
924*4882a593Smuzhiyun * modesetting activity. Returns corresponding system timestamp of the time
925*4882a593Smuzhiyun * of the vblank interval that corresponds to the current vblank counter value.
926*4882a593Smuzhiyun *
927*4882a593Smuzhiyun * This is the legacy version of drm_crtc_vblank_count_and_time().
928*4882a593Smuzhiyun */
drm_vblank_count_and_time(struct drm_device * dev,unsigned int pipe,ktime_t * vblanktime)929*4882a593Smuzhiyun static u64 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
930*4882a593Smuzhiyun ktime_t *vblanktime)
931*4882a593Smuzhiyun {
932*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
933*4882a593Smuzhiyun u64 vblank_count;
934*4882a593Smuzhiyun unsigned int seq;
935*4882a593Smuzhiyun
936*4882a593Smuzhiyun if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) {
937*4882a593Smuzhiyun *vblanktime = 0;
938*4882a593Smuzhiyun return 0;
939*4882a593Smuzhiyun }
940*4882a593Smuzhiyun
941*4882a593Smuzhiyun do {
942*4882a593Smuzhiyun seq = read_seqbegin(&vblank->seqlock);
943*4882a593Smuzhiyun vblank_count = atomic64_read(&vblank->count);
944*4882a593Smuzhiyun *vblanktime = vblank->time;
945*4882a593Smuzhiyun } while (read_seqretry(&vblank->seqlock, seq));
946*4882a593Smuzhiyun
947*4882a593Smuzhiyun return vblank_count;
948*4882a593Smuzhiyun }
949*4882a593Smuzhiyun
950*4882a593Smuzhiyun /**
951*4882a593Smuzhiyun * drm_crtc_vblank_count_and_time - retrieve "cooked" vblank counter value
952*4882a593Smuzhiyun * and the system timestamp corresponding to that vblank counter value
953*4882a593Smuzhiyun * @crtc: which counter to retrieve
954*4882a593Smuzhiyun * @vblanktime: Pointer to time to receive the vblank timestamp.
955*4882a593Smuzhiyun *
956*4882a593Smuzhiyun * Fetches the "cooked" vblank count value that represents the number of
957*4882a593Smuzhiyun * vblank events since the system was booted, including lost events due to
958*4882a593Smuzhiyun * modesetting activity. Returns corresponding system timestamp of the time
959*4882a593Smuzhiyun * of the vblank interval that corresponds to the current vblank counter value.
960*4882a593Smuzhiyun *
961*4882a593Smuzhiyun * Note that for a given vblank counter value drm_crtc_handle_vblank()
962*4882a593Smuzhiyun * and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time()
963*4882a593Smuzhiyun * provide a barrier: Any writes done before calling
964*4882a593Smuzhiyun * drm_crtc_handle_vblank() will be visible to callers of the later
965*4882a593Smuzhiyun * functions, iff the vblank count is the same or a later one.
966*4882a593Smuzhiyun *
967*4882a593Smuzhiyun * See also &drm_vblank_crtc.count.
968*4882a593Smuzhiyun */
drm_crtc_vblank_count_and_time(struct drm_crtc * crtc,ktime_t * vblanktime)969*4882a593Smuzhiyun u64 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc,
970*4882a593Smuzhiyun ktime_t *vblanktime)
971*4882a593Smuzhiyun {
972*4882a593Smuzhiyun return drm_vblank_count_and_time(crtc->dev, drm_crtc_index(crtc),
973*4882a593Smuzhiyun vblanktime);
974*4882a593Smuzhiyun }
975*4882a593Smuzhiyun EXPORT_SYMBOL(drm_crtc_vblank_count_and_time);
976*4882a593Smuzhiyun
send_vblank_event(struct drm_device * dev,struct drm_pending_vblank_event * e,u64 seq,ktime_t now)977*4882a593Smuzhiyun static void send_vblank_event(struct drm_device *dev,
978*4882a593Smuzhiyun struct drm_pending_vblank_event *e,
979*4882a593Smuzhiyun u64 seq, ktime_t now)
980*4882a593Smuzhiyun {
981*4882a593Smuzhiyun struct timespec64 tv;
982*4882a593Smuzhiyun
983*4882a593Smuzhiyun switch (e->event.base.type) {
984*4882a593Smuzhiyun case DRM_EVENT_VBLANK:
985*4882a593Smuzhiyun case DRM_EVENT_FLIP_COMPLETE:
986*4882a593Smuzhiyun tv = ktime_to_timespec64(now);
987*4882a593Smuzhiyun e->event.vbl.sequence = seq;
988*4882a593Smuzhiyun /*
989*4882a593Smuzhiyun * e->event is a user space structure, with hardcoded unsigned
990*4882a593Smuzhiyun * 32-bit seconds/microseconds. This is safe as we always use
991*4882a593Smuzhiyun * monotonic timestamps since linux-4.15
992*4882a593Smuzhiyun */
993*4882a593Smuzhiyun e->event.vbl.tv_sec = tv.tv_sec;
994*4882a593Smuzhiyun e->event.vbl.tv_usec = tv.tv_nsec / 1000;
995*4882a593Smuzhiyun break;
996*4882a593Smuzhiyun case DRM_EVENT_CRTC_SEQUENCE:
997*4882a593Smuzhiyun if (seq)
998*4882a593Smuzhiyun e->event.seq.sequence = seq;
999*4882a593Smuzhiyun e->event.seq.time_ns = ktime_to_ns(now);
1000*4882a593Smuzhiyun break;
1001*4882a593Smuzhiyun }
1002*4882a593Smuzhiyun trace_drm_vblank_event_delivered(e->base.file_priv, e->pipe, seq);
1003*4882a593Smuzhiyun /*
1004*4882a593Smuzhiyun * Use the same timestamp for any associated fence signal to avoid
1005*4882a593Smuzhiyun * mismatch in timestamps for vsync & fence events triggered by the
1006*4882a593Smuzhiyun * same HW event. Frameworks like SurfaceFlinger in Android expects the
1007*4882a593Smuzhiyun * retire-fence timestamp to match exactly with HW vsync as it uses it
1008*4882a593Smuzhiyun * for its software vsync modeling.
1009*4882a593Smuzhiyun */
1010*4882a593Smuzhiyun drm_send_event_timestamp_locked(dev, &e->base, now);
1011*4882a593Smuzhiyun }
1012*4882a593Smuzhiyun
1013*4882a593Smuzhiyun /**
1014*4882a593Smuzhiyun * drm_crtc_arm_vblank_event - arm vblank event after pageflip
1015*4882a593Smuzhiyun * @crtc: the source CRTC of the vblank event
1016*4882a593Smuzhiyun * @e: the event to send
1017*4882a593Smuzhiyun *
1018*4882a593Smuzhiyun * A lot of drivers need to generate vblank events for the very next vblank
1019*4882a593Smuzhiyun * interrupt. For example when the page flip interrupt happens when the page
1020*4882a593Smuzhiyun * flip gets armed, but not when it actually executes within the next vblank
1021*4882a593Smuzhiyun * period. This helper function implements exactly the required vblank arming
1022*4882a593Smuzhiyun * behaviour.
1023*4882a593Smuzhiyun *
1024*4882a593Smuzhiyun * NOTE: Drivers using this to send out the &drm_crtc_state.event as part of an
1025*4882a593Smuzhiyun * atomic commit must ensure that the next vblank happens at exactly the same
1026*4882a593Smuzhiyun * time as the atomic commit is committed to the hardware. This function itself
1027*4882a593Smuzhiyun * does **not** protect against the next vblank interrupt racing with either this
1028*4882a593Smuzhiyun * function call or the atomic commit operation. A possible sequence could be:
1029*4882a593Smuzhiyun *
1030*4882a593Smuzhiyun * 1. Driver commits new hardware state into vblank-synchronized registers.
1031*4882a593Smuzhiyun * 2. A vblank happens, committing the hardware state. Also the corresponding
1032*4882a593Smuzhiyun * vblank interrupt is fired off and fully processed by the interrupt
1033*4882a593Smuzhiyun * handler.
1034*4882a593Smuzhiyun * 3. The atomic commit operation proceeds to call drm_crtc_arm_vblank_event().
1035*4882a593Smuzhiyun * 4. The event is only send out for the next vblank, which is wrong.
1036*4882a593Smuzhiyun *
1037*4882a593Smuzhiyun * An equivalent race can happen when the driver calls
1038*4882a593Smuzhiyun * drm_crtc_arm_vblank_event() before writing out the new hardware state.
1039*4882a593Smuzhiyun *
1040*4882a593Smuzhiyun * The only way to make this work safely is to prevent the vblank from firing
1041*4882a593Smuzhiyun * (and the hardware from committing anything else) until the entire atomic
1042*4882a593Smuzhiyun * commit sequence has run to completion. If the hardware does not have such a
1043*4882a593Smuzhiyun * feature (e.g. using a "go" bit), then it is unsafe to use this functions.
1044*4882a593Smuzhiyun * Instead drivers need to manually send out the event from their interrupt
1045*4882a593Smuzhiyun * handler by calling drm_crtc_send_vblank_event() and make sure that there's no
1046*4882a593Smuzhiyun * possible race with the hardware committing the atomic update.
1047*4882a593Smuzhiyun *
1048*4882a593Smuzhiyun * Caller must hold a vblank reference for the event @e acquired by a
1049*4882a593Smuzhiyun * drm_crtc_vblank_get(), which will be dropped when the next vblank arrives.
1050*4882a593Smuzhiyun */
drm_crtc_arm_vblank_event(struct drm_crtc * crtc,struct drm_pending_vblank_event * e)1051*4882a593Smuzhiyun void drm_crtc_arm_vblank_event(struct drm_crtc *crtc,
1052*4882a593Smuzhiyun struct drm_pending_vblank_event *e)
1053*4882a593Smuzhiyun {
1054*4882a593Smuzhiyun struct drm_device *dev = crtc->dev;
1055*4882a593Smuzhiyun unsigned int pipe = drm_crtc_index(crtc);
1056*4882a593Smuzhiyun
1057*4882a593Smuzhiyun assert_spin_locked(&dev->event_lock);
1058*4882a593Smuzhiyun
1059*4882a593Smuzhiyun e->pipe = pipe;
1060*4882a593Smuzhiyun e->sequence = drm_crtc_accurate_vblank_count(crtc) + 1;
1061*4882a593Smuzhiyun list_add_tail(&e->base.link, &dev->vblank_event_list);
1062*4882a593Smuzhiyun }
1063*4882a593Smuzhiyun EXPORT_SYMBOL(drm_crtc_arm_vblank_event);
1064*4882a593Smuzhiyun
1065*4882a593Smuzhiyun /**
1066*4882a593Smuzhiyun * drm_crtc_send_vblank_event - helper to send vblank event after pageflip
1067*4882a593Smuzhiyun * @crtc: the source CRTC of the vblank event
1068*4882a593Smuzhiyun * @e: the event to send
1069*4882a593Smuzhiyun *
1070*4882a593Smuzhiyun * Updates sequence # and timestamp on event for the most recently processed
1071*4882a593Smuzhiyun * vblank, and sends it to userspace. Caller must hold event lock.
1072*4882a593Smuzhiyun *
1073*4882a593Smuzhiyun * See drm_crtc_arm_vblank_event() for a helper which can be used in certain
1074*4882a593Smuzhiyun * situation, especially to send out events for atomic commit operations.
1075*4882a593Smuzhiyun */
drm_crtc_send_vblank_event(struct drm_crtc * crtc,struct drm_pending_vblank_event * e)1076*4882a593Smuzhiyun void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
1077*4882a593Smuzhiyun struct drm_pending_vblank_event *e)
1078*4882a593Smuzhiyun {
1079*4882a593Smuzhiyun struct drm_device *dev = crtc->dev;
1080*4882a593Smuzhiyun u64 seq;
1081*4882a593Smuzhiyun unsigned int pipe = drm_crtc_index(crtc);
1082*4882a593Smuzhiyun ktime_t now;
1083*4882a593Smuzhiyun
1084*4882a593Smuzhiyun if (drm_dev_has_vblank(dev)) {
1085*4882a593Smuzhiyun seq = drm_vblank_count_and_time(dev, pipe, &now);
1086*4882a593Smuzhiyun } else {
1087*4882a593Smuzhiyun seq = 0;
1088*4882a593Smuzhiyun
1089*4882a593Smuzhiyun now = ktime_get();
1090*4882a593Smuzhiyun }
1091*4882a593Smuzhiyun e->pipe = pipe;
1092*4882a593Smuzhiyun send_vblank_event(dev, e, seq, now);
1093*4882a593Smuzhiyun }
1094*4882a593Smuzhiyun EXPORT_SYMBOL(drm_crtc_send_vblank_event);
1095*4882a593Smuzhiyun
__enable_vblank(struct drm_device * dev,unsigned int pipe)1096*4882a593Smuzhiyun static int __enable_vblank(struct drm_device *dev, unsigned int pipe)
1097*4882a593Smuzhiyun {
1098*4882a593Smuzhiyun if (drm_core_check_feature(dev, DRIVER_MODESET)) {
1099*4882a593Smuzhiyun struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
1100*4882a593Smuzhiyun
1101*4882a593Smuzhiyun if (drm_WARN_ON(dev, !crtc))
1102*4882a593Smuzhiyun return 0;
1103*4882a593Smuzhiyun
1104*4882a593Smuzhiyun if (crtc->funcs->enable_vblank)
1105*4882a593Smuzhiyun return crtc->funcs->enable_vblank(crtc);
1106*4882a593Smuzhiyun } else if (dev->driver->enable_vblank) {
1107*4882a593Smuzhiyun return dev->driver->enable_vblank(dev, pipe);
1108*4882a593Smuzhiyun }
1109*4882a593Smuzhiyun
1110*4882a593Smuzhiyun return -EINVAL;
1111*4882a593Smuzhiyun }
1112*4882a593Smuzhiyun
drm_vblank_enable(struct drm_device * dev,unsigned int pipe)1113*4882a593Smuzhiyun static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe)
1114*4882a593Smuzhiyun {
1115*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
1116*4882a593Smuzhiyun int ret = 0;
1117*4882a593Smuzhiyun
1118*4882a593Smuzhiyun assert_spin_locked(&dev->vbl_lock);
1119*4882a593Smuzhiyun
1120*4882a593Smuzhiyun spin_lock(&dev->vblank_time_lock);
1121*4882a593Smuzhiyun
1122*4882a593Smuzhiyun if (!vblank->enabled) {
1123*4882a593Smuzhiyun /*
1124*4882a593Smuzhiyun * Enable vblank irqs under vblank_time_lock protection.
1125*4882a593Smuzhiyun * All vblank count & timestamp updates are held off
1126*4882a593Smuzhiyun * until we are done reinitializing master counter and
1127*4882a593Smuzhiyun * timestamps. Filtercode in drm_handle_vblank() will
1128*4882a593Smuzhiyun * prevent double-accounting of same vblank interval.
1129*4882a593Smuzhiyun */
1130*4882a593Smuzhiyun ret = __enable_vblank(dev, pipe);
1131*4882a593Smuzhiyun drm_dbg_core(dev, "enabling vblank on crtc %u, ret: %d\n",
1132*4882a593Smuzhiyun pipe, ret);
1133*4882a593Smuzhiyun if (ret) {
1134*4882a593Smuzhiyun atomic_dec(&vblank->refcount);
1135*4882a593Smuzhiyun } else {
1136*4882a593Smuzhiyun drm_update_vblank_count(dev, pipe, 0);
1137*4882a593Smuzhiyun /* drm_update_vblank_count() includes a wmb so we just
1138*4882a593Smuzhiyun * need to ensure that the compiler emits the write
1139*4882a593Smuzhiyun * to mark the vblank as enabled after the call
1140*4882a593Smuzhiyun * to drm_update_vblank_count().
1141*4882a593Smuzhiyun */
1142*4882a593Smuzhiyun WRITE_ONCE(vblank->enabled, true);
1143*4882a593Smuzhiyun }
1144*4882a593Smuzhiyun }
1145*4882a593Smuzhiyun
1146*4882a593Smuzhiyun spin_unlock(&dev->vblank_time_lock);
1147*4882a593Smuzhiyun
1148*4882a593Smuzhiyun return ret;
1149*4882a593Smuzhiyun }
1150*4882a593Smuzhiyun
drm_vblank_get(struct drm_device * dev,unsigned int pipe)1151*4882a593Smuzhiyun int drm_vblank_get(struct drm_device *dev, unsigned int pipe)
1152*4882a593Smuzhiyun {
1153*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
1154*4882a593Smuzhiyun unsigned long irqflags;
1155*4882a593Smuzhiyun int ret = 0;
1156*4882a593Smuzhiyun
1157*4882a593Smuzhiyun if (!drm_dev_has_vblank(dev))
1158*4882a593Smuzhiyun return -EINVAL;
1159*4882a593Smuzhiyun
1160*4882a593Smuzhiyun if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
1161*4882a593Smuzhiyun return -EINVAL;
1162*4882a593Smuzhiyun
1163*4882a593Smuzhiyun spin_lock_irqsave(&dev->vbl_lock, irqflags);
1164*4882a593Smuzhiyun /* Going from 0->1 means we have to enable interrupts again */
1165*4882a593Smuzhiyun if (atomic_add_return(1, &vblank->refcount) == 1) {
1166*4882a593Smuzhiyun ret = drm_vblank_enable(dev, pipe);
1167*4882a593Smuzhiyun } else {
1168*4882a593Smuzhiyun if (!vblank->enabled) {
1169*4882a593Smuzhiyun atomic_dec(&vblank->refcount);
1170*4882a593Smuzhiyun ret = -EINVAL;
1171*4882a593Smuzhiyun }
1172*4882a593Smuzhiyun }
1173*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
1174*4882a593Smuzhiyun
1175*4882a593Smuzhiyun return ret;
1176*4882a593Smuzhiyun }
1177*4882a593Smuzhiyun
1178*4882a593Smuzhiyun /**
1179*4882a593Smuzhiyun * drm_crtc_vblank_get - get a reference count on vblank events
1180*4882a593Smuzhiyun * @crtc: which CRTC to own
1181*4882a593Smuzhiyun *
1182*4882a593Smuzhiyun * Acquire a reference count on vblank events to avoid having them disabled
1183*4882a593Smuzhiyun * while in use.
1184*4882a593Smuzhiyun *
1185*4882a593Smuzhiyun * Returns:
1186*4882a593Smuzhiyun * Zero on success or a negative error code on failure.
1187*4882a593Smuzhiyun */
drm_crtc_vblank_get(struct drm_crtc * crtc)1188*4882a593Smuzhiyun int drm_crtc_vblank_get(struct drm_crtc *crtc)
1189*4882a593Smuzhiyun {
1190*4882a593Smuzhiyun return drm_vblank_get(crtc->dev, drm_crtc_index(crtc));
1191*4882a593Smuzhiyun }
1192*4882a593Smuzhiyun EXPORT_SYMBOL(drm_crtc_vblank_get);
1193*4882a593Smuzhiyun
drm_vblank_put(struct drm_device * dev,unsigned int pipe)1194*4882a593Smuzhiyun void drm_vblank_put(struct drm_device *dev, unsigned int pipe)
1195*4882a593Smuzhiyun {
1196*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
1197*4882a593Smuzhiyun
1198*4882a593Smuzhiyun if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
1199*4882a593Smuzhiyun return;
1200*4882a593Smuzhiyun
1201*4882a593Smuzhiyun if (drm_WARN_ON(dev, atomic_read(&vblank->refcount) == 0))
1202*4882a593Smuzhiyun return;
1203*4882a593Smuzhiyun
1204*4882a593Smuzhiyun /* Last user schedules interrupt disable */
1205*4882a593Smuzhiyun if (atomic_dec_and_test(&vblank->refcount)) {
1206*4882a593Smuzhiyun if (drm_vblank_offdelay == 0)
1207*4882a593Smuzhiyun return;
1208*4882a593Smuzhiyun else if (drm_vblank_offdelay < 0)
1209*4882a593Smuzhiyun vblank_disable_fn(&vblank->disable_timer);
1210*4882a593Smuzhiyun else if (!dev->vblank_disable_immediate)
1211*4882a593Smuzhiyun mod_timer(&vblank->disable_timer,
1212*4882a593Smuzhiyun jiffies + ((drm_vblank_offdelay * HZ)/1000));
1213*4882a593Smuzhiyun }
1214*4882a593Smuzhiyun }
1215*4882a593Smuzhiyun
1216*4882a593Smuzhiyun /**
1217*4882a593Smuzhiyun * drm_crtc_vblank_put - give up ownership of vblank events
1218*4882a593Smuzhiyun * @crtc: which counter to give up
1219*4882a593Smuzhiyun *
1220*4882a593Smuzhiyun * Release ownership of a given vblank counter, turning off interrupts
1221*4882a593Smuzhiyun * if possible. Disable interrupts after drm_vblank_offdelay milliseconds.
1222*4882a593Smuzhiyun */
drm_crtc_vblank_put(struct drm_crtc * crtc)1223*4882a593Smuzhiyun void drm_crtc_vblank_put(struct drm_crtc *crtc)
1224*4882a593Smuzhiyun {
1225*4882a593Smuzhiyun drm_vblank_put(crtc->dev, drm_crtc_index(crtc));
1226*4882a593Smuzhiyun }
1227*4882a593Smuzhiyun EXPORT_SYMBOL(drm_crtc_vblank_put);
1228*4882a593Smuzhiyun
1229*4882a593Smuzhiyun /**
1230*4882a593Smuzhiyun * drm_wait_one_vblank - wait for one vblank
1231*4882a593Smuzhiyun * @dev: DRM device
1232*4882a593Smuzhiyun * @pipe: CRTC index
1233*4882a593Smuzhiyun *
1234*4882a593Smuzhiyun * This waits for one vblank to pass on @pipe, using the irq driver interfaces.
1235*4882a593Smuzhiyun * It is a failure to call this when the vblank irq for @pipe is disabled, e.g.
1236*4882a593Smuzhiyun * due to lack of driver support or because the crtc is off.
1237*4882a593Smuzhiyun *
1238*4882a593Smuzhiyun * This is the legacy version of drm_crtc_wait_one_vblank().
1239*4882a593Smuzhiyun */
drm_wait_one_vblank(struct drm_device * dev,unsigned int pipe)1240*4882a593Smuzhiyun void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe)
1241*4882a593Smuzhiyun {
1242*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
1243*4882a593Smuzhiyun int ret;
1244*4882a593Smuzhiyun u64 last;
1245*4882a593Smuzhiyun
1246*4882a593Smuzhiyun if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
1247*4882a593Smuzhiyun return;
1248*4882a593Smuzhiyun
1249*4882a593Smuzhiyun ret = drm_vblank_get(dev, pipe);
1250*4882a593Smuzhiyun if (drm_WARN(dev, ret, "vblank not available on crtc %i, ret=%i\n",
1251*4882a593Smuzhiyun pipe, ret))
1252*4882a593Smuzhiyun return;
1253*4882a593Smuzhiyun
1254*4882a593Smuzhiyun last = drm_vblank_count(dev, pipe);
1255*4882a593Smuzhiyun
1256*4882a593Smuzhiyun ret = wait_event_timeout(vblank->queue,
1257*4882a593Smuzhiyun last != drm_vblank_count(dev, pipe),
1258*4882a593Smuzhiyun msecs_to_jiffies(100));
1259*4882a593Smuzhiyun
1260*4882a593Smuzhiyun drm_WARN(dev, ret == 0, "vblank wait timed out on crtc %i\n", pipe);
1261*4882a593Smuzhiyun
1262*4882a593Smuzhiyun drm_vblank_put(dev, pipe);
1263*4882a593Smuzhiyun }
1264*4882a593Smuzhiyun EXPORT_SYMBOL(drm_wait_one_vblank);
1265*4882a593Smuzhiyun
1266*4882a593Smuzhiyun /**
1267*4882a593Smuzhiyun * drm_crtc_wait_one_vblank - wait for one vblank
1268*4882a593Smuzhiyun * @crtc: DRM crtc
1269*4882a593Smuzhiyun *
1270*4882a593Smuzhiyun * This waits for one vblank to pass on @crtc, using the irq driver interfaces.
1271*4882a593Smuzhiyun * It is a failure to call this when the vblank irq for @crtc is disabled, e.g.
1272*4882a593Smuzhiyun * due to lack of driver support or because the crtc is off.
1273*4882a593Smuzhiyun */
drm_crtc_wait_one_vblank(struct drm_crtc * crtc)1274*4882a593Smuzhiyun void drm_crtc_wait_one_vblank(struct drm_crtc *crtc)
1275*4882a593Smuzhiyun {
1276*4882a593Smuzhiyun drm_wait_one_vblank(crtc->dev, drm_crtc_index(crtc));
1277*4882a593Smuzhiyun }
1278*4882a593Smuzhiyun EXPORT_SYMBOL(drm_crtc_wait_one_vblank);
1279*4882a593Smuzhiyun
1280*4882a593Smuzhiyun /**
1281*4882a593Smuzhiyun * drm_crtc_vblank_off - disable vblank events on a CRTC
1282*4882a593Smuzhiyun * @crtc: CRTC in question
1283*4882a593Smuzhiyun *
1284*4882a593Smuzhiyun * Drivers can use this function to shut down the vblank interrupt handling when
1285*4882a593Smuzhiyun * disabling a crtc. This function ensures that the latest vblank frame count is
1286*4882a593Smuzhiyun * stored so that drm_vblank_on can restore it again.
1287*4882a593Smuzhiyun *
1288*4882a593Smuzhiyun * Drivers must use this function when the hardware vblank counter can get
1289*4882a593Smuzhiyun * reset, e.g. when suspending or disabling the @crtc in general.
1290*4882a593Smuzhiyun */
drm_crtc_vblank_off(struct drm_crtc * crtc)1291*4882a593Smuzhiyun void drm_crtc_vblank_off(struct drm_crtc *crtc)
1292*4882a593Smuzhiyun {
1293*4882a593Smuzhiyun struct drm_device *dev = crtc->dev;
1294*4882a593Smuzhiyun unsigned int pipe = drm_crtc_index(crtc);
1295*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
1296*4882a593Smuzhiyun struct drm_pending_vblank_event *e, *t;
1297*4882a593Smuzhiyun ktime_t now;
1298*4882a593Smuzhiyun u64 seq;
1299*4882a593Smuzhiyun
1300*4882a593Smuzhiyun if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
1301*4882a593Smuzhiyun return;
1302*4882a593Smuzhiyun
1303*4882a593Smuzhiyun /*
1304*4882a593Smuzhiyun * Grab event_lock early to prevent vblank work from being scheduled
1305*4882a593Smuzhiyun * while we're in the middle of shutting down vblank interrupts
1306*4882a593Smuzhiyun */
1307*4882a593Smuzhiyun spin_lock_irq(&dev->event_lock);
1308*4882a593Smuzhiyun
1309*4882a593Smuzhiyun spin_lock(&dev->vbl_lock);
1310*4882a593Smuzhiyun drm_dbg_vbl(dev, "crtc %d, vblank enabled %d, inmodeset %d\n",
1311*4882a593Smuzhiyun pipe, vblank->enabled, vblank->inmodeset);
1312*4882a593Smuzhiyun
1313*4882a593Smuzhiyun /* Avoid redundant vblank disables without previous
1314*4882a593Smuzhiyun * drm_crtc_vblank_on(). */
1315*4882a593Smuzhiyun if (drm_core_check_feature(dev, DRIVER_ATOMIC) || !vblank->inmodeset)
1316*4882a593Smuzhiyun drm_vblank_disable_and_save(dev, pipe);
1317*4882a593Smuzhiyun
1318*4882a593Smuzhiyun wake_up(&vblank->queue);
1319*4882a593Smuzhiyun
1320*4882a593Smuzhiyun /*
1321*4882a593Smuzhiyun * Prevent subsequent drm_vblank_get() from re-enabling
1322*4882a593Smuzhiyun * the vblank interrupt by bumping the refcount.
1323*4882a593Smuzhiyun */
1324*4882a593Smuzhiyun if (!vblank->inmodeset) {
1325*4882a593Smuzhiyun atomic_inc(&vblank->refcount);
1326*4882a593Smuzhiyun vblank->inmodeset = 1;
1327*4882a593Smuzhiyun }
1328*4882a593Smuzhiyun spin_unlock(&dev->vbl_lock);
1329*4882a593Smuzhiyun
1330*4882a593Smuzhiyun /* Send any queued vblank events, lest the natives grow disquiet */
1331*4882a593Smuzhiyun seq = drm_vblank_count_and_time(dev, pipe, &now);
1332*4882a593Smuzhiyun
1333*4882a593Smuzhiyun list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
1334*4882a593Smuzhiyun if (e->pipe != pipe)
1335*4882a593Smuzhiyun continue;
1336*4882a593Smuzhiyun drm_dbg_core(dev, "Sending premature vblank event on disable: "
1337*4882a593Smuzhiyun "wanted %llu, current %llu\n",
1338*4882a593Smuzhiyun e->sequence, seq);
1339*4882a593Smuzhiyun list_del(&e->base.link);
1340*4882a593Smuzhiyun drm_vblank_put(dev, pipe);
1341*4882a593Smuzhiyun send_vblank_event(dev, e, seq, now);
1342*4882a593Smuzhiyun }
1343*4882a593Smuzhiyun
1344*4882a593Smuzhiyun /* Cancel any leftover pending vblank work */
1345*4882a593Smuzhiyun drm_vblank_cancel_pending_works(vblank);
1346*4882a593Smuzhiyun
1347*4882a593Smuzhiyun spin_unlock_irq(&dev->event_lock);
1348*4882a593Smuzhiyun
1349*4882a593Smuzhiyun /* Will be reset by the modeset helpers when re-enabling the crtc by
1350*4882a593Smuzhiyun * calling drm_calc_timestamping_constants(). */
1351*4882a593Smuzhiyun vblank->hwmode.crtc_clock = 0;
1352*4882a593Smuzhiyun
1353*4882a593Smuzhiyun /* Wait for any vblank work that's still executing to finish */
1354*4882a593Smuzhiyun drm_vblank_flush_worker(vblank);
1355*4882a593Smuzhiyun }
1356*4882a593Smuzhiyun EXPORT_SYMBOL(drm_crtc_vblank_off);
1357*4882a593Smuzhiyun
1358*4882a593Smuzhiyun /**
1359*4882a593Smuzhiyun * drm_crtc_vblank_reset - reset vblank state to off on a CRTC
1360*4882a593Smuzhiyun * @crtc: CRTC in question
1361*4882a593Smuzhiyun *
1362*4882a593Smuzhiyun * Drivers can use this function to reset the vblank state to off at load time.
1363*4882a593Smuzhiyun * Drivers should use this together with the drm_crtc_vblank_off() and
1364*4882a593Smuzhiyun * drm_crtc_vblank_on() functions. The difference compared to
1365*4882a593Smuzhiyun * drm_crtc_vblank_off() is that this function doesn't save the vblank counter
1366*4882a593Smuzhiyun * and hence doesn't need to call any driver hooks.
1367*4882a593Smuzhiyun *
1368*4882a593Smuzhiyun * This is useful for recovering driver state e.g. on driver load, or on resume.
1369*4882a593Smuzhiyun */
drm_crtc_vblank_reset(struct drm_crtc * crtc)1370*4882a593Smuzhiyun void drm_crtc_vblank_reset(struct drm_crtc *crtc)
1371*4882a593Smuzhiyun {
1372*4882a593Smuzhiyun struct drm_device *dev = crtc->dev;
1373*4882a593Smuzhiyun unsigned int pipe = drm_crtc_index(crtc);
1374*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
1375*4882a593Smuzhiyun
1376*4882a593Smuzhiyun spin_lock_irq(&dev->vbl_lock);
1377*4882a593Smuzhiyun /*
1378*4882a593Smuzhiyun * Prevent subsequent drm_vblank_get() from enabling the vblank
1379*4882a593Smuzhiyun * interrupt by bumping the refcount.
1380*4882a593Smuzhiyun */
1381*4882a593Smuzhiyun if (!vblank->inmodeset) {
1382*4882a593Smuzhiyun atomic_inc(&vblank->refcount);
1383*4882a593Smuzhiyun vblank->inmodeset = 1;
1384*4882a593Smuzhiyun }
1385*4882a593Smuzhiyun spin_unlock_irq(&dev->vbl_lock);
1386*4882a593Smuzhiyun
1387*4882a593Smuzhiyun drm_WARN_ON(dev, !list_empty(&dev->vblank_event_list));
1388*4882a593Smuzhiyun drm_WARN_ON(dev, !list_empty(&vblank->pending_work));
1389*4882a593Smuzhiyun }
1390*4882a593Smuzhiyun EXPORT_SYMBOL(drm_crtc_vblank_reset);
1391*4882a593Smuzhiyun
1392*4882a593Smuzhiyun /**
1393*4882a593Smuzhiyun * drm_crtc_set_max_vblank_count - configure the hw max vblank counter value
1394*4882a593Smuzhiyun * @crtc: CRTC in question
1395*4882a593Smuzhiyun * @max_vblank_count: max hardware vblank counter value
1396*4882a593Smuzhiyun *
1397*4882a593Smuzhiyun * Update the maximum hardware vblank counter value for @crtc
1398*4882a593Smuzhiyun * at runtime. Useful for hardware where the operation of the
1399*4882a593Smuzhiyun * hardware vblank counter depends on the currently active
1400*4882a593Smuzhiyun * display configuration.
1401*4882a593Smuzhiyun *
1402*4882a593Smuzhiyun * For example, if the hardware vblank counter does not work
1403*4882a593Smuzhiyun * when a specific connector is active the maximum can be set
1404*4882a593Smuzhiyun * to zero. And when that specific connector isn't active the
1405*4882a593Smuzhiyun * maximum can again be set to the appropriate non-zero value.
1406*4882a593Smuzhiyun *
1407*4882a593Smuzhiyun * If used, must be called before drm_vblank_on().
1408*4882a593Smuzhiyun */
drm_crtc_set_max_vblank_count(struct drm_crtc * crtc,u32 max_vblank_count)1409*4882a593Smuzhiyun void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc,
1410*4882a593Smuzhiyun u32 max_vblank_count)
1411*4882a593Smuzhiyun {
1412*4882a593Smuzhiyun struct drm_device *dev = crtc->dev;
1413*4882a593Smuzhiyun unsigned int pipe = drm_crtc_index(crtc);
1414*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
1415*4882a593Smuzhiyun
1416*4882a593Smuzhiyun drm_WARN_ON(dev, dev->max_vblank_count);
1417*4882a593Smuzhiyun drm_WARN_ON(dev, !READ_ONCE(vblank->inmodeset));
1418*4882a593Smuzhiyun
1419*4882a593Smuzhiyun vblank->max_vblank_count = max_vblank_count;
1420*4882a593Smuzhiyun }
1421*4882a593Smuzhiyun EXPORT_SYMBOL(drm_crtc_set_max_vblank_count);
1422*4882a593Smuzhiyun
1423*4882a593Smuzhiyun /**
1424*4882a593Smuzhiyun * drm_crtc_vblank_on - enable vblank events on a CRTC
1425*4882a593Smuzhiyun * @crtc: CRTC in question
1426*4882a593Smuzhiyun *
1427*4882a593Smuzhiyun * This functions restores the vblank interrupt state captured with
1428*4882a593Smuzhiyun * drm_crtc_vblank_off() again and is generally called when enabling @crtc. Note
1429*4882a593Smuzhiyun * that calls to drm_crtc_vblank_on() and drm_crtc_vblank_off() can be
1430*4882a593Smuzhiyun * unbalanced and so can also be unconditionally called in driver load code to
1431*4882a593Smuzhiyun * reflect the current hardware state of the crtc.
1432*4882a593Smuzhiyun */
drm_crtc_vblank_on(struct drm_crtc * crtc)1433*4882a593Smuzhiyun void drm_crtc_vblank_on(struct drm_crtc *crtc)
1434*4882a593Smuzhiyun {
1435*4882a593Smuzhiyun struct drm_device *dev = crtc->dev;
1436*4882a593Smuzhiyun unsigned int pipe = drm_crtc_index(crtc);
1437*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
1438*4882a593Smuzhiyun
1439*4882a593Smuzhiyun if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
1440*4882a593Smuzhiyun return;
1441*4882a593Smuzhiyun
1442*4882a593Smuzhiyun spin_lock_irq(&dev->vbl_lock);
1443*4882a593Smuzhiyun drm_dbg_vbl(dev, "crtc %d, vblank enabled %d, inmodeset %d\n",
1444*4882a593Smuzhiyun pipe, vblank->enabled, vblank->inmodeset);
1445*4882a593Smuzhiyun
1446*4882a593Smuzhiyun /* Drop our private "prevent drm_vblank_get" refcount */
1447*4882a593Smuzhiyun if (vblank->inmodeset) {
1448*4882a593Smuzhiyun atomic_dec(&vblank->refcount);
1449*4882a593Smuzhiyun vblank->inmodeset = 0;
1450*4882a593Smuzhiyun }
1451*4882a593Smuzhiyun
1452*4882a593Smuzhiyun drm_reset_vblank_timestamp(dev, pipe);
1453*4882a593Smuzhiyun
1454*4882a593Smuzhiyun /*
1455*4882a593Smuzhiyun * re-enable interrupts if there are users left, or the
1456*4882a593Smuzhiyun * user wishes vblank interrupts to be enabled all the time.
1457*4882a593Smuzhiyun */
1458*4882a593Smuzhiyun if (atomic_read(&vblank->refcount) != 0 || drm_vblank_offdelay == 0)
1459*4882a593Smuzhiyun drm_WARN_ON(dev, drm_vblank_enable(dev, pipe));
1460*4882a593Smuzhiyun spin_unlock_irq(&dev->vbl_lock);
1461*4882a593Smuzhiyun }
1462*4882a593Smuzhiyun EXPORT_SYMBOL(drm_crtc_vblank_on);
1463*4882a593Smuzhiyun
1464*4882a593Smuzhiyun /**
1465*4882a593Smuzhiyun * drm_vblank_restore - estimate missed vblanks and update vblank count.
1466*4882a593Smuzhiyun * @dev: DRM device
1467*4882a593Smuzhiyun * @pipe: CRTC index
1468*4882a593Smuzhiyun *
1469*4882a593Smuzhiyun * Power manamement features can cause frame counter resets between vblank
1470*4882a593Smuzhiyun * disable and enable. Drivers can use this function in their
1471*4882a593Smuzhiyun * &drm_crtc_funcs.enable_vblank implementation to estimate missed vblanks since
1472*4882a593Smuzhiyun * the last &drm_crtc_funcs.disable_vblank using timestamps and update the
1473*4882a593Smuzhiyun * vblank counter.
1474*4882a593Smuzhiyun *
1475*4882a593Smuzhiyun * This function is the legacy version of drm_crtc_vblank_restore().
1476*4882a593Smuzhiyun */
drm_vblank_restore(struct drm_device * dev,unsigned int pipe)1477*4882a593Smuzhiyun void drm_vblank_restore(struct drm_device *dev, unsigned int pipe)
1478*4882a593Smuzhiyun {
1479*4882a593Smuzhiyun ktime_t t_vblank;
1480*4882a593Smuzhiyun struct drm_vblank_crtc *vblank;
1481*4882a593Smuzhiyun int framedur_ns;
1482*4882a593Smuzhiyun u64 diff_ns;
1483*4882a593Smuzhiyun u32 cur_vblank, diff = 1;
1484*4882a593Smuzhiyun int count = DRM_TIMESTAMP_MAXRETRIES;
1485*4882a593Smuzhiyun
1486*4882a593Smuzhiyun if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
1487*4882a593Smuzhiyun return;
1488*4882a593Smuzhiyun
1489*4882a593Smuzhiyun assert_spin_locked(&dev->vbl_lock);
1490*4882a593Smuzhiyun assert_spin_locked(&dev->vblank_time_lock);
1491*4882a593Smuzhiyun
1492*4882a593Smuzhiyun vblank = &dev->vblank[pipe];
1493*4882a593Smuzhiyun drm_WARN_ONCE(dev,
1494*4882a593Smuzhiyun drm_debug_enabled(DRM_UT_VBL) && !vblank->framedur_ns,
1495*4882a593Smuzhiyun "Cannot compute missed vblanks without frame duration\n");
1496*4882a593Smuzhiyun framedur_ns = vblank->framedur_ns;
1497*4882a593Smuzhiyun
1498*4882a593Smuzhiyun do {
1499*4882a593Smuzhiyun cur_vblank = __get_vblank_counter(dev, pipe);
1500*4882a593Smuzhiyun drm_get_last_vbltimestamp(dev, pipe, &t_vblank, false);
1501*4882a593Smuzhiyun } while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
1502*4882a593Smuzhiyun
1503*4882a593Smuzhiyun diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time));
1504*4882a593Smuzhiyun if (framedur_ns)
1505*4882a593Smuzhiyun diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns);
1506*4882a593Smuzhiyun
1507*4882a593Smuzhiyun
1508*4882a593Smuzhiyun drm_dbg_vbl(dev,
1509*4882a593Smuzhiyun "missed %d vblanks in %lld ns, frame duration=%d ns, hw_diff=%d\n",
1510*4882a593Smuzhiyun diff, diff_ns, framedur_ns, cur_vblank - vblank->last);
1511*4882a593Smuzhiyun store_vblank(dev, pipe, diff, t_vblank, cur_vblank);
1512*4882a593Smuzhiyun }
1513*4882a593Smuzhiyun EXPORT_SYMBOL(drm_vblank_restore);
1514*4882a593Smuzhiyun
1515*4882a593Smuzhiyun /**
1516*4882a593Smuzhiyun * drm_crtc_vblank_restore - estimate missed vblanks and update vblank count.
1517*4882a593Smuzhiyun * @crtc: CRTC in question
1518*4882a593Smuzhiyun *
1519*4882a593Smuzhiyun * Power manamement features can cause frame counter resets between vblank
1520*4882a593Smuzhiyun * disable and enable. Drivers can use this function in their
1521*4882a593Smuzhiyun * &drm_crtc_funcs.enable_vblank implementation to estimate missed vblanks since
1522*4882a593Smuzhiyun * the last &drm_crtc_funcs.disable_vblank using timestamps and update the
1523*4882a593Smuzhiyun * vblank counter.
1524*4882a593Smuzhiyun */
drm_crtc_vblank_restore(struct drm_crtc * crtc)1525*4882a593Smuzhiyun void drm_crtc_vblank_restore(struct drm_crtc *crtc)
1526*4882a593Smuzhiyun {
1527*4882a593Smuzhiyun drm_vblank_restore(crtc->dev, drm_crtc_index(crtc));
1528*4882a593Smuzhiyun }
1529*4882a593Smuzhiyun EXPORT_SYMBOL(drm_crtc_vblank_restore);
1530*4882a593Smuzhiyun
drm_legacy_vblank_pre_modeset(struct drm_device * dev,unsigned int pipe)1531*4882a593Smuzhiyun static void drm_legacy_vblank_pre_modeset(struct drm_device *dev,
1532*4882a593Smuzhiyun unsigned int pipe)
1533*4882a593Smuzhiyun {
1534*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
1535*4882a593Smuzhiyun
1536*4882a593Smuzhiyun /* vblank is not initialized (IRQ not installed ?), or has been freed */
1537*4882a593Smuzhiyun if (!drm_dev_has_vblank(dev))
1538*4882a593Smuzhiyun return;
1539*4882a593Smuzhiyun
1540*4882a593Smuzhiyun if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
1541*4882a593Smuzhiyun return;
1542*4882a593Smuzhiyun
1543*4882a593Smuzhiyun /*
1544*4882a593Smuzhiyun * To avoid all the problems that might happen if interrupts
1545*4882a593Smuzhiyun * were enabled/disabled around or between these calls, we just
1546*4882a593Smuzhiyun * have the kernel take a reference on the CRTC (just once though
1547*4882a593Smuzhiyun * to avoid corrupting the count if multiple, mismatch calls occur),
1548*4882a593Smuzhiyun * so that interrupts remain enabled in the interim.
1549*4882a593Smuzhiyun */
1550*4882a593Smuzhiyun if (!vblank->inmodeset) {
1551*4882a593Smuzhiyun vblank->inmodeset = 0x1;
1552*4882a593Smuzhiyun if (drm_vblank_get(dev, pipe) == 0)
1553*4882a593Smuzhiyun vblank->inmodeset |= 0x2;
1554*4882a593Smuzhiyun }
1555*4882a593Smuzhiyun }
1556*4882a593Smuzhiyun
drm_legacy_vblank_post_modeset(struct drm_device * dev,unsigned int pipe)1557*4882a593Smuzhiyun static void drm_legacy_vblank_post_modeset(struct drm_device *dev,
1558*4882a593Smuzhiyun unsigned int pipe)
1559*4882a593Smuzhiyun {
1560*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
1561*4882a593Smuzhiyun
1562*4882a593Smuzhiyun /* vblank is not initialized (IRQ not installed ?), or has been freed */
1563*4882a593Smuzhiyun if (!drm_dev_has_vblank(dev))
1564*4882a593Smuzhiyun return;
1565*4882a593Smuzhiyun
1566*4882a593Smuzhiyun if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
1567*4882a593Smuzhiyun return;
1568*4882a593Smuzhiyun
1569*4882a593Smuzhiyun if (vblank->inmodeset) {
1570*4882a593Smuzhiyun spin_lock_irq(&dev->vbl_lock);
1571*4882a593Smuzhiyun drm_reset_vblank_timestamp(dev, pipe);
1572*4882a593Smuzhiyun spin_unlock_irq(&dev->vbl_lock);
1573*4882a593Smuzhiyun
1574*4882a593Smuzhiyun if (vblank->inmodeset & 0x2)
1575*4882a593Smuzhiyun drm_vblank_put(dev, pipe);
1576*4882a593Smuzhiyun
1577*4882a593Smuzhiyun vblank->inmodeset = 0;
1578*4882a593Smuzhiyun }
1579*4882a593Smuzhiyun }
1580*4882a593Smuzhiyun
drm_legacy_modeset_ctl_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)1581*4882a593Smuzhiyun int drm_legacy_modeset_ctl_ioctl(struct drm_device *dev, void *data,
1582*4882a593Smuzhiyun struct drm_file *file_priv)
1583*4882a593Smuzhiyun {
1584*4882a593Smuzhiyun struct drm_modeset_ctl *modeset = data;
1585*4882a593Smuzhiyun unsigned int pipe;
1586*4882a593Smuzhiyun
1587*4882a593Smuzhiyun /* If drm_vblank_init() hasn't been called yet, just no-op */
1588*4882a593Smuzhiyun if (!drm_dev_has_vblank(dev))
1589*4882a593Smuzhiyun return 0;
1590*4882a593Smuzhiyun
1591*4882a593Smuzhiyun /* KMS drivers handle this internally */
1592*4882a593Smuzhiyun if (!drm_core_check_feature(dev, DRIVER_LEGACY))
1593*4882a593Smuzhiyun return 0;
1594*4882a593Smuzhiyun
1595*4882a593Smuzhiyun pipe = modeset->crtc;
1596*4882a593Smuzhiyun if (pipe >= dev->num_crtcs)
1597*4882a593Smuzhiyun return -EINVAL;
1598*4882a593Smuzhiyun
1599*4882a593Smuzhiyun switch (modeset->cmd) {
1600*4882a593Smuzhiyun case _DRM_PRE_MODESET:
1601*4882a593Smuzhiyun drm_legacy_vblank_pre_modeset(dev, pipe);
1602*4882a593Smuzhiyun break;
1603*4882a593Smuzhiyun case _DRM_POST_MODESET:
1604*4882a593Smuzhiyun drm_legacy_vblank_post_modeset(dev, pipe);
1605*4882a593Smuzhiyun break;
1606*4882a593Smuzhiyun default:
1607*4882a593Smuzhiyun return -EINVAL;
1608*4882a593Smuzhiyun }
1609*4882a593Smuzhiyun
1610*4882a593Smuzhiyun return 0;
1611*4882a593Smuzhiyun }
1612*4882a593Smuzhiyun
drm_queue_vblank_event(struct drm_device * dev,unsigned int pipe,u64 req_seq,union drm_wait_vblank * vblwait,struct drm_file * file_priv)1613*4882a593Smuzhiyun static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
1614*4882a593Smuzhiyun u64 req_seq,
1615*4882a593Smuzhiyun union drm_wait_vblank *vblwait,
1616*4882a593Smuzhiyun struct drm_file *file_priv)
1617*4882a593Smuzhiyun {
1618*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
1619*4882a593Smuzhiyun struct drm_pending_vblank_event *e;
1620*4882a593Smuzhiyun ktime_t now;
1621*4882a593Smuzhiyun u64 seq;
1622*4882a593Smuzhiyun int ret;
1623*4882a593Smuzhiyun
1624*4882a593Smuzhiyun e = kzalloc(sizeof(*e), GFP_KERNEL);
1625*4882a593Smuzhiyun if (e == NULL) {
1626*4882a593Smuzhiyun ret = -ENOMEM;
1627*4882a593Smuzhiyun goto err_put;
1628*4882a593Smuzhiyun }
1629*4882a593Smuzhiyun
1630*4882a593Smuzhiyun e->pipe = pipe;
1631*4882a593Smuzhiyun e->event.base.type = DRM_EVENT_VBLANK;
1632*4882a593Smuzhiyun e->event.base.length = sizeof(e->event.vbl);
1633*4882a593Smuzhiyun e->event.vbl.user_data = vblwait->request.signal;
1634*4882a593Smuzhiyun e->event.vbl.crtc_id = 0;
1635*4882a593Smuzhiyun if (drm_core_check_feature(dev, DRIVER_MODESET)) {
1636*4882a593Smuzhiyun struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
1637*4882a593Smuzhiyun
1638*4882a593Smuzhiyun if (crtc)
1639*4882a593Smuzhiyun e->event.vbl.crtc_id = crtc->base.id;
1640*4882a593Smuzhiyun }
1641*4882a593Smuzhiyun
1642*4882a593Smuzhiyun spin_lock_irq(&dev->event_lock);
1643*4882a593Smuzhiyun
1644*4882a593Smuzhiyun /*
1645*4882a593Smuzhiyun * drm_crtc_vblank_off() might have been called after we called
1646*4882a593Smuzhiyun * drm_vblank_get(). drm_crtc_vblank_off() holds event_lock around the
1647*4882a593Smuzhiyun * vblank disable, so no need for further locking. The reference from
1648*4882a593Smuzhiyun * drm_vblank_get() protects against vblank disable from another source.
1649*4882a593Smuzhiyun */
1650*4882a593Smuzhiyun if (!READ_ONCE(vblank->enabled)) {
1651*4882a593Smuzhiyun ret = -EINVAL;
1652*4882a593Smuzhiyun goto err_unlock;
1653*4882a593Smuzhiyun }
1654*4882a593Smuzhiyun
1655*4882a593Smuzhiyun ret = drm_event_reserve_init_locked(dev, file_priv, &e->base,
1656*4882a593Smuzhiyun &e->event.base);
1657*4882a593Smuzhiyun
1658*4882a593Smuzhiyun if (ret)
1659*4882a593Smuzhiyun goto err_unlock;
1660*4882a593Smuzhiyun
1661*4882a593Smuzhiyun seq = drm_vblank_count_and_time(dev, pipe, &now);
1662*4882a593Smuzhiyun
1663*4882a593Smuzhiyun drm_dbg_core(dev, "event on vblank count %llu, current %llu, crtc %u\n",
1664*4882a593Smuzhiyun req_seq, seq, pipe);
1665*4882a593Smuzhiyun
1666*4882a593Smuzhiyun trace_drm_vblank_event_queued(file_priv, pipe, req_seq);
1667*4882a593Smuzhiyun
1668*4882a593Smuzhiyun e->sequence = req_seq;
1669*4882a593Smuzhiyun if (drm_vblank_passed(seq, req_seq)) {
1670*4882a593Smuzhiyun drm_vblank_put(dev, pipe);
1671*4882a593Smuzhiyun send_vblank_event(dev, e, seq, now);
1672*4882a593Smuzhiyun vblwait->reply.sequence = seq;
1673*4882a593Smuzhiyun } else {
1674*4882a593Smuzhiyun /* drm_handle_vblank_events will call drm_vblank_put */
1675*4882a593Smuzhiyun list_add_tail(&e->base.link, &dev->vblank_event_list);
1676*4882a593Smuzhiyun vblwait->reply.sequence = req_seq;
1677*4882a593Smuzhiyun }
1678*4882a593Smuzhiyun
1679*4882a593Smuzhiyun spin_unlock_irq(&dev->event_lock);
1680*4882a593Smuzhiyun
1681*4882a593Smuzhiyun return 0;
1682*4882a593Smuzhiyun
1683*4882a593Smuzhiyun err_unlock:
1684*4882a593Smuzhiyun spin_unlock_irq(&dev->event_lock);
1685*4882a593Smuzhiyun kfree(e);
1686*4882a593Smuzhiyun err_put:
1687*4882a593Smuzhiyun drm_vblank_put(dev, pipe);
1688*4882a593Smuzhiyun return ret;
1689*4882a593Smuzhiyun }
1690*4882a593Smuzhiyun
drm_wait_vblank_is_query(union drm_wait_vblank * vblwait)1691*4882a593Smuzhiyun static bool drm_wait_vblank_is_query(union drm_wait_vblank *vblwait)
1692*4882a593Smuzhiyun {
1693*4882a593Smuzhiyun if (vblwait->request.sequence)
1694*4882a593Smuzhiyun return false;
1695*4882a593Smuzhiyun
1696*4882a593Smuzhiyun return _DRM_VBLANK_RELATIVE ==
1697*4882a593Smuzhiyun (vblwait->request.type & (_DRM_VBLANK_TYPES_MASK |
1698*4882a593Smuzhiyun _DRM_VBLANK_EVENT |
1699*4882a593Smuzhiyun _DRM_VBLANK_NEXTONMISS));
1700*4882a593Smuzhiyun }
1701*4882a593Smuzhiyun
1702*4882a593Smuzhiyun /*
1703*4882a593Smuzhiyun * Widen a 32-bit param to 64-bits.
1704*4882a593Smuzhiyun *
1705*4882a593Smuzhiyun * \param narrow 32-bit value (missing upper 32 bits)
1706*4882a593Smuzhiyun * \param near 64-bit value that should be 'close' to near
1707*4882a593Smuzhiyun *
1708*4882a593Smuzhiyun * This function returns a 64-bit value using the lower 32-bits from
1709*4882a593Smuzhiyun * 'narrow' and constructing the upper 32-bits so that the result is
1710*4882a593Smuzhiyun * as close as possible to 'near'.
1711*4882a593Smuzhiyun */
1712*4882a593Smuzhiyun
widen_32_to_64(u32 narrow,u64 near)1713*4882a593Smuzhiyun static u64 widen_32_to_64(u32 narrow, u64 near)
1714*4882a593Smuzhiyun {
1715*4882a593Smuzhiyun return near + (s32) (narrow - near);
1716*4882a593Smuzhiyun }
1717*4882a593Smuzhiyun
drm_wait_vblank_reply(struct drm_device * dev,unsigned int pipe,struct drm_wait_vblank_reply * reply)1718*4882a593Smuzhiyun static void drm_wait_vblank_reply(struct drm_device *dev, unsigned int pipe,
1719*4882a593Smuzhiyun struct drm_wait_vblank_reply *reply)
1720*4882a593Smuzhiyun {
1721*4882a593Smuzhiyun ktime_t now;
1722*4882a593Smuzhiyun struct timespec64 ts;
1723*4882a593Smuzhiyun
1724*4882a593Smuzhiyun /*
1725*4882a593Smuzhiyun * drm_wait_vblank_reply is a UAPI structure that uses 'long'
1726*4882a593Smuzhiyun * to store the seconds. This is safe as we always use monotonic
1727*4882a593Smuzhiyun * timestamps since linux-4.15.
1728*4882a593Smuzhiyun */
1729*4882a593Smuzhiyun reply->sequence = drm_vblank_count_and_time(dev, pipe, &now);
1730*4882a593Smuzhiyun ts = ktime_to_timespec64(now);
1731*4882a593Smuzhiyun reply->tval_sec = (u32)ts.tv_sec;
1732*4882a593Smuzhiyun reply->tval_usec = ts.tv_nsec / 1000;
1733*4882a593Smuzhiyun }
1734*4882a593Smuzhiyun
drm_wait_vblank_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)1735*4882a593Smuzhiyun int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
1736*4882a593Smuzhiyun struct drm_file *file_priv)
1737*4882a593Smuzhiyun {
1738*4882a593Smuzhiyun struct drm_crtc *crtc;
1739*4882a593Smuzhiyun struct drm_vblank_crtc *vblank;
1740*4882a593Smuzhiyun union drm_wait_vblank *vblwait = data;
1741*4882a593Smuzhiyun int ret;
1742*4882a593Smuzhiyun u64 req_seq, seq;
1743*4882a593Smuzhiyun unsigned int pipe_index;
1744*4882a593Smuzhiyun unsigned int flags, pipe, high_pipe;
1745*4882a593Smuzhiyun
1746*4882a593Smuzhiyun if (!dev->irq_enabled)
1747*4882a593Smuzhiyun return -EOPNOTSUPP;
1748*4882a593Smuzhiyun
1749*4882a593Smuzhiyun if (vblwait->request.type & _DRM_VBLANK_SIGNAL)
1750*4882a593Smuzhiyun return -EINVAL;
1751*4882a593Smuzhiyun
1752*4882a593Smuzhiyun if (vblwait->request.type &
1753*4882a593Smuzhiyun ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK |
1754*4882a593Smuzhiyun _DRM_VBLANK_HIGH_CRTC_MASK)) {
1755*4882a593Smuzhiyun drm_dbg_core(dev,
1756*4882a593Smuzhiyun "Unsupported type value 0x%x, supported mask 0x%x\n",
1757*4882a593Smuzhiyun vblwait->request.type,
1758*4882a593Smuzhiyun (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK |
1759*4882a593Smuzhiyun _DRM_VBLANK_HIGH_CRTC_MASK));
1760*4882a593Smuzhiyun return -EINVAL;
1761*4882a593Smuzhiyun }
1762*4882a593Smuzhiyun
1763*4882a593Smuzhiyun flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
1764*4882a593Smuzhiyun high_pipe = (vblwait->request.type & _DRM_VBLANK_HIGH_CRTC_MASK);
1765*4882a593Smuzhiyun if (high_pipe)
1766*4882a593Smuzhiyun pipe_index = high_pipe >> _DRM_VBLANK_HIGH_CRTC_SHIFT;
1767*4882a593Smuzhiyun else
1768*4882a593Smuzhiyun pipe_index = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
1769*4882a593Smuzhiyun
1770*4882a593Smuzhiyun /* Convert lease-relative crtc index into global crtc index */
1771*4882a593Smuzhiyun if (drm_core_check_feature(dev, DRIVER_MODESET)) {
1772*4882a593Smuzhiyun pipe = 0;
1773*4882a593Smuzhiyun drm_for_each_crtc(crtc, dev) {
1774*4882a593Smuzhiyun if (drm_lease_held(file_priv, crtc->base.id)) {
1775*4882a593Smuzhiyun if (pipe_index == 0)
1776*4882a593Smuzhiyun break;
1777*4882a593Smuzhiyun pipe_index--;
1778*4882a593Smuzhiyun }
1779*4882a593Smuzhiyun pipe++;
1780*4882a593Smuzhiyun }
1781*4882a593Smuzhiyun } else {
1782*4882a593Smuzhiyun pipe = pipe_index;
1783*4882a593Smuzhiyun }
1784*4882a593Smuzhiyun
1785*4882a593Smuzhiyun if (pipe >= dev->num_crtcs)
1786*4882a593Smuzhiyun return -EINVAL;
1787*4882a593Smuzhiyun
1788*4882a593Smuzhiyun vblank = &dev->vblank[pipe];
1789*4882a593Smuzhiyun
1790*4882a593Smuzhiyun /* If the counter is currently enabled and accurate, short-circuit
1791*4882a593Smuzhiyun * queries to return the cached timestamp of the last vblank.
1792*4882a593Smuzhiyun */
1793*4882a593Smuzhiyun if (dev->vblank_disable_immediate &&
1794*4882a593Smuzhiyun drm_wait_vblank_is_query(vblwait) &&
1795*4882a593Smuzhiyun READ_ONCE(vblank->enabled)) {
1796*4882a593Smuzhiyun drm_wait_vblank_reply(dev, pipe, &vblwait->reply);
1797*4882a593Smuzhiyun return 0;
1798*4882a593Smuzhiyun }
1799*4882a593Smuzhiyun
1800*4882a593Smuzhiyun ret = drm_vblank_get(dev, pipe);
1801*4882a593Smuzhiyun if (ret) {
1802*4882a593Smuzhiyun drm_dbg_core(dev,
1803*4882a593Smuzhiyun "crtc %d failed to acquire vblank counter, %d\n",
1804*4882a593Smuzhiyun pipe, ret);
1805*4882a593Smuzhiyun return ret;
1806*4882a593Smuzhiyun }
1807*4882a593Smuzhiyun seq = drm_vblank_count(dev, pipe);
1808*4882a593Smuzhiyun
1809*4882a593Smuzhiyun switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
1810*4882a593Smuzhiyun case _DRM_VBLANK_RELATIVE:
1811*4882a593Smuzhiyun req_seq = seq + vblwait->request.sequence;
1812*4882a593Smuzhiyun vblwait->request.sequence = req_seq;
1813*4882a593Smuzhiyun vblwait->request.type &= ~_DRM_VBLANK_RELATIVE;
1814*4882a593Smuzhiyun break;
1815*4882a593Smuzhiyun case _DRM_VBLANK_ABSOLUTE:
1816*4882a593Smuzhiyun req_seq = widen_32_to_64(vblwait->request.sequence, seq);
1817*4882a593Smuzhiyun break;
1818*4882a593Smuzhiyun default:
1819*4882a593Smuzhiyun ret = -EINVAL;
1820*4882a593Smuzhiyun goto done;
1821*4882a593Smuzhiyun }
1822*4882a593Smuzhiyun
1823*4882a593Smuzhiyun if ((flags & _DRM_VBLANK_NEXTONMISS) &&
1824*4882a593Smuzhiyun drm_vblank_passed(seq, req_seq)) {
1825*4882a593Smuzhiyun req_seq = seq + 1;
1826*4882a593Smuzhiyun vblwait->request.type &= ~_DRM_VBLANK_NEXTONMISS;
1827*4882a593Smuzhiyun vblwait->request.sequence = req_seq;
1828*4882a593Smuzhiyun }
1829*4882a593Smuzhiyun
1830*4882a593Smuzhiyun if (flags & _DRM_VBLANK_EVENT) {
1831*4882a593Smuzhiyun /* must hold on to the vblank ref until the event fires
1832*4882a593Smuzhiyun * drm_vblank_put will be called asynchronously
1833*4882a593Smuzhiyun */
1834*4882a593Smuzhiyun return drm_queue_vblank_event(dev, pipe, req_seq, vblwait, file_priv);
1835*4882a593Smuzhiyun }
1836*4882a593Smuzhiyun
1837*4882a593Smuzhiyun if (req_seq != seq) {
1838*4882a593Smuzhiyun int wait;
1839*4882a593Smuzhiyun
1840*4882a593Smuzhiyun drm_dbg_core(dev, "waiting on vblank count %llu, crtc %u\n",
1841*4882a593Smuzhiyun req_seq, pipe);
1842*4882a593Smuzhiyun wait = wait_event_interruptible_timeout(vblank->queue,
1843*4882a593Smuzhiyun drm_vblank_passed(drm_vblank_count(dev, pipe), req_seq) ||
1844*4882a593Smuzhiyun !READ_ONCE(vblank->enabled),
1845*4882a593Smuzhiyun msecs_to_jiffies(3000));
1846*4882a593Smuzhiyun
1847*4882a593Smuzhiyun switch (wait) {
1848*4882a593Smuzhiyun case 0:
1849*4882a593Smuzhiyun /* timeout */
1850*4882a593Smuzhiyun ret = -EBUSY;
1851*4882a593Smuzhiyun break;
1852*4882a593Smuzhiyun case -ERESTARTSYS:
1853*4882a593Smuzhiyun /* interrupted by signal */
1854*4882a593Smuzhiyun ret = -EINTR;
1855*4882a593Smuzhiyun break;
1856*4882a593Smuzhiyun default:
1857*4882a593Smuzhiyun ret = 0;
1858*4882a593Smuzhiyun break;
1859*4882a593Smuzhiyun }
1860*4882a593Smuzhiyun }
1861*4882a593Smuzhiyun
1862*4882a593Smuzhiyun if (ret != -EINTR) {
1863*4882a593Smuzhiyun drm_wait_vblank_reply(dev, pipe, &vblwait->reply);
1864*4882a593Smuzhiyun
1865*4882a593Smuzhiyun drm_dbg_core(dev, "crtc %d returning %u to client\n",
1866*4882a593Smuzhiyun pipe, vblwait->reply.sequence);
1867*4882a593Smuzhiyun } else {
1868*4882a593Smuzhiyun drm_dbg_core(dev, "crtc %d vblank wait interrupted by signal\n",
1869*4882a593Smuzhiyun pipe);
1870*4882a593Smuzhiyun }
1871*4882a593Smuzhiyun
1872*4882a593Smuzhiyun done:
1873*4882a593Smuzhiyun drm_vblank_put(dev, pipe);
1874*4882a593Smuzhiyun return ret;
1875*4882a593Smuzhiyun }
1876*4882a593Smuzhiyun
drm_handle_vblank_events(struct drm_device * dev,unsigned int pipe)1877*4882a593Smuzhiyun static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe)
1878*4882a593Smuzhiyun {
1879*4882a593Smuzhiyun struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe);
1880*4882a593Smuzhiyun bool high_prec = false;
1881*4882a593Smuzhiyun struct drm_pending_vblank_event *e, *t;
1882*4882a593Smuzhiyun ktime_t now;
1883*4882a593Smuzhiyun u64 seq;
1884*4882a593Smuzhiyun
1885*4882a593Smuzhiyun assert_spin_locked(&dev->event_lock);
1886*4882a593Smuzhiyun
1887*4882a593Smuzhiyun seq = drm_vblank_count_and_time(dev, pipe, &now);
1888*4882a593Smuzhiyun
1889*4882a593Smuzhiyun list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
1890*4882a593Smuzhiyun if (e->pipe != pipe)
1891*4882a593Smuzhiyun continue;
1892*4882a593Smuzhiyun if (!drm_vblank_passed(seq, e->sequence))
1893*4882a593Smuzhiyun continue;
1894*4882a593Smuzhiyun
1895*4882a593Smuzhiyun drm_dbg_core(dev, "vblank event on %llu, current %llu\n",
1896*4882a593Smuzhiyun e->sequence, seq);
1897*4882a593Smuzhiyun
1898*4882a593Smuzhiyun list_del(&e->base.link);
1899*4882a593Smuzhiyun drm_vblank_put(dev, pipe);
1900*4882a593Smuzhiyun send_vblank_event(dev, e, seq, now);
1901*4882a593Smuzhiyun }
1902*4882a593Smuzhiyun
1903*4882a593Smuzhiyun if (crtc && crtc->funcs->get_vblank_timestamp)
1904*4882a593Smuzhiyun high_prec = true;
1905*4882a593Smuzhiyun
1906*4882a593Smuzhiyun trace_drm_vblank_event(pipe, seq, now, high_prec);
1907*4882a593Smuzhiyun }
1908*4882a593Smuzhiyun
1909*4882a593Smuzhiyun /**
1910*4882a593Smuzhiyun * drm_handle_vblank - handle a vblank event
1911*4882a593Smuzhiyun * @dev: DRM device
1912*4882a593Smuzhiyun * @pipe: index of CRTC where this event occurred
1913*4882a593Smuzhiyun *
1914*4882a593Smuzhiyun * Drivers should call this routine in their vblank interrupt handlers to
1915*4882a593Smuzhiyun * update the vblank counter and send any signals that may be pending.
1916*4882a593Smuzhiyun *
1917*4882a593Smuzhiyun * This is the legacy version of drm_crtc_handle_vblank().
1918*4882a593Smuzhiyun */
drm_handle_vblank(struct drm_device * dev,unsigned int pipe)1919*4882a593Smuzhiyun bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe)
1920*4882a593Smuzhiyun {
1921*4882a593Smuzhiyun struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
1922*4882a593Smuzhiyun unsigned long irqflags;
1923*4882a593Smuzhiyun bool disable_irq;
1924*4882a593Smuzhiyun
1925*4882a593Smuzhiyun if (drm_WARN_ON_ONCE(dev, !drm_dev_has_vblank(dev)))
1926*4882a593Smuzhiyun return false;
1927*4882a593Smuzhiyun
1928*4882a593Smuzhiyun if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
1929*4882a593Smuzhiyun return false;
1930*4882a593Smuzhiyun
1931*4882a593Smuzhiyun spin_lock_irqsave(&dev->event_lock, irqflags);
1932*4882a593Smuzhiyun
1933*4882a593Smuzhiyun /* Need timestamp lock to prevent concurrent execution with
1934*4882a593Smuzhiyun * vblank enable/disable, as this would cause inconsistent
1935*4882a593Smuzhiyun * or corrupted timestamps and vblank counts.
1936*4882a593Smuzhiyun */
1937*4882a593Smuzhiyun spin_lock(&dev->vblank_time_lock);
1938*4882a593Smuzhiyun
1939*4882a593Smuzhiyun /* Vblank irq handling disabled. Nothing to do. */
1940*4882a593Smuzhiyun if (!vblank->enabled) {
1941*4882a593Smuzhiyun spin_unlock(&dev->vblank_time_lock);
1942*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->event_lock, irqflags);
1943*4882a593Smuzhiyun return false;
1944*4882a593Smuzhiyun }
1945*4882a593Smuzhiyun
1946*4882a593Smuzhiyun drm_update_vblank_count(dev, pipe, true);
1947*4882a593Smuzhiyun
1948*4882a593Smuzhiyun spin_unlock(&dev->vblank_time_lock);
1949*4882a593Smuzhiyun
1950*4882a593Smuzhiyun wake_up(&vblank->queue);
1951*4882a593Smuzhiyun
1952*4882a593Smuzhiyun /* With instant-off, we defer disabling the interrupt until after
1953*4882a593Smuzhiyun * we finish processing the following vblank after all events have
1954*4882a593Smuzhiyun * been signaled. The disable has to be last (after
1955*4882a593Smuzhiyun * drm_handle_vblank_events) so that the timestamp is always accurate.
1956*4882a593Smuzhiyun */
1957*4882a593Smuzhiyun disable_irq = (dev->vblank_disable_immediate &&
1958*4882a593Smuzhiyun drm_vblank_offdelay > 0 &&
1959*4882a593Smuzhiyun !atomic_read(&vblank->refcount));
1960*4882a593Smuzhiyun
1961*4882a593Smuzhiyun drm_handle_vblank_events(dev, pipe);
1962*4882a593Smuzhiyun drm_handle_vblank_works(vblank);
1963*4882a593Smuzhiyun
1964*4882a593Smuzhiyun spin_unlock_irqrestore(&dev->event_lock, irqflags);
1965*4882a593Smuzhiyun
1966*4882a593Smuzhiyun if (disable_irq)
1967*4882a593Smuzhiyun vblank_disable_fn(&vblank->disable_timer);
1968*4882a593Smuzhiyun
1969*4882a593Smuzhiyun return true;
1970*4882a593Smuzhiyun }
1971*4882a593Smuzhiyun EXPORT_SYMBOL(drm_handle_vblank);
1972*4882a593Smuzhiyun
1973*4882a593Smuzhiyun /**
1974*4882a593Smuzhiyun * drm_crtc_handle_vblank - handle a vblank event
1975*4882a593Smuzhiyun * @crtc: where this event occurred
1976*4882a593Smuzhiyun *
1977*4882a593Smuzhiyun * Drivers should call this routine in their vblank interrupt handlers to
1978*4882a593Smuzhiyun * update the vblank counter and send any signals that may be pending.
1979*4882a593Smuzhiyun *
1980*4882a593Smuzhiyun * This is the native KMS version of drm_handle_vblank().
1981*4882a593Smuzhiyun *
1982*4882a593Smuzhiyun * Note that for a given vblank counter value drm_crtc_handle_vblank()
1983*4882a593Smuzhiyun * and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time()
1984*4882a593Smuzhiyun * provide a barrier: Any writes done before calling
1985*4882a593Smuzhiyun * drm_crtc_handle_vblank() will be visible to callers of the later
1986*4882a593Smuzhiyun * functions, iff the vblank count is the same or a later one.
1987*4882a593Smuzhiyun *
1988*4882a593Smuzhiyun * See also &drm_vblank_crtc.count.
1989*4882a593Smuzhiyun *
1990*4882a593Smuzhiyun * Returns:
1991*4882a593Smuzhiyun * True if the event was successfully handled, false on failure.
1992*4882a593Smuzhiyun */
drm_crtc_handle_vblank(struct drm_crtc * crtc)1993*4882a593Smuzhiyun bool drm_crtc_handle_vblank(struct drm_crtc *crtc)
1994*4882a593Smuzhiyun {
1995*4882a593Smuzhiyun return drm_handle_vblank(crtc->dev, drm_crtc_index(crtc));
1996*4882a593Smuzhiyun }
1997*4882a593Smuzhiyun EXPORT_SYMBOL(drm_crtc_handle_vblank);
1998*4882a593Smuzhiyun
1999*4882a593Smuzhiyun /*
2000*4882a593Smuzhiyun * Get crtc VBLANK count.
2001*4882a593Smuzhiyun *
2002*4882a593Smuzhiyun * \param dev DRM device
2003*4882a593Smuzhiyun * \param data user arguement, pointing to a drm_crtc_get_sequence structure.
2004*4882a593Smuzhiyun * \param file_priv drm file private for the user's open file descriptor
2005*4882a593Smuzhiyun */
2006*4882a593Smuzhiyun
drm_crtc_get_sequence_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)2007*4882a593Smuzhiyun int drm_crtc_get_sequence_ioctl(struct drm_device *dev, void *data,
2008*4882a593Smuzhiyun struct drm_file *file_priv)
2009*4882a593Smuzhiyun {
2010*4882a593Smuzhiyun struct drm_crtc *crtc;
2011*4882a593Smuzhiyun struct drm_vblank_crtc *vblank;
2012*4882a593Smuzhiyun int pipe;
2013*4882a593Smuzhiyun struct drm_crtc_get_sequence *get_seq = data;
2014*4882a593Smuzhiyun ktime_t now;
2015*4882a593Smuzhiyun bool vblank_enabled;
2016*4882a593Smuzhiyun int ret;
2017*4882a593Smuzhiyun
2018*4882a593Smuzhiyun if (!drm_core_check_feature(dev, DRIVER_MODESET))
2019*4882a593Smuzhiyun return -EOPNOTSUPP;
2020*4882a593Smuzhiyun
2021*4882a593Smuzhiyun if (!dev->irq_enabled)
2022*4882a593Smuzhiyun return -EOPNOTSUPP;
2023*4882a593Smuzhiyun
2024*4882a593Smuzhiyun crtc = drm_crtc_find(dev, file_priv, get_seq->crtc_id);
2025*4882a593Smuzhiyun if (!crtc)
2026*4882a593Smuzhiyun return -ENOENT;
2027*4882a593Smuzhiyun
2028*4882a593Smuzhiyun pipe = drm_crtc_index(crtc);
2029*4882a593Smuzhiyun
2030*4882a593Smuzhiyun vblank = &dev->vblank[pipe];
2031*4882a593Smuzhiyun vblank_enabled = dev->vblank_disable_immediate && READ_ONCE(vblank->enabled);
2032*4882a593Smuzhiyun
2033*4882a593Smuzhiyun if (!vblank_enabled) {
2034*4882a593Smuzhiyun ret = drm_crtc_vblank_get(crtc);
2035*4882a593Smuzhiyun if (ret) {
2036*4882a593Smuzhiyun drm_dbg_core(dev,
2037*4882a593Smuzhiyun "crtc %d failed to acquire vblank counter, %d\n",
2038*4882a593Smuzhiyun pipe, ret);
2039*4882a593Smuzhiyun return ret;
2040*4882a593Smuzhiyun }
2041*4882a593Smuzhiyun }
2042*4882a593Smuzhiyun drm_modeset_lock(&crtc->mutex, NULL);
2043*4882a593Smuzhiyun if (crtc->state)
2044*4882a593Smuzhiyun get_seq->active = crtc->state->enable;
2045*4882a593Smuzhiyun else
2046*4882a593Smuzhiyun get_seq->active = crtc->enabled;
2047*4882a593Smuzhiyun drm_modeset_unlock(&crtc->mutex);
2048*4882a593Smuzhiyun get_seq->sequence = drm_vblank_count_and_time(dev, pipe, &now);
2049*4882a593Smuzhiyun get_seq->sequence_ns = ktime_to_ns(now);
2050*4882a593Smuzhiyun if (!vblank_enabled)
2051*4882a593Smuzhiyun drm_crtc_vblank_put(crtc);
2052*4882a593Smuzhiyun return 0;
2053*4882a593Smuzhiyun }
2054*4882a593Smuzhiyun
2055*4882a593Smuzhiyun /*
2056*4882a593Smuzhiyun * Queue a event for VBLANK sequence
2057*4882a593Smuzhiyun *
2058*4882a593Smuzhiyun * \param dev DRM device
2059*4882a593Smuzhiyun * \param data user arguement, pointing to a drm_crtc_queue_sequence structure.
2060*4882a593Smuzhiyun * \param file_priv drm file private for the user's open file descriptor
2061*4882a593Smuzhiyun */
2062*4882a593Smuzhiyun
drm_crtc_queue_sequence_ioctl(struct drm_device * dev,void * data,struct drm_file * file_priv)2063*4882a593Smuzhiyun int drm_crtc_queue_sequence_ioctl(struct drm_device *dev, void *data,
2064*4882a593Smuzhiyun struct drm_file *file_priv)
2065*4882a593Smuzhiyun {
2066*4882a593Smuzhiyun struct drm_crtc *crtc;
2067*4882a593Smuzhiyun struct drm_vblank_crtc *vblank;
2068*4882a593Smuzhiyun int pipe;
2069*4882a593Smuzhiyun struct drm_crtc_queue_sequence *queue_seq = data;
2070*4882a593Smuzhiyun ktime_t now;
2071*4882a593Smuzhiyun struct drm_pending_vblank_event *e;
2072*4882a593Smuzhiyun u32 flags;
2073*4882a593Smuzhiyun u64 seq;
2074*4882a593Smuzhiyun u64 req_seq;
2075*4882a593Smuzhiyun int ret;
2076*4882a593Smuzhiyun
2077*4882a593Smuzhiyun if (!drm_core_check_feature(dev, DRIVER_MODESET))
2078*4882a593Smuzhiyun return -EOPNOTSUPP;
2079*4882a593Smuzhiyun
2080*4882a593Smuzhiyun if (!dev->irq_enabled)
2081*4882a593Smuzhiyun return -EOPNOTSUPP;
2082*4882a593Smuzhiyun
2083*4882a593Smuzhiyun crtc = drm_crtc_find(dev, file_priv, queue_seq->crtc_id);
2084*4882a593Smuzhiyun if (!crtc)
2085*4882a593Smuzhiyun return -ENOENT;
2086*4882a593Smuzhiyun
2087*4882a593Smuzhiyun flags = queue_seq->flags;
2088*4882a593Smuzhiyun /* Check valid flag bits */
2089*4882a593Smuzhiyun if (flags & ~(DRM_CRTC_SEQUENCE_RELATIVE|
2090*4882a593Smuzhiyun DRM_CRTC_SEQUENCE_NEXT_ON_MISS))
2091*4882a593Smuzhiyun return -EINVAL;
2092*4882a593Smuzhiyun
2093*4882a593Smuzhiyun pipe = drm_crtc_index(crtc);
2094*4882a593Smuzhiyun
2095*4882a593Smuzhiyun vblank = &dev->vblank[pipe];
2096*4882a593Smuzhiyun
2097*4882a593Smuzhiyun e = kzalloc(sizeof(*e), GFP_KERNEL);
2098*4882a593Smuzhiyun if (e == NULL)
2099*4882a593Smuzhiyun return -ENOMEM;
2100*4882a593Smuzhiyun
2101*4882a593Smuzhiyun ret = drm_crtc_vblank_get(crtc);
2102*4882a593Smuzhiyun if (ret) {
2103*4882a593Smuzhiyun drm_dbg_core(dev,
2104*4882a593Smuzhiyun "crtc %d failed to acquire vblank counter, %d\n",
2105*4882a593Smuzhiyun pipe, ret);
2106*4882a593Smuzhiyun goto err_free;
2107*4882a593Smuzhiyun }
2108*4882a593Smuzhiyun
2109*4882a593Smuzhiyun seq = drm_vblank_count_and_time(dev, pipe, &now);
2110*4882a593Smuzhiyun req_seq = queue_seq->sequence;
2111*4882a593Smuzhiyun
2112*4882a593Smuzhiyun if (flags & DRM_CRTC_SEQUENCE_RELATIVE)
2113*4882a593Smuzhiyun req_seq += seq;
2114*4882a593Smuzhiyun
2115*4882a593Smuzhiyun if ((flags & DRM_CRTC_SEQUENCE_NEXT_ON_MISS) && drm_vblank_passed(seq, req_seq))
2116*4882a593Smuzhiyun req_seq = seq + 1;
2117*4882a593Smuzhiyun
2118*4882a593Smuzhiyun e->pipe = pipe;
2119*4882a593Smuzhiyun e->event.base.type = DRM_EVENT_CRTC_SEQUENCE;
2120*4882a593Smuzhiyun e->event.base.length = sizeof(e->event.seq);
2121*4882a593Smuzhiyun e->event.seq.user_data = queue_seq->user_data;
2122*4882a593Smuzhiyun
2123*4882a593Smuzhiyun spin_lock_irq(&dev->event_lock);
2124*4882a593Smuzhiyun
2125*4882a593Smuzhiyun /*
2126*4882a593Smuzhiyun * drm_crtc_vblank_off() might have been called after we called
2127*4882a593Smuzhiyun * drm_crtc_vblank_get(). drm_crtc_vblank_off() holds event_lock around the
2128*4882a593Smuzhiyun * vblank disable, so no need for further locking. The reference from
2129*4882a593Smuzhiyun * drm_crtc_vblank_get() protects against vblank disable from another source.
2130*4882a593Smuzhiyun */
2131*4882a593Smuzhiyun if (!READ_ONCE(vblank->enabled)) {
2132*4882a593Smuzhiyun ret = -EINVAL;
2133*4882a593Smuzhiyun goto err_unlock;
2134*4882a593Smuzhiyun }
2135*4882a593Smuzhiyun
2136*4882a593Smuzhiyun ret = drm_event_reserve_init_locked(dev, file_priv, &e->base,
2137*4882a593Smuzhiyun &e->event.base);
2138*4882a593Smuzhiyun
2139*4882a593Smuzhiyun if (ret)
2140*4882a593Smuzhiyun goto err_unlock;
2141*4882a593Smuzhiyun
2142*4882a593Smuzhiyun e->sequence = req_seq;
2143*4882a593Smuzhiyun
2144*4882a593Smuzhiyun if (drm_vblank_passed(seq, req_seq)) {
2145*4882a593Smuzhiyun drm_crtc_vblank_put(crtc);
2146*4882a593Smuzhiyun send_vblank_event(dev, e, seq, now);
2147*4882a593Smuzhiyun queue_seq->sequence = seq;
2148*4882a593Smuzhiyun } else {
2149*4882a593Smuzhiyun /* drm_handle_vblank_events will call drm_vblank_put */
2150*4882a593Smuzhiyun list_add_tail(&e->base.link, &dev->vblank_event_list);
2151*4882a593Smuzhiyun queue_seq->sequence = req_seq;
2152*4882a593Smuzhiyun }
2153*4882a593Smuzhiyun
2154*4882a593Smuzhiyun spin_unlock_irq(&dev->event_lock);
2155*4882a593Smuzhiyun return 0;
2156*4882a593Smuzhiyun
2157*4882a593Smuzhiyun err_unlock:
2158*4882a593Smuzhiyun spin_unlock_irq(&dev->event_lock);
2159*4882a593Smuzhiyun drm_crtc_vblank_put(crtc);
2160*4882a593Smuzhiyun err_free:
2161*4882a593Smuzhiyun kfree(e);
2162*4882a593Smuzhiyun return ret;
2163*4882a593Smuzhiyun }
2164*4882a593Smuzhiyun
2165