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
23 #include "nv_include.h"
24 #include "nv50_accel.h"
26 #if !defined(__AROS__)
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
;
36 if (!nouveau_exa_pixmap_is_onscreen(ppix
))
39 crtcs
= nv_window_belongs_to_crtc(pScrn
, box
->x1
, box
->y1
,
45 BEGIN_RING(chan
, nvsw
, 0x0060, 2);
46 OUT_RING (chan
, pNv
->vblank_sem
->handle
);
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);
59 NVAccelInitNV50TCL(ScrnInfoPtr pScrn
)
61 NVPtr pNv
= NVPTR(pScrn
);
62 struct nouveau_channel
*chan
= pNv
->chan
;
63 struct nouveau_grobj
*tesla
, *nvsw
;
67 switch (pNv
->dev
->chipset
& 0xf0) {
76 switch (pNv
->dev
->chipset
) {
95 if (nouveau_grobj_alloc(chan
, Nv3D
, class, &pNv
->Nv3D
))
98 if (nouveau_grobj_alloc(chan
, NvSW
, 0x506e, &pNv
->NvSW
)) {
99 nouveau_grobj_free(&pNv
->Nv3D
);
103 if (nouveau_notifier_alloc(chan
, NvVBlankSem
, 1,
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
);
120 if (MARK_RING(chan
, 512, 32))
123 BEGIN_RING(chan
, nvsw
, 0x018c, 1);
124 OUT_RING (chan
, pNv
->vblank_sem
->handle
);
125 BEGIN_RING(chan
, nvsw
, 0x0400, 1);
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);
141 BEGIN_RING(chan
, tesla
, NV50TCL_VIEWPORT_TRANSFORM_EN
, 1);
143 BEGIN_RING(chan
, tesla
, 0x0f90, 1);
146 BEGIN_RING(chan
, tesla
, NV50TCL_LINKED_TSC
, 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
)) {
160 OUT_RING (chan
, 0x00004000);
161 BEGIN_RING(chan
, tesla
, NV50TCL_CB_ADDR
, 1);
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);
183 if (tesla
->grclass
!= 0x8597) {
184 BEGIN_RING(chan
, tesla
, NV50TCL_VP_RESULT_MAP_SIZE
, 2);
186 OUT_RING (chan
, 0); /* NV50TCL_VP_REG_ALLOC_TEMP */
188 BEGIN_RING(chan
, tesla
, NV50TCL_VP_RESULT_MAP_SIZE
, 1);
191 BEGIN_RING(chan
, tesla
, NV50TCL_VP_START_ID
, 1);
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
)) {
202 OUT_RING (chan
, (0 << NV50TCL_CB_DEF_SET_BUFFER_SHIFT
) | 0x4000);
203 BEGIN_RING(chan
, tesla
, NV50TCL_CB_ADDR
, 1);
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
)) {
220 OUT_RING (chan
, (0 << NV50TCL_CB_DEF_SET_BUFFER_SHIFT
) | 0x4000);
221 BEGIN_RING(chan
, tesla
, NV50TCL_CB_ADDR
, 1);
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
)) {
248 OUT_RING (chan
, (0 << NV50TCL_CB_DEF_SET_BUFFER_SHIFT
) | 0x4000);
249 BEGIN_RING(chan
, tesla
, NV50TCL_CB_ADDR
, 1);
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
)) {
276 OUT_RING (chan
, (0 << NV50TCL_CB_DEF_SET_BUFFER_SHIFT
) | 0x4000);
277 BEGIN_RING(chan
, tesla
, NV50TCL_CB_ADDR
, 1);
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
)) {
304 OUT_RING (chan
, (0 << NV50TCL_CB_DEF_SET_BUFFER_SHIFT
) | 0x4000);
305 BEGIN_RING(chan
, tesla
, NV50TCL_CB_ADDR
, 1);
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
)) {
326 OUT_RING (chan
, (0 << NV50TCL_CB_DEF_SET_BUFFER_SHIFT
) | 0x4000);
327 BEGIN_RING(chan
, tesla
, NV50TCL_CB_ADDR
, 1);
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
)) {
354 OUT_RING (chan
, (0 << NV50TCL_CB_DEF_SET_BUFFER_SHIFT
) | 0x4000);
355 BEGIN_RING(chan
, tesla
, NV50TCL_CB_ADDR
, 1);
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);
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));