diff options
author | =?utf-8?q?Michel_D=C3=A4nzer?= <michel@tungstengraphics.com> | 2006-10-24 11:05:09 -0400 |
---|---|---|
committer | airlied <airlied@linux.ie> | 2006-12-06 23:53:31 -0500 |
commit | 2228ed67223f3f22ea09df8854e6a31ea06d5619 (patch) | |
tree | 5c7585a73680d2d172105df9a6699f47d89d6e5c /drivers | |
parent | a0b136bb696cfa744a79c4dbbbbd0c8f9f30fe3f (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')
-rw-r--r-- | drivers/char/drm/i915_drv.h | 4 | ||||
-rw-r--r-- | drivers/char/drm/i915_irq.c | 36 |
2 files changed, 21 insertions, 19 deletions
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h index 334b0ce8181d..93cdcfe6aa84 100644 --- a/drivers/char/drm/i915_drv.h +++ b/drivers/char/drm/i915_drv.h | |||
@@ -46,9 +46,11 @@ | |||
46 | * 1.3: Add vblank support | 46 | * 1.3: Add vblank support |
47 | * 1.4: Fix cmdbuffer path, add heap destroy | 47 | * 1.4: Fix cmdbuffer path, add heap destroy |
48 | * 1.5: Add vblank pipe configuration | 48 | * 1.5: Add vblank pipe configuration |
49 | * 1.6: - New ioctl for scheduling buffer swaps on vertical blank | ||
50 | * - Support vertical blank on secondary display pipe | ||
49 | */ | 51 | */ |
50 | #define DRIVER_MAJOR 1 | 52 | #define DRIVER_MAJOR 1 |
51 | #define DRIVER_MINOR 5 | 53 | #define DRIVER_MINOR 6 |
52 | #define DRIVER_PATCHLEVEL 0 | 54 | #define DRIVER_PATCHLEVEL 0 |
53 | 55 | ||
54 | typedef struct _drm_i915_ring_buffer { | 56 | typedef struct _drm_i915_ring_buffer { |
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 | ||