• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
nvc0_graph_zbc_clear_color(struct nvc0_graph_priv * priv,int zbc)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
nvc0_graph_zbc_color_get(struct nvc0_graph_priv * priv,int format,const u32 ds[4],const u32 l2[4])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
nvc0_graph_zbc_clear_depth(struct nvc0_graph_priv * priv,int zbc)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
nvc0_graph_zbc_depth_get(struct nvc0_graph_priv * priv,int format,const u32 ds,const u32 l2)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
nvc0_fermi_mthd_zbc_color(struct nouveau_object * object,void * data,u32 size)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
nvc0_fermi_mthd_zbc_depth(struct nouveau_object * object,void * data,u32 size)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
nvc0_fermi_mthd(struct nouveau_object * object,u32 mthd,void * data,u32 size)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
nvc0_graph_set_shader_exceptions(struct nouveau_object * object,u32 mthd,void * pdata,u32 size)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
nvc0_graph_context_ctor(struct nouveau_object * parent,struct nouveau_object * engine,struct nouveau_oclass * oclass,void * args,u32 size,struct nouveau_object ** pobject)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
nvc0_graph_context_dtor(struct nouveau_object * object)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
nvc0_graph_zbc_init(struct nvc0_graph_priv * priv)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
nvc0_graph_mmio(struct nvc0_graph_priv * priv,const struct nvc0_graph_pack * p)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
nvc0_graph_icmd(struct nvc0_graph_priv * priv,const struct nvc0_graph_pack * p)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
nvc0_graph_mthd(struct nvc0_graph_priv * priv,const struct nvc0_graph_pack * p)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
nvc0_graph_units(struct nouveau_graph * graph)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
nvc0_graph_trap_gpc_rop(struct nvc0_graph_priv * priv,int gpc)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
nvc0_graph_trap_mp(struct nvc0_graph_priv * priv,int gpc,int tpc)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
nvc0_graph_trap_tpc(struct nvc0_graph_priv * priv,int gpc,int tpc)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
nvc0_graph_trap_gpc(struct nvc0_graph_priv * priv,int gpc)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
nvc0_graph_trap_intr(struct nvc0_graph_priv * priv)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
nvc0_graph_ctxctl_debug_unit(struct nvc0_graph_priv * priv,u32 base)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
nvc0_graph_ctxctl_debug(struct nvc0_graph_priv * priv)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
nvc0_graph_ctxctl_isr(struct nvc0_graph_priv * priv)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
nvc0_graph_intr(struct nouveau_subdev * subdev)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
nvc0_graph_init_fw(struct nvc0_graph_priv * priv,u32 fuc_base,struct nvc0_graph_fuc * code,struct nvc0_graph_fuc * data)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
nvc0_graph_init_csdata(struct nvc0_graph_priv * priv,const struct nvc0_graph_pack * pack,u32 falcon,u32 starstar,u32 base)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
nvc0_graph_init_ctxctl(struct nvc0_graph_priv * priv)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
nvc0_graph_init(struct nouveau_object * object)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
nvc0_graph_dtor_fw(struct nvc0_graph_fuc * fuc)1479 nvc0_graph_dtor_fw(struct nvc0_graph_fuc *fuc)
1480 {
1481 	kfree(fuc->data);
1482 	fuc->data = NULL;
1483 }
1484 
1485 int
nvc0_graph_ctor_fw(struct nvc0_graph_priv * priv,const char * fwname,struct nvc0_graph_fuc * fuc)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
nvc0_graph_dtor(struct nouveau_object * object)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
nvc0_graph_ctor(struct nouveau_object * parent,struct nouveau_object * engine,struct nouveau_oclass * bclass,void * data,u32 size,struct nouveau_object ** pobject)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;
1668