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