diff options
Diffstat (limited to 'drivers/gpu/drm/drm_irq.c')
| -rw-r--r-- | drivers/gpu/drm/drm_irq.c | 177 |
1 files changed, 66 insertions, 111 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index f92da0a32f0d..d80d95289e10 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
| @@ -43,9 +43,8 @@ | |||
| 43 | #include <linux/export.h> | 43 | #include <linux/export.h> |
| 44 | 44 | ||
| 45 | /* Access macro for slots in vblank timestamp ringbuffer. */ | 45 | /* Access macro for slots in vblank timestamp ringbuffer. */ |
| 46 | #define vblanktimestamp(dev, crtc, count) ( \ | 46 | #define vblanktimestamp(dev, crtc, count) \ |
| 47 | (dev)->_vblank_time[(crtc) * DRM_VBLANKTIME_RBSIZE + \ | 47 | ((dev)->vblank[crtc].time[(count) % DRM_VBLANKTIME_RBSIZE]) |
| 48 | ((count) % DRM_VBLANKTIME_RBSIZE)]) | ||
| 49 | 48 | ||
| 50 | /* Retry timestamp calculation up to 3 times to satisfy | 49 | /* Retry timestamp calculation up to 3 times to satisfy |
| 51 | * drm_timestamp_precision before giving up. | 50 | * drm_timestamp_precision before giving up. |
| @@ -89,8 +88,7 @@ int drm_irq_by_busid(struct drm_device *dev, void *data, | |||
| 89 | */ | 88 | */ |
| 90 | static void clear_vblank_timestamps(struct drm_device *dev, int crtc) | 89 | static void clear_vblank_timestamps(struct drm_device *dev, int crtc) |
| 91 | { | 90 | { |
| 92 | memset(&dev->_vblank_time[crtc * DRM_VBLANKTIME_RBSIZE], 0, | 91 | memset(dev->vblank[crtc].time, 0, sizeof(dev->vblank[crtc].time)); |
| 93 | DRM_VBLANKTIME_RBSIZE * sizeof(struct timeval)); | ||
| 94 | } | 92 | } |
| 95 | 93 | ||
| 96 | /* | 94 | /* |
| @@ -115,7 +113,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) | |||
| 115 | spin_lock_irqsave(&dev->vblank_time_lock, irqflags); | 113 | spin_lock_irqsave(&dev->vblank_time_lock, irqflags); |
| 116 | 114 | ||
| 117 | dev->driver->disable_vblank(dev, crtc); | 115 | dev->driver->disable_vblank(dev, crtc); |
| 118 | dev->vblank_enabled[crtc] = 0; | 116 | dev->vblank[crtc].enabled = false; |
| 119 | 117 | ||
| 120 | /* No further vblank irq's will be processed after | 118 | /* No further vblank irq's will be processed after |
| 121 | * this point. Get current hardware vblank count and | 119 | * this point. Get current hardware vblank count and |
| @@ -130,9 +128,9 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) | |||
| 130 | * delayed gpu counter increment. | 128 | * delayed gpu counter increment. |
| 131 | */ | 129 | */ |
| 132 | do { | 130 | do { |
| 133 | dev->last_vblank[crtc] = dev->driver->get_vblank_counter(dev, crtc); | 131 | dev->vblank[crtc].last = dev->driver->get_vblank_counter(dev, crtc); |
| 134 | vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0); | 132 | vblrc = drm_get_last_vbltimestamp(dev, crtc, &tvblank, 0); |
| 135 | } while (dev->last_vblank[crtc] != dev->driver->get_vblank_counter(dev, crtc) && (--count) && vblrc); | 133 | } while (dev->vblank[crtc].last != dev->driver->get_vblank_counter(dev, crtc) && (--count) && vblrc); |
| 136 | 134 | ||
| 137 | if (!count) | 135 | if (!count) |
| 138 | vblrc = 0; | 136 | vblrc = 0; |
| @@ -140,7 +138,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) | |||
| 140 | /* Compute time difference to stored timestamp of last vblank | 138 | /* Compute time difference to stored timestamp of last vblank |
| 141 | * as updated by last invocation of drm_handle_vblank() in vblank irq. | 139 | * as updated by last invocation of drm_handle_vblank() in vblank irq. |
| 142 | */ | 140 | */ |
| 143 | vblcount = atomic_read(&dev->_vblank_count[crtc]); | 141 | vblcount = atomic_read(&dev->vblank[crtc].count); |
| 144 | diff_ns = timeval_to_ns(&tvblank) - | 142 | diff_ns = timeval_to_ns(&tvblank) - |
| 145 | timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount)); | 143 | timeval_to_ns(&vblanktimestamp(dev, crtc, vblcount)); |
| 146 | 144 | ||
| @@ -157,7 +155,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc) | |||
| 157 | * hope for the best. | 155 | * hope for the best. |
| 158 | */ | 156 | */ |
| 159 | if ((vblrc > 0) && (abs64(diff_ns) > 1000000)) { | 157 | if ((vblrc > 0) && (abs64(diff_ns) > 1000000)) { |
| 160 | atomic_inc(&dev->_vblank_count[crtc]); | 158 | atomic_inc(&dev->vblank[crtc].count); |
| 161 | smp_mb__after_atomic_inc(); | 159 | smp_mb__after_atomic_inc(); |
| 162 | } | 160 | } |
| 163 | 161 | ||
| @@ -178,8 +176,8 @@ static void vblank_disable_fn(unsigned long arg) | |||
| 178 | 176 | ||
| 179 | for (i = 0; i < dev->num_crtcs; i++) { | 177 | for (i = 0; i < dev->num_crtcs; i++) { |
| 180 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | 178 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
| 181 | if (atomic_read(&dev->vblank_refcount[i]) == 0 && | 179 | if (atomic_read(&dev->vblank[i].refcount) == 0 && |
| 182 | dev->vblank_enabled[i]) { | 180 | dev->vblank[i].enabled) { |
| 183 | DRM_DEBUG("disabling vblank on crtc %d\n", i); | 181 | DRM_DEBUG("disabling vblank on crtc %d\n", i); |
| 184 | vblank_disable_and_save(dev, i); | 182 | vblank_disable_and_save(dev, i); |
| 185 | } | 183 | } |
| @@ -197,14 +195,7 @@ void drm_vblank_cleanup(struct drm_device *dev) | |||
| 197 | 195 | ||
| 198 | vblank_disable_fn((unsigned long)dev); | 196 | vblank_disable_fn((unsigned long)dev); |
| 199 | 197 | ||
| 200 | kfree(dev->vbl_queue); | 198 | kfree(dev->vblank); |
| 201 | kfree(dev->_vblank_count); | ||
| 202 | kfree(dev->vblank_refcount); | ||
| 203 | kfree(dev->vblank_enabled); | ||
| 204 | kfree(dev->last_vblank); | ||
| 205 | kfree(dev->last_vblank_wait); | ||
| 206 | kfree(dev->vblank_inmodeset); | ||
| 207 | kfree(dev->_vblank_time); | ||
| 208 | 199 | ||
| 209 | dev->num_crtcs = 0; | 200 | dev->num_crtcs = 0; |
| 210 | } | 201 | } |
| @@ -221,42 +212,14 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs) | |||
| 221 | 212 | ||
| 222 | dev->num_crtcs = num_crtcs; | 213 | dev->num_crtcs = num_crtcs; |
| 223 | 214 | ||
| 224 | dev->vbl_queue = kmalloc(sizeof(wait_queue_head_t) * num_crtcs, | 215 | dev->vblank = kcalloc(num_crtcs, sizeof(*dev->vblank), GFP_KERNEL); |
| 225 | GFP_KERNEL); | 216 | if (!dev->vblank) |
| 226 | if (!dev->vbl_queue) | ||
| 227 | goto err; | 217 | goto err; |
| 228 | 218 | ||
| 229 | dev->_vblank_count = kmalloc(sizeof(atomic_t) * num_crtcs, GFP_KERNEL); | 219 | for (i = 0; i < num_crtcs; i++) |
| 230 | if (!dev->_vblank_count) | 220 | init_waitqueue_head(&dev->vblank[i].queue); |
| 231 | goto err; | ||
| 232 | |||
| 233 | dev->vblank_refcount = kmalloc(sizeof(atomic_t) * num_crtcs, | ||
| 234 | GFP_KERNEL); | ||
| 235 | if (!dev->vblank_refcount) | ||
| 236 | goto err; | ||
| 237 | |||
| 238 | dev->vblank_enabled = kcalloc(num_crtcs, sizeof(int), GFP_KERNEL); | ||
| 239 | if (!dev->vblank_enabled) | ||
| 240 | goto err; | ||
| 241 | 221 | ||
| 242 | dev->last_vblank = kcalloc(num_crtcs, sizeof(u32), GFP_KERNEL); | 222 | DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n"); |
| 243 | if (!dev->last_vblank) | ||
| 244 | goto err; | ||
| 245 | |||
| 246 | dev->last_vblank_wait = kcalloc(num_crtcs, sizeof(u32), GFP_KERNEL); | ||
| 247 | if (!dev->last_vblank_wait) | ||
| 248 | goto err; | ||
| 249 | |||
| 250 | dev->vblank_inmodeset = kcalloc(num_crtcs, sizeof(int), GFP_KERNEL); | ||
| 251 | if (!dev->vblank_inmodeset) | ||
| 252 | goto err; | ||
| 253 | |||
| 254 | dev->_vblank_time = kcalloc(num_crtcs * DRM_VBLANKTIME_RBSIZE, | ||
| 255 | sizeof(struct timeval), GFP_KERNEL); | ||
| 256 | if (!dev->_vblank_time) | ||
| 257 | goto err; | ||
| 258 | |||
| 259 | DRM_INFO("Supports vblank timestamp caching Rev 1 (10.10.2010).\n"); | ||
| 260 | 223 | ||
| 261 | /* Driver specific high-precision vblank timestamping supported? */ | 224 | /* Driver specific high-precision vblank timestamping supported? */ |
| 262 | if (dev->driver->get_vblank_timestamp) | 225 | if (dev->driver->get_vblank_timestamp) |
| @@ -264,14 +227,8 @@ int drm_vblank_init(struct drm_device *dev, int num_crtcs) | |||
| 264 | else | 227 | else |
| 265 | DRM_INFO("No driver support for vblank timestamp query.\n"); | 228 | DRM_INFO("No driver support for vblank timestamp query.\n"); |
| 266 | 229 | ||
| 267 | /* Zero per-crtc vblank stuff */ | 230 | dev->vblank_disable_allowed = false; |
| 268 | for (i = 0; i < num_crtcs; i++) { | ||
| 269 | init_waitqueue_head(&dev->vbl_queue[i]); | ||
| 270 | atomic_set(&dev->_vblank_count[i], 0); | ||
| 271 | atomic_set(&dev->vblank_refcount[i], 0); | ||
| 272 | } | ||
| 273 | 231 | ||
| 274 | dev->vblank_disable_allowed = 0; | ||
| 275 | return 0; | 232 | return 0; |
| 276 | 233 | ||
| 277 | err: | 234 | err: |
| @@ -336,7 +293,7 @@ int drm_irq_install(struct drm_device *dev) | |||
| 336 | mutex_unlock(&dev->struct_mutex); | 293 | mutex_unlock(&dev->struct_mutex); |
| 337 | return -EBUSY; | 294 | return -EBUSY; |
| 338 | } | 295 | } |
| 339 | dev->irq_enabled = 1; | 296 | dev->irq_enabled = true; |
| 340 | mutex_unlock(&dev->struct_mutex); | 297 | mutex_unlock(&dev->struct_mutex); |
| 341 | 298 | ||
| 342 | DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev)); | 299 | DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev)); |
| @@ -359,7 +316,7 @@ int drm_irq_install(struct drm_device *dev) | |||
| 359 | 316 | ||
| 360 | if (ret < 0) { | 317 | if (ret < 0) { |
| 361 | mutex_lock(&dev->struct_mutex); | 318 | mutex_lock(&dev->struct_mutex); |
| 362 | dev->irq_enabled = 0; | 319 | dev->irq_enabled = false; |
| 363 | mutex_unlock(&dev->struct_mutex); | 320 | mutex_unlock(&dev->struct_mutex); |
| 364 | return ret; | 321 | return ret; |
| 365 | } | 322 | } |
| @@ -373,7 +330,7 @@ int drm_irq_install(struct drm_device *dev) | |||
| 373 | 330 | ||
| 374 | if (ret < 0) { | 331 | if (ret < 0) { |
| 375 | mutex_lock(&dev->struct_mutex); | 332 | mutex_lock(&dev->struct_mutex); |
| 376 | dev->irq_enabled = 0; | 333 | dev->irq_enabled = false; |
| 377 | mutex_unlock(&dev->struct_mutex); | 334 | mutex_unlock(&dev->struct_mutex); |
| 378 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 335 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
| 379 | vga_client_register(dev->pdev, NULL, NULL, NULL); | 336 | vga_client_register(dev->pdev, NULL, NULL, NULL); |
| @@ -394,14 +351,15 @@ EXPORT_SYMBOL(drm_irq_install); | |||
| 394 | int drm_irq_uninstall(struct drm_device *dev) | 351 | int drm_irq_uninstall(struct drm_device *dev) |
| 395 | { | 352 | { |
| 396 | unsigned long irqflags; | 353 | unsigned long irqflags; |
| 397 | int irq_enabled, i; | 354 | bool irq_enabled; |
| 355 | int i; | ||
| 398 | 356 | ||
| 399 | if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) | 357 | if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) |
| 400 | return -EINVAL; | 358 | return -EINVAL; |
| 401 | 359 | ||
| 402 | mutex_lock(&dev->struct_mutex); | 360 | mutex_lock(&dev->struct_mutex); |
| 403 | irq_enabled = dev->irq_enabled; | 361 | irq_enabled = dev->irq_enabled; |
| 404 | dev->irq_enabled = 0; | 362 | dev->irq_enabled = false; |
| 405 | mutex_unlock(&dev->struct_mutex); | 363 | mutex_unlock(&dev->struct_mutex); |
| 406 | 364 | ||
| 407 | /* | 365 | /* |
| @@ -410,9 +368,9 @@ int drm_irq_uninstall(struct drm_device *dev) | |||
| 410 | if (dev->num_crtcs) { | 368 | if (dev->num_crtcs) { |
| 411 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | 369 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
| 412 | for (i = 0; i < dev->num_crtcs; i++) { | 370 | for (i = 0; i < dev->num_crtcs; i++) { |
| 413 | DRM_WAKEUP(&dev->vbl_queue[i]); | 371 | DRM_WAKEUP(&dev->vblank[i].queue); |
| 414 | dev->vblank_enabled[i] = 0; | 372 | dev->vblank[i].enabled = false; |
| 415 | dev->last_vblank[i] = | 373 | dev->vblank[i].last = |
| 416 | dev->driver->get_vblank_counter(dev, i); | 374 | dev->driver->get_vblank_counter(dev, i); |
| 417 | } | 375 | } |
| 418 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); | 376 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
| @@ -628,24 +586,20 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, | |||
| 628 | * code gets preempted or delayed for some reason. | 586 | * code gets preempted or delayed for some reason. |
| 629 | */ | 587 | */ |
| 630 | for (i = 0; i < DRM_TIMESTAMP_MAXRETRIES; i++) { | 588 | for (i = 0; i < DRM_TIMESTAMP_MAXRETRIES; i++) { |
| 631 | /* Disable preemption to make it very likely to | 589 | /* |
| 632 | * succeed in the first iteration even on PREEMPT_RT kernel. | 590 | * Get vertical and horizontal scanout position vpos, hpos, |
| 591 | * and bounding timestamps stime, etime, pre/post query. | ||
| 633 | */ | 592 | */ |
| 634 | preempt_disable(); | 593 | vbl_status = dev->driver->get_scanout_position(dev, crtc, &vpos, |
| 594 | &hpos, &stime, &etime); | ||
| 635 | 595 | ||
| 636 | /* Get system timestamp before query. */ | 596 | /* |
| 637 | stime = ktime_get(); | 597 | * Get correction for CLOCK_MONOTONIC -> CLOCK_REALTIME if |
| 638 | 598 | * CLOCK_REALTIME is requested. | |
| 639 | /* Get vertical and horizontal scanout pos. vpos, hpos. */ | 599 | */ |
| 640 | vbl_status = dev->driver->get_scanout_position(dev, crtc, &vpos, &hpos); | ||
| 641 | |||
| 642 | /* Get system timestamp after query. */ | ||
| 643 | etime = ktime_get(); | ||
| 644 | if (!drm_timestamp_monotonic) | 600 | if (!drm_timestamp_monotonic) |
| 645 | mono_time_offset = ktime_get_monotonic_offset(); | 601 | mono_time_offset = ktime_get_monotonic_offset(); |
| 646 | 602 | ||
| 647 | preempt_enable(); | ||
| 648 | |||
| 649 | /* Return as no-op if scanout query unsupported or failed. */ | 603 | /* Return as no-op if scanout query unsupported or failed. */ |
| 650 | if (!(vbl_status & DRM_SCANOUTPOS_VALID)) { | 604 | if (!(vbl_status & DRM_SCANOUTPOS_VALID)) { |
| 651 | DRM_DEBUG("crtc %d : scanoutpos query failed [%d].\n", | 605 | DRM_DEBUG("crtc %d : scanoutpos query failed [%d].\n", |
| @@ -653,6 +607,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, | |||
| 653 | return -EIO; | 607 | return -EIO; |
| 654 | } | 608 | } |
| 655 | 609 | ||
| 610 | /* Compute uncertainty in timestamp of scanout position query. */ | ||
| 656 | duration_ns = ktime_to_ns(etime) - ktime_to_ns(stime); | 611 | duration_ns = ktime_to_ns(etime) - ktime_to_ns(stime); |
| 657 | 612 | ||
| 658 | /* Accept result with < max_error nsecs timing uncertainty. */ | 613 | /* Accept result with < max_error nsecs timing uncertainty. */ |
| @@ -795,7 +750,7 @@ EXPORT_SYMBOL(drm_get_last_vbltimestamp); | |||
| 795 | */ | 750 | */ |
| 796 | u32 drm_vblank_count(struct drm_device *dev, int crtc) | 751 | u32 drm_vblank_count(struct drm_device *dev, int crtc) |
| 797 | { | 752 | { |
| 798 | return atomic_read(&dev->_vblank_count[crtc]); | 753 | return atomic_read(&dev->vblank[crtc].count); |
| 799 | } | 754 | } |
| 800 | EXPORT_SYMBOL(drm_vblank_count); | 755 | EXPORT_SYMBOL(drm_vblank_count); |
| 801 | 756 | ||
| @@ -824,10 +779,10 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc, | |||
| 824 | * a seqlock. | 779 | * a seqlock. |
| 825 | */ | 780 | */ |
| 826 | do { | 781 | do { |
| 827 | cur_vblank = atomic_read(&dev->_vblank_count[crtc]); | 782 | cur_vblank = atomic_read(&dev->vblank[crtc].count); |
| 828 | *vblanktime = vblanktimestamp(dev, crtc, cur_vblank); | 783 | *vblanktime = vblanktimestamp(dev, crtc, cur_vblank); |
| 829 | smp_rmb(); | 784 | smp_rmb(); |
| 830 | } while (cur_vblank != atomic_read(&dev->_vblank_count[crtc])); | 785 | } while (cur_vblank != atomic_read(&dev->vblank[crtc].count)); |
| 831 | 786 | ||
| 832 | return cur_vblank; | 787 | return cur_vblank; |
| 833 | } | 788 | } |
| @@ -914,12 +869,12 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc) | |||
| 914 | } while (cur_vblank != dev->driver->get_vblank_counter(dev, crtc)); | 869 | } while (cur_vblank != dev->driver->get_vblank_counter(dev, crtc)); |
| 915 | 870 | ||
| 916 | /* Deal with counter wrap */ | 871 | /* Deal with counter wrap */ |
| 917 | diff = cur_vblank - dev->last_vblank[crtc]; | 872 | diff = cur_vblank - dev->vblank[crtc].last; |
| 918 | if (cur_vblank < dev->last_vblank[crtc]) { | 873 | if (cur_vblank < dev->vblank[crtc].last) { |
| 919 | diff += dev->max_vblank_count; | 874 | diff += dev->max_vblank_count; |
| 920 | 875 | ||
| 921 | DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n", | 876 | DRM_DEBUG("last_vblank[%d]=0x%x, cur_vblank=0x%x => diff=0x%x\n", |
| 922 | crtc, dev->last_vblank[crtc], cur_vblank, diff); | 877 | crtc, dev->vblank[crtc].last, cur_vblank, diff); |
| 923 | } | 878 | } |
| 924 | 879 | ||
| 925 | DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n", | 880 | DRM_DEBUG("enabling vblank interrupts on crtc %d, missed %d\n", |
| @@ -930,12 +885,12 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc) | |||
| 930 | * reinitialize delayed at next vblank interrupt in that case. | 885 | * reinitialize delayed at next vblank interrupt in that case. |
| 931 | */ | 886 | */ |
| 932 | if (rc) { | 887 | if (rc) { |
| 933 | tslot = atomic_read(&dev->_vblank_count[crtc]) + diff; | 888 | tslot = atomic_read(&dev->vblank[crtc].count) + diff; |
| 934 | vblanktimestamp(dev, crtc, tslot) = t_vblank; | 889 | vblanktimestamp(dev, crtc, tslot) = t_vblank; |
| 935 | } | 890 | } |
| 936 | 891 | ||
| 937 | smp_mb__before_atomic_inc(); | 892 | smp_mb__before_atomic_inc(); |
| 938 | atomic_add(diff, &dev->_vblank_count[crtc]); | 893 | atomic_add(diff, &dev->vblank[crtc].count); |
| 939 | smp_mb__after_atomic_inc(); | 894 | smp_mb__after_atomic_inc(); |
| 940 | } | 895 | } |
| 941 | 896 | ||
| @@ -957,9 +912,9 @@ int drm_vblank_get(struct drm_device *dev, int crtc) | |||
| 957 | 912 | ||
| 958 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | 913 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
| 959 | /* Going from 0->1 means we have to enable interrupts again */ | 914 | /* Going from 0->1 means we have to enable interrupts again */ |
| 960 | if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) { | 915 | if (atomic_add_return(1, &dev->vblank[crtc].refcount) == 1) { |
| 961 | spin_lock_irqsave(&dev->vblank_time_lock, irqflags2); | 916 | spin_lock_irqsave(&dev->vblank_time_lock, irqflags2); |
| 962 | if (!dev->vblank_enabled[crtc]) { | 917 | if (!dev->vblank[crtc].enabled) { |
| 963 | /* Enable vblank irqs under vblank_time_lock protection. | 918 | /* Enable vblank irqs under vblank_time_lock protection. |
| 964 | * All vblank count & timestamp updates are held off | 919 | * All vblank count & timestamp updates are held off |
| 965 | * until we are done reinitializing master counter and | 920 | * until we are done reinitializing master counter and |
| @@ -970,16 +925,16 @@ int drm_vblank_get(struct drm_device *dev, int crtc) | |||
| 970 | DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", | 925 | DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", |
| 971 | crtc, ret); | 926 | crtc, ret); |
| 972 | if (ret) | 927 | if (ret) |
| 973 | atomic_dec(&dev->vblank_refcount[crtc]); | 928 | atomic_dec(&dev->vblank[crtc].refcount); |
| 974 | else { | 929 | else { |
| 975 | dev->vblank_enabled[crtc] = 1; | 930 | dev->vblank[crtc].enabled = true; |
| 976 | drm_update_vblank_count(dev, crtc); | 931 | drm_update_vblank_count(dev, crtc); |
| 977 | } | 932 | } |
| 978 | } | 933 | } |
| 979 | spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags2); | 934 | spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags2); |
| 980 | } else { | 935 | } else { |
| 981 | if (!dev->vblank_enabled[crtc]) { | 936 | if (!dev->vblank[crtc].enabled) { |
| 982 | atomic_dec(&dev->vblank_refcount[crtc]); | 937 | atomic_dec(&dev->vblank[crtc].refcount); |
| 983 | ret = -EINVAL; | 938 | ret = -EINVAL; |
| 984 | } | 939 | } |
| 985 | } | 940 | } |
| @@ -999,10 +954,10 @@ EXPORT_SYMBOL(drm_vblank_get); | |||
| 999 | */ | 954 | */ |
| 1000 | void drm_vblank_put(struct drm_device *dev, int crtc) | 955 | void drm_vblank_put(struct drm_device *dev, int crtc) |
| 1001 | { | 956 | { |
| 1002 | BUG_ON(atomic_read(&dev->vblank_refcount[crtc]) == 0); | 957 | BUG_ON(atomic_read(&dev->vblank[crtc].refcount) == 0); |
| 1003 | 958 | ||
| 1004 | /* Last user schedules interrupt disable */ | 959 | /* Last user schedules interrupt disable */ |
| 1005 | if (atomic_dec_and_test(&dev->vblank_refcount[crtc]) && | 960 | if (atomic_dec_and_test(&dev->vblank[crtc].refcount) && |
| 1006 | (drm_vblank_offdelay > 0)) | 961 | (drm_vblank_offdelay > 0)) |
| 1007 | mod_timer(&dev->vblank_disable_timer, | 962 | mod_timer(&dev->vblank_disable_timer, |
| 1008 | jiffies + ((drm_vblank_offdelay * DRM_HZ)/1000)); | 963 | jiffies + ((drm_vblank_offdelay * DRM_HZ)/1000)); |
| @@ -1025,7 +980,7 @@ void drm_vblank_off(struct drm_device *dev, int crtc) | |||
| 1025 | 980 | ||
| 1026 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | 981 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
| 1027 | vblank_disable_and_save(dev, crtc); | 982 | vblank_disable_and_save(dev, crtc); |
| 1028 | DRM_WAKEUP(&dev->vbl_queue[crtc]); | 983 | DRM_WAKEUP(&dev->vblank[crtc].queue); |
| 1029 | 984 | ||
| 1030 | /* Send any queued vblank events, lest the natives grow disquiet */ | 985 | /* Send any queued vblank events, lest the natives grow disquiet */ |
| 1031 | seq = drm_vblank_count_and_time(dev, crtc, &now); | 986 | seq = drm_vblank_count_and_time(dev, crtc, &now); |
| @@ -1067,10 +1022,10 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) | |||
| 1067 | * to avoid corrupting the count if multiple, mismatch calls occur), | 1022 | * to avoid corrupting the count if multiple, mismatch calls occur), |
| 1068 | * so that interrupts remain enabled in the interim. | 1023 | * so that interrupts remain enabled in the interim. |
| 1069 | */ | 1024 | */ |
| 1070 | if (!dev->vblank_inmodeset[crtc]) { | 1025 | if (!dev->vblank[crtc].inmodeset) { |
| 1071 | dev->vblank_inmodeset[crtc] = 0x1; | 1026 | dev->vblank[crtc].inmodeset = 0x1; |
| 1072 | if (drm_vblank_get(dev, crtc) == 0) | 1027 | if (drm_vblank_get(dev, crtc) == 0) |
| 1073 | dev->vblank_inmodeset[crtc] |= 0x2; | 1028 | dev->vblank[crtc].inmodeset |= 0x2; |
| 1074 | } | 1029 | } |
| 1075 | } | 1030 | } |
| 1076 | EXPORT_SYMBOL(drm_vblank_pre_modeset); | 1031 | EXPORT_SYMBOL(drm_vblank_pre_modeset); |
| @@ -1083,15 +1038,15 @@ void drm_vblank_post_modeset(struct drm_device *dev, int crtc) | |||
| 1083 | if (!dev->num_crtcs) | 1038 | if (!dev->num_crtcs) |
| 1084 | return; | 1039 | return; |
| 1085 | 1040 | ||
| 1086 | if (dev->vblank_inmodeset[crtc]) { | 1041 | if (dev->vblank[crtc].inmodeset) { |
| 1087 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | 1042 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
| 1088 | dev->vblank_disable_allowed = 1; | 1043 | dev->vblank_disable_allowed = true; |
| 1089 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); | 1044 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
| 1090 | 1045 | ||
| 1091 | if (dev->vblank_inmodeset[crtc] & 0x2) | 1046 | if (dev->vblank[crtc].inmodeset & 0x2) |
| 1092 | drm_vblank_put(dev, crtc); | 1047 | drm_vblank_put(dev, crtc); |
| 1093 | 1048 | ||
| 1094 | dev->vblank_inmodeset[crtc] = 0; | 1049 | dev->vblank[crtc].inmodeset = 0; |
| 1095 | } | 1050 | } |
| 1096 | } | 1051 | } |
| 1097 | EXPORT_SYMBOL(drm_vblank_post_modeset); | 1052 | EXPORT_SYMBOL(drm_vblank_post_modeset); |
| @@ -1288,8 +1243,8 @@ int drm_wait_vblank(struct drm_device *dev, void *data, | |||
| 1288 | 1243 | ||
| 1289 | DRM_DEBUG("waiting on vblank count %d, crtc %d\n", | 1244 | DRM_DEBUG("waiting on vblank count %d, crtc %d\n", |
| 1290 | vblwait->request.sequence, crtc); | 1245 | vblwait->request.sequence, crtc); |
| 1291 | dev->last_vblank_wait[crtc] = vblwait->request.sequence; | 1246 | dev->vblank[crtc].last_wait = vblwait->request.sequence; |
| 1292 | DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ, | 1247 | DRM_WAIT_ON(ret, dev->vblank[crtc].queue, 3 * DRM_HZ, |
| 1293 | (((drm_vblank_count(dev, crtc) - | 1248 | (((drm_vblank_count(dev, crtc) - |
| 1294 | vblwait->request.sequence) <= (1 << 23)) || | 1249 | vblwait->request.sequence) <= (1 << 23)) || |
| 1295 | !dev->irq_enabled)); | 1250 | !dev->irq_enabled)); |
| @@ -1367,7 +1322,7 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) | |||
| 1367 | spin_lock_irqsave(&dev->vblank_time_lock, irqflags); | 1322 | spin_lock_irqsave(&dev->vblank_time_lock, irqflags); |
| 1368 | 1323 | ||
| 1369 | /* Vblank irq handling disabled. Nothing to do. */ | 1324 | /* Vblank irq handling disabled. Nothing to do. */ |
| 1370 | if (!dev->vblank_enabled[crtc]) { | 1325 | if (!dev->vblank[crtc].enabled) { |
| 1371 | spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); | 1326 | spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); |
| 1372 | return false; | 1327 | return false; |
| 1373 | } | 1328 | } |
| @@ -1377,7 +1332,7 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) | |||
| 1377 | */ | 1332 | */ |
| 1378 | 1333 | ||
| 1379 | /* Get current timestamp and count. */ | 1334 | /* Get current timestamp and count. */ |
| 1380 | vblcount = atomic_read(&dev->_vblank_count[crtc]); | 1335 | vblcount = atomic_read(&dev->vblank[crtc].count); |
| 1381 | drm_get_last_vbltimestamp(dev, crtc, &tvblank, DRM_CALLED_FROM_VBLIRQ); | 1336 | drm_get_last_vbltimestamp(dev, crtc, &tvblank, DRM_CALLED_FROM_VBLIRQ); |
| 1382 | 1337 | ||
| 1383 | /* Compute time difference to timestamp of last vblank */ | 1338 | /* Compute time difference to timestamp of last vblank */ |
| @@ -1401,14 +1356,14 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc) | |||
| 1401 | * the timestamp computed above. | 1356 | * the timestamp computed above. |
| 1402 | */ | 1357 | */ |
| 1403 | smp_mb__before_atomic_inc(); | 1358 | smp_mb__before_atomic_inc(); |
| 1404 | atomic_inc(&dev->_vblank_count[crtc]); | 1359 | atomic_inc(&dev->vblank[crtc].count); |
| 1405 | smp_mb__after_atomic_inc(); | 1360 | smp_mb__after_atomic_inc(); |
| 1406 | } else { | 1361 | } else { |
| 1407 | DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n", | 1362 | DRM_DEBUG("crtc %d: Redundant vblirq ignored. diff_ns = %d\n", |
| 1408 | crtc, (int) diff_ns); | 1363 | crtc, (int) diff_ns); |
| 1409 | } | 1364 | } |
| 1410 | 1365 | ||
| 1411 | DRM_WAKEUP(&dev->vbl_queue[crtc]); | 1366 | DRM_WAKEUP(&dev->vblank[crtc].queue); |
| 1412 | drm_handle_vblank_events(dev, crtc); | 1367 | drm_handle_vblank_events(dev, crtc); |
| 1413 | 1368 | ||
| 1414 | spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); | 1369 | spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); |
