drm/nv50: fix iommu errors caused by device reading from address 0
[safe/jmp/linux-2.6] / drivers / gpu / drm / nouveau / nv10_graph.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 "drmP.h"
26 #include "drm.h"
27 #include "nouveau_drm.h"
28 #include "nouveau_drv.h"
29
30 #define NV10_FIFO_NUMBER 32
31
32 struct pipe_state {
33         uint32_t pipe_0x0000[0x040/4];
34         uint32_t pipe_0x0040[0x010/4];
35         uint32_t pipe_0x0200[0x0c0/4];
36         uint32_t pipe_0x4400[0x080/4];
37         uint32_t pipe_0x6400[0x3b0/4];
38         uint32_t pipe_0x6800[0x2f0/4];
39         uint32_t pipe_0x6c00[0x030/4];
40         uint32_t pipe_0x7000[0x130/4];
41         uint32_t pipe_0x7400[0x0c0/4];
42         uint32_t pipe_0x7800[0x0c0/4];
43 };
44
45 static int nv10_graph_ctx_regs[] = {
46         NV10_PGRAPH_CTX_SWITCH1,
47         NV10_PGRAPH_CTX_SWITCH2,
48         NV10_PGRAPH_CTX_SWITCH3,
49         NV10_PGRAPH_CTX_SWITCH4,
50         NV10_PGRAPH_CTX_SWITCH5,
51         NV10_PGRAPH_CTX_CACHE1, /* 8 values from 0x400160 to 0x40017c */
52         NV10_PGRAPH_CTX_CACHE2, /* 8 values from 0x400180 to 0x40019c */
53         NV10_PGRAPH_CTX_CACHE3, /* 8 values from 0x4001a0 to 0x4001bc */
54         NV10_PGRAPH_CTX_CACHE4, /* 8 values from 0x4001c0 to 0x4001dc */
55         NV10_PGRAPH_CTX_CACHE5, /* 8 values from 0x4001e0 to 0x4001fc */
56         0x00400164,
57         0x00400184,
58         0x004001a4,
59         0x004001c4,
60         0x004001e4,
61         0x00400168,
62         0x00400188,
63         0x004001a8,
64         0x004001c8,
65         0x004001e8,
66         0x0040016c,
67         0x0040018c,
68         0x004001ac,
69         0x004001cc,
70         0x004001ec,
71         0x00400170,
72         0x00400190,
73         0x004001b0,
74         0x004001d0,
75         0x004001f0,
76         0x00400174,
77         0x00400194,
78         0x004001b4,
79         0x004001d4,
80         0x004001f4,
81         0x00400178,
82         0x00400198,
83         0x004001b8,
84         0x004001d8,
85         0x004001f8,
86         0x0040017c,
87         0x0040019c,
88         0x004001bc,
89         0x004001dc,
90         0x004001fc,
91         NV10_PGRAPH_CTX_USER,
92         NV04_PGRAPH_DMA_START_0,
93         NV04_PGRAPH_DMA_START_1,
94         NV04_PGRAPH_DMA_LENGTH,
95         NV04_PGRAPH_DMA_MISC,
96         NV10_PGRAPH_DMA_PITCH,
97         NV04_PGRAPH_BOFFSET0,
98         NV04_PGRAPH_BBASE0,
99         NV04_PGRAPH_BLIMIT0,
100         NV04_PGRAPH_BOFFSET1,
101         NV04_PGRAPH_BBASE1,
102         NV04_PGRAPH_BLIMIT1,
103         NV04_PGRAPH_BOFFSET2,
104         NV04_PGRAPH_BBASE2,
105         NV04_PGRAPH_BLIMIT2,
106         NV04_PGRAPH_BOFFSET3,
107         NV04_PGRAPH_BBASE3,
108         NV04_PGRAPH_BLIMIT3,
109         NV04_PGRAPH_BOFFSET4,
110         NV04_PGRAPH_BBASE4,
111         NV04_PGRAPH_BLIMIT4,
112         NV04_PGRAPH_BOFFSET5,
113         NV04_PGRAPH_BBASE5,
114         NV04_PGRAPH_BLIMIT5,
115         NV04_PGRAPH_BPITCH0,
116         NV04_PGRAPH_BPITCH1,
117         NV04_PGRAPH_BPITCH2,
118         NV04_PGRAPH_BPITCH3,
119         NV04_PGRAPH_BPITCH4,
120         NV10_PGRAPH_SURFACE,
121         NV10_PGRAPH_STATE,
122         NV04_PGRAPH_BSWIZZLE2,
123         NV04_PGRAPH_BSWIZZLE5,
124         NV04_PGRAPH_BPIXEL,
125         NV10_PGRAPH_NOTIFY,
126         NV04_PGRAPH_PATT_COLOR0,
127         NV04_PGRAPH_PATT_COLOR1,
128         NV04_PGRAPH_PATT_COLORRAM, /* 64 values from 0x400900 to 0x4009fc */
129         0x00400904,
130         0x00400908,
131         0x0040090c,
132         0x00400910,
133         0x00400914,
134         0x00400918,
135         0x0040091c,
136         0x00400920,
137         0x00400924,
138         0x00400928,
139         0x0040092c,
140         0x00400930,
141         0x00400934,
142         0x00400938,
143         0x0040093c,
144         0x00400940,
145         0x00400944,
146         0x00400948,
147         0x0040094c,
148         0x00400950,
149         0x00400954,
150         0x00400958,
151         0x0040095c,
152         0x00400960,
153         0x00400964,
154         0x00400968,
155         0x0040096c,
156         0x00400970,
157         0x00400974,
158         0x00400978,
159         0x0040097c,
160         0x00400980,
161         0x00400984,
162         0x00400988,
163         0x0040098c,
164         0x00400990,
165         0x00400994,
166         0x00400998,
167         0x0040099c,
168         0x004009a0,
169         0x004009a4,
170         0x004009a8,
171         0x004009ac,
172         0x004009b0,
173         0x004009b4,
174         0x004009b8,
175         0x004009bc,
176         0x004009c0,
177         0x004009c4,
178         0x004009c8,
179         0x004009cc,
180         0x004009d0,
181         0x004009d4,
182         0x004009d8,
183         0x004009dc,
184         0x004009e0,
185         0x004009e4,
186         0x004009e8,
187         0x004009ec,
188         0x004009f0,
189         0x004009f4,
190         0x004009f8,
191         0x004009fc,
192         NV04_PGRAPH_PATTERN,    /* 2 values from 0x400808 to 0x40080c */
193         0x0040080c,
194         NV04_PGRAPH_PATTERN_SHAPE,
195         NV03_PGRAPH_MONO_COLOR0,
196         NV04_PGRAPH_ROP3,
197         NV04_PGRAPH_CHROMA,
198         NV04_PGRAPH_BETA_AND,
199         NV04_PGRAPH_BETA_PREMULT,
200         0x00400e70,
201         0x00400e74,
202         0x00400e78,
203         0x00400e7c,
204         0x00400e80,
205         0x00400e84,
206         0x00400e88,
207         0x00400e8c,
208         0x00400ea0,
209         0x00400ea4,
210         0x00400ea8,
211         0x00400e90,
212         0x00400e94,
213         0x00400e98,
214         0x00400e9c,
215         NV10_PGRAPH_WINDOWCLIP_HORIZONTAL, /* 8 values from 0x400f00-0x400f1c */
216         NV10_PGRAPH_WINDOWCLIP_VERTICAL,   /* 8 values from 0x400f20-0x400f3c */
217         0x00400f04,
218         0x00400f24,
219         0x00400f08,
220         0x00400f28,
221         0x00400f0c,
222         0x00400f2c,
223         0x00400f10,
224         0x00400f30,
225         0x00400f14,
226         0x00400f34,
227         0x00400f18,
228         0x00400f38,
229         0x00400f1c,
230         0x00400f3c,
231         NV10_PGRAPH_XFMODE0,
232         NV10_PGRAPH_XFMODE1,
233         NV10_PGRAPH_GLOBALSTATE0,
234         NV10_PGRAPH_GLOBALSTATE1,
235         NV04_PGRAPH_STORED_FMT,
236         NV04_PGRAPH_SOURCE_COLOR,
237         NV03_PGRAPH_ABS_X_RAM,  /* 32 values from 0x400400 to 0x40047c */
238         NV03_PGRAPH_ABS_Y_RAM,  /* 32 values from 0x400480 to 0x4004fc */
239         0x00400404,
240         0x00400484,
241         0x00400408,
242         0x00400488,
243         0x0040040c,
244         0x0040048c,
245         0x00400410,
246         0x00400490,
247         0x00400414,
248         0x00400494,
249         0x00400418,
250         0x00400498,
251         0x0040041c,
252         0x0040049c,
253         0x00400420,
254         0x004004a0,
255         0x00400424,
256         0x004004a4,
257         0x00400428,
258         0x004004a8,
259         0x0040042c,
260         0x004004ac,
261         0x00400430,
262         0x004004b0,
263         0x00400434,
264         0x004004b4,
265         0x00400438,
266         0x004004b8,
267         0x0040043c,
268         0x004004bc,
269         0x00400440,
270         0x004004c0,
271         0x00400444,
272         0x004004c4,
273         0x00400448,
274         0x004004c8,
275         0x0040044c,
276         0x004004cc,
277         0x00400450,
278         0x004004d0,
279         0x00400454,
280         0x004004d4,
281         0x00400458,
282         0x004004d8,
283         0x0040045c,
284         0x004004dc,
285         0x00400460,
286         0x004004e0,
287         0x00400464,
288         0x004004e4,
289         0x00400468,
290         0x004004e8,
291         0x0040046c,
292         0x004004ec,
293         0x00400470,
294         0x004004f0,
295         0x00400474,
296         0x004004f4,
297         0x00400478,
298         0x004004f8,
299         0x0040047c,
300         0x004004fc,
301         NV03_PGRAPH_ABS_UCLIP_XMIN,
302         NV03_PGRAPH_ABS_UCLIP_XMAX,
303         NV03_PGRAPH_ABS_UCLIP_YMIN,
304         NV03_PGRAPH_ABS_UCLIP_YMAX,
305         0x00400550,
306         0x00400558,
307         0x00400554,
308         0x0040055c,
309         NV03_PGRAPH_ABS_UCLIPA_XMIN,
310         NV03_PGRAPH_ABS_UCLIPA_XMAX,
311         NV03_PGRAPH_ABS_UCLIPA_YMIN,
312         NV03_PGRAPH_ABS_UCLIPA_YMAX,
313         NV03_PGRAPH_ABS_ICLIP_XMAX,
314         NV03_PGRAPH_ABS_ICLIP_YMAX,
315         NV03_PGRAPH_XY_LOGIC_MISC0,
316         NV03_PGRAPH_XY_LOGIC_MISC1,
317         NV03_PGRAPH_XY_LOGIC_MISC2,
318         NV03_PGRAPH_XY_LOGIC_MISC3,
319         NV03_PGRAPH_CLIPX_0,
320         NV03_PGRAPH_CLIPX_1,
321         NV03_PGRAPH_CLIPY_0,
322         NV03_PGRAPH_CLIPY_1,
323         NV10_PGRAPH_COMBINER0_IN_ALPHA,
324         NV10_PGRAPH_COMBINER1_IN_ALPHA,
325         NV10_PGRAPH_COMBINER0_IN_RGB,
326         NV10_PGRAPH_COMBINER1_IN_RGB,
327         NV10_PGRAPH_COMBINER_COLOR0,
328         NV10_PGRAPH_COMBINER_COLOR1,
329         NV10_PGRAPH_COMBINER0_OUT_ALPHA,
330         NV10_PGRAPH_COMBINER1_OUT_ALPHA,
331         NV10_PGRAPH_COMBINER0_OUT_RGB,
332         NV10_PGRAPH_COMBINER1_OUT_RGB,
333         NV10_PGRAPH_COMBINER_FINAL0,
334         NV10_PGRAPH_COMBINER_FINAL1,
335         0x00400e00,
336         0x00400e04,
337         0x00400e08,
338         0x00400e0c,
339         0x00400e10,
340         0x00400e14,
341         0x00400e18,
342         0x00400e1c,
343         0x00400e20,
344         0x00400e24,
345         0x00400e28,
346         0x00400e2c,
347         0x00400e30,
348         0x00400e34,
349         0x00400e38,
350         0x00400e3c,
351         NV04_PGRAPH_PASSTHRU_0,
352         NV04_PGRAPH_PASSTHRU_1,
353         NV04_PGRAPH_PASSTHRU_2,
354         NV10_PGRAPH_DIMX_TEXTURE,
355         NV10_PGRAPH_WDIMX_TEXTURE,
356         NV10_PGRAPH_DVD_COLORFMT,
357         NV10_PGRAPH_SCALED_FORMAT,
358         NV04_PGRAPH_MISC24_0,
359         NV04_PGRAPH_MISC24_1,
360         NV04_PGRAPH_MISC24_2,
361         NV03_PGRAPH_X_MISC,
362         NV03_PGRAPH_Y_MISC,
363         NV04_PGRAPH_VALID1,
364         NV04_PGRAPH_VALID2,
365 };
366
367 static int nv17_graph_ctx_regs[] = {
368         NV10_PGRAPH_DEBUG_4,
369         0x004006b0,
370         0x00400eac,
371         0x00400eb0,
372         0x00400eb4,
373         0x00400eb8,
374         0x00400ebc,
375         0x00400ec0,
376         0x00400ec4,
377         0x00400ec8,
378         0x00400ecc,
379         0x00400ed0,
380         0x00400ed4,
381         0x00400ed8,
382         0x00400edc,
383         0x00400ee0,
384         0x00400a00,
385         0x00400a04,
386 };
387
388 struct graph_state {
389         int nv10[ARRAY_SIZE(nv10_graph_ctx_regs)];
390         int nv17[ARRAY_SIZE(nv17_graph_ctx_regs)];
391         struct pipe_state pipe_state;
392         uint32_t lma_window[4];
393 };
394
395 #define PIPE_SAVE(dev, state, addr)                                     \
396         do {                                                            \
397                 int __i;                                                \
398                 nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr);           \
399                 for (__i = 0; __i < ARRAY_SIZE(state); __i++)           \
400                         state[__i] = nv_rd32(dev, NV10_PGRAPH_PIPE_DATA); \
401         } while (0)
402
403 #define PIPE_RESTORE(dev, state, addr)                                  \
404         do {                                                            \
405                 int __i;                                                \
406                 nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr);           \
407                 for (__i = 0; __i < ARRAY_SIZE(state); __i++)           \
408                         nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, state[__i]); \
409         } while (0)
410
411 static void nv10_graph_save_pipe(struct nouveau_channel *chan)
412 {
413         struct drm_device *dev = chan->dev;
414         struct graph_state *pgraph_ctx = chan->pgraph_ctx;
415         struct pipe_state *pipe = &pgraph_ctx->pipe_state;
416
417         PIPE_SAVE(dev, pipe->pipe_0x4400, 0x4400);
418         PIPE_SAVE(dev, pipe->pipe_0x0200, 0x0200);
419         PIPE_SAVE(dev, pipe->pipe_0x6400, 0x6400);
420         PIPE_SAVE(dev, pipe->pipe_0x6800, 0x6800);
421         PIPE_SAVE(dev, pipe->pipe_0x6c00, 0x6c00);
422         PIPE_SAVE(dev, pipe->pipe_0x7000, 0x7000);
423         PIPE_SAVE(dev, pipe->pipe_0x7400, 0x7400);
424         PIPE_SAVE(dev, pipe->pipe_0x7800, 0x7800);
425         PIPE_SAVE(dev, pipe->pipe_0x0040, 0x0040);
426         PIPE_SAVE(dev, pipe->pipe_0x0000, 0x0000);
427 }
428
429 static void nv10_graph_load_pipe(struct nouveau_channel *chan)
430 {
431         struct drm_device *dev = chan->dev;
432         struct graph_state *pgraph_ctx = chan->pgraph_ctx;
433         struct pipe_state *pipe = &pgraph_ctx->pipe_state;
434         uint32_t xfmode0, xfmode1;
435         int i;
436
437         nouveau_wait_for_idle(dev);
438         /* XXX check haiku comments */
439         xfmode0 = nv_rd32(dev, NV10_PGRAPH_XFMODE0);
440         xfmode1 = nv_rd32(dev, NV10_PGRAPH_XFMODE1);
441         nv_wr32(dev, NV10_PGRAPH_XFMODE0, 0x10000000);
442         nv_wr32(dev, NV10_PGRAPH_XFMODE1, 0x00000000);
443         nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0);
444         for (i = 0; i < 4; i++)
445                 nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
446         for (i = 0; i < 4; i++)
447                 nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
448
449         nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0);
450         for (i = 0; i < 3; i++)
451                 nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
452
453         nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80);
454         for (i = 0; i < 3; i++)
455                 nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
456
457         nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040);
458         nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000008);
459
460
461         PIPE_RESTORE(dev, pipe->pipe_0x0200, 0x0200);
462         nouveau_wait_for_idle(dev);
463
464         /* restore XFMODE */
465         nv_wr32(dev, NV10_PGRAPH_XFMODE0, xfmode0);
466         nv_wr32(dev, NV10_PGRAPH_XFMODE1, xfmode1);
467         PIPE_RESTORE(dev, pipe->pipe_0x6400, 0x6400);
468         PIPE_RESTORE(dev, pipe->pipe_0x6800, 0x6800);
469         PIPE_RESTORE(dev, pipe->pipe_0x6c00, 0x6c00);
470         PIPE_RESTORE(dev, pipe->pipe_0x7000, 0x7000);
471         PIPE_RESTORE(dev, pipe->pipe_0x7400, 0x7400);
472         PIPE_RESTORE(dev, pipe->pipe_0x7800, 0x7800);
473         PIPE_RESTORE(dev, pipe->pipe_0x4400, 0x4400);
474         PIPE_RESTORE(dev, pipe->pipe_0x0000, 0x0000);
475         PIPE_RESTORE(dev, pipe->pipe_0x0040, 0x0040);
476         nouveau_wait_for_idle(dev);
477 }
478
479 static void nv10_graph_create_pipe(struct nouveau_channel *chan)
480 {
481         struct drm_device *dev = chan->dev;
482         struct graph_state *pgraph_ctx = chan->pgraph_ctx;
483         struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state;
484         uint32_t *fifo_pipe_state_addr;
485         int i;
486 #define PIPE_INIT(addr) \
487         do { \
488                 fifo_pipe_state_addr = fifo_pipe_state->pipe_##addr; \
489         } while (0)
490 #define PIPE_INIT_END(addr) \
491         do { \
492                 uint32_t *__end_addr = fifo_pipe_state->pipe_##addr + \
493                                 ARRAY_SIZE(fifo_pipe_state->pipe_##addr); \
494                 if (fifo_pipe_state_addr != __end_addr) \
495                         NV_ERROR(dev, "incomplete pipe init for 0x%x :  %p/%p\n", \
496                                 addr, fifo_pipe_state_addr, __end_addr); \
497         } while (0)
498 #define NV_WRITE_PIPE_INIT(value) *(fifo_pipe_state_addr++) = value
499
500         PIPE_INIT(0x0200);
501         for (i = 0; i < 48; i++)
502                 NV_WRITE_PIPE_INIT(0x00000000);
503         PIPE_INIT_END(0x0200);
504
505         PIPE_INIT(0x6400);
506         for (i = 0; i < 211; i++)
507                 NV_WRITE_PIPE_INIT(0x00000000);
508         NV_WRITE_PIPE_INIT(0x3f800000);
509         NV_WRITE_PIPE_INIT(0x40000000);
510         NV_WRITE_PIPE_INIT(0x40000000);
511         NV_WRITE_PIPE_INIT(0x40000000);
512         NV_WRITE_PIPE_INIT(0x40000000);
513         NV_WRITE_PIPE_INIT(0x00000000);
514         NV_WRITE_PIPE_INIT(0x00000000);
515         NV_WRITE_PIPE_INIT(0x3f800000);
516         NV_WRITE_PIPE_INIT(0x00000000);
517         NV_WRITE_PIPE_INIT(0x3f000000);
518         NV_WRITE_PIPE_INIT(0x3f000000);
519         NV_WRITE_PIPE_INIT(0x00000000);
520         NV_WRITE_PIPE_INIT(0x00000000);
521         NV_WRITE_PIPE_INIT(0x00000000);
522         NV_WRITE_PIPE_INIT(0x00000000);
523         NV_WRITE_PIPE_INIT(0x3f800000);
524         NV_WRITE_PIPE_INIT(0x00000000);
525         NV_WRITE_PIPE_INIT(0x00000000);
526         NV_WRITE_PIPE_INIT(0x00000000);
527         NV_WRITE_PIPE_INIT(0x00000000);
528         NV_WRITE_PIPE_INIT(0x00000000);
529         NV_WRITE_PIPE_INIT(0x3f800000);
530         NV_WRITE_PIPE_INIT(0x3f800000);
531         NV_WRITE_PIPE_INIT(0x3f800000);
532         NV_WRITE_PIPE_INIT(0x3f800000);
533         PIPE_INIT_END(0x6400);
534
535         PIPE_INIT(0x6800);
536         for (i = 0; i < 162; i++)
537                 NV_WRITE_PIPE_INIT(0x00000000);
538         NV_WRITE_PIPE_INIT(0x3f800000);
539         for (i = 0; i < 25; i++)
540                 NV_WRITE_PIPE_INIT(0x00000000);
541         PIPE_INIT_END(0x6800);
542
543         PIPE_INIT(0x6c00);
544         NV_WRITE_PIPE_INIT(0x00000000);
545         NV_WRITE_PIPE_INIT(0x00000000);
546         NV_WRITE_PIPE_INIT(0x00000000);
547         NV_WRITE_PIPE_INIT(0x00000000);
548         NV_WRITE_PIPE_INIT(0xbf800000);
549         NV_WRITE_PIPE_INIT(0x00000000);
550         NV_WRITE_PIPE_INIT(0x00000000);
551         NV_WRITE_PIPE_INIT(0x00000000);
552         NV_WRITE_PIPE_INIT(0x00000000);
553         NV_WRITE_PIPE_INIT(0x00000000);
554         NV_WRITE_PIPE_INIT(0x00000000);
555         NV_WRITE_PIPE_INIT(0x00000000);
556         PIPE_INIT_END(0x6c00);
557
558         PIPE_INIT(0x7000);
559         NV_WRITE_PIPE_INIT(0x00000000);
560         NV_WRITE_PIPE_INIT(0x00000000);
561         NV_WRITE_PIPE_INIT(0x00000000);
562         NV_WRITE_PIPE_INIT(0x00000000);
563         NV_WRITE_PIPE_INIT(0x00000000);
564         NV_WRITE_PIPE_INIT(0x00000000);
565         NV_WRITE_PIPE_INIT(0x00000000);
566         NV_WRITE_PIPE_INIT(0x00000000);
567         NV_WRITE_PIPE_INIT(0x00000000);
568         NV_WRITE_PIPE_INIT(0x00000000);
569         NV_WRITE_PIPE_INIT(0x00000000);
570         NV_WRITE_PIPE_INIT(0x00000000);
571         NV_WRITE_PIPE_INIT(0x7149f2ca);
572         NV_WRITE_PIPE_INIT(0x00000000);
573         NV_WRITE_PIPE_INIT(0x00000000);
574         NV_WRITE_PIPE_INIT(0x00000000);
575         NV_WRITE_PIPE_INIT(0x7149f2ca);
576         NV_WRITE_PIPE_INIT(0x00000000);
577         NV_WRITE_PIPE_INIT(0x00000000);
578         NV_WRITE_PIPE_INIT(0x00000000);
579         NV_WRITE_PIPE_INIT(0x7149f2ca);
580         NV_WRITE_PIPE_INIT(0x00000000);
581         NV_WRITE_PIPE_INIT(0x00000000);
582         NV_WRITE_PIPE_INIT(0x00000000);
583         NV_WRITE_PIPE_INIT(0x7149f2ca);
584         NV_WRITE_PIPE_INIT(0x00000000);
585         NV_WRITE_PIPE_INIT(0x00000000);
586         NV_WRITE_PIPE_INIT(0x00000000);
587         NV_WRITE_PIPE_INIT(0x7149f2ca);
588         NV_WRITE_PIPE_INIT(0x00000000);
589         NV_WRITE_PIPE_INIT(0x00000000);
590         NV_WRITE_PIPE_INIT(0x00000000);
591         NV_WRITE_PIPE_INIT(0x7149f2ca);
592         NV_WRITE_PIPE_INIT(0x00000000);
593         NV_WRITE_PIPE_INIT(0x00000000);
594         NV_WRITE_PIPE_INIT(0x00000000);
595         NV_WRITE_PIPE_INIT(0x7149f2ca);
596         NV_WRITE_PIPE_INIT(0x00000000);
597         NV_WRITE_PIPE_INIT(0x00000000);
598         NV_WRITE_PIPE_INIT(0x00000000);
599         NV_WRITE_PIPE_INIT(0x7149f2ca);
600         for (i = 0; i < 35; i++)
601                 NV_WRITE_PIPE_INIT(0x00000000);
602         PIPE_INIT_END(0x7000);
603
604         PIPE_INIT(0x7400);
605         for (i = 0; i < 48; i++)
606                 NV_WRITE_PIPE_INIT(0x00000000);
607         PIPE_INIT_END(0x7400);
608
609         PIPE_INIT(0x7800);
610         for (i = 0; i < 48; i++)
611                 NV_WRITE_PIPE_INIT(0x00000000);
612         PIPE_INIT_END(0x7800);
613
614         PIPE_INIT(0x4400);
615         for (i = 0; i < 32; i++)
616                 NV_WRITE_PIPE_INIT(0x00000000);
617         PIPE_INIT_END(0x4400);
618
619         PIPE_INIT(0x0000);
620         for (i = 0; i < 16; i++)
621                 NV_WRITE_PIPE_INIT(0x00000000);
622         PIPE_INIT_END(0x0000);
623
624         PIPE_INIT(0x0040);
625         for (i = 0; i < 4; i++)
626                 NV_WRITE_PIPE_INIT(0x00000000);
627         PIPE_INIT_END(0x0040);
628
629 #undef PIPE_INIT
630 #undef PIPE_INIT_END
631 #undef NV_WRITE_PIPE_INIT
632 }
633
634 static int nv10_graph_ctx_regs_find_offset(struct drm_device *dev, int reg)
635 {
636         int i;
637         for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++) {
638                 if (nv10_graph_ctx_regs[i] == reg)
639                         return i;
640         }
641         NV_ERROR(dev, "unknow offset nv10_ctx_regs %d\n", reg);
642         return -1;
643 }
644
645 static int nv17_graph_ctx_regs_find_offset(struct drm_device *dev, int reg)
646 {
647         int i;
648         for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++) {
649                 if (nv17_graph_ctx_regs[i] == reg)
650                         return i;
651         }
652         NV_ERROR(dev, "unknow offset nv17_ctx_regs %d\n", reg);
653         return -1;
654 }
655
656 int nv10_graph_load_context(struct nouveau_channel *chan)
657 {
658         struct drm_device *dev = chan->dev;
659         struct drm_nouveau_private *dev_priv = dev->dev_private;
660         struct graph_state *pgraph_ctx = chan->pgraph_ctx;
661         uint32_t tmp;
662         int i;
663
664         for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++)
665                 nv_wr32(dev, nv10_graph_ctx_regs[i], pgraph_ctx->nv10[i]);
666         if (dev_priv->chipset >= 0x17) {
667                 for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++)
668                         nv_wr32(dev, nv17_graph_ctx_regs[i],
669                                                 pgraph_ctx->nv17[i]);
670         }
671
672         nv10_graph_load_pipe(chan);
673
674         nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100);
675         tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER);
676         nv_wr32(dev, NV10_PGRAPH_CTX_USER, (tmp & 0xffffff) | chan->id << 24);
677         tmp = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2);
678         nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, tmp & 0xcfffffff);
679         return 0;
680 }
681
682 int
683 nv10_graph_unload_context(struct drm_device *dev)
684 {
685         struct drm_nouveau_private *dev_priv = dev->dev_private;
686         struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
687         struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
688         struct nouveau_channel *chan;
689         struct graph_state *ctx;
690         uint32_t tmp;
691         int i;
692
693         chan = pgraph->channel(dev);
694         if (!chan)
695                 return 0;
696         ctx = chan->pgraph_ctx;
697
698         for (i = 0; i < ARRAY_SIZE(nv10_graph_ctx_regs); i++)
699                 ctx->nv10[i] = nv_rd32(dev, nv10_graph_ctx_regs[i]);
700
701         if (dev_priv->chipset >= 0x17) {
702                 for (i = 0; i < ARRAY_SIZE(nv17_graph_ctx_regs); i++)
703                         ctx->nv17[i] = nv_rd32(dev, nv17_graph_ctx_regs[i]);
704         }
705
706         nv10_graph_save_pipe(chan);
707
708         nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000000);
709         tmp  = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff;
710         tmp |= (pfifo->channels - 1) << 24;
711         nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp);
712         return 0;
713 }
714
715 void
716 nv10_graph_context_switch(struct drm_device *dev)
717 {
718         struct drm_nouveau_private *dev_priv = dev->dev_private;
719         struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
720         struct nouveau_channel *chan = NULL;
721         int chid;
722
723         pgraph->fifo_access(dev, false);
724         nouveau_wait_for_idle(dev);
725
726         /* If previous context is valid, we need to save it */
727         nv10_graph_unload_context(dev);
728
729         /* Load context for next channel */
730         chid = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 20) & 0x1f;
731         chan = dev_priv->fifos[chid];
732         if (chan)
733                 nv10_graph_load_context(chan);
734
735         pgraph->fifo_access(dev, true);
736 }
737
738 #define NV_WRITE_CTX(reg, val) do { \
739         int offset = nv10_graph_ctx_regs_find_offset(dev, reg); \
740         if (offset > 0) \
741                 pgraph_ctx->nv10[offset] = val; \
742         } while (0)
743
744 #define NV17_WRITE_CTX(reg, val) do { \
745         int offset = nv17_graph_ctx_regs_find_offset(dev, reg); \
746         if (offset > 0) \
747                 pgraph_ctx->nv17[offset] = val; \
748         } while (0)
749
750 struct nouveau_channel *
751 nv10_graph_channel(struct drm_device *dev)
752 {
753         struct drm_nouveau_private *dev_priv = dev->dev_private;
754         int chid = dev_priv->engine.fifo.channels;
755
756         if (nv_rd32(dev, NV10_PGRAPH_CTX_CONTROL) & 0x00010000)
757                 chid = nv_rd32(dev, NV10_PGRAPH_CTX_USER) >> 24;
758
759         if (chid >= dev_priv->engine.fifo.channels)
760                 return NULL;
761
762         return dev_priv->fifos[chid];
763 }
764
765 int nv10_graph_create_context(struct nouveau_channel *chan)
766 {
767         struct drm_device *dev = chan->dev;
768         struct drm_nouveau_private *dev_priv = dev->dev_private;
769         struct graph_state *pgraph_ctx;
770
771         NV_DEBUG(dev, "nv10_graph_context_create %d\n", chan->id);
772
773         chan->pgraph_ctx = pgraph_ctx = kzalloc(sizeof(*pgraph_ctx),
774                                                 GFP_KERNEL);
775         if (pgraph_ctx == NULL)
776                 return -ENOMEM;
777
778
779         NV_WRITE_CTX(0x00400e88, 0x08000000);
780         NV_WRITE_CTX(0x00400e9c, 0x4b7fffff);
781         NV_WRITE_CTX(NV03_PGRAPH_XY_LOGIC_MISC0, 0x0001ffff);
782         NV_WRITE_CTX(0x00400e10, 0x00001000);
783         NV_WRITE_CTX(0x00400e14, 0x00001000);
784         NV_WRITE_CTX(0x00400e30, 0x00080008);
785         NV_WRITE_CTX(0x00400e34, 0x00080008);
786         if (dev_priv->chipset >= 0x17) {
787                 /* is it really needed ??? */
788                 NV17_WRITE_CTX(NV10_PGRAPH_DEBUG_4,
789                                         nv_rd32(dev, NV10_PGRAPH_DEBUG_4));
790                 NV17_WRITE_CTX(0x004006b0, nv_rd32(dev, 0x004006b0));
791                 NV17_WRITE_CTX(0x00400eac, 0x0fff0000);
792                 NV17_WRITE_CTX(0x00400eb0, 0x0fff0000);
793                 NV17_WRITE_CTX(0x00400ec0, 0x00000080);
794                 NV17_WRITE_CTX(0x00400ed0, 0x00000080);
795         }
796         NV_WRITE_CTX(NV10_PGRAPH_CTX_USER, chan->id << 24);
797
798         nv10_graph_create_pipe(chan);
799         return 0;
800 }
801
802 void nv10_graph_destroy_context(struct nouveau_channel *chan)
803 {
804         struct graph_state *pgraph_ctx = chan->pgraph_ctx;
805
806         kfree(pgraph_ctx);
807         chan->pgraph_ctx = NULL;
808 }
809
810 void
811 nv10_graph_set_region_tiling(struct drm_device *dev, int i, uint32_t addr,
812                              uint32_t size, uint32_t pitch)
813 {
814         uint32_t limit = max(1u, addr + size) - 1;
815
816         if (pitch)
817                 addr |= 1 << 31;
818
819         nv_wr32(dev, NV10_PGRAPH_TLIMIT(i), limit);
820         nv_wr32(dev, NV10_PGRAPH_TSIZE(i), pitch);
821         nv_wr32(dev, NV10_PGRAPH_TILE(i), addr);
822 }
823
824 int nv10_graph_init(struct drm_device *dev)
825 {
826         struct drm_nouveau_private *dev_priv = dev->dev_private;
827         uint32_t tmp;
828         int i;
829
830         nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
831                         ~NV_PMC_ENABLE_PGRAPH);
832         nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |
833                          NV_PMC_ENABLE_PGRAPH);
834
835         nv_wr32(dev, NV03_PGRAPH_INTR   , 0xFFFFFFFF);
836         nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
837
838         nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
839         nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x00000000);
840         nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x00118700);
841         /* nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x24E00810); */ /* 0x25f92ad9 */
842         nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x25f92ad9);
843         nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0x55DE0830 |
844                                       (1<<29) |
845                                       (1<<31));
846         if (dev_priv->chipset >= 0x17) {
847                 nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x1f000000);
848                 nv_wr32(dev, 0x400a10, 0x3ff3fb6);
849                 nv_wr32(dev, 0x400838, 0x2f8684);
850                 nv_wr32(dev, 0x40083c, 0x115f3f);
851                 nv_wr32(dev, 0x004006b0, 0x40000020);
852         } else
853                 nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000);
854
855         /* Turn all the tiling regions off. */
856         for (i = 0; i < NV10_PFB_TILE__SIZE; i++)
857                 nv10_graph_set_region_tiling(dev, i, 0, 0, 0);
858
859         nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH1, 0x00000000);
860         nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH2, 0x00000000);
861         nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH3, 0x00000000);
862         nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH4, 0x00000000);
863         nv_wr32(dev, NV10_PGRAPH_STATE      , 0xFFFFFFFF);
864
865         tmp  = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff;
866         tmp |= (dev_priv->engine.fifo.channels - 1) << 24;
867         nv_wr32(dev, NV10_PGRAPH_CTX_USER, tmp);
868         nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10000100);
869         nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, 0x08000000);
870
871         return 0;
872 }
873
874 void nv10_graph_takedown(struct drm_device *dev)
875 {
876 }
877
878 static int
879 nv17_graph_mthd_lma_window(struct nouveau_channel *chan, int grclass,
880                            int mthd, uint32_t data)
881 {
882         struct drm_device *dev = chan->dev;
883         struct graph_state *ctx = chan->pgraph_ctx;
884         struct pipe_state *pipe = &ctx->pipe_state;
885         struct drm_nouveau_private *dev_priv = dev->dev_private;
886         struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
887         uint32_t pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3];
888         uint32_t xfmode0, xfmode1;
889         int i;
890
891         ctx->lma_window[(mthd - 0x1638) / 4] = data;
892
893         if (mthd != 0x1644)
894                 return 0;
895
896         nouveau_wait_for_idle(dev);
897
898         PIPE_SAVE(dev, pipe_0x0040, 0x0040);
899         PIPE_SAVE(dev, pipe->pipe_0x0200, 0x0200);
900
901         PIPE_RESTORE(dev, ctx->lma_window, 0x6790);
902
903         nouveau_wait_for_idle(dev);
904
905         xfmode0 = nv_rd32(dev, NV10_PGRAPH_XFMODE0);
906         xfmode1 = nv_rd32(dev, NV10_PGRAPH_XFMODE1);
907
908         PIPE_SAVE(dev, pipe->pipe_0x4400, 0x4400);
909         PIPE_SAVE(dev, pipe_0x64c0, 0x64c0);
910         PIPE_SAVE(dev, pipe_0x6ab0, 0x6ab0);
911         PIPE_SAVE(dev, pipe_0x6a80, 0x6a80);
912
913         nouveau_wait_for_idle(dev);
914
915         nv_wr32(dev, NV10_PGRAPH_XFMODE0, 0x10000000);
916         nv_wr32(dev, NV10_PGRAPH_XFMODE1, 0x00000000);
917         nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0);
918         for (i = 0; i < 4; i++)
919                 nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
920         for (i = 0; i < 4; i++)
921                 nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
922
923         nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0);
924         for (i = 0; i < 3; i++)
925                 nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000);
926
927         nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80);
928         for (i = 0; i < 3; i++)
929                 nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
930
931         nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040);
932         nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000008);
933
934         PIPE_RESTORE(dev, pipe->pipe_0x0200, 0x0200);
935
936         nouveau_wait_for_idle(dev);
937
938         PIPE_RESTORE(dev, pipe_0x0040, 0x0040);
939
940         nv_wr32(dev, NV10_PGRAPH_XFMODE0, xfmode0);
941         nv_wr32(dev, NV10_PGRAPH_XFMODE1, xfmode1);
942
943         PIPE_RESTORE(dev, pipe_0x64c0, 0x64c0);
944         PIPE_RESTORE(dev, pipe_0x6ab0, 0x6ab0);
945         PIPE_RESTORE(dev, pipe_0x6a80, 0x6a80);
946         PIPE_RESTORE(dev, pipe->pipe_0x4400, 0x4400);
947
948         nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000000c0);
949         nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000);
950
951         nouveau_wait_for_idle(dev);
952
953         pgraph->fifo_access(dev, true);
954
955         return 0;
956 }
957
958 static int
959 nv17_graph_mthd_lma_enable(struct nouveau_channel *chan, int grclass,
960                            int mthd, uint32_t data)
961 {
962         struct drm_device *dev = chan->dev;
963         struct drm_nouveau_private *dev_priv = dev->dev_private;
964         struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
965
966         nouveau_wait_for_idle(dev);
967
968         nv_wr32(dev, NV10_PGRAPH_DEBUG_4,
969                 nv_rd32(dev, NV10_PGRAPH_DEBUG_4) | 0x1 << 8);
970         nv_wr32(dev, 0x004006b0,
971                 nv_rd32(dev, 0x004006b0) | 0x8 << 24);
972
973         pgraph->fifo_access(dev, true);
974
975         return 0;
976 }
977
978 static struct nouveau_pgraph_object_method nv17_graph_celsius_mthds[] = {
979         { 0x1638, nv17_graph_mthd_lma_window },
980         { 0x163c, nv17_graph_mthd_lma_window },
981         { 0x1640, nv17_graph_mthd_lma_window },
982         { 0x1644, nv17_graph_mthd_lma_window },
983         { 0x1658, nv17_graph_mthd_lma_enable },
984         {}
985 };
986
987 struct nouveau_pgraph_object_class nv10_graph_grclass[] = {
988         { 0x0030, false, NULL }, /* null */
989         { 0x0039, false, NULL }, /* m2mf */
990         { 0x004a, false, NULL }, /* gdirect */
991         { 0x005f, false, NULL }, /* imageblit */
992         { 0x009f, false, NULL }, /* imageblit (nv12) */
993         { 0x008a, false, NULL }, /* ifc */
994         { 0x0089, false, NULL }, /* sifm */
995         { 0x0062, false, NULL }, /* surf2d */
996         { 0x0043, false, NULL }, /* rop */
997         { 0x0012, false, NULL }, /* beta1 */
998         { 0x0072, false, NULL }, /* beta4 */
999         { 0x0019, false, NULL }, /* cliprect */
1000         { 0x0044, false, NULL }, /* pattern */
1001         { 0x0052, false, NULL }, /* swzsurf */
1002         { 0x0093, false, NULL }, /* surf3d */
1003         { 0x0094, false, NULL }, /* tex_tri */
1004         { 0x0095, false, NULL }, /* multitex_tri */
1005         { 0x0056, false, NULL }, /* celcius (nv10) */
1006         { 0x0096, false, NULL }, /* celcius (nv11) */
1007         { 0x0099, false, nv17_graph_celsius_mthds }, /* celcius (nv17) */
1008         {}
1009 };