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