summaryrefslogtreecommitdiff
path: root/shared-core/nv04_instmem.c
diff options
context:
space:
mode:
authorBen Skeggs <skeggsb@gmail.com>2007-07-05 00:12:33 +1000
committerBen Skeggs <skeggsb@gmail.com>2007-07-09 16:16:44 +1000
commitc806bba4665bb369168ee0b453fa28e2e0bf2a5d (patch)
treec3ded5cfc4048301654769a6fa224c3abb57c707 /shared-core/nv04_instmem.c
parent3324342e42b78aef8e90e11273776dd2b3b92074 (diff)
nouveau/nv50: Initial channel/object support
Should be OK on G84 for a single channel, multiple channels *almost* work. Untested on G80.
Diffstat (limited to 'shared-core/nv04_instmem.c')
-rw-r--r--shared-core/nv04_instmem.c165
1 files changed, 165 insertions, 0 deletions
diff --git a/shared-core/nv04_instmem.c b/shared-core/nv04_instmem.c
new file mode 100644
index 00000000..ac7d4347
--- /dev/null
+++ b/shared-core/nv04_instmem.c
@@ -0,0 +1,165 @@
+#include "drmP.h"
+#include "drm.h"
+#include "nouveau_drv.h"
+
+static void
+nv04_instmem_determine_amount(struct drm_device *dev)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ int i;
+
+ /* Figure out how much instance memory we need */
+ switch (dev_priv->card_type) {
+ case NV_40:
+ /* We'll want more instance memory than this on some NV4x cards.
+ * There's a 16MB aperture to play with that maps onto the end
+ * of vram. For now, only reserve a small piece until we know
+ * more about what each chipset requires.
+ */
+ dev_priv->ramin_rsvd_vram = (1*1024* 1024);
+ break;
+ default:
+ /*XXX: what *are* the limits on <NV40 cards?, and does RAMIN
+ * exist in vram on those cards as well?
+ */
+ dev_priv->ramin_rsvd_vram = (512*1024);
+ break;
+ }
+ DRM_DEBUG("RAMIN size: %dKiB\n", dev_priv->ramin_rsvd_vram>>10);
+
+ /* Clear all of it, except the BIOS image that's in the first 64KiB */
+ for (i=(64*1024); i<dev_priv->ramin_rsvd_vram; i+=4)
+ NV_WI32(i, 0x00000000);
+}
+
+static void
+nv04_instmem_configure_fixed_tables(struct drm_device *dev)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+
+ /* FIFO hash table (RAMHT)
+ * use 4k hash table at RAMIN+0x10000
+ * TODO: extend the hash table
+ */
+ dev_priv->ramht_offset = 0x10000;
+ dev_priv->ramht_bits = 9;
+ dev_priv->ramht_size = (1 << dev_priv->ramht_bits);
+ DRM_DEBUG("RAMHT offset=0x%x, size=%d\n", dev_priv->ramht_offset,
+ dev_priv->ramht_size);
+
+ /* FIFO runout table (RAMRO) - 512k at 0x11200 */
+ dev_priv->ramro_offset = 0x11200;
+ dev_priv->ramro_size = 512;
+ DRM_DEBUG("RAMRO offset=0x%x, size=%d\n", dev_priv->ramro_offset,
+ dev_priv->ramro_size);
+
+ /* FIFO context table (RAMFC)
+ * NV40 : Not sure exactly how to position RAMFC on some cards,
+ * 0x30002 seems to position it at RAMIN+0x20000 on these
+ * cards. RAMFC is 4kb (32 fifos, 128byte entries).
+ * Others: Position RAMFC at RAMIN+0x11400
+ */
+ switch(dev_priv->card_type)
+ {
+ case NV_40:
+ case NV_44:
+ dev_priv->ramfc_offset = 0x20000;
+ dev_priv->ramfc_size = nouveau_fifo_number(dev) *
+ nouveau_fifo_ctx_size(dev);
+ break;
+ case NV_30:
+ case NV_20:
+ case NV_17:
+ case NV_10:
+ case NV_04:
+ case NV_03:
+ default:
+ dev_priv->ramfc_offset = 0x11400;
+ dev_priv->ramfc_size = nouveau_fifo_number(dev) *
+ nouveau_fifo_ctx_size(dev);
+ break;
+ }
+ DRM_DEBUG("RAMFC offset=0x%x, size=%d\n", dev_priv->ramfc_offset,
+ dev_priv->ramfc_size);
+}
+
+int nv04_instmem_init(struct drm_device *dev)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+ uint32_t offset;
+ int ret = 0;
+
+ nv04_instmem_determine_amount(dev);
+ nv04_instmem_configure_fixed_tables(dev);
+
+ if ((ret = nouveau_gpuobj_new_fake(dev, dev_priv->ramht_offset,
+ dev_priv->ramht_size,
+ NVOBJ_FLAG_ZERO_ALLOC |
+ NVOBJ_FLAG_ALLOW_NO_REFS,
+ &dev_priv->ramht, NULL)))
+ return ret;
+
+ /* Create a heap to manage RAMIN allocations, we don't allocate
+ * the space that was reserved for RAMHT/FC/RO.
+ */
+ offset = dev_priv->ramfc_offset + dev_priv->ramfc_size;
+ ret = nouveau_mem_init_heap(&dev_priv->ramin_heap,
+ offset, dev_priv->ramin_rsvd_vram - offset);
+ if (ret) {
+ dev_priv->ramin_heap = NULL;
+ DRM_ERROR("Failed to init RAMIN heap\n");
+ }
+
+ return ret;
+}
+
+void
+nv04_instmem_takedown(drm_device_t *dev)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+
+ nouveau_gpuobj_del(dev, &dev_priv->ramht);
+}
+
+int
+nv04_instmem_populate(drm_device_t *dev, nouveau_gpuobj_t *gpuobj, uint32_t *sz)
+{
+ if (gpuobj->im_backing)
+ return DRM_ERR(EINVAL);
+
+ return 0;
+}
+
+void
+nv04_instmem_clear(drm_device_t *dev, nouveau_gpuobj_t *gpuobj)
+{
+ drm_nouveau_private_t *dev_priv = dev->dev_private;
+
+ if (gpuobj && gpuobj->im_backing) {
+ if (gpuobj->im_bound)
+ dev_priv->Engine.instmem.unbind(dev, gpuobj);
+ nouveau_mem_free(dev, gpuobj->im_backing);
+ gpuobj->im_backing = NULL;
+ }
+}
+
+int
+nv04_instmem_bind(drm_device_t *dev, nouveau_gpuobj_t *gpuobj)
+{
+ if (!gpuobj->im_pramin || gpuobj->im_bound)
+ return DRM_ERR(EINVAL);
+
+ gpuobj->im_bound = 1;
+ return 0;
+}
+
+int
+nv04_instmem_unbind(drm_device_t *dev, nouveau_gpuobj_t *gpuobj)
+{
+ if (gpuobj->im_bound == 0)
+ return DRM_ERR(EINVAL);
+
+ gpuobj->im_bound = 0;
+ return 0;
+}
+