aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2011-03-31 20:59:53 -0400
committerBen Skeggs <bskeggs@redhat.com>2011-05-15 20:48:09 -0400
commit7a45cd19c95a383d81a7b2f5297958c0c16b5a08 (patch)
tree4a9634d575233e5bfdb9a60f478e7ba6fe99dc19 /drivers/gpu/drm
parent2703c21a82301f5c31ba5679e2d56422bd4cd404 (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.h8
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_state.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_graph.c406
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_graph.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_grctx.c4
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 *);
1194extern struct nouveau_enum nv50_data_error_names[]; 1194extern struct nouveau_enum nv50_data_error_names[];
1195 1195
1196/* nvc0_graph.c */ 1196/* nvc0_graph.c */
1197extern int nvc0_graph_init(struct drm_device *); 1197extern int nvc0_graph_create(struct drm_device *);
1198extern void nvc0_graph_takedown(struct drm_device *);
1199extern void nvc0_graph_fifo_access(struct drm_device *, bool); 1198extern void nvc0_graph_fifo_access(struct drm_device *, bool);
1200extern struct nouveau_channel *nvc0_graph_channel(struct drm_device *); 1199extern struct nouveau_channel *nvc0_graph_channel(struct drm_device *);
1201extern int nvc0_graph_create_context(struct nouveau_channel *);
1202extern void nvc0_graph_destroy_context(struct nouveau_channel *);
1203extern int nvc0_graph_load_context(struct nouveau_channel *);
1204extern int nvc0_graph_unload_context(struct drm_device *);
1205extern int nvc0_graph_object_new(struct nouveau_channel *, u32, u16);
1206 1200
1207/* nv84_crypt.c */ 1201/* nv84_crypt.c */
1208extern int nv84_crypt_create(struct drm_device *); 1202extern 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
33static void nvc0_graph_isr(struct drm_device *);
34static void nvc0_runk140_isr(struct drm_device *);
35static int nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan);
36
37void 33void
38nvc0_graph_fifo_access(struct drm_device *dev, bool enabled) 34nvc0_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
48static int 44static int
45nvc0_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
58static int
59nvc0_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
72static int
49nvc0_graph_construct_context(struct nouveau_channel *chan) 73nvc0_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)
89static int 113static int
90nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan) 114nvc0_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
161int 184static int
162nvc0_graph_create_context(struct nouveau_channel *chan) 185nvc0_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
215error: 236error:
216 pgraph->destroy_context(chan); 237 priv->base.context_del(chan, engine);
217 return ret; 238 return ret;
218} 239}
219 240
220void 241static void
221nvc0_graph_destroy_context(struct nouveau_channel *chan) 242nvc0_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
238int 254static int
239nvc0_graph_load_context(struct nouveau_channel *chan) 255nvc0_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
252static int 261static int
253nvc0_graph_unload_context_to(struct drm_device *dev, u64 chan) 262nvc0_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
266int
267nvc0_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
273int
274nvc0_graph_object_new(struct nouveau_channel *chan, u32 handle, u16 class)
275{
276 return 0;
277}
278
279static void
280nvc0_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
301void
302nvc0_graph_takedown(struct drm_device *dev)
303{
304 nvc0_graph_destroy(dev);
305}
306
307static int 273static int
308nvc0_graph_mthd_page_flip(struct nouveau_channel *chan, 274nvc0_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
315static int
316nvc0_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
417error:
418 nvc0_graph_destroy(dev);
419 return ret;
420}
421
422static void 281static void
423nvc0_graph_init_obj418880(struct drm_device *dev) 282nvc0_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)
455static void 312static void
456nvc0_graph_init_gpc_0(struct drm_device *dev) 313nvc0_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)
517static void 373static void
518nvc0_graph_init_gpc_1(struct drm_device *dev) 374nvc0_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)
543static void 398static void
544nvc0_graph_init_rop(struct drm_device *dev) 399nvc0_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,
596static int 450static int
597nvc0_graph_init_ctxctl(struct drm_device *dev) 451nvc0_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
655int 508static int
656nvc0_graph_init(struct drm_device *dev) 509nvc0_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
664static void
665nvc0_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
682int
683nvc0_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
791error:
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
37struct nvc0_graph_priv { 37struct 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
1797nvc0_grctx_generate(struct nouveau_channel *chan) 1797nvc0_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;