16ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs#include "drmP.h"
26ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs#include "drm.h"
36ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs#include "nouveau_drv.h"
4fbd2895e45aebdb3d3ea73a3a796cf3bb9c912daBen Skeggs#include "nouveau_ramht.h"
56ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
66ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs/* returns the size of fifo context */
76ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsstatic int
86ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsnouveau_fifo_ctx_size(struct drm_device *dev)
96ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
106ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	struct drm_nouveau_private *dev_priv = dev->dev_private;
116ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
126ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (dev_priv->chipset >= 0x40)
136ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		return 128;
146ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	else
156ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (dev_priv->chipset >= 0x17)
166ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		return 64;
176ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
186ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return 32;
196ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
206ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
216ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsint nv04_instmem_init(struct drm_device *dev)
226ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
236ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	struct drm_nouveau_private *dev_priv = dev->dev_private;
24fbd2895e45aebdb3d3ea73a3a796cf3bb9c912daBen Skeggs	struct nouveau_gpuobj *ramht = NULL;
25e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs	u32 offset, length;
26b833ac26f1f1c8e8d9149d83dbdd91432f2807d5Ben Skeggs	int ret;
276ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
2835fd5b42f035c795bd9c6649591f59b500cb62b3Francisco Jerez	/* RAMIN always available */
2935fd5b42f035c795bd9c6649591f59b500cb62b3Francisco Jerez	dev_priv->ramin_available = true;
3035fd5b42f035c795bd9c6649591f59b500cb62b3Francisco Jerez
313b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton	/* Reserve space at end of VRAM for PRAMIN */
323b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton	if (dev_priv->card_type >= NV_40) {
333b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton		u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8);
343b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton		u32 rsvd;
353b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton
363b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton		/* estimate grctx size, the magics come from nv40_grctx.c */
373b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton		if      (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs;
383b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton		else if (dev_priv->chipset  < 0x43) rsvd = 0x4f00 * vs;
393b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton		else if (nv44_graph_class(dev))	    rsvd = 0x4980 * vs;
403b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton		else				    rsvd = 0x4a40 * vs;
413b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton		rsvd += 16 * 1024;
423b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton		rsvd *= dev_priv->engine.fifo.channels;
433b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton
443b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton		/* pciegart table */
4558b6542b50ded4243c26c251c0507e5f658642f6Jon Mason		if (pci_is_pcie(dev->pdev))
463b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton			rsvd += 512 * 1024;
473b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton
483b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton		/* object storage */
493b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton		rsvd += 512 * 1024;
503b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton
513b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton		dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096);
523b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton	} else {
533b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton		dev_priv->ramin_rsvd_vram = 512 * 1024;
543b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton	}
553b40d07d8c4a9dc33ee6e1b4ad1d377309531ffeYounes Manton
56fbd2895e45aebdb3d3ea73a3a796cf3bb9c912daBen Skeggs	/* Setup shared RAMHT */
57e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs	ret = nouveau_gpuobj_new_fake(dev, 0x10000, ~0, 4096,
58fbd2895e45aebdb3d3ea73a3a796cf3bb9c912daBen Skeggs				      NVOBJ_FLAG_ZERO_ALLOC, &ramht);
59fbd2895e45aebdb3d3ea73a3a796cf3bb9c912daBen Skeggs	if (ret)
60fbd2895e45aebdb3d3ea73a3a796cf3bb9c912daBen Skeggs		return ret;
61fbd2895e45aebdb3d3ea73a3a796cf3bb9c912daBen Skeggs
62fbd2895e45aebdb3d3ea73a3a796cf3bb9c912daBen Skeggs	ret = nouveau_ramht_new(dev, ramht, &dev_priv->ramht);
63fbd2895e45aebdb3d3ea73a3a796cf3bb9c912daBen Skeggs	nouveau_gpuobj_ref(NULL, &ramht);
64fbd2895e45aebdb3d3ea73a3a796cf3bb9c912daBen Skeggs	if (ret)
65fbd2895e45aebdb3d3ea73a3a796cf3bb9c912daBen Skeggs		return ret;
66fbd2895e45aebdb3d3ea73a3a796cf3bb9c912daBen Skeggs
67e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs	/* And RAMRO */
68e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs	ret = nouveau_gpuobj_new_fake(dev, 0x11200, ~0, 512,
69e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs				      NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramro);
70e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs	if (ret)
71e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs		return ret;
72e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs
73e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs	/* And RAMFC */
74e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs	length = dev_priv->engine.fifo.channels * nouveau_fifo_ctx_size(dev);
75e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs	switch (dev_priv->card_type) {
76e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs	case NV_40:
77e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs		offset = 0x20000;
78e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs		break;
79e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs	default:
80e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs		offset = 0x11400;
81e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs		break;
82e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs	}
83e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs
84e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs	ret = nouveau_gpuobj_new_fake(dev, offset, ~0, length,
85e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs				      NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramfc);
86e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs	if (ret)
87e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs		return ret;
88e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs
89e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs	/* Only allow space after RAMFC to be used for object allocation */
90e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs	offset += length;
916ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
926ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	/* It appears RAMRO (or something?) is controlled by 0x2220/0x2230
936ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 * on certain NV4x chipsets as well as RAMFC.  When 0x2230 == 0
946ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 * ("new style" control) the upper 16-bits of 0x2220 points at this
956ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 * other mysterious table that's clobbering important things.
966ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 *
976ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 * We're now pointing this at RAMIN+0x30000 to avoid RAMFC getting
986ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 * smashed to pieces on us, so reserve 0x30000-0x40000 too..
996ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	 */
1006ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (dev_priv->card_type >= NV_40) {
1016ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs		if (offset < 0x40000)
1026ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs			offset = 0x40000;
1036ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	}
1046ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
105b833ac26f1f1c8e8d9149d83dbdd91432f2807d5Ben Skeggs	ret = drm_mm_init(&dev_priv->ramin_heap, offset,
106b833ac26f1f1c8e8d9149d83dbdd91432f2807d5Ben Skeggs			  dev_priv->ramin_rsvd_vram - offset);
1076ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	if (ret) {
108b833ac26f1f1c8e8d9149d83dbdd91432f2807d5Ben Skeggs		NV_ERROR(dev, "Failed to init RAMIN heap: %d\n", ret);
109b833ac26f1f1c8e8d9149d83dbdd91432f2807d5Ben Skeggs		return ret;
1106ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	}
1116ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
112b833ac26f1f1c8e8d9149d83dbdd91432f2807d5Ben Skeggs	return 0;
1136ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
1146ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
1156ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsvoid
1166ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsnv04_instmem_takedown(struct drm_device *dev)
1176ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
118e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs	struct drm_nouveau_private *dev_priv = dev->dev_private;
119e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs
120e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs	nouveau_ramht_ref(NULL, &dev_priv->ramht, NULL);
121e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs	nouveau_gpuobj_ref(NULL, &dev_priv->ramro);
122e05c5a317efb03854950a3fcc5c9501bfefc7d68Ben Skeggs	nouveau_gpuobj_ref(NULL, &dev_priv->ramfc);
1232abdb057e45ea9b558653a97d979053cfdd1a04aJimmy Rentz
1242abdb057e45ea9b558653a97d979053cfdd1a04aJimmy Rentz	if (drm_mm_initialized(&dev_priv->ramin_heap))
1252abdb057e45ea9b558653a97d979053cfdd1a04aJimmy Rentz		drm_mm_takedown(&dev_priv->ramin_heap);
1266ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
1276ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
1286ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsint
129e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggsnv04_instmem_suspend(struct drm_device *dev)
1306ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
1316ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return 0;
1326ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
1336ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
1346ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsvoid
135e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggsnv04_instmem_resume(struct drm_device *dev)
1366ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
1376ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
1386ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
1396ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsint
1406e32fedc8b50d3571bdec4e9849e45659ac96599Ben Skeggsnv04_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan,
1416e32fedc8b50d3571bdec4e9849e45659ac96599Ben Skeggs		 u32 size, u32 align)
1426ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
143e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs	struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
144e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs	struct drm_mm_node *ramin = NULL;
145e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs
146e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs	do {
147e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs		if (drm_mm_pre_get(&dev_priv->ramin_heap))
148e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs			return -ENOMEM;
149e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs
150e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs		spin_lock(&dev_priv->ramin_lock);
151e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs		ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, align, 0);
152e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs		if (ramin == NULL) {
153e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs			spin_unlock(&dev_priv->ramin_lock);
154e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs			return -ENOMEM;
155e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs		}
156e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs
157e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs		ramin = drm_mm_get_block_atomic(ramin, size, align);
158e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs		spin_unlock(&dev_priv->ramin_lock);
159e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs	} while (ramin == NULL);
160e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs
161e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs	gpuobj->node  = ramin;
162e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs	gpuobj->vinst = ramin->start;
1636ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return 0;
1646ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
1656ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
1666ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsvoid
167e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggsnv04_instmem_put(struct nouveau_gpuobj *gpuobj)
1686ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
169e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs	struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
170e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs
171e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs	spin_lock(&dev_priv->ramin_lock);
172e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs	drm_mm_put_block(gpuobj->node);
173e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs	gpuobj->node = NULL;
174e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs	spin_unlock(&dev_priv->ramin_lock);
1756ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
1766ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
1776ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsint
178e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggsnv04_instmem_map(struct nouveau_gpuobj *gpuobj)
1796ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
180e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs	gpuobj->pinst = gpuobj->vinst;
1816ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs	return 0;
1826ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
1836ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
1846ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggsvoid
185e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggsnv04_instmem_unmap(struct nouveau_gpuobj *gpuobj)
1866ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs{
1876ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs}
1886ee738610f41b59733f63718f0bdbcba7d3a3f12Ben Skeggs
189e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggsvoid
190e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggsnv04_instmem_flush(struct drm_device *dev)
191e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs{
192e41115d0ad5c40a7ea4d85b1c77b4c02185a5581Ben Skeggs}
193