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 18static Bool ApmOpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, 19 int *, int *, int *); 20static Bool ApmSetMode(ScrnInfoPtr, DGAModePtr); 21static int ApmGetViewport(ScrnInfoPtr); 22static void ApmSetViewport(ScrnInfoPtr, int, int, int); 23#ifdef HAVE_XAA_H 24static void ApmFillRect(ScrnInfoPtr, int, int, int, int, unsigned long); 25static void ApmBlitRect(ScrnInfoPtr, int, int, int, int, int, int); 26static void ApmBlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, 27 unsigned long); 28#endif 29static void ApmSync(ScrnInfoPtr); 30 31static 32DGAFunctionRec 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 */ 51void 52ApmSync(ScrnInfoPtr pScrn) 53{ 54} 55 56static __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 73static DGAModePtr 74ApmSetupDGAMode(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 85SECOND_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 171Bool 172ApmDGAInit(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 236static Bool 237ApmSetMode(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 299static int 300ApmGetViewport( 301 ScrnInfoPtr pScrn 302) 303{ 304 return 0; 305} 306 307static void 308ApmSetViewport( 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 343static void 344ApmFillRect ( 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 363static void 364ApmBlitRect( 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 390static void 391ApmBlitTransRect( 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 414static Bool 415ApmOpenFramebuffer( 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