xref: /linux/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c (revision 48dea9a700c8728cc31a1dd44588b97578de86ee)
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 "nv10.h"
25 #include "regs.h"
26 
27 #include <core/client.h>
28 #include <core/gpuobj.h>
29 #include <engine/fifo.h>
30 #include <engine/fifo/chan.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 #define nv10_gr(p) container_of((p), struct nv10_gr, base)
390 
391 struct nv10_gr {
392 	struct nvkm_gr base;
393 	struct nv10_gr_chan *chan[32];
394 	spinlock_t lock;
395 };
396 
397 #define nv10_gr_chan(p) container_of((p), struct nv10_gr_chan, object)
398 
399 struct nv10_gr_chan {
400 	struct nvkm_object object;
401 	struct nv10_gr *gr;
402 	int chid;
403 	int nv10[ARRAY_SIZE(nv10_gr_ctx_regs)];
404 	int nv17[ARRAY_SIZE(nv17_gr_ctx_regs)];
405 	struct pipe_state pipe_state;
406 	u32 lma_window[4];
407 };
408 
409 
410 /*******************************************************************************
411  * Graphics object classes
412  ******************************************************************************/
413 
414 #define PIPE_SAVE(gr, state, addr)					\
415 	do {								\
416 		int __i;						\
417 		nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, addr);		\
418 		for (__i = 0; __i < ARRAY_SIZE(state); __i++)		\
419 			state[__i] = nvkm_rd32(device, NV10_PGRAPH_PIPE_DATA); \
420 	} while (0)
421 
422 #define PIPE_RESTORE(gr, state, addr)					\
423 	do {								\
424 		int __i;						\
425 		nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, addr);		\
426 		for (__i = 0; __i < ARRAY_SIZE(state); __i++)		\
427 			nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, state[__i]); \
428 	} while (0)
429 
430 static void
431 nv17_gr_mthd_lma_window(struct nv10_gr_chan *chan, u32 mthd, u32 data)
432 {
433 	struct nvkm_device *device = chan->object.engine->subdev.device;
434 	struct nvkm_gr *gr = &chan->gr->base;
435 	struct pipe_state *pipe = &chan->pipe_state;
436 	u32 pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3];
437 	u32 xfmode0, xfmode1;
438 	int i;
439 
440 	chan->lma_window[(mthd - 0x1638) / 4] = data;
441 
442 	if (mthd != 0x1644)
443 		return;
444 
445 	nv04_gr_idle(gr);
446 
447 	PIPE_SAVE(device, pipe_0x0040, 0x0040);
448 	PIPE_SAVE(device, pipe->pipe_0x0200, 0x0200);
449 
450 	PIPE_RESTORE(device, chan->lma_window, 0x6790);
451 
452 	nv04_gr_idle(gr);
453 
454 	xfmode0 = nvkm_rd32(device, NV10_PGRAPH_XFMODE0);
455 	xfmode1 = nvkm_rd32(device, NV10_PGRAPH_XFMODE1);
456 
457 	PIPE_SAVE(device, pipe->pipe_0x4400, 0x4400);
458 	PIPE_SAVE(device, pipe_0x64c0, 0x64c0);
459 	PIPE_SAVE(device, pipe_0x6ab0, 0x6ab0);
460 	PIPE_SAVE(device, pipe_0x6a80, 0x6a80);
461 
462 	nv04_gr_idle(gr);
463 
464 	nvkm_wr32(device, NV10_PGRAPH_XFMODE0, 0x10000000);
465 	nvkm_wr32(device, NV10_PGRAPH_XFMODE1, 0x00000000);
466 	nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0);
467 	for (i = 0; i < 4; i++)
468 		nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
469 	for (i = 0; i < 4; i++)
470 		nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000000);
471 
472 	nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0);
473 	for (i = 0; i < 3; i++)
474 		nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
475 
476 	nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80);
477 	for (i = 0; i < 3; i++)
478 		nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000000);
479 
480 	nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040);
481 	nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000008);
482 
483 	PIPE_RESTORE(device, pipe->pipe_0x0200, 0x0200);
484 
485 	nv04_gr_idle(gr);
486 
487 	PIPE_RESTORE(device, pipe_0x0040, 0x0040);
488 
489 	nvkm_wr32(device, NV10_PGRAPH_XFMODE0, xfmode0);
490 	nvkm_wr32(device, NV10_PGRAPH_XFMODE1, xfmode1);
491 
492 	PIPE_RESTORE(device, pipe_0x64c0, 0x64c0);
493 	PIPE_RESTORE(device, pipe_0x6ab0, 0x6ab0);
494 	PIPE_RESTORE(device, pipe_0x6a80, 0x6a80);
495 	PIPE_RESTORE(device, pipe->pipe_0x4400, 0x4400);
496 
497 	nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x000000c0);
498 	nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000000);
499 
500 	nv04_gr_idle(gr);
501 }
502 
503 static void
504 nv17_gr_mthd_lma_enable(struct nv10_gr_chan *chan, u32 mthd, u32 data)
505 {
506 	struct nvkm_device *device = chan->object.engine->subdev.device;
507 	struct nvkm_gr *gr = &chan->gr->base;
508 
509 	nv04_gr_idle(gr);
510 
511 	nvkm_mask(device, NV10_PGRAPH_DEBUG_4, 0x00000100, 0x00000100);
512 	nvkm_mask(device, 0x4006b0, 0x08000000, 0x08000000);
513 }
514 
515 static bool
516 nv17_gr_mthd_celcius(struct nv10_gr_chan *chan, u32 mthd, u32 data)
517 {
518 	void (*func)(struct nv10_gr_chan *, u32, u32);
519 	switch (mthd) {
520 	case 0x1638 ... 0x1644:
521 		     func = nv17_gr_mthd_lma_window; break;
522 	case 0x1658: func = nv17_gr_mthd_lma_enable; break;
523 	default:
524 		return false;
525 	}
526 	func(chan, mthd, data);
527 	return true;
528 }
529 
530 static bool
531 nv10_gr_mthd(struct nv10_gr_chan *chan, u8 class, u32 mthd, u32 data)
532 {
533 	bool (*func)(struct nv10_gr_chan *, u32, u32);
534 	switch (class) {
535 	case 0x99: func = nv17_gr_mthd_celcius; break;
536 	default:
537 		return false;
538 	}
539 	return func(chan, mthd, data);
540 }
541 
542 /*******************************************************************************
543  * PGRAPH context
544  ******************************************************************************/
545 
546 static struct nv10_gr_chan *
547 nv10_gr_channel(struct nv10_gr *gr)
548 {
549 	struct nvkm_device *device = gr->base.engine.subdev.device;
550 	struct nv10_gr_chan *chan = NULL;
551 	if (nvkm_rd32(device, 0x400144) & 0x00010000) {
552 		int chid = nvkm_rd32(device, 0x400148) >> 24;
553 		if (chid < ARRAY_SIZE(gr->chan))
554 			chan = gr->chan[chid];
555 	}
556 	return chan;
557 }
558 
559 static void
560 nv10_gr_save_pipe(struct nv10_gr_chan *chan)
561 {
562 	struct nv10_gr *gr = chan->gr;
563 	struct pipe_state *pipe = &chan->pipe_state;
564 	struct nvkm_device *device = gr->base.engine.subdev.device;
565 
566 	PIPE_SAVE(gr, pipe->pipe_0x4400, 0x4400);
567 	PIPE_SAVE(gr, pipe->pipe_0x0200, 0x0200);
568 	PIPE_SAVE(gr, pipe->pipe_0x6400, 0x6400);
569 	PIPE_SAVE(gr, pipe->pipe_0x6800, 0x6800);
570 	PIPE_SAVE(gr, pipe->pipe_0x6c00, 0x6c00);
571 	PIPE_SAVE(gr, pipe->pipe_0x7000, 0x7000);
572 	PIPE_SAVE(gr, pipe->pipe_0x7400, 0x7400);
573 	PIPE_SAVE(gr, pipe->pipe_0x7800, 0x7800);
574 	PIPE_SAVE(gr, pipe->pipe_0x0040, 0x0040);
575 	PIPE_SAVE(gr, pipe->pipe_0x0000, 0x0000);
576 }
577 
578 static void
579 nv10_gr_load_pipe(struct nv10_gr_chan *chan)
580 {
581 	struct nv10_gr *gr = chan->gr;
582 	struct pipe_state *pipe = &chan->pipe_state;
583 	struct nvkm_device *device = gr->base.engine.subdev.device;
584 	u32 xfmode0, xfmode1;
585 	int i;
586 
587 	nv04_gr_idle(&gr->base);
588 	/* XXX check haiku comments */
589 	xfmode0 = nvkm_rd32(device, NV10_PGRAPH_XFMODE0);
590 	xfmode1 = nvkm_rd32(device, NV10_PGRAPH_XFMODE1);
591 	nvkm_wr32(device, NV10_PGRAPH_XFMODE0, 0x10000000);
592 	nvkm_wr32(device, NV10_PGRAPH_XFMODE1, 0x00000000);
593 	nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0);
594 	for (i = 0; i < 4; i++)
595 		nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
596 	for (i = 0; i < 4; i++)
597 		nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000000);
598 
599 	nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0);
600 	for (i = 0; i < 3; i++)
601 		nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
602 
603 	nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80);
604 	for (i = 0; i < 3; i++)
605 		nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000000);
606 
607 	nvkm_wr32(device, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040);
608 	nvkm_wr32(device, NV10_PGRAPH_PIPE_DATA, 0x00000008);
609 
610 
611 	PIPE_RESTORE(gr, pipe->pipe_0x0200, 0x0200);
612 	nv04_gr_idle(&gr->base);
613 
614 	/* restore XFMODE */
615 	nvkm_wr32(device, NV10_PGRAPH_XFMODE0, xfmode0);
616 	nvkm_wr32(device, NV10_PGRAPH_XFMODE1, xfmode1);
617 	PIPE_RESTORE(gr, pipe->pipe_0x6400, 0x6400);
618 	PIPE_RESTORE(gr, pipe->pipe_0x6800, 0x6800);
619 	PIPE_RESTORE(gr, pipe->pipe_0x6c00, 0x6c00);
620 	PIPE_RESTORE(gr, pipe->pipe_0x7000, 0x7000);
621 	PIPE_RESTORE(gr, pipe->pipe_0x7400, 0x7400);
622 	PIPE_RESTORE(gr, pipe->pipe_0x7800, 0x7800);
623 	PIPE_RESTORE(gr, pipe->pipe_0x4400, 0x4400);
624 	PIPE_RESTORE(gr, pipe->pipe_0x0000, 0x0000);
625 	PIPE_RESTORE(gr, pipe->pipe_0x0040, 0x0040);
626 	nv04_gr_idle(&gr->base);
627 }
628 
629 static void
630 nv10_gr_create_pipe(struct nv10_gr_chan *chan)
631 {
632 	struct nv10_gr *gr = chan->gr;
633 	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
634 	struct pipe_state *pipe_state = &chan->pipe_state;
635 	u32 *pipe_state_addr;
636 	int i;
637 #define PIPE_INIT(addr) \
638 	do { \
639 		pipe_state_addr = pipe_state->pipe_##addr; \
640 	} while (0)
641 #define PIPE_INIT_END(addr) \
642 	do { \
643 		u32 *__end_addr = pipe_state->pipe_##addr + \
644 				ARRAY_SIZE(pipe_state->pipe_##addr); \
645 		if (pipe_state_addr != __end_addr) \
646 			nvkm_error(subdev, "incomplete pipe init for 0x%x :  %p/%p\n", \
647 				addr, pipe_state_addr, __end_addr); \
648 	} while (0)
649 #define NV_WRITE_PIPE_INIT(value) *(pipe_state_addr++) = value
650 
651 	PIPE_INIT(0x0200);
652 	for (i = 0; i < 48; i++)
653 		NV_WRITE_PIPE_INIT(0x00000000);
654 	PIPE_INIT_END(0x0200);
655 
656 	PIPE_INIT(0x6400);
657 	for (i = 0; i < 211; i++)
658 		NV_WRITE_PIPE_INIT(0x00000000);
659 	NV_WRITE_PIPE_INIT(0x3f800000);
660 	NV_WRITE_PIPE_INIT(0x40000000);
661 	NV_WRITE_PIPE_INIT(0x40000000);
662 	NV_WRITE_PIPE_INIT(0x40000000);
663 	NV_WRITE_PIPE_INIT(0x40000000);
664 	NV_WRITE_PIPE_INIT(0x00000000);
665 	NV_WRITE_PIPE_INIT(0x00000000);
666 	NV_WRITE_PIPE_INIT(0x3f800000);
667 	NV_WRITE_PIPE_INIT(0x00000000);
668 	NV_WRITE_PIPE_INIT(0x3f000000);
669 	NV_WRITE_PIPE_INIT(0x3f000000);
670 	NV_WRITE_PIPE_INIT(0x00000000);
671 	NV_WRITE_PIPE_INIT(0x00000000);
672 	NV_WRITE_PIPE_INIT(0x00000000);
673 	NV_WRITE_PIPE_INIT(0x00000000);
674 	NV_WRITE_PIPE_INIT(0x3f800000);
675 	NV_WRITE_PIPE_INIT(0x00000000);
676 	NV_WRITE_PIPE_INIT(0x00000000);
677 	NV_WRITE_PIPE_INIT(0x00000000);
678 	NV_WRITE_PIPE_INIT(0x00000000);
679 	NV_WRITE_PIPE_INIT(0x00000000);
680 	NV_WRITE_PIPE_INIT(0x3f800000);
681 	NV_WRITE_PIPE_INIT(0x3f800000);
682 	NV_WRITE_PIPE_INIT(0x3f800000);
683 	NV_WRITE_PIPE_INIT(0x3f800000);
684 	PIPE_INIT_END(0x6400);
685 
686 	PIPE_INIT(0x6800);
687 	for (i = 0; i < 162; i++)
688 		NV_WRITE_PIPE_INIT(0x00000000);
689 	NV_WRITE_PIPE_INIT(0x3f800000);
690 	for (i = 0; i < 25; i++)
691 		NV_WRITE_PIPE_INIT(0x00000000);
692 	PIPE_INIT_END(0x6800);
693 
694 	PIPE_INIT(0x6c00);
695 	NV_WRITE_PIPE_INIT(0x00000000);
696 	NV_WRITE_PIPE_INIT(0x00000000);
697 	NV_WRITE_PIPE_INIT(0x00000000);
698 	NV_WRITE_PIPE_INIT(0x00000000);
699 	NV_WRITE_PIPE_INIT(0xbf800000);
700 	NV_WRITE_PIPE_INIT(0x00000000);
701 	NV_WRITE_PIPE_INIT(0x00000000);
702 	NV_WRITE_PIPE_INIT(0x00000000);
703 	NV_WRITE_PIPE_INIT(0x00000000);
704 	NV_WRITE_PIPE_INIT(0x00000000);
705 	NV_WRITE_PIPE_INIT(0x00000000);
706 	NV_WRITE_PIPE_INIT(0x00000000);
707 	PIPE_INIT_END(0x6c00);
708 
709 	PIPE_INIT(0x7000);
710 	NV_WRITE_PIPE_INIT(0x00000000);
711 	NV_WRITE_PIPE_INIT(0x00000000);
712 	NV_WRITE_PIPE_INIT(0x00000000);
713 	NV_WRITE_PIPE_INIT(0x00000000);
714 	NV_WRITE_PIPE_INIT(0x00000000);
715 	NV_WRITE_PIPE_INIT(0x00000000);
716 	NV_WRITE_PIPE_INIT(0x00000000);
717 	NV_WRITE_PIPE_INIT(0x00000000);
718 	NV_WRITE_PIPE_INIT(0x00000000);
719 	NV_WRITE_PIPE_INIT(0x00000000);
720 	NV_WRITE_PIPE_INIT(0x00000000);
721 	NV_WRITE_PIPE_INIT(0x00000000);
722 	NV_WRITE_PIPE_INIT(0x7149f2ca);
723 	NV_WRITE_PIPE_INIT(0x00000000);
724 	NV_WRITE_PIPE_INIT(0x00000000);
725 	NV_WRITE_PIPE_INIT(0x00000000);
726 	NV_WRITE_PIPE_INIT(0x7149f2ca);
727 	NV_WRITE_PIPE_INIT(0x00000000);
728 	NV_WRITE_PIPE_INIT(0x00000000);
729 	NV_WRITE_PIPE_INIT(0x00000000);
730 	NV_WRITE_PIPE_INIT(0x7149f2ca);
731 	NV_WRITE_PIPE_INIT(0x00000000);
732 	NV_WRITE_PIPE_INIT(0x00000000);
733 	NV_WRITE_PIPE_INIT(0x00000000);
734 	NV_WRITE_PIPE_INIT(0x7149f2ca);
735 	NV_WRITE_PIPE_INIT(0x00000000);
736 	NV_WRITE_PIPE_INIT(0x00000000);
737 	NV_WRITE_PIPE_INIT(0x00000000);
738 	NV_WRITE_PIPE_INIT(0x7149f2ca);
739 	NV_WRITE_PIPE_INIT(0x00000000);
740 	NV_WRITE_PIPE_INIT(0x00000000);
741 	NV_WRITE_PIPE_INIT(0x00000000);
742 	NV_WRITE_PIPE_INIT(0x7149f2ca);
743 	NV_WRITE_PIPE_INIT(0x00000000);
744 	NV_WRITE_PIPE_INIT(0x00000000);
745 	NV_WRITE_PIPE_INIT(0x00000000);
746 	NV_WRITE_PIPE_INIT(0x7149f2ca);
747 	NV_WRITE_PIPE_INIT(0x00000000);
748 	NV_WRITE_PIPE_INIT(0x00000000);
749 	NV_WRITE_PIPE_INIT(0x00000000);
750 	NV_WRITE_PIPE_INIT(0x7149f2ca);
751 	for (i = 0; i < 35; i++)
752 		NV_WRITE_PIPE_INIT(0x00000000);
753 	PIPE_INIT_END(0x7000);
754 
755 	PIPE_INIT(0x7400);
756 	for (i = 0; i < 48; i++)
757 		NV_WRITE_PIPE_INIT(0x00000000);
758 	PIPE_INIT_END(0x7400);
759 
760 	PIPE_INIT(0x7800);
761 	for (i = 0; i < 48; i++)
762 		NV_WRITE_PIPE_INIT(0x00000000);
763 	PIPE_INIT_END(0x7800);
764 
765 	PIPE_INIT(0x4400);
766 	for (i = 0; i < 32; i++)
767 		NV_WRITE_PIPE_INIT(0x00000000);
768 	PIPE_INIT_END(0x4400);
769 
770 	PIPE_INIT(0x0000);
771 	for (i = 0; i < 16; i++)
772 		NV_WRITE_PIPE_INIT(0x00000000);
773 	PIPE_INIT_END(0x0000);
774 
775 	PIPE_INIT(0x0040);
776 	for (i = 0; i < 4; i++)
777 		NV_WRITE_PIPE_INIT(0x00000000);
778 	PIPE_INIT_END(0x0040);
779 
780 #undef PIPE_INIT
781 #undef PIPE_INIT_END
782 #undef NV_WRITE_PIPE_INIT
783 }
784 
785 static int
786 nv10_gr_ctx_regs_find_offset(struct nv10_gr *gr, int reg)
787 {
788 	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
789 	int i;
790 	for (i = 0; i < ARRAY_SIZE(nv10_gr_ctx_regs); i++) {
791 		if (nv10_gr_ctx_regs[i] == reg)
792 			return i;
793 	}
794 	nvkm_error(subdev, "unknown offset nv10_ctx_regs %d\n", reg);
795 	return -1;
796 }
797 
798 static int
799 nv17_gr_ctx_regs_find_offset(struct nv10_gr *gr, int reg)
800 {
801 	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
802 	int i;
803 	for (i = 0; i < ARRAY_SIZE(nv17_gr_ctx_regs); i++) {
804 		if (nv17_gr_ctx_regs[i] == reg)
805 			return i;
806 	}
807 	nvkm_error(subdev, "unknown offset nv17_ctx_regs %d\n", reg);
808 	return -1;
809 }
810 
811 static void
812 nv10_gr_load_dma_vtxbuf(struct nv10_gr_chan *chan, int chid, u32 inst)
813 {
814 	struct nv10_gr *gr = chan->gr;
815 	struct nvkm_device *device = gr->base.engine.subdev.device;
816 	u32 st2, st2_dl, st2_dh, fifo_ptr, fifo[0x60/4];
817 	u32 ctx_user, ctx_switch[5];
818 	int i, subchan = -1;
819 
820 	/* NV10TCL_DMA_VTXBUF (method 0x18c) modifies hidden state
821 	 * that cannot be restored via MMIO. Do it through the FIFO
822 	 * instead.
823 	 */
824 
825 	/* Look for a celsius object */
826 	for (i = 0; i < 8; i++) {
827 		int class = nvkm_rd32(device, NV10_PGRAPH_CTX_CACHE(i, 0)) & 0xfff;
828 
829 		if (class == 0x56 || class == 0x96 || class == 0x99) {
830 			subchan = i;
831 			break;
832 		}
833 	}
834 
835 	if (subchan < 0 || !inst)
836 		return;
837 
838 	/* Save the current ctx object */
839 	ctx_user = nvkm_rd32(device, NV10_PGRAPH_CTX_USER);
840 	for (i = 0; i < 5; i++)
841 		ctx_switch[i] = nvkm_rd32(device, NV10_PGRAPH_CTX_SWITCH(i));
842 
843 	/* Save the FIFO state */
844 	st2 = nvkm_rd32(device, NV10_PGRAPH_FFINTFC_ST2);
845 	st2_dl = nvkm_rd32(device, NV10_PGRAPH_FFINTFC_ST2_DL);
846 	st2_dh = nvkm_rd32(device, NV10_PGRAPH_FFINTFC_ST2_DH);
847 	fifo_ptr = nvkm_rd32(device, NV10_PGRAPH_FFINTFC_FIFO_PTR);
848 
849 	for (i = 0; i < ARRAY_SIZE(fifo); i++)
850 		fifo[i] = nvkm_rd32(device, 0x4007a0 + 4 * i);
851 
852 	/* Switch to the celsius subchannel */
853 	for (i = 0; i < 5; i++)
854 		nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(i),
855 			nvkm_rd32(device, NV10_PGRAPH_CTX_CACHE(subchan, i)));
856 	nvkm_mask(device, NV10_PGRAPH_CTX_USER, 0xe000, subchan << 13);
857 
858 	/* Inject NV10TCL_DMA_VTXBUF */
859 	nvkm_wr32(device, NV10_PGRAPH_FFINTFC_FIFO_PTR, 0);
860 	nvkm_wr32(device, NV10_PGRAPH_FFINTFC_ST2,
861 		0x2c000000 | chid << 20 | subchan << 16 | 0x18c);
862 	nvkm_wr32(device, NV10_PGRAPH_FFINTFC_ST2_DL, inst);
863 	nvkm_mask(device, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000);
864 	nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
865 	nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
866 
867 	/* Restore the FIFO state */
868 	for (i = 0; i < ARRAY_SIZE(fifo); i++)
869 		nvkm_wr32(device, 0x4007a0 + 4 * i, fifo[i]);
870 
871 	nvkm_wr32(device, NV10_PGRAPH_FFINTFC_FIFO_PTR, fifo_ptr);
872 	nvkm_wr32(device, NV10_PGRAPH_FFINTFC_ST2, st2);
873 	nvkm_wr32(device, NV10_PGRAPH_FFINTFC_ST2_DL, st2_dl);
874 	nvkm_wr32(device, NV10_PGRAPH_FFINTFC_ST2_DH, st2_dh);
875 
876 	/* Restore the current ctx object */
877 	for (i = 0; i < 5; i++)
878 		nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(i), ctx_switch[i]);
879 	nvkm_wr32(device, NV10_PGRAPH_CTX_USER, ctx_user);
880 }
881 
882 static int
883 nv10_gr_load_context(struct nv10_gr_chan *chan, int chid)
884 {
885 	struct nv10_gr *gr = chan->gr;
886 	struct nvkm_device *device = gr->base.engine.subdev.device;
887 	u32 inst;
888 	int i;
889 
890 	for (i = 0; i < ARRAY_SIZE(nv10_gr_ctx_regs); i++)
891 		nvkm_wr32(device, nv10_gr_ctx_regs[i], chan->nv10[i]);
892 
893 	if (device->card_type >= NV_11 && device->chipset >= 0x17) {
894 		for (i = 0; i < ARRAY_SIZE(nv17_gr_ctx_regs); i++)
895 			nvkm_wr32(device, nv17_gr_ctx_regs[i], chan->nv17[i]);
896 	}
897 
898 	nv10_gr_load_pipe(chan);
899 
900 	inst = nvkm_rd32(device, NV10_PGRAPH_GLOBALSTATE1) & 0xffff;
901 	nv10_gr_load_dma_vtxbuf(chan, chid, inst);
902 
903 	nvkm_wr32(device, NV10_PGRAPH_CTX_CONTROL, 0x10010100);
904 	nvkm_mask(device, NV10_PGRAPH_CTX_USER, 0xff000000, chid << 24);
905 	nvkm_mask(device, NV10_PGRAPH_FFINTFC_ST2, 0x30000000, 0x00000000);
906 	return 0;
907 }
908 
909 static int
910 nv10_gr_unload_context(struct nv10_gr_chan *chan)
911 {
912 	struct nv10_gr *gr = chan->gr;
913 	struct nvkm_device *device = gr->base.engine.subdev.device;
914 	int i;
915 
916 	for (i = 0; i < ARRAY_SIZE(nv10_gr_ctx_regs); i++)
917 		chan->nv10[i] = nvkm_rd32(device, nv10_gr_ctx_regs[i]);
918 
919 	if (device->card_type >= NV_11 && device->chipset >= 0x17) {
920 		for (i = 0; i < ARRAY_SIZE(nv17_gr_ctx_regs); i++)
921 			chan->nv17[i] = nvkm_rd32(device, nv17_gr_ctx_regs[i]);
922 	}
923 
924 	nv10_gr_save_pipe(chan);
925 
926 	nvkm_wr32(device, NV10_PGRAPH_CTX_CONTROL, 0x10000000);
927 	nvkm_mask(device, NV10_PGRAPH_CTX_USER, 0xff000000, 0x1f000000);
928 	return 0;
929 }
930 
931 static void
932 nv10_gr_context_switch(struct nv10_gr *gr)
933 {
934 	struct nvkm_device *device = gr->base.engine.subdev.device;
935 	struct nv10_gr_chan *prev = NULL;
936 	struct nv10_gr_chan *next = NULL;
937 	int chid;
938 
939 	nv04_gr_idle(&gr->base);
940 
941 	/* If previous context is valid, we need to save it */
942 	prev = nv10_gr_channel(gr);
943 	if (prev)
944 		nv10_gr_unload_context(prev);
945 
946 	/* load context for next channel */
947 	chid = (nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f;
948 	next = gr->chan[chid];
949 	if (next)
950 		nv10_gr_load_context(next, chid);
951 }
952 
953 static int
954 nv10_gr_chan_fini(struct nvkm_object *object, bool suspend)
955 {
956 	struct nv10_gr_chan *chan = nv10_gr_chan(object);
957 	struct nv10_gr *gr = chan->gr;
958 	struct nvkm_device *device = gr->base.engine.subdev.device;
959 	unsigned long flags;
960 
961 	spin_lock_irqsave(&gr->lock, flags);
962 	nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
963 	if (nv10_gr_channel(gr) == chan)
964 		nv10_gr_unload_context(chan);
965 	nvkm_mask(device, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
966 	spin_unlock_irqrestore(&gr->lock, flags);
967 	return 0;
968 }
969 
970 static void *
971 nv10_gr_chan_dtor(struct nvkm_object *object)
972 {
973 	struct nv10_gr_chan *chan = nv10_gr_chan(object);
974 	struct nv10_gr *gr = chan->gr;
975 	unsigned long flags;
976 
977 	spin_lock_irqsave(&gr->lock, flags);
978 	gr->chan[chan->chid] = NULL;
979 	spin_unlock_irqrestore(&gr->lock, flags);
980 	return chan;
981 }
982 
983 static const struct nvkm_object_func
984 nv10_gr_chan = {
985 	.dtor = nv10_gr_chan_dtor,
986 	.fini = nv10_gr_chan_fini,
987 };
988 
989 #define NV_WRITE_CTX(reg, val) do { \
990 	int offset = nv10_gr_ctx_regs_find_offset(gr, reg); \
991 	if (offset > 0) \
992 		chan->nv10[offset] = val; \
993 	} while (0)
994 
995 #define NV17_WRITE_CTX(reg, val) do { \
996 	int offset = nv17_gr_ctx_regs_find_offset(gr, reg); \
997 	if (offset > 0) \
998 		chan->nv17[offset] = val; \
999 	} while (0)
1000 
1001 int
1002 nv10_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
1003 		 const struct nvkm_oclass *oclass, struct nvkm_object **pobject)
1004 {
1005 	struct nv10_gr *gr = nv10_gr(base);
1006 	struct nv10_gr_chan *chan;
1007 	struct nvkm_device *device = gr->base.engine.subdev.device;
1008 	unsigned long flags;
1009 
1010 	if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
1011 		return -ENOMEM;
1012 	nvkm_object_ctor(&nv10_gr_chan, oclass, &chan->object);
1013 	chan->gr = gr;
1014 	chan->chid = fifoch->chid;
1015 	*pobject = &chan->object;
1016 
1017 	NV_WRITE_CTX(0x00400e88, 0x08000000);
1018 	NV_WRITE_CTX(0x00400e9c, 0x4b7fffff);
1019 	NV_WRITE_CTX(NV03_PGRAPH_XY_LOGIC_MISC0, 0x0001ffff);
1020 	NV_WRITE_CTX(0x00400e10, 0x00001000);
1021 	NV_WRITE_CTX(0x00400e14, 0x00001000);
1022 	NV_WRITE_CTX(0x00400e30, 0x00080008);
1023 	NV_WRITE_CTX(0x00400e34, 0x00080008);
1024 	if (device->card_type >= NV_11 && device->chipset >= 0x17) {
1025 		/* is it really needed ??? */
1026 		NV17_WRITE_CTX(NV10_PGRAPH_DEBUG_4,
1027 			       nvkm_rd32(device, NV10_PGRAPH_DEBUG_4));
1028 		NV17_WRITE_CTX(0x004006b0, nvkm_rd32(device, 0x004006b0));
1029 		NV17_WRITE_CTX(0x00400eac, 0x0fff0000);
1030 		NV17_WRITE_CTX(0x00400eb0, 0x0fff0000);
1031 		NV17_WRITE_CTX(0x00400ec0, 0x00000080);
1032 		NV17_WRITE_CTX(0x00400ed0, 0x00000080);
1033 	}
1034 	NV_WRITE_CTX(NV10_PGRAPH_CTX_USER, chan->chid << 24);
1035 
1036 	nv10_gr_create_pipe(chan);
1037 
1038 	spin_lock_irqsave(&gr->lock, flags);
1039 	gr->chan[chan->chid] = chan;
1040 	spin_unlock_irqrestore(&gr->lock, flags);
1041 	return 0;
1042 }
1043 
1044 /*******************************************************************************
1045  * PGRAPH engine/subdev functions
1046  ******************************************************************************/
1047 
1048 void
1049 nv10_gr_tile(struct nvkm_gr *base, int i, struct nvkm_fb_tile *tile)
1050 {
1051 	struct nv10_gr *gr = nv10_gr(base);
1052 	struct nvkm_device *device = gr->base.engine.subdev.device;
1053 	struct nvkm_fifo *fifo = device->fifo;
1054 	unsigned long flags;
1055 
1056 	nvkm_fifo_pause(fifo, &flags);
1057 	nv04_gr_idle(&gr->base);
1058 
1059 	nvkm_wr32(device, NV10_PGRAPH_TLIMIT(i), tile->limit);
1060 	nvkm_wr32(device, NV10_PGRAPH_TSIZE(i), tile->pitch);
1061 	nvkm_wr32(device, NV10_PGRAPH_TILE(i), tile->addr);
1062 
1063 	nvkm_fifo_start(fifo, &flags);
1064 }
1065 
1066 const struct nvkm_bitfield nv10_gr_intr_name[] = {
1067 	{ NV_PGRAPH_INTR_NOTIFY, "NOTIFY" },
1068 	{ NV_PGRAPH_INTR_ERROR,  "ERROR"  },
1069 	{}
1070 };
1071 
1072 const struct nvkm_bitfield nv10_gr_nstatus[] = {
1073 	{ NV10_PGRAPH_NSTATUS_STATE_IN_USE,       "STATE_IN_USE" },
1074 	{ NV10_PGRAPH_NSTATUS_INVALID_STATE,      "INVALID_STATE" },
1075 	{ NV10_PGRAPH_NSTATUS_BAD_ARGUMENT,       "BAD_ARGUMENT" },
1076 	{ NV10_PGRAPH_NSTATUS_PROTECTION_FAULT,   "PROTECTION_FAULT" },
1077 	{}
1078 };
1079 
1080 void
1081 nv10_gr_intr(struct nvkm_gr *base)
1082 {
1083 	struct nv10_gr *gr = nv10_gr(base);
1084 	struct nvkm_subdev *subdev = &gr->base.engine.subdev;
1085 	struct nvkm_device *device = subdev->device;
1086 	u32 stat = nvkm_rd32(device, NV03_PGRAPH_INTR);
1087 	u32 nsource = nvkm_rd32(device, NV03_PGRAPH_NSOURCE);
1088 	u32 nstatus = nvkm_rd32(device, NV03_PGRAPH_NSTATUS);
1089 	u32 addr = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_ADDR);
1090 	u32 chid = (addr & 0x01f00000) >> 20;
1091 	u32 subc = (addr & 0x00070000) >> 16;
1092 	u32 mthd = (addr & 0x00001ffc);
1093 	u32 data = nvkm_rd32(device, NV04_PGRAPH_TRAPPED_DATA);
1094 	u32 class = nvkm_rd32(device, 0x400160 + subc * 4) & 0xfff;
1095 	u32 show = stat;
1096 	char msg[128], src[128], sta[128];
1097 	struct nv10_gr_chan *chan;
1098 	unsigned long flags;
1099 
1100 	spin_lock_irqsave(&gr->lock, flags);
1101 	chan = gr->chan[chid];
1102 
1103 	if (stat & NV_PGRAPH_INTR_ERROR) {
1104 		if (chan && (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD)) {
1105 			if (!nv10_gr_mthd(chan, class, mthd, data))
1106 				show &= ~NV_PGRAPH_INTR_ERROR;
1107 		}
1108 	}
1109 
1110 	if (stat & NV_PGRAPH_INTR_CONTEXT_SWITCH) {
1111 		nvkm_wr32(device, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH);
1112 		stat &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1113 		show &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
1114 		nv10_gr_context_switch(gr);
1115 	}
1116 
1117 	nvkm_wr32(device, NV03_PGRAPH_INTR, stat);
1118 	nvkm_wr32(device, NV04_PGRAPH_FIFO, 0x00000001);
1119 
1120 	if (show) {
1121 		nvkm_snprintbf(msg, sizeof(msg), nv10_gr_intr_name, show);
1122 		nvkm_snprintbf(src, sizeof(src), nv04_gr_nsource, nsource);
1123 		nvkm_snprintbf(sta, sizeof(sta), nv10_gr_nstatus, nstatus);
1124 		nvkm_error(subdev, "intr %08x [%s] nsource %08x [%s] "
1125 				   "nstatus %08x [%s] ch %d [%s] subc %d "
1126 				   "class %04x mthd %04x data %08x\n",
1127 			   show, msg, nsource, src, nstatus, sta, chid,
1128 			   chan ? chan->object.client->name : "unknown",
1129 			   subc, class, mthd, data);
1130 	}
1131 
1132 	spin_unlock_irqrestore(&gr->lock, flags);
1133 }
1134 
1135 int
1136 nv10_gr_init(struct nvkm_gr *base)
1137 {
1138 	struct nv10_gr *gr = nv10_gr(base);
1139 	struct nvkm_device *device = gr->base.engine.subdev.device;
1140 
1141 	nvkm_wr32(device, NV03_PGRAPH_INTR   , 0xFFFFFFFF);
1142 	nvkm_wr32(device, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
1143 
1144 	nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
1145 	nvkm_wr32(device, NV04_PGRAPH_DEBUG_0, 0x00000000);
1146 	nvkm_wr32(device, NV04_PGRAPH_DEBUG_1, 0x00118700);
1147 	/* nvkm_wr32(device, NV04_PGRAPH_DEBUG_2, 0x24E00810); */ /* 0x25f92ad9 */
1148 	nvkm_wr32(device, NV04_PGRAPH_DEBUG_2, 0x25f92ad9);
1149 	nvkm_wr32(device, NV04_PGRAPH_DEBUG_3, 0x55DE0830 | (1 << 29) | (1 << 31));
1150 
1151 	if (device->card_type >= NV_11 && device->chipset >= 0x17) {
1152 		nvkm_wr32(device, NV10_PGRAPH_DEBUG_4, 0x1f000000);
1153 		nvkm_wr32(device, 0x400a10, 0x03ff3fb6);
1154 		nvkm_wr32(device, 0x400838, 0x002f8684);
1155 		nvkm_wr32(device, 0x40083c, 0x00115f3f);
1156 		nvkm_wr32(device, 0x4006b0, 0x40000020);
1157 	} else {
1158 		nvkm_wr32(device, NV10_PGRAPH_DEBUG_4, 0x00000000);
1159 	}
1160 
1161 	nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(0), 0x00000000);
1162 	nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(1), 0x00000000);
1163 	nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(2), 0x00000000);
1164 	nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(3), 0x00000000);
1165 	nvkm_wr32(device, NV10_PGRAPH_CTX_SWITCH(4), 0x00000000);
1166 	nvkm_wr32(device, NV10_PGRAPH_STATE, 0xFFFFFFFF);
1167 
1168 	nvkm_mask(device, NV10_PGRAPH_CTX_USER, 0xff000000, 0x1f000000);
1169 	nvkm_wr32(device, NV10_PGRAPH_CTX_CONTROL, 0x10000100);
1170 	nvkm_wr32(device, NV10_PGRAPH_FFINTFC_ST2, 0x08000000);
1171 	return 0;
1172 }
1173 
1174 int
1175 nv10_gr_new_(const struct nvkm_gr_func *func, struct nvkm_device *device,
1176 	     int index, struct nvkm_gr **pgr)
1177 {
1178 	struct nv10_gr *gr;
1179 
1180 	if (!(gr = kzalloc(sizeof(*gr), GFP_KERNEL)))
1181 		return -ENOMEM;
1182 	spin_lock_init(&gr->lock);
1183 	*pgr = &gr->base;
1184 
1185 	return nvkm_gr_ctor(func, device, index, true, &gr->base);
1186 }
1187 
1188 static const struct nvkm_gr_func
1189 nv10_gr = {
1190 	.init = nv10_gr_init,
1191 	.intr = nv10_gr_intr,
1192 	.tile = nv10_gr_tile,
1193 	.chan_new = nv10_gr_chan_new,
1194 	.sclass = {
1195 		{ -1, -1, 0x0012, &nv04_gr_object }, /* beta1 */
1196 		{ -1, -1, 0x0019, &nv04_gr_object }, /* clip */
1197 		{ -1, -1, 0x0030, &nv04_gr_object }, /* null */
1198 		{ -1, -1, 0x0039, &nv04_gr_object }, /* m2mf */
1199 		{ -1, -1, 0x0043, &nv04_gr_object }, /* rop */
1200 		{ -1, -1, 0x0044, &nv04_gr_object }, /* pattern */
1201 		{ -1, -1, 0x004a, &nv04_gr_object }, /* gdi */
1202 		{ -1, -1, 0x0052, &nv04_gr_object }, /* swzsurf */
1203 		{ -1, -1, 0x005f, &nv04_gr_object }, /* blit */
1204 		{ -1, -1, 0x0062, &nv04_gr_object }, /* surf2d */
1205 		{ -1, -1, 0x0072, &nv04_gr_object }, /* beta4 */
1206 		{ -1, -1, 0x0089, &nv04_gr_object }, /* sifm */
1207 		{ -1, -1, 0x008a, &nv04_gr_object }, /* ifc */
1208 		{ -1, -1, 0x009f, &nv04_gr_object }, /* blit */
1209 		{ -1, -1, 0x0093, &nv04_gr_object }, /* surf3d */
1210 		{ -1, -1, 0x0094, &nv04_gr_object }, /* ttri */
1211 		{ -1, -1, 0x0095, &nv04_gr_object }, /* mtri */
1212 		{ -1, -1, 0x0056, &nv04_gr_object }, /* celcius */
1213 		{}
1214 	}
1215 };
1216 
1217 int
1218 nv10_gr_new(struct nvkm_device *device, int index, struct nvkm_gr **pgr)
1219 {
1220 	return nv10_gr_new_(&nv10_gr, device, index, pgr);
1221 }
1222