Use bios PLL functions on nv4x
[nouveau] / src / nv_accel_common.c
1 /*
2  * Copyright 2007 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
25 static Bool
26 NVAccelInitNullObject(ScrnInfoPtr pScrn)
27 {
28         NVPtr pNv = NVPTR(pScrn);
29
30         if (!pNv->NvNull) {
31                 if (nouveau_grobj_alloc(pNv->chan, NvNullObject, NV01_NULL,
32                                         &pNv->NvNull))
33                         return FALSE;
34         }
35
36         return TRUE;
37 }
38
39 static Bool
40 NVAccelInitDmaNotifier0(ScrnInfoPtr pScrn)
41 {
42         NVPtr pNv = NVPTR(pScrn);
43
44         if (!pNv->notify0) {
45                 if (nouveau_notifier_alloc(pNv->chan, NvDmaNotifier0, 1,
46                                            &pNv->notify0))
47                         return FALSE;
48         }
49
50         return TRUE;
51 }
52
53 /* FLAGS_ROP_AND, DmaFB, DmaFB, 0 */
54 static Bool
55 NVAccelInitContextSurfaces(ScrnInfoPtr pScrn)
56 {
57         NVPtr pNv = NVPTR(pScrn);
58         uint32_t   class;
59
60         class = (pNv->Architecture >= NV_10) ? NV10_CONTEXT_SURFACES_2D :
61                                                NV04_CONTEXT_SURFACES_2D;
62
63         if (!pNv->NvContextSurfaces) {
64                 if (nouveau_grobj_alloc(pNv->chan, NvContextSurfaces, class,
65                                         &pNv->NvContextSurfaces))
66                         return FALSE;
67         }
68
69         BEGIN_RING(NvContextSurfaces, NV04_CONTEXT_SURFACES_2D_DMA_NOTIFY, 1);
70         OUT_RING  (pNv->NvNull->handle);
71         BEGIN_RING(NvContextSurfaces,
72                    NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
73         OUT_RING  (pNv->chan->vram->handle);
74         OUT_RING  (pNv->chan->vram->handle);
75
76         return TRUE;
77 }
78
79 /* FLAGS_ROP_AND, DmaFB, DmaFB, 0 */
80 static Bool
81 NVAccelInitContextBeta1(ScrnInfoPtr pScrn)
82 {
83         NVPtr pNv = NVPTR(pScrn);
84         uint32_t   class;
85
86         class = 0x12;
87
88         if (!pNv->NvContextBeta1) {
89                 if (nouveau_grobj_alloc(pNv->chan, NvContextBeta1, class,
90                                         &pNv->NvContextBeta1))
91                         return FALSE;
92         }
93
94         BEGIN_RING(NvContextBeta1, 0x300, 1); /*alpha factor*/
95         OUT_RING  (0xff << 23);
96
97         return TRUE;
98 }
99
100
101 static Bool
102 NVAccelInitContextBeta4(ScrnInfoPtr pScrn)
103 {
104         NVPtr pNv = NVPTR(pScrn);
105         uint32_t   class;
106         
107         class = 0x72;
108
109         if (!pNv->NvContextBeta4) {
110                 if (nouveau_grobj_alloc(pNv->chan, NvContextBeta4, class,
111                                         &pNv->NvContextBeta4))
112                         return FALSE;
113         }
114
115         BEGIN_RING(NvContextBeta4, 0x300, 1); /*RGBA factor*/
116         OUT_RING  (0xffff0000);
117         return TRUE;
118 }
119
120 Bool
121 NVAccelGetCtxSurf2DFormatFromPixmap(PixmapPtr pPix, int *fmt_ret)
122 {
123         switch (pPix->drawable.bitsPerPixel) {
124         case 32:
125                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8;
126                 break;
127         case 24:
128                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_X8R8G8B8_Z8R8G8B8;
129                 break;
130         case 16:
131                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
132                 break;
133         case 8:
134                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
135                 break;
136         default:
137                 return FALSE;
138         }
139
140         return TRUE;
141 }
142
143 Bool
144 NVAccelGetCtxSurf2DFormatFromPicture(PicturePtr pPict, int *fmt_ret)
145 {
146         switch (pPict->format) {
147         case PICT_a8r8g8b8:
148                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8;
149                 break;
150         case PICT_x8r8g8b8:
151                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_X8R8G8B8_Z8R8G8B8;
152                 break;
153         case PICT_r5g6b5:
154                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
155                 break;
156         case PICT_a8:
157                 *fmt_ret = NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
158                 break;
159         default:
160                 return FALSE;
161         }
162
163         return TRUE;
164 }
165
166 static Bool
167 NVAccelInitImagePattern(ScrnInfoPtr pScrn)
168 {
169         NVPtr pNv = NVPTR(pScrn);
170         uint32_t   class;
171
172         class = NV04_IMAGE_PATTERN;
173
174         if (!pNv->NvImagePattern) {
175                 if (nouveau_grobj_alloc(pNv->chan, NvImagePattern, class,
176                                         &pNv->NvImagePattern))
177                         return FALSE;
178         }
179
180         BEGIN_RING(NvImagePattern, NV04_IMAGE_PATTERN_DMA_NOTIFY, 1);
181         OUT_RING  (pNv->NvNull->handle);
182         BEGIN_RING(NvImagePattern, NV04_IMAGE_PATTERN_MONOCHROME_FORMAT, 3);
183 #if X_BYTE_ORDER == X_BIG_ENDIAN
184         OUT_RING  (NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_LE);
185 #else
186         OUT_RING  (NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_CGA6);
187 #endif
188         OUT_RING  (NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_8X8);
189         OUT_RING  (NV04_IMAGE_PATTERN_PATTERN_SELECT_MONO);
190
191         return TRUE;
192 }
193
194 static Bool
195 NVAccelInitRasterOp(ScrnInfoPtr pScrn)
196 {
197         NVPtr pNv = NVPTR(pScrn);
198         uint32_t   class;
199
200         class = NV03_CONTEXT_ROP;
201
202         if (!pNv->NvRop) {
203                 if (nouveau_grobj_alloc(pNv->chan, NvRop, class,
204                                         &pNv->NvRop))
205                         return FALSE;
206         }
207
208         BEGIN_RING(NvRop, NV03_CONTEXT_ROP_DMA_NOTIFY, 1);
209         OUT_RING  (pNv->NvNull->handle);
210
211         pNv->currentRop = ~0;
212         return TRUE;
213 }
214
215 static Bool
216 NVAccelInitRectangle(ScrnInfoPtr pScrn)
217 {
218         NVPtr pNv = NVPTR(pScrn);
219         uint32_t   class;
220
221         class = NV04_GDI_RECTANGLE_TEXT;
222
223         if (!pNv->NvRectangle) {
224                 if (nouveau_grobj_alloc(pNv->chan, NvRectangle, class,
225                                         &pNv->NvRectangle))
226                         return FALSE;
227         }
228
229         BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY, 1);
230         OUT_RING  (pNv->notify0->handle);
231         BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_DMA_FONTS, 1);
232         OUT_RING  (pNv->NvNull->handle);
233         BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_SURFACE, 1);
234         OUT_RING  (pNv->NvContextSurfaces->handle);
235         BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_ROP, 1);
236         OUT_RING  (pNv->NvRop->handle);
237         BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_PATTERN, 1);
238         OUT_RING  (pNv->NvImagePattern->handle);
239         BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_OPERATION, 1);
240         OUT_RING  (NV04_GDI_RECTANGLE_TEXT_OPERATION_ROP_AND);
241         BEGIN_RING(NvRectangle, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT, 1);
242         /* XXX why putting 1 like renouveau dump, swap the text */
243 #if 1 || X_BYTE_ORDER == X_BIG_ENDIAN
244         OUT_RING  (NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
245 #else
246         OUT_RING  (NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_CGA6);
247 #endif
248
249         return TRUE;
250 }
251
252 static Bool
253 NVAccelInitImageBlit(ScrnInfoPtr pScrn)
254 {
255         NVPtr pNv = NVPTR(pScrn);
256         uint32_t   class;
257
258         class = (pNv->WaitVSyncPossible) ? NV12_IMAGE_BLIT : NV04_IMAGE_BLIT;
259
260         if (!pNv->NvImageBlit) {
261                 if (nouveau_grobj_alloc(pNv->chan, NvImageBlit, class,
262                                         &pNv->NvImageBlit))
263                         return FALSE;
264         }
265
266         BEGIN_RING(NvImageBlit, NV04_IMAGE_BLIT_DMA_NOTIFY, 1);
267         OUT_RING  (pNv->notify0->handle);
268         BEGIN_RING(NvImageBlit, NV04_IMAGE_BLIT_COLOR_KEY, 1);
269         OUT_RING  (pNv->NvNull->handle);
270         BEGIN_RING(NvImageBlit, NV04_IMAGE_BLIT_SURFACE, 1);
271         OUT_RING  (pNv->NvContextSurfaces->handle);
272         BEGIN_RING(NvImageBlit, NV04_IMAGE_BLIT_CLIP_RECTANGLE, 3);
273         OUT_RING  (pNv->NvNull->handle);
274         OUT_RING  (pNv->NvImagePattern->handle);
275         OUT_RING  (pNv->NvRop->handle);
276         BEGIN_RING(NvImageBlit, NV04_IMAGE_BLIT_OPERATION, 1);
277         OUT_RING  (NV04_IMAGE_BLIT_OPERATION_ROP_AND);
278
279         if (pNv->WaitVSyncPossible) {
280                 BEGIN_RING(NvImageBlit, 0x0120, 3);
281                 OUT_RING  (0);
282                 OUT_RING  (1);
283                 OUT_RING  (2);
284         }
285
286         return TRUE;
287 }
288
289 static Bool
290 NVAccelInitScaledImage(ScrnInfoPtr pScrn)
291 {
292         NVPtr pNv = NVPTR(pScrn);
293         uint32_t   class;
294
295         switch (pNv->Architecture) {
296         case NV_ARCH_04:
297                 class = NV04_SCALED_IMAGE_FROM_MEMORY;
298                 break;
299         case NV_ARCH_10:
300         case NV_ARCH_20:
301         case NV_ARCH_30:
302                 class = NV10_SCALED_IMAGE_FROM_MEMORY;
303                 break;
304         case NV_ARCH_40:
305         default:
306                 class = NV10_SCALED_IMAGE_FROM_MEMORY | 0x3000;
307                 break;
308         }
309
310         if (!pNv->NvScaledImage) {
311                 if (nouveau_grobj_alloc(pNv->chan, NvScaledImage, class,
312                                         &pNv->NvScaledImage))
313                         return FALSE;
314         }
315
316         BEGIN_RING(NvScaledImage,
317                         NV04_SCALED_IMAGE_FROM_MEMORY_DMA_NOTIFY, 7);
318         OUT_RING  (pNv->notify0->handle);
319         OUT_RING  (pNv->chan->vram->handle);
320         OUT_RING  (pNv->NvNull->handle);
321         OUT_RING  (pNv->NvNull->handle);
322         OUT_RING  (pNv->NvContextBeta1->handle);
323         OUT_RING  (pNv->NvContextBeta4->handle);
324         OUT_RING  (pNv->NvContextSurfaces->handle);
325         if (pNv->Architecture>=NV_ARCH_10) {
326         BEGIN_RING(NvScaledImage,
327                    NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 1);
328         OUT_RING  (NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_DITHER);
329         }
330         BEGIN_RING(NvScaledImage, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION, 1);
331         OUT_RING  (NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
332
333         return TRUE;
334 }
335
336 static Bool
337 NVAccelInitClipRectangle(ScrnInfoPtr pScrn)
338 {
339         NVPtr pNv = NVPTR(pScrn);
340         int class = NV01_CONTEXT_CLIP_RECTANGLE;
341
342         if (!pNv->NvClipRectangle) {
343                 if (nouveau_grobj_alloc(pNv->chan, NvClipRectangle, class,
344                                         &pNv->NvClipRectangle))
345                         return FALSE;
346         }
347
348         BEGIN_RING(NvClipRectangle, NV01_CONTEXT_CLIP_RECTANGLE_DMA_NOTIFY, 1);
349         OUT_RING  (pNv->NvNull->handle);
350
351         return TRUE;
352 }
353
354 /* FLAGS_NONE, NvDmaFB, NvDmaAGP, NvDmaNotifier0 */
355 static Bool
356 NVAccelInitMemFormat(ScrnInfoPtr pScrn)
357 {
358         NVPtr pNv = NVPTR(pScrn);
359         uint32_t   class;
360
361         if (pNv->Architecture < NV_ARCH_50)
362                 class = NV04_MEMORY_TO_MEMORY_FORMAT;
363         else
364                 class = NV50_MEMORY_TO_MEMORY_FORMAT;
365
366         if (!pNv->NvMemFormat) {
367                 if (nouveau_grobj_alloc(pNv->chan, NvMemFormat, class,
368                                         &pNv->NvMemFormat))
369                         return FALSE;
370         }
371
372         BEGIN_RING(NvMemFormat, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
373         OUT_RING  (pNv->notify0->handle);
374         BEGIN_RING(NvMemFormat, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
375         OUT_RING  (pNv->chan->vram->handle);
376         OUT_RING  (pNv->chan->vram->handle);
377
378         return TRUE;
379 }
380
381 static Bool
382 NVAccelInitImageFromCpu(ScrnInfoPtr pScrn)
383 {
384         NVPtr pNv = NVPTR(pScrn);
385         uint32_t   class;
386
387         switch (pNv->Architecture) {
388         case NV_ARCH_04:
389                 class = NV04_IMAGE_FROM_CPU;
390                 break;
391         case NV_ARCH_10:
392         case NV_ARCH_20:
393         case NV_ARCH_30:
394         case NV_ARCH_40:
395         default:
396                 class = NV10_IMAGE_FROM_CPU;
397                 break;
398         }
399
400         if (!pNv->NvImageFromCpu) {
401                 if (nouveau_grobj_alloc(pNv->chan, NvImageFromCpu, class,
402                                         &pNv->NvImageFromCpu))
403                         return FALSE;
404         }
405
406         BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_DMA_NOTIFY, 1);
407         OUT_RING  (pNv->notify0->handle);
408         BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_CLIP_RECTANGLE, 1);
409         OUT_RING  (pNv->NvNull->handle);
410         BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_PATTERN, 1);
411         OUT_RING  (pNv->NvNull->handle);
412         BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_ROP, 1);
413         OUT_RING  (pNv->NvNull->handle);
414         if (pNv->Architecture >= NV_ARCH_10)
415         {
416                 BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_BETA1, 1);
417                 OUT_RING  (pNv->NvNull->handle);
418                 BEGIN_RING(NvImageFromCpu, NV05_IMAGE_FROM_CPU_BETA4, 1);
419                 OUT_RING  (pNv->NvNull->handle);
420         }
421         BEGIN_RING(NvImageFromCpu, NV05_IMAGE_FROM_CPU_SURFACE, 1);
422         OUT_RING  (pNv->NvContextSurfaces->handle);
423         BEGIN_RING(NvImageFromCpu, NV01_IMAGE_FROM_CPU_OPERATION, 1);
424         OUT_RING  (NV01_IMAGE_FROM_CPU_OPERATION_SRCCOPY);
425         return TRUE;
426 }
427
428 static Bool
429 NVAccelInit2D_NV50(ScrnInfoPtr pScrn)
430 {
431         NVPtr pNv = NVPTR(pScrn);
432
433         if (!pNv->Nv2D) {
434                 if (nouveau_grobj_alloc(pNv->chan, Nv2D, 0x502d,
435                                         &pNv->Nv2D))
436                         return FALSE;
437         }
438
439         BEGIN_RING(Nv2D, 0x180, 3);
440         OUT_RING  (pNv->notify0->handle);
441         OUT_RING  (pNv->chan->vram->handle);
442         OUT_RING  (pNv->chan->vram->handle);
443
444         /* Magics from nv, no clue what they do, but at least some
445          * of them are needed to avoid crashes.
446          */
447         BEGIN_RING(Nv2D, 0x260, 1);
448         OUT_RING  (1);
449         BEGIN_RING(Nv2D, 0x290, 1);
450         OUT_RING  (1);
451         BEGIN_RING(Nv2D, 0x29c, 1);
452         OUT_RING  (0);
453         BEGIN_RING(Nv2D, 0x58c, 1);
454         OUT_RING  (0x111);
455
456         pNv->currentRop = 0xfffffffa;
457         return TRUE;
458 }
459
460 #define INIT_CONTEXT_OBJECT(name) do {                                        \
461         ret = NVAccelInit##name(pScrn);                                       \
462         if (!ret) {                                                           \
463                 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,                         \
464                            "Failed to initialise context object: "#name       \
465                            " (%d)\n", ret);                                   \
466                 return FALSE;                                                 \
467         }                                                                     \
468 } while(0)
469
470 Bool
471 NVAccelCommonInit(ScrnInfoPtr pScrn)
472 {
473         NVPtr pNv = NVPTR(pScrn);
474         Bool ret;
475         if(pNv->NoAccel) return TRUE;
476
477         /* General engine objects */
478         INIT_CONTEXT_OBJECT(NullObject);
479         INIT_CONTEXT_OBJECT(DmaNotifier0);
480
481         /* 2D engine */
482         if (pNv->Architecture < NV_ARCH_50) {
483                 INIT_CONTEXT_OBJECT(ContextSurfaces);
484                 INIT_CONTEXT_OBJECT(ContextBeta1);
485                 INIT_CONTEXT_OBJECT(ContextBeta4);
486                 INIT_CONTEXT_OBJECT(ImagePattern);
487                 INIT_CONTEXT_OBJECT(RasterOp);
488                 INIT_CONTEXT_OBJECT(Rectangle);
489                 INIT_CONTEXT_OBJECT(ImageBlit);
490                 INIT_CONTEXT_OBJECT(ScaledImage);
491                 INIT_CONTEXT_OBJECT(ClipRectangle);
492                 INIT_CONTEXT_OBJECT(ImageFromCpu);
493         } else {
494                 INIT_CONTEXT_OBJECT(2D_NV50);
495         }
496         INIT_CONTEXT_OBJECT(MemFormat);
497
498         /* 3D init */
499         switch (pNv->Architecture) {
500         case NV_ARCH_40:
501                 INIT_CONTEXT_OBJECT(NV40TCL);
502                 break;
503         case NV_ARCH_30:
504                 INIT_CONTEXT_OBJECT(NV30TCL);
505                 break;
506         case NV_ARCH_20:
507         case NV_ARCH_10:
508                 INIT_CONTEXT_OBJECT(NV10TCL);
509                 break;
510         default:
511                 break;
512         }
513
514         return TRUE;
515 }
516