Hint added.
[AROS.git] / workbench / hidds / nouveau / xf86-video-nouveau / nv50_accel.c
blob15899ef2ea857bb34e1c2455b914b1509bac801c
1 /*
2 * Copyright 2008 Ben Skeggs
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
23 #include "nv_include.h"
24 #include "nv50_accel.h"
26 #if !defined(__AROS__)
27 void
28 NV50SyncToVBlank(PixmapPtr ppix, BoxPtr box)
30 ScrnInfoPtr pScrn = xf86Screens[ppix->drawable.pScreen->myNum];
31 NVPtr pNv = NVPTR(pScrn);
32 struct nouveau_channel *chan = pNv->chan;
33 struct nouveau_grobj *nvsw = pNv->NvSW;
34 int crtcs;
36 if (!nouveau_exa_pixmap_is_onscreen(ppix))
37 return;
39 crtcs = nv_window_belongs_to_crtc(pScrn, box->x1, box->y1,
40 box->x2 - box->x1,
41 box->y2 - box->y1);
42 if (!crtcs)
43 return;
45 BEGIN_RING(chan, nvsw, 0x0060, 2);
46 OUT_RING (chan, pNv->vblank_sem->handle);
47 OUT_RING (chan, 0);
48 BEGIN_RING(chan, nvsw, 0x006c, 1);
49 OUT_RING (chan, 0x22222222);
50 BEGIN_RING(chan, nvsw, 0x0404, 2);
51 OUT_RING (chan, 0x11111111);
52 OUT_RING (chan, ffs(crtcs) - 1);
53 BEGIN_RING(chan, nvsw, 0x0068, 1);
54 OUT_RING (chan, 0x11111111);
56 #endif
58 Bool
59 NVAccelInitNV50TCL(ScrnInfoPtr pScrn)
61 NVPtr pNv = NVPTR(pScrn);
62 struct nouveau_channel *chan = pNv->chan;
63 struct nouveau_grobj *tesla, *nvsw;
64 unsigned class;
65 int i;
67 switch (pNv->dev->chipset & 0xf0) {
68 case 0x50:
69 class = NV50TCL;
70 break;
71 case 0x80:
72 case 0x90:
73 class = NV84TCL;
74 break;
75 case 0xa0:
76 switch (pNv->dev->chipset) {
77 case 0xa0:
78 case 0xaa:
79 case 0xac:
80 class = NVA0TCL;
81 break;
82 case 0xaf:
83 class = NVAFTCL;
84 break;
85 default:
86 class = NVA8TCL;
87 break;
89 break;
90 default:
91 return FALSE;
94 if (!pNv->Nv3D) {
95 if (nouveau_grobj_alloc(chan, Nv3D, class, &pNv->Nv3D))
96 return FALSE;
98 if (nouveau_grobj_alloc(chan, NvSW, 0x506e, &pNv->NvSW)) {
99 nouveau_grobj_free(&pNv->Nv3D);
100 return FALSE;
103 if (nouveau_notifier_alloc(chan, NvVBlankSem, 1,
104 &pNv->vblank_sem)) {
105 nouveau_grobj_free(&pNv->NvSW);
106 nouveau_grobj_free(&pNv->Nv3D);
109 if (nouveau_bo_new(pNv->dev, NOUVEAU_BO_VRAM, 0, 65536,
110 &pNv->tesla_scratch)) {
111 nouveau_notifier_free(&pNv->vblank_sem);
112 nouveau_grobj_free(&pNv->NvSW);
113 nouveau_grobj_free(&pNv->Nv3D);
114 return FALSE;
117 tesla = pNv->Nv3D;
118 nvsw = pNv->NvSW;
120 if (MARK_RING(chan, 512, 32))
121 return FALSE;
123 BEGIN_RING(chan, nvsw, 0x018c, 1);
124 OUT_RING (chan, pNv->vblank_sem->handle);
125 BEGIN_RING(chan, nvsw, 0x0400, 1);
126 OUT_RING (chan, 0);
128 BEGIN_RING(chan, tesla, NV50TCL_COND_MODE, 1);
129 OUT_RING (chan, NV50TCL_COND_MODE_ALWAYS);
130 BEGIN_RING(chan, tesla, NV50TCL_DMA_NOTIFY, 1);
131 OUT_RING (chan, chan->nullobj->handle);
132 BEGIN_RING(chan, tesla, NV50TCL_DMA_ZETA, 11);
133 for (i = 0; i < 11; i++)
134 OUT_RING (chan, pNv->chan->vram->handle);
135 BEGIN_RING(chan, tesla, NV50TCL_DMA_COLOR(0), NV50TCL_DMA_COLOR__SIZE);
136 for (i = 0; i < NV50TCL_DMA_COLOR__SIZE; i++)
137 OUT_RING (chan, pNv->chan->vram->handle);
138 BEGIN_RING(chan, tesla, NV50TCL_RT_CONTROL, 1);
139 OUT_RING (chan, 1);
141 BEGIN_RING(chan, tesla, NV50TCL_VIEWPORT_TRANSFORM_EN, 1);
142 OUT_RING (chan, 0);
143 BEGIN_RING(chan, tesla, 0x0f90, 1);
144 OUT_RING (chan, 1);
146 BEGIN_RING(chan, tesla, NV50TCL_LINKED_TSC, 1);
147 OUT_RING (chan, 1);
149 BEGIN_RING(chan, tesla, NV50TCL_TEX_LIMITS(2), 1);
150 OUT_RING (chan, 0x54);
152 BEGIN_RING(chan, tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
153 if (OUT_RELOCh(chan, pNv->tesla_scratch, PVP_OFFSET,
154 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR) ||
155 OUT_RELOCl(chan, pNv->tesla_scratch, PVP_OFFSET,
156 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) {
157 MARK_UNDO(chan);
158 return FALSE;
160 OUT_RING (chan, 0x00004000);
161 BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
162 OUT_RING (chan, 0);
163 BEGIN_RING_NI(chan, tesla, NV50TCL_CB_DATA(0), (3*2*2));
164 OUT_RING (chan, 0x10000001);
165 OUT_RING (chan, 0x0423c788);
166 OUT_RING (chan, 0x10000205);
167 OUT_RING (chan, 0x0423c788);
168 OUT_RING (chan, 0x10000409);
169 OUT_RING (chan, 0x0423c788);
170 OUT_RING (chan, 0x1000060d);
171 OUT_RING (chan, 0x0423c788);
172 OUT_RING (chan, 0x10000811);
173 OUT_RING (chan, 0x0423c788);
174 OUT_RING (chan, 0x10000a15);
175 OUT_RING (chan, 0x0423c789);
177 /* fetch only VTX_ATTR[0,8,9].xy */
178 BEGIN_RING(chan, tesla, NV50TCL_VP_ATTR_EN_0, 2);
179 OUT_RING (chan, 0x00000003);
180 OUT_RING (chan, 0x00000033);
181 BEGIN_RING(chan, tesla, NV50TCL_VP_REG_ALLOC_RESULT, 1);
182 OUT_RING (chan, 6);
183 if (tesla->grclass != 0x8597) {
184 BEGIN_RING(chan, tesla, NV50TCL_VP_RESULT_MAP_SIZE, 2);
185 OUT_RING (chan, 8);
186 OUT_RING (chan, 0); /* NV50TCL_VP_REG_ALLOC_TEMP */
187 } else {
188 BEGIN_RING(chan, tesla, NV50TCL_VP_RESULT_MAP_SIZE, 1);
189 OUT_RING (chan, 8);
191 BEGIN_RING(chan, tesla, NV50TCL_VP_START_ID, 1);
192 OUT_RING (chan, 0);
194 BEGIN_RING(chan, tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
195 if (OUT_RELOCh(chan, pNv->tesla_scratch,
196 PFP_OFFSET + PFP_S, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR) ||
197 OUT_RELOCl(chan, pNv->tesla_scratch,
198 PFP_OFFSET + PFP_S, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) {
199 MARK_UNDO(chan);
200 return FALSE;
202 OUT_RING (chan, (0 << NV50TCL_CB_DEF_SET_BUFFER_SHIFT) | 0x4000);
203 BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
204 OUT_RING (chan, 0);
205 BEGIN_RING_NI(chan, tesla, NV50TCL_CB_DATA(0), 6);
206 OUT_RING (chan, 0x80000000);
207 OUT_RING (chan, 0x90000004);
208 OUT_RING (chan, 0x82010200);
209 OUT_RING (chan, 0x82020204);
210 OUT_RING (chan, 0xf6400001);
211 OUT_RING (chan, 0x0000c785);
212 BEGIN_RING(chan, tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
213 if (OUT_RELOCh(chan, pNv->tesla_scratch,
214 PFP_OFFSET + PFP_C, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR) ||
215 OUT_RELOCl(chan, pNv->tesla_scratch,
216 PFP_OFFSET + PFP_C, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) {
217 MARK_UNDO(chan);
218 return FALSE;
220 OUT_RING (chan, (0 << NV50TCL_CB_DEF_SET_BUFFER_SHIFT) | 0x4000);
221 BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
222 OUT_RING (chan, 0);
223 BEGIN_RING_NI(chan, tesla, NV50TCL_CB_DATA(0), 16);
224 OUT_RING (chan, 0x80000000);
225 OUT_RING (chan, 0x90000004);
226 OUT_RING (chan, 0x82030210);
227 OUT_RING (chan, 0x82040214);
228 OUT_RING (chan, 0x82010200);
229 OUT_RING (chan, 0x82020204);
230 OUT_RING (chan, 0xf6400001);
231 OUT_RING (chan, 0x0000c784);
232 OUT_RING (chan, 0xf0400211);
233 OUT_RING (chan, 0x00008784);
234 OUT_RING (chan, 0xc0040000);
235 OUT_RING (chan, 0xc0040204);
236 OUT_RING (chan, 0xc0040409);
237 OUT_RING (chan, 0x00000780);
238 OUT_RING (chan, 0xc004060d);
239 OUT_RING (chan, 0x00000781);
240 BEGIN_RING(chan, tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
241 if (OUT_RELOCh(chan, pNv->tesla_scratch,
242 PFP_OFFSET + PFP_CCA, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR) ||
243 OUT_RELOCl(chan, pNv->tesla_scratch,
244 PFP_OFFSET + PFP_CCA, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) {
245 MARK_UNDO(chan);
246 return FALSE;
248 OUT_RING (chan, (0 << NV50TCL_CB_DEF_SET_BUFFER_SHIFT) | 0x4000);
249 BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
250 OUT_RING (chan, 0);
251 BEGIN_RING_NI(chan, tesla, NV50TCL_CB_DATA(0), 16);
252 OUT_RING (chan, 0x80000000);
253 OUT_RING (chan, 0x90000004);
254 OUT_RING (chan, 0x82030210);
255 OUT_RING (chan, 0x82040214);
256 OUT_RING (chan, 0x82010200);
257 OUT_RING (chan, 0x82020204);
258 OUT_RING (chan, 0xf6400001);
259 OUT_RING (chan, 0x0000c784);
260 OUT_RING (chan, 0xf6400211);
261 OUT_RING (chan, 0x0000c784);
262 OUT_RING (chan, 0xc0040000);
263 OUT_RING (chan, 0xc0050204);
264 OUT_RING (chan, 0xc0060409);
265 OUT_RING (chan, 0x00000780);
266 OUT_RING (chan, 0xc007060d);
267 OUT_RING (chan, 0x00000781);
268 BEGIN_RING(chan, tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
269 if (OUT_RELOCh(chan, pNv->tesla_scratch, PFP_OFFSET + PFP_CCASA,
270 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR) ||
271 OUT_RELOCl(chan, pNv->tesla_scratch, PFP_OFFSET + PFP_CCASA,
272 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) {
273 MARK_UNDO(chan);
274 return FALSE;
276 OUT_RING (chan, (0 << NV50TCL_CB_DEF_SET_BUFFER_SHIFT) | 0x4000);
277 BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
278 OUT_RING (chan, 0);
279 BEGIN_RING_NI(chan, tesla, NV50TCL_CB_DATA(0), 16);
280 OUT_RING (chan, 0x80000000);
281 OUT_RING (chan, 0x90000004);
282 OUT_RING (chan, 0x82030200);
283 OUT_RING (chan, 0x82040204);
284 OUT_RING (chan, 0x82010210);
285 OUT_RING (chan, 0x82020214);
286 OUT_RING (chan, 0xf6400201);
287 OUT_RING (chan, 0x0000c784);
288 OUT_RING (chan, 0xf0400011);
289 OUT_RING (chan, 0x00008784);
290 OUT_RING (chan, 0xc0040000);
291 OUT_RING (chan, 0xc0040204);
292 OUT_RING (chan, 0xc0040409);
293 OUT_RING (chan, 0x00000780);
294 OUT_RING (chan, 0xc004060d);
295 OUT_RING (chan, 0x00000781);
296 BEGIN_RING(chan, tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
297 if (OUT_RELOCh(chan, pNv->tesla_scratch, PFP_OFFSET + PFP_S_A8,
298 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR) ||
299 OUT_RELOCl(chan, pNv->tesla_scratch, PFP_OFFSET + PFP_S_A8,
300 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) {
301 MARK_UNDO(chan);
302 return FALSE;
304 OUT_RING (chan, (0 << NV50TCL_CB_DEF_SET_BUFFER_SHIFT) | 0x4000);
305 BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
306 OUT_RING (chan, 0);
307 BEGIN_RING_NI(chan, tesla, NV50TCL_CB_DATA(0), 10);
308 OUT_RING (chan, 0x80000000);
309 OUT_RING (chan, 0x90000004);
310 OUT_RING (chan, 0x82010200);
311 OUT_RING (chan, 0x82020204);
312 OUT_RING (chan, 0xf0400001);
313 OUT_RING (chan, 0x00008784);
314 OUT_RING (chan, 0x10008004);
315 OUT_RING (chan, 0x10008008);
316 OUT_RING (chan, 0x1000000d);
317 OUT_RING (chan, 0x0403c781);
318 BEGIN_RING(chan, tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
319 if (OUT_RELOCh(chan, pNv->tesla_scratch, PFP_OFFSET + PFP_C_A8,
320 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR) ||
321 OUT_RELOCl(chan, pNv->tesla_scratch, PFP_OFFSET + PFP_C_A8,
322 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) {
323 MARK_UNDO(chan);
324 return FALSE;
326 OUT_RING (chan, (0 << NV50TCL_CB_DEF_SET_BUFFER_SHIFT) | 0x4000);
327 BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
328 OUT_RING (chan, 0);
329 BEGIN_RING_NI(chan, tesla, NV50TCL_CB_DATA(0), 16);
330 OUT_RING (chan, 0x80000000);
331 OUT_RING (chan, 0x90000004);
332 OUT_RING (chan, 0x82030208);
333 OUT_RING (chan, 0x8204020c);
334 OUT_RING (chan, 0x82010200);
335 OUT_RING (chan, 0x82020204);
336 OUT_RING (chan, 0xf0400001);
337 OUT_RING (chan, 0x00008784);
338 OUT_RING (chan, 0xf0400209);
339 OUT_RING (chan, 0x00008784);
340 OUT_RING (chan, 0xc002000d);
341 OUT_RING (chan, 0x00000780);
342 OUT_RING (chan, 0x10008600);
343 OUT_RING (chan, 0x10008604);
344 OUT_RING (chan, 0x10000609);
345 OUT_RING (chan, 0x0403c781);
346 BEGIN_RING(chan, tesla, NV50TCL_CB_DEF_ADDRESS_HIGH, 3);
347 if (OUT_RELOCh(chan, pNv->tesla_scratch, PFP_OFFSET + PFP_NV12,
348 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR) ||
349 OUT_RELOCl(chan, pNv->tesla_scratch, PFP_OFFSET + PFP_NV12,
350 NOUVEAU_BO_VRAM | NOUVEAU_BO_WR)) {
351 MARK_UNDO(chan);
352 return FALSE;
354 OUT_RING (chan, (0 << NV50TCL_CB_DEF_SET_BUFFER_SHIFT) | 0x4000);
355 BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
356 OUT_RING (chan, 0);
357 BEGIN_RING_NI(chan, tesla, NV50TCL_CB_DATA(0), 24);
358 OUT_RING (chan, 0x80000008);
359 OUT_RING (chan, 0x90000408);
360 OUT_RING (chan, 0x82010400);
361 OUT_RING (chan, 0x82020404);
362 OUT_RING (chan, 0xf0400001);
363 OUT_RING (chan, 0x00008784);
364 OUT_RING (chan, 0xc0800014);
365 OUT_RING (chan, 0xb0810a0c);
366 OUT_RING (chan, 0xb0820a10);
367 OUT_RING (chan, 0xb0830a14);
368 OUT_RING (chan, 0x82030400);
369 OUT_RING (chan, 0x82040404);
370 OUT_RING (chan, 0xf0400201);
371 OUT_RING (chan, 0x0000c784);
372 OUT_RING (chan, 0xe084000c);
373 OUT_RING (chan, 0xe0850010);
374 OUT_RING (chan, 0xe0860015);
375 OUT_RING (chan, 0x00014780);
376 OUT_RING (chan, 0xe0870201);
377 OUT_RING (chan, 0x0000c780);
378 OUT_RING (chan, 0xe0890209);
379 OUT_RING (chan, 0x00014780);
380 OUT_RING (chan, 0xe0880205);
381 OUT_RING (chan, 0x00010781);
383 /* HPOS.xy = ($o0, $o1), HPOS.zw = (0.0, 1.0), then map $o2 - $o5 */
384 BEGIN_RING(chan, tesla, NV50TCL_VP_RESULT_MAP(0), 2);
385 OUT_RING (chan, 0x41400100);
386 OUT_RING (chan, 0x05040302);
387 BEGIN_RING(chan, tesla, NV50TCL_POINT_SPRITE_ENABLE, 1);
388 OUT_RING (chan, 0x00000000);
389 BEGIN_RING(chan, tesla, NV50TCL_FP_INTERPOLANT_CTRL, 2);
390 OUT_RING (chan, 0x08040404);
391 OUT_RING (chan, 0x00000008); /* NV50TCL_FP_REG_ALLOC_TEMP */
393 BEGIN_RING(chan, tesla, NV50TCL_SCISSOR_ENABLE(0), 1);
394 OUT_RING (chan, 1);
396 BEGIN_RING(chan, tesla, NV50TCL_VIEWPORT_HORIZ(0), 2);
397 OUT_RING (chan, 8192 << NV50TCL_VIEWPORT_HORIZ_W_SHIFT);
398 OUT_RING (chan, 8192 << NV50TCL_VIEWPORT_VERT_H_SHIFT);
399 /* NV50TCL_SCISSOR_VERT_T_SHIFT is wrong, because it was deducted with
400 * origin lying at the bottom left. This will be changed to _MIN_ and _MAX_
401 * later, because it is origin dependent.
403 BEGIN_RING(chan, tesla, NV50TCL_SCISSOR_HORIZ(0), 2);
404 OUT_RING (chan, 8192 << NV50TCL_SCISSOR_HORIZ_MAX_SHIFT);
405 OUT_RING (chan, 8192 << NV50TCL_SCISSOR_VERT_MAX_SHIFT);
406 BEGIN_RING(chan, tesla, NV50TCL_SCREEN_SCISSOR_HORIZ, 2);
407 OUT_RING (chan, 8192 << NV50TCL_SCREEN_SCISSOR_HORIZ_W_SHIFT);
408 OUT_RING (chan, 8192 << NV50TCL_SCREEN_SCISSOR_VERT_H_SHIFT);
410 BEGIN_RING(chan, tesla, NV50TCL_SET_PROGRAM_CB, 1);
411 OUT_RING (chan, 0x00000031 | (CB_PFP << 12));
413 return TRUE;