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>
This commit is contained in:
=?utf-8?q?Michel_D=C3=A4nzer?= 2006-10-25 01:05:09 +10:00 committed by airlied
parent a0b136bb69
commit 2228ed6722
2 changed files with 21 additions and 19 deletions

View file

@ -46,9 +46,11 @@
* 1.3: Add vblank support * 1.3: Add vblank support
* 1.4: Fix cmdbuffer path, add heap destroy * 1.4: Fix cmdbuffer path, add heap destroy
* 1.5: Add vblank pipe configuration * 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_MAJOR 1
#define DRIVER_MINOR 5 #define DRIVER_MINOR 6
#define DRIVER_PATCHLEVEL 0 #define DRIVER_PATCHLEVEL 0
typedef struct _drm_i915_ring_buffer { typedef struct _drm_i915_ring_buffer {

View file

@ -153,20 +153,26 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
DRM_WAKEUP(&dev_priv->irq_queue); DRM_WAKEUP(&dev_priv->irq_queue);
if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) { 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))
== (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) if (temp & VSYNC_PIPEA_FLAG)
atomic_inc(&dev->vbl_received); atomic_inc(&dev->vbl_received);
if (temp & VSYNC_PIPEB_FLAG) if (temp & VSYNC_PIPEB_FLAG)
atomic_inc(&dev->vbl_received2); 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); atomic_inc(&dev->vbl_received);
DRM_WAKEUP(&dev->vbl_queue); DRM_WAKEUP(&dev->vbl_queue);
drm_vbl_send_signals(dev); 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; return IRQ_HANDLED;
@ -397,7 +403,7 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
sizeof(swap)); sizeof(swap));
if (swap.seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE | 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); DRM_ERROR("Invalid sequence type 0x%x\n", swap.seqtype);
return DRM_ERR(EINVAL); return DRM_ERR(EINVAL);
} }
@ -406,11 +412,6 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
seqtype = swap.seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE); 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))) { if (!(dev_priv->vblank_pipe & (1 << pipe))) {
DRM_ERROR("Invalid pipe %d\n", pipe); DRM_ERROR("Invalid pipe %d\n", pipe);
return DRM_ERR(EINVAL); 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); curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); if (seqtype == _DRM_VBLANK_RELATIVE)
switch (seqtype) {
case _DRM_VBLANK_RELATIVE:
swap.sequence += curseq; swap.sequence += curseq;
break;
case _DRM_VBLANK_ABSOLUTE: if ((curseq - swap.sequence) <= (1<<23)) {
if ((curseq - swap.sequence) <= (1<<23)) { if (swap.seqtype & _DRM_VBLANK_NEXTONMISS) {
spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); swap.sequence = curseq + 1;
} else {
DRM_DEBUG("Missed target sequence\n"); DRM_DEBUG("Missed target sequence\n");
return DRM_ERR(EINVAL); return DRM_ERR(EINVAL);
} }
break;
} }
spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
list_for_each(list, &dev_priv->vbl_swaps.head) { list_for_each(list, &dev_priv->vbl_swaps.head) {
vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head); vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);