Rev 4560 | Rev 5271 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5060 | serge | 1 | /* |
2 | * drm_irq.c IRQ and vblank support |
||
1963 | serge | 3 | * |
4 | * \author Rickard E. (Rik) Faith |
||
5 | * \author Gareth Hughes |
||
6 | */ |
||
7 | |||
8 | /* |
||
9 | * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com |
||
10 | * |
||
11 | * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. |
||
12 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. |
||
13 | * All Rights Reserved. |
||
14 | * |
||
15 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
16 | * copy of this software and associated documentation files (the "Software"), |
||
17 | * to deal in the Software without restriction, including without limitation |
||
18 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
19 | * and/or sell copies of the Software, and to permit persons to whom the |
||
20 | * Software is furnished to do so, subject to the following conditions: |
||
21 | * |
||
22 | * The above copyright notice and this permission notice (including the next |
||
23 | * paragraph) shall be included in all copies or substantial portions of the |
||
24 | * Software. |
||
25 | * |
||
26 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
27 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
28 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
29 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
||
30 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
||
31 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
||
32 | * OTHER DEALINGS IN THE SOFTWARE. |
||
33 | */ |
||
34 | |||
3031 | serge | 35 | #include |
1963 | serge | 36 | #include |
37 | //#include "drm_trace.h" |
||
38 | |||
39 | //#include |
||
40 | #include |
||
41 | |||
42 | //#include |
||
3031 | serge | 43 | #include |
1963 | serge | 44 | |
45 | /* Access macro for slots in vblank timestamp ringbuffer. */ |
||
4560 | Serge | 46 | #define vblanktimestamp(dev, crtc, count) \ |
47 | ((dev)->vblank[crtc].time[(count) % DRM_VBLANKTIME_RBSIZE]) |
||
1963 | serge | 48 | |
49 | /* Retry timestamp calculation up to 3 times to satisfy |
||
50 | * drm_timestamp_precision before giving up. |
||
51 | */ |
||
52 | #define DRM_TIMESTAMP_MAXRETRIES 3 |
||
53 | |||
54 | /* Threshold in nanoseconds for detection of redundant |
||
55 | * vblank irq in drm_handle_vblank(). 1 msec should be ok. |
||
56 | */ |
||
57 | #define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000 |
||
58 | |||
5060 | serge | 59 | /* |
60 | * Clear vblank timestamp buffer for a crtc. |
||
61 | */ |
||
1963 | serge | 62 | |
5060 | serge | 63 | |
64 | #if 0 |
||
65 | /** |
||
66 | * drm_vblank_init - initialize vblank support |
||
67 | * @dev: drm_device |
||
68 | * @num_crtcs: number of crtcs supported by @dev |
||
69 | * |
||
70 | * This function initializes vblank support for @num_crtcs display pipelines. |
||
71 | * |
||
72 | * Returns: |
||
73 | * Zero on success or a negative error code on failure. |
||
74 | */ |
||
75 | int drm_vblank_init(struct drm_device *dev, int num_crtcs) |
||
76 | { |
||
77 | int i, ret = -ENOMEM; |
||
78 | |||
79 | spin_lock_init(&dev->vbl_lock); |
||
80 | spin_lock_init(&dev->vblank_time_lock); |
||
81 | |||
82 | dev->num_crtcs = num_crtcs; |
||
83 | |||
84 | dev->vblank = kcalloc(num_crtcs, sizeof(*dev->vblank), GFP_KERNEL); |
||
85 | if (!dev->vblank) |
||
86 | goto err; |
||
87 | |||
88 | for (i = 0; i < num_crtcs; i++) { |
||
89 | dev->vblank[i].dev = dev; |
||
90 | dev->vblank[i].crtc = i; |
||
91 | init_waitqueue_head(&dev->vblank[i].queue); |
||
92 | setup_timer(&dev->vblank[i].disable_timer, vblank_disable_fn, |
||
93 | (unsigned long)&dev->vblank[i]); |
||
94 | } |
||
95 | |||
96 | DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n"); |
||
97 | |||
98 | /* Driver specific high-precision vblank timestamping supported? */ |
||
99 | if (dev->driver->get_vblank_timestamp) |
||
100 | DRM_INFO("Driver supports precise vblank timestamp query.\n"); |
||
101 | else |
||
102 | DRM_INFO("No driver support for vblank timestamp query.\n"); |
||
103 | |||
104 | dev->vblank_disable_allowed = false; |
||
105 | |||
106 | return 0; |
||
107 | |||
108 | err: |
||
109 | drm_vblank_cleanup(dev); |
||
110 | return ret; |
||
111 | } |
||
112 | EXPORT_SYMBOL(drm_vblank_init); |
||
113 | |||
114 | #endif |
||
115 | |||
4075 | Serge | 116 | irqreturn_t device_irq_handler(struct drm_device *dev) |
117 | { |
||
118 | |||
4104 | Serge | 119 | // printf("video irq\n"); |
4075 | Serge | 120 | |
121 | // printf("device %p driver %p handler %p\n", dev, dev->driver, dev->driver->irq_handler) ; |
||
122 | |||
123 | return dev->driver->irq_handler(0, dev); |
||
124 | } |
||
125 | |||
126 | /** |
||
5060 | serge | 127 | * drm_irq_install - install IRQ handler |
128 | * @dev: DRM device |
||
129 | * @irq: IRQ number to install the handler for |
||
4075 | Serge | 130 | * |
5060 | serge | 131 | * Initializes the IRQ related data. Installs the handler, calling the driver |
132 | * irq_preinstall() and irq_postinstall() functions before and after the |
||
133 | * installation. |
||
4075 | Serge | 134 | * |
5060 | serge | 135 | * This is the simplified helper interface provided for drivers with no special |
136 | * needs. Drivers which need to install interrupt handlers for multiple |
||
137 | * interrupts must instead set drm_device->irq_enabled to signal the DRM core |
||
138 | * that vblank interrupts are available. |
||
139 | * |
||
140 | * Returns: |
||
141 | * Zero on success or a negative error code on failure. |
||
4075 | Serge | 142 | */ |
5060 | serge | 143 | int drm_irq_install(struct drm_device *dev, int irq) |
4075 | Serge | 144 | { |
145 | int ret; |
||
146 | unsigned long sh_flags = 0; |
||
147 | |||
4293 | Serge | 148 | if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) |
149 | return -EINVAL; |
||
4075 | Serge | 150 | |
5060 | serge | 151 | if (irq == 0) |
4075 | Serge | 152 | return -EINVAL; |
153 | |||
154 | /* Driver must have been initialized */ |
||
5060 | serge | 155 | if (!dev->dev_private) |
4075 | Serge | 156 | return -EINVAL; |
157 | |||
5060 | serge | 158 | if (dev->irq_enabled) |
4075 | Serge | 159 | return -EBUSY; |
4560 | Serge | 160 | dev->irq_enabled = true; |
4075 | Serge | 161 | |
5060 | serge | 162 | DRM_DEBUG("irq=%d\n", irq); |
4075 | Serge | 163 | |
164 | /* Before installing handler */ |
||
165 | if (dev->driver->irq_preinstall) |
||
166 | dev->driver->irq_preinstall(dev); |
||
167 | |||
5060 | serge | 168 | ret = !AttachIntHandler(irq, device_irq_handler, (u32)dev); |
4075 | Serge | 169 | |
170 | /* After installing handler */ |
||
171 | if (dev->driver->irq_postinstall) |
||
172 | ret = dev->driver->irq_postinstall(dev); |
||
173 | |||
174 | if (ret < 0) { |
||
5060 | serge | 175 | dev->irq_enabled = false; |
4539 | Serge | 176 | DRM_ERROR(__FUNCTION__); |
5060 | serge | 177 | } else { |
178 | dev->irq = irq; |
||
4075 | Serge | 179 | } |
180 | |||
181 | u16_t cmd = PciRead16(dev->pdev->busnr, dev->pdev->devfn, 4); |
||
182 | cmd&= ~(1<<10); |
||
183 | PciWrite16(dev->pdev->busnr, dev->pdev->devfn, 4, cmd); |
||
184 | |||
185 | return ret; |
||
186 | } |
||
187 | EXPORT_SYMBOL(drm_irq_install); |
||
188 | |||
189 | |||
1963 | serge | 190 | |
191 | |||
192 | u64 div64_u64(u64 dividend, u64 divisor) |
||
193 | { |
||
194 | u32 high, d; |
||
195 | |||
196 | high = divisor >> 32; |
||
197 | if (high) { |
||
198 | unsigned int shift = fls(high); |
||
199 | |||
200 | d = divisor >> shift; |
||
201 | dividend >>= shift; |
||
202 | } else |
||
203 | d = divisor; |
||
204 | |||
205 | return div_u64(dividend, d); |
||
206 | } |
||
207 | |||
208 | /** |
||
5060 | serge | 209 | * drm_calc_timestamping_constants - calculate vblank timestamp constants |
210 | * @crtc: drm_crtc whose timestamp constants should be updated. |
||
211 | * @mode: display mode containing the scanout timings |
||
1963 | serge | 212 | * |
4560 | Serge | 213 | * Calculate and store various constants which are later |
214 | * needed by vblank and swap-completion timestamping, e.g, |
||
215 | * by drm_calc_vbltimestamp_from_scanoutpos(). They are |
||
5060 | serge | 216 | * derived from CRTC's true scanout timing, so they take |
4560 | Serge | 217 | * things like panel scaling or other adjustments into account. |
1963 | serge | 218 | */ |
4560 | Serge | 219 | void drm_calc_timestamping_constants(struct drm_crtc *crtc, |
220 | const struct drm_display_mode *mode) |
||
1963 | serge | 221 | { |
4560 | Serge | 222 | int linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0; |
223 | int dotclock = mode->crtc_clock; |
||
1963 | serge | 224 | |
4560 | Serge | 225 | /* Valid dotclock? */ |
226 | if (dotclock > 0) { |
||
227 | int frame_size = mode->crtc_htotal * mode->crtc_vtotal; |
||
1963 | serge | 228 | |
4560 | Serge | 229 | /* |
230 | * Convert scanline length in pixels and video |
||
231 | * dot clock to line duration, frame duration |
||
232 | * and pixel duration in nanoseconds: |
||
1963 | serge | 233 | */ |
4560 | Serge | 234 | pixeldur_ns = 1000000 / dotclock; |
235 | linedur_ns = div_u64((u64) mode->crtc_htotal * 1000000, dotclock); |
||
236 | framedur_ns = div_u64((u64) frame_size * 1000000, dotclock); |
||
1963 | serge | 237 | |
4560 | Serge | 238 | /* |
239 | * Fields of interlaced scanout modes are only half a frame duration. |
||
1963 | serge | 240 | */ |
4560 | Serge | 241 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) |
242 | framedur_ns /= 2; |
||
1963 | serge | 243 | } else |
244 | DRM_ERROR("crtc %d: Can't calculate constants, dotclock = 0!\n", |
||
245 | crtc->base.id); |
||
246 | |||
247 | crtc->pixeldur_ns = pixeldur_ns; |
||
248 | crtc->linedur_ns = linedur_ns; |
||
249 | crtc->framedur_ns = framedur_ns; |
||
250 | |||
251 | DRM_DEBUG("crtc %d: hwmode: htotal %d, vtotal %d, vdisplay %d\n", |
||
4560 | Serge | 252 | crtc->base.id, mode->crtc_htotal, |
253 | mode->crtc_vtotal, mode->crtc_vdisplay); |
||
1963 | serge | 254 | DRM_DEBUG("crtc %d: clock %d kHz framedur %d linedur %d, pixeldur %d\n", |
4560 | Serge | 255 | crtc->base.id, dotclock, framedur_ns, |
256 | linedur_ns, pixeldur_ns); |
||
1963 | serge | 257 | } |
4293 | Serge | 258 | EXPORT_SYMBOL(drm_calc_timestamping_constants); |
1963 | serge | 259 | |
4293 | Serge | 260 | /** |
5060 | serge | 261 | * drm_calc_vbltimestamp_from_scanoutpos - precise vblank timestamp helper |
262 | * @dev: DRM device |
||
263 | * @crtc: Which CRTC's vblank timestamp to retrieve |
||
264 | * @max_error: Desired maximum allowable error in timestamps (nanosecs) |
||
265 | * On return contains true maximum error of timestamp |
||
266 | * @vblank_time: Pointer to struct timeval which should receive the timestamp |
||
267 | * @flags: Flags to pass to driver: |
||
268 | * 0 = Default, |
||
269 | * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl IRQ handler |
||
270 | * @refcrtc: CRTC which defines scanout timing |
||
271 | * @mode: mode which defines the scanout timings |
||
4293 | Serge | 272 | * |
5060 | serge | 273 | * Implements calculation of exact vblank timestamps from given drm_display_mode |
274 | * timings and current video scanout position of a CRTC. This can be called from |
||
275 | * within get_vblank_timestamp() implementation of a kms driver to implement the |
||
276 | * actual timestamping. |
||
277 | * |
||
4293 | Serge | 278 | * Should return timestamps conforming to the OML_sync_control OpenML |
279 | * extension specification. The timestamp corresponds to the end of |
||
280 | * the vblank interval, aka start of scanout of topmost-leftmost display |
||
281 | * pixel in the following video frame. |
||
282 | * |
||
283 | * Requires support for optional dev->driver->get_scanout_position() |
||
284 | * in kms driver, plus a bit of setup code to provide a drm_display_mode |
||
285 | * that corresponds to the true scanout timing. |
||
286 | * |
||
287 | * The current implementation only handles standard video modes. It |
||
288 | * returns as no operation if a doublescan or interlaced video mode is |
||
289 | * active. Higher level code is expected to handle this. |
||
290 | * |
||
5060 | serge | 291 | * Returns: |
292 | * Negative value on error, failure or if not supported in current |
||
4293 | Serge | 293 | * video mode: |
294 | * |
||
5060 | serge | 295 | * -EINVAL - Invalid CRTC. |
4293 | Serge | 296 | * -EAGAIN - Temporary unavailable, e.g., called before initial modeset. |
297 | * -ENOTSUPP - Function not supported in current display mode. |
||
298 | * -EIO - Failed, e.g., due to failed scanout position query. |
||
299 | * |
||
300 | * Returns or'ed positive status flags on success: |
||
301 | * |
||
302 | * DRM_VBLANKTIME_SCANOUTPOS_METHOD - Signal this method used for timestamping. |
||
303 | * DRM_VBLANKTIME_INVBL - Timestamp taken while scanout was in vblank interval. |
||
304 | * |
||
305 | */ |
||
306 | int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, |
||
307 | int *max_error, |
||
308 | struct timeval *vblank_time, |
||
309 | unsigned flags, |
||
4560 | Serge | 310 | const struct drm_crtc *refcrtc, |
311 | const struct drm_display_mode *mode) |
||
4293 | Serge | 312 | { |
313 | struct timeval tv_etime; |
||
4560 | Serge | 314 | int vbl_status; |
4293 | Serge | 315 | int vpos, hpos, i; |
4560 | Serge | 316 | int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns; |
4293 | Serge | 317 | bool invbl; |
3031 | serge | 318 | |
4293 | Serge | 319 | if (crtc < 0 || crtc >= dev->num_crtcs) { |
320 | DRM_ERROR("Invalid crtc %d\n", crtc); |
||
321 | return -EINVAL; |
||
322 | } |
||
323 | |||
324 | /* Scanout position query not supported? Should not happen. */ |
||
325 | if (!dev->driver->get_scanout_position) { |
||
326 | DRM_ERROR("Called from driver w/o get_scanout_position()!?\n"); |
||
327 | return -EIO; |
||
328 | } |
||
329 | |||
330 | /* Durations of frames, lines, pixels in nanoseconds. */ |
||
331 | framedur_ns = refcrtc->framedur_ns; |
||
332 | linedur_ns = refcrtc->linedur_ns; |
||
333 | pixeldur_ns = refcrtc->pixeldur_ns; |
||
334 | |||
335 | /* If mode timing undefined, just return as no-op: |
||
336 | * Happens during initial modesetting of a crtc. |
||
337 | */ |
||
4560 | Serge | 338 | if (framedur_ns == 0) { |
4293 | Serge | 339 | DRM_DEBUG("crtc %d: Noop due to uninitialized mode.\n", crtc); |
340 | return -EAGAIN; |
||
341 | } |
||
342 | |||
343 | return -EIO; |
||
344 | } |
||
345 | EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos); |
||
346 | |||
5060 | serge | 347 | /** |
348 | * drm_vblank_off - disable vblank events on a CRTC |
||
349 | * @dev: DRM device |
||
350 | * @crtc: CRTC in question |
||
351 | * |
||
352 | * Drivers can use this function to shut down the vblank interrupt handling when |
||
353 | * disabling a crtc. This function ensures that the latest vblank frame count is |
||
354 | * stored so that drm_vblank_on() can restore it again. |
||
355 | * |
||
356 | * Drivers must use this function when the hardware vblank counter can get |
||
357 | * reset, e.g. when suspending. |
||
358 | * |
||
359 | * This is the legacy version of drm_crtc_vblank_off(). |
||
360 | */ |
||
361 | void drm_vblank_off(struct drm_device *dev, int crtc) |
||
362 | { |
||
363 | struct drm_pending_vblank_event *e, *t; |
||
364 | struct timeval now; |
||
365 | unsigned long irqflags; |
||
366 | unsigned int seq; |
||
4293 | Serge | 367 | |
5060 | serge | 368 | |
369 | } |
||
370 | EXPORT_SYMBOL(drm_vblank_off); |
||
371 | |||
3031 | serge | 372 | /** |
5060 | serge | 373 | * drm_crtc_vblank_off - disable vblank events on a CRTC |
374 | * @crtc: CRTC in question |
||
375 | * |
||
376 | * Drivers can use this function to shut down the vblank interrupt handling when |
||
377 | * disabling a crtc. This function ensures that the latest vblank frame count is |
||
378 | * stored so that drm_vblank_on can restore it again. |
||
379 | * |
||
380 | * Drivers must use this function when the hardware vblank counter can get |
||
381 | * reset, e.g. when suspending. |
||
382 | * |
||
383 | * This is the native kms version of drm_vblank_off(). |
||
384 | */ |
||
385 | void drm_crtc_vblank_off(struct drm_crtc *crtc) |
||
386 | { |
||
387 | drm_vblank_off(crtc->dev, drm_crtc_index(crtc)); |
||
388 | } |
||
389 | EXPORT_SYMBOL(drm_crtc_vblank_off); |
||
390 | |||
391 | /** |
||
392 | * drm_vblank_on - enable vblank events on a CRTC |
||
393 | * @dev: DRM device |
||
394 | * @crtc: CRTC in question |
||
395 | * |
||
396 | * This functions restores the vblank interrupt state captured with |
||
397 | * drm_vblank_off() again. Note that calls to drm_vblank_on() and |
||
398 | * drm_vblank_off() can be unbalanced and so can also be unconditionaly called |
||
399 | * in driver load code to reflect the current hardware state of the crtc. |
||
400 | * |
||
401 | * This is the legacy version of drm_crtc_vblank_on(). |
||
402 | */ |
||
403 | void drm_vblank_on(struct drm_device *dev, int crtc) |
||
404 | { |
||
405 | unsigned long irqflags; |
||
406 | |||
407 | } |
||
408 | EXPORT_SYMBOL(drm_vblank_on); |
||
409 | |||
410 | /** |
||
411 | * drm_crtc_vblank_on - enable vblank events on a CRTC |
||
412 | * @crtc: CRTC in question |
||
413 | * |
||
414 | * This functions restores the vblank interrupt state captured with |
||
415 | * drm_vblank_off() again. Note that calls to drm_vblank_on() and |
||
416 | * drm_vblank_off() can be unbalanced and so can also be unconditionaly called |
||
417 | * in driver load code to reflect the current hardware state of the crtc. |
||
418 | * |
||
419 | * This is the native kms version of drm_vblank_on(). |
||
420 | */ |
||
421 | void drm_crtc_vblank_on(struct drm_crtc *crtc) |
||
422 | { |
||
423 | drm_vblank_on(crtc->dev, drm_crtc_index(crtc)); |
||
424 | } |
||
425 | EXPORT_SYMBOL(drm_crtc_vblank_on); |
||
426 | |||
427 | /** |
||
3031 | serge | 428 | * drm_vblank_pre_modeset - account for vblanks across mode sets |
429 | * @dev: DRM device |
||
430 | * @crtc: CRTC in question |
||
431 | * |
||
432 | * Account for vblank events across mode setting events, which will likely |
||
433 | * reset the hardware frame counter. |
||
5060 | serge | 434 | * |
435 | * This is done by grabbing a temporary vblank reference to ensure that the |
||
436 | * vblank interrupt keeps running across the modeset sequence. With this the |
||
437 | * software-side vblank frame counting will ensure that there are no jumps or |
||
438 | * discontinuities. |
||
439 | * |
||
440 | * Unfortunately this approach is racy and also doesn't work when the vblank |
||
441 | * interrupt stops running, e.g. across system suspend resume. It is therefore |
||
442 | * highly recommended that drivers use the newer drm_vblank_off() and |
||
443 | * drm_vblank_on() instead. drm_vblank_pre_modeset() only works correctly when |
||
444 | * using "cooked" software vblank frame counters and not relying on any hardware |
||
445 | * counters. |
||
446 | * |
||
447 | * Drivers must call drm_vblank_post_modeset() when re-enabling the same crtc |
||
448 | * again. |
||
3031 | serge | 449 | */ |
450 | void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) |
||
451 | { |
||
452 | #if 0 |
||
453 | /* vblank is not initialized (IRQ not installed ?) */ |
||
454 | if (!dev->num_crtcs) |
||
455 | return; |
||
456 | /* |
||
457 | * To avoid all the problems that might happen if interrupts |
||
458 | * were enabled/disabled around or between these calls, we just |
||
459 | * have the kernel take a reference on the CRTC (just once though |
||
460 | * to avoid corrupting the count if multiple, mismatch calls occur), |
||
461 | * so that interrupts remain enabled in the interim. |
||
462 | */ |
||
4560 | Serge | 463 | if (!dev->vblank[crtc].inmodeset) { |
464 | dev->vblank[crtc].inmodeset = 0x1; |
||
3031 | serge | 465 | if (drm_vblank_get(dev, crtc) == 0) |
4560 | Serge | 466 | dev->vblank[crtc].inmodeset |= 0x2; |
3031 | serge | 467 | } |
468 | #endif |
||
469 | } |
||
470 | EXPORT_SYMBOL(drm_vblank_pre_modeset); |
||
471 | |||
5060 | serge | 472 | /** |
473 | * drm_vblank_post_modeset - undo drm_vblank_pre_modeset changes |
||
474 | * @dev: DRM device |
||
475 | * @crtc: CRTC in question |
||
476 | * |
||
477 | * This function again drops the temporary vblank reference acquired in |
||
478 | * drm_vblank_pre_modeset. |
||
479 | */ |
||
3031 | serge | 480 | void drm_vblank_post_modeset(struct drm_device *dev, int crtc) |
481 | { |
||
482 | #if 0 |
||
483 | unsigned long irqflags; |
||
484 | |||
4075 | Serge | 485 | /* vblank is not initialized (IRQ not installed ?), or has been freed */ |
486 | if (!dev->num_crtcs) |
||
487 | return; |
||
488 | |||
4560 | Serge | 489 | if (dev->vblank[crtc].inmodeset) { |
3031 | serge | 490 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
4560 | Serge | 491 | dev->vblank_disable_allowed = true; |
3031 | serge | 492 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
493 | |||
4560 | Serge | 494 | if (dev->vblank[crtc].inmodeset & 0x2) |
3031 | serge | 495 | drm_vblank_put(dev, crtc); |
496 | |||
4560 | Serge | 497 | dev->vblank[crtc].inmodeset = 0; |
3031 | serge | 498 | } |
499 | #endif |
||
500 | } |
||
501 | EXPORT_SYMBOL(drm_vblank_post_modeset);>10); |