Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 702880f2 authored by Dave Airlie's avatar Dave Airlie
Browse files

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: default avatarDave Airlie <airlied@linux.ie>
parent d6fece05
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -758,7 +758,9 @@ drm_ioctl_desc_t i915_ioctls[] = {
	[DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH},
	[DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH},
	[DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
	[DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY},
	[DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH},
	[DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH},
	[DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }
	[DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
	[DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] = { i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY },
	[DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get, DRM_AUTH },
};
};


int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
+13 −0
Original line number Original line Diff line number Diff line
@@ -124,6 +124,8 @@ typedef struct _drm_i915_sarea {
#define DRM_I915_INIT_HEAP	0x0a
#define DRM_I915_INIT_HEAP	0x0a
#define DRM_I915_CMDBUFFER	0x0b
#define DRM_I915_CMDBUFFER	0x0b
#define DRM_I915_DESTROY_HEAP	0x0c
#define DRM_I915_DESTROY_HEAP	0x0c
#define DRM_I915_SET_VBLANK_PIPE	0x0d
#define DRM_I915_GET_VBLANK_PIPE	0x0e


#define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
#define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
#define DRM_IOCTL_I915_FLUSH		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
#define DRM_IOCTL_I915_FLUSH		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -138,6 +140,8 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_INIT_HEAP        DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t)
#define DRM_IOCTL_I915_INIT_HEAP        DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT_HEAP, drm_i915_mem_init_heap_t)
#define DRM_IOCTL_I915_CMDBUFFER	DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t)
#define DRM_IOCTL_I915_CMDBUFFER	DRM_IOW( DRM_COMMAND_BASE + DRM_I915_CMDBUFFER, drm_i915_cmdbuffer_t)
#define DRM_IOCTL_I915_DESTROY_HEAP	DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t)
#define DRM_IOCTL_I915_DESTROY_HEAP	DRM_IOW( DRM_COMMAND_BASE + DRM_I915_DESTROY_HEAP, drm_i915_mem_destroy_heap_t)
#define DRM_IOCTL_I915_SET_VBLANK_PIPE	DRM_IOW( DRM_COMMAND_BASE + DRM_I915_SET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
#define DRM_IOCTL_I915_GET_VBLANK_PIPE	DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)


/* Allow drivers to submit batchbuffers directly to hardware, relying
/* Allow drivers to submit batchbuffers directly to hardware, relying
 * on the security mechanisms provided by hardware.
 * on the security mechanisms provided by hardware.
@@ -224,4 +228,13 @@ typedef struct drm_i915_mem_destroy_heap {
	int region;
	int region;
} drm_i915_mem_destroy_heap_t;
} drm_i915_mem_destroy_heap_t;


/* Allow X server to configure which pipes to monitor for vblank signals
 */
#define	DRM_I915_VBLANK_PIPE_A	1
#define	DRM_I915_VBLANK_PIPE_B	2

typedef struct drm_i915_vblank_pipe {
	int pipe;
} drm_i915_vblank_pipe_t;

#endif				/* _I915_DRM_H_ */
#endif				/* _I915_DRM_H_ */
+5 −1
Original line number Original line Diff line number Diff line
@@ -45,9 +45,10 @@
 * 1.2: Add Power Management
 * 1.2: Add Power Management
 * 1.3: Add vblank support
 * 1.3: Add vblank support
 * 1.4: Fix cmdbuffer path, add heap destroy
 * 1.4: Fix cmdbuffer path, add heap destroy
 * 1.5: Add vblank pipe configuration
 */
 */
#define DRIVER_MAJOR		1
#define DRIVER_MAJOR		1
#define DRIVER_MINOR		4
#define DRIVER_MINOR		5
#define DRIVER_PATCHLEVEL	0
#define DRIVER_PATCHLEVEL	0


typedef struct _drm_i915_ring_buffer {
typedef struct _drm_i915_ring_buffer {
@@ -96,6 +97,7 @@ typedef struct drm_i915_private {
	int allow_batchbuffer;
	int allow_batchbuffer;
	struct mem_block *agp_heap;
	struct mem_block *agp_heap;
	unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
	unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
	int vblank_pipe;
} drm_i915_private_t;
} drm_i915_private_t;


extern drm_ioctl_desc_t i915_ioctls[];
extern drm_ioctl_desc_t i915_ioctls[];
@@ -119,6 +121,8 @@ extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
extern void i915_driver_irq_preinstall(drm_device_t * dev);
extern void i915_driver_irq_preinstall(drm_device_t * dev);
extern void i915_driver_irq_postinstall(drm_device_t * dev);
extern void i915_driver_irq_postinstall(drm_device_t * dev);
extern void i915_driver_irq_uninstall(drm_device_t * dev);
extern void i915_driver_irq_uninstall(drm_device_t * dev);
extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS);
extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS);


/* i915_mem.c */
/* i915_mem.c */
extern int i915_mem_alloc(DRM_IOCTL_ARGS);
extern int i915_mem_alloc(DRM_IOCTL_ARGS);
+66 −3
Original line number Original line Diff line number Diff line
@@ -44,7 +44,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
	u16 temp;
	u16 temp;


	temp = I915_READ16(I915REG_INT_IDENTITY_R);
	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);
	DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);


@@ -58,7 +59,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
	if (temp & USER_INT_FLAG)
	if (temp & USER_INT_FLAG)
		DRM_WAKEUP(&dev_priv->irq_queue);
		DRM_WAKEUP(&dev_priv->irq_queue);


	if (temp & VSYNC_PIPEA_FLAG) {
	if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
		atomic_inc(&dev->vbl_received);
		atomic_inc(&dev->vbl_received);
		DRM_WAKEUP(&dev->vbl_queue);
		DRM_WAKEUP(&dev->vbl_queue);
		drm_vbl_send_signals(dev);
		drm_vbl_send_signals(dev);
@@ -182,6 +183,68 @@ int i915_irq_wait(DRM_IOCTL_ARGS)
	return i915_wait_irq(dev, irqwait.irq_seq);
	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
/* drm_dma.h hooks
*/
*/
void i915_driver_irq_preinstall(drm_device_t * dev)
void i915_driver_irq_preinstall(drm_device_t * dev)
@@ -197,7 +260,7 @@ void i915_driver_irq_postinstall(drm_device_t * dev)
{
{
	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
	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);
	DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
}
}