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