aboutsummaryrefslogtreecommitdiffstats
path: root/include/drm
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2008-09-30 15:14:26 -0400
committerDave Airlie <airlied@linux.ie>2008-10-17 17:10:11 -0400
commit0a3e67a4caac273a3bfc4ced3da364830b1ab241 (patch)
tree02a2e5e76d9dffcb556d09b0eee4d34ebe5d81cb /include/drm
parent2df68b439fcb97a4c55f81516206ef4ee325e28d (diff)
drm: Rework vblank-wait handling to allow interrupt reduction.
Previously, drivers supporting vblank interrupt waits would run the interrupt all the time, or all the time that any 3d client was running, preventing the CPU from sleeping for long when the system was otherwise idle. Now, interrupts are disabled any time that no client is waiting on a vblank event. The new method uses vblank counters on the chipsets when the interrupts are turned off, rather than counting interrupts, so that we can continue to present accurate vblank numbers. Co-author: Michel Dänzer <michel@tungstengraphics.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 'include/drm')
-rw-r--r--include/drm/drm.h15
-rw-r--r--include/drm/drmP.h90
2 files changed, 94 insertions, 11 deletions
diff --git a/include/drm/drm.h b/include/drm/drm.h
index 0864c6920941..15e55039b7f1 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -454,6 +454,7 @@ struct drm_irq_busid {
454enum drm_vblank_seq_type { 454enum drm_vblank_seq_type {
455 _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ 455 _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
456 _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ 456 _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
457 _DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */
457 _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */ 458 _DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */
458 _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ 459 _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */
459 _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */ 460 _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
@@ -486,6 +487,19 @@ union drm_wait_vblank {
486 struct drm_wait_vblank_reply reply; 487 struct drm_wait_vblank_reply reply;
487}; 488};
488 489
490#define _DRM_PRE_MODESET 1
491#define _DRM_POST_MODESET 2
492
493/**
494 * DRM_IOCTL_MODESET_CTL ioctl argument type
495 *
496 * \sa drmModesetCtl().
497 */
498struct drm_modeset_ctl {
499 uint32_t crtc;
500 uint32_t cmd;
501};
502
489/** 503/**
490 * DRM_IOCTL_AGP_ENABLE ioctl argument type. 504 * DRM_IOCTL_AGP_ENABLE ioctl argument type.
491 * 505 *
@@ -570,6 +584,7 @@ struct drm_set_version {
570#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client) 584#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client)
571#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats) 585#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats)
572#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version) 586#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version)
587#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl)
573 588
574#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique) 589#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique)
575#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth) 590#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth)
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 1c1b13e29223..e79ce0781f0b 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -580,11 +580,54 @@ struct drm_driver {
580 int (*kernel_context_switch) (struct drm_device *dev, int old, 580 int (*kernel_context_switch) (struct drm_device *dev, int old,
581 int new); 581 int new);
582 void (*kernel_context_switch_unlock) (struct drm_device *dev); 582 void (*kernel_context_switch_unlock) (struct drm_device *dev);
583 int (*vblank_wait) (struct drm_device *dev, unsigned int *sequence);
584 int (*vblank_wait2) (struct drm_device *dev, unsigned int *sequence);
585 int (*dri_library_name) (struct drm_device *dev, char *buf); 583 int (*dri_library_name) (struct drm_device *dev, char *buf);
586 584
587 /** 585 /**
586 * get_vblank_counter - get raw hardware vblank counter
587 * @dev: DRM device
588 * @crtc: counter to fetch
589 *
590 * Driver callback for fetching a raw hardware vblank counter
591 * for @crtc. If a device doesn't have a hardware counter, the
592 * driver can simply return the value of drm_vblank_count and
593 * make the enable_vblank() and disable_vblank() hooks into no-ops,
594 * leaving interrupts enabled at all times.
595 *
596 * Wraparound handling and loss of events due to modesetting is dealt
597 * with in the DRM core code.
598 *
599 * RETURNS
600 * Raw vblank counter value.
601 */
602 u32 (*get_vblank_counter) (struct drm_device *dev, int crtc);
603
604 /**
605 * enable_vblank - enable vblank interrupt events
606 * @dev: DRM device
607 * @crtc: which irq to enable
608 *
609 * Enable vblank interrupts for @crtc. If the device doesn't have
610 * a hardware vblank counter, this routine should be a no-op, since
611 * interrupts will have to stay on to keep the count accurate.
612 *
613 * RETURNS
614 * Zero on success, appropriate errno if the given @crtc's vblank
615 * interrupt cannot be enabled.
616 */
617 int (*enable_vblank) (struct drm_device *dev, int crtc);
618
619 /**
620 * disable_vblank - disable vblank interrupt events
621 * @dev: DRM device
622 * @crtc: which irq to enable
623 *
624 * Disable vblank interrupts for @crtc. If the device doesn't have
625 * a hardware vblank counter, this routine should be a no-op, since
626 * interrupts will have to stay on to keep the count accurate.
627 */
628 void (*disable_vblank) (struct drm_device *dev, int crtc);
629
630 /**
588 * Called by \c drm_device_is_agp. Typically used to determine if a 631 * Called by \c drm_device_is_agp. Typically used to determine if a
589 * card is really attached to AGP or not. 632 * card is really attached to AGP or not.
590 * 633 *
@@ -601,7 +644,7 @@ struct drm_driver {
601 644
602 irqreturn_t(*irq_handler) (DRM_IRQ_ARGS); 645 irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
603 void (*irq_preinstall) (struct drm_device *dev); 646 void (*irq_preinstall) (struct drm_device *dev);
604 void (*irq_postinstall) (struct drm_device *dev); 647 int (*irq_postinstall) (struct drm_device *dev);
605 void (*irq_uninstall) (struct drm_device *dev); 648 void (*irq_uninstall) (struct drm_device *dev);
606 void (*reclaim_buffers) (struct drm_device *dev, 649 void (*reclaim_buffers) (struct drm_device *dev,
607 struct drm_file * file_priv); 650 struct drm_file * file_priv);
@@ -730,13 +773,28 @@ struct drm_device {
730 /** \name VBLANK IRQ support */ 773 /** \name VBLANK IRQ support */
731 /*@{ */ 774 /*@{ */
732 775
733 wait_queue_head_t vbl_queue; /**< VBLANK wait queue */ 776 /*
734 atomic_t vbl_received; 777 * At load time, disabling the vblank interrupt won't be allowed since
735 atomic_t vbl_received2; /**< number of secondary VBLANK interrupts */ 778 * old clients may not call the modeset ioctl and therefore misbehave.
779 * Once the modeset ioctl *has* been called though, we can safely
780 * disable them when unused.
781 */
782 int vblank_disable_allowed;
783
784 wait_queue_head_t *vbl_queue; /**< VBLANK wait queue */
785 atomic_t *_vblank_count; /**< number of VBLANK interrupts (driver must alloc the right number of counters) */
736 spinlock_t vbl_lock; 786 spinlock_t vbl_lock;
737 struct list_head vbl_sigs; /**< signal list to send on VBLANK */ 787 struct list_head *vbl_sigs; /**< signal list to send on VBLANK */
738 struct list_head vbl_sigs2; /**< signals to send on secondary VBLANK */ 788 atomic_t vbl_signal_pending; /* number of signals pending on all crtcs*/
739 unsigned int vbl_pending; 789 atomic_t *vblank_refcount; /* number of users of vblank interruptsper crtc */
790 u32 *last_vblank; /* protected by dev->vbl_lock, used */
791 /* for wraparound handling */
792 int *vblank_enabled; /* so we don't call enable more than
793 once per disable */
794 int *vblank_inmodeset; /* Display driver is setting mode */
795 struct timer_list vblank_disable_timer;
796
797 u32 max_vblank_count; /**< size of vblank counter register */
740 spinlock_t tasklet_lock; /**< For drm_locked_tasklet */ 798 spinlock_t tasklet_lock; /**< For drm_locked_tasklet */
741 void (*locked_tasklet_func)(struct drm_device *dev); 799 void (*locked_tasklet_func)(struct drm_device *dev);
742 800
@@ -757,6 +815,7 @@ struct drm_device {
757 struct pci_controller *hose; 815 struct pci_controller *hose;
758#endif 816#endif
759 struct drm_sg_mem *sg; /**< Scatter gather memory */ 817 struct drm_sg_mem *sg; /**< Scatter gather memory */
818 int num_crtcs; /**< Number of CRTCs on this device */
760 void *dev_private; /**< device private data */ 819 void *dev_private; /**< device private data */
761 struct drm_sigdata sigdata; /**< For block_all_signals */ 820 struct drm_sigdata sigdata; /**< For block_all_signals */
762 sigset_t sigmask; 821 sigset_t sigmask;
@@ -990,10 +1049,19 @@ extern void drm_driver_irq_preinstall(struct drm_device *dev);
990extern void drm_driver_irq_postinstall(struct drm_device *dev); 1049extern void drm_driver_irq_postinstall(struct drm_device *dev);
991extern void drm_driver_irq_uninstall(struct drm_device *dev); 1050extern void drm_driver_irq_uninstall(struct drm_device *dev);
992 1051
1052extern int drm_vblank_init(struct drm_device *dev, int num_crtcs);
993extern int drm_wait_vblank(struct drm_device *dev, void *data, 1053extern int drm_wait_vblank(struct drm_device *dev, void *data,
994 struct drm_file *file_priv); 1054 struct drm_file *filp);
995extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq); 1055extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
996extern void drm_vbl_send_signals(struct drm_device *dev); 1056extern void drm_locked_tasklet(struct drm_device *dev,
1057 void(*func)(struct drm_device *));
1058extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
1059extern void drm_handle_vblank(struct drm_device *dev, int crtc);
1060extern int drm_vblank_get(struct drm_device *dev, int crtc);
1061extern void drm_vblank_put(struct drm_device *dev, int crtc);
1062/* Modesetting support */
1063extern int drm_modeset_ctl(struct drm_device *dev, void *data,
1064 struct drm_file *file_priv);
997extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*)); 1065extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
998 1066
999 /* AGP/GART support (drm_agpsupport.h) */ 1067 /* AGP/GART support (drm_agpsupport.h) */