|
@@ -106,12 +106,50 @@ nvc0_vram_init(struct drm_device *dev)
|
|
|
struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
|
|
|
const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
|
|
|
const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
|
|
|
- u32 length;
|
|
|
+ u32 parts = nv_rd32(dev, 0x121c74);
|
|
|
+ u32 bsize = nv_rd32(dev, 0x10f20c);
|
|
|
+ u32 offset, length;
|
|
|
+ bool uniform = true;
|
|
|
+ int ret, i;
|
|
|
|
|
|
- dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20;
|
|
|
- dev_priv->vram_size *= nv_rd32(dev, 0x121c74);
|
|
|
+ NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800));
|
|
|
+ NV_DEBUG(dev, "parts 0x%08x bcast_mem_amount 0x%08x\n", parts, bsize);
|
|
|
|
|
|
- length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
|
|
|
+ /* read amount of vram attached to each memory controller */
|
|
|
+ for (i = 0; i < parts; i++) {
|
|
|
+ u32 psize = nv_rd32(dev, 0x11020c + (i * 0x1000));
|
|
|
+ if (psize != bsize) {
|
|
|
+ if (psize < bsize)
|
|
|
+ bsize = psize;
|
|
|
+ uniform = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", i, psize);
|
|
|
+
|
|
|
+ dev_priv->vram_size += (u64)psize << 20;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* if all controllers have the same amount attached, there's no holes */
|
|
|
+ if (uniform) {
|
|
|
+ offset = rsvd_head;
|
|
|
+ length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
|
|
|
+ return nouveau_mm_init(&vram->mm, offset, length, 1);
|
|
|
+ }
|
|
|
|
|
|
- return nouveau_mm_init(&vram->mm, rsvd_head, length, 1);
|
|
|
+ /* otherwise, address lowest common amount from 0GiB */
|
|
|
+ ret = nouveau_mm_init(&vram->mm, rsvd_head, (bsize << 8) * parts, 1);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ /* and the rest starting from (8GiB + common_size) */
|
|
|
+ offset = (0x0200000000ULL >> 12) + (bsize << 8);
|
|
|
+ length = (dev_priv->vram_size >> 12) - (bsize << 8) - rsvd_tail;
|
|
|
+
|
|
|
+ ret = nouveau_mm_init(&vram->mm, offset, length, 0);
|
|
|
+ if (ret) {
|
|
|
+ nouveau_mm_fini(&vram->mm);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|