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 /drivers/char | |
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>
Diffstat (limited to 'drivers/char')
-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 | ||