aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_vram.c48
1 files changed, 43 insertions, 5 deletions
diff --git a/drivers/gpu/drm/nouveau/nvc0_vram.c b/drivers/gpu/drm/nouveau/nvc0_vram.c
index abed0d3d5792..edbfe9360ae2 100644
--- a/drivers/gpu/drm/nouveau/nvc0_vram.c
+++ b/drivers/gpu/drm/nouveau/nvc0_vram.c
@@ -106,12 +106,50 @@ nvc0_vram_init(struct drm_device *dev)
106 struct nouveau_vram_engine *vram = &dev_priv->engine.vram; 106 struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
107 const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ 107 const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
108 const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ 108 const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
109 u32 length; 109 u32 parts = nv_rd32(dev, 0x121c74);
110 u32 bsize = nv_rd32(dev, 0x10f20c);
111 u32 offset, length;
112 bool uniform = true;
113 int ret, i;
110 114
111 dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20; 115 NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800));
112 dev_priv->vram_size *= nv_rd32(dev, 0x121c74); 116 NV_DEBUG(dev, "parts 0x%08x bcast_mem_amount 0x%08x\n", parts, bsize);
113 117
114 length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail; 118 /* read amount of vram attached to each memory controller */
119 for (i = 0; i < parts; i++) {
120 u32 psize = nv_rd32(dev, 0x11020c + (i * 0x1000));
121 if (psize != bsize) {
122 if (psize < bsize)
123 bsize = psize;
124 uniform = false;
125 }
126
127 NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", i, psize);
128
129 dev_priv->vram_size += (u64)psize << 20;
130 }
131
132 /* if all controllers have the same amount attached, there's no holes */
133 if (uniform) {
134 offset = rsvd_head;
135 length = (dev_priv->vram_size >> 12) - rsvd_head - rsvd_tail;
136 return nouveau_mm_init(&vram->mm, offset, length, 1);
137 }
115 138
116 return nouveau_mm_init(&vram->mm, rsvd_head, length, 1); 139 /* otherwise, address lowest common amount from 0GiB */
140 ret = nouveau_mm_init(&vram->mm, rsvd_head, (bsize << 8) * parts, 1);
141 if (ret)
142 return ret;
143
144 /* and the rest starting from (8GiB + common_size) */
145 offset = (0x0200000000ULL >> 12) + (bsize << 8);
146 length = (dev_priv->vram_size >> 12) - (bsize << 8) - rsvd_tail;
147
148 ret = nouveau_mm_init(&vram->mm, offset, length, 0);
149 if (ret) {
150 nouveau_mm_fini(&vram->mm);
151 return ret;
152 }
153
154 return 0;
117} 155}