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