diff options
author | anholt <anholt@FreeBSD.org> | 2006-09-07 23:04:47 +0000 |
---|---|---|
committer | anholt <anholt@FreeBSD.org> | 2006-09-07 23:04:47 +0000 |
commit | 50839278da46102d66fbb4dc57e4fb6b59650651 (patch) | |
tree | 21f57d00cf9d69a34b829085f6e21d3973d7c377 /sys/dev/drm/i915_irq.c | |
parent | 6f44289f61f88a6b36afa6b0923223763602f3de (diff) | |
download | FreeBSD-src-50839278da46102d66fbb4dc57e4fb6b59650651.zip FreeBSD-src-50839278da46102d66fbb4dc57e4fb6b59650651.tar.gz |
Merge from DRM upstream:
- Add support for Intel 965 Express chipsets.
- Add support for R200 vertex programs, along with minor bugfixes.
- Add support for vblank synchronization to pipe B of Intel hardware
(laptop screens).
Diffstat (limited to 'sys/dev/drm/i915_irq.c')
-rw-r--r-- | sys/dev/drm/i915_irq.c | 86 |
1 files changed, 79 insertions, 7 deletions
diff --git a/sys/dev/drm/i915_irq.c b/sys/dev/drm/i915_irq.c index f5a0674..b40669c 100644 --- a/sys/dev/drm/i915_irq.c +++ b/sys/dev/drm/i915_irq.c @@ -48,7 +48,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) temp = I915_READ16(I915REG_INT_IDENTITY_R); - temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG); + temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG); DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp); @@ -62,7 +62,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) if (temp & USER_INT_FLAG) DRM_WAKEUP(&dev_priv->irq_queue); - if (temp & VSYNC_PIPEA_FLAG) { + if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) { atomic_inc(&dev->vbl_received); DRM_WAKEUP(&dev->vbl_queue); drm_vbl_send_signals(dev); @@ -73,22 +73,32 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) static int i915_emit_irq(drm_device_t * dev) { + drm_i915_private_t *dev_priv = dev->dev_private; - u32 ret; RING_LOCALS; i915_kernel_lost_context(dev); DRM_DEBUG("%s\n", __FUNCTION__); - ret = dev_priv->counter; + dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter; + + if (dev_priv->counter > 0x7FFFFFFFUL) + dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1; + + BEGIN_LP_RING(6); + OUT_RING(CMD_STORE_DWORD_IDX); + OUT_RING(20); + OUT_RING(dev_priv->counter); - BEGIN_LP_RING(2); + OUT_RING(0); OUT_RING(0); OUT_RING(GFX_OP_USER_INTERRUPT); ADVANCE_LP_RING(); - return ret; + return dev_priv->counter; + + } static int i915_wait_irq(drm_device_t * dev, int irq_nr) @@ -185,6 +195,68 @@ int i915_irq_wait(DRM_IOCTL_ARGS) return i915_wait_irq(dev, irqwait.irq_seq); } +static int i915_enable_interrupt (drm_device_t *dev) +{ + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + u16 flag; + + flag = 0; + if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A) + flag |= VSYNC_PIPEA_FLAG; + if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B) + flag |= VSYNC_PIPEB_FLAG; + if (dev_priv->vblank_pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) { + DRM_ERROR("%s called with invalid pipe 0x%x\n", + __FUNCTION__, dev_priv->vblank_pipe); + return DRM_ERR(EINVAL); + } + I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag); + return 0; +} + +/* Set the vblank monitor pipe + */ +int i915_vblank_pipe_set(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_i915_private_t *dev_priv = dev->dev_private; + drm_i915_vblank_pipe_t pipe; + + if (!dev_priv) { + DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + return DRM_ERR(EINVAL); + } + + DRM_COPY_FROM_USER_IOCTL(pipe, (drm_i915_vblank_pipe_t __user *) data, + sizeof(pipe)); + + dev_priv->vblank_pipe = pipe.pipe; + return i915_enable_interrupt (dev); +} + +int i915_vblank_pipe_get(DRM_IOCTL_ARGS) +{ + DRM_DEVICE; + drm_i915_private_t *dev_priv = dev->dev_private; + drm_i915_vblank_pipe_t pipe; + u16 flag; + + if (!dev_priv) { + DRM_ERROR("%s called with no initialization\n", __FUNCTION__); + return DRM_ERR(EINVAL); + } + + flag = I915_READ(I915REG_INT_ENABLE_R); + pipe.pipe = 0; + if (flag & VSYNC_PIPEA_FLAG) + pipe.pipe |= DRM_I915_VBLANK_PIPE_A; + if (flag & VSYNC_PIPEB_FLAG) + pipe.pipe |= DRM_I915_VBLANK_PIPE_B; + DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_pipe_t __user *) data, pipe, + sizeof(pipe)); + return 0; +} + /* drm_dma.h hooks */ void i915_driver_irq_preinstall(drm_device_t * dev) @@ -200,7 +272,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 | VSYNC_PIPEA_FLAG); + i915_enable_interrupt(dev); DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); } |