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