drm/gf100-/gr: fix -ENOSPC detection when allocating zbc table entries
[pandora-kernel.git] / drivers / gpu / drm / nouveau / core / engine / graph / nvc0.c
1 /*
2  * Copyright 2012 Red Hat Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: Ben Skeggs
23  */
24
25 #include "nvc0.h"
26 #include "ctxnvc0.h"
27
28 /*******************************************************************************
29  * Zero Bandwidth Clear
30  ******************************************************************************/
31
32 static void
33 nvc0_graph_zbc_clear_color(struct nvc0_graph_priv *priv, int zbc)
34 {
35         if (priv->zbc_color[zbc].format) {
36                 nv_wr32(priv, 0x405804, priv->zbc_color[zbc].ds[0]);
37                 nv_wr32(priv, 0x405808, priv->zbc_color[zbc].ds[1]);
38                 nv_wr32(priv, 0x40580c, priv->zbc_color[zbc].ds[2]);
39                 nv_wr32(priv, 0x405810, priv->zbc_color[zbc].ds[3]);
40         }
41         nv_wr32(priv, 0x405814, priv->zbc_color[zbc].format);
42         nv_wr32(priv, 0x405820, zbc);
43         nv_wr32(priv, 0x405824, 0x00000004); /* TRIGGER | WRITE | COLOR */
44 }
45
46 static int
47 nvc0_graph_zbc_color_get(struct nvc0_graph_priv *priv, int format,
48                          const u32 ds[4], const u32 l2[4])
49 {
50         struct nouveau_ltc *ltc = nouveau_ltc(priv);
51         int zbc = -ENOSPC, i;
52
53         for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) {
54                 if (priv->zbc_color[i].format) {
55                         if (priv->zbc_color[i].format != format)
56                                 continue;
57                         if (memcmp(priv->zbc_color[i].ds, ds, sizeof(
58                                    priv->zbc_color[i].ds)))
59                                 continue;
60                         if (memcmp(priv->zbc_color[i].l2, l2, sizeof(
61                                    priv->zbc_color[i].l2))) {
62                                 WARN_ON(1);
63                                 return -EINVAL;
64                         }
65                         return i;
66                 } else {
67                         zbc = (zbc < 0) ? i : zbc;
68                 }
69         }
70
71         if (zbc < 0)
72                 return zbc;
73
74         memcpy(priv->zbc_color[zbc].ds, ds, sizeof(priv->zbc_color[zbc].ds));
75         memcpy(priv->zbc_color[zbc].l2, l2, sizeof(priv->zbc_color[zbc].l2));
76         priv->zbc_color[zbc].format = format;
77         ltc->zbc_color_get(ltc, zbc, l2);
78         nvc0_graph_zbc_clear_color(priv, zbc);
79         return zbc;
80 }
81
82 static void
83 nvc0_graph_zbc_clear_depth(struct nvc0_graph_priv *priv, int zbc)
84 {
85         if (priv->zbc_depth[zbc].format)
86                 nv_wr32(priv, 0x405818, priv->zbc_depth[zbc].ds);
87         nv_wr32(priv, 0x40581c, priv->zbc_depth[zbc].format);
88         nv_wr32(priv, 0x405820, zbc);
89         nv_wr32(priv, 0x405824, 0x00000005); /* TRIGGER | WRITE | DEPTH */
90 }
91
92 static int
93 nvc0_graph_zbc_depth_get(struct nvc0_graph_priv *priv, int format,
94                          const u32 ds, const u32 l2)
95 {
96         struct nouveau_ltc *ltc = nouveau_ltc(priv);
97         int zbc = -ENOSPC, i;
98
99         for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) {
100                 if (priv->zbc_depth[i].format) {
101                         if (priv->zbc_depth[i].format != format)
102                                 continue;
103                         if (priv->zbc_depth[i].ds != ds)
104                                 continue;
105                         if (priv->zbc_depth[i].l2 != l2) {
106                                 WARN_ON(1);
107                                 return -EINVAL;
108                         }
109                         return i;
110                 } else {
111                         zbc = (zbc < 0) ? i : zbc;
112                 }
113         }
114
115         if (zbc < 0)
116                 return zbc;
117
118         priv->zbc_depth[zbc].format = format;
119         priv->zbc_depth[zbc].ds = ds;
120         priv->zbc_depth[zbc].l2 = l2;
121         ltc->zbc_depth_get(ltc, zbc, l2);
122         nvc0_graph_zbc_clear_depth(priv, zbc);
123         return zbc;
124 }
125
126 /*******************************************************************************
127  * Graphics object classes
128  ******************************************************************************/
129
130 static int
131 nvc0_fermi_mthd_zbc_color(struct nouveau_object *object, void *data, u32 size)
132 {
133         struct nvc0_graph_priv *priv = (void *)object->engine;
134         union {
135                 struct fermi_a_zbc_color_v0 v0;
136         } *args = data;
137         int ret;
138
139         if (nvif_unpack(args->v0, 0, 0, false)) {
140                 switch (args->v0.format) {
141                 case FERMI_A_ZBC_COLOR_V0_FMT_ZERO:
142                 case FERMI_A_ZBC_COLOR_V0_FMT_UNORM_ONE:
143                 case FERMI_A_ZBC_COLOR_V0_FMT_RF32_GF32_BF32_AF32:
144                 case FERMI_A_ZBC_COLOR_V0_FMT_R16_G16_B16_A16:
145                 case FERMI_A_ZBC_COLOR_V0_FMT_RN16_GN16_BN16_AN16:
146                 case FERMI_A_ZBC_COLOR_V0_FMT_RS16_GS16_BS16_AS16:
147                 case FERMI_A_ZBC_COLOR_V0_FMT_RU16_GU16_BU16_AU16:
148                 case FERMI_A_ZBC_COLOR_V0_FMT_RF16_GF16_BF16_AF16:
149                 case FERMI_A_ZBC_COLOR_V0_FMT_A8R8G8B8:
150                 case FERMI_A_ZBC_COLOR_V0_FMT_A8RL8GL8BL8:
151                 case FERMI_A_ZBC_COLOR_V0_FMT_A2B10G10R10:
152                 case FERMI_A_ZBC_COLOR_V0_FMT_AU2BU10GU10RU10:
153                 case FERMI_A_ZBC_COLOR_V0_FMT_A8B8G8R8:
154                 case FERMI_A_ZBC_COLOR_V0_FMT_A8BL8GL8RL8:
155                 case FERMI_A_ZBC_COLOR_V0_FMT_AN8BN8GN8RN8:
156                 case FERMI_A_ZBC_COLOR_V0_FMT_AS8BS8GS8RS8:
157                 case FERMI_A_ZBC_COLOR_V0_FMT_AU8BU8GU8RU8:
158                 case FERMI_A_ZBC_COLOR_V0_FMT_A2R10G10B10:
159                 case FERMI_A_ZBC_COLOR_V0_FMT_BF10GF11RF11:
160                         ret = nvc0_graph_zbc_color_get(priv, args->v0.format,
161                                                              args->v0.ds,
162                                                              args->v0.l2);
163                         if (ret >= 0) {
164                                 args->v0.index = ret;
165                                 return 0;
166                         }
167                         break;
168                 default:
169                         return -EINVAL;
170                 }
171         }
172
173         return ret;
174 }
175
176 static int
177 nvc0_fermi_mthd_zbc_depth(struct nouveau_object *object, void *data, u32 size)
178 {
179         struct nvc0_graph_priv *priv = (void *)object->engine;
180         union {
181                 struct fermi_a_zbc_depth_v0 v0;
182         } *args = data;
183         int ret;
184
185         if (nvif_unpack(args->v0, 0, 0, false)) {
186                 switch (args->v0.format) {
187                 case FERMI_A_ZBC_DEPTH_V0_FMT_FP32:
188                         ret = nvc0_graph_zbc_depth_get(priv, args->v0.format,
189                                                              args->v0.ds,
190                                                              args->v0.l2);
191                         return (ret >= 0) ? 0 : -ENOSPC;
192                 default:
193                         return -EINVAL;
194                 }
195         }
196
197         return ret;
198 }
199
200 static int
201 nvc0_fermi_mthd(struct nouveau_object *object, u32 mthd, void *data, u32 size)
202 {
203         switch (mthd) {
204         case FERMI_A_ZBC_COLOR:
205                 return nvc0_fermi_mthd_zbc_color(object, data, size);
206         case FERMI_A_ZBC_DEPTH:
207                 return nvc0_fermi_mthd_zbc_depth(object, data, size);
208         default:
209                 break;
210         }
211         return -EINVAL;
212 }
213
214 struct nouveau_ofuncs
215 nvc0_fermi_ofuncs = {
216         .ctor = _nouveau_object_ctor,
217         .dtor = nouveau_object_destroy,
218         .init = nouveau_object_init,
219         .fini = nouveau_object_fini,
220         .mthd = nvc0_fermi_mthd,
221 };
222
223 static int
224 nvc0_graph_set_shader_exceptions(struct nouveau_object *object, u32 mthd,
225                                  void *pdata, u32 size)
226 {
227         struct nvc0_graph_priv *priv = (void *)nv_engine(object);
228         if (size >= sizeof(u32)) {
229                 u32 data = *(u32 *)pdata ? 0xffffffff : 0x00000000;
230                 nv_wr32(priv, 0x419e44, data);
231                 nv_wr32(priv, 0x419e4c, data);
232                 return 0;
233         }
234         return -EINVAL;
235 }
236
237 struct nouveau_omthds
238 nvc0_graph_9097_omthds[] = {
239         { 0x1528, 0x1528, nvc0_graph_set_shader_exceptions },
240         {}
241 };
242
243 struct nouveau_omthds
244 nvc0_graph_90c0_omthds[] = {
245         { 0x1528, 0x1528, nvc0_graph_set_shader_exceptions },
246         {}
247 };
248
249 struct nouveau_oclass
250 nvc0_graph_sclass[] = {
251         { 0x902d, &nouveau_object_ofuncs },
252         { 0x9039, &nouveau_object_ofuncs },
253         { FERMI_A, &nvc0_fermi_ofuncs, nvc0_graph_9097_omthds },
254         { FERMI_COMPUTE_A, &nouveau_object_ofuncs, nvc0_graph_90c0_omthds },
255         {}
256 };
257
258 /*******************************************************************************
259  * PGRAPH context
260  ******************************************************************************/
261
262 int
263 nvc0_graph_context_ctor(struct nouveau_object *parent,
264                         struct nouveau_object *engine,
265                         struct nouveau_oclass *oclass, void *args, u32 size,
266                         struct nouveau_object **pobject)
267 {
268         struct nouveau_vm *vm = nouveau_client(parent)->vm;
269         struct nvc0_graph_priv *priv = (void *)engine;
270         struct nvc0_graph_data *data = priv->mmio_data;
271         struct nvc0_graph_mmio *mmio = priv->mmio_list;
272         struct nvc0_graph_chan *chan;
273         int ret, i;
274
275         /* allocate memory for context, and fill with default values */
276         ret = nouveau_graph_context_create(parent, engine, oclass, NULL,
277                                            priv->size, 0x100,
278                                            NVOBJ_FLAG_ZERO_ALLOC, &chan);
279         *pobject = nv_object(chan);
280         if (ret)
281                 return ret;
282
283         /* allocate memory for a "mmio list" buffer that's used by the HUB
284          * fuc to modify some per-context register settings on first load
285          * of the context.
286          */
287         ret = nouveau_gpuobj_new(nv_object(chan), NULL, 0x1000, 0x100, 0,
288                                 &chan->mmio);
289         if (ret)
290                 return ret;
291
292         ret = nouveau_gpuobj_map_vm(nv_gpuobj(chan->mmio), vm,
293                                     NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS,
294                                     &chan->mmio_vma);
295         if (ret)
296                 return ret;
297
298         /* allocate buffers referenced by mmio list */
299         for (i = 0; data->size && i < ARRAY_SIZE(priv->mmio_data); i++) {
300                 ret = nouveau_gpuobj_new(nv_object(chan), NULL, data->size,
301                                          data->align, 0, &chan->data[i].mem);
302                 if (ret)
303                         return ret;
304
305                 ret = nouveau_gpuobj_map_vm(chan->data[i].mem, vm, data->access,
306                                            &chan->data[i].vma);
307                 if (ret)
308                         return ret;
309
310                 data++;
311         }
312
313         /* finally, fill in the mmio list and point the context at it */
314         for (i = 0; mmio->addr && i < ARRAY_SIZE(priv->mmio_list); i++) {
315                 u32 addr = mmio->addr;
316                 u32 data = mmio->data;
317
318                 if (mmio->buffer >= 0) {
319                         u64 info = chan->data[mmio->buffer].vma.offset;
320                         data |= info >> mmio->shift;
321                 }
322
323                 nv_wo32(chan->mmio, chan->mmio_nr++ * 4, addr);
324                 nv_wo32(chan->mmio, chan->mmio_nr++ * 4, data);
325                 mmio++;
326         }
327
328         for (i = 0; i < priv->size; i += 4)
329                 nv_wo32(chan, i, priv->data[i / 4]);
330
331         if (!priv->firmware) {
332                 nv_wo32(chan, 0x00, chan->mmio_nr / 2);
333                 nv_wo32(chan, 0x04, chan->mmio_vma.offset >> 8);
334         } else {
335                 nv_wo32(chan, 0xf4, 0);
336                 nv_wo32(chan, 0xf8, 0);
337                 nv_wo32(chan, 0x10, chan->mmio_nr / 2);
338                 nv_wo32(chan, 0x14, lower_32_bits(chan->mmio_vma.offset));
339                 nv_wo32(chan, 0x18, upper_32_bits(chan->mmio_vma.offset));
340                 nv_wo32(chan, 0x1c, 1);
341                 nv_wo32(chan, 0x20, 0);
342                 nv_wo32(chan, 0x28, 0);
343                 nv_wo32(chan, 0x2c, 0);
344         }
345
346         return 0;
347 }
348
349 void
350 nvc0_graph_context_dtor(struct nouveau_object *object)
351 {
352         struct nvc0_graph_chan *chan = (void *)object;
353         int i;
354
355         for (i = 0; i < ARRAY_SIZE(chan->data); i++) {
356                 nouveau_gpuobj_unmap(&chan->data[i].vma);
357                 nouveau_gpuobj_ref(NULL, &chan->data[i].mem);
358         }
359
360         nouveau_gpuobj_unmap(&chan->mmio_vma);
361         nouveau_gpuobj_ref(NULL, &chan->mmio);
362
363         nouveau_graph_context_destroy(&chan->base);
364 }
365
366 /*******************************************************************************
367  * PGRAPH register lists
368  ******************************************************************************/
369
370 const struct nvc0_graph_init
371 nvc0_graph_init_main_0[] = {
372         { 0x400080,   1, 0x04, 0x003083c2 },
373         { 0x400088,   1, 0x04, 0x00006fe7 },
374         { 0x40008c,   1, 0x04, 0x00000000 },
375         { 0x400090,   1, 0x04, 0x00000030 },
376         { 0x40013c,   1, 0x04, 0x013901f7 },
377         { 0x400140,   1, 0x04, 0x00000100 },
378         { 0x400144,   1, 0x04, 0x00000000 },
379         { 0x400148,   1, 0x04, 0x00000110 },
380         { 0x400138,   1, 0x04, 0x00000000 },
381         { 0x400130,   2, 0x04, 0x00000000 },
382         { 0x400124,   1, 0x04, 0x00000002 },
383         {}
384 };
385
386 const struct nvc0_graph_init
387 nvc0_graph_init_fe_0[] = {
388         { 0x40415c,   1, 0x04, 0x00000000 },
389         { 0x404170,   1, 0x04, 0x00000000 },
390         {}
391 };
392
393 const struct nvc0_graph_init
394 nvc0_graph_init_pri_0[] = {
395         { 0x404488,   2, 0x04, 0x00000000 },
396         {}
397 };
398
399 const struct nvc0_graph_init
400 nvc0_graph_init_rstr2d_0[] = {
401         { 0x407808,   1, 0x04, 0x00000000 },
402         {}
403 };
404
405 const struct nvc0_graph_init
406 nvc0_graph_init_pd_0[] = {
407         { 0x406024,   1, 0x04, 0x00000000 },
408         {}
409 };
410
411 const struct nvc0_graph_init
412 nvc0_graph_init_ds_0[] = {
413         { 0x405844,   1, 0x04, 0x00ffffff },
414         { 0x405850,   1, 0x04, 0x00000000 },
415         { 0x405908,   1, 0x04, 0x00000000 },
416         {}
417 };
418
419 const struct nvc0_graph_init
420 nvc0_graph_init_scc_0[] = {
421         { 0x40803c,   1, 0x04, 0x00000000 },
422         {}
423 };
424
425 const struct nvc0_graph_init
426 nvc0_graph_init_prop_0[] = {
427         { 0x4184a0,   1, 0x04, 0x00000000 },
428         {}
429 };
430
431 const struct nvc0_graph_init
432 nvc0_graph_init_gpc_unk_0[] = {
433         { 0x418604,   1, 0x04, 0x00000000 },
434         { 0x418680,   1, 0x04, 0x00000000 },
435         { 0x418714,   1, 0x04, 0x80000000 },
436         { 0x418384,   1, 0x04, 0x00000000 },
437         {}
438 };
439
440 const struct nvc0_graph_init
441 nvc0_graph_init_setup_0[] = {
442         { 0x418814,   3, 0x04, 0x00000000 },
443         {}
444 };
445
446 const struct nvc0_graph_init
447 nvc0_graph_init_crstr_0[] = {
448         { 0x418b04,   1, 0x04, 0x00000000 },
449         {}
450 };
451
452 const struct nvc0_graph_init
453 nvc0_graph_init_setup_1[] = {
454         { 0x4188c8,   1, 0x04, 0x80000000 },
455         { 0x4188cc,   1, 0x04, 0x00000000 },
456         { 0x4188d0,   1, 0x04, 0x00010000 },
457         { 0x4188d4,   1, 0x04, 0x00000001 },
458         {}
459 };
460
461 const struct nvc0_graph_init
462 nvc0_graph_init_zcull_0[] = {
463         { 0x418910,   1, 0x04, 0x00010001 },
464         { 0x418914,   1, 0x04, 0x00000301 },
465         { 0x418918,   1, 0x04, 0x00800000 },
466         { 0x418980,   1, 0x04, 0x77777770 },
467         { 0x418984,   3, 0x04, 0x77777777 },
468         {}
469 };
470
471 const struct nvc0_graph_init
472 nvc0_graph_init_gpm_0[] = {
473         { 0x418c04,   1, 0x04, 0x00000000 },
474         { 0x418c88,   1, 0x04, 0x00000000 },
475         {}
476 };
477
478 const struct nvc0_graph_init
479 nvc0_graph_init_gpc_unk_1[] = {
480         { 0x418d00,   1, 0x04, 0x00000000 },
481         { 0x418f08,   1, 0x04, 0x00000000 },
482         { 0x418e00,   1, 0x04, 0x00000050 },
483         { 0x418e08,   1, 0x04, 0x00000000 },
484         {}
485 };
486
487 const struct nvc0_graph_init
488 nvc0_graph_init_gcc_0[] = {
489         { 0x41900c,   1, 0x04, 0x00000000 },
490         { 0x419018,   1, 0x04, 0x00000000 },
491         {}
492 };
493
494 const struct nvc0_graph_init
495 nvc0_graph_init_tpccs_0[] = {
496         { 0x419d08,   2, 0x04, 0x00000000 },
497         { 0x419d10,   1, 0x04, 0x00000014 },
498         {}
499 };
500
501 const struct nvc0_graph_init
502 nvc0_graph_init_tex_0[] = {
503         { 0x419ab0,   1, 0x04, 0x00000000 },
504         { 0x419ab8,   1, 0x04, 0x000000e7 },
505         { 0x419abc,   2, 0x04, 0x00000000 },
506         {}
507 };
508
509 const struct nvc0_graph_init
510 nvc0_graph_init_pe_0[] = {
511         { 0x41980c,   3, 0x04, 0x00000000 },
512         { 0x419844,   1, 0x04, 0x00000000 },
513         { 0x41984c,   1, 0x04, 0x00005bc5 },
514         { 0x419850,   4, 0x04, 0x00000000 },
515         {}
516 };
517
518 const struct nvc0_graph_init
519 nvc0_graph_init_l1c_0[] = {
520         { 0x419c98,   1, 0x04, 0x00000000 },
521         { 0x419ca8,   1, 0x04, 0x80000000 },
522         { 0x419cb4,   1, 0x04, 0x00000000 },
523         { 0x419cb8,   1, 0x04, 0x00008bf4 },
524         { 0x419cbc,   1, 0x04, 0x28137606 },
525         { 0x419cc0,   2, 0x04, 0x00000000 },
526         {}
527 };
528
529 const struct nvc0_graph_init
530 nvc0_graph_init_wwdx_0[] = {
531         { 0x419bd4,   1, 0x04, 0x00800000 },
532         { 0x419bdc,   1, 0x04, 0x00000000 },
533         {}
534 };
535
536 const struct nvc0_graph_init
537 nvc0_graph_init_tpccs_1[] = {
538         { 0x419d2c,   1, 0x04, 0x00000000 },
539         {}
540 };
541
542 const struct nvc0_graph_init
543 nvc0_graph_init_mpc_0[] = {
544         { 0x419c0c,   1, 0x04, 0x00000000 },
545         {}
546 };
547
548 static const struct nvc0_graph_init
549 nvc0_graph_init_sm_0[] = {
550         { 0x419e00,   1, 0x04, 0x00000000 },
551         { 0x419ea0,   1, 0x04, 0x00000000 },
552         { 0x419ea4,   1, 0x04, 0x00000100 },
553         { 0x419ea8,   1, 0x04, 0x00001100 },
554         { 0x419eac,   1, 0x04, 0x11100702 },
555         { 0x419eb0,   1, 0x04, 0x00000003 },
556         { 0x419eb4,   4, 0x04, 0x00000000 },
557         { 0x419ec8,   1, 0x04, 0x06060618 },
558         { 0x419ed0,   1, 0x04, 0x0eff0e38 },
559         { 0x419ed4,   1, 0x04, 0x011104f1 },
560         { 0x419edc,   1, 0x04, 0x00000000 },
561         { 0x419f00,   1, 0x04, 0x00000000 },
562         { 0x419f2c,   1, 0x04, 0x00000000 },
563         {}
564 };
565
566 const struct nvc0_graph_init
567 nvc0_graph_init_be_0[] = {
568         { 0x40880c,   1, 0x04, 0x00000000 },
569         { 0x408910,   9, 0x04, 0x00000000 },
570         { 0x408950,   1, 0x04, 0x00000000 },
571         { 0x408954,   1, 0x04, 0x0000ffff },
572         { 0x408984,   1, 0x04, 0x00000000 },
573         { 0x408988,   1, 0x04, 0x08040201 },
574         { 0x40898c,   1, 0x04, 0x80402010 },
575         {}
576 };
577
578 const struct nvc0_graph_init
579 nvc0_graph_init_fe_1[] = {
580         { 0x4040f0,   1, 0x04, 0x00000000 },
581         {}
582 };
583
584 const struct nvc0_graph_init
585 nvc0_graph_init_pe_1[] = {
586         { 0x419880,   1, 0x04, 0x00000002 },
587         {}
588 };
589
590 static const struct nvc0_graph_pack
591 nvc0_graph_pack_mmio[] = {
592         { nvc0_graph_init_main_0 },
593         { nvc0_graph_init_fe_0 },
594         { nvc0_graph_init_pri_0 },
595         { nvc0_graph_init_rstr2d_0 },
596         { nvc0_graph_init_pd_0 },
597         { nvc0_graph_init_ds_0 },
598         { nvc0_graph_init_scc_0 },
599         { nvc0_graph_init_prop_0 },
600         { nvc0_graph_init_gpc_unk_0 },
601         { nvc0_graph_init_setup_0 },
602         { nvc0_graph_init_crstr_0 },
603         { nvc0_graph_init_setup_1 },
604         { nvc0_graph_init_zcull_0 },
605         { nvc0_graph_init_gpm_0 },
606         { nvc0_graph_init_gpc_unk_1 },
607         { nvc0_graph_init_gcc_0 },
608         { nvc0_graph_init_tpccs_0 },
609         { nvc0_graph_init_tex_0 },
610         { nvc0_graph_init_pe_0 },
611         { nvc0_graph_init_l1c_0 },
612         { nvc0_graph_init_wwdx_0 },
613         { nvc0_graph_init_tpccs_1 },
614         { nvc0_graph_init_mpc_0 },
615         { nvc0_graph_init_sm_0 },
616         { nvc0_graph_init_be_0 },
617         { nvc0_graph_init_fe_1 },
618         { nvc0_graph_init_pe_1 },
619         {}
620 };
621
622 /*******************************************************************************
623  * PGRAPH engine/subdev functions
624  ******************************************************************************/
625
626 void
627 nvc0_graph_zbc_init(struct nvc0_graph_priv *priv)
628 {
629         const u32  zero[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000,
630                               0x00000000, 0x00000000, 0x00000000, 0x00000000 };
631         const u32   one[] = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
632                               0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff };
633         const u32 f32_0[] = { 0x00000000, 0x00000000, 0x00000000, 0x00000000,
634                               0x00000000, 0x00000000, 0x00000000, 0x00000000 };
635         const u32 f32_1[] = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
636                               0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000 };
637         struct nouveau_ltc *ltc = nouveau_ltc(priv);
638         int index;
639
640         if (!priv->zbc_color[0].format) {
641                 nvc0_graph_zbc_color_get(priv, 1,  & zero[0],   &zero[4]);
642                 nvc0_graph_zbc_color_get(priv, 2,  &  one[0],    &one[4]);
643                 nvc0_graph_zbc_color_get(priv, 4,  &f32_0[0],  &f32_0[4]);
644                 nvc0_graph_zbc_color_get(priv, 4,  &f32_1[0],  &f32_1[4]);
645                 nvc0_graph_zbc_depth_get(priv, 1, 0x00000000, 0x00000000);
646                 nvc0_graph_zbc_depth_get(priv, 1, 0x3f800000, 0x3f800000);
647         }
648
649         for (index = ltc->zbc_min; index <= ltc->zbc_max; index++)
650                 nvc0_graph_zbc_clear_color(priv, index);
651         for (index = ltc->zbc_min; index <= ltc->zbc_max; index++)
652                 nvc0_graph_zbc_clear_depth(priv, index);
653 }
654
655 void
656 nvc0_graph_mmio(struct nvc0_graph_priv *priv, const struct nvc0_graph_pack *p)
657 {
658         const struct nvc0_graph_pack *pack;
659         const struct nvc0_graph_init *init;
660
661         pack_for_each_init(init, pack, p) {
662                 u32 next = init->addr + init->count * init->pitch;
663                 u32 addr = init->addr;
664                 while (addr < next) {
665                         nv_wr32(priv, addr, init->data);
666                         addr += init->pitch;
667                 }
668         }
669 }
670
671 void
672 nvc0_graph_icmd(struct nvc0_graph_priv *priv, const struct nvc0_graph_pack *p)
673 {
674         const struct nvc0_graph_pack *pack;
675         const struct nvc0_graph_init *init;
676         u32 data = 0;
677
678         nv_wr32(priv, 0x400208, 0x80000000);
679
680         pack_for_each_init(init, pack, p) {
681                 u32 next = init->addr + init->count * init->pitch;
682                 u32 addr = init->addr;
683
684                 if ((pack == p && init == p->init) || data != init->data) {
685                         nv_wr32(priv, 0x400204, init->data);
686                         data = init->data;
687                 }
688
689                 while (addr < next) {
690                         nv_wr32(priv, 0x400200, addr);
691                         nv_wait(priv, 0x400700, 0x00000002, 0x00000000);
692                         addr += init->pitch;
693                 }
694         }
695
696         nv_wr32(priv, 0x400208, 0x00000000);
697 }
698
699 void
700 nvc0_graph_mthd(struct nvc0_graph_priv *priv, const struct nvc0_graph_pack *p)
701 {
702         const struct nvc0_graph_pack *pack;
703         const struct nvc0_graph_init *init;
704         u32 data = 0;
705
706         pack_for_each_init(init, pack, p) {
707                 u32 ctrl = 0x80000000 | pack->type;
708                 u32 next = init->addr + init->count * init->pitch;
709                 u32 addr = init->addr;
710
711                 if ((pack == p && init == p->init) || data != init->data) {
712                         nv_wr32(priv, 0x40448c, init->data);
713                         data = init->data;
714                 }
715
716                 while (addr < next) {
717                         nv_wr32(priv, 0x404488, ctrl | (addr << 14));
718                         addr += init->pitch;
719                 }
720         }
721 }
722
723 u64
724 nvc0_graph_units(struct nouveau_graph *graph)
725 {
726         struct nvc0_graph_priv *priv = (void *)graph;
727         u64 cfg;
728
729         cfg  = (u32)priv->gpc_nr;
730         cfg |= (u32)priv->tpc_total << 8;
731         cfg |= (u64)priv->rop_nr << 32;
732
733         return cfg;
734 }
735
736 static const struct nouveau_enum nve0_sked_error[] = {
737         { 7, "CONSTANT_BUFFER_SIZE" },
738         { 9, "LOCAL_MEMORY_SIZE_POS" },
739         { 10, "LOCAL_MEMORY_SIZE_NEG" },
740         { 11, "WARP_CSTACK_SIZE" },
741         { 12, "TOTAL_TEMP_SIZE" },
742         { 13, "REGISTER_COUNT" },
743         { 18, "TOTAL_THREADS" },
744         { 20, "PROGRAM_OFFSET" },
745         { 21, "SHARED_MEMORY_SIZE" },
746         { 25, "SHARED_CONFIG_TOO_SMALL" },
747         { 26, "TOTAL_REGISTER_COUNT" },
748         {}
749 };
750
751 static const struct nouveau_enum nvc0_gpc_rop_error[] = {
752         { 1, "RT_PITCH_OVERRUN" },
753         { 4, "RT_WIDTH_OVERRUN" },
754         { 5, "RT_HEIGHT_OVERRUN" },
755         { 7, "ZETA_STORAGE_TYPE_MISMATCH" },
756         { 8, "RT_STORAGE_TYPE_MISMATCH" },
757         { 10, "RT_LINEAR_MISMATCH" },
758         {}
759 };
760
761 static void
762 nvc0_graph_trap_gpc_rop(struct nvc0_graph_priv *priv, int gpc)
763 {
764         u32 trap[4];
765         int i;
766
767         trap[0] = nv_rd32(priv, GPC_UNIT(gpc, 0x0420));
768         trap[1] = nv_rd32(priv, GPC_UNIT(gpc, 0x0434));
769         trap[2] = nv_rd32(priv, GPC_UNIT(gpc, 0x0438));
770         trap[3] = nv_rd32(priv, GPC_UNIT(gpc, 0x043c));
771
772         nv_error(priv, "GPC%d/PROP trap:", gpc);
773         for (i = 0; i <= 29; ++i) {
774                 if (!(trap[0] & (1 << i)))
775                         continue;
776                 pr_cont(" ");
777                 nouveau_enum_print(nvc0_gpc_rop_error, i);
778         }
779         pr_cont("\n");
780
781         nv_error(priv, "x = %u, y = %u, format = %x, storage type = %x\n",
782                  trap[1] & 0xffff, trap[1] >> 16, (trap[2] >> 8) & 0x3f,
783                  trap[3] & 0xff);
784         nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000);
785 }
786
787 static const struct nouveau_enum nvc0_mp_warp_error[] = {
788         { 0x00, "NO_ERROR" },
789         { 0x01, "STACK_MISMATCH" },
790         { 0x05, "MISALIGNED_PC" },
791         { 0x08, "MISALIGNED_GPR" },
792         { 0x09, "INVALID_OPCODE" },
793         { 0x0d, "GPR_OUT_OF_BOUNDS" },
794         { 0x0e, "MEM_OUT_OF_BOUNDS" },
795         { 0x0f, "UNALIGNED_MEM_ACCESS" },
796         { 0x11, "INVALID_PARAM" },
797         {}
798 };
799
800 static const struct nouveau_bitfield nvc0_mp_global_error[] = {
801         { 0x00000004, "MULTIPLE_WARP_ERRORS" },
802         { 0x00000008, "OUT_OF_STACK_SPACE" },
803         {}
804 };
805
806 static void
807 nvc0_graph_trap_mp(struct nvc0_graph_priv *priv, int gpc, int tpc)
808 {
809         u32 werr = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x648));
810         u32 gerr = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x650));
811
812         nv_error(priv, "GPC%i/TPC%i/MP trap:", gpc, tpc);
813         nouveau_bitfield_print(nvc0_mp_global_error, gerr);
814         if (werr) {
815                 pr_cont(" ");
816                 nouveau_enum_print(nvc0_mp_warp_error, werr & 0xffff);
817         }
818         pr_cont("\n");
819
820         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x648), 0x00000000);
821         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x650), gerr);
822 }
823
824 static void
825 nvc0_graph_trap_tpc(struct nvc0_graph_priv *priv, int gpc, int tpc)
826 {
827         u32 stat = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x0508));
828
829         if (stat & 0x00000001) {
830                 u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x0224));
831                 nv_error(priv, "GPC%d/TPC%d/TEX: 0x%08x\n", gpc, tpc, trap);
832                 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0224), 0xc0000000);
833                 stat &= ~0x00000001;
834         }
835
836         if (stat & 0x00000002) {
837                 nvc0_graph_trap_mp(priv, gpc, tpc);
838                 stat &= ~0x00000002;
839         }
840
841         if (stat & 0x00000004) {
842                 u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x0084));
843                 nv_error(priv, "GPC%d/TPC%d/POLY: 0x%08x\n", gpc, tpc, trap);
844                 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x0084), 0xc0000000);
845                 stat &= ~0x00000004;
846         }
847
848         if (stat & 0x00000008) {
849                 u32 trap = nv_rd32(priv, TPC_UNIT(gpc, tpc, 0x048c));
850                 nv_error(priv, "GPC%d/TPC%d/L1C: 0x%08x\n", gpc, tpc, trap);
851                 nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x048c), 0xc0000000);
852                 stat &= ~0x00000008;
853         }
854
855         if (stat) {
856                 nv_error(priv, "GPC%d/TPC%d/0x%08x: unknown\n", gpc, tpc, stat);
857         }
858 }
859
860 static void
861 nvc0_graph_trap_gpc(struct nvc0_graph_priv *priv, int gpc)
862 {
863         u32 stat = nv_rd32(priv, GPC_UNIT(gpc, 0x2c90));
864         int tpc;
865
866         if (stat & 0x00000001) {
867                 nvc0_graph_trap_gpc_rop(priv, gpc);
868                 stat &= ~0x00000001;
869         }
870
871         if (stat & 0x00000002) {
872                 u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x0900));
873                 nv_error(priv, "GPC%d/ZCULL: 0x%08x\n", gpc, trap);
874                 nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000);
875                 stat &= ~0x00000002;
876         }
877
878         if (stat & 0x00000004) {
879                 u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x1028));
880                 nv_error(priv, "GPC%d/CCACHE: 0x%08x\n", gpc, trap);
881                 nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000);
882                 stat &= ~0x00000004;
883         }
884
885         if (stat & 0x00000008) {
886                 u32 trap = nv_rd32(priv, GPC_UNIT(gpc, 0x0824));
887                 nv_error(priv, "GPC%d/ESETUP: 0x%08x\n", gpc, trap);
888                 nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000);
889                 stat &= ~0x00000009;
890         }
891
892         for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
893                 u32 mask = 0x00010000 << tpc;
894                 if (stat & mask) {
895                         nvc0_graph_trap_tpc(priv, gpc, tpc);
896                         nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), mask);
897                         stat &= ~mask;
898                 }
899         }
900
901         if (stat) {
902                 nv_error(priv, "GPC%d/0x%08x: unknown\n", gpc, stat);
903         }
904 }
905
906 static void
907 nvc0_graph_trap_intr(struct nvc0_graph_priv *priv)
908 {
909         u32 trap = nv_rd32(priv, 0x400108);
910         int rop, gpc, i;
911
912         if (trap & 0x00000001) {
913                 u32 stat = nv_rd32(priv, 0x404000);
914                 nv_error(priv, "DISPATCH 0x%08x\n", stat);
915                 nv_wr32(priv, 0x404000, 0xc0000000);
916                 nv_wr32(priv, 0x400108, 0x00000001);
917                 trap &= ~0x00000001;
918         }
919
920         if (trap & 0x00000002) {
921                 u32 stat = nv_rd32(priv, 0x404600);
922                 nv_error(priv, "M2MF 0x%08x\n", stat);
923                 nv_wr32(priv, 0x404600, 0xc0000000);
924                 nv_wr32(priv, 0x400108, 0x00000002);
925                 trap &= ~0x00000002;
926         }
927
928         if (trap & 0x00000008) {
929                 u32 stat = nv_rd32(priv, 0x408030);
930                 nv_error(priv, "CCACHE 0x%08x\n", stat);
931                 nv_wr32(priv, 0x408030, 0xc0000000);
932                 nv_wr32(priv, 0x400108, 0x00000008);
933                 trap &= ~0x00000008;
934         }
935
936         if (trap & 0x00000010) {
937                 u32 stat = nv_rd32(priv, 0x405840);
938                 nv_error(priv, "SHADER 0x%08x\n", stat);
939                 nv_wr32(priv, 0x405840, 0xc0000000);
940                 nv_wr32(priv, 0x400108, 0x00000010);
941                 trap &= ~0x00000010;
942         }
943
944         if (trap & 0x00000040) {
945                 u32 stat = nv_rd32(priv, 0x40601c);
946                 nv_error(priv, "UNK6 0x%08x\n", stat);
947                 nv_wr32(priv, 0x40601c, 0xc0000000);
948                 nv_wr32(priv, 0x400108, 0x00000040);
949                 trap &= ~0x00000040;
950         }
951
952         if (trap & 0x00000080) {
953                 u32 stat = nv_rd32(priv, 0x404490);
954                 nv_error(priv, "MACRO 0x%08x\n", stat);
955                 nv_wr32(priv, 0x404490, 0xc0000000);
956                 nv_wr32(priv, 0x400108, 0x00000080);
957                 trap &= ~0x00000080;
958         }
959
960         if (trap & 0x00000100) {
961                 u32 stat = nv_rd32(priv, 0x407020);
962
963                 nv_error(priv, "SKED:");
964                 for (i = 0; i <= 29; ++i) {
965                         if (!(stat & (1 << i)))
966                                 continue;
967                         pr_cont(" ");
968                         nouveau_enum_print(nve0_sked_error, i);
969                 }
970                 pr_cont("\n");
971
972                 if (stat & 0x3fffffff)
973                         nv_wr32(priv, 0x407020, 0x40000000);
974                 nv_wr32(priv, 0x400108, 0x00000100);
975                 trap &= ~0x00000100;
976         }
977
978         if (trap & 0x01000000) {
979                 u32 stat = nv_rd32(priv, 0x400118);
980                 for (gpc = 0; stat && gpc < priv->gpc_nr; gpc++) {
981                         u32 mask = 0x00000001 << gpc;
982                         if (stat & mask) {
983                                 nvc0_graph_trap_gpc(priv, gpc);
984                                 nv_wr32(priv, 0x400118, mask);
985                                 stat &= ~mask;
986                         }
987                 }
988                 nv_wr32(priv, 0x400108, 0x01000000);
989                 trap &= ~0x01000000;
990         }
991
992         if (trap & 0x02000000) {
993                 for (rop = 0; rop < priv->rop_nr; rop++) {
994                         u32 statz = nv_rd32(priv, ROP_UNIT(rop, 0x070));
995                         u32 statc = nv_rd32(priv, ROP_UNIT(rop, 0x144));
996                         nv_error(priv, "ROP%d 0x%08x 0x%08x\n",
997                                  rop, statz, statc);
998                         nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000);
999                         nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000);
1000                 }
1001                 nv_wr32(priv, 0x400108, 0x02000000);
1002                 trap &= ~0x02000000;
1003         }
1004
1005         if (trap) {
1006                 nv_error(priv, "TRAP UNHANDLED 0x%08x\n", trap);
1007                 nv_wr32(priv, 0x400108, trap);
1008         }
1009 }
1010
1011 static void
1012 nvc0_graph_ctxctl_debug_unit(struct nvc0_graph_priv *priv, u32 base)
1013 {
1014         nv_error(priv, "%06x - done 0x%08x\n", base,
1015                  nv_rd32(priv, base + 0x400));
1016         nv_error(priv, "%06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base,
1017                  nv_rd32(priv, base + 0x800), nv_rd32(priv, base + 0x804),
1018                  nv_rd32(priv, base + 0x808), nv_rd32(priv, base + 0x80c));
1019         nv_error(priv, "%06x - stat 0x%08x 0x%08x 0x%08x 0x%08x\n", base,
1020                  nv_rd32(priv, base + 0x810), nv_rd32(priv, base + 0x814),
1021                  nv_rd32(priv, base + 0x818), nv_rd32(priv, base + 0x81c));
1022 }
1023
1024 void
1025 nvc0_graph_ctxctl_debug(struct nvc0_graph_priv *priv)
1026 {
1027         u32 gpcnr = nv_rd32(priv, 0x409604) & 0xffff;
1028         u32 gpc;
1029
1030         nvc0_graph_ctxctl_debug_unit(priv, 0x409000);
1031         for (gpc = 0; gpc < gpcnr; gpc++)
1032                 nvc0_graph_ctxctl_debug_unit(priv, 0x502000 + (gpc * 0x8000));
1033 }
1034
1035 static void
1036 nvc0_graph_ctxctl_isr(struct nvc0_graph_priv *priv)
1037 {
1038         u32 stat = nv_rd32(priv, 0x409c18);
1039
1040         if (stat & 0x00000001) {
1041                 u32 code = nv_rd32(priv, 0x409814);
1042                 if (code == E_BAD_FWMTHD) {
1043                         u32 class = nv_rd32(priv, 0x409808);
1044                         u32  addr = nv_rd32(priv, 0x40980c);
1045                         u32  subc = (addr & 0x00070000) >> 16;
1046                         u32  mthd = (addr & 0x00003ffc);
1047                         u32  data = nv_rd32(priv, 0x409810);
1048
1049                         nv_error(priv, "FECS MTHD subc %d class 0x%04x "
1050                                        "mthd 0x%04x data 0x%08x\n",
1051                                  subc, class, mthd, data);
1052
1053                         nv_wr32(priv, 0x409c20, 0x00000001);
1054                         stat &= ~0x00000001;
1055                 } else {
1056                         nv_error(priv, "FECS ucode error %d\n", code);
1057                 }
1058         }
1059
1060         if (stat & 0x00080000) {
1061                 nv_error(priv, "FECS watchdog timeout\n");
1062                 nvc0_graph_ctxctl_debug(priv);
1063                 nv_wr32(priv, 0x409c20, 0x00080000);
1064                 stat &= ~0x00080000;
1065         }
1066
1067         if (stat) {
1068                 nv_error(priv, "FECS 0x%08x\n", stat);
1069                 nvc0_graph_ctxctl_debug(priv);
1070                 nv_wr32(priv, 0x409c20, stat);
1071         }
1072 }
1073
1074 static void
1075 nvc0_graph_intr(struct nouveau_subdev *subdev)
1076 {
1077         struct nouveau_fifo *pfifo = nouveau_fifo(subdev);
1078         struct nouveau_engine *engine = nv_engine(subdev);
1079         struct nouveau_object *engctx;
1080         struct nouveau_handle *handle;
1081         struct nvc0_graph_priv *priv = (void *)subdev;
1082         u64 inst = nv_rd32(priv, 0x409b00) & 0x0fffffff;
1083         u32 stat = nv_rd32(priv, 0x400100);
1084         u32 addr = nv_rd32(priv, 0x400704);
1085         u32 mthd = (addr & 0x00003ffc);
1086         u32 subc = (addr & 0x00070000) >> 16;
1087         u32 data = nv_rd32(priv, 0x400708);
1088         u32 code = nv_rd32(priv, 0x400110);
1089         u32 class = nv_rd32(priv, 0x404200 + (subc * 4));
1090         int chid;
1091
1092         engctx = nouveau_engctx_get(engine, inst);
1093         chid   = pfifo->chid(pfifo, engctx);
1094
1095         if (stat & 0x00000010) {
1096                 handle = nouveau_handle_get_class(engctx, class);
1097                 if (!handle || nv_call(handle->object, mthd, data)) {
1098                         nv_error(priv,
1099                                  "ILLEGAL_MTHD ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
1100                                  chid, inst << 12, nouveau_client_name(engctx),
1101                                  subc, class, mthd, data);
1102                 }
1103                 nouveau_handle_put(handle);
1104                 nv_wr32(priv, 0x400100, 0x00000010);
1105                 stat &= ~0x00000010;
1106         }
1107
1108         if (stat & 0x00000020) {
1109                 nv_error(priv,
1110                          "ILLEGAL_CLASS ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
1111                          chid, inst << 12, nouveau_client_name(engctx), subc,
1112                          class, mthd, data);
1113                 nv_wr32(priv, 0x400100, 0x00000020);
1114                 stat &= ~0x00000020;
1115         }
1116
1117         if (stat & 0x00100000) {
1118                 nv_error(priv, "DATA_ERROR [");
1119                 nouveau_enum_print(nv50_data_error_names, code);
1120                 pr_cont("] ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
1121                         chid, inst << 12, nouveau_client_name(engctx), subc,
1122                         class, mthd, data);
1123                 nv_wr32(priv, 0x400100, 0x00100000);
1124                 stat &= ~0x00100000;
1125         }
1126
1127         if (stat & 0x00200000) {
1128                 nv_error(priv, "TRAP ch %d [0x%010llx %s]\n", chid, inst << 12,
1129                          nouveau_client_name(engctx));
1130                 nvc0_graph_trap_intr(priv);
1131                 nv_wr32(priv, 0x400100, 0x00200000);
1132                 stat &= ~0x00200000;
1133         }
1134
1135         if (stat & 0x00080000) {
1136                 nvc0_graph_ctxctl_isr(priv);
1137                 nv_wr32(priv, 0x400100, 0x00080000);
1138                 stat &= ~0x00080000;
1139         }
1140
1141         if (stat) {
1142                 nv_error(priv, "unknown stat 0x%08x\n", stat);
1143                 nv_wr32(priv, 0x400100, stat);
1144         }
1145
1146         nv_wr32(priv, 0x400500, 0x00010001);
1147         nouveau_engctx_put(engctx);
1148 }
1149
1150 void
1151 nvc0_graph_init_fw(struct nvc0_graph_priv *priv, u32 fuc_base,
1152                    struct nvc0_graph_fuc *code, struct nvc0_graph_fuc *data)
1153 {
1154         int i;
1155
1156         nv_wr32(priv, fuc_base + 0x01c0, 0x01000000);
1157         for (i = 0; i < data->size / 4; i++)
1158                 nv_wr32(priv, fuc_base + 0x01c4, data->data[i]);
1159
1160         nv_wr32(priv, fuc_base + 0x0180, 0x01000000);
1161         for (i = 0; i < code->size / 4; i++) {
1162                 if ((i & 0x3f) == 0)
1163                         nv_wr32(priv, fuc_base + 0x0188, i >> 6);
1164                 nv_wr32(priv, fuc_base + 0x0184, code->data[i]);
1165         }
1166
1167         /* code must be padded to 0x40 words */
1168         for (; i & 0x3f; i++)
1169                 nv_wr32(priv, fuc_base + 0x0184, 0);
1170 }
1171
1172 static void
1173 nvc0_graph_init_csdata(struct nvc0_graph_priv *priv,
1174                        const struct nvc0_graph_pack *pack,
1175                        u32 falcon, u32 starstar, u32 base)
1176 {
1177         const struct nvc0_graph_pack *iter;
1178         const struct nvc0_graph_init *init;
1179         u32 addr = ~0, prev = ~0, xfer = 0;
1180         u32 star, temp;
1181
1182         nv_wr32(priv, falcon + 0x01c0, 0x02000000 + starstar);
1183         star = nv_rd32(priv, falcon + 0x01c4);
1184         temp = nv_rd32(priv, falcon + 0x01c4);
1185         if (temp > star)
1186                 star = temp;
1187         nv_wr32(priv, falcon + 0x01c0, 0x01000000 + star);
1188
1189         pack_for_each_init(init, iter, pack) {
1190                 u32 head = init->addr - base;
1191                 u32 tail = head + init->count * init->pitch;
1192                 while (head < tail) {
1193                         if (head != prev + 4 || xfer >= 32) {
1194                                 if (xfer) {
1195                                         u32 data = ((--xfer << 26) | addr);
1196                                         nv_wr32(priv, falcon + 0x01c4, data);
1197                                         star += 4;
1198                                 }
1199                                 addr = head;
1200                                 xfer = 0;
1201                         }
1202                         prev = head;
1203                         xfer = xfer + 1;
1204                         head = head + init->pitch;
1205                 }
1206         }
1207
1208         nv_wr32(priv, falcon + 0x01c4, (--xfer << 26) | addr);
1209         nv_wr32(priv, falcon + 0x01c0, 0x01000004 + starstar);
1210         nv_wr32(priv, falcon + 0x01c4, star + 4);
1211 }
1212
1213 int
1214 nvc0_graph_init_ctxctl(struct nvc0_graph_priv *priv)
1215 {
1216         struct nvc0_graph_oclass *oclass = (void *)nv_object(priv)->oclass;
1217         struct nvc0_grctx_oclass *cclass = (void *)nv_engine(priv)->cclass;
1218         int i;
1219
1220         if (priv->firmware) {
1221                 /* load fuc microcode */
1222                 nouveau_mc(priv)->unk260(nouveau_mc(priv), 0);
1223                 nvc0_graph_init_fw(priv, 0x409000, &priv->fuc409c,
1224                                                    &priv->fuc409d);
1225                 nvc0_graph_init_fw(priv, 0x41a000, &priv->fuc41ac,
1226                                                    &priv->fuc41ad);
1227                 nouveau_mc(priv)->unk260(nouveau_mc(priv), 1);
1228
1229                 /* start both of them running */
1230                 nv_wr32(priv, 0x409840, 0xffffffff);
1231                 nv_wr32(priv, 0x41a10c, 0x00000000);
1232                 nv_wr32(priv, 0x40910c, 0x00000000);
1233                 nv_wr32(priv, 0x41a100, 0x00000002);
1234                 nv_wr32(priv, 0x409100, 0x00000002);
1235                 if (!nv_wait(priv, 0x409800, 0x00000001, 0x00000001))
1236                         nv_warn(priv, "0x409800 wait failed\n");
1237
1238                 nv_wr32(priv, 0x409840, 0xffffffff);
1239                 nv_wr32(priv, 0x409500, 0x7fffffff);
1240                 nv_wr32(priv, 0x409504, 0x00000021);
1241
1242                 nv_wr32(priv, 0x409840, 0xffffffff);
1243                 nv_wr32(priv, 0x409500, 0x00000000);
1244                 nv_wr32(priv, 0x409504, 0x00000010);
1245                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
1246                         nv_error(priv, "fuc09 req 0x10 timeout\n");
1247                         return -EBUSY;
1248                 }
1249                 priv->size = nv_rd32(priv, 0x409800);
1250
1251                 nv_wr32(priv, 0x409840, 0xffffffff);
1252                 nv_wr32(priv, 0x409500, 0x00000000);
1253                 nv_wr32(priv, 0x409504, 0x00000016);
1254                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
1255                         nv_error(priv, "fuc09 req 0x16 timeout\n");
1256                         return -EBUSY;
1257                 }
1258
1259                 nv_wr32(priv, 0x409840, 0xffffffff);
1260                 nv_wr32(priv, 0x409500, 0x00000000);
1261                 nv_wr32(priv, 0x409504, 0x00000025);
1262                 if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
1263                         nv_error(priv, "fuc09 req 0x25 timeout\n");
1264                         return -EBUSY;
1265                 }
1266
1267                 if (nv_device(priv)->chipset >= 0xe0) {
1268                         nv_wr32(priv, 0x409800, 0x00000000);
1269                         nv_wr32(priv, 0x409500, 0x00000001);
1270                         nv_wr32(priv, 0x409504, 0x00000030);
1271                         if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
1272                                 nv_error(priv, "fuc09 req 0x30 timeout\n");
1273                                 return -EBUSY;
1274                         }
1275
1276                         nv_wr32(priv, 0x409810, 0xb00095c8);
1277                         nv_wr32(priv, 0x409800, 0x00000000);
1278                         nv_wr32(priv, 0x409500, 0x00000001);
1279                         nv_wr32(priv, 0x409504, 0x00000031);
1280                         if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
1281                                 nv_error(priv, "fuc09 req 0x31 timeout\n");
1282                                 return -EBUSY;
1283                         }
1284
1285                         nv_wr32(priv, 0x409810, 0x00080420);
1286                         nv_wr32(priv, 0x409800, 0x00000000);
1287                         nv_wr32(priv, 0x409500, 0x00000001);
1288                         nv_wr32(priv, 0x409504, 0x00000032);
1289                         if (!nv_wait_ne(priv, 0x409800, 0xffffffff, 0x00000000)) {
1290                                 nv_error(priv, "fuc09 req 0x32 timeout\n");
1291                                 return -EBUSY;
1292                         }
1293
1294                         nv_wr32(priv, 0x409614, 0x00000070);
1295                         nv_wr32(priv, 0x409614, 0x00000770);
1296                         nv_wr32(priv, 0x40802c, 0x00000001);
1297                 }
1298
1299                 if (priv->data == NULL) {
1300                         int ret = nvc0_grctx_generate(priv);
1301                         if (ret) {
1302                                 nv_error(priv, "failed to construct context\n");
1303                                 return ret;
1304                         }
1305                 }
1306
1307                 return 0;
1308         } else
1309         if (!oclass->fecs.ucode) {
1310                 return -ENOSYS;
1311         }
1312
1313         /* load HUB microcode */
1314         nouveau_mc(priv)->unk260(nouveau_mc(priv), 0);
1315         nv_wr32(priv, 0x4091c0, 0x01000000);
1316         for (i = 0; i < oclass->fecs.ucode->data.size / 4; i++)
1317                 nv_wr32(priv, 0x4091c4, oclass->fecs.ucode->data.data[i]);
1318
1319         nv_wr32(priv, 0x409180, 0x01000000);
1320         for (i = 0; i < oclass->fecs.ucode->code.size / 4; i++) {
1321                 if ((i & 0x3f) == 0)
1322                         nv_wr32(priv, 0x409188, i >> 6);
1323                 nv_wr32(priv, 0x409184, oclass->fecs.ucode->code.data[i]);
1324         }
1325
1326         /* load GPC microcode */
1327         nv_wr32(priv, 0x41a1c0, 0x01000000);
1328         for (i = 0; i < oclass->gpccs.ucode->data.size / 4; i++)
1329                 nv_wr32(priv, 0x41a1c4, oclass->gpccs.ucode->data.data[i]);
1330
1331         nv_wr32(priv, 0x41a180, 0x01000000);
1332         for (i = 0; i < oclass->gpccs.ucode->code.size / 4; i++) {
1333                 if ((i & 0x3f) == 0)
1334                         nv_wr32(priv, 0x41a188, i >> 6);
1335                 nv_wr32(priv, 0x41a184, oclass->gpccs.ucode->code.data[i]);
1336         }
1337         nouveau_mc(priv)->unk260(nouveau_mc(priv), 1);
1338
1339         /* load register lists */
1340         nvc0_graph_init_csdata(priv, cclass->hub, 0x409000, 0x000, 0x000000);
1341         nvc0_graph_init_csdata(priv, cclass->gpc, 0x41a000, 0x000, 0x418000);
1342         nvc0_graph_init_csdata(priv, cclass->tpc, 0x41a000, 0x004, 0x419800);
1343         nvc0_graph_init_csdata(priv, cclass->ppc, 0x41a000, 0x008, 0x41be00);
1344
1345         /* start HUB ucode running, it'll init the GPCs */
1346         nv_wr32(priv, 0x40910c, 0x00000000);
1347         nv_wr32(priv, 0x409100, 0x00000002);
1348         if (!nv_wait(priv, 0x409800, 0x80000000, 0x80000000)) {
1349                 nv_error(priv, "HUB_INIT timed out\n");
1350                 nvc0_graph_ctxctl_debug(priv);
1351                 return -EBUSY;
1352         }
1353
1354         priv->size = nv_rd32(priv, 0x409804);
1355         if (priv->data == NULL) {
1356                 int ret = nvc0_grctx_generate(priv);
1357                 if (ret) {
1358                         nv_error(priv, "failed to construct context\n");
1359                         return ret;
1360                 }
1361         }
1362
1363         return 0;
1364 }
1365
1366 int
1367 nvc0_graph_init(struct nouveau_object *object)
1368 {
1369         struct nvc0_graph_oclass *oclass = (void *)object->oclass;
1370         struct nvc0_graph_priv *priv = (void *)object;
1371         const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, priv->tpc_total);
1372         u32 data[TPC_MAX / 8] = {};
1373         u8  tpcnr[GPC_MAX];
1374         int gpc, tpc, rop;
1375         int ret, i;
1376
1377         ret = nouveau_graph_init(&priv->base);
1378         if (ret)
1379                 return ret;
1380
1381         nv_wr32(priv, GPC_BCAST(0x0880), 0x00000000);
1382         nv_wr32(priv, GPC_BCAST(0x08a4), 0x00000000);
1383         nv_wr32(priv, GPC_BCAST(0x0888), 0x00000000);
1384         nv_wr32(priv, GPC_BCAST(0x088c), 0x00000000);
1385         nv_wr32(priv, GPC_BCAST(0x0890), 0x00000000);
1386         nv_wr32(priv, GPC_BCAST(0x0894), 0x00000000);
1387         nv_wr32(priv, GPC_BCAST(0x08b4), priv->unk4188b4->addr >> 8);
1388         nv_wr32(priv, GPC_BCAST(0x08b8), priv->unk4188b8->addr >> 8);
1389
1390         nvc0_graph_mmio(priv, oclass->mmio);
1391
1392         memcpy(tpcnr, priv->tpc_nr, sizeof(priv->tpc_nr));
1393         for (i = 0, gpc = -1; i < priv->tpc_total; i++) {
1394                 do {
1395                         gpc = (gpc + 1) % priv->gpc_nr;
1396                 } while (!tpcnr[gpc]);
1397                 tpc = priv->tpc_nr[gpc] - tpcnr[gpc]--;
1398
1399                 data[i / 8] |= tpc << ((i % 8) * 4);
1400         }
1401
1402         nv_wr32(priv, GPC_BCAST(0x0980), data[0]);
1403         nv_wr32(priv, GPC_BCAST(0x0984), data[1]);
1404         nv_wr32(priv, GPC_BCAST(0x0988), data[2]);
1405         nv_wr32(priv, GPC_BCAST(0x098c), data[3]);
1406
1407         for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
1408                 nv_wr32(priv, GPC_UNIT(gpc, 0x0914),
1409                         priv->magic_not_rop_nr << 8 | priv->tpc_nr[gpc]);
1410                 nv_wr32(priv, GPC_UNIT(gpc, 0x0910), 0x00040000 |
1411                         priv->tpc_total);
1412                 nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918);
1413         }
1414
1415         if (nv_device(priv)->chipset != 0xd7)
1416                 nv_wr32(priv, GPC_BCAST(0x1bd4), magicgpc918);
1417         else
1418                 nv_wr32(priv, GPC_BCAST(0x3fd4), magicgpc918);
1419
1420         nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800));
1421
1422         nv_wr32(priv, 0x400500, 0x00010001);
1423
1424         nv_wr32(priv, 0x400100, 0xffffffff);
1425         nv_wr32(priv, 0x40013c, 0xffffffff);
1426
1427         nv_wr32(priv, 0x409c24, 0x000f0000);
1428         nv_wr32(priv, 0x404000, 0xc0000000);
1429         nv_wr32(priv, 0x404600, 0xc0000000);
1430         nv_wr32(priv, 0x408030, 0xc0000000);
1431         nv_wr32(priv, 0x40601c, 0xc0000000);
1432         nv_wr32(priv, 0x404490, 0xc0000000);
1433         nv_wr32(priv, 0x406018, 0xc0000000);
1434         nv_wr32(priv, 0x405840, 0xc0000000);
1435         nv_wr32(priv, 0x405844, 0x00ffffff);
1436         nv_mask(priv, 0x419cc0, 0x00000008, 0x00000008);
1437         nv_mask(priv, 0x419eb4, 0x00001000, 0x00001000);
1438
1439         for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
1440                 nv_wr32(priv, GPC_UNIT(gpc, 0x0420), 0xc0000000);
1441                 nv_wr32(priv, GPC_UNIT(gpc, 0x0900), 0xc0000000);
1442                 nv_wr32(priv, GPC_UNIT(gpc, 0x1028), 0xc0000000);
1443                 nv_wr32(priv, GPC_UNIT(gpc, 0x0824), 0xc0000000);
1444                 for (tpc = 0; tpc < priv->tpc_nr[gpc]; tpc++) {
1445                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x508), 0xffffffff);
1446                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x50c), 0xffffffff);
1447                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x224), 0xc0000000);
1448                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x48c), 0xc0000000);
1449                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x084), 0xc0000000);
1450                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x644), 0x001ffffe);
1451                         nv_wr32(priv, TPC_UNIT(gpc, tpc, 0x64c), 0x0000000f);
1452                 }
1453                 nv_wr32(priv, GPC_UNIT(gpc, 0x2c90), 0xffffffff);
1454                 nv_wr32(priv, GPC_UNIT(gpc, 0x2c94), 0xffffffff);
1455         }
1456
1457         for (rop = 0; rop < priv->rop_nr; rop++) {
1458                 nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000);
1459                 nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000);
1460                 nv_wr32(priv, ROP_UNIT(rop, 0x204), 0xffffffff);
1461                 nv_wr32(priv, ROP_UNIT(rop, 0x208), 0xffffffff);
1462         }
1463
1464         nv_wr32(priv, 0x400108, 0xffffffff);
1465         nv_wr32(priv, 0x400138, 0xffffffff);
1466         nv_wr32(priv, 0x400118, 0xffffffff);
1467         nv_wr32(priv, 0x400130, 0xffffffff);
1468         nv_wr32(priv, 0x40011c, 0xffffffff);
1469         nv_wr32(priv, 0x400134, 0xffffffff);
1470
1471         nv_wr32(priv, 0x400054, 0x34ce3464);
1472
1473         nvc0_graph_zbc_init(priv);
1474
1475         return nvc0_graph_init_ctxctl(priv);
1476 }
1477
1478 static void
1479 nvc0_graph_dtor_fw(struct nvc0_graph_fuc *fuc)
1480 {
1481         kfree(fuc->data);
1482         fuc->data = NULL;
1483 }
1484
1485 int
1486 nvc0_graph_ctor_fw(struct nvc0_graph_priv *priv, const char *fwname,
1487                    struct nvc0_graph_fuc *fuc)
1488 {
1489         struct nouveau_device *device = nv_device(priv);
1490         const struct firmware *fw;
1491         char f[32];
1492         int ret;
1493
1494         snprintf(f, sizeof(f), "nouveau/nv%02x_%s", device->chipset, fwname);
1495         ret = request_firmware(&fw, f, nv_device_base(device));
1496         if (ret) {
1497                 snprintf(f, sizeof(f), "nouveau/%s", fwname);
1498                 ret = request_firmware(&fw, f, nv_device_base(device));
1499                 if (ret) {
1500                         nv_error(priv, "failed to load %s\n", fwname);
1501                         return ret;
1502                 }
1503         }
1504
1505         fuc->size = fw->size;
1506         fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL);
1507         release_firmware(fw);
1508         return (fuc->data != NULL) ? 0 : -ENOMEM;
1509 }
1510
1511 void
1512 nvc0_graph_dtor(struct nouveau_object *object)
1513 {
1514         struct nvc0_graph_priv *priv = (void *)object;
1515
1516         kfree(priv->data);
1517
1518         nvc0_graph_dtor_fw(&priv->fuc409c);
1519         nvc0_graph_dtor_fw(&priv->fuc409d);
1520         nvc0_graph_dtor_fw(&priv->fuc41ac);
1521         nvc0_graph_dtor_fw(&priv->fuc41ad);
1522
1523         nouveau_gpuobj_ref(NULL, &priv->unk4188b8);
1524         nouveau_gpuobj_ref(NULL, &priv->unk4188b4);
1525
1526         nouveau_graph_destroy(&priv->base);
1527 }
1528
1529 int
1530 nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
1531                 struct nouveau_oclass *bclass, void *data, u32 size,
1532                 struct nouveau_object **pobject)
1533 {
1534         struct nvc0_graph_oclass *oclass = (void *)bclass;
1535         struct nouveau_device *device = nv_device(parent);
1536         struct nvc0_graph_priv *priv;
1537         bool use_ext_fw, enable;
1538         int ret, i, j;
1539
1540         use_ext_fw = nouveau_boolopt(device->cfgopt, "NvGrUseFW",
1541                                      oclass->fecs.ucode == NULL);
1542         enable = use_ext_fw || oclass->fecs.ucode != NULL;
1543
1544         ret = nouveau_graph_create(parent, engine, bclass, enable, &priv);
1545         *pobject = nv_object(priv);
1546         if (ret)
1547                 return ret;
1548
1549         nv_subdev(priv)->unit = 0x08001000;
1550         nv_subdev(priv)->intr = nvc0_graph_intr;
1551
1552         priv->base.units = nvc0_graph_units;
1553
1554         if (use_ext_fw) {
1555                 nv_info(priv, "using external firmware\n");
1556                 if (nvc0_graph_ctor_fw(priv, "fuc409c", &priv->fuc409c) ||
1557                     nvc0_graph_ctor_fw(priv, "fuc409d", &priv->fuc409d) ||
1558                     nvc0_graph_ctor_fw(priv, "fuc41ac", &priv->fuc41ac) ||
1559                     nvc0_graph_ctor_fw(priv, "fuc41ad", &priv->fuc41ad))
1560                         return -EINVAL;
1561                 priv->firmware = true;
1562         }
1563
1564         ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 256, 0,
1565                                 &priv->unk4188b4);
1566         if (ret)
1567                 return ret;
1568
1569         ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 256, 0,
1570                                 &priv->unk4188b8);
1571         if (ret)
1572                 return ret;
1573
1574         for (i = 0; i < 0x1000; i += 4) {
1575                 nv_wo32(priv->unk4188b4, i, 0x00000010);
1576                 nv_wo32(priv->unk4188b8, i, 0x00000010);
1577         }
1578
1579         priv->rop_nr = (nv_rd32(priv, 0x409604) & 0x001f0000) >> 16;
1580         priv->gpc_nr =  nv_rd32(priv, 0x409604) & 0x0000001f;
1581         for (i = 0; i < priv->gpc_nr; i++) {
1582                 priv->tpc_nr[i]  = nv_rd32(priv, GPC_UNIT(i, 0x2608));
1583                 priv->tpc_total += priv->tpc_nr[i];
1584                 priv->ppc_nr[i]  = oclass->ppc_nr;
1585                 for (j = 0; j < priv->ppc_nr[i]; j++) {
1586                         u8 mask = nv_rd32(priv, GPC_UNIT(i, 0x0c30 + (j * 4)));
1587                         priv->ppc_tpc_nr[i][j] = hweight8(mask);
1588                 }
1589         }
1590
1591         /*XXX: these need figuring out... though it might not even matter */
1592         switch (nv_device(priv)->chipset) {
1593         case 0xc0:
1594                 if (priv->tpc_total == 11) { /* 465, 3/4/4/0, 4 */
1595                         priv->magic_not_rop_nr = 0x07;
1596                 } else
1597                 if (priv->tpc_total == 14) { /* 470, 3/3/4/4, 5 */
1598                         priv->magic_not_rop_nr = 0x05;
1599                 } else
1600                 if (priv->tpc_total == 15) { /* 480, 3/4/4/4, 6 */
1601                         priv->magic_not_rop_nr = 0x06;
1602                 }
1603                 break;
1604         case 0xc3: /* 450, 4/0/0/0, 2 */
1605                 priv->magic_not_rop_nr = 0x03;
1606                 break;
1607         case 0xc4: /* 460, 3/4/0/0, 4 */
1608                 priv->magic_not_rop_nr = 0x01;
1609                 break;
1610         case 0xc1: /* 2/0/0/0, 1 */
1611                 priv->magic_not_rop_nr = 0x01;
1612                 break;
1613         case 0xc8: /* 4/4/3/4, 5 */
1614                 priv->magic_not_rop_nr = 0x06;
1615                 break;
1616         case 0xce: /* 4/4/0/0, 4 */
1617                 priv->magic_not_rop_nr = 0x03;
1618                 break;
1619         case 0xcf: /* 4/0/0/0, 3 */
1620                 priv->magic_not_rop_nr = 0x03;
1621                 break;
1622         case 0xd7:
1623         case 0xd9: /* 1/0/0/0, 1 */
1624                 priv->magic_not_rop_nr = 0x01;
1625                 break;
1626         }
1627
1628         nv_engine(priv)->cclass = *oclass->cclass;
1629         nv_engine(priv)->sclass =  oclass->sclass;
1630         return 0;
1631 }
1632
1633 #include "fuc/hubnvc0.fuc.h"
1634
1635 struct nvc0_graph_ucode
1636 nvc0_graph_fecs_ucode = {
1637         .code.data = nvc0_grhub_code,
1638         .code.size = sizeof(nvc0_grhub_code),
1639         .data.data = nvc0_grhub_data,
1640         .data.size = sizeof(nvc0_grhub_data),
1641 };
1642
1643 #include "fuc/gpcnvc0.fuc.h"
1644
1645 struct nvc0_graph_ucode
1646 nvc0_graph_gpccs_ucode = {
1647         .code.data = nvc0_grgpc_code,
1648         .code.size = sizeof(nvc0_grgpc_code),
1649         .data.data = nvc0_grgpc_data,
1650         .data.size = sizeof(nvc0_grgpc_data),
1651 };
1652
1653 struct nouveau_oclass *
1654 nvc0_graph_oclass = &(struct nvc0_graph_oclass) {
1655         .base.handle = NV_ENGINE(GR, 0xc0),
1656         .base.ofuncs = &(struct nouveau_ofuncs) {
1657                 .ctor = nvc0_graph_ctor,
1658                 .dtor = nvc0_graph_dtor,
1659                 .init = nvc0_graph_init,
1660                 .fini = _nouveau_graph_fini,
1661         },
1662         .cclass = &nvc0_grctx_oclass,
1663         .sclass =  nvc0_graph_sclass,
1664         .mmio = nvc0_graph_pack_mmio,
1665         .fecs.ucode = &nvc0_graph_fecs_ucode,
1666         .gpccs.ucode = &nvc0_graph_gpccs_ucode,
1667 }.base;