lg_driver.c revision afee0bec
1/* 2 * Driver for CL-GD546x -- The Laguna family 3 * 4 * lg_driver.c 5 * 6 * (c) 1998 Corin Anderson. 7 * corina@the4cs.com 8 * Tukwila, WA 9 * 10 * This driver is derived from the cir_driver.c module. 11 * Original authors and contributors list include: 12 * Radoslaw Kapitan, Andrew Vanderstock, Dirk Hohndel, 13 * David Dawes, Andrew E. Mileski, Leonard N. Zubkoff, 14 * Guy DESBIEF, Itai Nahshon. 15 */ 16/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/lg_driver.c,v 1.49 2003/11/03 05:11:09 tsi Exp $ */ 17 18#ifdef HAVE_CONFIG_H 19#include "config.h" 20#endif 21 22#define EXPERIMENTAL 23 24/* All drivers should typically include these */ 25#include "xf86.h" 26#include "xf86_OSproc.h" 27 28/* All drivers need this */ 29 30#include "compiler.h" 31 32/* Drivers for PCI hardware need this */ 33#include "xf86PciInfo.h" 34 35/* Drivers that need to access the PCI config space directly need this */ 36#include "xf86Pci.h" 37 38/* All drivers using the vgahw module need this */ 39/* This driver needs to be modified to not use vgaHW for multihead operation */ 40#include "vgaHW.h" 41 42#include "xf86RAC.h" 43#include "xf86Resources.h" 44 45/* All drivers initialising the SW cursor need this */ 46#include "mipointer.h" 47 48/* need this for inputInfo */ 49#include "inputstr.h" 50 51/* All drivers implementing backing store need this */ 52#include "mibstore.h" 53 54#include "micmap.h" 55 56/* Needed by the Shadow Framebuffer */ 57#include "shadowfb.h" 58 59#include "xf86int10.h" 60 61#include "fb.h" 62 63#include "inputstr.h" 64 65#include "xf86DDC.h" 66 67#undef LG_DEBUG 68 69#include "cir.h" 70#define _LG_PRIVATE_ 71#include "lg.h" 72 73#include "xf86xv.h" 74#include <X11/extensions/Xv.h> 75 76/* 77 * Forward definitions for the functions that make up the driver. 78 */ 79 80/* Mandatory functions */ 81Bool LgPreInit(ScrnInfoPtr pScrn, int flags); 82Bool LgScreenInit(int Index, ScreenPtr pScreen, int argc, char **argv); 83Bool LgEnterVT(int scrnIndex, int flags); 84void LgLeaveVT(int scrnIndex, int flags); 85static Bool LgCloseScreen(int scrnIndex, ScreenPtr pScreen); 86static Bool LgSaveScreen(ScreenPtr pScreen, Bool mode); 87 88/* Required if the driver supports mode switching */ 89Bool LgSwitchMode(int scrnIndex, DisplayModePtr mode, int flags); 90/* Required if the driver supports moving the viewport */ 91void LgAdjustFrame(int scrnIndex, int x, int y, int flags); 92 93/* Optional functions */ 94void LgFreeScreen(int scrnIndex, int flags); 95ModeStatus LgValidMode(int scrnIndex, DisplayModePtr mode, 96 Bool verbose, int flags); 97 98/* Internally used functions */ 99static void LgRestoreLgRegs(ScrnInfoPtr pScrn, LgRegPtr lgReg); 100static int LgFindLineData(int displayWidth, int bpp); 101static CARD16 LgSetClock(CirPtr pCir, vgaHWPtr hwp, int freq); 102static void lg_vgaHWSetMmioFunc(vgaHWPtr hwp, CARD8 *base); 103 104static void LgDisplayPowerManagementSet(ScrnInfoPtr pScrn, 105 int PowerManagementMode, int flags); 106 107/* 108 * This is intentionally screen-independent. It indicates the binding 109 * choice made in the first PreInit. 110 */ 111static int pix24bpp = 0; 112 113/* 114 * This contains the functions needed by the server after loading the 115 * driver module. It must be supplied, and gets added the driver list by 116 * the Module Setup funtion in the dynamic case. In the static case a 117 * reference to this is compiled in, and this requires that the name of 118 * this DriverRec be an upper-case version of the driver name. 119 */ 120 121typedef enum { 122 OPTION_HW_CURSOR, 123 OPTION_PCI_RETRY, 124 OPTION_ROTATE, 125 OPTION_SHADOW_FB, 126 OPTION_NOACCEL 127} LgOpts; 128 129static const OptionInfoRec LgOptions[] = { 130 { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, 131 { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 132 { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, 133 { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, 134 /* fifo_conservative/aggressive; fast/med/slow_dram; ... */ 135 { -1, NULL, OPTV_NONE, {0}, FALSE } 136}; 137 138 139/* 1/4bpp 8bpp 15/16bpp 24bpp 32bpp */ 140static int gd5462_MaxClocks[] = { 170000, 170000, 135100, 135100, 85500 }; 141static int gd5464_MaxClocks[] = { 170000, 250000, 170000, 170000, 135100 }; 142static int gd5465_MaxClocks[] = { 170000, 250000, 170000, 170000, 135100 }; 143 144LgLineDataRec LgLineData[] = { 145 { 5, 640, 0}, /* We're rather use skinny tiles, so put all of */ 146 { 8, 1024, 0}, /* them at the head of the table */ 147 {10, 1280, 0}, 148 {13, 1664, 0}, 149 {16, 2048, 0}, 150 {20, 2560, 0}, 151 {10, 2560, 1}, 152 {26, 3328, 0}, 153 { 5, 1280, 1}, 154 { 8, 2048, 1}, 155 {13, 3328, 1}, 156 {16, 4096, 1}, 157 {20, 5120, 1}, 158 {26, 6656, 1}, 159 {-1, -1, -1} /* Sentinal to indicate end of table */ 160}; 161 162static int LgLinePitches[4][11] = { 163 /* 8 */ { 640, 1024, 1280, 1664, 2048, 2560, 3328, 4096, 5120, 6656, 0 }, 164 /* 16 */ { 320, 512, 640, 832, 1024, 1280, 1664, 2048, 2560, 3328, 0 }, 165 /* 24 */ { 213, 341, 426, 554, 682, 853, 1109, 1365, 1706, 2218, 0 }, 166 /* 32 */ { 160, 256, 320, 416, 512, 640, 832, 1024, 1280, 1664, 0 } 167}; 168 169#ifdef XFree86LOADER 170 171#define LG_MAJOR_VERSION 1 172#define LG_MINOR_VERSION 0 173#define LG_PATCHLEVEL 0 174 175static MODULESETUPPROTO(lgSetup); 176 177static XF86ModuleVersionInfo lgVersRec = 178{ 179 "cirrus_laguna", 180 MODULEVENDORSTRING, 181 MODINFOSTRING1, 182 MODINFOSTRING2, 183 XORG_VERSION_CURRENT, 184 LG_MAJOR_VERSION, LG_MINOR_VERSION, LG_PATCHLEVEL, 185 ABI_CLASS_VIDEODRV, /* This is a video driver */ 186 ABI_VIDEODRV_VERSION, 187 MOD_CLASS_NONE, 188 {0,0,0,0} 189}; 190 191/* 192 * This is the module init data. 193 * Its name has to be the driver name followed by ModuleData. 194 */ 195_X_EXPORT XF86ModuleData cirrus_lagunaModuleData = { 196 &lgVersRec, 197 lgSetup, 198 NULL 199}; 200 201static pointer 202lgSetup(pointer module, pointer opts, int *errmaj, int *errmin) 203{ 204 static Bool setupDone = FALSE; 205 206 if (!setupDone) { 207 setupDone = TRUE; 208 } 209 return (pointer)1; 210} 211 212#endif /* XFree86LOADER */ 213 214_X_EXPORT const OptionInfoRec * 215LgAvailableOptions(int chipid) 216{ 217 return LgOptions; 218} 219 220_X_EXPORT ScrnInfoPtr 221LgProbe(int entity) 222{ 223 ScrnInfoPtr pScrn = NULL; 224 if ((pScrn = xf86ConfigPciEntity(pScrn, 0, entity, CIRPciChipsets, 225 NULL, NULL, NULL, NULL, NULL))) { 226 pScrn->PreInit = LgPreInit; 227 pScrn->ScreenInit = LgScreenInit; 228 pScrn->SwitchMode = LgSwitchMode; 229 pScrn->AdjustFrame = LgAdjustFrame; 230 pScrn->EnterVT = LgEnterVT; 231 pScrn->LeaveVT = LgLeaveVT; 232 pScrn->FreeScreen = LgFreeScreen; 233 pScrn->ValidMode = LgValidMode; 234 } 235 return pScrn; 236} 237 238 239static Bool 240LgGetRec(ScrnInfoPtr pScrn) 241{ 242 CirPtr pCir; 243 244 if (pScrn->driverPrivate != NULL) 245 return TRUE; 246 247 pScrn->driverPrivate = xnfcalloc(sizeof(CirRec), 1); 248 ((CirPtr)pScrn->driverPrivate)->chip.lg = xnfcalloc(sizeof(LgRec),1); 249 250 /* Initialize it */ 251 pCir = CIRPTR(pScrn); 252 pCir->chip.lg->oldBitmask = 0x00000000; 253 254 return TRUE; 255} 256 257static void 258LgFreeRec(ScrnInfoPtr pScrn) 259{ 260 if (pScrn->driverPrivate == NULL) 261 return; 262 xfree(pScrn->driverPrivate); 263 pScrn->driverPrivate = NULL; 264} 265 266 267 268/* 269 * LgCountRAM -- 270 * 271 * Counts amount of installed RAM 272 */ 273 274/* XXX We need to get rid of this PIO (MArk) */ 275static int 276LgCountRam(ScrnInfoPtr pScrn) 277{ 278 vgaHWPtr hwp = VGAHWPTR(pScrn); 279 CARD8 SR14; 280 281 vgaHWProtect(pScrn, TRUE); 282 283 /* The ROM BIOS scratchpad registers contain, 284 among other things, the amount of installed 285 RDRAM on the laguna chip. */ 286 SR14 = hwp->readSeq(hwp, 0x14); 287 288 ErrorF("Scratch Pads: 0:%02x 1:%02x 2:%02x 3:%02x\n", 289 hwp->readSeq(hwp, 9), hwp->readSeq(hwp, 10), 290 SR14, hwp->readSeq(hwp, 0x15)); 291 292 vgaHWProtect(pScrn, FALSE); 293 294 return 1024 * ((SR14&0x7) + 1); 295 296 /* !!! This function seems to be incorrect... */ 297} 298 299static xf86MonPtr 300LgDoDDC(ScrnInfoPtr pScrn) 301{ 302 CirPtr pCir = CIRPTR(pScrn); 303 xf86MonPtr MonInfo = NULL; 304 305 /* Map the CIR memory and MMIO areas */ 306 if (!CirMapMem(pCir, pScrn->scrnIndex)) 307 return FALSE; 308 309#if LGuseI2C 310 if (!LgI2CInit(pScrn)) { 311 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I2C initialization failed\n"); 312 313 goto unmap_out; 314 } 315 316 /* Read and output monitor info using DDC2 over I2C bus */ 317 MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, pCir->I2CPtr1); 318 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I2C Monitor info: %p\n", 319 (void *)MonInfo); 320 xf86PrintEDID(MonInfo); 321 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of I2C Monitor info\n\n"); 322#endif /* LGuseI2C */ 323 324 xf86SetDDCproperties(pScrn, MonInfo); 325 326unmap_out: 327 CirUnmapMem(pCir, pScrn->scrnIndex); 328 329 return MonInfo; 330} 331 332/* Mandatory */ 333Bool 334LgPreInit(ScrnInfoPtr pScrn, int flags) 335{ 336 CirPtr pCir; 337 vgaHWPtr hwp; 338 MessageType from; 339 int i; 340 ClockRangePtr clockRanges; 341 int fbPCIReg, ioPCIReg; 342 char *s; 343 344 if (flags & PROBE_DETECT) { 345 cirProbeDDC( pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index ); 346 return TRUE; 347 } 348 349#ifdef LG_DEBUG 350 ErrorF("LgPreInit\n"); 351#endif 352 353 /* Check the number of entities, and fail if it isn't one. */ 354 if (pScrn->numEntities != 1) 355 return FALSE; 356 357 /* The vgahw module should be loaded here when needed */ 358 if (!xf86LoadSubModule(pScrn, "vgahw")) 359 return FALSE; 360 361 /* 362 * Allocate a vgaHWRec 363 */ 364 if (!vgaHWGetHWRec(pScrn)) 365 return FALSE; 366 367 hwp = VGAHWPTR(pScrn); 368 vgaHWGetIOBase(hwp); 369 370 /* Allocate the LgRec driverPrivate */ 371 if (!LgGetRec(pScrn)) 372 return FALSE; 373 374 pCir = CIRPTR(pScrn); 375 pCir->pScrn = pScrn; 376 pCir->PIOReg = hwp->PIOOffset + 0x3CE; 377 378 /* Get the entity, and make sure it is PCI. */ 379 pCir->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 380 if (pCir->pEnt->location.type != BUS_PCI) 381 return FALSE; 382 pCir->Chipset = pCir->pEnt->chipset; 383 384 /* Find the PCI info for this screen */ 385 pCir->PciInfo = xf86GetPciInfoForEntity(pCir->pEnt->index); 386 pCir->PciTag = pciTag(PCI_DEV_BUS(pCir->PciInfo), 387 PCI_DEV_DEV(pCir->PciInfo), 388 PCI_DEV_FUNC(pCir->PciInfo)); 389 390 if (xf86LoadSubModule(pScrn, "int10")) { 391 xf86Int10InfoPtr int10InfoPtr; 392 393 int10InfoPtr = xf86InitInt10(pCir->pEnt->index); 394 395 if (int10InfoPtr) 396 xf86FreeInt10(int10InfoPtr); 397 } 398 399 /* Set pScrn->monitor */ 400 pScrn->monitor = pScrn->confScreen->monitor; 401 402 /* 403 * The first thing we should figure out is the depth, bpp, etc. 404 * We support both 24bpp and 32bpp layouts, so indicate that. 405 */ 406 if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb | 407 SupportConvert32to24 | PreferConvert32to24)) { 408 return FALSE; 409 } 410 /* Check that the returned depth is one we support */ 411 switch (pScrn->depth) { 412 case 8: 413 case 15: 414 case 16: 415 case 24: 416 case 32: 417 /* OK */ 418 break; 419 default: 420 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 421 "Given depth (%d) is not supported by this driver\n", pScrn->depth); 422 return FALSE; 423 } 424 xf86PrintDepthBpp(pScrn); 425 426 /* Get the depth24 pixmap format */ 427 if (pScrn->depth == 24 && pix24bpp == 0) 428 pix24bpp = xf86GetBppFromDepth(pScrn, 24); 429 430 /* 431 * This must happen after pScrn->display has been set because 432 * xf86SetWeight references it. 433 */ 434 if (pScrn->depth > 8) { 435 /* The defaults are OK for us */ 436 rgb zeros = {0, 0, 0}; 437 438 /* !!! I think we can force 5-6-5 weight for 16bpp here for 439 the 5462. */ 440 441 if (!xf86SetWeight(pScrn, zeros, zeros)) { 442 return FALSE; 443 } else { 444 /* XXX check that weight returned is supported */ 445 ; 446 } 447 } 448 449 if (!xf86SetDefaultVisual(pScrn, -1)) 450 return FALSE; 451 452 453 /* Collect all of the relevant option flags (fill in pScrn->options) */ 454 xf86CollectOptions(pScrn, NULL); 455 456 /* Process the options */ 457 if (!(pCir->Options = xalloc(sizeof(LgOptions)))) 458 return FALSE; 459 memcpy(pCir->Options, LgOptions, sizeof(LgOptions)); 460 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pCir->Options); 461 462 pScrn->rgbBits = 6; 463 from = X_DEFAULT; 464 pCir->HWCursor = FALSE; 465 if (xf86GetOptValBool(pCir->Options, OPTION_HW_CURSOR, &pCir->HWCursor)) 466 from = X_CONFIG; 467 468 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 469 pCir->HWCursor ? "HW" : "SW"); 470 if (xf86ReturnOptValBool(pCir->Options, OPTION_NOACCEL, FALSE)) { 471 pCir->NoAccel = TRUE; 472 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); 473 } 474 if (pScrn->bitsPerPixel < 8) { 475 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 476 "Cannot use in less than 8 bpp\n"); 477 return FALSE; 478 } 479 /* 480 * Set the ChipRev, allowing config file entries to 481 * override. 482 */ 483 if (pCir->pEnt->device->chipRev >= 0) { 484 pCir->ChipRev = pCir->pEnt->device->chipRev; 485 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 486 pCir->ChipRev); 487 } else { 488 pCir->ChipRev = PCI_DEV_REVISION(pCir->PciInfo); 489 } 490 491 /* Cirrus swapped the FB and IO registers in the 5465 (by design). */ 492 if (PCI_CHIP_GD5465 == pCir->Chipset) { 493 fbPCIReg = 0; 494 ioPCIReg = 1; 495 } else { 496 fbPCIReg = 1; 497 ioPCIReg = 0; 498 } 499 500 /* Find the frame buffer base address */ 501 if (pCir->pEnt->device->MemBase != 0) { 502 /* Require that the config file value matches one of the PCI values. */ 503 if (!xf86CheckPciMemBase(pCir->PciInfo, pCir->pEnt->device->MemBase)) { 504 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 505 "MemBase 0x%08lX doesn't match any PCI base register.\n", 506 pCir->pEnt->device->MemBase); 507 return FALSE; 508 } 509 pCir->FbAddress = pCir->pEnt->device->MemBase; 510 from = X_CONFIG; 511 } else { 512 if (PCI_REGION_BASE(pCir->PciInfo, fbPCIReg, REGION_MEM) != 0) { 513 pCir->FbAddress = PCI_REGION_BASE(pCir->PciInfo, fbPCIReg, REGION_MEM) & 0xff000000; 514 from = X_PROBED; 515 } else { 516 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 517 "No valid FB address in PCI config space\n"); 518 LgFreeRec(pScrn); 519 return FALSE; 520 } 521 } 522 xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", 523 (unsigned long)pCir->FbAddress); 524 525 /* Find the MMIO base address */ 526 if (pCir->pEnt->device->IOBase != 0) { 527 /* Require that the config file value matches one of the PCI values. */ 528 if (!xf86CheckPciMemBase(pCir->PciInfo, pCir->pEnt->device->IOBase)) { 529 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 530 "IOBase 0x%08lX doesn't match any PCI base register.\n", 531 pCir->pEnt->device->IOBase); 532 return FALSE; 533 } 534 pCir->IOAddress = pCir->pEnt->device->IOBase; 535 from = X_CONFIG; 536 } else { 537 if (PCI_REGION_BASE(pCir->PciInfo, ioPCIReg, REGION_MEM) != 0) { 538 pCir->IOAddress = PCI_REGION_BASE(pCir->PciInfo, ioPCIReg, REGION_MEM) & 0xfffff000; 539 from = X_PROBED; 540 } else { 541 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 542 "No valid MMIO address in PCI config space\n"); 543 } 544 } 545 xf86DrvMsg(pScrn->scrnIndex, from, "MMIO registers at 0x%lX\n", 546 (unsigned long)pCir->IOAddress); 547 548 /* 549 * If the user has specified the amount of memory in the XF86Config 550 * file, we respect that setting. 551 */ 552 if (pCir->pEnt->device->videoRam != 0) { 553 pScrn->videoRam = pCir->pEnt->device->videoRam; 554 from = X_CONFIG; 555 } else { 556 pScrn->videoRam = LgCountRam(pScrn); 557 from = X_PROBED; 558 } 559 if (2048 == pScrn->videoRam) { 560 /* Two-way interleaving */ 561 pCir->chip.lg->memInterleave = 0x40; 562 } else if (4096 == pScrn->videoRam || 8192 == pScrn->videoRam) { 563 /* Four-way interleaving */ 564 pCir->chip.lg->memInterleave = 0x80; 565 } else { 566 /* One-way interleaving */ 567 pCir->chip.lg->memInterleave = 0x00; 568 } 569 570 xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n", 571 pScrn->videoRam); 572 573 pCir->FbMapSize = pScrn->videoRam * 1024; 574 pCir->IoMapSize = 0x4000; /* 16K for moment, will increase */ 575 576 pScrn->racIoFlags = RAC_COLORMAP 577#ifndef EXPERIMENTAL 578 | RAC_VIEWPORT 579#endif 580; 581 xf86SetOperatingState(resVgaMem, pCir->pEnt->index, ResUnusedOpr); 582 583 /* Register the PCI-assigned resources. */ 584 if (xf86RegisterResources(pCir->pEnt->index, NULL, ResExclusive)) { 585 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 586 "xf86RegisterResources() found resource conflicts\n"); 587 return FALSE; 588 } 589 590 if (!xf86LoadSubModule(pScrn, "ddc")) { 591 LgFreeRec(pScrn); 592 return FALSE; 593 } 594 595#if LGuseI2C 596 if (!xf86LoadSubModule(pScrn, "i2c")) { 597 LgFreeRec(pScrn); 598 return FALSE; 599 } 600#endif 601 602 /* Read and print the monitor DDC information */ 603 pScrn->monitor->DDC = LgDoDDC(pScrn); 604 605 /* The gamma fields must be initialised when using the new cmap code */ 606 if (pScrn->depth > 1) { 607 Gamma zeros = {0.0, 0.0, 0.0}; 608 609 if (!xf86SetGamma(pScrn, zeros)) 610 return FALSE; 611 } 612 if (xf86GetOptValBool(pCir->Options, 613 OPTION_SHADOW_FB,&pCir->shadowFB)) 614 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowFB %s.\n", 615 pCir->shadowFB ? "enabled" : "disabled"); 616 617 if ((s = xf86GetOptValString(pCir->Options, OPTION_ROTATE))) { 618 if(!xf86NameCmp(s, "CW")) { 619 /* accel is disabled below for shadowFB */ 620 pCir->shadowFB = TRUE; 621 pCir->rotate = 1; 622 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 623 "Rotating screen clockwise - acceleration disabled\n"); 624 } else if(!xf86NameCmp(s, "CCW")) { 625 pCir->shadowFB = TRUE; 626 pCir->rotate = -1; 627 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen" 628 "counter clockwise - acceleration disabled\n"); 629 } else { 630 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" 631 "value for Option \"Rotate\"\n", s); 632 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 633 "Valid options are \"CW\" or \"CCW\"\n"); 634 } 635 } 636 637 if (pCir->shadowFB && !pCir->NoAccel) { 638 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 639 "HW acceleration not supported with \"shadowFB\".\n"); 640 pCir->NoAccel = TRUE; 641 } 642 643 if (pCir->rotate && pCir->HWCursor) { 644 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 645 "HW cursor not supported with \"rotate\".\n"); 646 pCir->HWCursor = FALSE; 647 } 648 649 /* We use a programmable clock */ 650 pScrn->progClock = TRUE; 651 652 /* XXX Set HW cursor use */ 653 654 /* Set the min pixel clock */ 655 pCir->MinClock = 12000; /* XXX Guess, need to check this */ 656 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n", 657 pCir->MinClock / 1000); 658 /* 659 * If the user has specified ramdac speed in the XF86Config 660 * file, we respect that setting. 661 */ 662 if (pCir->pEnt->device->dacSpeeds[0]) { 663 ErrorF("Do not specify a Clocks line for Cirrus chips\n"); 664 return FALSE; 665 } else { 666 int speed; 667 int *p; 668 switch (pCir->Chipset) { 669 case PCI_CHIP_GD5462: 670 p = gd5462_MaxClocks; 671 break; 672 case PCI_CHIP_GD5464: 673 case PCI_CHIP_GD5464BD: 674 p = gd5464_MaxClocks; 675 break; 676 case PCI_CHIP_GD5465: 677 p = gd5465_MaxClocks; 678 break; 679 default: 680 ErrorF("???\n"); 681 return FALSE; 682 } 683 switch (pScrn->bitsPerPixel) { 684 case 8: 685 speed = p[1]; 686 break; 687 case 15: 688 case 16: 689 speed = p[2]; 690 break; 691 case 24: 692 speed = p[3]; 693 break; 694 case 32: 695 speed = p[4]; 696 break; 697 default: 698 /* Should not get here */ 699 speed = 0; 700 break; 701 } 702 pCir->MaxClock = speed; 703 from = X_PROBED; 704 } 705 xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n", 706 pCir->MaxClock / 1000); 707 708 /* 709 * Setup the ClockRanges, which describe what clock ranges are available, 710 * and what sort of modes they can be used for. 711 */ 712 clockRanges = xnfcalloc(sizeof(ClockRange), 1); 713 clockRanges->next = NULL; 714 clockRanges->minClock = pCir->MinClock; 715 clockRanges->maxClock = pCir->MaxClock; 716 clockRanges->clockIndex = -1; /* programmable */ 717 clockRanges->interlaceAllowed = FALSE; /* XXX check this */ 718 clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ 719 clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ 720 clockRanges->doubleScanAllowed = FALSE; /* XXX check this */ 721 clockRanges->ClockMulFactor = 1; 722 clockRanges->ClockDivFactor = 1; 723 clockRanges->PrivFlags = 0; 724 725 /* Depending upon what sized tiles used, either 128 or 256. */ 726 /* Aw, heck. Just say 128. */ 727 pCir->Rounding = 128 >> pCir->BppShift; 728 729 /* 730 * xf86ValidateModes will check that the mode HTotal and VTotal values 731 * don't exceed the chipset's limit if pScrn->maxHValue and 732 * pScrn->maxVValue are set. Since our CIRValidMode() already takes 733 * care of this, we don't worry about setting them here. 734 */ 735 736 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, 737 clockRanges, 738 LgLinePitches[pScrn->bitsPerPixel / 8 - 1], 739 0, 0, 128 * 8, 740 0, 0, /* Any virtual height is allowed. */ 741 pScrn->display->virtualX, 742 pScrn->display->virtualY, 743 pCir->FbMapSize, 744 LOOKUP_BEST_REFRESH); 745 746 pCir->chip.lg->lineDataIndex = LgFindLineData(pScrn->displayWidth, 747 pScrn->bitsPerPixel); 748 749 if (i == -1) { 750 LgFreeRec(pScrn); 751 return FALSE; 752 } 753 754 /* Prune the modes marked as invalid */ 755 xf86PruneDriverModes(pScrn); 756 757 if (i == 0 || pScrn->modes == NULL) { 758 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 759 LgFreeRec(pScrn); 760 return FALSE; 761 } 762 763 /* 764 * Set the CRTC parameters for all of the modes based on the type 765 * of mode, and the chipset's interlace requirements. 766 * 767 * Calling this is required if the mode->Crtc* values are used by the 768 * driver and if the driver doesn't provide code to set them. They 769 * are not pre-initialised at all. 770 */ 771 xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 772 773 /* Set the current mode to the first in the list */ 774 pScrn->currentMode = pScrn->modes; 775 776 /* Print the list of modes being used */ 777 xf86PrintModes(pScrn); 778 779 /* Set display resolution */ 780 xf86SetDpi(pScrn, 0, 0); 781 782 /* Load bpp-specific modules */ 783 switch (pScrn->bitsPerPixel) { 784 case 8: 785 case 16: 786 case 24: 787 case 32: 788 if (xf86LoadSubModule(pScrn, "fb") == NULL) { 789 LgFreeRec(pScrn); 790 return FALSE; 791 } 792 break; 793 } 794 795 /* Load XAA if needed */ 796 if (!pCir->NoAccel) { 797 if (!xf86LoadSubModule(pScrn, "xaa")) { 798 LgFreeRec(pScrn); 799 return FALSE; 800 } 801 } 802 803 /* Load ramdac if needed */ 804 if (pCir->HWCursor) { 805 if (!xf86LoadSubModule(pScrn, "ramdac")) { 806 LgFreeRec(pScrn); 807 return FALSE; 808 } 809 } 810 811 if (pCir->shadowFB) { 812 if (!xf86LoadSubModule(pScrn, "shadowfb")) { 813 LgFreeRec(pScrn); 814 return FALSE; 815 } 816 } 817 818 return TRUE; 819} 820 821/* 822 * This function saves the video state. 823 */ 824static void 825LgSave(ScrnInfoPtr pScrn) 826{ 827 CirPtr pCir = CIRPTR(pScrn); 828 vgaHWPtr hwp = VGAHWPTR(pScrn); 829 830#ifdef LG_DEBUG 831 ErrorF("LgSave\n"); 832#endif 833 834 vgaHWSave(pScrn, &VGAHWPTR(pScrn)->SavedReg, VGA_SR_ALL); 835 836 pCir->chip.lg->ModeReg.ExtVga[CR1A] = pCir->chip.lg->SavedReg.ExtVga[CR1A] = hwp->readCrtc(hwp, 0x1A); 837 pCir->chip.lg->ModeReg.ExtVga[CR1B] = pCir->chip.lg->SavedReg.ExtVga[CR1B] = hwp->readCrtc(hwp, 0x1B); 838 pCir->chip.lg->ModeReg.ExtVga[CR1D] = pCir->chip.lg->SavedReg.ExtVga[CR1D] = hwp->readCrtc(hwp, 0x1D); 839 pCir->chip.lg->ModeReg.ExtVga[CR1E] = pCir->chip.lg->SavedReg.ExtVga[CR1E] = hwp->readCrtc(hwp, 0x1E); 840 pCir->chip.lg->ModeReg.ExtVga[SR07] = pCir->chip.lg->SavedReg.ExtVga[SR07] = hwp->readSeq(hwp, 0x07); 841 pCir->chip.lg->ModeReg.ExtVga[SR0E] = pCir->chip.lg->SavedReg.ExtVga[SR0E] = hwp->readSeq(hwp, 0x0E); 842 pCir->chip.lg->ModeReg.ExtVga[SR12] = pCir->chip.lg->SavedReg.ExtVga[SR12] = hwp->readSeq(hwp, 0x12); 843 pCir->chip.lg->ModeReg.ExtVga[SR13] = pCir->chip.lg->SavedReg.ExtVga[SR13] = hwp->readSeq(hwp, 0x13); 844 pCir->chip.lg->ModeReg.ExtVga[SR1E] = pCir->chip.lg->SavedReg.ExtVga[SR1E] = hwp->readSeq(hwp, 0x1E); 845 846 pCir->chip.lg->ModeReg.FORMAT = pCir->chip.lg->SavedReg.FORMAT = memrw(0xC0); 847 848 pCir->chip.lg->ModeReg.VSC = pCir->chip.lg->SavedReg.VSC = memrl(0x3FC); 849 850 pCir->chip.lg->ModeReg.DTTC = pCir->chip.lg->SavedReg.DTTC = memrw(0xEA); 851 852 if (pCir->Chipset == PCI_CHIP_GD5465) { 853 pCir->chip.lg->ModeReg.TileCtrl = pCir->chip.lg->SavedReg.TileCtrl = memrw(0x2C4); 854 } 855 856 pCir->chip.lg->ModeReg.TILE = pCir->chip.lg->SavedReg.TILE = memrb(0x407); 857 858 if (pCir->Chipset == PCI_CHIP_GD5465) 859 pCir->chip.lg->ModeReg.BCLK = pCir->chip.lg->SavedReg.BCLK = memrb(0x2C0); 860 else 861 pCir->chip.lg->ModeReg.BCLK = pCir->chip.lg->SavedReg.BCLK = memrb(0x8C); 862 863 pCir->chip.lg->ModeReg.CONTROL = pCir->chip.lg->SavedReg.CONTROL = memrw(0x402); 864} 865 866/* 867 * Initialise a new mode. This is currently still using the old 868 * "initialise struct, restore/write struct to HW" model. That could 869 * be changed. 870 */ 871 872static Bool 873LgModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 874{ 875 vgaHWPtr hwp; 876 CirPtr pCir; 877 int width; 878 Bool VDiv2 = FALSE; 879 CARD16 clockData; 880 LgLineDataPtr lineData; 881 882#ifdef LG_DEBUG 883 ErrorF("LgModeInit %d bpp, %d %d %d %d %d %d %d %d %d\n", 884 pScrn->bitsPerPixel, 885 mode->Clock, 886 mode->HDisplay, 887 mode->HSyncStart, 888 mode->HSyncEnd, 889 mode->HTotal, 890 mode->VDisplay, 891 mode->VSyncStart, 892 mode->VSyncEnd, 893 mode->VTotal); 894 895 ErrorF("LgModeInit: depth %d bits\n", pScrn->depth); 896#endif 897 898 pCir = CIRPTR(pScrn); 899 hwp = VGAHWPTR(pScrn); 900 vgaHWUnlock(hwp); 901 902 if (mode->VTotal >= 1024 && !(mode->Flags & V_INTERLACE)) { 903 /* For non-interlaced vertical timing >= 1024, the vertical timings */ 904 /* are divided by 2 and VGA CRTC 0x17 bit 2 is set. */ 905 if (!mode->CrtcVAdjusted) { 906 mode->CrtcVDisplay >>= 1; 907 mode->CrtcVSyncStart >>= 1; 908 mode->CrtcVSyncEnd >>= 1; 909 mode->CrtcVTotal >>= 1; 910 mode->CrtcVAdjusted = TRUE; 911 } 912 VDiv2 = TRUE; 913 } 914 915 /* Initialise the ModeReg values */ 916 if (!vgaHWInit(pScrn, mode)) 917 return FALSE; 918 pScrn->vtSema = TRUE; 919 920 if (VDiv2) 921 hwp->ModeReg.CRTC[0x17] |= 0x04; 922 923#ifdef LG_DEBUG 924 ErrorF("SynthClock = %d\n", mode->SynthClock); 925#endif 926 hwp->IOBase = 0x3D0; 927 hwp->ModeReg.MiscOutReg |= 0x01; 928#if 0 /* Mono address */ 929 hwp->IOBase = 0x3B0; 930 hwp->ModeReg.MiscOutReg &= ~0x01; 931#endif 932 933 934 /* ??? Should these be both ...End or ...Start, not one of each? */ 935 pCir->chip.lg->ModeReg.ExtVga[CR1A] = (((mode->CrtcVSyncStart + 1) & 0x300 ) >> 2) 936 | (((mode->CrtcHSyncEnd >> 3) & 0xC0) >> 2); 937 938 width = pScrn->displayWidth * pScrn->bitsPerPixel / 8; 939 if (pScrn->bitsPerPixel == 1) 940 width <<= 2; 941 hwp->ModeReg.CRTC[0x13] = (width + 7) >> 3; 942 /* Offset extension (see CR13) */ 943 pCir->chip.lg->ModeReg.ExtVga[CR1B] &= 0xEF; 944 pCir->chip.lg->ModeReg.ExtVga[CR1B] |= (((width + 7) >> 3) & 0x100)?0x10:0x00; 945 pCir->chip.lg->ModeReg.ExtVga[CR1B] |= 0x22; 946 pCir->chip.lg->ModeReg.ExtVga[CR1D] = (((width + 7) >> 3) & 0x200)?0x01:0x00; 947 948 /* Set the 28th bit to enable extended modes. */ 949 pCir->chip.lg->ModeReg.VSC = 0x10000000; 950 951 /* Overflow register (sure are a lot of overflow bits around...) */ 952 pCir->chip.lg->ModeReg.ExtVga[CR1E] = 0x00; 953 pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcHTotal>>3 & 0x0100)?1:0)<<7; 954 pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcHDisplay>>3 & 0x0100)?1:0)<<6; 955 pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcHSyncStart>>3 & 0x0100)?1:0)<<5; 956 pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcHSyncStart>>3 & 0x0100)?1:0)<<4; 957 pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcVTotal & 0x0400)?1:0)<<3; 958 pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcVDisplay & 0x0400)?1:0)<<2; 959 pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcVSyncStart & 0x0400)?1:0)<<1; 960 pCir->chip.lg->ModeReg.ExtVga[CR1E] |= ((mode->CrtcVSyncStart & 0x0400)?1:0)<<0; 961 962 lineData = &LgLineData[pCir->chip.lg->lineDataIndex]; 963 964 pCir->chip.lg->ModeReg.TILE = lineData->tilesPerLine & 0x3F; 965 966 if (8 == pScrn->bitsPerPixel) { 967 pCir->chip.lg->ModeReg.FORMAT = 0x0000; 968 969 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.TILE << 8) | 0x0080 970 | (lineData->width << 6); 971 pCir->chip.lg->ModeReg.CONTROL = 0x0000 | (lineData->width << 11); 972 973 974 /* There is an optimal FIFO threshold value (lower 5 bits of DTTC) 975 for every resolution and color depth combination. We'll hit 976 the highlights here, and get close for anything that's not 977 covered. */ 978 if (mode->CrtcHDisplay <= 640) { 979 /* BAD numbers: 0x1E */ 980 /* GOOD numbers: 0x14 */ 981 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0014); 982 } else if (mode->CrtcHDisplay <= 800) { 983 /* BAD numbers: 0x16 */ 984 /* GOOD numbers: 0x13 0x14 */ 985 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0014); 986 } else if (mode->CrtcHDisplay <= 1024) { 987 /* BAD numbers: */ 988 /* GOOD numbers: 0x15 */ 989 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0015); 990 } else if (mode->CrtcHDisplay <= 1280) { 991 /* BAD numbers: */ 992 /* GOOD numbers: 0x16 */ 993 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0016); 994 } else { 995 /* BAD numbers: */ 996 /* GOOD numbers: */ 997 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0017); 998 } 999 } else if (16 == pScrn->bitsPerPixel) { 1000 /* !!! Assume 5-6-5 RGB mode (for now...) */ 1001 pCir->chip.lg->ModeReg.FORMAT = 0x1400; 1002 1003 if (pScrn->depth == 15) 1004 pCir->chip.lg->ModeReg.FORMAT = 0x1600; 1005 1006 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.TILE << 8) | 0x0080 1007 | (lineData->width << 6); 1008 pCir->chip.lg->ModeReg.CONTROL = 0x2000 | (lineData->width << 11); 1009 1010 if (mode->CrtcHDisplay <= 640) { 1011 /* BAD numbers: 0x12 */ 1012 /* GOOD numbers: 0x10 */ 1013 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0010); 1014 } else if (mode->CrtcHDisplay <= 800) { 1015 /* BAD numbers: 0x13 */ 1016 /* GOOD numbers: 0x11 */ 1017 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0011); 1018 } else if (mode->CrtcHDisplay <= 1024) { 1019 /* BAD numbers: 0x14 */ 1020 /* GOOD numbers: 0x12 */ 1021 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0012); 1022 } else if (mode->CrtcHDisplay <= 1280) { 1023 /* BAD numbers: 0x08 0x10 */ 1024 /* Borderline numbers: 0x12 */ 1025 /* GOOD numbers: 0x15 */ 1026 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0015); 1027 } else { 1028 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0017); 1029 } 1030 } else if (24 == pScrn->bitsPerPixel) { 1031 pCir->chip.lg->ModeReg.FORMAT = 0x2400; 1032 1033 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.TILE << 8) | 0x0080 1034 | (lineData->width << 6); 1035 pCir->chip.lg->ModeReg.CONTROL = 0x4000 | (lineData->width << 11); 1036 1037 if (mode->CrtcHDisplay <= 640) { 1038 /* BAD numbers: */ 1039 /* GOOD numbers: 0x10 */ 1040 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0010); 1041 } else if (mode->CrtcHDisplay <= 800) { 1042 /* BAD numbers: */ 1043 /* GOOD numbers: 0x11 */ 1044 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0011); 1045 } else if (mode->CrtcHDisplay <= 1024) { 1046 /* BAD numbers: 0x12 0x13 */ 1047 /* Borderline numbers: 0x15 */ 1048 /* GOOD numbers: 0x17 */ 1049 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0017); 1050 } else if (mode->CrtcHDisplay <= 1280) { 1051 /* BAD numbers: */ 1052 /* GOOD numbers: 0x1E */ 1053 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x001E); 1054 } else { 1055 /* BAD numbers: */ 1056 /* GOOD numbers: */ 1057 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0020); 1058 } 1059 } else if (32 == pScrn->bitsPerPixel) { 1060 pCir->chip.lg->ModeReg.FORMAT = 0x3400; 1061 1062 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.TILE << 8) | 0x0080 1063 | (lineData->width << 6); 1064 pCir->chip.lg->ModeReg.CONTROL = 0x6000 | (lineData->width << 11); 1065 1066 if (mode->CrtcHDisplay <= 640) { 1067 /* GOOD numbers: 0x0E */ 1068 /* BAD numbers: */ 1069 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x000E); 1070 } else if (mode->CrtcHDisplay <= 800) { 1071 /* GOOD numbers: 0x17 */ 1072 /* BAD numbers: */ 1073 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0017); 1074 } else if (mode->CrtcHDisplay <= 1024) { 1075 /* GOOD numbers: 0x1D */ 1076 /* OKAY numbers: 0x15 0x14 0x16 0x18 0x19 */ 1077 /* BAD numbers: 0x0E 0x12 0x13 0x0D */ 1078 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x001D); 1079 } else if (mode->CrtcHDisplay <= 1280) { 1080 /* GOOD numbers: */ 1081 /* BAD numbers: */ 1082 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0022); /* 10 */ 1083 } else { 1084 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xFFE0) | (0x0024); 1085 } 1086 } else { 1087 /* ??? What could it be? Use some sane numbers. */ 1088 } 1089 1090 /* Setup the appropriate memory interleaving */ 1091 pCir->chip.lg->ModeReg.DTTC |= (pCir->chip.lg->memInterleave << 8); 1092 pCir->chip.lg->ModeReg.TILE |= pCir->chip.lg->memInterleave & 0xC0; 1093 1094 if (PCI_CHIP_GD5465 == pCir->Chipset) { 1095 /* The tile control information in the DTTC is also mirrored 1096 elsewhere. */ 1097 pCir->chip.lg->ModeReg.TileCtrl = pCir->chip.lg->ModeReg.DTTC & 0xFFC0; 1098 1099 /* The 5465's DTTC records _fetches_ per line, not 1100 tiles per line. Fetchs are 128-byte fetches. */ 1101 if (pCir->chip.lg->ModeReg.DTTC & 0x0040) { 1102 /* Using 256-byte wide tiles. Double the fetches 1103 per line field. */ 1104 pCir->chip.lg->ModeReg.DTTC = (pCir->chip.lg->ModeReg.DTTC & 0xC0FF) 1105 | ((pCir->chip.lg->ModeReg.DTTC & 0x3F00) << 1); 1106 } 1107 } 1108 1109 /* Program the registers */ 1110 vgaHWProtect(pScrn, TRUE); 1111 hwp->writeMiscOut(hwp, hwp->ModeReg.MiscOutReg); 1112 1113 clockData = LgSetClock(pCir, hwp, mode->SynthClock); 1114 pCir->chip.lg->ModeReg.ExtVga[SR0E] = (clockData >> 8) & 0xFF; 1115 pCir->chip.lg->ModeReg.ExtVga[SR1E] = clockData & 0xFF; 1116 1117 /* Write those registers out to the card. */ 1118 LgRestoreLgRegs(pScrn, &pCir->chip.lg->ModeReg); 1119 1120 /* Programme the registers */ 1121 vgaHWRestore(pScrn, &hwp->ModeReg, VGA_SR_MODE | VGA_SR_CMAP); 1122 1123 vgaHWProtect(pScrn, FALSE); 1124 1125 return TRUE; 1126} 1127 1128static int LgFindLineData(int displayWidth, int bpp) 1129{ 1130 /* Find the smallest tile-line-pitch such that the total byte pitch 1131 is greater than or equal to displayWidth*Bpp. */ 1132 int i; 1133 1134 /* Some pitch sizes are duplicates in the table. BUT, the invariant is 1135 that the _first_ time a pitch occurs in the table is always _before_ 1136 all other pitches greater than it. Said in another way... if all 1137 duplicate entries from the table were removed, then the resulting pitch 1138 values are strictly increasing. */ 1139 1140 for (i = 0; LgLineData[i].pitch > 0; i++) 1141 if (LgLineData[i].pitch >= displayWidth*bpp>>3) 1142 return i; 1143 1144 /* Um, uh oh! */ 1145 return -1; 1146} 1147 1148 1149 1150 1151static void 1152LgRestoreLgRegs(ScrnInfoPtr pScrn, LgRegPtr lgReg) 1153{ 1154 CirPtr pCir; 1155 vgaHWPtr hwp; 1156 CARD8 cr1D; 1157 1158 pCir = CIRPTR(pScrn); 1159 1160 /* First, VGAish registers. */ 1161 hwp = VGAHWPTR(pScrn); 1162 hwp->writeCrtc(hwp, 0x1A, lgReg->ExtVga[CR1A]); 1163 hwp->writeCrtc(hwp, 0x1B, lgReg->ExtVga[CR1B]); 1164 cr1D = (hwp->readCrtc(hwp, 0x1D) & ~1) | (lgReg->ExtVga[CR1D] & 0x01); 1165 hwp->writeCrtc(hwp, 0x1D, cr1D); 1166 hwp->writeCrtc(hwp, 0x1E, lgReg->ExtVga[CR1E]); 1167 1168 hwp->writeSeq(hwp, 0x07, lgReg->ExtVga[SR07]); 1169 hwp->writeSeq(hwp, 0x0E, lgReg->ExtVga[SR0E]); 1170 hwp->writeSeq(hwp, 0x12, lgReg->ExtVga[SR12]); 1171 hwp->writeSeq(hwp, 0x13, lgReg->ExtVga[SR13]); 1172 hwp->writeSeq(hwp, 0x1E, lgReg->ExtVga[SR1E]); 1173 memww(0xC0, lgReg->FORMAT); 1174 1175 /* Vendor Specific Control is touchy. Only bit 28 is of concern. */ 1176 memwl(0x3FC, ((memrl(0x3FC) & ~(1<<28)) | (lgReg->VSC & (1<<28)))); 1177 1178 memww(0xEA, lgReg->DTTC); 1179 1180 if (pCir->Chipset == PCI_CHIP_GD5465) { 1181 memww(0x2C4, lgReg->TileCtrl); 1182 } 1183 1184 memwb(0x407, lgReg->TILE); 1185 1186 if (pCir->Chipset == PCI_CHIP_GD5465) 1187 memwb(0x2C0, lgReg->BCLK); 1188 else 1189 memwb(0x8C, lgReg->BCLK); 1190 1191 memww(0x402, lgReg->CONTROL); 1192} 1193 1194/* 1195 * Restore the initial (text) mode. 1196 */ 1197static void 1198LgRestore(ScrnInfoPtr pScrn) 1199{ 1200 vgaHWPtr hwp; 1201 vgaRegPtr vgaReg; 1202 CirPtr pCir; 1203 LgRegPtr lgReg; 1204 1205#ifdef LG_DEBUG 1206 ErrorF("LgRestore pScrn = %p\n", (void *)pScrn); 1207#endif 1208 1209 pCir = CIRPTR(pScrn); 1210 hwp = VGAHWPTR(pScrn); 1211 vgaReg = &hwp->SavedReg; 1212 lgReg = &pCir->chip.lg->SavedReg; 1213 1214 vgaHWProtect(pScrn, TRUE); 1215 1216 LgRestoreLgRegs(pScrn, lgReg); 1217 1218 vgaHWRestore(pScrn, vgaReg, VGA_SR_ALL); 1219 vgaHWProtect(pScrn, FALSE); 1220} 1221 1222/* Mandatory */ 1223 1224/* This gets called at the start of each server generation */ 1225 1226Bool 1227LgScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 1228{ 1229 /* The vgaHW references will disappear one day */ 1230 ScrnInfoPtr pScrn; 1231 vgaHWPtr hwp; 1232 CirPtr pCir; 1233 int i, ret; 1234 VisualPtr visual; 1235 int displayWidth,width,height; 1236 unsigned char * FbBase = NULL; 1237 1238#ifdef LG_DEBUG 1239 ErrorF("LgScreenInit\n"); 1240#endif 1241 1242 /* 1243 * First get the ScrnInfoRec 1244 */ 1245 pScrn = xf86Screens[pScreen->myNum]; 1246 1247 hwp = VGAHWPTR(pScrn); 1248 1249 hwp->MapSize = 0x10000; /* Standard 64k VGA window */ 1250 1251 pCir = CIRPTR(pScrn); 1252 1253 /* Map the VGA memory and get the VGA IO base */ 1254 if (!vgaHWMapMem(pScrn)) 1255 return FALSE; 1256 1257 /* Map the CIR memory and MMIO areas */ 1258 if (!CirMapMem(pCir, pScrn->scrnIndex)) 1259 return FALSE; 1260#ifdef EXPERIMENTAL 1261 lg_vgaHWSetMmioFunc(hwp, pCir->IOBase); 1262#endif 1263 vgaHWGetIOBase(hwp); 1264 1265 /* Save the current state */ 1266 LgSave(pScrn); 1267 1268 /* Initialise the first mode */ 1269 if (!LgModeInit(pScrn, pScrn->currentMode)) 1270 return FALSE; 1271 1272 /* Make things beautiful */ 1273 LgSaveScreen(pScreen, SCREEN_SAVER_ON); 1274 1275 /* Set the viewport */ 1276 LgAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 1277 1278 /* 1279 * The next step is to setup the screen's visuals, and initialise the 1280 * framebuffer code. In cases where the framebuffer's default 1281 * choices for things like visual layouts and bits per RGB are OK, 1282 * this may be as simple as calling the framebuffer's ScreenInit() 1283 * function. If not, the visuals will need to be setup before calling 1284 * a fb ScreenInit() function and fixed up after. 1285 * 1286 */ 1287 1288 /* 1289 * Reset the visual list. 1290 */ 1291 miClearVisualTypes(); 1292 1293 /* Setup the visuals we support. */ 1294 1295 if (!miSetVisualTypes(pScrn->depth, 1296 miGetDefaultVisualMask(pScrn->depth), 1297 pScrn->rgbBits, pScrn->defaultVisual)) 1298 return FALSE; 1299 1300 miSetPixmapDepths (); 1301 1302#ifdef LG_DEBUG 1303 ErrorF("LgScreenInit after miSetVisualTypes\n"); 1304#endif 1305 displayWidth = pScrn->displayWidth; 1306 if (pCir->rotate) { 1307 height = pScrn->virtualX; 1308 width = pScrn->virtualY; 1309 } else { 1310 width = pScrn->virtualX; 1311 height = pScrn->virtualY; 1312 } 1313 1314 if(pCir->shadowFB) { 1315 pCir->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); 1316 pCir->ShadowPtr = xalloc(pCir->ShadowPitch * height); 1317 displayWidth = pCir->ShadowPitch / (pScrn->bitsPerPixel >> 3); 1318 FbBase = pCir->ShadowPtr; 1319 } else { 1320 pCir->ShadowPtr = NULL; 1321 FbBase = pCir->FbBase; 1322 } 1323 1324 /* 1325 * Call the framebuffer layer's ScreenInit function, and fill in other 1326 * pScreen fields. 1327 */ 1328 switch (pScrn->bitsPerPixel) { 1329 case 8: 1330 case 16: 1331 case 24: 1332 case 32: 1333 ret = fbScreenInit(pScreen, FbBase, 1334 width,height, 1335 pScrn->xDpi, pScrn->yDpi, 1336 displayWidth,pScrn->bitsPerPixel); 1337 break; 1338 default: 1339 xf86DrvMsg(scrnIndex, X_ERROR, 1340 "X11: Internal error: invalid bpp (%d) in LgScreenInit\n", 1341 pScrn->bitsPerPixel); 1342 ret = FALSE; 1343 break; 1344 } 1345 if (!ret) 1346 return FALSE; 1347 1348#ifdef LG_DEBUG 1349 ErrorF("LgScreenInit after depth dependent init\n"); 1350#endif 1351 1352 /* Override the default mask/offset settings */ 1353 if (pScrn->bitsPerPixel > 8) { 1354 for (i = 0; i < pScreen->numVisuals; i++) { 1355 visual = &pScreen->visuals[i]; 1356 if ((visual->class | DynamicClass) == DirectColor) { 1357 visual->offsetRed = pScrn->offset.red; 1358 visual->offsetGreen = pScrn->offset.green; 1359 visual->offsetBlue = pScrn->offset.blue; 1360 visual->redMask = pScrn->mask.red; 1361 visual->greenMask = pScrn->mask.green; 1362 visual->blueMask = pScrn->mask.blue; 1363 } 1364 } 1365 } 1366 1367 /* must be after RGB ordering fixed */ 1368 1369 fbPictureInit(pScreen, 0, 0); 1370 1371 miInitializeBackingStore(pScreen); 1372 1373 /* 1374 * Set initial black & white colourmap indices. 1375 */ 1376 xf86SetBlackWhitePixels(pScreen); 1377 1378 if (!pCir->NoAccel) { /* Initialize XAA functions */ 1379 if (!LgXAAInit(pScreen)) 1380 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Could not initialize XAA\n"); 1381 } 1382#if 1 1383 pCir->DGAModeInit = LgModeInit; 1384 if (!CirDGAInit(pScreen)) 1385 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1386 "DGA initialization failed\n"); 1387#endif 1388 xf86SetSilkenMouse(pScreen); 1389 1390 /* Initialise cursor functions */ 1391 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1392 1393 if (pCir->HWCursor) { /* Initialize HW cursor layer */ 1394 if (!LgHWCursorInit(pScreen)) 1395 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1396 "Hardware cursor initialization failed\n"); 1397 } 1398 1399 /* Initialise default colourmap */ 1400 if (!miCreateDefColormap(pScreen)) 1401 return FALSE; 1402 1403 if (pScrn->bitsPerPixel > 1 && pScrn->bitsPerPixel <= 8) 1404 vgaHWHandleColormaps(pScreen); 1405 1406 xf86DPMSInit(pScreen, LgDisplayPowerManagementSet, 0); 1407 1408 pScrn->memPhysBase = pCir->FbAddress; 1409 pScrn->fbOffset = 0; 1410 1411 { 1412 XF86VideoAdaptorPtr *ptr; 1413 int n; 1414 1415 n = xf86XVListGenericAdaptors(pScrn,&ptr); 1416 if (n) 1417 xf86XVScreenInit(pScreen, ptr, n); 1418 } 1419 1420 /* 1421 * Wrap the CloseScreen vector and set SaveScreen. 1422 */ 1423 pScreen->SaveScreen = LgSaveScreen; 1424 pCir->CloseScreen = pScreen->CloseScreen; 1425 pScreen->CloseScreen = LgCloseScreen; 1426 1427 /* Report any unused options (only for the first generation) */ 1428 if (serverGeneration == 1) 1429 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1430 1431 /* Done */ 1432 return TRUE; 1433} 1434 1435 1436/* Usually mandatory */ 1437Bool 1438LgSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 1439{ 1440 return LgModeInit(xf86Screens[scrnIndex], mode); 1441} 1442 1443#define ROUND_DOWN(x, mod) (((x) / (mod)) * (mod)) 1444#define ROUND_UP(x, mod) ((((x) + (mod) - 1) / (mod)) * (mod)) 1445 1446/* 1447 * This function is used to initialize the Start Address - the first 1448 * displayed location in the video memory. 1449 */ 1450/* Usually mandatory */ 1451void 1452LgAdjustFrame(int scrnIndex, int x, int y, int flags) 1453{ 1454 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1455 int Base, tmp; 1456 CirPtr pCir = CIRPTR(pScrn); 1457 vgaHWPtr hwp = VGAHWPTR(pScrn); 1458 int cursorX, cursorY; 1459 int middleX, middleY; 1460 const LgLineDataPtr lineData = &LgLineData[pCir->chip.lg->lineDataIndex]; 1461 const int viewportXRes = 1462 (PCI_CHIP_GD5465 == pCir->Chipset) ? (24==pScrn->bitsPerPixel?24:1) : 1463 (lineData->width?256:128) / 1464 (24==pScrn->bitsPerPixel?1:(pScrn->bitsPerPixel>>3)); 1465 const int viewportYRes = 1466 (PCI_CHIP_GD5465 == pCir->Chipset) ? 1 : (24==pScrn->bitsPerPixel?3:1); 1467 1468 /* Where's the pointer? */ 1469 miPointerGetPosition(inputInfo.pointer, &cursorX, &cursorY); 1470 1471 /* Where's the middle of the screen? We want to eventually know 1472 which side of the screen the pointer is on. */ 1473 middleX = (pScrn->frameX1 + pScrn->frameX0) / 2; 1474 middleY = (pScrn->frameY1 + pScrn->frameY0) / 2; 1475 1476 if (cursorX < middleX) { 1477 /* Pointer is on left side of screen. Round the frame value down. */ 1478 pScrn->frameX0 = ROUND_DOWN(pScrn->frameX0, viewportXRes); 1479 } else { 1480 /* Pointer is on right side of screen. Round the frame value 1481 up. A side effect of this rounding up is that we might expose 1482 a part of the screen that's actually on the far /left/ of the 1483 frame buffer. That's because, although the virtual desktop might 1484 be an integral number of tiles, the display might not. We'll 1485 just live with this artifact. */ 1486 pScrn->frameX0 = ROUND_UP(pScrn->frameX0, viewportXRes); 1487 } 1488 pScrn->frameX1 = pScrn->frameX0 + pScrn->currentMode->HDisplay - 1; 1489 1490 if (cursorY < middleY) { 1491 pScrn->frameY0 = ROUND_DOWN(pScrn->frameY0, viewportYRes); 1492 } else { 1493 pScrn->frameY0 = ROUND_UP(pScrn->frameY0, viewportYRes); 1494 } 1495 pScrn->frameY1 = pScrn->frameY0 + pScrn->currentMode->VDisplay - 1; 1496 1497 1498 if (x != pScrn->frameX0 || y != pScrn->frameY0) { 1499 /* !!! */ 1500 /* We moved the frame from where xf86SetViewport() placed it. 1501 If we're using a SW cursor, that's okay -- the pointer exists in 1502 the framebuffer, and those bits are still all aligned. But 1503 if we're using a HW cursor, then we need to re-align the pointer. 1504 Call SetCursorPosition() with the appropriate new pointer 1505 values, adjusted to be wrt the new frame. */ 1506 1507 x = pScrn->frameX0; 1508 y = pScrn->frameY0; 1509 } 1510 1511 /* ??? Will this work for 1bpp? */ 1512 Base = (y * lineData->pitch + (x*pScrn->bitsPerPixel/8)) / 4; 1513 1514 if ((Base & ~0x000FFFFF) != 0) { 1515 /* ??? */ 1516 ErrorF("X11: Internal error: LgAdjustFrame: cannot handle overflow\n"); 1517 return; 1518 } 1519 1520 hwp->writeCrtc(hwp, 0x0C, (Base >> 8) & 0xFF); 1521 hwp->writeCrtc(hwp, 0x0D, Base & 0xFF); 1522 tmp = hwp->readCrtc(hwp, 0x1B) & 0xF2; 1523 tmp |= (Base >> 16) & 0x01; 1524 tmp |= (Base >> 15) & 0x0C; 1525 hwp->writeCrtc(hwp, 0x1B, tmp); 1526 tmp = hwp->readCrtc(hwp, 0x1D) & 0xE7; 1527 tmp |= (Base >> 16) & 0x18; 1528 hwp->writeCrtc(hwp, 0x1D, tmp); 1529} 1530 1531/* 1532 * This is called when VT switching back to the X server. Its job is 1533 * to reinitialise the video mode. 1534 * 1535 * We may wish to unmap video/MMIO memory too. 1536 */ 1537 1538/* Mandatory */ 1539Bool 1540LgEnterVT(int scrnIndex, int flags) 1541{ 1542 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1543 CirPtr pCir = CIRPTR(pScrn); 1544#ifdef LG_DEBUG 1545 ErrorF("LgEnterVT\n"); 1546#endif 1547 1548 /* XXX Shouldn't this be in LeaveVT? */ 1549 /* Disable HW cursor */ 1550 if (pCir->HWCursor) 1551 LgHideCursor(pScrn); 1552 1553 /* Should we re-save the text mode on each VT enter? */ 1554 return LgModeInit(pScrn, pScrn->currentMode); 1555} 1556 1557 1558/* 1559 * This is called when VT switching away from the X server. Its job is 1560 * to restore the previous (text) mode. 1561 * 1562 * We may wish to remap video/MMIO memory too. 1563 */ 1564 1565/* Mandatory */ 1566void 1567LgLeaveVT(int scrnIndex, int flags) 1568{ 1569 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1570 vgaHWPtr hwp = VGAHWPTR(pScrn); 1571 CirPtr pCir = CIRPTR(pScrn); 1572#ifdef LG_DEBUG 1573 ErrorF("LgLeaveVT\n"); 1574#endif 1575 1576 /* XXX Shouldn't this be in EnterVT? */ 1577 /* Enable HW cursor */ 1578 if (pCir->HWCursor) 1579 LgShowCursor(pScrn); 1580 1581 LgRestore(pScrn); 1582 vgaHWLock(hwp); 1583} 1584 1585 1586/* 1587 * This is called at the end of each server generation. It restores the 1588 * original (text) mode. It should also unmap the video memory, and free 1589 * any per-generation data allocated by the driver. It should finish 1590 * by unwrapping and calling the saved CloseScreen function. 1591 */ 1592 1593/* Mandatory */ 1594static Bool 1595LgCloseScreen(int scrnIndex, ScreenPtr pScreen) 1596{ 1597 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1598 vgaHWPtr hwp = VGAHWPTR(pScrn); 1599 CirPtr pCir = CIRPTR(pScrn); 1600 1601 if(pScrn->vtSema) { 1602 LgRestore(pScrn); 1603 if (pCir->HWCursor) 1604 LgHideCursor(pScrn); 1605 1606 vgaHWLock(hwp); 1607 1608 CirUnmapMem(pCir, pScrn->scrnIndex); 1609 } 1610 1611 if (pCir->AccelInfoRec) 1612 XAADestroyInfoRec(pCir->AccelInfoRec); 1613 pCir->AccelInfoRec = NULL; 1614 1615 if (pCir->CursorInfoRec) 1616 xf86DestroyCursorInfoRec(pCir->CursorInfoRec); 1617 pCir->CursorInfoRec = NULL; 1618 if (pCir->DGAModes) 1619 xfree(pCir->DGAModes); 1620 pCir->DGAnumModes = 0; 1621 pCir->DGAModes = NULL; 1622 1623 pScrn->vtSema = FALSE; 1624 1625 pScreen->CloseScreen = pCir->CloseScreen; 1626 return (*pScreen->CloseScreen)(scrnIndex, pScreen); 1627} 1628 1629 1630/* Free up any persistent data structures */ 1631 1632/* Optional */ 1633void 1634LgFreeScreen(int scrnIndex, int flags) 1635{ 1636#ifdef LG_DEBUG 1637 ErrorF("LgFreeScreen\n"); 1638#endif 1639 /* 1640 * This only gets called when a screen is being deleted. It does not 1641 * get called routinely at the end of a server generation. 1642 */ 1643 if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) 1644 vgaHWFreeHWRec(xf86Screens[scrnIndex]); 1645 LgFreeRec(xf86Screens[scrnIndex]); 1646} 1647 1648 1649/* Checks if a mode is suitable for the selected chipset. */ 1650 1651/* Optional */ 1652ModeStatus 1653LgValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) 1654{ 1655 int lace; 1656 1657 lace = 1 + ((mode->Flags & V_INTERLACE) != 0); 1658 1659 if ((mode->CrtcHDisplay <= 2048) && 1660 (mode->CrtcHSyncStart <= 4096) && 1661 (mode->CrtcHSyncEnd <= 4096) && 1662 (mode->CrtcHTotal <= 4096) && 1663 (mode->CrtcVDisplay <= 2048 * lace) && 1664 (mode->CrtcVSyncStart <= 4096 * lace) && 1665 (mode->CrtcVSyncEnd <= 4096 * lace) && 1666 (mode->CrtcVTotal <= 4096 * lace)) { 1667 return(MODE_OK); 1668 } 1669 return(MODE_BAD); 1670} 1671 1672 1673/* Do screen blanking */ 1674 1675/* Mandatory */ 1676static Bool 1677LgSaveScreen(ScreenPtr pScreen, int mode) 1678{ 1679 CirPtr pCir = CIRPTR(xf86Screens[pScreen->myNum]); 1680 ScrnInfoPtr pScrn = NULL; 1681 Bool unblank; 1682 1683 unblank = xf86IsUnblank(mode); 1684 1685 if (pScreen != NULL) 1686 pScrn = xf86Screens[pScreen->myNum]; 1687 1688 if (pScrn != NULL && pScrn->vtSema) { 1689 if (unblank) 1690 /* Power up the palette DAC */ 1691 memwb(0xB0,memrb(0xB0) & 0x7F); 1692 else 1693 /* Power down the palette DAC */ 1694 memwb(0xB0,memrb(0xB0) | 0x80); 1695 } 1696 1697 return vgaHWSaveScreen(pScreen, mode); 1698} 1699 1700static CARD16 1701LgSetClock(CirPtr pCir, vgaHWPtr hwp, int freq) 1702{ 1703 int ffreq, num, den; 1704 CARD8 tmp; 1705 1706 ErrorF("LgSetClock freq=%d.%03dMHz\n", freq / 1000, freq % 1000); 1707 1708 ffreq = freq; 1709 if (!CirrusFindClock(&ffreq, pCir->MaxClock, &num, &den)) 1710 return 0; 1711 1712 ErrorF("LgSetClock: nom=%x den=%x ffreq=%d.%03dMHz\n", 1713 num, den, ffreq / 1000, ffreq % 1000); 1714 1715 /* Set VCLK3. */ 1716 /* The numerator and denominator registers are switched 1717 around in the Laguna chips. */ 1718 tmp = hwp->readSeq(hwp, 0x0E); 1719 hwp->writeSeq(hwp, 0x0E, (tmp & 0x80) | den); 1720 hwp->writeSeq(hwp, 0x1E, num); 1721 1722 return (den << 8) | num; 1723} 1724 1725/* 1726 * CIRDisplayPowerManagementSet -- 1727 * 1728 * Sets VESA Display Power Management Signaling (DPMS) Mode. 1729 */ 1730static void 1731LgDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, 1732 int flags) 1733{ 1734 unsigned char sr01, cr1a; 1735 vgaHWPtr hwp; 1736 1737#ifdef LG_DEBUG 1738 ErrorF("LgDisplayPowerManagementSet: %d\n", PowerManagementMode); 1739#endif 1740 1741 hwp = VGAHWPTR(pScrn); 1742 1743 switch (PowerManagementMode) { 1744 case DPMSModeOn: 1745 /* Screen: On; HSync: On, VSync: On */ 1746 sr01 = 0x00; 1747 cr1a = 0x00; 1748 break; 1749 case DPMSModeStandby: 1750 /* Screen: Off; HSync: Off, VSync: On */ 1751 sr01 = 0x20; 1752 cr1a = 0x08; 1753 break; 1754 case DPMSModeSuspend: 1755 /* Screen: Off; HSync: On, VSync: Off */ 1756 sr01 = 0x20; 1757 cr1a = 0x04; 1758 break; 1759 case DPMSModeOff: 1760 /* Screen: Off; HSync: Off, VSync: Off */ 1761 sr01 = 0x20; 1762 cr1a = 0x0c; 1763 break; 1764 default: 1765 return; 1766 } 1767 1768 sr01 |= hwp->readSeq(hwp, 0x01) & ~0x20; 1769 hwp->writeSeq(hwp, 0x01, sr01); 1770 cr1a |= hwp->readCrtc(hwp, 0x1A) & ~0x0C; 1771 hwp->writeCrtc(hwp, 0x1A, cr1a); 1772} 1773 1774#define minb(p) MMIO_IN8(hwp->MMIOBase, (p)) 1775#define moutb(p,v) MMIO_OUT8(hwp->MMIOBase, (p),(v)) 1776 1777static void 1778mmioWriteCrtc(vgaHWPtr hwp, CARD8 index, CARD8 value) 1779{ 1780 moutb(index << 2, value); 1781} 1782 1783static CARD8 1784mmioReadCrtc(vgaHWPtr hwp, CARD8 index) 1785{ 1786 return minb(index << 2); 1787} 1788 1789static void 1790lg_vgaHWSetMmioFunc(vgaHWPtr hwp, CARD8 *base) 1791{ 1792 hwp->writeCrtc = mmioWriteCrtc; 1793 hwp->readCrtc = mmioReadCrtc; 1794 hwp->MMIOBase = base; 1795 hwp->MMIOOffset = 0; 1796} 1797