summary refs log tree commit diff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2014-08-10 04:10:28 +1000
committerBen Skeggs <bskeggs@redhat.com>2014-08-10 05:28:13 +1000
commitf38fdb6a376ead4ce8c6c1c75f71cc35b9e40bfc (patch)
tree21a5a6ecc4d2b3ef3fba629bab1d17bb36f6d7a7 /drivers/gpu
parent95484b57265caa671a57efed06e322d56461774b (diff)
downloadlinux-f38fdb6a376ead4ce8c6c1c75f71cc35b9e40bfc.tar.gz
drm/nouveau/ltc: add zbc drivers
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/ltc.h7
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltc/base.c46
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c20
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltc/gk104.c3
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltc/gm107.c20
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/ltc/priv.h13
6 files changed, 108 insertions, 1 deletions
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/ltc.h b/drivers/gpu/drm/nouveau/core/include/subdev/ltc.h
index de9ac0325c6e..b909a7363f6b 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/ltc.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/ltc.h
@@ -4,6 +4,8 @@
 #include <core/subdev.h>
 #include <core/device.h>
 
+#define NOUVEAU_LTC_MAX_ZBC_CNT 16
+
 struct nouveau_mm_node;
 
 struct nouveau_ltc {
@@ -13,6 +15,11 @@ struct nouveau_ltc {
 	                   struct nouveau_mm_node **);
 	void (*tags_free)(struct nouveau_ltc *, struct nouveau_mm_node **);
 	void (*tags_clear)(struct nouveau_ltc *, u32 first, u32 count);
+
+	int zbc_min;
+	int zbc_max;
+	int (*zbc_color_get)(struct nouveau_ltc *, int index, const u32[4]);
+	int (*zbc_depth_get)(struct nouveau_ltc *, int index, const u32);
 };
 
 static inline struct nouveau_ltc *
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltc/base.c b/drivers/gpu/drm/nouveau/core/subdev/ltc/base.c
index c99bf3f7352f..32ed442c5913 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/ltc/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltc/base.c
@@ -58,6 +58,45 @@ nvkm_ltc_tags_clear(struct nouveau_ltc *ltc, u32 first, u32 count)
 	impl->cbc_wait(priv);
 }
 
+static int
+nvkm_ltc_zbc_color_get(struct nouveau_ltc *ltc, int index, const u32 color[4])
+{
+	const struct nvkm_ltc_impl *impl = (void *)nv_oclass(ltc);
+	struct nvkm_ltc_priv *priv = (void *)ltc;
+	memcpy(priv->zbc_color[index], color, sizeof(priv->zbc_color[index]));
+	impl->zbc_clear_color(priv, index, color);
+	return index;
+}
+
+static int
+nvkm_ltc_zbc_depth_get(struct nouveau_ltc *ltc, int index, const u32 depth)
+{
+	const struct nvkm_ltc_impl *impl = (void *)nv_oclass(ltc);
+	struct nvkm_ltc_priv *priv = (void *)ltc;
+	priv->zbc_depth[index] = depth;
+	impl->zbc_clear_depth(priv, index, depth);
+	return index;
+}
+
+int
+_nvkm_ltc_init(struct nouveau_object *object)
+{
+	const struct nvkm_ltc_impl *impl = (void *)nv_oclass(object);
+	struct nvkm_ltc_priv *priv = (void *)object;
+	int ret, i;
+
+	ret = nouveau_subdev_init(&priv->base.base);
+	if (ret)
+		return ret;
+
+	for (i = priv->base.zbc_min; i <= priv->base.zbc_max; i++) {
+		impl->zbc_clear_color(priv, i, priv->zbc_color[i]);
+		impl->zbc_clear_depth(priv, i, priv->zbc_depth[i]);
+	}
+
+	return 0;
+}
+
 int
 nvkm_ltc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
 		 struct nouveau_oclass *oclass, int length, void **pobject)
@@ -72,9 +111,16 @@ nvkm_ltc_create_(struct nouveau_object *parent, struct nouveau_object *engine,
 	if (ret)
 		return ret;
 
+	memset(priv->zbc_color, 0x00, sizeof(priv->zbc_color));
+	memset(priv->zbc_depth, 0x00, sizeof(priv->zbc_depth));
+
 	priv->base.base.intr = impl->intr;
 	priv->base.tags_alloc = nvkm_ltc_tags_alloc;
 	priv->base.tags_free = nvkm_ltc_tags_free;
 	priv->base.tags_clear = nvkm_ltc_tags_clear;
+	priv->base.zbc_min = 1; /* reserve 0 for disabled */
+	priv->base.zbc_max = min(impl->zbc, NOUVEAU_LTC_MAX_ZBC_CNT) - 1;
+	priv->base.zbc_color_get = nvkm_ltc_zbc_color_get;
+	priv->base.zbc_depth_get = nvkm_ltc_zbc_depth_get;
 	return 0;
 }
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c b/drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c
index f72ab8191d9d..9e00a1ede120 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltc/gf100.c
@@ -45,6 +45,23 @@ gf100_ltc_cbc_wait(struct nvkm_ltc_priv *priv)
 	}
 }
 
+void
+gf100_ltc_zbc_clear_color(struct nvkm_ltc_priv *priv, int i, const u32 color[4])
+{
+	nv_mask(priv, 0x17ea44, 0x0000000f, i);
+	nv_wr32(priv, 0x17ea48, color[0]);
+	nv_wr32(priv, 0x17ea4c, color[1]);
+	nv_wr32(priv, 0x17ea50, color[2]);
+	nv_wr32(priv, 0x17ea54, color[3]);
+}
+
+void
+gf100_ltc_zbc_clear_depth(struct nvkm_ltc_priv *priv, int i, const u32 depth)
+{
+	nv_mask(priv, 0x17ea44, 0x0000000f, i);
+	nv_wr32(priv, 0x17ea58, depth);
+}
+
 static void
 gf100_ltc_lts_isr(struct nvkm_ltc_priv *priv, int ltc, int lts)
 {
@@ -194,4 +211,7 @@ gf100_ltc_oclass = &(struct nvkm_ltc_impl) {
 	.intr = gf100_ltc_intr,
 	.cbc_clear = gf100_ltc_cbc_clear,
 	.cbc_wait = gf100_ltc_cbc_wait,
+	.zbc = 16,
+	.zbc_clear_color = gf100_ltc_zbc_clear_color,
+	.zbc_clear_depth = gf100_ltc_zbc_clear_depth,
 }.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltc/gk104.c b/drivers/gpu/drm/nouveau/core/subdev/ltc/gk104.c
index 063caf791800..ea716569745d 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/ltc/gk104.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltc/gk104.c
@@ -52,4 +52,7 @@ gk104_ltc_oclass = &(struct nvkm_ltc_impl) {
 	.intr = gf100_ltc_intr,
 	.cbc_clear = gf100_ltc_cbc_clear,
 	.cbc_wait = gf100_ltc_cbc_wait,
+	.zbc = 16,
+	.zbc_clear_color = gf100_ltc_zbc_clear_color,
+	.zbc_clear_depth = gf100_ltc_zbc_clear_depth,
 }.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltc/gm107.c b/drivers/gpu/drm/nouveau/core/subdev/ltc/gm107.c
index c05333ebaff2..4761b2e9af00 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/ltc/gm107.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltc/gm107.c
@@ -46,6 +46,23 @@ gm107_ltc_cbc_wait(struct nvkm_ltc_priv *priv)
 }
 
 static void
+gm107_ltc_zbc_clear_color(struct nvkm_ltc_priv *priv, int i, const u32 color[4])
+{
+	nv_mask(priv, 0x17e338, 0x0000000f, i);
+	nv_wr32(priv, 0x17e33c, color[0]);
+	nv_wr32(priv, 0x17e340, color[1]);
+	nv_wr32(priv, 0x17e344, color[2]);
+	nv_wr32(priv, 0x17e348, color[3]);
+}
+
+static void
+gm107_ltc_zbc_clear_depth(struct nvkm_ltc_priv *priv, int i, const u32 depth)
+{
+	nv_mask(priv, 0x17e338, 0x0000000f, i);
+	nv_wr32(priv, 0x17e34c, depth);
+}
+
+static void
 gm107_ltc_lts_isr(struct nvkm_ltc_priv *priv, int ltc, int lts)
 {
 	u32 base = 0x140000 + (ltc * 0x2000) + (lts * 0x400);
@@ -134,4 +151,7 @@ gm107_ltc_oclass = &(struct nvkm_ltc_impl) {
 	.intr = gm107_ltc_intr,
 	.cbc_clear = gm107_ltc_cbc_clear,
 	.cbc_wait = gm107_ltc_cbc_wait,
+	.zbc = 16,
+	.zbc_clear_color = gm107_ltc_zbc_clear_color,
+	.zbc_clear_depth = gm107_ltc_zbc_clear_depth,
 }.base;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/ltc/priv.h b/drivers/gpu/drm/nouveau/core/subdev/ltc/priv.h
index 96d12a220400..594924f39126 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/ltc/priv.h
+++ b/drivers/gpu/drm/nouveau/core/subdev/ltc/priv.h
@@ -8,10 +8,14 @@ struct nvkm_ltc_priv {
 	struct nouveau_ltc base;
 	u32 ltc_nr;
 	u32 lts_nr;
+
 	u32 num_tags;
 	u32 tag_base;
 	struct nouveau_mm tags;
 	struct nouveau_mm_node *tag_ram;
+
+	u32 zbc_color[NOUVEAU_LTC_MAX_ZBC_CNT][4];
+	u32 zbc_depth[NOUVEAU_LTC_MAX_ZBC_CNT];
 };
 
 #define nvkm_ltc_create(p,e,o,d)                                               \
@@ -33,7 +37,7 @@ int  nvkm_ltc_create_(struct nouveau_object *, struct nouveau_object *,
 		      struct nouveau_oclass *, int, void **);
 
 #define _nvkm_ltc_dtor _nouveau_subdev_dtor
-#define _nvkm_ltc_init _nouveau_subdev_init
+int _nvkm_ltc_init(struct nouveau_object *);
 #define _nvkm_ltc_fini _nouveau_subdev_fini
 
 int  gf100_ltc_ctor(struct nouveau_object *, struct nouveau_object *,
@@ -47,12 +51,19 @@ void gf100_ltc_tags_free(struct nouveau_ltc *, struct nouveau_mm_node **);
 struct nvkm_ltc_impl {
 	struct nouveau_oclass base;
 	void (*intr)(struct nouveau_subdev *);
+
 	void (*cbc_clear)(struct nvkm_ltc_priv *, u32 start, u32 limit);
 	void (*cbc_wait)(struct nvkm_ltc_priv *);
+
+	int zbc;
+	void (*zbc_clear_color)(struct nvkm_ltc_priv *, int, const u32[4]);
+	void (*zbc_clear_depth)(struct nvkm_ltc_priv *, int, const u32);
 };
 
 void gf100_ltc_intr(struct nouveau_subdev *);
 void gf100_ltc_cbc_clear(struct nvkm_ltc_priv *, u32, u32);
 void gf100_ltc_cbc_wait(struct nvkm_ltc_priv *);
+void gf100_ltc_zbc_clear_color(struct nvkm_ltc_priv *, int, const u32[4]);
+void gf100_ltc_zbc_clear_depth(struct nvkm_ltc_priv *, int, const u32);
 
 #endif