Commit | Line | Data |
---|---|---|
760285e7 | 1 | #include <drm/drmP.h> |
c420b2dc | 2 | |
6ee73861 | 3 | #include "nouveau_drv.h" |
c420b2dc | 4 | #include "nouveau_fifo.h" |
fbd2895e | 5 | #include "nouveau_ramht.h" |
6ee73861 BS |
6 | |
7 | /* returns the size of fifo context */ | |
8 | static int | |
9 | nouveau_fifo_ctx_size(struct drm_device *dev) | |
10 | { | |
11 | struct drm_nouveau_private *dev_priv = dev->dev_private; | |
12 | ||
13 | if (dev_priv->chipset >= 0x40) | |
c420b2dc | 14 | return 128 * 32; |
6ee73861 BS |
15 | else |
16 | if (dev_priv->chipset >= 0x17) | |
c420b2dc BS |
17 | return 64 * 32; |
18 | else | |
19 | if (dev_priv->chipset >= 0x10) | |
20 | return 32 * 32; | |
6ee73861 | 21 | |
c420b2dc | 22 | return 32 * 16; |
6ee73861 BS |
23 | } |
24 | ||
6ee73861 BS |
25 | int nv04_instmem_init(struct drm_device *dev) |
26 | { | |
27 | struct drm_nouveau_private *dev_priv = dev->dev_private; | |
fbd2895e | 28 | struct nouveau_gpuobj *ramht = NULL; |
e05c5a31 | 29 | u32 offset, length; |
b833ac26 | 30 | int ret; |
6ee73861 | 31 | |
35fd5b42 FJ |
32 | /* RAMIN always available */ |
33 | dev_priv->ramin_available = true; | |
34 | ||
3b40d07d YM |
35 | /* Reserve space at end of VRAM for PRAMIN */ |
36 | if (dev_priv->card_type >= NV_40) { | |
37 | u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8); | |
38 | u32 rsvd; | |
39 | ||
40 | /* estimate grctx size, the magics come from nv40_grctx.c */ | |
41 | if (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs; | |
42 | else if (dev_priv->chipset < 0x43) rsvd = 0x4f00 * vs; | |
43 | else if (nv44_graph_class(dev)) rsvd = 0x4980 * vs; | |
44 | else rsvd = 0x4a40 * vs; | |
45 | rsvd += 16 * 1024; | |
c420b2dc | 46 | rsvd *= 32; /* per-channel */ |
3b40d07d | 47 | |
d0f3c7e4 BS |
48 | rsvd += 512 * 1024; /* pci(e)gart table */ |
49 | rsvd += 512 * 1024; /* object storage */ | |
3b40d07d YM |
50 | |
51 | dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096); | |
52 | } else { | |
53 | dev_priv->ramin_rsvd_vram = 512 * 1024; | |
54 | } | |
55 | ||
fbd2895e | 56 | /* Setup shared RAMHT */ |
e05c5a31 | 57 | ret = nouveau_gpuobj_new_fake(dev, 0x10000, ~0, 4096, |
fbd2895e BS |
58 | NVOBJ_FLAG_ZERO_ALLOC, &ramht); |
59 | if (ret) | |
60 | return ret; | |
61 | ||
62 | ret = nouveau_ramht_new(dev, ramht, &dev_priv->ramht); | |
63 | nouveau_gpuobj_ref(NULL, &ramht); | |
64 | if (ret) | |
65 | return ret; | |
66 | ||
e05c5a31 BS |
67 | /* And RAMRO */ |
68 | ret = nouveau_gpuobj_new_fake(dev, 0x11200, ~0, 512, | |
69 | NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramro); | |
70 | if (ret) | |
71 | return ret; | |
72 | ||
73 | /* And RAMFC */ | |
c420b2dc | 74 | length = nouveau_fifo_ctx_size(dev); |
e05c5a31 BS |
75 | switch (dev_priv->card_type) { |
76 | case NV_40: | |
77 | offset = 0x20000; | |
78 | break; | |
79 | default: | |
80 | offset = 0x11400; | |
81 | break; | |
82 | } | |
83 | ||
84 | ret = nouveau_gpuobj_new_fake(dev, offset, ~0, length, | |
85 | NVOBJ_FLAG_ZERO_ALLOC, &dev_priv->ramfc); | |
86 | if (ret) | |
87 | return ret; | |
88 | ||
89 | /* Only allow space after RAMFC to be used for object allocation */ | |
90 | offset += length; | |
6ee73861 BS |
91 | |
92 | /* It appears RAMRO (or something?) is controlled by 0x2220/0x2230 | |
93 | * on certain NV4x chipsets as well as RAMFC. When 0x2230 == 0 | |
94 | * ("new style" control) the upper 16-bits of 0x2220 points at this | |
95 | * other mysterious table that's clobbering important things. | |
96 | * | |
97 | * We're now pointing this at RAMIN+0x30000 to avoid RAMFC getting | |
98 | * smashed to pieces on us, so reserve 0x30000-0x40000 too.. | |
99 | */ | |
100 | if (dev_priv->card_type >= NV_40) { | |
101 | if (offset < 0x40000) | |
102 | offset = 0x40000; | |
103 | } | |
104 | ||
b833ac26 BS |
105 | ret = drm_mm_init(&dev_priv->ramin_heap, offset, |
106 | dev_priv->ramin_rsvd_vram - offset); | |
6ee73861 | 107 | if (ret) { |
b833ac26 BS |
108 | NV_ERROR(dev, "Failed to init RAMIN heap: %d\n", ret); |
109 | return ret; | |
6ee73861 BS |
110 | } |
111 | ||
b833ac26 | 112 | return 0; |
6ee73861 BS |
113 | } |
114 | ||
115 | void | |
116 | nv04_instmem_takedown(struct drm_device *dev) | |
117 | { | |
e05c5a31 BS |
118 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
119 | ||
120 | nouveau_ramht_ref(NULL, &dev_priv->ramht, NULL); | |
121 | nouveau_gpuobj_ref(NULL, &dev_priv->ramro); | |
122 | nouveau_gpuobj_ref(NULL, &dev_priv->ramfc); | |
2abdb057 JR |
123 | |
124 | if (drm_mm_initialized(&dev_priv->ramin_heap)) | |
125 | drm_mm_takedown(&dev_priv->ramin_heap); | |
6ee73861 BS |
126 | } |
127 | ||
128 | int | |
e41115d0 | 129 | nv04_instmem_suspend(struct drm_device *dev) |
6ee73861 | 130 | { |
6ee73861 BS |
131 | return 0; |
132 | } | |
133 | ||
134 | void | |
e41115d0 | 135 | nv04_instmem_resume(struct drm_device *dev) |
6ee73861 | 136 | { |
6ee73861 BS |
137 | } |
138 | ||
139 | int | |
6e32fedc BS |
140 | nv04_instmem_get(struct nouveau_gpuobj *gpuobj, struct nouveau_channel *chan, |
141 | u32 size, u32 align) | |
6ee73861 | 142 | { |
e41115d0 BS |
143 | struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; |
144 | struct drm_mm_node *ramin = NULL; | |
145 | ||
146 | do { | |
147 | if (drm_mm_pre_get(&dev_priv->ramin_heap)) | |
148 | return -ENOMEM; | |
149 | ||
150 | spin_lock(&dev_priv->ramin_lock); | |
151 | ramin = drm_mm_search_free(&dev_priv->ramin_heap, size, align, 0); | |
152 | if (ramin == NULL) { | |
153 | spin_unlock(&dev_priv->ramin_lock); | |
154 | return -ENOMEM; | |
155 | } | |
156 | ||
157 | ramin = drm_mm_get_block_atomic(ramin, size, align); | |
158 | spin_unlock(&dev_priv->ramin_lock); | |
159 | } while (ramin == NULL); | |
160 | ||
161 | gpuobj->node = ramin; | |
162 | gpuobj->vinst = ramin->start; | |
6ee73861 BS |
163 | return 0; |
164 | } | |
165 | ||
166 | void | |
e41115d0 | 167 | nv04_instmem_put(struct nouveau_gpuobj *gpuobj) |
6ee73861 | 168 | { |
e41115d0 BS |
169 | struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private; |
170 | ||
171 | spin_lock(&dev_priv->ramin_lock); | |
172 | drm_mm_put_block(gpuobj->node); | |
173 | gpuobj->node = NULL; | |
174 | spin_unlock(&dev_priv->ramin_lock); | |
6ee73861 BS |
175 | } |
176 | ||
177 | int | |
e41115d0 | 178 | nv04_instmem_map(struct nouveau_gpuobj *gpuobj) |
6ee73861 | 179 | { |
e41115d0 | 180 | gpuobj->pinst = gpuobj->vinst; |
6ee73861 BS |
181 | return 0; |
182 | } | |
183 | ||
184 | void | |
e41115d0 | 185 | nv04_instmem_unmap(struct nouveau_gpuobj *gpuobj) |
6ee73861 BS |
186 | { |
187 | } | |
188 | ||
e41115d0 BS |
189 | void |
190 | nv04_instmem_flush(struct drm_device *dev) | |
191 | { | |
192 | } |