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