OSDN Git Service

Merge branch 'master' into vblank-rework, including mach64 support
[android-x86/external-libdrm.git] / shared-core / 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 to 0x400f1c */
216 NV10_PGRAPH_WINDOWCLIP_VERTICAL,   /* 8 values from 0x400f20 to 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[sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0])];
390         int nv17[sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0])];
391         struct pipe_state pipe_state;
392 };
393
394 static void nv10_graph_save_pipe(struct nouveau_channel *chan) {
395         struct drm_device *dev = chan->dev;
396         struct drm_nouveau_private *dev_priv = dev->dev_private;
397         struct graph_state* pgraph_ctx = chan->pgraph_ctx;
398         struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state;
399         int i;
400 #define PIPE_SAVE(addr) \
401         do { \
402                 NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, addr); \
403                 for (i=0; i < sizeof(fifo_pipe_state->pipe_##addr)/sizeof(fifo_pipe_state->pipe_##addr[0]); i++) \
404                         fifo_pipe_state->pipe_##addr[i] = NV_READ(NV10_PGRAPH_PIPE_DATA); \
405         } while (0)
406
407         PIPE_SAVE(0x4400);
408         PIPE_SAVE(0x0200);
409         PIPE_SAVE(0x6400);
410         PIPE_SAVE(0x6800);
411         PIPE_SAVE(0x6c00);
412         PIPE_SAVE(0x7000);
413         PIPE_SAVE(0x7400);
414         PIPE_SAVE(0x7800);
415         PIPE_SAVE(0x0040);
416         PIPE_SAVE(0x0000);
417
418 #undef PIPE_SAVE
419 }
420
421 static void nv10_graph_load_pipe(struct nouveau_channel *chan) {
422         struct drm_device *dev = chan->dev;
423         struct drm_nouveau_private *dev_priv = dev->dev_private;
424         struct graph_state* pgraph_ctx = chan->pgraph_ctx;
425         struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state;
426         int i;
427         uint32_t xfmode0, xfmode1;
428 #define PIPE_RESTORE(addr) \
429         do { \
430                 NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, addr); \
431                 for (i=0; i < sizeof(fifo_pipe_state->pipe_##addr)/sizeof(fifo_pipe_state->pipe_##addr[0]); i++) \
432                         NV_WRITE(NV10_PGRAPH_PIPE_DATA, fifo_pipe_state->pipe_##addr[i]); \
433         } while (0)
434
435
436         nouveau_wait_for_idle(dev);
437         /* XXX check haiku comments */
438         xfmode0 = NV_READ(NV10_PGRAPH_XFMODE0);
439         xfmode1 = NV_READ(NV10_PGRAPH_XFMODE1);
440         NV_WRITE(NV10_PGRAPH_XFMODE0, 0x10000000);
441         NV_WRITE(NV10_PGRAPH_XFMODE1, 0x00000000);
442         NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0);
443         for (i = 0; i < 4; i++)
444                 NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000);
445         for (i = 0; i < 4; i++)
446                 NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
447
448         NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0);
449         for (i = 0; i < 3; i++)
450                 NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x3f800000);
451
452         NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80);
453         for (i = 0; i < 3; i++)
454                 NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000000);
455
456         NV_WRITE(NV10_PGRAPH_PIPE_ADDRESS, 0x00000040);
457         NV_WRITE(NV10_PGRAPH_PIPE_DATA, 0x00000008);
458
459
460         PIPE_RESTORE(0x0200);
461         nouveau_wait_for_idle(dev);
462
463         /* restore XFMODE */
464         NV_WRITE(NV10_PGRAPH_XFMODE0, xfmode0);
465         NV_WRITE(NV10_PGRAPH_XFMODE1, xfmode1);
466         PIPE_RESTORE(0x6400);
467         PIPE_RESTORE(0x6800);
468         PIPE_RESTORE(0x6c00);
469         PIPE_RESTORE(0x7000);
470         PIPE_RESTORE(0x7400);
471         PIPE_RESTORE(0x7800);
472         PIPE_RESTORE(0x4400);
473         PIPE_RESTORE(0x0000);
474         PIPE_RESTORE(0x0040);
475         nouveau_wait_for_idle(dev);
476
477 #undef PIPE_RESTORE
478 }
479
480 static void nv10_graph_create_pipe(struct nouveau_channel *chan) {
481         struct graph_state* pgraph_ctx = chan->pgraph_ctx;
482         struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state;
483         uint32_t *fifo_pipe_state_addr;
484         int i;
485 #define PIPE_INIT(addr) \
486         do { \
487                 fifo_pipe_state_addr = fifo_pipe_state->pipe_##addr; \
488         } while (0)
489 #define PIPE_INIT_END(addr) \
490         do { \
491                 if (fifo_pipe_state_addr != \
492                                 sizeof(fifo_pipe_state->pipe_##addr)/sizeof(fifo_pipe_state->pipe_##addr[0]) + fifo_pipe_state->pipe_##addr) \
493                         DRM_ERROR("incomplete pipe init for 0x%x :  %p/%p\n", addr, fifo_pipe_state_addr, \
494                                         sizeof(fifo_pipe_state->pipe_##addr)/sizeof(fifo_pipe_state->pipe_##addr[0]) + fifo_pipe_state->pipe_##addr); \
495         } while (0)
496 #define NV_WRITE_PIPE_INIT(value) *(fifo_pipe_state_addr++) = value
497
498         PIPE_INIT(0x0200);
499         for (i = 0; i < 48; i++)
500                 NV_WRITE_PIPE_INIT(0x00000000);
501         PIPE_INIT_END(0x0200);
502
503         PIPE_INIT(0x6400);
504         for (i = 0; i < 211; i++)
505                 NV_WRITE_PIPE_INIT(0x00000000);
506         NV_WRITE_PIPE_INIT(0x3f800000);
507         NV_WRITE_PIPE_INIT(0x40000000);
508         NV_WRITE_PIPE_INIT(0x40000000);
509         NV_WRITE_PIPE_INIT(0x40000000);
510         NV_WRITE_PIPE_INIT(0x40000000);
511         NV_WRITE_PIPE_INIT(0x00000000);
512         NV_WRITE_PIPE_INIT(0x00000000);
513         NV_WRITE_PIPE_INIT(0x3f800000);
514         NV_WRITE_PIPE_INIT(0x00000000);
515         NV_WRITE_PIPE_INIT(0x3f000000);
516         NV_WRITE_PIPE_INIT(0x3f000000);
517         NV_WRITE_PIPE_INIT(0x00000000);
518         NV_WRITE_PIPE_INIT(0x00000000);
519         NV_WRITE_PIPE_INIT(0x00000000);
520         NV_WRITE_PIPE_INIT(0x00000000);
521         NV_WRITE_PIPE_INIT(0x3f800000);
522         NV_WRITE_PIPE_INIT(0x00000000);
523         NV_WRITE_PIPE_INIT(0x00000000);
524         NV_WRITE_PIPE_INIT(0x00000000);
525         NV_WRITE_PIPE_INIT(0x00000000);
526         NV_WRITE_PIPE_INIT(0x00000000);
527         NV_WRITE_PIPE_INIT(0x3f800000);
528         NV_WRITE_PIPE_INIT(0x3f800000);
529         NV_WRITE_PIPE_INIT(0x3f800000);
530         NV_WRITE_PIPE_INIT(0x3f800000);
531         PIPE_INIT_END(0x6400);
532
533         PIPE_INIT(0x6800);
534         for (i = 0; i < 162; i++)
535                 NV_WRITE_PIPE_INIT(0x00000000);
536         NV_WRITE_PIPE_INIT(0x3f800000);
537         for (i = 0; i < 25; i++)
538                 NV_WRITE_PIPE_INIT(0x00000000);
539         PIPE_INIT_END(0x6800);
540
541         PIPE_INIT(0x6c00);
542         NV_WRITE_PIPE_INIT(0x00000000);
543         NV_WRITE_PIPE_INIT(0x00000000);
544         NV_WRITE_PIPE_INIT(0x00000000);
545         NV_WRITE_PIPE_INIT(0x00000000);
546         NV_WRITE_PIPE_INIT(0xbf800000);
547         NV_WRITE_PIPE_INIT(0x00000000);
548         NV_WRITE_PIPE_INIT(0x00000000);
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         PIPE_INIT_END(0x6c00);
555
556         PIPE_INIT(0x7000);
557         NV_WRITE_PIPE_INIT(0x00000000);
558         NV_WRITE_PIPE_INIT(0x00000000);
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(0x7149f2ca);
570         NV_WRITE_PIPE_INIT(0x00000000);
571         NV_WRITE_PIPE_INIT(0x00000000);
572         NV_WRITE_PIPE_INIT(0x00000000);
573         NV_WRITE_PIPE_INIT(0x7149f2ca);
574         NV_WRITE_PIPE_INIT(0x00000000);
575         NV_WRITE_PIPE_INIT(0x00000000);
576         NV_WRITE_PIPE_INIT(0x00000000);
577         NV_WRITE_PIPE_INIT(0x7149f2ca);
578         NV_WRITE_PIPE_INIT(0x00000000);
579         NV_WRITE_PIPE_INIT(0x00000000);
580         NV_WRITE_PIPE_INIT(0x00000000);
581         NV_WRITE_PIPE_INIT(0x7149f2ca);
582         NV_WRITE_PIPE_INIT(0x00000000);
583         NV_WRITE_PIPE_INIT(0x00000000);
584         NV_WRITE_PIPE_INIT(0x00000000);
585         NV_WRITE_PIPE_INIT(0x7149f2ca);
586         NV_WRITE_PIPE_INIT(0x00000000);
587         NV_WRITE_PIPE_INIT(0x00000000);
588         NV_WRITE_PIPE_INIT(0x00000000);
589         NV_WRITE_PIPE_INIT(0x7149f2ca);
590         NV_WRITE_PIPE_INIT(0x00000000);
591         NV_WRITE_PIPE_INIT(0x00000000);
592         NV_WRITE_PIPE_INIT(0x00000000);
593         NV_WRITE_PIPE_INIT(0x7149f2ca);
594         NV_WRITE_PIPE_INIT(0x00000000);
595         NV_WRITE_PIPE_INIT(0x00000000);
596         NV_WRITE_PIPE_INIT(0x00000000);
597         NV_WRITE_PIPE_INIT(0x7149f2ca);
598         for (i = 0; i < 35; i++)
599                 NV_WRITE_PIPE_INIT(0x00000000);
600         PIPE_INIT_END(0x7000);
601
602         PIPE_INIT(0x7400);
603         for (i = 0; i < 48; i++)
604                 NV_WRITE_PIPE_INIT(0x00000000);
605         PIPE_INIT_END(0x7400);
606
607         PIPE_INIT(0x7800);
608         for (i = 0; i < 48; i++)
609                 NV_WRITE_PIPE_INIT(0x00000000);
610         PIPE_INIT_END(0x7800);
611
612         PIPE_INIT(0x4400);
613         for (i = 0; i < 32; i++)
614                 NV_WRITE_PIPE_INIT(0x00000000);
615         PIPE_INIT_END(0x4400);
616
617         PIPE_INIT(0x0000);
618         for (i = 0; i < 16; i++)
619                 NV_WRITE_PIPE_INIT(0x00000000);
620         PIPE_INIT_END(0x0000);
621
622         PIPE_INIT(0x0040);
623         for (i = 0; i < 4; i++)
624                 NV_WRITE_PIPE_INIT(0x00000000);
625         PIPE_INIT_END(0x0040);
626
627 #undef PIPE_INIT
628 #undef PIPE_INIT_END
629 #undef NV_WRITE_PIPE_INIT
630 }
631
632 static int nv10_graph_ctx_regs_find_offset(struct drm_device *dev, int reg)
633 {
634         int i;
635         for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++) {
636                 if (nv10_graph_ctx_regs[i] == reg)
637                         return i;
638         }
639         DRM_ERROR("unknow offset nv10_ctx_regs %d\n", reg);
640         return -1;
641 }
642
643 static int nv17_graph_ctx_regs_find_offset(struct drm_device *dev, int reg)
644 {
645         int i;
646         for (i = 0; i < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++) {
647                 if (nv17_graph_ctx_regs[i] == reg)
648                         return i;
649         }
650         DRM_ERROR("unknow offset nv17_ctx_regs %d\n", reg);
651         return -1;
652 }
653
654 int nv10_graph_load_context(struct nouveau_channel *chan)
655 {
656         struct drm_device *dev = chan->dev;
657         struct drm_nouveau_private *dev_priv = dev->dev_private;
658         struct graph_state* pgraph_ctx = chan->pgraph_ctx;
659         int i;
660
661         for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++)
662                 NV_WRITE(nv10_graph_ctx_regs[i], pgraph_ctx->nv10[i]);
663         if (dev_priv->chipset>=0x17) {
664                 for (i = 0; i < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++)
665                         NV_WRITE(nv17_graph_ctx_regs[i], pgraph_ctx->nv17[i]);
666         }
667
668         nv10_graph_load_pipe(chan);
669
670         return 0;
671 }
672
673 int nv10_graph_save_context(struct nouveau_channel *chan)
674 {
675         struct drm_device *dev = chan->dev;
676         struct drm_nouveau_private *dev_priv = dev->dev_private;
677         struct graph_state* pgraph_ctx = chan->pgraph_ctx;
678         int i;
679
680         for (i = 0; i < sizeof(nv10_graph_ctx_regs)/sizeof(nv10_graph_ctx_regs[0]); i++)
681                 pgraph_ctx->nv10[i] = NV_READ(nv10_graph_ctx_regs[i]);
682         if (dev_priv->chipset>=0x17) {
683                 for (i = 0; i < sizeof(nv17_graph_ctx_regs)/sizeof(nv17_graph_ctx_regs[0]); i++)
684                         pgraph_ctx->nv17[i] = NV_READ(nv17_graph_ctx_regs[i]);
685         }
686
687         nv10_graph_save_pipe(chan);
688
689         return 0;
690 }
691
692 void nouveau_nv10_context_switch(struct drm_device *dev)
693 {
694         struct drm_nouveau_private *dev_priv;
695         struct nouveau_engine *engine;
696         struct nouveau_channel *next, *last;
697         int chid;
698
699         if (!dev) {
700                 DRM_DEBUG("Invalid drm_device\n");
701                 return;
702         }
703         dev_priv = dev->dev_private;
704         if (!dev_priv) {
705                 DRM_DEBUG("Invalid drm_nouveau_private\n");
706                 return;
707         }
708         if (!dev_priv->fifos) {
709                 DRM_DEBUG("Invalid drm_nouveau_private->fifos\n");
710                 return;
711         }
712         engine = &dev_priv->Engine;
713
714         chid = (NV_READ(NV04_PGRAPH_TRAPPED_ADDR) >> 20) &
715                 (engine->fifo.channels - 1);
716         next = dev_priv->fifos[chid];
717
718         if (!next) {
719                 DRM_ERROR("Invalid next channel\n");
720                 return;
721         }
722
723         chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & 
724                 (engine->fifo.channels - 1);
725         last = dev_priv->fifos[chid];
726
727         if (!last) {
728                 DRM_INFO("WARNING: Invalid last channel, switch to %x\n",
729                           next->id);
730         } else {
731                 DRM_DEBUG("NV: PGRAPH context switch interrupt channel %x -> %x\n",
732                          last->id, next->id);
733         }
734
735         NV_WRITE(NV04_PGRAPH_FIFO,0x0);
736         if (last) {
737                 nouveau_wait_for_idle(dev);
738                 nv10_graph_save_context(last);
739         }
740
741         nouveau_wait_for_idle(dev);
742
743         NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10000000);
744
745         nouveau_wait_for_idle(dev);
746
747         nv10_graph_load_context(next);
748
749         NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100);
750         NV_WRITE(NV10_PGRAPH_FFINTFC_ST2, NV_READ(NV10_PGRAPH_FFINTFC_ST2)&0xCFFFFFFF);
751         NV_WRITE(NV04_PGRAPH_FIFO,0x1);
752 }
753
754 #define NV_WRITE_CTX(reg, val) do { \
755         int offset = nv10_graph_ctx_regs_find_offset(dev, reg); \
756         if (offset > 0) \
757                 pgraph_ctx->nv10[offset] = val; \
758         } while (0)
759
760 #define NV17_WRITE_CTX(reg, val) do { \
761         int offset = nv17_graph_ctx_regs_find_offset(dev, reg); \
762         if (offset > 0) \
763                 pgraph_ctx->nv17[offset] = val; \
764         } while (0)
765
766 int nv10_graph_create_context(struct nouveau_channel *chan) {
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         DRM_DEBUG("nv10_graph_context_create %d\n", chan->id);
772
773         chan->pgraph_ctx = pgraph_ctx = drm_calloc(1, sizeof(*pgraph_ctx),
774                                               DRM_MEM_DRIVER);
775
776         if (pgraph_ctx == NULL)
777                 return -ENOMEM;
778
779         /* mmio trace suggest that should be done in ddx with methods/objects */
780 #if 0
781         uint32_t tmp, vramsz;
782         /* per channel init from ddx */
783         tmp = NV_READ(NV10_PGRAPH_SURFACE) & 0x0007ff00;
784         /*XXX the original ddx code, does this in 2 steps :
785          * tmp = NV_READ(NV10_PGRAPH_SURFACE) & 0x0007ff00;
786          * NV_WRITE(NV10_PGRAPH_SURFACE, tmp);
787          * tmp = NV_READ(NV10_PGRAPH_SURFACE) | 0x00020100;
788          * NV_WRITE(NV10_PGRAPH_SURFACE, tmp);
789          */
790         tmp |= 0x00020100;
791         NV_WRITE_CTX(NV10_PGRAPH_SURFACE, tmp);
792
793         vramsz = drm_get_resource_len(dev, 0) - 1;
794         NV_WRITE_CTX(NV04_PGRAPH_BOFFSET0, 0);
795         NV_WRITE_CTX(NV04_PGRAPH_BOFFSET1, 0);
796         NV_WRITE_CTX(NV04_PGRAPH_BLIMIT0 , vramsz);
797         NV_WRITE_CTX(NV04_PGRAPH_BLIMIT1 , vramsz);
798
799         NV_WRITE_CTX(NV04_PGRAPH_PATTERN_SHAPE, 0x00000000);
800         NV_WRITE_CTX(NV04_PGRAPH_BETA_AND     , 0xFFFFFFFF);
801
802         NV_WRITE_CTX(NV03_PGRAPH_ABS_UCLIP_XMIN, 0);
803         NV_WRITE_CTX(NV03_PGRAPH_ABS_UCLIP_YMIN, 0);
804         NV_WRITE_CTX(NV03_PGRAPH_ABS_UCLIP_XMAX, 0x7fff);
805         NV_WRITE_CTX(NV03_PGRAPH_ABS_UCLIP_YMAX, 0x7fff);
806 #endif
807
808         NV_WRITE_CTX(0x00400e88, 0x08000000);
809         NV_WRITE_CTX(0x00400e9c, 0x4b7fffff);
810         NV_WRITE_CTX(NV03_PGRAPH_XY_LOGIC_MISC0, 0x0001ffff);
811         NV_WRITE_CTX(0x00400e10, 0x00001000);
812         NV_WRITE_CTX(0x00400e14, 0x00001000);
813         NV_WRITE_CTX(0x00400e30, 0x00080008);
814         NV_WRITE_CTX(0x00400e34, 0x00080008);
815         if (dev_priv->chipset>=0x17) {
816                 /* is it really needed ??? */
817                 NV17_WRITE_CTX(NV10_PGRAPH_DEBUG_4, NV_READ(NV10_PGRAPH_DEBUG_4));
818                 NV17_WRITE_CTX(0x004006b0, NV_READ(0x004006b0));
819                 NV17_WRITE_CTX(0x00400eac, 0x0fff0000);
820                 NV17_WRITE_CTX(0x00400eb0, 0x0fff0000);
821                 NV17_WRITE_CTX(0x00400ec0, 0x00000080);
822                 NV17_WRITE_CTX(0x00400ed0, 0x00000080);
823         }
824         NV_WRITE_CTX(NV10_PGRAPH_CTX_USER, chan->id << 24);
825
826         nv10_graph_create_pipe(chan);
827         return 0;
828 }
829
830 void nv10_graph_destroy_context(struct nouveau_channel *chan)
831 {
832         struct drm_device *dev = chan->dev;
833         struct drm_nouveau_private *dev_priv = dev->dev_private;
834         struct nouveau_engine *engine = &dev_priv->Engine;
835         struct graph_state* pgraph_ctx = chan->pgraph_ctx;
836         int chid;
837
838         drm_free(pgraph_ctx, sizeof(*pgraph_ctx), DRM_MEM_DRIVER);
839         chan->pgraph_ctx = NULL;
840
841         chid = (NV_READ(NV10_PGRAPH_CTX_USER) >> 24) & (engine->fifo.channels - 1);
842
843         /* This code seems to corrupt the 3D pipe, but blob seems to do similar things ????
844          */
845 #if 0
846         /* does this avoid a potential context switch while we are written graph
847          * reg, or we should mask graph interrupt ???
848          */
849         NV_WRITE(NV04_PGRAPH_FIFO,0x0);
850         if (chid == chan->id) {
851                 DRM_INFO("cleanning a channel with graph in current context\n");
852                 nouveau_wait_for_idle(dev);
853                 DRM_INFO("reseting current graph context\n");
854                 /* can't be call here because of dynamic mem alloc */
855                 //nv10_graph_create_context(chan);
856                 nv10_graph_load_context(chan);
857         }
858         NV_WRITE(NV04_PGRAPH_FIFO, 0x1);
859 #else
860         if (chid == chan->id) {
861                 DRM_INFO("cleanning a channel with graph in current context\n");
862         }
863 #endif
864 }
865
866 int nv10_graph_init(struct drm_device *dev) {
867         struct drm_nouveau_private *dev_priv = dev->dev_private;
868         int i;
869
870         NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) &
871                         ~NV_PMC_ENABLE_PGRAPH);
872         NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) |
873                          NV_PMC_ENABLE_PGRAPH);
874
875         NV_WRITE(NV03_PGRAPH_INTR   , 0xFFFFFFFF);
876         NV_WRITE(NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
877
878         NV_WRITE(NV04_PGRAPH_DEBUG_0, 0xFFFFFFFF);
879         NV_WRITE(NV04_PGRAPH_DEBUG_0, 0x00000000);
880         NV_WRITE(NV04_PGRAPH_DEBUG_1, 0x00118700);
881         //NV_WRITE(NV04_PGRAPH_DEBUG_2, 0x24E00810); /* 0x25f92ad9 */
882         NV_WRITE(NV04_PGRAPH_DEBUG_2, 0x25f92ad9);
883         NV_WRITE(NV04_PGRAPH_DEBUG_3, 0x55DE0830 |
884                                       (1<<29) |
885                                       (1<<31));
886         if (dev_priv->chipset>=0x17) {
887                 NV_WRITE(NV10_PGRAPH_DEBUG_4, 0x1f000000);
888                 NV_WRITE(0x004006b0, 0x40000020);
889         }
890         else
891                 NV_WRITE(NV10_PGRAPH_DEBUG_4, 0x00000000);
892
893         /* copy tile info from PFB */
894         for (i=0; i<NV10_PFB_TILE__SIZE; i++) {
895                 NV_WRITE(NV10_PGRAPH_TILE(i), NV_READ(NV10_PFB_TILE(i)));
896                 NV_WRITE(NV10_PGRAPH_TLIMIT(i), NV_READ(NV10_PFB_TLIMIT(i)));
897                 NV_WRITE(NV10_PGRAPH_TSIZE(i), NV_READ(NV10_PFB_TSIZE(i)));
898                 NV_WRITE(NV10_PGRAPH_TSTATUS(i), NV_READ(NV10_PFB_TSTATUS(i)));
899         }
900
901         NV_WRITE(NV10_PGRAPH_CTX_SWITCH1, 0x00000000);
902         NV_WRITE(NV10_PGRAPH_CTX_SWITCH2, 0x00000000);
903         NV_WRITE(NV10_PGRAPH_CTX_SWITCH3, 0x00000000);
904         NV_WRITE(NV10_PGRAPH_CTX_SWITCH4, 0x00000000);
905         NV_WRITE(NV10_PGRAPH_CTX_CONTROL, 0x10010100);
906         NV_WRITE(NV10_PGRAPH_STATE      , 0xFFFFFFFF);
907         NV_WRITE(NV04_PGRAPH_FIFO       , 0x00000001);
908
909         return 0;
910 }
911
912 void nv10_graph_takedown(struct drm_device *dev)
913 {
914 }