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