neo_driver.c revision c3c9db83
1/********************************************************************** 2Copyright 1998, 1999 by Precision Insight, Inc., Cedar Park, Texas. 3 4 All Rights Reserved 5 6Permission to use, copy, modify, distribute, and sell this software and 7its documentation for any purpose is hereby granted without fee, 8provided that the above copyright notice appear in all copies and that 9both that copyright notice and this permission notice appear in 10supporting documentation, and that the name of Precision Insight not be 11used in advertising or publicity pertaining to distribution of the 12software without specific, written prior permission. Precision Insight 13and its suppliers make no representations about the suitability of this 14software for any purpose. It is provided "as is" without express or 15implied warranty. 16 17PRECISION INSIGHT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY 20SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 21RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 22CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 23CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 24**********************************************************************/ 25 26/* 27 * Copyright 1998, 1999 Egbert Eich 28 * Copyright 2000, 2001 SuSE GmbH, Author: Egbert Eich 29 * Copyright 2002 SuSE Linux AG, Author: Egbert Eich 30 * Copyright 2002 Shigehiro Nomura 31 */ 32 33 34/* 35 * The original Precision Insight driver for 36 * XFree86 v.3.3 has been sponsored by Red Hat. 37 * 38 * Authors: 39 * Jens Owen (jens@tungstengraphics.com) 40 * Kevin E. Martin (kevin@precisioninsight.com) 41 * 42 * Port to Xfree86 v.4.0 43 * 1998, 1999 by Egbert Eich (Egbert.Eich@Physik.TU-Darmstadt.DE) 44 */ 45 46#ifdef HAVE_CONFIG_H 47#include "config.h" 48#endif 49 50/* All drivers should typically include these */ 51#include "xf86.h" 52#include "xf86_OSproc.h" 53 54/* Everything using inb/outb, etc needs "compiler.h" */ 55#include "compiler.h" 56 57#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 58#include "xf86Resources.h" 59/* Needed by Resources Access Control (RAC) */ 60#include "xf86RAC.h" 61#endif 62 63/* Drivers for PCI hardware need this */ 64#include "xf86PciInfo.h" 65 66/* Drivers that need to access the PCI config space directly need this */ 67#include "xf86Pci.h" 68 69/* All drivers using the vgahw module need this */ 70#include "vgaHW.h" 71 72/* All drivers initialising the SW cursor need this */ 73#include "mipointer.h" 74 75/* All drivers implementing backing store need this */ 76#include "mibstore.h" 77 78/* All drivers using the mi colormap manipulation need this */ 79#include "micmap.h" 80 81#include "xf86cmap.h" 82 83#include "fb.h" 84 85/* int10 */ 86#include "xf86int10.h" 87#include "vbe.h" 88 89/* Needed for Device Data Channel (DDC) support */ 90#include "xf86DDC.h" 91 92#include "picturestr.h" 93 94#include "xf86xv.h" 95#include <X11/extensions/Xv.h> 96 97/* 98 * Driver data structures. 99 */ 100#include "neo.h" 101#include "neo_reg.h" 102#include "neo_macros.h" 103 104/* These need to be checked */ 105#include <X11/X.h> 106#include <X11/Xproto.h> 107#include "scrnintstr.h" 108#include "servermd.h" 109 110#include <unistd.h> 111 112/* Mandatory functions */ 113static const OptionInfoRec * NEOAvailableOptions(int chipid, int busid); 114static void NEOIdentify(int flags); 115static Bool NEOProbe(DriverPtr drv, int flags); 116static Bool NEOPreInit(ScrnInfoPtr pScrn, int flags); 117static Bool NEOScreenInit(int Index, ScreenPtr pScreen, int argc, 118 char **argv); 119static Bool NEOEnterVT(int scrnIndex, int flags); 120static void NEOLeaveVT(int scrnIndex, int flags); 121static Bool NEOCloseScreen(int scrnIndex, ScreenPtr pScreen); 122static void NEOFreeScreen(int scrnIndex, int flags); 123static ModeStatus NEOValidMode(int scrnIndex, DisplayModePtr mode, 124 Bool verbose, int flags); 125 126/* Internally used functions */ 127static int neoFindIsaDevice(GDevPtr dev); 128static Bool neoModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); 129static void neoSave(ScrnInfoPtr pScrn); 130static void neoRestore(ScrnInfoPtr pScrn, vgaRegPtr VgaReg, 131 NeoRegPtr NeoReg, Bool restoreText); 132static void neoLock(ScrnInfoPtr pScrn); 133static void neoUnlock(ScrnInfoPtr pScrn); 134static Bool neoMapMem(ScrnInfoPtr pScrn); 135static Bool neoUnmapMem(ScrnInfoPtr pScrn); 136static void neoProgramShadowRegs(ScrnInfoPtr pScrn, vgaRegPtr VgaReg, 137 NeoRegPtr restore); 138static void neoCalcVCLK(ScrnInfoPtr pScrn, long freq); 139static xf86MonPtr neo_ddc1(int scrnIndex); 140static Bool neoDoDDC1(ScrnInfoPtr pScrn); 141static Bool neoDoDDC2(ScrnInfoPtr pScrn); 142static Bool neoDoDDCVBE(ScrnInfoPtr pScrn); 143static void neoProbeDDC(ScrnInfoPtr pScrn, int index); 144static void NeoDisplayPowerManagementSet(ScrnInfoPtr pScrn, 145 int PowerManagementMode, int flags); 146static int neoFindMode(int xres, int yres, int depth); 147 148#define NEO_VERSION 4000 149#define NEO_NAME "NEOMAGIC" 150#define NEO_DRIVER_NAME "neomagic" 151 152#define NEO_MAJOR_VERSION PACKAGE_VERSION_MAJOR 153#define NEO_MINOR_VERSION PACKAGE_VERSION_MINOR 154#define NEO_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL 155 156/* 157 * This is intentionally screen-independent. It indicates the binding 158 * choice made in the first PreInit. 159 */ 160static int pix24bpp = 0; 161 162 163static biosMode bios8[] = { 164 { 320, 240, 0x40 }, 165 { 300, 400, 0x42 }, 166 { 640, 400, 0x20 }, 167 { 640, 480, 0x21 }, 168 { 800, 600, 0x23 }, 169 { 1024, 768, 0x25 } 170}; 171 172static biosMode bios15[] = { 173 { 320, 200, 0x2D }, 174 { 640, 480, 0x30 }, 175 { 800, 600, 0x33 }, 176 { 1024, 768, 0x36 } 177}; 178 179static biosMode bios16[] = { 180 { 320, 200, 0x2e }, 181 { 320, 240, 0x41 }, 182 { 300, 400, 0x43 }, 183 { 640, 480, 0x31 }, 184 { 800, 600, 0x34 }, 185 { 1024, 768, 0x37 } 186}; 187 188static biosMode bios24[] = { 189 { 640, 480, 0x32 }, 190 { 800, 600, 0x35 }, 191 { 1024, 768, 0x38 } 192}; 193 194static DisplayModeRec neo800x480Mode = { 195 NULL, /* prev */ 196 NULL, /* next */ 197 "800x480", /* identifier of this mode */ 198 MODE_OK, /* mode status */ 199 M_T_BUILTIN, /* mode type */ 200 35260, /* Clock frequency */ 201 800, /* HDisplay */ 202 856, /* HSyncStart */ 203 1040, /* HSyncEnd */ 204 1056, /* HTotal */ 205 0, /* HSkew */ 206 480, /* VDisplay */ 207 480, /* VSyncStart */ 208 486, /* VSyncEnd */ 209 488, /* VTotal */ 210 0, /* VScan */ 211 V_PHSYNC | V_PVSYNC, /* Flags */ 212 -1, /* ClockIndex */ 213 35260, /* SynthClock */ 214 800, /* CRTC HDisplay */ 215 800, /* CRTC HBlankStart */ 216 856, /* CRTC HSyncStart */ 217 1040, /* CRTC HSyncEnd */ 218 872, /* CRTC HBlankEnd */ 219 1048, /* CRTC HTotal */ 220 0, /* CRTC HSkew */ 221 480, /* CRTC VDisplay */ 222 480, /* CRTC VBlankStart */ 223 480, /* CRTC VSyncStart */ 224 486, /* CRTC VSyncEnd */ 225 487, /* CRTC VBlankEnd */ 226 488, /* CRTC VTotal */ 227 FALSE, /* CrtcHAdjusted */ 228 FALSE, /* CrtcVAdjusted */ 229 0, /* PrivSize */ 230 NULL, /* Private */ 231 0.0, /* HSync */ 232 0.0 /* VRefresh */ 233}; 234 235static DisplayModeRec neo1024x480Mode = { 236 NULL, /* prev */ 237 NULL, /* next */ 238 "1024x480", /* identifier of this mode */ 239 MODE_OK, /* mode status */ 240 M_T_BUILTIN, /* mode type */ 241 45900, /* Clock frequency */ 242 1024, /* HDisplay */ 243 1048, /* HSyncStart */ 244 1184, /* HSyncEnd */ 245 1344, /* HTotal */ 246 0, /* HSkew */ 247 480, /* VDisplay */ 248 480, /* VSyncStart */ 249 486, /* VSyncEnd */ 250 488, /* VTotal */ 251 0, /* VScan */ 252 V_PHSYNC | V_PVSYNC, /* Flags */ 253 -1, /* ClockIndex */ 254 45900, /* SynthClock */ 255 1024, /* CRTC HDisplay */ 256 1024, /* CRTC HBlankStart */ 257 1048, /* CRTC HSyncStart */ 258 1184, /* CRTC HSyncEnd */ 259 1072, /* CRTC HBlankEnd */ 260 1344, /* CRTC HTotal */ 261 0, /* CRTC HSkew */ 262 480, /* CRTC VDisplay */ 263 480, /* CRTC VBlankStart */ 264 480, /* CRTC VSyncStart */ 265 486, /* CRTC VSyncEnd */ 266 487, /* CRTC VBlankEnd */ 267 488, /* CRTC VTotal */ 268 FALSE, /* CrtcHAdjusted */ 269 FALSE, /* CrtcVAdjusted */ 270 0, /* PrivSize */ 271 NULL, /* Private */ 272 0.0, /* HSync */ 273 0.0 /* VRefresh */ 274}; 275 276/* 277 * This contains the functions needed by the server after loading the driver 278 * module. It must be supplied, and gets passed back by the SetupProc 279 * function in the dynamic case. In the static case, a reference to this 280 * is compiled in, and this requires that the name of this DriverRec be 281 * an upper-case version of the driver name. 282 */ 283 284_X_EXPORT DriverRec NEOMAGIC = { 285 NEO_VERSION, 286 NEO_DRIVER_NAME, 287 NEOIdentify, 288 NEOProbe, 289 NEOAvailableOptions, 290 NULL, 291 0 292}; 293 294static SymTabRec NEOChipsets[] = { 295 { NM2070, "neo2070" }, 296 { NM2090, "neo2090" }, 297 { NM2093, "neo2093" }, 298 { NM2097, "neo2097" }, 299 { NM2160, "neo2160" }, 300 { NM2200, "neo2200" }, 301 { NM2230, "neo2230" }, 302 { NM2360, "neo2360" }, 303 { NM2380, "neo2380" }, 304 { -1, NULL } 305}; 306 307/* Conversion PCI ID to chipset name */ 308static PciChipsets NEOPCIchipsets[] = { 309 { NM2070, PCI_CHIP_NM2070, RES_SHARED_VGA }, 310 { NM2090, PCI_CHIP_NM2090, RES_SHARED_VGA }, 311 { NM2093, PCI_CHIP_NM2093, RES_SHARED_VGA }, 312 { NM2097, PCI_CHIP_NM2097, RES_SHARED_VGA }, 313 { NM2160, PCI_CHIP_NM2160, RES_SHARED_VGA }, 314 { NM2200, PCI_CHIP_NM2200, RES_SHARED_VGA }, 315 { NM2230, PCI_CHIP_NM2230, RES_SHARED_VGA }, 316 { NM2360, PCI_CHIP_NM2360, RES_SHARED_VGA }, 317 { NM2380, PCI_CHIP_NM2380, RES_SHARED_VGA }, 318 { -1, -1, RES_UNDEFINED} 319}; 320 321#ifdef HAVE_ISA 322static IsaChipsets NEOISAchipsets[] = { 323 { NM2070, RES_EXCLUSIVE_VGA }, 324 { NM2090, RES_EXCLUSIVE_VGA }, 325 { NM2093, RES_EXCLUSIVE_VGA }, 326 { NM2097, RES_EXCLUSIVE_VGA }, 327 { NM2160, RES_EXCLUSIVE_VGA }, 328 { NM2200, RES_EXCLUSIVE_VGA }, 329 { -1, RES_UNDEFINED } 330}; 331#endif 332 333/* The options supported by the Neomagic Driver */ 334typedef enum { 335 OPTION_NOACCEL, 336 OPTION_SW_CURSOR, 337 OPTION_NO_MMIO, 338 OPTION_INTERN_DISP, 339 OPTION_EXTERN_DISP, 340 OPTION_LCD_CENTER, 341 OPTION_LCD_STRETCH, 342 OPTION_SHADOW_FB, 343 OPTION_PCI_BURST, 344 OPTION_PROG_LCD_MODE_REGS, 345 OPTION_PROG_LCD_MODE_STRETCH, 346 OPTION_OVERRIDE_VALIDATE_MODE, 347 OPTION_SHOWCACHE, 348 OPTION_ROTATE, 349 OPTION_VIDEO_KEY, 350 OPTION_OVERLAYMEM, 351 OPTION_VIDEO_INTERLACE, 352 OPTION_DISPLAY_HEIGHT_480, 353 OPTION_STRANGE_LOCKUPS 354} NEOOpts; 355 356static const OptionInfoRec NEO_2070_Options[] = { 357 { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 358 { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, 359 { OPTION_NO_MMIO, "noMMIO", OPTV_BOOLEAN, {0}, FALSE }, 360 { OPTION_INTERN_DISP,"internDisp", OPTV_BOOLEAN, {0}, FALSE }, 361 { OPTION_EXTERN_DISP,"externDisp", OPTV_BOOLEAN, {0}, FALSE }, 362 { OPTION_LCD_CENTER, "LcdCenter", OPTV_BOOLEAN, {0}, FALSE }, 363 { OPTION_LCD_STRETCH, "NoStretch", OPTV_BOOLEAN, {0}, FALSE }, 364 { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, 365 { OPTION_PCI_BURST, "pciBurst", OPTV_BOOLEAN, {0}, FALSE }, 366 { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, 367 { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, 368 { OPTION_PROG_LCD_MODE_REGS, "progLcdModeRegs", 369 OPTV_BOOLEAN, {0}, FALSE }, 370 { OPTION_PROG_LCD_MODE_STRETCH, "progLcdModeStretch", 371 OPTV_BOOLEAN, {0}, FALSE }, 372 { OPTION_OVERRIDE_VALIDATE_MODE, "overrideValidateMode", 373 OPTV_BOOLEAN, {0}, FALSE }, 374 { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, 375 { OPTION_OVERLAYMEM, "OverlayMem", OPTV_INTEGER, {0}, FALSE }, 376 { OPTION_VIDEO_INTERLACE, "Interlace", 377 OPTV_INTEGER, {0}, FALSE }, 378 { -1, NULL, OPTV_NONE, {0}, FALSE } 379}; 380 381static const OptionInfoRec NEOOptions[] = { 382 { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 383 { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, 384 { OPTION_NO_MMIO, "noMMIO", OPTV_BOOLEAN, {0}, FALSE }, 385 { OPTION_INTERN_DISP,"internDisp", OPTV_BOOLEAN, {0}, FALSE }, 386 { OPTION_EXTERN_DISP,"externDisp", OPTV_BOOLEAN, {0}, FALSE }, 387 { OPTION_LCD_CENTER, "LcdCenter", OPTV_BOOLEAN, {0}, FALSE }, 388 { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, 389 { OPTION_LCD_STRETCH,"NoStretch", OPTV_BOOLEAN, {0}, FALSE }, 390 { OPTION_PCI_BURST, "pciBurst", OPTV_BOOLEAN, {0}, FALSE }, 391 { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, 392 { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, 393 { OPTION_STRANGE_LOCKUPS, "StrangeLockups", OPTV_BOOLEAN, {0}, FALSE }, 394 { OPTION_DISPLAY_HEIGHT_480, "DisplayHeight480", 395 OPTV_BOOLEAN, {0}, FALSE }, 396 { OPTION_PROG_LCD_MODE_REGS, "progLcdModeRegs", 397 OPTV_BOOLEAN, {0}, FALSE }, 398 { OPTION_PROG_LCD_MODE_STRETCH, "progLcdModeStretch", 399 OPTV_BOOLEAN, {0}, FALSE }, 400 { OPTION_OVERRIDE_VALIDATE_MODE, "overrideValidateMode", 401 OPTV_BOOLEAN, {0}, FALSE }, 402 { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, 403 { OPTION_OVERLAYMEM, "OverlayMem", OPTV_INTEGER, {0}, FALSE }, 404 { OPTION_VIDEO_INTERLACE, "Interlace", 405 OPTV_INTEGER, {0}, FALSE }, 406 { -1, NULL, OPTV_NONE, {0}, FALSE } 407}; 408 409#ifdef XFree86LOADER 410 411static MODULESETUPPROTO(neoSetup); 412 413static XF86ModuleVersionInfo neoVersRec = 414{ 415 "neomagic", 416 MODULEVENDORSTRING, 417 MODINFOSTRING1, 418 MODINFOSTRING2, 419 XORG_VERSION_CURRENT, 420 NEO_MAJOR_VERSION, NEO_MINOR_VERSION, NEO_PATCHLEVEL, 421 ABI_CLASS_VIDEODRV, 422 ABI_VIDEODRV_VERSION, 423 MOD_CLASS_VIDEODRV, 424 {0,0,0,0} 425}; 426 427/* 428 * This is the module init data. 429 * Its name has to be the driver name followed by ModuleData 430 */ 431_X_EXPORT XF86ModuleData neomagicModuleData = { &neoVersRec, neoSetup, NULL }; 432 433static pointer 434neoSetup(pointer module, pointer opts, int *errmaj, int *errmin) 435{ 436 static Bool setupDone = FALSE; 437 438 if (!setupDone) { 439 setupDone = TRUE; 440 xf86AddDriver(&NEOMAGIC, module, 0); 441 442 /* 443 * The return value must be non-NULL on success even though there 444 * is no TearDownProc. 445 */ 446 return (pointer)1; 447 } else { 448 if (errmaj) *errmaj = LDR_ONCEONLY; 449 return NULL; 450 } 451} 452 453#endif /* XFree86LOADER */ 454 455static Bool 456NEOGetRec(ScrnInfoPtr pScrn) 457{ 458 /* 459 * Allocate a NEORec, and hook it into pScrn->driverPrivate. 460 * pScrn->driverPrivate is initialised to NULL, so we can check if 461 * the allocation has already been done. 462 */ 463 if (pScrn->driverPrivate != NULL) 464 return TRUE; 465 466 pScrn->driverPrivate = xnfcalloc(sizeof(NEORec), 1); 467 468 if (pScrn->driverPrivate == NULL) 469 return FALSE; 470 return TRUE; 471} 472 473static void 474NEOFreeRec(ScrnInfoPtr pScrn) 475{ 476 if (pScrn->driverPrivate == NULL) 477 return; 478 xfree(pScrn->driverPrivate); 479 pScrn->driverPrivate = NULL; 480} 481 482static const OptionInfoRec * 483NEOAvailableOptions(int chipid, int busid) 484{ 485 int chip = (chipid & 0x0000ffff); 486 487 if (chip == PCI_CHIP_NM2070) 488 return NEO_2070_Options; 489 else 490 return NEOOptions; 491} 492 493/* Mandatory */ 494static void 495NEOIdentify(int flags) 496{ 497 xf86PrintChipsets(NEO_NAME, "Driver for Neomagic chipsets", 498 NEOChipsets); 499} 500 501/* Mandatory */ 502static Bool 503NEOProbe(DriverPtr drv, int flags) 504{ 505 Bool foundScreen = FALSE; 506 int numDevSections, numUsed; 507 GDevPtr *devSections; 508 int *usedChips; 509 int i; 510 511 /* 512 * Find the config file Device sections that match this 513 * driver, and return if there are none. 514 */ 515 if ((numDevSections = xf86MatchDevice(NEO_DRIVER_NAME, 516 &devSections)) <= 0) { 517 return FALSE; 518 } 519 520 /* PCI BUS */ 521#ifndef XSERVER_LIBPCIACCESS 522 if (xf86GetPciVideoInfo() ) 523#endif 524 { 525 numUsed = xf86MatchPciInstances(NEO_NAME, PCI_VENDOR_NEOMAGIC, 526 NEOChipsets, NEOPCIchipsets, 527 devSections,numDevSections, 528 drv, &usedChips); 529 530 if (numUsed > 0) { 531 if (flags & PROBE_DETECT) 532 foundScreen = TRUE; 533 else for (i = 0; i < numUsed; i++) { 534 ScrnInfoPtr pScrn = NULL; 535 /* Allocate a ScrnInfoRec and claim the slot */ 536 if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], 537 NEOPCIchipsets,NULL, NULL, 538 NULL, NULL, NULL))) { 539 pScrn->driverVersion = NEO_VERSION; 540 pScrn->driverName = NEO_DRIVER_NAME; 541 pScrn->name = NEO_NAME; 542 pScrn->Probe = NEOProbe; 543 pScrn->PreInit = NEOPreInit; 544 pScrn->ScreenInit = NEOScreenInit; 545 pScrn->SwitchMode = NEOSwitchMode; 546 pScrn->AdjustFrame = NEOAdjustFrame; 547 pScrn->EnterVT = NEOEnterVT; 548 pScrn->LeaveVT = NEOLeaveVT; 549 pScrn->FreeScreen = NEOFreeScreen; 550 pScrn->ValidMode = NEOValidMode; 551 foundScreen = TRUE; 552 } 553 } 554 xfree(usedChips); 555 } 556 } 557 558#ifdef HAVE_ISA 559 /* Isa Bus */ 560 561 numUsed = xf86MatchIsaInstances(NEO_NAME,NEOChipsets,NEOISAchipsets, 562 drv,neoFindIsaDevice,devSections, 563 numDevSections,&usedChips); 564 if (numUsed > 0) { 565 if (flags & PROBE_DETECT) 566 foundScreen = TRUE; 567 else for (i = 0; i < numUsed; i++) { 568 ScrnInfoPtr pScrn = NULL; 569 if ((pScrn = xf86ConfigIsaEntity(pScrn, 0, usedChips[i], 570 NEOISAchipsets, NULL, NULL, 571 NULL, NULL, NULL))) { 572 pScrn->driverVersion = NEO_VERSION; 573 pScrn->driverName = NEO_DRIVER_NAME; 574 pScrn->name = NEO_NAME; 575 pScrn->Probe = NEOProbe; 576 pScrn->PreInit = NEOPreInit; 577 pScrn->ScreenInit = NEOScreenInit; 578 pScrn->SwitchMode = NEOSwitchMode; 579 pScrn->AdjustFrame = NEOAdjustFrame; 580 pScrn->EnterVT = NEOEnterVT; 581 pScrn->LeaveVT = NEOLeaveVT; 582 pScrn->FreeScreen = NEOFreeScreen; 583 pScrn->ValidMode = NEOValidMode; 584 foundScreen = TRUE; 585 } 586 } 587 xfree(usedChips); 588 } 589#endif 590 591 xfree(devSections); 592 return foundScreen; 593} 594 595#ifdef HAVE_ISA 596static int 597neoFindIsaDevice(GDevPtr dev) 598{ 599 unsigned int vgaIOBase; 600 unsigned char id; 601 602 vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0; 603 /* §§§ Too intrusive ? */ 604 outw(GRAX, 0x2609); /* Unlock NeoMagic registers */ 605 606 outb(vgaIOBase + 4, 0x1A); 607 id = inb(vgaIOBase + 5); 608 609 outw(GRAX, 0x0009); /* Lock NeoMagic registers */ 610 611 switch (id) { 612 case PROBED_NM2070 : 613 return NM2070; 614 case PROBED_NM2090 : 615 return NM2090; 616 case PROBED_NM2093 : 617 return NM2093; 618 default : 619 return -1; 620 } 621} 622#endif 623 624/* Mandatory */ 625Bool 626NEOPreInit(ScrnInfoPtr pScrn, int flags) 627{ 628 ClockRangePtr clockRanges; 629 int i; 630 NEOPtr nPtr; 631 vgaHWPtr hwp; 632 int bppSupport = NoDepth24Support; 633 int videoRam = 896; 634 int maxClock = 65000; 635 int CursorMem = 1024; 636 int CursorOff = 0x100; 637 int linearSize = 1024; 638 int maxWidth = 1024; 639 int maxHeight = 1024; 640 unsigned char type, dpy; 641 int w; 642 int apertureSize; 643 Bool height_480 = FALSE; 644 Bool lcdCenterOptSet = FALSE; 645 char *s; 646 647 if (flags & PROBE_DETECT) { 648 neoProbeDDC( pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index ); 649 return TRUE; 650 } 651 652 /* The vgahw module should be loaded here when needed */ 653 if (!xf86LoadSubModule(pScrn, "vgahw")) 654 return FALSE; 655 656 /* 657 * Allocate a vgaHWRec. 658 */ 659 if (!vgaHWGetHWRec(pScrn)) 660 return FALSE; 661 hwp = VGAHWPTR(pScrn); 662 663 /* Allocate the NeoRec driverPrivate */ 664 if (!NEOGetRec(pScrn)) { 665 return FALSE; 666 } 667# define RETURN \ 668 { NEOFreeRec(pScrn);\ 669 return FALSE;\ 670 } 671 672 nPtr = NEOPTR(pScrn); 673 674 /* Since, the capabilities are determined by the chipset the very 675 * first thing to do is, figure out the chipset and its capabilities 676 */ 677 /* This driver doesn't expect more than one entity per screen */ 678 if (pScrn->numEntities > 1) 679 RETURN; 680 681 /* This is the general case */ 682 for (i = 0; i<pScrn->numEntities; i++) { 683 nPtr->pEnt = xf86GetEntityInfo(pScrn->entityList[i]); 684#ifndef XSERVER_LIBPCIACCESS 685 if (nPtr->pEnt->resources) return FALSE; 686#endif 687 nPtr->NeoChipset = nPtr->pEnt->chipset; 688 pScrn->chipset = (char *)xf86TokenToString(NEOChipsets, 689 nPtr->pEnt->chipset); 690 /* This driver can handle ISA and PCI buses */ 691 if (nPtr->pEnt->location.type == BUS_PCI) { 692 nPtr->PciInfo = xf86GetPciInfoForEntity(nPtr->pEnt->index); 693#ifndef XSERVER_LIBPCIACCESS 694 nPtr->PciTag = pciTag(nPtr->PciInfo->bus, 695 nPtr->PciInfo->device, 696 nPtr->PciInfo->func); 697#endif 698 } 699 } 700 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Chipset is a "); 701 switch(nPtr->NeoChipset){ 702 case NM2070: 703 xf86ErrorF("MagicGraph 128 (NM2070)"); 704 break; 705 case NM2090 : 706 xf86ErrorF("MagicGraph 128V (NM2090)"); 707 break; 708 case NM2093 : 709 xf86ErrorF("MagicGraph 128ZV (NM2093)"); 710 break; 711 case NM2097 : 712 xf86ErrorF("MagicGraph 128ZV+ (NM2097)"); 713 break; 714 case NM2160 : 715 xf86ErrorF("MagicGraph 128XD (NM2160)"); 716 break; 717 case NM2200 : 718 xf86ErrorF("MagicMedia 256AV (NM2200)"); 719 break; 720 case NM2230 : 721 xf86ErrorF("MagicMedia 256AV+ (NM2230)"); 722 break; 723 case NM2360 : 724 xf86ErrorF("MagicMedia 256ZX (NM2360)"); 725 break; 726 case NM2380 : 727 xf86ErrorF("MagicMedia 256XL+ (NM2380)"); 728 break; 729 } 730 xf86ErrorF("\n"); 731 732 vgaHWGetIOBase(hwp); 733 nPtr->vgaIOBase = hwp->IOBase; 734 vgaHWSetStdFuncs(hwp); 735 736 /* Determine the panel type */ 737 VGAwGR(0x09,0x26); 738 type = VGArGR(0x21); 739 dpy = VGArGR(0x20); 740 741 /* Determine panel width -- used in NeoValidMode. */ 742 w = VGArGR(0x20); 743 VGAwGR(0x09,0x00); 744 switch ((w & 0x18) >> 3) { 745 case 0x00 : 746 nPtr->NeoPanelWidth = 640; 747 nPtr->NeoPanelHeight = 480; 748 break; 749 case 0x01 : 750 nPtr->NeoPanelWidth = 800; 751 nPtr->NeoPanelHeight = 600; 752 break; 753 case 0x02 : 754 nPtr->NeoPanelWidth = 1024; 755 nPtr->NeoPanelHeight = 768; 756 break; 757 case 0x03 : 758 /* 1280x1024 panel support needs to be added */ 759#ifdef NOT_DONE 760 nPtr->NeoPanelWidth = 1280; 761 nPtr->NeoPanelHeight = 1024; 762 break; 763#else 764 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 765 "Only 640x480,\n" 766 " 800x600,\n" 767 " and 1024x768 panels are currently supported\n"); 768 return FALSE; 769#endif 770 default : 771 nPtr->NeoPanelWidth = 640; 772 nPtr->NeoPanelHeight = 480; 773 break; 774 } 775 776 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel is a %dx%d %s %s display\n", 777 nPtr->NeoPanelWidth, 778 nPtr->NeoPanelHeight, 779 (type & 0x02) ? "color" : "monochrome", 780 (type & 0x10) ? "TFT" : "dual scan"); 781 782 783 switch (nPtr->NeoChipset){ 784 case NM2070: 785 bppSupport = NoDepth24Support; 786 videoRam = 896; 787 maxClock = 65000; 788 CursorMem = 2048; 789 CursorOff = 0x100; 790 linearSize = 1024; 791 maxWidth = 1024; 792 maxHeight = 1024; 793 break; 794 case NM2090: 795 case NM2093: 796 bppSupport = Support24bppFb | Support32bppFb | 797 SupportConvert32to24 | PreferConvert32to24; 798 videoRam = 1152; 799 maxClock = 80000; 800 CursorMem = 2048; 801 CursorOff = 0x100; 802 linearSize = 2048; 803 maxWidth = 1024; 804 maxHeight = 1024; 805 break; 806 case NM2097: 807 bppSupport = Support24bppFb | Support32bppFb | 808 SupportConvert32to24 | PreferConvert32to24; 809 videoRam = 1152; 810 maxClock = 80000; 811 CursorMem = 1024; 812 CursorOff = 0x100; 813 linearSize = 2048; 814 maxWidth = 1024; 815 maxHeight = 1024; 816 break; 817 case NM2160: 818 bppSupport = Support24bppFb | Support32bppFb | 819 SupportConvert32to24 | PreferConvert32to24; 820 videoRam = 2048; 821 maxClock = 90000; 822 CursorMem = 1024; 823 CursorOff = 0x100; 824 linearSize = 2048; 825 maxWidth = 1024; 826 maxHeight = 1024; 827 break; 828 case NM2200: 829 bppSupport = Support24bppFb | Support32bppFb | 830 SupportConvert32to24 | PreferConvert32to24; 831 videoRam = 2560; 832 maxClock = 110000; 833 CursorMem = 1024; 834 CursorOff = 0x1000; 835 linearSize = 4096; 836 maxWidth = 1280; 837 maxHeight = 1024; /* ???? */ 838 break; 839 case NM2230: 840 bppSupport = Support24bppFb | Support32bppFb | 841 SupportConvert32to24 | PreferConvert32to24; 842 videoRam = 3008; 843 maxClock = 110000; 844 CursorMem = 1024; 845 CursorOff = 0x1000; 846 linearSize = 4096; 847 maxWidth = 1280; 848 maxHeight = 1024; /* ???? */ 849 break; 850 case NM2360: 851 bppSupport = Support24bppFb | Support32bppFb | 852 SupportConvert32to24 | PreferConvert32to24; 853 videoRam = 4096; 854 maxClock = 110000; 855 CursorMem = 1024; 856 CursorOff = 0x1000; 857 linearSize = 4096; 858 maxWidth = 1280; 859 maxHeight = 1024; /* ???? */ 860 break; 861 case NM2380: 862 bppSupport = Support24bppFb | Support32bppFb | 863 SupportConvert32to24 | PreferConvert32to24; 864 videoRam = 6144; 865 maxClock = 110000; 866 CursorMem = 1024; 867 CursorOff = 0x1000; 868 linearSize = 8192; 869 maxWidth = 1280; 870 maxHeight = 1024; /* ???? */ 871 break; 872 } 873 874 pScrn->monitor = pScrn->confScreen->monitor; 875 876 if (xf86LoadSubModule(pScrn, "ddc")) { 877#if 1 /* for DDC1 testing */ 878 if (!neoDoDDCVBE(pScrn)) 879 if (!neoDoDDC2(pScrn)) 880#endif 881 neoDoDDC1(pScrn); 882 } 883 884 if (!xf86SetDepthBpp(pScrn, 16, 0, 0, bppSupport )) 885 return FALSE; 886 else { 887 /* Check that the returned depth is one we support */ 888 switch (pScrn->depth) { 889 case 8: 890 case 15: 891 case 16: 892 break; 893 case 24: 894 if (nPtr->NeoChipset != NM2070) 895 break; 896 default: 897 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 898 "Given depth (%d) is not supported by this driver\n", 899 pScrn->depth); 900 return FALSE; 901 } 902 } 903 xf86PrintDepthBpp(pScrn); 904 if (pScrn->depth == 8) 905 pScrn->rgbBits = 6; 906 907 /* Get the depth24 pixmap format */ 908 if (pScrn->depth == 24 && pix24bpp == 0) 909 pix24bpp = xf86GetBppFromDepth(pScrn, 24); 910 911 /* 912 * This must happen after pScrn->display has been set because 913 * xf86SetWeight references it. 914 */ 915 if (pScrn->depth > 8) { 916 /* The defaults are OK for us */ 917 rgb zeros = {0, 0, 0}; 918 919 if (!xf86SetWeight(pScrn, zeros, zeros)) { 920 return FALSE; 921 } else { 922 /* XXX check that weight returned is supported */ 923 ; 924 } 925 } 926 927 if (!xf86SetDefaultVisual(pScrn, -1)) 928 return FALSE; 929 930 if (pScrn->depth > 1) { 931 Gamma zeros = {0.0, 0.0, 0.0}; 932 933 if (!xf86SetGamma(pScrn, zeros)) 934 return FALSE; 935 } 936 937 nPtr->strangeLockups = TRUE; 938 939 /* Collect all of the relevant option flags (fill in pScrn->options) */ 940 xf86CollectOptions(pScrn, NULL); 941 /* Process the options */ 942 if (nPtr->NeoChipset == NM2070) { 943 if (!(nPtr->Options = xalloc(sizeof(NEO_2070_Options)))) 944 return FALSE; 945 memcpy(nPtr->Options, NEO_2070_Options, sizeof(NEO_2070_Options)); 946 } else { 947 if (!(nPtr->Options = xalloc(sizeof(NEOOptions)))) 948 return FALSE; 949 memcpy(nPtr->Options, NEOOptions, sizeof(NEOOptions)); 950 } 951 952 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, nPtr->Options); 953 954 xf86GetOptValBool(nPtr->Options, OPTION_SW_CURSOR,&nPtr->swCursor); 955 xf86GetOptValBool(nPtr->Options, OPTION_NO_MMIO,&nPtr->noMMIO); 956 xf86GetOptValBool(nPtr->Options, OPTION_INTERN_DISP,&nPtr->internDisp); 957 xf86GetOptValBool(nPtr->Options, OPTION_EXTERN_DISP,&nPtr->externDisp); 958 if (xf86GetOptValBool(nPtr->Options, OPTION_LCD_CENTER,&nPtr->lcdCenter)) 959 lcdCenterOptSet = TRUE; 960 xf86GetOptValBool(nPtr->Options, OPTION_LCD_STRETCH,&nPtr->noLcdStretch); 961 xf86GetOptValBool(nPtr->Options, OPTION_SHADOW_FB,&nPtr->shadowFB); 962 xf86GetOptValBool(nPtr->Options, OPTION_SHOWCACHE,&nPtr->showcache); 963 nPtr->onPciBurst = TRUE; 964 xf86GetOptValBool(nPtr->Options, OPTION_PCI_BURST,&nPtr->onPciBurst); 965 xf86GetOptValBool(nPtr->Options, 966 OPTION_PROG_LCD_MODE_REGS,&nPtr->progLcdRegs); 967 if (xf86GetOptValBool(nPtr->Options, 968 OPTION_PROG_LCD_MODE_STRETCH,&nPtr->progLcdStretch)) 969 nPtr->progLcdStretchOpt = TRUE; 970 xf86GetOptValBool(nPtr->Options, 971 OPTION_OVERRIDE_VALIDATE_MODE, &nPtr->overrideValidate); 972 xf86GetOptValBool(nPtr->Options, OPTION_DISPLAY_HEIGHT_480,&height_480); 973 xf86GetOptValBool(nPtr->Options, OPTION_STRANGE_LOCKUPS, 974 &nPtr->strangeLockups); 975 nPtr->noAccelSet = 976 xf86GetOptValBool(nPtr->Options, OPTION_NOACCEL,&nPtr->noAccel); 977 978 nPtr->rotate = 0; 979 if ((s = xf86GetOptValString(nPtr->Options, OPTION_ROTATE))) { 980 if(!xf86NameCmp(s, "CW")) { 981 /* accel is disabled below for shadowFB */ 982 nPtr->shadowFB = TRUE; 983 nPtr->swCursor = TRUE; 984 nPtr->rotate = 1; 985 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 986 "Rotating screen clockwise - acceleration disabled\n"); 987 } else if(!xf86NameCmp(s, "CCW")) { 988 nPtr->shadowFB = TRUE; 989 nPtr->swCursor = TRUE; 990 nPtr->rotate = -1; 991 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen" 992 "counter clockwise - acceleration disabled\n"); 993 } else { 994 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" 995 "value for Option \"Rotate\"\n", s); 996 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 997 "Valid options are \"CW\" or \"CCW\"\n"); 998 } 999 } 1000 1001 if(xf86GetOptValInteger(nPtr->Options, 1002 OPTION_VIDEO_KEY, &(nPtr->videoKey))) { 1003 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n", 1004 nPtr->videoKey); 1005 } else { 1006 nPtr->videoKey = (1 << pScrn->offset.red) | 1007 (1 << pScrn->offset.green) | 1008 (((pScrn->mask.blue >> pScrn->offset.blue) - 1) 1009 << pScrn->offset.blue); 1010 } 1011 if(xf86GetOptValInteger(nPtr->Options, OPTION_OVERLAYMEM, 1012 &(nPtr->overlay))) { 1013 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1014 "reserve %d bytes for overlay.\n", nPtr->overlay); 1015 } else { 1016 nPtr->overlay = 0; 1017 } 1018 nPtr->interlace = 0; 1019 if(xf86GetOptValInteger(nPtr->Options, OPTION_VIDEO_INTERLACE, 1020 &(nPtr->interlace))) { 1021 if (nPtr->interlace >= 0 && nPtr->interlace <= 2){ 1022 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "interlace flag = %d\n", 1023 nPtr->interlace); 1024 } else { 1025 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1026 "\"%s\" is not a valid value for " 1027 "Option \"Interlaced\"\n", s); 1028 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Valid options are 0..2\n"); 1029 } 1030 } 1031 1032 if (height_480 1033 && (nPtr->NeoPanelWidth == 800 || nPtr->NeoPanelWidth == 1024)) { 1034 xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, 1035 "Overriding Panel height: Set to 480\n"); 1036 nPtr->NeoPanelHeight = 480; 1037 xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, 1038 "Disabling LCD stretching for panel height 480\n"); 1039 nPtr->noLcdStretch = TRUE; 1040 if (!lcdCenterOptSet) 1041 nPtr->lcdCenter = TRUE; 1042 } 1043 1044 if (nPtr->internDisp && nPtr->externDisp) 1045 xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, 1046 "Simultaneous LCD/CRT display mode\n"); 1047 else if (nPtr->externDisp) 1048 xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, 1049 "External CRT only display mode\n"); 1050 else if (nPtr->internDisp) 1051 xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, 1052 "Internal LCD only display mode\n"); 1053 else { 1054 nPtr->internDisp = ((dpy & 0x02) == 0x02); 1055 nPtr->externDisp = ((dpy & 0x01) == 0x01); 1056 if (nPtr->internDisp && nPtr->externDisp) 1057 xf86DrvMsg(pScrn->scrnIndex,X_PROBED, 1058 "Simultaneous LCD/CRT display mode\n"); 1059 else if (nPtr->externDisp) 1060 xf86DrvMsg(pScrn->scrnIndex,X_PROBED, 1061 "External CRT only display mode\n"); 1062 else if (nPtr->internDisp) 1063 xf86DrvMsg(pScrn->scrnIndex,X_PROBED, 1064 "Internal LCD only display mode\n"); 1065 else { 1066 /* this is a fallback if probed values are bogus */ 1067 nPtr->internDisp = TRUE; 1068 xf86DrvMsg(pScrn->scrnIndex,X_DEFAULT, 1069 "Internal LCD only display mode\n"); 1070 } 1071 } 1072 1073 if (nPtr->noLcdStretch) 1074 xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, 1075 "Low resolution video modes are not stretched\n"); 1076 if (nPtr->lcdCenter) 1077 xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, 1078 "Video modes are centered on the display\n"); 1079 if (nPtr->swCursor) 1080 xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, "using sofware cursor\n"); 1081 if (nPtr->noMMIO) 1082 xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, "MMIO mode disabled\n"); 1083 if (nPtr->onPciBurst) 1084 xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, "using PCI Burst mode\n"); 1085 if (nPtr->strangeLockups) 1086 xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, 1087 "Option StrangeLockups set: disabling some acceleration\n"); 1088 if (nPtr->showcache) 1089 xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, 1090 "Show chache for debugging\n"); 1091 if (nPtr->shadowFB) { 1092 nPtr->noAccel = TRUE; 1093 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1094 "Using \"Shadow Framebuffer\" - acceleration disabled\n"); 1095 } 1096 1097 nPtr->NeoFbMapSize = linearSize * 1024; 1098 nPtr->NeoCursorOffset = CursorOff; 1099 1100 if (nPtr->pEnt->device->MemBase) { 1101 /* XXX Check this matches a PCI base address */ 1102 nPtr->NeoLinearAddr = nPtr->pEnt->device->MemBase; 1103 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1104 "FB base address is set at 0x%lX.\n", 1105 nPtr->NeoLinearAddr); 1106 } else { 1107 nPtr->NeoLinearAddr = 0; 1108 } 1109 1110 nPtr->NeoMMIOAddr2 = 0; 1111 nPtr->NeoMMIOBase2 = NULL; 1112 if (nPtr->pEnt->device->IOBase && !nPtr->noMMIO) { 1113 /* XXX Check this matches a PCI base address */ 1114 nPtr->NeoMMIOAddr = nPtr->pEnt->device->IOBase; 1115 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1116 "MMIO base address is set at 0x%lX.\n", 1117 nPtr->NeoMMIOAddr); 1118 } else { 1119 nPtr->NeoMMIOAddr = 0; 1120 } 1121 1122 if (nPtr->pEnt->location.type == BUS_PCI) { 1123 if (!nPtr->NeoLinearAddr) { 1124 nPtr->NeoLinearAddr = PCI_REGION_BASE(nPtr->PciInfo, 0, REGION_MEM); 1125 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1126 "FB base address is set at 0x%lX.\n", 1127 nPtr->NeoLinearAddr); 1128 } 1129 if (!nPtr->NeoMMIOAddr && !nPtr->noMMIO) { 1130 switch (nPtr->NeoChipset) { 1131 case NM2070 : 1132 nPtr->NeoMMIOAddr = nPtr->NeoLinearAddr + 0x100000; 1133 break; 1134 case NM2090: 1135 case NM2093: 1136 nPtr->NeoMMIOAddr = nPtr->NeoLinearAddr + 0x200000; 1137 break; 1138 case NM2160: 1139 case NM2097: 1140 case NM2200: 1141 case NM2230: 1142 case NM2360: 1143 case NM2380: 1144 nPtr->NeoMMIOAddr = PCI_REGION_BASE(nPtr->PciInfo, 1, REGION_MEM); 1145 nPtr->NeoMMIOAddr2 = PCI_REGION_BASE(nPtr->PciInfo, 2, REGION_MEM); 1146 break; 1147 } 1148 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1149 "MMIO base address is set at 0x%lX.\n", 1150 nPtr->NeoMMIOAddr); 1151 if (nPtr->NeoMMIOAddr2 != 0){ 1152 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1153 "MMIO base address2 is set at 0x%lX.\n", 1154 nPtr->NeoMMIOAddr2); 1155 } 1156 } 1157#ifndef XSERVER_LIBPCIACCESS 1158 /* XXX What about VGA resources in OPERATING mode? */ 1159 if (xf86RegisterResources(nPtr->pEnt->index, NULL, ResExclusive)) 1160 RETURN; 1161#endif 1162 1163 } 1164#ifndef XSERVER_LIBPCIACCESS 1165 else if (nPtr->pEnt->location.type == BUS_ISA) { 1166 unsigned int addr; 1167 resRange linearRes[] = { {ResExcMemBlock|ResBios|ResBus,0,0},_END }; 1168 1169 if (!nPtr->NeoLinearAddr) { 1170 VGAwGR(0x09,0x26); 1171 addr = VGArGR(0x13); 1172 VGAwGR(0x09,0x00); 1173 nPtr->NeoLinearAddr = addr << 20; 1174 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1175 "FB base address is set at 0x%lX.\n", 1176 nPtr->NeoLinearAddr); 1177 } 1178 if (!nPtr->NeoMMIOAddr && !nPtr->noMMIO) { 1179 nPtr->NeoMMIOAddr = nPtr->NeoLinearAddr + 0x100000; 1180 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1181 "MMIO base address is set at 0x%lX.\n", 1182 nPtr->NeoMMIOAddr); 1183 } 1184 1185 linearRes[0].rBegin = nPtr->NeoLinearAddr; 1186 linearRes[1].rEnd = nPtr->NeoLinearAddr + nPtr->NeoFbMapSize - 1; 1187 if (xf86RegisterResources(nPtr->pEnt->index,linearRes,ResNone)) { 1188 RETURN; 1189 } 1190 } 1191#endif 1192 else 1193 RETURN; 1194 1195 if (nPtr->pEnt->device->videoRam != 0) { 1196 pScrn->videoRam = nPtr->pEnt->device->videoRam; 1197 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VideoRAM: %d kByte\n", 1198 pScrn->videoRam); 1199 } else { 1200 pScrn->videoRam = videoRam; 1201 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VideoRAM: %d kByte\n", 1202 pScrn->videoRam); 1203 } 1204 1205 if (nPtr->pEnt->device->dacSpeeds[0] != 0) { 1206 maxClock = nPtr->pEnt->device->dacSpeeds[0]; 1207 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Max Clock: %d kHz\n", 1208 maxClock); 1209 } else { 1210 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Max Clock: %d kHz\n", 1211 maxClock); 1212 } 1213 1214 pScrn->progClock = TRUE; 1215 /* 1216 * Setup the ClockRanges, which describe what clock ranges are available, 1217 * and what sort of modes they can be used for. 1218 */ 1219 clockRanges = (ClockRangePtr)xnfcalloc(sizeof(ClockRange), 1); 1220 clockRanges->next = NULL; 1221 clockRanges->ClockMulFactor = 1; 1222 clockRanges->minClock = 11000; /* guessed §§§ */ 1223 clockRanges->maxClock = maxClock; 1224 clockRanges->clockIndex = -1; /* programmable */ 1225 clockRanges->interlaceAllowed = FALSE; 1226 clockRanges->doubleScanAllowed = TRUE; 1227 1228 /* Subtract memory for HW cursor */ 1229 if (!nPtr->swCursor) 1230 nPtr->NeoCursorMem = CursorMem; 1231 else 1232 nPtr->NeoCursorMem = 0; 1233 apertureSize = (pScrn->videoRam * 1024) - nPtr->NeoCursorMem; 1234 1235 if ((nPtr->NeoPanelWidth == 800) && (nPtr->NeoPanelHeight == 480)) { 1236 neo800x480Mode.next = pScrn->monitor->Modes; 1237 pScrn->monitor->Modes = &neo800x480Mode; 1238 } 1239 if ((nPtr->NeoPanelWidth == 1024) && (nPtr->NeoPanelHeight == 480)) { 1240 neo1024x480Mode.next = pScrn->monitor->Modes; 1241 pScrn->monitor->Modes = &neo1024x480Mode; 1242 } 1243 1244 if (!pScrn->monitor->DDC) { 1245 /* 1246 * If the monitor parameters are not specified explicitly, set them 1247 * so that 60Hz modes up to the panel size are allowed. 1248 */ 1249 if (pScrn->monitor->nHsync == 0) { 1250 pScrn->monitor->nHsync = 1; 1251 pScrn->monitor->hsync[0].lo = 28; 1252 pScrn->monitor->hsync[0].hi = 1253 60.0 * 1.07 * nPtr->NeoPanelHeight / 1000.0; 1254 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1255 "Using hsync range matching panel size: %.2f-%.2f kHz\n", 1256 pScrn->monitor->hsync[0].lo, 1257 pScrn->monitor->hsync[0].hi); 1258 } 1259 if (pScrn->monitor->nVrefresh == 0) { 1260 pScrn->monitor->nVrefresh = 1; 1261 pScrn->monitor->vrefresh[0].lo = 55.0; 1262 pScrn->monitor->vrefresh[0].hi = 65.0; 1263 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1264 "Using vsync range for panel: %.2f-%.2f kHz\n", 1265 pScrn->monitor->vrefresh[0].lo, 1266 pScrn->monitor->vrefresh[0].hi); 1267 } 1268 } 1269 1270 /* 1271 * For external displays, limit the width to 1024 pixels or less. 1272 */ 1273 { 1274 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 1275 pScrn->display->modes, clockRanges, 1276 NULL, 256, maxWidth,(8 * pScrn->bitsPerPixel),/*§§§*/ 1277 128, maxHeight, pScrn->display->virtualX, 1278 pScrn->display->virtualY, apertureSize, 1279 LOOKUP_BEST_REFRESH); 1280 1281 if (i == -1) 1282 RETURN; 1283 } 1284 1285 /* Prune the modes marked as invalid */ 1286 xf86PruneDriverModes(pScrn); 1287 1288 if (i == 0 || pScrn->modes == NULL) { 1289 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 1290 RETURN; 1291 } 1292 1293 /* 1294 * Set the CRTC parameters for all of the modes based on the type 1295 * of mode, and the chipset's interlace requirements. 1296 * 1297 * Calling this is required if the mode->Crtc* values are used by the 1298 * driver and if the driver doesn't provide code to set them. They 1299 * are not pre-initialised at all. 1300 */ 1301 xf86SetCrtcForModes(pScrn, 0); 1302 1303 /* Set the current mode to the first in the list */ 1304 pScrn->currentMode = pScrn->modes; 1305 1306 /* Print the list of modes being used */ 1307 xf86PrintModes(pScrn); 1308 1309 /* If monitor resolution is set on the command line, use it */ 1310 xf86SetDpi(pScrn, 0, 0); 1311 1312 if (xf86LoadSubModule(pScrn, "fb") == NULL) { 1313 RETURN; 1314 } 1315 1316 if (!xf86LoadSubModule(pScrn, "xaa")) 1317 RETURN; 1318 1319 if (nPtr->shadowFB) { 1320 if (!xf86LoadSubModule(pScrn, "shadow")) { 1321 RETURN; 1322 } 1323 } 1324 1325 if (!nPtr->swCursor) { 1326 if (!xf86LoadSubModule(pScrn, "ramdac")) 1327 RETURN; 1328 } 1329 return TRUE; 1330} 1331#undef RETURN 1332 1333/* Mandatory */ 1334static Bool 1335NEOEnterVT(int scrnIndex, int flags) 1336{ 1337 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1338 NEOPtr nPtr = NEOPTR(pScrn); 1339 1340 /* Should we re-save the text mode on each VT enter? */ 1341 if(!neoModeInit(pScrn, pScrn->currentMode)) 1342 return FALSE; 1343 1344 if (nPtr->video) 1345 NEOResetVideo(pScrn); 1346 1347 if (nPtr->NeoHWCursorShown) 1348 NeoShowCursor(pScrn); 1349 NEOAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 1350 1351 return TRUE; 1352} 1353 1354/* Mandatory */ 1355static void 1356NEOLeaveVT(int scrnIndex, int flags) 1357{ 1358 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1359 NEOPtr nPtr = NEOPTR(pScrn); 1360 1361 /* Invalidate the cached acceleration registers */ 1362 if (nPtr->NeoHWCursorShown) 1363 NeoHideCursor(pScrn); 1364 neoRestore(pScrn, &(VGAHWPTR(pScrn))->SavedReg, &nPtr->NeoSavedReg, TRUE); 1365 neoLock(pScrn); 1366 1367} 1368 1369static void 1370NEOLoadPalette( 1371 ScrnInfoPtr pScrn, 1372 int numColors, 1373 int *indices, 1374 LOCO *colors, 1375 VisualPtr pVisual 1376){ 1377 int i, index, shift, Gshift; 1378 vgaHWPtr hwp = VGAHWPTR(pScrn); 1379 1380 switch(pScrn->depth) { 1381 case 15: 1382 shift = Gshift = 1; 1383 break; 1384 case 16: 1385 shift = 0; 1386 Gshift = 0; 1387 break; 1388 default: 1389 shift = Gshift = 0; 1390 break; 1391 } 1392 1393 for(i = 0; i < numColors; i++) { 1394 index = indices[i]; 1395 hwp->writeDacWriteAddr(hwp, index); 1396 DACDelay(hwp); 1397 hwp->writeDacData(hwp, colors[index].red << shift); 1398 DACDelay(hwp); 1399 hwp->writeDacData(hwp, colors[index].green << Gshift); 1400 DACDelay(hwp); 1401 hwp->writeDacData(hwp, colors[index].blue << shift); 1402 DACDelay(hwp); 1403 } 1404} 1405 1406/* Mandatory */ 1407static Bool 1408NEOScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 1409{ 1410 ScrnInfoPtr pScrn; 1411 vgaHWPtr hwp; 1412 NEOPtr nPtr; 1413 NEOACLPtr nAcl; 1414 int ret; 1415 VisualPtr visual; 1416 int allocatebase, freespace, currentaddr; 1417#ifndef XSERVER_LIBPCIACCESS 1418 unsigned int racflag = RAC_FB; 1419#endif 1420 unsigned char *FBStart; 1421 int height, width, displayWidth; 1422 1423 /* 1424 * we need to get the ScrnInfoRec for this screen, so let's allocate 1425 * one first thing 1426 */ 1427 pScrn = xf86Screens[pScreen->myNum]; 1428 nPtr = NEOPTR(pScrn); 1429 nAcl = NEOACLPTR(pScrn); 1430 1431 hwp = VGAHWPTR(pScrn); 1432 hwp->MapSize = 0x10000; /* Standard 64k VGA window */ 1433 /* Map the VGA memory */ 1434 if (!vgaHWMapMem(pScrn)) 1435 return FALSE; 1436 1437 /* Map the Neo memory and possible MMIO areas */ 1438 if (!neoMapMem(pScrn)) 1439 return FALSE; 1440 1441 /* 1442 * next we save the current state and setup the first mode 1443 */ 1444 neoSave(pScrn); 1445 1446 if (!neoModeInit(pScrn,pScrn->currentMode)) 1447 return FALSE; 1448 vgaHWSaveScreen(pScreen,SCREEN_SAVER_ON); 1449 NEOAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 1450 1451 /* 1452 * Reset visual list. 1453 */ 1454 miClearVisualTypes(); 1455 1456 /* Setup the visuals we support. */ 1457 if (!miSetVisualTypes(pScrn->depth, 1458 miGetDefaultVisualMask(pScrn->depth), 1459 pScrn->rgbBits, pScrn->defaultVisual)) 1460 return FALSE; 1461 1462 if (!miSetPixmapDepths ()) return FALSE; 1463 1464 /* 1465 * Call the framebuffer layer's ScreenInit function, and fill in other 1466 * pScreen fields. 1467 */ 1468 displayWidth = pScrn->displayWidth; 1469 if (nPtr->rotate) { 1470 height = pScrn->virtualX; 1471 width = pScrn->virtualY; 1472 } else { 1473 width = pScrn->virtualX; 1474 height = pScrn->virtualY; 1475 } 1476 1477 if(nPtr->shadowFB) { 1478 nPtr->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); 1479 nPtr->ShadowPtr = xalloc(nPtr->ShadowPitch * height); 1480 displayWidth = nPtr->ShadowPitch / (pScrn->bitsPerPixel >> 3); 1481 FBStart = nPtr->ShadowPtr; 1482 } else { 1483 nPtr->ShadowPtr = NULL; 1484 FBStart = nPtr->NeoFbBase; 1485 } 1486 1487 ret = fbScreenInit(pScreen, FBStart, 1488 width, height, 1489 pScrn->xDpi, pScrn->yDpi, 1490 displayWidth, pScrn->bitsPerPixel); 1491 if (!ret) 1492 return FALSE; 1493 if (pScrn->depth > 8) { 1494 /* Fixup RGB ordering */ 1495 visual = pScreen->visuals + pScreen->numVisuals; 1496 while (--visual >= pScreen->visuals) { 1497 if ((visual->class | DynamicClass) == DirectColor) { 1498 visual->offsetRed = pScrn->offset.red; 1499 visual->offsetGreen = pScrn->offset.green; 1500 visual->offsetBlue = pScrn->offset.blue; 1501 visual->redMask = pScrn->mask.red; 1502 visual->greenMask = pScrn->mask.green; 1503 visual->blueMask = pScrn->mask.blue; 1504 } 1505 } 1506 } 1507 1508 /* must be after RGB ordering fixed */ 1509 fbPictureInit(pScreen, 0, 0); 1510 1511 xf86SetBlackWhitePixels(pScreen); 1512 1513 if (!nPtr->shadowFB) 1514 NEODGAInit(pScreen); 1515 1516 nPtr->NeoHWCursorShown = FALSE; 1517 nPtr->NeoHWCursorInitialized = FALSE; 1518 nAcl->UseHWCursor = FALSE; 1519 nAcl->CursorAddress = -1; 1520 1521 nAcl->cacheStart = -1; 1522 nAcl->cacheEnd = -1; 1523 xf86DrvMsg(pScrn->scrnIndex,X_INFO, 1524 "Using linear framebuffer at: 0x%08lX\n", 1525 nPtr->NeoLinearAddr); 1526 /* Setup pointers to free space in video ram */ 1527 allocatebase = (pScrn->videoRam << 10); 1528 freespace = allocatebase - pScrn->displayWidth * 1529 pScrn->virtualY * (pScrn->bitsPerPixel >> 3); 1530 currentaddr = allocatebase; 1531 xf86DrvMsg(scrnIndex, X_PROBED, 1532 "%d bytes off-screen memory available\n", freespace); 1533 1534 if (nPtr->swCursor || !nPtr->NeoMMIOBase) { 1535 xf86DrvMsg(scrnIndex, X_CONFIG, 1536 "Using Software Cursor.\n"); 1537 } else if (nPtr->NeoCursorMem <= freespace) { 1538 currentaddr -= nPtr->NeoCursorMem; 1539 freespace -= nPtr->NeoCursorMem; 1540 /* alignment */ 1541 freespace -= currentaddr & 0x3FF; 1542 currentaddr &= 0xfffffc00; 1543 nAcl->CursorAddress = currentaddr; 1544 xf86DrvMsg(scrnIndex, X_INFO, 1545 "Using H/W Cursor.\n"); 1546 } else { 1547 xf86DrvMsg(scrnIndex, X_ERROR, 1548 "Too little space for H/W cursor.\n"); 1549 } 1550 1551 if (!nPtr->noAccel && !nPtr->NeoMMIOBase) 1552 xf86DrvMsg(pScrn->scrnIndex,X_INFO, 1553 "Acceleration disabled when not using MMIO\n"); 1554 1555 if (nPtr->overlay > 0){ 1556 if (nPtr->overlay > freespace){ 1557 xf86DrvMsg(pScrn->scrnIndex,X_INFO, 1558 "Can not reserve %d bytes for overlay. " 1559 "Resize to %d bytes.\n", 1560 nPtr->overlay, freespace); 1561 nPtr->overlay = freespace; 1562 } 1563 currentaddr -= nPtr->overlay; 1564 freespace -= nPtr->overlay; 1565 nPtr->overlay_offset = currentaddr; 1566 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Overlay at 0x%x\n", 1567 nPtr->overlay_offset); 1568 } 1569 1570 nAcl->cacheStart = currentaddr - freespace; 1571 nAcl->cacheEnd = currentaddr; 1572 freespace = 0; 1573 if (nAcl->cacheStart < nAcl->cacheEnd) { 1574 BoxRec AvailFBArea; 1575 int lines = nAcl->cacheEnd / 1576 (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3)); 1577 if (!nPtr->noAccel && nPtr->NeoMMIOBase && lines > 1024) 1578 lines = 1024; 1579 AvailFBArea.x1 = 0; 1580 AvailFBArea.y1 = 0; 1581 AvailFBArea.x2 = pScrn->displayWidth; 1582 AvailFBArea.y2 = lines; 1583 xf86InitFBManager(pScreen, &AvailFBArea); 1584 1585 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1586 "Using %i scanlines of offscreen memory \n", 1587 lines - pScrn->virtualY); 1588 } 1589 1590 /* Setup the acceleration primitives */ 1591 if (!nPtr->noAccel && nPtr->NeoMMIOBase) { 1592 Bool ret = FALSE; 1593 if (nAcl->cacheStart >= nAcl->cacheEnd) { 1594 xf86DrvMsg(scrnIndex, X_ERROR, 1595 "Too little space for pixmap cache.\n"); 1596 } 1597 switch(nPtr->NeoChipset) { 1598 case NM2070 : 1599 ret = Neo2070AccelInit(pScreen); 1600 break; 1601 case NM2090 : 1602 case NM2093 : 1603 ret = Neo2090AccelInit(pScreen); 1604 break; 1605 case NM2097 : 1606 case NM2160 : 1607 ret = Neo2097AccelInit(pScreen); 1608 break; 1609 case NM2200 : 1610 case NM2230 : 1611 case NM2360 : 1612 case NM2380 : 1613 ret = Neo2200AccelInit(pScreen); 1614 break; 1615 } 1616 xf86DrvMsg(pScrn->scrnIndex,X_INFO, 1617 "Acceleration %s Initialized\n",ret ? "" : "not"); 1618 } 1619 1620 miInitializeBackingStore(pScreen); 1621 xf86SetBackingStore(pScreen); 1622 xf86SetSilkenMouse(pScreen); 1623 1624 /* Initialise cursor functions */ 1625 miDCInitialize (pScreen, xf86GetPointerScreenFuncs()); 1626 1627 if (nAcl->CursorAddress != -1) { 1628 /* HW cursor functions */ 1629 if (!NeoCursorInit(pScreen)) { 1630 xf86DrvMsg(scrnIndex, X_ERROR, 1631 "Hardware cursor initialization failed\n"); 1632 return FALSE; 1633 } 1634 nAcl->UseHWCursor = TRUE; 1635 nPtr->NeoHWCursorInitialized = TRUE; 1636 } else 1637 nAcl->UseHWCursor = FALSE; 1638 1639 if (nPtr->shadowFB) { 1640 nPtr->refreshArea = neoRefreshArea; 1641 1642 if(nPtr->rotate) { 1643 if (!nPtr->PointerMoved) { 1644 nPtr->PointerMoved = pScrn->PointerMoved; 1645 pScrn->PointerMoved = neoPointerMoved; 1646 } 1647 switch(pScrn->bitsPerPixel) { 1648 case 8: nPtr->refreshArea = neoRefreshArea8; break; 1649 case 16: nPtr->refreshArea = neoRefreshArea16; break; 1650 case 24: nPtr->refreshArea = neoRefreshArea24; break; 1651 case 32: nPtr->refreshArea = neoRefreshArea32; break; 1652 } 1653 } 1654#if 0 1655 ShadowFBInit(pScreen, nPtr->refreshArea); 1656#else 1657 shadowInit (pScreen, neoShadowUpdate, 0); 1658#endif 1659 } 1660 1661 /* Initialise default colourmap */ 1662 if(!miCreateDefColormap(pScreen)) 1663 return FALSE; 1664 1665 if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, 1666 NEOLoadPalette, NULL, 1667 CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH)) 1668 return FALSE; 1669 1670#ifndef XSERVER_LIBPCIACCESS 1671 racflag |= RAC_COLORMAP; 1672 if (nPtr->NeoHWCursorInitialized) 1673 racflag |= RAC_CURSOR; 1674 1675 pScrn->racIoFlags = pScrn->racMemFlags = racflag; 1676#endif 1677 1678 NEOInitVideo(pScreen); 1679 1680 pScreen->SaveScreen = vgaHWSaveScreenWeak(); 1681 1682 /* Setup DPMS mode */ 1683 if (nPtr->NeoChipset != NM2070) 1684 xf86DPMSInit(pScreen, (DPMSSetProcPtr)NeoDisplayPowerManagementSet, 1685 0); 1686 1687 pScrn->memPhysBase = (unsigned long)nPtr->NeoLinearAddr; 1688 pScrn->fbOffset = 0; 1689 1690 /* Wrap the current CloseScreen function */ 1691 nPtr->CloseScreen = pScreen->CloseScreen; 1692 pScreen->CloseScreen = NEOCloseScreen; 1693 1694 /* Report any unused options (only for the first generation) */ 1695 if (serverGeneration == 1) { 1696 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1697 } 1698 1699 return TRUE; 1700} 1701 1702/* Mandatory */ 1703Bool 1704NEOSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 1705{ 1706 return neoModeInit(xf86Screens[scrnIndex], mode); 1707} 1708 1709/* Mandatory */ 1710void 1711NEOAdjustFrame(int scrnIndex, int x, int y, int flags) 1712{ 1713 ScrnInfoPtr pScrn; 1714 NEOPtr nPtr; 1715 vgaHWPtr hwp; 1716 int oldExtCRTDispAddr; 1717 int Base; 1718 1719 pScrn = xf86Screens[scrnIndex]; 1720 hwp = VGAHWPTR(pScrn); 1721 nPtr = NEOPTR(pScrn); 1722 1723 if (nPtr->showcache && y) { 1724 int lastline = nPtr->NeoFbMapSize / 1725 ((pScrn->displayWidth * pScrn->bitsPerPixel) / 8); 1726 1727 lastline -= pScrn->currentMode->VDisplay; 1728 y += pScrn->virtualY - 1; 1729 if (y > lastline) y = lastline; 1730 } 1731 1732 Base = (y * pScrn->displayWidth + x) >> 2; 1733 1734 /* Scale Base by the number of bytes per pixel. */ 1735 switch (pScrn->depth) { 1736 case 8 : 1737 break; 1738 case 15 : 1739 case 16 : 1740 Base *= 2; 1741 break; 1742 case 24 : 1743 Base *= 3; 1744 break; 1745 default : 1746 break; 1747 } 1748 /* 1749 * These are the generic starting address registers. 1750 */ 1751 VGAwCR(0x0C, (Base & 0x00FF00) >> 8); 1752 VGAwCR(0x0D, (Base & 0x00FF)); 1753 1754 /* 1755 * Make sure we don't clobber some other bits that might already 1756 * have been set. NOTE: NM2200 has a writable bit 3, but it shouldn't 1757 * be needed. 1758 */ 1759 oldExtCRTDispAddr = VGArGR(0x0E); 1760 VGAwGR(0x0E,(((Base >> 16) & 0x07) | (oldExtCRTDispAddr & 0xf8))); 1761#if 0 1762 /* 1763 * This is a workaround for a higher level bug that causes the cursor 1764 * to be at the wrong position after a virtual screen resolution change 1765 */ 1766 if (nPtr->NeoHWCursorInitialized) { /*§§§ do we still need this?*/ 1767 NeoRepositionCursor(); 1768 } 1769#endif 1770} 1771 1772/* Mandatory */ 1773static Bool 1774NEOCloseScreen(int scrnIndex, ScreenPtr pScreen) 1775{ 1776 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1777 NEOPtr nPtr = NEOPTR(pScrn); 1778 1779 if(pScrn->vtSema){ 1780 if (nPtr->NeoHWCursorShown) 1781 NeoHideCursor(pScrn); 1782 neoRestore(pScrn, &(VGAHWPTR(pScrn))->SavedReg, &nPtr->NeoSavedReg, TRUE); 1783 1784 neoLock(pScrn); 1785 neoUnmapMem(pScrn); 1786 } 1787 if (nPtr->AccelInfoRec) 1788 XAADestroyInfoRec(nPtr->AccelInfoRec); 1789 if (nPtr->CursorInfo) 1790 xf86DestroyCursorInfoRec(nPtr->CursorInfo); 1791 if (nPtr->ShadowPtr) 1792 xfree(nPtr->ShadowPtr); 1793 1794 pScrn->vtSema = FALSE; 1795 pScreen->CloseScreen = nPtr->CloseScreen; 1796 return (*pScreen->CloseScreen)(scrnIndex, pScreen); 1797} 1798 1799/* Optional */ 1800static void 1801NEOFreeScreen(int scrnIndex, int flags) 1802{ 1803 if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) 1804 vgaHWFreeHWRec(xf86Screens[scrnIndex]); 1805 NEOFreeRec(xf86Screens[scrnIndex]); 1806} 1807 1808/* Optional */ 1809static ModeStatus 1810NEOValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) 1811{ 1812 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1813 NEOPtr nPtr = NEOPTR(pScrn); 1814 int vDisplay = mode->VDisplay * ((mode->Flags & V_DBLSCAN) ? 2 : 1); 1815 1816 /* 1817 * Is there any LineCompare Bit 10? Where? 1818 * The 9 well known VGA bits give us a maximum height of 1024 1819 */ 1820 if (vDisplay > 1024) 1821 return MODE_BAD; 1822 1823 /* 1824 * Limit the modes to just those allowed by the various NeoMagic 1825 * chips. 1826 */ 1827 1828 if (nPtr->overrideValidate) { 1829 xf86DrvMsg(scrnIndex, X_WARNING, "display mode validation disabled\n"); 1830 } else { 1831 /* 1832 * When the LCD is active, only allow modes that are (1) equal to 1833 * or smaller than the size of the panel and (2) are one of the 1834 * following sizes: 1024x768, 800x600, 640x480. 1835 */ 1836 if (nPtr->internDisp || !nPtr->externDisp) { 1837 /* Is the mode larger than the LCD panel? */ 1838 if ((mode->HDisplay > nPtr->NeoPanelWidth) || 1839 (vDisplay > nPtr->NeoPanelHeight)) { 1840 xf86DrvMsg(scrnIndex,X_INFO, "Removing mode (%dx%d) " 1841 "larger than the LCD panel (%dx%d)\n", 1842 mode->HDisplay, 1843 mode->VDisplay, 1844 nPtr->NeoPanelWidth, 1845 nPtr->NeoPanelHeight); 1846 return(MODE_BAD); 1847 } 1848 1849 /* Is the mode one of the acceptable sizes? */ 1850 switch (mode->HDisplay) { 1851 case 1280: 1852 if (mode->VDisplay == 1024) 1853 return(MODE_OK); 1854 break; 1855 case 1024 : 1856 if (mode->VDisplay == 768) 1857 return(MODE_OK); 1858 if ((mode->VDisplay == 480) && (nPtr->NeoPanelHeight == 480)) 1859 return(MODE_OK); 1860 break; 1861 case 800 : 1862 if (mode->VDisplay == 600) 1863 return(MODE_OK); 1864 if ((mode->VDisplay == 480) && (nPtr->NeoPanelHeight == 480)) 1865 return(MODE_OK); 1866 break; 1867 case 640 : 1868 if (mode->VDisplay == 480) 1869 return(MODE_OK); 1870 break; 1871#if 1 1872 case 320: 1873 if (mode->VDisplay == 240) 1874 return(MODE_OK); 1875 break; 1876#endif 1877 default: 1878 break; 1879 } 1880 1881 xf86DrvMsg(scrnIndex, X_INFO, "Removing mode (%dx%d) that won't " 1882 "display properly on LCD\n", 1883 mode->HDisplay, 1884 mode->VDisplay); 1885 return(MODE_BAD); 1886 } 1887 } 1888 return(MODE_OK); 1889} 1890 1891static void 1892neoLock(ScrnInfoPtr pScrn) 1893{ 1894 vgaHWPtr hwp = VGAHWPTR(pScrn); 1895 1896 VGAwGR(0x09,0x00); 1897 vgaHWLock(hwp); 1898} 1899 1900static void 1901neoUnlock(ScrnInfoPtr pScrn) 1902{ 1903 vgaHWPtr hwp = VGAHWPTR(pScrn); 1904 1905 vgaHWUnlock(hwp); 1906 VGAwGR(0x09,0x26); 1907} 1908 1909static Bool 1910neoMapMem(ScrnInfoPtr pScrn) 1911{ 1912 NEOPtr nPtr = NEOPTR(pScrn); 1913 vgaHWPtr hwp = VGAHWPTR(pScrn); 1914 1915 if (!nPtr->noMMIO) { 1916 if (nPtr->pEnt->location.type == BUS_PCI){ 1917 1918#ifndef XSERVER_LIBPCIACCESS 1919 nPtr->NeoMMIOBase = 1920 xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 1921 nPtr->PciTag, nPtr->NeoMMIOAddr, 1922 0x200000L); 1923 if (nPtr->NeoMMIOAddr2 != 0){ 1924 nPtr->NeoMMIOBase2 = 1925 xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 1926 nPtr->PciTag, nPtr->NeoMMIOAddr2, 1927 0x100000L); 1928 } 1929 1930#else 1931 void** result = (void**)&nPtr->NeoMMIOBase; 1932 int err = pci_device_map_range(nPtr->PciInfo, 1933 nPtr->NeoMMIOAddr, 1934 0x200000L, 1935 PCI_DEV_MAP_FLAG_WRITABLE, 1936 result); 1937 if (err) 1938 return FALSE; 1939 1940 if (nPtr->NeoMMIOAddr2 != 0){ 1941 result = (void**)&nPtr->NeoMMIOBase2; 1942 err = pci_device_map_range(nPtr->PciInfo, 1943 nPtr->NeoMMIOAddr2, 1944 0x100000L, 1945 PCI_DEV_MAP_FLAG_WRITABLE, 1946 result); 1947 1948 if (err) 1949 return FALSE; 1950 } 1951#endif 1952 } else 1953 nPtr->NeoMMIOBase = 1954 xf86MapVidMem(pScrn->scrnIndex, 1955 VIDMEM_MMIO, nPtr->NeoMMIOAddr, 1956 0x200000L); 1957 if (nPtr->NeoMMIOBase == NULL) 1958 return FALSE; 1959 } 1960 1961 if (nPtr->pEnt->location.type == BUS_PCI) 1962 1963#ifndef XSERVER_LIBPCIACCESS 1964 nPtr->NeoFbBase = 1965 xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 1966 nPtr->PciTag, 1967 (unsigned long)nPtr->NeoLinearAddr, 1968 nPtr->NeoFbMapSize); 1969#else 1970 { 1971 void** result = (void**)&nPtr->NeoFbBase; 1972 int err = pci_device_map_range(nPtr->PciInfo, 1973 nPtr->NeoLinearAddr, 1974 nPtr->NeoFbMapSize, 1975 PCI_DEV_MAP_FLAG_WRITABLE | 1976 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 1977 result); 1978 if (err) 1979 return FALSE; 1980 } 1981#endif 1982 else 1983 nPtr->NeoFbBase = 1984 xf86MapVidMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 1985 (unsigned long)nPtr->NeoLinearAddr, 1986 nPtr->NeoFbMapSize); 1987 if (nPtr->NeoFbBase == NULL) 1988 return FALSE; 1989 return TRUE; 1990} 1991 1992/* 1993 * Unmap the framebuffer and MMIO memory. 1994 */ 1995 1996static Bool 1997neoUnmapMem(ScrnInfoPtr pScrn) 1998{ 1999 NEOPtr nPtr = NEOPTR(pScrn); 2000 2001#ifndef XSERVER_LIBPCIACCESS 2002 if (nPtr->NeoMMIOBase) 2003 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)nPtr->NeoMMIOBase, 2004 0x200000L); 2005#else 2006 if (nPtr->NeoMMIOBase) 2007 pci_device_unmap_range(nPtr->PciInfo, (pointer)nPtr->NeoMMIOBase, 0x200000L); 2008#endif 2009 nPtr->NeoMMIOBase = NULL; 2010#ifndef XSERVER_LIBPCIACCESS 2011 if (nPtr->NeoMMIOBase2) 2012 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)nPtr->NeoMMIOBase2, 2013 0x100000L); 2014#else 2015 if (nPtr->NeoMMIOBase2) 2016 pci_device_unmap_range(nPtr->PciInfo, (pointer)nPtr->NeoMMIOBase2, 0x100000L); 2017#endif 2018 nPtr->NeoMMIOBase2 = NULL; 2019#ifndef XSERVER_LIBPCIACCESS 2020 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)nPtr->NeoFbBase, 2021 nPtr->NeoFbMapSize); 2022#else 2023 pci_device_unmap_range(nPtr->PciInfo, (pointer)nPtr->NeoFbBase, nPtr->NeoFbMapSize); 2024#endif 2025 nPtr->NeoFbBase = NULL; 2026 2027 return TRUE; 2028} 2029 2030static void 2031neoSave(ScrnInfoPtr pScrn) 2032{ 2033 vgaRegPtr VgaSave = &VGAHWPTR(pScrn)->SavedReg; 2034 vgaHWPtr hwp = VGAHWPTR(pScrn); 2035 NEOPtr nPtr = NEOPTR(pScrn); 2036 NeoRegPtr save; 2037 int i; 2038 2039 save = &nPtr->NeoSavedReg; 2040 2041 VGAwGR(0x09,0x26); 2042 /* 2043 * Whatever code is needed to get back to bank zero goes here. 2044 */ 2045 VGAwGR(0x15,0x00); 2046 2047 /* get generic registers */ 2048 vgaHWSave(pScrn, VgaSave, VGA_SR_ALL); 2049 2050 /* 2051 * The port I/O code necessary to read in the extended registers 2052 * into the fields of the vgaNeoRec structure goes here. 2053 */ 2054 2055 save->GeneralLockReg = VGArGR(0x0A); 2056 2057 save->ExtCRTDispAddr = VGArGR(0x0E); 2058 if (nPtr->NeoChipset != NM2070) { 2059 save->ExtCRTOffset = VGArGR(0x0F); 2060 } 2061 save->SysIfaceCntl1 = VGArGR(0x10); 2062 save->SysIfaceCntl2 = VGArGR(0x11); 2063 save->SingleAddrPage = VGArGR(0x15); 2064 save->DualAddrPage = VGArGR(0x16); 2065 save->PanelDispCntlReg1 = VGArGR(0x20); 2066 save->PanelDispCntlReg2 = VGArGR(0x25); 2067 save->PanelDispCntlReg3 = VGArGR(0x30); 2068 save->PanelVertCenterReg1 = VGArGR(0x28); 2069 save->PanelVertCenterReg2 = VGArGR(0x29); 2070 save->PanelVertCenterReg3 = VGArGR(0x2A); 2071 if (nPtr->NeoChipset != NM2070) { 2072 save->PanelVertCenterReg4 = VGArGR(0x32); 2073 save->PanelHorizCenterReg1 = VGArGR(0x33); 2074 save->PanelHorizCenterReg2 = VGArGR(0x34); 2075 save->PanelHorizCenterReg3 = VGArGR(0x35); 2076 } 2077 if (nPtr->NeoChipset == NM2160) { 2078 save->PanelHorizCenterReg4 = VGArGR(0x36); 2079 } 2080 if (nPtr->NeoChipset == NM2200 || nPtr->NeoChipset == NM2230 2081 || nPtr->NeoChipset == NM2360 || nPtr->NeoChipset == NM2380) { 2082 save->PanelHorizCenterReg4 = VGArGR(0x36); 2083 save->PanelVertCenterReg5 = VGArGR(0x37); 2084 save->PanelHorizCenterReg5 = VGArGR(0x38); 2085 } 2086 save->ExtColorModeSelect = VGArGR(0x90); 2087 save->VCLK3NumeratorLow = VGArGR(0x9B); 2088 if (nPtr->NeoChipset == NM2200 || nPtr->NeoChipset == NM2230 2089 || nPtr->NeoChipset == NM2360 || nPtr->NeoChipset == NM2380) 2090 save->VCLK3NumeratorHigh = VGArGR(0x8F); 2091 save->VCLK3Denominator = VGArGR(0x9F); 2092 save->ProgramVCLK = TRUE; 2093 2094 if (save->reg == NULL) 2095 save->reg = (regSavePtr)xnfcalloc(sizeof(regSaveRec), 1); 2096 else 2097 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2098 "Non-NULL reg in NeoSave: reg=%p\n", (void *)save->reg); 2099 2100 save->reg->CR[0x23] = VGArCR(0x23); 2101 save->reg->CR[0x25] = VGArCR(0x25); 2102 save->reg->CR[0x2F] = VGArCR(0x2F); 2103 for (i = 0x40; i <= 0x59; i++) { 2104 save->reg->CR[i] = VGArCR(i); 2105 } 2106 for (i = 0x60; i <= 0x69; i++) { 2107 save->reg->CR[i] = VGArCR(i); 2108 } 2109 for (i = 0x70; i <= NEO_EXT_CR_MAX; i++) { 2110 save->reg->CR[i] = VGArCR(i); 2111 } 2112 2113 for (i = 0x0A; i <= NEO_EXT_GR_MAX; i++) { 2114 save->reg->GR[i] = VGArGR(i); 2115 } 2116} 2117 2118/* 2119 * neoProgramShadowRegs 2120 * 2121 * Setup the shadow registers to their default values. The NeoSave 2122 * routines will restore the proper values on server exit. 2123 */ 2124static void 2125neoProgramShadowRegs(ScrnInfoPtr pScrn, vgaRegPtr VgaReg, NeoRegPtr restore) 2126{ 2127 int i; 2128 Bool noProgramShadowRegs; 2129 vgaHWPtr hwp = VGAHWPTR(pScrn); 2130 NEOPtr nPtr = NEOPTR(pScrn); 2131 Bool prog_lcd; 2132 2133 /* 2134 * If display is external only and we want internal 2135 * we need to program the shadow registers. 2136 */ 2137 prog_lcd = (((VGArGR(0x20) & 0x3) == 0x1) && nPtr->internDisp); 2138 2139 2140 /* 2141 * Convoluted logic for shadow register programming. 2142 * 2143 * As far as we know, shadow programming is needed for the 2070, 2144 * but not in stretched modes. Special case this code. 2145 */ 2146 switch (nPtr->NeoChipset) { 2147 case NM2070: 2148 /* Program the shadow regs by default */ 2149 noProgramShadowRegs = FALSE; 2150 if (!nPtr->progLcdRegs && !prog_lcd) 2151 noProgramShadowRegs = TRUE; 2152 2153 if (restore->PanelDispCntlReg2 & 0x84) { 2154 /* Don't program by default if in stretch mode */ 2155 noProgramShadowRegs = TRUE; 2156 if (nPtr->progLcdStretch) 2157 noProgramShadowRegs = FALSE; 2158 } 2159 break; 2160 case NM2090: 2161 case NM2093: 2162 case NM2097: 2163 case NM2160: 2164 case NM2200: 2165 case NM2230: 2166 case NM2360: 2167 case NM2380: 2168 default: 2169 /* Don't program the shadow regs by default */ 2170 noProgramShadowRegs = TRUE; 2171 if (nPtr->progLcdRegs || prog_lcd) 2172 noProgramShadowRegs = FALSE; 2173 2174 if (restore->PanelDispCntlReg2 & 0x84) { 2175 /* Only change the behavior if an option is set */ 2176 if (nPtr->progLcdStretchOpt) 2177 noProgramShadowRegs = !nPtr->progLcdStretch; 2178 } 2179 break; 2180 } 2181 2182 if (noProgramShadowRegs) { 2183 xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,5,"Not programming shadow registers\n"); 2184 if (nPtr->NeoSavedReg.reg){ 2185 for (i = 0x40; i <= 0x59; i++) { 2186 VGAwCR(i, nPtr->NeoSavedReg.reg->CR[i]); 2187 } 2188 for (i = 0x60; i <= 0x64; i++) { 2189 VGAwCR(i, nPtr->NeoSavedReg.reg->CR[i]); 2190 } 2191 } 2192 } else { 2193 /* 2194 * Program the shadow regs based on the panel width. This works 2195 * fine for normal sized panels, but what about the odd ones like 2196 * the Libretto 100 which has an 800x480 panel??? 2197 */ 2198 switch (nPtr->NeoPanelWidth) { 2199 case 640 : 2200 VGAwCR(0x40,0x5F); 2201 VGAwCR(0x41,0x50); 2202 VGAwCR(0x42,0x02); 2203 VGAwCR(0x43,0x55); 2204 VGAwCR(0x44,0x81); 2205 VGAwCR(0x45,0x0B); 2206 VGAwCR(0x46,0x2E); 2207 VGAwCR(0x47,0xEA); 2208 VGAwCR(0x48,0x0C); 2209 VGAwCR(0x49,0xE7); 2210 VGAwCR(0x4A,0x04); 2211 VGAwCR(0x4B,0x2D); 2212 VGAwCR(0x4C,0x28); 2213 VGAwCR(0x4D,0x90); 2214 VGAwCR(0x4E,0x2B); 2215 VGAwCR(0x4F,0xA0); 2216 break; 2217 case 800 : 2218 switch (nPtr->NeoPanelHeight) { 2219 case 600: 2220 VGAwCR(0x40,0x7F); 2221 VGAwCR(0x41,0x63); 2222 VGAwCR(0x42,0x02); 2223 VGAwCR(0x43,0x6C); 2224 VGAwCR(0x44,0x1C); 2225 VGAwCR(0x45,0x72); 2226 VGAwCR(0x46,0xE0); 2227 VGAwCR(0x47,0x58); 2228 VGAwCR(0x48,0x0C); 2229 VGAwCR(0x49,0x57); 2230 VGAwCR(0x4A,0x73); 2231 VGAwCR(0x4B,0x3D); 2232 VGAwCR(0x4C,0x31); 2233 VGAwCR(0x4D,0x01); 2234 VGAwCR(0x4E,0x36); 2235 VGAwCR(0x4F,0x1E); 2236 if (nPtr->NeoChipset != NM2070) { 2237 VGAwCR(0x50,0x6B); 2238 VGAwCR(0x51,0x4F); 2239 VGAwCR(0x52,0x0E); 2240 VGAwCR(0x53,0x58); 2241 VGAwCR(0x54,0x88); 2242 VGAwCR(0x55,0x33); 2243 VGAwCR(0x56,0x27); 2244 VGAwCR(0x57,0x16); 2245 VGAwCR(0x58,0x2C); 2246 VGAwCR(0x59,0x94); 2247 } 2248 break; 2249 case 480: 2250 VGAwCR(0x40,0x7F); 2251 VGAwCR(0x41,0x63); 2252 VGAwCR(0x42,0x02); 2253 VGAwCR(0x43,0x6B); 2254 VGAwCR(0x44,0x1B); 2255 VGAwCR(0x45,0x72); 2256 VGAwCR(0x46,0xE0); 2257 VGAwCR(0x47,0x1C); 2258 VGAwCR(0x48,0x00); 2259 VGAwCR(0x49,0x57); 2260 VGAwCR(0x4A,0x73); 2261 VGAwCR(0x4B,0x3E); 2262 VGAwCR(0x4C,0x31); 2263 VGAwCR(0x4D,0x01); 2264 VGAwCR(0x4E,0x36); 2265 VGAwCR(0x4F,0x1E); 2266 VGAwCR(0x50,0x6B); 2267 VGAwCR(0x51,0x4F); 2268 VGAwCR(0x52,0x0E); 2269 VGAwCR(0x53,0x57); 2270 VGAwCR(0x54,0x87); 2271 VGAwCR(0x55,0x33); 2272 VGAwCR(0x56,0x27); 2273 VGAwCR(0x57,0x16); 2274 VGAwCR(0x58,0x2C); 2275 VGAwCR(0x59,0x94); 2276 break; 2277 break; 2278 /* Not done */ 2279 } 2280 break; 2281 case 1024 : 2282 switch (nPtr->NeoPanelHeight) { 2283 case 768: 2284 VGAwCR(0x40,0xA3); 2285 VGAwCR(0x41,0x7F); 2286 VGAwCR(0x42,0x06); 2287 VGAwCR(0x43,0x85); 2288 VGAwCR(0x44,0x96); 2289 VGAwCR(0x45,0x24); 2290 VGAwCR(0x46,0xE5); 2291 VGAwCR(0x47,0x02); 2292 VGAwCR(0x48,0x08); 2293 VGAwCR(0x49,0xFF); 2294 VGAwCR(0x4A,0x25); 2295 VGAwCR(0x4B,0x4F); 2296 VGAwCR(0x4C,0x40); 2297 VGAwCR(0x4D,0x00); 2298 VGAwCR(0x4E,0x44); 2299 VGAwCR(0x4F,0x0C); 2300 VGAwCR(0x50,0x7A); 2301 VGAwCR(0x51,0x56); 2302 VGAwCR(0x52,0x00); 2303 VGAwCR(0x53,0x5D); 2304 VGAwCR(0x54,0x0E); 2305 VGAwCR(0x55,0x3B); 2306 VGAwCR(0x56,0x2B); 2307 VGAwCR(0x57,0x00); 2308 VGAwCR(0x58,0x2F); 2309 VGAwCR(0x59,0x18); 2310 VGAwCR(0x60,0x88); 2311 VGAwCR(0x61,0x63); 2312 VGAwCR(0x62,0x0B); 2313 VGAwCR(0x63,0x69); 2314 VGAwCR(0x64,0x1A); 2315 break; 2316 case 480: 2317 VGAwCR(0x40,0xA3); 2318 VGAwCR(0x41,0x7F); 2319 VGAwCR(0x42,0x1B); 2320 VGAwCR(0x43,0x89); 2321 VGAwCR(0x44,0x16); 2322 VGAwCR(0x45,0x0B); 2323 VGAwCR(0x46,0x2C); 2324 VGAwCR(0x47,0xE8); 2325 VGAwCR(0x48,0x0C); 2326 VGAwCR(0x49,0xE7); 2327 VGAwCR(0x4A,0x09); 2328 VGAwCR(0x4B,0x4F); 2329 VGAwCR(0x4C,0x40); 2330 VGAwCR(0x4D,0x00); 2331 VGAwCR(0x4E,0x44); 2332 VGAwCR(0x4F,0x0C); 2333 VGAwCR(0x50,0x7A); 2334 VGAwCR(0x51,0x56); 2335 VGAwCR(0x52,0x00); 2336 VGAwCR(0x53,0x5D); 2337 VGAwCR(0x54,0x0E); 2338 VGAwCR(0x55,0x3B); 2339 VGAwCR(0x56,0x2A); 2340 VGAwCR(0x57,0x00); 2341 VGAwCR(0x58,0x2F); 2342 VGAwCR(0x59,0x18); 2343 VGAwCR(0x60,0x88); 2344 VGAwCR(0x61,0x63); 2345 VGAwCR(0x62,0x0B); 2346 VGAwCR(0x63,0x69); 2347 VGAwCR(0x64,0x1A); 2348 break; 2349 } 2350 break; 2351 case 1280: 2352#ifdef NOT_DONE 2353 VGAwCR(0x40,0x?? ); 2354 . 2355 . 2356 . 2357 VGAwCR(0x64,0x?? ); 2358 break; 2359#else 2360 /* Probe should prevent this case for now */ 2361 FatalError("1280 panel support incomplete\n"); 2362#endif 2363 } 2364 } 2365} 2366 2367static void 2368neoRestore(ScrnInfoPtr pScrn, vgaRegPtr VgaReg, NeoRegPtr restore, 2369 Bool restoreText) 2370{ 2371 NEOPtr nPtr = NEOPTR(pScrn); 2372 vgaHWPtr hwp = VGAHWPTR(pScrn); 2373 unsigned char temp; 2374 int i; 2375 Bool clock_hi = FALSE; 2376 2377 vgaHWProtect(pScrn,TRUE); /* Blank the screen */ 2378 2379 VGAwGR(0x09,0x26); 2380 2381 /* Init the shadow registers if necessary */ 2382 neoProgramShadowRegs(pScrn, VgaReg, restore); 2383 2384 VGAwGR(0x15,0x00); 2385 2386 VGAwGR(0x0A,restore->GeneralLockReg); 2387 2388 /* 2389 * The color mode needs to be set before calling vgaHWRestore 2390 * to ensure the DAC is initialized properly. 2391 * 2392 * NOTE: Make sure we don't change bits make sure we don't change 2393 * any reserved bits. 2394 */ 2395 temp = VGArGR(0x90); 2396 2397 switch (nPtr->NeoChipset) { 2398 case NM2070 : 2399 temp &= 0xF0; /* Save bits 7:4 */ 2400 temp |= (restore->ExtColorModeSelect & ~0xF0); 2401 break; 2402 case NM2090 : 2403 case NM2093 : 2404 case NM2097 : 2405 case NM2160 : 2406 case NM2200 : 2407 case NM2230 : 2408 case NM2360 : 2409 case NM2380 : 2410 temp &= 0x70; /* Save bits 6:4 */ 2411 temp |= (restore->ExtColorModeSelect & ~0x70); 2412 break; 2413 } 2414 VGAwGR(0x90,temp); 2415 2416 /* 2417 * In some rare cases a lockup might occur if we don't delay 2418 * here. (Reported by Miles Lane) 2419 */ 2420 usleep(200000); 2421 /* 2422 * Disable horizontal and vertical graphics and text expansions so 2423 * that vgaHWRestore works properly. 2424 */ 2425 temp = VGArGR(0x25); 2426 temp &= 0x39; 2427 VGAwGR(0x25, temp); 2428 2429 /* 2430 * Sleep for 200ms to make sure that the two operations above have 2431 * had time to take effect. 2432 */ 2433 usleep(200000); 2434 /* 2435 * This function handles restoring the generic VGA registers. */ 2436 vgaHWRestore(pScrn, VgaReg, 2437 VGA_SR_MODE 2438 | (restoreText ? (VGA_SR_FONTS | VGA_SR_CMAP) : 0)); 2439 2440 VGAwGR(0x0E, restore->ExtCRTDispAddr); 2441 VGAwGR(0x0F, restore->ExtCRTOffset); 2442 temp = VGArGR(0x10); 2443 temp &= 0x0F; /* Save bits 3:0 */ 2444 temp |= (restore->SysIfaceCntl1 & ~0x0F); 2445 VGAwGR(0x10, temp); 2446 2447 VGAwGR(0x11, restore->SysIfaceCntl2); 2448 VGAwGR(0x15, restore->SingleAddrPage); 2449 VGAwGR(0x16, restore->DualAddrPage); 2450 2451 temp = VGArGR(0x20); 2452 switch (nPtr->NeoChipset) { 2453 case NM2070 : 2454 temp &= 0xFC; /* Save bits 7:2 */ 2455 temp |= (restore->PanelDispCntlReg1 & ~0xFC); 2456 break; 2457 case NM2090 : 2458 case NM2093 : 2459 case NM2097 : 2460 case NM2160 : 2461 temp &= 0xDC; /* Save bits 7:6,4:2 */ 2462 temp |= (restore->PanelDispCntlReg1 & ~0xDC); 2463 break; 2464 case NM2200 : 2465 case NM2230 : 2466 case NM2360 : 2467 case NM2380 : 2468 temp &= 0x98; /* Save bits 7,4:3 */ 2469 temp |= (restore->PanelDispCntlReg1 & ~0x98); 2470 break; 2471 } 2472 VGAwGR(0x20, temp); 2473 2474 temp = VGArGR(0x25); 2475 temp &= 0x38; /* Save bits 5:3 */ 2476 temp |= (restore->PanelDispCntlReg2 & ~0x38); 2477 VGAwGR(0x25, temp); 2478 2479 if (nPtr->NeoChipset != NM2070) { 2480 temp = VGArGR(0x30); 2481 temp &= 0xEF; /* Save bits 7:5 and bits 3:0 */ 2482 temp |= (restore->PanelDispCntlReg3 & ~0xEF); 2483 VGAwGR(0x30, temp); 2484 } 2485 2486 VGAwGR(0x28, restore->PanelVertCenterReg1); 2487 VGAwGR(0x29, restore->PanelVertCenterReg2); 2488 VGAwGR(0x2a, restore->PanelVertCenterReg3); 2489 2490 if (nPtr->NeoChipset != NM2070) { 2491 VGAwGR(0x32, restore->PanelVertCenterReg4); 2492 VGAwGR(0x33, restore->PanelHorizCenterReg1); 2493 VGAwGR(0x34, restore->PanelHorizCenterReg2); 2494 VGAwGR(0x35, restore->PanelHorizCenterReg3); 2495 } 2496 2497 if (nPtr->NeoChipset == NM2160) { 2498 VGAwGR(0x36, restore->PanelHorizCenterReg4); 2499 } 2500 2501 if (nPtr->NeoChipset == NM2200 || nPtr->NeoChipset == NM2230 2502 || nPtr->NeoChipset == NM2360 || nPtr->NeoChipset == NM2380) { 2503 VGAwGR(0x36, restore->PanelHorizCenterReg4); 2504 VGAwGR(0x37, restore->PanelVertCenterReg5); 2505 VGAwGR(0x38, restore->PanelHorizCenterReg5); 2506 } 2507 if (nPtr->NeoChipset == NM2200 || nPtr->NeoChipset == NM2230 2508 || nPtr->NeoChipset == NM2360 || nPtr->NeoChipset == NM2380) 2509 clock_hi = TRUE; 2510 2511 /* Program VCLK3 if needed. */ 2512 if (restore->ProgramVCLK 2513 && ((VGArGR(0x9B) != restore->VCLK3NumeratorLow) 2514 || (VGArGR(0x9F) != restore->VCLK3Denominator) 2515 || (clock_hi && ((VGArGR(0x8F) & ~0x0f) 2516 != (restore->VCLK3NumeratorHigh & ~0x0F))))) { 2517 VGAwGR(0x9B, restore->VCLK3NumeratorLow); 2518 if (clock_hi) { 2519 temp = VGArGR(0x8F); 2520 temp &= 0x0F; /* Save bits 3:0 */ 2521 temp |= (restore->VCLK3NumeratorHigh & ~0x0F); 2522 VGAwGR(0x8F, temp); 2523 } 2524 VGAwGR(0x9F, restore->VCLK3Denominator); 2525 } 2526 if (restore->biosMode) 2527 VGAwCR(0x23,restore->biosMode); 2528 2529 if (restore->reg) { 2530 VGAwCR(0x23,restore->reg->CR[0x23]); 2531 VGAwCR(0x25,restore->reg->CR[0x25]); 2532 VGAwCR(0x2F,restore->reg->CR[0x2F]); 2533 for (i = 0x40; i <= 0x59; i++) { 2534 VGAwCR(i, restore->reg->CR[i]); 2535 } 2536 for (i = 0x60; i <= 0x69; i++) { 2537 VGAwCR(i, restore->reg->CR[i]); 2538 } 2539 for (i = 0x70; i <= NEO_EXT_CR_MAX; i++) { 2540 VGAwCR(i, restore->reg->CR[i]); 2541 } 2542 2543 for (i = 0x0a; i <= 0x3f; i++) { 2544 VGAwGR(i, restore->reg->GR[i]); 2545 } 2546 for (i = 0x90; i <= NEO_EXT_GR_MAX; i++) { 2547 VGAwGR(i, restore->reg->GR[i]); 2548 } 2549 } 2550 2551 VGAwGR (0x93, 0xc0); /* Gives faster framebuffer writes */ 2552 2553 /* Program vertical extension register */ 2554 if (nPtr->NeoChipset == NM2200 || nPtr->NeoChipset == NM2230 2555 || nPtr->NeoChipset == NM2360 || nPtr->NeoChipset == NM2380) { 2556 VGAwCR(0x70, restore->VerticalExt); 2557 } 2558 2559 vgaHWProtect(pScrn, FALSE); /* Turn on screen */ 2560} 2561 2562static Bool 2563neoModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 2564{ 2565 NEOPtr nPtr = NEOPTR(pScrn); 2566 NEOACLPtr nAcl = NEOACLPTR(pScrn); 2567 int hoffset, voffset; 2568 vgaHWPtr hwp = VGAHWPTR(pScrn); 2569 NeoRegPtr NeoNew = &nPtr->NeoModeReg; 2570 vgaRegPtr NeoStd = &hwp->ModeReg; 2571 Bool noLcdStretch = nPtr->noLcdStretch; 2572 int clockMul = 1; 2573 2574 neoUnlock(pScrn); 2575 2576 /* 2577 * This will allocate the datastructure and initialize all of the 2578 * generic VGA registers. 2579 */ 2580 2581 if (!vgaHWInit(pScrn, mode)) 2582 return(FALSE); 2583 2584 /* 2585 * Several registers need to be corrected from the default values 2586 * assigned by vgaHWinit(). 2587 */ 2588 pScrn->vtSema = TRUE; 2589 2590 /* 2591 * The default value assigned by vgaHW.c is 0x41, but this does 2592 * not work for NeoMagic. 2593 */ 2594 NeoStd->Attribute[16] = 0x01; 2595 2596 switch (pScrn->depth) { 2597 case 8 : 2598 NeoStd->CRTC[0x13] = pScrn->displayWidth >> 3; 2599 NeoNew->ExtCRTOffset = pScrn->displayWidth >> 11; 2600 NeoNew->ExtColorModeSelect = 0x11; 2601 break; 2602 case 15 : 2603 NeoNew->ExtColorModeSelect = 0x12; 2604 NeoStd->CRTC[0x13] = pScrn->displayWidth >> 2; 2605 NeoNew->ExtCRTOffset = pScrn->displayWidth >> 10; 2606 break; 2607 case 16 : 2608 NeoNew->ExtColorModeSelect = 0x13; 2609 NeoStd->CRTC[0x13] = pScrn->displayWidth >> 2; 2610 NeoNew->ExtCRTOffset = pScrn->displayWidth >> 10; 2611 break; 2612 case 24 : 2613 NeoStd->CRTC[0x13] = (pScrn->displayWidth * 3) >> 3; 2614 NeoNew->ExtCRTOffset = (pScrn->displayWidth * 3) >> 11; 2615 NeoNew->ExtColorModeSelect = 0x14; 2616 break; 2617 default : 2618 break; 2619 } 2620 2621 NeoNew->ExtCRTDispAddr = 0x10; 2622 2623 /* Vertical Extension */ 2624 NeoNew->VerticalExt = (((mode->CrtcVTotal -2) & 0x400) >> 10 ) 2625 | (((mode->CrtcVDisplay -1) & 0x400) >> 9 ) 2626 | (((mode->CrtcVSyncStart) & 0x400) >> 8 ) 2627 | (((mode->CrtcVBlankStart - 1) & 0x400) >> 7 ); 2628 2629 /* Fast write bursts on unless disabled. */ 2630 if (nPtr->onPciBurst) { 2631 NeoNew->SysIfaceCntl1 = 0x30; 2632 } else { 2633 NeoNew->SysIfaceCntl1 = 0x00; 2634 } 2635 2636 /* If they are used, enable linear addressing and/or enable MMIO. */ 2637 NeoNew->SysIfaceCntl2 = 0x00; 2638 NeoNew->SysIfaceCntl2 |= 0x80; 2639 if (!nPtr->noMMIO) 2640 NeoNew->SysIfaceCntl2 |= 0x40; 2641 2642 /* Enable any user specified display devices. */ 2643 NeoNew->PanelDispCntlReg1 = 0x00; 2644 if (nPtr->internDisp) { 2645 NeoNew->PanelDispCntlReg1 |= 0x02; 2646 } 2647 if (nPtr->externDisp) { 2648 NeoNew->PanelDispCntlReg1 |= 0x01; 2649 } 2650 2651#if 0 2652 /* 2653 * This was replaced: if no devices are specified take the 2654 * probed settings. If the probed settings are bogus fallback 2655 * to internal only. 2656 */ 2657 /* If the user did not specify any display devices, then... */ 2658 if (NeoNew->PanelDispCntlReg1 == 0x00) { 2659 /* Default to internal (i.e., LCD) only. */ 2660 NeoNew->PanelDispCntlReg1 |= 0x02; 2661 } 2662#endif 2663 /* If we are using a fixed mode, then tell the chip we are. */ 2664 switch (mode->HDisplay) { 2665 case 1280: 2666 NeoNew->PanelDispCntlReg1 |= 0x60; 2667 break; 2668 case 1024: 2669 NeoNew->PanelDispCntlReg1 |= 0x40; 2670 break; 2671 case 800: 2672 NeoNew->PanelDispCntlReg1 |= 0x20; 2673 break; 2674 case 640: 2675 default: 2676 break; 2677 } 2678 2679 /* Setup shadow register locking. */ 2680 switch (NeoNew->PanelDispCntlReg1 & 0x03) { 2681 case 0x01 : /* External CRT only mode: */ 2682 NeoNew->GeneralLockReg = 0x00; 2683 /* We need to program the VCLK for external display only mode. */ 2684 NeoNew->ProgramVCLK = TRUE; 2685 break; 2686 case 0x02 : /* Internal LCD only mode: */ 2687 case 0x03 : /* Simultaneous internal/external (LCD/CRT) mode: */ 2688 NeoNew->GeneralLockReg = 0x01; 2689 /* Don't program the VCLK when using the LCD. */ 2690 NeoNew->ProgramVCLK = FALSE; 2691 break; 2692 } 2693 2694 /* 2695 * If the screen is to be stretched, turn on stretching for the 2696 * various modes. 2697 * 2698 * OPTION_LCD_STRETCH means stretching should be turned off! 2699 */ 2700 NeoNew->PanelDispCntlReg2 = 0x00; 2701 NeoNew->PanelDispCntlReg3 = 0x00; 2702 nAcl->NoCursorMode = FALSE; 2703 2704 if ((!noLcdStretch) && 2705 (NeoNew->PanelDispCntlReg1 & 0x02)) { 2706 if (mode->HDisplay == nPtr->NeoPanelWidth) { 2707 /* 2708 * Don't disable the flag. It will be needed if another mode 2709 * is selected. 2710 */ 2711 /* 2712 * No stretching required when the requested display width 2713 * equals the panel width. 2714 */ 2715 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Stretching disabled\n"); 2716 noLcdStretch = TRUE; 2717 } else { 2718 2719 switch (mode->HDisplay) { 2720 case 320 : /* Needs testing. KEM -- 24 May 98 */ 2721 case 400 : /* Needs testing. KEM -- 24 May 98 */ 2722 case 640 : 2723 case 800 : 2724 case 1024 : 2725 NeoNew->PanelDispCntlReg2 |= 0xC6; 2726 nAcl->NoCursorMode = TRUE; 2727 break; 2728 default : 2729 /* No stretching in these modes. */ 2730 xf86DrvMsg(pScrn->scrnIndex,X_INFO, 2731 "Stretching disabled not supported in this mode\n"); 2732 noLcdStretch = TRUE; 2733 break; 2734 } 2735 } 2736 } else if (mode->Flags & V_DBLSCAN) { 2737 nAcl->NoCursorMode = TRUE; 2738 } 2739 2740 /* 2741 * If the screen is to be centerd, turn on the centering for the 2742 * various modes. 2743 */ 2744 NeoNew->PanelVertCenterReg1 = 0x00; 2745 NeoNew->PanelVertCenterReg2 = 0x00; 2746 NeoNew->PanelVertCenterReg3 = 0x00; 2747 NeoNew->PanelVertCenterReg4 = 0x00; 2748 NeoNew->PanelVertCenterReg5 = 0x00; 2749 NeoNew->PanelHorizCenterReg1 = 0x00; 2750 NeoNew->PanelHorizCenterReg2 = 0x00; 2751 NeoNew->PanelHorizCenterReg3 = 0x00; 2752 NeoNew->PanelHorizCenterReg4 = 0x00; 2753 NeoNew->PanelHorizCenterReg5 = 0x00; 2754 2755 if (nPtr->lcdCenter && 2756 (NeoNew->PanelDispCntlReg1 & 0x02)) { 2757 Bool doCenter = FALSE; 2758 2759 hoffset = 0; 2760 voffset = 0; 2761 if (mode->HDisplay == nPtr->NeoPanelWidth) { 2762 /* 2763 * No centering required when the requested display width 2764 * equals the panel width. 2765 */ 2766 } else { 2767 NeoNew->PanelDispCntlReg3 |= 0x10; 2768 if (noLcdStretch) { 2769 /* Calculate the horizontal offsets. */ 2770 int HDisplay = mode->HDisplay 2771 << ((mode->VDisplay < 480) ? 1 : 0); 2772 hoffset = ((nPtr->NeoPanelWidth - HDisplay) >> 4) - 1; 2773 if (mode->VDisplay < 480) 2774 hoffset >>= 1; 2775 doCenter = TRUE; 2776 } else { 2777 /* Stretched modes cannot be centered. */ 2778 hoffset = 0; 2779 } 2780 } 2781 if (mode->VDisplay == nPtr->NeoPanelHeight) { 2782 /* 2783 * No centering required when the requested display width 2784 * equals the panel width. 2785 */ 2786 } else { 2787 NeoNew->PanelDispCntlReg2 |= 0x01; 2788 if (noLcdStretch) { 2789 /* Calculate the vertical offsets. */ 2790 int VDisplay = mode->VDisplay 2791 << ((mode->Flags & V_DBLSCAN) ? 1 : 0); 2792 voffset = ((nPtr->NeoPanelHeight - VDisplay) >> 1) - 2; 2793 doCenter = TRUE; 2794 } else { 2795 /* Stretched modes cannot be centered. */ 2796 voffset = 0; 2797 } 2798 } 2799 2800 if (doCenter) { 2801 switch (mode->HDisplay) { 2802 case 320 : /* Needs testing. KEM -- 24 May 98 */ 2803 NeoNew->PanelHorizCenterReg3 = hoffset; 2804 NeoNew->PanelVertCenterReg3 = voffset; 2805 break; 2806 case 400 : /* Needs testing. KEM -- 24 May 98 */ 2807 NeoNew->PanelHorizCenterReg4 = hoffset; 2808 NeoNew->PanelVertCenterReg1 = voffset; 2809 break; 2810 case 640 : 2811 NeoNew->PanelHorizCenterReg1 = hoffset; 2812 NeoNew->PanelVertCenterReg3 = voffset; 2813 break; 2814 case 800 : 2815 NeoNew->PanelHorizCenterReg2 = hoffset; 2816 switch (mode->VDisplay) { 2817 case 600: 2818 NeoNew->PanelVertCenterReg4 = voffset; 2819 break; 2820 case 480: 2821 /* Not sure if this is correct */ 2822 NeoNew->PanelVertCenterReg3 = voffset; 2823 break; 2824 } 2825 break; 2826 case 1024 : 2827 NeoNew->PanelHorizCenterReg5 = hoffset; 2828 NeoNew->PanelVertCenterReg5 = voffset; 2829 break; 2830 case 1280 : 2831 default : 2832 /* No centering in these modes. */ 2833 break; 2834 } 2835 } 2836 } 2837 2838 if (!noLcdStretch && 2839 (NeoNew->PanelDispCntlReg1 & 0x02)) { 2840 if (mode->HDisplay != nPtr->NeoPanelWidth) 2841 nPtr->videoHZoom = (double)nPtr->NeoPanelWidth/mode->HDisplay; 2842 if (mode->VDisplay != nPtr->NeoPanelHeight) 2843 nPtr->videoVZoom = (double)nPtr->NeoPanelHeight/mode->VDisplay; 2844 } else { 2845 nPtr->videoHZoom = 1.0; 2846 nPtr->videoVZoom = 1.0; 2847 } 2848 /* Do double scan */ 2849 if (mode->VDisplay < 480) { 2850 NeoStd->Sequencer[1] |= 0x8; 2851 clockMul = 2; 2852 } 2853 2854 NeoNew->biosMode = neoFindMode(mode->HDisplay,mode->VDisplay,pScrn->depth); 2855 2856 /* 2857 * New->reg should be empty. Just in 2858 * case it isn't, warn us and clear it anyway. 2859 */ 2860 if (NeoNew->reg) { 2861 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2862 "Non-NULL reg in NeoInit: reg=%p\n", (void *)NeoNew->reg); 2863 xfree(NeoNew->reg); 2864 NeoNew->reg = NULL; 2865 } 2866 2867 /* 2868 * Calculate the VCLK that most closely matches the requested dot 2869 * clock. 2870 */ 2871 neoCalcVCLK(pScrn, mode->SynthClock*clockMul); 2872 2873 /* Since we program the clocks ourselves, always use VCLK3. */ 2874 NeoStd->MiscOutReg |= 0x0C; 2875 2876 neoRestore(pScrn, NeoStd, NeoNew, FALSE); 2877 2878 return(TRUE); 2879} 2880 2881/* 2882 * neoCalcVCLK -- 2883 * 2884 * Determine the closest clock frequency to the one requested. 2885 */ 2886#define REF_FREQ 14.31818 2887#define MAX_N 127 2888#define MAX_D 31 2889#define MAX_F 1 2890 2891static void 2892neoCalcVCLK(ScrnInfoPtr pScrn, long freq) 2893{ 2894 NEOPtr nPtr = NEOPTR(pScrn); 2895 2896 int n, d, f; 2897 double f_out; 2898 double f_diff; 2899 int n_best = 0, d_best = 1, f_best = 0; 2900 double f_best_diff = 999999.0; 2901 double f_target = freq/1000.0; 2902 2903 for (f = 0; f <= MAX_F; f++) 2904 for (n = 0; n <= MAX_N; n++) 2905 for (d = 1; d <= MAX_D; d++) { 2906 f_out = (n+1.0)/((d+1.0)*(1<<f))*REF_FREQ; 2907 f_diff = abs(f_out-f_target); 2908 if (f_diff < f_best_diff) { 2909 f_best_diff = f_diff; 2910 n_best = n; 2911 d_best = d; 2912 f_best = f; 2913 } 2914 } 2915 2916 if (nPtr->NeoChipset == NM2200 || nPtr->NeoChipset == NM2230 2917 || nPtr->NeoChipset == NM2360 || nPtr->NeoChipset == NM2380) { 2918 /* NOT_DONE: We are trying the full range of the 2200 clock. 2919 We should be able to try n up to 2047 */ 2920 nPtr->NeoModeReg.VCLK3NumeratorLow = n_best; 2921 nPtr->NeoModeReg.VCLK3NumeratorHigh = (f_best << 7); 2922 } 2923 else { 2924 nPtr->NeoModeReg.VCLK3NumeratorLow = n_best | (f_best << 7); 2925 } 2926 nPtr->NeoModeReg.VCLK3Denominator = d_best; 2927#ifdef DEBUG 2928 ErrorF("neoVCLK: f:%f NumLow=%i NumHi=%i Den=%i Df=%f\n", 2929 f_target, 2930 nPtr->NeoModeReg.VCLK3NumeratorLow, 2931 nPtr->NeoModeReg.VCLK3NumeratorHigh, 2932 nPtr->NeoModeReg.VCLK3Denominator, 2933 f_best_diff); 2934#endif 2935} 2936 2937/* 2938 * NeoDisplayPowerManagementSet -- 2939 * 2940 * Sets VESA Display Power Management Signaling (DPMS) Mode. 2941 */ 2942static void 2943NeoDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, 2944 int flags) 2945{ 2946 NEOPtr nPtr = NEOPTR(pScrn); 2947 vgaHWPtr hwp = VGAHWPTR(pScrn); 2948 unsigned char SEQ01 = 0; 2949 unsigned char LogicPowerMgmt = 0; 2950 unsigned char LCD_on = 0; 2951 2952 if (!pScrn->vtSema) 2953 return; 2954 2955 switch (PowerManagementMode) { 2956 case DPMSModeOn: 2957 /* Screen: On; HSync: On, VSync: On */ 2958 SEQ01 = 0x00; 2959 LogicPowerMgmt = 0x00; 2960 if (nPtr->internDisp || ! nPtr->externDisp) 2961 LCD_on = 0x02; 2962 else 2963 LCD_on = 0x00; 2964 break; 2965 case DPMSModeStandby: 2966 /* Screen: Off; HSync: Off, VSync: On */ 2967 SEQ01 = 0x20; 2968 LogicPowerMgmt = 0x10; 2969 LCD_on = 0x00; 2970 break; 2971 case DPMSModeSuspend: 2972 /* Screen: Off; HSync: On, VSync: Off */ 2973 SEQ01 = 0x20; 2974 LogicPowerMgmt = 0x20; 2975 LCD_on = 0x00; 2976 break; 2977 case DPMSModeOff: 2978 /* Screen: Off; HSync: Off, VSync: Off */ 2979 SEQ01 = 0x20; 2980 LogicPowerMgmt = 0x30; 2981 LCD_on = 0x00; 2982 break; 2983 } 2984 2985 /* Turn the screen on/off */ 2986 SEQ01 |= VGArSR(0x01) & ~0x20; 2987 VGAwSR(0x01, SEQ01); 2988 2989 /* Turn the LCD on/off */ 2990 LCD_on |= VGArGR(0x20) & ~0x02; 2991 VGAwGR(0x20, LCD_on); 2992 2993 /* Set the DPMS mode */ 2994 LogicPowerMgmt |= 0x80; 2995 LogicPowerMgmt |= VGArGR(0x01) & ~0xF0; 2996 VGAwGR(0x01,LogicPowerMgmt); 2997} 2998 2999static unsigned int 3000neo_ddc1Read(ScrnInfoPtr pScrn) 3001{ 3002 register vgaHWPtr hwp = VGAHWPTR(pScrn); 3003 register unsigned int tmp; 3004 3005 /* This needs to be investigated: we may have to swap this around */ 3006 while (!(hwp->readST01(hwp)&0x8)) {}; 3007 while (hwp->readST01(hwp)&0x8) {}; 3008 3009 tmp = (VGArGR(0xA1) & 0x08); 3010 3011 return (tmp); 3012} 3013 3014static xf86MonPtr 3015neo_ddc1(int scrnIndex) 3016{ 3017 vgaHWPtr hwp = VGAHWPTR(xf86Screens[scrnIndex]); 3018 unsigned int reg1, reg2, reg3; 3019 xf86MonPtr ret; 3020 3021 /* initialize chipset */ 3022 reg1 = VGArCR(0x21); 3023 reg2 = VGArCR(0x1D); 3024 reg3 = VGArCR(0xA1); 3025 VGAwCR(0x21,0x00); 3026 VGAwCR(0x1D,0x01); /* some Voodoo */ 3027 VGAwGR(0xA1,0x2F); 3028 ret = xf86DoEDID_DDC1(scrnIndex,vgaHWddc1SetSpeedWeak(),neo_ddc1Read); 3029 /* undo initialization */ 3030 VGAwCR(0x21,reg1); 3031 VGAwCR(0x1D,reg2); 3032 VGAwGR(0xA1,reg3); 3033 return ret; 3034} 3035 3036static Bool 3037neoDoDDC1(ScrnInfoPtr pScrn) 3038{ 3039 Bool ret = FALSE; 3040 vgaHWPtr hwp = VGAHWPTR(pScrn); 3041 3042 VGAwGR(0x09,0x26); 3043 ret = xf86SetDDCproperties(pScrn, 3044 xf86PrintEDID(neo_ddc1(pScrn->scrnIndex))); 3045 VGAwGR(0x09,0x00); 3046 3047 return ret; 3048} 3049 3050static Bool 3051neoDoDDC2(ScrnInfoPtr pScrn) 3052{ 3053 NEOPtr nPtr = NEOPTR(pScrn); 3054 vgaHWPtr hwp = VGAHWPTR(pScrn); 3055 Bool ret = FALSE; 3056 3057 VGAwGR(0x09,0x26); 3058 if (xf86LoadSubModule(pScrn, "i2c")) { 3059 if (neo_I2CInit(pScrn)) { 3060 ret = xf86SetDDCproperties(pScrn,xf86PrintEDID(xf86DoEDID_DDC2( 3061 pScrn->scrnIndex,nPtr->I2C))); 3062 } 3063 } 3064 VGAwGR(0x09,0x00); 3065 3066 return ret; 3067} 3068 3069static Bool 3070neoDoDDCVBE(ScrnInfoPtr pScrn) 3071{ 3072 NEOPtr nPtr = NEOPTR(pScrn); 3073 vgaHWPtr hwp = VGAHWPTR(pScrn); 3074 vbeInfoPtr pVbe; 3075 Bool ret = FALSE; 3076 3077 VGAwGR(0x09,0x26); 3078 if (xf86LoadSubModule(pScrn, "vbe")) { 3079 if ((pVbe = VBEInit(NULL,nPtr->pEnt->index))) { 3080 ret = xf86SetDDCproperties( 3081 pScrn,xf86PrintEDID(vbeDoEDID(pVbe,NULL))); 3082 vbeFree(pVbe); 3083 } 3084 } 3085 VGAwGR(0x09,0x00); 3086 return ret; 3087} 3088 3089static int 3090neoFindMode(int xres, int yres, int depth) 3091{ 3092 int xres_s; 3093 int i, size; 3094 biosMode *mode; 3095 3096 switch (depth) { 3097 case 8: 3098 size = sizeof(bios8) / sizeof(biosMode); 3099 mode = bios8; 3100 break; 3101 case 15: 3102 size = sizeof(bios15) / sizeof(biosMode); 3103 mode = bios15; 3104 break; 3105 case 16: 3106 size = sizeof(bios16) / sizeof(biosMode); 3107 mode = bios16; 3108 break; 3109 case 24: 3110 size = sizeof(bios24) / sizeof(biosMode); 3111 mode = bios24; 3112 break; 3113 default: 3114 return 0; 3115 } 3116 3117 for (i = 0; i < size; i++) { 3118 if (xres <= mode[i].x_res) { 3119 xres_s = mode[i].x_res; 3120 for (; i < size; i++) { 3121 if (mode[i].x_res != xres_s) 3122 return mode[i-1].mode; 3123 if (yres <= mode[i].y_res) 3124 return mode[i].mode; 3125 } 3126 } 3127 } 3128 return mode[size - 1].mode; 3129 3130} 3131 3132static void 3133neoProbeDDC(ScrnInfoPtr pScrn, int index) 3134{ 3135 vbeInfoPtr pVbe; 3136 3137 if (xf86LoadSubModule(pScrn, "vbe")) { 3138 if ((pVbe = VBEInit(NULL,index))) { 3139 ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 3140 vbeFree(pVbe); 3141 } 3142 } 3143} 3144