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 "nvc0_accel.h"
25
26#include "shader/xfrm2nvc0.vp"
27#include "shader/videonvc0.fp"
28
29#include "shader/exascnvc0.fp"
30#include "shader/exacmnvc0.fp"
31#include "shader/exacanvc0.fp"
32#include "shader/exasanvc0.fp"
33#include "shader/exas8nvc0.fp"
34#include "shader/exac8nvc0.fp"
35
36#include "shader/xfrm2nve0.vp"
37#include "shader/videonve0.fp"
38
39#include "shader/exascnve0.fp"
40#include "shader/exacmnve0.fp"
41#include "shader/exacanve0.fp"
42#include "shader/exasanve0.fp"
43#include "shader/exas8nve0.fp"
44#include "shader/exac8nve0.fp"
45
46#include "shader/xfrm2nvf0.vp"
47#include "shader/videonvf0.fp"
48
49#include "shader/exascnvf0.fp"
50#include "shader/exacmnvf0.fp"
51#include "shader/exacanvf0.fp"
52#include "shader/exasanvf0.fp"
53#include "shader/exas8nvf0.fp"
54#include "shader/exac8nvf0.fp"
55
56#include "shader/xfrm2nv110.vp"
57#include "shader/videonv110.fp"
58
59#include "shader/exascnv110.fp"
60#include "shader/exacmnv110.fp"
61#include "shader/exacanv110.fp"
62#include "shader/exasanv110.fp"
63#include "shader/exas8nv110.fp"
64#include "shader/exac8nv110.fp"
65
66#define NVC0PushProgram(pNv,addr,code) do {                                    \
67	const unsigned size = sizeof(code) / sizeof(code[0]);                  \
68	PUSH_DATAu((pNv)->pushbuf, (pNv)->scratch, (addr), size);              \
69	PUSH_DATAp((pNv)->pushbuf, (code), size);                              \
70} while(0)
71
72void
73NVC0SyncToVBlank(PixmapPtr ppix, BoxPtr box)
74{
75	ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen);
76	NVPtr pNv = NVPTR(pScrn);
77	struct nouveau_pushbuf *push = pNv->pushbuf;
78	int head;
79	xf86CrtcPtr crtc;
80
81	if (!pNv->NvSW || !nouveau_exa_pixmap_is_onscreen(ppix))
82		return;
83
84	crtc = nouveau_pick_best_crtc(pScrn, box->x1, box->y1,
85				      box->x2 - box->x1,
86				      box->y2 - box->y1);
87	if (!crtc)
88		return;
89
90	if (!PUSH_SPACE(push, 32))
91		return;
92
93	head = drmmode_head(crtc);
94
95	BEGIN_NVC0(push, NV01_SUBC(NVSW, OBJECT), 1);
96	PUSH_DATA (push, pNv->NvSW->handle);
97	BEGIN_NVC0(push, NV84_SUBC(NVSW, SEMAPHORE_ADDRESS_HIGH), 4);
98	PUSH_DATA (push, (pNv->scratch->offset + SEMA_OFFSET) >> 32);
99	PUSH_DATA (push, (pNv->scratch->offset + SEMA_OFFSET));
100	PUSH_DATA (push, 0x22222222);
101	PUSH_DATA (push, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG);
102	BEGIN_NVC0(push, SUBC_NVSW(0x0400), 4);
103	PUSH_DATA (push, (pNv->scratch->offset + SEMA_OFFSET) >> 32);
104	PUSH_DATA (push, (pNv->scratch->offset + SEMA_OFFSET));
105	PUSH_DATA (push, 0x11111111);
106	PUSH_DATA (push, head);
107	BEGIN_NVC0(push, NV84_SUBC(NVSW, SEMAPHORE_ADDRESS_HIGH), 4);
108	PUSH_DATA (push, (pNv->scratch->offset + SEMA_OFFSET) >> 32);
109	PUSH_DATA (push, (pNv->scratch->offset + SEMA_OFFSET));
110	PUSH_DATA (push, 0x11111111);
111	PUSH_DATA (push, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_EQUAL);
112}
113
114Bool
115NVAccelInitM2MF_NVC0(ScrnInfoPtr pScrn)
116{
117	NVPtr pNv = NVPTR(pScrn);
118	struct nouveau_pushbuf *push = pNv->pushbuf;
119	int ret;
120
121	ret = nouveau_object_new(pNv->channel, 0x00009039, 0x9039,
122				 NULL, 0, &pNv->NvMemFormat);
123	if (ret)
124		return FALSE;
125
126	BEGIN_NVC0(push, NV01_SUBC(M2MF, OBJECT), 1);
127	PUSH_DATA (push, pNv->NvMemFormat->handle);
128	BEGIN_NVC0(push, NVC0_M2MF(QUERY_ADDRESS_HIGH), 3);
129	PUSH_DATA (push, (pNv->scratch->offset + NTFY_OFFSET) >> 32);
130	PUSH_DATA (push, (pNv->scratch->offset + NTFY_OFFSET));
131	PUSH_DATA (push, 0);
132
133	return TRUE;
134}
135
136Bool
137NVAccelInitP2MF_NVE0(ScrnInfoPtr pScrn)
138{
139	NVPtr pNv = NVPTR(pScrn);
140	struct nouveau_pushbuf *push = pNv->pushbuf;
141	uint32_t class = (pNv->dev->chipset < 0xf0) ? 0xa040 : 0xa140;
142	int ret;
143
144	ret = nouveau_object_new(pNv->channel, class, class, NULL, 0,
145				&pNv->NvMemFormat);
146	if (ret)
147		return FALSE;
148
149	BEGIN_NVC0(push, NV01_SUBC(P2MF, OBJECT), 1);
150	PUSH_DATA (push, pNv->NvMemFormat->handle);
151	return TRUE;
152}
153
154Bool
155NVAccelInitCOPY_NVE0(ScrnInfoPtr pScrn)
156{
157	NVPtr pNv = NVPTR(pScrn);
158	struct nouveau_pushbuf *push = pNv->pushbuf;
159	uint32_t class;
160	int ret;
161
162	if (pNv->dev->chipset < 0x110)
163		class = 0xa0b5;
164	else if (pNv->dev->chipset < 0x130)
165		class = 0xb0b5;
166	else
167		class = 0xc0b5;
168
169	ret = nouveau_object_new(pNv->channel, class, class,
170				 NULL, 0, &pNv->NvCOPY);
171	if (ret)
172		return FALSE;
173
174	BEGIN_NVC0(push, NV01_SUBC(COPY, OBJECT), 1);
175	PUSH_DATA (push, pNv->NvCOPY->handle);
176	return TRUE;
177}
178
179Bool
180NVAccelInit2D_NVC0(ScrnInfoPtr pScrn)
181{
182	NVPtr pNv = NVPTR(pScrn);
183	struct nouveau_pushbuf *push = pNv->pushbuf;
184	int ret;
185
186	ret = nouveau_object_new(pNv->channel, 0x0000902d, 0x902d,
187				 NULL, 0, &pNv->Nv2D);
188	if (ret)
189		return FALSE;
190
191	if (!PUSH_SPACE(push, 64))
192		return FALSE;
193
194	BEGIN_NVC0(push, NV01_SUBC(2D, OBJECT), 1);
195	PUSH_DATA (push, pNv->Nv2D->handle);
196
197	BEGIN_NVC0(push, NV50_2D(CLIP_ENABLE), 1);
198	PUSH_DATA (push, 1);
199	BEGIN_NVC0(push, NV50_2D(COLOR_KEY_ENABLE), 1);
200	PUSH_DATA (push, 0);
201	BEGIN_NVC0(push, NV50_2D(UNK0884), 1);
202	PUSH_DATA (push, 0x3f);
203	BEGIN_NVC0(push, NV50_2D(UNK0888), 1);
204	PUSH_DATA (push, 1);
205	BEGIN_NVC0(push, NV50_2D(ROP), 1);
206	PUSH_DATA (push, 0x55);
207	BEGIN_NVC0(push, NV50_2D(OPERATION), 1);
208	PUSH_DATA (push, NV50_2D_OPERATION_SRCCOPY);
209
210	BEGIN_NVC0(push, NV50_2D(BLIT_DU_DX_FRACT), 4);
211	PUSH_DATA (push, 0);
212	PUSH_DATA (push, 1);
213	PUSH_DATA (push, 0);
214	PUSH_DATA (push, 1);
215	BEGIN_NVC0(push, NV50_2D(DRAW_SHAPE), 2);
216	PUSH_DATA (push, 4);
217	PUSH_DATA (push, NV50_SURFACE_FORMAT_B5G6R5_UNORM);
218	BEGIN_NVC0(push, NV50_2D(PATTERN_COLOR_FORMAT), 2);
219	PUSH_DATA (push, 2);
220	PUSH_DATA (push, 1);
221
222	pNv->currentRop = 0xfffffffa;
223	return TRUE;
224}
225
226Bool
227NVAccelInit3D_NVC0(ScrnInfoPtr pScrn)
228{
229	NVPtr pNv = NVPTR(pScrn);
230	struct nouveau_pushbuf *push = pNv->pushbuf;
231	struct nouveau_bo *bo = pNv->scratch;
232	uint32_t class, handle;
233	int ret;
234
235	if (pNv->Architecture < NV_KEPLER) {
236		class  = 0x9097;
237		handle = 0x001f906e;
238	} else if (pNv->dev->chipset == 0xea) {
239		class = 0xa297;
240		handle = 0x0000906e;
241	} else if (pNv->dev->chipset < 0xf0) {
242		class  = 0xa097;
243		handle = 0x0000906e;
244	} else if (pNv->dev->chipset < 0x110) {
245		class  = 0xa197;
246		handle = 0x0000906e;
247	} else if (pNv->dev->chipset < 0x120) {
248		class  = 0xb097;
249		handle = 0x0000906e;
250	} else if (pNv->dev->chipset < 0x130) {
251		class  = 0xb197;
252		handle = 0x0000906e;
253	} else if (pNv->dev->chipset == 0x130) {
254		class  = 0xc097;
255		handle = 0x0000906e;
256	} else if (pNv->dev->chipset < 0x140) {
257		class  = 0xc197;
258		handle = 0x0000906e;
259	} else {
260		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
261			   "No 3D acceleration support for NV%X\n",
262			   pNv->dev->chipset);
263		return FALSE;
264	}
265
266	ret = nouveau_object_new(pNv->channel, class, class,
267				 NULL, 0, &pNv->Nv3D);
268	if (ret)
269		return FALSE;
270
271	ret = nouveau_object_new(pNv->channel, handle, 0x906e,
272				 NULL, 0, &pNv->NvSW);
273	if (ret) {
274		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
275			   "DRM doesn't support sync-to-vblank\n");
276	}
277
278	if (nouveau_pushbuf_space(push, 512, 0, 0) ||
279	    nouveau_pushbuf_refn (push, &(struct nouveau_pushbuf_refn) {
280					pNv->scratch, NOUVEAU_BO_VRAM |
281					NOUVEAU_BO_WR }, 1))
282		return FALSE;
283
284	BEGIN_NVC0(push, NV01_SUBC(3D, OBJECT), 1);
285	PUSH_DATA (push, pNv->Nv3D->handle);
286	BEGIN_NVC0(push, NVC0_3D(COND_MODE), 1);
287	PUSH_DATA (push, NVC0_3D_COND_MODE_ALWAYS);
288	BEGIN_NVC0(push, SUBC_3D(NVC0_GRAPH_NOTIFY_ADDRESS_HIGH), 3);
289	PUSH_DATA (push, (pNv->scratch->offset + NTFY_OFFSET) >> 32);
290	PUSH_DATA (push, (pNv->scratch->offset + NTFY_OFFSET));
291	PUSH_DATA (push, 0);
292	BEGIN_NVC0(push, NVC0_3D(CSAA_ENABLE), 1);
293	PUSH_DATA (push, 0);
294	BEGIN_NVC0(push, NVC0_3D(ZETA_ENABLE), 1);
295	PUSH_DATA (push, 0);
296	BEGIN_NVC0(push, NVC0_3D(RT_SEPARATE_FRAG_DATA), 1);
297	PUSH_DATA (push, 0);
298
299	BEGIN_NVC0(push, NVC0_3D(VIEWPORT_HORIZ(0)), 2);
300	PUSH_DATA (push, (8192 << 16) | 0);
301	PUSH_DATA (push, (8192 << 16) | 0);
302	BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2);
303	PUSH_DATA (push, (8192 << 16) | 0);
304	PUSH_DATA (push, (8192 << 16) | 0);
305	BEGIN_NVC0(push, NVC0_3D(SCISSOR_ENABLE(0)), 1);
306	PUSH_DATA (push, 1);
307	BEGIN_NVC0(push, NVC0_3D(VIEWPORT_TRANSFORM_EN), 1);
308	PUSH_DATA (push, 0);
309	BEGIN_NVC0(push, NVC0_3D(VIEW_VOLUME_CLIP_CTRL), 1);
310	PUSH_DATA (push, 0);
311
312	BEGIN_NVC0(push, NVC0_3D(TIC_ADDRESS_HIGH), 3);
313	PUSH_DATA (push, (bo->offset + TIC_OFFSET) >> 32);
314	PUSH_DATA (push, (bo->offset + TIC_OFFSET));
315	PUSH_DATA (push, 15);
316	BEGIN_NVC0(push, NVC0_3D(TSC_ADDRESS_HIGH), 3);
317	PUSH_DATA (push, (bo->offset + TSC_OFFSET) >> 32);
318	PUSH_DATA (push, (bo->offset + TSC_OFFSET));
319	PUSH_DATA (push, 0);
320	BEGIN_NVC0(push, NVC0_3D(LINKED_TSC), 1);
321	PUSH_DATA (push, 1);
322	if (pNv->Architecture < NV_KEPLER) {
323		BEGIN_NVC0(push, NVC0_3D(TEX_LIMITS(4)), 1);
324		PUSH_DATA (push, 0x54);
325		BEGIN_NIC0(push, NVC0_3D(BIND_TIC(4)), 2);
326		PUSH_DATA (push, (0 << 9) | (0 << 1) | NVC0_3D_BIND_TIC_ACTIVE);
327		PUSH_DATA (push, (1 << 9) | (1 << 1) | NVC0_3D_BIND_TIC_ACTIVE);
328	} else {
329		BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 6);
330		PUSH_DATA (push, 256);
331		PUSH_DATA (push, (bo->offset + TB_OFFSET) >> 32);
332		PUSH_DATA (push, (bo->offset + TB_OFFSET));
333		PUSH_DATA (push, 0);
334		PUSH_DATA (push, 0x00000000);
335		PUSH_DATA (push, 0x00000001);
336		BEGIN_NVC0(push, NVC0_3D(CB_BIND(4)), 1);
337		PUSH_DATA (push, 0x11);
338		BEGIN_NVC0(push, NVE4_3D(TEX_CB_INDEX), 1);
339		PUSH_DATA (push, 1);
340	}
341
342	if (pNv->Architecture < NV_MAXWELL) {
343		BEGIN_NVC0(push, NVC0_3D(VERTEX_QUARANTINE_ADDRESS_HIGH), 3);
344		PUSH_DATA (push, (bo->offset + MISC_OFFSET) >> 32);
345		PUSH_DATA (push, (bo->offset + MISC_OFFSET));
346		PUSH_DATA (push, 1);
347	} else {
348		/* Use new TIC format. Not strictly necessary for GM20x+ */
349		IMMED_NVC0(push, SUBC_3D(0x0f10), 1);
350		if (pNv->dev->chipset >= 0x120) {
351			/* Use center sample locations. */
352			BEGIN_NVC0(push, SUBC_3D(0x11e0), 4);
353			PUSH_DATA (push, 0x88888888);
354			PUSH_DATA (push, 0x88888888);
355			PUSH_DATA (push, 0x88888888);
356			PUSH_DATA (push, 0x88888888);
357		}
358	}
359
360	BEGIN_NVC0(push, NVC0_3D(CODE_ADDRESS_HIGH), 2);
361	PUSH_DATA (push, (bo->offset + CODE_OFFSET) >> 32);
362	PUSH_DATA (push, (bo->offset + CODE_OFFSET));
363	if (pNv->Architecture < NV_KEPLER) {
364		NVC0PushProgram(pNv, PVP_PASS, NVC0VP_Transform2);
365		NVC0PushProgram(pNv, PFP_S, NVC0FP_Source);
366		NVC0PushProgram(pNv, PFP_C, NVC0FP_Composite);
367		NVC0PushProgram(pNv, PFP_CCA, NVC0FP_CAComposite);
368		NVC0PushProgram(pNv, PFP_CCASA, NVC0FP_CACompositeSrcAlpha);
369		NVC0PushProgram(pNv, PFP_S_A8, NVC0FP_Source_A8);
370		NVC0PushProgram(pNv, PFP_C_A8, NVC0FP_Composite_A8);
371		NVC0PushProgram(pNv, PFP_NV12, NVC0FP_NV12);
372
373		BEGIN_NVC0(push, NVC0_3D(MEM_BARRIER), 1);
374		PUSH_DATA (push, 0x1111);
375	} else
376	if (pNv->dev->chipset < 0xf0 && pNv->dev->chipset != 0xea) {
377		NVC0PushProgram(pNv, PVP_PASS, NVE0VP_Transform2);
378		NVC0PushProgram(pNv, PFP_S, NVE0FP_Source);
379		NVC0PushProgram(pNv, PFP_C, NVE0FP_Composite);
380		NVC0PushProgram(pNv, PFP_CCA, NVE0FP_CAComposite);
381		NVC0PushProgram(pNv, PFP_CCASA, NVE0FP_CACompositeSrcAlpha);
382		NVC0PushProgram(pNv, PFP_S_A8, NVE0FP_Source_A8);
383		NVC0PushProgram(pNv, PFP_C_A8, NVE0FP_Composite_A8);
384		NVC0PushProgram(pNv, PFP_NV12, NVE0FP_NV12);
385	} else
386	if (pNv->dev->chipset < 0x110) {
387		NVC0PushProgram(pNv, PVP_PASS, NVF0VP_Transform2);
388		NVC0PushProgram(pNv, PFP_S, NVF0FP_Source);
389		NVC0PushProgram(pNv, PFP_C, NVF0FP_Composite);
390		NVC0PushProgram(pNv, PFP_CCA, NVF0FP_CAComposite);
391		NVC0PushProgram(pNv, PFP_CCASA, NVF0FP_CACompositeSrcAlpha);
392		NVC0PushProgram(pNv, PFP_S_A8, NVF0FP_Source_A8);
393		NVC0PushProgram(pNv, PFP_C_A8, NVF0FP_Composite_A8);
394		NVC0PushProgram(pNv, PFP_NV12, NVF0FP_NV12);
395	} else {
396		NVC0PushProgram(pNv, PVP_PASS, NV110VP_Transform2);
397		NVC0PushProgram(pNv, PFP_S, NV110FP_Source);
398		NVC0PushProgram(pNv, PFP_C, NV110FP_Composite);
399		NVC0PushProgram(pNv, PFP_CCA, NV110FP_CAComposite);
400		NVC0PushProgram(pNv, PFP_CCASA, NV110FP_CACompositeSrcAlpha);
401		NVC0PushProgram(pNv, PFP_S_A8, NV110FP_Source_A8);
402		NVC0PushProgram(pNv, PFP_C_A8, NV110FP_Composite_A8);
403		NVC0PushProgram(pNv, PFP_NV12, NV110FP_NV12);
404	}
405
406	BEGIN_NVC0(push, NVC0_3D(SP_SELECT(1)), 4);
407	PUSH_DATA (push, NVC0_3D_SP_SELECT_PROGRAM_VP_B |
408			 NVC0_3D_SP_SELECT_ENABLE);
409	PUSH_DATA (push, PVP_PASS);
410	PUSH_DATA (push, 0x00000000);
411	PUSH_DATA (push, 8);
412	BEGIN_NVC0(push, NVC0_3D(VERT_COLOR_CLAMP_EN), 1);
413	PUSH_DATA (push, 1);
414	BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
415	PUSH_DATA (push, 256);
416	PUSH_DATA (push, (bo->offset + PVP_DATA) >> 32);
417	PUSH_DATA (push, (bo->offset + PVP_DATA));
418	BEGIN_NVC0(push, NVC0_3D(CB_BIND(0)), 1);
419	PUSH_DATA (push, 0x01);
420
421	BEGIN_NVC0(push, NVC0_3D(SP_SELECT(5)), 4);
422	PUSH_DATA (push, NVC0_3D_SP_SELECT_PROGRAM_FP |
423			 NVC0_3D_SP_SELECT_ENABLE);
424	PUSH_DATA (push, PFP_S);
425	PUSH_DATA (push, 0x00000000);
426	PUSH_DATA (push, 8);
427	BEGIN_NVC0(push, NVC0_3D(FRAG_COLOR_CLAMP_EN), 1);
428	PUSH_DATA (push, 0x11111111);
429	BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
430	PUSH_DATA (push, 256);
431	PUSH_DATA (push, (bo->offset + PFP_DATA) >> 32);
432	PUSH_DATA (push, (bo->offset + PFP_DATA));
433	BEGIN_NVC0(push, NVC0_3D(CB_BIND(4)), 1);
434	PUSH_DATA (push, 0x01);
435
436	return TRUE;
437}
438
439