diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2011-03-31 20:59:53 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2011-05-15 20:48:09 -0400 |
commit | 7a45cd19c95a383d81a7b2f5297958c0c16b5a08 (patch) | |
tree | 4a9634d575233e5bfdb9a60f478e7ba6fe99dc19 /drivers/gpu/drm | |
parent | 2703c21a82301f5c31ba5679e2d56422bd4cd404 (diff) |
drm/nvc0/gr: move to exec engine interfaces
Much nicer to do that nv50, the code was pretty much written to expect
such a change in the future.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_state.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvc0_graph.c | 406 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvc0_graph.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvc0_grctx.c | 4 |
5 files changed, 200 insertions, 230 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 66591d39cad7..139864f6aabb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
@@ -1194,15 +1194,9 @@ extern int nv50_grctx_init(struct nouveau_grctx *); | |||
1194 | extern struct nouveau_enum nv50_data_error_names[]; | 1194 | extern struct nouveau_enum nv50_data_error_names[]; |
1195 | 1195 | ||
1196 | /* nvc0_graph.c */ | 1196 | /* nvc0_graph.c */ |
1197 | extern int nvc0_graph_init(struct drm_device *); | 1197 | extern int nvc0_graph_create(struct drm_device *); |
1198 | extern void nvc0_graph_takedown(struct drm_device *); | ||
1199 | extern void nvc0_graph_fifo_access(struct drm_device *, bool); | 1198 | extern void nvc0_graph_fifo_access(struct drm_device *, bool); |
1200 | extern struct nouveau_channel *nvc0_graph_channel(struct drm_device *); | 1199 | extern struct nouveau_channel *nvc0_graph_channel(struct drm_device *); |
1201 | extern int nvc0_graph_create_context(struct nouveau_channel *); | ||
1202 | extern void nvc0_graph_destroy_context(struct nouveau_channel *); | ||
1203 | extern int nvc0_graph_load_context(struct nouveau_channel *); | ||
1204 | extern int nvc0_graph_unload_context(struct drm_device *); | ||
1205 | extern int nvc0_graph_object_new(struct nouveau_channel *, u32, u16); | ||
1206 | 1200 | ||
1207 | /* nv84_crypt.c */ | 1201 | /* nv84_crypt.c */ |
1208 | extern int nv84_crypt_create(struct drm_device *); | 1202 | extern int nv84_crypt_create(struct drm_device *); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 6fd6736a15fa..958f312a497c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c | |||
@@ -440,15 +440,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
440 | engine->timer.takedown = nv04_timer_takedown; | 440 | engine->timer.takedown = nv04_timer_takedown; |
441 | engine->fb.init = nvc0_fb_init; | 441 | engine->fb.init = nvc0_fb_init; |
442 | engine->fb.takedown = nvc0_fb_takedown; | 442 | engine->fb.takedown = nvc0_fb_takedown; |
443 | engine->graph.init = nvc0_graph_init; | ||
444 | engine->graph.takedown = nvc0_graph_takedown; | ||
445 | engine->graph.fifo_access = nvc0_graph_fifo_access; | 443 | engine->graph.fifo_access = nvc0_graph_fifo_access; |
446 | engine->graph.channel = nvc0_graph_channel; | 444 | engine->graph.channel = nvc0_graph_channel; |
447 | engine->graph.create_context = nvc0_graph_create_context; | ||
448 | engine->graph.destroy_context = nvc0_graph_destroy_context; | ||
449 | engine->graph.load_context = nvc0_graph_load_context; | ||
450 | engine->graph.unload_context = nvc0_graph_unload_context; | ||
451 | engine->graph.object_new = nvc0_graph_object_new; | ||
452 | engine->fifo.channels = 128; | 445 | engine->fifo.channels = 128; |
453 | engine->fifo.init = nvc0_fifo_init; | 446 | engine->fifo.init = nvc0_fifo_init; |
454 | engine->fifo.takedown = nvc0_fifo_takedown; | 447 | engine->fifo.takedown = nvc0_fifo_takedown; |
@@ -627,6 +620,9 @@ nouveau_card_init(struct drm_device *dev) | |||
627 | 620 | ||
628 | if (dev_priv->card_type == NV_50) | 621 | if (dev_priv->card_type == NV_50) |
629 | nv50_graph_create(dev); | 622 | nv50_graph_create(dev); |
623 | else | ||
624 | if (dev_priv->card_type == NV_C0) | ||
625 | nvc0_graph_create(dev); | ||
630 | 626 | ||
631 | switch (dev_priv->chipset) { | 627 | switch (dev_priv->chipset) { |
632 | case 0x84: | 628 | case 0x84: |
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c index d1f2d56b1279..24f036c85f30 100644 --- a/drivers/gpu/drm/nouveau/nvc0_graph.c +++ b/drivers/gpu/drm/nouveau/nvc0_graph.c | |||
@@ -30,10 +30,6 @@ | |||
30 | #include "nouveau_mm.h" | 30 | #include "nouveau_mm.h" |
31 | #include "nvc0_graph.h" | 31 | #include "nvc0_graph.h" |
32 | 32 | ||
33 | static void nvc0_graph_isr(struct drm_device *); | ||
34 | static void nvc0_runk140_isr(struct drm_device *); | ||
35 | static int nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan); | ||
36 | |||
37 | void | 33 | void |
38 | nvc0_graph_fifo_access(struct drm_device *dev, bool enabled) | 34 | nvc0_graph_fifo_access(struct drm_device *dev, bool enabled) |
39 | { | 35 | { |
@@ -46,11 +42,39 @@ nvc0_graph_channel(struct drm_device *dev) | |||
46 | } | 42 | } |
47 | 43 | ||
48 | static int | 44 | static int |
45 | nvc0_graph_load_context(struct nouveau_channel *chan) | ||
46 | { | ||
47 | struct drm_device *dev = chan->dev; | ||
48 | |||
49 | nv_wr32(dev, 0x409840, 0x00000030); | ||
50 | nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); | ||
51 | nv_wr32(dev, 0x409504, 0x00000003); | ||
52 | if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010)) | ||
53 | NV_ERROR(dev, "PGRAPH: load_ctx timeout\n"); | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static int | ||
59 | nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan) | ||
60 | { | ||
61 | nv_wr32(dev, 0x409840, 0x00000003); | ||
62 | nv_wr32(dev, 0x409500, 0x80000000 | chan >> 12); | ||
63 | nv_wr32(dev, 0x409504, 0x00000009); | ||
64 | if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000000)) { | ||
65 | NV_ERROR(dev, "PGRAPH: unload_ctx timeout\n"); | ||
66 | return -EBUSY; | ||
67 | } | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static int | ||
49 | nvc0_graph_construct_context(struct nouveau_channel *chan) | 73 | nvc0_graph_construct_context(struct nouveau_channel *chan) |
50 | { | 74 | { |
51 | struct drm_nouveau_private *dev_priv = chan->dev->dev_private; | 75 | struct drm_nouveau_private *dev_priv = chan->dev->dev_private; |
52 | struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; | 76 | struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); |
53 | struct nvc0_graph_chan *grch = chan->pgraph_ctx; | 77 | struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; |
54 | struct drm_device *dev = chan->dev; | 78 | struct drm_device *dev = chan->dev; |
55 | int ret, i; | 79 | int ret, i; |
56 | u32 *ctx; | 80 | u32 *ctx; |
@@ -89,9 +113,8 @@ nvc0_graph_construct_context(struct nouveau_channel *chan) | |||
89 | static int | 113 | static int |
90 | nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) | 114 | nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) |
91 | { | 115 | { |
92 | struct drm_nouveau_private *dev_priv = chan->dev->dev_private; | 116 | struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); |
93 | struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; | 117 | struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; |
94 | struct nvc0_graph_chan *grch = chan->pgraph_ctx; | ||
95 | struct drm_device *dev = chan->dev; | 118 | struct drm_device *dev = chan->dev; |
96 | int i = 0, gpc, tp, ret; | 119 | int i = 0, gpc, tp, ret; |
97 | u32 magic; | 120 | u32 magic; |
@@ -158,29 +181,27 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) | |||
158 | return 0; | 181 | return 0; |
159 | } | 182 | } |
160 | 183 | ||
161 | int | 184 | static int |
162 | nvc0_graph_create_context(struct nouveau_channel *chan) | 185 | nvc0_graph_context_new(struct nouveau_channel *chan, int engine) |
163 | { | 186 | { |
164 | struct drm_nouveau_private *dev_priv = chan->dev->dev_private; | 187 | struct drm_device *dev = chan->dev; |
188 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
165 | struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; | 189 | struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem; |
166 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | 190 | struct nvc0_graph_priv *priv = nv_engine(dev, engine); |
167 | struct nvc0_graph_priv *priv = pgraph->priv; | ||
168 | struct nvc0_graph_chan *grch; | 191 | struct nvc0_graph_chan *grch; |
169 | struct drm_device *dev = chan->dev; | ||
170 | struct nouveau_gpuobj *grctx; | 192 | struct nouveau_gpuobj *grctx; |
171 | int ret, i; | 193 | int ret, i; |
172 | 194 | ||
173 | chan->pgraph_ctx = kzalloc(sizeof(*grch), GFP_KERNEL); | 195 | grch = kzalloc(sizeof(*grch), GFP_KERNEL); |
174 | if (!chan->pgraph_ctx) | 196 | if (!grch) |
175 | return -ENOMEM; | 197 | return -ENOMEM; |
176 | grch = chan->pgraph_ctx; | 198 | chan->engctx[NVOBJ_ENGINE_GR] = grch; |
177 | 199 | ||
178 | ret = nouveau_gpuobj_new(dev, NULL, priv->grctx_size, 256, | 200 | ret = nouveau_gpuobj_new(dev, NULL, priv->grctx_size, 256, |
179 | NVOBJ_FLAG_VM | NVOBJ_FLAG_ZERO_ALLOC, | 201 | NVOBJ_FLAG_VM | NVOBJ_FLAG_ZERO_ALLOC, |
180 | &grch->grctx); | 202 | &grch->grctx); |
181 | if (ret) | 203 | if (ret) |
182 | goto error; | 204 | goto error; |
183 | chan->ramin_grctx = grch->grctx; | ||
184 | grctx = grch->grctx; | 205 | grctx = grch->grctx; |
185 | 206 | ||
186 | ret = nvc0_graph_create_context_mmio_list(chan); | 207 | ret = nvc0_graph_create_context_mmio_list(chan); |
@@ -213,97 +234,42 @@ nvc0_graph_create_context(struct nouveau_channel *chan) | |||
213 | return 0; | 234 | return 0; |
214 | 235 | ||
215 | error: | 236 | error: |
216 | pgraph->destroy_context(chan); | 237 | priv->base.context_del(chan, engine); |
217 | return ret; | 238 | return ret; |
218 | } | 239 | } |
219 | 240 | ||
220 | void | 241 | static void |
221 | nvc0_graph_destroy_context(struct nouveau_channel *chan) | 242 | nvc0_graph_context_del(struct nouveau_channel *chan, int engine) |
222 | { | 243 | { |
223 | struct nvc0_graph_chan *grch; | 244 | struct nvc0_graph_chan *grch = chan->engctx[engine]; |
224 | |||
225 | grch = chan->pgraph_ctx; | ||
226 | chan->pgraph_ctx = NULL; | ||
227 | if (!grch) | ||
228 | return; | ||
229 | 245 | ||
230 | nouveau_gpuobj_ref(NULL, &grch->mmio); | 246 | nouveau_gpuobj_ref(NULL, &grch->mmio); |
231 | nouveau_gpuobj_ref(NULL, &grch->unk418810); | 247 | nouveau_gpuobj_ref(NULL, &grch->unk418810); |
232 | nouveau_gpuobj_ref(NULL, &grch->unk40800c); | 248 | nouveau_gpuobj_ref(NULL, &grch->unk40800c); |
233 | nouveau_gpuobj_ref(NULL, &grch->unk408004); | 249 | nouveau_gpuobj_ref(NULL, &grch->unk408004); |
234 | nouveau_gpuobj_ref(NULL, &grch->grctx); | 250 | nouveau_gpuobj_ref(NULL, &grch->grctx); |
235 | chan->ramin_grctx = NULL; | 251 | chan->engctx[engine] = NULL; |
236 | } | 252 | } |
237 | 253 | ||
238 | int | 254 | static int |
239 | nvc0_graph_load_context(struct nouveau_channel *chan) | 255 | nvc0_graph_object_new(struct nouveau_channel *chan, int engine, |
256 | u32 handle, u16 class) | ||
240 | { | 257 | { |
241 | struct drm_device *dev = chan->dev; | ||
242 | |||
243 | nv_wr32(dev, 0x409840, 0x00000030); | ||
244 | nv_wr32(dev, 0x409500, 0x80000000 | chan->ramin->vinst >> 12); | ||
245 | nv_wr32(dev, 0x409504, 0x00000003); | ||
246 | if (!nv_wait(dev, 0x409800, 0x00000010, 0x00000010)) | ||
247 | NV_ERROR(dev, "PGRAPH: load_ctx timeout\n"); | ||
248 | |||
249 | return 0; | 258 | return 0; |
250 | } | 259 | } |
251 | 260 | ||
252 | static int | 261 | static int |
253 | nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan) | 262 | nvc0_graph_fini(struct drm_device *dev, int engine) |
254 | { | 263 | { |
255 | nv_wr32(dev, 0x409840, 0x00000003); | 264 | u32 inst = nv_rd32(dev, 0x409b00); |
256 | nv_wr32(dev, 0x409500, 0x80000000 | chan >> 12); | 265 | if (inst & 0x80000000) { |
257 | nv_wr32(dev, 0x409504, 0x00000009); | 266 | inst &= 0x0fffffff; |
258 | if (!nv_wait(dev, 0x409800, 0x00000001, 0x00000000)) { | 267 | nvc0_graph_unload_context_to(dev, (u64)inst << 12); |
259 | NV_ERROR(dev, "PGRAPH: unload_ctx timeout\n"); | ||
260 | return -EBUSY; | ||
261 | } | 268 | } |
262 | 269 | ||
263 | return 0; | 270 | return 0; |
264 | } | 271 | } |
265 | 272 | ||
266 | int | ||
267 | nvc0_graph_unload_context(struct drm_device *dev) | ||
268 | { | ||
269 | u64 inst = (u64)(nv_rd32(dev, 0x409b00) & 0x0fffffff) << 12; | ||
270 | return nvc0_graph_unload_context_to(dev, inst); | ||
271 | } | ||
272 | |||
273 | int | ||
274 | nvc0_graph_object_new(struct nouveau_channel *chan, u32 handle, u16 class) | ||
275 | { | ||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static void | ||
280 | nvc0_graph_destroy(struct drm_device *dev) | ||
281 | { | ||
282 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
283 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | ||
284 | struct nvc0_graph_priv *priv; | ||
285 | |||
286 | priv = pgraph->priv; | ||
287 | if (!priv) | ||
288 | return; | ||
289 | |||
290 | nouveau_irq_unregister(dev, 12); | ||
291 | nouveau_irq_unregister(dev, 25); | ||
292 | |||
293 | nouveau_gpuobj_ref(NULL, &priv->unk4188b8); | ||
294 | nouveau_gpuobj_ref(NULL, &priv->unk4188b4); | ||
295 | |||
296 | if (priv->grctx_vals) | ||
297 | kfree(priv->grctx_vals); | ||
298 | kfree(priv); | ||
299 | } | ||
300 | |||
301 | void | ||
302 | nvc0_graph_takedown(struct drm_device *dev) | ||
303 | { | ||
304 | nvc0_graph_destroy(dev); | ||
305 | } | ||
306 | |||
307 | static int | 273 | static int |
308 | nvc0_graph_mthd_page_flip(struct nouveau_channel *chan, | 274 | nvc0_graph_mthd_page_flip(struct nouveau_channel *chan, |
309 | u32 class, u32 mthd, u32 data) | 275 | u32 class, u32 mthd, u32 data) |
@@ -312,119 +278,10 @@ nvc0_graph_mthd_page_flip(struct nouveau_channel *chan, | |||
312 | return 0; | 278 | return 0; |
313 | } | 279 | } |
314 | 280 | ||
315 | static int | ||
316 | nvc0_graph_create(struct drm_device *dev) | ||
317 | { | ||
318 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
319 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | ||
320 | struct nvc0_graph_priv *priv; | ||
321 | int ret, gpc, i; | ||
322 | |||
323 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
324 | if (!priv) | ||
325 | return -ENOMEM; | ||
326 | pgraph->priv = priv; | ||
327 | |||
328 | ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4); | ||
329 | if (ret) | ||
330 | goto error; | ||
331 | |||
332 | ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b8); | ||
333 | if (ret) | ||
334 | goto error; | ||
335 | |||
336 | for (i = 0; i < 0x1000; i += 4) { | ||
337 | nv_wo32(priv->unk4188b4, i, 0x00000010); | ||
338 | nv_wo32(priv->unk4188b8, i, 0x00000010); | ||
339 | } | ||
340 | |||
341 | priv->gpc_nr = nv_rd32(dev, 0x409604) & 0x0000001f; | ||
342 | priv->rop_nr = (nv_rd32(dev, 0x409604) & 0x001f0000) >> 16; | ||
343 | for (gpc = 0; gpc < priv->gpc_nr; gpc++) { | ||
344 | priv->tp_nr[gpc] = nv_rd32(dev, GPC_UNIT(gpc, 0x2608)); | ||
345 | priv->tp_total += priv->tp_nr[gpc]; | ||
346 | } | ||
347 | |||
348 | /*XXX: these need figuring out... */ | ||
349 | switch (dev_priv->chipset) { | ||
350 | case 0xc0: | ||
351 | if (priv->tp_total == 11) { /* 465, 3/4/4/0, 4 */ | ||
352 | priv->magic_not_rop_nr = 0x07; | ||
353 | /* filled values up to tp_total, the rest 0 */ | ||
354 | priv->magicgpc980[0] = 0x22111000; | ||
355 | priv->magicgpc980[1] = 0x00000233; | ||
356 | priv->magicgpc980[2] = 0x00000000; | ||
357 | priv->magicgpc980[3] = 0x00000000; | ||
358 | priv->magicgpc918 = 0x000ba2e9; | ||
359 | } else | ||
360 | if (priv->tp_total == 14) { /* 470, 3/3/4/4, 5 */ | ||
361 | priv->magic_not_rop_nr = 0x05; | ||
362 | priv->magicgpc980[0] = 0x11110000; | ||
363 | priv->magicgpc980[1] = 0x00233222; | ||
364 | priv->magicgpc980[2] = 0x00000000; | ||
365 | priv->magicgpc980[3] = 0x00000000; | ||
366 | priv->magicgpc918 = 0x00092493; | ||
367 | } else | ||
368 | if (priv->tp_total == 15) { /* 480, 3/4/4/4, 6 */ | ||
369 | priv->magic_not_rop_nr = 0x06; | ||
370 | priv->magicgpc980[0] = 0x11110000; | ||
371 | priv->magicgpc980[1] = 0x03332222; | ||
372 | priv->magicgpc980[2] = 0x00000000; | ||
373 | priv->magicgpc980[3] = 0x00000000; | ||
374 | priv->magicgpc918 = 0x00088889; | ||
375 | } | ||
376 | break; | ||
377 | case 0xc3: /* 450, 4/0/0/0, 2 */ | ||
378 | priv->magic_not_rop_nr = 0x03; | ||
379 | priv->magicgpc980[0] = 0x00003210; | ||
380 | priv->magicgpc980[1] = 0x00000000; | ||
381 | priv->magicgpc980[2] = 0x00000000; | ||
382 | priv->magicgpc980[3] = 0x00000000; | ||
383 | priv->magicgpc918 = 0x00200000; | ||
384 | break; | ||
385 | case 0xc4: /* 460, 3/4/0/0, 4 */ | ||
386 | priv->magic_not_rop_nr = 0x01; | ||
387 | priv->magicgpc980[0] = 0x02321100; | ||
388 | priv->magicgpc980[1] = 0x00000000; | ||
389 | priv->magicgpc980[2] = 0x00000000; | ||
390 | priv->magicgpc980[3] = 0x00000000; | ||
391 | priv->magicgpc918 = 0x00124925; | ||
392 | break; | ||
393 | } | ||
394 | |||
395 | if (!priv->magic_not_rop_nr) { | ||
396 | NV_ERROR(dev, "PGRAPH: unknown config: %d/%d/%d/%d, %d\n", | ||
397 | priv->tp_nr[0], priv->tp_nr[1], priv->tp_nr[2], | ||
398 | priv->tp_nr[3], priv->rop_nr); | ||
399 | /* use 0xc3's values... */ | ||
400 | priv->magic_not_rop_nr = 0x03; | ||
401 | priv->magicgpc980[0] = 0x00003210; | ||
402 | priv->magicgpc980[1] = 0x00000000; | ||
403 | priv->magicgpc980[2] = 0x00000000; | ||
404 | priv->magicgpc980[3] = 0x00000000; | ||
405 | priv->magicgpc918 = 0x00200000; | ||
406 | } | ||
407 | |||
408 | nouveau_irq_register(dev, 12, nvc0_graph_isr); | ||
409 | nouveau_irq_register(dev, 25, nvc0_runk140_isr); | ||
410 | NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */ | ||
411 | NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */ | ||
412 | NVOBJ_MTHD (dev, 0x9039, 0x0500, nvc0_graph_mthd_page_flip); | ||
413 | NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */ | ||
414 | NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */ | ||
415 | return 0; | ||
416 | |||
417 | error: | ||
418 | nvc0_graph_destroy(dev); | ||
419 | return ret; | ||
420 | } | ||
421 | |||
422 | static void | 281 | static void |
423 | nvc0_graph_init_obj418880(struct drm_device *dev) | 282 | nvc0_graph_init_obj418880(struct drm_device *dev) |
424 | { | 283 | { |
425 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 284 | struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); |
426 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | ||
427 | struct nvc0_graph_priv *priv = pgraph->priv; | ||
428 | int i; | 285 | int i; |
429 | 286 | ||
430 | nv_wr32(dev, GPC_BCAST(0x0880), 0x00000000); | 287 | nv_wr32(dev, GPC_BCAST(0x0880), 0x00000000); |
@@ -455,8 +312,7 @@ nvc0_graph_init_regs(struct drm_device *dev) | |||
455 | static void | 312 | static void |
456 | nvc0_graph_init_gpc_0(struct drm_device *dev) | 313 | nvc0_graph_init_gpc_0(struct drm_device *dev) |
457 | { | 314 | { |
458 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 315 | struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); |
459 | struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; | ||
460 | int gpc; | 316 | int gpc; |
461 | 317 | ||
462 | /* | 318 | /* |
@@ -517,8 +373,7 @@ nvc0_graph_init_units(struct drm_device *dev) | |||
517 | static void | 373 | static void |
518 | nvc0_graph_init_gpc_1(struct drm_device *dev) | 374 | nvc0_graph_init_gpc_1(struct drm_device *dev) |
519 | { | 375 | { |
520 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 376 | struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); |
521 | struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; | ||
522 | int gpc, tp; | 377 | int gpc, tp; |
523 | 378 | ||
524 | for (gpc = 0; gpc < priv->gpc_nr; gpc++) { | 379 | for (gpc = 0; gpc < priv->gpc_nr; gpc++) { |
@@ -543,8 +398,7 @@ nvc0_graph_init_gpc_1(struct drm_device *dev) | |||
543 | static void | 398 | static void |
544 | nvc0_graph_init_rop(struct drm_device *dev) | 399 | nvc0_graph_init_rop(struct drm_device *dev) |
545 | { | 400 | { |
546 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 401 | struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); |
547 | struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; | ||
548 | int rop; | 402 | int rop; |
549 | 403 | ||
550 | for (rop = 0; rop < priv->rop_nr; rop++) { | 404 | for (rop = 0; rop < priv->rop_nr; rop++) { |
@@ -596,8 +450,7 @@ nvc0_fuc_load_fw(struct drm_device *dev, u32 fuc_base, | |||
596 | static int | 450 | static int |
597 | nvc0_graph_init_ctxctl(struct drm_device *dev) | 451 | nvc0_graph_init_ctxctl(struct drm_device *dev) |
598 | { | 452 | { |
599 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 453 | struct nvc0_graph_priv *priv = nv_engine(dev, NVOBJ_ENGINE_GR); |
600 | struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; | ||
601 | u32 r000260; | 454 | u32 r000260; |
602 | int ret; | 455 | int ret; |
603 | 456 | ||
@@ -652,11 +505,10 @@ nvc0_graph_init_ctxctl(struct drm_device *dev) | |||
652 | return 0; | 505 | return 0; |
653 | } | 506 | } |
654 | 507 | ||
655 | int | 508 | static int |
656 | nvc0_graph_init(struct drm_device *dev) | 509 | nvc0_graph_init(struct drm_device *dev, int engine) |
657 | { | 510 | { |
658 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 511 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
659 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | ||
660 | int ret; | 512 | int ret; |
661 | 513 | ||
662 | dev_priv->engine.graph.accel_blocked = true; | 514 | dev_priv->engine.graph.accel_blocked = true; |
@@ -676,12 +528,6 @@ nvc0_graph_init(struct drm_device *dev) | |||
676 | nv_mask(dev, 0x000200, 0x18001000, 0x00000000); | 528 | nv_mask(dev, 0x000200, 0x18001000, 0x00000000); |
677 | nv_mask(dev, 0x000200, 0x18001000, 0x18001000); | 529 | nv_mask(dev, 0x000200, 0x18001000, 0x18001000); |
678 | 530 | ||
679 | if (!pgraph->priv) { | ||
680 | ret = nvc0_graph_create(dev); | ||
681 | if (ret) | ||
682 | return ret; | ||
683 | } | ||
684 | |||
685 | nvc0_graph_init_obj418880(dev); | 531 | nvc0_graph_init_obj418880(dev); |
686 | nvc0_graph_init_regs(dev); | 532 | nvc0_graph_init_regs(dev); |
687 | /*nvc0_graph_init_unitplemented_magics(dev);*/ | 533 | /*nvc0_graph_init_unitplemented_magics(dev);*/ |
@@ -814,3 +660,135 @@ nvc0_runk140_isr(struct drm_device *dev) | |||
814 | units &= ~(1 << unit); | 660 | units &= ~(1 << unit); |
815 | } | 661 | } |
816 | } | 662 | } |
663 | |||
664 | static void | ||
665 | nvc0_graph_destroy(struct drm_device *dev, int engine) | ||
666 | { | ||
667 | struct nvc0_graph_priv *priv = nv_engine(dev, engine); | ||
668 | |||
669 | nouveau_irq_unregister(dev, 12); | ||
670 | nouveau_irq_unregister(dev, 25); | ||
671 | |||
672 | nouveau_gpuobj_ref(NULL, &priv->unk4188b8); | ||
673 | nouveau_gpuobj_ref(NULL, &priv->unk4188b4); | ||
674 | |||
675 | if (priv->grctx_vals) | ||
676 | kfree(priv->grctx_vals); | ||
677 | |||
678 | NVOBJ_ENGINE_DEL(dev, GR); | ||
679 | kfree(priv); | ||
680 | } | ||
681 | |||
682 | int | ||
683 | nvc0_graph_create(struct drm_device *dev) | ||
684 | { | ||
685 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
686 | struct nvc0_graph_priv *priv; | ||
687 | int ret, gpc, i; | ||
688 | |||
689 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
690 | if (!priv) | ||
691 | return -ENOMEM; | ||
692 | |||
693 | priv->base.destroy = nvc0_graph_destroy; | ||
694 | priv->base.init = nvc0_graph_init; | ||
695 | priv->base.fini = nvc0_graph_fini; | ||
696 | priv->base.context_new = nvc0_graph_context_new; | ||
697 | priv->base.context_del = nvc0_graph_context_del; | ||
698 | priv->base.object_new = nvc0_graph_object_new; | ||
699 | |||
700 | NVOBJ_ENGINE_ADD(dev, GR, &priv->base); | ||
701 | nouveau_irq_register(dev, 12, nvc0_graph_isr); | ||
702 | nouveau_irq_register(dev, 25, nvc0_runk140_isr); | ||
703 | |||
704 | ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b4); | ||
705 | if (ret) | ||
706 | goto error; | ||
707 | |||
708 | ret = nouveau_gpuobj_new(dev, NULL, 0x1000, 256, 0, &priv->unk4188b8); | ||
709 | if (ret) | ||
710 | goto error; | ||
711 | |||
712 | for (i = 0; i < 0x1000; i += 4) { | ||
713 | nv_wo32(priv->unk4188b4, i, 0x00000010); | ||
714 | nv_wo32(priv->unk4188b8, i, 0x00000010); | ||
715 | } | ||
716 | |||
717 | priv->gpc_nr = nv_rd32(dev, 0x409604) & 0x0000001f; | ||
718 | priv->rop_nr = (nv_rd32(dev, 0x409604) & 0x001f0000) >> 16; | ||
719 | for (gpc = 0; gpc < priv->gpc_nr; gpc++) { | ||
720 | priv->tp_nr[gpc] = nv_rd32(dev, GPC_UNIT(gpc, 0x2608)); | ||
721 | priv->tp_total += priv->tp_nr[gpc]; | ||
722 | } | ||
723 | |||
724 | /*XXX: these need figuring out... */ | ||
725 | switch (dev_priv->chipset) { | ||
726 | case 0xc0: | ||
727 | if (priv->tp_total == 11) { /* 465, 3/4/4/0, 4 */ | ||
728 | priv->magic_not_rop_nr = 0x07; | ||
729 | /* filled values up to tp_total, the rest 0 */ | ||
730 | priv->magicgpc980[0] = 0x22111000; | ||
731 | priv->magicgpc980[1] = 0x00000233; | ||
732 | priv->magicgpc980[2] = 0x00000000; | ||
733 | priv->magicgpc980[3] = 0x00000000; | ||
734 | priv->magicgpc918 = 0x000ba2e9; | ||
735 | } else | ||
736 | if (priv->tp_total == 14) { /* 470, 3/3/4/4, 5 */ | ||
737 | priv->magic_not_rop_nr = 0x05; | ||
738 | priv->magicgpc980[0] = 0x11110000; | ||
739 | priv->magicgpc980[1] = 0x00233222; | ||
740 | priv->magicgpc980[2] = 0x00000000; | ||
741 | priv->magicgpc980[3] = 0x00000000; | ||
742 | priv->magicgpc918 = 0x00092493; | ||
743 | } else | ||
744 | if (priv->tp_total == 15) { /* 480, 3/4/4/4, 6 */ | ||
745 | priv->magic_not_rop_nr = 0x06; | ||
746 | priv->magicgpc980[0] = 0x11110000; | ||
747 | priv->magicgpc980[1] = 0x03332222; | ||
748 | priv->magicgpc980[2] = 0x00000000; | ||
749 | priv->magicgpc980[3] = 0x00000000; | ||
750 | priv->magicgpc918 = 0x00088889; | ||
751 | } | ||
752 | break; | ||
753 | case 0xc3: /* 450, 4/0/0/0, 2 */ | ||
754 | priv->magic_not_rop_nr = 0x03; | ||
755 | priv->magicgpc980[0] = 0x00003210; | ||
756 | priv->magicgpc980[1] = 0x00000000; | ||
757 | priv->magicgpc980[2] = 0x00000000; | ||
758 | priv->magicgpc980[3] = 0x00000000; | ||
759 | priv->magicgpc918 = 0x00200000; | ||
760 | break; | ||
761 | case 0xc4: /* 460, 3/4/0/0, 4 */ | ||
762 | priv->magic_not_rop_nr = 0x01; | ||
763 | priv->magicgpc980[0] = 0x02321100; | ||
764 | priv->magicgpc980[1] = 0x00000000; | ||
765 | priv->magicgpc980[2] = 0x00000000; | ||
766 | priv->magicgpc980[3] = 0x00000000; | ||
767 | priv->magicgpc918 = 0x00124925; | ||
768 | break; | ||
769 | } | ||
770 | |||
771 | if (!priv->magic_not_rop_nr) { | ||
772 | NV_ERROR(dev, "PGRAPH: unknown config: %d/%d/%d/%d, %d\n", | ||
773 | priv->tp_nr[0], priv->tp_nr[1], priv->tp_nr[2], | ||
774 | priv->tp_nr[3], priv->rop_nr); | ||
775 | /* use 0xc3's values... */ | ||
776 | priv->magic_not_rop_nr = 0x03; | ||
777 | priv->magicgpc980[0] = 0x00003210; | ||
778 | priv->magicgpc980[1] = 0x00000000; | ||
779 | priv->magicgpc980[2] = 0x00000000; | ||
780 | priv->magicgpc980[3] = 0x00000000; | ||
781 | priv->magicgpc918 = 0x00200000; | ||
782 | } | ||
783 | |||
784 | NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */ | ||
785 | NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */ | ||
786 | NVOBJ_MTHD (dev, 0x9039, 0x0500, nvc0_graph_mthd_page_flip); | ||
787 | NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */ | ||
788 | NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */ | ||
789 | return 0; | ||
790 | |||
791 | error: | ||
792 | nvc0_graph_destroy(dev, NVOBJ_ENGINE_GR); | ||
793 | return ret; | ||
794 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.h b/drivers/gpu/drm/nouveau/nvc0_graph.h index d32b38594a31..fecc187d724c 100644 --- a/drivers/gpu/drm/nouveau/nvc0_graph.h +++ b/drivers/gpu/drm/nouveau/nvc0_graph.h | |||
@@ -35,6 +35,8 @@ | |||
35 | #define TP_UNIT(t, m, r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r)) | 35 | #define TP_UNIT(t, m, r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r)) |
36 | 36 | ||
37 | struct nvc0_graph_priv { | 37 | struct nvc0_graph_priv { |
38 | struct nouveau_exec_engine base; | ||
39 | |||
38 | u8 gpc_nr; | 40 | u8 gpc_nr; |
39 | u8 rop_nr; | 41 | u8 rop_nr; |
40 | u8 tp_nr[GPC_MAX]; | 42 | u8 tp_nr[GPC_MAX]; |
diff --git a/drivers/gpu/drm/nouveau/nvc0_grctx.c b/drivers/gpu/drm/nouveau/nvc0_grctx.c index 6cede9f05c88..6df066114133 100644 --- a/drivers/gpu/drm/nouveau/nvc0_grctx.c +++ b/drivers/gpu/drm/nouveau/nvc0_grctx.c | |||
@@ -1797,8 +1797,8 @@ int | |||
1797 | nvc0_grctx_generate(struct nouveau_channel *chan) | 1797 | nvc0_grctx_generate(struct nouveau_channel *chan) |
1798 | { | 1798 | { |
1799 | struct drm_nouveau_private *dev_priv = chan->dev->dev_private; | 1799 | struct drm_nouveau_private *dev_priv = chan->dev->dev_private; |
1800 | struct nvc0_graph_priv *priv = dev_priv->engine.graph.priv; | 1800 | struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR); |
1801 | struct nvc0_graph_chan *grch = chan->pgraph_ctx; | 1801 | struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR]; |
1802 | struct drm_device *dev = chan->dev; | 1802 | struct drm_device *dev = chan->dev; |
1803 | int i, gpc, tp, id; | 1803 | int i, gpc, tp, id; |
1804 | u32 r000260, tmp; | 1804 | u32 r000260, tmp; |