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