Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2228ed67 authored by Michel Dänzer's avatar Michel Dänzer Committed by airlied
Browse files

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: default avatarDave Airlie <airlied@linux.ie>
parent a0b136bb
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -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 {
+18 −18
Original line number Original line Diff line number Diff line
@@ -153,19 +153,25 @@ 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);


		if (dev_priv->swaps_pending > 0)
			drm_locked_tasklet(dev, i915_vblank_tasklet);
			drm_locked_tasklet(dev, i915_vblank_tasklet);
	}
	}


@@ -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)) {
			spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
		if (swap.seqtype & _DRM_VBLANK_NEXTONMISS) {
			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);