Rev 4560 | Rev 5271 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4560 | Rev 5060 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | /** |
1 | /* |
2 | * \file drm_irq.c |
- | |
3 | * IRQ support |
2 | * drm_irq.c IRQ and vblank support |
4 | * |
3 | * |
5 | * \author Rickard E. (Rik) Faith |
4 | * \author Rickard E. (Rik) Faith |
6 | * \author Gareth Hughes |
5 | * \author Gareth Hughes |
7 | */ |
6 | */ |
Line 55... | Line 54... | ||
55 | /* Threshold in nanoseconds for detection of redundant |
54 | /* Threshold in nanoseconds for detection of redundant |
56 | * vblank irq in drm_handle_vblank(). 1 msec should be ok. |
55 | * vblank irq in drm_handle_vblank(). 1 msec should be ok. |
57 | */ |
56 | */ |
58 | #define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000 |
57 | #define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000 |
Line -... | Line 58... | ||
- | 58 | ||
- | 59 | /* |
|
- | 60 | * Clear vblank timestamp buffer for a crtc. |
|
- | 61 | */ |
|
- | 62 | ||
- | 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 | ||
Line 59... | Line 114... | ||
59 | 114 | #endif |
|
60 | 115 | ||
Line 61... | Line 116... | ||
61 | irqreturn_t device_irq_handler(struct drm_device *dev) |
116 | irqreturn_t device_irq_handler(struct drm_device *dev) |
Line 67... | Line 122... | ||
67 | 122 | ||
68 | return dev->driver->irq_handler(0, dev); |
123 | return dev->driver->irq_handler(0, dev); |
Line 69... | Line 124... | ||
69 | } |
124 | } |
70 | 125 | ||
71 | /** |
- | |
72 | * Install IRQ handler. |
126 | /** |
- | 127 | * drm_irq_install - install IRQ handler |
|
73 | * |
128 | * @dev: DRM device |
74 | * \param dev DRM device. |
129 | * @irq: IRQ number to install the handler for |
75 | * |
130 | * |
- | 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. |
|
- | 134 | * |
|
- | 135 | * This is the simplified helper interface provided for drivers with no special |
|
76 | * Initializes the IRQ related data. Installs the handler, calling the driver |
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 | * |
|
77 | * \c irq_preinstall() and \c irq_postinstall() functions |
140 | * Returns: |
78 | * before and after the installation. |
141 | * Zero on success or a negative error code on failure. |
79 | */ |
142 | */ |
80 | int drm_irq_install(struct drm_device *dev) |
143 | int drm_irq_install(struct drm_device *dev, int irq) |
81 | { |
144 | { |
82 | int ret; |
- | |
Line 83... | Line 145... | ||
83 | unsigned long sh_flags = 0; |
145 | int ret; |
84 | char *irqname; |
146 | unsigned long sh_flags = 0; |
Line 85... | Line 147... | ||
85 | 147 | ||
86 | if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) |
148 | if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) |
Line 87... | Line -... | ||
87 | return -EINVAL; |
- | |
88 | - | ||
89 | if (drm_dev_to_irq(dev) == 0) |
149 | return -EINVAL; |
90 | return -EINVAL; |
150 | |
91 | - | ||
92 | mutex_lock(&dev->struct_mutex); |
151 | if (irq == 0) |
93 | - | ||
Line 94... | Line 152... | ||
94 | /* Driver must have been initialized */ |
152 | return -EINVAL; |
95 | if (!dev->dev_private) { |
- | |
96 | mutex_unlock(&dev->struct_mutex); |
153 | |
97 | return -EINVAL; |
- | |
98 | } |
154 | /* Driver must have been initialized */ |
99 | - | ||
Line 100... | Line 155... | ||
100 | if (dev->irq_enabled) { |
155 | if (!dev->dev_private) |
Line 101... | Line 156... | ||
101 | mutex_unlock(&dev->struct_mutex); |
156 | return -EINVAL; |
102 | return -EBUSY; |
157 | |
103 | } |
158 | if (dev->irq_enabled) |
Line 104... | Line 159... | ||
104 | dev->irq_enabled = true; |
159 | return -EBUSY; |
Line 105... | Line 160... | ||
105 | mutex_unlock(&dev->struct_mutex); |
160 | dev->irq_enabled = true; |
106 | 161 | ||
107 | DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev)); |
162 | DRM_DEBUG("irq=%d\n", irq); |
Line 108... | Line 163... | ||
108 | 163 | ||
109 | /* Before installing handler */ |
164 | /* Before installing handler */ |
110 | if (dev->driver->irq_preinstall) |
165 | if (dev->driver->irq_preinstall) |
- | 166 | dev->driver->irq_preinstall(dev); |
|
- | 167 | ||
111 | dev->driver->irq_preinstall(dev); |
168 | ret = !AttachIntHandler(irq, device_irq_handler, (u32)dev); |
Line 112... | Line 169... | ||
112 | 169 | ||
113 | ret = !AttachIntHandler(drm_dev_to_irq(dev), device_irq_handler, (u32)dev); |
170 | /* After installing handler */ |
114 | 171 | if (dev->driver->irq_postinstall) |
|
Line 147... | Line 204... | ||
147 | 204 | ||
148 | return div_u64(dividend, d); |
205 | return div_u64(dividend, d); |
Line 149... | Line 206... | ||
149 | } |
206 | } |
150 | 207 | ||
151 | /** |
- | |
152 | * drm_calc_timestamping_constants - Calculate vblank timestamp constants |
208 | /** |
153 | * |
209 | * drm_calc_timestamping_constants - calculate vblank timestamp constants |
154 | * @crtc drm_crtc whose timestamp constants should be updated. |
210 | * @crtc: drm_crtc whose timestamp constants should be updated. |
155 | * @mode display mode containing the scanout timings |
211 | * @mode: display mode containing the scanout timings |
156 | * |
212 | * |
157 | * Calculate and store various constants which are later |
213 | * Calculate and store various constants which are later |
158 | * needed by vblank and swap-completion timestamping, e.g, |
214 | * needed by vblank and swap-completion timestamping, e.g, |
159 | * by drm_calc_vbltimestamp_from_scanoutpos(). They are |
215 | * by drm_calc_vbltimestamp_from_scanoutpos(). They are |
160 | * derived from crtc's true scanout timing, so they take |
216 | * derived from CRTC's true scanout timing, so they take |
161 | * things like panel scaling or other adjustments into account. |
217 | * things like panel scaling or other adjustments into account. |
162 | */ |
218 | */ |
163 | void drm_calc_timestamping_constants(struct drm_crtc *crtc, |
219 | void drm_calc_timestamping_constants(struct drm_crtc *crtc, |
Line 200... | Line 256... | ||
200 | linedur_ns, pixeldur_ns); |
256 | linedur_ns, pixeldur_ns); |
201 | } |
257 | } |
202 | EXPORT_SYMBOL(drm_calc_timestamping_constants); |
258 | EXPORT_SYMBOL(drm_calc_timestamping_constants); |
Line 203... | Line 259... | ||
203 | 259 | ||
204 | /** |
260 | /** |
- | 261 | * drm_calc_vbltimestamp_from_scanoutpos - precise vblank timestamp helper |
|
- | 262 | * @dev: DRM device |
|
205 | * drm_calc_vbltimestamp_from_scanoutpos - helper routine for kms |
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 |
|
206 | * drivers. Implements calculation of exact vblank timestamps from |
270 | * @refcrtc: CRTC which defines scanout timing |
- | 271 | * @mode: mode which defines the scanout timings |
|
- | 272 | * |
|
207 | * given drm_display_mode timings and current video scanout position |
273 | * Implements calculation of exact vblank timestamps from given drm_display_mode |
208 | * of a crtc. This can be called from within get_vblank_timestamp() |
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 |
|
209 | * implementation of a kms driver to implement the actual timestamping. |
276 | * actual timestamping. |
210 | * |
277 | * |
211 | * Should return timestamps conforming to the OML_sync_control OpenML |
278 | * Should return timestamps conforming to the OML_sync_control OpenML |
212 | * extension specification. The timestamp corresponds to the end of |
279 | * extension specification. The timestamp corresponds to the end of |
213 | * the vblank interval, aka start of scanout of topmost-leftmost display |
280 | * the vblank interval, aka start of scanout of topmost-leftmost display |
Line 219... | Line 286... | ||
219 | * |
286 | * |
220 | * The current implementation only handles standard video modes. It |
287 | * The current implementation only handles standard video modes. It |
221 | * returns as no operation if a doublescan or interlaced video mode is |
288 | * returns as no operation if a doublescan or interlaced video mode is |
222 | * active. Higher level code is expected to handle this. |
289 | * active. Higher level code is expected to handle this. |
223 | * |
290 | * |
224 | * @dev: DRM device. |
291 | * Returns: |
225 | * @crtc: Which crtc's vblank timestamp to retrieve. |
- | |
226 | * @max_error: Desired maximum allowable error in timestamps (nanosecs). |
- | |
227 | * On return contains true maximum error of timestamp. |
- | |
228 | * @vblank_time: Pointer to struct timeval which should receive the timestamp. |
- | |
229 | * @flags: Flags to pass to driver: |
- | |
230 | * 0 = Default. |
- | |
231 | * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl irq handler. |
- | |
232 | * @refcrtc: drm_crtc* of crtc which defines scanout timing. |
- | |
233 | * @mode: mode which defines the scanout timings |
- | |
234 | * |
- | |
235 | * Returns negative value on error, failure or if not supported in current |
292 | * Negative value on error, failure or if not supported in current |
236 | * video mode: |
293 | * video mode: |
237 | * |
294 | * |
238 | * -EINVAL - Invalid crtc. |
295 | * -EINVAL - Invalid CRTC. |
239 | * -EAGAIN - Temporary unavailable, e.g., called before initial modeset. |
296 | * -EAGAIN - Temporary unavailable, e.g., called before initial modeset. |
240 | * -ENOTSUPP - Function not supported in current display mode. |
297 | * -ENOTSUPP - Function not supported in current display mode. |
241 | * -EIO - Failed, e.g., due to failed scanout position query. |
298 | * -EIO - Failed, e.g., due to failed scanout position query. |
242 | * |
299 | * |
243 | * Returns or'ed positive status flags on success: |
300 | * Returns or'ed positive status flags on success: |
Line 285... | Line 342... | ||
285 | 342 | ||
286 | return -EIO; |
343 | return -EIO; |
287 | } |
344 | } |
Line -... | Line 345... | ||
- | 345 | EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos); |
|
- | 346 | ||
- | 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; |
|
- | 367 | ||
- | 368 | ||
- | 369 | } |
|
- | 370 | EXPORT_SYMBOL(drm_vblank_off); |
|
- | 371 | ||
- | 372 | /** |
|
- | 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)); |
|
Line 288... | Line 424... | ||
288 | EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos); |
424 | } |
289 | 425 | EXPORT_SYMBOL(drm_crtc_vblank_on); |
|
290 | 426 | ||
291 | /** |
427 | /** |
292 | * drm_vblank_pre_modeset - account for vblanks across mode sets |
428 | * drm_vblank_pre_modeset - account for vblanks across mode sets |
293 | * @dev: DRM device |
429 | * @dev: DRM device |
294 | * @crtc: CRTC in question |
430 | * @crtc: CRTC in question |
- | 431 | * |
|
- | 432 | * Account for vblank events across mode setting events, which will likely |
|
- | 433 | * reset the hardware frame counter. |
|
- | 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. |
|
295 | * |
446 | * |
296 | * Account for vblank events across mode setting events, which will likely |
447 | * Drivers must call drm_vblank_post_modeset() when re-enabling the same crtc |
297 | * reset the hardware frame counter. |
448 | * again. |
298 | */ |
449 | */ |
299 | void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) |
450 | void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) |
Line 316... | Line 467... | ||
316 | } |
467 | } |
317 | #endif |
468 | #endif |
318 | } |
469 | } |
319 | EXPORT_SYMBOL(drm_vblank_pre_modeset); |
470 | EXPORT_SYMBOL(drm_vblank_pre_modeset); |
Line -... | Line 471... | ||
- | 471 | ||
- | 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. |
|
320 | 479 | */ |
|
321 | void drm_vblank_post_modeset(struct drm_device *dev, int crtc) |
480 | void drm_vblank_post_modeset(struct drm_device *dev, int crtc) |
322 | { |
481 | { |
323 | #if 0 |
482 | #if 0 |