diff options
| author | Dave Airlie <airlied@linux.ie> | 2006-06-24 03:07:34 -0400 |
|---|---|---|
| committer | Dave Airlie <airlied@linux.ie> | 2006-06-24 03:32:58 -0400 |
| commit | 702880f24373dfb31edb0bcd997ff924d07decc3 (patch) | |
| tree | ce78f61ee3b9b71d97bed31437af84c5fa0682da | |
| parent | d6fece051a4ef330922bfafb9d64e3e133e3a8a6 (diff) | |
Add i915 ioctls to configure pipes for vblank interrupt.
i915 vblanks can be generated from either pipe a or b, however a disabled
pipe generates no interrupts. This change allows the X server to select
which pipe generates vblank interrupts.
From: Keith Packard <keith.packard@intel.com> via DRM CVS
Signed-off-by: Dave Airlie <airlied@linux.ie>
| -rw-r--r-- | drivers/char/drm/i915_dma.c | 4 | ||||
| -rw-r--r-- | drivers/char/drm/i915_drm.h | 13 | ||||
| -rw-r--r-- | drivers/char/drm/i915_drv.h | 6 | ||||
| -rw-r--r-- | drivers/char/drm/i915_irq.c | 69 |
4 files changed, 87 insertions, 5 deletions
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index 9f4b8ce4c05e..a94233bdbc0e 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c | |||
| @@ -758,7 +758,9 @@ drm_ioctl_desc_t i915_ioctls[] = { | |||
| 758 | [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH}, | 758 | [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH}, |
| 759 | [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, | 759 | [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
| 760 | [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH}, | 760 | [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH}, |
| 761 | [DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY } | 761 | [DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, |
| 762 | [DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] = { i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, | ||
| 763 | [DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get, DRM_AUTH }, | ||
| 762 | }; | 764 | }; |
| 763 | 765 | ||
| 764 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); | 766 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); |
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h index 4cb3da578330..5aa3e0e3bb45 100644 --- a/drivers/char/drm/i915_drm.h +++ b/drivers/char/drm/i915_drm.h | |||
| @@ -124,6 +124,8 @@ typedef struct _drm_i915_sarea { | |||
| 124 | #define DRM_I915_INIT_HEAP 0x0a | 124 | #define DRM_I915_INIT_HEAP 0x0a |
| 125 | #define DRM_I915_CMDBUFFER 0x0b | 125 | #define DRM_I915_CMDBUFFER 0x0b |
| 126 | #define DRM_I915_DESTROY_HEAP 0x0c | 126 | #define DRM_I915_DESTROY_HEAP 0x0c |
| 127 | #define DRM_I915_SET_VBLANK_PIPE 0x0d | ||
| 128 | #define DRM_I915_GET_VBLANK_PIPE 0x0e | ||
| 127 | 129 | ||
| 128 | #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) | 130 | #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) |
| 129 | #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) | 131 | #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) |
| @@ -138,6 +140,8 @@ typedef struct _drm_i915_sarea { | |||
| 138 | #define DRM_IOCTL_I915_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t) | 140 | #define DRM_IOCTL_I915_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t) |
| 139 | #define DRM_IOCTL_I915_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t) | 141 | #define DRM_IOCTL_I915_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t) |
| 140 | #define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t) | 142 | #define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t) |
| 143 | #define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t) | ||
| 144 | #define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t) | ||
| 141 | 145 | ||
| 142 | /* Allow drivers to submit batchbuffers directly to hardware, relying | 146 | /* Allow drivers to submit batchbuffers directly to hardware, relying |
| 143 | * on the security mechanisms provided by hardware. | 147 | * on the security mechanisms provided by hardware. |
| @@ -224,4 +228,13 @@ typedef struct drm_i915_mem_destroy_heap { | |||
| 224 | int region; | 228 | int region; |
| 225 | } drm_i915_mem_destroy_heap_t; | 229 | } drm_i915_mem_destroy_heap_t; |
| 226 | 230 | ||
| 231 | /* Allow X server to configure which pipes to monitor for vblank signals | ||
| 232 | */ | ||
| 233 | #define DRM_I915_VBLANK_PIPE_A 1 | ||
| 234 | #define DRM_I915_VBLANK_PIPE_B 2 | ||
| 235 | |||
| 236 | typedef struct drm_i915_vblank_pipe { | ||
| 237 | int pipe; | ||
| 238 | } drm_i915_vblank_pipe_t; | ||
| 239 | |||
| 227 | #endif /* _I915_DRM_H_ */ | 240 | #endif /* _I915_DRM_H_ */ |
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h index 7a65666899e4..2d565031c002 100644 --- a/drivers/char/drm/i915_drv.h +++ b/drivers/char/drm/i915_drv.h | |||
| @@ -45,9 +45,10 @@ | |||
| 45 | * 1.2: Add Power Management | 45 | * 1.2: Add Power Management |
| 46 | * 1.3: Add vblank support | 46 | * 1.3: Add vblank support |
| 47 | * 1.4: Fix cmdbuffer path, add heap destroy | 47 | * 1.4: Fix cmdbuffer path, add heap destroy |
| 48 | * 1.5: Add vblank pipe configuration | ||
| 48 | */ | 49 | */ |
| 49 | #define DRIVER_MAJOR 1 | 50 | #define DRIVER_MAJOR 1 |
| 50 | #define DRIVER_MINOR 4 | 51 | #define DRIVER_MINOR 5 |
| 51 | #define DRIVER_PATCHLEVEL 0 | 52 | #define DRIVER_PATCHLEVEL 0 |
| 52 | 53 | ||
| 53 | typedef struct _drm_i915_ring_buffer { | 54 | typedef struct _drm_i915_ring_buffer { |
| @@ -96,6 +97,7 @@ typedef struct drm_i915_private { | |||
| 96 | int allow_batchbuffer; | 97 | int allow_batchbuffer; |
| 97 | struct mem_block *agp_heap; | 98 | struct mem_block *agp_heap; |
| 98 | unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; | 99 | unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; |
| 100 | int vblank_pipe; | ||
| 99 | } drm_i915_private_t; | 101 | } drm_i915_private_t; |
| 100 | 102 | ||
| 101 | extern drm_ioctl_desc_t i915_ioctls[]; | 103 | extern drm_ioctl_desc_t i915_ioctls[]; |
| @@ -119,6 +121,8 @@ extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); | |||
| 119 | extern void i915_driver_irq_preinstall(drm_device_t * dev); | 121 | extern void i915_driver_irq_preinstall(drm_device_t * dev); |
| 120 | extern void i915_driver_irq_postinstall(drm_device_t * dev); | 122 | extern void i915_driver_irq_postinstall(drm_device_t * dev); |
| 121 | extern void i915_driver_irq_uninstall(drm_device_t * dev); | 123 | extern void i915_driver_irq_uninstall(drm_device_t * dev); |
| 124 | extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS); | ||
| 125 | extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS); | ||
| 122 | 126 | ||
| 123 | /* i915_mem.c */ | 127 | /* i915_mem.c */ |
| 124 | extern int i915_mem_alloc(DRM_IOCTL_ARGS); | 128 | extern int i915_mem_alloc(DRM_IOCTL_ARGS); |
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c index a752afd86ab8..cd96cfa430db 100644 --- a/drivers/char/drm/i915_irq.c +++ b/drivers/char/drm/i915_irq.c | |||
| @@ -44,7 +44,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
| 44 | u16 temp; | 44 | u16 temp; |
| 45 | 45 | ||
| 46 | temp = I915_READ16(I915REG_INT_IDENTITY_R); | 46 | temp = I915_READ16(I915REG_INT_IDENTITY_R); |
| 47 | temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG); | 47 | |
| 48 | temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG); | ||
| 48 | 49 | ||
| 49 | DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp); | 50 | DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp); |
| 50 | 51 | ||
| @@ -58,7 +59,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
| 58 | if (temp & USER_INT_FLAG) | 59 | if (temp & USER_INT_FLAG) |
| 59 | DRM_WAKEUP(&dev_priv->irq_queue); | 60 | DRM_WAKEUP(&dev_priv->irq_queue); |
| 60 | 61 | ||
| 61 | if (temp & VSYNC_PIPEA_FLAG) { | 62 | if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) { |
| 62 | atomic_inc(&dev->vbl_received); | 63 | atomic_inc(&dev->vbl_received); |
| 63 | DRM_WAKEUP(&dev->vbl_queue); | 64 | DRM_WAKEUP(&dev->vbl_queue); |
| 64 | drm_vbl_send_signals(dev); | 65 | drm_vbl_send_signals(dev); |
| @@ -182,6 +183,68 @@ int i915_irq_wait(DRM_IOCTL_ARGS) | |||
| 182 | return i915_wait_irq(dev, irqwait.irq_seq); | 183 | return i915_wait_irq(dev, irqwait.irq_seq); |
| 183 | } | 184 | } |
| 184 | 185 | ||
| 186 | static int i915_enable_interrupt (drm_device_t *dev) | ||
| 187 | { | ||
| 188 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | ||
| 189 | u16 flag; | ||
| 190 | |||
| 191 | flag = 0; | ||
| 192 | if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A) | ||
| 193 | flag |= VSYNC_PIPEA_FLAG; | ||
| 194 | if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B) | ||
| 195 | flag |= VSYNC_PIPEB_FLAG; | ||
| 196 | if (dev_priv->vblank_pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) { | ||
| 197 | DRM_ERROR("%s called with invalid pipe 0x%x\n", | ||
| 198 | __FUNCTION__, dev_priv->vblank_pipe); | ||
| 199 | return DRM_ERR(EINVAL); | ||
| 200 | } | ||
| 201 | I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag); | ||
| 202 | return 0; | ||
| 203 | } | ||
| 204 | |||
| 205 | /* Set the vblank monitor pipe | ||
| 206 | */ | ||
| 207 | int i915_vblank_pipe_set(DRM_IOCTL_ARGS) | ||
| 208 | { | ||
| 209 | DRM_DEVICE; | ||
| 210 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
| 211 | drm_i915_vblank_pipe_t pipe; | ||
| 212 | |||
| 213 | if (!dev_priv) { | ||
| 214 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | ||
| 215 | return DRM_ERR(EINVAL); | ||
| 216 | } | ||
| 217 | |||
| 218 | DRM_COPY_FROM_USER_IOCTL(pipe, (drm_i915_vblank_pipe_t __user *) data, | ||
| 219 | sizeof(pipe)); | ||
| 220 | |||
| 221 | dev_priv->vblank_pipe = pipe.pipe; | ||
| 222 | return i915_enable_interrupt (dev); | ||
| 223 | } | ||
| 224 | |||
| 225 | int i915_vblank_pipe_get(DRM_IOCTL_ARGS) | ||
| 226 | { | ||
| 227 | DRM_DEVICE; | ||
| 228 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
| 229 | drm_i915_vblank_pipe_t pipe; | ||
| 230 | u16 flag; | ||
| 231 | |||
| 232 | if (!dev_priv) { | ||
| 233 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | ||
| 234 | return DRM_ERR(EINVAL); | ||
| 235 | } | ||
| 236 | |||
| 237 | flag = I915_READ(I915REG_INT_ENABLE_R); | ||
| 238 | pipe.pipe = 0; | ||
| 239 | if (flag & VSYNC_PIPEA_FLAG) | ||
| 240 | pipe.pipe |= DRM_I915_VBLANK_PIPE_A; | ||
| 241 | if (flag & VSYNC_PIPEB_FLAG) | ||
| 242 | pipe.pipe |= DRM_I915_VBLANK_PIPE_B; | ||
| 243 | DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_pipe_t __user *) data, pipe, | ||
| 244 | sizeof(pipe)); | ||
| 245 | return 0; | ||
| 246 | } | ||
| 247 | |||
| 185 | /* drm_dma.h hooks | 248 | /* drm_dma.h hooks |
| 186 | */ | 249 | */ |
| 187 | void i915_driver_irq_preinstall(drm_device_t * dev) | 250 | void i915_driver_irq_preinstall(drm_device_t * dev) |
| @@ -197,7 +260,7 @@ void i915_driver_irq_postinstall(drm_device_t * dev) | |||
| 197 | { | 260 | { |
| 198 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 261 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
| 199 | 262 | ||
| 200 | I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | VSYNC_PIPEA_FLAG); | 263 | i915_enable_interrupt(dev); |
| 201 | DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); | 264 | DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); |
| 202 | } | 265 | } |
| 203 | 266 | ||
