diff options
author | =?utf-8?q?Michel_D=C3=A4nzer?= <michel@tungstengraphics.com> | 2006-10-24 22:24:38 +1000 |
---|---|---|
committer | airlied <airlied@linux.ie> | 2006-12-07 15:53:28 +1100 |
commit | 776c9443e28dddbde9b513db6cb8221c45b3a269 (patch) | |
tree | 41b753829e949371ee01d2930f5be1185f29b737 | |
parent | 620034c84d1d939717bdfbe02c51a3fee43541c3 (diff) | |
download | op-kernel-dev-776c9443e28dddbde9b513db6cb8221c45b3a269.zip op-kernel-dev-776c9443e28dddbde9b513db6cb8221c45b3a269.tar.gz |
drm: add support for secondary vertical blank interrupt to DRM core
Signed-off-by: Dave Airlie <airlied@linux.ie>
-rw-r--r-- | drivers/char/drm/drm.h | 4 | ||||
-rw-r--r-- | drivers/char/drm/drmP.h | 4 | ||||
-rw-r--r-- | drivers/char/drm/drm_core.h | 8 | ||||
-rw-r--r-- | drivers/char/drm/drm_irq.c | 72 |
4 files changed, 60 insertions, 28 deletions
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h index 5642ac4..077d0b1 100644 --- a/drivers/char/drm/drm.h +++ b/drivers/char/drm/drm.h @@ -465,10 +465,12 @@ typedef struct drm_irq_busid { typedef enum { _DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */ _DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */ + _DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */ _DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */ } drm_vblank_seq_type_t; -#define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL +#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE) +#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_SIGNAL | _DRM_VBLANK_SECONDARY) struct drm_wait_vblank_request { drm_vblank_seq_type_t type; diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 7690a59..d7135d4 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -97,6 +97,7 @@ #define DRIVER_IRQ_VBL 0x100 #define DRIVER_DMA_QUEUE 0x200 #define DRIVER_FB_DMA 0x400 +#define DRIVER_IRQ_VBL2 0x800 /***********************************************************************/ /** \name Begin the DRM... */ @@ -562,6 +563,7 @@ struct drm_driver { void (*kernel_context_switch_unlock) (struct drm_device * dev, drm_lock_t *lock); int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence); + int (*vblank_wait2) (struct drm_device * dev, unsigned int *sequence); int (*dri_library_name) (struct drm_device *dev, char *buf); /** @@ -708,8 +710,10 @@ typedef struct drm_device { wait_queue_head_t vbl_queue; /**< VBLANK wait queue */ atomic_t vbl_received; + atomic_t vbl_received2; /**< number of secondary VBLANK interrupts */ spinlock_t vbl_lock; drm_vbl_sig_t vbl_sigs; /**< signal list to send on VBLANK */ + drm_vbl_sig_t vbl_sigs2; /**< signals to send on secondary VBLANK */ unsigned int vbl_pending; /*@} */ diff --git a/drivers/char/drm/drm_core.h b/drivers/char/drm/drm_core.h index f4f9db6c..3167390 100644 --- a/drivers/char/drm/drm_core.h +++ b/drivers/char/drm/drm_core.h @@ -24,11 +24,11 @@ #define CORE_NAME "drm" #define CORE_DESC "DRM shared core routines" -#define CORE_DATE "20051102" +#define CORE_DATE "20060810" #define DRM_IF_MAJOR 1 -#define DRM_IF_MINOR 2 +#define DRM_IF_MINOR 3 #define CORE_MAJOR 1 -#define CORE_MINOR 0 -#define CORE_PATCHLEVEL 1 +#define CORE_MINOR 1 +#define CORE_PATCHLEVEL 0 diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c index 4553a3a..3c77756 100644 --- a/drivers/char/drm/drm_irq.c +++ b/drivers/char/drm/drm_irq.c @@ -121,6 +121,7 @@ static int drm_irq_install(drm_device_t * dev) spin_lock_init(&dev->vbl_lock); INIT_LIST_HEAD(&dev->vbl_sigs.head); + INIT_LIST_HEAD(&dev->vbl_sigs2.head); dev->vbl_pending = 0; } @@ -248,9 +249,7 @@ int drm_wait_vblank(DRM_IOCTL_ARGS) struct timeval now; int ret = 0; unsigned int flags; - - if (!drm_core_check_feature(dev, DRIVER_IRQ_VBL)) - return -EINVAL; + atomic_t *seq; if (!dev->irq) return -EINVAL; @@ -258,9 +257,26 @@ int drm_wait_vblank(DRM_IOCTL_ARGS) if (copy_from_user(&vblwait, argp, sizeof(vblwait))) return -EFAULT; - switch (vblwait.request.type & ~_DRM_VBLANK_FLAGS_MASK) { + if (vblwait.request.type & + ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) { + DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n", + vblwait.request.type, + (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)); + return -EINVAL; + } + + flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK; + + if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ? + DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL)) + return -EINVAL; + + seq = (flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2 : + &dev->vbl_received; + + switch (vblwait.request.type & _DRM_VBLANK_TYPES_MASK) { case _DRM_VBLANK_RELATIVE: - vblwait.request.sequence += atomic_read(&dev->vbl_received); + vblwait.request.sequence += atomic_read(seq); vblwait.request.type &= ~_DRM_VBLANK_RELATIVE; case _DRM_VBLANK_ABSOLUTE: break; @@ -268,13 +284,13 @@ int drm_wait_vblank(DRM_IOCTL_ARGS) return -EINVAL; } - flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK; - if (flags & _DRM_VBLANK_SIGNAL) { unsigned long irqflags; + drm_vbl_sig_t *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY) + ? &dev->vbl_sigs2 : &dev->vbl_sigs; drm_vbl_sig_t *vbl_sig; - vblwait.reply.sequence = atomic_read(&dev->vbl_received); + vblwait.reply.sequence = atomic_read(seq); spin_lock_irqsave(&dev->vbl_lock, irqflags); @@ -282,7 +298,7 @@ int drm_wait_vblank(DRM_IOCTL_ARGS) * for the same vblank sequence number; nothing to be done in * that case */ - list_for_each_entry(vbl_sig, &dev->vbl_sigs.head, head) { + list_for_each_entry(vbl_sig, &vbl_sigs->head, head) { if (vbl_sig->sequence == vblwait.request.sequence && vbl_sig->info.si_signo == vblwait.request.signal && vbl_sig->task == current) { @@ -315,11 +331,14 @@ int drm_wait_vblank(DRM_IOCTL_ARGS) spin_lock_irqsave(&dev->vbl_lock, irqflags); - list_add_tail((struct list_head *)vbl_sig, &dev->vbl_sigs.head); + list_add_tail((struct list_head *)vbl_sig, &vbl_sigs->head); spin_unlock_irqrestore(&dev->vbl_lock, irqflags); } else { - if (dev->driver->vblank_wait) + if (flags & _DRM_VBLANK_SECONDARY) { + if (dev->driver->vblank_wait2) + ret = dev->driver->vblank_wait2(dev, &vblwait.request.sequence); + } else if (dev->driver->vblank_wait) ret = dev->driver->vblank_wait(dev, &vblwait.request.sequence); @@ -347,25 +366,32 @@ int drm_wait_vblank(DRM_IOCTL_ARGS) */ void drm_vbl_send_signals(drm_device_t * dev) { - struct list_head *list, *tmp; - drm_vbl_sig_t *vbl_sig; - unsigned int vbl_seq = atomic_read(&dev->vbl_received); unsigned long flags; + int i; spin_lock_irqsave(&dev->vbl_lock, flags); - list_for_each_safe(list, tmp, &dev->vbl_sigs.head) { - vbl_sig = list_entry(list, drm_vbl_sig_t, head); - if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) { - vbl_sig->info.si_code = vbl_seq; - send_sig_info(vbl_sig->info.si_signo, &vbl_sig->info, - vbl_sig->task); + for (i = 0; i < 2; i++) { + struct list_head *list, *tmp; + drm_vbl_sig_t *vbl_sig; + drm_vbl_sig_t *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs; + unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 : + &dev->vbl_received); + + list_for_each_safe(list, tmp, &vbl_sigs->head) { + vbl_sig = list_entry(list, drm_vbl_sig_t, head); + if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) { + vbl_sig->info.si_code = vbl_seq; + send_sig_info(vbl_sig->info.si_signo, + &vbl_sig->info, vbl_sig->task); - list_del(list); + list_del(list); - drm_free(vbl_sig, sizeof(*vbl_sig), DRM_MEM_DRIVER); + drm_free(vbl_sig, sizeof(*vbl_sig), + DRM_MEM_DRIVER); - dev->vbl_pending--; + dev->vbl_pending--; + } } } |