neo_driver.c revision 2f60eb46
1692f60a7Smrg/********************************************************************** 2692f60a7SmrgCopyright 1998, 1999 by Precision Insight, Inc., Cedar Park, Texas. 3692f60a7Smrg 4692f60a7Smrg All Rights Reserved 5692f60a7Smrg 6692f60a7SmrgPermission to use, copy, modify, distribute, and sell this software and 7692f60a7Smrgits documentation for any purpose is hereby granted without fee, 8692f60a7Smrgprovided that the above copyright notice appear in all copies and that 9692f60a7Smrgboth that copyright notice and this permission notice appear in 10692f60a7Smrgsupporting documentation, and that the name of Precision Insight not be 11692f60a7Smrgused in advertising or publicity pertaining to distribution of the 12692f60a7Smrgsoftware without specific, written prior permission. Precision Insight 13692f60a7Smrgand its suppliers make no representations about the suitability of this 14692f60a7Smrgsoftware for any purpose. It is provided "as is" without express or 15692f60a7Smrgimplied warranty. 16692f60a7Smrg 17692f60a7SmrgPRECISION INSIGHT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18692f60a7SmrgINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19692f60a7SmrgEVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY 20692f60a7SmrgSPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 21692f60a7SmrgRESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 22692f60a7SmrgCONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 23692f60a7SmrgCONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 24692f60a7Smrg**********************************************************************/ 25692f60a7Smrg 26692f60a7Smrg/* 27692f60a7Smrg * Copyright 1998, 1999 Egbert Eich 28692f60a7Smrg * Copyright 2000, 2001 SuSE GmbH, Author: Egbert Eich 29692f60a7Smrg * Copyright 2002 SuSE Linux AG, Author: Egbert Eich 30692f60a7Smrg * Copyright 2002 Shigehiro Nomura 31692f60a7Smrg */ 32692f60a7Smrg 33692f60a7Smrg 34692f60a7Smrg/* 35692f60a7Smrg * The original Precision Insight driver for 36692f60a7Smrg * XFree86 v.3.3 has been sponsored by Red Hat. 37692f60a7Smrg * 38692f60a7Smrg * Authors: 39692f60a7Smrg * Jens Owen (jens@tungstengraphics.com) 40692f60a7Smrg * Kevin E. Martin (kevin@precisioninsight.com) 41692f60a7Smrg * 42692f60a7Smrg * Port to Xfree86 v.4.0 43692f60a7Smrg * 1998, 1999 by Egbert Eich (Egbert.Eich@Physik.TU-Darmstadt.DE) 44692f60a7Smrg */ 45692f60a7Smrg 46692f60a7Smrg#ifdef HAVE_CONFIG_H 47692f60a7Smrg#include "config.h" 48692f60a7Smrg#endif 49692f60a7Smrg 50692f60a7Smrg/* All drivers should typically include these */ 51692f60a7Smrg#include "xf86.h" 52692f60a7Smrg#include "xf86_OSproc.h" 53692f60a7Smrg 54692f60a7Smrg/* Everything using inb/outb, etc needs "compiler.h" */ 55692f60a7Smrg#include "compiler.h" 56692f60a7Smrg 572e71ea71Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 58692f60a7Smrg#include "xf86Resources.h" 592e71ea71Smrg/* Needed by Resources Access Control (RAC) */ 602e71ea71Smrg#include "xf86RAC.h" 612e71ea71Smrg#endif 62692f60a7Smrg 63692f60a7Smrg/* Drivers that need to access the PCI config space directly need this */ 64692f60a7Smrg#include "xf86Pci.h" 65692f60a7Smrg 66692f60a7Smrg/* All drivers using the vgahw module need this */ 67692f60a7Smrg#include "vgaHW.h" 68692f60a7Smrg 69692f60a7Smrg/* All drivers initialising the SW cursor need this */ 70692f60a7Smrg#include "mipointer.h" 71692f60a7Smrg 72692f60a7Smrg/* All drivers using the mi colormap manipulation need this */ 73692f60a7Smrg#include "micmap.h" 74692f60a7Smrg 75692f60a7Smrg#include "xf86cmap.h" 76692f60a7Smrg 77692f60a7Smrg#include "fb.h" 78692f60a7Smrg 79692f60a7Smrg/* int10 */ 80692f60a7Smrg#include "xf86int10.h" 81692f60a7Smrg#include "vbe.h" 82692f60a7Smrg 83692f60a7Smrg/* Needed for Device Data Channel (DDC) support */ 84692f60a7Smrg#include "xf86DDC.h" 85692f60a7Smrg 86692f60a7Smrg#include "picturestr.h" 87692f60a7Smrg 88692f60a7Smrg#include "xf86xv.h" 89692f60a7Smrg#include <X11/extensions/Xv.h> 90692f60a7Smrg 91692f60a7Smrg/* 92692f60a7Smrg * Driver data structures. 93692f60a7Smrg */ 94692f60a7Smrg#include "neo.h" 95692f60a7Smrg#include "neo_reg.h" 96692f60a7Smrg#include "neo_macros.h" 97692f60a7Smrg 98692f60a7Smrg/* These need to be checked */ 99692f60a7Smrg#include <X11/X.h> 100692f60a7Smrg#include <X11/Xproto.h> 101692f60a7Smrg#include "scrnintstr.h" 102692f60a7Smrg#include "servermd.h" 103c3c9db83Smrg 1043f6d0e1dSmrg#include <stdlib.h> 105c3c9db83Smrg#include <unistd.h> 106692f60a7Smrg 107692f60a7Smrg/* Mandatory functions */ 108692f60a7Smrgstatic const OptionInfoRec * NEOAvailableOptions(int chipid, int busid); 109692f60a7Smrgstatic void NEOIdentify(int flags); 110692f60a7Smrgstatic Bool NEOProbe(DriverPtr drv, int flags); 111692f60a7Smrgstatic Bool NEOPreInit(ScrnInfoPtr pScrn, int flags); 1123f6d0e1dSmrgstatic Bool NEOScreenInit(SCREEN_INIT_ARGS_DECL); 1133f6d0e1dSmrgstatic Bool NEOEnterVT(VT_FUNC_ARGS_DECL); 1143f6d0e1dSmrgstatic void NEOLeaveVT(VT_FUNC_ARGS_DECL); 1153f6d0e1dSmrgstatic Bool NEOCloseScreen(CLOSE_SCREEN_ARGS_DECL); 1163f6d0e1dSmrgstatic void NEOFreeScreen(FREE_SCREEN_ARGS_DECL); 1173f6d0e1dSmrgstatic ModeStatus NEOValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, 118692f60a7Smrg Bool verbose, int flags); 119692f60a7Smrg 120692f60a7Smrg/* Internally used functions */ 1212f60eb46Smrg#ifdef HAVE_ISA 122692f60a7Smrgstatic int neoFindIsaDevice(GDevPtr dev); 1232f60eb46Smrg#endif 124692f60a7Smrgstatic Bool neoModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); 125692f60a7Smrgstatic void neoSave(ScrnInfoPtr pScrn); 126692f60a7Smrgstatic void neoRestore(ScrnInfoPtr pScrn, vgaRegPtr VgaReg, 127692f60a7Smrg NeoRegPtr NeoReg, Bool restoreText); 128692f60a7Smrgstatic void neoLock(ScrnInfoPtr pScrn); 129692f60a7Smrgstatic void neoUnlock(ScrnInfoPtr pScrn); 130692f60a7Smrgstatic Bool neoMapMem(ScrnInfoPtr pScrn); 131692f60a7Smrgstatic Bool neoUnmapMem(ScrnInfoPtr pScrn); 132692f60a7Smrgstatic void neoProgramShadowRegs(ScrnInfoPtr pScrn, vgaRegPtr VgaReg, 133692f60a7Smrg NeoRegPtr restore); 134692f60a7Smrgstatic void neoCalcVCLK(ScrnInfoPtr pScrn, long freq); 1353f6d0e1dSmrgstatic xf86MonPtr neo_ddc1(ScrnInfoPtr pScrn); 136692f60a7Smrgstatic Bool neoDoDDC1(ScrnInfoPtr pScrn); 137692f60a7Smrgstatic Bool neoDoDDC2(ScrnInfoPtr pScrn); 138692f60a7Smrgstatic Bool neoDoDDCVBE(ScrnInfoPtr pScrn); 139692f60a7Smrgstatic void neoProbeDDC(ScrnInfoPtr pScrn, int index); 140692f60a7Smrgstatic void NeoDisplayPowerManagementSet(ScrnInfoPtr pScrn, 141692f60a7Smrg int PowerManagementMode, int flags); 142692f60a7Smrgstatic int neoFindMode(int xres, int yres, int depth); 143692f60a7Smrg 144692f60a7Smrg#define NEO_VERSION 4000 145692f60a7Smrg#define NEO_NAME "NEOMAGIC" 146692f60a7Smrg#define NEO_DRIVER_NAME "neomagic" 147692f60a7Smrg 14854569438Smrg#define NEO_MAJOR_VERSION PACKAGE_VERSION_MAJOR 14954569438Smrg#define NEO_MINOR_VERSION PACKAGE_VERSION_MINOR 15054569438Smrg#define NEO_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL 151692f60a7Smrg 152692f60a7Smrg/* 153692f60a7Smrg * This is intentionally screen-independent. It indicates the binding 154692f60a7Smrg * choice made in the first PreInit. 155692f60a7Smrg */ 156692f60a7Smrgstatic int pix24bpp = 0; 157692f60a7Smrg 158692f60a7Smrg 159692f60a7Smrgstatic biosMode bios8[] = { 160692f60a7Smrg { 320, 240, 0x40 }, 161692f60a7Smrg { 300, 400, 0x42 }, 162692f60a7Smrg { 640, 400, 0x20 }, 163692f60a7Smrg { 640, 480, 0x21 }, 164692f60a7Smrg { 800, 600, 0x23 }, 165692f60a7Smrg { 1024, 768, 0x25 } 166692f60a7Smrg}; 167692f60a7Smrg 168692f60a7Smrgstatic biosMode bios15[] = { 169692f60a7Smrg { 320, 200, 0x2D }, 170692f60a7Smrg { 640, 480, 0x30 }, 171692f60a7Smrg { 800, 600, 0x33 }, 172692f60a7Smrg { 1024, 768, 0x36 } 173692f60a7Smrg}; 174692f60a7Smrg 175692f60a7Smrgstatic biosMode bios16[] = { 176692f60a7Smrg { 320, 200, 0x2e }, 177692f60a7Smrg { 320, 240, 0x41 }, 178692f60a7Smrg { 300, 400, 0x43 }, 179692f60a7Smrg { 640, 480, 0x31 }, 180692f60a7Smrg { 800, 600, 0x34 }, 181692f60a7Smrg { 1024, 768, 0x37 } 182692f60a7Smrg}; 183692f60a7Smrg 184692f60a7Smrgstatic biosMode bios24[] = { 185692f60a7Smrg { 640, 480, 0x32 }, 186692f60a7Smrg { 800, 600, 0x35 }, 187692f60a7Smrg { 1024, 768, 0x38 } 188692f60a7Smrg}; 189692f60a7Smrg 190692f60a7Smrgstatic DisplayModeRec neo800x480Mode = { 191692f60a7Smrg NULL, /* prev */ 192692f60a7Smrg NULL, /* next */ 193692f60a7Smrg "800x480", /* identifier of this mode */ 194692f60a7Smrg MODE_OK, /* mode status */ 195692f60a7Smrg M_T_BUILTIN, /* mode type */ 196692f60a7Smrg 35260, /* Clock frequency */ 197692f60a7Smrg 800, /* HDisplay */ 198692f60a7Smrg 856, /* HSyncStart */ 199692f60a7Smrg 1040, /* HSyncEnd */ 200692f60a7Smrg 1056, /* HTotal */ 201692f60a7Smrg 0, /* HSkew */ 202692f60a7Smrg 480, /* VDisplay */ 203692f60a7Smrg 480, /* VSyncStart */ 204692f60a7Smrg 486, /* VSyncEnd */ 205692f60a7Smrg 488, /* VTotal */ 206692f60a7Smrg 0, /* VScan */ 207692f60a7Smrg V_PHSYNC | V_PVSYNC, /* Flags */ 208692f60a7Smrg -1, /* ClockIndex */ 209692f60a7Smrg 35260, /* SynthClock */ 210692f60a7Smrg 800, /* CRTC HDisplay */ 211692f60a7Smrg 800, /* CRTC HBlankStart */ 212692f60a7Smrg 856, /* CRTC HSyncStart */ 213692f60a7Smrg 1040, /* CRTC HSyncEnd */ 214692f60a7Smrg 872, /* CRTC HBlankEnd */ 215692f60a7Smrg 1048, /* CRTC HTotal */ 216692f60a7Smrg 0, /* CRTC HSkew */ 217692f60a7Smrg 480, /* CRTC VDisplay */ 218692f60a7Smrg 480, /* CRTC VBlankStart */ 219692f60a7Smrg 480, /* CRTC VSyncStart */ 220692f60a7Smrg 486, /* CRTC VSyncEnd */ 221692f60a7Smrg 487, /* CRTC VBlankEnd */ 222692f60a7Smrg 488, /* CRTC VTotal */ 223692f60a7Smrg FALSE, /* CrtcHAdjusted */ 224692f60a7Smrg FALSE, /* CrtcVAdjusted */ 225692f60a7Smrg 0, /* PrivSize */ 226692f60a7Smrg NULL, /* Private */ 227692f60a7Smrg 0.0, /* HSync */ 228692f60a7Smrg 0.0 /* VRefresh */ 229692f60a7Smrg}; 230692f60a7Smrg 231692f60a7Smrgstatic DisplayModeRec neo1024x480Mode = { 232692f60a7Smrg NULL, /* prev */ 233692f60a7Smrg NULL, /* next */ 234692f60a7Smrg "1024x480", /* identifier of this mode */ 235692f60a7Smrg MODE_OK, /* mode status */ 236692f60a7Smrg M_T_BUILTIN, /* mode type */ 237692f60a7Smrg 45900, /* Clock frequency */ 238692f60a7Smrg 1024, /* HDisplay */ 239692f60a7Smrg 1048, /* HSyncStart */ 240692f60a7Smrg 1184, /* HSyncEnd */ 241692f60a7Smrg 1344, /* HTotal */ 242692f60a7Smrg 0, /* HSkew */ 243692f60a7Smrg 480, /* VDisplay */ 244692f60a7Smrg 480, /* VSyncStart */ 245692f60a7Smrg 486, /* VSyncEnd */ 246692f60a7Smrg 488, /* VTotal */ 247692f60a7Smrg 0, /* VScan */ 248692f60a7Smrg V_PHSYNC | V_PVSYNC, /* Flags */ 249692f60a7Smrg -1, /* ClockIndex */ 250692f60a7Smrg 45900, /* SynthClock */ 251692f60a7Smrg 1024, /* CRTC HDisplay */ 252692f60a7Smrg 1024, /* CRTC HBlankStart */ 253692f60a7Smrg 1048, /* CRTC HSyncStart */ 254692f60a7Smrg 1184, /* CRTC HSyncEnd */ 255692f60a7Smrg 1072, /* CRTC HBlankEnd */ 256692f60a7Smrg 1344, /* CRTC HTotal */ 257692f60a7Smrg 0, /* CRTC HSkew */ 258692f60a7Smrg 480, /* CRTC VDisplay */ 259692f60a7Smrg 480, /* CRTC VBlankStart */ 260692f60a7Smrg 480, /* CRTC VSyncStart */ 261692f60a7Smrg 486, /* CRTC VSyncEnd */ 262692f60a7Smrg 487, /* CRTC VBlankEnd */ 263692f60a7Smrg 488, /* CRTC VTotal */ 264692f60a7Smrg FALSE, /* CrtcHAdjusted */ 265692f60a7Smrg FALSE, /* CrtcVAdjusted */ 266692f60a7Smrg 0, /* PrivSize */ 267692f60a7Smrg NULL, /* Private */ 268692f60a7Smrg 0.0, /* HSync */ 269692f60a7Smrg 0.0 /* VRefresh */ 270692f60a7Smrg}; 271692f60a7Smrg 272692f60a7Smrg/* 273692f60a7Smrg * This contains the functions needed by the server after loading the driver 274692f60a7Smrg * module. It must be supplied, and gets passed back by the SetupProc 275692f60a7Smrg * function in the dynamic case. In the static case, a reference to this 276692f60a7Smrg * is compiled in, and this requires that the name of this DriverRec be 277692f60a7Smrg * an upper-case version of the driver name. 278692f60a7Smrg */ 279692f60a7Smrg 280692f60a7Smrg_X_EXPORT DriverRec NEOMAGIC = { 281692f60a7Smrg NEO_VERSION, 282692f60a7Smrg NEO_DRIVER_NAME, 283692f60a7Smrg NEOIdentify, 284692f60a7Smrg NEOProbe, 285692f60a7Smrg NEOAvailableOptions, 286692f60a7Smrg NULL, 287692f60a7Smrg 0 288692f60a7Smrg}; 289692f60a7Smrg 290692f60a7Smrgstatic SymTabRec NEOChipsets[] = { 291692f60a7Smrg { NM2070, "neo2070" }, 292692f60a7Smrg { NM2090, "neo2090" }, 293692f60a7Smrg { NM2093, "neo2093" }, 294692f60a7Smrg { NM2097, "neo2097" }, 295692f60a7Smrg { NM2160, "neo2160" }, 296692f60a7Smrg { NM2200, "neo2200" }, 297692f60a7Smrg { NM2230, "neo2230" }, 298692f60a7Smrg { NM2360, "neo2360" }, 299692f60a7Smrg { NM2380, "neo2380" }, 300692f60a7Smrg { -1, NULL } 301692f60a7Smrg}; 302692f60a7Smrg 303692f60a7Smrg/* Conversion PCI ID to chipset name */ 304692f60a7Smrgstatic PciChipsets NEOPCIchipsets[] = { 305692f60a7Smrg { NM2070, PCI_CHIP_NM2070, RES_SHARED_VGA }, 306692f60a7Smrg { NM2090, PCI_CHIP_NM2090, RES_SHARED_VGA }, 307692f60a7Smrg { NM2093, PCI_CHIP_NM2093, RES_SHARED_VGA }, 308692f60a7Smrg { NM2097, PCI_CHIP_NM2097, RES_SHARED_VGA }, 309692f60a7Smrg { NM2160, PCI_CHIP_NM2160, RES_SHARED_VGA }, 310692f60a7Smrg { NM2200, PCI_CHIP_NM2200, RES_SHARED_VGA }, 311692f60a7Smrg { NM2230, PCI_CHIP_NM2230, RES_SHARED_VGA }, 312692f60a7Smrg { NM2360, PCI_CHIP_NM2360, RES_SHARED_VGA }, 313692f60a7Smrg { NM2380, PCI_CHIP_NM2380, RES_SHARED_VGA }, 314692f60a7Smrg { -1, -1, RES_UNDEFINED} 315692f60a7Smrg}; 316692f60a7Smrg 31754569438Smrg#ifdef HAVE_ISA 318692f60a7Smrgstatic IsaChipsets NEOISAchipsets[] = { 319692f60a7Smrg { NM2070, RES_EXCLUSIVE_VGA }, 320692f60a7Smrg { NM2090, RES_EXCLUSIVE_VGA }, 321692f60a7Smrg { NM2093, RES_EXCLUSIVE_VGA }, 322692f60a7Smrg { NM2097, RES_EXCLUSIVE_VGA }, 323692f60a7Smrg { NM2160, RES_EXCLUSIVE_VGA }, 324692f60a7Smrg { NM2200, RES_EXCLUSIVE_VGA }, 325692f60a7Smrg { -1, RES_UNDEFINED } 326692f60a7Smrg}; 32754569438Smrg#endif 328692f60a7Smrg 329692f60a7Smrg/* The options supported by the Neomagic Driver */ 330692f60a7Smrgtypedef enum { 331692f60a7Smrg OPTION_NOACCEL, 332692f60a7Smrg OPTION_SW_CURSOR, 333692f60a7Smrg OPTION_NO_MMIO, 334692f60a7Smrg OPTION_INTERN_DISP, 335692f60a7Smrg OPTION_EXTERN_DISP, 336692f60a7Smrg OPTION_LCD_CENTER, 337692f60a7Smrg OPTION_LCD_STRETCH, 338692f60a7Smrg OPTION_SHADOW_FB, 339692f60a7Smrg OPTION_PCI_BURST, 340692f60a7Smrg OPTION_PROG_LCD_MODE_REGS, 341692f60a7Smrg OPTION_PROG_LCD_MODE_STRETCH, 342692f60a7Smrg OPTION_OVERRIDE_VALIDATE_MODE, 343692f60a7Smrg OPTION_SHOWCACHE, 344692f60a7Smrg OPTION_ROTATE, 345692f60a7Smrg OPTION_VIDEO_KEY, 346692f60a7Smrg OPTION_OVERLAYMEM, 347692f60a7Smrg OPTION_VIDEO_INTERLACE, 348692f60a7Smrg OPTION_DISPLAY_HEIGHT_480, 349692f60a7Smrg OPTION_STRANGE_LOCKUPS 350692f60a7Smrg} NEOOpts; 351692f60a7Smrg 352692f60a7Smrgstatic const OptionInfoRec NEO_2070_Options[] = { 353692f60a7Smrg { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 354692f60a7Smrg { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, 355692f60a7Smrg { OPTION_NO_MMIO, "noMMIO", OPTV_BOOLEAN, {0}, FALSE }, 356692f60a7Smrg { OPTION_INTERN_DISP,"internDisp", OPTV_BOOLEAN, {0}, FALSE }, 357692f60a7Smrg { OPTION_EXTERN_DISP,"externDisp", OPTV_BOOLEAN, {0}, FALSE }, 358692f60a7Smrg { OPTION_LCD_CENTER, "LcdCenter", OPTV_BOOLEAN, {0}, FALSE }, 359692f60a7Smrg { OPTION_LCD_STRETCH, "NoStretch", OPTV_BOOLEAN, {0}, FALSE }, 360692f60a7Smrg { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, 361692f60a7Smrg { OPTION_PCI_BURST, "pciBurst", OPTV_BOOLEAN, {0}, FALSE }, 362692f60a7Smrg { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, 363692f60a7Smrg { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, 364692f60a7Smrg { OPTION_PROG_LCD_MODE_REGS, "progLcdModeRegs", 365692f60a7Smrg OPTV_BOOLEAN, {0}, FALSE }, 366692f60a7Smrg { OPTION_PROG_LCD_MODE_STRETCH, "progLcdModeStretch", 367692f60a7Smrg OPTV_BOOLEAN, {0}, FALSE }, 368692f60a7Smrg { OPTION_OVERRIDE_VALIDATE_MODE, "overrideValidateMode", 369692f60a7Smrg OPTV_BOOLEAN, {0}, FALSE }, 370692f60a7Smrg { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, 371692f60a7Smrg { OPTION_OVERLAYMEM, "OverlayMem", OPTV_INTEGER, {0}, FALSE }, 372692f60a7Smrg { OPTION_VIDEO_INTERLACE, "Interlace", 373692f60a7Smrg OPTV_INTEGER, {0}, FALSE }, 374692f60a7Smrg { -1, NULL, OPTV_NONE, {0}, FALSE } 375692f60a7Smrg}; 376692f60a7Smrg 377692f60a7Smrgstatic const OptionInfoRec NEOOptions[] = { 378692f60a7Smrg { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 379692f60a7Smrg { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, 380692f60a7Smrg { OPTION_NO_MMIO, "noMMIO", OPTV_BOOLEAN, {0}, FALSE }, 381692f60a7Smrg { OPTION_INTERN_DISP,"internDisp", OPTV_BOOLEAN, {0}, FALSE }, 382692f60a7Smrg { OPTION_EXTERN_DISP,"externDisp", OPTV_BOOLEAN, {0}, FALSE }, 383692f60a7Smrg { OPTION_LCD_CENTER, "LcdCenter", OPTV_BOOLEAN, {0}, FALSE }, 384692f60a7Smrg { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, 385692f60a7Smrg { OPTION_LCD_STRETCH,"NoStretch", OPTV_BOOLEAN, {0}, FALSE }, 386692f60a7Smrg { OPTION_PCI_BURST, "pciBurst", OPTV_BOOLEAN, {0}, FALSE }, 387692f60a7Smrg { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, 388692f60a7Smrg { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, 389692f60a7Smrg { OPTION_STRANGE_LOCKUPS, "StrangeLockups", OPTV_BOOLEAN, {0}, FALSE }, 390692f60a7Smrg { OPTION_DISPLAY_HEIGHT_480, "DisplayHeight480", 391692f60a7Smrg OPTV_BOOLEAN, {0}, FALSE }, 392692f60a7Smrg { OPTION_PROG_LCD_MODE_REGS, "progLcdModeRegs", 393692f60a7Smrg OPTV_BOOLEAN, {0}, FALSE }, 394692f60a7Smrg { OPTION_PROG_LCD_MODE_STRETCH, "progLcdModeStretch", 395692f60a7Smrg OPTV_BOOLEAN, {0}, FALSE }, 396692f60a7Smrg { OPTION_OVERRIDE_VALIDATE_MODE, "overrideValidateMode", 397692f60a7Smrg OPTV_BOOLEAN, {0}, FALSE }, 398692f60a7Smrg { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, 399692f60a7Smrg { OPTION_OVERLAYMEM, "OverlayMem", OPTV_INTEGER, {0}, FALSE }, 400692f60a7Smrg { OPTION_VIDEO_INTERLACE, "Interlace", 401692f60a7Smrg OPTV_INTEGER, {0}, FALSE }, 402692f60a7Smrg { -1, NULL, OPTV_NONE, {0}, FALSE } 403692f60a7Smrg}; 404692f60a7Smrg 405692f60a7Smrg#ifdef XFree86LOADER 406692f60a7Smrg 407692f60a7Smrgstatic MODULESETUPPROTO(neoSetup); 408692f60a7Smrg 409692f60a7Smrgstatic XF86ModuleVersionInfo neoVersRec = 410692f60a7Smrg{ 411692f60a7Smrg "neomagic", 412692f60a7Smrg MODULEVENDORSTRING, 413692f60a7Smrg MODINFOSTRING1, 414692f60a7Smrg MODINFOSTRING2, 415692f60a7Smrg XORG_VERSION_CURRENT, 416692f60a7Smrg NEO_MAJOR_VERSION, NEO_MINOR_VERSION, NEO_PATCHLEVEL, 417692f60a7Smrg ABI_CLASS_VIDEODRV, 418692f60a7Smrg ABI_VIDEODRV_VERSION, 419692f60a7Smrg MOD_CLASS_VIDEODRV, 420692f60a7Smrg {0,0,0,0} 421692f60a7Smrg}; 422692f60a7Smrg 423692f60a7Smrg/* 424692f60a7Smrg * This is the module init data. 425692f60a7Smrg * Its name has to be the driver name followed by ModuleData 426692f60a7Smrg */ 427692f60a7Smrg_X_EXPORT XF86ModuleData neomagicModuleData = { &neoVersRec, neoSetup, NULL }; 428692f60a7Smrg 429692f60a7Smrgstatic pointer 430692f60a7SmrgneoSetup(pointer module, pointer opts, int *errmaj, int *errmin) 431692f60a7Smrg{ 432692f60a7Smrg static Bool setupDone = FALSE; 433692f60a7Smrg 434692f60a7Smrg if (!setupDone) { 435692f60a7Smrg setupDone = TRUE; 436692f60a7Smrg xf86AddDriver(&NEOMAGIC, module, 0); 437692f60a7Smrg 438692f60a7Smrg /* 439692f60a7Smrg * The return value must be non-NULL on success even though there 440692f60a7Smrg * is no TearDownProc. 441692f60a7Smrg */ 442692f60a7Smrg return (pointer)1; 443692f60a7Smrg } else { 444692f60a7Smrg if (errmaj) *errmaj = LDR_ONCEONLY; 445692f60a7Smrg return NULL; 446692f60a7Smrg } 447692f60a7Smrg} 448692f60a7Smrg 449692f60a7Smrg#endif /* XFree86LOADER */ 450692f60a7Smrg 451692f60a7Smrgstatic Bool 452692f60a7SmrgNEOGetRec(ScrnInfoPtr pScrn) 453692f60a7Smrg{ 454692f60a7Smrg /* 455692f60a7Smrg * Allocate a NEORec, and hook it into pScrn->driverPrivate. 456692f60a7Smrg * pScrn->driverPrivate is initialised to NULL, so we can check if 457692f60a7Smrg * the allocation has already been done. 458692f60a7Smrg */ 459692f60a7Smrg if (pScrn->driverPrivate != NULL) 460692f60a7Smrg return TRUE; 461692f60a7Smrg 462692f60a7Smrg pScrn->driverPrivate = xnfcalloc(sizeof(NEORec), 1); 463692f60a7Smrg 464692f60a7Smrg if (pScrn->driverPrivate == NULL) 465692f60a7Smrg return FALSE; 466692f60a7Smrg return TRUE; 467692f60a7Smrg} 468692f60a7Smrg 469692f60a7Smrgstatic void 470692f60a7SmrgNEOFreeRec(ScrnInfoPtr pScrn) 471692f60a7Smrg{ 472692f60a7Smrg if (pScrn->driverPrivate == NULL) 473692f60a7Smrg return; 4743f6d0e1dSmrg free(pScrn->driverPrivate); 475692f60a7Smrg pScrn->driverPrivate = NULL; 476692f60a7Smrg} 477692f60a7Smrg 478692f60a7Smrgstatic const OptionInfoRec * 479692f60a7SmrgNEOAvailableOptions(int chipid, int busid) 480692f60a7Smrg{ 481692f60a7Smrg int chip = (chipid & 0x0000ffff); 482692f60a7Smrg 483692f60a7Smrg if (chip == PCI_CHIP_NM2070) 484692f60a7Smrg return NEO_2070_Options; 485692f60a7Smrg else 486692f60a7Smrg return NEOOptions; 487692f60a7Smrg} 488692f60a7Smrg 489692f60a7Smrg/* Mandatory */ 490692f60a7Smrgstatic void 491692f60a7SmrgNEOIdentify(int flags) 492692f60a7Smrg{ 493692f60a7Smrg xf86PrintChipsets(NEO_NAME, "Driver for Neomagic chipsets", 494692f60a7Smrg NEOChipsets); 495692f60a7Smrg} 496692f60a7Smrg 497692f60a7Smrg/* Mandatory */ 498692f60a7Smrgstatic Bool 499692f60a7SmrgNEOProbe(DriverPtr drv, int flags) 500692f60a7Smrg{ 501692f60a7Smrg Bool foundScreen = FALSE; 502692f60a7Smrg int numDevSections, numUsed; 503692f60a7Smrg GDevPtr *devSections; 504692f60a7Smrg int *usedChips; 505692f60a7Smrg int i; 506692f60a7Smrg 507692f60a7Smrg /* 508692f60a7Smrg * Find the config file Device sections that match this 509692f60a7Smrg * driver, and return if there are none. 510692f60a7Smrg */ 511692f60a7Smrg if ((numDevSections = xf86MatchDevice(NEO_DRIVER_NAME, 512692f60a7Smrg &devSections)) <= 0) { 513692f60a7Smrg return FALSE; 514692f60a7Smrg } 515692f60a7Smrg 516692f60a7Smrg /* PCI BUS */ 51754569438Smrg#ifndef XSERVER_LIBPCIACCESS 51854569438Smrg if (xf86GetPciVideoInfo() ) 51954569438Smrg#endif 52054569438Smrg { 521692f60a7Smrg numUsed = xf86MatchPciInstances(NEO_NAME, PCI_VENDOR_NEOMAGIC, 522692f60a7Smrg NEOChipsets, NEOPCIchipsets, 523692f60a7Smrg devSections,numDevSections, 524692f60a7Smrg drv, &usedChips); 525692f60a7Smrg 526692f60a7Smrg if (numUsed > 0) { 527692f60a7Smrg if (flags & PROBE_DETECT) 528692f60a7Smrg foundScreen = TRUE; 529692f60a7Smrg else for (i = 0; i < numUsed; i++) { 530692f60a7Smrg ScrnInfoPtr pScrn = NULL; 531692f60a7Smrg /* Allocate a ScrnInfoRec and claim the slot */ 532692f60a7Smrg if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], 533692f60a7Smrg NEOPCIchipsets,NULL, NULL, 534692f60a7Smrg NULL, NULL, NULL))) { 535692f60a7Smrg pScrn->driverVersion = NEO_VERSION; 536692f60a7Smrg pScrn->driverName = NEO_DRIVER_NAME; 537692f60a7Smrg pScrn->name = NEO_NAME; 538692f60a7Smrg pScrn->Probe = NEOProbe; 539692f60a7Smrg pScrn->PreInit = NEOPreInit; 540692f60a7Smrg pScrn->ScreenInit = NEOScreenInit; 541692f60a7Smrg pScrn->SwitchMode = NEOSwitchMode; 542692f60a7Smrg pScrn->AdjustFrame = NEOAdjustFrame; 543692f60a7Smrg pScrn->EnterVT = NEOEnterVT; 544692f60a7Smrg pScrn->LeaveVT = NEOLeaveVT; 545692f60a7Smrg pScrn->FreeScreen = NEOFreeScreen; 546692f60a7Smrg pScrn->ValidMode = NEOValidMode; 547692f60a7Smrg foundScreen = TRUE; 548692f60a7Smrg } 549692f60a7Smrg } 5503f6d0e1dSmrg free(usedChips); 551692f60a7Smrg } 552692f60a7Smrg } 55354569438Smrg 55454569438Smrg#ifdef HAVE_ISA 555692f60a7Smrg /* Isa Bus */ 556692f60a7Smrg 557692f60a7Smrg numUsed = xf86MatchIsaInstances(NEO_NAME,NEOChipsets,NEOISAchipsets, 558692f60a7Smrg drv,neoFindIsaDevice,devSections, 559692f60a7Smrg numDevSections,&usedChips); 560692f60a7Smrg if (numUsed > 0) { 561692f60a7Smrg if (flags & PROBE_DETECT) 562692f60a7Smrg foundScreen = TRUE; 563692f60a7Smrg else for (i = 0; i < numUsed; i++) { 564692f60a7Smrg ScrnInfoPtr pScrn = NULL; 565692f60a7Smrg if ((pScrn = xf86ConfigIsaEntity(pScrn, 0, usedChips[i], 566692f60a7Smrg NEOISAchipsets, NULL, NULL, 567692f60a7Smrg NULL, NULL, NULL))) { 568692f60a7Smrg pScrn->driverVersion = NEO_VERSION; 569692f60a7Smrg pScrn->driverName = NEO_DRIVER_NAME; 570692f60a7Smrg pScrn->name = NEO_NAME; 571692f60a7Smrg pScrn->Probe = NEOProbe; 572692f60a7Smrg pScrn->PreInit = NEOPreInit; 573692f60a7Smrg pScrn->ScreenInit = NEOScreenInit; 574692f60a7Smrg pScrn->SwitchMode = NEOSwitchMode; 575692f60a7Smrg pScrn->AdjustFrame = NEOAdjustFrame; 576692f60a7Smrg pScrn->EnterVT = NEOEnterVT; 577692f60a7Smrg pScrn->LeaveVT = NEOLeaveVT; 578692f60a7Smrg pScrn->FreeScreen = NEOFreeScreen; 579692f60a7Smrg pScrn->ValidMode = NEOValidMode; 580692f60a7Smrg foundScreen = TRUE; 581692f60a7Smrg } 582692f60a7Smrg } 5833f6d0e1dSmrg free(usedChips); 584692f60a7Smrg } 58554569438Smrg#endif 586692f60a7Smrg 5873f6d0e1dSmrg free(devSections); 588692f60a7Smrg return foundScreen; 589692f60a7Smrg} 590692f60a7Smrg 59154569438Smrg#ifdef HAVE_ISA 592692f60a7Smrgstatic int 593692f60a7SmrgneoFindIsaDevice(GDevPtr dev) 594692f60a7Smrg{ 595692f60a7Smrg unsigned int vgaIOBase; 596692f60a7Smrg unsigned char id; 597692f60a7Smrg 598692f60a7Smrg vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0; 599692f60a7Smrg /* §§§ Too intrusive ? */ 600692f60a7Smrg outw(GRAX, 0x2609); /* Unlock NeoMagic registers */ 601692f60a7Smrg 602692f60a7Smrg outb(vgaIOBase + 4, 0x1A); 603692f60a7Smrg id = inb(vgaIOBase + 5); 604692f60a7Smrg 605692f60a7Smrg outw(GRAX, 0x0009); /* Lock NeoMagic registers */ 606692f60a7Smrg 607692f60a7Smrg switch (id) { 608692f60a7Smrg case PROBED_NM2070 : 609692f60a7Smrg return NM2070; 610692f60a7Smrg case PROBED_NM2090 : 611692f60a7Smrg return NM2090; 612692f60a7Smrg case PROBED_NM2093 : 613692f60a7Smrg return NM2093; 614692f60a7Smrg default : 615692f60a7Smrg return -1; 616692f60a7Smrg } 617692f60a7Smrg} 61854569438Smrg#endif 619692f60a7Smrg 620692f60a7Smrg/* Mandatory */ 621692f60a7SmrgBool 622692f60a7SmrgNEOPreInit(ScrnInfoPtr pScrn, int flags) 623692f60a7Smrg{ 624692f60a7Smrg ClockRangePtr clockRanges; 625692f60a7Smrg int i; 626692f60a7Smrg NEOPtr nPtr; 627692f60a7Smrg vgaHWPtr hwp; 628692f60a7Smrg int bppSupport = NoDepth24Support; 629692f60a7Smrg int videoRam = 896; 630692f60a7Smrg int maxClock = 65000; 631692f60a7Smrg int CursorMem = 1024; 632692f60a7Smrg int CursorOff = 0x100; 633692f60a7Smrg int linearSize = 1024; 634692f60a7Smrg int maxWidth = 1024; 635692f60a7Smrg int maxHeight = 1024; 636692f60a7Smrg unsigned char type, dpy; 637692f60a7Smrg int w; 638692f60a7Smrg int apertureSize; 639692f60a7Smrg Bool height_480 = FALSE; 640692f60a7Smrg Bool lcdCenterOptSet = FALSE; 64195903e71Smrg const char *s; 642692f60a7Smrg 643692f60a7Smrg if (flags & PROBE_DETECT) { 644692f60a7Smrg neoProbeDDC( pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index ); 645692f60a7Smrg return TRUE; 646692f60a7Smrg } 647692f60a7Smrg 648692f60a7Smrg /* The vgahw module should be loaded here when needed */ 649692f60a7Smrg if (!xf86LoadSubModule(pScrn, "vgahw")) 650692f60a7Smrg return FALSE; 651692f60a7Smrg 652692f60a7Smrg /* 653692f60a7Smrg * Allocate a vgaHWRec. 654692f60a7Smrg */ 655692f60a7Smrg if (!vgaHWGetHWRec(pScrn)) 656692f60a7Smrg return FALSE; 657692f60a7Smrg hwp = VGAHWPTR(pScrn); 6583f6d0e1dSmrg vgaHWSetStdFuncs(hwp); 659692f60a7Smrg 660692f60a7Smrg /* Allocate the NeoRec driverPrivate */ 661692f60a7Smrg if (!NEOGetRec(pScrn)) { 662692f60a7Smrg return FALSE; 663692f60a7Smrg } 664692f60a7Smrg# define RETURN \ 665692f60a7Smrg { NEOFreeRec(pScrn);\ 666692f60a7Smrg return FALSE;\ 667692f60a7Smrg } 668692f60a7Smrg 669692f60a7Smrg nPtr = NEOPTR(pScrn); 670692f60a7Smrg 671692f60a7Smrg /* Since, the capabilities are determined by the chipset the very 672692f60a7Smrg * first thing to do is, figure out the chipset and its capabilities 673692f60a7Smrg */ 674692f60a7Smrg /* This driver doesn't expect more than one entity per screen */ 675692f60a7Smrg if (pScrn->numEntities > 1) 676692f60a7Smrg RETURN; 677692f60a7Smrg 678692f60a7Smrg /* This is the general case */ 679692f60a7Smrg for (i = 0; i<pScrn->numEntities; i++) { 680692f60a7Smrg nPtr->pEnt = xf86GetEntityInfo(pScrn->entityList[i]); 6812e71ea71Smrg#ifndef XSERVER_LIBPCIACCESS 682692f60a7Smrg if (nPtr->pEnt->resources) return FALSE; 6832e71ea71Smrg#endif 684692f60a7Smrg nPtr->NeoChipset = nPtr->pEnt->chipset; 685692f60a7Smrg pScrn->chipset = (char *)xf86TokenToString(NEOChipsets, 686692f60a7Smrg nPtr->pEnt->chipset); 687692f60a7Smrg /* This driver can handle ISA and PCI buses */ 688692f60a7Smrg if (nPtr->pEnt->location.type == BUS_PCI) { 689692f60a7Smrg nPtr->PciInfo = xf86GetPciInfoForEntity(nPtr->pEnt->index); 69054569438Smrg#ifndef XSERVER_LIBPCIACCESS 691692f60a7Smrg nPtr->PciTag = pciTag(nPtr->PciInfo->bus, 692692f60a7Smrg nPtr->PciInfo->device, 693692f60a7Smrg nPtr->PciInfo->func); 69454569438Smrg#endif 695692f60a7Smrg } 696692f60a7Smrg } 697692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Chipset is a "); 698692f60a7Smrg switch(nPtr->NeoChipset){ 699692f60a7Smrg case NM2070: 700692f60a7Smrg xf86ErrorF("MagicGraph 128 (NM2070)"); 701692f60a7Smrg break; 702692f60a7Smrg case NM2090 : 703692f60a7Smrg xf86ErrorF("MagicGraph 128V (NM2090)"); 704692f60a7Smrg break; 705692f60a7Smrg case NM2093 : 706692f60a7Smrg xf86ErrorF("MagicGraph 128ZV (NM2093)"); 707692f60a7Smrg break; 708692f60a7Smrg case NM2097 : 709692f60a7Smrg xf86ErrorF("MagicGraph 128ZV+ (NM2097)"); 710692f60a7Smrg break; 711692f60a7Smrg case NM2160 : 712692f60a7Smrg xf86ErrorF("MagicGraph 128XD (NM2160)"); 713692f60a7Smrg break; 714692f60a7Smrg case NM2200 : 715692f60a7Smrg xf86ErrorF("MagicMedia 256AV (NM2200)"); 716692f60a7Smrg break; 717692f60a7Smrg case NM2230 : 718692f60a7Smrg xf86ErrorF("MagicMedia 256AV+ (NM2230)"); 719692f60a7Smrg break; 720692f60a7Smrg case NM2360 : 721692f60a7Smrg xf86ErrorF("MagicMedia 256ZX (NM2360)"); 722692f60a7Smrg break; 723692f60a7Smrg case NM2380 : 724692f60a7Smrg xf86ErrorF("MagicMedia 256XL+ (NM2380)"); 725692f60a7Smrg break; 726692f60a7Smrg } 727692f60a7Smrg xf86ErrorF("\n"); 728692f60a7Smrg 729692f60a7Smrg vgaHWGetIOBase(hwp); 730692f60a7Smrg nPtr->vgaIOBase = hwp->IOBase; 731692f60a7Smrg vgaHWSetStdFuncs(hwp); 732692f60a7Smrg 733692f60a7Smrg /* Determine the panel type */ 734692f60a7Smrg VGAwGR(0x09,0x26); 735692f60a7Smrg type = VGArGR(0x21); 736692f60a7Smrg dpy = VGArGR(0x20); 737692f60a7Smrg 738692f60a7Smrg /* Determine panel width -- used in NeoValidMode. */ 739692f60a7Smrg w = VGArGR(0x20); 740692f60a7Smrg VGAwGR(0x09,0x00); 741692f60a7Smrg switch ((w & 0x18) >> 3) { 742692f60a7Smrg case 0x00 : 743692f60a7Smrg nPtr->NeoPanelWidth = 640; 744692f60a7Smrg nPtr->NeoPanelHeight = 480; 745692f60a7Smrg break; 746692f60a7Smrg case 0x01 : 747692f60a7Smrg nPtr->NeoPanelWidth = 800; 748692f60a7Smrg nPtr->NeoPanelHeight = 600; 749692f60a7Smrg break; 750692f60a7Smrg case 0x02 : 751692f60a7Smrg nPtr->NeoPanelWidth = 1024; 752692f60a7Smrg nPtr->NeoPanelHeight = 768; 753692f60a7Smrg break; 754692f60a7Smrg case 0x03 : 755692f60a7Smrg /* 1280x1024 panel support needs to be added */ 756692f60a7Smrg#ifdef NOT_DONE 757692f60a7Smrg nPtr->NeoPanelWidth = 1280; 758692f60a7Smrg nPtr->NeoPanelHeight = 1024; 759692f60a7Smrg break; 760692f60a7Smrg#else 761692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 762692f60a7Smrg "Only 640x480,\n" 763692f60a7Smrg " 800x600,\n" 764692f60a7Smrg " and 1024x768 panels are currently supported\n"); 765692f60a7Smrg return FALSE; 766692f60a7Smrg#endif 767692f60a7Smrg default : 768692f60a7Smrg nPtr->NeoPanelWidth = 640; 769692f60a7Smrg nPtr->NeoPanelHeight = 480; 770692f60a7Smrg break; 771692f60a7Smrg } 772692f60a7Smrg 773692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Panel is a %dx%d %s %s display\n", 774692f60a7Smrg nPtr->NeoPanelWidth, 775692f60a7Smrg nPtr->NeoPanelHeight, 776692f60a7Smrg (type & 0x02) ? "color" : "monochrome", 777692f60a7Smrg (type & 0x10) ? "TFT" : "dual scan"); 778692f60a7Smrg 779692f60a7Smrg 780692f60a7Smrg switch (nPtr->NeoChipset){ 781692f60a7Smrg case NM2070: 782692f60a7Smrg bppSupport = NoDepth24Support; 783692f60a7Smrg videoRam = 896; 784692f60a7Smrg maxClock = 65000; 785692f60a7Smrg CursorMem = 2048; 786692f60a7Smrg CursorOff = 0x100; 787692f60a7Smrg linearSize = 1024; 788692f60a7Smrg maxWidth = 1024; 789692f60a7Smrg maxHeight = 1024; 790692f60a7Smrg break; 791692f60a7Smrg case NM2090: 792692f60a7Smrg case NM2093: 793692f60a7Smrg bppSupport = Support24bppFb | Support32bppFb | 794692f60a7Smrg SupportConvert32to24 | PreferConvert32to24; 795692f60a7Smrg videoRam = 1152; 796692f60a7Smrg maxClock = 80000; 797692f60a7Smrg CursorMem = 2048; 798692f60a7Smrg CursorOff = 0x100; 799692f60a7Smrg linearSize = 2048; 800692f60a7Smrg maxWidth = 1024; 801692f60a7Smrg maxHeight = 1024; 802692f60a7Smrg break; 803692f60a7Smrg case NM2097: 804692f60a7Smrg bppSupport = Support24bppFb | Support32bppFb | 805692f60a7Smrg SupportConvert32to24 | PreferConvert32to24; 806692f60a7Smrg videoRam = 1152; 807692f60a7Smrg maxClock = 80000; 808692f60a7Smrg CursorMem = 1024; 809692f60a7Smrg CursorOff = 0x100; 810692f60a7Smrg linearSize = 2048; 811692f60a7Smrg maxWidth = 1024; 812692f60a7Smrg maxHeight = 1024; 813692f60a7Smrg break; 814692f60a7Smrg case NM2160: 815692f60a7Smrg bppSupport = Support24bppFb | Support32bppFb | 816692f60a7Smrg SupportConvert32to24 | PreferConvert32to24; 817692f60a7Smrg videoRam = 2048; 818692f60a7Smrg maxClock = 90000; 819692f60a7Smrg CursorMem = 1024; 820692f60a7Smrg CursorOff = 0x100; 821692f60a7Smrg linearSize = 2048; 822692f60a7Smrg maxWidth = 1024; 823692f60a7Smrg maxHeight = 1024; 824692f60a7Smrg break; 825692f60a7Smrg case NM2200: 826692f60a7Smrg bppSupport = Support24bppFb | Support32bppFb | 827692f60a7Smrg SupportConvert32to24 | PreferConvert32to24; 828692f60a7Smrg videoRam = 2560; 829692f60a7Smrg maxClock = 110000; 830692f60a7Smrg CursorMem = 1024; 831692f60a7Smrg CursorOff = 0x1000; 832692f60a7Smrg linearSize = 4096; 833692f60a7Smrg maxWidth = 1280; 834692f60a7Smrg maxHeight = 1024; /* ???? */ 835692f60a7Smrg break; 836692f60a7Smrg case NM2230: 837692f60a7Smrg bppSupport = Support24bppFb | Support32bppFb | 838692f60a7Smrg SupportConvert32to24 | PreferConvert32to24; 839692f60a7Smrg videoRam = 3008; 840692f60a7Smrg maxClock = 110000; 841692f60a7Smrg CursorMem = 1024; 842692f60a7Smrg CursorOff = 0x1000; 843692f60a7Smrg linearSize = 4096; 844692f60a7Smrg maxWidth = 1280; 845692f60a7Smrg maxHeight = 1024; /* ???? */ 846692f60a7Smrg break; 847692f60a7Smrg case NM2360: 848692f60a7Smrg bppSupport = Support24bppFb | Support32bppFb | 849692f60a7Smrg SupportConvert32to24 | PreferConvert32to24; 850692f60a7Smrg videoRam = 4096; 851692f60a7Smrg maxClock = 110000; 852692f60a7Smrg CursorMem = 1024; 853692f60a7Smrg CursorOff = 0x1000; 854692f60a7Smrg linearSize = 4096; 855692f60a7Smrg maxWidth = 1280; 856692f60a7Smrg maxHeight = 1024; /* ???? */ 857692f60a7Smrg break; 858692f60a7Smrg case NM2380: 859692f60a7Smrg bppSupport = Support24bppFb | Support32bppFb | 860692f60a7Smrg SupportConvert32to24 | PreferConvert32to24; 861692f60a7Smrg videoRam = 6144; 862692f60a7Smrg maxClock = 110000; 863692f60a7Smrg CursorMem = 1024; 864692f60a7Smrg CursorOff = 0x1000; 865692f60a7Smrg linearSize = 8192; 866692f60a7Smrg maxWidth = 1280; 867692f60a7Smrg maxHeight = 1024; /* ???? */ 868692f60a7Smrg break; 869692f60a7Smrg } 870692f60a7Smrg 871692f60a7Smrg pScrn->monitor = pScrn->confScreen->monitor; 872692f60a7Smrg 873692f60a7Smrg if (xf86LoadSubModule(pScrn, "ddc")) { 874692f60a7Smrg#if 1 /* for DDC1 testing */ 875692f60a7Smrg if (!neoDoDDCVBE(pScrn)) 876692f60a7Smrg if (!neoDoDDC2(pScrn)) 877692f60a7Smrg#endif 878692f60a7Smrg neoDoDDC1(pScrn); 879692f60a7Smrg } 880692f60a7Smrg 881692f60a7Smrg if (!xf86SetDepthBpp(pScrn, 16, 0, 0, bppSupport )) 882692f60a7Smrg return FALSE; 883692f60a7Smrg else { 884692f60a7Smrg /* Check that the returned depth is one we support */ 885692f60a7Smrg switch (pScrn->depth) { 886692f60a7Smrg case 8: 887692f60a7Smrg case 15: 888692f60a7Smrg case 16: 889692f60a7Smrg break; 890692f60a7Smrg case 24: 891692f60a7Smrg if (nPtr->NeoChipset != NM2070) 892692f60a7Smrg break; 893692f60a7Smrg default: 894692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 895692f60a7Smrg "Given depth (%d) is not supported by this driver\n", 896692f60a7Smrg pScrn->depth); 897692f60a7Smrg return FALSE; 898692f60a7Smrg } 899692f60a7Smrg } 900692f60a7Smrg xf86PrintDepthBpp(pScrn); 901692f60a7Smrg if (pScrn->depth == 8) 902692f60a7Smrg pScrn->rgbBits = 6; 903692f60a7Smrg 904692f60a7Smrg /* Get the depth24 pixmap format */ 905692f60a7Smrg if (pScrn->depth == 24 && pix24bpp == 0) 906692f60a7Smrg pix24bpp = xf86GetBppFromDepth(pScrn, 24); 907692f60a7Smrg 908692f60a7Smrg /* 909692f60a7Smrg * This must happen after pScrn->display has been set because 910692f60a7Smrg * xf86SetWeight references it. 911692f60a7Smrg */ 912692f60a7Smrg if (pScrn->depth > 8) { 913692f60a7Smrg /* The defaults are OK for us */ 914692f60a7Smrg rgb zeros = {0, 0, 0}; 915692f60a7Smrg 916692f60a7Smrg if (!xf86SetWeight(pScrn, zeros, zeros)) { 917692f60a7Smrg return FALSE; 918692f60a7Smrg } else { 919692f60a7Smrg /* XXX check that weight returned is supported */ 920692f60a7Smrg ; 921692f60a7Smrg } 922692f60a7Smrg } 923692f60a7Smrg 924692f60a7Smrg if (!xf86SetDefaultVisual(pScrn, -1)) 925692f60a7Smrg return FALSE; 926692f60a7Smrg 927692f60a7Smrg if (pScrn->depth > 1) { 928692f60a7Smrg Gamma zeros = {0.0, 0.0, 0.0}; 929692f60a7Smrg 930692f60a7Smrg if (!xf86SetGamma(pScrn, zeros)) 931692f60a7Smrg return FALSE; 932692f60a7Smrg } 933692f60a7Smrg 934692f60a7Smrg nPtr->strangeLockups = TRUE; 935692f60a7Smrg 936692f60a7Smrg /* Collect all of the relevant option flags (fill in pScrn->options) */ 937692f60a7Smrg xf86CollectOptions(pScrn, NULL); 938692f60a7Smrg /* Process the options */ 939692f60a7Smrg if (nPtr->NeoChipset == NM2070) { 9403f6d0e1dSmrg if (!(nPtr->Options = malloc(sizeof(NEO_2070_Options)))) 941692f60a7Smrg return FALSE; 942692f60a7Smrg memcpy(nPtr->Options, NEO_2070_Options, sizeof(NEO_2070_Options)); 943692f60a7Smrg } else { 9443f6d0e1dSmrg if (!(nPtr->Options = malloc(sizeof(NEOOptions)))) 945692f60a7Smrg return FALSE; 946692f60a7Smrg memcpy(nPtr->Options, NEOOptions, sizeof(NEOOptions)); 947692f60a7Smrg } 948692f60a7Smrg 949692f60a7Smrg xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, nPtr->Options); 950692f60a7Smrg 951692f60a7Smrg xf86GetOptValBool(nPtr->Options, OPTION_SW_CURSOR,&nPtr->swCursor); 952692f60a7Smrg xf86GetOptValBool(nPtr->Options, OPTION_NO_MMIO,&nPtr->noMMIO); 953692f60a7Smrg xf86GetOptValBool(nPtr->Options, OPTION_INTERN_DISP,&nPtr->internDisp); 954692f60a7Smrg xf86GetOptValBool(nPtr->Options, OPTION_EXTERN_DISP,&nPtr->externDisp); 955692f60a7Smrg if (xf86GetOptValBool(nPtr->Options, OPTION_LCD_CENTER,&nPtr->lcdCenter)) 956692f60a7Smrg lcdCenterOptSet = TRUE; 957692f60a7Smrg xf86GetOptValBool(nPtr->Options, OPTION_LCD_STRETCH,&nPtr->noLcdStretch); 958692f60a7Smrg xf86GetOptValBool(nPtr->Options, OPTION_SHADOW_FB,&nPtr->shadowFB); 959692f60a7Smrg xf86GetOptValBool(nPtr->Options, OPTION_SHOWCACHE,&nPtr->showcache); 960692f60a7Smrg nPtr->onPciBurst = TRUE; 961692f60a7Smrg xf86GetOptValBool(nPtr->Options, OPTION_PCI_BURST,&nPtr->onPciBurst); 962692f60a7Smrg xf86GetOptValBool(nPtr->Options, 963692f60a7Smrg OPTION_PROG_LCD_MODE_REGS,&nPtr->progLcdRegs); 964692f60a7Smrg if (xf86GetOptValBool(nPtr->Options, 965692f60a7Smrg OPTION_PROG_LCD_MODE_STRETCH,&nPtr->progLcdStretch)) 966692f60a7Smrg nPtr->progLcdStretchOpt = TRUE; 967692f60a7Smrg xf86GetOptValBool(nPtr->Options, 968692f60a7Smrg OPTION_OVERRIDE_VALIDATE_MODE, &nPtr->overrideValidate); 969692f60a7Smrg xf86GetOptValBool(nPtr->Options, OPTION_DISPLAY_HEIGHT_480,&height_480); 970692f60a7Smrg xf86GetOptValBool(nPtr->Options, OPTION_STRANGE_LOCKUPS, 971692f60a7Smrg &nPtr->strangeLockups); 972692f60a7Smrg nPtr->noAccelSet = 973692f60a7Smrg xf86GetOptValBool(nPtr->Options, OPTION_NOACCEL,&nPtr->noAccel); 974692f60a7Smrg 975692f60a7Smrg nPtr->rotate = 0; 976692f60a7Smrg if ((s = xf86GetOptValString(nPtr->Options, OPTION_ROTATE))) { 977692f60a7Smrg if(!xf86NameCmp(s, "CW")) { 978692f60a7Smrg /* accel is disabled below for shadowFB */ 979692f60a7Smrg nPtr->shadowFB = TRUE; 980692f60a7Smrg nPtr->swCursor = TRUE; 981692f60a7Smrg nPtr->rotate = 1; 982692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 983692f60a7Smrg "Rotating screen clockwise - acceleration disabled\n"); 984692f60a7Smrg } else if(!xf86NameCmp(s, "CCW")) { 985692f60a7Smrg nPtr->shadowFB = TRUE; 986692f60a7Smrg nPtr->swCursor = TRUE; 987692f60a7Smrg nPtr->rotate = -1; 988692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen" 989692f60a7Smrg "counter clockwise - acceleration disabled\n"); 990692f60a7Smrg } else { 991692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" 992692f60a7Smrg "value for Option \"Rotate\"\n", s); 993692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 994692f60a7Smrg "Valid options are \"CW\" or \"CCW\"\n"); 995692f60a7Smrg } 996692f60a7Smrg } 997692f60a7Smrg 998692f60a7Smrg if(xf86GetOptValInteger(nPtr->Options, 999692f60a7Smrg OPTION_VIDEO_KEY, &(nPtr->videoKey))) { 1000692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n", 1001692f60a7Smrg nPtr->videoKey); 1002692f60a7Smrg } else { 1003692f60a7Smrg nPtr->videoKey = (1 << pScrn->offset.red) | 1004692f60a7Smrg (1 << pScrn->offset.green) | 1005692f60a7Smrg (((pScrn->mask.blue >> pScrn->offset.blue) - 1) 1006692f60a7Smrg << pScrn->offset.blue); 1007692f60a7Smrg } 1008692f60a7Smrg if(xf86GetOptValInteger(nPtr->Options, OPTION_OVERLAYMEM, 1009692f60a7Smrg &(nPtr->overlay))) { 1010692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1011692f60a7Smrg "reserve %d bytes for overlay.\n", nPtr->overlay); 1012692f60a7Smrg } else { 1013692f60a7Smrg nPtr->overlay = 0; 1014692f60a7Smrg } 1015692f60a7Smrg nPtr->interlace = 0; 1016692f60a7Smrg if(xf86GetOptValInteger(nPtr->Options, OPTION_VIDEO_INTERLACE, 1017692f60a7Smrg &(nPtr->interlace))) { 1018692f60a7Smrg if (nPtr->interlace >= 0 && nPtr->interlace <= 2){ 1019692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "interlace flag = %d\n", 1020692f60a7Smrg nPtr->interlace); 1021692f60a7Smrg } else { 1022692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1023692f60a7Smrg "\"%s\" is not a valid value for " 1024692f60a7Smrg "Option \"Interlaced\"\n", s); 1025692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Valid options are 0..2\n"); 1026692f60a7Smrg } 1027692f60a7Smrg } 1028692f60a7Smrg 1029692f60a7Smrg if (height_480 1030692f60a7Smrg && (nPtr->NeoPanelWidth == 800 || nPtr->NeoPanelWidth == 1024)) { 1031692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, 1032692f60a7Smrg "Overriding Panel height: Set to 480\n"); 1033692f60a7Smrg nPtr->NeoPanelHeight = 480; 1034692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, 1035692f60a7Smrg "Disabling LCD stretching for panel height 480\n"); 1036692f60a7Smrg nPtr->noLcdStretch = TRUE; 1037692f60a7Smrg if (!lcdCenterOptSet) 1038692f60a7Smrg nPtr->lcdCenter = TRUE; 1039692f60a7Smrg } 1040692f60a7Smrg 1041692f60a7Smrg if (nPtr->internDisp && nPtr->externDisp) 1042692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, 1043692f60a7Smrg "Simultaneous LCD/CRT display mode\n"); 1044692f60a7Smrg else if (nPtr->externDisp) 1045692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, 1046692f60a7Smrg "External CRT only display mode\n"); 1047692f60a7Smrg else if (nPtr->internDisp) 1048692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, 1049692f60a7Smrg "Internal LCD only display mode\n"); 1050692f60a7Smrg else { 1051692f60a7Smrg nPtr->internDisp = ((dpy & 0x02) == 0x02); 1052692f60a7Smrg nPtr->externDisp = ((dpy & 0x01) == 0x01); 1053692f60a7Smrg if (nPtr->internDisp && nPtr->externDisp) 1054692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_PROBED, 1055692f60a7Smrg "Simultaneous LCD/CRT display mode\n"); 1056692f60a7Smrg else if (nPtr->externDisp) 1057692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_PROBED, 1058692f60a7Smrg "External CRT only display mode\n"); 1059692f60a7Smrg else if (nPtr->internDisp) 1060692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_PROBED, 1061692f60a7Smrg "Internal LCD only display mode\n"); 1062692f60a7Smrg else { 1063692f60a7Smrg /* this is a fallback if probed values are bogus */ 1064692f60a7Smrg nPtr->internDisp = TRUE; 1065692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_DEFAULT, 1066692f60a7Smrg "Internal LCD only display mode\n"); 1067692f60a7Smrg } 1068692f60a7Smrg } 1069692f60a7Smrg 1070692f60a7Smrg if (nPtr->noLcdStretch) 1071692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, 1072692f60a7Smrg "Low resolution video modes are not stretched\n"); 1073692f60a7Smrg if (nPtr->lcdCenter) 1074692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, 1075692f60a7Smrg "Video modes are centered on the display\n"); 1076692f60a7Smrg if (nPtr->swCursor) 1077692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, "using sofware cursor\n"); 1078692f60a7Smrg if (nPtr->noMMIO) 1079692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, "MMIO mode disabled\n"); 1080692f60a7Smrg if (nPtr->onPciBurst) 1081692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, "using PCI Burst mode\n"); 1082692f60a7Smrg if (nPtr->strangeLockups) 1083692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, 1084692f60a7Smrg "Option StrangeLockups set: disabling some acceleration\n"); 1085692f60a7Smrg if (nPtr->showcache) 1086692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_CONFIG, 1087692f60a7Smrg "Show chache for debugging\n"); 10883f6d0e1dSmrg 10893f6d0e1dSmrg if (!xf86LoadSubModule(pScrn, "xaa")) { 10903f6d0e1dSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Falling back to shadow\n"); 10913f6d0e1dSmrg nPtr->shadowFB = 1; 10923f6d0e1dSmrg } 10933f6d0e1dSmrg 10943f6d0e1dSmrg if (nPtr->shadowFB) { 10953f6d0e1dSmrg if (!xf86LoadSubModule(pScrn, "shadow")) { 10963f6d0e1dSmrg RETURN; 10973f6d0e1dSmrg } 10983f6d0e1dSmrg } 10993f6d0e1dSmrg 1100692f60a7Smrg if (nPtr->shadowFB) { 1101c3c9db83Smrg nPtr->noAccel = TRUE; 1102c3c9db83Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1103c3c9db83Smrg "Using \"Shadow Framebuffer\" - acceleration disabled\n"); 1104692f60a7Smrg } 1105692f60a7Smrg 1106692f60a7Smrg nPtr->NeoFbMapSize = linearSize * 1024; 1107692f60a7Smrg nPtr->NeoCursorOffset = CursorOff; 1108692f60a7Smrg 1109692f60a7Smrg if (nPtr->pEnt->device->MemBase) { 1110692f60a7Smrg /* XXX Check this matches a PCI base address */ 1111692f60a7Smrg nPtr->NeoLinearAddr = nPtr->pEnt->device->MemBase; 1112692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1113692f60a7Smrg "FB base address is set at 0x%lX.\n", 1114692f60a7Smrg nPtr->NeoLinearAddr); 1115692f60a7Smrg } else { 1116692f60a7Smrg nPtr->NeoLinearAddr = 0; 1117692f60a7Smrg } 1118692f60a7Smrg 1119692f60a7Smrg nPtr->NeoMMIOAddr2 = 0; 1120692f60a7Smrg nPtr->NeoMMIOBase2 = NULL; 1121692f60a7Smrg if (nPtr->pEnt->device->IOBase && !nPtr->noMMIO) { 1122692f60a7Smrg /* XXX Check this matches a PCI base address */ 1123692f60a7Smrg nPtr->NeoMMIOAddr = nPtr->pEnt->device->IOBase; 1124692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1125692f60a7Smrg "MMIO base address is set at 0x%lX.\n", 1126692f60a7Smrg nPtr->NeoMMIOAddr); 1127692f60a7Smrg } else { 1128692f60a7Smrg nPtr->NeoMMIOAddr = 0; 1129692f60a7Smrg } 1130692f60a7Smrg 1131692f60a7Smrg if (nPtr->pEnt->location.type == BUS_PCI) { 1132692f60a7Smrg if (!nPtr->NeoLinearAddr) { 113354569438Smrg nPtr->NeoLinearAddr = PCI_REGION_BASE(nPtr->PciInfo, 0, REGION_MEM); 1134692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1135692f60a7Smrg "FB base address is set at 0x%lX.\n", 1136692f60a7Smrg nPtr->NeoLinearAddr); 1137692f60a7Smrg } 1138692f60a7Smrg if (!nPtr->NeoMMIOAddr && !nPtr->noMMIO) { 1139692f60a7Smrg switch (nPtr->NeoChipset) { 1140692f60a7Smrg case NM2070 : 1141692f60a7Smrg nPtr->NeoMMIOAddr = nPtr->NeoLinearAddr + 0x100000; 1142692f60a7Smrg break; 1143692f60a7Smrg case NM2090: 1144692f60a7Smrg case NM2093: 1145692f60a7Smrg nPtr->NeoMMIOAddr = nPtr->NeoLinearAddr + 0x200000; 1146692f60a7Smrg break; 1147692f60a7Smrg case NM2160: 1148692f60a7Smrg case NM2097: 1149692f60a7Smrg case NM2200: 1150692f60a7Smrg case NM2230: 1151692f60a7Smrg case NM2360: 1152692f60a7Smrg case NM2380: 115354569438Smrg nPtr->NeoMMIOAddr = PCI_REGION_BASE(nPtr->PciInfo, 1, REGION_MEM); 115454569438Smrg nPtr->NeoMMIOAddr2 = PCI_REGION_BASE(nPtr->PciInfo, 2, REGION_MEM); 1155692f60a7Smrg break; 1156692f60a7Smrg } 1157692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1158692f60a7Smrg "MMIO base address is set at 0x%lX.\n", 1159692f60a7Smrg nPtr->NeoMMIOAddr); 1160692f60a7Smrg if (nPtr->NeoMMIOAddr2 != 0){ 1161692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1162692f60a7Smrg "MMIO base address2 is set at 0x%lX.\n", 1163692f60a7Smrg nPtr->NeoMMIOAddr2); 1164692f60a7Smrg } 1165692f60a7Smrg } 11662e71ea71Smrg#ifndef XSERVER_LIBPCIACCESS 1167692f60a7Smrg /* XXX What about VGA resources in OPERATING mode? */ 1168692f60a7Smrg if (xf86RegisterResources(nPtr->pEnt->index, NULL, ResExclusive)) 1169692f60a7Smrg RETURN; 11702e71ea71Smrg#endif 1171692f60a7Smrg 11722e71ea71Smrg } 11732e71ea71Smrg#ifndef XSERVER_LIBPCIACCESS 11742e71ea71Smrg else if (nPtr->pEnt->location.type == BUS_ISA) { 1175692f60a7Smrg unsigned int addr; 1176692f60a7Smrg resRange linearRes[] = { {ResExcMemBlock|ResBios|ResBus,0,0},_END }; 1177692f60a7Smrg 1178692f60a7Smrg if (!nPtr->NeoLinearAddr) { 1179692f60a7Smrg VGAwGR(0x09,0x26); 1180692f60a7Smrg addr = VGArGR(0x13); 1181692f60a7Smrg VGAwGR(0x09,0x00); 1182692f60a7Smrg nPtr->NeoLinearAddr = addr << 20; 1183692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1184692f60a7Smrg "FB base address is set at 0x%lX.\n", 1185692f60a7Smrg nPtr->NeoLinearAddr); 1186692f60a7Smrg } 1187692f60a7Smrg if (!nPtr->NeoMMIOAddr && !nPtr->noMMIO) { 1188692f60a7Smrg nPtr->NeoMMIOAddr = nPtr->NeoLinearAddr + 0x100000; 1189692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1190692f60a7Smrg "MMIO base address is set at 0x%lX.\n", 1191692f60a7Smrg nPtr->NeoMMIOAddr); 1192692f60a7Smrg } 11932e71ea71Smrg 1194692f60a7Smrg linearRes[0].rBegin = nPtr->NeoLinearAddr; 1195692f60a7Smrg linearRes[1].rEnd = nPtr->NeoLinearAddr + nPtr->NeoFbMapSize - 1; 1196692f60a7Smrg if (xf86RegisterResources(nPtr->pEnt->index,linearRes,ResNone)) { 1197c3c9db83Smrg RETURN; 1198692f60a7Smrg } 11992e71ea71Smrg } 12002e71ea71Smrg#endif 12012e71ea71Smrg else 1202692f60a7Smrg RETURN; 1203692f60a7Smrg 1204692f60a7Smrg if (nPtr->pEnt->device->videoRam != 0) { 1205692f60a7Smrg pScrn->videoRam = nPtr->pEnt->device->videoRam; 1206692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VideoRAM: %d kByte\n", 1207692f60a7Smrg pScrn->videoRam); 1208692f60a7Smrg } else { 1209692f60a7Smrg pScrn->videoRam = videoRam; 1210692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VideoRAM: %d kByte\n", 1211692f60a7Smrg pScrn->videoRam); 1212692f60a7Smrg } 1213692f60a7Smrg 1214692f60a7Smrg if (nPtr->pEnt->device->dacSpeeds[0] != 0) { 1215692f60a7Smrg maxClock = nPtr->pEnt->device->dacSpeeds[0]; 1216692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Max Clock: %d kHz\n", 1217692f60a7Smrg maxClock); 1218692f60a7Smrg } else { 1219692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Max Clock: %d kHz\n", 1220692f60a7Smrg maxClock); 1221692f60a7Smrg } 1222692f60a7Smrg 1223692f60a7Smrg pScrn->progClock = TRUE; 1224692f60a7Smrg /* 1225692f60a7Smrg * Setup the ClockRanges, which describe what clock ranges are available, 1226692f60a7Smrg * and what sort of modes they can be used for. 1227692f60a7Smrg */ 1228692f60a7Smrg clockRanges = (ClockRangePtr)xnfcalloc(sizeof(ClockRange), 1); 1229692f60a7Smrg clockRanges->next = NULL; 1230692f60a7Smrg clockRanges->ClockMulFactor = 1; 1231692f60a7Smrg clockRanges->minClock = 11000; /* guessed §§§ */ 1232692f60a7Smrg clockRanges->maxClock = maxClock; 1233692f60a7Smrg clockRanges->clockIndex = -1; /* programmable */ 1234692f60a7Smrg clockRanges->interlaceAllowed = FALSE; 1235692f60a7Smrg clockRanges->doubleScanAllowed = TRUE; 1236692f60a7Smrg 1237692f60a7Smrg /* Subtract memory for HW cursor */ 1238692f60a7Smrg if (!nPtr->swCursor) 1239692f60a7Smrg nPtr->NeoCursorMem = CursorMem; 1240692f60a7Smrg else 1241692f60a7Smrg nPtr->NeoCursorMem = 0; 1242692f60a7Smrg apertureSize = (pScrn->videoRam * 1024) - nPtr->NeoCursorMem; 1243692f60a7Smrg 1244692f60a7Smrg if ((nPtr->NeoPanelWidth == 800) && (nPtr->NeoPanelHeight == 480)) { 1245692f60a7Smrg neo800x480Mode.next = pScrn->monitor->Modes; 1246692f60a7Smrg pScrn->monitor->Modes = &neo800x480Mode; 1247692f60a7Smrg } 1248692f60a7Smrg if ((nPtr->NeoPanelWidth == 1024) && (nPtr->NeoPanelHeight == 480)) { 1249692f60a7Smrg neo1024x480Mode.next = pScrn->monitor->Modes; 1250692f60a7Smrg pScrn->monitor->Modes = &neo1024x480Mode; 1251692f60a7Smrg } 1252692f60a7Smrg 1253692f60a7Smrg if (!pScrn->monitor->DDC) { 1254692f60a7Smrg /* 1255692f60a7Smrg * If the monitor parameters are not specified explicitly, set them 1256692f60a7Smrg * so that 60Hz modes up to the panel size are allowed. 1257692f60a7Smrg */ 1258692f60a7Smrg if (pScrn->monitor->nHsync == 0) { 1259692f60a7Smrg pScrn->monitor->nHsync = 1; 1260692f60a7Smrg pScrn->monitor->hsync[0].lo = 28; 1261692f60a7Smrg pScrn->monitor->hsync[0].hi = 1262692f60a7Smrg 60.0 * 1.07 * nPtr->NeoPanelHeight / 1000.0; 1263692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1264692f60a7Smrg "Using hsync range matching panel size: %.2f-%.2f kHz\n", 1265692f60a7Smrg pScrn->monitor->hsync[0].lo, 1266692f60a7Smrg pScrn->monitor->hsync[0].hi); 1267692f60a7Smrg } 1268692f60a7Smrg if (pScrn->monitor->nVrefresh == 0) { 1269692f60a7Smrg pScrn->monitor->nVrefresh = 1; 1270692f60a7Smrg pScrn->monitor->vrefresh[0].lo = 55.0; 1271692f60a7Smrg pScrn->monitor->vrefresh[0].hi = 65.0; 1272692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1273692f60a7Smrg "Using vsync range for panel: %.2f-%.2f kHz\n", 1274692f60a7Smrg pScrn->monitor->vrefresh[0].lo, 1275692f60a7Smrg pScrn->monitor->vrefresh[0].hi); 1276692f60a7Smrg } 1277692f60a7Smrg } 1278692f60a7Smrg 1279692f60a7Smrg /* 1280692f60a7Smrg * For external displays, limit the width to 1024 pixels or less. 1281692f60a7Smrg */ 1282692f60a7Smrg { 1283692f60a7Smrg i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 1284692f60a7Smrg pScrn->display->modes, clockRanges, 1285692f60a7Smrg NULL, 256, maxWidth,(8 * pScrn->bitsPerPixel),/*§§§*/ 1286692f60a7Smrg 128, maxHeight, pScrn->display->virtualX, 1287692f60a7Smrg pScrn->display->virtualY, apertureSize, 1288692f60a7Smrg LOOKUP_BEST_REFRESH); 1289692f60a7Smrg 1290692f60a7Smrg if (i == -1) 1291692f60a7Smrg RETURN; 1292692f60a7Smrg } 1293692f60a7Smrg 1294692f60a7Smrg /* Prune the modes marked as invalid */ 1295692f60a7Smrg xf86PruneDriverModes(pScrn); 1296692f60a7Smrg 1297692f60a7Smrg if (i == 0 || pScrn->modes == NULL) { 1298692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 1299692f60a7Smrg RETURN; 1300692f60a7Smrg } 1301692f60a7Smrg 1302692f60a7Smrg /* 1303692f60a7Smrg * Set the CRTC parameters for all of the modes based on the type 1304692f60a7Smrg * of mode, and the chipset's interlace requirements. 1305692f60a7Smrg * 1306692f60a7Smrg * Calling this is required if the mode->Crtc* values are used by the 1307692f60a7Smrg * driver and if the driver doesn't provide code to set them. They 1308692f60a7Smrg * are not pre-initialised at all. 1309692f60a7Smrg */ 1310692f60a7Smrg xf86SetCrtcForModes(pScrn, 0); 1311692f60a7Smrg 1312692f60a7Smrg /* Set the current mode to the first in the list */ 1313692f60a7Smrg pScrn->currentMode = pScrn->modes; 1314692f60a7Smrg 1315692f60a7Smrg /* Print the list of modes being used */ 1316692f60a7Smrg xf86PrintModes(pScrn); 1317692f60a7Smrg 1318692f60a7Smrg /* If monitor resolution is set on the command line, use it */ 1319692f60a7Smrg xf86SetDpi(pScrn, 0, 0); 1320692f60a7Smrg 1321692f60a7Smrg if (xf86LoadSubModule(pScrn, "fb") == NULL) { 1322692f60a7Smrg RETURN; 1323692f60a7Smrg } 1324692f60a7Smrg 1325692f60a7Smrg if (!nPtr->swCursor) { 1326692f60a7Smrg if (!xf86LoadSubModule(pScrn, "ramdac")) 1327692f60a7Smrg RETURN; 1328692f60a7Smrg } 1329692f60a7Smrg return TRUE; 1330692f60a7Smrg} 1331692f60a7Smrg#undef RETURN 1332692f60a7Smrg 1333692f60a7Smrg/* Mandatory */ 1334692f60a7Smrgstatic Bool 13353f6d0e1dSmrgNEOEnterVT(VT_FUNC_ARGS_DECL) 1336692f60a7Smrg{ 13373f6d0e1dSmrg SCRN_INFO_PTR(arg); 1338692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 1339692f60a7Smrg 1340692f60a7Smrg /* Should we re-save the text mode on each VT enter? */ 1341692f60a7Smrg if(!neoModeInit(pScrn, pScrn->currentMode)) 1342692f60a7Smrg return FALSE; 1343692f60a7Smrg 1344692f60a7Smrg if (nPtr->video) 1345692f60a7Smrg NEOResetVideo(pScrn); 1346692f60a7Smrg 1347692f60a7Smrg if (nPtr->NeoHWCursorShown) 1348692f60a7Smrg NeoShowCursor(pScrn); 13493f6d0e1dSmrg NEOAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 1350692f60a7Smrg 1351692f60a7Smrg return TRUE; 1352692f60a7Smrg} 1353692f60a7Smrg 1354692f60a7Smrg/* Mandatory */ 1355692f60a7Smrgstatic void 13563f6d0e1dSmrgNEOLeaveVT(VT_FUNC_ARGS_DECL) 1357692f60a7Smrg{ 13583f6d0e1dSmrg SCRN_INFO_PTR(arg); 1359692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 1360692f60a7Smrg 1361692f60a7Smrg /* Invalidate the cached acceleration registers */ 1362692f60a7Smrg if (nPtr->NeoHWCursorShown) 1363692f60a7Smrg NeoHideCursor(pScrn); 1364692f60a7Smrg neoRestore(pScrn, &(VGAHWPTR(pScrn))->SavedReg, &nPtr->NeoSavedReg, TRUE); 1365692f60a7Smrg neoLock(pScrn); 1366692f60a7Smrg 1367692f60a7Smrg} 1368692f60a7Smrg 1369692f60a7Smrgstatic void 1370692f60a7SmrgNEOLoadPalette( 1371692f60a7Smrg ScrnInfoPtr pScrn, 1372692f60a7Smrg int numColors, 1373692f60a7Smrg int *indices, 1374692f60a7Smrg LOCO *colors, 1375692f60a7Smrg VisualPtr pVisual 1376692f60a7Smrg){ 1377692f60a7Smrg int i, index, shift, Gshift; 1378692f60a7Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 1379692f60a7Smrg 1380692f60a7Smrg switch(pScrn->depth) { 1381692f60a7Smrg case 15: 1382692f60a7Smrg shift = Gshift = 1; 1383692f60a7Smrg break; 1384692f60a7Smrg case 16: 1385692f60a7Smrg shift = 0; 1386692f60a7Smrg Gshift = 0; 1387692f60a7Smrg break; 1388692f60a7Smrg default: 1389692f60a7Smrg shift = Gshift = 0; 1390692f60a7Smrg break; 1391692f60a7Smrg } 1392692f60a7Smrg 1393692f60a7Smrg for(i = 0; i < numColors; i++) { 1394692f60a7Smrg index = indices[i]; 1395692f60a7Smrg hwp->writeDacWriteAddr(hwp, index); 1396692f60a7Smrg DACDelay(hwp); 1397692f60a7Smrg hwp->writeDacData(hwp, colors[index].red << shift); 1398692f60a7Smrg DACDelay(hwp); 1399692f60a7Smrg hwp->writeDacData(hwp, colors[index].green << Gshift); 1400692f60a7Smrg DACDelay(hwp); 1401692f60a7Smrg hwp->writeDacData(hwp, colors[index].blue << shift); 1402692f60a7Smrg DACDelay(hwp); 1403692f60a7Smrg } 1404692f60a7Smrg} 1405692f60a7Smrg 1406eaa3dbe0Smrgstatic Bool 1407eaa3dbe0SmrgNEOCreateScreenResources(ScreenPtr pScreen) 1408eaa3dbe0Smrg{ 1409eaa3dbe0Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1410eaa3dbe0Smrg NEOPtr pNeo = NEOPTR(pScrn); 1411eaa3dbe0Smrg PixmapPtr pPixmap; 1412eaa3dbe0Smrg Bool ret; 1413eaa3dbe0Smrg 1414eaa3dbe0Smrg pScreen->CreateScreenResources = pNeo->CreateScreenResources; 1415eaa3dbe0Smrg ret = pScreen->CreateScreenResources(pScreen); 1416eaa3dbe0Smrg pScreen->CreateScreenResources = NEOCreateScreenResources; 1417eaa3dbe0Smrg 1418eaa3dbe0Smrg if (!ret) 1419eaa3dbe0Smrg return FALSE; 1420eaa3dbe0Smrg 1421eaa3dbe0Smrg pPixmap = pScreen->GetScreenPixmap(pScreen); 1422eaa3dbe0Smrg 1423eaa3dbe0Smrg if (!shadowAdd(pScreen, pPixmap, neoShadowUpdate, 1424eaa3dbe0Smrg NULL, 0, NULL)) { 1425eaa3dbe0Smrg return FALSE; 1426eaa3dbe0Smrg } 1427eaa3dbe0Smrg return TRUE; 1428eaa3dbe0Smrg} 1429eaa3dbe0Smrg 1430eaa3dbe0Smrgstatic Bool 1431eaa3dbe0SmrgNEOShadowInit(ScreenPtr pScreen) 1432eaa3dbe0Smrg{ 1433eaa3dbe0Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1434eaa3dbe0Smrg NEOPtr pNeo = NEOPTR(pScrn); 1435eaa3dbe0Smrg 1436eaa3dbe0Smrg if (!shadowSetup(pScreen)) 1437eaa3dbe0Smrg return FALSE; 1438eaa3dbe0Smrg pNeo->CreateScreenResources = pScreen->CreateScreenResources; 1439eaa3dbe0Smrg pScreen->CreateScreenResources = NEOCreateScreenResources; 1440eaa3dbe0Smrg 1441eaa3dbe0Smrg return TRUE; 1442eaa3dbe0Smrg} 1443eaa3dbe0Smrg 144495903e71Smrgstatic Bool 144595903e71SmrgNEOSaveScreen(ScreenPtr pScreen, int mode) 144695903e71Smrg{ 144795903e71Smrg return vgaHWSaveScreen(pScreen, mode); 144895903e71Smrg} 144995903e71Smrg 1450692f60a7Smrg/* Mandatory */ 1451692f60a7Smrgstatic Bool 14523f6d0e1dSmrgNEOScreenInit(SCREEN_INIT_ARGS_DECL) 1453692f60a7Smrg{ 1454692f60a7Smrg ScrnInfoPtr pScrn; 1455692f60a7Smrg vgaHWPtr hwp; 1456692f60a7Smrg NEOPtr nPtr; 1457692f60a7Smrg NEOACLPtr nAcl; 1458692f60a7Smrg int ret; 1459692f60a7Smrg VisualPtr visual; 1460692f60a7Smrg int allocatebase, freespace, currentaddr; 14612e71ea71Smrg#ifndef XSERVER_LIBPCIACCESS 1462692f60a7Smrg unsigned int racflag = RAC_FB; 14632e71ea71Smrg#endif 1464692f60a7Smrg unsigned char *FBStart; 1465692f60a7Smrg int height, width, displayWidth; 1466692f60a7Smrg 1467692f60a7Smrg /* 1468692f60a7Smrg * we need to get the ScrnInfoRec for this screen, so let's allocate 1469692f60a7Smrg * one first thing 1470692f60a7Smrg */ 14713f6d0e1dSmrg pScrn = xf86ScreenToScrn(pScreen); 1472692f60a7Smrg nPtr = NEOPTR(pScrn); 1473692f60a7Smrg nAcl = NEOACLPTR(pScrn); 1474692f60a7Smrg 1475692f60a7Smrg hwp = VGAHWPTR(pScrn); 1476692f60a7Smrg hwp->MapSize = 0x10000; /* Standard 64k VGA window */ 1477692f60a7Smrg /* Map the VGA memory */ 1478692f60a7Smrg if (!vgaHWMapMem(pScrn)) 1479692f60a7Smrg return FALSE; 1480692f60a7Smrg 1481692f60a7Smrg /* Map the Neo memory and possible MMIO areas */ 1482692f60a7Smrg if (!neoMapMem(pScrn)) 1483692f60a7Smrg return FALSE; 1484692f60a7Smrg 1485692f60a7Smrg /* 1486692f60a7Smrg * next we save the current state and setup the first mode 1487692f60a7Smrg */ 1488692f60a7Smrg neoSave(pScrn); 1489692f60a7Smrg 1490692f60a7Smrg if (!neoModeInit(pScrn,pScrn->currentMode)) 1491692f60a7Smrg return FALSE; 1492692f60a7Smrg vgaHWSaveScreen(pScreen,SCREEN_SAVER_ON); 14933f6d0e1dSmrg NEOAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); 1494692f60a7Smrg 1495692f60a7Smrg /* 1496692f60a7Smrg * Reset visual list. 1497692f60a7Smrg */ 1498692f60a7Smrg miClearVisualTypes(); 1499692f60a7Smrg 1500692f60a7Smrg /* Setup the visuals we support. */ 1501692f60a7Smrg if (!miSetVisualTypes(pScrn->depth, 1502692f60a7Smrg miGetDefaultVisualMask(pScrn->depth), 1503692f60a7Smrg pScrn->rgbBits, pScrn->defaultVisual)) 1504692f60a7Smrg return FALSE; 1505c3c9db83Smrg 1506692f60a7Smrg if (!miSetPixmapDepths ()) return FALSE; 1507692f60a7Smrg 1508692f60a7Smrg /* 1509692f60a7Smrg * Call the framebuffer layer's ScreenInit function, and fill in other 1510692f60a7Smrg * pScreen fields. 1511692f60a7Smrg */ 1512692f60a7Smrg displayWidth = pScrn->displayWidth; 1513692f60a7Smrg if (nPtr->rotate) { 1514692f60a7Smrg height = pScrn->virtualX; 1515692f60a7Smrg width = pScrn->virtualY; 1516692f60a7Smrg } else { 1517692f60a7Smrg width = pScrn->virtualX; 1518692f60a7Smrg height = pScrn->virtualY; 1519692f60a7Smrg } 1520692f60a7Smrg 1521692f60a7Smrg if(nPtr->shadowFB) { 1522692f60a7Smrg nPtr->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); 15233f6d0e1dSmrg nPtr->ShadowPtr = malloc(nPtr->ShadowPitch * height); 1524692f60a7Smrg displayWidth = nPtr->ShadowPitch / (pScrn->bitsPerPixel >> 3); 1525692f60a7Smrg FBStart = nPtr->ShadowPtr; 1526692f60a7Smrg } else { 1527692f60a7Smrg nPtr->ShadowPtr = NULL; 1528692f60a7Smrg FBStart = nPtr->NeoFbBase; 1529692f60a7Smrg } 1530692f60a7Smrg 1531692f60a7Smrg ret = fbScreenInit(pScreen, FBStart, 1532692f60a7Smrg width, height, 1533692f60a7Smrg pScrn->xDpi, pScrn->yDpi, 1534692f60a7Smrg displayWidth, pScrn->bitsPerPixel); 1535692f60a7Smrg if (!ret) 1536692f60a7Smrg return FALSE; 1537692f60a7Smrg if (pScrn->depth > 8) { 1538692f60a7Smrg /* Fixup RGB ordering */ 1539692f60a7Smrg visual = pScreen->visuals + pScreen->numVisuals; 1540692f60a7Smrg while (--visual >= pScreen->visuals) { 1541c3c9db83Smrg if ((visual->class | DynamicClass) == DirectColor) { 1542692f60a7Smrg visual->offsetRed = pScrn->offset.red; 1543692f60a7Smrg visual->offsetGreen = pScrn->offset.green; 1544692f60a7Smrg visual->offsetBlue = pScrn->offset.blue; 1545692f60a7Smrg visual->redMask = pScrn->mask.red; 1546692f60a7Smrg visual->greenMask = pScrn->mask.green; 1547692f60a7Smrg visual->blueMask = pScrn->mask.blue; 1548692f60a7Smrg } 1549692f60a7Smrg } 1550692f60a7Smrg } 1551692f60a7Smrg 1552692f60a7Smrg /* must be after RGB ordering fixed */ 1553692f60a7Smrg fbPictureInit(pScreen, 0, 0); 1554692f60a7Smrg 1555692f60a7Smrg xf86SetBlackWhitePixels(pScreen); 1556692f60a7Smrg 1557692f60a7Smrg if (!nPtr->shadowFB) 1558692f60a7Smrg NEODGAInit(pScreen); 1559692f60a7Smrg 1560692f60a7Smrg nPtr->NeoHWCursorShown = FALSE; 1561692f60a7Smrg nPtr->NeoHWCursorInitialized = FALSE; 1562692f60a7Smrg nAcl->UseHWCursor = FALSE; 1563692f60a7Smrg nAcl->CursorAddress = -1; 1564692f60a7Smrg 1565c3c9db83Smrg nAcl->cacheStart = -1; 1566c3c9db83Smrg nAcl->cacheEnd = -1; 1567c3c9db83Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, 1568c3c9db83Smrg "Using linear framebuffer at: 0x%08lX\n", 1569c3c9db83Smrg nPtr->NeoLinearAddr); 1570c3c9db83Smrg /* Setup pointers to free space in video ram */ 1571c3c9db83Smrg allocatebase = (pScrn->videoRam << 10); 1572c3c9db83Smrg freespace = allocatebase - pScrn->displayWidth * 1573c3c9db83Smrg pScrn->virtualY * (pScrn->bitsPerPixel >> 3); 1574c3c9db83Smrg currentaddr = allocatebase; 15753f6d0e1dSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1576c3c9db83Smrg "%d bytes off-screen memory available\n", freespace); 1577c3c9db83Smrg 1578c3c9db83Smrg if (nPtr->swCursor || !nPtr->NeoMMIOBase) { 15793f6d0e1dSmrg xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1580c3c9db83Smrg "Using Software Cursor.\n"); 1581c3c9db83Smrg } else if (nPtr->NeoCursorMem <= freespace) { 1582c3c9db83Smrg currentaddr -= nPtr->NeoCursorMem; 1583c3c9db83Smrg freespace -= nPtr->NeoCursorMem; 1584c3c9db83Smrg /* alignment */ 1585c3c9db83Smrg freespace -= currentaddr & 0x3FF; 1586c3c9db83Smrg currentaddr &= 0xfffffc00; 1587c3c9db83Smrg nAcl->CursorAddress = currentaddr; 15883f6d0e1dSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1589c3c9db83Smrg "Using H/W Cursor.\n"); 1590692f60a7Smrg } else { 15913f6d0e1dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1592c3c9db83Smrg "Too little space for H/W cursor.\n"); 1593692f60a7Smrg } 1594c3c9db83Smrg 1595c3c9db83Smrg if (!nPtr->noAccel && !nPtr->NeoMMIOBase) 1596c3c9db83Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, 1597c3c9db83Smrg "Acceleration disabled when not using MMIO\n"); 1598c3c9db83Smrg 1599c3c9db83Smrg if (nPtr->overlay > 0){ 1600c3c9db83Smrg if (nPtr->overlay > freespace){ 1601c3c9db83Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, 1602c3c9db83Smrg "Can not reserve %d bytes for overlay. " 1603c3c9db83Smrg "Resize to %d bytes.\n", 1604c3c9db83Smrg nPtr->overlay, freespace); 1605c3c9db83Smrg nPtr->overlay = freespace; 1606c3c9db83Smrg } 1607c3c9db83Smrg currentaddr -= nPtr->overlay; 1608c3c9db83Smrg freespace -= nPtr->overlay; 1609c3c9db83Smrg nPtr->overlay_offset = currentaddr; 1610c3c9db83Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Overlay at 0x%x\n", 1611c3c9db83Smrg nPtr->overlay_offset); 1612c3c9db83Smrg } 1613c3c9db83Smrg 1614c3c9db83Smrg nAcl->cacheStart = currentaddr - freespace; 1615c3c9db83Smrg nAcl->cacheEnd = currentaddr; 1616c3c9db83Smrg freespace = 0; 1617c3c9db83Smrg if (nAcl->cacheStart < nAcl->cacheEnd) { 1618c3c9db83Smrg BoxRec AvailFBArea; 1619c3c9db83Smrg int lines = nAcl->cacheEnd / 1620c3c9db83Smrg (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3)); 1621c3c9db83Smrg if (!nPtr->noAccel && nPtr->NeoMMIOBase && lines > 1024) 1622c3c9db83Smrg lines = 1024; 1623c3c9db83Smrg AvailFBArea.x1 = 0; 1624c3c9db83Smrg AvailFBArea.y1 = 0; 1625c3c9db83Smrg AvailFBArea.x2 = pScrn->displayWidth; 1626c3c9db83Smrg AvailFBArea.y2 = lines; 1627c3c9db83Smrg xf86InitFBManager(pScreen, &AvailFBArea); 1628c3c9db83Smrg 1629c3c9db83Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1630c3c9db83Smrg "Using %i scanlines of offscreen memory \n", 1631c3c9db83Smrg lines - pScrn->virtualY); 1632c3c9db83Smrg } 1633c3c9db83Smrg 1634c3c9db83Smrg /* Setup the acceleration primitives */ 1635c3c9db83Smrg if (!nPtr->noAccel && nPtr->NeoMMIOBase) { 1636c3c9db83Smrg Bool ret = FALSE; 1637c3c9db83Smrg if (nAcl->cacheStart >= nAcl->cacheEnd) { 16383f6d0e1dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1639c3c9db83Smrg "Too little space for pixmap cache.\n"); 1640c3c9db83Smrg } 1641c3c9db83Smrg switch(nPtr->NeoChipset) { 1642c3c9db83Smrg case NM2070 : 1643c3c9db83Smrg ret = Neo2070AccelInit(pScreen); 1644c3c9db83Smrg break; 1645c3c9db83Smrg case NM2090 : 1646c3c9db83Smrg case NM2093 : 1647c3c9db83Smrg ret = Neo2090AccelInit(pScreen); 1648c3c9db83Smrg break; 1649c3c9db83Smrg case NM2097 : 1650c3c9db83Smrg case NM2160 : 1651c3c9db83Smrg ret = Neo2097AccelInit(pScreen); 1652c3c9db83Smrg break; 1653c3c9db83Smrg case NM2200 : 1654c3c9db83Smrg case NM2230 : 1655c3c9db83Smrg case NM2360 : 1656c3c9db83Smrg case NM2380 : 1657c3c9db83Smrg ret = Neo2200AccelInit(pScreen); 1658c3c9db83Smrg break; 1659c3c9db83Smrg } 1660c3c9db83Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, 1661c3c9db83Smrg "Acceleration %s Initialized\n",ret ? "" : "not"); 1662c3c9db83Smrg } 1663c3c9db83Smrg 1664692f60a7Smrg xf86SetBackingStore(pScreen); 1665692f60a7Smrg xf86SetSilkenMouse(pScreen); 1666692f60a7Smrg 1667692f60a7Smrg /* Initialise cursor functions */ 1668692f60a7Smrg miDCInitialize (pScreen, xf86GetPointerScreenFuncs()); 1669692f60a7Smrg 1670692f60a7Smrg if (nAcl->CursorAddress != -1) { 1671692f60a7Smrg /* HW cursor functions */ 1672692f60a7Smrg if (!NeoCursorInit(pScreen)) { 16733f6d0e1dSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1674692f60a7Smrg "Hardware cursor initialization failed\n"); 1675692f60a7Smrg return FALSE; 1676692f60a7Smrg } 1677692f60a7Smrg nAcl->UseHWCursor = TRUE; 1678692f60a7Smrg nPtr->NeoHWCursorInitialized = TRUE; 1679692f60a7Smrg } else 1680692f60a7Smrg nAcl->UseHWCursor = FALSE; 1681692f60a7Smrg 1682692f60a7Smrg if (nPtr->shadowFB) { 1683692f60a7Smrg nPtr->refreshArea = neoRefreshArea; 1684692f60a7Smrg 1685692f60a7Smrg if(nPtr->rotate) { 1686692f60a7Smrg if (!nPtr->PointerMoved) { 1687692f60a7Smrg nPtr->PointerMoved = pScrn->PointerMoved; 1688692f60a7Smrg pScrn->PointerMoved = neoPointerMoved; 1689692f60a7Smrg } 1690692f60a7Smrg switch(pScrn->bitsPerPixel) { 1691692f60a7Smrg case 8: nPtr->refreshArea = neoRefreshArea8; break; 1692692f60a7Smrg case 16: nPtr->refreshArea = neoRefreshArea16; break; 1693692f60a7Smrg case 24: nPtr->refreshArea = neoRefreshArea24; break; 1694692f60a7Smrg case 32: nPtr->refreshArea = neoRefreshArea32; break; 1695692f60a7Smrg } 1696692f60a7Smrg } 1697692f60a7Smrg#if 0 1698692f60a7Smrg ShadowFBInit(pScreen, nPtr->refreshArea); 1699692f60a7Smrg#else 1700eaa3dbe0Smrg NEOShadowInit (pScreen); 1701692f60a7Smrg#endif 1702692f60a7Smrg } 1703692f60a7Smrg 1704692f60a7Smrg /* Initialise default colourmap */ 1705692f60a7Smrg if(!miCreateDefColormap(pScreen)) 1706692f60a7Smrg return FALSE; 1707692f60a7Smrg 1708692f60a7Smrg if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, 1709692f60a7Smrg NEOLoadPalette, NULL, 1710692f60a7Smrg CMAP_PALETTED_TRUECOLOR | CMAP_RELOAD_ON_MODE_SWITCH)) 1711692f60a7Smrg return FALSE; 1712692f60a7Smrg 17132e71ea71Smrg#ifndef XSERVER_LIBPCIACCESS 1714692f60a7Smrg racflag |= RAC_COLORMAP; 1715692f60a7Smrg if (nPtr->NeoHWCursorInitialized) 1716692f60a7Smrg racflag |= RAC_CURSOR; 1717692f60a7Smrg 1718692f60a7Smrg pScrn->racIoFlags = pScrn->racMemFlags = racflag; 17192e71ea71Smrg#endif 1720692f60a7Smrg 1721692f60a7Smrg NEOInitVideo(pScreen); 1722692f60a7Smrg 172395903e71Smrg pScreen->SaveScreen = NEOSaveScreen; 1724692f60a7Smrg 1725692f60a7Smrg /* Setup DPMS mode */ 1726692f60a7Smrg if (nPtr->NeoChipset != NM2070) 1727692f60a7Smrg xf86DPMSInit(pScreen, (DPMSSetProcPtr)NeoDisplayPowerManagementSet, 1728692f60a7Smrg 0); 1729692f60a7Smrg 1730c3c9db83Smrg pScrn->memPhysBase = (unsigned long)nPtr->NeoLinearAddr; 1731c3c9db83Smrg pScrn->fbOffset = 0; 1732692f60a7Smrg 1733692f60a7Smrg /* Wrap the current CloseScreen function */ 1734692f60a7Smrg nPtr->CloseScreen = pScreen->CloseScreen; 1735692f60a7Smrg pScreen->CloseScreen = NEOCloseScreen; 1736692f60a7Smrg 1737692f60a7Smrg /* Report any unused options (only for the first generation) */ 1738692f60a7Smrg if (serverGeneration == 1) { 1739692f60a7Smrg xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 1740692f60a7Smrg } 1741692f60a7Smrg 1742692f60a7Smrg return TRUE; 1743692f60a7Smrg} 1744692f60a7Smrg 1745692f60a7Smrg/* Mandatory */ 1746692f60a7SmrgBool 17473f6d0e1dSmrgNEOSwitchMode(SWITCH_MODE_ARGS_DECL) 1748692f60a7Smrg{ 17493f6d0e1dSmrg SCRN_INFO_PTR(arg); 17503f6d0e1dSmrg return neoModeInit(pScrn, mode); 1751692f60a7Smrg} 1752692f60a7Smrg 1753692f60a7Smrg/* Mandatory */ 1754692f60a7Smrgvoid 17553f6d0e1dSmrgNEOAdjustFrame(ADJUST_FRAME_ARGS_DECL) 1756692f60a7Smrg{ 17573f6d0e1dSmrg SCRN_INFO_PTR(arg); 1758692f60a7Smrg NEOPtr nPtr; 1759692f60a7Smrg vgaHWPtr hwp; 1760692f60a7Smrg int oldExtCRTDispAddr; 1761692f60a7Smrg int Base; 1762692f60a7Smrg 1763692f60a7Smrg hwp = VGAHWPTR(pScrn); 1764692f60a7Smrg nPtr = NEOPTR(pScrn); 1765692f60a7Smrg 1766692f60a7Smrg if (nPtr->showcache && y) { 1767692f60a7Smrg int lastline = nPtr->NeoFbMapSize / 1768692f60a7Smrg ((pScrn->displayWidth * pScrn->bitsPerPixel) / 8); 1769692f60a7Smrg 1770692f60a7Smrg lastline -= pScrn->currentMode->VDisplay; 1771692f60a7Smrg y += pScrn->virtualY - 1; 1772692f60a7Smrg if (y > lastline) y = lastline; 1773692f60a7Smrg } 1774692f60a7Smrg 1775692f60a7Smrg Base = (y * pScrn->displayWidth + x) >> 2; 1776692f60a7Smrg 1777692f60a7Smrg /* Scale Base by the number of bytes per pixel. */ 1778692f60a7Smrg switch (pScrn->depth) { 1779692f60a7Smrg case 8 : 1780692f60a7Smrg break; 1781692f60a7Smrg case 15 : 1782692f60a7Smrg case 16 : 1783692f60a7Smrg Base *= 2; 1784692f60a7Smrg break; 1785692f60a7Smrg case 24 : 1786692f60a7Smrg Base *= 3; 1787692f60a7Smrg break; 1788692f60a7Smrg default : 1789692f60a7Smrg break; 1790692f60a7Smrg } 1791692f60a7Smrg /* 1792692f60a7Smrg * These are the generic starting address registers. 1793692f60a7Smrg */ 1794692f60a7Smrg VGAwCR(0x0C, (Base & 0x00FF00) >> 8); 1795692f60a7Smrg VGAwCR(0x0D, (Base & 0x00FF)); 1796692f60a7Smrg 1797692f60a7Smrg /* 1798692f60a7Smrg * Make sure we don't clobber some other bits that might already 1799692f60a7Smrg * have been set. NOTE: NM2200 has a writable bit 3, but it shouldn't 1800692f60a7Smrg * be needed. 1801692f60a7Smrg */ 1802692f60a7Smrg oldExtCRTDispAddr = VGArGR(0x0E); 1803692f60a7Smrg VGAwGR(0x0E,(((Base >> 16) & 0x07) | (oldExtCRTDispAddr & 0xf8))); 1804692f60a7Smrg#if 0 1805692f60a7Smrg /* 1806692f60a7Smrg * This is a workaround for a higher level bug that causes the cursor 1807692f60a7Smrg * to be at the wrong position after a virtual screen resolution change 1808692f60a7Smrg */ 1809692f60a7Smrg if (nPtr->NeoHWCursorInitialized) { /*§§§ do we still need this?*/ 1810692f60a7Smrg NeoRepositionCursor(); 1811692f60a7Smrg } 1812692f60a7Smrg#endif 1813692f60a7Smrg} 1814692f60a7Smrg 1815692f60a7Smrg/* Mandatory */ 1816692f60a7Smrgstatic Bool 18173f6d0e1dSmrgNEOCloseScreen(CLOSE_SCREEN_ARGS_DECL) 1818692f60a7Smrg{ 18193f6d0e1dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 1820692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 1821692f60a7Smrg 1822692f60a7Smrg if(pScrn->vtSema){ 1823692f60a7Smrg if (nPtr->NeoHWCursorShown) 1824692f60a7Smrg NeoHideCursor(pScrn); 1825692f60a7Smrg neoRestore(pScrn, &(VGAHWPTR(pScrn))->SavedReg, &nPtr->NeoSavedReg, TRUE); 1826692f60a7Smrg 1827692f60a7Smrg neoLock(pScrn); 1828692f60a7Smrg neoUnmapMem(pScrn); 1829692f60a7Smrg } 18303f6d0e1dSmrg#ifdef HAVE_XAA_H 1831692f60a7Smrg if (nPtr->AccelInfoRec) 1832692f60a7Smrg XAADestroyInfoRec(nPtr->AccelInfoRec); 18333f6d0e1dSmrg#endif 1834692f60a7Smrg if (nPtr->CursorInfo) 1835692f60a7Smrg xf86DestroyCursorInfoRec(nPtr->CursorInfo); 1836692f60a7Smrg if (nPtr->ShadowPtr) 18373f6d0e1dSmrg free(nPtr->ShadowPtr); 1838692f60a7Smrg 1839692f60a7Smrg pScrn->vtSema = FALSE; 1840692f60a7Smrg pScreen->CloseScreen = nPtr->CloseScreen; 18413f6d0e1dSmrg return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 1842692f60a7Smrg} 1843692f60a7Smrg 1844692f60a7Smrg/* Optional */ 1845692f60a7Smrgstatic void 18463f6d0e1dSmrgNEOFreeScreen(FREE_SCREEN_ARGS_DECL) 1847692f60a7Smrg{ 18483f6d0e1dSmrg SCRN_INFO_PTR(arg); 1849692f60a7Smrg if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) 18503f6d0e1dSmrg vgaHWFreeHWRec(pScrn); 18513f6d0e1dSmrg NEOFreeRec(pScrn); 1852692f60a7Smrg} 1853692f60a7Smrg 1854692f60a7Smrg/* Optional */ 1855692f60a7Smrgstatic ModeStatus 18563f6d0e1dSmrgNEOValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 1857692f60a7Smrg{ 18583f6d0e1dSmrg SCRN_INFO_PTR(arg); 1859692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 1860692f60a7Smrg int vDisplay = mode->VDisplay * ((mode->Flags & V_DBLSCAN) ? 2 : 1); 1861692f60a7Smrg 1862692f60a7Smrg /* 1863692f60a7Smrg * Is there any LineCompare Bit 10? Where? 1864692f60a7Smrg * The 9 well known VGA bits give us a maximum height of 1024 1865692f60a7Smrg */ 1866692f60a7Smrg if (vDisplay > 1024) 1867692f60a7Smrg return MODE_BAD; 1868692f60a7Smrg 1869692f60a7Smrg /* 1870692f60a7Smrg * Limit the modes to just those allowed by the various NeoMagic 1871692f60a7Smrg * chips. 1872692f60a7Smrg */ 1873692f60a7Smrg 1874692f60a7Smrg if (nPtr->overrideValidate) { 18753f6d0e1dSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "display mode validation disabled\n"); 1876692f60a7Smrg } else { 1877692f60a7Smrg /* 1878692f60a7Smrg * When the LCD is active, only allow modes that are (1) equal to 1879692f60a7Smrg * or smaller than the size of the panel and (2) are one of the 1880692f60a7Smrg * following sizes: 1024x768, 800x600, 640x480. 1881692f60a7Smrg */ 1882692f60a7Smrg if (nPtr->internDisp || !nPtr->externDisp) { 1883692f60a7Smrg /* Is the mode larger than the LCD panel? */ 1884692f60a7Smrg if ((mode->HDisplay > nPtr->NeoPanelWidth) || 1885692f60a7Smrg (vDisplay > nPtr->NeoPanelHeight)) { 18863f6d0e1dSmrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, "Removing mode (%dx%d) " 1887692f60a7Smrg "larger than the LCD panel (%dx%d)\n", 1888692f60a7Smrg mode->HDisplay, 1889692f60a7Smrg mode->VDisplay, 1890692f60a7Smrg nPtr->NeoPanelWidth, 1891692f60a7Smrg nPtr->NeoPanelHeight); 1892692f60a7Smrg return(MODE_BAD); 1893692f60a7Smrg } 1894692f60a7Smrg 1895692f60a7Smrg /* Is the mode one of the acceptable sizes? */ 1896692f60a7Smrg switch (mode->HDisplay) { 1897692f60a7Smrg case 1280: 1898692f60a7Smrg if (mode->VDisplay == 1024) 1899692f60a7Smrg return(MODE_OK); 1900692f60a7Smrg break; 1901692f60a7Smrg case 1024 : 1902692f60a7Smrg if (mode->VDisplay == 768) 1903692f60a7Smrg return(MODE_OK); 1904692f60a7Smrg if ((mode->VDisplay == 480) && (nPtr->NeoPanelHeight == 480)) 1905692f60a7Smrg return(MODE_OK); 1906692f60a7Smrg break; 1907692f60a7Smrg case 800 : 1908692f60a7Smrg if (mode->VDisplay == 600) 1909692f60a7Smrg return(MODE_OK); 1910692f60a7Smrg if ((mode->VDisplay == 480) && (nPtr->NeoPanelHeight == 480)) 1911692f60a7Smrg return(MODE_OK); 1912692f60a7Smrg break; 1913692f60a7Smrg case 640 : 1914692f60a7Smrg if (mode->VDisplay == 480) 1915692f60a7Smrg return(MODE_OK); 1916692f60a7Smrg break; 1917692f60a7Smrg#if 1 1918692f60a7Smrg case 320: 1919692f60a7Smrg if (mode->VDisplay == 240) 1920692f60a7Smrg return(MODE_OK); 1921692f60a7Smrg break; 1922692f60a7Smrg#endif 1923692f60a7Smrg default: 1924692f60a7Smrg break; 1925692f60a7Smrg } 1926692f60a7Smrg 19273f6d0e1dSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Removing mode (%dx%d) that won't " 1928692f60a7Smrg "display properly on LCD\n", 1929692f60a7Smrg mode->HDisplay, 1930692f60a7Smrg mode->VDisplay); 1931692f60a7Smrg return(MODE_BAD); 1932692f60a7Smrg } 1933692f60a7Smrg } 1934692f60a7Smrg return(MODE_OK); 1935692f60a7Smrg} 1936692f60a7Smrg 1937692f60a7Smrgstatic void 1938692f60a7SmrgneoLock(ScrnInfoPtr pScrn) 1939692f60a7Smrg{ 1940692f60a7Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 1941692f60a7Smrg 1942692f60a7Smrg VGAwGR(0x09,0x00); 1943692f60a7Smrg vgaHWLock(hwp); 1944692f60a7Smrg} 1945692f60a7Smrg 1946692f60a7Smrgstatic void 1947692f60a7SmrgneoUnlock(ScrnInfoPtr pScrn) 1948692f60a7Smrg{ 1949692f60a7Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 1950692f60a7Smrg 1951692f60a7Smrg vgaHWUnlock(hwp); 1952692f60a7Smrg VGAwGR(0x09,0x26); 1953692f60a7Smrg} 1954692f60a7Smrg 1955692f60a7Smrgstatic Bool 1956692f60a7SmrgneoMapMem(ScrnInfoPtr pScrn) 1957692f60a7Smrg{ 1958692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 1959692f60a7Smrg 1960c3c9db83Smrg if (!nPtr->noMMIO) { 1961c3c9db83Smrg if (nPtr->pEnt->location.type == BUS_PCI){ 196254569438Smrg 196354569438Smrg#ifndef XSERVER_LIBPCIACCESS 1964c3c9db83Smrg nPtr->NeoMMIOBase = 1965c3c9db83Smrg xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 1966c3c9db83Smrg nPtr->PciTag, nPtr->NeoMMIOAddr, 1967c3c9db83Smrg 0x200000L); 1968c3c9db83Smrg if (nPtr->NeoMMIOAddr2 != 0){ 1969c3c9db83Smrg nPtr->NeoMMIOBase2 = 1970c3c9db83Smrg xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, 1971c3c9db83Smrg nPtr->PciTag, nPtr->NeoMMIOAddr2, 1972c3c9db83Smrg 0x100000L); 1973c3c9db83Smrg } 197454569438Smrg 197554569438Smrg#else 1976c3c9db83Smrg void** result = (void**)&nPtr->NeoMMIOBase; 1977c3c9db83Smrg int err = pci_device_map_range(nPtr->PciInfo, 1978c3c9db83Smrg nPtr->NeoMMIOAddr, 1979c3c9db83Smrg 0x200000L, 1980c3c9db83Smrg PCI_DEV_MAP_FLAG_WRITABLE, 1981c3c9db83Smrg result); 1982c3c9db83Smrg if (err) 1983c3c9db83Smrg return FALSE; 1984c3c9db83Smrg 1985c3c9db83Smrg if (nPtr->NeoMMIOAddr2 != 0){ 1986c3c9db83Smrg result = (void**)&nPtr->NeoMMIOBase2; 1987c3c9db83Smrg err = pci_device_map_range(nPtr->PciInfo, 1988c3c9db83Smrg nPtr->NeoMMIOAddr2, 1989c3c9db83Smrg 0x100000L, 1990c3c9db83Smrg PCI_DEV_MAP_FLAG_WRITABLE, 1991c3c9db83Smrg result); 1992c3c9db83Smrg 1993c3c9db83Smrg if (err) 1994c3c9db83Smrg return FALSE; 1995c3c9db83Smrg } 199654569438Smrg#endif 1997c3c9db83Smrg } else 199895903e71Smrg#ifdef VIDMEM_MMIO 1999c3c9db83Smrg nPtr->NeoMMIOBase = 2000c3c9db83Smrg xf86MapVidMem(pScrn->scrnIndex, 2001c3c9db83Smrg VIDMEM_MMIO, nPtr->NeoMMIOAddr, 2002c3c9db83Smrg 0x200000L); 200395903e71Smrg#endif 2004c3c9db83Smrg if (nPtr->NeoMMIOBase == NULL) 2005c3c9db83Smrg return FALSE; 2006c3c9db83Smrg } 2007692f60a7Smrg 2008c3c9db83Smrg if (nPtr->pEnt->location.type == BUS_PCI) 200954569438Smrg 201054569438Smrg#ifndef XSERVER_LIBPCIACCESS 2011c3c9db83Smrg nPtr->NeoFbBase = 2012c3c9db83Smrg xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 2013c3c9db83Smrg nPtr->PciTag, 2014c3c9db83Smrg (unsigned long)nPtr->NeoLinearAddr, 2015c3c9db83Smrg nPtr->NeoFbMapSize); 201654569438Smrg#else 2017c3c9db83Smrg { 2018c3c9db83Smrg void** result = (void**)&nPtr->NeoFbBase; 2019c3c9db83Smrg int err = pci_device_map_range(nPtr->PciInfo, 2020c3c9db83Smrg nPtr->NeoLinearAddr, 2021c3c9db83Smrg nPtr->NeoFbMapSize, 2022c3c9db83Smrg PCI_DEV_MAP_FLAG_WRITABLE | 2023c3c9db83Smrg PCI_DEV_MAP_FLAG_WRITE_COMBINE, 2024c3c9db83Smrg result); 2025c3c9db83Smrg if (err) 2026c3c9db83Smrg return FALSE; 2027692f60a7Smrg } 2028c3c9db83Smrg#endif 2029c3c9db83Smrg else 203095903e71Smrg#ifdef VIDMEM_FRAMEBUFFER 2031c3c9db83Smrg nPtr->NeoFbBase = 2032c3c9db83Smrg xf86MapVidMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, 2033c3c9db83Smrg (unsigned long)nPtr->NeoLinearAddr, 2034c3c9db83Smrg nPtr->NeoFbMapSize); 203595903e71Smrg#endif 2036c3c9db83Smrg if (nPtr->NeoFbBase == NULL) 2037c3c9db83Smrg return FALSE; 2038692f60a7Smrg return TRUE; 2039692f60a7Smrg} 2040692f60a7Smrg 2041692f60a7Smrg/* 2042692f60a7Smrg * Unmap the framebuffer and MMIO memory. 2043692f60a7Smrg */ 2044692f60a7Smrg 2045692f60a7Smrgstatic Bool 2046692f60a7SmrgneoUnmapMem(ScrnInfoPtr pScrn) 2047692f60a7Smrg{ 2048692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 2049692f60a7Smrg 205054569438Smrg#ifndef XSERVER_LIBPCIACCESS 2051c3c9db83Smrg if (nPtr->NeoMMIOBase) 2052c3c9db83Smrg xf86UnMapVidMem(pScrn->scrnIndex, (pointer)nPtr->NeoMMIOBase, 2053c3c9db83Smrg 0x200000L); 205454569438Smrg#else 2055c3c9db83Smrg if (nPtr->NeoMMIOBase) 2056c3c9db83Smrg pci_device_unmap_range(nPtr->PciInfo, (pointer)nPtr->NeoMMIOBase, 0x200000L); 205754569438Smrg#endif 2058c3c9db83Smrg nPtr->NeoMMIOBase = NULL; 205954569438Smrg#ifndef XSERVER_LIBPCIACCESS 2060c3c9db83Smrg if (nPtr->NeoMMIOBase2) 2061c3c9db83Smrg xf86UnMapVidMem(pScrn->scrnIndex, (pointer)nPtr->NeoMMIOBase2, 2062c3c9db83Smrg 0x100000L); 206354569438Smrg#else 2064c3c9db83Smrg if (nPtr->NeoMMIOBase2) 2065c3c9db83Smrg pci_device_unmap_range(nPtr->PciInfo, (pointer)nPtr->NeoMMIOBase2, 0x100000L); 206654569438Smrg#endif 2067c3c9db83Smrg nPtr->NeoMMIOBase2 = NULL; 206854569438Smrg#ifndef XSERVER_LIBPCIACCESS 2069c3c9db83Smrg xf86UnMapVidMem(pScrn->scrnIndex, (pointer)nPtr->NeoFbBase, 2070c3c9db83Smrg nPtr->NeoFbMapSize); 207154569438Smrg#else 2072c3c9db83Smrg pci_device_unmap_range(nPtr->PciInfo, (pointer)nPtr->NeoFbBase, nPtr->NeoFbMapSize); 207354569438Smrg#endif 2074692f60a7Smrg nPtr->NeoFbBase = NULL; 2075692f60a7Smrg 2076692f60a7Smrg return TRUE; 2077692f60a7Smrg} 2078692f60a7Smrg 2079692f60a7Smrgstatic void 2080692f60a7SmrgneoSave(ScrnInfoPtr pScrn) 2081692f60a7Smrg{ 2082692f60a7Smrg vgaRegPtr VgaSave = &VGAHWPTR(pScrn)->SavedReg; 2083692f60a7Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 2084692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 2085692f60a7Smrg NeoRegPtr save; 2086692f60a7Smrg int i; 2087692f60a7Smrg 2088692f60a7Smrg save = &nPtr->NeoSavedReg; 2089692f60a7Smrg 2090692f60a7Smrg VGAwGR(0x09,0x26); 2091692f60a7Smrg /* 2092692f60a7Smrg * Whatever code is needed to get back to bank zero goes here. 2093692f60a7Smrg */ 2094692f60a7Smrg VGAwGR(0x15,0x00); 2095692f60a7Smrg 2096692f60a7Smrg /* get generic registers */ 2097692f60a7Smrg vgaHWSave(pScrn, VgaSave, VGA_SR_ALL); 2098692f60a7Smrg 2099692f60a7Smrg /* 2100692f60a7Smrg * The port I/O code necessary to read in the extended registers 2101692f60a7Smrg * into the fields of the vgaNeoRec structure goes here. 2102692f60a7Smrg */ 2103692f60a7Smrg 2104692f60a7Smrg save->GeneralLockReg = VGArGR(0x0A); 2105692f60a7Smrg 2106692f60a7Smrg save->ExtCRTDispAddr = VGArGR(0x0E); 2107692f60a7Smrg if (nPtr->NeoChipset != NM2070) { 2108692f60a7Smrg save->ExtCRTOffset = VGArGR(0x0F); 2109692f60a7Smrg } 2110692f60a7Smrg save->SysIfaceCntl1 = VGArGR(0x10); 2111692f60a7Smrg save->SysIfaceCntl2 = VGArGR(0x11); 2112692f60a7Smrg save->SingleAddrPage = VGArGR(0x15); 2113692f60a7Smrg save->DualAddrPage = VGArGR(0x16); 2114692f60a7Smrg save->PanelDispCntlReg1 = VGArGR(0x20); 2115692f60a7Smrg save->PanelDispCntlReg2 = VGArGR(0x25); 2116692f60a7Smrg save->PanelDispCntlReg3 = VGArGR(0x30); 2117692f60a7Smrg save->PanelVertCenterReg1 = VGArGR(0x28); 2118692f60a7Smrg save->PanelVertCenterReg2 = VGArGR(0x29); 2119692f60a7Smrg save->PanelVertCenterReg3 = VGArGR(0x2A); 2120692f60a7Smrg if (nPtr->NeoChipset != NM2070) { 2121692f60a7Smrg save->PanelVertCenterReg4 = VGArGR(0x32); 2122692f60a7Smrg save->PanelHorizCenterReg1 = VGArGR(0x33); 2123692f60a7Smrg save->PanelHorizCenterReg2 = VGArGR(0x34); 2124692f60a7Smrg save->PanelHorizCenterReg3 = VGArGR(0x35); 2125692f60a7Smrg } 2126692f60a7Smrg if (nPtr->NeoChipset == NM2160) { 2127692f60a7Smrg save->PanelHorizCenterReg4 = VGArGR(0x36); 2128692f60a7Smrg } 2129692f60a7Smrg if (nPtr->NeoChipset == NM2200 || nPtr->NeoChipset == NM2230 2130692f60a7Smrg || nPtr->NeoChipset == NM2360 || nPtr->NeoChipset == NM2380) { 2131692f60a7Smrg save->PanelHorizCenterReg4 = VGArGR(0x36); 2132692f60a7Smrg save->PanelVertCenterReg5 = VGArGR(0x37); 2133692f60a7Smrg save->PanelHorizCenterReg5 = VGArGR(0x38); 2134692f60a7Smrg } 2135692f60a7Smrg save->ExtColorModeSelect = VGArGR(0x90); 2136692f60a7Smrg save->VCLK3NumeratorLow = VGArGR(0x9B); 2137692f60a7Smrg if (nPtr->NeoChipset == NM2200 || nPtr->NeoChipset == NM2230 2138692f60a7Smrg || nPtr->NeoChipset == NM2360 || nPtr->NeoChipset == NM2380) 2139692f60a7Smrg save->VCLK3NumeratorHigh = VGArGR(0x8F); 2140692f60a7Smrg save->VCLK3Denominator = VGArGR(0x9F); 2141692f60a7Smrg save->ProgramVCLK = TRUE; 2142692f60a7Smrg 2143692f60a7Smrg if (save->reg == NULL) 2144692f60a7Smrg save->reg = (regSavePtr)xnfcalloc(sizeof(regSaveRec), 1); 2145692f60a7Smrg else 2146692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2147692f60a7Smrg "Non-NULL reg in NeoSave: reg=%p\n", (void *)save->reg); 2148692f60a7Smrg 2149692f60a7Smrg save->reg->CR[0x23] = VGArCR(0x23); 2150692f60a7Smrg save->reg->CR[0x25] = VGArCR(0x25); 2151692f60a7Smrg save->reg->CR[0x2F] = VGArCR(0x2F); 2152692f60a7Smrg for (i = 0x40; i <= 0x59; i++) { 2153692f60a7Smrg save->reg->CR[i] = VGArCR(i); 2154692f60a7Smrg } 2155692f60a7Smrg for (i = 0x60; i <= 0x69; i++) { 2156692f60a7Smrg save->reg->CR[i] = VGArCR(i); 2157692f60a7Smrg } 2158692f60a7Smrg for (i = 0x70; i <= NEO_EXT_CR_MAX; i++) { 2159692f60a7Smrg save->reg->CR[i] = VGArCR(i); 2160692f60a7Smrg } 2161692f60a7Smrg 2162692f60a7Smrg for (i = 0x0A; i <= NEO_EXT_GR_MAX; i++) { 2163692f60a7Smrg save->reg->GR[i] = VGArGR(i); 2164692f60a7Smrg } 2165692f60a7Smrg} 2166692f60a7Smrg 2167692f60a7Smrg/* 2168692f60a7Smrg * neoProgramShadowRegs 2169692f60a7Smrg * 2170692f60a7Smrg * Setup the shadow registers to their default values. The NeoSave 2171692f60a7Smrg * routines will restore the proper values on server exit. 2172692f60a7Smrg */ 2173692f60a7Smrgstatic void 2174692f60a7SmrgneoProgramShadowRegs(ScrnInfoPtr pScrn, vgaRegPtr VgaReg, NeoRegPtr restore) 2175692f60a7Smrg{ 2176692f60a7Smrg int i; 2177692f60a7Smrg Bool noProgramShadowRegs; 2178692f60a7Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 2179692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 2180692f60a7Smrg Bool prog_lcd; 2181692f60a7Smrg 2182692f60a7Smrg /* 2183692f60a7Smrg * If display is external only and we want internal 2184692f60a7Smrg * we need to program the shadow registers. 2185692f60a7Smrg */ 2186692f60a7Smrg prog_lcd = (((VGArGR(0x20) & 0x3) == 0x1) && nPtr->internDisp); 2187692f60a7Smrg 2188692f60a7Smrg 2189692f60a7Smrg /* 2190692f60a7Smrg * Convoluted logic for shadow register programming. 2191692f60a7Smrg * 2192692f60a7Smrg * As far as we know, shadow programming is needed for the 2070, 2193692f60a7Smrg * but not in stretched modes. Special case this code. 2194692f60a7Smrg */ 2195692f60a7Smrg switch (nPtr->NeoChipset) { 2196692f60a7Smrg case NM2070: 2197692f60a7Smrg /* Program the shadow regs by default */ 2198692f60a7Smrg noProgramShadowRegs = FALSE; 2199692f60a7Smrg if (!nPtr->progLcdRegs && !prog_lcd) 2200692f60a7Smrg noProgramShadowRegs = TRUE; 2201692f60a7Smrg 2202692f60a7Smrg if (restore->PanelDispCntlReg2 & 0x84) { 2203692f60a7Smrg /* Don't program by default if in stretch mode */ 2204692f60a7Smrg noProgramShadowRegs = TRUE; 2205692f60a7Smrg if (nPtr->progLcdStretch) 2206692f60a7Smrg noProgramShadowRegs = FALSE; 2207692f60a7Smrg } 2208692f60a7Smrg break; 2209692f60a7Smrg case NM2090: 2210692f60a7Smrg case NM2093: 2211692f60a7Smrg case NM2097: 2212692f60a7Smrg case NM2160: 2213692f60a7Smrg case NM2200: 2214692f60a7Smrg case NM2230: 2215692f60a7Smrg case NM2360: 2216692f60a7Smrg case NM2380: 2217692f60a7Smrg default: 2218692f60a7Smrg /* Don't program the shadow regs by default */ 2219692f60a7Smrg noProgramShadowRegs = TRUE; 2220692f60a7Smrg if (nPtr->progLcdRegs || prog_lcd) 2221692f60a7Smrg noProgramShadowRegs = FALSE; 2222692f60a7Smrg 2223692f60a7Smrg if (restore->PanelDispCntlReg2 & 0x84) { 2224692f60a7Smrg /* Only change the behavior if an option is set */ 2225692f60a7Smrg if (nPtr->progLcdStretchOpt) 2226692f60a7Smrg noProgramShadowRegs = !nPtr->progLcdStretch; 2227692f60a7Smrg } 2228692f60a7Smrg break; 2229692f60a7Smrg } 2230692f60a7Smrg 2231692f60a7Smrg if (noProgramShadowRegs) { 2232692f60a7Smrg xf86DrvMsgVerb(pScrn->scrnIndex,X_INFO,5,"Not programming shadow registers\n"); 2233692f60a7Smrg if (nPtr->NeoSavedReg.reg){ 2234692f60a7Smrg for (i = 0x40; i <= 0x59; i++) { 2235692f60a7Smrg VGAwCR(i, nPtr->NeoSavedReg.reg->CR[i]); 2236692f60a7Smrg } 2237692f60a7Smrg for (i = 0x60; i <= 0x64; i++) { 2238692f60a7Smrg VGAwCR(i, nPtr->NeoSavedReg.reg->CR[i]); 2239692f60a7Smrg } 2240692f60a7Smrg } 2241692f60a7Smrg } else { 2242692f60a7Smrg /* 2243692f60a7Smrg * Program the shadow regs based on the panel width. This works 2244692f60a7Smrg * fine for normal sized panels, but what about the odd ones like 2245692f60a7Smrg * the Libretto 100 which has an 800x480 panel??? 2246692f60a7Smrg */ 2247692f60a7Smrg switch (nPtr->NeoPanelWidth) { 2248692f60a7Smrg case 640 : 2249692f60a7Smrg VGAwCR(0x40,0x5F); 2250692f60a7Smrg VGAwCR(0x41,0x50); 2251692f60a7Smrg VGAwCR(0x42,0x02); 2252692f60a7Smrg VGAwCR(0x43,0x55); 2253692f60a7Smrg VGAwCR(0x44,0x81); 2254692f60a7Smrg VGAwCR(0x45,0x0B); 2255692f60a7Smrg VGAwCR(0x46,0x2E); 2256692f60a7Smrg VGAwCR(0x47,0xEA); 2257692f60a7Smrg VGAwCR(0x48,0x0C); 2258692f60a7Smrg VGAwCR(0x49,0xE7); 2259692f60a7Smrg VGAwCR(0x4A,0x04); 2260692f60a7Smrg VGAwCR(0x4B,0x2D); 2261692f60a7Smrg VGAwCR(0x4C,0x28); 2262692f60a7Smrg VGAwCR(0x4D,0x90); 2263692f60a7Smrg VGAwCR(0x4E,0x2B); 2264692f60a7Smrg VGAwCR(0x4F,0xA0); 2265692f60a7Smrg break; 2266692f60a7Smrg case 800 : 2267692f60a7Smrg switch (nPtr->NeoPanelHeight) { 2268692f60a7Smrg case 600: 2269692f60a7Smrg VGAwCR(0x40,0x7F); 2270692f60a7Smrg VGAwCR(0x41,0x63); 2271692f60a7Smrg VGAwCR(0x42,0x02); 2272692f60a7Smrg VGAwCR(0x43,0x6C); 2273692f60a7Smrg VGAwCR(0x44,0x1C); 2274692f60a7Smrg VGAwCR(0x45,0x72); 2275692f60a7Smrg VGAwCR(0x46,0xE0); 2276692f60a7Smrg VGAwCR(0x47,0x58); 2277692f60a7Smrg VGAwCR(0x48,0x0C); 2278692f60a7Smrg VGAwCR(0x49,0x57); 2279692f60a7Smrg VGAwCR(0x4A,0x73); 2280692f60a7Smrg VGAwCR(0x4B,0x3D); 2281692f60a7Smrg VGAwCR(0x4C,0x31); 2282692f60a7Smrg VGAwCR(0x4D,0x01); 2283692f60a7Smrg VGAwCR(0x4E,0x36); 2284692f60a7Smrg VGAwCR(0x4F,0x1E); 2285692f60a7Smrg if (nPtr->NeoChipset != NM2070) { 2286692f60a7Smrg VGAwCR(0x50,0x6B); 2287692f60a7Smrg VGAwCR(0x51,0x4F); 2288692f60a7Smrg VGAwCR(0x52,0x0E); 2289692f60a7Smrg VGAwCR(0x53,0x58); 2290692f60a7Smrg VGAwCR(0x54,0x88); 2291692f60a7Smrg VGAwCR(0x55,0x33); 2292692f60a7Smrg VGAwCR(0x56,0x27); 2293692f60a7Smrg VGAwCR(0x57,0x16); 2294692f60a7Smrg VGAwCR(0x58,0x2C); 2295692f60a7Smrg VGAwCR(0x59,0x94); 2296692f60a7Smrg } 2297692f60a7Smrg break; 2298692f60a7Smrg case 480: 2299692f60a7Smrg VGAwCR(0x40,0x7F); 2300692f60a7Smrg VGAwCR(0x41,0x63); 2301692f60a7Smrg VGAwCR(0x42,0x02); 2302692f60a7Smrg VGAwCR(0x43,0x6B); 2303692f60a7Smrg VGAwCR(0x44,0x1B); 2304692f60a7Smrg VGAwCR(0x45,0x72); 2305692f60a7Smrg VGAwCR(0x46,0xE0); 2306692f60a7Smrg VGAwCR(0x47,0x1C); 2307692f60a7Smrg VGAwCR(0x48,0x00); 2308692f60a7Smrg VGAwCR(0x49,0x57); 2309692f60a7Smrg VGAwCR(0x4A,0x73); 2310692f60a7Smrg VGAwCR(0x4B,0x3E); 2311692f60a7Smrg VGAwCR(0x4C,0x31); 2312692f60a7Smrg VGAwCR(0x4D,0x01); 2313692f60a7Smrg VGAwCR(0x4E,0x36); 2314692f60a7Smrg VGAwCR(0x4F,0x1E); 2315692f60a7Smrg VGAwCR(0x50,0x6B); 2316692f60a7Smrg VGAwCR(0x51,0x4F); 2317692f60a7Smrg VGAwCR(0x52,0x0E); 2318692f60a7Smrg VGAwCR(0x53,0x57); 2319692f60a7Smrg VGAwCR(0x54,0x87); 2320692f60a7Smrg VGAwCR(0x55,0x33); 2321692f60a7Smrg VGAwCR(0x56,0x27); 2322692f60a7Smrg VGAwCR(0x57,0x16); 2323692f60a7Smrg VGAwCR(0x58,0x2C); 2324692f60a7Smrg VGAwCR(0x59,0x94); 2325692f60a7Smrg break; 2326692f60a7Smrg break; 2327692f60a7Smrg /* Not done */ 2328692f60a7Smrg } 2329692f60a7Smrg break; 2330692f60a7Smrg case 1024 : 2331692f60a7Smrg switch (nPtr->NeoPanelHeight) { 2332692f60a7Smrg case 768: 2333692f60a7Smrg VGAwCR(0x40,0xA3); 2334692f60a7Smrg VGAwCR(0x41,0x7F); 2335692f60a7Smrg VGAwCR(0x42,0x06); 2336692f60a7Smrg VGAwCR(0x43,0x85); 2337692f60a7Smrg VGAwCR(0x44,0x96); 2338692f60a7Smrg VGAwCR(0x45,0x24); 2339692f60a7Smrg VGAwCR(0x46,0xE5); 2340692f60a7Smrg VGAwCR(0x47,0x02); 2341692f60a7Smrg VGAwCR(0x48,0x08); 2342692f60a7Smrg VGAwCR(0x49,0xFF); 2343692f60a7Smrg VGAwCR(0x4A,0x25); 2344692f60a7Smrg VGAwCR(0x4B,0x4F); 2345692f60a7Smrg VGAwCR(0x4C,0x40); 2346692f60a7Smrg VGAwCR(0x4D,0x00); 2347692f60a7Smrg VGAwCR(0x4E,0x44); 2348692f60a7Smrg VGAwCR(0x4F,0x0C); 2349692f60a7Smrg VGAwCR(0x50,0x7A); 2350692f60a7Smrg VGAwCR(0x51,0x56); 2351692f60a7Smrg VGAwCR(0x52,0x00); 2352692f60a7Smrg VGAwCR(0x53,0x5D); 2353692f60a7Smrg VGAwCR(0x54,0x0E); 2354692f60a7Smrg VGAwCR(0x55,0x3B); 2355692f60a7Smrg VGAwCR(0x56,0x2B); 2356692f60a7Smrg VGAwCR(0x57,0x00); 2357692f60a7Smrg VGAwCR(0x58,0x2F); 2358692f60a7Smrg VGAwCR(0x59,0x18); 2359692f60a7Smrg VGAwCR(0x60,0x88); 2360692f60a7Smrg VGAwCR(0x61,0x63); 2361692f60a7Smrg VGAwCR(0x62,0x0B); 2362692f60a7Smrg VGAwCR(0x63,0x69); 2363692f60a7Smrg VGAwCR(0x64,0x1A); 2364692f60a7Smrg break; 2365692f60a7Smrg case 480: 2366692f60a7Smrg VGAwCR(0x40,0xA3); 2367692f60a7Smrg VGAwCR(0x41,0x7F); 2368692f60a7Smrg VGAwCR(0x42,0x1B); 2369692f60a7Smrg VGAwCR(0x43,0x89); 2370692f60a7Smrg VGAwCR(0x44,0x16); 2371692f60a7Smrg VGAwCR(0x45,0x0B); 2372692f60a7Smrg VGAwCR(0x46,0x2C); 2373692f60a7Smrg VGAwCR(0x47,0xE8); 2374692f60a7Smrg VGAwCR(0x48,0x0C); 2375692f60a7Smrg VGAwCR(0x49,0xE7); 2376692f60a7Smrg VGAwCR(0x4A,0x09); 2377692f60a7Smrg VGAwCR(0x4B,0x4F); 2378692f60a7Smrg VGAwCR(0x4C,0x40); 2379692f60a7Smrg VGAwCR(0x4D,0x00); 2380692f60a7Smrg VGAwCR(0x4E,0x44); 2381692f60a7Smrg VGAwCR(0x4F,0x0C); 2382692f60a7Smrg VGAwCR(0x50,0x7A); 2383692f60a7Smrg VGAwCR(0x51,0x56); 2384692f60a7Smrg VGAwCR(0x52,0x00); 2385692f60a7Smrg VGAwCR(0x53,0x5D); 2386692f60a7Smrg VGAwCR(0x54,0x0E); 2387692f60a7Smrg VGAwCR(0x55,0x3B); 2388692f60a7Smrg VGAwCR(0x56,0x2A); 2389692f60a7Smrg VGAwCR(0x57,0x00); 2390692f60a7Smrg VGAwCR(0x58,0x2F); 2391692f60a7Smrg VGAwCR(0x59,0x18); 2392692f60a7Smrg VGAwCR(0x60,0x88); 2393692f60a7Smrg VGAwCR(0x61,0x63); 2394692f60a7Smrg VGAwCR(0x62,0x0B); 2395692f60a7Smrg VGAwCR(0x63,0x69); 2396692f60a7Smrg VGAwCR(0x64,0x1A); 2397692f60a7Smrg break; 2398692f60a7Smrg } 2399692f60a7Smrg break; 2400692f60a7Smrg case 1280: 2401692f60a7Smrg#ifdef NOT_DONE 2402692f60a7Smrg VGAwCR(0x40,0x?? ); 2403692f60a7Smrg . 2404692f60a7Smrg . 2405692f60a7Smrg . 2406692f60a7Smrg VGAwCR(0x64,0x?? ); 2407692f60a7Smrg break; 2408692f60a7Smrg#else 2409692f60a7Smrg /* Probe should prevent this case for now */ 2410692f60a7Smrg FatalError("1280 panel support incomplete\n"); 2411692f60a7Smrg#endif 2412692f60a7Smrg } 2413692f60a7Smrg } 2414692f60a7Smrg} 2415692f60a7Smrg 2416692f60a7Smrgstatic void 2417692f60a7SmrgneoRestore(ScrnInfoPtr pScrn, vgaRegPtr VgaReg, NeoRegPtr restore, 2418692f60a7Smrg Bool restoreText) 2419692f60a7Smrg{ 2420692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 2421692f60a7Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 2422692f60a7Smrg unsigned char temp; 2423692f60a7Smrg int i; 2424692f60a7Smrg Bool clock_hi = FALSE; 2425692f60a7Smrg 2426692f60a7Smrg vgaHWProtect(pScrn,TRUE); /* Blank the screen */ 2427692f60a7Smrg 2428692f60a7Smrg VGAwGR(0x09,0x26); 2429692f60a7Smrg 2430692f60a7Smrg /* Init the shadow registers if necessary */ 2431692f60a7Smrg neoProgramShadowRegs(pScrn, VgaReg, restore); 2432692f60a7Smrg 2433692f60a7Smrg VGAwGR(0x15,0x00); 2434692f60a7Smrg 2435692f60a7Smrg VGAwGR(0x0A,restore->GeneralLockReg); 2436692f60a7Smrg 2437692f60a7Smrg /* 2438692f60a7Smrg * The color mode needs to be set before calling vgaHWRestore 2439692f60a7Smrg * to ensure the DAC is initialized properly. 2440692f60a7Smrg * 2441692f60a7Smrg * NOTE: Make sure we don't change bits make sure we don't change 2442692f60a7Smrg * any reserved bits. 2443692f60a7Smrg */ 2444692f60a7Smrg temp = VGArGR(0x90); 2445692f60a7Smrg 2446692f60a7Smrg switch (nPtr->NeoChipset) { 2447692f60a7Smrg case NM2070 : 2448692f60a7Smrg temp &= 0xF0; /* Save bits 7:4 */ 2449692f60a7Smrg temp |= (restore->ExtColorModeSelect & ~0xF0); 2450692f60a7Smrg break; 2451692f60a7Smrg case NM2090 : 2452692f60a7Smrg case NM2093 : 2453692f60a7Smrg case NM2097 : 2454692f60a7Smrg case NM2160 : 2455692f60a7Smrg case NM2200 : 2456692f60a7Smrg case NM2230 : 2457692f60a7Smrg case NM2360 : 2458692f60a7Smrg case NM2380 : 2459692f60a7Smrg temp &= 0x70; /* Save bits 6:4 */ 2460692f60a7Smrg temp |= (restore->ExtColorModeSelect & ~0x70); 2461692f60a7Smrg break; 2462692f60a7Smrg } 2463692f60a7Smrg VGAwGR(0x90,temp); 2464692f60a7Smrg 2465692f60a7Smrg /* 2466692f60a7Smrg * In some rare cases a lockup might occur if we don't delay 2467692f60a7Smrg * here. (Reported by Miles Lane) 2468692f60a7Smrg */ 2469c3c9db83Smrg usleep(200000); 2470692f60a7Smrg /* 2471692f60a7Smrg * Disable horizontal and vertical graphics and text expansions so 2472692f60a7Smrg * that vgaHWRestore works properly. 2473692f60a7Smrg */ 2474692f60a7Smrg temp = VGArGR(0x25); 2475692f60a7Smrg temp &= 0x39; 2476692f60a7Smrg VGAwGR(0x25, temp); 2477692f60a7Smrg 2478692f60a7Smrg /* 2479692f60a7Smrg * Sleep for 200ms to make sure that the two operations above have 2480692f60a7Smrg * had time to take effect. 2481692f60a7Smrg */ 2482c3c9db83Smrg usleep(200000); 2483692f60a7Smrg /* 2484692f60a7Smrg * This function handles restoring the generic VGA registers. */ 2485692f60a7Smrg vgaHWRestore(pScrn, VgaReg, 2486692f60a7Smrg VGA_SR_MODE 2487692f60a7Smrg | (restoreText ? (VGA_SR_FONTS | VGA_SR_CMAP) : 0)); 2488692f60a7Smrg 2489692f60a7Smrg VGAwGR(0x0E, restore->ExtCRTDispAddr); 2490692f60a7Smrg VGAwGR(0x0F, restore->ExtCRTOffset); 2491692f60a7Smrg temp = VGArGR(0x10); 2492692f60a7Smrg temp &= 0x0F; /* Save bits 3:0 */ 2493692f60a7Smrg temp |= (restore->SysIfaceCntl1 & ~0x0F); 2494692f60a7Smrg VGAwGR(0x10, temp); 2495692f60a7Smrg 2496692f60a7Smrg VGAwGR(0x11, restore->SysIfaceCntl2); 2497692f60a7Smrg VGAwGR(0x15, restore->SingleAddrPage); 2498692f60a7Smrg VGAwGR(0x16, restore->DualAddrPage); 2499692f60a7Smrg 2500692f60a7Smrg temp = VGArGR(0x20); 2501692f60a7Smrg switch (nPtr->NeoChipset) { 2502692f60a7Smrg case NM2070 : 2503692f60a7Smrg temp &= 0xFC; /* Save bits 7:2 */ 2504692f60a7Smrg temp |= (restore->PanelDispCntlReg1 & ~0xFC); 2505692f60a7Smrg break; 2506692f60a7Smrg case NM2090 : 2507692f60a7Smrg case NM2093 : 2508692f60a7Smrg case NM2097 : 2509692f60a7Smrg case NM2160 : 2510692f60a7Smrg temp &= 0xDC; /* Save bits 7:6,4:2 */ 2511692f60a7Smrg temp |= (restore->PanelDispCntlReg1 & ~0xDC); 2512692f60a7Smrg break; 2513692f60a7Smrg case NM2200 : 2514692f60a7Smrg case NM2230 : 2515692f60a7Smrg case NM2360 : 2516692f60a7Smrg case NM2380 : 2517692f60a7Smrg temp &= 0x98; /* Save bits 7,4:3 */ 2518692f60a7Smrg temp |= (restore->PanelDispCntlReg1 & ~0x98); 2519692f60a7Smrg break; 2520692f60a7Smrg } 2521692f60a7Smrg VGAwGR(0x20, temp); 2522692f60a7Smrg 2523692f60a7Smrg temp = VGArGR(0x25); 2524692f60a7Smrg temp &= 0x38; /* Save bits 5:3 */ 2525692f60a7Smrg temp |= (restore->PanelDispCntlReg2 & ~0x38); 2526692f60a7Smrg VGAwGR(0x25, temp); 2527692f60a7Smrg 2528692f60a7Smrg if (nPtr->NeoChipset != NM2070) { 2529692f60a7Smrg temp = VGArGR(0x30); 2530692f60a7Smrg temp &= 0xEF; /* Save bits 7:5 and bits 3:0 */ 2531692f60a7Smrg temp |= (restore->PanelDispCntlReg3 & ~0xEF); 2532692f60a7Smrg VGAwGR(0x30, temp); 2533692f60a7Smrg } 2534692f60a7Smrg 2535692f60a7Smrg VGAwGR(0x28, restore->PanelVertCenterReg1); 2536692f60a7Smrg VGAwGR(0x29, restore->PanelVertCenterReg2); 2537692f60a7Smrg VGAwGR(0x2a, restore->PanelVertCenterReg3); 2538692f60a7Smrg 2539692f60a7Smrg if (nPtr->NeoChipset != NM2070) { 2540692f60a7Smrg VGAwGR(0x32, restore->PanelVertCenterReg4); 2541692f60a7Smrg VGAwGR(0x33, restore->PanelHorizCenterReg1); 2542692f60a7Smrg VGAwGR(0x34, restore->PanelHorizCenterReg2); 2543692f60a7Smrg VGAwGR(0x35, restore->PanelHorizCenterReg3); 2544692f60a7Smrg } 2545692f60a7Smrg 2546692f60a7Smrg if (nPtr->NeoChipset == NM2160) { 2547692f60a7Smrg VGAwGR(0x36, restore->PanelHorizCenterReg4); 2548692f60a7Smrg } 2549692f60a7Smrg 2550692f60a7Smrg if (nPtr->NeoChipset == NM2200 || nPtr->NeoChipset == NM2230 2551692f60a7Smrg || nPtr->NeoChipset == NM2360 || nPtr->NeoChipset == NM2380) { 2552692f60a7Smrg VGAwGR(0x36, restore->PanelHorizCenterReg4); 2553692f60a7Smrg VGAwGR(0x37, restore->PanelVertCenterReg5); 2554692f60a7Smrg VGAwGR(0x38, restore->PanelHorizCenterReg5); 2555692f60a7Smrg } 2556692f60a7Smrg if (nPtr->NeoChipset == NM2200 || nPtr->NeoChipset == NM2230 2557692f60a7Smrg || nPtr->NeoChipset == NM2360 || nPtr->NeoChipset == NM2380) 2558692f60a7Smrg clock_hi = TRUE; 2559692f60a7Smrg 2560692f60a7Smrg /* Program VCLK3 if needed. */ 2561692f60a7Smrg if (restore->ProgramVCLK 2562692f60a7Smrg && ((VGArGR(0x9B) != restore->VCLK3NumeratorLow) 2563692f60a7Smrg || (VGArGR(0x9F) != restore->VCLK3Denominator) 2564692f60a7Smrg || (clock_hi && ((VGArGR(0x8F) & ~0x0f) 2565692f60a7Smrg != (restore->VCLK3NumeratorHigh & ~0x0F))))) { 2566692f60a7Smrg VGAwGR(0x9B, restore->VCLK3NumeratorLow); 2567692f60a7Smrg if (clock_hi) { 2568692f60a7Smrg temp = VGArGR(0x8F); 2569692f60a7Smrg temp &= 0x0F; /* Save bits 3:0 */ 2570692f60a7Smrg temp |= (restore->VCLK3NumeratorHigh & ~0x0F); 2571692f60a7Smrg VGAwGR(0x8F, temp); 2572692f60a7Smrg } 2573692f60a7Smrg VGAwGR(0x9F, restore->VCLK3Denominator); 2574692f60a7Smrg } 2575692f60a7Smrg if (restore->biosMode) 2576692f60a7Smrg VGAwCR(0x23,restore->biosMode); 2577692f60a7Smrg 2578692f60a7Smrg if (restore->reg) { 2579692f60a7Smrg VGAwCR(0x23,restore->reg->CR[0x23]); 2580692f60a7Smrg VGAwCR(0x25,restore->reg->CR[0x25]); 2581692f60a7Smrg VGAwCR(0x2F,restore->reg->CR[0x2F]); 2582692f60a7Smrg for (i = 0x40; i <= 0x59; i++) { 2583692f60a7Smrg VGAwCR(i, restore->reg->CR[i]); 2584692f60a7Smrg } 2585692f60a7Smrg for (i = 0x60; i <= 0x69; i++) { 2586692f60a7Smrg VGAwCR(i, restore->reg->CR[i]); 2587692f60a7Smrg } 2588692f60a7Smrg for (i = 0x70; i <= NEO_EXT_CR_MAX; i++) { 2589692f60a7Smrg VGAwCR(i, restore->reg->CR[i]); 2590692f60a7Smrg } 2591692f60a7Smrg 2592692f60a7Smrg for (i = 0x0a; i <= 0x3f; i++) { 2593692f60a7Smrg VGAwGR(i, restore->reg->GR[i]); 2594692f60a7Smrg } 2595692f60a7Smrg for (i = 0x90; i <= NEO_EXT_GR_MAX; i++) { 2596692f60a7Smrg VGAwGR(i, restore->reg->GR[i]); 2597692f60a7Smrg } 2598692f60a7Smrg } 2599692f60a7Smrg 2600692f60a7Smrg VGAwGR (0x93, 0xc0); /* Gives faster framebuffer writes */ 2601692f60a7Smrg 2602692f60a7Smrg /* Program vertical extension register */ 2603692f60a7Smrg if (nPtr->NeoChipset == NM2200 || nPtr->NeoChipset == NM2230 2604692f60a7Smrg || nPtr->NeoChipset == NM2360 || nPtr->NeoChipset == NM2380) { 2605692f60a7Smrg VGAwCR(0x70, restore->VerticalExt); 2606692f60a7Smrg } 2607692f60a7Smrg 2608692f60a7Smrg vgaHWProtect(pScrn, FALSE); /* Turn on screen */ 2609692f60a7Smrg} 2610692f60a7Smrg 2611692f60a7Smrgstatic Bool 2612692f60a7SmrgneoModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 2613692f60a7Smrg{ 2614692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 2615692f60a7Smrg NEOACLPtr nAcl = NEOACLPTR(pScrn); 2616692f60a7Smrg int hoffset, voffset; 2617692f60a7Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 2618692f60a7Smrg NeoRegPtr NeoNew = &nPtr->NeoModeReg; 2619692f60a7Smrg vgaRegPtr NeoStd = &hwp->ModeReg; 2620692f60a7Smrg Bool noLcdStretch = nPtr->noLcdStretch; 2621692f60a7Smrg int clockMul = 1; 2622692f60a7Smrg 2623692f60a7Smrg neoUnlock(pScrn); 2624692f60a7Smrg 2625692f60a7Smrg /* 2626692f60a7Smrg * This will allocate the datastructure and initialize all of the 2627692f60a7Smrg * generic VGA registers. 2628692f60a7Smrg */ 2629692f60a7Smrg 2630692f60a7Smrg if (!vgaHWInit(pScrn, mode)) 2631692f60a7Smrg return(FALSE); 2632692f60a7Smrg 2633692f60a7Smrg /* 2634692f60a7Smrg * Several registers need to be corrected from the default values 2635692f60a7Smrg * assigned by vgaHWinit(). 2636692f60a7Smrg */ 2637692f60a7Smrg pScrn->vtSema = TRUE; 2638692f60a7Smrg 2639692f60a7Smrg /* 2640692f60a7Smrg * The default value assigned by vgaHW.c is 0x41, but this does 2641692f60a7Smrg * not work for NeoMagic. 2642692f60a7Smrg */ 2643692f60a7Smrg NeoStd->Attribute[16] = 0x01; 2644692f60a7Smrg 2645c3c9db83Smrg switch (pScrn->depth) { 2646692f60a7Smrg case 8 : 2647692f60a7Smrg NeoStd->CRTC[0x13] = pScrn->displayWidth >> 3; 2648692f60a7Smrg NeoNew->ExtCRTOffset = pScrn->displayWidth >> 11; 2649692f60a7Smrg NeoNew->ExtColorModeSelect = 0x11; 2650692f60a7Smrg break; 2651692f60a7Smrg case 15 : 2652692f60a7Smrg NeoNew->ExtColorModeSelect = 0x12; 2653692f60a7Smrg NeoStd->CRTC[0x13] = pScrn->displayWidth >> 2; 2654692f60a7Smrg NeoNew->ExtCRTOffset = pScrn->displayWidth >> 10; 2655692f60a7Smrg break; 2656692f60a7Smrg case 16 : 2657692f60a7Smrg NeoNew->ExtColorModeSelect = 0x13; 2658692f60a7Smrg NeoStd->CRTC[0x13] = pScrn->displayWidth >> 2; 2659692f60a7Smrg NeoNew->ExtCRTOffset = pScrn->displayWidth >> 10; 2660692f60a7Smrg break; 2661692f60a7Smrg case 24 : 2662692f60a7Smrg NeoStd->CRTC[0x13] = (pScrn->displayWidth * 3) >> 3; 2663692f60a7Smrg NeoNew->ExtCRTOffset = (pScrn->displayWidth * 3) >> 11; 2664692f60a7Smrg NeoNew->ExtColorModeSelect = 0x14; 2665692f60a7Smrg break; 2666692f60a7Smrg default : 2667692f60a7Smrg break; 2668692f60a7Smrg } 2669692f60a7Smrg 2670692f60a7Smrg NeoNew->ExtCRTDispAddr = 0x10; 2671692f60a7Smrg 2672692f60a7Smrg /* Vertical Extension */ 2673692f60a7Smrg NeoNew->VerticalExt = (((mode->CrtcVTotal -2) & 0x400) >> 10 ) 2674692f60a7Smrg | (((mode->CrtcVDisplay -1) & 0x400) >> 9 ) 2675692f60a7Smrg | (((mode->CrtcVSyncStart) & 0x400) >> 8 ) 2676692f60a7Smrg | (((mode->CrtcVBlankStart - 1) & 0x400) >> 7 ); 2677692f60a7Smrg 2678692f60a7Smrg /* Fast write bursts on unless disabled. */ 2679692f60a7Smrg if (nPtr->onPciBurst) { 2680692f60a7Smrg NeoNew->SysIfaceCntl1 = 0x30; 2681692f60a7Smrg } else { 2682692f60a7Smrg NeoNew->SysIfaceCntl1 = 0x00; 2683692f60a7Smrg } 2684692f60a7Smrg 2685692f60a7Smrg /* If they are used, enable linear addressing and/or enable MMIO. */ 2686692f60a7Smrg NeoNew->SysIfaceCntl2 = 0x00; 2687c3c9db83Smrg NeoNew->SysIfaceCntl2 |= 0x80; 2688692f60a7Smrg if (!nPtr->noMMIO) 2689692f60a7Smrg NeoNew->SysIfaceCntl2 |= 0x40; 2690692f60a7Smrg 2691692f60a7Smrg /* Enable any user specified display devices. */ 2692692f60a7Smrg NeoNew->PanelDispCntlReg1 = 0x00; 2693692f60a7Smrg if (nPtr->internDisp) { 2694692f60a7Smrg NeoNew->PanelDispCntlReg1 |= 0x02; 2695692f60a7Smrg } 2696692f60a7Smrg if (nPtr->externDisp) { 2697692f60a7Smrg NeoNew->PanelDispCntlReg1 |= 0x01; 2698692f60a7Smrg } 2699692f60a7Smrg 2700692f60a7Smrg#if 0 2701692f60a7Smrg /* 2702692f60a7Smrg * This was replaced: if no devices are specified take the 2703692f60a7Smrg * probed settings. If the probed settings are bogus fallback 2704692f60a7Smrg * to internal only. 2705692f60a7Smrg */ 2706692f60a7Smrg /* If the user did not specify any display devices, then... */ 2707692f60a7Smrg if (NeoNew->PanelDispCntlReg1 == 0x00) { 2708692f60a7Smrg /* Default to internal (i.e., LCD) only. */ 2709692f60a7Smrg NeoNew->PanelDispCntlReg1 |= 0x02; 2710692f60a7Smrg } 2711692f60a7Smrg#endif 2712692f60a7Smrg /* If we are using a fixed mode, then tell the chip we are. */ 2713692f60a7Smrg switch (mode->HDisplay) { 2714692f60a7Smrg case 1280: 2715692f60a7Smrg NeoNew->PanelDispCntlReg1 |= 0x60; 2716692f60a7Smrg break; 2717692f60a7Smrg case 1024: 2718692f60a7Smrg NeoNew->PanelDispCntlReg1 |= 0x40; 2719692f60a7Smrg break; 2720692f60a7Smrg case 800: 2721692f60a7Smrg NeoNew->PanelDispCntlReg1 |= 0x20; 2722692f60a7Smrg break; 2723692f60a7Smrg case 640: 2724692f60a7Smrg default: 2725692f60a7Smrg break; 2726692f60a7Smrg } 2727692f60a7Smrg 2728692f60a7Smrg /* Setup shadow register locking. */ 2729692f60a7Smrg switch (NeoNew->PanelDispCntlReg1 & 0x03) { 2730692f60a7Smrg case 0x01 : /* External CRT only mode: */ 2731692f60a7Smrg NeoNew->GeneralLockReg = 0x00; 2732692f60a7Smrg /* We need to program the VCLK for external display only mode. */ 2733692f60a7Smrg NeoNew->ProgramVCLK = TRUE; 2734692f60a7Smrg break; 2735692f60a7Smrg case 0x02 : /* Internal LCD only mode: */ 2736692f60a7Smrg case 0x03 : /* Simultaneous internal/external (LCD/CRT) mode: */ 2737692f60a7Smrg NeoNew->GeneralLockReg = 0x01; 2738692f60a7Smrg /* Don't program the VCLK when using the LCD. */ 2739692f60a7Smrg NeoNew->ProgramVCLK = FALSE; 2740692f60a7Smrg break; 2741692f60a7Smrg } 2742692f60a7Smrg 2743692f60a7Smrg /* 2744692f60a7Smrg * If the screen is to be stretched, turn on stretching for the 2745692f60a7Smrg * various modes. 2746692f60a7Smrg * 2747692f60a7Smrg * OPTION_LCD_STRETCH means stretching should be turned off! 2748692f60a7Smrg */ 2749692f60a7Smrg NeoNew->PanelDispCntlReg2 = 0x00; 2750692f60a7Smrg NeoNew->PanelDispCntlReg3 = 0x00; 2751692f60a7Smrg nAcl->NoCursorMode = FALSE; 2752692f60a7Smrg 2753692f60a7Smrg if ((!noLcdStretch) && 2754692f60a7Smrg (NeoNew->PanelDispCntlReg1 & 0x02)) { 2755692f60a7Smrg if (mode->HDisplay == nPtr->NeoPanelWidth) { 2756692f60a7Smrg /* 2757692f60a7Smrg * Don't disable the flag. It will be needed if another mode 2758692f60a7Smrg * is selected. 2759692f60a7Smrg */ 2760692f60a7Smrg /* 2761692f60a7Smrg * No stretching required when the requested display width 2762692f60a7Smrg * equals the panel width. 2763692f60a7Smrg */ 2764692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Stretching disabled\n"); 2765692f60a7Smrg noLcdStretch = TRUE; 2766692f60a7Smrg } else { 2767692f60a7Smrg 2768692f60a7Smrg switch (mode->HDisplay) { 2769692f60a7Smrg case 320 : /* Needs testing. KEM -- 24 May 98 */ 2770692f60a7Smrg case 400 : /* Needs testing. KEM -- 24 May 98 */ 2771692f60a7Smrg case 640 : 2772692f60a7Smrg case 800 : 2773692f60a7Smrg case 1024 : 2774692f60a7Smrg NeoNew->PanelDispCntlReg2 |= 0xC6; 2775692f60a7Smrg nAcl->NoCursorMode = TRUE; 2776692f60a7Smrg break; 2777692f60a7Smrg default : 2778692f60a7Smrg /* No stretching in these modes. */ 2779692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex,X_INFO, 2780692f60a7Smrg "Stretching disabled not supported in this mode\n"); 2781692f60a7Smrg noLcdStretch = TRUE; 2782692f60a7Smrg break; 2783692f60a7Smrg } 2784692f60a7Smrg } 2785692f60a7Smrg } else if (mode->Flags & V_DBLSCAN) { 2786692f60a7Smrg nAcl->NoCursorMode = TRUE; 2787692f60a7Smrg } 2788692f60a7Smrg 2789692f60a7Smrg /* 2790692f60a7Smrg * If the screen is to be centerd, turn on the centering for the 2791692f60a7Smrg * various modes. 2792692f60a7Smrg */ 2793692f60a7Smrg NeoNew->PanelVertCenterReg1 = 0x00; 2794692f60a7Smrg NeoNew->PanelVertCenterReg2 = 0x00; 2795692f60a7Smrg NeoNew->PanelVertCenterReg3 = 0x00; 2796692f60a7Smrg NeoNew->PanelVertCenterReg4 = 0x00; 2797692f60a7Smrg NeoNew->PanelVertCenterReg5 = 0x00; 2798692f60a7Smrg NeoNew->PanelHorizCenterReg1 = 0x00; 2799692f60a7Smrg NeoNew->PanelHorizCenterReg2 = 0x00; 2800692f60a7Smrg NeoNew->PanelHorizCenterReg3 = 0x00; 2801692f60a7Smrg NeoNew->PanelHorizCenterReg4 = 0x00; 2802692f60a7Smrg NeoNew->PanelHorizCenterReg5 = 0x00; 2803692f60a7Smrg 2804692f60a7Smrg if (nPtr->lcdCenter && 2805692f60a7Smrg (NeoNew->PanelDispCntlReg1 & 0x02)) { 2806692f60a7Smrg Bool doCenter = FALSE; 2807692f60a7Smrg 2808692f60a7Smrg hoffset = 0; 2809692f60a7Smrg voffset = 0; 2810692f60a7Smrg if (mode->HDisplay == nPtr->NeoPanelWidth) { 2811692f60a7Smrg /* 2812692f60a7Smrg * No centering required when the requested display width 2813692f60a7Smrg * equals the panel width. 2814692f60a7Smrg */ 2815692f60a7Smrg } else { 2816692f60a7Smrg NeoNew->PanelDispCntlReg3 |= 0x10; 2817692f60a7Smrg if (noLcdStretch) { 2818692f60a7Smrg /* Calculate the horizontal offsets. */ 2819692f60a7Smrg int HDisplay = mode->HDisplay 2820692f60a7Smrg << ((mode->VDisplay < 480) ? 1 : 0); 2821692f60a7Smrg hoffset = ((nPtr->NeoPanelWidth - HDisplay) >> 4) - 1; 2822692f60a7Smrg if (mode->VDisplay < 480) 2823692f60a7Smrg hoffset >>= 1; 2824692f60a7Smrg doCenter = TRUE; 2825692f60a7Smrg } else { 2826692f60a7Smrg /* Stretched modes cannot be centered. */ 2827692f60a7Smrg hoffset = 0; 2828692f60a7Smrg } 2829692f60a7Smrg } 2830692f60a7Smrg if (mode->VDisplay == nPtr->NeoPanelHeight) { 2831692f60a7Smrg /* 2832692f60a7Smrg * No centering required when the requested display width 2833692f60a7Smrg * equals the panel width. 2834692f60a7Smrg */ 2835692f60a7Smrg } else { 2836692f60a7Smrg NeoNew->PanelDispCntlReg2 |= 0x01; 2837692f60a7Smrg if (noLcdStretch) { 2838692f60a7Smrg /* Calculate the vertical offsets. */ 2839692f60a7Smrg int VDisplay = mode->VDisplay 2840692f60a7Smrg << ((mode->Flags & V_DBLSCAN) ? 1 : 0); 2841692f60a7Smrg voffset = ((nPtr->NeoPanelHeight - VDisplay) >> 1) - 2; 2842692f60a7Smrg doCenter = TRUE; 2843692f60a7Smrg } else { 2844692f60a7Smrg /* Stretched modes cannot be centered. */ 2845692f60a7Smrg voffset = 0; 2846692f60a7Smrg } 2847692f60a7Smrg } 2848692f60a7Smrg 2849692f60a7Smrg if (doCenter) { 2850692f60a7Smrg switch (mode->HDisplay) { 2851692f60a7Smrg case 320 : /* Needs testing. KEM -- 24 May 98 */ 2852692f60a7Smrg NeoNew->PanelHorizCenterReg3 = hoffset; 2853692f60a7Smrg NeoNew->PanelVertCenterReg3 = voffset; 2854692f60a7Smrg break; 2855692f60a7Smrg case 400 : /* Needs testing. KEM -- 24 May 98 */ 2856692f60a7Smrg NeoNew->PanelHorizCenterReg4 = hoffset; 2857692f60a7Smrg NeoNew->PanelVertCenterReg1 = voffset; 2858692f60a7Smrg break; 2859692f60a7Smrg case 640 : 2860692f60a7Smrg NeoNew->PanelHorizCenterReg1 = hoffset; 2861692f60a7Smrg NeoNew->PanelVertCenterReg3 = voffset; 2862692f60a7Smrg break; 2863692f60a7Smrg case 800 : 2864692f60a7Smrg NeoNew->PanelHorizCenterReg2 = hoffset; 2865692f60a7Smrg switch (mode->VDisplay) { 2866692f60a7Smrg case 600: 2867692f60a7Smrg NeoNew->PanelVertCenterReg4 = voffset; 2868692f60a7Smrg break; 2869692f60a7Smrg case 480: 2870692f60a7Smrg /* Not sure if this is correct */ 2871692f60a7Smrg NeoNew->PanelVertCenterReg3 = voffset; 2872692f60a7Smrg break; 2873692f60a7Smrg } 2874692f60a7Smrg break; 2875692f60a7Smrg case 1024 : 2876692f60a7Smrg NeoNew->PanelHorizCenterReg5 = hoffset; 2877692f60a7Smrg NeoNew->PanelVertCenterReg5 = voffset; 2878692f60a7Smrg break; 2879692f60a7Smrg case 1280 : 2880692f60a7Smrg default : 2881692f60a7Smrg /* No centering in these modes. */ 2882692f60a7Smrg break; 2883692f60a7Smrg } 2884692f60a7Smrg } 2885692f60a7Smrg } 2886692f60a7Smrg 2887692f60a7Smrg if (!noLcdStretch && 2888692f60a7Smrg (NeoNew->PanelDispCntlReg1 & 0x02)) { 2889692f60a7Smrg if (mode->HDisplay != nPtr->NeoPanelWidth) 2890692f60a7Smrg nPtr->videoHZoom = (double)nPtr->NeoPanelWidth/mode->HDisplay; 2891692f60a7Smrg if (mode->VDisplay != nPtr->NeoPanelHeight) 2892692f60a7Smrg nPtr->videoVZoom = (double)nPtr->NeoPanelHeight/mode->VDisplay; 2893692f60a7Smrg } else { 2894692f60a7Smrg nPtr->videoHZoom = 1.0; 2895692f60a7Smrg nPtr->videoVZoom = 1.0; 2896692f60a7Smrg } 2897692f60a7Smrg /* Do double scan */ 2898692f60a7Smrg if (mode->VDisplay < 480) { 2899692f60a7Smrg NeoStd->Sequencer[1] |= 0x8; 2900692f60a7Smrg clockMul = 2; 2901692f60a7Smrg } 2902692f60a7Smrg 2903692f60a7Smrg NeoNew->biosMode = neoFindMode(mode->HDisplay,mode->VDisplay,pScrn->depth); 2904692f60a7Smrg 2905692f60a7Smrg /* 2906692f60a7Smrg * New->reg should be empty. Just in 2907692f60a7Smrg * case it isn't, warn us and clear it anyway. 2908692f60a7Smrg */ 2909692f60a7Smrg if (NeoNew->reg) { 2910692f60a7Smrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2911692f60a7Smrg "Non-NULL reg in NeoInit: reg=%p\n", (void *)NeoNew->reg); 29123f6d0e1dSmrg free(NeoNew->reg); 2913692f60a7Smrg NeoNew->reg = NULL; 2914692f60a7Smrg } 2915692f60a7Smrg 2916692f60a7Smrg /* 2917692f60a7Smrg * Calculate the VCLK that most closely matches the requested dot 2918692f60a7Smrg * clock. 2919692f60a7Smrg */ 2920692f60a7Smrg neoCalcVCLK(pScrn, mode->SynthClock*clockMul); 2921692f60a7Smrg 2922692f60a7Smrg /* Since we program the clocks ourselves, always use VCLK3. */ 2923692f60a7Smrg NeoStd->MiscOutReg |= 0x0C; 2924692f60a7Smrg 2925692f60a7Smrg neoRestore(pScrn, NeoStd, NeoNew, FALSE); 2926692f60a7Smrg 2927692f60a7Smrg return(TRUE); 2928692f60a7Smrg} 2929692f60a7Smrg 2930692f60a7Smrg/* 2931692f60a7Smrg * neoCalcVCLK -- 2932692f60a7Smrg * 2933692f60a7Smrg * Determine the closest clock frequency to the one requested. 2934692f60a7Smrg */ 2935692f60a7Smrg#define REF_FREQ 14.31818 2936692f60a7Smrg#define MAX_N 127 2937692f60a7Smrg#define MAX_D 31 2938692f60a7Smrg#define MAX_F 1 2939692f60a7Smrg 2940692f60a7Smrgstatic void 2941692f60a7SmrgneoCalcVCLK(ScrnInfoPtr pScrn, long freq) 2942692f60a7Smrg{ 2943692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 2944692f60a7Smrg 2945692f60a7Smrg int n, d, f; 2946692f60a7Smrg double f_out; 2947692f60a7Smrg double f_diff; 2948692f60a7Smrg int n_best = 0, d_best = 1, f_best = 0; 2949692f60a7Smrg double f_best_diff = 999999.0; 2950692f60a7Smrg double f_target = freq/1000.0; 2951692f60a7Smrg 2952692f60a7Smrg for (f = 0; f <= MAX_F; f++) 2953692f60a7Smrg for (n = 0; n <= MAX_N; n++) 2954692f60a7Smrg for (d = 1; d <= MAX_D; d++) { 2955692f60a7Smrg f_out = (n+1.0)/((d+1.0)*(1<<f))*REF_FREQ; 2956692f60a7Smrg f_diff = abs(f_out-f_target); 2957692f60a7Smrg if (f_diff < f_best_diff) { 2958692f60a7Smrg f_best_diff = f_diff; 2959692f60a7Smrg n_best = n; 2960692f60a7Smrg d_best = d; 2961692f60a7Smrg f_best = f; 2962692f60a7Smrg } 2963692f60a7Smrg } 2964692f60a7Smrg 2965692f60a7Smrg if (nPtr->NeoChipset == NM2200 || nPtr->NeoChipset == NM2230 2966692f60a7Smrg || nPtr->NeoChipset == NM2360 || nPtr->NeoChipset == NM2380) { 2967692f60a7Smrg /* NOT_DONE: We are trying the full range of the 2200 clock. 2968692f60a7Smrg We should be able to try n up to 2047 */ 2969692f60a7Smrg nPtr->NeoModeReg.VCLK3NumeratorLow = n_best; 2970692f60a7Smrg nPtr->NeoModeReg.VCLK3NumeratorHigh = (f_best << 7); 2971692f60a7Smrg } 2972692f60a7Smrg else { 2973692f60a7Smrg nPtr->NeoModeReg.VCLK3NumeratorLow = n_best | (f_best << 7); 2974692f60a7Smrg } 2975692f60a7Smrg nPtr->NeoModeReg.VCLK3Denominator = d_best; 2976692f60a7Smrg#ifdef DEBUG 2977692f60a7Smrg ErrorF("neoVCLK: f:%f NumLow=%i NumHi=%i Den=%i Df=%f\n", 2978692f60a7Smrg f_target, 2979692f60a7Smrg nPtr->NeoModeReg.VCLK3NumeratorLow, 2980692f60a7Smrg nPtr->NeoModeReg.VCLK3NumeratorHigh, 2981692f60a7Smrg nPtr->NeoModeReg.VCLK3Denominator, 2982692f60a7Smrg f_best_diff); 2983692f60a7Smrg#endif 2984692f60a7Smrg} 2985692f60a7Smrg 2986692f60a7Smrg/* 2987692f60a7Smrg * NeoDisplayPowerManagementSet -- 2988692f60a7Smrg * 2989692f60a7Smrg * Sets VESA Display Power Management Signaling (DPMS) Mode. 2990692f60a7Smrg */ 2991692f60a7Smrgstatic void 2992692f60a7SmrgNeoDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, 2993692f60a7Smrg int flags) 2994692f60a7Smrg{ 2995692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 2996692f60a7Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 2997692f60a7Smrg unsigned char SEQ01 = 0; 2998692f60a7Smrg unsigned char LogicPowerMgmt = 0; 2999692f60a7Smrg unsigned char LCD_on = 0; 3000692f60a7Smrg 3001692f60a7Smrg if (!pScrn->vtSema) 3002692f60a7Smrg return; 3003692f60a7Smrg 3004692f60a7Smrg switch (PowerManagementMode) { 3005692f60a7Smrg case DPMSModeOn: 3006692f60a7Smrg /* Screen: On; HSync: On, VSync: On */ 3007692f60a7Smrg SEQ01 = 0x00; 3008692f60a7Smrg LogicPowerMgmt = 0x00; 3009692f60a7Smrg if (nPtr->internDisp || ! nPtr->externDisp) 3010692f60a7Smrg LCD_on = 0x02; 3011692f60a7Smrg else 3012692f60a7Smrg LCD_on = 0x00; 3013692f60a7Smrg break; 3014692f60a7Smrg case DPMSModeStandby: 3015692f60a7Smrg /* Screen: Off; HSync: Off, VSync: On */ 3016692f60a7Smrg SEQ01 = 0x20; 3017692f60a7Smrg LogicPowerMgmt = 0x10; 3018692f60a7Smrg LCD_on = 0x00; 3019692f60a7Smrg break; 3020692f60a7Smrg case DPMSModeSuspend: 3021692f60a7Smrg /* Screen: Off; HSync: On, VSync: Off */ 3022692f60a7Smrg SEQ01 = 0x20; 3023692f60a7Smrg LogicPowerMgmt = 0x20; 3024692f60a7Smrg LCD_on = 0x00; 3025692f60a7Smrg break; 3026692f60a7Smrg case DPMSModeOff: 3027692f60a7Smrg /* Screen: Off; HSync: Off, VSync: Off */ 3028692f60a7Smrg SEQ01 = 0x20; 3029692f60a7Smrg LogicPowerMgmt = 0x30; 3030692f60a7Smrg LCD_on = 0x00; 3031692f60a7Smrg break; 3032692f60a7Smrg } 3033692f60a7Smrg 3034692f60a7Smrg /* Turn the screen on/off */ 3035692f60a7Smrg SEQ01 |= VGArSR(0x01) & ~0x20; 3036692f60a7Smrg VGAwSR(0x01, SEQ01); 3037692f60a7Smrg 3038692f60a7Smrg /* Turn the LCD on/off */ 3039692f60a7Smrg LCD_on |= VGArGR(0x20) & ~0x02; 3040692f60a7Smrg VGAwGR(0x20, LCD_on); 3041692f60a7Smrg 3042692f60a7Smrg /* Set the DPMS mode */ 3043692f60a7Smrg LogicPowerMgmt |= 0x80; 3044692f60a7Smrg LogicPowerMgmt |= VGArGR(0x01) & ~0xF0; 3045692f60a7Smrg VGAwGR(0x01,LogicPowerMgmt); 3046692f60a7Smrg} 3047692f60a7Smrg 3048692f60a7Smrgstatic unsigned int 3049692f60a7Smrgneo_ddc1Read(ScrnInfoPtr pScrn) 3050692f60a7Smrg{ 3051692f60a7Smrg register vgaHWPtr hwp = VGAHWPTR(pScrn); 3052692f60a7Smrg register unsigned int tmp; 3053692f60a7Smrg 3054692f60a7Smrg /* This needs to be investigated: we may have to swap this around */ 3055692f60a7Smrg while (!(hwp->readST01(hwp)&0x8)) {}; 3056692f60a7Smrg while (hwp->readST01(hwp)&0x8) {}; 3057692f60a7Smrg 3058692f60a7Smrg tmp = (VGArGR(0xA1) & 0x08); 3059692f60a7Smrg 3060692f60a7Smrg return (tmp); 3061692f60a7Smrg} 3062692f60a7Smrg 306395903e71Smrgstatic void 306495903e71Smrgneo_ddc1SetSpeed(ScrnInfoPtr pScrn, xf86ddcSpeed speed) 306595903e71Smrg{ 306695903e71Smrg vgaHWddc1SetSpeed(pScrn, speed); 306795903e71Smrg} 306895903e71Smrg 3069692f60a7Smrgstatic xf86MonPtr 30703f6d0e1dSmrgneo_ddc1(ScrnInfoPtr pScrn) 3071692f60a7Smrg{ 30723f6d0e1dSmrg vgaHWPtr hwp = VGAHWPTR(pScrn); 3073692f60a7Smrg unsigned int reg1, reg2, reg3; 3074692f60a7Smrg xf86MonPtr ret; 3075692f60a7Smrg 3076692f60a7Smrg /* initialize chipset */ 3077692f60a7Smrg reg1 = VGArCR(0x21); 3078692f60a7Smrg reg2 = VGArCR(0x1D); 3079692f60a7Smrg reg3 = VGArCR(0xA1); 3080692f60a7Smrg VGAwCR(0x21,0x00); 3081692f60a7Smrg VGAwCR(0x1D,0x01); /* some Voodoo */ 3082692f60a7Smrg VGAwGR(0xA1,0x2F); 308395903e71Smrg ret = xf86DoEDID_DDC1(XF86_SCRN_ARG(pScrn),neo_ddc1SetSpeed,neo_ddc1Read); 3084692f60a7Smrg /* undo initialization */ 3085692f60a7Smrg VGAwCR(0x21,reg1); 3086692f60a7Smrg VGAwCR(0x1D,reg2); 3087692f60a7Smrg VGAwGR(0xA1,reg3); 3088692f60a7Smrg return ret; 3089692f60a7Smrg} 3090692f60a7Smrg 3091692f60a7Smrgstatic Bool 3092692f60a7SmrgneoDoDDC1(ScrnInfoPtr pScrn) 3093692f60a7Smrg{ 3094692f60a7Smrg Bool ret = FALSE; 3095692f60a7Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 3096692f60a7Smrg 3097692f60a7Smrg VGAwGR(0x09,0x26); 3098692f60a7Smrg ret = xf86SetDDCproperties(pScrn, 30993f6d0e1dSmrg xf86PrintEDID(neo_ddc1(pScrn))); 3100692f60a7Smrg VGAwGR(0x09,0x00); 3101692f60a7Smrg 3102692f60a7Smrg return ret; 3103692f60a7Smrg} 3104692f60a7Smrg 3105692f60a7Smrgstatic Bool 3106692f60a7SmrgneoDoDDC2(ScrnInfoPtr pScrn) 3107692f60a7Smrg{ 3108692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 3109692f60a7Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 3110692f60a7Smrg Bool ret = FALSE; 3111692f60a7Smrg 3112692f60a7Smrg VGAwGR(0x09,0x26); 3113692f60a7Smrg if (xf86LoadSubModule(pScrn, "i2c")) { 3114692f60a7Smrg if (neo_I2CInit(pScrn)) { 3115692f60a7Smrg ret = xf86SetDDCproperties(pScrn,xf86PrintEDID(xf86DoEDID_DDC2( 31163f6d0e1dSmrg XF86_SCRN_ARG(pScrn),nPtr->I2C))); 3117692f60a7Smrg } 3118692f60a7Smrg } 3119692f60a7Smrg VGAwGR(0x09,0x00); 3120692f60a7Smrg 3121692f60a7Smrg return ret; 3122692f60a7Smrg} 3123692f60a7Smrg 3124692f60a7Smrgstatic Bool 3125692f60a7SmrgneoDoDDCVBE(ScrnInfoPtr pScrn) 3126692f60a7Smrg{ 3127692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 3128692f60a7Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 3129692f60a7Smrg vbeInfoPtr pVbe; 3130692f60a7Smrg Bool ret = FALSE; 3131692f60a7Smrg 3132692f60a7Smrg VGAwGR(0x09,0x26); 3133692f60a7Smrg if (xf86LoadSubModule(pScrn, "vbe")) { 3134692f60a7Smrg if ((pVbe = VBEInit(NULL,nPtr->pEnt->index))) { 3135692f60a7Smrg ret = xf86SetDDCproperties( 3136692f60a7Smrg pScrn,xf86PrintEDID(vbeDoEDID(pVbe,NULL))); 3137692f60a7Smrg vbeFree(pVbe); 3138692f60a7Smrg } 3139692f60a7Smrg } 3140692f60a7Smrg VGAwGR(0x09,0x00); 3141692f60a7Smrg return ret; 3142692f60a7Smrg} 3143692f60a7Smrg 3144692f60a7Smrgstatic int 3145692f60a7SmrgneoFindMode(int xres, int yres, int depth) 3146692f60a7Smrg{ 3147692f60a7Smrg int xres_s; 3148692f60a7Smrg int i, size; 3149692f60a7Smrg biosMode *mode; 3150692f60a7Smrg 3151692f60a7Smrg switch (depth) { 3152692f60a7Smrg case 8: 3153692f60a7Smrg size = sizeof(bios8) / sizeof(biosMode); 3154692f60a7Smrg mode = bios8; 3155692f60a7Smrg break; 3156692f60a7Smrg case 15: 3157692f60a7Smrg size = sizeof(bios15) / sizeof(biosMode); 3158692f60a7Smrg mode = bios15; 3159692f60a7Smrg break; 3160692f60a7Smrg case 16: 3161692f60a7Smrg size = sizeof(bios16) / sizeof(biosMode); 3162692f60a7Smrg mode = bios16; 3163692f60a7Smrg break; 3164692f60a7Smrg case 24: 3165692f60a7Smrg size = sizeof(bios24) / sizeof(biosMode); 3166692f60a7Smrg mode = bios24; 3167692f60a7Smrg break; 3168692f60a7Smrg default: 3169692f60a7Smrg return 0; 3170692f60a7Smrg } 3171692f60a7Smrg 3172692f60a7Smrg for (i = 0; i < size; i++) { 3173692f60a7Smrg if (xres <= mode[i].x_res) { 3174692f60a7Smrg xres_s = mode[i].x_res; 3175692f60a7Smrg for (; i < size; i++) { 3176692f60a7Smrg if (mode[i].x_res != xres_s) 3177692f60a7Smrg return mode[i-1].mode; 3178692f60a7Smrg if (yres <= mode[i].y_res) 3179692f60a7Smrg return mode[i].mode; 3180692f60a7Smrg } 3181692f60a7Smrg } 3182692f60a7Smrg } 3183692f60a7Smrg return mode[size - 1].mode; 3184692f60a7Smrg 3185692f60a7Smrg} 3186692f60a7Smrg 3187692f60a7Smrgstatic void 3188692f60a7SmrgneoProbeDDC(ScrnInfoPtr pScrn, int index) 3189692f60a7Smrg{ 3190692f60a7Smrg vbeInfoPtr pVbe; 3191692f60a7Smrg 3192692f60a7Smrg if (xf86LoadSubModule(pScrn, "vbe")) { 3193692f60a7Smrg if ((pVbe = VBEInit(NULL,index))) { 3194692f60a7Smrg ConfiguredMonitor = vbeDoEDID(pVbe, NULL); 3195692f60a7Smrg vbeFree(pVbe); 3196692f60a7Smrg } 3197692f60a7Smrg } 3198692f60a7Smrg} 3199