xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/nouveau/nvkm/engine/gr/nouveau_nvkm_engine_gr_nv04.c (revision 798b8d11ecd8257a8e35c3396210f98abf3d9ade)
1 /*	$NetBSD: nouveau_nvkm_engine_gr_nv04.c,v 1.4 2021/12/19 11:34:45 riastradh Exp $	*/
2 
3 /*
4  * Copyright 2007 Stephane Marchesin
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a
8  * copy of this software and associated documentation files (the "Software"),
9  * to deal in the Software without restriction, including without limitation
10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11  * and/or sell copies of the Software, and to permit persons to whom the
12  * Software is furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the next
15  * paragr) shall be included in all copies or substantial portions of the
16  * Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24  * DEALINGS IN THE SOFTWARE.
25  */
26 #include <sys/cdefs.h>
27 __KERNEL_RCSID(0, "$NetBSD: nouveau_nvkm_engine_gr_nv04.c,v 1.4 2021/12/19 11:34:45 riastradh Exp $");
28 
29 #include "priv.h"
30 #include "regs.h"
31 
32 #include <core/client.h>
33 #include <core/gpuobj.h>
34 #include <engine/fifo.h>
35 #include <engine/fifo/chan.h>
36 #include <subdev/instmem.h>
37 #include <subdev/timer.h>
38 
39 static u32
40 nv04_gr_ctx_regs[] = {
41 	0x0040053c,
42 	0x00400544,
43 	0x00400540,
44 	0x00400548,
45 	NV04_PGRAPH_CTX_SWITCH1,
46 	NV04_PGRAPH_CTX_SWITCH2,
47 	NV04_PGRAPH_CTX_SWITCH3,
48 	NV04_PGRAPH_CTX_SWITCH4,
49 	NV04_PGRAPH_CTX_CACHE1,
50 	NV04_PGRAPH_CTX_CACHE2,
51 	NV04_PGRAPH_CTX_CACHE3,
52 	NV04_PGRAPH_CTX_CACHE4,
53 	0x00400184,
54 	0x004001a4,
55 	0x004001c4,
56 	0x004001e4,
57 	0x00400188,
58 	0x004001a8,
59 	0x004001c8,
60 	0x004001e8,
61 	0x0040018c,
62 	0x004001ac,
63 	0x004001cc,
64 	0x004001ec,
65 	0x00400190,
66 	0x004001b0,
67 	0x004001d0,
68 	0x004001f0,
69 	0x00400194,
70 	0x004001b4,
71 	0x004001d4,
72 	0x004001f4,
73 	0x00400198,
74 	0x004001b8,
75 	0x004001d8,
76 	0x004001f8,
77 	0x0040019c,
78 	0x004001bc,
79 	0x004001dc,
80 	0x004001fc,
81 	0x00400174,
82 	NV04_PGRAPH_DMA_START_0,
83 	NV04_PGRAPH_DMA_START_1,
84 	NV04_PGRAPH_DMA_LENGTH,
85 	NV04_PGRAPH_DMA_MISC,
86 	NV04_PGRAPH_DMA_PITCH,
87 	NV04_PGRAPH_BOFFSET0,
88 	NV04_PGRAPH_BBASE0,
89 	NV04_PGRAPH_BLIMIT0,
90 	NV04_PGRAPH_BOFFSET1,
91 	NV04_PGRAPH_BBASE1,
92 	NV04_PGRAPH_BLIMIT1,
93 	NV04_PGRAPH_BOFFSET2,
94 	NV04_PGRAPH_BBASE2,
95 	NV04_PGRAPH_BLIMIT2,
96 	NV04_PGRAPH_BOFFSET3,
97 	NV04_PGRAPH_BBASE3,
98 	NV04_PGRAPH_BLIMIT3,
99 	NV04_PGRAPH_BOFFSET4,
100 	NV04_PGRAPH_BBASE4,
101 	NV04_PGRAPH_BLIMIT4,
102 	NV04_PGRAPH_BOFFSET5,
103 	NV04_PGRAPH_BBASE5,
104 	NV04_PGRAPH_BLIMIT5,
105 	NV04_PGRAPH_BPITCH0,
106 	NV04_PGRAPH_BPITCH1,
107 	NV04_PGRAPH_BPITCH2,
108 	NV04_PGRAPH_BPITCH3,
109 	NV04_PGRAPH_BPITCH4,
110 	NV04_PGRAPH_SURFACE,
111 	NV04_PGRAPH_STATE,
112 	NV04_PGRAPH_BSWIZZLE2,
113 	NV04_PGRAPH_BSWIZZLE5,
114 	NV04_PGRAPH_BPIXEL,
115 	NV04_PGRAPH_NOTIFY,
116 	NV04_PGRAPH_PATT_COLOR0,
117 	NV04_PGRAPH_PATT_COLOR1,
118 	NV04_PGRAPH_PATT_COLORRAM+0x00,
119 	NV04_PGRAPH_PATT_COLORRAM+0x04,
120 	NV04_PGRAPH_PATT_COLORRAM+0x08,
121 	NV04_PGRAPH_PATT_COLORRAM+0x0c,
122 	NV04_PGRAPH_PATT_COLORRAM+0x10,
123 	NV04_PGRAPH_PATT_COLORRAM+0x14,
124 	NV04_PGRAPH_PATT_COLORRAM+0x18,
125 	NV04_PGRAPH_PATT_COLORRAM+0x1c,
126 	NV04_PGRAPH_PATT_COLORRAM+0x20,
127 	NV04_PGRAPH_PATT_COLORRAM+0x24,
128 	NV04_PGRAPH_PATT_COLORRAM+0x28,
129 	NV04_PGRAPH_PATT_COLORRAM+0x2c,
130 	NV04_PGRAPH_PATT_COLORRAM+0x30,
131 	NV04_PGRAPH_PATT_COLORRAM+0x34,
132 	NV04_PGRAPH_PATT_COLORRAM+0x38,
133 	NV04_PGRAPH_PATT_COLORRAM+0x3c,
134 	NV04_PGRAPH_PATT_COLORRAM+0x40,
135 	NV04_PGRAPH_PATT_COLORRAM+0x44,
136 	NV04_PGRAPH_PATT_COLORRAM+0x48,
137 	NV04_PGRAPH_PATT_COLORRAM+0x4c,
138 	NV04_PGRAPH_PATT_COLORRAM+0x50,
139 	NV04_PGRAPH_PATT_COLORRAM+0x54,
140 	NV04_PGRAPH_PATT_COLORRAM+0x58,
141 	NV04_PGRAPH_PATT_COLORRAM+0x5c,
142 	NV04_PGRAPH_PATT_COLORRAM+0x60,
143 	NV04_PGRAPH_PATT_COLORRAM+0x64,
144 	NV04_PGRAPH_PATT_COLORRAM+0x68,
145 	NV04_PGRAPH_PATT_COLORRAM+0x6c,
146 	NV04_PGRAPH_PATT_COLORRAM+0x70,
147 	NV04_PGRAPH_PATT_COLORRAM+0x74,
148 	NV04_PGRAPH_PATT_COLORRAM+0x78,
149 	NV04_PGRAPH_PATT_COLORRAM+0x7c,
150 	NV04_PGRAPH_PATT_COLORRAM+0x80,
151 	NV04_PGRAPH_PATT_COLORRAM+0x84,
152 	NV04_PGRAPH_PATT_COLORRAM+0x88,
153 	NV04_PGRAPH_PATT_COLORRAM+0x8c,
154 	NV04_PGRAPH_PATT_COLORRAM+0x90,
155 	NV04_PGRAPH_PATT_COLORRAM+0x94,
156 	NV04_PGRAPH_PATT_COLORRAM+0x98,
157 	NV04_PGRAPH_PATT_COLORRAM+0x9c,
158 	NV04_PGRAPH_PATT_COLORRAM+0xa0,
159 	NV04_PGRAPH_PATT_COLORRAM+0xa4,
160 	NV04_PGRAPH_PATT_COLORRAM+0xa8,
161 	NV04_PGRAPH_PATT_COLORRAM+0xac,
162 	NV04_PGRAPH_PATT_COLORRAM+0xb0,
163 	NV04_PGRAPH_PATT_COLORRAM+0xb4,
164 	NV04_PGRAPH_PATT_COLORRAM+0xb8,
165 	NV04_PGRAPH_PATT_COLORRAM+0xbc,
166 	NV04_PGRAPH_PATT_COLORRAM+0xc0,
167 	NV04_PGRAPH_PATT_COLORRAM+0xc4,
168 	NV04_PGRAPH_PATT_COLORRAM+0xc8,
169 	NV04_PGRAPH_PATT_COLORRAM+0xcc,
170 	NV04_PGRAPH_PATT_COLORRAM+0xd0,
171 	NV04_PGRAPH_PATT_COLORRAM+0xd4,
172 	NV04_PGRAPH_PATT_COLORRAM+0xd8,
173 	NV04_PGRAPH_PATT_COLORRAM+0xdc,
174 	NV04_PGRAPH_PATT_COLORRAM+0xe0,
175 	NV04_PGRAPH_PATT_COLORRAM+0xe4,
176 	NV04_PGRAPH_PATT_COLORRAM+0xe8,
177 	NV04_PGRAPH_PATT_COLORRAM+0xec,
178 	NV04_PGRAPH_PATT_COLORRAM+0xf0,
179 	NV04_PGRAPH_PATT_COLORRAM+0xf4,
180 	NV04_PGRAPH_PATT_COLORRAM+0xf8,
181 	NV04_PGRAPH_PATT_COLORRAM+0xfc,
182 	NV04_PGRAPH_PATTERN,
183 	0x0040080c,
184 	NV04_PGRAPH_PATTERN_SHAPE,
185 	0x00400600,
186 	NV04_PGRAPH_ROP3,
187 	NV04_PGRAPH_CHROMA,
188 	NV04_PGRAPH_BETA_AND,
189 	NV04_PGRAPH_BETA_PREMULT,
190 	NV04_PGRAPH_CONTROL0,
191 	NV04_PGRAPH_CONTROL1,
192 	NV04_PGRAPH_CONTROL2,
193 	NV04_PGRAPH_BLEND,
194 	NV04_PGRAPH_STORED_FMT,
195 	NV04_PGRAPH_SOURCE_COLOR,
196 	0x00400560,
197 	0x00400568,
198 	0x00400564,
199 	0x0040056c,
200 	0x00400400,
201 	0x00400480,
202 	0x00400404,
203 	0x00400484,
204 	0x00400408,
205 	0x00400488,
206 	0x0040040c,
207 	0x0040048c,
208 	0x00400410,
209 	0x00400490,
210 	0x00400414,
211 	0x00400494,
212 	0x00400418,
213 	0x00400498,
214 	0x0040041c,
215 	0x0040049c,
216 	0x00400420,
217 	0x004004a0,
218 	0x00400424,
219 	0x004004a4,
220 	0x00400428,
221 	0x004004a8,
222 	0x0040042c,
223 	0x004004ac,
224 	0x00400430,
225 	0x004004b0,
226 	0x00400434,
227 	0x004004b4,
228 	0x00400438,
229 	0x004004b8,
230 	0x0040043c,
231 	0x004004bc,
232 	0x00400440,
233 	0x004004c0,
234 	0x00400444,
235 	0x004004c4,
236 	0x00400448,
237 	0x004004c8,
238 	0x0040044c,
239 	0x004004cc,
240 	0x00400450,
241 	0x004004d0,
242 	0x00400454,
243 	0x004004d4,
244 	0x00400458,
245 	0x004004d8,
246 	0x0040045c,
247 	0x004004dc,
248 	0x00400460,
249 	0x004004e0,
250 	0x00400464,
251 	0x004004e4,
252 	0x00400468,
253 	0x004004e8,
254 	0x0040046c,
255 	0x004004ec,
256 	0x00400470,
257 	0x004004f0,
258 	0x00400474,
259 	0x004004f4,
260 	0x00400478,
261 	0x004004f8,
262 	0x0040047c,
263 	0x004004fc,
264 	0x00400534,
265 	0x00400538,
266 	0x00400514,
267 	0x00400518,
268 	0x0040051c,
269 	0x00400520,
270 	0x00400524,
271 	0x00400528,
272 	0x0040052c,
273 	0x00400530,
274 	0x00400d00,
275 	0x00400d40,
276 	0x00400d80,
277 	0x00400d04,
278 	0x00400d44,
279 	0x00400d84,
280 	0x00400d08,
281 	0x00400d48,
282 	0x00400d88,
283 	0x00400d0c,
284 	0x00400d4c,
285 	0x00400d8c,
286 	0x00400d10,
287 	0x00400d50,
288 	0x00400d90,
289 	0x00400d14,
290 	0x00400d54,
291 	0x00400d94,
292 	0x00400d18,
293 	0x00400d58,
294 	0x00400d98,
295 	0x00400d1c,
296 	0x00400d5c,
297 	0x00400d9c,
298 	0x00400d20,
299 	0x00400d60,
300 	0x00400da0,
301 	0x00400d24,
302 	0x00400d64,
303 	0x00400da4,
304 	0x00400d28,
305 	0x00400d68,
306 	0x00400da8,
307 	0x00400d2c,
308 	0x00400d6c,
309 	0x00400dac,
310 	0x00400d30,
311 	0x00400d70,
312 	0x00400db0,
313 	0x00400d34,
314 	0x00400d74,
315 	0x00400db4,
316 	0x00400d38,
317 	0x00400d78,
318 	0x00400db8,
319 	0x00400d3c,
320 	0x00400d7c,
321 	0x00400dbc,
322 	0x00400590,
323 	0x00400594,
324 	0x00400598,
325 	0x0040059c,
326 	0x004005a8,
327 	0x004005ac,
328 	0x004005b0,
329 	0x004005b4,
330 	0x004005c0,
331 	0x004005c4,
332 	0x004005c8,
333 	0x004005cc,
334 	0x004005d0,
335 	0x004005d4,
336 	0x004005d8,
337 	0x004005dc,
338 	0x004005e0,
339 	NV04_PGRAPH_PASSTHRU_0,
340 	NV04_PGRAPH_PASSTHRU_1,
341 	NV04_PGRAPH_PASSTHRU_2,
342 	NV04_PGRAPH_DVD_COLORFMT,
343 	NV04_PGRAPH_SCALED_FORMAT,
344 	NV04_PGRAPH_MISC24_0,
345 	NV04_PGRAPH_MISC24_1,
346 	NV04_PGRAPH_MISC24_2,
347 	0x00400500,
348 	0x00400504,
349 	NV04_PGRAPH_VALID1,
350 	NV04_PGRAPH_VALID2,
351 	NV04_PGRAPH_DEBUG_3
352 };
353 
354 #define nv04_gr(p) container_of((p), struct nv04_gr, base)
355 
356 struct nv04_gr {
357 	struct nvkm_gr base;
358 	struct nv04_gr_chan *chan[16];
359 	spinlock_t lock;
360 };
361 
362 #define nv04_gr_chan(p) container_of((p), struct nv04_gr_chan, object)
363 
364 struct nv04_gr_chan {
365 	struct nvkm_object object;
366 	struct nv04_gr *gr;
367 	int chid;
368 	u32 nv04[ARRAY_SIZE(nv04_gr_ctx_regs)];
369 };
370 
371 /*******************************************************************************
372  * Graphics object classes
373  ******************************************************************************/
374 
375 /*
376  * Software methods, why they are needed, and how they all work:
377  *
378  * NV04 and NV05 keep most of the state in PGRAPH context itself, but some
379  * 2d engine settings are kept inside the grobjs themselves. The grobjs are
380  * 3 words long on both. grobj format on NV04 is:
381  *
382  * word 0:
383  *  - bits 0-7: class
384  *  - bit 12: color key active
385  *  - bit 13: clip rect active
386  *  - bit 14: if set, destination surface is swizzled and taken from buffer 5
387  *            [set by NV04_SWIZZLED_SURFACE], otherwise it's linear and taken
388  *            from buffer 0 [set by NV04_CONTEXT_SURFACES_2D or
389  *            NV03_CONTEXT_SURFACE_DST].
390  *  - bits 15-17: 2d operation [aka patch config]
391  *  - bit 24: patch valid [enables rendering using this object]
392  *  - bit 25: surf3d valid [for tex_tri and multitex_tri only]
393  * word 1:
394  *  - bits 0-1: mono format
395  *  - bits 8-13: color format
396  *  - bits 16-31: DMA_NOTIFY instance
397  * word 2:
398  *  - bits 0-15: DMA_A instance
399  *  - bits 16-31: DMA_B instance
400  *
401  * On NV05 it's:
402  *
403  * word 0:
404  *  - bits 0-7: class
405  *  - bit 12: color key active
406  *  - bit 13: clip rect active
407  *  - bit 14: if set, destination surface is swizzled and taken from buffer 5
408  *            [set by NV04_SWIZZLED_SURFACE], otherwise it's linear and taken
409  *            from buffer 0 [set by NV04_CONTEXT_SURFACES_2D or
410  *            NV03_CONTEXT_SURFACE_DST].
411  *  - bits 15-17: 2d operation [aka patch config]
412  *  - bits 20-22: dither mode
413  *  - bit 24: patch valid [enables rendering using this object]
414  *  - bit 25: surface_dst/surface_color/surf2d/surf3d valid
415  *  - bit 26: surface_src/surface_zeta valid
416  *  - bit 27: pattern valid
417  *  - bit 28: rop valid
418  *  - bit 29: beta1 valid
419  *  - bit 30: beta4 valid
420  * word 1:
421  *  - bits 0-1: mono format
422  *  - bits 8-13: color format
423  *  - bits 16-31: DMA_NOTIFY instance
424  * word 2:
425  *  - bits 0-15: DMA_A instance
426  *  - bits 16-31: DMA_B instance
427  *
428  * NV05 will set/unset the relevant valid bits when you poke the relevant
429  * object-binding methods with object of the proper type, or with the NULL
430  * type. It'll only allow rendering using the grobj if all needed objects
431  * are bound. The needed set of objects depends on selected operation: for
432  * example rop object is needed by ROP_AND, but not by SRCCOPY_AND.
433  *
434  * NV04 doesn't have these methods implemented at all, and doesn't have the
435  * relevant bits in grobj. Instead, it'll allow rendering whenever bit 24
436  * is set. So we have to emulate them in software, internally keeping the
437  * same bits as NV05 does. Since grobjs are aligned to 16 bytes on nv04,
438  * but the last word isn't actually used for anything, we abuse it for this
439  * purpose.
440  *
441  * Actually, NV05 can optionally check bit 24 too, but we disable this since
442  * there's no use for it.
443  *
444  * For unknown reasons, NV04 implements surf3d binding in hardware as an
445  * exception. Also for unknown reasons, NV04 doesn't implement the clipping
446  * methods on the surf3d object, so we have to emulate them too.
447  */
448 
449 static void
nv04_gr_set_ctx1(struct nvkm_device * device,u32 inst,u32 mask,u32 value)450 nv04_gr_set_ctx1(struct nvkm_device *device, u32 inst, u32 mask, u32 value)
451 {
452 	int subc = (nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7;
453 	u32 tmp;
454 
455 	tmp  = nvkm_rd32(device, 0x700000 + inst);
456 	tmp &= ~mask;
457 	tmp |= value;
458 	nvkm_wr32(device, 0x700000 + inst, tmp);
459 
460 	nvkm_wr32(device, NV04_PGRAPH_CTX_SWITCH1, tmp);
461 	nvkm_wr32(device, NV04_PGRAPH_CTX_CACHE1 + (subc << 2), tmp);
462 }
463 
464 static void
nv04_gr_set_ctx_val(struct nvkm_device * device,u32 inst,u32 mask,u32 value)465 nv04_gr_set_ctx_val(struct nvkm_device *device, u32 inst, u32 mask, u32 value)
466 {
467 	int class, op, valid = 1;
468 	u32 tmp, ctx1;
469 
470 	ctx1 = nvkm_rd32(device, 0x700000 + inst);
471 	class = ctx1 & 0xff;
472 	op = (ctx1 >> 15) & 7;
473 
474 	tmp = nvkm_rd32(device, 0x70000c + inst);
475 	tmp &= ~mask;
476 	tmp |= value;
477 	nvkm_wr32(device, 0x70000c + inst, tmp);
478 
479 	/* check for valid surf2d/surf_dst/surf_color */
480 	if (!(tmp & 0x02000000))
481 		valid = 0;
482 	/* check for valid surf_src/surf_zeta */
483 	if ((class == 0x1f || class == 0x48) && !(tmp & 0x04000000))
484 		valid = 0;
485 
486 	switch (op) {
487 	/* SRCCOPY_AND, SRCCOPY: no extra objects required */
488 	case 0:
489 	case 3:
490 		break;
491 	/* ROP_AND: requires pattern and rop */
492 	case 1:
493 		if (!(tmp & 0x18000000))
494 			valid = 0;
495 		break;
496 	/* BLEND_AND: requires beta1 */
497 	case 2:
498 		if (!(tmp & 0x20000000))
499 			valid = 0;
500 		break;
501 	/* SRCCOPY_PREMULT, BLEND_PREMULT: beta4 required */
502 	case 4:
503 	case 5:
504 		if (!(tmp & 0x40000000))
505 			valid = 0;
506 		break;
507 	}
508 
509 	nv04_gr_set_ctx1(device, inst, 0x01000000, valid << 24);
510 }
511 
512 static bool
nv04_gr_mthd_set_operation(struct nvkm_device * device,u32 inst,u32 data)513 nv04_gr_mthd_set_operation(struct nvkm_device *device, u32 inst, u32 data)
514 {
515 	u8 class = nvkm_rd32(device, 0x700000) & 0x000000ff;
516 	if (data > 5)
517 		return false;
518 	/* Old versions of the objects only accept first three operations. */
519 	if (data > 2 && class < 0x40)
520 		return false;
521 	nv04_gr_set_ctx1(device, inst, 0x00038000, data << 15);
522 	/* changing operation changes set of objects needed for validation */
523 	nv04_gr_set_ctx_val(device, inst, 0, 0);
524 	return true;
525 }
526 
527 static bool
nv04_gr_mthd_surf3d_clip_h(struct nvkm_device * device,u32 inst,u32 data)528 nv04_gr_mthd_surf3d_clip_h(struct nvkm_device *device, u32 inst, u32 data)
529 {
530 	u32 min = data & 0xffff, max;
531 	u32 w = data >> 16;
532 	if (min & 0x8000)
533 		/* too large */
534 		return false;
535 	if (w & 0x8000)
536 		/* yes, it accepts negative for some reason. */
537 		w |= 0xffff0000;
538 	max = min + w;
539 	max &= 0x3ffff;
540 	nvkm_wr32(device, 0x40053c, min);
541 	nvkm_wr32(device, 0x400544, max);
542 	return true;
543 }
544 
545 static bool
nv04_gr_mthd_surf3d_clip_v(struct nvkm_device * device,u32 inst,u32 data)546 nv04_gr_mthd_surf3d_clip_v(struct nvkm_device *device, u32 inst, u32 data)
547 {
548 	u32 min = data & 0xffff, max;
549 	u32 w = data >> 16;
550 	if (min & 0x8000)
551 		/* too large */
552 		return false;
553 	if (w & 0x8000)
554 		/* yes, it accepts negative for some reason. */
555 		w |= 0xffff0000;
556 	max = min + w;
557 	max &= 0x3ffff;
558 	nvkm_wr32(device, 0x400540, min);
559 	nvkm_wr32(device, 0x400548, max);
560 	return true;
561 }
562 
563 static u8
nv04_gr_mthd_bind_class(struct nvkm_device * device,u32 inst)564 nv04_gr_mthd_bind_class(struct nvkm_device *device, u32 inst)
565 {
566 	return nvkm_rd32(device, 0x700000 + (inst << 4));
567 }
568 
569 static bool
nv04_gr_mthd_bind_surf2d(struct nvkm_device * device,u32 inst,u32 data)570 nv04_gr_mthd_bind_surf2d(struct nvkm_device *device, u32 inst, u32 data)
571 {
572 	switch (nv04_gr_mthd_bind_class(device, data)) {
573 	case 0x30:
574 		nv04_gr_set_ctx1(device, inst, 0x00004000, 0);
575 		nv04_gr_set_ctx_val(device, inst, 0x02000000, 0);
576 		return true;
577 	case 0x42:
578 		nv04_gr_set_ctx1(device, inst, 0x00004000, 0);
579 		nv04_gr_set_ctx_val(device, inst, 0x02000000, 0x02000000);
580 		return true;
581 	}
582 	return false;
583 }
584 
585 static bool
nv04_gr_mthd_bind_surf2d_swzsurf(struct nvkm_device * device,u32 inst,u32 data)586 nv04_gr_mthd_bind_surf2d_swzsurf(struct nvkm_device *device, u32 inst, u32 data)
587 {
588 	switch (nv04_gr_mthd_bind_class(device, data)) {
589 	case 0x30:
590 		nv04_gr_set_ctx1(device, inst, 0x00004000, 0);
591 		nv04_gr_set_ctx_val(device, inst, 0x02000000, 0);
592 		return true;
593 	case 0x42:
594 		nv04_gr_set_ctx1(device, inst, 0x00004000, 0);
595 		nv04_gr_set_ctx_val(device, inst, 0x02000000, 0x02000000);
596 		return true;
597 	case 0x52:
598 		nv04_gr_set_ctx1(device, inst, 0x00004000, 0x00004000);
599 		nv04_gr_set_ctx_val(device, inst, 0x02000000, 0x02000000);
600 		return true;
601 	}
602 	return false;
603 }
604 
605 static bool
nv01_gr_mthd_bind_patt(struct nvkm_device * device,u32 inst,u32 data)606 nv01_gr_mthd_bind_patt(struct nvkm_device *device, u32 inst, u32 data)
607 {
608 	switch (nv04_gr_mthd_bind_class(device, data)) {
609 	case 0x30:
610 		nv04_gr_set_ctx_val(device, inst, 0x08000000, 0);
611 		return true;
612 	case 0x18:
613 		nv04_gr_set_ctx_val(device, inst, 0x08000000, 0x08000000);
614 		return true;
615 	}
616 	return false;
617 }
618 
619 static bool
nv04_gr_mthd_bind_patt(struct nvkm_device * device,u32 inst,u32 data)620 nv04_gr_mthd_bind_patt(struct nvkm_device *device, u32 inst, u32 data)
621 {
622 	switch (nv04_gr_mthd_bind_class(device, data)) {
623 	case 0x30:
624 		nv04_gr_set_ctx_val(device, inst, 0x08000000, 0);
625 		return true;
626 	case 0x44:
627 		nv04_gr_set_ctx_val(device, inst, 0x08000000, 0x08000000);
628 		return true;
629 	}
630 	return false;
631 }
632 
633 static bool
nv04_gr_mthd_bind_rop(struct nvkm_device * device,u32 inst,u32 data)634 nv04_gr_mthd_bind_rop(struct nvkm_device *device, u32 inst, u32 data)
635 {
636 	switch (nv04_gr_mthd_bind_class(device, data)) {
637 	case 0x30:
638 		nv04_gr_set_ctx_val(device, inst, 0x10000000, 0);
639 		return true;
640 	case 0x43:
641 		nv04_gr_set_ctx_val(device, inst, 0x10000000, 0x10000000);
642 		return true;
643 	}
644 	return false;
645 }
646 
647 static bool
nv04_gr_mthd_bind_beta1(struct nvkm_device * device,u32 inst,u32 data)648 nv04_gr_mthd_bind_beta1(struct nvkm_device *device, u32 inst, u32 data)
649 {
650 	switch (nv04_gr_mthd_bind_class(device, data)) {
651 	case 0x30:
652 		nv04_gr_set_ctx_val(device, inst, 0x20000000, 0);
653 		return true;
654 	case 0x12:
655 		nv04_gr_set_ctx_val(device, inst, 0x20000000, 0x20000000);
656 		return true;
657 	}
658 	return false;
659 }
660 
661 static bool
nv04_gr_mthd_bind_beta4(struct nvkm_device * device,u32 inst,u32 data)662 nv04_gr_mthd_bind_beta4(struct nvkm_device *device, u32 inst, u32 data)
663 {
664 	switch (nv04_gr_mthd_bind_class(device, data)) {
665 	case 0x30:
666 		nv04_gr_set_ctx_val(device, inst, 0x40000000, 0);
667 		return true;
668 	case 0x72:
669 		nv04_gr_set_ctx_val(device, inst, 0x40000000, 0x40000000);
670 		return true;
671 	}
672 	return false;
673 }
674 
675 static bool
nv04_gr_mthd_bind_surf_dst(struct nvkm_device * device,u32 inst,u32 data)676 nv04_gr_mthd_bind_surf_dst(struct nvkm_device *device, u32 inst, u32 data)
677 {
678 	switch (nv04_gr_mthd_bind_class(device, data)) {
679 	case 0x30:
680 		nv04_gr_set_ctx_val(device, inst, 0x02000000, 0);
681 		return true;
682 	case 0x58:
683 		nv04_gr_set_ctx_val(device, inst, 0x02000000, 0x02000000);
684 		return true;
685 	}
686 	return false;
687 }
688 
689 static bool
nv04_gr_mthd_bind_surf_src(struct nvkm_device * device,u32 inst,u32 data)690 nv04_gr_mthd_bind_surf_src(struct nvkm_device *device, u32 inst, u32 data)
691 {
692 	switch (nv04_gr_mthd_bind_class(device, data)) {
693 	case 0x30:
694 		nv04_gr_set_ctx_val(device, inst, 0x04000000, 0);
695 		return true;
696 	case 0x59:
697 		nv04_gr_set_ctx_val(device, inst, 0x04000000, 0x04000000);
698 		return true;
699 	}
700 	return false;
701 }
702 
703 static bool
nv04_gr_mthd_bind_surf_color(struct nvkm_device * device,u32 inst,u32 data)704 nv04_gr_mthd_bind_surf_color(struct nvkm_device *device, u32 inst, u32 data)
705 {
706 	switch (nv04_gr_mthd_bind_class(device, data)) {
707 	case 0x30:
708 		nv04_gr_set_ctx_val(device, inst, 0x02000000, 0);
709 		return true;
710 	case 0x5a:
711 		nv04_gr_set_ctx_val(device, inst, 0x02000000, 0x02000000);
712 		return true;
713 	}
714 	return false;
715 }
716 
717 static bool
nv04_gr_mthd_bind_surf_zeta(struct nvkm_device * device,u32 inst,u32 data)718 nv04_gr_mthd_bind_surf_zeta(struct nvkm_device *device, u32 inst, u32 data)
719 {
720 	switch (nv04_gr_mthd_bind_class(device, data)) {
721 	case 0x30:
722 		nv04_gr_set_ctx_val(device, inst, 0x04000000, 0);
723 		return true;
724 	case 0x5b:
725 		nv04_gr_set_ctx_val(device, inst, 0x04000000, 0x04000000);
726 		return true;
727 	}
728 	return false;
729 }
730 
731 static bool
nv01_gr_mthd_bind_clip(struct nvkm_device * device,u32 inst,u32 data)732 nv01_gr_mthd_bind_clip(struct nvkm_device *device, u32 inst, u32 data)
733 {
734 	switch (nv04_gr_mthd_bind_class(device, data)) {
735 	case 0x30:
736 		nv04_gr_set_ctx1(device, inst, 0x2000, 0);
737 		return true;
738 	case 0x19:
739 		nv04_gr_set_ctx1(device, inst, 0x2000, 0x2000);
740 		return true;
741 	}
742 	return false;
743 }
744 
745 static bool
nv01_gr_mthd_bind_chroma(struct nvkm_device * device,u32 inst,u32 data)746 nv01_gr_mthd_bind_chroma(struct nvkm_device *device, u32 inst, u32 data)
747 {
748 	switch (nv04_gr_mthd_bind_class(device, data)) {
749 	case 0x30:
750 		nv04_gr_set_ctx1(device, inst, 0x1000, 0);
751 		return true;
752 	/* Yes, for some reason even the old versions of objects
753 	 * accept 0x57 and not 0x17. Consistency be damned.
754 	 */
755 	case 0x57:
756 		nv04_gr_set_ctx1(device, inst, 0x1000, 0x1000);
757 		return true;
758 	}
759 	return false;
760 }
761 
762 static bool
nv03_gr_mthd_gdi(struct nvkm_device * device,u32 inst,u32 mthd,u32 data)763 nv03_gr_mthd_gdi(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
764 {
765 	bool (*func)(struct nvkm_device *, u32, u32);
766 	switch (mthd) {
767 	case 0x0184: func = nv01_gr_mthd_bind_patt; break;
768 	case 0x0188: func = nv04_gr_mthd_bind_rop; break;
769 	case 0x018c: func = nv04_gr_mthd_bind_beta1; break;
770 	case 0x0190: func = nv04_gr_mthd_bind_surf_dst; break;
771 	case 0x02fc: func = nv04_gr_mthd_set_operation; break;
772 	default:
773 		return false;
774 	}
775 	return func(device, inst, data);
776 }
777 
778 static bool
nv04_gr_mthd_gdi(struct nvkm_device * device,u32 inst,u32 mthd,u32 data)779 nv04_gr_mthd_gdi(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
780 {
781 	bool (*func)(struct nvkm_device *, u32, u32);
782 	switch (mthd) {
783 	case 0x0188: func = nv04_gr_mthd_bind_patt; break;
784 	case 0x018c: func = nv04_gr_mthd_bind_rop; break;
785 	case 0x0190: func = nv04_gr_mthd_bind_beta1; break;
786 	case 0x0194: func = nv04_gr_mthd_bind_beta4; break;
787 	case 0x0198: func = nv04_gr_mthd_bind_surf2d; break;
788 	case 0x02fc: func = nv04_gr_mthd_set_operation; break;
789 	default:
790 		return false;
791 	}
792 	return func(device, inst, data);
793 }
794 
795 static bool
nv01_gr_mthd_blit(struct nvkm_device * device,u32 inst,u32 mthd,u32 data)796 nv01_gr_mthd_blit(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
797 {
798 	bool (*func)(struct nvkm_device *, u32, u32);
799 	switch (mthd) {
800 	case 0x0184: func = nv01_gr_mthd_bind_chroma; break;
801 	case 0x0188: func = nv01_gr_mthd_bind_clip; break;
802 	case 0x018c: func = nv01_gr_mthd_bind_patt; break;
803 	case 0x0190: func = nv04_gr_mthd_bind_rop; break;
804 	case 0x0194: func = nv04_gr_mthd_bind_beta1; break;
805 	case 0x0198: func = nv04_gr_mthd_bind_surf_dst; break;
806 	case 0x019c: func = nv04_gr_mthd_bind_surf_src; break;
807 	case 0x02fc: func = nv04_gr_mthd_set_operation; break;
808 	default:
809 		return false;
810 	}
811 	return func(device, inst, data);
812 }
813 
814 static bool
nv04_gr_mthd_blit(struct nvkm_device * device,u32 inst,u32 mthd,u32 data)815 nv04_gr_mthd_blit(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
816 {
817 	bool (*func)(struct nvkm_device *, u32, u32);
818 	switch (mthd) {
819 	case 0x0184: func = nv01_gr_mthd_bind_chroma; break;
820 	case 0x0188: func = nv01_gr_mthd_bind_clip; break;
821 	case 0x018c: func = nv04_gr_mthd_bind_patt; break;
822 	case 0x0190: func = nv04_gr_mthd_bind_rop; break;
823 	case 0x0194: func = nv04_gr_mthd_bind_beta1; break;
824 	case 0x0198: func = nv04_gr_mthd_bind_beta4; break;
825 	case 0x019c: func = nv04_gr_mthd_bind_surf2d; break;
826 	case 0x02fc: func = nv04_gr_mthd_set_operation; break;
827 	default:
828 		return false;
829 	}
830 	return func(device, inst, data);
831 }
832 
833 static bool
nv04_gr_mthd_iifc(struct nvkm_device * device,u32 inst,u32 mthd,u32 data)834 nv04_gr_mthd_iifc(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
835 {
836 	bool (*func)(struct nvkm_device *, u32, u32);
837 	switch (mthd) {
838 	case 0x0188: func = nv01_gr_mthd_bind_chroma; break;
839 	case 0x018c: func = nv01_gr_mthd_bind_clip; break;
840 	case 0x0190: func = nv04_gr_mthd_bind_patt; break;
841 	case 0x0194: func = nv04_gr_mthd_bind_rop; break;
842 	case 0x0198: func = nv04_gr_mthd_bind_beta1; break;
843 	case 0x019c: func = nv04_gr_mthd_bind_beta4; break;
844 	case 0x01a0: func = nv04_gr_mthd_bind_surf2d_swzsurf; break;
845 	case 0x03e4: func = nv04_gr_mthd_set_operation; break;
846 	default:
847 		return false;
848 	}
849 	return func(device, inst, data);
850 }
851 
852 static bool
nv01_gr_mthd_ifc(struct nvkm_device * device,u32 inst,u32 mthd,u32 data)853 nv01_gr_mthd_ifc(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
854 {
855 	bool (*func)(struct nvkm_device *, u32, u32);
856 	switch (mthd) {
857 	case 0x0184: func = nv01_gr_mthd_bind_chroma; break;
858 	case 0x0188: func = nv01_gr_mthd_bind_clip; break;
859 	case 0x018c: func = nv01_gr_mthd_bind_patt; break;
860 	case 0x0190: func = nv04_gr_mthd_bind_rop; break;
861 	case 0x0194: func = nv04_gr_mthd_bind_beta1; break;
862 	case 0x0198: func = nv04_gr_mthd_bind_surf_dst; break;
863 	case 0x02fc: func = nv04_gr_mthd_set_operation; break;
864 	default:
865 		return false;
866 	}
867 	return func(device, inst, data);
868 }
869 
870 static bool
nv04_gr_mthd_ifc(struct nvkm_device * device,u32 inst,u32 mthd,u32 data)871 nv04_gr_mthd_ifc(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
872 {
873 	bool (*func)(struct nvkm_device *, u32, u32);
874 	switch (mthd) {
875 	case 0x0184: func = nv01_gr_mthd_bind_chroma; break;
876 	case 0x0188: func = nv01_gr_mthd_bind_clip; break;
877 	case 0x018c: func = nv04_gr_mthd_bind_patt; break;
878 	case 0x0190: func = nv04_gr_mthd_bind_rop; break;
879 	case 0x0194: func = nv04_gr_mthd_bind_beta1; break;
880 	case 0x0198: func = nv04_gr_mthd_bind_beta4; break;
881 	case 0x019c: func = nv04_gr_mthd_bind_surf2d; break;
882 	case 0x02fc: func = nv04_gr_mthd_set_operation; break;
883 	default:
884 		return false;
885 	}
886 	return func(device, inst, data);
887 }
888 
889 static bool
nv03_gr_mthd_sifc(struct nvkm_device * device,u32 inst,u32 mthd,u32 data)890 nv03_gr_mthd_sifc(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
891 {
892 	bool (*func)(struct nvkm_device *, u32, u32);
893 	switch (mthd) {
894 	case 0x0184: func = nv01_gr_mthd_bind_chroma; break;
895 	case 0x0188: func = nv01_gr_mthd_bind_patt; break;
896 	case 0x018c: func = nv04_gr_mthd_bind_rop; break;
897 	case 0x0190: func = nv04_gr_mthd_bind_beta1; break;
898 	case 0x0194: func = nv04_gr_mthd_bind_surf_dst; break;
899 	case 0x02fc: func = nv04_gr_mthd_set_operation; break;
900 	default:
901 		return false;
902 	}
903 	return func(device, inst, data);
904 }
905 
906 static bool
nv04_gr_mthd_sifc(struct nvkm_device * device,u32 inst,u32 mthd,u32 data)907 nv04_gr_mthd_sifc(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
908 {
909 	bool (*func)(struct nvkm_device *, u32, u32);
910 	switch (mthd) {
911 	case 0x0184: func = nv01_gr_mthd_bind_chroma; break;
912 	case 0x0188: func = nv04_gr_mthd_bind_patt; break;
913 	case 0x018c: func = nv04_gr_mthd_bind_rop; break;
914 	case 0x0190: func = nv04_gr_mthd_bind_beta1; break;
915 	case 0x0194: func = nv04_gr_mthd_bind_beta4; break;
916 	case 0x0198: func = nv04_gr_mthd_bind_surf2d; break;
917 	case 0x02fc: func = nv04_gr_mthd_set_operation; break;
918 	default:
919 		return false;
920 	}
921 	return func(device, inst, data);
922 }
923 
924 static bool
nv03_gr_mthd_sifm(struct nvkm_device * device,u32 inst,u32 mthd,u32 data)925 nv03_gr_mthd_sifm(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
926 {
927 	bool (*func)(struct nvkm_device *, u32, u32);
928 	switch (mthd) {
929 	case 0x0188: func = nv01_gr_mthd_bind_patt; break;
930 	case 0x018c: func = nv04_gr_mthd_bind_rop; break;
931 	case 0x0190: func = nv04_gr_mthd_bind_beta1; break;
932 	case 0x0194: func = nv04_gr_mthd_bind_surf_dst; break;
933 	case 0x0304: func = nv04_gr_mthd_set_operation; break;
934 	default:
935 		return false;
936 	}
937 	return func(device, inst, data);
938 }
939 
940 static bool
nv04_gr_mthd_sifm(struct nvkm_device * device,u32 inst,u32 mthd,u32 data)941 nv04_gr_mthd_sifm(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
942 {
943 	bool (*func)(struct nvkm_device *, u32, u32);
944 	switch (mthd) {
945 	case 0x0188: func = nv04_gr_mthd_bind_patt; break;
946 	case 0x018c: func = nv04_gr_mthd_bind_rop; break;
947 	case 0x0190: func = nv04_gr_mthd_bind_beta1; break;
948 	case 0x0194: func = nv04_gr_mthd_bind_beta4; break;
949 	case 0x0198: func = nv04_gr_mthd_bind_surf2d; break;
950 	case 0x0304: func = nv04_gr_mthd_set_operation; break;
951 	default:
952 		return false;
953 	}
954 	return func(device, inst, data);
955 }
956 
957 static bool
nv04_gr_mthd_surf3d(struct nvkm_device * device,u32 inst,u32 mthd,u32 data)958 nv04_gr_mthd_surf3d(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
959 {
960 	bool (*func)(struct nvkm_device *, u32, u32);
961 	switch (mthd) {
962 	case 0x02f8: func = nv04_gr_mthd_surf3d_clip_h; break;
963 	case 0x02fc: func = nv04_gr_mthd_surf3d_clip_v; break;
964 	default:
965 		return false;
966 	}
967 	return func(device, inst, data);
968 }
969 
970 static bool
nv03_gr_mthd_ttri(struct nvkm_device * device,u32 inst,u32 mthd,u32 data)971 nv03_gr_mthd_ttri(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
972 {
973 	bool (*func)(struct nvkm_device *, u32, u32);
974 	switch (mthd) {
975 	case 0x0188: func = nv01_gr_mthd_bind_clip; break;
976 	case 0x018c: func = nv04_gr_mthd_bind_surf_color; break;
977 	case 0x0190: func = nv04_gr_mthd_bind_surf_zeta; break;
978 	default:
979 		return false;
980 	}
981 	return func(device, inst, data);
982 }
983 
984 static bool
nv01_gr_mthd_prim(struct nvkm_device * device,u32 inst,u32 mthd,u32 data)985 nv01_gr_mthd_prim(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
986 {
987 	bool (*func)(struct nvkm_device *, u32, u32);
988 	switch (mthd) {
989 	case 0x0184: func = nv01_gr_mthd_bind_clip; break;
990 	case 0x0188: func = nv01_gr_mthd_bind_patt; break;
991 	case 0x018c: func = nv04_gr_mthd_bind_rop; break;
992 	case 0x0190: func = nv04_gr_mthd_bind_beta1; break;
993 	case 0x0194: func = nv04_gr_mthd_bind_surf_dst; break;
994 	case 0x02fc: func = nv04_gr_mthd_set_operation; break;
995 	default:
996 		return false;
997 	}
998 	return func(device, inst, data);
999 }
1000 
1001 static bool
nv04_gr_mthd_prim(struct nvkm_device * device,u32 inst,u32 mthd,u32 data)1002 nv04_gr_mthd_prim(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
1003 {
1004 	bool (*func)(struct nvkm_device *, u32, u32);
1005 	switch (mthd) {
1006 	case 0x0184: func = nv01_gr_mthd_bind_clip; break;
1007 	case 0x0188: func = nv04_gr_mthd_bind_patt; break;
1008 	case 0x018c: func = nv04_gr_mthd_bind_rop; break;
1009 	case 0x0190: func = nv04_gr_mthd_bind_beta1; break;
1010 	case 0x0194: func = nv04_gr_mthd_bind_beta4; break;
1011 	case 0x0198: func = nv04_gr_mthd_bind_surf2d; break;
1012 	case 0x02fc: func = nv04_gr_mthd_set_operation; break;
1013 	default:
1014 		return false;
1015 	}
1016 	return func(device, inst, data);
1017 }
1018 
1019 static bool
nv04_gr_mthd(struct nvkm_device * device,u32 inst,u32 mthd,u32 data)1020 nv04_gr_mthd(struct nvkm_device *device, u32 inst, u32 mthd, u32 data)
1021 {
1022 	bool (*func)(struct nvkm_device *, u32, u32, u32);
1023 	switch (nvkm_rd32(device, 0x700000 + inst) & 0x000000ff) {
1024 	case 0x1c ... 0x1e:
1025 		   func = nv01_gr_mthd_prim; break;
1026 	case 0x1f: func = nv01_gr_mthd_blit; break;
1027 	case 0x21: func = nv01_gr_mthd_ifc; break;
1028 	case 0x36: func = nv03_gr_mthd_sifc; break;
1029 	case 0x37: func = nv03_gr_mthd_sifm; break;
1030 	case 0x48: func = nv03_gr_mthd_ttri; break;
1031 	case 0x4a: func = nv04_gr_mthd_gdi; break;
1032 	case 0x4b: func = nv03_gr_mthd_gdi; break;
1033 	case 0x53: func = nv04_gr_mthd_surf3d; break;
1034 	case 0x5c ... 0x5e:
1035 		   func = nv04_gr_mthd_prim; break;
1036 	case 0x5f: func = nv04_gr_mthd_blit; break;
1037 	case 0x60: func = nv04_gr_mthd_iifc; break;
1038 	case 0x61: func = nv04_gr_mthd_ifc; break;
1039 	case 0x76: func = nv04_gr_mthd_sifc; break;
1040 	case 0x77: func = nv04_gr_mthd_sifm; break;
1041 	default:
1042 		return false;
1043 	}
1044 	return func(device, inst, mthd, data);
1045 }
1046 
1047 static int
nv04_gr_object_bind(struct nvkm_object * object,struct nvkm_gpuobj * parent,int align,struct nvkm_gpuobj ** pgpuobj)1048 nv04_gr_object_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent,
1049 		    int align, struct nvkm_gpuobj **pgpuobj)
1050 {
1051 	int ret = nvkm_gpuobj_new(object->engine->subdev.device, 16, align,
1052 				  false, parent, pgpuobj);
1053 	if (ret == 0) {
1054 		nvkm_kmap(*pgpuobj);
1055 		nvkm_wo32(*pgpuobj, 0x00, object->oclass);
1056 #ifdef __BIG_ENDIAN
1057 		nvkm_mo32(*pgpuobj, 0x00, 0x00080000, 0x00080000);
1058 #endif
1059 		nvkm_wo32(*pgpuobj, 0x04, 0x00000000);
1060 		nvkm_wo32(*pgpuobj, 0x08, 0x00000000);
1061 		nvkm_wo32(*pgpuobj, 0x0c, 0x00000000);
1062 		nvkm_done(*pgpuobj);
1063 	}
1064 	return ret;
1065 }
1066 
1067 const struct nvkm_object_func
1068 nv04_gr_object = {
1069 	.bind = nv04_gr_object_bind,
1070 };
1071 
1072 /*******************************************************************************
1073  * PGRAPH context
1074  ******************************************************************************/
1075 
1076 static struct nv04_gr_chan *
nv04_gr_channel(struct nv04_gr * gr)1077 nv04_gr_channel(struct nv04_gr *gr)
1078 {
1079 	struct nvkm_device *device = gr->base.engine.subdev.device;
1080 	struct nv04_gr_chan *chan = NULL;
1081 	if (nvkm_rd32(device, NV04_PGRAPH_CTX_CONTROL) & 0x00010000) {
1082 		int chid = nvkm_rd32(device, NV04_PGRAPH_CTX_USER) >> 24;
1083 		if (chid < ARRAY_SIZE(gr->chan))
1084 			chan = gr->chan[chid];
1085 	}
1086 	return chan;
1087 }
1088 
1089 static int
nv04_gr_load_context(struct nv04_gr_chan * chan,int chid)1090 nv04_gr_load_context(struct nv04_gr_chan *chan, int chid)
1091 {
1092 	struct nvkm_device *device = chan->gr->base.engine.subdev.device;
1093 	int i;
1094 
1095 	for (i = 0; i < ARRAY_SIZE(nv04_gr_ctx_regs); i++)
1096 		nvkm_wr32(device, nv04_gr_ctx_regs[i], chan->nv04[i]);
1097 
1098 	nvkm_wr32(device, NV04_PGRAPH_CTX_CONTROL, 0x10010100);
1099 	nvkm_mask(device, NV04_PGRAPH_CTX_USER, 0xff000000, chid << 24);
1100 	nvkm_mask(device, NV04_PGRAPH_FFINTFC_ST2, 0xfff00000, 0x00000000);
1101 	return 0;
1102 }
1103 
1104 static int
nv04_gr_unload_context(struct nv04_gr_chan * chan)1105 nv04_gr_unload_context(struct nv04_gr_chan *chan)
1106 {
1107 	struct nvkm_device *device = chan->gr->base.engine.subdev.device;
1108 	int i;
1109 
1110 	for (i = 0; i < ARRAY_SIZE(nv04_gr_ctx_regs); i++)
1111 		chan->nv04[i] = nvkm_rd32(device, nv04_gr_ctx_regs[i]);
1112 
1113 	nvkm_wr32(device, NV04_PGRAPH_CTX_CONTROL, 0x10000000);
1114 	nvkm_mask(device, NV04_PGRAPH_CTX_USER, 0xff000000, 0x0f000000);
1115 	return 0;
1116 }
1117 
1118 static void
nv04_gr_context_switch(struct nv04_gr * gr)1119 nv04_gr_context_switch(struct nv04_gr *gr)
1120 {
1121 	struct nvkm_device *device = gr->base.engine.subdev.device;
1122 	struct nv04_gr_chan *prev = NULL;
1123 	struct nv04_gr_chan *next = NULL;
1124 	int chid;
1125 
1126 	nv04_gr_idle(&gr->base);
1127 
1128 	/* If previous context is valid, we need to save it */
1129 	prev = nv04_gr_channel(gr);
1130 	if (prev)
1131 		nv04_gr_unload_context(prev);
1132 
1133 	/* load context for next channel */
1134 	chid = (nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR) >> 24) & 0x0f;
1135 	next = gr->chan[chid];
1136 	if (next)
1137 		nv04_gr_load_context(next, chid);
1138 }
1139 
ctx_reg(struct nv04_gr_chan * chan,u32 reg)1140 static u32 *ctx_reg(struct nv04_gr_chan *chan, u32 reg)
1141 {
1142 	int i;
1143 
1144 	for (i = 0; i < ARRAY_SIZE(nv04_gr_ctx_regs); i++) {
1145 		if (nv04_gr_ctx_regs[i] == reg)
1146 			return &chan->nv04[i];
1147 	}
1148 
1149 	return NULL;
1150 }
1151 
1152 static void *
nv04_gr_chan_dtor(struct nvkm_object * object)1153 nv04_gr_chan_dtor(struct nvkm_object *object)
1154 {
1155 	struct nv04_gr_chan *chan = nv04_gr_chan(object);
1156 	struct nv04_gr *gr = chan->gr;
1157 	unsigned long flags;
1158 
1159 	spin_lock_irqsave(&gr->lock, flags);
1160 	gr->chan[chan->chid] = NULL;
1161 	spin_unlock_irqrestore(&gr->lock, flags);
1162 	return chan;
1163 }
1164 
1165 static int
nv04_gr_chan_fini(struct nvkm_object * object,bool suspend)1166 nv04_gr_chan_fini(struct nvkm_object *object, bool suspend)
1167 {
1168 	struct nv04_gr_chan *chan = nv04_gr_chan(object);
1169 	struct nv04_gr *gr = chan->gr;
1170 	struct nvkm_device *device = gr->base.engine.subdev.device;
1171 	unsigned long flags;
1172 
1173 	spin_lock_irqsave(&gr->lock, flags);
1174 	nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
1175 	if (nv04_gr_channel(gr) == chan)
1176 		nv04_gr_unload_context(chan);
1177 	nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
1178 	spin_unlock_irqrestore(&gr->lock, flags);
1179 	return 0;
1180 }
1181 
1182 static const struct nvkm_object_func
1183 nv04_gr_chan = {
1184 	.dtor = nv04_gr_chan_dtor,
1185 	.fini = nv04_gr_chan_fini,
1186 };
1187 
1188 static int
nv04_gr_chan_new(struct nvkm_gr * base,struct nvkm_fifo_chan * fifoch,const struct nvkm_oclass * oclass,struct nvkm_object ** pobject)1189 nv04_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
1190 		 const struct nvkm_oclass *oclass, struct nvkm_object **pobject)
1191 {
1192 	struct nv04_gr *gr = nv04_gr(base);
1193 	struct nv04_gr_chan *chan;
1194 	unsigned long flags;
1195 
1196 	if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
1197 		return -ENOMEM;
1198 	nvkm_object_ctor(&nv04_gr_chan, oclass, &chan->object);
1199 	chan->gr = gr;
1200 	chan->chid = fifoch->chid;
1201 	*pobject = &chan->object;
1202 
1203 	*ctx_reg(chan, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31;
1204 
1205 	spin_lock_irqsave(&gr->lock, flags);
1206 	gr->chan[chan->chid] = chan;
1207 	spin_unlock_irqrestore(&gr->lock, flags);
1208 	return 0;
1209 }
1210 
1211 /*******************************************************************************
1212  * PGRAPH engine/subdev functions
1213  ******************************************************************************/
1214 
1215 bool
nv04_gr_idle(struct nvkm_gr * gr)1216 nv04_gr_idle(struct nvkm_gr *gr)
1217 {
1218 	struct nvkm_subdev *subdev = &gr->engine.subdev;
1219 	struct nvkm_device *device = subdev->device;
1220 	u32 mask = 0xffffffff;
1221 
1222 	if (device->card_type == NV_40)
1223 		mask &= ~NV40_PGRAPH_STATUS_SYNC_STALL;
1224 
1225 	if (nvkm_msec(device, 2000,
1226 		if (!(nvkm_rd32(device, NV04_PGRAPH_STATUS) & mask))
1227 			break;
1228 	) < 0) {
1229 		nvkm_error(subdev, "idle timed out with status %08x\n",
1230 			   nvkm_rd32(device, NV04_PGRAPH_STATUS));
1231 		return false;
1232 	}
1233 
1234 	return true;
1235 }
1236 
1237 static const struct nvkm_bitfield
1238 nv04_gr_intr_name[] = {
1239 	{ NV_PGRAPH_INTR_NOTIFY, "NOTIFY" },
1240 	{}
1241 };
1242 
1243 static const struct nvkm_bitfield
1244 nv04_gr_nstatus[] = {
1245 	{ NV04_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
1246 	{ NV04_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
1247 	{ NV04_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
1248 	{ NV04_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" },
1249 	{}
1250 };
1251 
1252 const struct nvkm_bitfield
1253 nv04_gr_nsource[] = {
1254 	{ NV03_PGRAPH_NSOURCE_NOTIFICATION,       "NOTIFICATION" },
1255 	{ NV03_PGRAPH_NSOURCE_DATA_ERROR,         "DATA_ERROR" },
1256 	{ NV03_PGRAPH_NSOURCE_PROTECTION_ERROR,   "PROTECTION_ERROR" },
1257 	{ NV03_PGRAPH_NSOURCE_RANGE_EXCEPTION,    "RANGE_EXCEPTION" },
1258 	{ NV03_PGRAPH_NSOURCE_LIMIT_COLOR,        "LIMIT_COLOR" },
1259 	{ NV03_PGRAPH_NSOURCE_LIMIT_ZETA,         "LIMIT_ZETA" },
1260 	{ NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD,       "ILLEGAL_MTHD" },
1261 	{ NV03_PGRAPH_NSOURCE_DMA_R_PROTECTION,   "DMA_R_PROTECTION" },
1262 	{ NV03_PGRAPH_NSOURCE_DMA_W_PROTECTION,   "DMA_W_PROTECTION" },
1263 	{ NV03_PGRAPH_NSOURCE_FORMAT_EXCEPTION,   "FORMAT_EXCEPTION" },
1264 	{ NV03_PGRAPH_NSOURCE_PATCH_EXCEPTION,    "PATCH_EXCEPTION" },
1265 	{ NV03_PGRAPH_NSOURCE_STATE_INVALID,      "STATE_INVALID" },
1266 	{ NV03_PGRAPH_NSOURCE_DOUBLE_NOTIFY,      "DOUBLE_NOTIFY" },
1267 	{ NV03_PGRAPH_NSOURCE_NOTIFY_IN_USE,      "NOTIFY_IN_USE" },
1268 	{ NV03_PGRAPH_NSOURCE_METHOD_CNT,         "METHOD_CNT" },
1269 	{ NV03_PGRAPH_NSOURCE_BFR_NOTIFICATION,   "BFR_NOTIFICATION" },
1270 	{ NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION, "DMA_VTX_PROTECTION" },
1271 	{ NV03_PGRAPH_NSOURCE_DMA_WIDTH_A,        "DMA_WIDTH_A" },
1272 	{ NV03_PGRAPH_NSOURCE_DMA_WIDTH_B,        "DMA_WIDTH_B" },
1273 	{}
1274 };
1275 
1276 static void
nv04_gr_intr(struct nvkm_gr * base)1277 nv04_gr_intr(struct nvkm_gr *base)
1278 {
1279 	struct nv04_gr *gr = nv04_gr(base);
1280 	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
1281 	struct nvkm_device *device = subdev->device;
1282 	u32 stat = nvkm_rd32(device, NV03_PGRAPH_INTR);
1283 	u32 nsource = nvkm_rd32(device, NV03_PGRAPH_NSOURCE);
1284 	u32 nstatus = nvkm_rd32(device, NV03_PGRAPH_NSTATUS);
1285 	u32 addr = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR);
1286 	u32 chid = (addr & 0x0f000000) >> 24;
1287 	u32 subc = (addr & 0x0000e000) >> 13;
1288 	u32 mthd = (addr & 0x00001ffc);
1289 	u32 data = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_DATA);
1290 	u32 class = nvkm_rd32(device, 0x400180 + subc * 4) & 0xff;
1291 	u32 inst = (nvkm_rd32(device, 0x40016c) & 0xffff) << 4;
1292 	u32 show = stat;
1293 	char msg[128], src[128], sta[128];
1294 	struct nv04_gr_chan *chan;
1295 	unsigned long flags;
1296 
1297 	spin_lock_irqsave(&gr->lock, flags);
1298 	chan = gr->chan[chid];
1299 
1300 	if (stat & NV_PGRAPH_INTR_NOTIFY) {
1301 		if (chan && (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD)) {
1302 			if (!nv04_gr_mthd(device, inst, mthd, data))
1303 				show &= ~NV_PGRAPH_INTR_NOTIFY;
1304 		}
1305 	}
1306 
1307 	if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
1308 		nvkm_wr32(device, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH);
1309 		stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1310 		show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1311 		nv04_gr_context_switch(gr);
1312 	}
1313 
1314 	nvkm_wr32(device, NV03_PGRAPH_INTR, stat);
1315 	nvkm_wr32(device, NV04_PGRAPH_FIFO, 0x00000001);
1316 
1317 	if (show) {
1318 		nvkm_snprintbf(msg, sizeof(msg), nv04_gr_intr_name, show);
1319 		nvkm_snprintbf(src, sizeof(src), nv04_gr_nsource, nsource);
1320 		nvkm_snprintbf(sta, sizeof(sta), nv04_gr_nstatus, nstatus);
1321 		nvkm_error(subdev, "intr %08x [%s] nsource %08x [%s] "
1322 				   "nstatus %08x [%s] ch %d [%s] subc %d "
1323 				   "class %04x mthd %04x data %08x\n",
1324 			   show, msg, nsource, src, nstatus, sta, chid,
1325 			   chan ? chan->object.client->name : "unknown",
1326 			   subc, class, mthd, data);
1327 	}
1328 
1329 	spin_unlock_irqrestore(&gr->lock, flags);
1330 }
1331 
1332 static int
nv04_gr_init(struct nvkm_gr * base)1333 nv04_gr_init(struct nvkm_gr *base)
1334 {
1335 	struct nv04_gr *gr = nv04_gr(base);
1336 	struct nvkm_device *device = gr->base.engine.subdev.device;
1337 
1338 	/* Enable PGRAPH interrupts */
1339 	nvkm_wr32(device, NV03_PGRAPH_INTR, 0xFFFFFFFF);
1340 	nvkm_wr32(device, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
1341 
1342 	nvkm_wr32(device, NV04_PGRAPH_VALID1, 0);
1343 	nvkm_wr32(device, NV04_PGRAPH_VALID2, 0);
1344 	/*nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x000001FF);
1345 	nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x001FFFFF);*/
1346 	nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x1231c000);
1347 	/*1231C000 blob, 001 haiku*/
1348 	/*V_WRITE(NV04_PGRAPH_DEBUG_1, 0xf2d91100);*/
1349 	nvkm_wr32(device, NV04_PGRAPH_DEBUG_1, 0x72111100);
1350 	/*0x72111100 blob , 01 haiku*/
1351 	/*nvkm_wr32(device, NV04_PGRAPH_DEBUG_2, 0x11d5f870);*/
1352 	nvkm_wr32(device, NV04_PGRAPH_DEBUG_2, 0x11d5f071);
1353 	/*haiku same*/
1354 
1355 	/*nvkm_wr32(device, NV04_PGRAPH_DEBUG_3, 0xfad4ff31);*/
1356 	nvkm_wr32(device, NV04_PGRAPH_DEBUG_3, 0xf0d4ff31);
1357 	/*haiku and blob 10d4*/
1358 
1359 	nvkm_wr32(device, NV04_PGRAPH_STATE        , 0xFFFFFFFF);
1360 	nvkm_wr32(device, NV04_PGRAPH_CTX_CONTROL  , 0x10000100);
1361 	nvkm_mask(device, NV04_PGRAPH_CTX_USER, 0xff000000, 0x0f000000);
1362 
1363 	/* These don't belong here, they're part of a per-channel context */
1364 	nvkm_wr32(device, NV04_PGRAPH_PATTERN_SHAPE, 0x00000000);
1365 	nvkm_wr32(device, NV04_PGRAPH_BETA_AND     , 0xFFFFFFFF);
1366 	return 0;
1367 }
1368 
1369 static void *
nv04_gr_dtor(struct nvkm_gr * gr)1370 nv04_gr_dtor(struct nvkm_gr *gr)
1371 {
1372 	spin_lock_destroy(&nv04_gr(gr)->lock);
1373 	return gr;
1374 }
1375 
1376 static const struct nvkm_gr_func
1377 nv04_gr = {
1378 	.init = nv04_gr_init,
1379 	.dtor = nv04_gr_dtor,
1380 	.intr = nv04_gr_intr,
1381 	.chan_new = nv04_gr_chan_new,
1382 	.sclass = {
1383 		{ -1, -1, 0x0012, &nv04_gr_object }, /* beta1 */
1384 		{ -1, -1, 0x0017, &nv04_gr_object }, /* chroma */
1385 		{ -1, -1, 0x0018, &nv04_gr_object }, /* pattern (nv01) */
1386 		{ -1, -1, 0x0019, &nv04_gr_object }, /* clip */
1387 		{ -1, -1, 0x001c, &nv04_gr_object }, /* line */
1388 		{ -1, -1, 0x001d, &nv04_gr_object }, /* tri */
1389 		{ -1, -1, 0x001e, &nv04_gr_object }, /* rect */
1390 		{ -1, -1, 0x001f, &nv04_gr_object },
1391 		{ -1, -1, 0x0021, &nv04_gr_object },
1392 		{ -1, -1, 0x0030, &nv04_gr_object }, /* null */
1393 		{ -1, -1, 0x0036, &nv04_gr_object },
1394 		{ -1, -1, 0x0037, &nv04_gr_object },
1395 		{ -1, -1, 0x0038, &nv04_gr_object }, /* dvd subpicture */
1396 		{ -1, -1, 0x0039, &nv04_gr_object }, /* m2mf */
1397 		{ -1, -1, 0x0042, &nv04_gr_object }, /* surf2d */
1398 		{ -1, -1, 0x0043, &nv04_gr_object }, /* rop */
1399 		{ -1, -1, 0x0044, &nv04_gr_object }, /* pattern */
1400 		{ -1, -1, 0x0048, &nv04_gr_object },
1401 		{ -1, -1, 0x004a, &nv04_gr_object },
1402 		{ -1, -1, 0x004b, &nv04_gr_object },
1403 		{ -1, -1, 0x0052, &nv04_gr_object }, /* swzsurf */
1404 		{ -1, -1, 0x0053, &nv04_gr_object },
1405 		{ -1, -1, 0x0054, &nv04_gr_object }, /* ttri */
1406 		{ -1, -1, 0x0055, &nv04_gr_object }, /* mtri */
1407 		{ -1, -1, 0x0057, &nv04_gr_object }, /* chroma */
1408 		{ -1, -1, 0x0058, &nv04_gr_object }, /* surf_dst */
1409 		{ -1, -1, 0x0059, &nv04_gr_object }, /* surf_src */
1410 		{ -1, -1, 0x005a, &nv04_gr_object }, /* surf_color */
1411 		{ -1, -1, 0x005b, &nv04_gr_object }, /* surf_zeta */
1412 		{ -1, -1, 0x005c, &nv04_gr_object }, /* line */
1413 		{ -1, -1, 0x005d, &nv04_gr_object }, /* tri */
1414 		{ -1, -1, 0x005e, &nv04_gr_object }, /* rect */
1415 		{ -1, -1, 0x005f, &nv04_gr_object },
1416 		{ -1, -1, 0x0060, &nv04_gr_object },
1417 		{ -1, -1, 0x0061, &nv04_gr_object },
1418 		{ -1, -1, 0x0064, &nv04_gr_object }, /* iifc (nv05) */
1419 		{ -1, -1, 0x0065, &nv04_gr_object }, /* ifc (nv05) */
1420 		{ -1, -1, 0x0066, &nv04_gr_object }, /* sifc (nv05) */
1421 		{ -1, -1, 0x0072, &nv04_gr_object }, /* beta4 */
1422 		{ -1, -1, 0x0076, &nv04_gr_object },
1423 		{ -1, -1, 0x0077, &nv04_gr_object },
1424 		{}
1425 	}
1426 };
1427 
1428 int
nv04_gr_new(struct nvkm_device * device,int index,struct nvkm_gr ** pgr)1429 nv04_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr)
1430 {
1431 	struct nv04_gr *gr;
1432 
1433 	if (!(gr = kzalloc(sizeof(*gr), GFP_KERNEL)))
1434 		return -ENOMEM;
1435 	spin_lock_init(&gr->lock);
1436 	*pgr = &gr->base;
1437 
1438 	return nvkm_gr_ctor(&nv04_gr, device, index, true, &gr->base);
1439 }
1440