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