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