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