1 /*
2 * file: apm_dga.c
3 * ported from s3virge, ported from mga
4 *
5 */
6
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10
11 #include "xf86.h"
12 #include "xf86_OSproc.h"
13 #include "xf86Pci.h"
14 #include "apm.h"
15 #include "dgaproc.h"
16
17
18 static Bool ApmOpenFramebuffer(ScrnInfoPtr, char **, unsigned char **,
19 int *, int *, int *);
20 static Bool ApmSetMode(ScrnInfoPtr, DGAModePtr);
21 static int ApmGetViewport(ScrnInfoPtr);
22 static void ApmSetViewport(ScrnInfoPtr, int, int, int);
23 #ifdef HAVE_XAA_H
24 static void ApmFillRect(ScrnInfoPtr, int, int, int, int, unsigned long);
25 static void ApmBlitRect(ScrnInfoPtr, int, int, int, int, int, int);
26 static void ApmBlitTransRect(ScrnInfoPtr, int, int, int, int, int, int,
27 unsigned long);
28 #endif
29 static void ApmSync(ScrnInfoPtr);
30
31 static
32 DGAFunctionRec ApmDGAFuncs = {
33 ApmOpenFramebuffer,
34 NULL,
35 ApmSetMode,
36 ApmSetViewport,
37 ApmGetViewport,
38 ApmSync,
39 #ifdef HAVE_XAA_H
40 ApmFillRect,
41 ApmBlitRect,
42 ApmBlitTransRect
43 #else
44 NULL, NULL, NULL
45 #endif
46 };
47
48 /*
49 * Placeholder
50 */
51 void
ApmSync(ScrnInfoPtr pScrn)52 ApmSync(ScrnInfoPtr pScrn)
53 {
54 }
55
FindSmallestPitch(ApmPtr pApm,int Bpp,int width)56 static __inline__ int FindSmallestPitch(ApmPtr pApm, int Bpp, int width)
57 {
58 if (width <= 640)
59 return 640;
60 else if (width <= 800)
61 return 800;
62 else if (width <= 1024)
63 return 1024;
64 else if (width <= 1152)
65 return 1152;
66 else if (width <= 1280)
67 return 1280;
68 else if (width <= 1600)
69 return 1600;
70 return (width + 7) & ~7;
71 }
72
73 static DGAModePtr
ApmSetupDGAMode(ScrnInfoPtr pScrn,DGAModePtr modes,int * num,int bitsPerPixel,int depth,Bool pixmap,int secondPitch,unsigned long red,unsigned long green,unsigned long blue,short visualClass)74 ApmSetupDGAMode(ScrnInfoPtr pScrn, DGAModePtr modes, int *num,
75 int bitsPerPixel, int depth, Bool pixmap, int secondPitch,
76 unsigned long red, unsigned long green, unsigned long blue,
77 short visualClass)
78 {
79 DisplayModePtr firstMode, pMode;
80 APMDECL(pScrn);
81 DGAModePtr mode, newmodes;
82 int size, pitch, Bpp = bitsPerPixel >> 3;
83 Bool reduced_pitch = TRUE;
84
85 SECOND_PASS:
86
87 firstMode = NULL;
88
89 for (pMode = pScrn->modes; pMode != firstMode; pMode = pMode->next) {
90
91 if (!firstMode)
92 firstMode = pMode;
93
94 if (reduced_pitch)
95 pitch = FindSmallestPitch(pApm, Bpp, pMode->HDisplay);
96 else
97 pitch = pMode->HDisplay;
98 if (!reduced_pitch && pitch == FindSmallestPitch(pApm, Bpp, pMode->HDisplay))
99 continue;
100
101 size = pitch * Bpp * pMode->VDisplay;
102
103 if((!secondPitch || (pitch != secondPitch)) &&
104 (size <= pScrn->videoRam * 1024 - pApm->OffscreenReserved)) {
105
106 if(secondPitch)
107 pitch = secondPitch;
108
109 if(!(newmodes = realloc(modes, (*num + 1) * sizeof(DGAModeRec))))
110 break;
111
112 modes = newmodes;
113 mode = modes + *num;
114
115 mode->mode = pMode;
116 mode->flags = DGA_CONCURRENT_ACCESS;
117
118 if(pixmap)
119 mode->flags |= DGA_PIXMAP_AVAILABLE;
120 if(!pApm->NoAccel) {
121 mode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT;
122 if (Bpp != 3)
123 mode->flags |= DGA_BLIT_RECT_TRANS;
124 }
125 if(pMode->Flags & V_DBLSCAN)
126 mode->flags |= DGA_DOUBLESCAN;
127 if(pMode->Flags & V_INTERLACE)
128 mode->flags |= DGA_INTERLACED;
129 mode->byteOrder = pScrn->imageByteOrder;
130 mode->depth = depth;
131 mode->bitsPerPixel = bitsPerPixel;
132 mode->red_mask = red;
133 mode->green_mask = green;
134 mode->blue_mask = blue;
135 mode->visualClass = visualClass;
136 mode->viewportWidth = pMode->HDisplay;
137 mode->viewportHeight = pMode->VDisplay;
138 mode->xViewportStep = (bitsPerPixel == 24) ? 4 : 1;
139 mode->yViewportStep = 1;
140 mode->viewportFlags = DGA_FLIP_RETRACE;
141 mode->offset = 0;
142 mode->address = pApm->FbBase;
143 mode->bytesPerScanline = pitch * Bpp;
144 mode->imageWidth = pitch;
145 mode->imageHeight = (pScrn->videoRam * 1024 -
146 pApm->OffscreenReserved) / mode->bytesPerScanline;
147 mode->pixmapWidth = mode->imageWidth;
148 mode->pixmapHeight = mode->imageHeight;
149 mode->maxViewportX = mode->imageWidth - mode->viewportWidth;
150 /* this might need to get clamped to some maximum */
151 mode->maxViewportY = mode->imageHeight - mode->viewportHeight;
152
153 (*num)++;
154 }
155
156 }
157
158 if(secondPitch) {
159 secondPitch = 0;
160 goto SECOND_PASS;
161 }
162
163 if (reduced_pitch) {
164 reduced_pitch = FALSE;
165 goto SECOND_PASS;
166 }
167
168 return modes;
169 }
170
171 Bool
ApmDGAInit(ScreenPtr pScreen)172 ApmDGAInit(ScreenPtr pScreen)
173 {
174 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
175 APMDECL(pScrn);
176 DGAModePtr modes = NULL;
177 int num = 0;
178
179 /* 8 */
180 modes = ApmSetupDGAMode (pScrn, modes, &num, 8, 8,
181 (pScrn->bitsPerPixel != 24),
182 (pScrn->bitsPerPixel != 8) ? 0 : pScrn->displayWidth,
183 0, 0, 0, PseudoColor);
184
185 /* 15 */
186 modes = ApmSetupDGAMode (pScrn, modes, &num, 16, 15,
187 (pScrn->bitsPerPixel != 24),
188 (pScrn->depth != 15) ? 0 : pScrn->displayWidth,
189 0x7C00, 0x03E0, 0x001F, TrueColor);
190
191 modes = ApmSetupDGAMode (pScrn, modes, &num, 16, 15,
192 (pScrn->bitsPerPixel != 24),
193 (pScrn->depth != 15) ? 0 : pScrn->displayWidth,
194 0x7C00, 0x03E0, 0x001F, DirectColor);
195
196 /* 16 */
197 modes = ApmSetupDGAMode (pScrn, modes, &num, 16, 16,
198 (pScrn->bitsPerPixel != 24),
199 (pScrn->depth != 16) ? 0 : pScrn->displayWidth,
200 0xF800, 0x07E0, 0x001F, TrueColor);
201
202 modes = ApmSetupDGAMode (pScrn, modes, &num, 16, 16,
203 (pScrn->bitsPerPixel != 24),
204 (pScrn->depth != 16) ? 0 : pScrn->displayWidth,
205 0xF800, 0x07E0, 0x001F, DirectColor);
206
207 /* 24 */
208 modes = ApmSetupDGAMode (pScrn, modes, &num, 24, 24,
209 (pScrn->bitsPerPixel == 24),
210 (pScrn->bitsPerPixel != 24) ? 0 : pScrn->displayWidth,
211 0xFF0000, 0x00FF00, 0x0000FF, TrueColor);
212
213 modes = ApmSetupDGAMode (pScrn, modes, &num, 24, 24,
214 (pScrn->bitsPerPixel == 24),
215 (pScrn->bitsPerPixel != 24) ? 0 : pScrn->displayWidth,
216 0xFF0000, 0x00FF00, 0x0000FF, DirectColor);
217
218 /* 32 */
219 modes = ApmSetupDGAMode (pScrn, modes, &num, 32, 24,
220 (pScrn->bitsPerPixel != 24),
221 (pScrn->bitsPerPixel != 32) ? 0 : pScrn->displayWidth,
222 0xFF0000, 0x00FF00, 0x0000FF, TrueColor);
223
224 modes = ApmSetupDGAMode (pScrn, modes, &num, 32, 24,
225 (pScrn->bitsPerPixel != 24),
226 (pScrn->bitsPerPixel != 32) ? 0 : pScrn->displayWidth,
227 0xFF0000, 0x00FF00, 0x0000FF, DirectColor);
228
229 pApm->numDGAModes = num;
230 pApm->DGAModes = modes;
231
232 return DGAInit(pScreen, &ApmDGAFuncs, modes, num);
233 }
234
235
236 static Bool
ApmSetMode(ScrnInfoPtr pScrn,DGAModePtr pMode)237 ApmSetMode(ScrnInfoPtr pScrn, DGAModePtr pMode)
238 {
239 APMDECL(pScrn);
240
241 if (!pMode) { /* restore the original mode */
242 if (pApm->DGAactive) {
243 memcpy(&pApm->CurrentLayout, &pApm->SavedLayout,
244 sizeof pApm->CurrentLayout);
245 pApm->DGAactive = FALSE;
246 }
247
248 pScrn->currentMode = pApm->CurrentLayout.pMode;
249 ApmSwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode));
250 ApmAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
251 #if 0
252 if (pApm->AccelInfoRec)
253 XAAInit(pScrn->pScreen, pApm->AccelInfoRec);
254 #endif
255 }
256 else {
257 if (!pApm->DGAactive) {
258 memcpy(&pApm->SavedLayout, &pApm->CurrentLayout,
259 sizeof pApm->CurrentLayout);
260 pApm->DGAactive = TRUE;
261 }
262
263 pApm->CurrentLayout.displayWidth = pMode->imageWidth;
264 pApm->CurrentLayout.displayHeight = pMode->imageHeight;
265 pApm->CurrentLayout.Scanlines = pMode->imageHeight + 1;
266 pApm->CurrentLayout.depth = pMode->depth;
267 pApm->CurrentLayout.bitsPerPixel = pMode->bitsPerPixel;
268 pApm->CurrentLayout.bytesPerScanline = pMode->bytesPerScanline;
269 pApm->CurrentLayout.pMode = pMode->mode;
270 if (pMode->bitsPerPixel == 24)
271 pApm->CurrentLayout.mask32 = 3;
272 else
273 pApm->CurrentLayout.mask32 = 32 / pMode->bitsPerPixel - 1;
274
275 ApmSwitchMode(SWITCH_MODE_ARGS(pScrn, pMode->mode));
276 #ifdef HAVE_XAA_H
277 ApmSetupXAAInfo(pApm, NULL);
278 #endif
279
280 #if 0
281 if (pApm->DGAXAAInfo)
282 bzero(pApm->DGAXAAInfo, sizeof(*pApm->DGAXAAInfo));
283 else
284 pApm->DGAXAAInfo = XAACreateInfoRec();
285 ApmSetupXAAInfo(pApm, pApm->DGAXAAInfo);
286 /*
287 * Let's hope this won't fail, that is reinitialize XAA for this
288 * setup...
289 */
290 XAAInit(pScrn->pScreen, pApm->DGAXAAInfo);
291 #endif
292 }
293
294 return TRUE;
295 }
296
297
298
299 static int
ApmGetViewport(ScrnInfoPtr pScrn)300 ApmGetViewport(
301 ScrnInfoPtr pScrn
302 )
303 {
304 return 0;
305 }
306
307 static void
ApmSetViewport(ScrnInfoPtr pScrn,int x,int y,int flags)308 ApmSetViewport(
309 ScrnInfoPtr pScrn,
310 int x, int y,
311 int flags
312 )
313 {
314 unsigned char tmp;
315
316 APMDECL(pScrn);
317
318 if (pApm->apmLock) {
319 /*
320 * This is just an attempt, because Daryll is tampering with MY
321 * registers.
322 */
323 tmp = (RDXB(0xDB) & 0xF4) | 0x0A;
324 WRXB(0xDB, tmp);
325 ApmWriteSeq(0x1B, 0x20);
326 ApmWriteSeq(0x1C, 0x2F);
327 pApm->apmLock = FALSE;
328 }
329 pScrn->AdjustFrame(ADJUST_FRAME_ARGS(pScrn, x, y));
330 if (pApm->VGAMap) {
331 /* Wait until vertical retrace is in progress. */
332 while (APMVGAB(0x3DA) & 0x08);
333 while (!(APMVGAB(0x3DA) & 0x08));
334 }
335 else {
336 /* Wait until vertical retrace is in progress. */
337 while (inb(pApm->iobase + 0x3DA) & 0x08);
338 while (!(inb(pApm->iobase + 0x3DA) & 0x08));
339 }
340 }
341
342 #ifdef HAVE_XAA_H
343 static void
ApmFillRect(ScrnInfoPtr pScrn,int x,int y,int w,int h,unsigned long color)344 ApmFillRect (
345 ScrnInfoPtr pScrn,
346 int x, int y, int w, int h,
347 unsigned long color
348 )
349 {
350 APMDECL(pScrn);
351
352 if(pApm->CurrentLayout.depth != 24) {
353 (*pApm->SetupForSolidFill)(pScrn, color, GXcopy, ~0);
354 (*pApm->SubsequentSolidFillRect)(pScrn, x, y, w, h);
355 }
356 else {
357 (*pApm->SetupForSolidFill24)(pScrn, color, GXcopy, ~0);
358 (*pApm->SubsequentSolidFillRect24)(pScrn, x, y, w, h);
359 }
360 SET_SYNC_FLAG(pApm->AccelInfoRec);
361 }
362
363 static void
ApmBlitRect(ScrnInfoPtr pScrn,int srcx,int srcy,int w,int h,int dstx,int dsty)364 ApmBlitRect(
365 ScrnInfoPtr pScrn,
366 int srcx, int srcy,
367 int w, int h,
368 int dstx, int dsty
369 )
370 {
371 APMDECL(pScrn);
372 int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
373 int ydir = (srcy < dsty) ? -1 : 1;
374
375 if(pApm->CurrentLayout.depth != 24) {
376 (*pApm->SetupForScreenToScreenCopy)(
377 pScrn, xdir, ydir, GXcopy, ~0, -1);
378 (*pApm->SubsequentScreenToScreenCopy)(
379 pScrn, srcx, srcy, dstx, dsty, w, h);
380 }
381 else {
382 (*pApm->SetupForScreenToScreenCopy24)(
383 pScrn, xdir, ydir, GXcopy, ~0, -1);
384 (*pApm->SubsequentScreenToScreenCopy24)(
385 pScrn, srcx, srcy, dstx, dsty, w, h);
386 }
387 SET_SYNC_FLAG(pApm->AccelInfoRec);
388 }
389
390 static void
ApmBlitTransRect(ScrnInfoPtr pScrn,int srcx,int srcy,int w,int h,int dstx,int dsty,unsigned long color)391 ApmBlitTransRect(
392 ScrnInfoPtr pScrn,
393 int srcx, int srcy,
394 int w, int h,
395 int dstx, int dsty,
396 unsigned long color
397 )
398 {
399 APMDECL(pScrn);
400
401 if(pApm->AccelInfoRec) {
402 int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1;
403 int ydir = (srcy < dsty) ? -1 : 1;
404
405 (*pApm->AccelInfoRec->SetupForScreenToScreenCopy)(
406 pScrn, xdir, ydir, GXcopy, ~0, (int)color);
407 (*pApm->AccelInfoRec->SubsequentScreenToScreenCopy)(
408 pScrn, srcx, srcy, dstx, dsty, w, h);
409 SET_SYNC_FLAG(pApm->AccelInfoRec);
410 }
411 }
412 #endif
413
414 static Bool
ApmOpenFramebuffer(ScrnInfoPtr pScrn,char ** name,unsigned char ** mem,int * size,int * offset,int * flags)415 ApmOpenFramebuffer(
416 ScrnInfoPtr pScrn,
417 char **name,
418 unsigned char **mem,
419 int *size,
420 int *offset,
421 int *flags
422 )
423 {
424 APMDECL(pScrn);
425
426 *name = NULL; /* no special device */
427 *mem = (unsigned char*)(pApm->LinAddress +
428 0*((char *)pApm->FbBase - (char *)pApm->LinMap));
429 *size = pScrn->videoRam << 10;
430 *offset = 0;
431 *flags = DGA_NEED_ROOT;
432
433 return TRUE;
434 }
435