summaryrefslogtreecommitdiffstats
path: root/drivers/char/drm
diff options
context:
space:
mode:
author=?utf-8?q?Michel_D=C3=A4nzer?= <michel@tungstengraphics.com>2006-10-25 01:05:09 +1000
committerairlied <airlied@linux.ie>2006-12-07 15:53:31 +1100
commit2228ed67223f3f22ea09df8854e6a31ea06d5619 (patch)
tree5c7585a73680d2d172105df9a6699f47d89d6e5c /drivers/char/drm
parenta0b136bb696cfa744a79c4dbbbbd0c8f9f30fe3f (diff)
drm: i915 updates
Add support for DRM_VBLANK_NEXTONMISS. Bump minor for swap scheduling ioctl and secondary vblank support. Avoid mis-counting vblank interrupts when they're only enabled for pipe A. Only schedule vblank tasklet if there are scheduled swaps pending. Signed-off-by: Dave Airlie <airlied@linux.ie>
Diffstat (limited to 'drivers/char/drm')
-rw-r--r--drivers/char/drm/i915_drv.h4
-rw-r--r--drivers/char/drm/i915_irq.c36
2 files changed, 21 insertions, 19 deletions
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index 334b0ce8181..93cdcfe6aa8 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -46,9 +46,11 @@
* 1.3: Add vblank support
* 1.4: Fix cmdbuffer path, add heap destroy
* 1.5: Add vblank pipe configuration
+ * 1.6: - New ioctl for scheduling buffer swaps on vertical blank
+ * - Support vertical blank on secondary display pipe
*/
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 5
+#define DRIVER_MINOR 6
#define DRIVER_PATCHLEVEL 0
typedef struct _drm_i915_ring_buffer {
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index 1a5edec7e19..e5463b111fc 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -153,20 +153,26 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
DRM_WAKEUP(&dev_priv->irq_queue);
if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
- if ((dev_priv->vblank_pipe &
+ int vblank_pipe = dev_priv->vblank_pipe;
+
+ if ((vblank_pipe &
(DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
== (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
if (temp & VSYNC_PIPEA_FLAG)
atomic_inc(&dev->vbl_received);
if (temp & VSYNC_PIPEB_FLAG)
atomic_inc(&dev->vbl_received2);
- } else
+ } else if (((temp & VSYNC_PIPEA_FLAG) &&
+ (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
+ ((temp & VSYNC_PIPEB_FLAG) &&
+ (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
atomic_inc(&dev->vbl_received);
DRM_WAKEUP(&dev->vbl_queue);
drm_vbl_send_signals(dev);
- drm_locked_tasklet(dev, i915_vblank_tasklet);
+ if (dev_priv->swaps_pending > 0)
+ drm_locked_tasklet(dev, i915_vblank_tasklet);
}
return IRQ_HANDLED;
@@ -397,7 +403,7 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
sizeof(swap));
if (swap.seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE |
- _DRM_VBLANK_SECONDARY)) {
+ _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)) {
DRM_ERROR("Invalid sequence type 0x%x\n", swap.seqtype);
return DRM_ERR(EINVAL);
}
@@ -406,11 +412,6 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
seqtype = swap.seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
- if (seqtype == _DRM_VBLANK_RELATIVE && swap.sequence == 0) {
- DRM_DEBUG("Not scheduling swap for current sequence\n");
- return DRM_ERR(EINVAL);
- }
-
if (!(dev_priv->vblank_pipe & (1 << pipe))) {
DRM_ERROR("Invalid pipe %d\n", pipe);
return DRM_ERR(EINVAL);
@@ -428,21 +429,20 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
- spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
-
- switch (seqtype) {
- case _DRM_VBLANK_RELATIVE:
+ if (seqtype == _DRM_VBLANK_RELATIVE)
swap.sequence += curseq;
- break;
- case _DRM_VBLANK_ABSOLUTE:
- if ((curseq - swap.sequence) <= (1<<23)) {
- spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
+
+ if ((curseq - swap.sequence) <= (1<<23)) {
+ if (swap.seqtype & _DRM_VBLANK_NEXTONMISS) {
+ swap.sequence = curseq + 1;
+ } else {
DRM_DEBUG("Missed target sequence\n");
return DRM_ERR(EINVAL);
}
- break;
}
+ spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
+
list_for_each(list, &dev_priv->vbl_swaps.head) {
vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);