Add support for secondary vertical blank interrupt to i915 driver.
authorMichel Dänzer <michel@tungstengraphics.com>
Fri, 11 Aug 2006 16:06:46 +0000 (18:06 +0200)
committerMichel Dänzer <michel@tungstengraphics.com>
Fri, 29 Sep 2006 10:55:08 +0000 (12:55 +0200)
When the vertical blank interrupt is enabled for both pipes, pipe A is
considered primary and pipe B secondary. When it's only enabled for one pipe,
it's always considered primary for backwards compatibility.
(cherry picked from 0c7d7f43610f705e8536a949cf2407efaa5ec217 commit)

linux-core/i915_drv.c
shared-core/i915_drv.h
shared-core/i915_irq.c

index 0a0e5f9..1263bca 100644 (file)
@@ -67,12 +67,14 @@ static struct drm_driver driver = {
         */
        .driver_features =
            DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR | */
-           DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
+           DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL |
+           DRIVER_IRQ_VBL2,
        .load = i915_driver_load,
        .lastclose = i915_driver_lastclose,
        .preclose = i915_driver_preclose,
        .device_is_agp = i915_driver_device_is_agp,
        .vblank_wait = i915_driver_vblank_wait,
+       .vblank_wait2 = i915_driver_vblank_wait2,
        .irq_preinstall = i915_driver_irq_preinstall,
        .irq_postinstall = i915_driver_irq_postinstall,
        .irq_uninstall = i915_driver_irq_uninstall,
index 745377c..2732401 100644 (file)
@@ -137,6 +137,7 @@ extern int i915_irq_emit(DRM_IOCTL_ARGS);
 extern int i915_irq_wait(DRM_IOCTL_ARGS);
 
 extern int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
+extern int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence);
 extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
 extern void i915_driver_irq_preinstall(drm_device_t * dev);
 extern void i915_driver_irq_postinstall(drm_device_t * dev);
index 51112b6..c26c276 100644 (file)
@@ -65,7 +65,16 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
        }
 
        if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
-               atomic_inc(&dev->vbl_received);
+               if ((dev_priv->vblank_pipe &
+                    (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)
+                               atomic_inc(&dev->vbl_received);
+                       if (temp & VSYNC_PIPEB_FLAG)
+                               atomic_inc(&dev->vbl_received2);
+               } else
+                       atomic_inc(&dev->vbl_received);
+
                DRM_WAKEUP(&dev->vbl_queue);
                drm_vbl_send_signals(dev);
        }
@@ -153,7 +162,8 @@ static int i915_wait_irq(drm_device_t * dev, int irq_nr)
        return ret;
 }
 
-int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+static int i915_driver_vblank_do_wait(drm_device_t *dev, unsigned int *sequence,
+                                     atomic_t *counter)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
        unsigned int cur_vblank;
@@ -165,7 +175,7 @@ int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
        }
 
        DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
-                   (((cur_vblank = atomic_read(&dev->vbl_received))
+                   (((cur_vblank = atomic_read(counter))
                        - *sequence) <= (1<<23)));
        
        *sequence = cur_vblank;
@@ -173,6 +183,16 @@ int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
        return ret;
 }
 
+int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
+{
+       return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
+}
+
+int i915_driver_vblank_wait2(drm_device_t *dev, unsigned int *sequence)
+{
+       return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
+}
+
 /* Needs the lock as it touches the ring.
  */
 int i915_irq_emit(DRM_IOCTL_ARGS)