1 // SPDX-License-Identifier: MIT
2
3 #include <drm/drm_atomic.h>
4 #include <drm/drm_crtc.h>
5 #include <drm/drm_managed.h>
6 #include <drm/drm_modeset_helper_vtables.h>
7 #include <drm/drm_print.h>
8 #include <drm/drm_vblank.h>
9 #include <drm/drm_vblank_helper.h>
10
11 /**
12 * DOC: overview
13 *
14 * The vblank helper library provides functions for supporting vertical
15 * blanking in DRM drivers.
16 *
17 * For vblank timers, several callback implementations are available.
18 * Drivers enable support for vblank timers by setting the vblank callbacks
19 * in struct &drm_crtc_funcs to the helpers provided by this library. The
20 * initializer macro DRM_CRTC_VBLANK_TIMER_FUNCS does this conveniently.
21 * The driver further has to send the VBLANK event from its atomic_flush
22 * callback and control vblank from the CRTC's atomic_enable and atomic_disable
23 * callbacks. The callbacks are located in struct &drm_crtc_helper_funcs.
24 * The vblank helper library provides implementations of these callbacks
25 * for drivers without further requirements. The initializer macro
26 * DRM_CRTC_HELPER_VBLANK_FUNCS sets them coveniently.
27 *
28 * Once the driver enables vblank support with drm_vblank_init(), each
29 * CRTC's vblank timer fires according to the programmed display mode. By
30 * default, the vblank timer invokes drm_crtc_handle_vblank(). Drivers with
31 * more specific requirements can set their own handler function in
32 * struct &drm_crtc_helper_funcs.handle_vblank_timeout.
33 */
34
35 /*
36 * VBLANK helpers
37 */
38
39 /**
40 * drm_crtc_vblank_atomic_flush -
41 * Implements struct &drm_crtc_helper_funcs.atomic_flush
42 * @crtc: The CRTC
43 * @state: The atomic state to apply
44 *
45 * The helper drm_crtc_vblank_atomic_flush() implements atomic_flush of
46 * struct drm_crtc_helper_funcs for CRTCs that only need to send out a
47 * VBLANK event.
48 *
49 * See also struct &drm_crtc_helper_funcs.atomic_flush.
50 */
drm_crtc_vblank_atomic_flush(struct drm_crtc * crtc,struct drm_atomic_state * state)51 void drm_crtc_vblank_atomic_flush(struct drm_crtc *crtc,
52 struct drm_atomic_state *state)
53 {
54 struct drm_device *dev = crtc->dev;
55 struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
56 struct drm_pending_vblank_event *event;
57
58 spin_lock_irq(&dev->event_lock);
59
60 event = crtc_state->event;
61 crtc_state->event = NULL;
62
63 if (event) {
64 if (drm_crtc_vblank_get(crtc) == 0)
65 drm_crtc_arm_vblank_event(crtc, event);
66 else
67 drm_crtc_send_vblank_event(crtc, event);
68 }
69
70 spin_unlock_irq(&dev->event_lock);
71 }
72 EXPORT_SYMBOL(drm_crtc_vblank_atomic_flush);
73
74 /**
75 * drm_crtc_vblank_atomic_enable - Implements struct &drm_crtc_helper_funcs.atomic_enable
76 * @crtc: The CRTC
77 * @state: The atomic state
78 *
79 * The helper drm_crtc_vblank_atomic_enable() implements atomic_enable
80 * of struct drm_crtc_helper_funcs for CRTCs the only need to enable VBLANKs.
81 *
82 * See also struct &drm_crtc_helper_funcs.atomic_enable.
83 */
drm_crtc_vblank_atomic_enable(struct drm_crtc * crtc,struct drm_atomic_state * state)84 void drm_crtc_vblank_atomic_enable(struct drm_crtc *crtc,
85 struct drm_atomic_state *state)
86 {
87 drm_crtc_vblank_on(crtc);
88 }
89 EXPORT_SYMBOL(drm_crtc_vblank_atomic_enable);
90
91 /**
92 * drm_crtc_vblank_atomic_disable - Implements struct &drm_crtc_helper_funcs.atomic_disable
93 * @crtc: The CRTC
94 * @state: The atomic state
95 *
96 * The helper drm_crtc_vblank_atomic_disable() implements atomic_disable
97 * of struct drm_crtc_helper_funcs for CRTCs the only need to disable VBLANKs.
98 *
99 * See also struct &drm_crtc_funcs.atomic_disable.
100 */
drm_crtc_vblank_atomic_disable(struct drm_crtc * crtc,struct drm_atomic_state * state)101 void drm_crtc_vblank_atomic_disable(struct drm_crtc *crtc,
102 struct drm_atomic_state *state)
103 {
104 drm_crtc_vblank_off(crtc);
105 }
106 EXPORT_SYMBOL(drm_crtc_vblank_atomic_disable);
107
108 /*
109 * VBLANK timer
110 */
111
112 /**
113 * drm_crtc_vblank_helper_enable_vblank_timer - Implements struct &drm_crtc_funcs.enable_vblank
114 * @crtc: The CRTC
115 *
116 * The helper drm_crtc_vblank_helper_enable_vblank_timer() implements
117 * enable_vblank of struct drm_crtc_helper_funcs for CRTCs that require
118 * a VBLANK timer. It sets up the timer on the first invocation. The
119 * started timer expires after the current frame duration. See struct
120 * &drm_vblank_crtc.framedur_ns.
121 *
122 * See also struct &drm_crtc_helper_funcs.enable_vblank.
123 *
124 * Returns:
125 * 0 on success, or a negative errno code otherwise.
126 */
drm_crtc_vblank_helper_enable_vblank_timer(struct drm_crtc * crtc)127 int drm_crtc_vblank_helper_enable_vblank_timer(struct drm_crtc *crtc)
128 {
129 return drm_crtc_vblank_start_timer(crtc);
130 }
131 EXPORT_SYMBOL(drm_crtc_vblank_helper_enable_vblank_timer);
132
133 /**
134 * drm_crtc_vblank_helper_disable_vblank_timer - Implements struct &drm_crtc_funcs.disable_vblank
135 * @crtc: The CRTC
136 *
137 * The helper drm_crtc_vblank_helper_disable_vblank_timer() implements
138 * disable_vblank of struct drm_crtc_funcs for CRTCs that require a
139 * VBLANK timer.
140 *
141 * See also struct &drm_crtc_helper_funcs.disable_vblank.
142 */
drm_crtc_vblank_helper_disable_vblank_timer(struct drm_crtc * crtc)143 void drm_crtc_vblank_helper_disable_vblank_timer(struct drm_crtc *crtc)
144 {
145 drm_crtc_vblank_cancel_timer(crtc);
146 }
147 EXPORT_SYMBOL(drm_crtc_vblank_helper_disable_vblank_timer);
148
149 /**
150 * drm_crtc_vblank_helper_get_vblank_timestamp_from_timer -
151 * Implements struct &drm_crtc_funcs.get_vblank_timestamp
152 * @crtc: The CRTC
153 * @max_error: Maximum acceptable error
154 * @vblank_time: Returns the next vblank timestamp
155 * @in_vblank_irq: True is called from drm_crtc_handle_vblank()
156 *
157 * The helper drm_crtc_helper_get_vblank_timestamp_from_timer() implements
158 * get_vblank_timestamp of struct drm_crtc_funcs for CRTCs that require a
159 * VBLANK timer. It returns the timestamp according to the timer's expiry
160 * time.
161 *
162 * See also struct &drm_crtc_funcs.get_vblank_timestamp.
163 *
164 * Returns:
165 * True on success, or false otherwise.
166 */
drm_crtc_vblank_helper_get_vblank_timestamp_from_timer(struct drm_crtc * crtc,int * max_error,ktime_t * vblank_time,bool in_vblank_irq)167 bool drm_crtc_vblank_helper_get_vblank_timestamp_from_timer(struct drm_crtc *crtc,
168 int *max_error,
169 ktime_t *vblank_time,
170 bool in_vblank_irq)
171 {
172 drm_crtc_vblank_get_vblank_timeout(crtc, vblank_time);
173
174 return true;
175 }
176 EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp_from_timer);
177