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