• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/gpu/drm/nouveau/
1/*
2 * Copyright 2007 Stephane Marchesin
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
30static uint32_t nv04_graph_ctx_regs[] = {
31	0x0040053c,
32	0x00400544,
33	0x00400540,
34	0x00400548,
35	NV04_PGRAPH_CTX_SWITCH1,
36	NV04_PGRAPH_CTX_SWITCH2,
37	NV04_PGRAPH_CTX_SWITCH3,
38	NV04_PGRAPH_CTX_SWITCH4,
39	NV04_PGRAPH_CTX_CACHE1,
40	NV04_PGRAPH_CTX_CACHE2,
41	NV04_PGRAPH_CTX_CACHE3,
42	NV04_PGRAPH_CTX_CACHE4,
43	0x00400184,
44	0x004001a4,
45	0x004001c4,
46	0x004001e4,
47	0x00400188,
48	0x004001a8,
49	0x004001c8,
50	0x004001e8,
51	0x0040018c,
52	0x004001ac,
53	0x004001cc,
54	0x004001ec,
55	0x00400190,
56	0x004001b0,
57	0x004001d0,
58	0x004001f0,
59	0x00400194,
60	0x004001b4,
61	0x004001d4,
62	0x004001f4,
63	0x00400198,
64	0x004001b8,
65	0x004001d8,
66	0x004001f8,
67	0x0040019c,
68	0x004001bc,
69	0x004001dc,
70	0x004001fc,
71	0x00400174,
72	NV04_PGRAPH_DMA_START_0,
73	NV04_PGRAPH_DMA_START_1,
74	NV04_PGRAPH_DMA_LENGTH,
75	NV04_PGRAPH_DMA_MISC,
76	NV04_PGRAPH_DMA_PITCH,
77	NV04_PGRAPH_BOFFSET0,
78	NV04_PGRAPH_BBASE0,
79	NV04_PGRAPH_BLIMIT0,
80	NV04_PGRAPH_BOFFSET1,
81	NV04_PGRAPH_BBASE1,
82	NV04_PGRAPH_BLIMIT1,
83	NV04_PGRAPH_BOFFSET2,
84	NV04_PGRAPH_BBASE2,
85	NV04_PGRAPH_BLIMIT2,
86	NV04_PGRAPH_BOFFSET3,
87	NV04_PGRAPH_BBASE3,
88	NV04_PGRAPH_BLIMIT3,
89	NV04_PGRAPH_BOFFSET4,
90	NV04_PGRAPH_BBASE4,
91	NV04_PGRAPH_BLIMIT4,
92	NV04_PGRAPH_BOFFSET5,
93	NV04_PGRAPH_BBASE5,
94	NV04_PGRAPH_BLIMIT5,
95	NV04_PGRAPH_BPITCH0,
96	NV04_PGRAPH_BPITCH1,
97	NV04_PGRAPH_BPITCH2,
98	NV04_PGRAPH_BPITCH3,
99	NV04_PGRAPH_BPITCH4,
100	NV04_PGRAPH_SURFACE,
101	NV04_PGRAPH_STATE,
102	NV04_PGRAPH_BSWIZZLE2,
103	NV04_PGRAPH_BSWIZZLE5,
104	NV04_PGRAPH_BPIXEL,
105	NV04_PGRAPH_NOTIFY,
106	NV04_PGRAPH_PATT_COLOR0,
107	NV04_PGRAPH_PATT_COLOR1,
108	NV04_PGRAPH_PATT_COLORRAM+0x00,
109	NV04_PGRAPH_PATT_COLORRAM+0x04,
110	NV04_PGRAPH_PATT_COLORRAM+0x08,
111	NV04_PGRAPH_PATT_COLORRAM+0x0c,
112	NV04_PGRAPH_PATT_COLORRAM+0x10,
113	NV04_PGRAPH_PATT_COLORRAM+0x14,
114	NV04_PGRAPH_PATT_COLORRAM+0x18,
115	NV04_PGRAPH_PATT_COLORRAM+0x1c,
116	NV04_PGRAPH_PATT_COLORRAM+0x20,
117	NV04_PGRAPH_PATT_COLORRAM+0x24,
118	NV04_PGRAPH_PATT_COLORRAM+0x28,
119	NV04_PGRAPH_PATT_COLORRAM+0x2c,
120	NV04_PGRAPH_PATT_COLORRAM+0x30,
121	NV04_PGRAPH_PATT_COLORRAM+0x34,
122	NV04_PGRAPH_PATT_COLORRAM+0x38,
123	NV04_PGRAPH_PATT_COLORRAM+0x3c,
124	NV04_PGRAPH_PATT_COLORRAM+0x40,
125	NV04_PGRAPH_PATT_COLORRAM+0x44,
126	NV04_PGRAPH_PATT_COLORRAM+0x48,
127	NV04_PGRAPH_PATT_COLORRAM+0x4c,
128	NV04_PGRAPH_PATT_COLORRAM+0x50,
129	NV04_PGRAPH_PATT_COLORRAM+0x54,
130	NV04_PGRAPH_PATT_COLORRAM+0x58,
131	NV04_PGRAPH_PATT_COLORRAM+0x5c,
132	NV04_PGRAPH_PATT_COLORRAM+0x60,
133	NV04_PGRAPH_PATT_COLORRAM+0x64,
134	NV04_PGRAPH_PATT_COLORRAM+0x68,
135	NV04_PGRAPH_PATT_COLORRAM+0x6c,
136	NV04_PGRAPH_PATT_COLORRAM+0x70,
137	NV04_PGRAPH_PATT_COLORRAM+0x74,
138	NV04_PGRAPH_PATT_COLORRAM+0x78,
139	NV04_PGRAPH_PATT_COLORRAM+0x7c,
140	NV04_PGRAPH_PATT_COLORRAM+0x80,
141	NV04_PGRAPH_PATT_COLORRAM+0x84,
142	NV04_PGRAPH_PATT_COLORRAM+0x88,
143	NV04_PGRAPH_PATT_COLORRAM+0x8c,
144	NV04_PGRAPH_PATT_COLORRAM+0x90,
145	NV04_PGRAPH_PATT_COLORRAM+0x94,
146	NV04_PGRAPH_PATT_COLORRAM+0x98,
147	NV04_PGRAPH_PATT_COLORRAM+0x9c,
148	NV04_PGRAPH_PATT_COLORRAM+0xa0,
149	NV04_PGRAPH_PATT_COLORRAM+0xa4,
150	NV04_PGRAPH_PATT_COLORRAM+0xa8,
151	NV04_PGRAPH_PATT_COLORRAM+0xac,
152	NV04_PGRAPH_PATT_COLORRAM+0xb0,
153	NV04_PGRAPH_PATT_COLORRAM+0xb4,
154	NV04_PGRAPH_PATT_COLORRAM+0xb8,
155	NV04_PGRAPH_PATT_COLORRAM+0xbc,
156	NV04_PGRAPH_PATT_COLORRAM+0xc0,
157	NV04_PGRAPH_PATT_COLORRAM+0xc4,
158	NV04_PGRAPH_PATT_COLORRAM+0xc8,
159	NV04_PGRAPH_PATT_COLORRAM+0xcc,
160	NV04_PGRAPH_PATT_COLORRAM+0xd0,
161	NV04_PGRAPH_PATT_COLORRAM+0xd4,
162	NV04_PGRAPH_PATT_COLORRAM+0xd8,
163	NV04_PGRAPH_PATT_COLORRAM+0xdc,
164	NV04_PGRAPH_PATT_COLORRAM+0xe0,
165	NV04_PGRAPH_PATT_COLORRAM+0xe4,
166	NV04_PGRAPH_PATT_COLORRAM+0xe8,
167	NV04_PGRAPH_PATT_COLORRAM+0xec,
168	NV04_PGRAPH_PATT_COLORRAM+0xf0,
169	NV04_PGRAPH_PATT_COLORRAM+0xf4,
170	NV04_PGRAPH_PATT_COLORRAM+0xf8,
171	NV04_PGRAPH_PATT_COLORRAM+0xfc,
172	NV04_PGRAPH_PATTERN,
173	0x0040080c,
174	NV04_PGRAPH_PATTERN_SHAPE,
175	0x00400600,
176	NV04_PGRAPH_ROP3,
177	NV04_PGRAPH_CHROMA,
178	NV04_PGRAPH_BETA_AND,
179	NV04_PGRAPH_BETA_PREMULT,
180	NV04_PGRAPH_CONTROL0,
181	NV04_PGRAPH_CONTROL1,
182	NV04_PGRAPH_CONTROL2,
183	NV04_PGRAPH_BLEND,
184	NV04_PGRAPH_STORED_FMT,
185	NV04_PGRAPH_SOURCE_COLOR,
186	0x00400560,
187	0x00400568,
188	0x00400564,
189	0x0040056c,
190	0x00400400,
191	0x00400480,
192	0x00400404,
193	0x00400484,
194	0x00400408,
195	0x00400488,
196	0x0040040c,
197	0x0040048c,
198	0x00400410,
199	0x00400490,
200	0x00400414,
201	0x00400494,
202	0x00400418,
203	0x00400498,
204	0x0040041c,
205	0x0040049c,
206	0x00400420,
207	0x004004a0,
208	0x00400424,
209	0x004004a4,
210	0x00400428,
211	0x004004a8,
212	0x0040042c,
213	0x004004ac,
214	0x00400430,
215	0x004004b0,
216	0x00400434,
217	0x004004b4,
218	0x00400438,
219	0x004004b8,
220	0x0040043c,
221	0x004004bc,
222	0x00400440,
223	0x004004c0,
224	0x00400444,
225	0x004004c4,
226	0x00400448,
227	0x004004c8,
228	0x0040044c,
229	0x004004cc,
230	0x00400450,
231	0x004004d0,
232	0x00400454,
233	0x004004d4,
234	0x00400458,
235	0x004004d8,
236	0x0040045c,
237	0x004004dc,
238	0x00400460,
239	0x004004e0,
240	0x00400464,
241	0x004004e4,
242	0x00400468,
243	0x004004e8,
244	0x0040046c,
245	0x004004ec,
246	0x00400470,
247	0x004004f0,
248	0x00400474,
249	0x004004f4,
250	0x00400478,
251	0x004004f8,
252	0x0040047c,
253	0x004004fc,
254	0x00400534,
255	0x00400538,
256	0x00400514,
257	0x00400518,
258	0x0040051c,
259	0x00400520,
260	0x00400524,
261	0x00400528,
262	0x0040052c,
263	0x00400530,
264	0x00400d00,
265	0x00400d40,
266	0x00400d80,
267	0x00400d04,
268	0x00400d44,
269	0x00400d84,
270	0x00400d08,
271	0x00400d48,
272	0x00400d88,
273	0x00400d0c,
274	0x00400d4c,
275	0x00400d8c,
276	0x00400d10,
277	0x00400d50,
278	0x00400d90,
279	0x00400d14,
280	0x00400d54,
281	0x00400d94,
282	0x00400d18,
283	0x00400d58,
284	0x00400d98,
285	0x00400d1c,
286	0x00400d5c,
287	0x00400d9c,
288	0x00400d20,
289	0x00400d60,
290	0x00400da0,
291	0x00400d24,
292	0x00400d64,
293	0x00400da4,
294	0x00400d28,
295	0x00400d68,
296	0x00400da8,
297	0x00400d2c,
298	0x00400d6c,
299	0x00400dac,
300	0x00400d30,
301	0x00400d70,
302	0x00400db0,
303	0x00400d34,
304	0x00400d74,
305	0x00400db4,
306	0x00400d38,
307	0x00400d78,
308	0x00400db8,
309	0x00400d3c,
310	0x00400d7c,
311	0x00400dbc,
312	0x00400590,
313	0x00400594,
314	0x00400598,
315	0x0040059c,
316	0x004005a8,
317	0x004005ac,
318	0x004005b0,
319	0x004005b4,
320	0x004005c0,
321	0x004005c4,
322	0x004005c8,
323	0x004005cc,
324	0x004005d0,
325	0x004005d4,
326	0x004005d8,
327	0x004005dc,
328	0x004005e0,
329	NV04_PGRAPH_PASSTHRU_0,
330	NV04_PGRAPH_PASSTHRU_1,
331	NV04_PGRAPH_PASSTHRU_2,
332	NV04_PGRAPH_DVD_COLORFMT,
333	NV04_PGRAPH_SCALED_FORMAT,
334	NV04_PGRAPH_MISC24_0,
335	NV04_PGRAPH_MISC24_1,
336	NV04_PGRAPH_MISC24_2,
337	0x00400500,
338	0x00400504,
339	NV04_PGRAPH_VALID1,
340	NV04_PGRAPH_VALID2,
341	NV04_PGRAPH_DEBUG_3
342};
343
344struct graph_state {
345	uint32_t nv04[ARRAY_SIZE(nv04_graph_ctx_regs)];
346};
347
348struct nouveau_channel *
349nv04_graph_channel(struct drm_device *dev)
350{
351	struct drm_nouveau_private *dev_priv = dev->dev_private;
352	int chid = dev_priv->engine.fifo.channels;
353
354	if (nv_rd32(dev, NV04_PGRAPH_CTX_CONTROL) & 0x00010000)
355		chid = nv_rd32(dev, NV04_PGRAPH_CTX_USER) >> 24;
356
357	if (chid >= dev_priv->engine.fifo.channels)
358		return NULL;
359
360	return dev_priv->fifos[chid];
361}
362
363void
364nv04_graph_context_switch(struct drm_device *dev)
365{
366	struct drm_nouveau_private *dev_priv = dev->dev_private;
367	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
368	struct nouveau_channel *chan = NULL;
369	int chid;
370
371	pgraph->fifo_access(dev, false);
372	nouveau_wait_for_idle(dev);
373
374	/* If previous context is valid, we need to save it */
375	pgraph->unload_context(dev);
376
377	/* Load context for next channel */
378	chid = dev_priv->engine.fifo.channel_id(dev);
379	chan = dev_priv->fifos[chid];
380	if (chan)
381		nv04_graph_load_context(chan);
382
383	pgraph->fifo_access(dev, true);
384}
385
386static uint32_t *ctx_reg(struct graph_state *ctx, uint32_t reg)
387{
388	int i;
389
390	for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++) {
391		if (nv04_graph_ctx_regs[i] == reg)
392			return &ctx->nv04[i];
393	}
394
395	return NULL;
396}
397
398int nv04_graph_create_context(struct nouveau_channel *chan)
399{
400	struct graph_state *pgraph_ctx;
401	NV_DEBUG(chan->dev, "nv04_graph_context_create %d\n", chan->id);
402
403	chan->pgraph_ctx = pgraph_ctx = kzalloc(sizeof(*pgraph_ctx),
404						GFP_KERNEL);
405	if (pgraph_ctx == NULL)
406		return -ENOMEM;
407
408	*ctx_reg(pgraph_ctx, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31;
409
410	return 0;
411}
412
413void nv04_graph_destroy_context(struct nouveau_channel *chan)
414{
415	struct graph_state *pgraph_ctx = chan->pgraph_ctx;
416
417	kfree(pgraph_ctx);
418	chan->pgraph_ctx = NULL;
419}
420
421int nv04_graph_load_context(struct nouveau_channel *chan)
422{
423	struct drm_device *dev = chan->dev;
424	struct graph_state *pgraph_ctx = chan->pgraph_ctx;
425	uint32_t tmp;
426	int i;
427
428	for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++)
429		nv_wr32(dev, nv04_graph_ctx_regs[i], pgraph_ctx->nv04[i]);
430
431	nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL, 0x10010100);
432
433	tmp  = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff;
434	nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp | chan->id << 24);
435
436	tmp = nv_rd32(dev, NV04_PGRAPH_FFINTFC_ST2);
437	nv_wr32(dev, NV04_PGRAPH_FFINTFC_ST2, tmp & 0x000fffff);
438
439	return 0;
440}
441
442int
443nv04_graph_unload_context(struct drm_device *dev)
444{
445	struct drm_nouveau_private *dev_priv = dev->dev_private;
446	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
447	struct nouveau_channel *chan = NULL;
448	struct graph_state *ctx;
449	uint32_t tmp;
450	int i;
451
452	chan = pgraph->channel(dev);
453	if (!chan)
454		return 0;
455	ctx = chan->pgraph_ctx;
456
457	for (i = 0; i < ARRAY_SIZE(nv04_graph_ctx_regs); i++)
458		ctx->nv04[i] = nv_rd32(dev, nv04_graph_ctx_regs[i]);
459
460	nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL, 0x10000000);
461	tmp  = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff;
462	tmp |= (dev_priv->engine.fifo.channels - 1) << 24;
463	nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp);
464	return 0;
465}
466
467int nv04_graph_init(struct drm_device *dev)
468{
469	struct drm_nouveau_private *dev_priv = dev->dev_private;
470	uint32_t tmp;
471
472	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) &
473			~NV_PMC_ENABLE_PGRAPH);
474	nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) |
475			 NV_PMC_ENABLE_PGRAPH);
476
477	/* Enable PGRAPH interrupts */
478	nv_wr32(dev, NV03_PGRAPH_INTR, 0xFFFFFFFF);
479	nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0xFFFFFFFF);
480
481	nv_wr32(dev, NV04_PGRAPH_VALID1, 0);
482	nv_wr32(dev, NV04_PGRAPH_VALID2, 0);
483	/*nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x000001FF);
484	nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x001FFFFF);*/
485	nv_wr32(dev, NV04_PGRAPH_DEBUG_0, 0x1231c000);
486	/*1231C000 blob, 001 haiku*/
487	//*V_WRITE(NV04_PGRAPH_DEBUG_1, 0xf2d91100);*/
488	nv_wr32(dev, NV04_PGRAPH_DEBUG_1, 0x72111100);
489	/*0x72111100 blob , 01 haiku*/
490	/*nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x11d5f870);*/
491	nv_wr32(dev, NV04_PGRAPH_DEBUG_2, 0x11d5f071);
492	/*haiku same*/
493
494	/*nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xfad4ff31);*/
495	nv_wr32(dev, NV04_PGRAPH_DEBUG_3, 0xf0d4ff31);
496	/*haiku and blob 10d4*/
497
498	nv_wr32(dev, NV04_PGRAPH_STATE        , 0xFFFFFFFF);
499	nv_wr32(dev, NV04_PGRAPH_CTX_CONTROL  , 0x10000100);
500	tmp  = nv_rd32(dev, NV04_PGRAPH_CTX_USER) & 0x00ffffff;
501	tmp |= (dev_priv->engine.fifo.channels - 1) << 24;
502	nv_wr32(dev, NV04_PGRAPH_CTX_USER, tmp);
503
504	/* These don't belong here, they're part of a per-channel context */
505	nv_wr32(dev, NV04_PGRAPH_PATTERN_SHAPE, 0x00000000);
506	nv_wr32(dev, NV04_PGRAPH_BETA_AND     , 0xFFFFFFFF);
507
508	return 0;
509}
510
511void nv04_graph_takedown(struct drm_device *dev)
512{
513}
514
515void
516nv04_graph_fifo_access(struct drm_device *dev, bool enabled)
517{
518	if (enabled)
519		nv_wr32(dev, NV04_PGRAPH_FIFO,
520					nv_rd32(dev, NV04_PGRAPH_FIFO) | 1);
521	else
522		nv_wr32(dev, NV04_PGRAPH_FIFO,
523					nv_rd32(dev, NV04_PGRAPH_FIFO) & ~1);
524}
525
526static int
527nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass,
528			int mthd, uint32_t data)
529{
530	atomic_set(&chan->fence.last_sequence_irq, data);
531	return 0;
532}
533
534/*
535 * Software methods, why they are needed, and how they all work:
536 *
537 * NV04 and NV05 keep most of the state in PGRAPH context itself, but some
538 * 2d engine settings are kept inside the grobjs themselves. The grobjs are
539 * 3 words long on both. grobj format on NV04 is:
540 *
541 * word 0:
542 *  - bits 0-7: class
543 *  - bit 12: color key active
544 *  - bit 13: clip rect active
545 *  - bit 14: if set, destination surface is swizzled and taken from buffer 5
546 *            [set by NV04_SWIZZLED_SURFACE], otherwise it's linear and taken
547 *            from buffer 0 [set by NV04_CONTEXT_SURFACES_2D or
548 *            NV03_CONTEXT_SURFACE_DST].
549 *  - bits 15-17: 2d operation [aka patch config]
550 *  - bit 24: patch valid [enables rendering using this object]
551 *  - bit 25: surf3d valid [for tex_tri and multitex_tri only]
552 * word 1:
553 *  - bits 0-1: mono format
554 *  - bits 8-13: color format
555 *  - bits 16-31: DMA_NOTIFY instance
556 * word 2:
557 *  - bits 0-15: DMA_A instance
558 *  - bits 16-31: DMA_B instance
559 *
560 * On NV05 it's:
561 *
562 * word 0:
563 *  - bits 0-7: class
564 *  - bit 12: color key active
565 *  - bit 13: clip rect active
566 *  - bit 14: if set, destination surface is swizzled and taken from buffer 5
567 *            [set by NV04_SWIZZLED_SURFACE], otherwise it's linear and taken
568 *            from buffer 0 [set by NV04_CONTEXT_SURFACES_2D or
569 *            NV03_CONTEXT_SURFACE_DST].
570 *  - bits 15-17: 2d operation [aka patch config]
571 *  - bits 20-22: dither mode
572 *  - bit 24: patch valid [enables rendering using this object]
573 *  - bit 25: surface_dst/surface_color/surf2d/surf3d valid
574 *  - bit 26: surface_src/surface_zeta valid
575 *  - bit 27: pattern valid
576 *  - bit 28: rop valid
577 *  - bit 29: beta1 valid
578 *  - bit 30: beta4 valid
579 * word 1:
580 *  - bits 0-1: mono format
581 *  - bits 8-13: color format
582 *  - bits 16-31: DMA_NOTIFY instance
583 * word 2:
584 *  - bits 0-15: DMA_A instance
585 *  - bits 16-31: DMA_B instance
586 *
587 * NV05 will set/unset the relevant valid bits when you poke the relevant
588 * object-binding methods with object of the proper type, or with the NULL
589 * type. It'll only allow rendering using the grobj if all needed objects
590 * are bound. The needed set of objects depends on selected operation: for
591 * example rop object is needed by ROP_AND, but not by SRCCOPY_AND.
592 *
593 * NV04 doesn't have these methods implemented at all, and doesn't have the
594 * relevant bits in grobj. Instead, it'll allow rendering whenever bit 24
595 * is set. So we have to emulate them in software, internally keeping the
596 * same bits as NV05 does. Since grobjs are aligned to 16 bytes on nv04,
597 * but the last word isn't actually used for anything, we abuse it for this
598 * purpose.
599 *
600 * Actually, NV05 can optionally check bit 24 too, but we disable this since
601 * there's no use for it.
602 *
603 * For unknown reasons, NV04 implements surf3d binding in hardware as an
604 * exception. Also for unknown reasons, NV04 doesn't implement the clipping
605 * methods on the surf3d object, so we have to emulate them too.
606 */
607
608static void
609nv04_graph_set_ctx1(struct nouveau_channel *chan, uint32_t mask, uint32_t value)
610{
611	struct drm_device *dev = chan->dev;
612	uint32_t instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4;
613	int subc = (nv_rd32(dev, NV04_PGRAPH_TRAPPED_ADDR) >> 13) & 0x7;
614	uint32_t tmp;
615
616	tmp  = nv_ri32(dev, instance);
617	tmp &= ~mask;
618	tmp |= value;
619
620	nv_wi32(dev, instance, tmp);
621	nv_wr32(dev, NV04_PGRAPH_CTX_SWITCH1, tmp);
622	nv_wr32(dev, NV04_PGRAPH_CTX_CACHE1 + (subc<<2), tmp);
623}
624
625static void
626nv04_graph_set_ctx_val(struct nouveau_channel *chan, uint32_t mask, uint32_t value)
627{
628	struct drm_device *dev = chan->dev;
629	uint32_t instance = (nv_rd32(dev, NV04_PGRAPH_CTX_SWITCH4) & 0xffff) << 4;
630	uint32_t tmp, ctx1;
631	int class, op, valid = 1;
632
633	ctx1 = nv_ri32(dev, instance);
634	class = ctx1 & 0xff;
635	op = (ctx1 >> 15) & 7;
636	tmp  = nv_ri32(dev, instance + 0xc);
637	tmp &= ~mask;
638	tmp |= value;
639	nv_wi32(dev, instance + 0xc, tmp);
640
641	/* check for valid surf2d/surf_dst/surf_color */
642	if (!(tmp & 0x02000000))
643		valid = 0;
644	/* check for valid surf_src/surf_zeta */
645	if ((class == 0x1f || class == 0x48) && !(tmp & 0x04000000))
646		valid = 0;
647
648	switch (op) {
649	/* SRCCOPY_AND, SRCCOPY: no extra objects required */
650	case 0:
651	case 3:
652		break;
653	/* ROP_AND: requires pattern and rop */
654	case 1:
655		if (!(tmp & 0x18000000))
656			valid = 0;
657		break;
658	/* BLEND_AND: requires beta1 */
659	case 2:
660		if (!(tmp & 0x20000000))
661			valid = 0;
662		break;
663	/* SRCCOPY_PREMULT, BLEND_PREMULT: beta4 required */
664	case 4:
665	case 5:
666		if (!(tmp & 0x40000000))
667			valid = 0;
668		break;
669	}
670
671	nv04_graph_set_ctx1(chan, 0x01000000, valid << 24);
672}
673
674static int
675nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass,
676			      int mthd, uint32_t data)
677{
678	if (data > 5)
679		return 1;
680	/* Old versions of the objects only accept first three operations. */
681	if (data > 2 && grclass < 0x40)
682		return 1;
683	nv04_graph_set_ctx1(chan, 0x00038000, data << 15);
684	/* changing operation changes set of objects needed for validation */
685	nv04_graph_set_ctx_val(chan, 0, 0);
686	return 0;
687}
688
689static int
690nv04_graph_mthd_surf3d_clip_h(struct nouveau_channel *chan, int grclass,
691			      int mthd, uint32_t data)
692{
693	uint32_t min = data & 0xffff, max;
694	uint32_t w = data >> 16;
695	if (min & 0x8000)
696		/* too large */
697		return 1;
698	if (w & 0x8000)
699		/* yes, it accepts negative for some reason. */
700		w |= 0xffff0000;
701	max = min + w;
702	max &= 0x3ffff;
703	nv_wr32(chan->dev, 0x40053c, min);
704	nv_wr32(chan->dev, 0x400544, max);
705	return 0;
706}
707
708static int
709nv04_graph_mthd_surf3d_clip_v(struct nouveau_channel *chan, int grclass,
710			      int mthd, uint32_t data)
711{
712	uint32_t min = data & 0xffff, max;
713	uint32_t w = data >> 16;
714	if (min & 0x8000)
715		/* too large */
716		return 1;
717	if (w & 0x8000)
718		/* yes, it accepts negative for some reason. */
719		w |= 0xffff0000;
720	max = min + w;
721	max &= 0x3ffff;
722	nv_wr32(chan->dev, 0x400540, min);
723	nv_wr32(chan->dev, 0x400548, max);
724	return 0;
725}
726
727static int
728nv04_graph_mthd_bind_surf2d(struct nouveau_channel *chan, int grclass,
729			      int mthd, uint32_t data)
730{
731	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
732	case 0x30:
733		nv04_graph_set_ctx1(chan, 0x00004000, 0);
734		nv04_graph_set_ctx_val(chan, 0x02000000, 0);
735		return 0;
736	case 0x42:
737		nv04_graph_set_ctx1(chan, 0x00004000, 0);
738		nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000);
739		return 0;
740	}
741	return 1;
742}
743
744static int
745nv04_graph_mthd_bind_surf2d_swzsurf(struct nouveau_channel *chan, int grclass,
746			      int mthd, uint32_t data)
747{
748	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
749	case 0x30:
750		nv04_graph_set_ctx1(chan, 0x00004000, 0);
751		nv04_graph_set_ctx_val(chan, 0x02000000, 0);
752		return 0;
753	case 0x42:
754		nv04_graph_set_ctx1(chan, 0x00004000, 0);
755		nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000);
756		return 0;
757	case 0x52:
758		nv04_graph_set_ctx1(chan, 0x00004000, 0x00004000);
759		nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000);
760		return 0;
761	}
762	return 1;
763}
764
765static int
766nv04_graph_mthd_bind_nv01_patt(struct nouveau_channel *chan, int grclass,
767			      int mthd, uint32_t data)
768{
769	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
770	case 0x30:
771		nv04_graph_set_ctx_val(chan, 0x08000000, 0);
772		return 0;
773	case 0x18:
774		nv04_graph_set_ctx_val(chan, 0x08000000, 0x08000000);
775		return 0;
776	}
777	return 1;
778}
779
780static int
781nv04_graph_mthd_bind_nv04_patt(struct nouveau_channel *chan, int grclass,
782			      int mthd, uint32_t data)
783{
784	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
785	case 0x30:
786		nv04_graph_set_ctx_val(chan, 0x08000000, 0);
787		return 0;
788	case 0x44:
789		nv04_graph_set_ctx_val(chan, 0x08000000, 0x08000000);
790		return 0;
791	}
792	return 1;
793}
794
795static int
796nv04_graph_mthd_bind_rop(struct nouveau_channel *chan, int grclass,
797			      int mthd, uint32_t data)
798{
799	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
800	case 0x30:
801		nv04_graph_set_ctx_val(chan, 0x10000000, 0);
802		return 0;
803	case 0x43:
804		nv04_graph_set_ctx_val(chan, 0x10000000, 0x10000000);
805		return 0;
806	}
807	return 1;
808}
809
810static int
811nv04_graph_mthd_bind_beta1(struct nouveau_channel *chan, int grclass,
812			      int mthd, uint32_t data)
813{
814	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
815	case 0x30:
816		nv04_graph_set_ctx_val(chan, 0x20000000, 0);
817		return 0;
818	case 0x12:
819		nv04_graph_set_ctx_val(chan, 0x20000000, 0x20000000);
820		return 0;
821	}
822	return 1;
823}
824
825static int
826nv04_graph_mthd_bind_beta4(struct nouveau_channel *chan, int grclass,
827			      int mthd, uint32_t data)
828{
829	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
830	case 0x30:
831		nv04_graph_set_ctx_val(chan, 0x40000000, 0);
832		return 0;
833	case 0x72:
834		nv04_graph_set_ctx_val(chan, 0x40000000, 0x40000000);
835		return 0;
836	}
837	return 1;
838}
839
840static int
841nv04_graph_mthd_bind_surf_dst(struct nouveau_channel *chan, int grclass,
842			      int mthd, uint32_t data)
843{
844	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
845	case 0x30:
846		nv04_graph_set_ctx_val(chan, 0x02000000, 0);
847		return 0;
848	case 0x58:
849		nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000);
850		return 0;
851	}
852	return 1;
853}
854
855static int
856nv04_graph_mthd_bind_surf_src(struct nouveau_channel *chan, int grclass,
857			      int mthd, uint32_t data)
858{
859	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
860	case 0x30:
861		nv04_graph_set_ctx_val(chan, 0x04000000, 0);
862		return 0;
863	case 0x59:
864		nv04_graph_set_ctx_val(chan, 0x04000000, 0x04000000);
865		return 0;
866	}
867	return 1;
868}
869
870static int
871nv04_graph_mthd_bind_surf_color(struct nouveau_channel *chan, int grclass,
872			      int mthd, uint32_t data)
873{
874	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
875	case 0x30:
876		nv04_graph_set_ctx_val(chan, 0x02000000, 0);
877		return 0;
878	case 0x5a:
879		nv04_graph_set_ctx_val(chan, 0x02000000, 0x02000000);
880		return 0;
881	}
882	return 1;
883}
884
885static int
886nv04_graph_mthd_bind_surf_zeta(struct nouveau_channel *chan, int grclass,
887			      int mthd, uint32_t data)
888{
889	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
890	case 0x30:
891		nv04_graph_set_ctx_val(chan, 0x04000000, 0);
892		return 0;
893	case 0x5b:
894		nv04_graph_set_ctx_val(chan, 0x04000000, 0x04000000);
895		return 0;
896	}
897	return 1;
898}
899
900static int
901nv04_graph_mthd_bind_clip(struct nouveau_channel *chan, int grclass,
902			      int mthd, uint32_t data)
903{
904	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
905	case 0x30:
906		nv04_graph_set_ctx1(chan, 0x2000, 0);
907		return 0;
908	case 0x19:
909		nv04_graph_set_ctx1(chan, 0x2000, 0x2000);
910		return 0;
911	}
912	return 1;
913}
914
915static int
916nv04_graph_mthd_bind_chroma(struct nouveau_channel *chan, int grclass,
917			      int mthd, uint32_t data)
918{
919	switch (nv_ri32(chan->dev, data << 4) & 0xff) {
920	case 0x30:
921		nv04_graph_set_ctx1(chan, 0x1000, 0);
922		return 0;
923	/* Yes, for some reason even the old versions of objects
924	 * accept 0x57 and not 0x17. Consistency be damned.
925	 */
926	case 0x57:
927		nv04_graph_set_ctx1(chan, 0x1000, 0x1000);
928		return 0;
929	}
930	return 1;
931}
932
933static struct nouveau_pgraph_object_method nv04_graph_mthds_sw[] = {
934	{ 0x0150, nv04_graph_mthd_set_ref },
935	{}
936};
937
938static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_gdirect[] = {
939	{ 0x0184, nv04_graph_mthd_bind_nv01_patt },
940	{ 0x0188, nv04_graph_mthd_bind_rop },
941	{ 0x018c, nv04_graph_mthd_bind_beta1 },
942	{ 0x0190, nv04_graph_mthd_bind_surf_dst },
943	{ 0x02fc, nv04_graph_mthd_set_operation },
944	{},
945};
946
947static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_gdirect[] = {
948	{ 0x0188, nv04_graph_mthd_bind_nv04_patt },
949	{ 0x018c, nv04_graph_mthd_bind_rop },
950	{ 0x0190, nv04_graph_mthd_bind_beta1 },
951	{ 0x0194, nv04_graph_mthd_bind_beta4 },
952	{ 0x0198, nv04_graph_mthd_bind_surf2d },
953	{ 0x02fc, nv04_graph_mthd_set_operation },
954	{},
955};
956
957static struct nouveau_pgraph_object_method nv04_graph_mthds_nv01_imageblit[] = {
958	{ 0x0184, nv04_graph_mthd_bind_chroma },
959	{ 0x0188, nv04_graph_mthd_bind_clip },
960	{ 0x018c, nv04_graph_mthd_bind_nv01_patt },
961	{ 0x0190, nv04_graph_mthd_bind_rop },
962	{ 0x0194, nv04_graph_mthd_bind_beta1 },
963	{ 0x0198, nv04_graph_mthd_bind_surf_dst },
964	{ 0x019c, nv04_graph_mthd_bind_surf_src },
965	{ 0x02fc, nv04_graph_mthd_set_operation },
966	{},
967};
968
969static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_imageblit_ifc[] = {
970	{ 0x0184, nv04_graph_mthd_bind_chroma },
971	{ 0x0188, nv04_graph_mthd_bind_clip },
972	{ 0x018c, nv04_graph_mthd_bind_nv04_patt },
973	{ 0x0190, nv04_graph_mthd_bind_rop },
974	{ 0x0194, nv04_graph_mthd_bind_beta1 },
975	{ 0x0198, nv04_graph_mthd_bind_beta4 },
976	{ 0x019c, nv04_graph_mthd_bind_surf2d },
977	{ 0x02fc, nv04_graph_mthd_set_operation },
978	{},
979};
980
981static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_iifc[] = {
982	{ 0x0188, nv04_graph_mthd_bind_chroma },
983	{ 0x018c, nv04_graph_mthd_bind_clip },
984	{ 0x0190, nv04_graph_mthd_bind_nv04_patt },
985	{ 0x0194, nv04_graph_mthd_bind_rop },
986	{ 0x0198, nv04_graph_mthd_bind_beta1 },
987	{ 0x019c, nv04_graph_mthd_bind_beta4 },
988	{ 0x01a0, nv04_graph_mthd_bind_surf2d_swzsurf },
989	{ 0x03e4, nv04_graph_mthd_set_operation },
990	{},
991};
992
993static struct nouveau_pgraph_object_method nv04_graph_mthds_nv01_ifc[] = {
994	{ 0x0184, nv04_graph_mthd_bind_chroma },
995	{ 0x0188, nv04_graph_mthd_bind_clip },
996	{ 0x018c, nv04_graph_mthd_bind_nv01_patt },
997	{ 0x0190, nv04_graph_mthd_bind_rop },
998	{ 0x0194, nv04_graph_mthd_bind_beta1 },
999	{ 0x0198, nv04_graph_mthd_bind_surf_dst },
1000	{ 0x02fc, nv04_graph_mthd_set_operation },
1001	{},
1002};
1003
1004static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_sifc[] = {
1005	{ 0x0184, nv04_graph_mthd_bind_chroma },
1006	{ 0x0188, nv04_graph_mthd_bind_nv01_patt },
1007	{ 0x018c, nv04_graph_mthd_bind_rop },
1008	{ 0x0190, nv04_graph_mthd_bind_beta1 },
1009	{ 0x0194, nv04_graph_mthd_bind_surf_dst },
1010	{ 0x02fc, nv04_graph_mthd_set_operation },
1011	{},
1012};
1013
1014static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_sifc[] = {
1015	{ 0x0184, nv04_graph_mthd_bind_chroma },
1016	{ 0x0188, nv04_graph_mthd_bind_nv04_patt },
1017	{ 0x018c, nv04_graph_mthd_bind_rop },
1018	{ 0x0190, nv04_graph_mthd_bind_beta1 },
1019	{ 0x0194, nv04_graph_mthd_bind_beta4 },
1020	{ 0x0198, nv04_graph_mthd_bind_surf2d },
1021	{ 0x02fc, nv04_graph_mthd_set_operation },
1022	{},
1023};
1024
1025static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_sifm[] = {
1026	{ 0x0188, nv04_graph_mthd_bind_nv01_patt },
1027	{ 0x018c, nv04_graph_mthd_bind_rop },
1028	{ 0x0190, nv04_graph_mthd_bind_beta1 },
1029	{ 0x0194, nv04_graph_mthd_bind_surf_dst },
1030	{ 0x0304, nv04_graph_mthd_set_operation },
1031	{},
1032};
1033
1034static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_sifm[] = {
1035	{ 0x0188, nv04_graph_mthd_bind_nv04_patt },
1036	{ 0x018c, nv04_graph_mthd_bind_rop },
1037	{ 0x0190, nv04_graph_mthd_bind_beta1 },
1038	{ 0x0194, nv04_graph_mthd_bind_beta4 },
1039	{ 0x0198, nv04_graph_mthd_bind_surf2d_swzsurf },
1040	{ 0x0304, nv04_graph_mthd_set_operation },
1041	{},
1042};
1043
1044static struct nouveau_pgraph_object_method nv04_graph_mthds_nv01_shape[] = {
1045	{ 0x0184, nv04_graph_mthd_bind_clip },
1046	{ 0x0188, nv04_graph_mthd_bind_nv01_patt },
1047	{ 0x018c, nv04_graph_mthd_bind_rop },
1048	{ 0x0190, nv04_graph_mthd_bind_beta1 },
1049	{ 0x0194, nv04_graph_mthd_bind_surf_dst },
1050	{ 0x02fc, nv04_graph_mthd_set_operation },
1051	{},
1052};
1053
1054static struct nouveau_pgraph_object_method nv04_graph_mthds_nv04_shape[] = {
1055	{ 0x0184, nv04_graph_mthd_bind_clip },
1056	{ 0x0188, nv04_graph_mthd_bind_nv04_patt },
1057	{ 0x018c, nv04_graph_mthd_bind_rop },
1058	{ 0x0190, nv04_graph_mthd_bind_beta1 },
1059	{ 0x0194, nv04_graph_mthd_bind_beta4 },
1060	{ 0x0198, nv04_graph_mthd_bind_surf2d },
1061	{ 0x02fc, nv04_graph_mthd_set_operation },
1062	{},
1063};
1064
1065static struct nouveau_pgraph_object_method nv04_graph_mthds_nv03_tex_tri[] = {
1066	{ 0x0188, nv04_graph_mthd_bind_clip },
1067	{ 0x018c, nv04_graph_mthd_bind_surf_color },
1068	{ 0x0190, nv04_graph_mthd_bind_surf_zeta },
1069	{},
1070};
1071
1072static struct nouveau_pgraph_object_method nv04_graph_mthds_surf3d[] = {
1073	{ 0x02f8, nv04_graph_mthd_surf3d_clip_h },
1074	{ 0x02fc, nv04_graph_mthd_surf3d_clip_v },
1075	{},
1076};
1077
1078struct nouveau_pgraph_object_class nv04_graph_grclass[] = {
1079	{ 0x0038, false, NULL }, /* dvd subpicture */
1080	{ 0x0039, false, NULL }, /* m2mf */
1081	{ 0x004b, false, nv04_graph_mthds_nv03_gdirect }, /* nv03 gdirect */
1082	{ 0x004a, false, nv04_graph_mthds_nv04_gdirect }, /* nv04 gdirect */
1083	{ 0x001f, false, nv04_graph_mthds_nv01_imageblit }, /* nv01 imageblit */
1084	{ 0x005f, false, nv04_graph_mthds_nv04_imageblit_ifc }, /* nv04 imageblit */
1085	{ 0x0060, false, nv04_graph_mthds_nv04_iifc }, /* nv04 iifc */
1086	{ 0x0064, false, NULL }, /* nv05 iifc */
1087	{ 0x0021, false, nv04_graph_mthds_nv01_ifc }, /* nv01 ifc */
1088	{ 0x0061, false, nv04_graph_mthds_nv04_imageblit_ifc }, /* nv04 ifc */
1089	{ 0x0065, false, NULL }, /* nv05 ifc */
1090	{ 0x0036, false, nv04_graph_mthds_nv03_sifc }, /* nv03 sifc */
1091	{ 0x0076, false, nv04_graph_mthds_nv04_sifc }, /* nv04 sifc */
1092	{ 0x0066, false, NULL }, /* nv05 sifc */
1093	{ 0x0037, false, nv04_graph_mthds_nv03_sifm }, /* nv03 sifm */
1094	{ 0x0077, false, nv04_graph_mthds_nv04_sifm }, /* nv04 sifm */
1095	{ 0x0030, false, NULL }, /* null */
1096	{ 0x0042, false, NULL }, /* surf2d */
1097	{ 0x0043, false, NULL }, /* rop */
1098	{ 0x0012, false, NULL }, /* beta1 */
1099	{ 0x0072, false, NULL }, /* beta4 */
1100	{ 0x0019, false, NULL }, /* cliprect */
1101	{ 0x0018, false, NULL }, /* nv01 pattern */
1102	{ 0x0044, false, NULL }, /* nv04 pattern */
1103	{ 0x0052, false, NULL }, /* swzsurf */
1104	{ 0x0053, false, nv04_graph_mthds_surf3d }, /* surf3d */
1105	{ 0x0048, false, nv04_graph_mthds_nv03_tex_tri }, /* nv03 tex_tri */
1106	{ 0x0054, false, NULL }, /* tex_tri */
1107	{ 0x0055, false, NULL }, /* multitex_tri */
1108	{ 0x0017, false, NULL }, /* nv01 chroma */
1109	{ 0x0057, false, NULL }, /* nv04 chroma */
1110	{ 0x0058, false, NULL }, /* surf_dst */
1111	{ 0x0059, false, NULL }, /* surf_src */
1112	{ 0x005a, false, NULL }, /* surf_color */
1113	{ 0x005b, false, NULL }, /* surf_zeta */
1114	{ 0x001c, false, nv04_graph_mthds_nv01_shape }, /* nv01 line */
1115	{ 0x005c, false, nv04_graph_mthds_nv04_shape }, /* nv04 line */
1116	{ 0x001d, false, nv04_graph_mthds_nv01_shape }, /* nv01 tri */
1117	{ 0x005d, false, nv04_graph_mthds_nv04_shape }, /* nv04 tri */
1118	{ 0x001e, false, nv04_graph_mthds_nv01_shape }, /* nv01 rect */
1119	{ 0x005e, false, nv04_graph_mthds_nv04_shape }, /* nv04 rect */
1120	{ 0x506e, true, nv04_graph_mthds_sw },
1121	{}
1122};
1123