From c806bba4665bb369168ee0b453fa28e2e0bf2a5d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 5 Jul 2007 00:12:33 +1000 Subject: nouveau/nv50: Initial channel/object support Should be OK on G84 for a single channel, multiple channels *almost* work. Untested on G80. --- shared-core/nv04_instmem.c | 165 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 shared-core/nv04_instmem.c (limited to 'shared-core/nv04_instmem.c') 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 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); iramin_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; +} + -- cgit v1.2.3