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