1/*
2 * Copyright 2008 Ben Skeggs
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23#include "nv_include.h"
24#include "nv50_accel.h"
25
26#include "hwdefs/nv_object.xml.h"
27#include "hwdefs/nv50_2d.xml.h"
28#include "hwdefs/nv50_3d.xml.h"
29
30void
31NV50SyncToVBlank(PixmapPtr ppix, BoxPtr box)
32{
33	ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen);
34	NVPtr pNv = NVPTR(pScrn);
35	struct nouveau_pushbuf *push = pNv->pushbuf;
36	int head;
37	xf86CrtcPtr crtc;
38
39	if (!nouveau_exa_pixmap_is_onscreen(ppix))
40		return;
41
42	crtc = nouveau_pick_best_crtc(pScrn, box->x1, box->y1,
43				      box->x2 - box->x1,
44				      box->y2 - box->y1);
45	if (!crtc)
46		return;
47
48	if (!PUSH_SPACE(push, 10))
49		return;
50
51	head = drmmode_head(crtc);
52
53	BEGIN_NV04(push, SUBC_NVSW(0x0060), 2);
54	PUSH_DATA (push, pNv->vblank_sem->handle);
55	PUSH_DATA (push, 0);
56	BEGIN_NV04(push, SUBC_NVSW(0x006c), 1);
57	PUSH_DATA (push, 0x22222222);
58	BEGIN_NV04(push, SUBC_NVSW(0x0404), 2);
59	PUSH_DATA (push, 0x11111111);
60	PUSH_DATA (push, head);
61	BEGIN_NV04(push, SUBC_NVSW(0x0068), 1);
62	PUSH_DATA (push, 0x11111111);
63}
64
65Bool
66NVAccelInitM2MF_NV50(ScrnInfoPtr pScrn)
67{
68	NVPtr pNv = NVPTR(pScrn);
69	struct nouveau_pushbuf *push = pNv->pushbuf;
70	struct nv04_fifo *fifo = pNv->channel->data;
71
72	if (nouveau_object_new(pNv->channel, NvMemFormat, NV50_M2MF_CLASS,
73			       NULL, 0, &pNv->NvMemFormat))
74		return FALSE;
75
76	if (!PUSH_SPACE(push, 8))
77		return FALSE;
78
79	BEGIN_NV04(push, NV01_SUBC(M2MF, OBJECT), 1);
80	PUSH_DATA (push, pNv->NvMemFormat->handle);
81	BEGIN_NV04(push, NV03_M2MF(DMA_NOTIFY), 1);
82	PUSH_DATA (push, pNv->notify0->handle);
83	BEGIN_NV04(push, NV03_M2MF(DMA_BUFFER_IN), 2);
84	PUSH_DATA (push, fifo->vram);
85	PUSH_DATA (push, fifo->vram);
86	return TRUE;
87}
88
89Bool
90NVAccelInit2D_NV50(ScrnInfoPtr pScrn)
91{
92	NVPtr pNv = NVPTR(pScrn);
93	struct nouveau_pushbuf *push = pNv->pushbuf;
94	struct nv04_fifo *fifo = pNv->channel->data;
95
96	if (nouveau_object_new(pNv->channel, Nv2D, NV50_2D_CLASS,
97			       NULL, 0, &pNv->Nv2D))
98		return FALSE;
99
100	if (!PUSH_SPACE(push, 64))
101		return FALSE;
102
103	BEGIN_NV04(push, NV01_SUBC(2D, OBJECT), 1);
104	PUSH_DATA (push, pNv->Nv2D->handle);
105	BEGIN_NV04(push, NV50_2D(DMA_NOTIFY), 3);
106	PUSH_DATA (push, pNv->notify0->handle);
107	PUSH_DATA (push, fifo->vram);
108	PUSH_DATA (push, fifo->vram);
109
110	/* Magics from nv, no clue what they do, but at least some
111	 * of them are needed to avoid crashes.
112	 */
113	BEGIN_NV04(push, NV50_2D(UNK260), 1);
114	PUSH_DATA (push, 1);
115	BEGIN_NV04(push, NV50_2D(CLIP_ENABLE), 1);
116	PUSH_DATA (push, 1);
117	BEGIN_NV04(push, NV50_2D(COLOR_KEY_ENABLE), 1);
118	PUSH_DATA (push, 0);
119	BEGIN_NV04(push, NV50_2D(UNK58C), 1);
120	PUSH_DATA (push, 0x111);
121
122	pNv->currentRop = 0xfffffffa;
123	return TRUE;
124}
125
126Bool
127NVAccelInitNV50TCL(ScrnInfoPtr pScrn)
128{
129	NVPtr pNv = NVPTR(pScrn);
130	struct nv04_fifo *fifo = pNv->channel->data;
131	struct nouveau_pushbuf *push = pNv->pushbuf;
132	struct nv04_notify ntfy = { .length = 32 };
133	unsigned class;
134	int i;
135
136	switch (pNv->dev->chipset & 0xf0) {
137	case 0x50:
138		class = NV50_3D_CLASS;
139		break;
140	case 0x80:
141	case 0x90:
142		class = NV84_3D_CLASS;
143		break;
144	case 0xa0:
145		switch (pNv->dev->chipset) {
146		case 0xa0:
147		case 0xaa:
148		case 0xac:
149			class = NVA0_3D_CLASS;
150			break;
151		case 0xaf:
152			class = NVAF_3D_CLASS;
153			break;
154		default:
155			class = NVA3_3D_CLASS;
156			break;
157		}
158		break;
159	default:
160		return FALSE;
161	}
162
163	if (nouveau_object_new(pNv->channel, Nv3D, class, NULL, 0, &pNv->Nv3D))
164		return FALSE;
165
166	if (nouveau_object_new(pNv->channel, NvSW, 0x506e, NULL, 0, &pNv->NvSW)) {
167		nouveau_object_del(&pNv->Nv3D);
168		return FALSE;
169	}
170
171	if (nouveau_object_new(pNv->channel, NvVBlankSem, NOUVEAU_NOTIFIER_CLASS,
172			       &ntfy, sizeof(ntfy), &pNv->vblank_sem)) {
173		nouveau_object_del(&pNv->NvSW);
174		nouveau_object_del(&pNv->Nv3D);
175		return FALSE;
176	}
177
178	if (nouveau_pushbuf_space(push, 512, 0, 0) ||
179	    nouveau_pushbuf_refn (push, &(struct nouveau_pushbuf_refn) {
180					pNv->scratch, NOUVEAU_BO_VRAM |
181					NOUVEAU_BO_WR }, 1))
182		return FALSE;
183
184	BEGIN_NV04(push, NV01_SUBC(NVSW, OBJECT), 1);
185	PUSH_DATA (push, pNv->NvSW->handle);
186	BEGIN_NV04(push, SUBC_NVSW(0x018c), 1);
187	PUSH_DATA (push, pNv->vblank_sem->handle);
188	BEGIN_NV04(push, SUBC_NVSW(0x0400), 1);
189	PUSH_DATA (push, 0);
190
191	BEGIN_NV04(push, NV01_SUBC(3D, OBJECT), 1);
192	PUSH_DATA (push, pNv->Nv3D->handle);
193	BEGIN_NV04(push, NV50_3D(COND_MODE), 1);
194	PUSH_DATA (push, NV50_3D_COND_MODE_ALWAYS);
195	BEGIN_NV04(push, NV50_3D(DMA_NOTIFY), 1);
196	PUSH_DATA (push, pNv->NvNull->handle);
197	BEGIN_NV04(push, NV50_3D(DMA_ZETA), 11);
198	for (i = 0; i < 11; i++)
199		PUSH_DATA (push, fifo->vram);
200	BEGIN_NV04(push, NV50_3D(DMA_COLOR(0)), NV50_3D_DMA_COLOR__LEN);
201	for (i = 0; i < NV50_3D_DMA_COLOR__LEN; i++)
202		PUSH_DATA (push, fifo->vram);
203	BEGIN_NV04(push, NV50_3D(RT_CONTROL), 1);
204	PUSH_DATA (push, 1);
205
206	BEGIN_NV04(push, NV50_3D(VIEWPORT_TRANSFORM_EN), 1);
207	PUSH_DATA (push, 0);
208	BEGIN_NV04(push, NV50_3D(COLOR_MASK_COMMON), 1);
209	PUSH_DATA (push, 1);
210	BEGIN_NV04(push, NV50_3D(ZETA_ENABLE), 1);
211	PUSH_DATA (push, 0);
212
213	BEGIN_NV04(push, NV50_3D(TIC_ADDRESS_HIGH), 3);
214	PUSH_DATA (push, (pNv->scratch->offset + TIC_OFFSET) >> 32);
215	PUSH_DATA (push, (pNv->scratch->offset + TIC_OFFSET));
216	PUSH_DATA (push, 0x00000800);
217	BEGIN_NV04(push, NV50_3D(TSC_ADDRESS_HIGH), 3);
218	PUSH_DATA (push, (pNv->scratch->offset + TSC_OFFSET) >> 32);
219	PUSH_DATA (push, (pNv->scratch->offset + TSC_OFFSET));
220	PUSH_DATA (push, 0x00000000);
221	BEGIN_NV04(push, NV50_3D(LINKED_TSC), 1);
222	PUSH_DATA (push, 1);
223	BEGIN_NV04(push, NV50_3D(TEX_LIMITS(2)), 1);
224	PUSH_DATA (push, 0x54);
225
226	PUSH_DATAu(push, pNv->scratch, PVP_OFFSET, 30 * 2);
227	PUSH_DATA (push, 0x10000001);
228	PUSH_DATA (push, 0x0423c788); /* mov b32 o[0x0] a[0x0] */
229	PUSH_DATA (push, 0x10000205);
230	PUSH_DATA (push, 0x0423c788); /* mov b32 o[0x4] a[0x4] */
231	PUSH_DATA (push, 0xc0800401);
232	PUSH_DATA (push, 0x00200780); /* mul rn f32 $r0 a[0x8] c0[0x0] */
233	PUSH_DATA (push, 0xc0830405);
234	PUSH_DATA (push, 0x00200780); /* mul rn f32 $r1 a[0x8] c0[0xc] */
235	PUSH_DATA (push, 0xc0860409);
236	PUSH_DATA (push, 0x00200780); /* mul rn f32 $r2 a[0x8] c0[0x18] */
237	PUSH_DATA (push, 0xe0810601);
238	PUSH_DATA (push, 0x00200780); /* add f32 $r0 (mul a[0xc] c0[0x4]) $r0 */
239	PUSH_DATA (push, 0xe0840605);
240	PUSH_DATA (push, 0x00204780); /* add f32 $r1 (mul a[0xc] c0[0x10]) $r1 */
241	PUSH_DATA (push, 0xe0870609);
242	PUSH_DATA (push, 0x00208780); /* add f32 $r2 (mul a[0xc] c0[0x1c]) $r2 */
243	PUSH_DATA (push, 0xb1000001);
244	PUSH_DATA (push, 0x00008780); /* add rn f32 $r0 $r0 c0[0x8] */
245	PUSH_DATA (push, 0xb1000205);
246	PUSH_DATA (push, 0x00014780); /* add rn f32 $r1 $r1 c0[0x14] */
247	PUSH_DATA (push, 0xb1000409);
248	PUSH_DATA (push, 0x00020780); /* add rn f32 $r2 $r2 c0[0x20] */
249	PUSH_DATA (push, 0x90000409);
250	PUSH_DATA (push, 0x00000780); /* rcp f32 $r2 $r2 */
251	PUSH_DATA (push, 0xc0020001);
252	PUSH_DATA (push, 0x00000780); /* mul rn f32 $r0 $r0 $r2 */
253	PUSH_DATA (push, 0xc0020205);
254	PUSH_DATA (push, 0x00000780); /* mul rn f32 $r1 $r1 $r2 */
255	PUSH_DATA (push, 0xc0890009);
256	PUSH_DATA (push, 0x00000788); /* mul rn f32 o[0x8] $r0 c0[0x24] */
257	PUSH_DATA (push, 0xc08a020d);
258	PUSH_DATA (push, 0x00000788); /* mul rn f32 o[0xc] $r1 c0[0x28] */
259	PUSH_DATA (push, 0xc08b0801);
260	PUSH_DATA (push, 0x00200780); /* mul rn f32 $r0 a[0x10] c0[0x2c] */
261	PUSH_DATA (push, 0xc08e0805);
262	PUSH_DATA (push, 0x00200780); /* mul rn f32 $r1 a[0x10] c0[0x38] */
263	PUSH_DATA (push, 0xc0910809);
264	PUSH_DATA (push, 0x00200780); /* mul rn f32 $r2 a[0x10] c0[0x44] */
265	PUSH_DATA (push, 0xe08c0a01);
266	PUSH_DATA (push, 0x00200780); /* add f32 $r0 (mul a[0x14] c0[0x30]) $r0 */
267	PUSH_DATA (push, 0xe08f0a05);
268	PUSH_DATA (push, 0x00204780); /* add f32 $r1 (mul a[0x14] c0[0x3c]) $r1 */
269	PUSH_DATA (push, 0xe0920a09);
270	PUSH_DATA (push, 0x00208780); /* add f32 $r2 (mul a[0x14] c0[0x48]) $r2 */
271	PUSH_DATA (push, 0xb1000001);
272	PUSH_DATA (push, 0x00034780); /* add rn f32 $r0 $r0 c0[0x34] */
273	PUSH_DATA (push, 0xb1000205);
274	PUSH_DATA (push, 0x00040780); /* add rn f32 $r1 $r1 c0[0x40] */
275	PUSH_DATA (push, 0xb1000409);
276	PUSH_DATA (push, 0x0004c780); /* add rn f32 $r2 $r2 c0[0x4c] */
277	PUSH_DATA (push, 0x90000409);
278	PUSH_DATA (push, 0x00000780); /* rcp f32 $r2 $r2 */
279	PUSH_DATA (push, 0xc0020001);
280	PUSH_DATA (push, 0x00000780); /* mul rn f32 $r0 $r0 $r2 */
281	PUSH_DATA (push, 0xc0020205);
282	PUSH_DATA (push, 0x00000780); /* mul rn f32 $r1 $r1 $r2 */
283	PUSH_DATA (push, 0xc0940011);
284	PUSH_DATA (push, 0x00000788); /* mul rn f32 o[0x10] $r0 c0[0x50] */
285	PUSH_DATA (push, 0xc0950215);
286	PUSH_DATA (push, 0x00000789); /* exit mul rn f32 o[0x14] $r1 c0[0x54] */
287
288	/* fetch only VTX_ATTR[0,8,9].xy */
289	BEGIN_NV04(push, NV50_3D(VP_ATTR_EN(0)), 2);
290	PUSH_DATA (push, 0x00000003);
291	PUSH_DATA (push, 0x00000033);
292	BEGIN_NV04(push, NV50_3D(VP_REG_ALLOC_RESULT), 1);
293	PUSH_DATA (push, 6);
294	BEGIN_NV04(push, NV50_3D(VP_RESULT_MAP_SIZE), 2);
295	PUSH_DATA (push, 8);
296	PUSH_DATA (push, 4); /* NV50_3D_VP_REG_ALLOC_TEMP */
297	BEGIN_NV04(push, NV50_3D(VP_ADDRESS_HIGH), 2);
298	PUSH_DATA (push, (pNv->scratch->offset + PVP_OFFSET) >> 32);
299	PUSH_DATA (push, (pNv->scratch->offset + PVP_OFFSET));
300	BEGIN_NV04(push, NV50_3D(CB_DEF_ADDRESS_HIGH), 3);
301	PUSH_DATA (push, (pNv->scratch->offset + PVP_DATA) >> 32);
302	PUSH_DATA (push, (pNv->scratch->offset + PVP_DATA));
303	PUSH_DATA (push, (CB_PVP << NV50_3D_CB_DEF_SET_BUFFER__SHIFT) | 256);
304	BEGIN_NV04(push, NV50_3D(SET_PROGRAM_CB), 1);
305	PUSH_DATA (push, 0x00000001 | (CB_PVP << 12));
306	BEGIN_NV04(push, NV50_3D(VP_START_ID), 1);
307	PUSH_DATA (push, 0);
308
309	PUSH_DATAu(push, pNv->scratch, PFP_OFFSET + PFP_S, 6);
310	PUSH_DATA (push, 0x80000000); /* interp $r0 v[0x0] */
311	PUSH_DATA (push, 0x90000004); /* rcp f32 $r1 $r0 */
312	PUSH_DATA (push, 0x82010200); /* interp $r0 v[0x4] $r1 */
313	PUSH_DATA (push, 0x82020204); /* interp $r1 v[0x8] $r1 */
314	PUSH_DATA (push, 0xf6400001);
315	PUSH_DATA (push, 0x0000c785); /* exit texauto live $r0:$r1:$r2:$r3 $t0 $s0 $r0:$r1 0x0 0x0 0x0 */
316	PUSH_DATAu(push, pNv->scratch, PFP_OFFSET + PFP_C, 16);
317	PUSH_DATA (push, 0x80000000); /* interp $r0 v[0x0] */
318	PUSH_DATA (push, 0x90000004); /* rcp f32 $r1 $r0 */
319	PUSH_DATA (push, 0x82030210); /* interp $r4 v[0xc] $r1 */
320	PUSH_DATA (push, 0x82040214); /* interp $r5 v[0x10] $r1 */
321	PUSH_DATA (push, 0x82010200); /* interp $r0 v[0x4] $r1 */
322	PUSH_DATA (push, 0x82020204); /* interp $r1 v[0x8] $r1 */
323	PUSH_DATA (push, 0xf6400001);
324	PUSH_DATA (push, 0x0000c784); /* texauto live $r0:$r1:$r2:$r3 $t0 $s0 $r0:$r1 0x0 0x0 0x0 */
325	PUSH_DATA (push, 0xf0400211);
326	PUSH_DATA (push, 0x00008784); /* texauto live #:#:#:$r4 $t1 $s0 $r4:$r5 0x0 0x0 0x0 */
327	PUSH_DATA (push, 0xc0040000); /* mul f32 $r0 $r0 $r4 */
328	PUSH_DATA (push, 0xc0040204); /* mul f32 $r1 $r1 $r4 */
329	PUSH_DATA (push, 0xc0040409);
330	PUSH_DATA (push, 0x00000780); /* mul rn f32 $r2 $r2 $r4 */
331	PUSH_DATA (push, 0xc004060d);
332	PUSH_DATA (push, 0x00000781); /* exit mul rn f32 $r3 $r3 $r4 */
333	PUSH_DATAu(push, pNv->scratch, PFP_OFFSET + PFP_CCA, 16);
334	PUSH_DATA (push, 0x80000000); /* interp $r0 v[0x0] */
335	PUSH_DATA (push, 0x90000004); /* rcp f32 $r1 $r0 */
336	PUSH_DATA (push, 0x82030210); /* interp $r4 v[0xc] $r1 */
337	PUSH_DATA (push, 0x82040214); /* interp $r5 v[0x10] $r1 */
338	PUSH_DATA (push, 0x82010200); /* interp $r0 v[0x4] $r1 */
339	PUSH_DATA (push, 0x82020204); /* interp $r1 v[0x8] $r1 */
340	PUSH_DATA (push, 0xf6400001);
341	PUSH_DATA (push, 0x0000c784); /* texauto live $r0:$r1:$r2:$r3 $t0 $s0 $r0:$r1 0x0 0x0 0x0 */
342	PUSH_DATA (push, 0xf6400211);
343	PUSH_DATA (push, 0x0000c784); /* texauto live $r4:$r5:$r6:$r7 $t1 $s0 $r4:$r5 0x0 0x0 0x0 */
344	PUSH_DATA (push, 0xc0040000); /* mul f32 $r0 $r0 $r4 */
345	PUSH_DATA (push, 0xc0050204); /* mul f32 $r1 $r1 $r5 */
346	PUSH_DATA (push, 0xc0060409);
347	PUSH_DATA (push, 0x00000780); /* mul rn f32 $r2 $r2 $r6 */
348	PUSH_DATA (push, 0xc007060d);
349	PUSH_DATA (push, 0x00000781); /* exit mul rn f32 $r3 $r3 $r7 */
350	PUSH_DATAu(push, pNv->scratch, PFP_OFFSET + PFP_CCASA, 16);
351	PUSH_DATA (push, 0x80000000); /* interp $r0 v[0x0] */
352	PUSH_DATA (push, 0x90000004); /* rcp f32 $r1 $r0 */
353	PUSH_DATA (push, 0x82030200); /* interp $r0 v[0xc] $r1 */
354	PUSH_DATA (push, 0x82040204); /* interp $r1 v[0x10] $r1 */
355	PUSH_DATA (push, 0x82010210); /* interp $r4 v[0x4] $r1 */
356	PUSH_DATA (push, 0x82020214); /* interp $r5 v[0x8] $r1 */
357	PUSH_DATA (push, 0xf6400201);
358	PUSH_DATA (push, 0x0000c784); /* texauto live $r0:$r1:$r2:$r3 $t1 $s0 $r0:$r1 0x0 0x0 0x0 */
359	PUSH_DATA (push, 0xf0400011);
360	PUSH_DATA (push, 0x00008784); /* texauto live #:#:#:$r4 $t0 $s0 $r4:$r5 0x0 0x0 0x0 */
361	PUSH_DATA (push, 0xc0040000); /* mul f32 $r0 $r0 $r4 */
362	PUSH_DATA (push, 0xc0040204); /* mul f32 $r1 $r1 $r4 */
363	PUSH_DATA (push, 0xc0040409);
364	PUSH_DATA (push, 0x00000780); /* mul rn f32 $r2 $r2 $r4 */
365	PUSH_DATA (push, 0xc004060d);
366	PUSH_DATA (push, 0x00000781); /* exit mul rn f32 $r3 $r3 $r4 */
367	PUSH_DATAu(push, pNv->scratch, PFP_OFFSET + PFP_S_A8, 10);
368	PUSH_DATA (push, 0x80000000); /* interp $r0 v[0x0] */
369	PUSH_DATA (push, 0x90000004); /* rcp f32 $r1 $r0 */
370	PUSH_DATA (push, 0x82010200); /* interp $r0 v[0x4] $r1 */
371	PUSH_DATA (push, 0x82020204); /* interp $r1 v[0x8] $r1 */
372	PUSH_DATA (push, 0xf0400001);
373	PUSH_DATA (push, 0x00008784); /* texauto live #:#:#:$r0 $t0 $s0 $r0:$r1 0x0 0x0 0x0 */
374	PUSH_DATA (push, 0x10008004); /* mov b32 $r1 $r0 */
375	PUSH_DATA (push, 0x10008008); /* mov b32 $r2 $r0 */
376	PUSH_DATA (push, 0x1000000d);
377	PUSH_DATA (push, 0x0403c781); /* exit mov b32 $r3 $r0 */
378	PUSH_DATAu(push, pNv->scratch, PFP_OFFSET + PFP_C_A8, 16);
379	PUSH_DATA (push, 0x80000000); /* interp $r0 v[0x0] */
380	PUSH_DATA (push, 0x90000004); /* rcp f32 $r1 $r0 */
381	PUSH_DATA (push, 0x82030208); /* interp $r2 v[0xc] $r1 */
382	PUSH_DATA (push, 0x8204020c); /* interp $r3 v[0x10] $r1 */
383	PUSH_DATA (push, 0x82010200); /* interp $r0 v[0x4] $r1 */
384	PUSH_DATA (push, 0x82020204); /* interp $r1 v[0x8] $r1 */
385	PUSH_DATA (push, 0xf0400001);
386	PUSH_DATA (push, 0x00008784); /* texauto live #:#:#:$r0 $t0 $s0 $r0:$r1 0x0 0x0 0x0 */
387	PUSH_DATA (push, 0xf0400209);
388	PUSH_DATA (push, 0x00008784); /* texauto live #:#:#:$r2 $t1 $s0 $r2:$r3 0x0 0x0 0x0 */
389	PUSH_DATA (push, 0xc002000d);
390	PUSH_DATA (push, 0x00000780); /* mul rn f32 $r3 $r0 $r2 */
391	PUSH_DATA (push, 0x10008600); /* mov b32 $r0 $r3 */
392	PUSH_DATA (push, 0x10008604); /* mov b32 $r1 $r3 */
393	PUSH_DATA (push, 0x10000609);
394	PUSH_DATA (push, 0x0403c781); /* exit mov b32 $r2 $r3 */
395	PUSH_DATAu(push, pNv->scratch, PFP_OFFSET + PFP_NV12, 24);
396	PUSH_DATA (push, 0x80000008); /* interp $r2 v[0x0] */
397	PUSH_DATA (push, 0x90000408); /* rcp f32 $r2 $r2 */
398	PUSH_DATA (push, 0x82010400); /* interp $r0 v[0x4] $r2 */
399	PUSH_DATA (push, 0x82020404); /* interp $r1 v[0x8] $r2 */
400	PUSH_DATA (push, 0xf0400001);
401	PUSH_DATA (push, 0x00008784); /* texauto live #:#:#:$r0 $t0 $s0 $r0:$r1 0x0 0x0 0x0 */
402	PUSH_DATA (push, 0xc0800014); /* mul f32 $r5 $r0 c0[0x0] */
403	PUSH_DATA (push, 0xb0810a0c); /* add f32 $r3 $r5 c0[0x4] */
404	PUSH_DATA (push, 0xb0820a10); /* add f32 $r4 $r5 c0[0x8] */
405	PUSH_DATA (push, 0xb0830a14); /* add f32 $r5 $r5 c0[0xc] */
406	PUSH_DATA (push, 0x82010400); /* interp $r0 v[0x4] $r2 */
407	PUSH_DATA (push, 0x82020404); /* interp $r1 v[0x8] $r2 */
408	PUSH_DATA (push, 0xf0400201);
409	PUSH_DATA (push, 0x0000c784); /* texauto live #:#:$r0:$r1 $t1 $s0 $r0:$r1 0x0 0x0 0x0 */
410	PUSH_DATA (push, 0xe084000c); /* add f32 $r3 (mul $r0 c0[0x10]) $r3 */
411	PUSH_DATA (push, 0xe0850010); /* add f32 $r4 (mul $r0 c0[0x14]) $r4 */
412	PUSH_DATA (push, 0xe0860015);
413	PUSH_DATA (push, 0x00014780); /* add f32 $r5 (mul $r0 c0[0x18]) $r5 */
414	PUSH_DATA (push, 0xe0870201);
415	PUSH_DATA (push, 0x0000c780); /* add f32 $r0 (mul $r1 c0[0x1c]) $r3 */
416	PUSH_DATA (push, 0xe0890209);
417	PUSH_DATA (push, 0x00014780); /* add f32 $r2 (mul $r1 c0[0x24]) $r5 */
418	PUSH_DATA (push, 0xe0880205);
419	PUSH_DATA (push, 0x00010781); /* exit add f32 $r1 (mul $r1 c0[0x20]) $r4 */
420
421	/* HPOS.xy = ($o0, $o1), HPOS.zw = (0.0, 1.0), then map $o2 - $o5 */
422	BEGIN_NV04(push, NV50_3D(VP_RESULT_MAP(0)), 2);
423	PUSH_DATA (push, 0x41400100);
424	PUSH_DATA (push, 0x05040302);
425	BEGIN_NV04(push, NV50_3D(POINT_SPRITE_ENABLE), 1);
426	PUSH_DATA (push, 0x00000000);
427	BEGIN_NV04(push, NV50_3D(FP_INTERPOLANT_CTRL), 2);
428	PUSH_DATA (push, 0x08040404);
429	PUSH_DATA (push, 0x00000008); /* NV50_3D_FP_REG_ALLOC_TEMP */
430	BEGIN_NV04(push, NV50_3D(FP_ADDRESS_HIGH), 2);
431	PUSH_DATA (push, (pNv->scratch->offset + PFP_OFFSET) >> 32);
432	PUSH_DATA (push, (pNv->scratch->offset + PFP_OFFSET));
433	BEGIN_NV04(push, NV50_3D(CB_DEF_ADDRESS_HIGH), 3);
434	PUSH_DATA (push, (pNv->scratch->offset + PFP_DATA) >> 32);
435	PUSH_DATA (push, (pNv->scratch->offset + PFP_DATA));
436	PUSH_DATA (push, (CB_PFP << NV50_3D_CB_DEF_SET_BUFFER__SHIFT) | 256);
437	BEGIN_NV04(push, NV50_3D(SET_PROGRAM_CB), 1);
438	PUSH_DATA (push, 0x00000031 | (CB_PFP << 12));
439
440	BEGIN_NV04(push, NV50_3D(SCISSOR_ENABLE(0)), 1);
441	PUSH_DATA (push, 1);
442
443	BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2);
444	PUSH_DATA (push, 8192 << NV50_3D_VIEWPORT_HORIZ_W__SHIFT);
445	PUSH_DATA (push, 8192 << NV50_3D_VIEWPORT_VERT_H__SHIFT);
446	/* NV50_3D_SCISSOR_VERT_T_SHIFT is wrong, because it was deducted with
447	 * origin lying at the bottom left. This will be changed to _MIN_ and _MAX_
448	 * later, because it is origin dependent.
449	 */
450	BEGIN_NV04(push, NV50_3D(SCISSOR_HORIZ(0)), 2);
451	PUSH_DATA (push, 8192 << NV50_3D_SCISSOR_HORIZ_MAX__SHIFT);
452	PUSH_DATA (push, 8192 << NV50_3D_SCISSOR_VERT_MAX__SHIFT);
453	BEGIN_NV04(push, NV50_3D(SCREEN_SCISSOR_HORIZ), 2);
454	PUSH_DATA (push, 8192 << NV50_3D_SCREEN_SCISSOR_HORIZ_W__SHIFT);
455	PUSH_DATA (push, 8192 << NV50_3D_SCREEN_SCISSOR_VERT_H__SHIFT);
456
457	return TRUE;
458}
459