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