aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorDave Airlie <airlied@linux.ie>2006-06-24 03:07:34 -0400
committerDave Airlie <airlied@linux.ie>2006-06-24 03:32:58 -0400
commit702880f24373dfb31edb0bcd997ff924d07decc3 (patch)
treece78f61ee3b9b71d97bed31437af84c5fa0682da /drivers/char
parentd6fece051a4ef330922bfafb9d64e3e133e3a8a6 (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.c4
-rw-r--r--drivers/char/drm/i915_drm.h13
-rw-r--r--drivers/char/drm/i915_drv.h6
-rw-r--r--drivers/char/drm/i915_irq.c69
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
764int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); 766int 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
236typedef 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
53typedef struct _drm_i915_ring_buffer { 54typedef 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
101extern drm_ioctl_desc_t i915_ioctls[]; 103extern drm_ioctl_desc_t i915_ioctls[];
@@ -119,6 +121,8 @@ extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
119extern void i915_driver_irq_preinstall(drm_device_t * dev); 121extern void i915_driver_irq_preinstall(drm_device_t * dev);
120extern void i915_driver_irq_postinstall(drm_device_t * dev); 122extern void i915_driver_irq_postinstall(drm_device_t * dev);
121extern void i915_driver_irq_uninstall(drm_device_t * dev); 123extern void i915_driver_irq_uninstall(drm_device_t * dev);
124extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS);
125extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS);
122 126
123/* i915_mem.c */ 127/* i915_mem.c */
124extern int i915_mem_alloc(DRM_IOCTL_ARGS); 128extern 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
186static 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 */
207int 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
225int 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*/
187void i915_driver_irq_preinstall(drm_device_t * dev) 250void 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