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
32struct 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
45static int nv10_graph_ctx_regs [] = {
46NV10_PGRAPH_CTX_SWITCH1,
47NV10_PGRAPH_CTX_SWITCH2,
48NV10_PGRAPH_CTX_SWITCH3,
49NV10_PGRAPH_CTX_SWITCH4,
50NV10_PGRAPH_CTX_SWITCH5,
51NV10_PGRAPH_CTX_CACHE1,	/* 8 values from 0x400160 to 0x40017c */
52NV10_PGRAPH_CTX_CACHE2,	/* 8 values from 0x400180 to 0x40019c */
53NV10_PGRAPH_CTX_CACHE3,	/* 8 values from 0x4001a0 to 0x4001bc */
54NV10_PGRAPH_CTX_CACHE4,	/* 8 values from 0x4001c0 to 0x4001dc */
55NV10_PGRAPH_CTX_CACHE5,	/* 8 values from 0x4001e0 to 0x4001fc */
560x00400164,
570x00400184,
580x004001a4,
590x004001c4,
600x004001e4,
610x00400168,
620x00400188,
630x004001a8,
640x004001c8,
650x004001e8,
660x0040016c,
670x0040018c,
680x004001ac,
690x004001cc,
700x004001ec,
710x00400170,
720x00400190,
730x004001b0,
740x004001d0,
750x004001f0,
760x00400174,
770x00400194,
780x004001b4,
790x004001d4,
800x004001f4,
810x00400178,
820x00400198,
830x004001b8,
840x004001d8,
850x004001f8,
860x0040017c,
870x0040019c,
880x004001bc,
890x004001dc,
900x004001fc,
91NV10_PGRAPH_CTX_USER,
92NV04_PGRAPH_DMA_START_0,
93NV04_PGRAPH_DMA_START_1,
94NV04_PGRAPH_DMA_LENGTH,
95NV04_PGRAPH_DMA_MISC,
96NV10_PGRAPH_DMA_PITCH,
97NV04_PGRAPH_BOFFSET0,
98NV04_PGRAPH_BBASE0,
99NV04_PGRAPH_BLIMIT0,
100NV04_PGRAPH_BOFFSET1,
101NV04_PGRAPH_BBASE1,
102NV04_PGRAPH_BLIMIT1,
103NV04_PGRAPH_BOFFSET2,
104NV04_PGRAPH_BBASE2,
105NV04_PGRAPH_BLIMIT2,
106NV04_PGRAPH_BOFFSET3,
107NV04_PGRAPH_BBASE3,
108NV04_PGRAPH_BLIMIT3,
109NV04_PGRAPH_BOFFSET4,
110NV04_PGRAPH_BBASE4,
111NV04_PGRAPH_BLIMIT4,
112NV04_PGRAPH_BOFFSET5,
113NV04_PGRAPH_BBASE5,
114NV04_PGRAPH_BLIMIT5,
115NV04_PGRAPH_BPITCH0,
116NV04_PGRAPH_BPITCH1,
117NV04_PGRAPH_BPITCH2,
118NV04_PGRAPH_BPITCH3,
119NV04_PGRAPH_BPITCH4,
120NV10_PGRAPH_SURFACE,
121NV10_PGRAPH_STATE,
122NV04_PGRAPH_BSWIZZLE2,
123NV04_PGRAPH_BSWIZZLE5,
124NV04_PGRAPH_BPIXEL,
125NV10_PGRAPH_NOTIFY,
126NV04_PGRAPH_PATT_COLOR0,
127NV04_PGRAPH_PATT_COLOR1,
128NV04_PGRAPH_PATT_COLORRAM, /* 64 values from 0x400900 to 0x4009fc */
1290x00400904,
1300x00400908,
1310x0040090c,
1320x00400910,
1330x00400914,
1340x00400918,
1350x0040091c,
1360x00400920,
1370x00400924,
1380x00400928,
1390x0040092c,
1400x00400930,
1410x00400934,
1420x00400938,
1430x0040093c,
1440x00400940,
1450x00400944,
1460x00400948,
1470x0040094c,
1480x00400950,
1490x00400954,
1500x00400958,
1510x0040095c,
1520x00400960,
1530x00400964,
1540x00400968,
1550x0040096c,
1560x00400970,
1570x00400974,
1580x00400978,
1590x0040097c,
1600x00400980,
1610x00400984,
1620x00400988,
1630x0040098c,
1640x00400990,
1650x00400994,
1660x00400998,
1670x0040099c,
1680x004009a0,
1690x004009a4,
1700x004009a8,
1710x004009ac,
1720x004009b0,
1730x004009b4,
1740x004009b8,
1750x004009bc,
1760x004009c0,
1770x004009c4,
1780x004009c8,
1790x004009cc,
1800x004009d0,
1810x004009d4,
1820x004009d8,
1830x004009dc,
1840x004009e0,
1850x004009e4,
1860x004009e8,
1870x004009ec,
1880x004009f0,
1890x004009f4,
1900x004009f8,
1910x004009fc,
192NV04_PGRAPH_PATTERN,	/* 2 values from 0x400808 to 0x40080c */
1930x0040080c,
194NV04_PGRAPH_PATTERN_SHAPE,
195NV03_PGRAPH_MONO_COLOR0,
196NV04_PGRAPH_ROP3,
197NV04_PGRAPH_CHROMA,
198NV04_PGRAPH_BETA_AND,
199NV04_PGRAPH_BETA_PREMULT,
2000x00400e70,
2010x00400e74,
2020x00400e78,
2030x00400e7c,
2040x00400e80,
2050x00400e84,
2060x00400e88,
2070x00400e8c,
2080x00400ea0,
2090x00400ea4,
2100x00400ea8,
2110x00400e90,
2120x00400e94,
2130x00400e98,
2140x00400e9c,
215NV10_PGRAPH_WINDOWCLIP_HORIZONTAL, /* 8 values from 0x400f00 to 0x400f1c */
216NV10_PGRAPH_WINDOWCLIP_VERTICAL,   /* 8 values from 0x400f20 to 0x400f3c */
2170x00400f04,
2180x00400f24,
2190x00400f08,
2200x00400f28,
2210x00400f0c,
2220x00400f2c,
2230x00400f10,
2240x00400f30,
2250x00400f14,
2260x00400f34,
2270x00400f18,
2280x00400f38,
2290x00400f1c,
2300x00400f3c,
231NV10_PGRAPH_XFMODE0,
232NV10_PGRAPH_XFMODE1,
233NV10_PGRAPH_GLOBALSTATE0,
234NV10_PGRAPH_GLOBALSTATE1,
235NV04_PGRAPH_STORED_FMT,
236NV04_PGRAPH_SOURCE_COLOR,
237NV03_PGRAPH_ABS_X_RAM,	/* 32 values from 0x400400 to 0x40047c */
238NV03_PGRAPH_ABS_Y_RAM,	/* 32 values from 0x400480 to 0x4004fc */
2390x00400404,
2400x00400484,
2410x00400408,
2420x00400488,
2430x0040040c,
2440x0040048c,
2450x00400410,
2460x00400490,
2470x00400414,
2480x00400494,
2490x00400418,
2500x00400498,
2510x0040041c,
2520x0040049c,
2530x00400420,
2540x004004a0,
2550x00400424,
2560x004004a4,
2570x00400428,
2580x004004a8,
2590x0040042c,
2600x004004ac,
2610x00400430,
2620x004004b0,
2630x00400434,
2640x004004b4,
2650x00400438,
2660x004004b8,
2670x0040043c,
2680x004004bc,
2690x00400440,
2700x004004c0,
2710x00400444,
2720x004004c4,
2730x00400448,
2740x004004c8,
2750x0040044c,
2760x004004cc,
2770x00400450,
2780x004004d0,
2790x00400454,
2800x004004d4,
2810x00400458,
2820x004004d8,
2830x0040045c,
2840x004004dc,
2850x00400460,
2860x004004e0,
2870x00400464,
2880x004004e4,
2890x00400468,
2900x004004e8,
2910x0040046c,
2920x004004ec,
2930x00400470,
2940x004004f0,
2950x00400474,
2960x004004f4,
2970x00400478,
2980x004004f8,
2990x0040047c,
3000x004004fc,
301NV03_PGRAPH_ABS_UCLIP_XMIN,
302NV03_PGRAPH_ABS_UCLIP_XMAX,
303NV03_PGRAPH_ABS_UCLIP_YMIN,
304NV03_PGRAPH_ABS_UCLIP_YMAX,
3050x00400550,
3060x00400558,
3070x00400554,
3080x0040055c,
309NV03_PGRAPH_ABS_UCLIPA_XMIN,
310NV03_PGRAPH_ABS_UCLIPA_XMAX,
311NV03_PGRAPH_ABS_UCLIPA_YMIN,
312NV03_PGRAPH_ABS_UCLIPA_YMAX,
313NV03_PGRAPH_ABS_ICLIP_XMAX,
314NV03_PGRAPH_ABS_ICLIP_YMAX,
315NV03_PGRAPH_XY_LOGIC_MISC0,
316NV03_PGRAPH_XY_LOGIC_MISC1,
317NV03_PGRAPH_XY_LOGIC_MISC2,
318NV03_PGRAPH_XY_LOGIC_MISC3,
319NV03_PGRAPH_CLIPX_0,
320NV03_PGRAPH_CLIPX_1,
321NV03_PGRAPH_CLIPY_0,
322NV03_PGRAPH_CLIPY_1,
323NV10_PGRAPH_COMBINER0_IN_ALPHA,
324NV10_PGRAPH_COMBINER1_IN_ALPHA,
325NV10_PGRAPH_COMBINER0_IN_RGB,
326NV10_PGRAPH_COMBINER1_IN_RGB,
327NV10_PGRAPH_COMBINER_COLOR0,
328NV10_PGRAPH_COMBINER_COLOR1,
329NV10_PGRAPH_COMBINER0_OUT_ALPHA,
330NV10_PGRAPH_COMBINER1_OUT_ALPHA,
331NV10_PGRAPH_COMBINER0_OUT_RGB,
332NV10_PGRAPH_COMBINER1_OUT_RGB,
333NV10_PGRAPH_COMBINER_FINAL0,
334NV10_PGRAPH_COMBINER_FINAL1,
3350x00400e00,
3360x00400e04,
3370x00400e08,
3380x00400e0c,
3390x00400e10,
3400x00400e14,
3410x00400e18,
3420x00400e1c,
3430x00400e20,
3440x00400e24,
3450x00400e28,
3460x00400e2c,
3470x00400e30,
3480x00400e34,
3490x00400e38,
3500x00400e3c,
351NV04_PGRAPH_PASSTHRU_0,
352NV04_PGRAPH_PASSTHRU_1,
353NV04_PGRAPH_PASSTHRU_2,
354NV10_PGRAPH_DIMX_TEXTURE,
355NV10_PGRAPH_WDIMX_TEXTURE,
356NV10_PGRAPH_DVD_COLORFMT,
357NV10_PGRAPH_SCALED_FORMAT,
358NV04_PGRAPH_MISC24_0,
359NV04_PGRAPH_MISC24_1,
360NV04_PGRAPH_MISC24_2,
361NV03_PGRAPH_X_MISC,
362NV03_PGRAPH_Y_MISC,
363NV04_PGRAPH_VALID1,
364NV04_PGRAPH_VALID2,
365};
366
367static int nv17_graph_ctx_regs [] = {
368NV10_PGRAPH_DEBUG_4,
3690x004006b0,
3700x00400eac,
3710x00400eb0,
3720x00400eb4,
3730x00400eb8,
3740x00400ebc,
3750x00400ec0,
3760x00400ec4,
3770x00400ec8,
3780x00400ecc,
3790x00400ed0,
3800x00400ed4,
3810x00400ed8,
3820x00400edc,
3830x00400ee0,
3840x00400a00,
3850x00400a04,
386};
387
388struct 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
394static 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
421static 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
480static 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
632static 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
643static 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
654int 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
673int 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
692void 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
766int 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
830void 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
866int 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
912void nv10_graph_takedown(struct drm_device *dev)
913{
914}
915