nouveau_nvkm_engine_gr_nv04.c revision 1.2
1/*	$NetBSD: nouveau_nvkm_engine_gr_nv04.c,v 1.2 2018/08/27 04:58:32 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.2 2018/08/27 04:58:32 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
39static u32
40nv04_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
356struct 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
364struct 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
449static void
450nv04_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
464static void
465nv04_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
512static bool
513nv04_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
527static bool
528nv04_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
545static bool
546nv04_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
563static u8
564nv04_gr_mthd_bind_class(struct nvkm_device *device, u32 inst)
565{
566	return nvkm_rd32(device, 0x700000 + (inst << 4));
567}
568
569static bool
570nv04_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
585static bool
586nv04_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
605static bool
606nv01_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
619static bool
620nv04_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
633static bool
634nv04_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
647static bool
648nv04_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
661static bool
662nv04_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
675static bool
676nv04_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
689static bool
690nv04_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
703static bool
704nv04_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
717static bool
718nv04_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
731static bool
732nv01_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
745static bool
746nv01_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
762static bool
763nv03_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
778static bool
779nv04_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
795static bool
796nv01_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
814static bool
815nv04_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
833static bool
834nv04_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
852static bool
853nv01_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
870static bool
871nv04_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
889static bool
890nv03_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
906static bool
907nv04_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
924static bool
925nv03_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
940static bool
941nv04_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
957static bool
958nv04_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
970static bool
971nv03_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
984static bool
985nv01_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
1001static bool
1002nv04_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
1019static bool
1020nv04_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
1047static int
1048nv04_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
1067const struct nvkm_object_func
1068nv04_gr_object = {
1069	.bind = nv04_gr_object_bind,
1070};
1071
1072/*******************************************************************************
1073 * PGRAPH context
1074 ******************************************************************************/
1075
1076static struct nv04_gr_chan *
1077nv04_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
1089static int
1090nv04_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
1104static int
1105nv04_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
1118static void
1119nv04_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
1140static 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
1152static void *
1153nv04_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
1165static int
1166nv04_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
1182static const struct nvkm_object_func
1183nv04_gr_chan = {
1184	.dtor = nv04_gr_chan_dtor,
1185	.fini = nv04_gr_chan_fini,
1186};
1187
1188static int
1189nv04_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
1215bool
1216nv04_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
1237static const struct nvkm_bitfield
1238nv04_gr_intr_name[] = {
1239	{ NV_PGRAPH_INTR_NOTIFY, "NOTIFY" },
1240	{}
1241};
1242
1243static const struct nvkm_bitfield
1244nv04_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
1252const struct nvkm_bitfield
1253nv04_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
1276static void
1277nv04_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
1332static int
1333nv04_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
1369static const struct nvkm_gr_func
1370nv04_gr = {
1371	.init = nv04_gr_init,
1372	.intr = nv04_gr_intr,
1373	.chan_new = nv04_gr_chan_new,
1374	.sclass = {
1375		{ -1, -1, 0x0012, &nv04_gr_object }, /* beta1 */
1376		{ -1, -1, 0x0017, &nv04_gr_object }, /* chroma */
1377		{ -1, -1, 0x0018, &nv04_gr_object }, /* pattern (nv01) */
1378		{ -1, -1, 0x0019, &nv04_gr_object }, /* clip */
1379		{ -1, -1, 0x001c, &nv04_gr_object }, /* line */
1380		{ -1, -1, 0x001d, &nv04_gr_object }, /* tri */
1381		{ -1, -1, 0x001e, &nv04_gr_object }, /* rect */
1382		{ -1, -1, 0x001f, &nv04_gr_object },
1383		{ -1, -1, 0x0021, &nv04_gr_object },
1384		{ -1, -1, 0x0030, &nv04_gr_object }, /* null */
1385		{ -1, -1, 0x0036, &nv04_gr_object },
1386		{ -1, -1, 0x0037, &nv04_gr_object },
1387		{ -1, -1, 0x0038, &nv04_gr_object }, /* dvd subpicture */
1388		{ -1, -1, 0x0039, &nv04_gr_object }, /* m2mf */
1389		{ -1, -1, 0x0042, &nv04_gr_object }, /* surf2d */
1390		{ -1, -1, 0x0043, &nv04_gr_object }, /* rop */
1391		{ -1, -1, 0x0044, &nv04_gr_object }, /* pattern */
1392		{ -1, -1, 0x0048, &nv04_gr_object },
1393		{ -1, -1, 0x004a, &nv04_gr_object },
1394		{ -1, -1, 0x004b, &nv04_gr_object },
1395		{ -1, -1, 0x0052, &nv04_gr_object }, /* swzsurf */
1396		{ -1, -1, 0x0053, &nv04_gr_object },
1397		{ -1, -1, 0x0054, &nv04_gr_object }, /* ttri */
1398		{ -1, -1, 0x0055, &nv04_gr_object }, /* mtri */
1399		{ -1, -1, 0x0057, &nv04_gr_object }, /* chroma */
1400		{ -1, -1, 0x0058, &nv04_gr_object }, /* surf_dst */
1401		{ -1, -1, 0x0059, &nv04_gr_object }, /* surf_src */
1402		{ -1, -1, 0x005a, &nv04_gr_object }, /* surf_color */
1403		{ -1, -1, 0x005b, &nv04_gr_object }, /* surf_zeta */
1404		{ -1, -1, 0x005c, &nv04_gr_object }, /* line */
1405		{ -1, -1, 0x005d, &nv04_gr_object }, /* tri */
1406		{ -1, -1, 0x005e, &nv04_gr_object }, /* rect */
1407		{ -1, -1, 0x005f, &nv04_gr_object },
1408		{ -1, -1, 0x0060, &nv04_gr_object },
1409		{ -1, -1, 0x0061, &nv04_gr_object },
1410		{ -1, -1, 0x0064, &nv04_gr_object }, /* iifc (nv05) */
1411		{ -1, -1, 0x0065, &nv04_gr_object }, /* ifc (nv05) */
1412		{ -1, -1, 0x0066, &nv04_gr_object }, /* sifc (nv05) */
1413		{ -1, -1, 0x0072, &nv04_gr_object }, /* beta4 */
1414		{ -1, -1, 0x0076, &nv04_gr_object },
1415		{ -1, -1, 0x0077, &nv04_gr_object },
1416		{}
1417	}
1418};
1419
1420int
1421nv04_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr)
1422{
1423	struct nv04_gr *gr;
1424
1425	if (!(gr = kzalloc(sizeof(*gr), GFP_KERNEL)))
1426		return -ENOMEM;
1427	spin_lock_init(&gr->lock);
1428	*pgr = &gr->base;
1429
1430	return nvkm_gr_ctor(&nv04_gr, device, index, 0x00001000,
1431			    true, &gr->base);
1432}
1433