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