drm/radeon: add basic zmask/hiz support (v4)

This interface allows userspace to request hyperz support, it probably
needs more locking, and really reporting that you can have hyperz is racy
since someone else might get it before you do.

v2: modify so we pass 0 valued packets to let DDX/r300c keep working.
also fixed incorrect 0x4f1c reference.

v3: fixup zb_bw_cntl so older drivers keep working

v4: add locking, fixup SC_HYPERZ_EN - patch stream to disable hiz

Signed-off-by: Dave Airlie <airlied@redhat.com>
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 4c48df4..e817a0b 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -1803,6 +1803,11 @@
 			return r;
 		break;
 		/* triggers drawing using indices to vertex buffer */
+	case PACKET3_3D_CLEAR_HIZ:
+	case PACKET3_3D_CLEAR_ZMASK:
+		if (p->rdev->hyperz_filp != p->filp)
+			return -EINVAL;
+		break;
 	case PACKET3_NOP:
 		break;
 	default:
diff --git a/drivers/gpu/drm/radeon/r100d.h b/drivers/gpu/drm/radeon/r100d.h
index d016b16..b121b6c 100644
--- a/drivers/gpu/drm/radeon/r100d.h
+++ b/drivers/gpu/drm/radeon/r100d.h
@@ -48,10 +48,12 @@
 #define		PACKET3_3D_DRAW_IMMD		0x29
 #define		PACKET3_3D_DRAW_INDX		0x2A
 #define		PACKET3_3D_LOAD_VBPNTR		0x2F
+#define		PACKET3_3D_CLEAR_ZMASK		0x32
 #define		PACKET3_INDX_BUFFER		0x33
 #define		PACKET3_3D_DRAW_VBUF_2		0x34
 #define		PACKET3_3D_DRAW_IMMD_2		0x35
 #define		PACKET3_3D_DRAW_INDX_2		0x36
+#define		PACKET3_3D_CLEAR_HIZ		0x37
 #define		PACKET3_BITBLT_MULTI		0x9B
 
 #define PACKET0(reg, n)	(CP_PACKET0 |					\
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c
index 58eab5d4..c827738 100644
--- a/drivers/gpu/drm/radeon/r300.c
+++ b/drivers/gpu/drm/radeon/r300.c
@@ -1048,14 +1048,47 @@
 		/* RB3D_COLOR_CHANNEL_MASK */
 		track->color_channel_mask = idx_value;
 		break;
-	case 0x4d1c:
+	case 0x43a4:
+		/* SC_HYPERZ_EN */
+		/* r300c emits this register - we need to disable hyperz for it
+		 * without complaining */
+		if (p->rdev->hyperz_filp != p->filp) {
+			if (idx_value & 0x1)
+				ib[idx] = idx_value & ~1;
+		}
+		break;
+	case 0x4f1c:
 		/* ZB_BW_CNTL */
 		track->zb_cb_clear = !!(idx_value & (1 << 5));
+		if (p->rdev->hyperz_filp != p->filp) {
+			if (idx_value & (R300_HIZ_ENABLE |
+					 R300_RD_COMP_ENABLE |
+					 R300_WR_COMP_ENABLE |
+					 R300_FAST_FILL_ENABLE))
+				goto fail;
+		}
 		break;
 	case 0x4e04:
 		/* RB3D_BLENDCNTL */
 		track->blend_read_enable = !!(idx_value & (1 << 2));
 		break;
+	case 0x4f28: /* ZB_DEPTHCLEARVALUE */
+		break;
+	case 0x4f30: /* ZB_MASK_OFFSET */
+	case 0x4f34: /* ZB_ZMASK_PITCH */
+	case 0x4f44: /* ZB_HIZ_OFFSET */
+	case 0x4f54: /* ZB_HIZ_PITCH */
+		if (idx_value && (p->rdev->hyperz_filp != p->filp))
+			goto fail;
+		break;
+	case 0x4028:
+		if (idx_value && (p->rdev->hyperz_filp != p->filp))
+			goto fail;
+		/* GB_Z_PEQ_CONFIG */
+		if (p->rdev->family >= CHIP_RV350)
+			break;
+		goto fail;
+		break;
 	case 0x4be8:
 		/* valid register only on RV530 */
 		if (p->rdev->family == CHIP_RV530)
@@ -1066,8 +1099,8 @@
 	}
 	return 0;
 fail:
-	printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
-	       reg, idx);
+	printk(KERN_ERR "Forbidden register 0x%04X in cs at %d (val=%08x)\n",
+	       reg, idx, idx_value);
 	return -EINVAL;
 }
 
@@ -1161,6 +1194,11 @@
 			return r;
 		}
 		break;
+	case PACKET3_3D_CLEAR_HIZ:
+	case PACKET3_3D_CLEAR_ZMASK:
+		if (p->rdev->hyperz_filp != p->filp)
+			return -EINVAL;
+		break;
 	case PACKET3_NOP:
 		break;
 	default:
diff --git a/drivers/gpu/drm/radeon/r300d.h b/drivers/gpu/drm/radeon/r300d.h
index 968a333..0c036c6 100644
--- a/drivers/gpu/drm/radeon/r300d.h
+++ b/drivers/gpu/drm/radeon/r300d.h
@@ -48,10 +48,12 @@
 #define		PACKET3_3D_DRAW_IMMD		0x29
 #define		PACKET3_3D_DRAW_INDX		0x2A
 #define		PACKET3_3D_LOAD_VBPNTR		0x2F
+#define		PACKET3_3D_CLEAR_ZMASK		0x32
 #define		PACKET3_INDX_BUFFER		0x33
 #define		PACKET3_3D_DRAW_VBUF_2		0x34
 #define		PACKET3_3D_DRAW_IMMD_2		0x35
 #define		PACKET3_3D_DRAW_INDX_2		0x36
+#define		PACKET3_3D_CLEAR_HIZ		0x37
 #define		PACKET3_BITBLT_MULTI		0x9B
 
 #define PACKET0(reg, n)	(CP_PACKET0 |					\
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index c84f9a3..368fecf0 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -1098,6 +1098,8 @@
 
 	bool powered_down;
 	struct notifier_block acpi_nb;
+	/* only one userspace can use Hyperz features at a time */
+	struct drm_file *hyperz_filp;
 };
 
 int radeon_device_init(struct radeon_device *rdev,
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 6f8a2e5..795403b 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -46,7 +46,7 @@
  * - 2.3.0 - add MSPOS + 3D texture + r500 VAP regs
  * - 2.4.0 - add crtc id query
  * - 2.5.0 - add get accel 2 to work around ddx breakage for evergreen
- * - 2.6.0 - add tiling config query (r6xx+)
+ * - 2.6.0 - add tiling config query (r6xx+), add initial HiZ support (r300->r500)
  */
 #define KMS_DRIVER_MAJOR	2
 #define KMS_DRIVER_MINOR	6
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index dd0a78e9..e5b7054 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -159,6 +159,15 @@
 			DRM_DEBUG_KMS("tiling config is r6xx+ only!\n");
 			return -EINVAL;
 		}
+	case RADEON_INFO_WANT_HYPERZ:
+		mutex_lock(&dev->struct_mutex);
+		if (rdev->hyperz_filp)
+			value = 0;
+		else {
+			rdev->hyperz_filp = filp;
+			value = 1;
+		}
+		mutex_unlock(&dev->struct_mutex);
 		break;
 	default:
 		DRM_DEBUG_KMS("Invalid request %d\n", info->request);
@@ -199,9 +208,11 @@
 void radeon_driver_preclose_kms(struct drm_device *dev,
 				struct drm_file *file_priv)
 {
+	struct radeon_device *rdev = dev->dev_private;
+	if (rdev->hyperz_filp == file_priv)
+		rdev->hyperz_filp = NULL;
 }
 
-
 /*
  * VBlank related functions.
  */
diff --git a/drivers/gpu/drm/radeon/reg_srcs/r300 b/drivers/gpu/drm/radeon/reg_srcs/r300
index 1e97b2d..b506ec1 100644
--- a/drivers/gpu/drm/radeon/reg_srcs/r300
+++ b/drivers/gpu/drm/radeon/reg_srcs/r300
@@ -187,7 +187,6 @@
 0x4364 RS_INST_13
 0x4368 RS_INST_14
 0x436C RS_INST_15
-0x43A4 SC_HYPERZ_EN
 0x43A8 SC_EDGERULE
 0x43B0 SC_CLIP_0_A
 0x43B4 SC_CLIP_0_B
@@ -716,16 +715,4 @@
 0x4F08 ZB_STENCILREFMASK
 0x4F14 ZB_ZTOP
 0x4F18 ZB_ZCACHE_CTLSTAT
-0x4F1C ZB_BW_CNTL
-0x4F28 ZB_DEPTHCLEARVALUE
-0x4F30 ZB_ZMASK_OFFSET
-0x4F34 ZB_ZMASK_PITCH
-0x4F38 ZB_ZMASK_WRINDEX
-0x4F3C ZB_ZMASK_DWORD
-0x4F40 ZB_ZMASK_RDINDEX
-0x4F44 ZB_HIZ_OFFSET
-0x4F48 ZB_HIZ_WRINDEX
-0x4F4C ZB_HIZ_DWORD
-0x4F50 ZB_HIZ_RDINDEX
-0x4F54 ZB_HIZ_PITCH
 0x4F58 ZB_ZPASS_DATA
diff --git a/drivers/gpu/drm/radeon/reg_srcs/r420 b/drivers/gpu/drm/radeon/reg_srcs/r420
index e958980..8c1214c 100644
--- a/drivers/gpu/drm/radeon/reg_srcs/r420
+++ b/drivers/gpu/drm/radeon/reg_srcs/r420
@@ -130,6 +130,7 @@
 0x401C GB_SELECT
 0x4020 GB_AA_CONFIG
 0x4024 GB_FIFO_SIZE
+0x4028 GB_Z_PEQ_CONFIG
 0x4100 TX_INVALTAGS
 0x4200 GA_POINT_S0
 0x4204 GA_POINT_T0
@@ -187,7 +188,6 @@
 0x4364 RS_INST_13
 0x4368 RS_INST_14
 0x436C RS_INST_15
-0x43A4 SC_HYPERZ_EN
 0x43A8 SC_EDGERULE
 0x43B0 SC_CLIP_0_A
 0x43B4 SC_CLIP_0_B
@@ -782,16 +782,4 @@
 0x4F08 ZB_STENCILREFMASK
 0x4F14 ZB_ZTOP
 0x4F18 ZB_ZCACHE_CTLSTAT
-0x4F1C ZB_BW_CNTL
-0x4F28 ZB_DEPTHCLEARVALUE
-0x4F30 ZB_ZMASK_OFFSET
-0x4F34 ZB_ZMASK_PITCH
-0x4F38 ZB_ZMASK_WRINDEX
-0x4F3C ZB_ZMASK_DWORD
-0x4F40 ZB_ZMASK_RDINDEX
-0x4F44 ZB_HIZ_OFFSET
-0x4F48 ZB_HIZ_WRINDEX
-0x4F4C ZB_HIZ_DWORD
-0x4F50 ZB_HIZ_RDINDEX
-0x4F54 ZB_HIZ_PITCH
 0x4F58 ZB_ZPASS_DATA
diff --git a/drivers/gpu/drm/radeon/reg_srcs/rs600 b/drivers/gpu/drm/radeon/reg_srcs/rs600
index 83e8bc0..0828d80 100644
--- a/drivers/gpu/drm/radeon/reg_srcs/rs600
+++ b/drivers/gpu/drm/radeon/reg_srcs/rs600
@@ -187,7 +187,6 @@
 0x4364 RS_INST_13
 0x4368 RS_INST_14
 0x436C RS_INST_15
-0x43A4 SC_HYPERZ_EN
 0x43A8 SC_EDGERULE
 0x43B0 SC_CLIP_0_A
 0x43B4 SC_CLIP_0_B
@@ -782,16 +781,4 @@
 0x4F08 ZB_STENCILREFMASK
 0x4F14 ZB_ZTOP
 0x4F18 ZB_ZCACHE_CTLSTAT
-0x4F1C ZB_BW_CNTL
-0x4F28 ZB_DEPTHCLEARVALUE
-0x4F30 ZB_ZMASK_OFFSET
-0x4F34 ZB_ZMASK_PITCH
-0x4F38 ZB_ZMASK_WRINDEX
-0x4F3C ZB_ZMASK_DWORD
-0x4F40 ZB_ZMASK_RDINDEX
-0x4F44 ZB_HIZ_OFFSET
-0x4F48 ZB_HIZ_WRINDEX
-0x4F4C ZB_HIZ_DWORD
-0x4F50 ZB_HIZ_RDINDEX
-0x4F54 ZB_HIZ_PITCH
 0x4F58 ZB_ZPASS_DATA
diff --git a/drivers/gpu/drm/radeon/reg_srcs/rv515 b/drivers/gpu/drm/radeon/reg_srcs/rv515
index 1e46233..8293855 100644
--- a/drivers/gpu/drm/radeon/reg_srcs/rv515
+++ b/drivers/gpu/drm/radeon/reg_srcs/rv515
@@ -235,7 +235,6 @@
 0x4354 RS_INST_13
 0x4358 RS_INST_14
 0x435C RS_INST_15
-0x43A4 SC_HYPERZ_EN
 0x43A8 SC_EDGERULE
 0x43B0 SC_CLIP_0_A
 0x43B4 SC_CLIP_0_B
@@ -479,17 +478,5 @@
 0x4F08 ZB_STENCILREFMASK
 0x4F14 ZB_ZTOP
 0x4F18 ZB_ZCACHE_CTLSTAT
-0x4F1C ZB_BW_CNTL
-0x4F28 ZB_DEPTHCLEARVALUE
-0x4F30 ZB_ZMASK_OFFSET
-0x4F34 ZB_ZMASK_PITCH
-0x4F38 ZB_ZMASK_WRINDEX
-0x4F3C ZB_ZMASK_DWORD
-0x4F40 ZB_ZMASK_RDINDEX
-0x4F44 ZB_HIZ_OFFSET
-0x4F48 ZB_HIZ_WRINDEX
-0x4F4C ZB_HIZ_DWORD
-0x4F50 ZB_HIZ_RDINDEX
-0x4F54 ZB_HIZ_PITCH
 0x4F58 ZB_ZPASS_DATA
 0x4FD4 ZB_STENCILREFMASK_BF
diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h
index ac5f040..0acaf8f 100644
--- a/include/drm/radeon_drm.h
+++ b/include/drm/radeon_drm.h
@@ -905,6 +905,7 @@
 #define RADEON_INFO_CRTC_FROM_ID	0x04
 #define RADEON_INFO_ACCEL_WORKING2	0x05
 #define RADEON_INFO_TILING_CONFIG	0x06
+#define RADEON_INFO_WANT_HYPERZ		0x07
 
 struct drm_radeon_info {
 	uint32_t		request;