nvbios: Add some valid register ranges for nv50.
[nouveau] / src / nv50_exa.c
1 #include "nv_include.h"
2
3 #define NV50EXA_LOCALS(p)                                              \
4         ScrnInfoPtr pScrn = xf86Screens[(p)->drawable.pScreen->myNum]; \
5         NVPtr pNv = NVPTR(pScrn);                                      \
6         (void)pNv
7
8 static Bool
9 NV50EXA2DSurfaceFormat(PixmapPtr pPix, uint32_t *fmt)
10 {
11         NV50EXA_LOCALS(pPix);
12
13         switch (pPix->drawable.depth) {
14         case 8 : *fmt = NV50_2D_SRC_FORMAT_8BPP; break;
15         case 15: *fmt = NV50_2D_SRC_FORMAT_15BPP; break;
16         case 16: *fmt = NV50_2D_SRC_FORMAT_16BPP; break;
17         case 24: *fmt = NV50_2D_SRC_FORMAT_24BPP; break;
18         case 32: *fmt = NV50_2D_SRC_FORMAT_32BPP; break;
19         default:
20                  xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
21                             "Unknown surface format for bpp=%d\n",
22                             pPix->drawable.depth);
23                  return FALSE;
24         }
25
26         return TRUE;
27 }
28
29 static Bool
30 NV50EXAAcquireSurface2D(PixmapPtr pPix, int is_src)
31 {
32         NV50EXA_LOCALS(pPix);
33         int mthd = is_src ? NV50_2D_SRC_FORMAT : NV50_2D_DST_FORMAT;
34         uint32_t fmt, bo_flags;
35
36         if (!NV50EXA2DSurfaceFormat(pPix, &fmt))
37                 return FALSE;
38
39         bo_flags  = NOUVEAU_BO_VRAM;
40         bo_flags |= is_src ? NOUVEAU_BO_RD : NOUVEAU_BO_WR;
41
42         BEGIN_RING(Nv2D, mthd, 2);
43         OUT_RING  (fmt);
44         OUT_RING  (1);
45
46         BEGIN_RING(Nv2D, mthd + 0x14, 5);
47         OUT_RING  ((uint32_t)exaGetPixmapPitch(pPix));
48         OUT_RING  (pPix->drawable.width);
49         OUT_RING  (pPix->drawable.height);
50         OUT_PIXMAPh(pPix, 0, bo_flags);
51         OUT_PIXMAPl(pPix, 0, bo_flags);
52
53         if (is_src == 0) {
54                 BEGIN_RING(Nv2D, NV50_2D_CLIP_X, 4);
55                 OUT_RING  (0);
56                 OUT_RING  (0);
57                 OUT_RING  (pPix->drawable.width);
58                 OUT_RING  (pPix->drawable.height);
59         }
60
61         return TRUE;
62 }
63
64 static Bool
65 NV50EXAAcquireSurfaces(PixmapPtr pdPix)
66 {
67         NV50EXA_LOCALS(pdPix);
68
69         return TRUE;
70 }
71
72 static void
73 NV50EXAReleaseSurfaces(PixmapPtr pdPix)
74 {
75         NV50EXA_LOCALS(pdPix);
76
77         BEGIN_RING(Nv2D, NV50_2D_NOP, 1);
78         OUT_RING  (0);
79         FIRE_RING();
80 }
81
82 static void
83 NV50EXASetPattern(PixmapPtr pdPix, int col0, int col1, int pat0, int pat1)
84 {
85         NV50EXA_LOCALS(pdPix);
86
87         BEGIN_RING(Nv2D, NV50_2D_PATTERN_COLOR(0), 4);
88         OUT_RING  (col0);
89         OUT_RING  (col1);
90         OUT_RING  (pat0);
91         OUT_RING  (pat1);
92 }
93
94 extern const int NVCopyROP[16];
95 static void
96 NV50EXASetROP(PixmapPtr pdPix, int alu, Pixel planemask)
97 {
98         NV50EXA_LOCALS(pdPix);
99         int rop = NVCopyROP[alu];
100
101         BEGIN_RING(Nv2D, NV50_2D_OPERATION, 1);
102         if(alu == GXcopy && planemask == ~0) {
103                 OUT_RING  (NV50_2D_OPERATION_SRCCOPY);
104                 return;
105         } else {
106                 OUT_RING  (NV50_2D_OPERATION_ROP_AND);
107         }
108
109         BEGIN_RING(Nv2D, NV50_2D_PATTERN_FORMAT, 2);
110         switch (pdPix->drawable.depth) {
111                 case  8: OUT_RING  (3); break;
112                 case 15: OUT_RING  (1); break;
113                 case 16: OUT_RING  (0); break;
114                 case 24:
115                 case 32:
116                 default:
117                          OUT_RING  (2);
118                          break;
119         }
120         OUT_RING(1);
121
122         if(planemask != ~0) {
123                 NV50EXASetPattern(pdPix, 0, planemask, ~0, ~0);
124                 rop = (rop & 0xf0) | 0x0a;
125         } else
126         if((pNv->currentRop & 0x0f) == 0x0a) {
127                 NV50EXASetPattern(pdPix, ~0, ~0, ~0, ~0);
128         }
129
130         if (pNv->currentRop != rop) {
131                 BEGIN_RING(Nv2D, NV50_2D_ROP, 1);
132                 OUT_RING  (rop);
133                 pNv->currentRop = rop;
134         }
135 }
136
137 Bool
138 NV50EXAPrepareSolid(PixmapPtr pdPix, int alu, Pixel planemask, Pixel fg)
139 {
140         NV50EXA_LOCALS(pdPix);
141         uint32_t fmt;
142
143         if(pdPix->drawable.depth > 24)
144                 return FALSE;
145         if (!NV50EXA2DSurfaceFormat(pdPix, &fmt))
146                 return FALSE;
147
148         if (!NV50EXAAcquireSurface2D(pdPix, 0))
149                 return FALSE;
150         if (!NV50EXAAcquireSurfaces(pdPix))
151                 return FALSE;
152         NV50EXASetROP(pdPix, alu, planemask);
153
154         BEGIN_RING(Nv2D, 0x580, 3);
155         OUT_RING  (4);
156         OUT_RING  (fmt);
157         OUT_RING  (fg);
158
159         return TRUE;
160 }
161
162 void
163 NV50EXASolid(PixmapPtr pdPix, int x1, int y1, int x2, int y2)
164 {
165         NV50EXA_LOCALS(pdPix);
166
167         BEGIN_RING(Nv2D, NV50_2D_RECT_X1, 4);
168         OUT_RING  (x1);
169         OUT_RING  (y1);
170         OUT_RING  (x2);
171         OUT_RING  (y2);
172
173         if((x2 - x1) * (y2 - y1) >= 512)
174                 FIRE_RING();
175 }
176
177 void
178 NV50EXADoneSolid(PixmapPtr pdPix)
179 {
180         NV50EXA_LOCALS(pdPix);
181
182         NV50EXAReleaseSurfaces(pdPix);
183 }
184
185 Bool
186 NV50EXAPrepareCopy(PixmapPtr psPix, PixmapPtr pdPix, int dx, int dy,
187                    int alu, Pixel planemask)
188 {
189         NV50EXA_LOCALS(pdPix);
190
191         if (!NV50EXAAcquireSurface2D(psPix, 1))
192                 return FALSE;
193         if (!NV50EXAAcquireSurface2D(pdPix, 0))
194                 return FALSE;
195         if (!NV50EXAAcquireSurfaces(pdPix))
196                 return FALSE;
197         NV50EXASetROP(pdPix, alu, planemask);
198
199         return TRUE;
200 }
201
202 void
203 NV50EXACopy(PixmapPtr pdPix, int srcX , int srcY,
204                              int dstX , int dstY,
205                              int width, int height)
206 {
207         NV50EXA_LOCALS(pdPix);
208
209         BEGIN_RING(Nv2D, 0x0110, 1);
210         OUT_RING  (0);
211         BEGIN_RING(Nv2D, NV50_2D_BLIT_DST_X, 12);
212         OUT_RING  (dstX);
213         OUT_RING  (dstY);
214         OUT_RING  (width);
215         OUT_RING  (height);
216         OUT_RING  (0);
217         OUT_RING  (1);
218         OUT_RING  (0);
219         OUT_RING  (1);
220         OUT_RING  (0);
221         OUT_RING  (srcX);
222         OUT_RING  (0);
223         OUT_RING  (srcY);
224
225         if(width * height >= 512)
226                 FIRE_RING();
227 }
228
229 void
230 NV50EXADoneCopy(PixmapPtr pdPix)
231 {
232         NV50EXA_LOCALS(pdPix);
233
234         NV50EXAReleaseSurfaces(pdPix);
235 }
236
237 Bool
238 NV50EXAUploadSIFC(ScrnInfoPtr pScrn, const char *src, int src_pitch,
239                   PixmapPtr pdPix, int x, int y, int w, int h, int cpp)
240 {
241         NVPtr pNv = NVPTR(pScrn);
242         int line_dwords = (w * cpp + 3) / 4;
243         uint32_t sifc_fmt;
244
245         if (!NV50EXA2DSurfaceFormat(pdPix, &sifc_fmt))
246                 return FALSE;
247         if (!NV50EXAAcquireSurface2D(pdPix, 0))
248                 return FALSE;
249
250         BEGIN_RING(Nv2D, NV50_2D_OPERATION, 1);
251         OUT_RING (NV50_2D_OPERATION_SRCCOPY);
252         BEGIN_RING(Nv2D, NV50_2D_SIFC_UNK0800, 2);
253         OUT_RING (0);
254         OUT_RING (sifc_fmt);
255         BEGIN_RING(Nv2D, NV50_2D_SIFC_WIDTH, 10);
256         OUT_RING ((line_dwords * 4) / cpp);
257         OUT_RING (h);
258         OUT_RING (0);
259         OUT_RING (1);
260         OUT_RING (0);
261         OUT_RING (1);
262         OUT_RING (0);
263         OUT_RING (x);
264         OUT_RING (0);
265         OUT_RING (y);
266
267         while (h--) {
268                 int count = line_dwords;
269                 const char *p = src;
270
271                 while(count) {
272                         int size = count > 1792 ? 1792 : count;
273
274                         BEGIN_RING(Nv2D, NV50_2D_SIFC_DATA | 0x40000000, size);
275                         OUT_RINGp (p, size);
276
277                         p += size * cpp;
278                         count -= size;
279                 }
280
281                 src += src_pitch;
282         }
283
284         return TRUE;
285 }
286