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