apm_driver.c revision 3a2d322d
1 2#ifdef HAVE_CONFIG_H 3#include "config.h" 4#endif 5 6#include "apm.h" 7#include "xf86cmap.h" 8#include "shadowfb.h" 9#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 10#include "xf86Resources.h" 11#include "xf86RAC.h" 12#endif 13#include "xf86int10.h" 14#include "vbe.h" 15 16#include "opaque.h" 17#ifdef HAVE_XEXTPROTO_71 18#include <X11/extensions/dpmsconst.h> 19#else 20#define DPMS_SERVER 21#include <X11/extensions/dpms.h> 22#endif 23 24 25#define APM_VERSION 4000 26#define APM_NAME "APM" 27#define APM_DRIVER_NAME "apm" 28#define APM_MAJOR_VERSION PACKAGE_VERSION_MAJOR 29#define APM_MINOR_VERSION PACKAGE_VERSION_MINOR 30#define APM_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL 31 32#define PCI_VENDOR_ALLIANCE 0x1142 33#define PCI_CHIP_AP6422 0x6422 34#define PCI_CHIP_AT24 0x6424 35#define PCI_CHIP_AT3D 0x643D 36 37/* bytes to save for text/font data */ 38#define TEXT_AMOUNT 32768 39 40/* Mandatory functions */ 41static const OptionInfoRec * ApmAvailableOptions(int chipid, int busid); 42static void ApmIdentify(int flags); 43static Bool ApmProbe(DriverPtr drv, int flags); 44static Bool ApmPreInit(ScrnInfoPtr pScrn, int flags); 45static Bool ApmScreenInit(SCREEN_INIT_ARGS_DECL); 46static Bool ApmEnterVT(VT_FUNC_ARGS_DECL); 47static void ApmLeaveVT(VT_FUNC_ARGS_DECL); 48static Bool ApmCloseScreen(CLOSE_SCREEN_ARGS_DECL); 49static void ApmFreeScreen(FREE_SCREEN_ARGS_DECL); 50static ModeStatus ApmValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, 51 Bool verbose, int flags); 52static Bool ApmSaveScreen(ScreenPtr pScreen, int mode); 53static void ApmUnlock(ApmPtr pApm); 54static void ApmLock(ApmPtr pApm); 55static void ApmRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, 56 ApmRegPtr ApmReg); 57static void ApmLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, 58 LOCO *colors, VisualPtr pVisual); 59static void ApmDisplayPowerManagementSet(ScrnInfoPtr pScrn, 60 int PowerManagementMode, 61 int flags); 62static void ApmProbeDDC(ScrnInfoPtr pScrn, int index); 63 64#ifdef XF86RUSH 65int ApmPixmapIndex = -1; 66static unsigned long ApmGeneration = 0; 67#endif 68 69_X_EXPORT DriverRec APM = { 70 APM_VERSION, 71 APM_DRIVER_NAME, 72 ApmIdentify, 73 ApmProbe, 74 ApmAvailableOptions, 75 NULL, 76 0 77}; 78 79static SymTabRec ApmChipsets[] = { 80 { AP6422, "AP6422" }, 81 { AT24, "AT24" }, 82 { AT3D, "AT3D" }, 83 { -1, NULL } 84}; 85 86static PciChipsets ApmPciChipsets[] = { 87 { PCI_CHIP_AP6422, PCI_CHIP_AP6422, RES_SHARED_VGA }, 88 { PCI_CHIP_AT24, PCI_CHIP_AT24, RES_SHARED_VGA }, 89 { PCI_CHIP_AT3D, PCI_CHIP_AT3D, RES_SHARED_VGA }, 90 { -1, -1, RES_UNDEFINED } 91}; 92 93typedef enum { 94 OPTION_SET_MCLK, 95 OPTION_SW_CURSOR, 96 OPTION_HW_CURSOR, 97 OPTION_NOLINEAR, 98 OPTION_NOACCEL, 99 OPTION_SHADOW_FB, 100 OPTION_PCI_BURST, 101 OPTION_REMAP_DPMS_ON, 102 OPTION_REMAP_DPMS_STANDBY, 103 OPTION_REMAP_DPMS_SUSPEND, 104 OPTION_REMAP_DPMS_OFF, 105 OPTION_PCI_RETRY 106} ApmOpts; 107 108static const OptionInfoRec ApmOptions[] = 109{ 110 {OPTION_SET_MCLK, "SetMclk", OPTV_FREQ, 111 {0}, FALSE}, 112 {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, 113 {0}, FALSE}, 114 {OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, 115 {0}, TRUE}, 116 {OPTION_NOLINEAR, "NoLinear", OPTV_BOOLEAN, 117 {0}, FALSE}, 118 {OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, 119 {0}, FALSE}, 120 {OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, 121 {0}, FALSE}, 122 {OPTION_PCI_BURST, "pci_burst", OPTV_BOOLEAN, 123 {0}, FALSE}, 124 {OPTION_REMAP_DPMS_ON, "Remap_DPMS_On", OPTV_ANYSTR, 125 {0}, FALSE}, 126 {OPTION_REMAP_DPMS_STANDBY, "Remap_DPMS_Standby", OPTV_ANYSTR, 127 {0}, FALSE}, 128 {OPTION_REMAP_DPMS_SUSPEND, "Remap_DPMS_Suspend", OPTV_ANYSTR, 129 {0}, FALSE}, 130 {OPTION_REMAP_DPMS_OFF, "Remap_DPMS_Off", OPTV_ANYSTR, 131 {0}, FALSE}, 132 {OPTION_PCI_RETRY, "PciRetry", OPTV_BOOLEAN, 133 {0}, FALSE}, 134 {-1, NULL, OPTV_NONE, 135 {0}, FALSE} 136}; 137 138#ifdef XFree86LOADER 139 140static XF86ModuleVersionInfo apmVersRec = { 141 "apm", 142 MODULEVENDORSTRING, 143 MODINFOSTRING1, 144 MODINFOSTRING2, 145 XORG_VERSION_CURRENT, 146 APM_MAJOR_VERSION, APM_MINOR_VERSION, APM_PATCHLEVEL, 147 ABI_CLASS_VIDEODRV, /* This is a video driver */ 148 ABI_VIDEODRV_VERSION, 149 MOD_CLASS_VIDEODRV, 150 {0,0,0,0} 151}; 152 153static MODULESETUPPROTO(apmSetup); 154 155/* 156 * This is the module init data. 157 * Its name has to be the driver name followed by ModuleData. 158 */ 159_X_EXPORT XF86ModuleData apmModuleData = { &apmVersRec, apmSetup, NULL }; 160 161static pointer 162apmSetup(pointer module, pointer opts, int *errmaj, int *errmain) 163{ 164 static Bool setupDone = FALSE; 165 166 if (!setupDone) { 167 setupDone = TRUE; 168 xf86AddDriver(&APM, module, 0); 169 170 return (pointer)1; 171 } 172 else { 173 if (errmaj) *errmaj = LDR_ONCEONLY; 174 return NULL; 175 } 176} 177#endif 178 179static Bool 180ApmGetRec(ScrnInfoPtr pScrn) 181{ 182 if (pScrn->driverPrivate) 183 return TRUE; 184 pScrn->driverPrivate = xnfcalloc(sizeof(ApmRec), 1); 185 /* pScrn->driverPrivate != NULL at this point */ 186 187 return TRUE; 188} 189 190static void 191ApmFreeRec(ScrnInfoPtr pScrn) 192{ 193 free(pScrn->driverPrivate); 194 pScrn->driverPrivate = NULL; 195} 196 197 198/* unlock Alliance registers */ 199static void 200ApmUnlock(ApmPtr pApm) 201{ 202 if (pApm->Chipset >= AT3D) 203 ApmWriteSeq(0x10, 0x12); 204 else 205 wrinx(pApm->xport, 0x10, 0x12); 206} 207 208/* lock Alliance registers */ 209static void 210ApmLock(ApmPtr pApm) 211{ 212 if (pApm->Chipset >= AT3D) 213 ApmWriteSeq(0x10, pApm->savedSR10 ? 0 : 0x12); 214 else 215 wrinx(pApm->xport, 0x10, pApm->savedSR10 ? 0 : 0x12); 216} 217 218static void 219ApmIdentify(int flags) 220{ 221 xf86PrintChipsets(APM_NAME, "driver for the Alliance chipsets", 222 ApmChipsets); 223} 224 225static const OptionInfoRec * 226ApmAvailableOptions(int chipid, int busid) 227{ 228 return ApmOptions; 229} 230 231static void 232ApmAssignFPtr(ScrnInfoPtr pScrn) 233{ 234 pScrn->driverVersion = APM_VERSION; 235 pScrn->driverName = APM_DRIVER_NAME; 236 pScrn->name = APM_NAME; 237 pScrn->Probe = ApmProbe; 238 pScrn->PreInit = ApmPreInit; 239 pScrn->ScreenInit = ApmScreenInit; 240 pScrn->SwitchMode = ApmSwitchMode; 241 pScrn->AdjustFrame = ApmAdjustFrame; 242 pScrn->EnterVT = ApmEnterVT; 243 pScrn->LeaveVT = ApmLeaveVT; 244 pScrn->FreeScreen = ApmFreeScreen; 245 pScrn->ValidMode = ApmValidMode; 246} 247 248static Bool 249ApmProbe(DriverPtr drv, int flags) 250{ 251 int numDevSections, numUsed, i; 252 GDevPtr *DevSections; 253 int *usedChips; 254 int foundScreen = FALSE; 255 256 /* 257 * Check if there is a chipset override in the config file 258 */ 259 if ((numDevSections = xf86MatchDevice(APM_DRIVER_NAME, 260 &DevSections)) <= 0) 261 return FALSE; 262 263 /* 264 * We need to probe the hardware first. We then need to see how this 265 * fits in with what is given in the config file, and allow the config 266 * file info to override any contradictions. 267 */ 268 269#ifndef XSERVER_LIBPCIACCESS 270 if (xf86GetPciVideoInfo() == NULL) { 271 return FALSE; 272 } 273#endif 274 numUsed = xf86MatchPciInstances(APM_NAME, PCI_VENDOR_ALLIANCE, 275 ApmChipsets, ApmPciChipsets, DevSections, numDevSections, 276 drv, &usedChips); 277 278 if (numUsed > 0) { 279 if (flags & PROBE_DETECT) 280 foundScreen = TRUE; 281 else for (i = 0; i < numUsed; i++) { 282 ScrnInfoPtr pScrn; 283 284 /* 285 * Allocate a ScrnInfoRec and claim the slot 286 */ 287 pScrn = NULL; 288 if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], 289 ApmPciChipsets, NULL, 290 NULL,NULL,NULL,NULL))){ 291 292 /* 293 * Fill in what we can of the ScrnInfoRec 294 */ 295 ApmAssignFPtr(pScrn); 296 foundScreen = TRUE; 297 } 298 } 299 } 300 301 302 free(DevSections); 303 return foundScreen; 304} 305 306/* 307 * GetAccelPitchValues - 308 * 309 * This function returns a list of display width (pitch) values that can 310 * be used in accelerated mode. 311 */ 312static int * 313GetAccelPitchValues(ScrnInfoPtr pScrn) 314{ 315 int *linePitches = NULL; 316 int linep[] = {640, 800, 1024, 1152, 1280, 0}; 317 318 if (sizeof linep > 0) { 319 linePitches = (int *)xnfalloc(sizeof linep); 320 memcpy(linePitches, linep, sizeof linep); 321 } 322 323 return linePitches; 324} 325 326static unsigned int 327ddc1Read(ScrnInfoPtr pScrn) 328{ 329 APMDECL(pScrn); 330 unsigned char tmp; 331 332 tmp = RDXB_IOP(0xD0); 333 WRXB_IOP(0xD0, tmp & 0x07); 334 while (STATUS_IOP() & 0x800); 335 while (!(STATUS_IOP() & 0x800)); 336 return (STATUS_IOP() & STATUS_SDA) != 0; 337} 338 339static void 340ApmProbeDDC(ScrnInfoPtr pScrn, int index) 341{ 342 vbeInfoPtr pVbe; 343 344 if (xf86LoadSubModule(pScrn, "vbe")) { 345 pVbe = VBEInit(NULL, index); 346 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 347 vbeFree(pVbe); 348 } 349} 350 351static Bool 352ApmPreInit(ScrnInfoPtr pScrn, int flags) 353{ 354 APMDECL(pScrn); 355 EntityInfoPtr pEnt; 356 vgaHWPtr hwp; 357 MessageType from; 358 char *mod = NULL; 359 const char *s; 360 ClockRangePtr clockRanges; 361 int i; 362 xf86MonPtr MonInfo = NULL; 363 double real; 364 365 /* 366 * Note: This function is only called once at server startup, and 367 * not at the start of each server generation. This means that 368 * only things that are persistent across server generations can 369 * be initialised here. xf86Screens[] is (pScrn is a pointer to one 370 * of these). Privates allocated using xf86AllocateScrnInfoPrivateIndex() 371 * are too, and should be used for data that must persist across 372 * server generations. 373 * 374 * Per-generation data should be allocated with 375 * AllocateScreenPrivateIndex() from the ScreenInit() function. 376 */ 377 378 /* Check the number of entities, and fail if it isn't one. */ 379 if (pScrn->numEntities != 1) 380 return FALSE; 381 382 /* Allocate the ApmRec driverPrivate */ 383 if (!ApmGetRec(pScrn)) { 384 return FALSE; 385 } 386 pApm = APMPTR(pScrn); 387 388 /* Get the entity */ 389 pEnt = pApm->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 390 if (pEnt->location.type == BUS_PCI) { 391 pApm->PciInfo = xf86GetPciInfoForEntity(pEnt->index); 392#ifndef XSERVER_LIBPCIACCESS 393 pApm->PciTag = pciTag(pApm->PciInfo->bus, pApm->PciInfo->device, 394 pApm->PciInfo->func); 395#endif 396 } 397 else { 398 pApm->PciInfo = NULL; 399#ifndef XSERVER_LIBPCIACCESS 400 pApm->PciTag = 0; 401#endif 402 } 403 404 if (flags & PROBE_DETECT) { 405 ApmProbeDDC(pScrn, pEnt->index); 406 return TRUE; 407 } 408 409 /* The vgahw module should be allocated here when needed */ 410 if (!xf86LoadSubModule(pScrn, "vgahw")) 411 return FALSE; 412 413 /* 414 * Allocate a vgaHWRec 415 */ 416 if (!vgaHWGetHWRec(pScrn)) 417 return FALSE; 418 419 hwp = VGAHWPTR(pScrn); 420 vgaHWSetStdFuncs(hwp); 421 vgaHWGetIOBase(hwp); 422#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 423#define PIOOFFSET hwp->PIOOffset 424#else 425/* FIXME reintroduce domain support */ 426#define PIOOFFSET 0 427#endif 428 pApm->iobase = PIOOFFSET; 429 pApm->xport = PIOOFFSET + 0x3C4; 430 431 /* Set pScrn->monitor */ 432 pScrn->monitor = pScrn->confScreen->monitor; 433 434 /* XXX: Access funcs */ 435 /* 436 * The first thing we should figure out is the depth, bpp, etc. 437 */ 438 if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb)) { 439 return FALSE; 440 } else { 441 /* Check that the returned depth is one we support */ 442 switch (pScrn->depth) { 443 case 4: 444 case 8: 445 case 15: 446 case 16: 447 case 24: 448 /* OK */ 449 break; 450 default: 451 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 452 "Given depth (%d) is not supported by this driver\n", 453 pScrn->depth); 454 return FALSE; 455 } 456 } 457 xf86PrintDepthBpp(pScrn); 458 459 /* 460 * This must happen after pScrn->display has been set because 461 * xf86SetWeight references it. 462 */ 463 if (pScrn->depth > 8) { 464 /* The defaults are OK for us */ 465 rgb zeros = {0, 0, 0}; 466 467 if (!xf86SetWeight(pScrn, zeros, zeros)) { 468 return FALSE; 469 } else { 470 /* XXX check that weight returned is supported */ 471 ; 472 } 473 } 474 475 if (!xf86SetDefaultVisual(pScrn, -1)) { 476 return FALSE; 477 } else { 478 if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 479 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual" 480 " (%s) is not supported at depth %d\n", 481 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); 482 return FALSE; 483 } 484 } 485 486 /* We use a programmable clock */ 487 pScrn->progClock = TRUE; 488 489 /* Collect all of the relevant option flags (fill in pScrn->options) */ 490 xf86CollectOptions(pScrn, NULL); 491 492 /* Process the options */ 493 if (!(pApm->Options = malloc(sizeof(ApmOptions)))) 494 return FALSE; 495 memcpy(pApm->Options, ApmOptions, sizeof(ApmOptions)); 496 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pApm->Options); 497 498 pApm->scrnIndex = pScrn->scrnIndex; 499 /* Set the bits per RGB for 8bpp mode */ 500 if (pScrn->depth > 1 && pScrn->depth <= 8) { 501 /* Default to 8 */ 502 pScrn->rgbBits = 8; 503 } 504 from = X_DEFAULT; 505 pApm->hwCursor = FALSE; 506 if (xf86GetOptValBool(pApm->Options, OPTION_HW_CURSOR, &pApm->hwCursor)) 507 from = X_CONFIG; 508 if (xf86ReturnOptValBool(pApm->Options, OPTION_SW_CURSOR, FALSE)) { 509 from = X_CONFIG; 510 pApm->hwCursor = FALSE; 511 } 512 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 513 pApm->hwCursor ? "HW" : "SW"); 514 from = X_DEFAULT; 515 if (pScrn->bitsPerPixel < 8) 516 pApm->NoAccel = TRUE; 517 if (xf86ReturnOptValBool(pApm->Options, OPTION_NOACCEL, FALSE)) { 518 from = X_CONFIG; 519 pApm->NoAccel = TRUE; 520 } 521 if (pApm->NoAccel) 522 xf86DrvMsg(pScrn->scrnIndex, from, "Acceleration disabled\n"); 523 if (xf86GetOptValFreq(pApm->Options, OPTION_SET_MCLK, OPTUNITS_MHZ, &real)) { 524 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "MCLK used is %.1f MHz\n", real); 525 pApm->MemClk = (int)(real * 1000.0); 526 } 527 if (xf86ReturnOptValBool(pApm->Options, OPTION_SHADOW_FB, FALSE)) { 528 pApm->ShadowFB = TRUE; 529 pApm->NoAccel = TRUE; 530 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 531 "Using \"Shadow Framebuffer\" - acceleration disabled\n"); 532 } 533 if (xf86ReturnOptValBool(pApm->Options, OPTION_PCI_RETRY, FALSE)) { 534 if (xf86ReturnOptValBool(pApm->Options, OPTION_PCI_BURST, FALSE)) { 535 pApm->UsePCIRetry = TRUE; 536 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n"); 537 } 538 else 539 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"pci_retry\" option requires pci_burst \"on\".\n"); 540 } 541 pApm->DPMSMask[DPMSModeOn] = DPMSModeOn; 542 pApm->DPMSMask[DPMSModeStandby] = DPMSModeStandby; 543 pApm->DPMSMask[DPMSModeSuspend] = DPMSModeSuspend; 544 pApm->DPMSMask[DPMSModeOff] = DPMSModeOff; 545 if ((s = xf86GetOptValString(pApm->Options, OPTION_REMAP_DPMS_ON))) { 546 if (!strcmp(s, "on")) 547 pApm->DPMSMask[DPMSModeOn] = DPMSModeOn; 548 else if (!strcmp(s, "standby")) 549 pApm->DPMSMask[DPMSModeOn] = DPMSModeStandby; 550 else if (!strcmp(s, "suspend")) 551 pApm->DPMSMask[DPMSModeOn] = DPMSModeSuspend; 552 else if (!strcmp(s, "off")) 553 pApm->DPMSMask[DPMSModeOn] = DPMSModeOff; 554 else if (s[0] >= '0' && s[0] <= '9') { 555 pApm->DPMSMask[DPMSModeOn] = strtol(s, NULL, 0); 556 if (pApm->DPMSMask[DPMSModeOn] > (sizeof pApm->DPMSMask)-1) 557 pApm->DPMSMask[DPMSModeOn] = (sizeof pApm->DPMSMask) - 1; 558 } 559 } 560 if ((s = xf86GetOptValString(pApm->Options, OPTION_REMAP_DPMS_STANDBY))) { 561 if (!strcmp(s, "on")) 562 pApm->DPMSMask[DPMSModeStandby] = DPMSModeOn; 563 else if (!strcmp(s, "standby")) 564 pApm->DPMSMask[DPMSModeStandby] = DPMSModeStandby; 565 else if (!strcmp(s, "suspend")) 566 pApm->DPMSMask[DPMSModeStandby] = DPMSModeSuspend; 567 else if (!strcmp(s, "off")) 568 pApm->DPMSMask[DPMSModeStandby] = DPMSModeOff; 569 else if (s[0] >= '0' && s[0] <= '9') { 570 pApm->DPMSMask[DPMSModeStandby] = strtol(s, NULL, 0); 571 if (pApm->DPMSMask[DPMSModeStandby] > (sizeof pApm->DPMSMask)-1) 572 pApm->DPMSMask[DPMSModeStandby] = (sizeof pApm->DPMSMask) - 1; 573 } 574 } 575 if ((s = xf86GetOptValString(pApm->Options, OPTION_REMAP_DPMS_SUSPEND))) { 576 if (!strcmp(s, "on")) 577 pApm->DPMSMask[DPMSModeSuspend] = DPMSModeOn; 578 else if (!strcmp(s, "standby")) 579 pApm->DPMSMask[DPMSModeSuspend] = DPMSModeStandby; 580 else if (!strcmp(s, "suspend")) 581 pApm->DPMSMask[DPMSModeSuspend] = DPMSModeSuspend; 582 else if (!strcmp(s, "off")) 583 pApm->DPMSMask[DPMSModeSuspend] = DPMSModeOff; 584 else if (s[0] >= '0' && s[0] <= '9') { 585 pApm->DPMSMask[DPMSModeSuspend] = strtol(s, NULL, 0); 586 if (pApm->DPMSMask[DPMSModeSuspend] > (sizeof pApm->DPMSMask)-1) 587 pApm->DPMSMask[DPMSModeSuspend] = (sizeof pApm->DPMSMask) - 1; 588 } 589 } 590 if ((s = xf86GetOptValString(pApm->Options, OPTION_REMAP_DPMS_OFF))) { 591 if (!strcmp(s, "on")) 592 pApm->DPMSMask[DPMSModeOff] = DPMSModeOn; 593 else if (!strcmp(s, "standby")) 594 pApm->DPMSMask[DPMSModeOff] = DPMSModeStandby; 595 else if (!strcmp(s, "suspend")) 596 pApm->DPMSMask[DPMSModeOff] = DPMSModeSuspend; 597 else if (!strcmp(s, "off")) 598 pApm->DPMSMask[DPMSModeOff] = DPMSModeOff; 599 else if (s[0] >= '0' && s[0] <= '9') { 600 pApm->DPMSMask[DPMSModeOff] = strtol(s, NULL, 0); 601 if (pApm->DPMSMask[DPMSModeOff] > (sizeof pApm->DPMSMask)-1) 602 pApm->DPMSMask[DPMSModeOff] = (sizeof pApm->DPMSMask) - 1; 603 } 604 } 605 606 /* 607 * Set the Chipset and ChipRev, allowing config file entries to 608 * override. 609 */ 610 if (pEnt->device->chipset && *pEnt->device->chipset) { 611 pScrn->chipset = pEnt->device->chipset; 612 pApm->Chipset = xf86StringToToken(ApmChipsets, pScrn->chipset); 613 from = X_CONFIG; 614 } else if (pEnt->device->chipID >= 0) { 615 pApm->Chipset = pEnt->device->chipID; 616 pScrn->chipset = (char *)xf86TokenToString(ApmChipsets, pApm->Chipset); 617 618 from = X_CONFIG; 619 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", 620 pApm->Chipset); 621 } else { 622 from = X_PROBED; 623 if (pApm->PciInfo) 624 pApm->Chipset = PCI_DEV_DEVICE_ID(pApm->PciInfo); 625 else 626 pApm->Chipset = pEnt->chipset; 627 pScrn->chipset = (char *)xf86TokenToString(ApmChipsets, pApm->Chipset); 628 } 629 if (pScrn->bitsPerPixel == 24 && pApm->Chipset < AT24) { 630 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 631 "Given depth (%d) is not supported by this driver\n", 632 pScrn->depth); 633 return FALSE; 634 } 635 if (pEnt->device->chipRev >= 0) { 636 pApm->ChipRev = pEnt->device->chipRev; 637 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 638 pApm->ChipRev); 639 } else if (pApm->PciInfo) { 640 pApm->ChipRev = PCI_DEV_REVISION(pApm->PciInfo); 641 } 642 643 /* 644 * This shouldn't happen because such problems should be caught in 645 * ApmProbe(), but check it just in case. 646 */ 647 if (pScrn->chipset == NULL) { 648 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 649 "ChipID 0x%04X is not recognised\n", pApm->Chipset); 650 return FALSE; 651 } 652 if (pApm->Chipset < 0) { 653 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 654 "Chipset \"%s\" is not recognised\n", pScrn->chipset); 655 return FALSE; 656 } 657 658 xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset); 659 660 if (pEnt->device->MemBase != 0) { 661 pApm->LinAddress = pEnt->device->MemBase; 662 from = X_CONFIG; 663 } else if (pApm->PciInfo) { 664 pApm->LinAddress = PCI_REGION_BASE(pApm->PciInfo, 0, REGION_MEM) & 0xFF800000; 665 from = X_PROBED; 666 } else { 667 /* 668 * VESA local bus. 669 * Pray that 2048MB works. 670 */ 671 pApm->LinAddress = 0x80000000; 672 } 673 674 xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", 675 (unsigned long)pApm->LinAddress); 676 677 if (xf86LoadSubModule(pScrn, "ddc")) { 678 if (xf86LoadSubModule(pScrn, "i2c")) { 679 pApm->I2C = TRUE; 680 } 681 } 682 683 if (pApm->Chipset >= AT3D) 684 pApm->LinMapSize = 16 * 1024 * 1024; 685 else 686 pApm->LinMapSize = 6 * 1024 * 1024; 687 pApm->FbMapSize = 4 * 1024 * 1024; 688 689 if (xf86LoadSubModule(pScrn, "int10")) { 690 void *ptr; 691 692 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n"); 693 ptr = xf86InitInt10(pEnt->index); 694 if (ptr) 695 xf86FreeInt10(ptr); 696 } 697 698#ifndef XSERVER_LIBPCIACCESS 699 xf86RegisterResources(pEnt->index, NULL, ResNone); 700 xf86SetOperatingState(resVga, pEnt->index, ResDisableOpr); 701 pScrn->racMemFlags = 0; /* For noLinear, access to 0xA0000 */ 702 if (pApm->VGAMap) 703 pScrn->racIoFlags = 0; 704 else 705 pScrn->racIoFlags = RAC_COLORMAP | RAC_VIEWPORT; 706#endif 707 if (pEnt->device->videoRam != 0) { 708 pScrn->videoRam = pEnt->device->videoRam; 709 from = X_CONFIG; 710 } else if (pApm->Chipset >= AT3D) { 711 unsigned char d9, db, uc; 712 /*unsigned long save;*/ 713 volatile unsigned char *LinMap; 714 715#ifndef XSERVER_LIBPCIACCESS 716 LinMap = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 717 pApm->PciTag, pApm->LinAddress, 718 pApm->LinMapSize); 719#else 720 { 721 void** result = (void**)&LinMap; 722 int err = pci_device_map_range(pApm->PciInfo, 723 pApm->LinAddress, 724 pApm->LinMapSize, 725 PCI_DEV_MAP_FLAG_WRITABLE, 726 result); 727 728 if (err) 729 return FALSE; 730 } 731#endif 732 733 /*save = pciReadLong(pApm->PciTag, PCI_CMD_STAT_REG); 734 pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, save | PCI_CMD_MEM_ENABLE);*/ 735 d9 = LinMap[0xFFECD9]; 736 db = LinMap[0xFFECDB]; 737 LinMap[0xFFECDB] = (db & 0xF4) | 0x0A; 738 LinMap[0xFFECD9] = (d9 & 0xCF) | 0x20; 739 LinMap[0xFFF3C4] = 0x1C; 740 uc = LinMap[0xFFF3C5]; 741 LinMap[0xFFF3C5] = 0x3F; 742 LinMap[0xFFF3C4] = 0x20; 743 pScrn->videoRam = LinMap[0xFFF3C5] * 64; 744 LinMap[0xFFF3C4] = 0x10; 745 pApm->savedSR10 = LinMap[0xFFF3C5]; 746 LinMap[0xFFF3C4] = 0x1E; 747 pApm->xbase = LinMap[0xFFF3C5]; 748 LinMap[0xFFF3C4] = 0x1F; 749 pApm->xbase |= LinMap[0xFFF3C5] << 8; 750 LinMap[0xFFF3C4] = 0x1C; 751 LinMap[0xFFF3C5] = uc; 752 LinMap[0xFFECDB] = db; 753 LinMap[0xFFECD9] = d9; 754 /*pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, save);*/ 755#ifndef XSERVER_LIBPCIACCESS 756 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)LinMap, pApm->LinMapSize); 757#else 758 pci_device_unmap_range(pApm->PciInfo, (pointer)LinMap, pApm->LinMapSize); 759#endif 760 from = X_PROBED; 761 } 762 else { 763 /*unsigned long save; 764 765 save = pciReadLong(pApm->PciTag, PCI_CMD_STAT_REG); 766 pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, save | PCI_CMD_IO_ENABLE);*/ 767 pApm->savedSR10 = rdinx(pApm->xport, 0x10); 768 wrinx(pApm->xport, 0x10, 0x12); 769 pScrn->videoRam = rdinx(pApm->xport, 0x20) * 64; 770 pApm->xbase = rdinx(pApm->xport, 0x1F) << 8; 771 pApm->xbase |= rdinx(pApm->xport, 0x1E); 772 pApm->xbase += pApm->iobase; 773 wrinx(pApm->xport, 0x10, pApm->savedSR10 ? 0 : 0x12); 774 /*pciWriteLong(pApm->PciTag, PCI_CMD_STAT_REG, save);*/ 775 from = X_PROBED; 776 } 777 if (pApm->Chipset < AT3D && pScrn->videoRam >= 4096) 778 pScrn->videoRam -= 32; 779 780 xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n", 781 pScrn->videoRam); 782 783#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 784 if (!xf86IsPc98()) 785#endif 786 { 787 hwp->MapSize = 0x10000; 788 vgaHWMapMem(pScrn); 789 if (pApm->I2C) { 790 if (!ApmI2CInit(pScrn)) { 791 xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"I2C initialization failed\n"); 792 } 793 else { 794 MonInfo = xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn),pApm->I2CPtr); 795 } 796 } 797 if (0 && !MonInfo) 798 MonInfo = xf86DoEDID_DDC1(XF86_SCRN_ARG(pScrn),vgaHWddc1SetSpeed,ddc1Read); 799 if (MonInfo) { 800 xf86PrintEDID(MonInfo); 801 xf86SetDDCproperties(pScrn, MonInfo); 802 } 803 pScrn->monitor->DDC = MonInfo; 804 } 805 806 /* The gamma fields must be initialised when using the new cmap code */ 807 if (pScrn->depth > 1) { 808 Gamma zeros = {0.0, 0.0, 0.0}; 809 810 if (!xf86SetGamma(pScrn, zeros)) { 811 return FALSE; 812 } 813 } 814 815 pApm->MinClock = 23125; 816 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock set to %d MHz\n", 817 pApm->MinClock / 1000); 818 819 /* 820 * If the user has specified ramdac speed in the XF86Config 821 * file, we respect that setting. 822 */ 823 from = X_DEFAULT; 824 if (pEnt->device->dacSpeeds[0]) { 825 int speed = 0; 826 827 switch (pScrn->bitsPerPixel) { 828 case 4: 829 case 8: 830 speed = pEnt->device->dacSpeeds[DAC_BPP8]; 831 break; 832 case 16: 833 speed = pEnt->device->dacSpeeds[DAC_BPP16]; 834 break; 835 case 24: 836 speed = pEnt->device->dacSpeeds[DAC_BPP24]; 837 break; 838 case 32: 839 speed = pEnt->device->dacSpeeds[DAC_BPP32]; 840 break; 841 } 842 if (speed == 0) 843 pApm->MaxClock = pEnt->device->dacSpeeds[0]; 844 else 845 pApm->MaxClock = speed; 846 from = X_CONFIG; 847 } else { 848 switch(pApm->Chipset) 849 { 850 /* These values come from the Manual for AT24 and AT3D 851 in the overview of various modes. I've taken the largest 852 number for the different modes. Alliance wouldn't 853 tell me what the maximum frequency was, so... 854 */ 855 case AT24: 856 switch(pScrn->bitsPerPixel) 857 { 858 case 4: 859 case 8: 860 pApm->MaxClock = 160000; 861 break; 862 case 16: 863 pApm->MaxClock = 144000; 864 break; 865 case 24: 866 pApm->MaxClock = 75000; /* Hmm. */ 867 break; 868 case 32: 869 pApm->MaxClock = 94500; 870 break; 871 default: 872 return FALSE; 873 } 874 break; 875 case AT3D: 876 switch(pScrn->bitsPerPixel) 877 { 878 case 4: 879 case 8: 880 pApm->MaxClock = 175500; 881 break; 882 case 16: 883 pApm->MaxClock = 144000; 884 break; 885 case 24: 886 pApm->MaxClock = 94000; /* Changed from 75000 by Grenié */ 887 break; 888 case 32: 889 pApm->MaxClock = 94500; 890 break; 891 default: 892 return FALSE; 893 } 894 break; 895 case AP6422: 896 switch(pScrn->bitsPerPixel) 897 { 898 case 4: 899 case 8: 900 pApm->MaxClock = 135000; 901 break; 902 case 16: 903 pApm->MaxClock = 75000; 904 break; 905 case 32: 906 pApm->MaxClock = 60000; 907 break; 908 default: 909 return FALSE; 910 } 911 break; 912 default: 913 pApm->MaxClock = 135000; 914 break; 915 } 916 } 917 xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n", 918 pApm->MaxClock / 1000); 919 920 /* 921 * Setup the ClockRanges, which describe what clock ranges are available, 922 * and what sort of modes they can be used for. 923 */ 924 clockRanges = (ClockRangePtr)xnfcalloc(sizeof(ClockRange), 1); 925 clockRanges->next = NULL; 926 clockRanges->minClock = pApm->MinClock; 927 clockRanges->maxClock = pApm->MaxClock; 928 clockRanges->clockIndex = -1; /* programmable */ 929 clockRanges->interlaceAllowed = FALSE; /* XXX change this */ 930 clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ 931 932 /* Select valid modes from those available */ 933 if (pApm->NoAccel) { 934 /* 935 * XXX Assuming min pitch 256, max 2048 936 * XXX Assuming min height 128, max 1024 (changed EE) 937 */ 938 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 939 pScrn->display->modes, clockRanges, 940 NULL, 256, 2048, 941 pScrn->bitsPerPixel, 128, 1024, 942 pScrn->display->virtualX, 943 pScrn->display->virtualY, 944 pApm->FbMapSize, 945 LOOKUP_BEST_REFRESH); 946 } else { 947 /* 948 * XXX Assuming min height 128, max 2048 949 */ 950 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 951 pScrn->display->modes, clockRanges, 952 GetAccelPitchValues(pScrn), 0, 0, 953 pScrn->bitsPerPixel, 128, 1024, 954 pScrn->display->virtualX, 955 pScrn->display->virtualY, 956 pApm->FbMapSize, 957 LOOKUP_BEST_REFRESH); 958 } 959 960 if (i == -1) { 961 ApmFreeRec(pScrn); 962 return FALSE; 963 } 964 965 /* Prune the modes marked as invalid */ 966 xf86PruneDriverModes(pScrn); 967 968 if (i == 0 || pScrn->modes == NULL) { 969 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 970 ApmFreeRec(pScrn); 971 return FALSE; 972 } 973 974 xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 975 976 /* Set the current mode to the first in the list */ 977 pScrn->currentMode = pScrn->modes; 978 979 /* Print the list of modes being used */ 980 xf86PrintModes(pScrn); 981 982 /* Set display resolution */ 983 xf86SetDpi(pScrn, 0, 0); 984 985 /* Load bpp-specific modules */ 986 switch (pScrn->bitsPerPixel) { 987 case 8: 988 case 16: 989 case 24: 990 case 32: 991 mod = "fb"; 992 break; 993 } 994 995 if (mod && xf86LoadSubModule(pScrn, mod) == NULL) { 996 ApmFreeRec(pScrn); 997 return FALSE; 998 } 999 1000 /* Load XAA if needed */ 1001 if (!pApm->NoAccel) { 1002#ifdef HAVE_XAA_H 1003 if (!xf86LoadSubModule(pScrn, "xaa")) { 1004 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Falling back to shadowfb\n"); 1005 pApm->NoAccel = TRUE; 1006 pApm->ShadowFB = TRUE; 1007 } 1008#else 1009 pApm->NoAccel = TRUE; 1010 pApm->ShadowFB = TRUE; 1011#endif 1012 } 1013 1014 /* Load ramdac if needed */ 1015 if (pApm->hwCursor) { 1016 if (!xf86LoadSubModule(pScrn, "ramdac")) { 1017 ApmFreeRec(pScrn); 1018 return FALSE; 1019 } 1020 } 1021 1022 /* Load shadowfb if needed */ 1023 if (pApm->ShadowFB) { 1024 if (!xf86LoadSubModule(pScrn, "shadowfb")) { 1025 ApmFreeRec(pScrn); 1026 return FALSE; 1027 } 1028 } 1029 1030 pApm->CurrentLayout.displayWidth = pScrn->virtualX; 1031 pApm->CurrentLayout.displayHeight = pScrn->virtualY; 1032 pApm->CurrentLayout.bitsPerPixel = pScrn->bitsPerPixel; 1033 pApm->CurrentLayout.bytesPerScanline= (pApm->CurrentLayout.displayWidth * pApm->CurrentLayout.bitsPerPixel) >> 3; 1034 pApm->CurrentLayout.depth = pScrn->depth; 1035 pApm->CurrentLayout.Scanlines = 2 * (pScrn->videoRam << 10) / pApm->CurrentLayout.bytesPerScanline; 1036 if (pScrn->bitsPerPixel == 24) 1037 pApm->CurrentLayout.mask32 = 3; 1038 else 1039 pApm->CurrentLayout.mask32 = 32 / pScrn->bitsPerPixel - 1; 1040 1041 return TRUE; 1042} 1043 1044/* 1045 * Map the framebuffer and MMIO memory. 1046 */ 1047 1048static Bool 1049ApmMapMem(ScrnInfoPtr pScrn) 1050{ 1051 APMDECL(pScrn); 1052 vgaHWPtr hwp = VGAHWPTR(pScrn); 1053 1054#ifndef XSERVER_LIBPCIACCESS 1055 pApm->LinMap = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 1056 pApm->PciTag, 1057 (unsigned long)pApm->LinAddress, 1058 pApm->LinMapSize); 1059#else 1060 { 1061 void** result = (void**)&pApm->LinMap; 1062 int err = pci_device_map_range(pApm->PciInfo, 1063 pApm->LinAddress, 1064 pApm->LinMapSize, 1065 PCI_DEV_MAP_FLAG_WRITABLE | 1066 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 1067 result); 1068 1069 if (err) 1070 return FALSE; 1071 } 1072#endif 1073 1074 1075 if (pApm->LinMap == NULL) 1076 return FALSE; 1077 1078 if (pApm->Chipset >= AT3D) { 1079 pApm->FbBase = (void *)(((char *)pApm->LinMap) + 0x800000); 1080 pApm->VGAMap = ((char *)pApm->LinMap) + 0xFFF000; 1081 pApm->MemMap = ((char *)pApm->LinMap) + 0xFFEC00; 1082 pApm->BltMap = (void *)(((char *)pApm->LinMap) + 0x3F8000); 1083 } 1084 else { 1085 pApm->FbBase = (void *)pApm->LinMap; 1086 pApm->VGAMap = NULL; 1087 if (pScrn->videoRam == 6 * 1024 - 32) { 1088 pApm->MemMap = ((char *)pApm->LinMap) + 0x5FF800; 1089 pApm->BltMap = (void *)(((char *)pApm->LinMap) + 0x5F8000); 1090 } 1091 else { 1092 pApm->MemMap = ((char *)pApm->LinMap) + 0x3FF800; 1093 pApm->BltMap = (void *)(((char *)pApm->LinMap) + 0x3F8000); 1094 } 1095 } 1096 1097 /* 1098 * Initialize chipset 1099 */ 1100 pApm->c9 = RDXB(0xC9); 1101 if (pApm->Chipset >= AT3D) { 1102 pApm->d9 = RDXB(0xD9); 1103 pApm->db = RDXB(0xDB); 1104 1105 /* If you change these two, change them also in apm_funcs.c */ 1106 WRXB(0xDB, (pApm->db & 0xF4) | 0x0A); 1107 WRXB(0xD9, (pApm->d9 & 0xCF) | 0x20); 1108 1109 vgaHWSetMmioFuncs(hwp, (CARD8 *)pApm->LinMap, 0xFFF000); 1110 } 1111 if (pApm->Chipset >= AP6422) 1112 WRXB(0xC9, pApm->c9 | 0x10); 1113 1114 /* 1115 * Save color mode 1116 */ 1117 pApm->MiscOut = hwp->readMiscOut(hwp); 1118 1119 return TRUE; 1120} 1121 1122/* 1123 * Unmap the framebuffer and MMIO memory 1124 */ 1125 1126static Bool 1127ApmUnmapMem(ScrnInfoPtr pScrn) 1128{ 1129 APMDECL(pScrn); 1130 vgaHWPtr hwp = VGAHWPTR(pScrn); 1131 1132 /* 1133 * Reset color mode 1134 */ 1135 hwp->writeMiscOut(hwp, pApm->MiscOut); 1136 if (pApm->LinMap) { 1137 if (pApm->Chipset >= AT3D) { 1138 WRXB(0xD9, pApm->d9); 1139 WRXB(0xDB, pApm->db); 1140 } 1141 WRXB(0xC9, pApm->c9); 1142#ifndef XSERVER_LIBPCIACCESS 1143 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pApm->LinMap, pApm->LinMapSize); 1144#else 1145 pci_device_unmap_range(pApm->PciInfo, (pointer)pApm->LinMap, pApm->LinMapSize); 1146#endif 1147 pApm->LinMap = NULL; 1148 } 1149 else if (pApm->FbBase) 1150#ifndef XSERVER_LIBPCIACCESS 1151 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pApm->LinMap, 0x10000); 1152#else 1153 pci_device_unmap_range(pApm->PciInfo, (pointer)pApm->LinMap, 0x10000); 1154#endif 1155 1156 return TRUE; 1157} 1158 1159/* 1160 * This function saves the video state. 1161 */ 1162static void 1163ApmSave(ScrnInfoPtr pScrn) 1164{ 1165 APMDECL(pScrn); 1166 ApmRegPtr ApmReg = &pApm->SavedReg; 1167 vgaHWPtr hwp = VGAHWPTR(pScrn); 1168 1169 if (pApm->VGAMap) { 1170 ApmReg->SEQ[0x1B] = ApmReadSeq(0x1B); 1171 ApmReg->SEQ[0x1C] = ApmReadSeq(0x1C); 1172 1173 /* 1174 * Save fonts 1175 */ 1176 if (!(hwp->SavedReg.Attribute[0x10] & 1)) { 1177 if (pApm->FontInfo || (pApm->FontInfo = malloc(TEXT_AMOUNT))) { 1178 int locked; 1179 1180 locked = ApmReadSeq(0x10); 1181 if (locked) 1182 ApmWriteSeq(0x10, 0x12); 1183 ApmWriteSeq(0x1C, 0x3F); 1184 memcpy(pApm->FontInfo, pApm->FbBase, TEXT_AMOUNT); 1185 ApmWriteSeq(0x1C, ApmReg->SEQ[0x1C]); 1186 if (locked) 1187 ApmWriteSeq(0x10, 0); 1188 } 1189 } 1190 /* 1191 * This function will handle creating the data structure and filling 1192 * in the generic VGA portion. 1193 */ 1194 vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_MODE | VGA_SR_CMAP); 1195 1196 /* Hardware cursor registers. */ 1197 ApmReg->EX[XR140] = RDXL(0x140); 1198 ApmReg->EX[XR144] = RDXW(0x144); 1199 ApmReg->EX[XR148] = RDXL(0x148); 1200 ApmReg->EX[XR14C] = RDXW(0x14C); 1201 1202 ApmReg->CRT[0x19] = ApmReadCrtc(0x19); 1203 ApmReg->CRT[0x1A] = ApmReadCrtc(0x1A); 1204 ApmReg->CRT[0x1B] = ApmReadCrtc(0x1B); 1205 ApmReg->CRT[0x1C] = ApmReadCrtc(0x1C); 1206 ApmReg->CRT[0x1D] = ApmReadCrtc(0x1D); 1207 ApmReg->CRT[0x1E] = ApmReadCrtc(0x1E); 1208 1209 /* RAMDAC registers. */ 1210 ApmReg->EX[XRE8] = RDXL(0xE8); 1211 ApmReg->EX[XREC] = RDXL(0xEC); 1212 1213 /* Color correction */ 1214 ApmReg->EX[XRE0] = RDXL(0xE0); 1215 1216 ApmReg->EX[XR80] = RDXB(0x80); 1217 } 1218 else { 1219 /* 1220 * This function will handle creating the data structure and filling 1221 * in the generic VGA portion. 1222 */ 1223 vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_ALL); 1224 1225 ApmReg->SEQ[0x1B] = rdinx(pApm->xport, 0x1B); 1226 ApmReg->SEQ[0x1C] = rdinx(pApm->xport, 0x1C); 1227 1228 /* Hardware cursor registers. */ 1229 ApmReg->EX[XR140] = RDXL(0x140); 1230 ApmReg->EX[XR144] = RDXW(0x144); 1231 ApmReg->EX[XR148] = RDXL(0x148); 1232 ApmReg->EX[XR14C] = RDXW(0x14C); 1233 1234 ApmReg->CRT[0x19] = rdinx(pApm->iobase + 0x3D4, 0x19); 1235 ApmReg->CRT[0x1A] = rdinx(pApm->iobase + 0x3D4, 0x1A); 1236 ApmReg->CRT[0x1B] = rdinx(pApm->iobase + 0x3D4, 0x1B); 1237 ApmReg->CRT[0x1C] = rdinx(pApm->iobase + 0x3D4, 0x1C); 1238 ApmReg->CRT[0x1D] = rdinx(pApm->iobase + 0x3D4, 0x1D); 1239 ApmReg->CRT[0x1E] = rdinx(pApm->iobase + 0x3D4, 0x1E); 1240 1241 /* RAMDAC registers. */ 1242 ApmReg->EX[XRE8] = RDXL(0xE8); 1243 ApmReg->EX[XREC] = RDXL(0xEC); 1244 1245 /* Color correction */ 1246 ApmReg->EX[XRE0] = RDXL(0xE0); 1247 1248 ApmReg->EX[XR80] = RDXB(0x80); 1249 } 1250} 1251 1252#define WITHIN(v,c1,c2) (((v) >= (c1)) && ((v) <= (c2))) 1253 1254static unsigned 1255comp_lmn(ApmPtr pApm, long clock) 1256{ 1257 int n, m, l, f; 1258 double fvco; 1259 double fout; 1260 double fmax, fmin; 1261 double fref; 1262 double fvco_goal; 1263 double k, c; 1264 double fout_best = 0; 1265 unsigned int best = 0; 1266 1267 if (pApm->Chipset >= AT3D) 1268 fmax = 370000.0; 1269 else 1270 fmax = 250000.0; 1271 1272 fref = 14318.0; 1273 fmin = fmax / 2.0; 1274 1275 for (m = 1; m <= 5; m++) 1276 { 1277 for (l = 3; l >= 0; l--) 1278 { 1279 for (n = 8; n <= 127; n++) 1280 { 1281 fout = ((double)(n + 1) * fref)/((double)(m + 1) * (1 << l)); 1282 fvco_goal = (double)clock * (double)(1 << l); 1283 fvco = fout * (double)(1 << l); 1284 if (!WITHIN(fvco, 0.99*fvco_goal, 1.01*fvco_goal)) 1285 continue; 1286 if (!WITHIN(fvco, fmin, fmax)) 1287 continue; 1288 if (!WITHIN(fvco / (double)(n+1), 300.0, 300000.0)) 1289 continue; 1290 if (!WITHIN(fref / (double)(m+1), 300.0, 300000.0)) 1291 continue; 1292 1293 if (fout_best != 0) { 1294 double diff_new = clock - fout; 1295 double diff_old = clock - best; 1296 diff_new = diff_new < 0 ? -diff_new : diff_new; 1297 diff_old = diff_old < 0 ? -diff_old : diff_old; 1298 if (diff_new > diff_old) 1299 continue; 1300 } 1301 fout_best = fout; 1302 1303 /* The following formula was empirically derived by 1304 matching a number of fvco values with acceptable 1305 values of f. 1306 1307 (fvco can be 185MHz - 370MHz on AT3D) 1308 (fvco can be 125MHz - 250MHz on AT24/AP6422) 1309 1310 The table that was measured up follows: 1311 1312 AT3D 1313 1314 fvco f 1315 (125) (x-7) guess 1316 200 5-7 1317 219 4-7 1318 253 3-6 1319 289 2-5 1320 320 0-4 1321 (400) (0-x) guess 1322 1323 AT24 1324 1325 fvco f 1326 126 7 1327 200 5-7 1328 211 4-7 1329 1330 AP6422 1331 1332 fvco f 1333 126 7 1334 169 5-7 1335 200 4-5 1336 211 4-5 1337 1338 From this, a function "f = k * fvco + c" was derived. 1339 1340 For AT3D, this table was measured with MCLK == 50MHz. 1341 The driver has since been set to use MCLK == 57.3MHz for, 1342 but I don't think that makes a difference here. 1343 */ 1344 1345 if (pApm->Chipset >= AT24) 1346 { 1347 k = 7.0 / (175.0 - 380.0); 1348 c = -k * 380.0; 1349 f = (int)(k * fvco/1000.0 + c + 0.5); 1350 if (f > 7) f = 7; 1351 if (f < 0) f = 0; 1352 } else { /* i.e AP6422 */ 1353 c = (211.0*6.0-169.0*4.5)/(211.0-169.0); 1354 k = (4.5-c)/211.0; 1355 f = (int)(k * fvco/1000.0 + c + 0.5); 1356 if (f > 7) f = 7; 1357 if (f < 0) f = 0; 1358 } 1359 1360 best = (n << 16) | (m << 8) | (l << 2) | (f << 4); 1361 } 1362 } 1363 } 1364 1365 if (fout_best != 0) 1366 return best; 1367 1368 xf86DrvMsg(pApm->scrnIndex, X_PROBED, 1369 "Cannot find register values for clock %6.2f MHz. " 1370 "Please use a (slightly) different clock.\n", 1371 (double)clock / 1000.0); 1372 return 0; 1373} 1374 1375/* 1376 * Initialise a new mode. This is currently still using the old 1377 * "initialise struct, restore/write struct to HW" model. That could 1378 * be changed. 1379 */ 1380 1381static Bool 1382ApmModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 1383{ 1384 APMDECL(pScrn); 1385 ApmRegPtr ApmReg = &pApm->ModeReg; 1386 vgaHWPtr hwp; 1387 1388 1389 /* set clockIndex to "2" for programmable clocks */ 1390 if (pScrn->progClock) 1391 mode->ClockIndex = 2; 1392 1393 /* prepare standard VGA register contents */ 1394 if (!vgaHWInit(pScrn, mode)) 1395 return FALSE; 1396 pScrn->vtSema = TRUE; 1397 hwp = VGAHWPTR(pScrn); 1398 1399 hwp->writeMiscOut(hwp, pApm->MiscOut | 0x0F); 1400 1401#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 1402 if (xf86IsPc98()) 1403 outb(0xFAC, 0xFF); 1404#endif 1405 1406 memcpy(ApmReg, &pApm->SavedReg, sizeof pApm->SavedReg); 1407 1408 /* 1409 * The APM chips have a scale factor of 8 for the 1410 * scanline offset. There are four extended bit in addition 1411 * to the 8 VGA bits. 1412 */ 1413 { 1414 int offset; 1415 1416 offset = (pApm->CurrentLayout.displayWidth * 1417 pApm->CurrentLayout.bitsPerPixel / 8) >> 3; 1418 hwp->ModeReg.CRTC[0x13] = offset; 1419 /* Bit 8 resides at CR1C bits 7:4. */ 1420 ApmReg->CRT[0x1C] = (offset & 0xF00) >> 4; 1421 } 1422 1423 /* Set pixel depth. */ 1424 switch(pApm->CurrentLayout.bitsPerPixel) 1425 { 1426 case 4: 1427 ApmReg->EX[XR80] = 0x01; 1428 break; 1429 case 8: 1430 ApmReg->EX[XR80] = 0x02; 1431 break; 1432 case 16: 1433 if (pApm->CurrentLayout.depth == 15) 1434 ApmReg->EX[XR80] = 0x0C; 1435 else 1436 ApmReg->EX[XR80] = 0x0D; 1437 break; 1438 case 24: 1439 ApmReg->EX[XR80] = 0x0E; 1440 break; 1441 case 32: 1442 ApmReg->EX[XR80] = 0x0F; 1443 break; 1444 default: 1445 FatalError("Unsupported bit depth %d\n", pApm->CurrentLayout.depth); 1446 break; 1447 } 1448 1449 /* Set banking register to zero. */ 1450 ApmReg->EX[XRC0] = 0; 1451 1452 /* Handle the CRTC overflow bits. */ 1453 { 1454 unsigned char val; 1455 /* Vertical Overflow. */ 1456 val = 0; 1457 if ((mode->CrtcVTotal - 2) & 0x400) 1458 val |= 0x01; 1459 if ((mode->CrtcVDisplay - 1) & 0x400) 1460 val |= 0x02; 1461 /* VBlankStart is equal to VSyncStart + 1. */ 1462 if (mode->CrtcVSyncStart & 0x400) 1463 val |= 0x04; 1464 /* VRetraceStart is equal to VSyncStart + 1. */ 1465 if (mode->CrtcVSyncStart & 0x400) 1466 val |= 0x08; 1467 ApmReg->CRT[0x1A] = val; 1468 1469 /* Horizontal Overflow. */ 1470 val = 0; 1471 if ((mode->CrtcHTotal / 8 - 5) & 0x100) 1472 val |= 1; 1473 if ((mode->CrtcHDisplay / 8 - 1) & 0x100) 1474 val |= 2; 1475 /* HBlankStart is equal to HSyncStart - 1. */ 1476 if ((mode->CrtcHSyncStart / 8 - 1) & 0x100) 1477 val |= 4; 1478 /* HRetraceStart is equal to HSyncStart. */ 1479 if ((mode->CrtcHSyncStart / 8) & 0x100) 1480 val |= 8; 1481 ApmReg->CRT[0x1B] = val; 1482 1483 /* Assume the CRTC is not KGA (see vgaHWInit) */ 1484 hwp->ModeReg.CRTC[3] = (hwp->ModeReg.CRTC[3] & 0xE0) | 1485 (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F); 1486 hwp->ModeReg.CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2) 1487 | (hwp->ModeReg.CRTC[5] & 0x7F); 1488 hwp->ModeReg.CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF; 1489 } 1490 ApmReg->CRT[0x1E] = 1; /* disable autoreset feature */ 1491 1492 /* Program clock select. */ 1493 ApmReg->EX[XREC] = comp_lmn(pApm, mode->Clock); 1494 if (!ApmReg->EX[XREC]) 1495 return FALSE; 1496 hwp->ModeReg.MiscOutReg |= 0x0C; 1497 1498 /* Set up the RAMDAC registers. */ 1499 1500 if (pApm->CurrentLayout.bitsPerPixel > 8) 1501 /* Get rid of white border. */ 1502 hwp->ModeReg.Attribute[0x11] = 0x00; 1503 else 1504 hwp->ModeReg.Attribute[0x11] = 0xFF; 1505 if (pApm->MemClk) 1506 ApmReg->EX[XRE8] = comp_lmn(pApm, pApm->MemClk); 1507 else if (pApm->Chipset >= AT3D) 1508 ApmReg->EX[XRE8] = 0x071F01E8; /* Enable 58MHz MCLK (actually 57.3 MHz) 1509 This is what is used in the Windows 1510 drivers. The BIOS sets it to 50MHz. */ 1511 else 1512 ApmReg->EX[XRE8] = RDXL(0xE8); /* No change */ 1513 1514 ApmReg->EX[XRE0] = 0x10; 1515 1516 /* If you change it, change in apm_funcs.c as well */ 1517 if (pApm->Chipset >= AT3D) { 1518 ApmReg->SEQ[0x1B] = 0x20; 1519 ApmReg->SEQ[0x1C] = 0x2F; 1520 } 1521 else { 1522 ApmReg->SEQ[0x1B] = 0x24; 1523 if (pScrn->videoRam >= 6 * 1024) 1524 ApmReg->SEQ[0x1C] = 0x2F; 1525 else 1526 ApmReg->SEQ[0x1C] = 0x2D; 1527 } 1528 1529 /* ICICICICI */ 1530 ApmRestore(pScrn, &hwp->ModeReg, ApmReg); 1531 1532 return TRUE; 1533} 1534 1535/* 1536 * Restore the initial mode. 1537 */ 1538static void 1539ApmRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, ApmRegPtr ApmReg) 1540{ 1541 APMDECL(pScrn); 1542 1543 vgaHWProtect(pScrn, TRUE); 1544 ApmUnlock(pApm); 1545 1546 if (pApm->VGAMap) { 1547 /* 1548 * Restore fonts 1549 */ 1550 if (!(vgaReg->Attribute[0x10] & 1) && pApm->FontInfo) { 1551 ApmWriteSeq(0x1C, 0x3F); 1552 memcpy(pApm->FbBase, pApm->FontInfo, TEXT_AMOUNT); 1553 } 1554 1555 /* Set aperture index to 0. */ 1556 WRXW(0xC0, 0); 1557 1558 /* 1559 * Write the extended registers first 1560 */ 1561 ApmWriteSeq(0x1B, ApmReg->SEQ[0x1B]); 1562 ApmWriteSeq(0x1C, ApmReg->SEQ[0x1C]); 1563 1564 /* Hardware cursor registers. */ 1565 WRXL(0x140, ApmReg->EX[XR140]); 1566 WRXW(0x144, ApmReg->EX[XR144]); 1567 WRXL(0x148, ApmReg->EX[XR148]); 1568 WRXW(0x14C, ApmReg->EX[XR14C]); 1569 1570 ApmWriteCrtc(0x19, ApmReg->CRT[0x19]); 1571 ApmWriteCrtc(0x1A, ApmReg->CRT[0x1A]); 1572 ApmWriteCrtc(0x1B, ApmReg->CRT[0x1B]); 1573 ApmWriteCrtc(0x1D, ApmReg->CRT[0x1D]); 1574 ApmWriteCrtc(0x1E, ApmReg->CRT[0x1E]); 1575 1576 /* RAMDAC registers. */ 1577 WRXL(0xE8, ApmReg->EX[XRE8]); 1578 1579 WRXL(0xEC, ApmReg->EX[XREC] & ~(1 << 7)); 1580 WRXL(0xEC, ApmReg->EX[XREC] | (1 << 7)); /* Do a PLL resync */ 1581 1582 /* Color correction */ 1583 WRXL(0xE0, ApmReg->EX[XRE0]); 1584 1585 /* 1586 * This function handles restoring the generic VGA registers. 1587 */ 1588 vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP); 1589 1590 /* set these after setting the default VGA registers */ 1591 ApmWriteCrtc(0x1C, ApmReg->CRT[0x1C]); 1592 WRXB(0x80, ApmReg->EX[XR80]); 1593 } 1594 else { 1595 /* Set aperture index to 0. */ 1596 WRXW(0xC0, 0); 1597 1598 /* 1599 * Write the extended registers first 1600 */ 1601 wrinx(pApm->xport, 0x1B, ApmReg->SEQ[0x1B]); 1602 wrinx(pApm->xport, 0x1C, ApmReg->SEQ[0x1C]); 1603 1604 /* Hardware cursor registers. */ 1605 WRXL(0x140, ApmReg->EX[XR140]); 1606 WRXW(0x144, ApmReg->EX[XR144]); 1607 WRXL(0x148, ApmReg->EX[XR148]); 1608 WRXW(0x14C, ApmReg->EX[XR14C]); 1609 1610 wrinx(pApm->iobase + 0x3D4, 0x19, ApmReg->CRT[0x19]); 1611 wrinx(pApm->iobase + 0x3D4, 0x1A, ApmReg->CRT[0x1A]); 1612 wrinx(pApm->iobase + 0x3D4, 0x1B, ApmReg->CRT[0x1B]); 1613 wrinx(pApm->iobase + 0x3D4, 0x1C, ApmReg->CRT[0x1C]); 1614 wrinx(pApm->iobase + 0x3D4, 0x1D, ApmReg->CRT[0x1D]); 1615 wrinx(pApm->iobase + 0x3D4, 0x1E, ApmReg->CRT[0x1E]); 1616 1617 /* RAMDAC registers. */ 1618 WRXL(0xE8, ApmReg->EX[XRE8]); 1619 WRXL(0xEC, ApmReg->EX[XREC] & ~(1 << 7)); 1620 WRXL(0xEC, ApmReg->EX[XREC] | (1 << 7)); /* Do a PLL resync */ 1621 1622 /* Color correction */ 1623 WRXL(0xE0, ApmReg->EX[XRE0]); 1624 1625 WRXB(0x80, ApmReg->EX[XR80]); 1626 1627 /* 1628 * This function handles restoring the generic VGA registers. 1629 */ 1630 vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); 1631 } 1632 1633 vgaHWProtect(pScrn, FALSE); 1634} 1635 1636 1637/* Refresh a region of the shadow framebuffer to the screen */ 1638static void 1639ApmRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) 1640{ 1641 APMDECL(pScrn); 1642 int width, height, Bpp, FBPitch; 1643 unsigned char *src, *dst; 1644 1645 Bpp = pApm->CurrentLayout.bitsPerPixel >> 3; 1646 FBPitch = pApm->CurrentLayout.bytesPerScanline; 1647 1648 while(num--) { 1649 width = (pbox->x2 - pbox->x1) * Bpp; 1650 height = pbox->y2 - pbox->y1; 1651 src = pApm->ShadowPtr + (pbox->y1 * pApm->ShadowPitch) + 1652 (pbox->x1 * Bpp); 1653 dst = (unsigned char *)pApm->FbBase + (pbox->y1 * FBPitch) + (pbox->x1 * Bpp); 1654 1655 while(height--) { 1656 memcpy(dst, src, width); 1657 dst += FBPitch; 1658 src += pApm->ShadowPitch; 1659 } 1660 1661 pbox++; 1662 } 1663} 1664 1665 1666/* Mandatory */ 1667 1668/* This gets called at the start of each server generation */ 1669 1670static Bool 1671ApmScreenInit(SCREEN_INIT_ARGS_DECL) 1672{ 1673 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1674 APMDECL(pScrn); 1675 int ret; 1676 unsigned char *FbBase; 1677 1678 pApm->pScreen = pScreen; 1679 1680 /* Map the chip memory and MMIO areas */ 1681 if (!ApmMapMem(pScrn)) 1682 return FALSE; 1683 1684 /* No memory reserved yet */ 1685 pApm->OffscreenReserved = 0; 1686 1687 /* Save the current state */ 1688 ApmSave(pScrn); 1689 1690 /* Initialise the first mode */ 1691 ApmModeInit(pScrn, pScrn->currentMode); 1692 pApm->CurrentLayout.pMode = pScrn->currentMode; 1693 1694 /* Darken the screen for aesthetic reasons and set the viewport */ 1695 ApmSaveScreen(pScreen, SCREEN_SAVER_ON); 1696 ApmAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 1697 1698 /* 1699 * Reset fb's visual list. 1700 */ 1701 miClearVisualTypes(); 1702 1703 /* Setup the visuals we support. */ 1704 1705 /* 1706 * For bpp > 8, the default visuals are not acceptable because we only 1707 * support TrueColor and not DirectColor. To deal with this, call 1708 * miSetVisualTypes for each visual supported. 1709 */ 1710 1711 if (pApm->CurrentLayout.bitsPerPixel > 8) { 1712 if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits, 1713 pScrn->defaultVisual)) 1714 return FALSE; 1715 } else { 1716 if (!miSetVisualTypes(pScrn->depth, 1717 miGetDefaultVisualMask(pScrn->depth), 1718 pScrn->rgbBits, pScrn->defaultVisual)) 1719 return FALSE; 1720 } 1721 1722 /* 1723 * Call the framebuffer layer's ScreenInit function, and fill in other 1724 * pScreen fields. 1725 */ 1726 1727 if(pApm->ShadowFB) { 1728 pApm->ShadowPitch = 1729 ((pScrn->virtualX * pScrn->bitsPerPixel >> 3) + 3) & ~3L; 1730 pApm->ShadowPtr = malloc(pApm->ShadowPitch * pScrn->virtualY); 1731 FbBase = pApm->ShadowPtr; 1732 } else { 1733 pApm->ShadowPtr = NULL; 1734 FbBase = pApm->FbBase; 1735 } 1736 1737 /* Reserve memory */ 1738 ApmHWCursorReserveSpace(pApm); 1739 ApmAccelReserveSpace(pApm); 1740 1741 miSetPixmapDepths(); 1742 1743 switch (pScrn->bitsPerPixel) { 1744 case 8: 1745 case 16: 1746 case 24: 1747 case 32: 1748 ret = fbScreenInit(pScreen, FbBase, pScrn->virtualX, 1749 pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, 1750 pScrn->displayWidth, pScrn->bitsPerPixel); 1751 break; 1752 default: 1753 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1754 "Internal error: invalid bpp (%d) in ApmScrnInit\n", 1755 pScrn->bitsPerPixel); 1756 ret = FALSE; 1757 break; 1758 } 1759 if (!ret) 1760 return FALSE; 1761 1762 if (pScrn->bitsPerPixel > 8) { 1763 VisualPtr visual; 1764 1765 /* Fixup RGB ordering */ 1766 visual = pScreen->visuals + pScreen->numVisuals; 1767 while (--visual >= pScreen->visuals) { 1768 if ((visual->class | DynamicClass) == DirectColor) { 1769 visual->offsetRed = pScrn->offset.red; 1770 visual->offsetGreen = pScrn->offset.green; 1771 visual->offsetBlue = pScrn->offset.blue; 1772 visual->redMask = pScrn->mask.red; 1773 visual->greenMask = pScrn->mask.green; 1774 visual->blueMask = pScrn->mask.blue; 1775 } 1776 } 1777 } 1778 1779 /* must be after visual RGB order fixed */ 1780 if (pScrn->bitsPerPixel > 4) 1781 fbPictureInit(pScreen, 0, 0); 1782 1783 xf86SetBlackWhitePixels(pScreen); 1784 1785 if (!pApm->ShadowFB) { /* hardware cursor needs to wrap this layer */ 1786 if(!ApmDGAInit(pScreen)) { 1787 xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"DGA initialization failed\n"); 1788 } 1789 } 1790 1791 /* 1792 * Initialize the acceleration interface. 1793 */ 1794#ifdef HAVE_XAA_H 1795 if (!pApm->NoAccel) { 1796 ApmAccelInit(pScreen); /* set up XAA interface */ 1797 } 1798#endif 1799 1800 xf86SetBackingStore(pScreen); 1801 xf86SetSilkenMouse(pScreen); 1802 1803 /* Initialise cursor functions */ 1804 miDCInitialize (pScreen, xf86GetPointerScreenFuncs()); 1805 1806 /* Initialize HW cursor layer (after DGA and SW cursor) */ 1807 if (pApm->hwCursor) { 1808 if (!ApmHWCursorInit(pScreen)) 1809 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1810 "Hardware cursor initialization failed\n"); 1811 } 1812 1813 1814 /* Initialise default colourmap */ 1815 if (!miCreateDefColormap(pScreen)) 1816 return FALSE; 1817 1818 /* 1819 * Initialize colormap layer. 1820 * Must follow initialization of the default colormap. 1821 */ 1822 if (!xf86HandleColormaps(pScreen, 256, 8, ApmLoadPalette, NULL, 1823 CMAP_RELOAD_ON_MODE_SWITCH)) { 1824 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Colormap initialization failed\n"); 1825 return FALSE; 1826 } 1827 1828 if (pApm->ShadowFB) 1829 ShadowFBInit(pScreen, ApmRefreshArea); 1830 1831 xf86DPMSInit(pScreen, ApmDisplayPowerManagementSet, 0); 1832 1833 ApmInitVideo(pScreen); 1834 1835 pScreen->SaveScreen = ApmSaveScreen; 1836 1837 pApm->CloseScreen = pScreen->CloseScreen; 1838 pScreen->CloseScreen = ApmCloseScreen; 1839 1840 pScrn->memPhysBase = pApm->LinAddress; 1841 pScrn->fbOffset = (((char *)pApm->FbBase) - ((char *)pApm->LinMap)); 1842 1843 /* Report any unused options (only for the first generation) */ 1844 if (serverGeneration == 1) { 1845 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1846 } 1847 1848#ifdef XF86RUSH 1849 if (ApmGeneration != serverGeneration) { 1850 if ((ApmPixmapIndex = AllocatePixmapPrivateIndex()) < 0) 1851 return FALSE; 1852 ApmGeneration = serverGeneration; 1853 } 1854 1855 if (!AllocatePixmapPrivate(pScreen, ApmPixmapIndex, sizeof(ApmPixmapRec))) 1856 return FALSE; 1857#endif 1858 1859 /* Done */ 1860 return TRUE; 1861} 1862 1863/* mandatory */ 1864static void 1865ApmLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, 1866 VisualPtr pVisual) 1867{ 1868 APMDECL(pScrn); 1869 int i, index, last = -1; 1870 1871 if (pApm->VGAMap) { 1872 for (i = 0; i < numColors; i++) { 1873 index = indices[i]; 1874 if (index != last) 1875 ApmWriteDacWriteAddr(index); 1876 last = index + 1; 1877 ApmWriteDacData(colors[index].red); 1878 ApmWriteDacData(colors[index].green); 1879 ApmWriteDacData(colors[index].blue); 1880 } 1881 } 1882 else { 1883 for (i = 0; i < numColors; i++) { 1884 index = indices[i]; 1885 if (index != last) 1886 outb(pApm->iobase + 0x3C8, index); 1887 last = index + 1; 1888 outb(pApm->iobase + 0x3C9, colors[index].red); 1889 outb(pApm->iobase + 0x3C9, colors[index].green); 1890 outb(pApm->iobase + 0x3C9, colors[index].blue); 1891 } 1892 } 1893} 1894 1895/* Usually mandatory */ 1896Bool 1897ApmSwitchMode(SWITCH_MODE_ARGS_DECL) 1898{ 1899 SCRN_INFO_PTR(arg); 1900 return ApmModeInit(pScrn, mode); 1901} 1902 1903/* 1904 * This function is used to initialize the Start Address - the first 1905 * displayed location in the video memory. 1906 */ 1907/* Usually mandatory */ 1908void 1909ApmAdjustFrame(ADJUST_FRAME_ARGS_DECL) 1910{ 1911 SCRN_INFO_PTR(arg); 1912 APMDECL(pScrn); 1913 int Base; 1914 1915 if (pApm->CurrentLayout.bitsPerPixel == 24) 1916 x = (x + 3) & ~3; 1917 Base = ((y * pApm->CurrentLayout.displayWidth + x) * (pApm->CurrentLayout.bitsPerPixel / 8)) >> 2; 1918 /* 1919 * These are the generic starting address registers. 1920 */ 1921 if (pApm->VGAMap) { 1922 ApmWriteCrtc(0x0C, Base >> 8); 1923 ApmWriteCrtc(0x0D, Base); 1924 1925 /* 1926 * Here the high-order bits are masked and shifted, and put into 1927 * the appropriate extended registers. 1928 */ 1929 ApmWriteCrtc(0x1C, (ApmReadCrtc(0x1C) & 0xF0) | ((Base & 0x0F0000) >> 16)); 1930 } 1931 else { 1932 outw(pApm->iobase + 0x3D4, (Base & 0x00FF00) | 0x0C); 1933 outw(pApm->iobase + 0x3D4, ((Base & 0x00FF) << 8) | 0x0D); 1934 1935 /* 1936 * Here the high-order bits are masked and shifted, and put into 1937 * the appropriate extended registers. 1938 */ 1939 modinx(pApm->iobase + 0x3D4, 0x1C, 0x0F, (Base & 0x0F0000) >> 16); 1940 } 1941} 1942 1943/* 1944 * This is called when VT switching back to the X server. Its job is 1945 * to reinitialise the video mode. 1946 * 1947 * We may wish to unmap video/MMIO memory too. 1948 */ 1949 1950/* Mandatory */ 1951static Bool 1952ApmEnterVT(VT_FUNC_ARGS_DECL) 1953{ 1954 SCRN_INFO_PTR(arg); 1955 APMDECL(pScrn); 1956 vgaHWPtr hwp = VGAHWPTR(pScrn); 1957 1958 if (pApm->Chipset >= AT3D) { 1959 /* If you change it, change it also in apm_funcs.c */ 1960 WRXB(0xDB, (pApm->db & 0xF4) | 0x0A | pApm->Rush); 1961 WRXB(0xD9, (pApm->d9 & 0xCF) | 0x20); 1962 } 1963 if (pApm->Chipset >= AP6422) 1964 WRXB(0xC9, pApm->c9 | 0x10); 1965 ApmUnlock(APMPTR(pScrn)); 1966 vgaHWUnlock(hwp); 1967 /* 1968 * Set color mode 1969 */ 1970 hwp->writeMiscOut(hwp, pApm->MiscOut | 0x0F); 1971 1972 if (!ApmModeInit(pScrn, pScrn->currentMode)) 1973 return FALSE; 1974 ApmAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 1975 1976 return TRUE; 1977} 1978 1979/* Mandatory */ 1980static void 1981ApmLeaveVT(VT_FUNC_ARGS_DECL) 1982{ 1983 SCRN_INFO_PTR(arg); 1984 APMDECL(pScrn); 1985 vgaHWPtr hwp = VGAHWPTR(pScrn); 1986 1987 ApmRestore(pScrn, &hwp->SavedReg, &pApm->SavedReg); 1988 /* 1989 * Reset color mode 1990 */ 1991 (*hwp->writeMiscOut)(hwp, pApm->MiscOut); 1992 vgaHWLock(hwp); 1993 ApmLock(pApm); 1994 if (pApm->Chipset >= AT3D) { 1995 WRXB(0xD9, pApm->d9); 1996 WRXB(0xDB, pApm->db); 1997 } 1998 WRXB(0xC9, pApm->c9); 1999 2000#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 2001 if (xf86IsPc98()) 2002 outb(0xFAC, 0xFE); 2003#endif 2004} 2005 2006/* 2007 * This is called at the end of each server generation. It restores the 2008 * original (text) mode. It should really also unmap the video memory too. 2009 */ 2010 2011/* Mandatory */ 2012static Bool 2013ApmCloseScreen(CLOSE_SCREEN_ARGS_DECL) 2014{ 2015 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 2016 vgaHWPtr hwp = VGAHWPTR(pScrn); 2017 APMDECL(pScrn); 2018 2019 if (pScrn->vtSema) { 2020 ApmRestore(pScrn, &hwp->SavedReg, &pApm->SavedReg); 2021 vgaHWLock(hwp); 2022 ApmUnmapMem(pScrn); 2023 } 2024#ifdef HAVE_XAA_H 2025 if(pApm->AccelInfoRec) 2026 XAADestroyInfoRec(pApm->AccelInfoRec); 2027 if(pApm->DGAXAAInfo) 2028 XAADestroyInfoRec(pApm->DGAXAAInfo); 2029 pApm->AccelInfoRec = NULL; 2030#endif 2031 if(pApm->CursorInfoRec) 2032 xf86DestroyCursorInfoRec(pApm->CursorInfoRec); 2033 pApm->CursorInfoRec = NULL; 2034 free(pApm->DGAModes); 2035 free(pApm->adaptor); 2036 2037 pScrn->vtSema = FALSE; 2038 2039#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 2040 if (xf86IsPc98()) 2041 outb(0xFAC, 0xFE); 2042#endif 2043 2044 pScreen->CloseScreen = pApm->CloseScreen; 2045 return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 2046} 2047 2048/* Free up any per-generation data structures */ 2049 2050/* Optional */ 2051static void 2052ApmFreeScreen(FREE_SCREEN_ARGS_DECL) 2053{ 2054 SCRN_INFO_PTR(arg); 2055 vgaHWFreeHWRec(pScrn); 2056 ApmFreeRec(pScrn); 2057} 2058 2059/* Checks if a mode is suitable for the selected chipset. */ 2060 2061/* Optional */ 2062static ModeStatus 2063ApmValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 2064{ 2065 if (mode->Flags & V_INTERLACE) 2066 return(MODE_BAD); 2067 2068 return(MODE_OK); 2069} 2070 2071 2072/* 2073 * ApmDisplayPowerManagementSet -- 2074 * 2075 * Sets VESA Display Power Management Signaling (DPMS) Mode. 2076 */ 2077static void 2078ApmDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, 2079 int flags) 2080{ 2081 APMDECL(pScrn); 2082 unsigned char dpmsreg, tmp; 2083 2084 if (PowerManagementMode < sizeof pApm->DPMSMask && 2085 PowerManagementMode >= 0) 2086 PowerManagementMode = pApm->DPMSMask[PowerManagementMode]; 2087 switch (PowerManagementMode) 2088 { 2089 case DPMSModeOn: 2090 /* Screen: On; HSync: On, VSync: On */ 2091 dpmsreg = 0x00; 2092 break; 2093 case DPMSModeStandby: 2094 /* Screen: Off; HSync: Off, VSync: On */ 2095 dpmsreg = 0x01; 2096 break; 2097 case DPMSModeSuspend: 2098 /* Screen: Off; HSync: On, VSync: Off */ 2099 dpmsreg = 0x02; 2100 break; 2101 case DPMSModeOff: 2102 /* Screen: Off; HSync: Off, VSync: Off */ 2103 dpmsreg = 0x03; 2104 break; 2105 default: 2106 dpmsreg = 0; 2107 } 2108 tmp = RDXB(0xD0); 2109 WRXB(0xD0, (tmp & 0xFC) | dpmsreg); 2110} 2111 2112static Bool 2113ApmSaveScreen(ScreenPtr pScreen, int mode) 2114{ 2115 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 2116 Bool unblank; 2117 2118 unblank = xf86IsUnblank(mode); 2119 2120 if (unblank) 2121 SetTimeSinceLastInputEvent(); 2122 2123 if (pScrn->vtSema) 2124 vgaHWBlankScreen(pScrn, unblank); 2125 return TRUE; 2126} 2127 2128#ifdef APM_DEBUG 2129unsigned char _L_ACR(unsigned char *x); 2130unsigned char _L_ACR(unsigned char *x) 2131{ 2132 return *x; 2133} 2134 2135unsigned short _L_ASR(unsigned short *x); 2136unsigned short _L_ASR(unsigned short *x) 2137{ 2138 return *x; 2139} 2140 2141unsigned int _L_AIR(unsigned int *x); 2142unsigned int _L_AIR(unsigned int *x) 2143{ 2144 return *x; 2145} 2146 2147void _L_ACW(char *x, char y); 2148void _L_ACW(char *x, char y) 2149{ 2150 *x = y; 2151} 2152 2153void _L_ASW(short *x, short y); 2154void _L_ASW(short *x, short y) 2155{ 2156 *x = y; 2157} 2158 2159void _L_AIW(int *x, int y); 2160void _L_AIW(int *x, int y) 2161{ 2162 *x = y; 2163} 2164#endif 2165