diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 5e18a53e2c0c5b16b5c35f5fc1a3e9c3a0d86ade..68043a40d9ea29e2ff3af0a608208c9d5c4f44ca 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -67,6 +67,7 @@ nouveau-y += core/subdev/i2c/base.o 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 f01063c078e6ec71a10b797c000f2b8c2d840667..8265ca8adf3fadcd9437ff7093bafcbd8b89d4f8 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 @@ nouveau_fifo_ctx_size(struct drm_device *dev) { 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 @@ int nv04_instmem_init(struct drm_device *dev) /* 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 @@ int nv04_instmem_init(struct drm_device *dev) /* 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 @@ int nv04_instmem_init(struct drm_device *dev) /* 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 0000000000000000000000000000000000000000..a8c1104a83dac2b9690b1f6162cc10572123cda9 --- /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 0000000000000000000000000000000000000000..91abf0beb07a9e5b6269720761cf99bc4c07ef20 --- /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 +#include + +/* 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 c7bc6ecad60192021bd9d1d64a7a7637ddc6eacb..ca88403be3f96b56705b4305b4a31f4fe84d69af 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1072,6 +1072,18 @@ extern int nv04_instmem_map(struct nouveau_gpuobj *); 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 d8d9e5c527a4aaba09563ff485f5b3bdcb98b3a2..14998ee89c949382f562e7251500228cf7c90f93 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -135,15 +135,15 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) 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;