1 2/************************************************************************** 3 4Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 5All Rights Reserved. 6 7Permission is hereby granted, free of charge, to any person obtaining a 8copy of this software and associated documentation files (the 9"Software"), to deal in the Software without restriction, including 10without limitation the rights to use, copy, modify, merge, publish, 11distribute, sub license, and/or sell copies of the Software, and to 12permit persons to whom the Software is furnished to do so, subject to 13the following conditions: 14 15The above copyright notice and this permission notice (including the 16next paragraph) shall be included in all copies or substantial portions 17of the Software. 18 19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 23ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 27**************************************************************************/ 28 29/* 30 * Authors: 31 * Daryll Strauss <daryll@precisioninsight.com> 32 * 33 */ 34 35#ifdef HAVE_CONFIG_H 36#include "config.h" 37#endif 38 39#include <string.h> 40#include <math.h> 41#include <unistd.h> 42 43/* 44 * This server does not support these XFree86 4.0 features yet 45 * DDC1 & DDC2 (requires I2C) 46 * shadowFb (if requested or acceleration is off) 47 * Overlay planes 48 * DGA 49 */ 50 51/* 52 * These are X and server generic header files. 53 */ 54#include "xf86.h" 55#include "xf86_OSproc.h" 56#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 57#include "xf86Resources.h" 58#include "xf86RAC.h" 59#endif 60#include "xf86cmap.h" 61 62/* If the driver uses port I/O directly, it needs: */ 63 64#include "compiler.h" 65 66/* All drivers using the vgahw module need this */ 67/* This driver needs to be modified to not use vgaHW for multihead operation */ 68#include "vgaHW.h" 69 70/* Drivers using the mi SW cursor need: */ 71 72#include "mipointer.h" 73 74/* Drivers using the mi colourmap code need: */ 75 76#include "micmap.h" 77 78#include "fb.h" 79 80/* The driver's own header file: */ 81 82 83#include "regionstr.h" 84 85#include "xf86xv.h" 86#include <X11/extensions/Xv.h> 87 88#include "vbe.h" 89#include "i740_dga.h" 90#include "i740.h" 91 92 93/* Required Functions: */ 94static const OptionInfoRec * I740AvailableOptions(int chipid, int busid); 95 96/* Print a driver identifying message. */ 97static void I740Identify(int flags); 98 99/* Identify if there is any hardware present that I know how to drive. */ 100static Bool I740Probe(DriverPtr drv, int flags); 101 102/* Process the config file and see if we have a valid configuration */ 103static Bool I740PreInit(ScrnInfoPtr pScrn, int flags); 104 105/* Initialize a screen */ 106static Bool I740ScreenInit(SCREEN_INIT_ARGS_DECL); 107 108/* Enter from a virtual terminal */ 109static Bool I740EnterVT(VT_FUNC_ARGS_DECL); 110 111/* Leave to a virtual terminal */ 112static void I740LeaveVT(VT_FUNC_ARGS_DECL); 113 114/* Close down each screen we initialized */ 115static Bool I740CloseScreen(CLOSE_SCREEN_ARGS_DECL); 116 117/* Change screensaver state */ 118static Bool I740SaveScreen(ScreenPtr pScreen, int mode); 119 120/* Cleanup server private data */ 121static void I740FreeScreen(FREE_SCREEN_ARGS_DECL); 122 123/* Check if a mode is valid on the hardware */ 124static ModeStatus I740ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, 125 Bool verbose, int flags); 126 127/* Switch to various Display Power Management System levels */ 128static void I740DisplayPowerManagementSet(ScrnInfoPtr pScrn, 129 int PowerManagermentMode, int flags); 130 131static void I740ProbeDDC(ScrnInfoPtr pScrn, int index); 132 133static Bool I740MapMem(ScrnInfoPtr pScrn); 134static Bool I740UnmapMem(ScrnInfoPtr pScrn); 135 136#define I740_VERSION 4000 137#define I740_NAME "I740" 138#define I740_DRIVER_NAME "i740" 139#define I740_MAJOR_VERSION PACKAGE_VERSION_MAJOR 140#define I740_MINOR_VERSION PACKAGE_VERSION_MINOR 141#define I740_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL 142 143_X_EXPORT DriverRec I740 = { 144 I740_VERSION, 145 I740_DRIVER_NAME, 146 I740Identify, 147 I740Probe, 148 I740AvailableOptions, 149 NULL, 150 0 151}; 152 153/* Chipsets */ 154static SymTabRec I740Chipsets[] = { 155 { PCI_CHIP_I740_AGP, "i740 (agp)"}, 156 { PCI_CHIP_I740_PCI, "i740 (pci)"}, 157 { -1, NULL } 158}; 159 160static PciChipsets I740PciChipsets[] = { 161 { PCI_CHIP_I740_AGP, PCI_CHIP_I740_AGP, RES_SHARED_VGA }, 162 { PCI_CHIP_I740_PCI, PCI_CHIP_I740_PCI, RES_SHARED_VGA }, 163 { -1, -1, RES_UNDEFINED } 164}; 165 166typedef enum { 167 OPTION_NOACCEL, 168 OPTION_SW_CURSOR, 169 OPTION_SDRAM, 170 OPTION_SGRAM, 171 OPTION_SLOW_RAM, 172 OPTION_DAC_6BIT, 173 OPTION_USE_PIO, 174 OPTION_VGACOMPAT 175} I740Opts; 176 177static const OptionInfoRec I740Options[] = { 178 { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 179 { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, 180 { OPTION_SDRAM, "SDRAM", OPTV_BOOLEAN, {0}, FALSE}, 181 { OPTION_SGRAM, "SGRAM", OPTV_BOOLEAN, {0}, FALSE}, 182 { OPTION_SLOW_RAM, "SlowRam", OPTV_BOOLEAN, {0}, FALSE}, 183 { OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE}, 184 { OPTION_USE_PIO, "UsePIO", OPTV_BOOLEAN, {0}, FALSE}, 185 { OPTION_VGACOMPAT, "VGACompat", OPTV_BOOLEAN, {0}, FALSE}, 186 { -1, NULL, OPTV_NONE, {0}, FALSE} 187}; 188 189#ifdef XFree86LOADER 190 191static MODULESETUPPROTO(i740Setup); 192 193static XF86ModuleVersionInfo i740VersRec = 194{ 195 "i740", 196 MODULEVENDORSTRING, 197 MODINFOSTRING1, 198 MODINFOSTRING2, 199 XORG_VERSION_CURRENT, 200 I740_MAJOR_VERSION, I740_MINOR_VERSION, I740_PATCHLEVEL, 201 ABI_CLASS_VIDEODRV, 202 ABI_VIDEODRV_VERSION, 203 MOD_CLASS_VIDEODRV, 204 {0,0,0,0} 205}; 206 207_X_EXPORT XF86ModuleData i740ModuleData = {&i740VersRec, i740Setup, 0}; 208 209static pointer 210i740Setup(pointer module, pointer opts, int *errmaj, int *errmin) 211{ 212 static Bool setupDone = FALSE; 213 214 /* This module should be loaded only once, but check to be sure. */ 215 216 if (!setupDone) { 217 setupDone = TRUE; 218 xf86AddDriver(&I740, module, 0); 219 220 /* 221 * Modules that this driver always requires may be loaded here 222 * by calling LoadSubModule(). 223 */ 224 225 /* 226 * The return value must be non-NULL on success even though there 227 * is no TearDownProc. 228 */ 229 return (pointer)1; 230 } else { 231 if (errmaj) *errmaj = LDR_ONCEONLY; 232 return NULL; 233 } 234} 235 236#endif 237 238/* 239 * I740GetRec and I740FreeRec -- 240 * 241 * Private data for the driver is stored in the screen structure. 242 * These two functions create and destroy that private data. 243 * 244 */ 245static Bool 246I740GetRec(ScrnInfoPtr pScrn) { 247 if (pScrn->driverPrivate) return TRUE; 248 249 pScrn->driverPrivate = xnfcalloc(sizeof(I740Rec), 1); 250 return TRUE; 251} 252 253static void 254I740FreeRec(ScrnInfoPtr pScrn) { 255 if (!pScrn) return; 256 free(pScrn->driverPrivate); 257 pScrn->driverPrivate=0; 258} 259 260static const OptionInfoRec * 261I740AvailableOptions(int chipid, int busid) 262{ 263 return I740Options; 264} 265 266/* 267 * I740Identify -- 268 * 269 * Returns the string name for the driver based on the chipset. In this 270 * case it will always be an I740, so we can return a static string. 271 * 272 */ 273static void 274I740Identify(int flags) { 275 xf86PrintChipsets(I740_NAME, "Driver for Intel i740 chipset", I740Chipsets); 276} 277 278/* 279 * I740Probe -- 280 * 281 * Look through the PCI bus to find cards that are I740 boards. 282 * Setup the dispatch table for the rest of the driver functions. 283 * 284 */ 285static Bool 286I740Probe(DriverPtr drv, int flags) { 287 int i, numUsed, numDevSections, *usedChips; 288 GDevPtr *devSections; 289 Bool foundScreen = FALSE; 290 291 /* 292 Find the config file Device sections that match this 293 driver, and return if there are none. 294 */ 295 if ((numDevSections = xf86MatchDevice(I740_DRIVER_NAME, &devSections))<=0) { 296 return FALSE; 297 } 298 299#ifndef XSERVER_LIBPCIACCESS 300 /* 301 Since these Probing is just checking the PCI data the server already 302 collected. 303 */ 304 if (!xf86GetPciVideoInfo()) return FALSE; 305#endif 306 307 /* Look for Intel based chips */ 308 numUsed = xf86MatchPciInstances(I740_NAME, PCI_VENDOR_INTEL, 309 I740Chipsets, I740PciChipsets, 310 devSections, numDevSections, 311 drv, &usedChips); 312 313 if (numUsed > 0) { 314 if (flags & PROBE_DETECT) 315 foundScreen = TRUE; 316 else for (i=0; i<numUsed; i++) { 317 ScrnInfoPtr pScrn = NULL; 318 /* Allocate new ScrnInfoRec and claim the slot */ 319 if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], 320 I740PciChipsets, 0, 0, 0, 0, 0))) { 321 pScrn->driverVersion = I740_VERSION; 322 pScrn->driverName = I740_DRIVER_NAME; 323 pScrn->name = I740_NAME; 324 pScrn->Probe = I740Probe; 325 pScrn->PreInit = I740PreInit; 326 pScrn->ScreenInit = I740ScreenInit; 327 pScrn->SwitchMode = I740SwitchMode; 328 pScrn->AdjustFrame = I740AdjustFrame; 329 pScrn->EnterVT = I740EnterVT; 330 pScrn->LeaveVT = I740LeaveVT; 331 pScrn->FreeScreen = I740FreeScreen; 332 pScrn->ValidMode = I740ValidMode; 333 foundScreen = TRUE; 334 335 } 336 } 337 } 338 339 340 /* Look for Real3D based chips */ 341 numUsed = xf86MatchPciInstances(I740_NAME, PCI_VENDOR_REAL3D, 342 I740Chipsets, I740PciChipsets, 343 devSections, numDevSections, 344 drv, &usedChips); 345 346 if (numUsed > 0) { 347 if (flags & PROBE_DETECT) 348 foundScreen = TRUE; 349 else for (i=0; i<numUsed; i++) { 350 ScrnInfoPtr pScrn = NULL; 351 if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], 352 I740PciChipsets, 0, 0, 0, 0, 0))) { 353 pScrn->driverVersion = I740_VERSION; 354 pScrn->driverName = I740_DRIVER_NAME; 355 pScrn->name = I740_NAME; 356 pScrn->Probe = I740Probe; 357 pScrn->PreInit = I740PreInit; 358 pScrn->ScreenInit = I740ScreenInit; 359 pScrn->SwitchMode = I740SwitchMode; 360 pScrn->AdjustFrame = I740AdjustFrame; 361 pScrn->EnterVT = I740EnterVT; 362 pScrn->LeaveVT = I740LeaveVT; 363 pScrn->FreeScreen = I740FreeScreen; 364 pScrn->ValidMode = I740ValidMode; 365 foundScreen = TRUE; 366 } 367 } 368 } 369 370 free(devSections); 371 free(usedChips); 372 373 return foundScreen; 374} 375 376/* Ugh. Can we not do this? */ 377static void 378I740ProbeDDC(ScrnInfoPtr pScrn, int index) 379{ 380 vbeInfoPtr pVbe; 381 if (xf86LoadSubModule(pScrn, "vbe")) { 382 pVbe = VBEInit(NULL,index); 383 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 384 vbeFree(pVbe); 385 } 386} 387 388/* 389 * I740PreInit -- 390 * 391 * Do initial setup of the board before we know what resolution we will 392 * be running at. 393 * 394 */ 395static Bool 396I740PreInit(ScrnInfoPtr pScrn, int flags) { 397 I740Ptr pI740; 398 ClockRangePtr clockRanges; 399 int i; 400 MessageType from; 401 int temp; 402 int flags24; 403 rgb defaultWeight = {0, 0, 0}; 404 405 if (pScrn->numEntities != 1) return FALSE; 406 407 /* Allocate driverPrivate */ 408 if (!I740GetRec(pScrn)) { 409 return FALSE; 410 } 411 412 pI740 = I740PTR(pScrn); 413 414 pI740->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); 415 if (pI740->pEnt->location.type != BUS_PCI) return FALSE; 416 417 /*I740ProbeDDC(pScrn, pI740->pEnt->index);*/ 418 if (flags & PROBE_DETECT) { 419 I740ProbeDDC(pScrn, pI740->pEnt->index); 420 return TRUE; 421 } 422 423 /* The vgahw module should be loaded here when needed */ 424 if (!xf86LoadSubModule(pScrn, "vgahw")) return FALSE; 425 426 /* Allocate a vgaHWRec */ 427 if (!vgaHWGetHWRec(pScrn)) return FALSE; 428 vgaHWSetStdFuncs(VGAHWPTR(pScrn)); 429 430 pI740->PciInfo = xf86GetPciInfoForEntity(pI740->pEnt->index); 431#ifndef XSERVER_LIBPCIACCESS 432 pI740->PciTag = pciTag(pI740->PciInfo->bus, pI740->PciInfo->device, 433 pI740->PciInfo->func); 434 435 if (xf86RegisterResources(pI740->pEnt->index, 0, ResNone)) 436 return FALSE; 437 if (pI740->usePIO) 438 pScrn->racIoFlags = RAC_FB | RAC_COLORMAP; 439 else 440 pScrn->racMemFlags = RAC_FB | RAC_COLORMAP; 441#endif 442 /* Set pScrn->monitor */ 443 pScrn->monitor = pScrn->confScreen->monitor; 444 445 446 flags24=Support24bppFb | Support32bppFb | SupportConvert32to24; 447 if (!xf86SetDepthBpp(pScrn, 0, 0, 0, flags24)) { 448 return FALSE; 449 } else { 450 switch (pScrn->depth) { 451 case 8: 452 case 15: 453 case 16: 454 case 24: 455 break; 456 default: 457 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 458 "Given depth (%d) is not supported by i740 driver\n", 459 pScrn->depth); 460 return FALSE; 461 } 462 } 463 /*xf86PrintDepthBpp(pScrn);*/ 464 465 if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) 466 return FALSE; 467 468 if (!xf86SetDefaultVisual(pScrn, -1)) { 469 return FALSE; 470 } else { 471 /* We don't currently support DirectColor at > 8bpp */ 472 if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) { 473 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual" 474 " (%s) is not supported at depth %d\n", 475 xf86GetVisualName(pScrn->defaultVisual), pScrn->depth); 476 return FALSE; 477 } 478 } 479 480 /* We use a programamble clock */ 481 pScrn->progClock = TRUE; 482 483 pI740->cpp = pScrn->bitsPerPixel/8; 484 485 /* Process the options */ 486 xf86CollectOptions(pScrn, NULL); 487 if (!(pI740->Options = malloc(sizeof(I740Options)))) 488 return FALSE; 489 memcpy(pI740->Options, I740Options, sizeof(I740Options)); 490 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI740->Options); 491 492 /* 6-BIT dac isn't reasonable for modes with > 8bpp */ 493 if (xf86ReturnOptValBool(pI740->Options, OPTION_DAC_6BIT, FALSE) && 494 pScrn->bitsPerPixel>8) { 495 OptionInfoPtr ptr; 496 ptr=xf86TokenToOptinfo(pI740->Options, OPTION_DAC_6BIT); 497 ptr->found=FALSE; 498 } 499 500 if (xf86ReturnOptValBool(pI740->Options, OPTION_DAC_6BIT, FALSE)) 501 pScrn->rgbBits=8; 502 else 503 pScrn->rgbBits=6; 504 505 /* We have to use PIO to probe, because we haven't mappend yet */ 506 I740SetPIOAccess(pI740); 507 508 /* 509 * Set the Chipset and ChipRev, allowing config file entries to 510 * override. 511 */ 512 if (pI740->pEnt->device->chipset && *pI740->pEnt->device->chipset) { 513 pScrn->chipset = pI740->pEnt->device->chipset; 514 from = X_CONFIG; 515 } else if (pI740->pEnt->device->chipID >= 0) { 516 pScrn->chipset = (char *)xf86TokenToString(I740Chipsets, pI740->pEnt->device->chipID); 517 from = X_CONFIG; 518 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", 519 pI740->pEnt->device->chipID); 520 } else { 521 from = X_PROBED; 522 pScrn->chipset = (char *)xf86TokenToString(I740Chipsets, PCI_DEV_DEVICE_ID(pI740->PciInfo)); 523 } 524 if (pI740->pEnt->device->chipRev >= 0) { 525 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", 526 pI740->pEnt->device->chipRev); 527 } 528 529 xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", (pScrn->chipset!=NULL)?pScrn->chipset:"Unknown i740"); 530 531 if (pI740->pEnt->device->MemBase != 0) { 532 pI740->LinearAddr = pI740->pEnt->device->MemBase; 533 from = X_CONFIG; 534 } else { 535 if (PCI_REGION_BASE(pI740->PciInfo, 0, REGION_MEM) != 0) { 536 pI740->LinearAddr = PCI_REGION_BASE(pI740->PciInfo, 0, REGION_MEM)&0xFF000000; 537 from = X_PROBED; 538 } else { 539 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 540 "No valid FB address in PCI config space\n"); 541 I740FreeRec(pScrn); 542 return FALSE; 543 } 544 } 545 xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", 546 pI740->LinearAddr); 547 548 if (pI740->pEnt->device->IOBase != 0) { 549 pI740->MMIOAddr = pI740->pEnt->device->IOBase; 550 from = X_CONFIG; 551 } else { 552 if (PCI_REGION_BASE(pI740->PciInfo, 1, REGION_MEM)) { 553 pI740->MMIOAddr = PCI_REGION_BASE(pI740->PciInfo, 1, REGION_MEM)&0xFFF80000; 554 from = X_PROBED; 555 } else { 556 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 557 "No valid MMIO address in PCI config space\n"); 558 I740FreeRec(pScrn); 559 return FALSE; 560 } 561 } 562 xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n", 563 pI740->MMIOAddr); 564 565 /* Calculate memory */ 566 if (pI740->pEnt->device->videoRam) { 567 pScrn->videoRam = pI740->pEnt->device->videoRam; 568 from = X_CONFIG; 569 } else { 570 if ((pI740->readControl(pI740, XRX, DRAM_ROW_TYPE)&DRAM_ROW_1)==DRAM_ROW_1_SDRAM) 571 pScrn->videoRam=pI740->readControl(pI740, XRX, DRAM_ROW_BNDRY_1); 572 else 573 pScrn->videoRam=pI740->readControl(pI740, XRX, DRAM_ROW_BNDRY_0); 574 pScrn->videoRam = (pScrn->videoRam&0x0F)*1024; 575 from = X_PROBED; 576 } 577 578 temp=pI740->readControl(pI740, XRX, DRAM_ROW_CNTL_LO); 579 pI740->HasSGRAM = !((temp&DRAM_RAS_TIMING)||(temp&DRAM_RAS_PRECHARGE)); 580 if (xf86IsOptionSet(pI740->Options, OPTION_SDRAM)) { 581 if (xf86IsOptionSet(pI740->Options, OPTION_SGRAM)) { 582 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 583 "It is nonsensical to set both SDRAM and SGRAM options\n"); 584 return FALSE; 585 } 586 if (xf86ReturnOptValBool(pI740->Options, OPTION_SDRAM, FALSE)) { 587 pI740->HasSGRAM = FALSE; 588 } else { 589 pI740->HasSGRAM = TRUE; 590 } 591 } else { 592 if (xf86IsOptionSet(pI740->Options, OPTION_SDRAM)) { 593 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 594 "It is nonsensical to set both SDRAM and SGRAM options\n"); 595 return FALSE; 596 } 597 if (xf86ReturnOptValBool(pI740->Options, OPTION_SGRAM, FALSE)) { 598 pI740->HasSGRAM = TRUE; 599 } else { 600 pI740->HasSGRAM = FALSE; 601 } 602 } 603 604 xf86DrvMsg(pScrn->scrnIndex, from, "Steve was here! VideoRAM: %d kByte %s\n", 605 pScrn->videoRam, (pI740->HasSGRAM)?"SGRAM":"SDRAM"); 606 pI740->FbMapSize = pScrn->videoRam*1024; 607 608 /* 609 * If the driver can do gamma correction, it should call xf86SetGamma() 610 * here. 611 */ 612 613 { 614 Gamma zeros = {0.0, 0.0, 0.0}; 615 616 if (!xf86SetGamma(pScrn, zeros)) { 617 return FALSE; 618 } 619 } 620 621 pI740->MaxClock = 0; 622 if (pI740->pEnt->device->dacSpeeds[0]) { 623 switch (pScrn->bitsPerPixel) { 624 case 8: 625 pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP8]; 626 break; 627 case 16: 628 pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP16]; 629 break; 630 case 24: 631 pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP24]; 632 break; 633 case 32: 634 pI740->MaxClock = pI740->pEnt->device->dacSpeeds[DAC_BPP32]; 635 break; 636 } 637 if (!pI740->MaxClock) 638 pI740->MaxClock = pI740->pEnt->device->dacSpeeds[0]; 639 from = X_CONFIG; 640 } else { 641 switch (pScrn->bitsPerPixel) { 642 case 8: 643 pI740->MaxClock = 203000; 644 break; 645 case 16: 646 pI740->MaxClock = 163000; 647 break; 648 case 24: 649 if (pI740->HasSGRAM) 650 pI740->MaxClock = 136000; 651 else 652 pI740->MaxClock = 128000; 653 break; 654 case 32: 655 pI740->MaxClock = 86000; 656 } 657 } 658 clockRanges = xnfcalloc(sizeof(ClockRange), 1); 659 clockRanges->next=NULL; 660 clockRanges->minClock= 12000; /* !!! What's the min clock? !!! */ 661 clockRanges->maxClock=pI740->MaxClock; 662 clockRanges->clockIndex = -1; 663 clockRanges->interlaceAllowed = FALSE; /*PL*/ 664 clockRanges->doubleScanAllowed = TRUE; /*PL*/ 665 666 { /*PL*/ 667 668 if (xf86LoadSubModule(pScrn, "ddc")) { 669 if (xf86LoadSubModule(pScrn, "i2c") ) { 670 if (I740MapMem(pScrn)) { 671 if (I740_I2CInit(pScrn)) 672 { 673 xf86MonPtr MonInfo; 674 if ((MonInfo = xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn),pI740->rc_i2c))) { 675 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC Monitor info: %p\n", 676 MonInfo); 677 xf86PrintEDID( MonInfo ); 678 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "end of DDC Monitor " 679 "info\n\n"); 680 xf86SetDDCproperties(pScrn,MonInfo); 681 } 682 } 683 else 684 xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"I2C initialization failed\n"); 685 686 I740UnmapMem(pScrn); 687 } 688 } 689 } 690 } 691 692 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 693 pScrn->display->modes, clockRanges, 694 0, 320, 1600, 695 8, 200, 1200, 696 pScrn->display->virtualX, pScrn->display->virtualY, 697 pI740->FbMapSize, LOOKUP_BEST_REFRESH); 698 699 if (i==-1) { 700 I740FreeRec(pScrn); 701 return FALSE; 702 } 703 704 xf86PruneDriverModes(pScrn); 705 706 if (!i || !pScrn->modes) { 707 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 708 I740FreeRec(pScrn); 709 return FALSE; 710 } 711 712 xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 713 714 pScrn->currentMode = pScrn->modes; 715 716 xf86PrintModes(pScrn); 717 718 xf86SetDpi(pScrn, 0, 0); 719 720 if (!xf86LoadSubModule(pScrn, "fb")) { 721 I740FreeRec(pScrn); 722 return FALSE; 723 } 724 725 pI740->NoAccel = xf86ReturnOptValBool(pI740->Options, OPTION_NOACCEL, FALSE); 726 if (!pI740->NoAccel) { 727 if (!xf86LoadSubModule(pScrn, "xaa")) { 728 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No acceleration available\n"); 729 pI740->NoAccel = 1; 730 } 731 } 732 733 if (!xf86ReturnOptValBool(pI740->Options, OPTION_SW_CURSOR, FALSE)) { 734 if (!xf86LoadSubModule(pScrn, "ramdac")) { 735 I740FreeRec(pScrn); 736 return FALSE; 737 } 738 } 739 740 /* We wont be using the VGA access after the probe */ 741 if (!xf86ReturnOptValBool(pI740->Options, OPTION_USE_PIO, FALSE)) { 742#ifndef XSERVER_LIBPCIACCESS 743 resRange vgaio[] = { {ResShrIoBlock,0x3B0,0x3BB}, 744 {ResShrIoBlock,0x3C0,0x3DF}, 745 _END }; 746 resRange vgamem[] = {{ResShrMemBlock,0xA0000,0xAFFFF}, 747 {ResShrMemBlock,0xB8000,0xBFFFF}, 748 {ResShrMemBlock,0xB0000,0xB7FFF}, 749 _END }; 750#endif 751 pI740->usePIO=FALSE; 752 I740SetMMIOAccess(pI740); 753#ifndef XSERVER_LIBPCIACCESS 754 xf86SetOperatingState(vgaio, pI740->pEnt->index, ResUnusedOpr); 755 xf86SetOperatingState(vgamem, pI740->pEnt->index, ResDisableOpr); 756#endif 757 } else { 758 pI740->usePIO=TRUE; 759 } 760 761 if(xf86IsOptionSet(pI740->Options, OPTION_VGACOMPAT)) 762 pI740->usevgacompat=TRUE; 763 else 764 pI740->usevgacompat=FALSE; 765 766 767 768 { /* Overlay */ 769 pI740->colorKey = (1 << pScrn->offset.red) | (1 << pScrn->offset.green) | 770 (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue); 771 772 pI740->colorKey &= ((1 << pScrn->depth) - 1); 773 774 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video overlay key set to 0x%x\n", pI740->colorKey); 775 } 776 777 778 return TRUE; 779} 780 781static Bool I740MapMem(ScrnInfoPtr pScrn) 782{ 783#ifndef XSERVER_LIBPCIACCESS 784 int mmioFlags; 785#endif 786 I740Ptr pI740; 787 788 pI740 = I740PTR(pScrn); 789 790#ifndef XSERVER_LIBPCIACCESS 791 mmioFlags = VIDMEM_MMIO | VIDMEM_READSIDEEFFECT; 792 793 pI740->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, mmioFlags, 794 pI740->PciTag, 795 pI740->MMIOAddr, 796 0x80000); 797#else 798 { 799 void** result = (void**)&pI740->MMIOBase; 800 int err = pci_device_map_range(pI740->PciInfo, 801 pI740->MMIOAddr, 802 0x80000, 803 PCI_DEV_MAP_FLAG_WRITABLE, 804 result); 805 806 if (err) 807 return FALSE; 808 } 809 810#endif 811 if (!pI740->MMIOBase) return FALSE; 812 813#ifndef XSERVER_LIBPCIACCESS 814 pI740->FbBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 815 pI740->PciTag, 816 pI740->LinearAddr, 817 pI740->FbMapSize); 818#else 819 { 820 void** result = (void**)&pI740->FbBase; 821 int err = pci_device_map_range(pI740->PciInfo, 822 pI740->LinearAddr, 823 pI740->FbMapSize, 824 PCI_DEV_MAP_FLAG_WRITABLE | 825 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 826 result); 827 828 if (err) 829 return FALSE; 830 } 831#endif 832 if (!pI740->FbBase) return FALSE; 833 834 return TRUE; 835} 836 837static Bool I740UnmapMem(ScrnInfoPtr pScrn) 838{ 839 I740Ptr pI740; 840 841 pI740 = I740PTR(pScrn); 842 843#ifndef XSERVER_LIBPCIACCESS 844 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pI740->MMIOBase, 0x80000); 845#else 846 pci_device_unmap_range(pI740->PciInfo, pI740->MMIOBase, 0x80000); 847#endif 848 pI740->MMIOBase=0; 849 850#ifndef XSERVER_LIBPCIACCESS 851 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pI740->FbBase, pI740->FbMapSize); 852#else 853 pci_device_unmap_range(pI740->PciInfo, pI740->FbBase, pI740->FbMapSize); 854#endif 855 pI740->FbBase = 0; 856 return TRUE; 857} 858 859/* 860 * I740Save -- 861 * 862 * This function saves the video state. It reads all of the SVGA registers 863 * into the vgaI740Rec data structure. There is in general no need to 864 * mask out bits here - just read the registers. 865 */ 866static void 867DoSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I740RegPtr i740Reg, Bool saveFonts) 868{ 869 I740Ptr pI740; 870 vgaHWPtr hwp; 871 872 pI740 = I740PTR(pScrn); 873 hwp = VGAHWPTR(pScrn); 874 875 /* 876 * This function will handle creating the data structure and filling 877 * in the generic VGA portion. 878 */ 879 if (saveFonts) 880 vgaHWSave(pScrn, vgaReg, VGA_SR_MODE|VGA_SR_FONTS); 881 else 882 vgaHWSave(pScrn, vgaReg, VGA_SR_MODE); 883 884 /* 885 * The port I/O code necessary to read in the extended registers 886 * into the fields of the vgaI740Rec structure goes here. 887 */ 888 889 i740Reg->IOControl = pI740->readControl(pI740, XRX, IO_CTNL); 890 i740Reg->AddressMapping = pI740->readControl(pI740, XRX, ADDRESS_MAPPING); 891 i740Reg->BitBLTControl = pI740->readControl(pI740, XRX, BITBLT_CNTL); 892 i740Reg->VideoClk2_M = pI740->readControl(pI740, XRX, VCLK2_VCO_M); 893 i740Reg->VideoClk2_N = pI740->readControl(pI740, XRX, VCLK2_VCO_N); 894 i740Reg->VideoClk2_MN_MSBs = pI740->readControl(pI740, XRX, VCLK2_VCO_MN_MSBS); 895 i740Reg->VideoClk2_DivisorSel = pI740->readControl(pI740, XRX, VCLK2_VCO_DIV_SEL); 896 i740Reg->PLLControl = pI740->readControl(pI740, XRX, PLL_CNTL); 897 898 i740Reg->ExtVertTotal=hwp->readCrtc(hwp, EXT_VERT_TOTAL); 899 i740Reg->ExtVertDispEnd=hwp->readCrtc(hwp, EXT_VERT_DISPLAY); 900 i740Reg->ExtVertSyncStart=hwp->readCrtc(hwp, EXT_VERT_SYNC_START); 901 i740Reg->ExtVertBlankStart=hwp->readCrtc(hwp, EXT_VERT_BLANK_START); 902 i740Reg->ExtHorizTotal=hwp->readCrtc(hwp, EXT_HORIZ_TOTAL); 903 i740Reg->ExtHorizBlank=hwp->readCrtc(hwp, EXT_HORIZ_BLANK); 904 i740Reg->ExtOffset=hwp->readCrtc(hwp, EXT_OFFSET); 905 i740Reg->InterlaceControl=hwp->readCrtc(hwp, INTERLACE_CNTL); 906 907 i740Reg->PixelPipeCfg0 = pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_0); 908 i740Reg->PixelPipeCfg1 = pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_1); 909 i740Reg->PixelPipeCfg2 = pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_2); 910 i740Reg->DisplayControl = pI740->readControl(pI740, XRX, DISPLAY_CNTL); 911 912 i740Reg->LMI_FIFO_Watermark = INREG(FWATER_BLC); 913} 914 915static void 916I740Save(ScrnInfoPtr pScrn) 917{ 918 vgaHWPtr hwp; 919 I740Ptr pI740; 920 921 hwp = VGAHWPTR(pScrn); 922 pI740 = I740PTR(pScrn); 923 DoSave(pScrn, &hwp->SavedReg, &pI740->SavedReg, TRUE); 924} 925 926static void 927DoRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I740RegPtr i740Reg, 928 Bool restoreFonts) { 929 I740Ptr pI740; 930 vgaHWPtr hwp; 931 unsigned char temp; 932 unsigned int itemp; 933 934 pI740 = I740PTR(pScrn); 935 hwp = VGAHWPTR(pScrn); 936 937 vgaHWProtect(pScrn, TRUE); 938#if 0 939 temp=hwp->readCrtc(hwp, VERT_SYNC_END); 940 hwp->writeCrtc(hwp, VERT_SYNC_END, temp&0x7F); 941#endif 942 943 temp = pI740->readControl(pI740, MRX, ACQ_CNTL_2); 944 if ((temp & FRAME_CAP_MODE) == SINGLE_CAP_MODE) { 945 temp=pI740->readControl(pI740, MRX, COL_KEY_CNTL_1); 946 temp |= BLANK_DISP_OVERLAY; /* Disable the overlay */ 947 pI740->writeControl(pI740, MRX, COL_KEY_CNTL_1, temp); 948 } else { 949 temp &= ~FRAME_CAP_MODE; 950 pI740->writeControl(pI740, MRX, ACQ_CNTL_2, temp); 951 } 952 usleep(50000); 953 954 /* Turn off DRAM Refresh */ 955 pI740->writeControl(pI740, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_DISABLE); 956 957 usleep(1000); /* Wait 1 ms */ 958 959 /* Write the M, N and P values */ 960 pI740->writeControl(pI740, XRX, VCLK2_VCO_M, i740Reg->VideoClk2_M); 961 pI740->writeControl(pI740, XRX, VCLK2_VCO_N, i740Reg->VideoClk2_N); 962 pI740->writeControl(pI740, XRX, VCLK2_VCO_MN_MSBS, i740Reg->VideoClk2_MN_MSBs); 963 pI740->writeControl(pI740, XRX, VCLK2_VCO_DIV_SEL, i740Reg->VideoClk2_DivisorSel); 964 965 /* 966 * Turn on 8 bit dac mode, if requested. This is needed to make 967 * sure that vgaHWRestore writes the values into the DAC properly. 968 * The problem occurs if 8 bit dac mode is requested and the HW is 969 * in 6 bit dac mode. If this happens, all the values are 970 * automatically shifted left twice by the HW and incorrect colors 971 * will be displayed on the screen. The only time this can happen 972 * is at server startup time and when switching back from a VT. 973 */ 974 temp=pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_0); 975 temp &= 0x7F; /* Save all but the 8 bit dac mode bit */ 976 temp |= (i740Reg->PixelPipeCfg0 & DAC_8_BIT); 977 pI740->writeControl(pI740, XRX, PIXPIPE_CONFIG_0, temp); 978 979 /* 980 * Code to restore any SVGA registers that have been saved/modified 981 * goes here. Note that it is allowable, and often correct, to 982 * only modify certain bits in a register by a read/modify/write cycle. 983 * 984 * A special case - when using an external clock-setting program, 985 * this function must not change bits associated with the clock 986 * selection. This condition can be checked by the condition: 987 * 988 * if (restore->std.NoClock >= 0) 989 * restore clock-select bits. 990 */ 991 if (restoreFonts) 992 vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS|VGA_SR_MODE); 993 else 994 vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE); 995 996 hwp->writeCrtc(hwp, EXT_VERT_TOTAL, i740Reg->ExtVertTotal); 997 hwp->writeCrtc(hwp, EXT_VERT_DISPLAY, i740Reg->ExtVertDispEnd); 998 hwp->writeCrtc(hwp, EXT_VERT_SYNC_START, i740Reg->ExtVertSyncStart); 999 hwp->writeCrtc(hwp, EXT_VERT_BLANK_START, i740Reg->ExtVertBlankStart); 1000 hwp->writeCrtc(hwp, EXT_HORIZ_TOTAL, i740Reg->ExtHorizTotal); 1001 hwp->writeCrtc(hwp, EXT_HORIZ_BLANK, i740Reg->ExtHorizBlank); 1002 hwp->writeCrtc(hwp, EXT_OFFSET, i740Reg->ExtOffset); 1003 1004 temp=hwp->readCrtc(hwp, INTERLACE_CNTL); 1005 temp &= ~INTERLACE_ENABLE; 1006 temp |= i740Reg->InterlaceControl; 1007 hwp->writeCrtc(hwp, INTERLACE_CNTL, temp); 1008 1009 temp=pI740->readControl(pI740, XRX, ADDRESS_MAPPING); 1010 temp &= 0xE0; /* Save reserved bits 7:5 */ 1011 temp |= i740Reg->AddressMapping; 1012 pI740->writeControl(pI740, XRX, ADDRESS_MAPPING, temp); 1013 1014 temp=pI740->readControl(pI740, XRX, BITBLT_CNTL); 1015 temp &= ~COLEXP_MODE; 1016 temp |= i740Reg->BitBLTControl; 1017 pI740->writeControl(pI740, XRX, BITBLT_CNTL, temp); 1018 1019 temp=pI740->readControl(pI740, XRX, DISPLAY_CNTL); 1020 temp &= ~(VGA_WRAP_MODE | GUI_MODE); 1021 temp |= i740Reg->DisplayControl; 1022 pI740->writeControl(pI740, XRX, DISPLAY_CNTL, temp); 1023 1024 temp=pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_0); 1025 temp &= 0x64; /* Save reserved bits 6:5,2 */ 1026 temp |= i740Reg->PixelPipeCfg0; 1027 pI740->writeControl(pI740, XRX, PIXPIPE_CONFIG_0, temp); 1028 1029 temp=pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_2); 1030 temp &= 0xF3; /* Save reserved bits 7:4,1:0 */ 1031 temp |= i740Reg->PixelPipeCfg2; 1032 pI740->writeControl(pI740, XRX, PIXPIPE_CONFIG_2, temp); 1033 1034 temp=pI740->readControl(pI740, XRX, PLL_CNTL); 1035 temp = i740Reg->PLLControl; /* To fix the 2.3X BIOS problem */ 1036 pI740->writeControl(pI740, XRX, PLL_CNTL, temp); 1037 1038 temp=pI740->readControl(pI740, XRX, PIXPIPE_CONFIG_1); 1039 temp &= ~DISPLAY_COLOR_MODE; 1040 temp |= i740Reg->PixelPipeCfg1; 1041 pI740->writeControl(pI740, XRX, PIXPIPE_CONFIG_1, temp); 1042 1043 itemp = INREG(FWATER_BLC); 1044 itemp &= ~(LMI_BURST_LENGTH | LMI_FIFO_WATERMARK); 1045 itemp |= i740Reg->LMI_FIFO_Watermark; 1046 OUTREG(FWATER_BLC, itemp); 1047 1048 /* Turn on DRAM Refresh */ 1049 pI740->writeControl(pI740, XRX, DRAM_EXT_CNTL, DRAM_REFRESH_60HZ); 1050 1051 temp=pI740->readControl(pI740, MRX, COL_KEY_CNTL_1); 1052 temp &= ~BLANK_DISP_OVERLAY; /* Re-enable the overlay */ 1053 pI740->writeControl(pI740, MRX, COL_KEY_CNTL_1, temp); 1054 1055 if (!(vgaReg->Attribute[0x10] & 0x1)) { 1056 usleep(50000); 1057 if (restoreFonts) 1058 vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS|VGA_SR_MODE); 1059 else 1060 vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE); 1061 } 1062 1063 vgaHWProtect(pScrn, FALSE); 1064 temp=pI740->readControl(pI740, XRX, IO_CTNL); 1065 temp &= ~(EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL); 1066 temp |= i740Reg->IOControl; 1067 pI740->writeControl(pI740, XRX, IO_CTNL, temp); 1068#if 0 1069 temp=hwp->readCrtc(hwp, VERT_SYNC_END); 1070 hwp->writeCrtc(hwp, VERT_SYNC_END, temp|0x80); 1071#endif 1072} 1073 1074static void 1075I740Restore(ScrnInfoPtr pScrn) { 1076 vgaHWPtr hwp; 1077 I740Ptr pI740; 1078 1079 hwp = VGAHWPTR(pScrn); 1080 pI740 = I740PTR(pScrn); 1081 1082 DoRestore(pScrn, &hwp->SavedReg, &pI740->SavedReg, TRUE); 1083} 1084 1085/* 1086 * I740CalcFIFO -- 1087 * 1088 * Calculate burst length and FIFO watermark. 1089 */ 1090 1091static unsigned int 1092I740CalcFIFO(ScrnInfoPtr pScrn, double freq) 1093{ 1094 unsigned int wm = 0x18120000; 1095 I740Ptr pI740; 1096 1097 pI740 = I740PTR(pScrn); 1098 1099 /* 1100 * Would like to calculate these values automatically, but a generic 1101 * algorithm does not seem possible. Note: These FIFO water mark 1102 * values were tested on several cards and seem to eliminate the 1103 * all of the snow and vertical banding, but fine adjustments will 1104 * probably be required for other cards. 1105 */ 1106 1107 switch (pScrn->bitsPerPixel) { 1108 case 8: 1109 if (pI740->HasSGRAM) { 1110 if (freq > 200) wm = 0x18120000; 1111 else if (freq > 175) wm = 0x16110000; 1112 else if (freq > 135) wm = 0x120E0000; 1113 else wm = 0x100D0000; 1114 } else { 1115 if (freq > 200) wm = 0x18120000; 1116 else if (freq > 175) wm = 0x16110000; 1117 else if (freq > 135) wm = 0x120E0000; 1118 else wm = 0x100D0000; 1119 } 1120 break; 1121 case 16: 1122 if (pI740->HasSGRAM) { 1123 if (freq > 140) wm = 0x2C1D0000; 1124 else if (freq > 120) wm = 0x2C180000; 1125 else if (freq > 100) wm = 0x24160000; 1126 else if (freq > 90) wm = 0x18120000; 1127 else if (freq > 50) wm = 0x16110000; 1128 else if (freq > 32) wm = 0x13100000; 1129 else wm = 0x120E0000; 1130 } else { 1131 if (freq > 160) wm = 0x28200000; 1132 else if (freq > 140) wm = 0x2A1E0000; 1133 else if (freq > 130) wm = 0x2B1A0000; 1134 else if (freq > 120) wm = 0x2C180000; 1135 else if (freq > 100) wm = 0x24180000; 1136 else if (freq > 90) wm = 0x18120000; 1137 else if (freq > 50) wm = 0x16110000; 1138 else if (freq > 32) wm = 0x13100000; 1139 else wm = 0x120E0000; 1140 } 1141 break; 1142 case 24: 1143 if (pI740->HasSGRAM) { 1144 if (freq > 130) wm = 0x31200000; 1145 else if (freq > 120) wm = 0x2E200000; 1146 else if (freq > 100) wm = 0x2C1D0000; 1147 else if (freq > 80) wm = 0x25180000; 1148 else if (freq > 64) wm = 0x24160000; 1149 else if (freq > 49) wm = 0x18120000; 1150 else if (freq > 32) wm = 0x16110000; 1151 else wm = 0x13100000; 1152 } else { 1153 if (freq > 120) wm = 0x311F0000; 1154 else if (freq > 100) wm = 0x2C1D0000; 1155 else if (freq > 80) wm = 0x25180000; 1156 else if (freq > 64) wm = 0x24160000; 1157 else if (freq > 49) wm = 0x18120000; 1158 else if (freq > 32) wm = 0x16110000; 1159 else wm = 0x13100000; 1160 } 1161 break; 1162 case 32: 1163 if (pI740->HasSGRAM) { 1164 if (freq > 80) wm = 0x2A200000; 1165 else if (freq > 60) wm = 0x281A0000; 1166 else if (freq > 49) wm = 0x25180000; 1167 else if (freq > 32) wm = 0x18120000; 1168 else wm = 0x16110000; 1169 } else { 1170 if (freq > 80) wm = 0x29200000; 1171 else if (freq > 60) wm = 0x281A0000; 1172 else if (freq > 49) wm = 0x25180000; 1173 else if (freq > 32) wm = 0x18120000; 1174 else wm = 0x16110000; 1175 } 1176 break; 1177 } 1178 1179 return wm; 1180} 1181 1182/* 1183 * I740CalcVCLK -- 1184 * 1185 * Determine the closest clock frequency to the one requested. 1186 */ 1187 1188#define MAX_VCO_FREQ 450.0 1189#define TARGET_MAX_N 30 1190#define REF_FREQ 66.66666666667 1191 1192#define CALC_VCLK(m,n,p,d) \ 1193 (double)m / ((double)n * (1 << p)) * (4 << (d << 1)) * REF_FREQ 1194 1195static void 1196I740CalcVCLK(ScrnInfoPtr pScrn, double freq) 1197{ 1198 I740Ptr pI740; 1199 I740RegPtr i740Reg; 1200 int m, n, p, d; 1201 double f_out; 1202 double f_err; 1203 double f_vco; 1204 int m_best = 0, n_best = 0, p_best = 0, d_best = 0; 1205 double f_target = freq; 1206 double err_max = 0.005; 1207 double err_target = 0.001; 1208 double err_best = 999999.0; 1209 1210 pI740 = I740PTR(pScrn); 1211 i740Reg = &pI740->ModeReg; 1212 1213 p_best = p = log(MAX_VCO_FREQ/f_target)/log((double)2); 1214 d_best = d = 0; 1215 1216 f_vco = f_target * (1 << p); 1217 1218 n = 2; 1219 do { 1220 n++; 1221 m = f_vco / (REF_FREQ / (double)n) / (double)4.0 + 0.5; 1222 if (m < 3) m = 3; 1223 f_out = CALC_VCLK(m,n,p,d); 1224 f_err = 1.0 - (f_target/f_out); 1225 if (fabs(f_err) < err_max) { 1226 m_best = m; 1227 n_best = n; 1228 err_best = f_err; 1229 } 1230 } while ((fabs(f_err) >= err_target) && 1231 ((n <= TARGET_MAX_N) || (fabs(err_best) > err_max))); 1232 1233 if (fabs(f_err) < err_target) { 1234 m_best = m; 1235 n_best = n; 1236 } 1237 1238 i740Reg->VideoClk2_M = (m_best-2) & 0xFF; 1239 i740Reg->VideoClk2_N = (n_best-2) & 0xFF; 1240 i740Reg->VideoClk2_MN_MSBs = ((((n_best-2) >> 4) & VCO_N_MSBS) | 1241 (((m_best-2) >> 8) & VCO_M_MSBS)); 1242 i740Reg->VideoClk2_DivisorSel = ((p_best << 4) | 1243 (d_best ? 4 : 0) | 1244 REF_DIV_1); 1245} 1246 1247static Bool 1248I740SetMode(ScrnInfoPtr pScrn, DisplayModePtr mode) { 1249 I740Ptr pI740; 1250 I740RegPtr i740Reg; 1251 vgaRegPtr pVga; 1252 double dclk = mode->Clock/1000.0; 1253 1254 pI740 = I740PTR(pScrn); 1255 i740Reg = &pI740->ModeReg; 1256 pVga = &VGAHWPTR(pScrn)->ModeReg; 1257 1258 switch (pScrn->bitsPerPixel) { 1259 case 8: 1260 pVga->CRTC[0x13] = pScrn->displayWidth >> 3; 1261 i740Reg->ExtOffset = pScrn->displayWidth >> 11; 1262 i740Reg->PixelPipeCfg1 = DISPLAY_8BPP_MODE; 1263 i740Reg->BitBLTControl = COLEXP_8BPP; 1264 break; 1265 case 16: 1266 if (pScrn->weight.green == 5) { 1267 i740Reg->PixelPipeCfg1 = DISPLAY_15BPP_MODE; 1268 } else { 1269 i740Reg->PixelPipeCfg1 = DISPLAY_16BPP_MODE; 1270 } 1271 pVga->CRTC[0x13] = pScrn->displayWidth >> 2; 1272 i740Reg->ExtOffset = pScrn->displayWidth >> 10; 1273 i740Reg->BitBLTControl = COLEXP_16BPP; 1274 break; 1275 case 24: 1276 pVga->CRTC[0x13] = (pScrn->displayWidth * 3) >> 3; 1277 i740Reg->ExtOffset = (pScrn->displayWidth * 3) >> 11; 1278 i740Reg->PixelPipeCfg1 = DISPLAY_24BPP_MODE; 1279 i740Reg->BitBLTControl = COLEXP_24BPP; 1280 break; 1281 case 32: 1282 pVga->CRTC[0x13] = pScrn->displayWidth >> 1; 1283 i740Reg->ExtOffset = pScrn->displayWidth >> 9; 1284 i740Reg->PixelPipeCfg1 = DISPLAY_32BPP_MODE; 1285 i740Reg->BitBLTControl = COLEXP_RESERVED; /* Not implemented on i740 */ 1286 break; 1287 default: 1288 break; 1289 } 1290 1291 /* Turn on 8 bit dac if requested */ 1292 if (xf86ReturnOptValBool(pI740->Options, OPTION_DAC_6BIT, FALSE)) 1293 i740Reg->PixelPipeCfg0 = DAC_6_BIT; 1294 else 1295 i740Reg->PixelPipeCfg0 = DAC_8_BIT; 1296 1297 i740Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE /*| OVERLAY_GAMMA_ENABLE*/; 1298 1299 /* Turn on Extended VGA Interpretation */ 1300 i740Reg->IOControl = EXTENDED_CRTC_CNTL; 1301 1302 /* Turn on linear and page mapping */ 1303 i740Reg->AddressMapping = LINEAR_MODE_ENABLE | PAGE_MAPPING_ENABLE; 1304 1305 /* Turn on GUI mode */ 1306 i740Reg->DisplayControl = HIRES_MODE; 1307 1308 /* Set the MCLK freq */ 1309 if (xf86ReturnOptValBool(pI740->Options, OPTION_SLOW_RAM, FALSE)) 1310 i740Reg->PLLControl = PLL_MEMCLK__66667KHZ; /* 66 MHz */ 1311 else 1312 i740Reg->PLLControl = PLL_MEMCLK_100000KHZ; /* 100 MHz -- use as default */ 1313 1314 /* Calculate the extended CRTC regs */ 1315 i740Reg->ExtVertTotal = (mode->CrtcVTotal - 2) >> 8; 1316 i740Reg->ExtVertDispEnd = (mode->CrtcVDisplay - 1) >> 8; 1317 i740Reg->ExtVertSyncStart = mode->CrtcVSyncStart >> 8; 1318 i740Reg->ExtVertBlankStart = mode->CrtcVBlankStart >> 8; 1319 i740Reg->ExtHorizTotal = ((mode->CrtcHTotal >> 3) - 5) >> 8; 1320 /* 1321 * the KGA fix in vgaHW.c results in the first 1322 * scanline and the first character clock (8 pixels) 1323 * of each scanline thereafter on display with an i740 1324 * to be blank. Restoring CRTC 3, 5, & 22 to their 1325 * "theoretical" values corrects the problem. KAO. 1326 */ 1327 i740Reg->ExtHorizBlank = vgaHWHBlankKGA(mode, pVga, 7, 0) << 6; 1328 vgaHWVBlankKGA(mode, pVga, 8, 0); 1329 1330 /* Turn on interlaced mode if necessary */ 1331 if (mode->Flags & V_INTERLACE) 1332 i740Reg->InterlaceControl = INTERLACE_ENABLE; 1333 else 1334 i740Reg->InterlaceControl = INTERLACE_DISABLE; 1335 1336 /* 1337 * Set the overscan color to 0. 1338 * NOTE: This only affects >8bpp mode. 1339 */ 1340 pVga->Attribute[0x11] = 0; 1341 1342 /* 1343 * Calculate the VCLK that most closely matches the requested dot 1344 * clock. 1345 */ 1346 I740CalcVCLK(pScrn, dclk); 1347 1348 /* Since we program the clocks ourselves, always use VCLK2. */ 1349 pVga->MiscOutReg |= 0x0C; 1350 1351 /* Calculate the FIFO Watermark and Burst Length. */ 1352 i740Reg->LMI_FIFO_Watermark = I740CalcFIFO(pScrn, dclk); 1353 1354 /*-Overlay-*/ 1355 pI740->ov_offset_x=((mode->CrtcHTotal-mode->CrtcHDisplay) & ~7)-9; 1356 pI740->ov_offset_y=mode->CrtcVTotal-mode->CrtcVSyncEnd-2; 1357 /*-*/ 1358 1359 return TRUE; 1360} 1361 1362static Bool 1363I740ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode_src) 1364{ 1365 vgaHWPtr hwp; 1366 I740Ptr pI740; 1367 struct _DisplayModeRec mode_dst; 1368 DisplayModePtr mode=&mode_dst; 1369 1370 *mode=*mode_src; 1371 1372 hwp = VGAHWPTR(pScrn); 1373 pI740 = I740PTR(pScrn); 1374 1375 vgaHWUnlock(hwp); 1376 1377 1378 if(pI740->usevgacompat) 1379 { /* Try to get the same visual aspect as a S3 board */ 1380 mode->CrtcHSyncStart+=16; 1381 mode->CrtcHSyncEnd +=16; 1382 } 1383 1384 if (!vgaHWInit(pScrn, mode)) return FALSE; 1385 1386 pScrn->vtSema = TRUE; 1387 1388 if (!I740SetMode(pScrn, mode)) return FALSE; 1389 1390 DoRestore(pScrn, &hwp->ModeReg, &pI740->ModeReg, FALSE); 1391 1392 return TRUE; 1393} 1394 1395static void I740LoadPalette15(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual) 1396{ 1397 vgaHWPtr hwp; 1398 int i, index; 1399 unsigned char r, g, b; 1400 1401 hwp = VGAHWPTR(pScrn); 1402 1403 for (i=0; i<numColors; i++) 1404 { 1405 index=indices[i/2]; 1406 r=colors[index].red; 1407 b=colors[index].blue; 1408 g=colors[index].green; 1409 1410 hwp->writeDacWriteAddr(hwp, index<<2); 1411 hwp->writeDacData(hwp, r); 1412 hwp->writeDacData(hwp, g); 1413 hwp->writeDacData(hwp, b); 1414 1415 i++; 1416 hwp->writeDacWriteAddr(hwp, index<<2); 1417 hwp->writeDacData(hwp, r); 1418 hwp->writeDacData(hwp, g); 1419 hwp->writeDacData(hwp, b); 1420 } 1421} 1422 1423static void I740LoadPalette16(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual) 1424{ 1425 vgaHWPtr hwp; 1426 int i, index; 1427 unsigned char r, g, b; 1428 1429 hwp = VGAHWPTR(pScrn); 1430 for (i=0; i<numColors; i++) { 1431 index=indices[i/2]; 1432 r=colors[index].red; 1433 b=colors[index].blue; 1434 index=indices[i]; 1435 g=colors[index].green; 1436 hwp->writeDacWriteAddr(hwp, index<<2); 1437 hwp->writeDacData(hwp, r); 1438 hwp->writeDacData(hwp, g); 1439 hwp->writeDacData(hwp, b); 1440 i++; 1441 index=indices[i]; 1442 g=colors[index].green; 1443 hwp->writeDacWriteAddr(hwp, index<<2); 1444 hwp->writeDacData(hwp, r); 1445 hwp->writeDacData(hwp, g); 1446 hwp->writeDacData(hwp, b); 1447 } 1448} 1449 1450static void 1451I740LoadPalette24(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, 1452 VisualPtr pVisual) { 1453 vgaHWPtr hwp; 1454 int i, index; 1455 unsigned char r, g, b; 1456 1457 hwp = VGAHWPTR(pScrn); 1458 for (i=0; i<numColors; i++) { 1459 index=indices[i]; 1460 r=colors[index].red; 1461 b=colors[index].blue; 1462 index=indices[i]; 1463 g=colors[index].green; 1464 hwp->writeDacWriteAddr(hwp, index); 1465 hwp->writeDacData(hwp, r); 1466 hwp->writeDacData(hwp, g); 1467 hwp->writeDacData(hwp, b); 1468 } 1469} 1470 1471static Bool 1472I740ScreenInit(SCREEN_INIT_ARGS_DECL) { 1473 ScrnInfoPtr pScrn; 1474 vgaHWPtr hwp; 1475 I740Ptr pI740; 1476 VisualPtr visual; 1477 1478 pScrn = xf86ScreenToScrn(pScreen); 1479 pI740 = I740PTR(pScrn); 1480 hwp = VGAHWPTR(pScrn); 1481 1482 if (!I740MapMem(pScrn)) return FALSE; 1483 pScrn->memPhysBase = pI740->LinearAddr; 1484 pScrn->fbOffset = 0; 1485 1486 if (!pI740->usePIO) 1487 vgaHWSetMmioFuncs(hwp, pI740->MMIOBase, 0); 1488 vgaHWGetIOBase(hwp); 1489 if (!vgaHWMapMem(pScrn)) return FALSE; 1490 1491 I740Save(pScrn); 1492 if (!I740ModeInit(pScrn, pScrn->currentMode)) return FALSE; 1493 1494 I740SaveScreen(pScreen, SCREEN_SAVER_ON); 1495 I740AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 1496 1497 miClearVisualTypes(); 1498 1499 if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth), 1500 pScrn->rgbBits, pScrn->defaultVisual)) 1501 return FALSE; 1502 if (!miSetPixmapDepths ()) return FALSE; 1503 1504 switch (pScrn->bitsPerPixel) { 1505 case 8: 1506 case 16: 1507 case 24: 1508 case 32: 1509 if (!fbScreenInit(pScreen, pI740->FbBase, 1510 pScrn->virtualX, pScrn->virtualY, 1511 pScrn->xDpi, pScrn->yDpi, 1512 pScrn->displayWidth,pScrn->bitsPerPixel)) 1513 return FALSE; 1514 break; 1515 default: 1516 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1517 "Internal error: invalid bpp (%d) in I740ScrnInit\n", 1518 pScrn->bitsPerPixel); 1519 return FALSE; 1520 } 1521 fbPictureInit(pScreen,0,0); 1522 1523 xf86SetBlackWhitePixels(pScreen); 1524 1525 memset(&(pI740->FbMemBox), 0, sizeof(BoxRec)); 1526 pI740->FbMemBox.x1=0; 1527 pI740->FbMemBox.x2=pScrn->displayWidth; 1528 pI740->FbMemBox.y1=0; 1529 pI740->FbMemBox.y2=pI740->FbMapSize/(pScrn->displayWidth*pI740->cpp); 1530 1531 I740DGAInit(pScreen); 1532 1533 if (!xf86InitFBManager(pScreen, &pI740->FbMemBox)) { 1534 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to init memory manager\n"); 1535 return FALSE; 1536 } 1537 1538 if (!pI740->NoAccel) { 1539 if (!I740AccelInit(pScreen)) { 1540 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1541 "Hardware acceleration initialization failed\n"); 1542 } 1543 } 1544 1545 if (pScrn->bitsPerPixel>8) { 1546 visual = pScreen->visuals + pScreen->numVisuals; 1547 while (--visual >= pScreen->visuals) { 1548 if ((visual->class | DynamicClass) == DirectColor) { 1549 visual->offsetRed = pScrn->offset.red; 1550 visual->offsetGreen = pScrn->offset.green; 1551 visual->offsetBlue = pScrn->offset.blue; 1552 visual->redMask = pScrn->mask.red; 1553 visual->greenMask = pScrn->mask.green; 1554 visual->blueMask = pScrn->mask.blue; 1555 } 1556 } 1557 } 1558 1559 xf86SetBackingStore(pScreen); 1560 xf86SetSilkenMouse(pScreen); 1561 1562 miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); 1563 1564 if (!xf86ReturnOptValBool(pI740->Options, OPTION_SW_CURSOR, FALSE)) { 1565 if (!I740CursorInit(pScreen)) { 1566 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1567 "Hardware cursor initialization failed\n"); 1568 } 1569 } 1570 1571 if (!miCreateDefColormap(pScreen)) return FALSE; 1572 1573 if (pScrn->bitsPerPixel==16) 1574 { 1575 if (pScrn->weight.green == 5) 1576 { 1577 if (!xf86HandleColormaps(pScreen, 256, 8, I740LoadPalette15, 0, CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH)) 1578 return FALSE; 1579 } 1580 else 1581 { 1582 if (!xf86HandleColormaps(pScreen, 256, 8, I740LoadPalette16, 0, CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH)) 1583 return FALSE; 1584 } 1585 } 1586 else 1587 { 1588 if (!xf86HandleColormaps(pScreen, 256, 8, I740LoadPalette24, 0, CMAP_PALETTED_TRUECOLOR|CMAP_RELOAD_ON_MODE_SWITCH)) 1589 return FALSE; 1590 } 1591 1592 xf86DPMSInit(pScreen, I740DisplayPowerManagementSet, 0); 1593 1594 pScreen->SaveScreen = I740SaveScreen; 1595 pI740->CloseScreen = pScreen->CloseScreen; 1596 pScreen->CloseScreen = I740CloseScreen; 1597 1598 if (serverGeneration == 1) 1599 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1600 1601 /* Overlay */ 1602 I740InitVideo(pScreen); pI740->OverlayStart = pI740->CursorStart + 1024; 1603 1604 return TRUE; 1605} 1606 1607Bool 1608I740SwitchMode(SWITCH_MODE_ARGS_DECL) { 1609 SCRN_INFO_PTR(arg); 1610 return I740ModeInit(pScrn, mode); 1611} 1612 1613void 1614I740AdjustFrame(ADJUST_FRAME_ARGS_DECL) { 1615 SCRN_INFO_PTR(arg); 1616 int Base; 1617 vgaHWPtr hwp; 1618 1619 hwp = VGAHWPTR(pScrn); 1620 1621 Base = (y * pScrn->displayWidth + x) >> 2; 1622 switch (pScrn->bitsPerPixel) { 1623 case 8: 1624 break; 1625 case 16: 1626 Base *= 2; 1627 break; 1628 case 24: 1629 /* 1630 * The last bit does not seem to have any effect on the start 1631 * address register in 24bpp mode, so... 1632 */ 1633 Base &= 0xFFFFFFFE; /* ...ignore the last bit. */ 1634 Base *= 3; 1635 break; 1636 case 32: 1637 Base *= 4; 1638 break; 1639 } 1640 1641 hwp->writeCrtc(hwp, START_ADDR_LO, Base&0xFF); 1642 hwp->writeCrtc(hwp, START_ADDR_HI, (Base&0xFF00)>>8); 1643 hwp->writeCrtc(hwp, EXT_START_ADDR_HI, (Base&0x3FC00000)>>22); 1644 hwp->writeCrtc(hwp, EXT_START_ADDR, 1645 ((Base&0x00eF0000)>>16|EXT_START_ADDR_ENABLE)); 1646} 1647 1648static Bool 1649I740EnterVT(VT_FUNC_ARGS_DECL) { 1650 SCRN_INFO_PTR(arg); 1651 1652 if (!I740ModeInit(pScrn, pScrn->currentMode)) return FALSE; 1653 I740AdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 1654 return TRUE; 1655} 1656 1657static void 1658I740LeaveVT(VT_FUNC_ARGS_DECL) { 1659 SCRN_INFO_PTR(arg); 1660 vgaHWPtr hwp; 1661 1662 hwp=VGAHWPTR(pScrn); 1663 I740Restore(pScrn); 1664 vgaHWLock(hwp); 1665} 1666 1667static Bool 1668I740CloseScreen(CLOSE_SCREEN_ARGS_DECL) 1669{ 1670 ScrnInfoPtr pScrn; 1671 vgaHWPtr hwp; 1672 I740Ptr pI740; 1673 1674 pScrn = xf86ScreenToScrn(pScreen); 1675 hwp = VGAHWPTR(pScrn); 1676 pI740 = I740PTR(pScrn); 1677 1678 if (pScrn->vtSema) { 1679 I740Restore(pScrn); 1680 vgaHWLock(hwp); 1681 } 1682 1683 I740UnmapMem(pScrn); 1684 vgaHWUnmapMem(pScrn); 1685#ifdef HAVE_XAA_H 1686 if (pI740->AccelInfoRec) 1687 XAADestroyInfoRec(pI740->AccelInfoRec); 1688 pI740->AccelInfoRec=0; 1689#endif 1690 if (pI740->CursorInfoRec) 1691 xf86DestroyCursorInfoRec(pI740->CursorInfoRec); 1692 pI740->CursorInfoRec=0; 1693 pScrn->vtSema=FALSE; 1694 1695 pScreen->CloseScreen = pI740->CloseScreen; 1696 return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 1697} 1698 1699static void 1700I740FreeScreen(FREE_SCREEN_ARGS_DECL) { 1701 SCRN_INFO_PTR(arg); 1702 I740FreeRec(pScrn); 1703 if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) 1704 vgaHWFreeHWRec(pScrn); 1705} 1706 1707static ModeStatus 1708I740ValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) { 1709 SCRN_INFO_PTR(arg); 1710 if (mode->Flags & V_INTERLACE) { 1711 if (verbose) { 1712 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1713 "Removing interlaced mode \"%s\"\n", 1714 mode->name); 1715 } 1716 return MODE_BAD; 1717 } 1718 return MODE_OK; 1719} 1720 1721static Bool 1722I740SaveScreen(ScreenPtr pScreen, int mode) 1723{ 1724#if 0 1725 Bool unblack = xf86IsUnblank(mode); 1726 if (unblack) outw(SRX, 0x0300); 1727 else outw(SRX, 0x0100); 1728#endif 1729 return vgaHWSaveScreen(pScreen, mode); 1730} 1731 1732static void 1733I740DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, 1734 int flags) { 1735 I740Ptr pI740; 1736 unsigned char SEQ01=0; 1737 int DPMSSyncSelect=0; 1738 1739 pI740 = I740PTR(pScrn); 1740 switch (PowerManagementMode) { 1741 case DPMSModeOn: 1742 /* Screen: On; HSync: On, VSync: On */ 1743 SEQ01 = 0x00; 1744 DPMSSyncSelect = HSYNC_ON | VSYNC_ON; 1745 break; 1746 case DPMSModeStandby: 1747 /* Screen: Off; HSync: Off, VSync: On */ 1748 SEQ01 = 0x20; 1749 DPMSSyncSelect = HSYNC_OFF | VSYNC_ON; 1750 break; 1751 case DPMSModeSuspend: 1752 /* Screen: Off; HSync: On, VSync: Off */ 1753 SEQ01 = 0x20; 1754 DPMSSyncSelect = HSYNC_ON | VSYNC_OFF; 1755 break; 1756 case DPMSModeOff: 1757 /* Screen: Off; HSync: Off, VSync: Off */ 1758 SEQ01 = 0x20; 1759 DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF; 1760 break; 1761 } 1762 1763 /* Turn the screen on/off */ 1764 SEQ01 |= pI740->readControl(pI740, SRX, 0x01) & ~0x20; 1765 pI740->writeControl(pI740, SRX, 0x01, SEQ01); 1766 1767 /* Set the DPMS mode */ 1768 pI740->writeControl(pI740, XRX, DPMS_SYNC_SELECT, DPMSSyncSelect); 1769} 1770