diff options
Diffstat (limited to 'drivers/char/drm/i915_irq.c')
-rw-r--r-- | drivers/char/drm/i915_irq.c | 48 |
1 files changed, 39 insertions, 9 deletions
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c index 4fa448ee846..a1381c61aa6 100644 --- a/drivers/char/drm/i915_irq.c +++ b/drivers/char/drm/i915_irq.c @@ -1,7 +1,6 @@ -/* i915_dma.c -- DMA support for the I915 -*- linux-c -*- +/* i915_irq.c -- IRQ support for the I915 -*- linux-c -*- */ -/************************************************************************** - * +/* * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. * @@ -25,16 +24,18 @@ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - **************************************************************************/ + */ #include "drmP.h" #include "drm.h" #include "i915_drm.h" #include "i915_drv.h" -#define USER_INT_FLAG 0x2 +#define USER_INT_FLAG (1<<1) +#define VSYNC_PIPEB_FLAG (1<<5) +#define VSYNC_PIPEA_FLAG (1<<7) + #define MAX_NOPID ((u32)~0) -#define READ_BREADCRUMB(dev_priv) (((u32*)(dev_priv->hw_status_page))[5]) irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) { @@ -43,7 +44,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) u16 temp; temp = I915_READ16(I915REG_INT_IDENTITY_R); - temp &= USER_INT_FLAG; + temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG); DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp); @@ -51,7 +52,15 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) return IRQ_NONE; I915_WRITE16(I915REG_INT_IDENTITY_R, temp); - DRM_WAKEUP(&dev_priv->irq_queue); + + if (temp & USER_INT_FLAG) + DRM_WAKEUP(&dev_priv->irq_queue); + + if (temp & VSYNC_PIPEA_FLAG) { + atomic_inc(&dev->vbl_received); + DRM_WAKEUP(&dev->vbl_queue); + drm_vbl_send_signals(dev); + } return IRQ_HANDLED; } @@ -102,6 +111,27 @@ 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) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + unsigned int cur_vblank; + int ret = 0; + + if (!dev_priv) { + DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + return DRM_ERR(EINVAL); + } + + DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, + (((cur_vblank = atomic_read(&dev->vbl_received)) + - *sequence) <= (1<<23))); + + *sequence = cur_vblank; + + return ret; +} + + /* Needs the lock as it touches the ring. */ int i915_irq_emit(DRM_IOCTL_ARGS) @@ -165,7 +195,7 @@ void i915_driver_irq_postinstall(drm_device_t * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG); + I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | VSYNC_PIPEA_FLAG); DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); } |