drm/nv04-nv40/instmem: duplicate nv04 code as nv40, remove alternate paths

A ton of duplication for the moment, will go away when they become subdevs.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile
index 5e18a53..68043a40 100644
--- a/drivers/gpu/drm/nouveau/Makefile
+++ b/drivers/gpu/drm/nouveau/Makefile
@@ -67,6 +67,7 @@
 nouveau-y += core/subdev/i2c/aux.o
 nouveau-y += core/subdev/i2c/bit.o
 nouveau-y += core/subdev/instmem/nv04.o
+nouveau-y += core/subdev/instmem/nv40.o
 nouveau-y += core/subdev/instmem/nv50.o
 nouveau-y += core/subdev/instmem/nvc0.o
 nouveau-y += core/subdev/ltcg/nvc0.o
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c
index f01063c..8265ca8 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.c
@@ -11,9 +11,6 @@
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 
-	if (dev_priv->chipset >= 0x40)
-		return 128 * 32;
-	else
 	if (dev_priv->chipset >= 0x17)
 		return 64 * 32;
 	else
@@ -32,27 +29,7 @@
 
 	/* RAMIN always available */
 	dev_priv->ramin_available = true;
-
-	/* Reserve space at end of VRAM for PRAMIN */
-	if (dev_priv->card_type >= NV_40) {
-		u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8);
-		u32 rsvd;
-
-		/* estimate grctx size, the magics come from nv40_grctx.c */
-		if      (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs;
-		else if (dev_priv->chipset  < 0x43) rsvd = 0x4f00 * vs;
-		else if (nv44_graph_class(dev))	    rsvd = 0x4980 * vs;
-		else				    rsvd = 0x4a40 * vs;
-		rsvd += 16 * 1024;
-		rsvd *= 32; /* per-channel */
-
-		rsvd += 512 * 1024; /* pci(e)gart table */
-		rsvd += 512 * 1024; /* object storage */
-
-		dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096);
-	} else {
-		dev_priv->ramin_rsvd_vram = 512 * 1024;
-	}
+	dev_priv->ramin_rsvd_vram = 512 * 1024;
 
 	/* Setup shared RAMHT */
 	ret = nouveau_gpuobj_new_fake(dev, 0x10000, ~0, 4096,
@@ -73,14 +50,7 @@
 
 	/* And RAMFC */
 	length = nouveau_fifo_ctx_size(dev);
-	switch (dev_priv->card_type) {
-	case NV_40:
-		offset = 0x20000;
-		break;
-	default:
-		offset = 0x11400;
-		break;
-	}
+	offset = 0x11400;
 
 	ret = nouveau_gpuobj_new_fake(dev, offset, ~0, length,
 				      NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramfc);
@@ -90,19 +60,6 @@
 	/* Only allow space after RAMFC to be used for object allocation */
 	offset += length;
 
-	/* It appears RAMRO (or something?) is controlled by 0x2220/0x2230
-	 * on certain NV4x chipsets as well as RAMFC.  When 0x2230 == 0
-	 * ("new style" control) the upper 16-bits of 0x2220 points at this
-	 * other mysterious table that's clobbering important things.
-	 *
-	 * We're now pointing this at RAMIN+0x30000 to avoid RAMFC getting
-	 * smashed to pieces on us, so reserve 0x30000-0x40000 too..
-	 */
-	if (dev_priv->card_type >= NV_40) {
-		if (offset < 0x40000)
-			offset = 0x40000;
-	}
-
 	ret = drm_mm_init(&dev_priv->ramin_heap, offset,
 			  dev_priv->ramin_rsvd_vram - offset);
 	if (ret) {
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h
new file mode 100644
index 0000000..a8c1104
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv04.h
@@ -0,0 +1,11 @@
+#ifndef __NV04_INSTMEM_H__
+#define __NV04_INSTMEM_H__
+
+struct nv04_instmem_priv {
+	struct nouveau_gpuobj *vbios;
+	struct nouveau_gpuobj *ramht;
+	struct nouveau_gpuobj *ramro;
+	struct nouveau_gpuobj *ramfc;
+};
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
new file mode 100644
index 0000000..91abf0be
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c
@@ -0,0 +1,167 @@
+#include "drmP.h"
+#include "drm.h"
+
+#include "nouveau_drv.h"
+#include <engine/fifo.h>
+#include <core/ramht.h>
+
+/* returns the size of fifo context */
+static int
+nouveau_fifo_ctx_size(struct drm_device *dev)
+{
+	return 128 * 32;
+}
+
+int nv40_instmem_init(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *ramht = NULL;
+	u32 offset, length, vs, rsvd;
+	int ret;
+
+	/* RAMIN always available */
+	dev_priv->ramin_available = true;
+
+	/* Reserve space at end of VRAM for PRAMIN */
+	/* estimate grctx size, the magics come from nv40_grctx.c */
+	vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8);
+	if      (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs;
+	else if (dev_priv->chipset  < 0x43) rsvd = 0x4f00 * vs;
+	else if (nv44_graph_class(dev))	    rsvd = 0x4980 * vs;
+	else				    rsvd = 0x4a40 * vs;
+	rsvd += 16 * 1024;
+	rsvd *= 32; /* per-channel */
+
+	rsvd += 512 * 1024; /* pci(e)gart table */
+	rsvd += 512 * 1024; /* object storage */
+
+	dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096);
+
+	/* Setup shared RAMHT */
+	ret = nouveau_gpuobj_new_fake(dev, 0x10000, ~0, 4096,
+				      NVOBJ_FLAG_ZERO_ALLOC, &ramht);
+	if (ret)
+		return ret;
+
+	ret = nouveau_ramht_new(dev, ramht, &dev_priv->ramht);
+	nouveau_gpuobj_ref(NULL, &ramht);
+	if (ret)
+		return ret;
+
+	/* And RAMRO */
+	ret = nouveau_gpuobj_new_fake(dev, 0x11200, ~0, 512,
+				      NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramro);
+	if (ret)
+		return ret;
+
+	/* And RAMFC */
+	length = nouveau_fifo_ctx_size(dev);
+	offset = 0x20000;
+
+	ret = nouveau_gpuobj_new_fake(dev, offset, ~0, length,
+				      NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramfc);
+	if (ret)
+		return ret;
+
+	/* Only allow space after RAMFC to be used for object allocation */
+	offset += length;
+
+	/* It appears RAMRO (or something?) is controlled by 0x2220/0x2230
+	 * on certain NV4x chipsets as well as RAMFC.  When 0x2230 == 0
+	 * ("new style" control) the upper 16-bits of 0x2220 points at this
+	 * other mysterious table that's clobbering important things.
+	 *
+	 * We're now pointing this at RAMIN+0x30000 to avoid RAMFC getting
+	 * smashed to pieces on us, so reserve 0x30000-0x40000 too..
+	 */
+	if (offset < 0x40000)
+		offset = 0x40000;
+
+	ret = drm_mm_init(&dev_priv->ramin_heap, offset,
+			  dev_priv->ramin_rsvd_vram - offset);
+	if (ret) {
+		NV_ERROR(dev, "Failed to init RAMIN heap: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+void
+nv40_instmem_takedown(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	nouveau_ramht_ref(NULL, &dev_priv->ramht, NULL);
+	nouveau_gpuobj_ref(NULL, &dev_priv->ramro);
+	nouveau_gpuobj_ref(NULL, &dev_priv->ramfc);
+
+	if (drm_mm_initialized(&dev_priv->ramin_heap))
+		drm_mm_takedown(&dev_priv->ramin_heap);
+}
+
+int
+nv40_instmem_suspend(struct drm_device *dev)
+{
+	return 0;
+}
+
+void
+nv40_instmem_resume(struct drm_device *dev)
+{
+}
+
+int
+nv40_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan,
+		 u32 size, u32 align)
+{
+	struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
+	struct drm_mm_node *ramin = NULL;
+
+	do {
+		if (drm_mm_pre_get(&dev_priv->ramin_heap))
+			return -ENOMEM;
+
+		spin_lock(&dev_priv->ramin_lock);
+		ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, align, 0);
+		if (ramin == NULL) {
+			spin_unlock(&dev_priv->ramin_lock);
+			return -ENOMEM;
+		}
+
+		ramin = drm_mm_get_block_atomic(ramin, size, align);
+		spin_unlock(&dev_priv->ramin_lock);
+	} while (ramin == NULL);
+
+	gpuobj->node  = ramin;
+	gpuobj->vinst = ramin->start;
+	return 0;
+}
+
+void
+nv40_instmem_put(struct nouveau_gpuobj *gpuobj)
+{
+	struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
+
+	spin_lock(&dev_priv->ramin_lock);
+	drm_mm_put_block(gpuobj->node);
+	gpuobj->node = NULL;
+	spin_unlock(&dev_priv->ramin_lock);
+}
+
+int
+nv40_instmem_map(struct nouveau_gpuobj *gpuobj)
+{
+	gpuobj->pinst = gpuobj->vinst;
+	return 0;
+}
+
+void
+nv40_instmem_unmap(struct nouveau_gpuobj *gpuobj)
+{
+}
+
+void
+nv40_instmem_flush(struct drm_device *dev)
+{
+}
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index c7bc6ec..ca88403 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -1072,6 +1072,18 @@
 extern void nv04_instmem_unmap(struct nouveau_gpuobj *);
 extern void nv04_instmem_flush(struct drm_device *);
 
+/* nv40_instmem.c */
+extern int  nv40_instmem_init(struct drm_device *);
+extern void nv40_instmem_takedown(struct drm_device *);
+extern int  nv40_instmem_suspend(struct drm_device *);
+extern void nv40_instmem_resume(struct drm_device *);
+extern int  nv40_instmem_get(struct nouveau_gpuobj *, struct nouveau_channel *,
+			     u32 size, u32 align);
+extern void nv40_instmem_put(struct nouveau_gpuobj *);
+extern int  nv40_instmem_map(struct nouveau_gpuobj *);
+extern void nv40_instmem_unmap(struct nouveau_gpuobj *);
+extern void nv40_instmem_flush(struct drm_device *);
+
 /* nv50_instmem.c */
 extern int  nv50_instmem_init(struct drm_device *);
 extern void nv50_instmem_takedown(struct drm_device *);
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c
index d8d9e5c..14998ee 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -135,15 +135,15 @@
 		break;
 	case 0x40:
 	case 0x60:
-		engine->instmem.init		= nv04_instmem_init;
-		engine->instmem.takedown	= nv04_instmem_takedown;
-		engine->instmem.suspend		= nv04_instmem_suspend;
-		engine->instmem.resume		= nv04_instmem_resume;
-		engine->instmem.get		= nv04_instmem_get;
-		engine->instmem.put		= nv04_instmem_put;
-		engine->instmem.map		= nv04_instmem_map;
-		engine->instmem.unmap		= nv04_instmem_unmap;
-		engine->instmem.flush		= nv04_instmem_flush;
+		engine->instmem.init		= nv40_instmem_init;
+		engine->instmem.takedown	= nv40_instmem_takedown;
+		engine->instmem.suspend		= nv40_instmem_suspend;
+		engine->instmem.resume		= nv40_instmem_resume;
+		engine->instmem.get		= nv40_instmem_get;
+		engine->instmem.put		= nv40_instmem_put;
+		engine->instmem.map		= nv40_instmem_map;
+		engine->instmem.unmap		= nv40_instmem_unmap;
+		engine->instmem.flush		= nv40_instmem_flush;
 		engine->display.early_init	= nv04_display_early_init;
 		engine->display.late_takedown	= nv04_display_late_takedown;
 		engine->display.create		= nv04_display_create;