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