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