.. | .. |
---|
27 | 27 | #include <linux/seqlock.h> |
---|
28 | 28 | #include <linux/idr.h> |
---|
29 | 29 | #include <linux/poll.h> |
---|
| 30 | +#include <linux/kthread.h> |
---|
30 | 31 | |
---|
31 | 32 | #include <drm/drm_file.h> |
---|
32 | 33 | #include <drm/drm_modes.h> |
---|
33 | | -#include <uapi/drm/drm.h> |
---|
34 | 34 | |
---|
35 | 35 | struct drm_device; |
---|
36 | 36 | struct drm_crtc; |
---|
| 37 | +struct drm_vblank_work; |
---|
37 | 38 | |
---|
38 | 39 | /** |
---|
39 | 40 | * struct drm_pending_vblank_event - pending vblank event tracking |
---|
.. | .. |
---|
95 | 96 | /** |
---|
96 | 97 | * @queue: Wait queue for vblank waiters. |
---|
97 | 98 | */ |
---|
98 | | - wait_queue_head_t queue; /**< VBLANK wait queue */ |
---|
| 99 | + wait_queue_head_t queue; |
---|
99 | 100 | /** |
---|
100 | 101 | * @disable_timer: Disable timer for the delayed vblank disabling |
---|
101 | 102 | * hysteresis logic. Vblank disabling is controlled through the |
---|
.. | .. |
---|
107 | 108 | /** |
---|
108 | 109 | * @seqlock: Protect vblank count and time. |
---|
109 | 110 | */ |
---|
110 | | - seqlock_t seqlock; /* protects vblank count and time */ |
---|
| 111 | + seqlock_t seqlock; |
---|
111 | 112 | |
---|
112 | 113 | /** |
---|
113 | | - * @count: Current software vblank counter. |
---|
| 114 | + * @count: |
---|
| 115 | + * |
---|
| 116 | + * Current software vblank counter. |
---|
| 117 | + * |
---|
| 118 | + * Note that for a given vblank counter value drm_crtc_handle_vblank() |
---|
| 119 | + * and drm_crtc_vblank_count() or drm_crtc_vblank_count_and_time() |
---|
| 120 | + * provide a barrier: Any writes done before calling |
---|
| 121 | + * drm_crtc_handle_vblank() will be visible to callers of the later |
---|
| 122 | + * functions, iff the vblank count is the same or a later one. |
---|
| 123 | + * |
---|
| 124 | + * IMPORTANT: This guarantee requires barriers, therefor never access |
---|
| 125 | + * this field directly. Use drm_crtc_vblank_count() instead. |
---|
114 | 126 | */ |
---|
115 | | - u64 count; |
---|
| 127 | + atomic64_t count; |
---|
116 | 128 | /** |
---|
117 | 129 | * @time: Vblank timestamp corresponding to @count. |
---|
118 | 130 | */ |
---|
.. | .. |
---|
123 | 135 | * this refcount reaches 0 can the hardware interrupt be disabled using |
---|
124 | 136 | * @disable_timer. |
---|
125 | 137 | */ |
---|
126 | | - atomic_t refcount; /* number of users of vblank interruptsper crtc */ |
---|
| 138 | + atomic_t refcount; |
---|
127 | 139 | /** |
---|
128 | 140 | * @last: Protected by &drm_device.vbl_lock, used for wraparound handling. |
---|
129 | 141 | */ |
---|
.. | .. |
---|
156 | 168 | * call drm_crtc_vblank_off() and drm_crtc_vblank_on(), which explicitly |
---|
157 | 169 | * save and restore the vblank count. |
---|
158 | 170 | */ |
---|
159 | | - unsigned int inmodeset; /* Display driver is setting mode */ |
---|
| 171 | + unsigned int inmodeset; |
---|
160 | 172 | /** |
---|
161 | 173 | * @pipe: drm_crtc_index() of the &drm_crtc corresponding to this |
---|
162 | 174 | * structure. |
---|
.. | .. |
---|
164 | 176 | unsigned int pipe; |
---|
165 | 177 | /** |
---|
166 | 178 | * @framedur_ns: Frame/Field duration in ns, used by |
---|
167 | | - * drm_calc_vbltimestamp_from_scanoutpos() and computed by |
---|
| 179 | + * drm_crtc_vblank_helper_get_vblank_timestamp() and computed by |
---|
168 | 180 | * drm_calc_timestamping_constants(). |
---|
169 | 181 | */ |
---|
170 | 182 | int framedur_ns; |
---|
171 | 183 | /** |
---|
172 | 184 | * @linedur_ns: Line duration in ns, used by |
---|
173 | | - * drm_calc_vbltimestamp_from_scanoutpos() and computed by |
---|
| 185 | + * drm_crtc_vblank_helper_get_vblank_timestamp() and computed by |
---|
174 | 186 | * drm_calc_timestamping_constants(). |
---|
175 | 187 | */ |
---|
176 | 188 | int linedur_ns; |
---|
.. | .. |
---|
180 | 192 | * |
---|
181 | 193 | * Cache of the current hardware display mode. Only valid when @enabled |
---|
182 | 194 | * is set. This is used by helpers like |
---|
183 | | - * drm_calc_vbltimestamp_from_scanoutpos(). We can't just access the |
---|
184 | | - * hardware mode by e.g. looking at &drm_crtc_state.adjusted_mode, |
---|
| 195 | + * drm_crtc_vblank_helper_get_vblank_timestamp(). We can't just access |
---|
| 196 | + * the hardware mode by e.g. looking at &drm_crtc_state.adjusted_mode, |
---|
185 | 197 | * because that one is really hard to get from interrupt context. |
---|
186 | 198 | */ |
---|
187 | 199 | struct drm_display_mode hwmode; |
---|
.. | .. |
---|
193 | 205 | * disabling functions multiple times. |
---|
194 | 206 | */ |
---|
195 | 207 | bool enabled; |
---|
| 208 | + |
---|
| 209 | + /** |
---|
| 210 | + * @worker: The &kthread_worker used for executing vblank works. |
---|
| 211 | + */ |
---|
| 212 | + struct kthread_worker *worker; |
---|
| 213 | + |
---|
| 214 | + /** |
---|
| 215 | + * @pending_work: A list of scheduled &drm_vblank_work items that are |
---|
| 216 | + * waiting for a future vblank. |
---|
| 217 | + */ |
---|
| 218 | + struct list_head pending_work; |
---|
| 219 | + |
---|
| 220 | + /** |
---|
| 221 | + * @work_wait_queue: The wait queue used for signaling that a |
---|
| 222 | + * &drm_vblank_work item has either finished executing, or was |
---|
| 223 | + * cancelled. |
---|
| 224 | + */ |
---|
| 225 | + wait_queue_head_t work_wait_queue; |
---|
196 | 226 | }; |
---|
197 | 227 | |
---|
198 | 228 | int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs); |
---|
| 229 | +bool drm_dev_has_vblank(const struct drm_device *dev); |
---|
199 | 230 | u64 drm_crtc_vblank_count(struct drm_crtc *crtc); |
---|
200 | 231 | u64 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, |
---|
201 | 232 | ktime_t *vblanktime); |
---|
.. | .. |
---|
219 | 250 | void drm_vblank_restore(struct drm_device *dev, unsigned int pipe); |
---|
220 | 251 | void drm_crtc_vblank_restore(struct drm_crtc *crtc); |
---|
221 | 252 | |
---|
222 | | -bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, |
---|
223 | | - unsigned int pipe, int *max_error, |
---|
224 | | - ktime_t *vblank_time, |
---|
225 | | - bool in_vblank_irq); |
---|
226 | 253 | void drm_calc_timestamping_constants(struct drm_crtc *crtc, |
---|
227 | 254 | const struct drm_display_mode *mode); |
---|
228 | 255 | wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc); |
---|
229 | 256 | void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc, |
---|
230 | 257 | u32 max_vblank_count); |
---|
| 258 | + |
---|
| 259 | +/* |
---|
| 260 | + * Helpers for struct drm_crtc_funcs |
---|
| 261 | + */ |
---|
| 262 | + |
---|
| 263 | +typedef bool (*drm_vblank_get_scanout_position_func)(struct drm_crtc *crtc, |
---|
| 264 | + bool in_vblank_irq, |
---|
| 265 | + int *vpos, int *hpos, |
---|
| 266 | + ktime_t *stime, |
---|
| 267 | + ktime_t *etime, |
---|
| 268 | + const struct drm_display_mode *mode); |
---|
| 269 | + |
---|
| 270 | +bool |
---|
| 271 | +drm_crtc_vblank_helper_get_vblank_timestamp_internal(struct drm_crtc *crtc, |
---|
| 272 | + int *max_error, |
---|
| 273 | + ktime_t *vblank_time, |
---|
| 274 | + bool in_vblank_irq, |
---|
| 275 | + drm_vblank_get_scanout_position_func get_scanout_position); |
---|
| 276 | +bool drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc *crtc, |
---|
| 277 | + int *max_error, |
---|
| 278 | + ktime_t *vblank_time, |
---|
| 279 | + bool in_vblank_irq); |
---|
| 280 | + |
---|
231 | 281 | #endif |
---|