Эх сурвалжийг харах

Merge branch 'drm-patches' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6

* 'drm-patches' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6:
  drm: radeon constify radeon microcode
  Add i915 ioctls to configure pipes for vblank interrupt.
  drm: update radeon to 1.25 add r200 vertex program support
  drm: radeon add a tcl state flush before accessing tcl vector space
Linus Torvalds 19 жил өмнө
parent
commit
abb1cf3cb9

+ 3 - 1
drivers/char/drm/i915_dma.c

@@ -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_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_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);

+ 13 - 0
drivers/char/drm/i915_drm.h

@@ -124,6 +124,8 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_INIT_HEAP	0x0a
 #define DRM_I915_CMDBUFFER	0x0b
 #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_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_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_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
  * on the security mechanisms provided by hardware.
@@ -224,4 +228,13 @@ typedef struct drm_i915_mem_destroy_heap {
 	int region;
 } 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_ */

+ 5 - 1
drivers/char/drm/i915_drv.h

@@ -45,9 +45,10 @@
  * 1.2: Add Power Management
  * 1.3: Add vblank support
  * 1.4: Fix cmdbuffer path, add heap destroy
+ * 1.5: Add vblank pipe configuration
  */
 #define DRIVER_MAJOR		1
-#define DRIVER_MINOR		4
+#define DRIVER_MINOR		5
 #define DRIVER_PATCHLEVEL	0
 
 typedef struct _drm_i915_ring_buffer {
@@ -96,6 +97,7 @@ typedef struct drm_i915_private {
 	int allow_batchbuffer;
 	struct mem_block *agp_heap;
 	unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
+	int vblank_pipe;
 } drm_i915_private_t;
 
 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_postinstall(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 */
 extern int i915_mem_alloc(DRM_IOCTL_ARGS);

+ 66 - 3
drivers/char/drm/i915_irq.c

@@ -44,7 +44,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 	u16 temp;
 
 	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);
 
@@ -58,7 +59,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 	if (temp & USER_INT_FLAG)
 		DRM_WAKEUP(&dev_priv->irq_queue);
 
-	if (temp & VSYNC_PIPEA_FLAG) {
+	if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
 		atomic_inc(&dev->vbl_received);
 		DRM_WAKEUP(&dev->vbl_queue);
 		drm_vbl_send_signals(dev);
@@ -182,6 +183,68 @@ int i915_irq_wait(DRM_IOCTL_ARGS)
 	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
 */
 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;
 
-	I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | VSYNC_PIPEA_FLAG);
+	i915_enable_interrupt(dev);
 	DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
 }
 

+ 3 - 3
drivers/char/drm/radeon_cp.c

@@ -39,7 +39,7 @@
 static int radeon_do_cleanup_cp(drm_device_t * dev);
 
 /* CP microcode (from ATI) */
-static u32 R200_cp_microcode[][2] = {
+static const u32 R200_cp_microcode[][2] = {
 	{0x21007000, 0000000000},
 	{0x20007000, 0000000000},
 	{0x000000ab, 0x00000004},
@@ -298,7 +298,7 @@ static u32 R200_cp_microcode[][2] = {
 	{0000000000, 0000000000},
 };
 
-static u32 radeon_cp_microcode[][2] = {
+static const u32 radeon_cp_microcode[][2] = {
 	{0x21007000, 0000000000},
 	{0x20007000, 0000000000},
 	{0x000000b4, 0x00000004},
@@ -557,7 +557,7 @@ static u32 radeon_cp_microcode[][2] = {
 	{0000000000, 0000000000},
 };
 
-static u32 R300_cp_microcode[][2] = {
+static const u32 R300_cp_microcode[][2] = {
 	{0x4200e000, 0000000000},
 	{0x4000e000, 0000000000},
 	{0x000000af, 0x00000008},

+ 6 - 1
drivers/char/drm/radeon_drm.h

@@ -161,7 +161,8 @@
 #define R200_EMIT_PP_TXCTLALL_3                     91
 #define R200_EMIT_PP_TXCTLALL_4                     92
 #define R200_EMIT_PP_TXCTLALL_5                     93
-#define RADEON_MAX_STATE_PACKETS                    94
+#define R200_EMIT_VAP_PVS_CNTL                      94
+#define RADEON_MAX_STATE_PACKETS                    95
 
 /* Commands understood by cmd_buffer ioctl.  More can be added but
  * obviously these can't be removed or changed:
@@ -176,6 +177,7 @@
 #define RADEON_CMD_WAIT         8	/* emit hw wait commands -- note:
 					 *  doesn't make the cpu wait, just
 					 *  the graphics hardware */
+#define RADEON_CMD_VECLINEAR	9       /* another r200 stopgap */
 
 typedef union {
 	int i;
@@ -191,6 +193,9 @@ typedef union {
 	struct {
 		unsigned char cmd_type, offset, stride, count;
 	} vectors;
+	struct {
+		unsigned char cmd_type, addr_lo, addr_hi, count;
+	} veclinear;
 	struct {
 		unsigned char cmd_type, buf_idx, pad0, pad1;
 	} dma;

+ 8 - 2
drivers/char/drm/radeon_drv.h

@@ -38,7 +38,7 @@
 
 #define DRIVER_NAME		"radeon"
 #define DRIVER_DESC		"ATI Radeon"
-#define DRIVER_DATE		"20060225"
+#define DRIVER_DATE		"20060524"
 
 /* Interface history:
  *
@@ -93,9 +93,11 @@
  * 1.22- Add support for texture cache flushes (R300_TX_CNTL)
  * 1.23- Add new radeon memory map work from benh
  * 1.24- Add general-purpose packet for manipulating scratch registers (r300)
+ * 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL,
+ *       new packet type)
  */
 #define DRIVER_MAJOR		1
-#define DRIVER_MINOR		24
+#define DRIVER_MINOR		25
 #define DRIVER_PATCHLEVEL	0
 
 /*
@@ -884,6 +886,8 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
 #define RADEON_PP_CUBIC_OFFSET_T1_0         0x1e00
 #define RADEON_PP_CUBIC_OFFSET_T2_0         0x1e14
 
+#define RADEON_SE_TCL_STATE_FLUSH           0x2284
+
 #define SE_VAP_CNTL__TCL_ENA_MASK                          0x00000001
 #define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK                   0x00010000
 #define SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT                 0x00000012
@@ -905,6 +909,8 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp,
 #define R200_PP_AFS_0                     0x2f80
 #define R200_PP_AFS_1                     0x2f00	/* same as txcblend_0 */
 
+#define R200_VAP_PVS_CNTL_1               0x22D0
+
 /* Constants */
 #define RADEON_MAX_USEC_TIMEOUT		100000	/* 100 ms */
 

+ 38 - 1
drivers/char/drm/radeon_state.c

@@ -249,6 +249,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t *
 	case R200_EMIT_PP_TXCTLALL_3:
 	case R200_EMIT_PP_TXCTLALL_4:
 	case R200_EMIT_PP_TXCTLALL_5:
+	case R200_EMIT_VAP_PVS_CNTL:
 		/* These packets don't contain memory offsets */
 		break;
 
@@ -626,6 +627,7 @@ static struct {
 	{R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"},
 	{R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"},
 	{R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"},
+	{R200_VAP_PVS_CNTL_1, 2, "R200_VAP_PVS_CNTL"},
 };
 
 /* ================================================================
@@ -2595,7 +2597,8 @@ static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv,
 	int stride = header.vectors.stride;
 	RING_LOCALS;
 
-	BEGIN_RING(3 + sz);
+	BEGIN_RING(5 + sz);
+	OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
 	OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
 	OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
 	OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
@@ -2607,6 +2610,32 @@ static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv,
 	return 0;
 }
 
+static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv,
+					  drm_radeon_cmd_header_t header,
+					  drm_radeon_kcmd_buffer_t *cmdbuf)
+{
+	int sz = header.veclinear.count * 4;
+	int start = header.veclinear.addr_lo | (header.veclinear.addr_hi << 8);
+	RING_LOCALS;
+
+        if (!sz)
+                return 0;
+        if (sz * 4 > cmdbuf->bufsz)
+                return DRM_ERR(EINVAL);
+
+	BEGIN_RING(5 + sz);
+	OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0);
+	OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0));
+	OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
+	OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1)));
+	OUT_RING_TABLE(cmdbuf->buf, sz);
+	ADVANCE_RING();
+
+	cmdbuf->buf += sz * sizeof(int);
+	cmdbuf->bufsz -= sz * sizeof(int);
+	return 0;
+}
+
 static int radeon_emit_packet3(drm_device_t * dev,
 			       drm_file_t * filp_priv,
 			       drm_radeon_kcmd_buffer_t *cmdbuf)
@@ -2865,6 +2894,14 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS)
 				goto err;
 			}
 			break;
+		case RADEON_CMD_VECLINEAR:
+			DRM_DEBUG("RADEON_CMD_VECLINEAR\n");
+			if (radeon_emit_veclinear(dev_priv, header, &cmdbuf)) {
+				DRM_ERROR("radeon_emit_veclinear failed\n");
+				goto err;
+			}
+			break;
+
 		default:
 			DRM_ERROR("bad cmd_type %d at %p\n",
 				  header.header.cmd_type,