aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/drm/i915_irq.c
diff options
context:
space:
mode:
author=?utf-8?q?Michel_D=C3=A4nzer?= <michel@tungstengraphics.com>2006-10-24 11:05:09 -0400
committerairlied <airlied@linux.ie>2006-12-06 23:53:31 -0500
commit2228ed67223f3f22ea09df8854e6a31ea06d5619 (patch)
tree5c7585a73680d2d172105df9a6699f47d89d6e5c /drivers/char/drm/i915_irq.c
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/i915_irq.c')
-rw-r--r--drivers/char/drm/i915_irq.c36
1 files changed, 18 insertions, 18 deletions
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index 1a5edec7e190..e5463b111fc0 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)
153 DRM_WAKEUP(&dev_priv->irq_queue); 153 DRM_WAKEUP(&dev_priv->irq_queue);
154 154
155 if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) { 155 if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
156 if ((dev_priv->vblank_pipe & 156 int vblank_pipe = dev_priv->vblank_pipe;
157
158 if ((vblank_pipe &
157 (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) 159 (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
158 == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) { 160 == (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
159 if (temp & VSYNC_PIPEA_FLAG) 161 if (temp & VSYNC_PIPEA_FLAG)
160 atomic_inc(&dev->vbl_received); 162 atomic_inc(&dev->vbl_received);
161 if (temp & VSYNC_PIPEB_FLAG) 163 if (temp & VSYNC_PIPEB_FLAG)
162 atomic_inc(&dev->vbl_received2); 164 atomic_inc(&dev->vbl_received2);
163 } else 165 } else if (((temp & VSYNC_PIPEA_FLAG) &&
166 (vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
167 ((temp & VSYNC_PIPEB_FLAG) &&
168 (vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
164 atomic_inc(&dev->vbl_received); 169 atomic_inc(&dev->vbl_received);
165 170
166 DRM_WAKEUP(&dev->vbl_queue); 171 DRM_WAKEUP(&dev->vbl_queue);
167 drm_vbl_send_signals(dev); 172 drm_vbl_send_signals(dev);
168 173
169 drm_locked_tasklet(dev, i915_vblank_tasklet); 174 if (dev_priv->swaps_pending > 0)
175 drm_locked_tasklet(dev, i915_vblank_tasklet);
170 } 176 }
171 177
172 return IRQ_HANDLED; 178 return IRQ_HANDLED;
@@ -397,7 +403,7 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
397 sizeof(swap)); 403 sizeof(swap));
398 404
399 if (swap.seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE | 405 if (swap.seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE |
400 _DRM_VBLANK_SECONDARY)) { 406 _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)) {
401 DRM_ERROR("Invalid sequence type 0x%x\n", swap.seqtype); 407 DRM_ERROR("Invalid sequence type 0x%x\n", swap.seqtype);
402 return DRM_ERR(EINVAL); 408 return DRM_ERR(EINVAL);
403 } 409 }
@@ -406,11 +412,6 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
406 412
407 seqtype = swap.seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE); 413 seqtype = swap.seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
408 414
409 if (seqtype == _DRM_VBLANK_RELATIVE && swap.sequence == 0) {
410 DRM_DEBUG("Not scheduling swap for current sequence\n");
411 return DRM_ERR(EINVAL);
412 }
413
414 if (!(dev_priv->vblank_pipe & (1 << pipe))) { 415 if (!(dev_priv->vblank_pipe & (1 << pipe))) {
415 DRM_ERROR("Invalid pipe %d\n", pipe); 416 DRM_ERROR("Invalid pipe %d\n", pipe);
416 return DRM_ERR(EINVAL); 417 return DRM_ERR(EINVAL);
@@ -428,21 +429,20 @@ int i915_vblank_swap(DRM_IOCTL_ARGS)
428 429
429 curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received); 430 curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
430 431
431 spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); 432 if (seqtype == _DRM_VBLANK_RELATIVE)
432
433 switch (seqtype) {
434 case _DRM_VBLANK_RELATIVE:
435 swap.sequence += curseq; 433 swap.sequence += curseq;
436 break; 434
437 case _DRM_VBLANK_ABSOLUTE: 435 if ((curseq - swap.sequence) <= (1<<23)) {
438 if ((curseq - swap.sequence) <= (1<<23)) { 436 if (swap.seqtype & _DRM_VBLANK_NEXTONMISS) {
439 spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); 437 swap.sequence = curseq + 1;
438 } else {
440 DRM_DEBUG("Missed target sequence\n"); 439 DRM_DEBUG("Missed target sequence\n");
441 return DRM_ERR(EINVAL); 440 return DRM_ERR(EINVAL);
442 } 441 }
443 break;
444 } 442 }
445 443
444 spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
445
446 list_for_each(list, &dev_priv->vbl_swaps.head) { 446 list_for_each(list, &dev_priv->vbl_swaps.head) {
447 vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head); 447 vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
448 448