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