aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_irq.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2008-11-07 17:05:41 -0500
committerDave Airlie <airlied@linux.ie>2008-12-29 02:47:23 -0500
commitf453ba0460742ad027ae0c4c7d61e62817b3e7ef (patch)
tree29e6ecacd6e8971aa62e1825d77f2c1876ac3eb2 /drivers/gpu/drm/drm_irq.c
parentde151cf67ce52ed2d88083daa5e60c7858947329 (diff)
DRM: add mode setting support
Add mode setting support to the DRM layer. This is a fairly big chunk of work that allows DRM drivers to provide full output control and configuration capabilities to userspace. It was motivated by several factors: - the fb layer's APIs aren't suited for anything but simple configurations - coordination between the fb layer, DRM layer, and various userspace drivers is poor to non-existent (radeonfb excepted) - user level mode setting drivers makes displaying panic & oops messages more difficult - suspend/resume of graphics state is possible in many more configurations with kernel level support This commit just adds the core DRM part of the mode setting APIs. Driver specific commits using these new structure and APIs will follow. Co-authors: Jesse Barnes <jbarnes@virtuousgeek.org>, Jakob Bornecrantz <jakob@tungstengraphics.com> Contributors: Alan Hourihane <alanh@tungstengraphics.com>, Maarten Maathuis <madman2003@gmail.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Eric Anholt <eric@anholt.net> Signed-off-by: Dave Airlie <airlied@redhat.com>
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 1e787f894b3c..1608f8dbfda0 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;