From fd3a5225864cfa51633c0b4eff145b92e8b4ba1c Mon Sep 17 00:00:00 2001
From: Ben Skeggs <bskeggs@redhat.com>
Date: Fri, 12 Oct 2012 11:24:39 +1000
Subject: [PATCH] drm/nv20/fb: fixup compression tag allocation size

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
---
 .../gpu/drm/nouveau/core/include/subdev/fb.h  |  2 ++
 drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c | 24 +++++++------------
 drivers/gpu/drm/nouveau/core/subdev/fb/nv25.c | 21 +++++-----------
 3 files changed, 17 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h
index 863709371861f..aa13f6b2d8ebf 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/fb.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/fb.h
@@ -69,7 +69,9 @@ struct nouveau_fb {
 		} type;
 		u64 stolen;
 		u64 size;
+
 		int ranks;
+		int parts;
 
 		int  (*init)(struct nouveau_fb *);
 		int  (*get)(struct nouveau_fb *, u64 size, u32 align,
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c
index d26adee63c1ef..5d14612a2c8ea 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv20.c
@@ -41,7 +41,8 @@ nv20_fb_vram_init(struct nouveau_fb *pfb)
 	case 0x00000200: pfb->ram.type = NV_MEM_TYPE_GDDR3; break;
 	case 0x00000300: pfb->ram.type = NV_MEM_TYPE_GDDR2; break;
 	}
-	pfb->ram.size = nv_rd32(pfb, 0x10020c) & 0xff000000;
+	pfb->ram.size  = (nv_rd32(pfb, 0x10020c) & 0xff000000);
+	pfb->ram.parts = (nv_rd32(pfb, 0x100200) & 0x00000003) + 1;
 
 	return nv_rd32(pfb, 0x100320);
 }
@@ -63,20 +64,13 @@ static void
 nv20_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,
 		  struct nouveau_fb_tile *tile)
 {
-	int bpp = (flags & 2) ? 32 : 16;
-
-	/* Allocate some of the on-die tag memory, used to store Z
-	 * compression meta-data (most likely just a bitmap determining
-	 * if a given tile is compressed or not).
-	 */
-	size /= 256;
-
-	if (!nouveau_mm_head(&pfb->tags, 1, size, size, 1, &tile->tag)) {
-		/* Enable Z compression */
-		tile->zcomp = tile->tag->offset;
-		tile->zcomp |= 0x80000000;
-		if (bpp != 16)
-			tile->zcomp |= 0x04000000;
+	u32 tiles = DIV_ROUND_UP(size, 0x40);
+	u32 tags  = round_up(tiles / pfb->ram.parts, 0x40);
+	if (!nouveau_mm_head(&pfb->tags, 1, tags, tags, 1, &tile->tag)) {
+		if (!(flags & 2)) tile->zcomp = 0x00000000; /* Z16 */
+		else              tile->zcomp = 0x04000000; /* Z24S8 */
+		tile->zcomp |= tile->tag->offset;
+		tile->zcomp |= 0x80000000; /* enable */
 #ifdef __BIG_ENDIAN
 		tile->zcomp |= 0x08000000;
 #endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv25.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv25.c
index b6858ca6de863..0042ace6bef99 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv25.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv25.c
@@ -34,21 +34,12 @@ static void
 nv25_fb_tile_comp(struct nouveau_fb *pfb, int i, u32 size, u32 flags,
 		  struct nouveau_fb_tile *tile)
 {
-	int bpp = (flags & 2) ? 32 : 16;
-
-	/* Allocate some of the on-die tag memory, used to store Z
-	 * compression meta-data (most likely just a bitmap determining
-	 * if a given tile is compressed or not).
-	 */
-	size /= 256;
-
-	if (!nouveau_mm_head(&pfb->tags, 1, size, size, 1, &tile->tag)) {
-		/* Enable Z compression */
-		tile->zcomp = tile->tag->offset;
-		if (bpp == 16)
-			tile->zcomp |= 0x00100000;
-		else
-			tile->zcomp |= 0x00200000;
+	u32 tiles = DIV_ROUND_UP(size, 0x40);
+	u32 tags  = round_up(tiles / pfb->ram.parts, 0x40);
+	if (!nouveau_mm_head(&pfb->tags, 1, tags, tags, 1, &tile->tag)) {
+		if (!(flags & 2)) tile->zcomp = 0x00100000; /* Z16 */
+		else              tile->zcomp = 0x00200000; /* Z24S8 */
+		tile->zcomp |= tile->tag->offset;
 #ifdef __BIG_ENDIAN
 		tile->zcomp |= 0x01000000;
 #endif
-- 
2.30.2