Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+87 -5
+3 -1
drivers/char/drm/i915_dma.c
··· 758 758 [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH}, 759 759 [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, 760 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 766 int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
+13
drivers/char/drm/i915_drm.h
··· 124 124 #define DRM_I915_INIT_HEAP 0x0a 125 125 #define DRM_I915_CMDBUFFER 0x0b 126 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 130 #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) 129 131 #define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH) ··· 140 138 #define DRM_IOCTL_I915_INIT_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t) 141 139 #define DRM_IOCTL_I915_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t) 142 140 #define DRM_IOCTL_I915_DESTROY_HEAP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t) 141 + #define DRM_IOCTL_I915_SET_VBLANK_PIPE DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t) 142 + #define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t) 143 143 144 144 /* Allow drivers to submit batchbuffers directly to hardware, relying 145 145 * on the security mechanisms provided by hardware. ··· 227 223 typedef struct drm_i915_mem_destroy_heap { 228 224 int region; 229 225 } drm_i915_mem_destroy_heap_t; 226 + 227 + /* Allow X server to configure which pipes to monitor for vblank signals 228 + */ 229 + #define DRM_I915_VBLANK_PIPE_A 1 230 + #define DRM_I915_VBLANK_PIPE_B 2 231 + 232 + typedef struct drm_i915_vblank_pipe { 233 + int pipe; 234 + } drm_i915_vblank_pipe_t; 230 235 231 236 #endif /* _I915_DRM_H_ */
+5 -1
drivers/char/drm/i915_drv.h
··· 45 45 * 1.2: Add Power Management 46 46 * 1.3: Add vblank support 47 47 * 1.4: Fix cmdbuffer path, add heap destroy 48 + * 1.5: Add vblank pipe configuration 48 49 */ 49 50 #define DRIVER_MAJOR 1 50 - #define DRIVER_MINOR 4 51 + #define DRIVER_MINOR 5 51 52 #define DRIVER_PATCHLEVEL 0 52 53 53 54 typedef struct _drm_i915_ring_buffer { ··· 97 96 int allow_batchbuffer; 98 97 struct mem_block *agp_heap; 99 98 unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; 99 + int vblank_pipe; 100 100 } drm_i915_private_t; 101 101 102 102 extern drm_ioctl_desc_t i915_ioctls[]; ··· 121 119 extern void i915_driver_irq_preinstall(drm_device_t * dev); 122 120 extern void i915_driver_irq_postinstall(drm_device_t * dev); 123 121 extern void i915_driver_irq_uninstall(drm_device_t * dev); 122 + extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS); 123 + extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS); 124 124 125 125 /* i915_mem.c */ 126 126 extern int i915_mem_alloc(DRM_IOCTL_ARGS);
+66 -3
drivers/char/drm/i915_irq.c
··· 44 44 u16 temp; 45 45 46 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 50 DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp); 50 51 ··· 59 58 if (temp & USER_INT_FLAG) 60 59 DRM_WAKEUP(&dev_priv->irq_queue); 61 60 62 - if (temp & VSYNC_PIPEA_FLAG) { 61 + if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) { 63 62 atomic_inc(&dev->vbl_received); 64 63 DRM_WAKEUP(&dev->vbl_queue); 65 64 drm_vbl_send_signals(dev); ··· 183 182 return i915_wait_irq(dev, irqwait.irq_seq); 184 183 } 185 184 185 + static int i915_enable_interrupt (drm_device_t *dev) 186 + { 187 + drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 188 + u16 flag; 189 + 190 + flag = 0; 191 + if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A) 192 + flag |= VSYNC_PIPEA_FLAG; 193 + if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B) 194 + flag |= VSYNC_PIPEB_FLAG; 195 + if (dev_priv->vblank_pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) { 196 + DRM_ERROR("%s called with invalid pipe 0x%x\n", 197 + __FUNCTION__, dev_priv->vblank_pipe); 198 + return DRM_ERR(EINVAL); 199 + } 200 + I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag); 201 + return 0; 202 + } 203 + 204 + /* Set the vblank monitor pipe 205 + */ 206 + int i915_vblank_pipe_set(DRM_IOCTL_ARGS) 207 + { 208 + DRM_DEVICE; 209 + drm_i915_private_t *dev_priv = dev->dev_private; 210 + drm_i915_vblank_pipe_t pipe; 211 + 212 + if (!dev_priv) { 213 + DRM_ERROR("%s called with no initialization\n", __FUNCTION__); 214 + return DRM_ERR(EINVAL); 215 + } 216 + 217 + DRM_COPY_FROM_USER_IOCTL(pipe, (drm_i915_vblank_pipe_t __user *) data, 218 + sizeof(pipe)); 219 + 220 + dev_priv->vblank_pipe = pipe.pipe; 221 + return i915_enable_interrupt (dev); 222 + } 223 + 224 + int i915_vblank_pipe_get(DRM_IOCTL_ARGS) 225 + { 226 + DRM_DEVICE; 227 + drm_i915_private_t *dev_priv = dev->dev_private; 228 + drm_i915_vblank_pipe_t pipe; 229 + u16 flag; 230 + 231 + if (!dev_priv) { 232 + DRM_ERROR("%s called with no initialization\n", __FUNCTION__); 233 + return DRM_ERR(EINVAL); 234 + } 235 + 236 + flag = I915_READ(I915REG_INT_ENABLE_R); 237 + pipe.pipe = 0; 238 + if (flag & VSYNC_PIPEA_FLAG) 239 + pipe.pipe |= DRM_I915_VBLANK_PIPE_A; 240 + if (flag & VSYNC_PIPEB_FLAG) 241 + pipe.pipe |= DRM_I915_VBLANK_PIPE_B; 242 + DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_pipe_t __user *) data, pipe, 243 + sizeof(pipe)); 244 + return 0; 245 + } 246 + 186 247 /* drm_dma.h hooks 187 248 */ 188 249 void i915_driver_irq_preinstall(drm_device_t * dev) ··· 260 197 { 261 198 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 262 199 263 - I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | VSYNC_PIPEA_FLAG); 200 + i915_enable_interrupt(dev); 264 201 DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); 265 202 } 266 203