Fix pipe<->plane mapping vs. vblank handling (again)
authorJesse Barnes <jbarnes@nietzche.virtuousgeek.org>
Fri, 7 Dec 2007 22:24:45 +0000 (14:24 -0800)
committerJesse Barnes <jbarnes@nietzche.virtuousgeek.org>
Fri, 7 Dec 2007 22:24:45 +0000 (14:24 -0800)
If drmMinor >= 6, the intel DDX driver will enable vblank events on both
pipes.  If drmMinor >= 10 on pre-965 chipsets, the intel DDX driver will
swap the pipe<->plane mapping to allow for framebuffer compression on
laptop screens.  This means the secondary vblank counter (corresponding
to pipe B) will be incremented when vblank interrupts occur.

Now Mesa waits for vblank events on whichever plane has a greater
portion of the displayed window.  So it will happly ask to wait for the
primary counter even though that one won't increment.

So we can fix this in either the DDX driver, Mesa or the kernel (though
I thought we already had several times).

Since current (and previous) userspace assumes it's talking about a pipe
== plane situation and now uses planes when talking to the kernel, we
should probably just hide the mapping details there (indeed they already
are hidden there for vblank swaps), which this patch does.

So as far as userland is concerned, whether we call things planes or
pipes is irrelevant, as long as kernel developers understand that
userland hands them planes and they have to figure out which pipe that
corresponds to (which will typically be the same on 965+ hardware and
reversed on pre-965 mobile chips).

shared-core/i915_irq.c

index e7f3b08..ee7c40b 100644 (file)
@@ -456,12 +456,25 @@ static int i915_driver_vblank_do_wait(struct drm_device *dev,
 
 int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
 {
-       return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
+       atomic_t *counter;
+
+       if (i915_get_pipe(dev, 0) == 0)
+               counter = &dev->vbl_received;
+       else
+               counter = &dev->vbl_received2;
+       return i915_driver_vblank_do_wait(dev, sequence, counter);
 }
 
 int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
 {
-       return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
+       atomic_t *counter;
+
+       if (i915_get_pipe(dev, 1) == 0)
+               counter = &dev->vbl_received;
+       else
+               counter = &dev->vbl_received2;
+
+       return i915_driver_vblank_do_wait(dev, sequence, counter);
 }
 
 /* Needs the lock as it touches the ring.