1 /*
2  * Copyright 2007 Matthieu CASTET <castet.matthieu@free.fr>
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 
25 #include <core/client.h>
26 #include <core/os.h>
27 #include <core/handle.h>
28 
29 #include <subdev/fb.h>
30 
31 #include <engine/fifo.h>
32 #include <engine/gr.h>
33 
34 #include "regs.h"
35 
36 struct pipe_state {
37 	u32 pipe_0x0000[0x040/4];
38 	u32 pipe_0x0040[0x010/4];
39 	u32 pipe_0x0200[0x0c0/4];
40 	u32 pipe_0x4400[0x080/4];
41 	u32 pipe_0x6400[0x3b0/4];
42 	u32 pipe_0x6800[0x2f0/4];
43 	u32 pipe_0x6c00[0x030/4];
44 	u32 pipe_0x7000[0x130/4];
45 	u32 pipe_0x7400[0x0c0/4];
46 	u32 pipe_0x7800[0x0c0/4];
47 };
48 
49 static int nv10_gr_ctx_regs[] = {
50 	NV10_PGRAPH_CTX_SWITCH(0),
51 	NV10_PGRAPH_CTX_SWITCH(1),
52 	NV10_PGRAPH_CTX_SWITCH(2),
53 	NV10_PGRAPH_CTX_SWITCH(3),
54 	NV10_PGRAPH_CTX_SWITCH(4),
55 	NV10_PGRAPH_CTX_CACHE(0, 0),
56 	NV10_PGRAPH_CTX_CACHE(0, 1),
57 	NV10_PGRAPH_CTX_CACHE(0, 2),
58 	NV10_PGRAPH_CTX_CACHE(0, 3),
59 	NV10_PGRAPH_CTX_CACHE(0, 4),
60 	NV10_PGRAPH_CTX_CACHE(1, 0),
61 	NV10_PGRAPH_CTX_CACHE(1, 1),
62 	NV10_PGRAPH_CTX_CACHE(1, 2),
63 	NV10_PGRAPH_CTX_CACHE(1, 3),
64 	NV10_PGRAPH_CTX_CACHE(1, 4),
65 	NV10_PGRAPH_CTX_CACHE(2, 0),
66 	NV10_PGRAPH_CTX_CACHE(2, 1),
67 	NV10_PGRAPH_CTX_CACHE(2, 2),
68 	NV10_PGRAPH_CTX_CACHE(2, 3),
69 	NV10_PGRAPH_CTX_CACHE(2, 4),
70 	NV10_PGRAPH_CTX_CACHE(3, 0),
71 	NV10_PGRAPH_CTX_CACHE(3, 1),
72 	NV10_PGRAPH_CTX_CACHE(3, 2),
73 	NV10_PGRAPH_CTX_CACHE(3, 3),
74 	NV10_PGRAPH_CTX_CACHE(3, 4),
75 	NV10_PGRAPH_CTX_CACHE(4, 0),
76 	NV10_PGRAPH_CTX_CACHE(4, 1),
77 	NV10_PGRAPH_CTX_CACHE(4, 2),
78 	NV10_PGRAPH_CTX_CACHE(4, 3),
79 	NV10_PGRAPH_CTX_CACHE(4, 4),
80 	NV10_PGRAPH_CTX_CACHE(5, 0),
81 	NV10_PGRAPH_CTX_CACHE(5, 1),
82 	NV10_PGRAPH_CTX_CACHE(5, 2),
83 	NV10_PGRAPH_CTX_CACHE(5, 3),
84 	NV10_PGRAPH_CTX_CACHE(5, 4),
85 	NV10_PGRAPH_CTX_CACHE(6, 0),
86 	NV10_PGRAPH_CTX_CACHE(6, 1),
87 	NV10_PGRAPH_CTX_CACHE(6, 2),
88 	NV10_PGRAPH_CTX_CACHE(6, 3),
89 	NV10_PGRAPH_CTX_CACHE(6, 4),
90 	NV10_PGRAPH_CTX_CACHE(7, 0),
91 	NV10_PGRAPH_CTX_CACHE(7, 1),
92 	NV10_PGRAPH_CTX_CACHE(7, 2),
93 	NV10_PGRAPH_CTX_CACHE(7, 3),
94 	NV10_PGRAPH_CTX_CACHE(7, 4),
95 	NV10_PGRAPH_CTX_USER,
96 	NV04_PGRAPH_DMA_START_0,
97 	NV04_PGRAPH_DMA_START_1,
98 	NV04_PGRAPH_DMA_LENGTH,
99 	NV04_PGRAPH_DMA_MISC,
100 	NV10_PGRAPH_DMA_PITCH,
101 	NV04_PGRAPH_BOFFSET0,
102 	NV04_PGRAPH_BBASE0,
103 	NV04_PGRAPH_BLIMIT0,
104 	NV04_PGRAPH_BOFFSET1,
105 	NV04_PGRAPH_BBASE1,
106 	NV04_PGRAPH_BLIMIT1,
107 	NV04_PGRAPH_BOFFSET2,
108 	NV04_PGRAPH_BBASE2,
109 	NV04_PGRAPH_BLIMIT2,
110 	NV04_PGRAPH_BOFFSET3,
111 	NV04_PGRAPH_BBASE3,
112 	NV04_PGRAPH_BLIMIT3,
113 	NV04_PGRAPH_BOFFSET4,
114 	NV04_PGRAPH_BBASE4,
115 	NV04_PGRAPH_BLIMIT4,
116 	NV04_PGRAPH_BOFFSET5,
117 	NV04_PGRAPH_BBASE5,
118 	NV04_PGRAPH_BLIMIT5,
119 	NV04_PGRAPH_BPITCH0,
120 	NV04_PGRAPH_BPITCH1,
121 	NV04_PGRAPH_BPITCH2,
122 	NV04_PGRAPH_BPITCH3,
123 	NV04_PGRAPH_BPITCH4,
124 	NV10_PGRAPH_SURFACE,
125 	NV10_PGRAPH_STATE,
126 	NV04_PGRAPH_BSWIZZLE2,
127 	NV04_PGRAPH_BSWIZZLE5,
128 	NV04_PGRAPH_BPIXEL,
129 	NV10_PGRAPH_NOTIFY,
130 	NV04_PGRAPH_PATT_COLOR0,
131 	NV04_PGRAPH_PATT_COLOR1,
132 	NV04_PGRAPH_PATT_COLORRAM, /* 64 values from 0x400900 to 0x4009fc */
133 	0x00400904,
134 	0x00400908,
135 	0x0040090c,
136 	0x00400910,
137 	0x00400914,
138 	0x00400918,
139 	0x0040091c,
140 	0x00400920,
141 	0x00400924,
142 	0x00400928,
143 	0x0040092c,
144 	0x00400930,
145 	0x00400934,
146 	0x00400938,
147 	0x0040093c,
148 	0x00400940,
149 	0x00400944,
150 	0x00400948,
151 	0x0040094c,
152 	0x00400950,
153 	0x00400954,
154 	0x00400958,
155 	0x0040095c,
156 	0x00400960,
157 	0x00400964,
158 	0x00400968,
159 	0x0040096c,
160 	0x00400970,
161 	0x00400974,
162 	0x00400978,
163 	0x0040097c,
164 	0x00400980,
165 	0x00400984,
166 	0x00400988,
167 	0x0040098c,
168 	0x00400990,
169 	0x00400994,
170 	0x00400998,
171 	0x0040099c,
172 	0x004009a0,
173 	0x004009a4,
174 	0x004009a8,
175 	0x004009ac,
176 	0x004009b0,
177 	0x004009b4,
178 	0x004009b8,
179 	0x004009bc,
180 	0x004009c0,
181 	0x004009c4,
182 	0x004009c8,
183 	0x004009cc,
184 	0x004009d0,
185 	0x004009d4,
186 	0x004009d8,
187 	0x004009dc,
188 	0x004009e0,
189 	0x004009e4,
190 	0x004009e8,
191 	0x004009ec,
192 	0x004009f0,
193 	0x004009f4,
194 	0x004009f8,
195 	0x004009fc,
196 	NV04_PGRAPH_PATTERN,	/* 2 values from 0x400808 to 0x40080c */
197 	0x0040080c,
198 	NV04_PGRAPH_PATTERN_SHAPE,
199 	NV03_PGRAPH_MONO_COLOR0,
200 	NV04_PGRAPH_ROP3,
201 	NV04_PGRAPH_CHROMA,
202 	NV04_PGRAPH_BETA_AND,
203 	NV04_PGRAPH_BETA_PREMULT,
204 	0x00400e70,
205 	0x00400e74,
206 	0x00400e78,
207 	0x00400e7c,
208 	0x00400e80,
209 	0x00400e84,
210 	0x00400e88,
211 	0x00400e8c,
212 	0x00400ea0,
213 	0x00400ea4,
214 	0x00400ea8,
215 	0x00400e90,
216 	0x00400e94,
217 	0x00400e98,
218 	0x00400e9c,
219 	NV10_PGRAPH_WINDOWCLIP_HORIZONTAL, /* 8 values from 0x400f00-0x400f1c */
220 	NV10_PGRAPH_WINDOWCLIP_VERTICAL,   /* 8 values from 0x400f20-0x400f3c */
221 	0x00400f04,
222 	0x00400f24,
223 	0x00400f08,
224 	0x00400f28,
225 	0x00400f0c,
226 	0x00400f2c,
227 	0x00400f10,
228 	0x00400f30,
229 	0x00400f14,
230 	0x00400f34,
231 	0x00400f18,
232 	0x00400f38,
233 	0x00400f1c,
234 	0x00400f3c,
235 	NV10_PGRAPH_XFMODE0,
236 	NV10_PGRAPH_XFMODE1,
237 	NV10_PGRAPH_GLOBALSTATE0,
238 	NV10_PGRAPH_GLOBALSTATE1,
239 	NV04_PGRAPH_STORED_FMT,
240 	NV04_PGRAPH_SOURCE_COLOR,
241 	NV03_PGRAPH_ABS_X_RAM,	/* 32 values from 0x400400 to 0x40047c */
242 	NV03_PGRAPH_ABS_Y_RAM,	/* 32 values from 0x400480 to 0x4004fc */
243 	0x00400404,
244 	0x00400484,
245 	0x00400408,
246 	0x00400488,
247 	0x0040040c,
248 	0x0040048c,
249 	0x00400410,
250 	0x00400490,
251 	0x00400414,
252 	0x00400494,
253 	0x00400418,
254 	0x00400498,
255 	0x0040041c,
256 	0x0040049c,
257 	0x00400420,
258 	0x004004a0,
259 	0x00400424,
260 	0x004004a4,
261 	0x00400428,
262 	0x004004a8,
263 	0x0040042c,
264 	0x004004ac,
265 	0x00400430,
266 	0x004004b0,
267 	0x00400434,
268 	0x004004b4,
269 	0x00400438,
270 	0x004004b8,
271 	0x0040043c,
272 	0x004004bc,
273 	0x00400440,
274 	0x004004c0,
275 	0x00400444,
276 	0x004004c4,
277 	0x00400448,
278 	0x004004c8,
279 	0x0040044c,
280 	0x004004cc,
281 	0x00400450,
282 	0x004004d0,
283 	0x00400454,
284 	0x004004d4,
285 	0x00400458,
286 	0x004004d8,
287 	0x0040045c,
288 	0x004004dc,
289 	0x00400460,
290 	0x004004e0,
291 	0x00400464,
292 	0x004004e4,
293 	0x00400468,
294 	0x004004e8,
295 	0x0040046c,
296 	0x004004ec,
297 	0x00400470,
298 	0x004004f0,
299 	0x00400474,
300 	0x004004f4,
301 	0x00400478,
302 	0x004004f8,
303 	0x0040047c,
304 	0x004004fc,
305 	NV03_PGRAPH_ABS_UCLIP_XMIN,
306 	NV03_PGRAPH_ABS_UCLIP_XMAX,
307 	NV03_PGRAPH_ABS_UCLIP_YMIN,
308 	NV03_PGRAPH_ABS_UCLIP_YMAX,
309 	0x00400550,
310 	0x00400558,
311 	0x00400554,
312 	0x0040055c,
313 	NV03_PGRAPH_ABS_UCLIPA_XMIN,
314 	NV03_PGRAPH_ABS_UCLIPA_XMAX,
315 	NV03_PGRAPH_ABS_UCLIPA_YMIN,
316 	NV03_PGRAPH_ABS_UCLIPA_YMAX,
317 	NV03_PGRAPH_ABS_ICLIP_XMAX,
318 	NV03_PGRAPH_ABS_ICLIP_YMAX,
319 	NV03_PGRAPH_XY_LOGIC_MISC0,
320 	NV03_PGRAPH_XY_LOGIC_MISC1,
321 	NV03_PGRAPH_XY_LOGIC_MISC2,
322 	NV03_PGRAPH_XY_LOGIC_MISC3,
323 	NV03_PGRAPH_CLIPX_0,
324 	NV03_PGRAPH_CLIPX_1,
325 	NV03_PGRAPH_CLIPY_0,
326 	NV03_PGRAPH_CLIPY_1,
327 	NV10_PGRAPH_COMBINER0_IN_ALPHA,
328 	NV10_PGRAPH_COMBINER1_IN_ALPHA,
329 	NV10_PGRAPH_COMBINER0_IN_RGB,
330 	NV10_PGRAPH_COMBINER1_IN_RGB,
331 	NV10_PGRAPH_COMBINER_COLOR0,
332 	NV10_PGRAPH_COMBINER_COLOR1,
333 	NV10_PGRAPH_COMBINER0_OUT_ALPHA,
334 	NV10_PGRAPH_COMBINER1_OUT_ALPHA,
335 	NV10_PGRAPH_COMBINER0_OUT_RGB,
336 	NV10_PGRAPH_COMBINER1_OUT_RGB,
337 	NV10_PGRAPH_COMBINER_FINAL0,
338 	NV10_PGRAPH_COMBINER_FINAL1,
339 	0x00400e00,
340 	0x00400e04,
341 	0x00400e08,
342 	0x00400e0c,
343 	0x00400e10,
344 	0x00400e14,
345 	0x00400e18,
346 	0x00400e1c,
347 	0x00400e20,
348 	0x00400e24,
349 	0x00400e28,
350 	0x00400e2c,
351 	0x00400e30,
352 	0x00400e34,
353 	0x00400e38,
354 	0x00400e3c,
355 	NV04_PGRAPH_PASSTHRU_0,
356 	NV04_PGRAPH_PASSTHRU_1,
357 	NV04_PGRAPH_PASSTHRU_2,
358 	NV10_PGRAPH_DIMX_TEXTURE,
359 	NV10_PGRAPH_WDIMX_TEXTURE,
360 	NV10_PGRAPH_DVD_COLORFMT,
361 	NV10_PGRAPH_SCALED_FORMAT,
362 	NV04_PGRAPH_MISC24_0,
363 	NV04_PGRAPH_MISC24_1,
364 	NV04_PGRAPH_MISC24_2,
365 	NV03_PGRAPH_X_MISC,
366 	NV03_PGRAPH_Y_MISC,
367 	NV04_PGRAPH_VALID1,
368 	NV04_PGRAPH_VALID2,
369 };
370 
371 static int nv17_gr_ctx_regs[] = {
372 	NV10_PGRAPH_DEBUG_4,
373 	0x004006b0,
374 	0x00400eac,
375 	0x00400eb0,
376 	0x00400eb4,
377 	0x00400eb8,
378 	0x00400ebc,
379 	0x00400ec0,
380 	0x00400ec4,
381 	0x00400ec8,
382 	0x00400ecc,
383 	0x00400ed0,
384 	0x00400ed4,
385 	0x00400ed8,
386 	0x00400edc,
387 	0x00400ee0,
388 	0x00400a00,
389 	0x00400a04,
390 };
391 
392 struct nv10_gr_priv {
393 	struct nouveau_gr base;
394 	struct nv10_gr_chan *chan[32];
395 	spinlock_t lock;
396 };
397 
398 struct nv10_gr_chan {
399 	struct nouveau_object base;
400 	int chid;
401 	int nv10[ARRAY_SIZE(nv10_gr_ctx_regs)];
402 	int nv17[ARRAY_SIZE(nv17_gr_ctx_regs)];
403 	struct pipe_state pipe_state;
404 	u32 lma_window[4];
405 };
406 
407 
408 static inline struct nv10_gr_priv *
409 nv10_gr_priv(struct nv10_gr_chan *chan)
410 {
411 	return (void *)nv_object(chan)->engine;
412 }
413 
414 /*******************************************************************************
415  * Graphics object classes
416  ******************************************************************************/
417 
418 #define PIPE_SAVE(priv, state, addr)					\
419 	do {								\
420 		int __i;						\
421 		nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, addr);		\
422 		for (__i = 0; __i < ARRAY_SIZE(state); __i++)		\
423 			state[__i] = nv_rd32(priv, NV10_PGRAPH_PIPE_DATA); \
424 	} while (0)
425 
426 #define PIPE_RESTORE(priv, state, addr)					\
427 	do {								\
428 		int __i;						\
429 		nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, addr);		\
430 		for (__i = 0; __i < ARRAY_SIZE(state); __i++)		\
431 			nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, state[__i]); \
432 	} while (0)
433 
434 static struct nouveau_oclass
435 nv10_gr_sclass[] = {
436 	{ 0x0012, &nv04_gr_ofuncs }, /* beta1 */
437 	{ 0x0019, &nv04_gr_ofuncs }, /* clip */
438 	{ 0x0030, &nv04_gr_ofuncs }, /* null */
439 	{ 0x0039, &nv04_gr_ofuncs }, /* m2mf */
440 	{ 0x0043, &nv04_gr_ofuncs }, /* rop */
441 	{ 0x0044, &nv04_gr_ofuncs }, /* pattern */
442 	{ 0x004a, &nv04_gr_ofuncs }, /* gdi */
443 	{ 0x0052, &nv04_gr_ofuncs }, /* swzsurf */
444 	{ 0x005f, &nv04_gr_ofuncs }, /* blit */
445 	{ 0x0062, &nv04_gr_ofuncs }, /* surf2d */
446 	{ 0x0072, &nv04_gr_ofuncs }, /* beta4 */
447 	{ 0x0089, &nv04_gr_ofuncs }, /* sifm */
448 	{ 0x008a, &nv04_gr_ofuncs }, /* ifc */
449 	{ 0x009f, &nv04_gr_ofuncs }, /* blit */
450 	{ 0x0093, &nv04_gr_ofuncs }, /* surf3d */
451 	{ 0x0094, &nv04_gr_ofuncs }, /* ttri */
452 	{ 0x0095, &nv04_gr_ofuncs }, /* mtri */
453 	{ 0x0056, &nv04_gr_ofuncs }, /* celcius */
454 	{},
455 };
456 
457 static struct nouveau_oclass
458 nv15_gr_sclass[] = {
459 	{ 0x0012, &nv04_gr_ofuncs }, /* beta1 */
460 	{ 0x0019, &nv04_gr_ofuncs }, /* clip */
461 	{ 0x0030, &nv04_gr_ofuncs }, /* null */
462 	{ 0x0039, &nv04_gr_ofuncs }, /* m2mf */
463 	{ 0x0043, &nv04_gr_ofuncs }, /* rop */
464 	{ 0x0044, &nv04_gr_ofuncs }, /* pattern */
465 	{ 0x004a, &nv04_gr_ofuncs }, /* gdi */
466 	{ 0x0052, &nv04_gr_ofuncs }, /* swzsurf */
467 	{ 0x005f, &nv04_gr_ofuncs }, /* blit */
468 	{ 0x0062, &nv04_gr_ofuncs }, /* surf2d */
469 	{ 0x0072, &nv04_gr_ofuncs }, /* beta4 */
470 	{ 0x0089, &nv04_gr_ofuncs }, /* sifm */
471 	{ 0x008a, &nv04_gr_ofuncs }, /* ifc */
472 	{ 0x009f, &nv04_gr_ofuncs }, /* blit */
473 	{ 0x0093, &nv04_gr_ofuncs }, /* surf3d */
474 	{ 0x0094, &nv04_gr_ofuncs }, /* ttri */
475 	{ 0x0095, &nv04_gr_ofuncs }, /* mtri */
476 	{ 0x0096, &nv04_gr_ofuncs }, /* celcius */
477 	{},
478 };
479 
480 static int
481 nv17_gr_mthd_lma_window(struct nouveau_object *object, u32 mthd,
482 			   void *args, u32 size)
483 {
484 	struct nv10_gr_chan *chan = (void *)object->parent;
485 	struct nv10_gr_priv *priv = nv10_gr_priv(chan);
486 	struct pipe_state *pipe = &chan->pipe_state;
487 	u32 pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3];
488 	u32 xfmode0, xfmode1;
489 	u32 data = *(u32 *)args;
490 	int i;
491 
492 	chan->lma_window[(mthd - 0x1638) / 4] = data;
493 
494 	if (mthd != 0x1644)
495 		return 0;
496 
497 	nv04_gr_idle(priv);
498 
499 	PIPE_SAVE(priv, pipe_0x0040, 0x0040);
500 	PIPE_SAVE(priv, pipe->pipe_0x0200, 0x0200);
501 
502 	PIPE_RESTORE(priv, chan->lma_window, 0x6790);
503 
504 	nv04_gr_idle(priv);
505 
506 	xfmode0 = nv_rd32(priv, NV10_PGRAPH_XFMODE0);
507 	xfmode1 = nv_rd32(priv, NV10_PGRAPH_XFMODE1);
508 
509 	PIPE_SAVE(priv, pipe->pipe_0x4400, 0x4400);
510 	PIPE_SAVE(priv, pipe_0x64c0, 0x64c0);
511 	PIPE_SAVE(priv, pipe_0x6ab0, 0x6ab0);
512 	PIPE_SAVE(priv, pipe_0x6a80, 0x6a80);
513 
514 	nv04_gr_idle(priv);
515 
516 	nv_wr32(priv, NV10_PGRAPH_XFMODE0, 0x10000000);
517 	nv_wr32(priv, NV10_PGRAPH_XFMODE1, 0x00000000);
518 	nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0);
519 	for (i = 0; i < 4; i++)
520 		nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
521 	for (i = 0; i < 4; i++)
522 		nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000);
523 
524 	nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0);
525 	for (i = 0; i < 3; i++)
526 		nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
527 
528 	nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80);
529 	for (i = 0; i < 3; i++)
530 		nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000);
531 
532 	nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040);
533 	nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000008);
534 
535 	PIPE_RESTORE(priv, pipe->pipe_0x0200, 0x0200);
536 
537 	nv04_gr_idle(priv);
538 
539 	PIPE_RESTORE(priv, pipe_0x0040, 0x0040);
540 
541 	nv_wr32(priv, NV10_PGRAPH_XFMODE0, xfmode0);
542 	nv_wr32(priv, NV10_PGRAPH_XFMODE1, xfmode1);
543 
544 	PIPE_RESTORE(priv, pipe_0x64c0, 0x64c0);
545 	PIPE_RESTORE(priv, pipe_0x6ab0, 0x6ab0);
546 	PIPE_RESTORE(priv, pipe_0x6a80, 0x6a80);
547 	PIPE_RESTORE(priv, pipe->pipe_0x4400, 0x4400);
548 
549 	nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x000000c0);
550 	nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000);
551 
552 	nv04_gr_idle(priv);
553 
554 	return 0;
555 }
556 
557 static int
558 nv17_gr_mthd_lma_enable(struct nouveau_object *object, u32 mthd,
559 			   void *args, u32 size)
560 {
561 	struct nv10_gr_chan *chan = (void *)object->parent;
562 	struct nv10_gr_priv *priv = nv10_gr_priv(chan);
563 
564 	nv04_gr_idle(priv);
565 
566 	nv_mask(priv, NV10_PGRAPH_DEBUG_4, 0x00000100, 0x00000100);
567 	nv_mask(priv, 0x4006b0, 0x08000000, 0x08000000);
568 	return 0;
569 }
570 
571 static struct nouveau_omthds
572 nv17_celcius_omthds[] = {
573 	{ 0x1638, 0x1638, nv17_gr_mthd_lma_window },
574 	{ 0x163c, 0x163c, nv17_gr_mthd_lma_window },
575 	{ 0x1640, 0x1640, nv17_gr_mthd_lma_window },
576 	{ 0x1644, 0x1644, nv17_gr_mthd_lma_window },
577 	{ 0x1658, 0x1658, nv17_gr_mthd_lma_enable },
578 	{}
579 };
580 
581 static struct nouveau_oclass
582 nv17_gr_sclass[] = {
583 	{ 0x0012, &nv04_gr_ofuncs }, /* beta1 */
584 	{ 0x0019, &nv04_gr_ofuncs }, /* clip */
585 	{ 0x0030, &nv04_gr_ofuncs }, /* null */
586 	{ 0x0039, &nv04_gr_ofuncs }, /* m2mf */
587 	{ 0x0043, &nv04_gr_ofuncs }, /* rop */
588 	{ 0x0044, &nv04_gr_ofuncs }, /* pattern */
589 	{ 0x004a, &nv04_gr_ofuncs }, /* gdi */
590 	{ 0x0052, &nv04_gr_ofuncs }, /* swzsurf */
591 	{ 0x005f, &nv04_gr_ofuncs }, /* blit */
592 	{ 0x0062, &nv04_gr_ofuncs }, /* surf2d */
593 	{ 0x0072, &nv04_gr_ofuncs }, /* beta4 */
594 	{ 0x0089, &nv04_gr_ofuncs }, /* sifm */
595 	{ 0x008a, &nv04_gr_ofuncs }, /* ifc */
596 	{ 0x009f, &nv04_gr_ofuncs }, /* blit */
597 	{ 0x0093, &nv04_gr_ofuncs }, /* surf3d */
598 	{ 0x0094, &nv04_gr_ofuncs }, /* ttri */
599 	{ 0x0095, &nv04_gr_ofuncs }, /* mtri */
600 	{ 0x0099, &nv04_gr_ofuncs, nv17_celcius_omthds },
601 	{},
602 };
603 
604 /*******************************************************************************
605  * PGRAPH context
606  ******************************************************************************/
607 
608 static struct nv10_gr_chan *
609 nv10_gr_channel(struct nv10_gr_priv *priv)
610 {
611 	struct nv10_gr_chan *chan = NULL;
612 	if (nv_rd32(priv, 0x400144) & 0x00010000) {
613 		int chid = nv_rd32(priv, 0x400148) >> 24;
614 		if (chid < ARRAY_SIZE(priv->chan))
615 			chan = priv->chan[chid];
616 	}
617 	return chan;
618 }
619 
620 static void
621 nv10_gr_save_pipe(struct nv10_gr_chan *chan)
622 {
623 	struct nv10_gr_priv *priv = nv10_gr_priv(chan);
624 	struct pipe_state *pipe = &chan->pipe_state;
625 
626 	PIPE_SAVE(priv, pipe->pipe_0x4400, 0x4400);
627 	PIPE_SAVE(priv, pipe->pipe_0x0200, 0x0200);
628 	PIPE_SAVE(priv, pipe->pipe_0x6400, 0x6400);
629 	PIPE_SAVE(priv, pipe->pipe_0x6800, 0x6800);
630 	PIPE_SAVE(priv, pipe->pipe_0x6c00, 0x6c00);
631 	PIPE_SAVE(priv, pipe->pipe_0x7000, 0x7000);
632 	PIPE_SAVE(priv, pipe->pipe_0x7400, 0x7400);
633 	PIPE_SAVE(priv, pipe->pipe_0x7800, 0x7800);
634 	PIPE_SAVE(priv, pipe->pipe_0x0040, 0x0040);
635 	PIPE_SAVE(priv, pipe->pipe_0x0000, 0x0000);
636 }
637 
638 static void
639 nv10_gr_load_pipe(struct nv10_gr_chan *chan)
640 {
641 	struct nv10_gr_priv *priv = nv10_gr_priv(chan);
642 	struct pipe_state *pipe = &chan->pipe_state;
643 	u32 xfmode0, xfmode1;
644 	int i;
645 
646 	nv04_gr_idle(priv);
647 	/* XXX check haiku comments */
648 	xfmode0 = nv_rd32(priv, NV10_PGRAPH_XFMODE0);
649 	xfmode1 = nv_rd32(priv, NV10_PGRAPH_XFMODE1);
650 	nv_wr32(priv, NV10_PGRAPH_XFMODE0, 0x10000000);
651 	nv_wr32(priv, NV10_PGRAPH_XFMODE1, 0x00000000);
652 	nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0);
653 	for (i = 0; i < 4; i++)
654 		nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
655 	for (i = 0; i < 4; i++)
656 		nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000);
657 
658 	nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0);
659 	for (i = 0; i < 3; i++)
660 		nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
661 
662 	nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80);
663 	for (i = 0; i < 3; i++)
664 		nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000000);
665 
666 	nv_wr32(priv, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040);
667 	nv_wr32(priv, NV10_PGRAPH_PIPE_DATA, 0x00000008);
668 
669 
670 	PIPE_RESTORE(priv, pipe->pipe_0x0200, 0x0200);
671 	nv04_gr_idle(priv);
672 
673 	/* restore XFMODE */
674 	nv_wr32(priv, NV10_PGRAPH_XFMODE0, xfmode0);
675 	nv_wr32(priv, NV10_PGRAPH_XFMODE1, xfmode1);
676 	PIPE_RESTORE(priv, pipe->pipe_0x6400, 0x6400);
677 	PIPE_RESTORE(priv, pipe->pipe_0x6800, 0x6800);
678 	PIPE_RESTORE(priv, pipe->pipe_0x6c00, 0x6c00);
679 	PIPE_RESTORE(priv, pipe->pipe_0x7000, 0x7000);
680 	PIPE_RESTORE(priv, pipe->pipe_0x7400, 0x7400);
681 	PIPE_RESTORE(priv, pipe->pipe_0x7800, 0x7800);
682 	PIPE_RESTORE(priv, pipe->pipe_0x4400, 0x4400);
683 	PIPE_RESTORE(priv, pipe->pipe_0x0000, 0x0000);
684 	PIPE_RESTORE(priv, pipe->pipe_0x0040, 0x0040);
685 	nv04_gr_idle(priv);
686 }
687 
688 static void
689 nv10_gr_create_pipe(struct nv10_gr_chan *chan)
690 {
691 	struct nv10_gr_priv *priv = nv10_gr_priv(chan);
692 	struct pipe_state *pipe_state = &chan->pipe_state;
693 	u32 *pipe_state_addr;
694 	int i;
695 #define PIPE_INIT(addr) \
696 	do { \
697 		pipe_state_addr = pipe_state->pipe_##addr; \
698 	} while (0)
699 #define PIPE_INIT_END(addr) \
700 	do { \
701 		u32 *__end_addr = pipe_state->pipe_##addr + \
702 				ARRAY_SIZE(pipe_state->pipe_##addr); \
703 		if (pipe_state_addr != __end_addr) \
704 			nv_error(priv, "incomplete pipe init for 0x%x :  %p/%p\n", \
705 				addr, pipe_state_addr, __end_addr); \
706 	} while (0)
707 #define NV_WRITE_PIPE_INIT(value) *(pipe_state_addr++) = value
708 
709 	PIPE_INIT(0x0200);
710 	for (i = 0; i < 48; i++)
711 		NV_WRITE_PIPE_INIT(0x00000000);
712 	PIPE_INIT_END(0x0200);
713 
714 	PIPE_INIT(0x6400);
715 	for (i = 0; i < 211; i++)
716 		NV_WRITE_PIPE_INIT(0x00000000);
717 	NV_WRITE_PIPE_INIT(0x3f800000);
718 	NV_WRITE_PIPE_INIT(0x40000000);
719 	NV_WRITE_PIPE_INIT(0x40000000);
720 	NV_WRITE_PIPE_INIT(0x40000000);
721 	NV_WRITE_PIPE_INIT(0x40000000);
722 	NV_WRITE_PIPE_INIT(0x00000000);
723 	NV_WRITE_PIPE_INIT(0x00000000);
724 	NV_WRITE_PIPE_INIT(0x3f800000);
725 	NV_WRITE_PIPE_INIT(0x00000000);
726 	NV_WRITE_PIPE_INIT(0x3f000000);
727 	NV_WRITE_PIPE_INIT(0x3f000000);
728 	NV_WRITE_PIPE_INIT(0x00000000);
729 	NV_WRITE_PIPE_INIT(0x00000000);
730 	NV_WRITE_PIPE_INIT(0x00000000);
731 	NV_WRITE_PIPE_INIT(0x00000000);
732 	NV_WRITE_PIPE_INIT(0x3f800000);
733 	NV_WRITE_PIPE_INIT(0x00000000);
734 	NV_WRITE_PIPE_INIT(0x00000000);
735 	NV_WRITE_PIPE_INIT(0x00000000);
736 	NV_WRITE_PIPE_INIT(0x00000000);
737 	NV_WRITE_PIPE_INIT(0x00000000);
738 	NV_WRITE_PIPE_INIT(0x3f800000);
739 	NV_WRITE_PIPE_INIT(0x3f800000);
740 	NV_WRITE_PIPE_INIT(0x3f800000);
741 	NV_WRITE_PIPE_INIT(0x3f800000);
742 	PIPE_INIT_END(0x6400);
743 
744 	PIPE_INIT(0x6800);
745 	for (i = 0; i < 162; i++)
746 		NV_WRITE_PIPE_INIT(0x00000000);
747 	NV_WRITE_PIPE_INIT(0x3f800000);
748 	for (i = 0; i < 25; i++)
749 		NV_WRITE_PIPE_INIT(0x00000000);
750 	PIPE_INIT_END(0x6800);
751 
752 	PIPE_INIT(0x6c00);
753 	NV_WRITE_PIPE_INIT(0x00000000);
754 	NV_WRITE_PIPE_INIT(0x00000000);
755 	NV_WRITE_PIPE_INIT(0x00000000);
756 	NV_WRITE_PIPE_INIT(0x00000000);
757 	NV_WRITE_PIPE_INIT(0xbf800000);
758 	NV_WRITE_PIPE_INIT(0x00000000);
759 	NV_WRITE_PIPE_INIT(0x00000000);
760 	NV_WRITE_PIPE_INIT(0x00000000);
761 	NV_WRITE_PIPE_INIT(0x00000000);
762 	NV_WRITE_PIPE_INIT(0x00000000);
763 	NV_WRITE_PIPE_INIT(0x00000000);
764 	NV_WRITE_PIPE_INIT(0x00000000);
765 	PIPE_INIT_END(0x6c00);
766 
767 	PIPE_INIT(0x7000);
768 	NV_WRITE_PIPE_INIT(0x00000000);
769 	NV_WRITE_PIPE_INIT(0x00000000);
770 	NV_WRITE_PIPE_INIT(0x00000000);
771 	NV_WRITE_PIPE_INIT(0x00000000);
772 	NV_WRITE_PIPE_INIT(0x00000000);
773 	NV_WRITE_PIPE_INIT(0x00000000);
774 	NV_WRITE_PIPE_INIT(0x00000000);
775 	NV_WRITE_PIPE_INIT(0x00000000);
776 	NV_WRITE_PIPE_INIT(0x00000000);
777 	NV_WRITE_PIPE_INIT(0x00000000);
778 	NV_WRITE_PIPE_INIT(0x00000000);
779 	NV_WRITE_PIPE_INIT(0x00000000);
780 	NV_WRITE_PIPE_INIT(0x7149f2ca);
781 	NV_WRITE_PIPE_INIT(0x00000000);
782 	NV_WRITE_PIPE_INIT(0x00000000);
783 	NV_WRITE_PIPE_INIT(0x00000000);
784 	NV_WRITE_PIPE_INIT(0x7149f2ca);
785 	NV_WRITE_PIPE_INIT(0x00000000);
786 	NV_WRITE_PIPE_INIT(0x00000000);
787 	NV_WRITE_PIPE_INIT(0x00000000);
788 	NV_WRITE_PIPE_INIT(0x7149f2ca);
789 	NV_WRITE_PIPE_INIT(0x00000000);
790 	NV_WRITE_PIPE_INIT(0x00000000);
791 	NV_WRITE_PIPE_INIT(0x00000000);
792 	NV_WRITE_PIPE_INIT(0x7149f2ca);
793 	NV_WRITE_PIPE_INIT(0x00000000);
794 	NV_WRITE_PIPE_INIT(0x00000000);
795 	NV_WRITE_PIPE_INIT(0x00000000);
796 	NV_WRITE_PIPE_INIT(0x7149f2ca);
797 	NV_WRITE_PIPE_INIT(0x00000000);
798 	NV_WRITE_PIPE_INIT(0x00000000);
799 	NV_WRITE_PIPE_INIT(0x00000000);
800 	NV_WRITE_PIPE_INIT(0x7149f2ca);
801 	NV_WRITE_PIPE_INIT(0x00000000);
802 	NV_WRITE_PIPE_INIT(0x00000000);
803 	NV_WRITE_PIPE_INIT(0x00000000);
804 	NV_WRITE_PIPE_INIT(0x7149f2ca);
805 	NV_WRITE_PIPE_INIT(0x00000000);
806 	NV_WRITE_PIPE_INIT(0x00000000);
807 	NV_WRITE_PIPE_INIT(0x00000000);
808 	NV_WRITE_PIPE_INIT(0x7149f2ca);
809 	for (i = 0; i < 35; i++)
810 		NV_WRITE_PIPE_INIT(0x00000000);
811 	PIPE_INIT_END(0x7000);
812 
813 	PIPE_INIT(0x7400);
814 	for (i = 0; i < 48; i++)
815 		NV_WRITE_PIPE_INIT(0x00000000);
816 	PIPE_INIT_END(0x7400);
817 
818 	PIPE_INIT(0x7800);
819 	for (i = 0; i < 48; i++)
820 		NV_WRITE_PIPE_INIT(0x00000000);
821 	PIPE_INIT_END(0x7800);
822 
823 	PIPE_INIT(0x4400);
824 	for (i = 0; i < 32; i++)
825 		NV_WRITE_PIPE_INIT(0x00000000);
826 	PIPE_INIT_END(0x4400);
827 
828 	PIPE_INIT(0x0000);
829 	for (i = 0; i < 16; i++)
830 		NV_WRITE_PIPE_INIT(0x00000000);
831 	PIPE_INIT_END(0x0000);
832 
833 	PIPE_INIT(0x0040);
834 	for (i = 0; i < 4; i++)
835 		NV_WRITE_PIPE_INIT(0x00000000);
836 	PIPE_INIT_END(0x0040);
837 
838 #undef PIPE_INIT
839 #undef PIPE_INIT_END
840 #undef NV_WRITE_PIPE_INIT
841 }
842 
843 static int
844 nv10_gr_ctx_regs_find_offset(struct nv10_gr_priv *priv, int reg)
845 {
846 	int i;
847 	for (i = 0; i < ARRAY_SIZE(nv10_gr_ctx_regs); i++) {
848 		if (nv10_gr_ctx_regs[i] == reg)
849 			return i;
850 	}
851 	nv_error(priv, "unknow offset nv10_ctx_regs %d\n", reg);
852 	return -1;
853 }
854 
855 static int
856 nv17_gr_ctx_regs_find_offset(struct nv10_gr_priv *priv, int reg)
857 {
858 	int i;
859 	for (i = 0; i < ARRAY_SIZE(nv17_gr_ctx_regs); i++) {
860 		if (nv17_gr_ctx_regs[i] == reg)
861 			return i;
862 	}
863 	nv_error(priv, "unknow offset nv17_ctx_regs %d\n", reg);
864 	return -1;
865 }
866 
867 static void
868 nv10_gr_load_dma_vtxbuf(struct nv10_gr_chan *chan, int chid, u32 inst)
869 {
870 	struct nv10_gr_priv *priv = nv10_gr_priv(chan);
871 	u32 st2, st2_dl, st2_dh, fifo_ptr, fifo[0x60/4];
872 	u32 ctx_user, ctx_switch[5];
873 	int i, subchan = -1;
874 
875 	/* NV10TCL_DMA_VTXBUF (method 0x18c) modifies hidden state
876 	 * that cannot be restored via MMIO. Do it through the FIFO
877 	 * instead.
878 	 */
879 
880 	/* Look for a celsius object */
881 	for (i = 0; i < 8; i++) {
882 		int class = nv_rd32(priv, NV10_PGRAPH_CTX_CACHE(i, 0)) & 0xfff;
883 
884 		if (class == 0x56 || class == 0x96 || class == 0x99) {
885 			subchan = i;
886 			break;
887 		}
888 	}
889 
890 	if (subchan < 0 || !inst)
891 		return;
892 
893 	/* Save the current ctx object */
894 	ctx_user = nv_rd32(priv, NV10_PGRAPH_CTX_USER);
895 	for (i = 0; i < 5; i++)
896 		ctx_switch[i] = nv_rd32(priv, NV10_PGRAPH_CTX_SWITCH(i));
897 
898 	/* Save the FIFO state */
899 	st2 = nv_rd32(priv, NV10_PGRAPH_FFINTFC_ST2);
900 	st2_dl = nv_rd32(priv, NV10_PGRAPH_FFINTFC_ST2_DL);
901 	st2_dh = nv_rd32(priv, NV10_PGRAPH_FFINTFC_ST2_DH);
902 	fifo_ptr = nv_rd32(priv, NV10_PGRAPH_FFINTFC_FIFO_PTR);
903 
904 	for (i = 0; i < ARRAY_SIZE(fifo); i++)
905 		fifo[i] = nv_rd32(priv, 0x4007a0 + 4 * i);
906 
907 	/* Switch to the celsius subchannel */
908 	for (i = 0; i < 5; i++)
909 		nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(i),
910 			nv_rd32(priv, NV10_PGRAPH_CTX_CACHE(subchan, i)));
911 	nv_mask(priv, NV10_PGRAPH_CTX_USER, 0xe000, subchan << 13);
912 
913 	/* Inject NV10TCL_DMA_VTXBUF */
914 	nv_wr32(priv, NV10_PGRAPH_FFINTFC_FIFO_PTR, 0);
915 	nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2,
916 		0x2c000000 | chid << 20 | subchan << 16 | 0x18c);
917 	nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2_DL, inst);
918 	nv_mask(priv, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000);
919 	nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
920 	nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
921 
922 	/* Restore the FIFO state */
923 	for (i = 0; i < ARRAY_SIZE(fifo); i++)
924 		nv_wr32(priv, 0x4007a0 + 4 * i, fifo[i]);
925 
926 	nv_wr32(priv, NV10_PGRAPH_FFINTFC_FIFO_PTR, fifo_ptr);
927 	nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2, st2);
928 	nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2_DL, st2_dl);
929 	nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2_DH, st2_dh);
930 
931 	/* Restore the current ctx object */
932 	for (i = 0; i < 5; i++)
933 		nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(i), ctx_switch[i]);
934 	nv_wr32(priv, NV10_PGRAPH_CTX_USER, ctx_user);
935 }
936 
937 static int
938 nv10_gr_load_context(struct nv10_gr_chan *chan, int chid)
939 {
940 	struct nv10_gr_priv *priv = nv10_gr_priv(chan);
941 	u32 inst;
942 	int i;
943 
944 	for (i = 0; i < ARRAY_SIZE(nv10_gr_ctx_regs); i++)
945 		nv_wr32(priv, nv10_gr_ctx_regs[i], chan->nv10[i]);
946 
947 	if (nv_device(priv)->card_type >= NV_11 &&
948 	    nv_device(priv)->chipset >= 0x17) {
949 		for (i = 0; i < ARRAY_SIZE(nv17_gr_ctx_regs); i++)
950 			nv_wr32(priv, nv17_gr_ctx_regs[i], chan->nv17[i]);
951 	}
952 
953 	nv10_gr_load_pipe(chan);
954 
955 	inst = nv_rd32(priv, NV10_PGRAPH_GLOBALSTATE1) & 0xffff;
956 	nv10_gr_load_dma_vtxbuf(chan, chid, inst);
957 
958 	nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10010100);
959 	nv_mask(priv, NV10_PGRAPH_CTX_USER, 0xff000000, chid << 24);
960 	nv_mask(priv, NV10_PGRAPH_FFINTFC_ST2, 0x30000000, 0x00000000);
961 	return 0;
962 }
963 
964 static int
965 nv10_gr_unload_context(struct nv10_gr_chan *chan)
966 {
967 	struct nv10_gr_priv *priv = nv10_gr_priv(chan);
968 	int i;
969 
970 	for (i = 0; i < ARRAY_SIZE(nv10_gr_ctx_regs); i++)
971 		chan->nv10[i] = nv_rd32(priv, nv10_gr_ctx_regs[i]);
972 
973 	if (nv_device(priv)->card_type >= NV_11 &&
974 	    nv_device(priv)->chipset >= 0x17) {
975 		for (i = 0; i < ARRAY_SIZE(nv17_gr_ctx_regs); i++)
976 			chan->nv17[i] = nv_rd32(priv, nv17_gr_ctx_regs[i]);
977 	}
978 
979 	nv10_gr_save_pipe(chan);
980 
981 	nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10000000);
982 	nv_mask(priv, NV10_PGRAPH_CTX_USER, 0xff000000, 0x1f000000);
983 	return 0;
984 }
985 
986 static void
987 nv10_gr_context_switch(struct nv10_gr_priv *priv)
988 {
989 	struct nv10_gr_chan *prev = NULL;
990 	struct nv10_gr_chan *next = NULL;
991 	unsigned long flags;
992 	int chid;
993 
994 	spin_lock_irqsave(&priv->lock, flags);
995 	nv04_gr_idle(priv);
996 
997 	/* If previous context is valid, we need to save it */
998 	prev = nv10_gr_channel(priv);
999 	if (prev)
1000 		nv10_gr_unload_context(prev);
1001 
1002 	/* load context for next channel */
1003 	chid = (nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f;
1004 	next = priv->chan[chid];
1005 	if (next)
1006 		nv10_gr_load_context(next, chid);
1007 
1008 	spin_unlock_irqrestore(&priv->lock, flags);
1009 }
1010 
1011 #define NV_WRITE_CTX(reg, val) do { \
1012 	int offset = nv10_gr_ctx_regs_find_offset(priv, reg); \
1013 	if (offset > 0) \
1014 		chan->nv10[offset] = val; \
1015 	} while (0)
1016 
1017 #define NV17_WRITE_CTX(reg, val) do { \
1018 	int offset = nv17_gr_ctx_regs_find_offset(priv, reg); \
1019 	if (offset > 0) \
1020 		chan->nv17[offset] = val; \
1021 	} while (0)
1022 
1023 static int
1024 nv10_gr_context_ctor(struct nouveau_object *parent,
1025 			struct nouveau_object *engine,
1026 			struct nouveau_oclass *oclass, void *data, u32 size,
1027 			struct nouveau_object **pobject)
1028 {
1029 	struct nouveau_fifo_chan *fifo = (void *)parent;
1030 	struct nv10_gr_priv *priv = (void *)engine;
1031 	struct nv10_gr_chan *chan;
1032 	unsigned long flags;
1033 	int ret;
1034 
1035 	ret = nouveau_object_create(parent, engine, oclass, 0, &chan);
1036 	*pobject = nv_object(chan);
1037 	if (ret)
1038 		return ret;
1039 
1040 	spin_lock_irqsave(&priv->lock, flags);
1041 	if (priv->chan[fifo->chid]) {
1042 		*pobject = nv_object(priv->chan[fifo->chid]);
1043 		atomic_inc(&(*pobject)->refcount);
1044 		spin_unlock_irqrestore(&priv->lock, flags);
1045 		nouveau_object_destroy(&chan->base);
1046 		return 1;
1047 	}
1048 
1049 	NV_WRITE_CTX(0x00400e88, 0x08000000);
1050 	NV_WRITE_CTX(0x00400e9c, 0x4b7fffff);
1051 	NV_WRITE_CTX(NV03_PGRAPH_XY_LOGIC_MISC0, 0x0001ffff);
1052 	NV_WRITE_CTX(0x00400e10, 0x00001000);
1053 	NV_WRITE_CTX(0x00400e14, 0x00001000);
1054 	NV_WRITE_CTX(0x00400e30, 0x00080008);
1055 	NV_WRITE_CTX(0x00400e34, 0x00080008);
1056 	if (nv_device(priv)->card_type >= NV_11 &&
1057 	    nv_device(priv)->chipset >= 0x17) {
1058 		/* is it really needed ??? */
1059 		NV17_WRITE_CTX(NV10_PGRAPH_DEBUG_4,
1060 					nv_rd32(priv, NV10_PGRAPH_DEBUG_4));
1061 		NV17_WRITE_CTX(0x004006b0, nv_rd32(priv, 0x004006b0));
1062 		NV17_WRITE_CTX(0x00400eac, 0x0fff0000);
1063 		NV17_WRITE_CTX(0x00400eb0, 0x0fff0000);
1064 		NV17_WRITE_CTX(0x00400ec0, 0x00000080);
1065 		NV17_WRITE_CTX(0x00400ed0, 0x00000080);
1066 	}
1067 	NV_WRITE_CTX(NV10_PGRAPH_CTX_USER, chan->chid << 24);
1068 
1069 	nv10_gr_create_pipe(chan);
1070 
1071 	priv->chan[fifo->chid] = chan;
1072 	chan->chid = fifo->chid;
1073 	spin_unlock_irqrestore(&priv->lock, flags);
1074 	return 0;
1075 }
1076 
1077 static void
1078 nv10_gr_context_dtor(struct nouveau_object *object)
1079 {
1080 	struct nv10_gr_priv *priv = (void *)object->engine;
1081 	struct nv10_gr_chan *chan = (void *)object;
1082 	unsigned long flags;
1083 
1084 	spin_lock_irqsave(&priv->lock, flags);
1085 	priv->chan[chan->chid] = NULL;
1086 	spin_unlock_irqrestore(&priv->lock, flags);
1087 
1088 	nouveau_object_destroy(&chan->base);
1089 }
1090 
1091 static int
1092 nv10_gr_context_fini(struct nouveau_object *object, bool suspend)
1093 {
1094 	struct nv10_gr_priv *priv = (void *)object->engine;
1095 	struct nv10_gr_chan *chan = (void *)object;
1096 	unsigned long flags;
1097 
1098 	spin_lock_irqsave(&priv->lock, flags);
1099 	nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
1100 	if (nv10_gr_channel(priv) == chan)
1101 		nv10_gr_unload_context(chan);
1102 	nv_mask(priv, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
1103 	spin_unlock_irqrestore(&priv->lock, flags);
1104 
1105 	return nouveau_object_fini(&chan->base, suspend);
1106 }
1107 
1108 static struct nouveau_oclass
1109 nv10_gr_cclass = {
1110 	.handle = NV_ENGCTX(GR, 0x10),
1111 	.ofuncs = &(struct nouveau_ofuncs) {
1112 		.ctor = nv10_gr_context_ctor,
1113 		.dtor = nv10_gr_context_dtor,
1114 		.init = nouveau_object_init,
1115 		.fini = nv10_gr_context_fini,
1116 	},
1117 };
1118 
1119 /*******************************************************************************
1120  * PGRAPH engine/subdev functions
1121  ******************************************************************************/
1122 
1123 static void
1124 nv10_gr_tile_prog(struct nouveau_engine *engine, int i)
1125 {
1126 	struct nouveau_fb_tile *tile = &nouveau_fb(engine)->tile.region[i];
1127 	struct nouveau_fifo *pfifo = nouveau_fifo(engine);
1128 	struct nv10_gr_priv *priv = (void *)engine;
1129 	unsigned long flags;
1130 
1131 	pfifo->pause(pfifo, &flags);
1132 	nv04_gr_idle(priv);
1133 
1134 	nv_wr32(priv, NV10_PGRAPH_TLIMIT(i), tile->limit);
1135 	nv_wr32(priv, NV10_PGRAPH_TSIZE(i), tile->pitch);
1136 	nv_wr32(priv, NV10_PGRAPH_TILE(i), tile->addr);
1137 
1138 	pfifo->start(pfifo, &flags);
1139 }
1140 
1141 const struct nouveau_bitfield nv10_gr_intr_name[] = {
1142 	{ NV_PGRAPH_INTR_NOTIFY, "NOTIFY" },
1143 	{ NV_PGRAPH_INTR_ERROR,  "ERROR"  },
1144 	{}
1145 };
1146 
1147 const struct nouveau_bitfield nv10_gr_nstatus[] = {
1148 	{ NV10_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
1149 	{ NV10_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
1150 	{ NV10_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
1151 	{ NV10_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" },
1152 	{}
1153 };
1154 
1155 static void
1156 nv10_gr_intr(struct nouveau_subdev *subdev)
1157 {
1158 	struct nv10_gr_priv *priv = (void *)subdev;
1159 	struct nv10_gr_chan *chan = NULL;
1160 	struct nouveau_namedb *namedb = NULL;
1161 	struct nouveau_handle *handle = NULL;
1162 	u32 stat = nv_rd32(priv, NV03_PGRAPH_INTR);
1163 	u32 nsource = nv_rd32(priv, NV03_PGRAPH_NSOURCE);
1164 	u32 nstatus = nv_rd32(priv, NV03_PGRAPH_NSTATUS);
1165 	u32 addr = nv_rd32(priv, NV04_PGRAPH_TRAPPED_ADDR);
1166 	u32 chid = (addr & 0x01f00000) >> 20;
1167 	u32 subc = (addr & 0x00070000) >> 16;
1168 	u32 mthd = (addr & 0x00001ffc);
1169 	u32 data = nv_rd32(priv, NV04_PGRAPH_TRAPPED_DATA);
1170 	u32 class = nv_rd32(priv, 0x400160 + subc * 4) & 0xfff;
1171 	u32 show = stat;
1172 	unsigned long flags;
1173 
1174 	spin_lock_irqsave(&priv->lock, flags);
1175 	chan = priv->chan[chid];
1176 	if (chan)
1177 		namedb = (void *)nv_pclass(nv_object(chan), NV_NAMEDB_CLASS);
1178 	spin_unlock_irqrestore(&priv->lock, flags);
1179 
1180 	if (stat & NV_PGRAPH_INTR_ERROR) {
1181 		if (chan && (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD)) {
1182 			handle = nouveau_namedb_get_class(namedb, class);
1183 			if (handle && !nv_call(handle->object, mthd, data))
1184 				show &= ~NV_PGRAPH_INTR_ERROR;
1185 		}
1186 	}
1187 
1188 	if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
1189 		nv_wr32(priv, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH);
1190 		stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1191 		show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1192 		nv10_gr_context_switch(priv);
1193 	}
1194 
1195 	nv_wr32(priv, NV03_PGRAPH_INTR, stat);
1196 	nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001);
1197 
1198 	if (show) {
1199 		nv_error(priv, "%s", "");
1200 		nouveau_bitfield_print(nv10_gr_intr_name, show);
1201 		pr_cont(" nsource:");
1202 		nouveau_bitfield_print(nv04_gr_nsource, nsource);
1203 		pr_cont(" nstatus:");
1204 		nouveau_bitfield_print(nv10_gr_nstatus, nstatus);
1205 		pr_cont("\n");
1206 		nv_error(priv,
1207 			 "ch %d [%s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n",
1208 			 chid, nouveau_client_name(chan), subc, class, mthd,
1209 			 data);
1210 	}
1211 
1212 	nouveau_namedb_put(handle);
1213 }
1214 
1215 static int
1216 nv10_gr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
1217 		struct nouveau_oclass *oclass, void *data, u32 size,
1218 		struct nouveau_object **pobject)
1219 {
1220 	struct nv10_gr_priv *priv;
1221 	int ret;
1222 
1223 	ret = nouveau_gr_create(parent, engine, oclass, true, &priv);
1224 	*pobject = nv_object(priv);
1225 	if (ret)
1226 		return ret;
1227 
1228 	nv_subdev(priv)->unit = 0x00001000;
1229 	nv_subdev(priv)->intr = nv10_gr_intr;
1230 	nv_engine(priv)->cclass = &nv10_gr_cclass;
1231 
1232 	if (nv_device(priv)->chipset <= 0x10)
1233 		nv_engine(priv)->sclass = nv10_gr_sclass;
1234 	else
1235 	if (nv_device(priv)->chipset <  0x17 ||
1236 	    nv_device(priv)->card_type < NV_11)
1237 		nv_engine(priv)->sclass = nv15_gr_sclass;
1238 	else
1239 		nv_engine(priv)->sclass = nv17_gr_sclass;
1240 
1241 	nv_engine(priv)->tile_prog = nv10_gr_tile_prog;
1242 	spin_lock_init(&priv->lock);
1243 	return 0;
1244 }
1245 
1246 static void
1247 nv10_gr_dtor(struct nouveau_object *object)
1248 {
1249 	struct nv10_gr_priv *priv = (void *)object;
1250 	nouveau_gr_destroy(&priv->base);
1251 }
1252 
1253 static int
1254 nv10_gr_init(struct nouveau_object *object)
1255 {
1256 	struct nouveau_engine *engine = nv_engine(object);
1257 	struct nouveau_fb *pfb = nouveau_fb(object);
1258 	struct nv10_gr_priv *priv = (void *)engine;
1259 	int ret, i;
1260 
1261 	ret = nouveau_gr_init(&priv->base);
1262 	if (ret)
1263 		return ret;
1264 
1265 	nv_wr32(priv, NV03_PGRAPH_INTR   , 0xFFFFFFFF);
1266 	nv_wr32(priv, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
1267 
1268 	nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
1269 	nv_wr32(priv, NV04_PGRAPH_DEBUG_0, 0x00000000);
1270 	nv_wr32(priv, NV04_PGRAPH_DEBUG_1, 0x00118700);
1271 	/* nv_wr32(priv, NV04_PGRAPH_DEBUG_2, 0x24E00810); */ /* 0x25f92ad9 */
1272 	nv_wr32(priv, NV04_PGRAPH_DEBUG_2, 0x25f92ad9);
1273 	nv_wr32(priv, NV04_PGRAPH_DEBUG_3, 0x55DE0830 | (1 << 29) | (1 << 31));
1274 
1275 	if (nv_device(priv)->card_type >= NV_11 &&
1276 	    nv_device(priv)->chipset >= 0x17) {
1277 		nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x1f000000);
1278 		nv_wr32(priv, 0x400a10, 0x03ff3fb6);
1279 		nv_wr32(priv, 0x400838, 0x002f8684);
1280 		nv_wr32(priv, 0x40083c, 0x00115f3f);
1281 		nv_wr32(priv, 0x4006b0, 0x40000020);
1282 	} else {
1283 		nv_wr32(priv, NV10_PGRAPH_DEBUG_4, 0x00000000);
1284 	}
1285 
1286 	/* Turn all the tiling regions off. */
1287 	for (i = 0; i < pfb->tile.regions; i++)
1288 		engine->tile_prog(engine, i);
1289 
1290 	nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(0), 0x00000000);
1291 	nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(1), 0x00000000);
1292 	nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(2), 0x00000000);
1293 	nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(3), 0x00000000);
1294 	nv_wr32(priv, NV10_PGRAPH_CTX_SWITCH(4), 0x00000000);
1295 	nv_wr32(priv, NV10_PGRAPH_STATE, 0xFFFFFFFF);
1296 
1297 	nv_mask(priv, NV10_PGRAPH_CTX_USER, 0xff000000, 0x1f000000);
1298 	nv_wr32(priv, NV10_PGRAPH_CTX_CONTROL, 0x10000100);
1299 	nv_wr32(priv, NV10_PGRAPH_FFINTFC_ST2, 0x08000000);
1300 	return 0;
1301 }
1302 
1303 static int
1304 nv10_gr_fini(struct nouveau_object *object, bool suspend)
1305 {
1306 	struct nv10_gr_priv *priv = (void *)object;
1307 	return nouveau_gr_fini(&priv->base, suspend);
1308 }
1309 
1310 struct nouveau_oclass
1311 nv10_gr_oclass = {
1312 	.handle = NV_ENGINE(GR, 0x10),
1313 	.ofuncs = &(struct nouveau_ofuncs) {
1314 		.ctor = nv10_gr_ctor,
1315 		.dtor = nv10_gr_dtor,
1316 		.init = nv10_gr_init,
1317 		.fini = nv10_gr_fini,
1318 	},
1319 };
1320