xref: /linux/drivers/gpu/drm/drm_vblank_helper.c (revision face6a3615a649456eb4549f6d474221d877d604)
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  */
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  */
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  */
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  */
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  */
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  */
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