Rev 5271 | Rev 6088 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5271 | Rev 6084 | ||
---|---|---|---|
Line 40... | Line 40... | ||
40 | #include |
40 | #include |
Line 41... | Line 41... | ||
41 | 41 | ||
42 | #include |
42 | #include |
Line -... | Line 43... | ||
- | 43 | #include |
|
- | 44 | ||
- | 45 | ktime_t ktime_get(void); |
|
- | 46 | ||
- | 47 | static inline ktime_t ktime_get_real(void) |
|
- | 48 | { |
|
- | 49 | return ktime_get(); |
|
- | 50 | } |
|
- | 51 | ||
- | 52 | static inline ktime_t ktime_mono_to_real(ktime_t mono) |
|
- | 53 | { |
|
- | 54 | return mono; |
|
- | 55 | } |
|
43 | #include |
56 | |
44 | 57 | ||
45 | /* Access macro for slots in vblank timestamp ringbuffer. */ |
58 | /* Access macro for slots in vblank timestamp ringbuffer. */ |
Line 46... | Line 59... | ||
46 | #define vblanktimestamp(dev, crtc, count) \ |
59 | #define vblanktimestamp(dev, pipe, count) \ |
47 | ((dev)->vblank[crtc].time[(count) % DRM_VBLANKTIME_RBSIZE]) |
60 | ((dev)->vblank[pipe].time[(count) % DRM_VBLANKTIME_RBSIZE]) |
48 | 61 | ||
49 | /* Retry timestamp calculation up to 3 times to satisfy |
62 | /* Retry timestamp calculation up to 3 times to satisfy |
Line 55... | Line 68... | ||
55 | * vblank irq in drm_handle_vblank(). 1 msec should be ok. |
68 | * vblank irq in drm_handle_vblank(). 1 msec should be ok. |
56 | */ |
69 | */ |
57 | #define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000 |
70 | #define DRM_REDUNDANT_VBLIRQ_THRESH_NS 1000000 |
Line 58... | Line 71... | ||
58 | 71 | ||
59 | static bool |
72 | static bool |
60 | drm_get_last_vbltimestamp(struct drm_device *dev, int crtc, |
73 | drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, |
Line 61... | Line 74... | ||
61 | struct timeval *tvblank, unsigned flags); |
74 | struct timeval *tvblank, unsigned flags); |
Line 62... | Line 75... | ||
62 | 75 | ||
63 | static unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */ |
76 | static unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */ |
- | 77 | ||
64 | 78 | /* |
|
- | 79 | * Default to use monotonic timestamps for wait-for-vblank and page-flip |
|
Line -... | Line 80... | ||
- | 80 | * complete events. |
|
- | 81 | */ |
|
- | 82 | unsigned int drm_timestamp_monotonic = 1; |
|
- | 83 | ||
- | 84 | static int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */ |
|
- | 85 | ||
- | 86 | module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600); |
|
- | 87 | module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600); |
|
- | 88 | module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600); |
|
- | 89 | ||
- | 90 | static void store_vblank(struct drm_device *dev, unsigned int pipe, |
|
- | 91 | u32 vblank_count_inc, |
|
- | 92 | struct timeval *t_vblank, u32 last) |
|
- | 93 | { |
|
- | 94 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
|
- | 95 | u32 tslot; |
|
- | 96 | ||
- | 97 | assert_spin_locked(&dev->vblank_time_lock); |
|
- | 98 | ||
- | 99 | vblank->last = last; |
|
- | 100 | ||
- | 101 | /* All writers hold the spinlock, but readers are serialized by |
|
- | 102 | * the latching of vblank->count below. |
|
- | 103 | */ |
|
- | 104 | tslot = vblank->count + vblank_count_inc; |
|
- | 105 | vblanktimestamp(dev, pipe, tslot) = *t_vblank; |
|
- | 106 | ||
- | 107 | /* |
|
- | 108 | * vblank timestamp updates are protected on the write side with |
|
- | 109 | * vblank_time_lock, but on the read side done locklessly using a |
|
- | 110 | * sequence-lock on the vblank counter. Ensure correct ordering using |
|
- | 111 | * memory barrriers. We need the barrier both before and also after the |
|
- | 112 | * counter update to synchronize with the next timestamp write. |
|
- | 113 | * The read-side barriers for this are in drm_vblank_count_and_time. |
|
- | 114 | */ |
|
- | 115 | smp_wmb(); |
|
- | 116 | vblank->count += vblank_count_inc; |
|
- | 117 | smp_wmb(); |
|
- | 118 | } |
|
- | 119 | ||
- | 120 | /** |
|
- | 121 | * drm_reset_vblank_timestamp - reset the last timestamp to the last vblank |
|
- | 122 | * @dev: DRM device |
|
- | 123 | * @pipe: index of CRTC for which to reset the timestamp |
|
- | 124 | * |
|
- | 125 | * Reset the stored timestamp for the current vblank count to correspond |
|
- | 126 | * to the last vblank occurred. |
|
- | 127 | * |
|
- | 128 | * Only to be called from drm_vblank_on(). |
|
- | 129 | * |
|
- | 130 | * Note: caller must hold dev->vbl_lock since this reads & writes |
|
- | 131 | * device vblank fields. |
|
- | 132 | */ |
|
- | 133 | static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe) |
|
- | 134 | { |
|
- | 135 | u32 cur_vblank; |
|
- | 136 | bool rc; |
|
- | 137 | struct timeval t_vblank; |
|
- | 138 | int count = DRM_TIMESTAMP_MAXRETRIES; |
|
- | 139 | ||
- | 140 | spin_lock(&dev->vblank_time_lock); |
|
- | 141 | ||
- | 142 | /* |
|
- | 143 | * sample the current counter to avoid random jumps |
|
- | 144 | * when drm_vblank_enable() applies the diff |
|
- | 145 | */ |
|
- | 146 | do { |
|
- | 147 | cur_vblank = dev->driver->get_vblank_counter(dev, pipe); |
|
- | 148 | rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, 0); |
|
- | 149 | } while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe) && --count > 0); |
|
- | 150 | ||
- | 151 | /* |
|
- | 152 | * Only reinitialize corresponding vblank timestamp if high-precision query |
|
- | 153 | * available and didn't fail. Otherwise reinitialize delayed at next vblank |
|
- | 154 | * interrupt and assign 0 for now, to mark the vblanktimestamp as invalid. |
|
- | 155 | */ |
|
- | 156 | if (!rc) |
|
- | 157 | t_vblank = (struct timeval) {0, 0}; |
|
- | 158 | ||
- | 159 | /* |
|
- | 160 | * +1 to make sure user will never see the same |
|
- | 161 | * vblank counter value before and after a modeset |
|
- | 162 | */ |
|
- | 163 | store_vblank(dev, pipe, 1, &t_vblank, cur_vblank); |
|
- | 164 | ||
- | 165 | spin_unlock(&dev->vblank_time_lock); |
|
- | 166 | } |
|
- | 167 | ||
- | 168 | /** |
|
- | 169 | * drm_update_vblank_count - update the master vblank counter |
|
- | 170 | * @dev: DRM device |
|
- | 171 | * @pipe: counter to update |
|
- | 172 | * |
|
- | 173 | * Call back into the driver to update the appropriate vblank counter |
|
- | 174 | * (specified by @pipe). Deal with wraparound, if it occurred, and |
|
- | 175 | * update the last read value so we can deal with wraparound on the next |
|
- | 176 | * call if necessary. |
|
- | 177 | * |
|
- | 178 | * Only necessary when going from off->on, to account for frames we |
|
- | 179 | * didn't get an interrupt for. |
|
- | 180 | * |
|
- | 181 | * Note: caller must hold dev->vbl_lock since this reads & writes |
|
- | 182 | * device vblank fields. |
|
- | 183 | */ |
|
- | 184 | static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, |
|
- | 185 | unsigned long flags) |
|
- | 186 | { |
|
- | 187 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
|
- | 188 | u32 cur_vblank, diff; |
|
- | 189 | bool rc; |
|
- | 190 | struct timeval t_vblank; |
|
- | 191 | int count = DRM_TIMESTAMP_MAXRETRIES; |
|
- | 192 | int framedur_ns = vblank->framedur_ns; |
|
- | 193 | ||
- | 194 | /* |
|
- | 195 | * Interrupts were disabled prior to this call, so deal with counter |
|
- | 196 | * wrap if needed. |
|
- | 197 | * NOTE! It's possible we lost a full dev->max_vblank_count + 1 events |
|
- | 198 | * here if the register is small or we had vblank interrupts off for |
|
- | 199 | * a long time. |
|
- | 200 | * |
|
- | 201 | * We repeat the hardware vblank counter & timestamp query until |
|
- | 202 | * we get consistent results. This to prevent races between gpu |
|
- | 203 | * updating its hardware counter while we are retrieving the |
|
- | 204 | * corresponding vblank timestamp. |
|
- | 205 | */ |
|
- | 206 | do { |
|
- | 207 | cur_vblank = dev->driver->get_vblank_counter(dev, pipe); |
|
- | 208 | rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, flags); |
|
- | 209 | } while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe) && --count > 0); |
|
- | 210 | ||
- | 211 | if (dev->max_vblank_count != 0) { |
|
- | 212 | /* trust the hw counter when it's around */ |
|
- | 213 | diff = (cur_vblank - vblank->last) & dev->max_vblank_count; |
|
- | 214 | } else if (rc && framedur_ns) { |
|
- | 215 | const struct timeval *t_old; |
|
- | 216 | u64 diff_ns; |
|
- | 217 | ||
- | 218 | t_old = &vblanktimestamp(dev, pipe, vblank->count); |
|
- | 219 | diff_ns = timeval_to_ns(&t_vblank) - timeval_to_ns(t_old); |
|
- | 220 | ||
- | 221 | /* |
|
- | 222 | * Figure out how many vblanks we've missed based |
|
- | 223 | * on the difference in the timestamps and the |
|
- | 224 | * frame/field duration. |
|
- | 225 | */ |
|
- | 226 | diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns); |
|
- | 227 | ||
- | 228 | if (diff == 0 && flags & DRM_CALLED_FROM_VBLIRQ) |
|
- | 229 | DRM_DEBUG_VBL("crtc %u: Redundant vblirq ignored." |
|
- | 230 | " diff_ns = %lld, framedur_ns = %d)\n", |
|
- | 231 | pipe, (long long) diff_ns, framedur_ns); |
|
- | 232 | } else { |
|
- | 233 | /* some kind of default for drivers w/o accurate vbl timestamping */ |
|
- | 234 | diff = (flags & DRM_CALLED_FROM_VBLIRQ) != 0; |
|
- | 235 | } |
|
- | 236 | ||
- | 237 | DRM_DEBUG_VBL("updating vblank count on crtc %u:" |
|
- | 238 | " current=%u, diff=%u, hw=%u hw_last=%u\n", |
|
- | 239 | pipe, vblank->count, diff, cur_vblank, vblank->last); |
|
- | 240 | ||
- | 241 | if (diff == 0) { |
|
- | 242 | WARN_ON_ONCE(cur_vblank != vblank->last); |
|
- | 243 | return; |
|
- | 244 | } |
|
- | 245 | ||
- | 246 | /* |
|
- | 247 | * Only reinitialize corresponding vblank timestamp if high-precision query |
|
- | 248 | * available and didn't fail, or we were called from the vblank interrupt. |
|
- | 249 | * Otherwise reinitialize delayed at next vblank interrupt and assign 0 |
|
- | 250 | * for now, to mark the vblanktimestamp as invalid. |
|
- | 251 | */ |
|
- | 252 | if (!rc && (flags & DRM_CALLED_FROM_VBLIRQ) == 0) |
|
- | 253 | t_vblank = (struct timeval) {0, 0}; |
|
- | 254 | ||
- | 255 | store_vblank(dev, pipe, diff, &t_vblank, cur_vblank); |
|
- | 256 | } |
|
- | 257 | ||
- | 258 | /* |
|
- | 259 | * Disable vblank irq's on crtc, make sure that last vblank count |
|
- | 260 | * of hardware and corresponding consistent software vblank counter |
|
- | 261 | * are preserved, even if there are any spurious vblank irq's after |
|
- | 262 | * disable. |
|
- | 263 | */ |
|
- | 264 | static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe) |
|
- | 265 | { |
|
- | 266 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
|
- | 267 | unsigned long irqflags; |
|
- | 268 | ||
- | 269 | /* Prevent vblank irq processing while disabling vblank irqs, |
|
- | 270 | * so no updates of timestamps or count can happen after we've |
|
- | 271 | * disabled. Needed to prevent races in case of delayed irq's. |
|
- | 272 | */ |
|
- | 273 | spin_lock_irqsave(&dev->vblank_time_lock, irqflags); |
|
- | 274 | ||
- | 275 | /* |
|
- | 276 | * Only disable vblank interrupts if they're enabled. This avoids |
|
- | 277 | * calling the ->disable_vblank() operation in atomic context with the |
|
- | 278 | * hardware potentially runtime suspended. |
|
- | 279 | */ |
|
- | 280 | if (vblank->enabled) { |
|
- | 281 | dev->driver->disable_vblank(dev, pipe); |
|
- | 282 | vblank->enabled = false; |
|
- | 283 | } |
|
- | 284 | ||
- | 285 | /* |
|
- | 286 | * Always update the count and timestamp to maintain the |
|
- | 287 | * appearance that the counter has been ticking all along until |
|
- | 288 | * this time. This makes the count account for the entire time |
|
- | 289 | * between drm_vblank_on() and drm_vblank_off(). |
|
- | 290 | */ |
|
- | 291 | drm_update_vblank_count(dev, pipe, 0); |
|
- | 292 | ||
- | 293 | spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); |
|
- | 294 | } |
|
- | 295 | ||
- | 296 | static void vblank_disable_fn(unsigned long arg) |
|
- | 297 | { |
|
- | 298 | struct drm_vblank_crtc *vblank = (void *)arg; |
|
- | 299 | struct drm_device *dev = vblank->dev; |
|
- | 300 | unsigned int pipe = vblank->pipe; |
|
- | 301 | unsigned long irqflags; |
|
- | 302 | ||
- | 303 | if (!dev->vblank_disable_allowed) |
|
- | 304 | return; |
|
- | 305 | ||
- | 306 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
|
- | 307 | if (atomic_read(&vblank->refcount) == 0 && vblank->enabled) { |
|
- | 308 | DRM_DEBUG("disabling vblank on crtc %u\n", pipe); |
|
- | 309 | vblank_disable_and_save(dev, pipe); |
|
- | 310 | } |
|
- | 311 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
|
- | 312 | } |
|
- | 313 | ||
- | 314 | /** |
|
- | 315 | * drm_vblank_cleanup - cleanup vblank support |
|
- | 316 | * @dev: DRM device |
|
- | 317 | * |
|
- | 318 | * This function cleans up any resources allocated in drm_vblank_init. |
|
- | 319 | */ |
|
- | 320 | void drm_vblank_cleanup(struct drm_device *dev) |
|
- | 321 | { |
|
- | 322 | unsigned int pipe; |
|
- | 323 | ||
- | 324 | /* Bail if the driver didn't call drm_vblank_init() */ |
|
- | 325 | if (dev->num_crtcs == 0) |
|
- | 326 | return; |
|
- | 327 | ||
- | 328 | for (pipe = 0; pipe < dev->num_crtcs; pipe++) { |
|
- | 329 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
|
- | 330 | ||
- | 331 | WARN_ON(vblank->enabled && |
|
- | 332 | drm_core_check_feature(dev, DRIVER_MODESET)); |
|
- | 333 | ||
- | 334 | del_timer_sync(&vblank->disable_timer); |
|
- | 335 | } |
|
- | 336 | ||
- | 337 | kfree(dev->vblank); |
|
Line 65... | Line -... | ||
65 | /* |
- | |
66 | * Clear vblank timestamp buffer for a crtc. |
338 | |
67 | */ |
339 | dev->num_crtcs = 0; |
68 | 340 | } |
|
69 | 341 | EXPORT_SYMBOL(drm_vblank_cleanup); |
|
70 | #if 0 |
342 | |
71 | /** |
343 | /** |
72 | * drm_vblank_init - initialize vblank support |
344 | * drm_vblank_init - initialize vblank support |
73 | * @dev: drm_device |
345 | * @dev: DRM device |
74 | * @num_crtcs: number of crtcs supported by @dev |
346 | * @num_crtcs: number of CRTCs supported by @dev |
75 | * |
347 | * |
76 | * This function initializes vblank support for @num_crtcs display pipelines. |
348 | * This function initializes vblank support for @num_crtcs display pipelines. |
77 | * |
349 | * |
78 | * Returns: |
350 | * Returns: |
- | 351 | * Zero on success or a negative error code on failure. |
|
Line 79... | Line 352... | ||
79 | * Zero on success or a negative error code on failure. |
352 | */ |
80 | */ |
353 | int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs) |
Line 81... | Line 354... | ||
81 | int drm_vblank_init(struct drm_device *dev, int num_crtcs) |
354 | { |
Line 93... | Line 366... | ||
93 | 366 | ||
94 | for (i = 0; i < num_crtcs; i++) { |
367 | for (i = 0; i < num_crtcs; i++) { |
Line 95... | Line 368... | ||
95 | struct drm_vblank_crtc *vblank = &dev->vblank[i]; |
368 | struct drm_vblank_crtc *vblank = &dev->vblank[i]; |
96 | 369 | ||
97 | vblank->dev = dev; |
370 | vblank->dev = dev; |
98 | vblank->crtc = i; |
371 | vblank->pipe = i; |
99 | init_waitqueue_head(&vblank->queue); |
372 | init_waitqueue_head(&vblank->queue); |
100 | setup_timer(&vblank->disable_timer, vblank_disable_fn, |
373 | // setup_timer(&vblank->disable_timer, vblank_disable_fn, |
Line 101... | Line 374... | ||
101 | (unsigned long)vblank); |
374 | // (unsigned long)vblank); |
Line 102... | Line 375... | ||
102 | } |
375 | } |
103 | 376 | ||
104 | DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n"); |
377 | DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n"); |
105 | 378 | ||
106 | /* Driver specific high-precision vblank timestamping supported? */ |
379 | /* Driver specific high-precision vblank timestamping supported? */ |
Line -... | Line 380... | ||
- | 380 | if (dev->driver->get_vblank_timestamp) |
|
- | 381 | DRM_INFO("Driver supports precise vblank timestamp query.\n"); |
|
- | 382 | else |
|
- | 383 | DRM_INFO("No driver support for vblank timestamp query.\n"); |
|
- | 384 | ||
- | 385 | /* Must have precise timestamping for reliable vblank instant disable */ |
|
- | 386 | if (dev->vblank_disable_immediate && !dev->driver->get_vblank_timestamp) { |
|
107 | if (dev->driver->get_vblank_timestamp) |
387 | dev->vblank_disable_immediate = false; |
Line 108... | Line 388... | ||
108 | DRM_INFO("Driver supports precise vblank timestamp query.\n"); |
388 | DRM_INFO("Setting vblank_disable_immediate to false because " |
Line 109... | Line 389... | ||
109 | else |
389 | "get_vblank_timestamp == NULL\n"); |
110 | DRM_INFO("No driver support for vblank timestamp query.\n"); |
390 | } |
111 | 391 | ||
112 | dev->vblank_disable_allowed = false; |
392 | dev->vblank_disable_allowed = false; |
113 | 393 | ||
Line 114... | Line 394... | ||
114 | return 0; |
394 | return 0; |
Line 115... | Line 395... | ||
115 | 395 | ||
116 | err: |
396 | err: |
Line 117... | Line 397... | ||
117 | dev->num_crtcs = 0; |
397 | dev->num_crtcs = 0; |
Line 149... | Line 429... | ||
149 | * Zero on success or a negative error code on failure. |
429 | * Zero on success or a negative error code on failure. |
150 | */ |
430 | */ |
151 | int drm_irq_install(struct drm_device *dev, int irq) |
431 | int drm_irq_install(struct drm_device *dev, int irq) |
152 | { |
432 | { |
153 | int ret; |
433 | int ret; |
154 | unsigned long sh_flags = 0; |
434 | unsigned long sh_flags = 0; |
Line 155... | Line 435... | ||
155 | 435 | ||
156 | if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) |
436 | if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) |
Line 157... | Line 437... | ||
157 | return -EINVAL; |
437 | return -EINVAL; |
158 | 438 | ||
Line 159... | Line 439... | ||
159 | if (irq == 0) |
439 | if (irq == 0) |
160 | return -EINVAL; |
440 | return -EINVAL; |
161 | 441 | ||
Line 162... | Line 442... | ||
162 | /* Driver must have been initialized */ |
442 | /* Driver must have been initialized */ |
163 | if (!dev->dev_private) |
443 | if (!dev->dev_private) |
164 | return -EINVAL; |
444 | return -EINVAL; |
Line 165... | Line 445... | ||
165 | 445 | ||
Line 166... | Line 446... | ||
166 | if (dev->irq_enabled) |
446 | if (dev->irq_enabled) |
167 | return -EBUSY; |
447 | return -EBUSY; |
168 | dev->irq_enabled = true; |
448 | dev->irq_enabled = true; |
Line 169... | Line 449... | ||
169 | 449 | ||
Line 170... | Line 450... | ||
170 | DRM_DEBUG("irq=%d\n", irq); |
450 | DRM_DEBUG("irq=%d\n", irq); |
171 | 451 | ||
172 | /* Before installing handler */ |
452 | /* Before installing handler */ |
Line 173... | Line 453... | ||
173 | if (dev->driver->irq_preinstall) |
453 | if (dev->driver->irq_preinstall) |
174 | dev->driver->irq_preinstall(dev); |
454 | dev->driver->irq_preinstall(dev); |
175 | - | ||
176 | ret = !AttachIntHandler(irq, device_irq_handler, (u32)dev); |
455 | |
177 | 456 | ret = !AttachIntHandler(irq, device_irq_handler, (u32)dev); |
|
178 | /* After installing handler */ |
457 | |
Line 179... | Line 458... | ||
179 | if (dev->driver->irq_postinstall) |
458 | /* After installing handler */ |
180 | ret = dev->driver->irq_postinstall(dev); |
459 | if (dev->driver->irq_postinstall) |
181 | 460 | ret = dev->driver->irq_postinstall(dev); |
|
Line 195... | Line 474... | ||
195 | EXPORT_SYMBOL(drm_irq_install); |
474 | EXPORT_SYMBOL(drm_irq_install); |
Line 196... | Line -... | ||
196 | - | ||
197 | - | ||
198 | - | ||
199 | - | ||
200 | u64 div64_u64(u64 dividend, u64 divisor) |
- | |
201 | { |
- | |
202 | u32 high, d; |
- | |
203 | - | ||
204 | high = divisor >> 32; |
- | |
205 | if (high) { |
- | |
206 | unsigned int shift = fls(high); |
- | |
207 | - | ||
208 | d = divisor >> shift; |
- | |
209 | dividend >>= shift; |
- | |
210 | } else |
- | |
Line 211... | Line 475... | ||
211 | d = divisor; |
475 | |
212 | 476 | ||
213 | return div_u64(dividend, d); |
477 | |
214 | } |
478 | |
Line 225... | Line 489... | ||
225 | * things like panel scaling or other adjustments into account. |
489 | * things like panel scaling or other adjustments into account. |
226 | */ |
490 | */ |
227 | void drm_calc_timestamping_constants(struct drm_crtc *crtc, |
491 | void drm_calc_timestamping_constants(struct drm_crtc *crtc, |
228 | const struct drm_display_mode *mode) |
492 | const struct drm_display_mode *mode) |
229 | { |
493 | { |
- | 494 | struct drm_device *dev = crtc->dev; |
|
- | 495 | unsigned int pipe = drm_crtc_index(crtc); |
|
- | 496 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
|
230 | int linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0; |
497 | int linedur_ns = 0, framedur_ns = 0; |
231 | int dotclock = mode->crtc_clock; |
498 | int dotclock = mode->crtc_clock; |
Line -... | Line 499... | ||
- | 499 | ||
- | 500 | if (!dev->num_crtcs) |
|
- | 501 | return; |
|
- | 502 | ||
- | 503 | if (WARN_ON(pipe >= dev->num_crtcs)) |
|
- | 504 | return; |
|
232 | 505 | ||
233 | /* Valid dotclock? */ |
506 | /* Valid dotclock? */ |
234 | if (dotclock > 0) { |
507 | if (dotclock > 0) { |
Line 235... | Line 508... | ||
235 | int frame_size = mode->crtc_htotal * mode->crtc_vtotal; |
508 | int frame_size = mode->crtc_htotal * mode->crtc_vtotal; |
236 | 509 | ||
237 | /* |
510 | /* |
238 | * Convert scanline length in pixels and video |
511 | * Convert scanline length in pixels and video |
239 | * dot clock to line duration, frame duration |
512 | * dot clock to line duration and frame duration |
240 | * and pixel duration in nanoseconds: |
- | |
241 | */ |
513 | * in nanoseconds: |
242 | pixeldur_ns = 1000000 / dotclock; |
514 | */ |
Line 243... | Line 515... | ||
243 | linedur_ns = div_u64((u64) mode->crtc_htotal * 1000000, dotclock); |
515 | linedur_ns = div_u64((u64) mode->crtc_htotal * 1000000, dotclock); |
244 | framedur_ns = div_u64((u64) frame_size * 1000000, dotclock); |
516 | framedur_ns = div_u64((u64) frame_size * 1000000, dotclock); |
245 | 517 | ||
246 | /* |
518 | /* |
247 | * Fields of interlaced scanout modes are only half a frame duration. |
519 | * Fields of interlaced scanout modes are only half a frame duration. |
248 | */ |
520 | */ |
249 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) |
521 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) |
250 | framedur_ns /= 2; |
522 | framedur_ns /= 2; |
Line 251... | Line -... | ||
251 | } else |
- | |
252 | DRM_ERROR("crtc %d: Can't calculate constants, dotclock = 0!\n", |
523 | } else |
253 | crtc->base.id); |
524 | DRM_ERROR("crtc %u: Can't calculate constants, dotclock = 0!\n", |
Line 254... | Line 525... | ||
254 | 525 | crtc->base.id); |
|
255 | crtc->pixeldur_ns = pixeldur_ns; |
526 | |
256 | crtc->linedur_ns = linedur_ns; |
527 | vblank->linedur_ns = linedur_ns; |
257 | crtc->framedur_ns = framedur_ns; |
528 | vblank->framedur_ns = framedur_ns; |
258 | 529 | ||
259 | DRM_DEBUG("crtc %d: hwmode: htotal %d, vtotal %d, vdisplay %d\n", |
- | |
260 | crtc->base.id, mode->crtc_htotal, |
530 | DRM_DEBUG("crtc %u: hwmode: htotal %d, vtotal %d, vdisplay %d\n", |
261 | mode->crtc_vtotal, mode->crtc_vdisplay); |
531 | crtc->base.id, mode->crtc_htotal, |
Line 262... | Line 532... | ||
262 | DRM_DEBUG("crtc %d: clock %d kHz framedur %d linedur %d, pixeldur %d\n", |
532 | mode->crtc_vtotal, mode->crtc_vdisplay); |
263 | crtc->base.id, dotclock, framedur_ns, |
533 | DRM_DEBUG("crtc %u: clock %d kHz framedur %d linedur %d\n", |
264 | linedur_ns, pixeldur_ns); |
534 | crtc->base.id, dotclock, framedur_ns, linedur_ns); |
265 | } |
535 | } |
266 | EXPORT_SYMBOL(drm_calc_timestamping_constants); |
536 | EXPORT_SYMBOL(drm_calc_timestamping_constants); |
267 | 537 | ||
268 | /** |
538 | /** |
269 | * drm_calc_vbltimestamp_from_scanoutpos - precise vblank timestamp helper |
539 | * drm_calc_vbltimestamp_from_scanoutpos - precise vblank timestamp helper |
270 | * @dev: DRM device |
540 | * @dev: DRM device |
271 | * @crtc: Which CRTC's vblank timestamp to retrieve |
541 | * @pipe: index of CRTC whose vblank timestamp to retrieve |
272 | * @max_error: Desired maximum allowable error in timestamps (nanosecs) |
- | |
273 | * On return contains true maximum error of timestamp |
542 | * @max_error: Desired maximum allowable error in timestamps (nanosecs) |
274 | * @vblank_time: Pointer to struct timeval which should receive the timestamp |
543 | * On return contains true maximum error of timestamp |
275 | * @flags: Flags to pass to driver: |
544 | * @vblank_time: Pointer to struct timeval which should receive the timestamp |
276 | * 0 = Default, |
545 | * @flags: Flags to pass to driver: |
277 | * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl IRQ handler |
546 | * 0 = Default, |
Line 309... | Line 578... | ||
309 | * |
578 | * |
310 | * DRM_VBLANKTIME_SCANOUTPOS_METHOD - Signal this method used for timestamping. |
579 | * DRM_VBLANKTIME_SCANOUTPOS_METHOD - Signal this method used for timestamping. |
311 | * DRM_VBLANKTIME_INVBL - Timestamp taken while scanout was in vblank interval. |
580 | * DRM_VBLANKTIME_INVBL - Timestamp taken while scanout was in vblank interval. |
312 | * |
581 | * |
313 | */ |
582 | */ |
314 | int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, |
583 | int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, |
- | 584 | unsigned int pipe, |
|
315 | int *max_error, |
585 | int *max_error, |
316 | struct timeval *vblank_time, |
586 | struct timeval *vblank_time, |
317 | unsigned flags, |
587 | unsigned flags, |
318 | const struct drm_crtc *refcrtc, |
- | |
319 | const struct drm_display_mode *mode) |
588 | const struct drm_display_mode *mode) |
320 | { |
589 | { |
321 | struct timeval tv_etime; |
590 | struct timeval tv_etime; |
- | 591 | ktime_t stime, etime; |
|
322 | int vbl_status; |
592 | unsigned int vbl_status; |
- | 593 | int ret = DRM_VBLANKTIME_SCANOUTPOS_METHOD; |
|
323 | int vpos, hpos, i; |
594 | int vpos, hpos, i; |
324 | int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns; |
595 | int delta_ns, duration_ns; |
325 | bool invbl; |
- | |
Line 326... | Line 596... | ||
326 | 596 | ||
327 | if (crtc < 0 || crtc >= dev->num_crtcs) { |
597 | if (pipe >= dev->num_crtcs) { |
328 | DRM_ERROR("Invalid crtc %d\n", crtc); |
598 | DRM_ERROR("Invalid crtc %u\n", pipe); |
329 | return -EINVAL; |
599 | return -EINVAL; |
Line 330... | Line 600... | ||
330 | } |
600 | } |
331 | 601 | ||
332 | /* Scanout position query not supported? Should not happen. */ |
602 | /* Scanout position query not supported? Should not happen. */ |
333 | if (!dev->driver->get_scanout_position) { |
603 | if (!dev->driver->get_scanout_position) { |
334 | DRM_ERROR("Called from driver w/o get_scanout_position()!?\n"); |
604 | DRM_ERROR("Called from driver w/o get_scanout_position()!?\n"); |
Line 335... | Line -... | ||
335 | return -EIO; |
- | |
336 | } |
- | |
337 | - | ||
338 | /* Durations of frames, lines, pixels in nanoseconds. */ |
- | |
339 | framedur_ns = refcrtc->framedur_ns; |
- | |
340 | linedur_ns = refcrtc->linedur_ns; |
605 | return -EIO; |
341 | pixeldur_ns = refcrtc->pixeldur_ns; |
606 | } |
342 | 607 | ||
343 | /* If mode timing undefined, just return as no-op: |
608 | /* If mode timing undefined, just return as no-op: |
344 | * Happens during initial modesetting of a crtc. |
609 | * Happens during initial modesetting of a crtc. |
345 | */ |
610 | */ |
346 | if (framedur_ns == 0) { |
611 | if (mode->crtc_clock == 0) { |
Line -... | Line 612... | ||
- | 612 | DRM_DEBUG("crtc %u: Noop due to uninitialized mode.\n", pipe); |
|
- | 613 | return -EAGAIN; |
|
- | 614 | } |
|
- | 615 | ||
- | 616 | /* Get current scanout position with system timestamp. |
|
- | 617 | * Repeat query up to DRM_TIMESTAMP_MAXRETRIES times |
|
- | 618 | * if single query takes longer than max_error nanoseconds. |
|
- | 619 | * |
|
- | 620 | * This guarantees a tight bound on maximum error if |
|
- | 621 | * code gets preempted or delayed for some reason. |
|
- | 622 | */ |
|
- | 623 | for (i = 0; i < DRM_TIMESTAMP_MAXRETRIES; i++) { |
|
- | 624 | /* |
|
- | 625 | * Get vertical and horizontal scanout position vpos, hpos, |
|
- | 626 | * and bounding timestamps stime, etime, pre/post query. |
|
- | 627 | */ |
|
- | 628 | vbl_status = dev->driver->get_scanout_position(dev, pipe, flags, |
|
- | 629 | &vpos, &hpos, |
|
- | 630 | &stime, &etime, |
|
- | 631 | mode); |
|
- | 632 | ||
347 | DRM_DEBUG("crtc %d: Noop due to uninitialized mode.\n", crtc); |
633 | /* Return as no-op if scanout query unsupported or failed. */ |
- | 634 | if (!(vbl_status & DRM_SCANOUTPOS_VALID)) { |
|
- | 635 | DRM_DEBUG("crtc %u : scanoutpos query failed [0x%x].\n", |
|
- | 636 | pipe, vbl_status); |
|
- | 637 | return -EIO; |
|
- | 638 | } |
|
- | 639 | ||
- | 640 | /* Compute uncertainty in timestamp of scanout position query. */ |
|
- | 641 | duration_ns = ktime_to_ns(etime) - ktime_to_ns(stime); |
|
- | 642 | ||
- | 643 | /* Accept result with < max_error nsecs timing uncertainty. */ |
|
- | 644 | if (duration_ns <= *max_error) |
|
- | 645 | break; |
|
- | 646 | } |
|
- | 647 | ||
- | 648 | /* Noisy system timing? */ |
|
- | 649 | if (i == DRM_TIMESTAMP_MAXRETRIES) { |
|
- | 650 | DRM_DEBUG("crtc %u: Noisy timestamp %d us > %d us [%d reps].\n", |
|
- | 651 | pipe, duration_ns/1000, *max_error/1000, i); |
|
- | 652 | } |
|
- | 653 | ||
- | 654 | /* Return upper bound of timestamp precision error. */ |
|
- | 655 | *max_error = duration_ns; |
|
- | 656 | ||
- | 657 | /* Check if in vblank area: |
|
- | 658 | * vpos is >=0 in video scanout area, but negative |
|
- | 659 | * within vblank area, counting down the number of lines until |
|
- | 660 | * start of scanout. |
|
- | 661 | */ |
|
- | 662 | if (vbl_status & DRM_SCANOUTPOS_IN_VBLANK) |
|
- | 663 | ret |= DRM_VBLANKTIME_IN_VBLANK; |
|
- | 664 | ||
- | 665 | /* Convert scanout position into elapsed time at raw_time query |
|
- | 666 | * since start of scanout at first display scanline. delta_ns |
|
- | 667 | * can be negative if start of scanout hasn't happened yet. |
|
- | 668 | */ |
|
- | 669 | delta_ns = div_s64(1000000LL * (vpos * mode->crtc_htotal + hpos), |
|
- | 670 | mode->crtc_clock); |
|
- | 671 | ||
- | 672 | if (!drm_timestamp_monotonic) |
|
- | 673 | etime = ktime_mono_to_real(etime); |
|
- | 674 | ||
- | 675 | /* save this only for debugging purposes */ |
|
- | 676 | tv_etime = ktime_to_timeval(etime); |
|
- | 677 | /* Subtract time delta from raw timestamp to get final |
|
- | 678 | * vblank_time timestamp for end of vblank. |
|
- | 679 | */ |
|
- | 680 | if (delta_ns < 0) |
|
- | 681 | etime = ktime_add_ns(etime, -delta_ns); |
|
- | 682 | else |
|
- | 683 | etime = ktime_sub_ns(etime, delta_ns); |
|
- | 684 | *vblank_time = ktime_to_timeval(etime); |
|
- | 685 | ||
- | 686 | DRM_DEBUG_VBL("crtc %u : v 0x%x p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n", |
|
- | 687 | pipe, vbl_status, hpos, vpos, |
|
- | 688 | (long)tv_etime.tv_sec, (long)tv_etime.tv_usec, |
|
348 | return -EAGAIN; |
689 | (long)vblank_time->tv_sec, (long)vblank_time->tv_usec, |
349 | } |
690 | duration_ns/1000, i); |
Line -... | Line 691... | ||
- | 691 | ||
- | 692 | return ret; |
|
- | 693 | } |
|
- | 694 | EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos); |
|
- | 695 | ||
- | 696 | static struct timeval get_drm_timestamp(void) |
|
- | 697 | { |
|
- | 698 | ktime_t now; |
|
- | 699 | ||
- | 700 | now = drm_timestamp_monotonic ? ktime_get() : ktime_get_real(); |
|
- | 701 | return ktime_to_timeval(now); |
|
- | 702 | } |
|
- | 703 | ||
- | 704 | /** |
|
- | 705 | * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent |
|
- | 706 | * vblank interval |
|
- | 707 | * @dev: DRM device |
|
- | 708 | * @pipe: index of CRTC whose vblank timestamp to retrieve |
|
- | 709 | * @tvblank: Pointer to target struct timeval which should receive the timestamp |
|
- | 710 | * @flags: Flags to pass to driver: |
|
- | 711 | * 0 = Default, |
|
- | 712 | * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl IRQ handler |
|
- | 713 | * |
|
- | 714 | * Fetches the system timestamp corresponding to the time of the most recent |
|
- | 715 | * vblank interval on specified CRTC. May call into kms-driver to |
|
- | 716 | * compute the timestamp with a high-precision GPU specific method. |
|
- | 717 | * |
|
- | 718 | * Returns zero if timestamp originates from uncorrected do_gettimeofday() |
|
- | 719 | * call, i.e., it isn't very precisely locked to the true vblank. |
|
- | 720 | * |
|
- | 721 | * Returns: |
|
- | 722 | * True if timestamp is considered to be very precise, false otherwise. |
|
- | 723 | */ |
|
- | 724 | static bool |
|
- | 725 | drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, |
|
- | 726 | struct timeval *tvblank, unsigned flags) |
|
- | 727 | { |
|
- | 728 | int ret; |
|
- | 729 | ||
- | 730 | /* Define requested maximum error on timestamps (nanoseconds). */ |
|
- | 731 | int max_error = (int) drm_timestamp_precision * 1000; |
|
- | 732 | ||
- | 733 | /* Query driver if possible and precision timestamping enabled. */ |
|
- | 734 | if (dev->driver->get_vblank_timestamp && (max_error > 0)) { |
|
- | 735 | ret = dev->driver->get_vblank_timestamp(dev, pipe, &max_error, |
|
- | 736 | tvblank, flags); |
|
- | 737 | if (ret > 0) |
|
- | 738 | return true; |
|
- | 739 | } |
|
- | 740 | ||
- | 741 | /* GPU high precision timestamp query unsupported or failed. |
|
- | 742 | * Return current monotonic/gettimeofday timestamp as best estimate. |
|
- | 743 | */ |
|
- | 744 | *tvblank = get_drm_timestamp(); |
|
- | 745 | ||
- | 746 | return false; |
|
- | 747 | } |
|
- | 748 | ||
- | 749 | /** |
|
- | 750 | * drm_vblank_count - retrieve "cooked" vblank counter value |
|
- | 751 | * @dev: DRM device |
|
- | 752 | * @pipe: index of CRTC for which to retrieve the counter |
|
- | 753 | * |
|
- | 754 | * Fetches the "cooked" vblank count value that represents the number of |
|
- | 755 | * vblank events since the system was booted, including lost events due to |
|
- | 756 | * modesetting activity. |
|
- | 757 | * |
|
- | 758 | * This is the legacy version of drm_crtc_vblank_count(). |
|
- | 759 | * |
|
- | 760 | * Returns: |
|
- | 761 | * The software vblank counter. |
|
- | 762 | */ |
|
- | 763 | u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe) |
|
- | 764 | { |
|
- | 765 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
|
- | 766 | ||
- | 767 | if (WARN_ON(pipe >= dev->num_crtcs)) |
|
- | 768 | return 0; |
|
- | 769 | ||
- | 770 | return vblank->count; |
|
- | 771 | } |
|
- | 772 | EXPORT_SYMBOL(drm_vblank_count); |
|
- | 773 | ||
- | 774 | /** |
|
- | 775 | * drm_crtc_vblank_count - retrieve "cooked" vblank counter value |
|
- | 776 | * @crtc: which counter to retrieve |
|
- | 777 | * |
|
- | 778 | * Fetches the "cooked" vblank count value that represents the number of |
|
- | 779 | * vblank events since the system was booted, including lost events due to |
|
- | 780 | * modesetting activity. |
|
- | 781 | * |
|
- | 782 | * This is the native KMS version of drm_vblank_count(). |
|
- | 783 | * |
|
- | 784 | * Returns: |
|
- | 785 | * The software vblank counter. |
|
- | 786 | */ |
|
- | 787 | u32 drm_crtc_vblank_count(struct drm_crtc *crtc) |
|
- | 788 | { |
|
- | 789 | return drm_vblank_count(crtc->dev, drm_crtc_index(crtc)); |
|
- | 790 | } |
|
- | 791 | EXPORT_SYMBOL(drm_crtc_vblank_count); |
|
- | 792 | ||
- | 793 | /** |
|
- | 794 | * drm_vblank_count_and_time - retrieve "cooked" vblank counter value and the |
|
- | 795 | * system timestamp corresponding to that vblank counter value. |
|
- | 796 | * @dev: DRM device |
|
- | 797 | * @pipe: index of CRTC whose counter to retrieve |
|
- | 798 | * @vblanktime: Pointer to struct timeval to receive the vblank timestamp. |
|
- | 799 | * |
|
- | 800 | * Fetches the "cooked" vblank count value that represents the number of |
|
- | 801 | * vblank events since the system was booted, including lost events due to |
|
- | 802 | * modesetting activity. Returns corresponding system timestamp of the time |
|
- | 803 | * of the vblank interval that corresponds to the current vblank counter value. |
|
- | 804 | * |
|
- | 805 | * This is the legacy version of drm_crtc_vblank_count_and_time(). |
|
- | 806 | */ |
|
- | 807 | u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, |
|
- | 808 | struct timeval *vblanktime) |
|
- | 809 | { |
|
- | 810 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
|
- | 811 | int count = DRM_TIMESTAMP_MAXRETRIES; |
|
- | 812 | u32 cur_vblank; |
|
- | 813 | ||
- | 814 | if (WARN_ON(pipe >= dev->num_crtcs)) |
|
- | 815 | return 0; |
|
- | 816 | ||
- | 817 | /* |
|
- | 818 | * Vblank timestamps are read lockless. To ensure consistency the vblank |
|
- | 819 | * counter is rechecked and ordering is ensured using memory barriers. |
|
- | 820 | * This works like a seqlock. The write-side barriers are in store_vblank. |
|
- | 821 | */ |
|
- | 822 | do { |
|
- | 823 | cur_vblank = vblank->count; |
|
- | 824 | smp_rmb(); |
|
- | 825 | *vblanktime = vblanktimestamp(dev, pipe, cur_vblank); |
|
- | 826 | smp_rmb(); |
|
- | 827 | } while (cur_vblank != vblank->count && --count > 0); |
|
- | 828 | ||
- | 829 | return cur_vblank; |
|
- | 830 | } |
|
- | 831 | EXPORT_SYMBOL(drm_vblank_count_and_time); |
|
- | 832 | /** |
|
- | 833 | * drm_vblank_enable - enable the vblank interrupt on a CRTC |
|
- | 834 | * @dev: DRM device |
|
- | 835 | * @pipe: CRTC index |
|
- | 836 | * |
|
- | 837 | * Returns: |
|
- | 838 | * Zero on success or a negative error code on failure. |
|
- | 839 | */ |
|
- | 840 | static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe) |
|
- | 841 | { |
|
- | 842 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
|
- | 843 | int ret = 0; |
|
- | 844 | ||
- | 845 | assert_spin_locked(&dev->vbl_lock); |
|
- | 846 | ||
- | 847 | spin_lock(&dev->vblank_time_lock); |
|
- | 848 | ||
- | 849 | if (!vblank->enabled) { |
|
- | 850 | /* |
|
- | 851 | * Enable vblank irqs under vblank_time_lock protection. |
|
- | 852 | * All vblank count & timestamp updates are held off |
|
- | 853 | * until we are done reinitializing master counter and |
|
- | 854 | * timestamps. Filtercode in drm_handle_vblank() will |
|
- | 855 | * prevent double-accounting of same vblank interval. |
|
- | 856 | */ |
|
- | 857 | ret = dev->driver->enable_vblank(dev, pipe); |
|
- | 858 | DRM_DEBUG("enabling vblank on crtc %u, ret: %d\n", pipe, ret); |
|
- | 859 | if (ret) |
|
- | 860 | atomic_dec(&vblank->refcount); |
|
- | 861 | else { |
|
- | 862 | vblank->enabled = true; |
|
- | 863 | drm_update_vblank_count(dev, pipe, 0); |
|
- | 864 | } |
|
- | 865 | } |
|
- | 866 | ||
350 | 867 | spin_unlock(&dev->vblank_time_lock); |
|
351 | return -EIO; |
868 | |
352 | } |
869 | return ret; |
353 | EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos); |
870 | } |
354 | 871 | ||
355 | /** |
872 | /** |
356 | * drm_vblank_get - get a reference count on vblank events |
873 | * drm_vblank_get - get a reference count on vblank events |
357 | * @dev: DRM device |
874 | * @dev: DRM device |
358 | * @crtc: which CRTC to own |
875 | * @pipe: index of CRTC to own |
359 | * |
876 | * |
360 | * Acquire a reference count on vblank events to avoid having them disabled |
877 | * Acquire a reference count on vblank events to avoid having them disabled |
361 | * while in use. |
878 | * while in use. |
362 | * |
879 | * |
363 | * This is the legacy version of drm_crtc_vblank_get(). |
880 | * This is the legacy version of drm_crtc_vblank_get(). |
364 | * |
881 | * |
365 | * Returns: |
882 | * Returns: |
366 | * Zero on success, nonzero on failure. |
883 | * Zero on success or a negative error code on failure. |
367 | */ |
884 | */ |
368 | int drm_vblank_get(struct drm_device *dev, int crtc) |
- | |
Line -... | Line 885... | ||
- | 885 | int drm_vblank_get(struct drm_device *dev, unsigned int pipe) |
|
- | 886 | { |
|
- | 887 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
|
369 | { |
888 | unsigned long irqflags; |
370 | struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; |
889 | int ret = 0; |
Line 371... | Line 890... | ||
371 | unsigned long irqflags; |
890 | |
372 | int ret = 0; |
891 | if (!dev->num_crtcs) |
373 | #if 0 |
892 | return -EINVAL; |
374 | 893 | ||
375 | if (WARN_ON(crtc >= dev->num_crtcs)) |
894 | if (WARN_ON(pipe >= dev->num_crtcs)) |
376 | return -EINVAL; |
895 | return -EINVAL; |
377 | 896 | ||
378 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
897 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
379 | /* Going from 0->1 means we have to enable interrupts again */ |
898 | /* Going from 0->1 means we have to enable interrupts again */ |
380 | if (atomic_add_return(1, &vblank->refcount) == 1) { |
899 | if (atomic_add_return(1, &vblank->refcount) == 1) { |
381 | ret = drm_vblank_enable(dev, crtc); |
900 | ret = drm_vblank_enable(dev, pipe); |
382 | } else { |
901 | } else { |
383 | if (!vblank->enabled) { |
902 | if (!vblank->enabled) { |
384 | atomic_dec(&vblank->refcount); |
903 | atomic_dec(&vblank->refcount); |
385 | ret = -EINVAL; |
904 | ret = -EINVAL; |
Line 386... | Line 905... | ||
386 | } |
905 | } |
Line 396... | Line 915... | ||
396 | * @crtc: which CRTC to own |
915 | * @crtc: which CRTC to own |
397 | * |
916 | * |
398 | * Acquire a reference count on vblank events to avoid having them disabled |
917 | * Acquire a reference count on vblank events to avoid having them disabled |
399 | * while in use. |
918 | * while in use. |
400 | * |
919 | * |
401 | * This is the native kms version of drm_vblank_off(). |
920 | * This is the native kms version of drm_vblank_get(). |
402 | * |
921 | * |
403 | * Returns: |
922 | * Returns: |
404 | * Zero on success, nonzero on failure. |
923 | * Zero on success or a negative error code on failure. |
405 | */ |
924 | */ |
406 | int drm_crtc_vblank_get(struct drm_crtc *crtc) |
925 | int drm_crtc_vblank_get(struct drm_crtc *crtc) |
407 | { |
926 | { |
408 | return drm_vblank_get(crtc->dev, drm_crtc_index(crtc)); |
927 | return drm_vblank_get(crtc->dev, drm_crtc_index(crtc)); |
409 | } |
928 | } |
410 | EXPORT_SYMBOL(drm_crtc_vblank_get); |
929 | EXPORT_SYMBOL(drm_crtc_vblank_get); |
Line 411... | Line 930... | ||
411 | 930 | ||
412 | /** |
931 | /** |
413 | * drm_vblank_put - give up ownership of vblank events |
932 | * drm_vblank_put - release ownership of vblank events |
414 | * @dev: DRM device |
933 | * @dev: DRM device |
415 | * @crtc: which counter to give up |
934 | * @pipe: index of CRTC to release |
416 | * |
935 | * |
417 | * Release ownership of a given vblank counter, turning off interrupts |
936 | * Release ownership of a given vblank counter, turning off interrupts |
418 | * if possible. Disable interrupts after drm_vblank_offdelay milliseconds. |
937 | * if possible. Disable interrupts after drm_vblank_offdelay milliseconds. |
419 | * |
938 | * |
420 | * This is the legacy version of drm_crtc_vblank_put(). |
939 | * This is the legacy version of drm_crtc_vblank_put(). |
421 | */ |
940 | */ |
422 | void drm_vblank_put(struct drm_device *dev, int crtc) |
941 | void drm_vblank_put(struct drm_device *dev, unsigned int pipe) |
423 | { |
- | |
424 | #if 0 |
942 | { |
Line 425... | Line 943... | ||
425 | struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; |
943 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
426 | 944 | ||
Line 427... | Line 945... | ||
427 | if (WARN_ON(atomic_read(&vblank->refcount) == 0)) |
945 | if (WARN_ON(pipe >= dev->num_crtcs)) |
428 | return; |
946 | return; |
Line 429... | Line 947... | ||
429 | 947 | ||
430 | if (WARN_ON(crtc >= dev->num_crtcs)) |
948 | if (WARN_ON(atomic_read(&vblank->refcount) == 0)) |
431 | return; |
949 | return; |
Line 438... | Line 956... | ||
438 | vblank_disable_fn((unsigned long)vblank); |
956 | vblank_disable_fn((unsigned long)vblank); |
439 | else |
957 | else |
440 | mod_timer(&vblank->disable_timer, |
958 | mod_timer(&vblank->disable_timer, |
441 | jiffies + ((drm_vblank_offdelay * HZ)/1000)); |
959 | jiffies + ((drm_vblank_offdelay * HZ)/1000)); |
442 | } |
960 | } |
443 | #endif |
- | |
444 | } |
961 | } |
445 | EXPORT_SYMBOL(drm_vblank_put); |
962 | EXPORT_SYMBOL(drm_vblank_put); |
Line 446... | Line 963... | ||
446 | 963 | ||
447 | /** |
964 | /** |
Line 460... | Line 977... | ||
460 | EXPORT_SYMBOL(drm_crtc_vblank_put); |
977 | EXPORT_SYMBOL(drm_crtc_vblank_put); |
Line 461... | Line 978... | ||
461 | 978 | ||
462 | /** |
979 | /** |
463 | * drm_wait_one_vblank - wait for one vblank |
980 | * drm_wait_one_vblank - wait for one vblank |
464 | * @dev: DRM device |
981 | * @dev: DRM device |
465 | * @crtc: crtc index |
982 | * @pipe: CRTC index |
466 | * |
983 | * |
467 | * This waits for one vblank to pass on @crtc, using the irq driver interfaces. |
984 | * This waits for one vblank to pass on @pipe, using the irq driver interfaces. |
468 | * It is a failure to call this when the vblank irq for @crtc is disabled, e.g. |
985 | * It is a failure to call this when the vblank irq for @pipe is disabled, e.g. |
469 | * due to lack of driver support or because the crtc is off. |
986 | * due to lack of driver support or because the crtc is off. |
470 | */ |
987 | */ |
471 | void drm_wait_one_vblank(struct drm_device *dev, int crtc) |
988 | void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe) |
472 | { |
989 | { |
473 | #if 0 |
990 | #if 0 |
474 | int ret; |
991 | int ret; |
Line 506... | Line 1023... | ||
506 | EXPORT_SYMBOL(drm_crtc_wait_one_vblank); |
1023 | EXPORT_SYMBOL(drm_crtc_wait_one_vblank); |
Line 507... | Line 1024... | ||
507 | 1024 | ||
508 | /** |
1025 | /** |
509 | * drm_vblank_off - disable vblank events on a CRTC |
1026 | * drm_vblank_off - disable vblank events on a CRTC |
510 | * @dev: DRM device |
1027 | * @dev: DRM device |
511 | * @crtc: CRTC in question |
1028 | * @pipe: CRTC index |
512 | * |
1029 | * |
513 | * Drivers can use this function to shut down the vblank interrupt handling when |
1030 | * Drivers can use this function to shut down the vblank interrupt handling when |
514 | * disabling a crtc. This function ensures that the latest vblank frame count is |
1031 | * disabling a crtc. This function ensures that the latest vblank frame count is |
515 | * stored so that drm_vblank_on() can restore it again. |
1032 | * stored so that drm_vblank_on() can restore it again. |
516 | * |
1033 | * |
517 | * Drivers must use this function when the hardware vblank counter can get |
1034 | * Drivers must use this function when the hardware vblank counter can get |
518 | * reset, e.g. when suspending. |
1035 | * reset, e.g. when suspending. |
519 | * |
1036 | * |
520 | * This is the legacy version of drm_crtc_vblank_off(). |
1037 | * This is the legacy version of drm_crtc_vblank_off(). |
521 | */ |
1038 | */ |
522 | void drm_vblank_off(struct drm_device *dev, int crtc) |
1039 | void drm_vblank_off(struct drm_device *dev, unsigned int pipe) |
523 | { |
1040 | { |
524 | struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; |
1041 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
525 | struct drm_pending_vblank_event *e, *t; |
1042 | struct drm_pending_vblank_event *e, *t; |
526 | struct timeval now; |
1043 | struct timeval now; |
527 | unsigned long irqflags; |
1044 | unsigned long irqflags; |
Line 549... | Line 1066... | ||
549 | drm_vblank_off(crtc->dev, drm_crtc_index(crtc)); |
1066 | drm_vblank_off(crtc->dev, drm_crtc_index(crtc)); |
550 | } |
1067 | } |
551 | EXPORT_SYMBOL(drm_crtc_vblank_off); |
1068 | EXPORT_SYMBOL(drm_crtc_vblank_off); |
Line 552... | Line 1069... | ||
552 | 1069 | ||
- | 1070 | /** |
|
- | 1071 | * drm_crtc_vblank_reset - reset vblank state to off on a CRTC |
|
- | 1072 | * @crtc: CRTC in question |
|
- | 1073 | * |
|
- | 1074 | * Drivers can use this function to reset the vblank state to off at load time. |
|
- | 1075 | * Drivers should use this together with the drm_crtc_vblank_off() and |
|
- | 1076 | * drm_crtc_vblank_on() functions. The difference compared to |
|
- | 1077 | * drm_crtc_vblank_off() is that this function doesn't save the vblank counter |
|
- | 1078 | * and hence doesn't need to call any driver hooks. |
|
- | 1079 | */ |
|
- | 1080 | void drm_crtc_vblank_reset(struct drm_crtc *crtc) |
|
- | 1081 | { |
|
- | 1082 | struct drm_device *dev = crtc->dev; |
|
- | 1083 | unsigned long irqflags; |
|
- | 1084 | unsigned int pipe = drm_crtc_index(crtc); |
|
- | 1085 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
|
- | 1086 | ||
- | 1087 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
|
- | 1088 | /* |
|
- | 1089 | * Prevent subsequent drm_vblank_get() from enabling the vblank |
|
- | 1090 | * interrupt by bumping the refcount. |
|
- | 1091 | */ |
|
- | 1092 | if (!vblank->inmodeset) { |
|
- | 1093 | atomic_inc(&vblank->refcount); |
|
- | 1094 | vblank->inmodeset = 1; |
|
- | 1095 | } |
|
- | 1096 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
|
- | 1097 | ||
- | 1098 | WARN_ON(!list_empty(&dev->vblank_event_list)); |
|
- | 1099 | } |
|
- | 1100 | EXPORT_SYMBOL(drm_crtc_vblank_reset); |
|
- | 1101 | ||
553 | /** |
1102 | /** |
554 | * drm_vblank_on - enable vblank events on a CRTC |
1103 | * drm_vblank_on - enable vblank events on a CRTC |
555 | * @dev: DRM device |
1104 | * @dev: DRM device |
556 | * @crtc: CRTC in question |
1105 | * @pipe: CRTC index |
557 | * |
1106 | * |
558 | * This functions restores the vblank interrupt state captured with |
1107 | * This functions restores the vblank interrupt state captured with |
559 | * drm_vblank_off() again. Note that calls to drm_vblank_on() and |
1108 | * drm_vblank_off() again. Note that calls to drm_vblank_on() and |
560 | * drm_vblank_off() can be unbalanced and so can also be unconditionally called |
1109 | * drm_vblank_off() can be unbalanced and so can also be unconditionally called |
561 | * in driver load code to reflect the current hardware state of the crtc. |
1110 | * in driver load code to reflect the current hardware state of the crtc. |
562 | * |
1111 | * |
563 | * This is the legacy version of drm_crtc_vblank_on(). |
1112 | * This is the legacy version of drm_crtc_vblank_on(). |
564 | */ |
1113 | */ |
565 | void drm_vblank_on(struct drm_device *dev, int crtc) |
1114 | void drm_vblank_on(struct drm_device *dev, unsigned int pipe) |
566 | { |
1115 | { |
567 | struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; |
1116 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
Line -... | Line 1117... | ||
- | 1117 | unsigned long irqflags; |
|
- | 1118 | ||
- | 1119 | dbgprintf("%s pipe %d dev->num_crtcs %d\n", pipe,dev->num_crtcs);\ |
|
- | 1120 | ||
- | 1121 | if (WARN_ON(pipe >= dev->num_crtcs)) |
|
- | 1122 | return; |
|
- | 1123 | ||
- | 1124 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
|
- | 1125 | /* Drop our private "prevent drm_vblank_get" refcount */ |
|
- | 1126 | if (vblank->inmodeset) { |
|
- | 1127 | atomic_dec(&vblank->refcount); |
|
- | 1128 | vblank->inmodeset = 0; |
|
- | 1129 | } |
|
- | 1130 | ||
- | 1131 | drm_reset_vblank_timestamp(dev, pipe); |
|
- | 1132 | ||
- | 1133 | /* |
|
- | 1134 | * re-enable interrupts if there are users left, or the |
|
- | 1135 | * user wishes vblank interrupts to be enabled all the time. |
|
- | 1136 | */ |
|
- | 1137 | if (atomic_read(&vblank->refcount) != 0 || |
|
- | 1138 | (!dev->vblank_disable_immediate && drm_vblank_offdelay == 0)) |
|
568 | unsigned long irqflags; |
1139 | WARN_ON(drm_vblank_enable(dev, pipe)); |
569 | 1140 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
|
Line 570... | Line 1141... | ||
570 | } |
1141 | } |
571 | EXPORT_SYMBOL(drm_vblank_on); |
1142 | EXPORT_SYMBOL(drm_vblank_on); |
Line 588... | Line 1159... | ||
588 | EXPORT_SYMBOL(drm_crtc_vblank_on); |
1159 | EXPORT_SYMBOL(drm_crtc_vblank_on); |
Line 589... | Line 1160... | ||
589 | 1160 | ||
590 | /** |
1161 | /** |
591 | * drm_vblank_pre_modeset - account for vblanks across mode sets |
1162 | * drm_vblank_pre_modeset - account for vblanks across mode sets |
592 | * @dev: DRM device |
1163 | * @dev: DRM device |
593 | * @crtc: CRTC in question |
1164 | * @pipe: CRTC index |
594 | * |
1165 | * |
595 | * Account for vblank events across mode setting events, which will likely |
1166 | * Account for vblank events across mode setting events, which will likely |
596 | * reset the hardware frame counter. |
1167 | * reset the hardware frame counter. |
597 | * |
1168 | * |
Line 608... | Line 1179... | ||
608 | * counters. |
1179 | * counters. |
609 | * |
1180 | * |
610 | * Drivers must call drm_vblank_post_modeset() when re-enabling the same crtc |
1181 | * Drivers must call drm_vblank_post_modeset() when re-enabling the same crtc |
611 | * again. |
1182 | * again. |
612 | */ |
1183 | */ |
613 | void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) |
1184 | void drm_vblank_pre_modeset(struct drm_device *dev, unsigned int pipe) |
614 | { |
1185 | { |
615 | #if 0 |
- | |
616 | /* vblank is not initialized (IRQ not installed ?) */ |
1186 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
617 | if (!dev->num_crtcs) |
- | |
618 | return; |
- | |
619 | 1187 | ||
- | 1188 | /* vblank is not initialized (IRQ not installed ?), or has been freed */ |
|
620 | if (WARN_ON(crtc >= dev->num_crtcs)) |
1189 | if (!dev->num_crtcs) |
621 | return; |
1190 | return; |
Line -... | Line 1191... | ||
- | 1191 | ||
- | 1192 | if (WARN_ON(pipe >= dev->num_crtcs)) |
|
- | 1193 | return; |
|
622 | 1194 | ||
623 | /* |
1195 | /* |
624 | * To avoid all the problems that might happen if interrupts |
1196 | * To avoid all the problems that might happen if interrupts |
625 | * were enabled/disabled around or between these calls, we just |
1197 | * were enabled/disabled around or between these calls, we just |
626 | * have the kernel take a reference on the CRTC (just once though |
1198 | * have the kernel take a reference on the CRTC (just once though |
627 | * to avoid corrupting the count if multiple, mismatch calls occur), |
1199 | * to avoid corrupting the count if multiple, mismatch calls occur), |
628 | * so that interrupts remain enabled in the interim. |
1200 | * so that interrupts remain enabled in the interim. |
629 | */ |
1201 | */ |
630 | if (!vblank->inmodeset) { |
1202 | if (!vblank->inmodeset) { |
631 | vblank->inmodeset = 0x1; |
1203 | vblank->inmodeset = 0x1; |
632 | if (drm_vblank_get(dev, crtc) == 0) |
1204 | if (drm_vblank_get(dev, pipe) == 0) |
633 | vblank->inmodeset |= 0x2; |
1205 | vblank->inmodeset |= 0x2; |
634 | } |
- | |
635 | #endif |
1206 | } |
636 | } |
1207 | } |
Line 637... | Line 1208... | ||
637 | EXPORT_SYMBOL(drm_vblank_pre_modeset); |
1208 | EXPORT_SYMBOL(drm_vblank_pre_modeset); |
638 | 1209 | ||
639 | /** |
1210 | /** |
640 | * drm_vblank_post_modeset - undo drm_vblank_pre_modeset changes |
1211 | * drm_vblank_post_modeset - undo drm_vblank_pre_modeset changes |
641 | * @dev: DRM device |
1212 | * @dev: DRM device |
642 | * @crtc: CRTC in question |
1213 | * @pipe: CRTC index |
643 | * |
1214 | * |
644 | * This function again drops the temporary vblank reference acquired in |
1215 | * This function again drops the temporary vblank reference acquired in |
645 | * drm_vblank_pre_modeset. |
1216 | * drm_vblank_pre_modeset. |
646 | */ |
1217 | */ |
647 | void drm_vblank_post_modeset(struct drm_device *dev, int crtc) |
- | |
- | 1218 | void drm_vblank_post_modeset(struct drm_device *dev, unsigned int pipe) |
|
648 | { |
1219 | { |
Line 649... | Line 1220... | ||
649 | #if 0 |
1220 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
650 | unsigned long irqflags; |
1221 | unsigned long irqflags; |
651 | 1222 | ||
Line -... | Line 1223... | ||
- | 1223 | /* vblank is not initialized (IRQ not installed ?), or has been freed */ |
|
- | 1224 | if (!dev->num_crtcs) |
|
- | 1225 | return; |
|
652 | /* vblank is not initialized (IRQ not installed ?), or has been freed */ |
1226 | |
653 | if (!dev->num_crtcs) |
1227 | if (WARN_ON(pipe >= dev->num_crtcs)) |
654 | return; |
1228 | return; |
655 | 1229 | ||
Line 656... | Line 1230... | ||
656 | if (vblank->inmodeset) { |
1230 | if (vblank->inmodeset) { |
657 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
1231 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
Line 658... | Line 1232... | ||
658 | dev->vblank_disable_allowed = true; |
1232 | dev->vblank_disable_allowed = true; |
659 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
1233 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
660 | - | ||
661 | if (vblank->inmodeset & 0x2) |
1234 | |
662 | drm_vblank_put(dev, crtc); |
1235 | if (vblank->inmodeset & 0x2) |
Line -... | Line 1236... | ||
- | 1236 | drm_vblank_put(dev, pipe); |
|
- | 1237 | ||
- | 1238 | vblank->inmodeset = 0; |
|
- | 1239 | } |
|
- | 1240 | } |
|
- | 1241 | EXPORT_SYMBOL(drm_vblank_post_modeset); |
|
- | 1242 | ||
- | 1243 | ||
- | 1244 | u64 div64_u64(u64 dividend, u64 divisor) |
|
- | 1245 | { |
|
- | 1246 | u32 high, d; |
|
- | 1247 | ||
- | 1248 | high = divisor >> 32; |
|
- | 1249 | if (high) { |
|
- | 1250 | unsigned int shift = fls(high); |