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:
parent
a0b136bb69
commit
2228ed6722
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue