aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_irq.c')
-rw-r--r--drivers/gpu/drm/drm_irq.c64
1 files changed, 45 insertions, 19 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 1e787f894b3..1608f8dbfda 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -305,6 +305,8 @@ int drm_control(struct drm_device *dev, void *data,
305 case DRM_INST_HANDLER: 305 case DRM_INST_HANDLER:
306 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 306 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
307 return 0; 307 return 0;
308 if (drm_core_check_feature(dev, DRIVER_MODESET))
309 return 0;
308 if (dev->if_version < DRM_IF_VERSION(1, 2) && 310 if (dev->if_version < DRM_IF_VERSION(1, 2) &&
309 ctl->irq != dev->pdev->irq) 311 ctl->irq != dev->pdev->irq)
310 return -EINVAL; 312 return -EINVAL;
@@ -312,6 +314,8 @@ int drm_control(struct drm_device *dev, void *data,
312 case DRM_UNINST_HANDLER: 314 case DRM_UNINST_HANDLER:
313 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 315 if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
314 return 0; 316 return 0;
317 if (drm_core_check_feature(dev, DRIVER_MODESET))
318 return 0;
315 return drm_irq_uninstall(dev); 319 return drm_irq_uninstall(dev);
316 default: 320 default:
317 return -EINVAL; 321 return -EINVAL;
@@ -427,6 +431,45 @@ void drm_vblank_put(struct drm_device *dev, int crtc)
427EXPORT_SYMBOL(drm_vblank_put); 431EXPORT_SYMBOL(drm_vblank_put);
428 432
429/** 433/**
434 * drm_vblank_pre_modeset - account for vblanks across mode sets
435 * @dev: DRM device
436 * @crtc: CRTC in question
437 * @post: post or pre mode set?
438 *
439 * Account for vblank events across mode setting events, which will likely
440 * reset the hardware frame counter.
441 */
442void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
443{
444 /*
445 * To avoid all the problems that might happen if interrupts
446 * were enabled/disabled around or between these calls, we just
447 * have the kernel take a reference on the CRTC (just once though
448 * to avoid corrupting the count if multiple, mismatch calls occur),
449 * so that interrupts remain enabled in the interim.
450 */
451 if (!dev->vblank_inmodeset[crtc]) {
452 dev->vblank_inmodeset[crtc] = 1;
453 drm_vblank_get(dev, crtc);
454 }
455}
456EXPORT_SYMBOL(drm_vblank_pre_modeset);
457
458void drm_vblank_post_modeset(struct drm_device *dev, int crtc)
459{
460 unsigned long irqflags;
461
462 if (dev->vblank_inmodeset[crtc]) {
463 spin_lock_irqsave(&dev->vbl_lock, irqflags);
464 dev->vblank_disable_allowed = 1;
465 dev->vblank_inmodeset[crtc] = 0;
466 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
467 drm_vblank_put(dev, crtc);
468 }
469}
470EXPORT_SYMBOL(drm_vblank_post_modeset);
471
472/**
430 * drm_modeset_ctl - handle vblank event counter changes across mode switch 473 * drm_modeset_ctl - handle vblank event counter changes across mode switch
431 * @DRM_IOCTL_ARGS: standard ioctl arguments 474 * @DRM_IOCTL_ARGS: standard ioctl arguments
432 * 475 *
@@ -441,7 +484,6 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,
441 struct drm_file *file_priv) 484 struct drm_file *file_priv)
442{ 485{
443 struct drm_modeset_ctl *modeset = data; 486 struct drm_modeset_ctl *modeset = data;
444 unsigned long irqflags;
445 int crtc, ret = 0; 487 int crtc, ret = 0;
446 488
447 /* If drm_vblank_init() hasn't been called yet, just no-op */ 489 /* If drm_vblank_init() hasn't been called yet, just no-op */
@@ -454,28 +496,12 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,
454 goto out; 496 goto out;
455 } 497 }
456 498
457 /*
458 * To avoid all the problems that might happen if interrupts
459 * were enabled/disabled around or between these calls, we just
460 * have the kernel take a reference on the CRTC (just once though
461 * to avoid corrupting the count if multiple, mismatch calls occur),
462 * so that interrupts remain enabled in the interim.
463 */
464 switch (modeset->cmd) { 499 switch (modeset->cmd) {
465 case _DRM_PRE_MODESET: 500 case _DRM_PRE_MODESET:
466 if (!dev->vblank_inmodeset[crtc]) { 501 drm_vblank_pre_modeset(dev, crtc);
467 dev->vblank_inmodeset[crtc] = 1;
468 drm_vblank_get(dev, crtc);
469 }
470 break; 502 break;
471 case _DRM_POST_MODESET: 503 case _DRM_POST_MODESET:
472 if (dev->vblank_inmodeset[crtc]) { 504 drm_vblank_post_modeset(dev, crtc);
473 spin_lock_irqsave(&dev->vbl_lock, irqflags);
474 dev->vblank_disable_allowed = 1;
475 dev->vblank_inmodeset[crtc] = 0;
476 spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
477 drm_vblank_put(dev, crtc);
478 }
479 break; 505 break;
480 default: 506 default:
481 ret = -EINVAL; 507 ret = -EINVAL;