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