/* * Copyright 1993 by Jon Block * Modified by Mike Hollick * Modified 1994 by Régis Cridlig * * Major Contributors to XFree86 3.2 * Modified 1995/6 by Nozomi Ytow * Modified 1996 by Egbert Eich * Modified 1996 by David Bateman * Modified 1996 by Xavier Ducoin * * Contributors to XFree86 3.2 * Modified 1995/6 by Ken Raeburn * Modified 1996 by Shigehiro Nomura * Modified 1996 by Marc de Courville * Modified 1996 by Adam Sulmicki * Modified 1996 by Jens Maurer * * Large parts rewritten for XFree86 4.0 * Modified 1998 by David Bateman * Modified 1998 by Egbert Eich * Modified 1998 by Nozomi Ytow * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of the authors not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. The authors makes no representations * about the suitability of this software for any purpose. It is provided * "as is" without express or implied warranty. * * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /* * Copyright 1997 * Digital Equipment Corporation. All rights reserved. * This software is furnished under license and may be used and copied only in * accordance with the following terms and conditions. Subject to these * conditions, you may download, copy, install, use, modify and distribute * this software in source and/or binary form. No title or ownership is * transferred hereby. * 1) Any source code used, modified or distributed must reproduce and retain * this copyright notice and list of conditions as they appear in the * source file. * * 2) No right is granted to use any trade name, trademark, or logo of Digital * Equipment Corporation. Neither the "Digital Equipment Corporation" name * nor any trademark or logo of Digital Equipment Corporation may be used * to endorse or promote products derived from this software without the * prior written permission of Digital Equipment Corporation. * * 3) This software is provided "AS-IS" and any express or implied warranties, * including but not limited to, any implied warranties of merchantability, * fitness for a particular purpose, or non-infringement are disclaimed. In * no event shall DIGITAL be liable for any damages whatsoever, and in * particular, DIGITAL shall not be liable for special, indirect, * consequential, or incidental damages or damages for lost profits, loss * of revenue or loss of use, whether such damages arise in contract, * negligence, tort, under statute, in equity, at law or otherwise, even if * advised of the possibility of such damage. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* All drivers should typically include these */ #include "xf86.h" #include "xf86_OSproc.h" /* Everything using inb/outb, etc needs "compiler.h" */ #include "compiler.h" /* Drivers that need to access the PCI config space directly need this */ #include "xf86Pci.h" #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 /* Standard resources are defined here */ #include "xf86Resources.h" /* Needed by Resources Access Control (RAC) */ #include "xf86RAC.h" #endif /* All drivers using the vgahw module need this */ #include "vgaHW.h" /* All drivers initialising the SW cursor need this */ #include "mipointer.h" /* All drivers using the mi banking wrapper need this */ #ifdef HAVE_ISA #include "mibank.h" #endif /* All drivers using the mi colormap manipulation need this */ #include "micmap.h" #include "fb.h" #include "fboverlay.h" /* Needed for the 1 and 4 bpp framebuffers */ #ifdef HAVE_XF1BPP #include "xf1bpp.h" #endif #ifdef HAVE_XF4BPP #include "xf4bpp.h" #endif /* int10 */ #include "xf86int10.h" #include "vbe.h" /* Needed by the Shadow Framebuffer */ #include "shadowfb.h" /* Needed for replacement LoadPalette function for Gamma Correction */ #include "xf86cmap.h" #include "dixstruct.h" #include "xf86fbman.h" /* Driver specific headers */ #include "ct_driver.h" /* Mandatory functions */ static const OptionInfoRec * CHIPSAvailableOptions(int chipid, int busid); static void CHIPSIdentify(int flags); #ifdef XSERVER_LIBPCIACCESS static Bool CHIPSPciProbe(DriverPtr drv, int entity_num, struct pci_device *dev, intptr_t match_data); #else static Bool CHIPSProbe(DriverPtr drv, int flags); #endif static Bool CHIPSPreInit(ScrnInfoPtr pScrn, int flags); static Bool CHIPSScreenInit(SCREEN_INIT_ARGS_DECL); static Bool CHIPSEnterVT(VT_FUNC_ARGS_DECL); static void CHIPSLeaveVT(VT_FUNC_ARGS_DECL); static Bool CHIPSCloseScreen(CLOSE_SCREEN_ARGS_DECL); static void CHIPSFreeScreen(FREE_SCREEN_ARGS_DECL); static ModeStatus CHIPSValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags); static Bool CHIPSSaveScreen(ScreenPtr pScreen, int mode); /* Internally used functions */ #ifdef HAVE_ISA static int chipsFindIsaDevice(GDevPtr dev); #endif static Bool chipsClockSelect(ScrnInfoPtr pScrn, int no); Bool chipsModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); static void chipsSave(ScrnInfoPtr pScrn, vgaRegPtr VgaSave, CHIPSRegPtr ChipsSave); static void chipsRestore(ScrnInfoPtr pScrn, vgaRegPtr VgaReg, CHIPSRegPtr ChipsReg, Bool restoreFonts); static void chipsLock(ScrnInfoPtr pScrn); static void chipsUnlock(ScrnInfoPtr pScrn); static void chipsClockSave(ScrnInfoPtr pScrn, CHIPSClockPtr Clock); static void chipsClockLoad(ScrnInfoPtr pScrn, CHIPSClockPtr Clock); static Bool chipsClockFind(ScrnInfoPtr pScrn, DisplayModePtr mode, int no, CHIPSClockPtr Clock); static void chipsCalcClock(ScrnInfoPtr pScrn, int Clock, unsigned char *vclk); static int chipsGetHWClock(ScrnInfoPtr pScrn); static Bool chipsPreInit655xx(ScrnInfoPtr pScrn, int flags); static Bool chipsPreInitHiQV(ScrnInfoPtr pScrn, int flags); static Bool chipsPreInitWingine(ScrnInfoPtr pScrn, int flags); static int chipsSetMonitor(ScrnInfoPtr pScrn); static Bool chipsMapMem(ScrnInfoPtr pScrn); static Bool chipsUnmapMem(ScrnInfoPtr pScrn); static void chipsProtect(ScrnInfoPtr pScrn, Bool on); static void chipsBlankScreen(ScrnInfoPtr pScrn, Bool unblank); static void chipsRestoreExtendedRegs(ScrnInfoPtr pScrn, CHIPSRegPtr Regs); static void chipsRestoreStretching(ScrnInfoPtr pScrn, unsigned char ctHorizontalStretch, unsigned char ctVerticalStretch); static Bool chipsModeInitHiQV(ScrnInfoPtr pScrn, DisplayModePtr mode); static Bool chipsModeInitWingine(ScrnInfoPtr pScrn, DisplayModePtr mode); static Bool chipsModeInit655xx(ScrnInfoPtr pScrn, DisplayModePtr mode); static int chipsVideoMode(int vgaBitsPerPixel,int displayHSize, int displayVSize); static void chipsDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags); static void chipsHWCursorOn(CHIPSPtr cPtr, ScrnInfoPtr pScrn); static void chipsHWCursorOff(CHIPSPtr cPtr, ScrnInfoPtr pScrn); static void chipsFixResume(ScrnInfoPtr pScrn); static void chipsLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual); static void chipsLoadPalette16(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual); static void chipsSetPanelType(CHIPSPtr cPtr); static void chipsBlockHandler(BLOCKHANDLER_ARGS_DECL); /* * This is intentionally screen-independent. It indicates the binding * choice made in the first PreInit. */ static int pix24bpp = 0; /* * Index of Entity */ static int CHIPSEntityIndex = -1; /* Set the non-documented SAR04 register for overlay/video */ #define SAR04 /* * Initialise some arrays that are used in multiple instances of the * acceleration code. Set them up here as its a convenient place to do it. */ /* alu to C&T conversion for use with source data */ int ChipsAluConv[] = { 0x00, /* dest = 0; GXclear, 0 */ 0x88, /* dest &= src; GXand, 0x1 */ 0x44, /* dest = src & ~dest; GXandReverse, 0x2 */ 0xCC, /* dest = src; GXcopy, 0x3 */ 0x22, /* dest &= ~src; GXandInverted, 0x4 */ 0xAA, /* dest = dest; GXnoop, 0x5 */ 0x66, /* dest = ^src; GXxor, 0x6 */ 0xEE, /* dest |= src; GXor, 0x7 */ 0x11, /* dest = ~src & ~dest;GXnor, 0x8 */ 0x99, /* dest ^= ~src ;GXequiv, 0x9 */ 0x55, /* dest = ~dest; GXInvert, 0xA */ 0xDD, /* dest = src|~dest ;GXorReverse, 0xB */ 0x33, /* dest = ~src; GXcopyInverted, 0xC */ 0xBB, /* dest |= ~src; GXorInverted, 0xD */ 0x77, /* dest = ~src|~dest ;GXnand, 0xE */ 0xFF, /* dest = 0xFF; GXset, 0xF */ }; /* alu to C&T conversion for use with pattern data */ int ChipsAluConv2[] = { 0x00, /* dest = 0; GXclear, 0 */ 0xA0, /* dest &= src; GXand, 0x1 */ 0x50, /* dest = src & ~dest; GXandReverse, 0x2 */ 0xF0, /* dest = src; GXcopy, 0x3 */ 0x0A, /* dest &= ~src; GXandInverted, 0x4 */ 0xAA, /* dest = dest; GXnoop, 0x5 */ 0x5A, /* dest = ^src; GXxor, 0x6 */ 0xFA, /* dest |= src; GXor, 0x7 */ 0x05, /* dest = ~src & ~dest;GXnor, 0x8 */ 0xA5, /* dest ^= ~src ;GXequiv, 0x9 */ 0x55, /* dest = ~dest; GXInvert, 0xA */ 0xF5, /* dest = src|~dest ;GXorReverse, 0xB */ 0x0F, /* dest = ~src; GXcopyInverted, 0xC */ 0xAF, /* dest |= ~src; GXorInverted, 0xD */ 0x5F, /* dest = ~src|~dest ;GXnand, 0xE */ 0xFF, /* dest = 0xFF; GXset, 0xF */ }; /* alu to C&T conversion for use with pattern data as a planemask */ int ChipsAluConv3[] = { 0x0A, /* dest = 0; GXclear, 0 */ 0x8A, /* dest &= src; GXand, 0x1 */ 0x4A, /* dest = src & ~dest; GXandReverse, 0x2 */ 0xCA, /* dest = src; GXcopy, 0x3 */ 0x2A, /* dest &= ~src; GXandInverted, 0x4 */ 0xAA, /* dest = dest; GXnoop, 0x5 */ 0x6A, /* dest = ^src; GXxor, 0x6 */ 0xEA, /* dest |= src; GXor, 0x7 */ 0x1A, /* dest = ~src & ~dest;GXnor, 0x8 */ 0x9A, /* dest ^= ~src ;GXequiv, 0x9 */ 0x5A, /* dest = ~dest; GXInvert, 0xA */ 0xDA, /* dest = src|~dest ;GXorReverse, 0xB */ 0x3A, /* dest = ~src; GXcopyInverted, 0xC */ 0xBA, /* dest |= ~src; GXorInverted, 0xD */ 0x7A, /* dest = ~src|~dest ;GXnand, 0xE */ 0xFA, /* dest = 0xFF; GXset, 0xF */ }; /* The addresses of the acceleration registers */ unsigned int ChipsReg32HiQV[] = { 0x00, /* BR00 Source and Destination offset register */ 0x04, /* BR01 Color expansion background color */ 0x08, /* BR02 Color expansion foreground color */ 0x0C, /* BR03 Monochrome source control register */ 0x10, /* BR04 BitBLT control register */ 0x14, /* BR05 Pattern address register */ 0x18, /* BR06 Source address register */ 0x1C, /* BR07 Destination address register */ 0x20 /* BR08 Destination width and height register */ }; unsigned int ChipsReg32[] = { /*BitBLT */ 0x83D0, /*DR0 src/dest offset */ 0x87D0, /*DR1 BitBlt. address of freeVram? */ 0x8BD0, /*DR2 BitBlt. paintBrush, or tile pat.*/ 0x8FD0, /*DR3 */ 0x93D0, /*DR4 BitBlt. */ 0x97D0, /*DR5 BitBlt. srcAddr, or 0 in VRAM */ 0x9BD0, /*DR6 BitBlt. dest? */ 0x9FD0, /*DR7 BitBlt. width << 16 | height */ /*H/W cursor */ 0xA3D0, /*DR8 write/erase cursor */ /*bit 0-1 if 0 cursor is not shown * if 1 32x32 cursor * if 2 64x64 cursor * if 3 128x128 cursor */ /* bit 7 if 1 cursor is not shown */ /* bit 9 cursor expansion in X */ /* bit 10 cursor expansion in Y */ 0xA7D0, /* DR9 foreGroundCursorColor */ 0xABD0, /* DR0xA backGroundCursorColor */ 0xAFD0, /* DR0xB cursorPosition */ /* bit 0-7 x coordinate */ /* bit 8-14 0 */ /* bit 15 x signum */ /* bit 16-23 y coordinate */ /* bit 24-30 0 */ /* bit 31 y signum */ 0xB3D0, /* DR0xC address of cursor pattern */ }; #if defined(__arm32__) && defined(__NetBSD__) /* * Built in TV output modes: These modes have been tested on NetBSD with * CT65550 and StrongARM. They give what seems to be the best output for * a roughly 640x480 display. To enable one of the built in modes, add * the identifier "NTSC" or "PAL" to the list of modes in the appropriate * "Display" subsection of the "Screen" section in the XF86Config file. * Note that the call to xf86SetTVOut(), which tells the kernel to enable * TV output results in hardware specific actions. There must be code to * support this in the kernel or TV output won't work. */ static DisplayModeRec ChipsPALMode = { NULL, NULL, /* prev, next */ "PAL", /* identifier of this mode */ MODE_OK, /* mode status */ M_T_BUILTIN, /* mode type */ 15000, /* Clock frequency */ 776, /* HDisplay */ 800, /* HSyncStart */ 872, /* HSyncEnd */ 960, /* HTotal */ 0, /* HSkew */ 585, /* VDisplay */ 590, /* VSyncStart */ 595, /* VSyncEnd */ 625, /* VTotal */ 0, /* VScan */ V_INTERLACE, /* Flags */ -1, /* ClockIndex */ 15000, /* SynthClock */ 776, /* CRTC HDisplay */ 800, /* CRTC HBlankStart */ 800, /* CRTC HSyncStart */ 872, /* CRTC HSyncEnd */ 872, /* CRTC HBlankEnd */ 960, /* CRTC HTotal */ 0, /* CRTC HSkew */ 585, /* CRTC VDisplay */ 590, /* CRTC VBlankStart */ 590, /* CRTC VSyncStart */ 595, /* CRTC VSyncEnd */ 595, /* CRTC VBlankEnd */ 625, /* CRTC VTotal */ FALSE, /* CrtcHAdjusted */ FALSE, /* CrtcVAdjusted */ 0, /* PrivSize */ NULL, /* Private */ 0.0, /* HSync */ 0.0 /* VRefresh */ }; /* ** So far, it looks like SECAM uses the same values as PAL */ static DisplayModeRec ChipsSECAMMode = { NULL, /* prev */ &ChipsPALMode, /* next */ "SECAM", /* identifier of this mode */ MODE_OK, /* mode status */ M_T_BUILTIN, /* mode type */ 15000, /* Clock frequency */ 776, /* HDisplay */ 800, /* HSyncStart */ 872, /* HSyncEnd */ 960, /* HTotal */ 0, /* HSkew */ 585, /* VDisplay */ 590, /* VSyncStart */ 595, /* VSyncEnd */ 625, /* VTotal */ 0, /* VScan */ V_INTERLACE, /* Flags */ -1, /* ClockIndex */ 15000, /* SynthClock */ 776, /* CRTC HDisplay */ 800, /* CRTC HBlankStart */ 800, /* CRTC HSyncStart */ 872, /* CRTC HSyncEnd */ 872, /* CRTC HBlankEnd */ 960, /* CRTC HTotal */ 0, /* CRTC HSkew */ 585, /* CRTC VDisplay */ 590, /* CRTC VBlankStart */ 590, /* CRTC VSyncStart */ 595, /* CRTC VSyncEnd */ 595, /* CRTC VBlankEnd */ 625, /* CRTC VTotal */ FALSE, /* CrtcHAdjusted */ FALSE, /* CrtcVAdjusted */ 0, /* PrivSize */ NULL, /* Private */ 0.0, /* HSync */ 0.0 /* VRefresh */ }; static DisplayModeRec ChipsNTSCMode = { NULL, /* prev */ &ChipsSECAMMode,/* next */ "NTSC", /* identifier of this mode */ MODE_OK, /* mode status */ M_T_BUILTIN, /* mode type */ 11970, /* Clock frequency */ 584, /* HDisplay */ 640, /* HSyncStart */ 696, /* HSyncEnd */ 760, /* HTotal */ 0, /* HSkew */ 450, /* VDisplay */ 479, /* VSyncStart */ 485, /* VSyncEnd */ 525, /* VTotal */ 0, /* VScan */ V_INTERLACE | V_NVSYNC | V_NHSYNC , /* Flags */ -1, /* ClockIndex */ 11970, /* SynthClock */ 584, /* CRTC HDisplay */ 640, /* CRTC HBlankStart */ 640, /* CRTC HSyncStart */ 696, /* CRTC HSyncEnd */ 696, /* CRTC HBlankEnd */ 760, /* CRTC HTotal */ 0, /* CRTC HSkew */ 450, /* CRTC VDisplay */ 479, /* CRTC VBlankStart */ 479, /* CRTC VSyncStart */ 485, /* CRTC VSyncEnd */ 485, /* CRTC VBlankEnd */ 525, /* CRTC VTotal */ FALSE, /* CrtcHAdjusted */ FALSE, /* CrtcVAdjusted */ 0, /* PrivSize */ NULL, /* Private */ 0.0, /* HSync */ 0.0 /* VRefresh */ }; #endif #define CHIPS_VERSION 4000 #define CHIPS_NAME "CHIPS" #define CHIPS_DRIVER_NAME "chips" #define CHIPS_MAJOR_VERSION PACKAGE_VERSION_MAJOR #define CHIPS_MINOR_VERSION PACKAGE_VERSION_MINOR #define CHIPS_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL #ifdef XSERVER_LIBPCIACCESS #ifndef _XF86_PCIINFO_H #define PCI_VENDOR_CHIPSTECH 0x102C /* Chips & Tech */ #define PCI_CHIP_65545 0x00D8 #define PCI_CHIP_65548 0x00DC #define PCI_CHIP_65550 0x00E0 #define PCI_CHIP_65554 0x00E4 #define PCI_CHIP_65555 0x00E5 #define PCI_CHIP_68554 0x00F4 #define PCI_CHIP_69000 0x00C0 #define PCI_CHIP_69030 0x0C30 #endif #define CHIPS_DEVICE_MATCH(d, i) \ { PCI_VENDOR_CHIPSTECH, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) } static const struct pci_id_match chips_device_match[] = { CHIPS_DEVICE_MATCH(PCI_CHIP_65545, CHIPS_CT65545), CHIPS_DEVICE_MATCH(PCI_CHIP_65548, CHIPS_CT65548), CHIPS_DEVICE_MATCH(PCI_CHIP_65550, CHIPS_CT65550), CHIPS_DEVICE_MATCH(PCI_CHIP_65554, CHIPS_CT65554), CHIPS_DEVICE_MATCH(PCI_CHIP_65555, CHIPS_CT65555), CHIPS_DEVICE_MATCH(PCI_CHIP_68554, CHIPS_CT68554), CHIPS_DEVICE_MATCH(PCI_CHIP_69000, CHIPS_CT69000), CHIPS_DEVICE_MATCH(PCI_CHIP_69030, CHIPS_CT69030), { 0, 0, 0 }, }; #endif /* * This contains the functions needed by the server after loading the driver * module. It must be supplied, and gets passed back by the SetupProc * function in the dynamic case. In the static case, a reference to this * is compiled in, and this requires that the name of this DriverRec be * an upper-case version of the driver name. */ _X_EXPORT DriverRec CHIPS = { CHIPS_VERSION, CHIPS_DRIVER_NAME, CHIPSIdentify, #ifdef XSERVER_LIBPCIACCESS NULL, #else CHIPSProbe, #endif CHIPSAvailableOptions, NULL, 0, NULL, #ifdef XSERVER_LIBPCIACCESS chips_device_match, CHIPSPciProbe, #endif }; static SymTabRec CHIPSChipsets[] = { { CHIPS_CT65520, "ct65520" }, { CHIPS_CT65525, "ct65525" }, { CHIPS_CT65530, "ct65530" }, { CHIPS_CT65535, "ct65535" }, { CHIPS_CT65540, "ct65540" }, { CHIPS_CT65545, "ct65545" }, { CHIPS_CT65546, "ct65546" }, { CHIPS_CT65548, "ct65548" }, { CHIPS_CT65550, "ct65550" }, { CHIPS_CT65554, "ct65554" }, { CHIPS_CT65555, "ct65555" }, { CHIPS_CT68554, "ct68554" }, { CHIPS_CT69000, "ct69000" }, { CHIPS_CT69030, "ct69030" }, { CHIPS_CT64200, "ct64200" }, { CHIPS_CT64300, "ct64300" }, { -1, NULL } }; /* Conversion PCI ID to chipset name */ static PciChipsets CHIPSPCIchipsets[] = { { CHIPS_CT65545, PCI_CHIP_65545, RES_SHARED_VGA }, { CHIPS_CT65548, PCI_CHIP_65548, RES_SHARED_VGA }, { CHIPS_CT65550, PCI_CHIP_65550, RES_SHARED_VGA }, { CHIPS_CT65554, PCI_CHIP_65554, RES_SHARED_VGA }, { CHIPS_CT65555, PCI_CHIP_65555, RES_SHARED_VGA }, { CHIPS_CT68554, PCI_CHIP_68554, RES_SHARED_VGA }, { CHIPS_CT69000, PCI_CHIP_69000, RES_SHARED_VGA }, { CHIPS_CT69030, PCI_CHIP_69030, RES_SHARED_VGA }, { -1, -1, RES_UNDEFINED} }; #ifdef HAVE_ISA static IsaChipsets CHIPSISAchipsets[] = { { CHIPS_CT65520, RES_EXCLUSIVE_VGA }, { CHIPS_CT65525, RES_EXCLUSIVE_VGA }, { CHIPS_CT65530, RES_EXCLUSIVE_VGA }, { CHIPS_CT65535, RES_EXCLUSIVE_VGA }, { CHIPS_CT65540, RES_EXCLUSIVE_VGA }, { CHIPS_CT65545, RES_EXCLUSIVE_VGA }, { CHIPS_CT65546, RES_EXCLUSIVE_VGA }, { CHIPS_CT65548, RES_EXCLUSIVE_VGA }, { CHIPS_CT65550, RES_EXCLUSIVE_VGA }, { CHIPS_CT65554, RES_EXCLUSIVE_VGA }, { CHIPS_CT65555, RES_EXCLUSIVE_VGA }, { CHIPS_CT68554, RES_EXCLUSIVE_VGA }, { CHIPS_CT69000, RES_EXCLUSIVE_VGA }, { CHIPS_CT69030, RES_EXCLUSIVE_VGA }, { CHIPS_CT64200, RES_EXCLUSIVE_VGA }, { CHIPS_CT64300, RES_EXCLUSIVE_VGA }, { -1, RES_UNDEFINED } }; #endif /* The options supported by the Chips and Technologies Driver */ typedef enum { OPTION_LINEAR, OPTION_NOACCEL, OPTION_HW_CLKS, OPTION_SW_CURSOR, OPTION_HW_CURSOR, OPTION_STN, OPTION_USE_MODELINE, OPTION_LCD_STRETCH, OPTION_LCD_CENTER, OPTION_MMIO, OPTION_FULL_MMIO, OPTION_SUSPEND_HACK, OPTION_RGB_BITS, OPTION_SYNC_ON_GREEN, OPTION_PANEL_SIZE, OPTION_18_BIT_BUS, OPTION_SHOWCACHE, OPTION_SHADOW_FB, OPTION_OVERLAY, OPTION_COLOR_KEY, OPTION_VIDEO_KEY, OPTION_FP_CLOCK_8, OPTION_FP_CLOCK_16, OPTION_FP_CLOCK_24, OPTION_FP_CLOCK_32, OPTION_SET_MCLK, OPTION_ROTATE, OPTION_NO_TMED, OPTION_CRT2_MEM, OPTION_DUAL_REFRESH, OPTION_CRT_CLK_INDX, OPTION_FP_CLK_INDX, OPTION_FP_MODE } CHIPSOpts; static const OptionInfoRec Chips655xxOptions[] = { { OPTION_LINEAR, "Linear", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_HW_CLKS, "HWclocks", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_STN, "STN", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_USE_MODELINE, "UseModeline", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_LCD_STRETCH, "Stretch", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_LCD_CENTER, "LcdCenter", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_MMIO, "MMIO", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_SUSPEND_HACK, "SuspendHack", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_PANEL_SIZE, "FixPanelSize", OPTV_BOOLEAN, {0}, FALSE }, #if 0 { OPTION_RGB_BITS, "RGBbits", OPTV_INTEGER, {0}, FALSE }, #endif { OPTION_18_BIT_BUS, "18BitBus", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, { OPTION_SET_MCLK, "SetMclk", OPTV_FREQ, {0}, FALSE }, { OPTION_FP_CLOCK_8, "FPClock8", OPTV_FREQ, {0}, FALSE }, { OPTION_FP_CLOCK_16, "FPClock16", OPTV_FREQ, {0}, FALSE }, { OPTION_FP_CLOCK_24, "FPClock24", OPTV_FREQ, {0}, FALSE }, { OPTION_FP_MODE, "FPMode", OPTV_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; static const OptionInfoRec ChipsWingineOptions[] = { { OPTION_LINEAR, "Linear", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_HW_CLKS, "HWclocks", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, #if 0 { OPTION_RGB_BITS, "RGBbits", OPTV_INTEGER, {0}, FALSE }, #endif { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; static const OptionInfoRec ChipsHiQVOptions[] = { { OPTION_LINEAR, "Linear", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_STN, "STN", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_USE_MODELINE, "UseModeline", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_LCD_STRETCH, "Stretch", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_LCD_CENTER, "LcdCenter", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_MMIO, "MMIO", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_FULL_MMIO, "FullMMIO", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_SUSPEND_HACK, "SuspendHack", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_PANEL_SIZE, "FixPanelSize", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_RGB_BITS, "RGBbits", OPTV_INTEGER, {0}, FALSE }, { OPTION_SYNC_ON_GREEN, "SyncOnGreen", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, { OPTION_OVERLAY, "Overlay", OPTV_ANYSTR, {0}, FALSE }, { OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE }, { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, { OPTION_FP_CLOCK_8, "FPClock8", OPTV_FREQ, {0}, FALSE }, { OPTION_FP_CLOCK_16, "FPClock16", OPTV_FREQ, {0}, FALSE }, { OPTION_FP_CLOCK_24, "FPClock24", OPTV_FREQ, {0}, FALSE }, { OPTION_FP_CLOCK_32, "FPClock32", OPTV_FREQ, {0}, FALSE }, { OPTION_SET_MCLK, "SetMclk", OPTV_FREQ, {0}, FALSE }, { OPTION_NO_TMED, "NoTMED", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_CRT2_MEM, "Crt2Memory", OPTV_INTEGER, {0}, FALSE }, { OPTION_DUAL_REFRESH, "DualRefresh", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_CRT_CLK_INDX, "CrtClkIndx", OPTV_INTEGER, {0}, FALSE }, { OPTION_FP_CLK_INDX, "FPClkIndx", OPTV_INTEGER, {0}, FALSE }, { OPTION_FP_MODE, "FPMode", OPTV_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; #ifdef XFree86LOADER static MODULESETUPPROTO(chipsSetup); static XF86ModuleVersionInfo chipsVersRec = { "chips", MODULEVENDORSTRING, MODINFOSTRING1, MODINFOSTRING2, XORG_VERSION_CURRENT, CHIPS_MAJOR_VERSION, CHIPS_MINOR_VERSION, CHIPS_PATCHLEVEL, ABI_CLASS_VIDEODRV, ABI_VIDEODRV_VERSION, MOD_CLASS_VIDEODRV, {0,0,0,0} }; /* * This is the module init data. * Its name has to be the driver name followed by ModuleData */ _X_EXPORT XF86ModuleData chipsModuleData = { &chipsVersRec, chipsSetup, NULL }; static pointer chipsSetup(pointer module, pointer opts, int *errmaj, int *errmin) { static Bool setupDone = FALSE; if (!setupDone) { setupDone = TRUE; xf86AddDriver(&CHIPS, module, HaveDriverFuncs); /* * Modules that this driver always requires can be loaded here * by calling LoadSubModule(). */ /* * The return value must be non-NULL on success even though there * is no TearDownProc. */ return (pointer)1; } else { if (errmaj) *errmaj = LDR_ONCEONLY; return NULL; } } #endif /* XFree86LOADER */ static Bool CHIPSGetRec(ScrnInfoPtr pScrn) { /* * Allocate a CHIPSRec, and hook it into pScrn->driverPrivate. * pScrn->driverPrivate is initialised to NULL, so we can check if * the allocation has already been done. */ if (pScrn->driverPrivate != NULL) return TRUE; pScrn->driverPrivate = xnfcalloc(sizeof(CHIPSRec), 1); if (pScrn->driverPrivate == NULL) return FALSE; return TRUE; } static void CHIPSFreeRec(ScrnInfoPtr pScrn) { if (pScrn->driverPrivate == NULL) return; free(pScrn->driverPrivate); pScrn->driverPrivate = NULL; } /* Mandatory */ static void CHIPSIdentify(int flags) { xf86PrintChipsets(CHIPS_NAME, "Driver for Chips and Technologies chipsets", CHIPSChipsets); } static const OptionInfoRec * CHIPSAvailableOptions(int chipid, int busid) { int chip = chipid & 0x0000ffff; #ifdef HAVE_ISA if (busid == BUS_ISA) { if ((chip == CHIPS_CT64200) || (chip == CHIPS_CT64300)) return ChipsWingineOptions; } #endif if (busid == BUS_PCI) { if ((chip >= CHIPS_CT65550) && (chip <= CHIPS_CT69030)) return ChipsHiQVOptions; } return Chips655xxOptions; } /* Mandatory */ #ifdef XSERVER_LIBPCIACCESS Bool CHIPSPciProbe(DriverPtr drv, int entity_num, struct pci_device * dev, intptr_t match_data) { ScrnInfoPtr pScrn = NULL; CHIPSPtr cPtr; /* Allocate a ScrnInfoRec and claim the slot */ pScrn = xf86ConfigPciEntity(pScrn, 0, entity_num, CHIPSPCIchipsets, NULL, NULL, NULL, NULL, NULL); if (pScrn != NULL) { /* Fill in what we can of the ScrnInfoRec */ pScrn->driverVersion = CHIPS_VERSION; pScrn->driverName = CHIPS_DRIVER_NAME; pScrn->name = CHIPS_NAME; pScrn->Probe = NULL; pScrn->PreInit = CHIPSPreInit; pScrn->ScreenInit = CHIPSScreenInit; pScrn->SwitchMode = CHIPSSwitchMode; pScrn->AdjustFrame = CHIPSAdjustFrame; pScrn->EnterVT = CHIPSEnterVT; pScrn->LeaveVT = CHIPSLeaveVT; pScrn->FreeScreen = CHIPSFreeScreen; pScrn->ValidMode = CHIPSValidMode; if (!CHIPSGetRec(pScrn)) { return FALSE; } cPtr = CHIPSPTR(pScrn); cPtr->Chipset = match_data; /* * For cards that can do dual head per entity, mark the entity * as sharable. */ if (match_data == CHIPS_CT69030) { CHIPSEntPtr cPtrEnt = NULL; DevUnion *pPriv; xf86SetEntitySharable(entity_num); /* Allocate an entity private if necessary */ if (CHIPSEntityIndex < 0) CHIPSEntityIndex = xf86AllocateEntityPrivateIndex(); pPriv = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex); if (!pPriv->ptr) { pPriv->ptr = xnfcalloc(sizeof(CHIPSEntRec), 1); cPtrEnt = pPriv->ptr; cPtrEnt->lastInstance = -1; } else { cPtrEnt = pPriv->ptr; } /* * Set the entity instance for this instance of the driver. For * dual head per card, instance 0 is the "master" instance, driving * the primary head, and instance 1 is the "slave". */ cPtrEnt->lastInstance++; xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0], cPtrEnt->lastInstance); } } return (pScrn != NULL); } #else static Bool CHIPSProbe(DriverPtr drv, int flags) { Bool foundScreen = FALSE; int numDevSections, numUsed; GDevPtr *devSections; int *usedChips; int i; /* * Find the config file Device sections that match this * driver, and return if there are none. */ if ((numDevSections = xf86MatchDevice(CHIPS_DRIVER_NAME, &devSections)) <= 0) { return FALSE; } /* PCI BUS */ if (xf86GetPciVideoInfo() ) { numUsed = xf86MatchPciInstances(CHIPS_NAME, PCI_VENDOR_CHIPSTECH, CHIPSChipsets, CHIPSPCIchipsets, devSections,numDevSections, drv, &usedChips); if (numUsed > 0) { if (flags & PROBE_DETECT) foundScreen = TRUE; else for (i = 0; i < numUsed; i++) { EntityInfoPtr pEnt; /* Allocate a ScrnInfoRec */ ScrnInfoPtr pScrn = NULL; if ((pScrn = xf86ConfigPciEntity(pScrn,0,usedChips[i], CHIPSPCIchipsets,NULL, NULL,NULL,NULL,NULL))){ pScrn->driverVersion = CHIPS_VERSION; pScrn->driverName = CHIPS_DRIVER_NAME; pScrn->name = CHIPS_NAME; pScrn->Probe = CHIPSProbe; pScrn->PreInit = CHIPSPreInit; pScrn->ScreenInit = CHIPSScreenInit; pScrn->SwitchMode = CHIPSSwitchMode; pScrn->AdjustFrame = CHIPSAdjustFrame; pScrn->EnterVT = CHIPSEnterVT; pScrn->LeaveVT = CHIPSLeaveVT; pScrn->FreeScreen = CHIPSFreeScreen; pScrn->ValidMode = CHIPSValidMode; foundScreen = TRUE; } /* * For cards that can do dual head per entity, mark the entity * as sharable. */ pEnt = xf86GetEntityInfo(usedChips[i]); if (pEnt->chipset == CHIPS_CT69030) { CHIPSEntPtr cPtrEnt = NULL; DevUnion *pPriv; xf86SetEntitySharable(usedChips[i]); /* Allocate an entity private if necessary */ if (CHIPSEntityIndex < 0) CHIPSEntityIndex = xf86AllocateEntityPrivateIndex(); pPriv = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex); if (!pPriv->ptr) { pPriv->ptr = xnfcalloc(sizeof(CHIPSEntRec), 1); cPtrEnt = pPriv->ptr; cPtrEnt->lastInstance = -1; } else { cPtrEnt = pPriv->ptr; } /* * Set the entity instance for this instance of the * driver. For dual head per card, instance 0 is the * "master" instance, driving the primary head, and * instance 1 is the "slave". */ cPtrEnt->lastInstance++; xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0], cPtrEnt->lastInstance); } } free(usedChips); } } #ifdef HAVE_ISA /* Isa Bus */ numUsed = xf86MatchIsaInstances(CHIPS_NAME,CHIPSChipsets,CHIPSISAchipsets, drv,chipsFindIsaDevice,devSections, numDevSections,&usedChips); if (numUsed > 0) { if (flags & PROBE_DETECT) foundScreen = TRUE; else for (i = 0; i < numUsed; i++) { ScrnInfoPtr pScrn = NULL; if ((pScrn = xf86ConfigIsaEntity(pScrn,0, usedChips[i], CHIPSISAchipsets,NULL, NULL,NULL,NULL,NULL))) { pScrn->driverVersion = CHIPS_VERSION; pScrn->driverName = CHIPS_DRIVER_NAME; pScrn->name = CHIPS_NAME; pScrn->Probe = CHIPSProbe; pScrn->PreInit = CHIPSPreInit; pScrn->ScreenInit = CHIPSScreenInit; pScrn->SwitchMode = CHIPSSwitchMode; pScrn->AdjustFrame = CHIPSAdjustFrame; pScrn->EnterVT = CHIPSEnterVT; pScrn->LeaveVT = CHIPSLeaveVT; pScrn->FreeScreen = CHIPSFreeScreen; pScrn->ValidMode = CHIPSValidMode; foundScreen = TRUE; } free(usedChips); } } #endif free(devSections); return foundScreen; } #endif #ifdef HAVE_ISA static int chipsFindIsaDevice(GDevPtr dev) { int found = -1; unsigned char tmp; /* * This function has the only direct register access in the C&T driver. * All other register access through functions to allow for full MMIO. */ outb(0x3D6, 0x00); tmp = inb(0x3D7); switch (tmp & 0xF0) { case 0x70: /* CT65520 */ found = CHIPS_CT65520; break; case 0x80: /* CT65525 or CT65530 */ found = CHIPS_CT65530; break; case 0xA0: /* CT64200 */ found = CHIPS_CT64200; break; case 0xB0: /* CT64300 */ found = CHIPS_CT64300; break; case 0xC0: /* CT65535 */ found = CHIPS_CT65535; break; default: switch (tmp & 0xF8) { case 0xD0: /* CT65540 */ found = CHIPS_CT65540; break; case 0xD8: /* CT65545 or CT65546 or CT65548 */ switch (tmp & 7) { case 3: found = CHIPS_CT65546; break; case 4: found = CHIPS_CT65548; break; default: found = CHIPS_CT65545; break; } break; default: if (tmp == 0x2C) { outb(0x3D6, 0x01); tmp = inb(0x3D7); if (tmp != 0x10) break; outb(0x3D6, 0x02); tmp = inb(0x3D7); switch (tmp) { case 0xE0: /* CT65550 */ found = CHIPS_CT65550; break; case 0xE4: /* CT65554 */ found = CHIPS_CT65554; break; case 0xE5: /* CT65555 */ found = CHIPS_CT65555; break; case 0xF4: /* CT68554 */ found = CHIPS_CT68554; break; case 0xC0: /* CT69000 */ found = CHIPS_CT69000; break; case 0x30: /* CT69030 */ outb(0x3D6, 0x03); tmp = inb(0x3D7); if (tmp == 0xC) found = CHIPS_CT69030; break; default: break; } } break; } break; } /* We only want ISA/VL Bus - so check for PCI Bus */ if(found > CHIPS_CT65548) { outb(0x3D6, 0x08); tmp = inb(0x3D7); if(tmp & 0x01) found = -1; } else if(found > CHIPS_CT65535) { outb(0x3D6, 0x01); tmp = inb(0x3D7); if ((tmp & 0x07) == 0x06) found = -1; } return found; } #endif /* Mandatory */ Bool CHIPSPreInit(ScrnInfoPtr pScrn, int flags) { pciVideoPtr pciPtr; ClockRangePtr clockRanges; int i; CHIPSPtr cPtr; Bool res = FALSE; CHIPSEntPtr cPtrEnt = NULL; if (flags & PROBE_DETECT) return FALSE; /* The vgahw module should be loaded here when needed */ if (!xf86LoadSubModule(pScrn, "vgahw")) return FALSE; /* Allocate the ChipsRec driverPrivate */ if (!CHIPSGetRec(pScrn)) { return FALSE; } cPtr = CHIPSPTR(pScrn); /* XXX Check the number of entities, and fail if it isn't one. */ if (pScrn->numEntities != 1) return FALSE; /* Since the capabilities are determined by the chipset the very * first thing to do is, figure out the chipset and its capabilities */ /* This is the general case */ for (i = 0; inumEntities; i++) { cPtr->pEnt = xf86GetEntityInfo(pScrn->entityList[i]); #ifndef XSERVER_LIBPCIACCESS if (cPtr->pEnt->resources) return FALSE; #endif /* If we are using libpciaccess this is already set in CHIPSPciProbe. * If we are using something else we need to set it here. */ if (!cPtr->Chipset) cPtr->Chipset = cPtr->pEnt->chipset; pScrn->chipset = (char *)xf86TokenToString(CHIPSChipsets, cPtr->pEnt->chipset); if ((cPtr->Chipset == CHIPS_CT64200) || (cPtr->Chipset == CHIPS_CT64300)) cPtr->Flags |= ChipsWingine; if ((cPtr->Chipset >= CHIPS_CT65550) && (cPtr->Chipset <= CHIPS_CT69030)) cPtr->Flags |= ChipsHiQV; /* This driver can handle ISA and PCI buses */ if (cPtr->pEnt->location.type == BUS_PCI) { pciPtr = xf86GetPciInfoForEntity(cPtr->pEnt->index); cPtr->PciInfo = pciPtr; #ifndef XSERVER_LIBPCIACCESS cPtr->PciTag = pciTag(cPtr->PciInfo->bus, cPtr->PciInfo->device, cPtr->PciInfo->func); #endif } } /* INT10 */ #if 0 if (xf86LoadSubModule(pScrn, "int10")) { xf86Int10InfoPtr pInt; #if 1 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n"); pInt = xf86InitInt10(cPtr->pEnt->index); xf86FreeInt10(pInt); #endif } #endif if (xf86LoadSubModule(pScrn, "vbe")) { cPtr->pVbe = VBEInit(NULL,cPtr->pEnt->index); } /* Now that we've identified the chipset, setup the capabilities flags */ switch (cPtr->Chipset) { case CHIPS_CT69030: cPtr->Flags |= ChipsDualChannelSupport; case CHIPS_CT69000: cPtr->Flags |= ChipsFullMMIOSupport; /* Fall through */ case CHIPS_CT65555: cPtr->Flags |= ChipsImageReadSupport; /* Does the 69000 support it? */ /* Fall through */ case CHIPS_CT68554: cPtr->Flags |= ChipsTMEDSupport; /* Fall through */ case CHIPS_CT65554: case CHIPS_CT65550: cPtr->Flags |= ChipsGammaSupport; cPtr->Flags |= ChipsVideoSupport; /* Fall through */ case CHIPS_CT65548: case CHIPS_CT65546: case CHIPS_CT65545: cPtr->Flags |= ChipsMMIOSupport; /* Fall through */ case CHIPS_CT64300: cPtr->Flags |= ChipsAccelSupport; /* Fall through */ case CHIPS_CT65540: cPtr->Flags |= ChipsHDepthSupport; cPtr->Flags |= ChipsDPMSSupport; /* Fall through */ case CHIPS_CT65535: case CHIPS_CT65530: case CHIPS_CT65525: cPtr->Flags |= ChipsLinearSupport; /* Fall through */ case CHIPS_CT64200: case CHIPS_CT65520: break; } /* Check for shared entities */ if (xf86IsEntityShared(pScrn->entityList[0])) { if (!(cPtr->Flags & ChipsDualChannelSupport)) return FALSE; /* Make sure entity is PCI for now, though this might not be needed. */ if (cPtr->pEnt->location.type != BUS_PCI) return FALSE; /* Allocate an entity private if necessary */ if (xf86IsEntityShared(pScrn->entityList[0])) { cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex)->ptr; cPtr->entityPrivate = cPtrEnt; } #if 0 /* Set cPtr->device to the relevant Device section */ cPtr->device = xf86GetDevFromEntity(pScrn->entityList[0], pScrn->entityInstanceList[0]); #endif } /* Set the driver to use the PIO register functions by default */ CHIPSSetStdExtFuncs(cPtr); /* Call the device specific PreInit */ if (IS_HiQV(cPtr)) res = chipsPreInitHiQV(pScrn, flags); else if (IS_Wingine(cPtr)) res = chipsPreInitWingine(pScrn, flags); else res = chipsPreInit655xx(pScrn, flags); if (cPtr->UseFullMMIO) chipsUnmapMem(pScrn); if (!res) { vbeFree(cPtr->pVbe); cPtr->pVbe = NULL; return FALSE; } /*********/ /* * Setup the ClockRanges, which describe what clock ranges are available, * and what sort of modes they can be used for. */ clockRanges = xnfcalloc(sizeof(ClockRange), 1); clockRanges->next = NULL; clockRanges->ClockMulFactor = cPtr->ClockMulFactor; clockRanges->minClock = cPtr->MinClock; clockRanges->maxClock = cPtr->MaxClock; clockRanges->clockIndex = -1; /* programmable */ if (cPtr->PanelType & ChipsLCD) { clockRanges->interlaceAllowed = FALSE; clockRanges->doubleScanAllowed = FALSE; } else { clockRanges->interlaceAllowed = TRUE; clockRanges->doubleScanAllowed = TRUE; } /* * Reduce the amount of video ram for the modes, so that they * don't overlap with the DSTN framebuffer */ pScrn->videoRam -= (cPtr->FrameBufferSize + 1023) / 1024; cPtr->Rounding = 8 * (pScrn->bitsPerPixel <= 8 ? 8 : pScrn->bitsPerPixel); i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, clockRanges, NULL, 256, 2048, cPtr->Rounding, 128, 2048, pScrn->display->virtualX, pScrn->display->virtualY, cPtr->FbMapSize, LOOKUP_BEST_REFRESH); if (i == -1) { vbeFree(cPtr->pVbe); cPtr->pVbe = NULL; CHIPSFreeRec(pScrn); return FALSE; } /* * Put the DSTN framebuffer back into the video ram */ pScrn->videoRam += (cPtr->FrameBufferSize + 1023) / 1024; /* Prune the modes marked as invalid */ xf86PruneDriverModes(pScrn); if (i == 0 || pScrn->modes == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); vbeFree(cPtr->pVbe); cPtr->pVbe = NULL; CHIPSFreeRec(pScrn); return FALSE; } /* * Set the CRTC parameters for all of the modes based on the type * of mode, and the chipset's interlace requirements. * * Calling this is required if the mode->Crtc* values are used by the * driver and if the driver doesn't provide code to set them. They * are not pre-initialised at all. */ xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); /* Set the current mode to the first in the list */ pScrn->currentMode = pScrn->modes; /* Print the list of modes being used */ xf86PrintModes(pScrn); /* If monitor resolution is set on the command line, use it */ xf86SetDpi(pScrn, 0, 0); /* Load bpp-specific modules */ switch (pScrn->bitsPerPixel) { #ifdef HAVE_XF1BPP case 1: if (xf86LoadSubModule(pScrn, "xf1bpp") == NULL) { vbeFree(cPtr->pVbe); cPtr->pVbe = NULL; CHIPSFreeRec(pScrn); return FALSE; } break; #endif #ifdef HAVE_XF4BPP case 4: if (xf86LoadSubModule(pScrn, "xf4bpp") == NULL) { vbeFree(cPtr->pVbe); cPtr->pVbe = NULL; CHIPSFreeRec(pScrn); return FALSE; } break; #endif default: if (xf86LoadSubModule(pScrn, "fb") == NULL) { vbeFree(cPtr->pVbe); cPtr->pVbe = NULL; CHIPSFreeRec(pScrn); return FALSE; } break; } if (cPtr->Flags & ChipsAccelSupport) { if (!xf86LoadSubModule(pScrn, "xaa")) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Falling back to shadowfb\n"); cPtr->Flags &= ~(ChipsAccelSupport); cPtr->Flags |= ChipsShadowFB; } } if (cPtr->Flags & ChipsShadowFB) { if (!xf86LoadSubModule(pScrn, "shadowfb")) { vbeFree(cPtr->pVbe); cPtr->pVbe = NULL; CHIPSFreeRec(pScrn); return FALSE; } } if (cPtr->Accel.UseHWCursor) { if (!xf86LoadSubModule(pScrn, "ramdac")) { vbeFree(cPtr->pVbe); cPtr->pVbe = NULL; CHIPSFreeRec(pScrn); return FALSE; } } #ifndef XSERVER_LIBPCIACCESS if (cPtr->Flags & ChipsLinearSupport) xf86SetOperatingState(resVgaMem, cPtr->pEnt->index, ResDisableOpr); if (cPtr->MMIOBaseVGA) xf86SetOperatingState(resVgaIo, cPtr->pEnt->index, ResDisableOpr); #endif vbeFree(cPtr->pVbe); cPtr->pVbe = NULL; return TRUE; } static Bool chipsPreInitHiQV(ScrnInfoPtr pScrn, int flags) { int bytesPerPixel; unsigned char tmp; MessageType from; int i; unsigned int Probed[3], FPclkI, CRTclkI; double real; int val, indx; const char *s; pointer pVbeModule = NULL; vgaHWPtr hwp; CHIPSPtr cPtr = CHIPSPTR(pScrn); CHIPSEntPtr cPtrEnt = NULL; CHIPSPanelSizePtr Size = &cPtr->PanelSize; CHIPSMemClockPtr MemClk = &cPtr->MemClock; CHIPSClockPtr SaveClk = &(cPtr->SavedReg.Clock); #ifndef XSERVER_LIBPCIACCESS resRange linearRes[] = { {ResExcMemBlock|ResBios|ResBus,0,0},_END }; #endif /* Set pScrn->monitor */ pScrn->monitor = pScrn->confScreen->monitor; /* All HiQV chips support 16/24/32 bpp */ if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb | SupportConvert32to24 | PreferConvert32to24)) return FALSE; else { /* Check that the returned depth is one we support */ switch (pScrn->depth) { case 1: case 4: case 8: case 15: case 16: case 24: case 32: /* OK */ break; default: xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given depth (%d) is not supported by this driver\n", pScrn->depth); return FALSE; } } xf86PrintDepthBpp(pScrn); /* Get the depth24 pixmap format */ if (pScrn->depth == 24 && pix24bpp == 0) pix24bpp = xf86GetBppFromDepth(pScrn, 24); /* * Allocate a vgaHWRec, this must happen after xf86SetDepthBpp for 1bpp */ if (!vgaHWGetHWRec(pScrn)) return FALSE; hwp = VGAHWPTR(pScrn); vgaHWSetStdFuncs(hwp); vgaHWGetIOBase(hwp); #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12 cPtr->PIOBase = hwp->PIOOffset; #else cPtr->PIOBase = 0; #endif /* * Must allow ensure that storage for the 2nd set of vga registers is * allocated for dual channel cards */ if ((cPtr->Flags & ChipsDualChannelSupport) && (! xf86IsEntityShared(pScrn->entityList[0]))) vgaHWAllocDefaultRegs(&(cPtr->VgaSavedReg2)); /* * This must happen after pScrn->display has been set because * xf86SetWeight references it. */ if (pScrn->depth > 8) { /* The defaults are OK for us */ rgb zeros = {0, 0, 0}; if (!xf86SetWeight(pScrn, zeros, zeros)) { return FALSE; } else { /* XXX check that weight returned is supported */ ; } } if (!xf86SetDefaultVisual(pScrn, -1)) return FALSE; /* The gamma fields must be initialised when using the new cmap code */ if (pScrn->depth > 1) { Gamma zeros = {0.0, 0.0, 0.0}; if (!xf86SetGamma(pScrn, zeros)) return FALSE; } bytesPerPixel = max(1, pScrn->bitsPerPixel >> 3); /* Collect all of the relevant option flags (fill in pScrn->options) */ xf86CollectOptions(pScrn, NULL); /* Process the options */ if (!(cPtr->Options = malloc(sizeof(ChipsHiQVOptions)))) return FALSE; memcpy(cPtr->Options, ChipsHiQVOptions, sizeof(ChipsHiQVOptions)); xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, cPtr->Options); /* Set the bits per RGB */ if (pScrn->depth > 1) { /* Default to 6, is this right for HiQV?? */ pScrn->rgbBits = 8; if (xf86GetOptValInteger(cPtr->Options, OPTION_RGB_BITS, &val)) { if (val == 6 || val == 8) { pScrn->rgbBits = val; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Bits per RGB set to " "%d\n", pScrn->rgbBits); } else xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid number of " "rgb bits %d\n", val); } } if ((cPtr->Flags & ChipsAccelSupport) && (xf86ReturnOptValBool(cPtr->Options, OPTION_NOACCEL, FALSE))) { cPtr->Flags &= ~ChipsAccelSupport; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); } from = X_DEFAULT; if (pScrn->bitsPerPixel < 8) { /* Default to SW cursor for 1/4 bpp */ cPtr->Accel.UseHWCursor = FALSE; } else { cPtr->Accel.UseHWCursor = TRUE; } if (xf86GetOptValBool(cPtr->Options, OPTION_HW_CURSOR, &cPtr->Accel.UseHWCursor)) from = X_CONFIG; if (xf86GetOptValBool(cPtr->Options, OPTION_SW_CURSOR, &cPtr->Accel.UseHWCursor)) { from = X_CONFIG; cPtr->Accel.UseHWCursor = !cPtr->Accel.UseHWCursor; } xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", (cPtr->Accel.UseHWCursor) ? "HW" : "SW"); /* Default to nonlinear for < 8bpp and linear for >= 8bpp. */ if (pScrn->bitsPerPixel < 8) { if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, FALSE)) { cPtr->Flags &= ~ChipsLinearSupport; from = X_CONFIG; } } else if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, TRUE)) { cPtr->Flags &= ~ChipsLinearSupport; from = X_CONFIG; } #ifndef HAVE_ISA if (!(cPtr->Flags & ChipsLinearSupport)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Linear framebuffer required\n"); return FALSE; } #endif /* linear base */ if (cPtr->Flags & ChipsLinearSupport) { if (cPtr->pEnt->location.type == BUS_PCI) { /* Tack on 0x800000 to access the big-endian aperture? */ #if X_BYTE_ORDER == X_BIG_ENDIAN if (BE_SWAP_APRETURE(pScrn,cPtr)) cPtr->FbAddress = (PCI_REGION_BASE(cPtr->PciInfo, 0, REGION_MEM) & 0xff800000) + 0x800000L; else #endif cPtr->FbAddress = PCI_REGION_BASE(cPtr->PciInfo, 0, REGION_MEM) & 0xff800000; from = X_PROBED; #ifndef XSERVER_LIBPCIACCESS if (xf86RegisterResources(cPtr->pEnt->index,NULL,ResNone)) cPtr->Flags &= ~ChipsLinearSupport; #endif } else { if (cPtr->pEnt->device->MemBase) { cPtr->FbAddress = cPtr->pEnt->device->MemBase; from = X_CONFIG; } else { cPtr->FbAddress = ((unsigned int) (cPtr->readXR(cPtr, 0x06))) << 24; cPtr->FbAddress |= ((unsigned int) (0x80 & (cPtr->readXR(cPtr, 0x05)))) << 16; from = X_PROBED; } #ifndef XSERVER_LIBPCIACCESS linearRes[0].rBegin = cPtr->FbAddress; linearRes[0].rEnd = cPtr->FbAddress + 0x800000; if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) { cPtr->Flags &= ~ChipsLinearSupport; from = X_PROBED; } #endif } } if (cPtr->Flags & ChipsLinearSupport) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling linear addressing\n"); xf86DrvMsg(pScrn->scrnIndex, from, "base address is set at 0x%lX.\n", cPtr->FbAddress); #if X_BYTE_ORDER == X_BIG_ENDIAN if (BE_SWAP_APRETURE(pScrn,cPtr)) cPtr->IOAddress = cPtr->FbAddress - 0x400000L; else #endif cPtr->IOAddress = cPtr->FbAddress + 0x400000L; xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "IOAddress is set at 0x%lX.\n",(unsigned long)cPtr->IOAddress); } else xf86DrvMsg(pScrn->scrnIndex, from, "Disabling linear addressing\n"); if ((s = xf86GetOptValString(cPtr->Options, OPTION_ROTATE)) || xf86ReturnOptValBool(cPtr->Options, OPTION_SHADOW_FB, FALSE)) { if (!(cPtr->Flags & ChipsLinearSupport)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Option \"ShadowFB\" ignored. Not supported without linear addressing\n"); } else if (pScrn->depth < 8) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Option \"ShadowFB\" ignored. Not supported at this depth.\n"); } else { cPtr->Rotate = 0; if (s) { if(!xf86NameCmp(s, "CW")) { /* accel is disabled below for shadowFB */ cPtr->Flags |= ChipsShadowFB; cPtr->Rotate = 1; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen clockwise\n"); } else if(!xf86NameCmp(s, "CCW")) { cPtr->Flags |= ChipsShadowFB; cPtr->Rotate = -1; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen" "counter clockwise\n"); } else { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" "value for Option \"Rotate\"\n", s); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Valid options are \"CW\" or \"CCW\"\n"); } } else { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using \"Shadow Framebuffer\"\n"); cPtr->Flags |= ChipsShadowFB; } } } if(xf86GetOptValInteger(cPtr->Options, OPTION_VIDEO_KEY, &(cPtr->videoKey))) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n", cPtr->videoKey); } else { cPtr->videoKey = (1 << pScrn->offset.red) | (1 << pScrn->offset.green) | (((pScrn->mask.blue >> pScrn->offset.blue) - 1) << pScrn->offset.blue); } if (cPtr->Flags & ChipsShadowFB) { if (cPtr->Flags & ChipsAccelSupport) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HW acceleration is not supported with shadow fb\n"); cPtr->Flags &= ~ChipsAccelSupport; } if (cPtr->Rotate && cPtr->Accel.UseHWCursor) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HW cursor is not supported with rotate\n"); cPtr->Accel.UseHWCursor = FALSE; } } if (xf86ReturnOptValBool(cPtr->Options, OPTION_MMIO, TRUE)) { cPtr->UseMMIO = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using MMIO\n"); /* Are we using MMIO mapping of VGA registers */ if (xf86ReturnOptValBool(cPtr->Options, OPTION_FULL_MMIO, FALSE)) { if ((cPtr->Flags & ChipsLinearSupport) && (cPtr->Flags & ChipsFullMMIOSupport) && (cPtr->pEnt->location.type == BUS_PCI)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling Full MMIO\n"); cPtr->UseFullMMIO = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using Full MMIO\n"); /* * We need to map the framebuffer to read/write regs. * but can't do that without the FbMapSize. So need to * fake value for PreInit. This isn't a problem as * framebuffer isn't actually used in PreInit */ cPtr->FbMapSize = 1024 * 1024; /* Map the linear framebuffer */ if (!chipsMapMem(pScrn)) return FALSE; /* Setup the MMIO register functions */ if (cPtr->MMIOBaseVGA) { CHIPSSetMmioExtFuncs(cPtr); CHIPSHWSetMmioFuncs(pScrn, cPtr->MMIOBaseVGA, 0x0); } } else { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "FULL_MMIO option ignored\n"); } } } else { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,"Disabling MMIO: " "no acceleration, no hw_cursor\n"); cPtr->UseMMIO = FALSE; cPtr->Accel.UseHWCursor = FALSE; cPtr->Flags &= ~ChipsAccelSupport; } if (cPtr->Flags & ChipsDualChannelSupport) { if (xf86IsEntityShared(pScrn->entityList[0])) { cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex)->ptr; #if 1 /* * XXX This assumes that the lower number screen is always the * "master" head, and that the "master" is the first CRTC. This * can result in unexpected behaviour when the config file marks * the primary CRTC as the second screen. */ if (xf86IsPrimInitDone(pScrn->entityList[0])) #else /* * This is an alternative version that determines which is the * secondary CRTC from the screen field in cPtr->pEnt->device. * It doesn't currently work because there are things that assume * the primary CRTC is initialised first. */ if (cPtr->pEnt->device->screen == 1) #endif { /* This is the second crtc */ cPtr->SecondCrtc = TRUE; cPtr->UseDualChannel = TRUE; } else cPtr->SecondCrtc = FALSE; } else { if (xf86ReturnOptValBool(cPtr->Options, OPTION_DUAL_REFRESH, FALSE)) { cPtr->Flags |= ChipsDualRefresh; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Dual Refresh mode enabled\n"); cPtr->UseDualChannel = TRUE; } } /* Store IOSS/MSS so that we can restore them */ cPtr->storeIOSS = cPtr->readIOSS(cPtr); cPtr->storeMSS = cPtr->readMSS(cPtr); DUALOPEN; } /* memory size */ if (cPtr->pEnt->device->videoRam != 0) { pScrn->videoRam = cPtr->pEnt->device->videoRam; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VideoRAM: %d kByte\n", pScrn->videoRam); } else { /* not given, probe it */ switch (cPtr->Chipset) { case CHIPS_CT69030: /* The ct69030 has 4Mb of SGRAM integrated */ pScrn->videoRam = 4096; cPtr->Flags |= Chips64BitMemory; break; case CHIPS_CT69000: /* The ct69000 has 2Mb of SGRAM integrated */ pScrn->videoRam = 2048; cPtr->Flags |= Chips64BitMemory; break; case CHIPS_CT65550: /* XR43: DRAM interface */ /* bit 2-1: memory size */ /* 0: 1024 kB */ /* 1: 2048 kB */ /* 2: reserved */ /* 3: reserved */ switch (((cPtr->readXR(cPtr, 0x43)) & 0x06) >> 1) { case 0: pScrn->videoRam = 1024; break; case 1: case 2: case 3: pScrn->videoRam = 2048; break; } break; default: /* XRE0: Software reg */ /* bit 3-0: memory size */ /* 0: 512k */ /* 1: 1024k */ /* 2: 1536k(1.5M)*/ /* 3: 2048k */ /* 7: 4096k */ tmp = (cPtr->readXR(cPtr, 0xE0)) & 0xF; switch (tmp) { case 0: pScrn->videoRam = 512; break; case 1: pScrn->videoRam = 1024; break; case 2: pScrn->videoRam = 1536; break; case 3: pScrn->videoRam = 2048; break; case 7: pScrn->videoRam = 4096; break; default: pScrn->videoRam = 1024; break; } /* XR43: DRAM interface */ /* bit 4-5 mem interface width */ /* 00: 32Bit */ /* 01: 64Bit */ tmp = cPtr->readXR(cPtr, 0x43); if ((tmp & 0x10) == 0x10) cPtr->Flags |= Chips64BitMemory; break; } } #if X_BYTE_ORDER == X_BIG_ENDIAN if (cPtr->pEnt->chipset == CHIPS_CT69030 && ((cPtr->readXR(cPtr, 0x71) & 0x2)) == 0) /* CFG9: Pipeline variable ByteSwap mapping */ cPtr->dualEndianAp = TRUE; else /* CFG9: Pipeline A/B mapping */ cPtr->dualEndianAp = FALSE; #endif if ((cPtr->Flags & ChipsDualChannelSupport) && (xf86IsEntityShared(pScrn->entityList[0]))) { /* * This takes gives either half or the amount of memory specified * with the Crt2Memory option */ pScrn->memPhysBase = cPtr->FbAddress; if(cPtr->SecondCrtc == FALSE) { int crt2mem = -1, adjust; xf86GetOptValInteger(cPtr->Options, OPTION_CRT2_MEM, &crt2mem); if (crt2mem > 0) { adjust = crt2mem; from = X_CONFIG; } else { adjust = pScrn->videoRam / 2; from = X_DEFAULT; } xf86DrvMsg(pScrn->scrnIndex, from, "CRT2 will use %dK of VideoRam\n", adjust); cPtrEnt->mastervideoRam = pScrn->videoRam - adjust; pScrn->videoRam = cPtrEnt->mastervideoRam; cPtrEnt->slavevideoRam = adjust; cPtrEnt->masterFbAddress = cPtr->FbAddress; cPtr->FbMapSize = cPtrEnt->masterFbMapSize = pScrn->videoRam * 1024; cPtrEnt->slaveFbMapSize = cPtrEnt->slavevideoRam * 1024; pScrn->fbOffset = 0; } else { cPtrEnt->slaveFbAddress = cPtr->FbAddress + cPtrEnt->masterFbMapSize; cPtr->FbMapSize = cPtrEnt->slaveFbMapSize; pScrn->videoRam = cPtrEnt->slavevideoRam; pScrn->fbOffset = cPtrEnt->masterFbMapSize; } cPtrEnt->refCount++; } else { /* Normal Handling of video ram etc */ cPtr->FbMapSize = pScrn->videoRam * 1024; } xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VideoRAM: %d kByte\n", pScrn->videoRam); /* Store register values that might be messed up by a suspend resume */ /* Do this early as some of the other code in PreInit relies on it */ cPtr->SuspendHack.vgaIOBaseFlag = ((hwp->readMiscOut(hwp)) & 0x01); cPtr->IOBase = (unsigned int)(cPtr->SuspendHack.vgaIOBaseFlag ? 0x3D0 : 0x3B0); /* * Do DDC here: if VESA BIOS detects an external monitor it * might switch. SetPanelType() will detect this. */ if ((pVbeModule = xf86LoadSubModule(pScrn, "ddc"))) { Bool ddc_done = FALSE; xf86MonPtr pMon; if (cPtr->pVbe) { if ((pMon = xf86PrintEDID(vbeDoEDID(cPtr->pVbe, pVbeModule))) != NULL) { ddc_done = TRUE; xf86SetDDCproperties(pScrn,pMon); } } if (!ddc_done) if (xf86LoadSubModule(pScrn, "i2c")) { if (chips_i2cInit(pScrn)) { if ((pMon = xf86PrintEDID(xf86DoEDID_DDC2(XF86_SCRN_ARG(pScrn), cPtr->I2C))) != NULL) ddc_done = TRUE; xf86SetDDCproperties(pScrn,pMon); } } if (!ddc_done) chips_ddc1(pScrn); } /*test STN / TFT */ tmp = cPtr->readFR(cPtr, 0x10); /* XR51 or FR10: DISPLAY TYPE REGISTER */ /* XR51[1-0] or FR10[1:0] for ct65550 : PanelType, */ /* 0 = Single Panel Single Drive, 3 = Dual Panel Dual Drive */ switch (tmp & 0x3) { case 0: if (xf86ReturnOptValBool(cPtr->Options, OPTION_STN, FALSE)) { cPtr->PanelType |= ChipsSS; xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "SS-STN probed\n"); } else { cPtr->PanelType |= ChipsTFT; xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "TFT probed\n"); } break; case 2: cPtr->PanelType |= ChipsDS; xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DS-STN probed\n"); case 3: cPtr->PanelType |= ChipsDD; xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DD-STN probed\n"); break; default: break; } chipsSetPanelType(cPtr); from = X_PROBED; { Bool fp_mode; if (xf86GetOptValBool(cPtr->Options, OPTION_FP_MODE, &fp_mode)) { if (fp_mode) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing FP Mode on\n"); cPtr->PanelType |= ChipsLCD; } else { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing FP Mode off\n"); cPtr->PanelType = ~ChipsLCD; } from = X_CONFIG; } } if ((cPtr->PanelType & ChipsLCD) && (cPtr->PanelType & ChipsCRT)) xf86DrvMsg(pScrn->scrnIndex, from, "LCD/CRT\n"); else if (cPtr->PanelType & ChipsLCD) xf86DrvMsg(pScrn->scrnIndex, from, "LCD\n"); else if (cPtr->PanelType & ChipsCRT) { xf86DrvMsg(pScrn->scrnIndex, from, "CRT\n"); /* monitor info */ #if 1 cPtr->Monitor = chipsSetMonitor(pScrn); #endif } /* screen size */ /* * In LCD mode / dual mode we want to derive the timing values from * the ones preset by bios */ if (cPtr->PanelType & ChipsLCD) { /* for 65550 we only need H/VDisplay values for screen size */ unsigned char fr25, tmp1; #ifdef DEBUG unsigned char fr26; char tmp2; #endif fr25 = cPtr->readFR(cPtr, 0x25); tmp = cPtr->readFR(cPtr, 0x20); Size->HDisplay = ((tmp + ((fr25 & 0x0F) << 8)) + 1) << 3; tmp = cPtr->readFR(cPtr, 0x30); tmp1 = cPtr->readFR(cPtr, 0x35); Size->VDisplay = ((tmp1 & 0x0F) << 8) + tmp + 1; #ifdef DEBUG tmp = cPtr->readFR(cPtr, 0x21); Size->HRetraceStart = ((tmp + ((fr25 & 0xF0) << 4)) + 1) << 3; tmp1 = cPtr->readFR(cPtr, 0x22); tmp2 = (tmp1 & 0x1F) - (tmp & 0x3F); Size->HRetraceEnd = ((((tmp2 < 0) ? (tmp2 + 0x40) : tmp2) << 3) + Size->HRetraceStart); tmp = cPtr->readFR(cPtr, 0x23); fr26 = cPtr->readFR(cPtr, 0x26); Size->HTotal = ((tmp + ((fr26 & 0x0F) << 8)) + 5) << 3; xf86ErrorF("x=%i, y=%i; xSync=%i, xSyncEnd=%i, xTotal=%i\n", Size->HDisplay, Size->VDisplay, Size->HRetraceStart,Size->HRetraceEnd, Size->HTotal); #endif xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Display Size: x=%i; y=%i\n", Size->HDisplay, Size->VDisplay); /* Warn the user if the panel size has been overridden by * the modeline values */ if (xf86ReturnOptValBool(cPtr->Options, OPTION_PANEL_SIZE, FALSE)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Display size overridden by modelines.\n"); } } /* Frame Buffer */ /* for LCDs */ if (IS_STN(cPtr->PanelType)) { tmp = cPtr->readFR(cPtr, 0x1A); /*Frame Buffer Ctrl. */ if (tmp & 1) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Frame Buffer used\n"); if (!(tmp & 0x80)) { /* Formula for calculating the size of the framebuffer. 3 * bits per pixel 10 pixels per 32 bit dword. If frame * acceleration is enabled the size can be halved. */ cPtr->FrameBufferSize = ( Size->HDisplay * Size->VDisplay / 5 ) * ((tmp & 2) ? 1 : 2); xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Using embedded Frame Buffer, size %d bytes\n", cPtr->FrameBufferSize); } else xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Using external Frame Buffer used\n"); } if (tmp & 2) xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Frame accelerator enabled\n"); } /* bus type */ tmp = (cPtr->readXR(cPtr, 0x08)) & 1; if (tmp == 1) { /*PCI */ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "PCI Bus\n"); cPtr->Bus = ChipsPCI; } else { /* XR08: Linear addressing base, not for PCI */ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VL Bus\n"); cPtr->Bus = ChipsVLB; } /* disable acceleration for 1 and 4 bpp */ if (pScrn->bitsPerPixel < 8) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Disabling acceleration for %d bpp\n", pScrn->bitsPerPixel); cPtr->Flags &= ~ChipsAccelSupport; } /* Set the flags for Colour transparency. This is dependent * on the revision on the chip. Until exactly which chips * have this bug are found, only allow 8bpp Colour transparency */ if ((pScrn->bitsPerPixel == 8) || ((cPtr->Chipset >= CHIPS_CT65555) && (pScrn->bitsPerPixel >= 8) && (pScrn->bitsPerPixel <= 24))) cPtr->Flags |= ChipsColorTransparency; else cPtr->Flags &= ~ChipsColorTransparency; /* DAC info */ if (!((cPtr->readXR(cPtr, 0xD0)) & 0x01)) xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Internal DAC disabled\n"); /* MMIO address offset */ cPtr->Regs32 = ChipsReg32HiQV; /* sync reset ignored on this chipset */ cPtr->SyncResetIgn = TRUE; /* !! */ /* We use a programmable clock */ pScrn->numClocks = 26; /* Some number */ pScrn->progClock = TRUE; cPtr->ClockType = HiQV_STYLE | TYPE_PROGRAMMABLE; if (cPtr->pEnt->device->textClockFreq > 0) { SaveClk->Clock = cPtr->pEnt->device->textClockFreq; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using textclock freq: %7.3f.\n", SaveClk->Clock/1000.0); } else SaveClk->Clock = 0; xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Using programmable clocks\n"); /* Set the maximum memory clock. */ switch (cPtr->Chipset) { case CHIPS_CT65550: if (((cPtr->readXR(cPtr, 0x04)) & 0xF) < 6) MemClk->Max = 38000; /* Revision A chips */ else MemClk->Max = 50000; /* Revision B chips */ break; case CHIPS_CT65554: case CHIPS_CT65555: case CHIPS_CT68554: MemClk->Max = 55000; break; case CHIPS_CT69000: MemClk->Max = 83000; break; case CHIPS_CT69030: MemClk->Max = 100000; break; } /* Probe the dot clocks */ for (i = 0; i < 3; i++) { unsigned int N,M,PSN,P,VCO_D; int offset = i * 4; tmp = cPtr->readXR(cPtr,0xC2 + offset); M = (cPtr->readXR(cPtr, 0xC0 + offset) | (tmp & 0x03)) + 2; N = (cPtr->readXR(cPtr, 0xC1 + offset) | (( tmp >> 4) & 0x03)) + 2; tmp = cPtr->readXR(cPtr, 0xC3 + offset); PSN = (cPtr->Chipset == CHIPS_CT69000 || cPtr->Chipset == CHIPS_CT69030) ? 1 : (((tmp & 0x1) ? 1 : 4) * ((tmp & 0x02) ? 5 : 1)); VCO_D = ((tmp & 0x04) ? ((cPtr->Chipset == CHIPS_CT69000 || cPtr->Chipset == CHIPS_CT69030) ? 1 : 16) : 4); P = ((tmp & 0x70) >> 4); Probed[i] = VCO_D * Fref / N; Probed[i] = Probed[i] * M / (PSN * (1 << P)); Probed[i] = Probed[i] / 1000; } CRTclkI = (hwp->readMiscOut(hwp) >> 2) & 0x03; if (CRTclkI == 3) CRTclkI = 2; if (cPtr->Chipset == CHIPS_CT69030) FPclkI = (cPtr->readFR(cPtr, 0x01) >> 2) & 0x3; else FPclkI = (cPtr->readFR(cPtr, 0x03) >> 2) & 0x3; if (FPclkI == 3) FPclkI = 2; for (i = 0; i < 3; i++) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Dot clock %i: %7.3f MHz",i, (float)(Probed[i])/1000.); if (FPclkI == i) xf86ErrorF(" FPclk"); if (CRTclkI == i) xf86ErrorF(" CRTclk"); xf86ErrorF("\n"); } cPtr->FPclock = Probed[FPclkI]; cPtr->FPclkInx = FPclkI; if (CRTclkI == FPclkI) { if (FPclkI == 2) CRTclkI = 1; else CRTclkI = 2; } cPtr->CRTclkInx = CRTclkI; /* * Some chips seem to dislike some clocks in one of the PLL's. Give * the user the oppurtunity to change it */ if (xf86GetOptValInteger(cPtr->Options, OPTION_CRT_CLK_INDX, &indx)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Force CRT Clock index to %d\n", indx); cPtr->CRTclkInx = indx; if (xf86GetOptValInteger(cPtr->Options, OPTION_FP_CLK_INDX, &indx)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Force FP Clock index to %d\n", indx); cPtr->FPclkInx = indx; } else { if (indx == cPtr->FPclkInx) { if (indx == 2) cPtr->FPclkInx = 1; else cPtr->FPclkInx = indx + 1; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "FP Clock index forced to %d\n", cPtr->FPclkInx); } } } else if (xf86GetOptValInteger(cPtr->Options, OPTION_FP_CLK_INDX, &indx)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Force FP Clock index to %d\n", indx); cPtr->FPclkInx = indx; if (indx == cPtr->CRTclkInx) { if (indx == 2) cPtr->CRTclkInx = 1; else cPtr->CRTclkInx = indx + 1; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "CRT Clock index forced to %d\n", cPtr->CRTclkInx); } } /* Probe the memory clock currently in use */ MemClk->xrCC = cPtr->readXR(cPtr, 0xCC); MemClk->M = (MemClk->xrCC & 0x7F) + 2; MemClk->xrCD = cPtr->readXR(cPtr, 0xCD); MemClk->N = (MemClk->xrCD & 0x7F) + 2; MemClk->xrCE = cPtr->readXR(cPtr, 0xCE); MemClk->PSN = (MemClk->xrCE & 0x1) ? 1 : 4; MemClk->P = ((MemClk->xrCE & 0x70) >> 4); /* Be careful with the calculation of ProbeClk as it can overflow */ MemClk->ProbedClk = 4 * Fref / MemClk->N; MemClk->ProbedClk = MemClk->ProbedClk * MemClk->M / (MemClk->PSN * (1 << MemClk->P)); MemClk->ProbedClk = MemClk->ProbedClk / 1000; MemClk->Clk = MemClk->ProbedClk; if (xf86GetOptValFreq(cPtr->Options, OPTION_SET_MCLK, OPTUNITS_MHZ, &real)) { int mclk = (int)(real * 1000.0); if (mclk <= MemClk->Max) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using memory clock of %7.3f MHz\n", (float)(mclk/1000.)); /* Only alter the memory clock if the desired memory clock differs * by 50kHz from the one currently being used. */ if (abs(mclk - MemClk->ProbedClk) > 50) { unsigned char vclk[3]; MemClk->Clk = mclk; chipsCalcClock(pScrn, MemClk->Clk, vclk); MemClk->M = vclk[1] + 2; MemClk->N = vclk[2] + 2; MemClk->P = (vclk[0] & 0x70) >> 4; MemClk->PSN = (vclk[0] & 0x1) ? 1 : 4; MemClk->xrCC = vclk[1]; MemClk->xrCD = vclk[2]; MemClk->xrCE = 0x80 || vclk[0]; } } else xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Memory clock of %7.3f MHz exceeds limit of %7.3f MHz\n", (float)(mclk/1000.), (float)(MemClk->Max/1000.)); } else xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Probed memory clock of %7.3f MHz\n", (float)(MemClk->ProbedClk/1000.)); cPtr->ClockMulFactor = 1; /* Set the min/max pixel clock */ switch (cPtr->Chipset) { case CHIPS_CT69030: cPtr->MinClock = 3000; cPtr->MaxClock = 170000; break; case CHIPS_CT69000: cPtr->MinClock = 3000; cPtr->MaxClock = 135000; break; case CHIPS_CT68554: case CHIPS_CT65555: cPtr->MinClock = 1000; cPtr->MaxClock = 110000; break; case CHIPS_CT65554: cPtr->MinClock = 1000; cPtr->MaxClock = 95000; break; case CHIPS_CT65550: cPtr->MinClock = 1000; if (((cPtr->readXR(cPtr, 0x04)) & 0xF) < 6) { if ((cPtr->readFR(cPtr, 0x0A)) & 2) { /*5V Vcc */ cPtr->MaxClock = 100000; } else { /*3.3V Vcc */ cPtr->MaxClock = 80000; } } else cPtr->MaxClock = 95000; /* Revision B */ break; } xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %7.3f MHz\n", (float)(cPtr->MinClock / 1000.)); /* Check if maxClock is limited by the MemClk. Only 70% to allow for */ /* RAS/CAS. Extra byte per memory clock needed if framebuffer used */ /* Extra byte if the overlay plane is activated */ /* If flag Chips64BitMemory is set assume a 64bitmemory interface, */ /* and 32bits on the others. Thus multiply by a suitable factor */ if (cPtr->Flags & Chips64BitMemory) { if (cPtr->FrameBufferSize && (cPtr->PanelType & ChipsLCD)) cPtr->MaxClock = min(cPtr->MaxClock, MemClk->Clk * 8 * 0.7 / (bytesPerPixel + 1)); else cPtr->MaxClock = min(cPtr->MaxClock, MemClk->Clk * 8 * 0.7 / bytesPerPixel); } else { if (cPtr->FrameBufferSize && (cPtr->PanelType & ChipsLCD)) cPtr->MaxClock = min(cPtr->MaxClock, MemClk->Clk * 4 * 0.7 / (bytesPerPixel + 1)); else cPtr->MaxClock = min(cPtr->MaxClock, MemClk->Clk * 4 * 0.7 / bytesPerPixel); } if (cPtr->pEnt->device->dacSpeeds[0]) { int speed = 0; switch (pScrn->bitsPerPixel) { case 1: case 4: case 8: speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP8]; break; case 16: speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP16]; break; case 24: speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP24]; break; case 32: speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP32]; break; } if (speed == 0) speed = cPtr->pEnt->device->dacSpeeds[0]; from = X_CONFIG; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "User max pixel clock of %7.3f MHz overrides %7.3f MHz limit\n", (float)(speed / 1000.), (float)(cPtr->MaxClock / 1000.)); cPtr->MaxClock = speed; } else { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Max pixel clock is %7.3f MHz\n", (float)(cPtr->MaxClock / 1000.)); } /* * Prepare the FPclock: * if FPclock <= MaxClock : don't modify the FP clock. * else set FPclock to 90% of MaxClock. */ real = 0.; switch(bytesPerPixel) { case 1: if (xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_8, OPTUNITS_MHZ, &real)) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "FP clock %7.3f MHz requested\n",real); break; case 2: if (xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_16, OPTUNITS_MHZ, &real)) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "FP clock %7.3f MHz requested\n",real); break; case 3: if (xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_24, OPTUNITS_MHZ, &real)) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "FP clock %7.3f MHz requested\n",real); break; case 4: if (xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_32, OPTUNITS_MHZ, &real)) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "FP clock %7.3f MHz requested\n",real); break; } val = (int) (real * 1000.); if (val && val >= cPtr->MinClock && val <= cPtr->MaxClock) cPtr->FPclock = val; else if (cPtr->FPclock > cPtr->MaxClock) cPtr->FPclock = (int)((float)cPtr->MaxClock * 0.9); else cPtr->FPclock = 0; /* special value */ cPtr->FPClkModified = FALSE; if (cPtr->FPclock) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "FP clock set to %7.3f MHz\n", (float)(cPtr->FPclock / 1000.)); #if defined(__arm32__) && defined(__NetBSD__) ChipsPALMode.next = pScrn->monitor->Modes; pScrn->monitor->Modes = &ChipsNTSCMode; #endif if (cPtr->Flags & ChipsDualChannelSupport) { if (xf86IsEntityShared(pScrn->entityList[0])) { if (cPtr->SecondCrtc == TRUE) { cPtrEnt->slaveActive = FALSE; } else { cPtrEnt->masterActive = FALSE; } } /* Put IOSS/MSS back to normal */ cPtr->writeIOSS(cPtr, cPtr->storeIOSS); cPtr->writeMSS(cPtr, hwp, cPtr->storeMSS); xf86SetPrimInitDone(pScrn->entityList[0]); } return TRUE; } static Bool chipsPreInitWingine(ScrnInfoPtr pScrn, int flags) { int i, bytesPerPixel, NoClocks = 0; unsigned char tmp; MessageType from; vgaHWPtr hwp; CHIPSPtr cPtr = CHIPSPTR(pScrn); CHIPSClockPtr SaveClk = &(cPtr->SavedReg.Clock); Bool useLinear = FALSE; char *s; #ifndef XSERVER_LIBPCIACCESS resRange linearRes[] = { {ResExcMemBlock|ResBios|ResBus,0,0},_END }; #endif /* Set pScrn->monitor */ pScrn->monitor = pScrn->confScreen->monitor; if (cPtr->Flags & ChipsHDepthSupport) i = xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | SupportConvert32to24 | PreferConvert32to24); else i = xf86SetDepthBpp(pScrn, 8, 0, 0, NoDepth24Support); if (!i) return FALSE; else { /* Check that the returned depth is one we support */ switch (pScrn->depth) { case 1: case 4: case 8: /* OK */ break; case 15: case 16: case 24: if (cPtr->Flags & ChipsHDepthSupport) break; /* OK */ /* fall through */ default: xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given depth (%d) is not supported by this driver\n", pScrn->depth); return FALSE; } } xf86PrintDepthBpp(pScrn); /* Get the depth24 pixmap format */ if (pScrn->depth == 24 && pix24bpp == 0) pix24bpp = xf86GetBppFromDepth(pScrn, 24); /* * Allocate a vgaHWRec, this must happen after xf86SetDepthBpp for 1bpp */ if (!vgaHWGetHWRec(pScrn)) return FALSE; hwp = VGAHWPTR(pScrn); vgaHWGetIOBase(hwp); /* * This must happen after pScrn->display has been set because * xf86SetWeight references it. */ if (pScrn->depth > 8) { /* The defaults are OK for us */ rgb zeros = {0, 0, 0}; if (!xf86SetWeight(pScrn, zeros, zeros)) { return FALSE; } else { /* XXX check that weight returned is supported */ ; } } if (!xf86SetDefaultVisual(pScrn, -1)) return FALSE; /* The gamma fields must be initialised when using the new cmap code */ if (pScrn->depth > 1) { Gamma zeros = {0.0, 0.0, 0.0}; if (!xf86SetGamma(pScrn, zeros)) return FALSE; } /* Store register values that might be messed up by a suspend resume */ /* Do this early as some of the other code in PreInit relies on it */ cPtr->SuspendHack.xr02 = (cPtr->readXR(cPtr, 0x02)) & 0x18; cPtr->SuspendHack.xr03 = (cPtr->readXR(cPtr, 0x03)) & 0x0A; cPtr->SuspendHack.xr14 = (cPtr->readXR(cPtr, 0x14)) & 0x20; cPtr->SuspendHack.xr15 = cPtr->readXR(cPtr, 0x15); cPtr->SuspendHack.vgaIOBaseFlag = ((hwp->readMiscOut(hwp)) & 0x01); cPtr->IOBase = (unsigned int)(cPtr->SuspendHack.vgaIOBaseFlag ? 0x3D0 : 0x3B0); bytesPerPixel = max(1, pScrn->bitsPerPixel >> 3); /* Collect all of the relevant option flags (fill in pScrn->options) */ xf86CollectOptions(pScrn, NULL); /* Process the options */ if (!(cPtr->Options = malloc(sizeof(ChipsWingineOptions)))) return FALSE; memcpy(cPtr->Options, ChipsWingineOptions, sizeof(ChipsWingineOptions)); xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, cPtr->Options); /* Set the bits per RGB */ if (pScrn->depth > 1) { /* Default to 6, is this right?? */ pScrn->rgbBits = 6; #if 0 if (xf86GetOptValInteger(cPtr->Options, OPTION_RGB_BITS, &pScrn->rgbBits)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Bits per RGB set to %d\n", pScrn->rgbBits); } #endif } if ((cPtr->Flags & ChipsAccelSupport) && (xf86ReturnOptValBool(cPtr->Options, OPTION_NOACCEL, FALSE))) { cPtr->Flags &= ~ChipsAccelSupport; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); } from = X_DEFAULT; if (pScrn->bitsPerPixel < 8) { /* Default to SW cursor for 1/4 bpp */ cPtr->Accel.UseHWCursor = FALSE; } else { cPtr->Accel.UseHWCursor = TRUE; } if (xf86GetOptValBool(cPtr->Options, OPTION_HW_CURSOR, &cPtr->Accel.UseHWCursor)) from = X_CONFIG; if (xf86GetOptValBool(cPtr->Options, OPTION_SW_CURSOR, &cPtr->Accel.UseHWCursor)) { from = X_CONFIG; cPtr->Accel.UseHWCursor = !cPtr->Accel.UseHWCursor; } xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", (cPtr->Accel.UseHWCursor) ? "HW" : "SW"); /* memory size */ if (cPtr->pEnt->device->videoRam != 0) { pScrn->videoRam = cPtr->pEnt->device->videoRam; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VideoRAM: %d kByte\n", pScrn->videoRam); } else { /* not given, probe it */ /* XR0F: Software flags 0 */ /* bit 1-0: memory size */ /* 0: 256 kB */ /* 1: 512 kB */ /* 2: 1024 kB */ /* 3: 1024 kB */ switch ((cPtr->readXR(cPtr, 0x0F)) & 3) { case 0: pScrn->videoRam = 256; break; case 1: pScrn->videoRam = 512; break; case 2: pScrn->videoRam = 1024; break; case 3: pScrn->videoRam = 2048; break; } xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VideoRAM: %d kByte\n", pScrn->videoRam); } cPtr->FbMapSize = pScrn->videoRam * 1024; /* Default to nonlinear for < 8bpp and linear for >= 8bpp. */ if (cPtr->Flags & ChipsLinearSupport) useLinear = TRUE; if (pScrn->bitsPerPixel < 8) { if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, FALSE)) { useLinear = FALSE; from = X_CONFIG; } } else if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, TRUE)) { useLinear = FALSE; from = X_CONFIG; } #ifndef HAVE_ISA if (!(cPtr->Flags & ChipsLinearSupport)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Linear framebuffer required\n"); return FALSE; } #endif /* linear base */ if (useLinear) { unsigned char mask = 0xF8; if (pScrn->videoRam == 1024) mask = 0xF0; else if (pScrn->videoRam == 2048) mask = 0xE0; if (cPtr->pEnt->device->MemBase) { cPtr->FbAddress = cPtr->pEnt->device->MemBase & ((0xFF << 24) | (mask << 16)); from = X_CONFIG; } else { cPtr->FbAddress = ((0xFF & (cPtr->readXR(cPtr, 0x09))) << 24); cPtr->FbAddress |= ((mask & (cPtr->readXR(cPtr, 0x08))) << 16); from = X_PROBED; } #ifndef XSERVER_LIBPCIACCESS linearRes[0].rBegin = cPtr->FbAddress; linearRes[0].rEnd = cPtr->FbAddress + 0x800000; if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) { useLinear = FALSE; from = X_PROBED; } #endif } if (useLinear) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling linear addressing\n"); xf86DrvMsg(pScrn->scrnIndex, from, "base address is set at 0x%lX.\n", cPtr->FbAddress); if (xf86ReturnOptValBool(cPtr->Options, OPTION_MMIO, FALSE) && (cPtr->Flags & ChipsMMIOSupport)) { cPtr->UseMMIO = TRUE; cPtr->IOAddress = cPtr->FbAddress + 0x200000L; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling MMIO\n"); } } else { if (cPtr->Flags & ChipsLinearSupport) xf86DrvMsg(pScrn->scrnIndex, from, "Disabling linear addressing\n"); cPtr->Flags &= ~ChipsLinearSupport; } if ((s = xf86GetOptValString(cPtr->Options, OPTION_ROTATE)) || xf86ReturnOptValBool(cPtr->Options, OPTION_SHADOW_FB, FALSE)) { if (!(cPtr->Flags & ChipsLinearSupport)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Option \"ShadowFB\" ignored. Not supported without linear addressing\n"); } else if (pScrn->depth < 8) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Option \"ShadowFB\" ignored. Not supported at this depth.\n"); } else { cPtr->Rotate = 0; if (s) { if(!xf86NameCmp(s, "CW")) { /* accel is disabled below for shadowFB */ cPtr->Flags |= ChipsShadowFB; cPtr->Rotate = 1; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen clockwise\n"); } else if(!xf86NameCmp(s, "CCW")) { cPtr->Flags |= ChipsShadowFB; cPtr->Rotate = -1; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen" "counter clockwise\n"); } else { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" "value for Option \"Rotate\"\n", s); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Valid options are \"CW\" or \"CCW\"\n"); } } else { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using \"Shadow Framebuffer\"\n"); cPtr->Flags |= ChipsShadowFB; } } } if (cPtr->Flags & ChipsShadowFB) { if (cPtr->Flags & ChipsAccelSupport) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HW acceleration is not supported with shadow fb\n"); cPtr->Flags &= ~ChipsAccelSupport; } if (cPtr->Rotate && cPtr->Accel.UseHWCursor) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HW cursor is not supported with rotate\n"); cPtr->Accel.UseHWCursor = FALSE; } } cPtr->PanelType |= ChipsCRT; xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT\n"); /* monitor info */ cPtr->Monitor = chipsSetMonitor(pScrn); /* bus type */ tmp = cPtr->readXR(cPtr, 0x01) & 3; switch (tmp) { case 0: xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "ISA Bus\n"); cPtr->Bus = ChipsISA; break; case 3: xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VL Bus\n"); cPtr->Bus = ChipsVLB; break; default: xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Unknown Bus\n"); cPtr->Bus = ChipsUnknown; break; } /* disable acceleration for 1 and 4 bpp */ if (pScrn->bitsPerPixel < 8) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Disabling acceleration for %d bpp\n", pScrn->bitsPerPixel); cPtr->Flags &= ~ChipsAccelSupport; } /* 32bit register address offsets */ if ((cPtr->Flags & ChipsAccelSupport) || (cPtr->Accel.UseHWCursor)) { cPtr->Regs32 = xnfalloc(sizeof(ChipsReg32)); tmp = cPtr->readXR(cPtr, 0x07); for( i = 0; i < (sizeof(ChipsReg32) / sizeof(ChipsReg32[0])); i++) { cPtr->Regs32[i] = ((ChipsReg32[i] & 0x7E03)) | ((tmp & 0x80) << 8)| ((tmp & 0x7F) << 2); #ifdef DEBUG ErrorF("DR[%X] = %X\n",i,cPtr->Regs32[i]); #endif } #ifndef XSERVER_LIBPCIACCESS linearRes[0].type = ResExcIoSparse | ResBios | ResBus; linearRes[0].rBase = cPtr->Regs32[0]; linearRes[0].rMask = 0x83FC; if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) { if (cPtr->Flags & ChipsAccelSupport) { cPtr->Flags &= ~ChipsAccelSupport; xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Cannot allocate IO registers: " "Disabling acceleration\n"); } if (cPtr->Accel.UseHWCursor) { cPtr->Accel.UseHWCursor = FALSE; xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Cannot allocate IO registers: " "Disabling HWCursor\n"); } } #endif } cPtr->ClockMulFactor = ((pScrn->bitsPerPixel >= 8) ? bytesPerPixel : 1); if (cPtr->ClockMulFactor != 1) xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Clocks scaled by %d\n", cPtr->ClockMulFactor); /* Clock type */ switch (cPtr->Chipset) { case CHIPS_CT64200: NoClocks = 4; cPtr->ClockType = WINGINE_1_STYLE | TYPE_HW; break; default: if (!((cPtr->readXR(cPtr, 0x01)) & 0x10)) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Using external clock generator\n"); NoClocks = 4; cPtr->ClockType = WINGINE_1_STYLE | TYPE_HW; } else { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Using internal clock generator\n"); if (xf86ReturnOptValBool(cPtr->Options, OPTION_HW_CLKS, FALSE)) { NoClocks = 3; cPtr->ClockType = WINGINE_2_STYLE | TYPE_HW; } else { NoClocks = 26; /* some number */ cPtr->ClockType = WINGINE_2_STYLE | TYPE_PROGRAMMABLE; pScrn->progClock = TRUE; } } } if (cPtr->ClockType & TYPE_PROGRAMMABLE) { pScrn->numClocks = NoClocks; if(cPtr->pEnt->device->textClockFreq > 0) { SaveClk->Clock = cPtr->pEnt->device->textClockFreq; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using textclock freq: %7.3f.\n", SaveClk->Clock/1000.0); } else SaveClk->Clock = CRT_TEXT_CLK_FREQ; xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Using programmable clocks\n"); } else { /* TYPE_PROGRAMMABLE */ SaveClk->Clock = chipsGetHWClock(pScrn); xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using textclock clock %i.\n", SaveClk->Clock); if (!cPtr->pEnt->device->numclocks) { pScrn->numClocks = NoClocks; xf86GetClocks(pScrn, NoClocks, chipsClockSelect, chipsProtect, chipsBlankScreen, cPtr->IOBase + 0x0A, 0x08, 1, 28322); from = X_PROBED; } else { pScrn->numClocks = cPtr->pEnt->device->numclocks; if (pScrn->numClocks > NoClocks) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Too many Clocks specified in configuration file.\n"); xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\t\tAt most %d clocks may be specified\n", NoClocks); pScrn->numClocks= NoClocks; } for (i = 0; i < pScrn->numClocks; i++) pScrn->clock[i] = cPtr->pEnt->device->clock[i]; from = X_CONFIG; } xf86ShowClocks(pScrn, from); } /* Set the min pixel clock */ /* XXX Guess, need to check this */ cPtr->MinClock = 11000 / cPtr->ClockMulFactor; xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %7.3f MHz\n", (float)(cPtr->MinClock / 1000.)); /* maximal clock */ switch (cPtr->Chipset) { case CHIPS_CT64200: cPtr->MaxClock = 80000 / cPtr->ClockMulFactor; break; case CHIPS_CT64300: cPtr->MaxClock = 85000 / cPtr->ClockMulFactor; break; } if (cPtr->pEnt->device->dacSpeeds[0]) { int speed = 0; switch (pScrn->bitsPerPixel) { case 1: case 4: case 8: speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP8]; break; case 16: speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP16]; break; case 24: speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP24]; break; } if (speed == 0) cPtr->MaxClock = cPtr->pEnt->device->dacSpeeds[0]; from = X_CONFIG; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "User max pixel clock of %7.3f MHz overrides %7.3f MHz limit\n", (float)(cPtr->MaxClock / 1000.), (float)(speed / 1000.)); cPtr->MaxClock = speed; } else { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Max pixel clock is %7.3f MHz\n", (float)(cPtr->MaxClock / 1000.)); } if (xf86LoadSubModule(pScrn, "ddc")) { if (cPtr->pVbe) xf86SetDDCproperties(pScrn,xf86PrintEDID(vbeDoEDID(cPtr->pVbe, NULL))); } return TRUE; } static Bool chipsPreInit655xx(ScrnInfoPtr pScrn, int flags) { int i, bytesPerPixel, NoClocks = 0; unsigned char tmp; MessageType from; vgaHWPtr hwp; CHIPSPtr cPtr = CHIPSPTR(pScrn); CHIPSPanelSizePtr Size = &cPtr->PanelSize; CHIPSClockPtr SaveClk = &(cPtr->SavedReg.Clock); Bool useLinear = FALSE; char *s; #ifndef XSERVER_LIBPCIACCESS resRange linearRes[] = { {ResExcMemBlock|ResBios|ResBus,0,0},_END }; #endif /* Set pScrn->monitor */ pScrn->monitor = pScrn->confScreen->monitor; if (cPtr->Flags & ChipsHDepthSupport) i = xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | SupportConvert32to24 | PreferConvert32to24); else i = xf86SetDepthBpp(pScrn, 8, 0, 0, NoDepth24Support); if (!i) return FALSE; else { /* Check that the returned depth is one we support */ switch (pScrn->depth) { case 1: case 4: case 8: /* OK */ break; case 15: case 16: case 24: if (cPtr->Flags & ChipsHDepthSupport) break; /* OK */ /* fall through */ default: xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given depth (%d) is not supported by this driver\n", pScrn->depth); return FALSE; } } xf86PrintDepthBpp(pScrn); /* Get the depth24 pixmap format */ if (pScrn->depth == 24 && pix24bpp == 0) pix24bpp = xf86GetBppFromDepth(pScrn, 24); /* * Allocate a vgaHWRec, this must happen after xf86SetDepthBpp for 1bpp */ if (!vgaHWGetHWRec(pScrn)) return FALSE; hwp = VGAHWPTR(pScrn); vgaHWGetIOBase(hwp); /* * This must happen after pScrn->display has been set because * xf86SetWeight references it. */ if (pScrn->depth > 8) { /* The defaults are OK for us */ rgb zeros = {0, 0, 0}; if (!xf86SetWeight(pScrn, zeros, zeros)) { return FALSE; } else { /* XXX check that weight returned is supported */ ; } } if (!xf86SetDefaultVisual(pScrn, -1)) return FALSE; /* The gamma fields must be initialised when using the new cmap code */ if (pScrn->depth > 1) { Gamma zeros = {0.0, 0.0, 0.0}; if (!xf86SetGamma(pScrn, zeros)) return FALSE; } /* Store register values that might be messed up by a suspend resume */ /* Do this early as some of the other code in PreInit relies on it */ cPtr->SuspendHack.xr02 = (cPtr->readXR(cPtr, 0x02)) & 0x18; cPtr->SuspendHack.xr03 = (cPtr->readXR(cPtr, 0x03)) & 0x0A; cPtr->SuspendHack.xr14 = (cPtr->readXR(cPtr, 0x14)) & 0x20; cPtr->SuspendHack.xr15 = cPtr->readXR(cPtr, 0x15); cPtr->SuspendHack.vgaIOBaseFlag = ((hwp->readMiscOut(hwp)) & 0x01); cPtr->IOBase = cPtr->SuspendHack.vgaIOBaseFlag ? 0x3D0 : 0x3B0; bytesPerPixel = max(1, pScrn->bitsPerPixel >> 3); /* Collect all of the relevant option flags (fill in pScrn->options) */ xf86CollectOptions(pScrn, NULL); /* Process the options */ if (!(cPtr->Options = malloc(sizeof(Chips655xxOptions)))) return FALSE; memcpy(cPtr->Options, Chips655xxOptions, sizeof(Chips655xxOptions)); xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, cPtr->Options); /* Set the bits per RGB */ if (pScrn->depth > 1) { /* Default to 6, is this right */ pScrn->rgbBits = 6; #if 0 if (xf86GetOptValInteger(cPtr->Options, OPTION_RGB_BITS, &pScrn->rgbBits)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Bits per RGB set to %d\n", pScrn->rgbBits); } #endif } if ((cPtr->Flags & ChipsAccelSupport) && (xf86ReturnOptValBool(cPtr->Options, OPTION_NOACCEL, FALSE))) { cPtr->Flags &= ~ChipsAccelSupport; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); } from = X_DEFAULT; if (pScrn->bitsPerPixel < 8) { /* Default to SW cursor for 1/4 bpp */ cPtr->Accel.UseHWCursor = FALSE; } else { cPtr->Accel.UseHWCursor = TRUE; } if (xf86GetOptValBool(cPtr->Options, OPTION_HW_CURSOR, &cPtr->Accel.UseHWCursor)) from = X_CONFIG; if (xf86GetOptValBool(cPtr->Options, OPTION_SW_CURSOR, &cPtr->Accel.UseHWCursor)) { from = X_CONFIG; cPtr->Accel.UseHWCursor = !cPtr->Accel.UseHWCursor; } xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", (cPtr->Accel.UseHWCursor) ? "HW" : "SW"); /* memory size */ if (cPtr->pEnt->device->videoRam != 0) { pScrn->videoRam = cPtr->pEnt->device->videoRam; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VideoRAM: %d kByte\n", pScrn->videoRam); } else { /* not given, probe it */ /* XR0F: Software flags 0 */ /* bit 1-0: memory size */ /* 0: 256 kB */ /* 1: 512 kB */ /* 2: 1024 kB */ /* 3: 1024 kB */ switch ((cPtr->readXR(cPtr, 0x0F)) & 3) { case 0: pScrn->videoRam = 256; break; case 1: pScrn->videoRam = 512; break; case 2: case 3: pScrn->videoRam = 1024; break; } xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VideoRAM: %d kByte\n", pScrn->videoRam); } cPtr->FbMapSize = pScrn->videoRam * 1024; /* Default to nonlinear for < 8bpp and linear for >= 8bpp. */ if (cPtr->Flags & ChipsLinearSupport) useLinear = TRUE; if (pScrn->bitsPerPixel < 8) { if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, FALSE)) { useLinear = FALSE; from = X_CONFIG; } } else if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, TRUE)) { useLinear = FALSE; from = X_CONFIG; } #ifndef HAVE_ISA if (!(cPtr->Flags & ChipsLinearSupport)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Linear framebuffer required\n"); return FALSE; } #endif /* linear base */ if (useLinear) { unsigned char mask; if (cPtr->Chipset == CHIPS_CT65535) { mask = (pScrn->videoRam > 512) ? 0xF8 :0xFC; if (cPtr->Bus == ChipsISA) mask &= 0x7F; } else if (cPtr->Bus == ChipsISA) { mask = 0x0F; } else { mask = 0xFF; tmp = cPtr->readXR(cPtr, 0x01); if(tmp & 0x40) mask &= 0x3F; if(!(tmp & 0x80)) mask &= 0xCF; } if (cPtr->pEnt->location.type == BUS_PCI) { cPtr->FbAddress = PCI_REGION_BASE(cPtr->PciInfo, 0, REGION_MEM) & 0xff800000; #ifndef XSERVER_LIBPCIACCESS if (xf86RegisterResources(cPtr->pEnt->index,NULL,ResNone)) { useLinear = FALSE; from = X_PROBED; } #endif } else { if (cPtr->pEnt->device->MemBase) { cPtr->FbAddress = cPtr->pEnt->device->MemBase; if (cPtr->Chipset == CHIPS_CT65535) cPtr->FbAddress &= (mask << 17); else if (cPtr->Chipset > CHIPS_CT65535) cPtr->FbAddress &= (mask << 20); from = X_CONFIG; } else { if (cPtr->Chipset <= CHIPS_CT65530) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "base address assumed at 0xC00000!\n"); cPtr->FbAddress = 0xC00000; from = X_CONFIG; } else if (cPtr->Chipset == CHIPS_CT65535) { cPtr->FbAddress = ((mask & (cPtr->readXR(cPtr, 0x08))) << 17); } else { cPtr->FbAddress = ((mask & (cPtr->readXR(cPtr, 0x08))) << 20); } from = X_PROBED; } #ifndef XSERVER_LIBPCIACCESS linearRes[0].rBegin = cPtr->FbAddress; linearRes[0].rEnd = cPtr->FbAddress + 0x800000; if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) { useLinear = FALSE; from = X_PROBED; } #endif } } if (useLinear) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling linear addressing\n"); xf86DrvMsg(pScrn->scrnIndex, from, "base address is set at 0x%lX.\n", cPtr->FbAddress); if (xf86ReturnOptValBool(cPtr->Options, OPTION_MMIO, FALSE) && (cPtr->Flags & ChipsMMIOSupport)) { cPtr->UseMMIO = TRUE; cPtr->IOAddress = cPtr->FbAddress + 0x200000L; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling MMIO\n"); } } else { if (cPtr->Flags & ChipsLinearSupport) xf86DrvMsg(pScrn->scrnIndex, from, "Disabling linear addressing\n"); cPtr->Flags &= ~ChipsLinearSupport; } if ((s = xf86GetOptValString(cPtr->Options, OPTION_ROTATE)) || xf86ReturnOptValBool(cPtr->Options, OPTION_SHADOW_FB, FALSE)) { if (!(cPtr->Flags & ChipsLinearSupport)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Option \"ShadowFB\" ignored. Not supported without linear addressing\n"); } else if (pScrn->depth < 8) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Option \"ShadowFB\" ignored. Not supported at this depth.\n"); } else { cPtr->Rotate = 0; if (s) { if(!xf86NameCmp(s, "CW")) { /* accel is disabled below for shadowFB */ cPtr->Flags |= ChipsShadowFB; cPtr->Rotate = 1; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen clockwise\n"); } else if(!xf86NameCmp(s, "CCW")) { cPtr->Flags |= ChipsShadowFB; cPtr->Rotate = -1; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen" "counter clockwise\n"); } else { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" "value for Option \"Rotate\"\n", s); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Valid options are \"CW\" or \"CCW\"\n"); } } else { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using \"Shadow Framebuffer\"\n"); cPtr->Flags |= ChipsShadowFB; } } } if (cPtr->Flags & ChipsShadowFB) { if (cPtr->Flags & ChipsAccelSupport) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HW acceleration is not supported with shadow fb\n"); cPtr->Flags &= ~ChipsAccelSupport; } if (cPtr->Rotate && cPtr->Accel.UseHWCursor) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "HW cursor is not supported with rotate\n"); cPtr->Accel.UseHWCursor = FALSE; } } /*test STN / TFT */ tmp = cPtr->readXR(cPtr, 0x51); /* XR51 or FR10: DISPLAY TYPE REGISTER */ /* XR51[1-0] or FR10[1:0] for ct65550 : PanelType, */ /* 0 = Single Panel Single Drive, 3 = Dual Panel Dual Drive */ switch (tmp & 0x3) { case 0: if (xf86ReturnOptValBool(cPtr->Options, OPTION_STN, FALSE)) { cPtr->PanelType |= ChipsSS; xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "SS-STN probed\n"); } else { cPtr->PanelType |= ChipsTFT; xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "TFT probed\n"); } break; case 2: cPtr->PanelType |= ChipsDS; xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DS-STN probed\n"); case 3: cPtr->PanelType |= ChipsDD; xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DD-STN probed\n"); break; default: break; } chipsSetPanelType(cPtr); from = X_PROBED; { Bool fp_mode; if (xf86GetOptValBool(cPtr->Options, OPTION_FP_MODE, &fp_mode)) { if (fp_mode) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing FP Mode on\n"); cPtr->PanelType |= ChipsLCD; } else { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing FP Mode off\n"); cPtr->PanelType = ~ChipsLCD; } from = X_CONFIG; } } if ((cPtr->PanelType & ChipsLCD) && (cPtr->PanelType & ChipsCRT)) xf86DrvMsg(pScrn->scrnIndex, from, "LCD/CRT\n"); else if (cPtr->PanelType & ChipsLCD) xf86DrvMsg(pScrn->scrnIndex, from, "LCD\n"); else if (cPtr->PanelType & ChipsCRT) { xf86DrvMsg(pScrn->scrnIndex, from, "CRT\n"); /* monitor info */ cPtr->Monitor = chipsSetMonitor(pScrn); } /* screen size */ /* * In LCD mode / dual mode we want to derive the timing values from * the ones preset by bios */ if (cPtr->PanelType & ChipsLCD) { unsigned char xr17, tmp1; char tmp2; xr17 = cPtr->readXR(cPtr, 0x17); tmp = cPtr->readXR(cPtr, 0x1B); Size->HTotal =((tmp + ((xr17 & 0x01) << 8)) + 5) << 3; tmp = cPtr->readXR(cPtr, 0x1C); Size->HDisplay = ((tmp + ((xr17 & 0x02) << 7)) + 1) << 3; tmp = cPtr->readXR(cPtr, 0x19); Size->HRetraceStart = ((tmp + ((xr17 & 0x04) << 9)) + 1) << 3; tmp1 = cPtr->readXR(cPtr, 0x1A); tmp2 = (tmp1 & 0x1F) + ((xr17 & 0x08) << 2) - (tmp & 0x3F); Size->HRetraceEnd = ((((tmp2 & 0x080u) ? (tmp2 + 0x40) : tmp2) << 3) + Size->HRetraceStart); tmp1 = cPtr->readXR(cPtr, 0x65); tmp = cPtr->readXR(cPtr, 0x68); Size->VDisplay = ((tmp1 & 0x02) << 7) + ((tmp1 & 0x40) << 3) + tmp + 1; tmp = cPtr->readXR(cPtr, 0x66); Size->VRetraceStart = ((tmp1 & 0x04) << 6) + ((tmp1 & 0x80) << 2) + tmp + 1; tmp = cPtr->readXR(cPtr, 0x64); Size->VTotal = ((tmp1 & 0x01) << 8) + ((tmp1 & 0x20) << 4) + tmp + 2; #ifdef DEBUG ErrorF("x=%i, y=%i; xSync=%i, xSyncEnd=%i, xTotal=%i\n", Size->HDisplay, Size->VDisplay, Size->HRetraceStart, Size->HRetraceEnd, Size->HTotal); #endif xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Display Size: x=%i; y=%i\n", Size->HDisplay, Size->VDisplay); /* Warn the user if the panel size has been overridden by * the modeline values */ if (xf86ReturnOptValBool(cPtr->Options, OPTION_PANEL_SIZE, FALSE)) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Display size overridden by modelines.\n"); } } /* Frame Buffer */ /* for LCDs */ if (IS_STN(cPtr->PanelType)) { tmp = cPtr->readXR(cPtr, 0x6F); /*Frame Buffer Ctrl. */ if (tmp & 1) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Frame Buffer used\n"); if ((cPtr->Chipset > CHIPS_CT65530) && !(tmp & 0x80)) { /* Formula for calculating the size of the framebuffer. 3 * bits per pixel 10 pixels per 32 bit dword. If frame * acceleration is enabled the size can be halved. */ cPtr->FrameBufferSize = ( Size->HDisplay * Size->VDisplay / 5 ) * ((tmp & 2) ? 1 : 2); xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Using embedded Frame Buffer, size %d bytes\n", cPtr->FrameBufferSize); } else xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Using external Frame Buffer used\n"); } if (tmp & 2) xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Frame accelerator enabled\n"); } /* bus type */ if (cPtr->Chipset > CHIPS_CT65535) { tmp = (cPtr->readXR(cPtr, 0x01)) & 7; if (tmp == 6) { /*PCI */ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "PCI Bus\n"); cPtr->Bus = ChipsPCI; if ((cPtr->Chipset == CHIPS_CT65545) || (cPtr->Chipset == CHIPS_CT65546)) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "32Bit IO not supported on 65545 PCI\n"); xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "\tenabling MMIO\n"); cPtr->UseMMIO = TRUE; cPtr->IOAddress = cPtr->FbAddress + 0x200000L; } } else { /* XR08: Linear addressing base, not for PCI */ switch (tmp) { case 3: xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CPU Direct\n"); cPtr->Bus = ChipsCPUDirect; break; case 5: xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "ISA Bus\n"); cPtr->Bus = ChipsISA; break; case 7: xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VL Bus\n"); cPtr->Bus = ChipsVLB; break; default: xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Unknown Bus\n"); } } } else { tmp = (cPtr->readXR(cPtr, 0x01)) & 3; switch (tmp) { case 0: xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "PI Bus\n"); cPtr->Bus = ChipsPIB; break; case 1: xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MC Bus\n"); cPtr->Bus = ChipsMCB; break; case 2: xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VL Bus\n"); cPtr->Bus = ChipsVLB; break; case 3: xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "ISA Bus\n"); cPtr->Bus = ChipsISA; break; } } if (!(cPtr->Bus == ChipsPCI) && (cPtr->UseMMIO)) { cPtr->UseMMIO = FALSE; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "MMIO only supported on PCI Bus. Disabling MMIO\n"); } /* disable acceleration for 1 and 4 bpp */ if (pScrn->bitsPerPixel < 8) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Disabling acceleration for %d bpp\n", pScrn->bitsPerPixel); cPtr->Flags &= ~ChipsAccelSupport; } if ((cPtr->Chipset == CHIPS_CT65530) && (cPtr->Flags & ChipsLinearSupport)) { /* linear mode is no longer default on ct65530 since it */ /* requires additional hardware which some manufacturers*/ /* might not provide. */ if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, FALSE)) cPtr->Flags &= ~ChipsLinearSupport; /* Test wether linear addressing is possible on 65530 */ /* on the 65530 only the A19 select scheme can be used*/ /* for linear addressing since MEMW is used on ISA bus*/ /* systems. */ /* A19 however is used if video memory is > 512 Mb */ if ((cPtr->Bus == ChipsISA) && (pScrn->videoRam > 512)) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "User selected linear fb not supported by HW!\n"); cPtr->Flags &= ~ChipsLinearSupport; } } /* DAC info */ if ((cPtr->readXR(cPtr, 0x06)) & 0x02) xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Internal DAC disabled\n"); /* MMIO address offset */ if (cPtr->UseMMIO) cPtr->Regs32 = ChipsReg32; else if ((cPtr->Flags & ChipsAccelSupport) || (cPtr->Accel.UseHWCursor)) { cPtr->Regs32 = xnfalloc(sizeof(ChipsReg32)); tmp = cPtr->readXR(cPtr, 0x07); for (i = 0; i < (sizeof(ChipsReg32)/sizeof(ChipsReg32[0])); i++) { cPtr->Regs32[i] = ((ChipsReg32[i] & 0x7E03)) | ((tmp & 0x80)<< 8) | ((tmp & 0x7F) << 2); #ifdef DEBUG ErrorF("DR[%X] = %X\n",i,cPtr->Regs32[i]); #endif } #ifndef XSERVER_LIBPCIACCESS linearRes[0].type = ResExcIoSparse | ResBios | ResBus; linearRes[0].rBase = cPtr->Regs32[0]; linearRes[0].rMask = 0x83FC; if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) { if (cPtr->Flags & ChipsAccelSupport) { cPtr->Flags &= ~ChipsAccelSupport; xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Cannot allocate IO registers: " "Disabling acceleration\n"); } if (cPtr->Accel.UseHWCursor) { cPtr->Accel.UseHWCursor = FALSE; xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Cannot allocate IO registers: " "Disabling HWCursor\n"); } } #endif } /* sync reset ignored on this chipset */ if (cPtr->Chipset > CHIPS_CT65530) { tmp = cPtr->readXR(cPtr, 0x0E); if (tmp & 0x80) cPtr->SyncResetIgn = TRUE; xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Synchronous reset %signored.\n", (cPtr->SyncResetIgn ? "" : "not ")); } cPtr->ClockMulFactor = ((pScrn->bitsPerPixel >= 8) ? bytesPerPixel : 1); if (cPtr->ClockMulFactor != 1) xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Clocks scaled by %d\n", cPtr->ClockMulFactor); /* We use a programmable clock */ switch (cPtr->Chipset) { case CHIPS_CT65520: case CHIPS_CT65525: case CHIPS_CT65530: NoClocks = 4; /* Some number */ cPtr->ClockType = OLD_STYLE | TYPE_HW; break; default: if (xf86ReturnOptValBool(cPtr->Options, OPTION_HW_CLKS, FALSE)) { NoClocks = 5; /* Some number */ cPtr->ClockType = NEW_STYLE | TYPE_HW; } else { NoClocks = 26; /* Some number */ cPtr->ClockType = NEW_STYLE | TYPE_PROGRAMMABLE; pScrn->progClock = TRUE; } } if (cPtr->ClockType & TYPE_PROGRAMMABLE) { pScrn->numClocks = NoClocks; if (cPtr->pEnt->device->textClockFreq > 0) { SaveClk->Clock = cPtr->pEnt->device->textClockFreq; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using textclock freq: %7.3f.\n", SaveClk->Clock/1000.0); } else SaveClk->Clock = ((cPtr->PanelType & ChipsLCDProbed) ? LCD_TEXT_CLK_FREQ : CRT_TEXT_CLK_FREQ); xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Using programmable clocks\n"); } else { /* TYPE_PROGRAMMABLE */ SaveClk->Clock = chipsGetHWClock(pScrn); xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using textclock clock %i.\n", SaveClk->Clock); if (!cPtr->pEnt->device->numclocks) { pScrn->numClocks = NoClocks; xf86GetClocks(pScrn, NoClocks, chipsClockSelect, chipsProtect, chipsBlankScreen, cPtr->IOBase + 0x0A, 0x08, 1, 28322); from = X_PROBED; } else { pScrn->numClocks = cPtr->pEnt->device->numclocks; if (pScrn->numClocks > NoClocks) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Too many Clocks specified in configuration file.\n"); xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\t\tAt most %d clocks may be specified\n", NoClocks); pScrn->numClocks = NoClocks; } for (i = 0; i < pScrn->numClocks; i++) pScrn->clock[i] = cPtr->pEnt->device->clock[i]; from = X_CONFIG; } xf86ShowClocks(pScrn, from); } /* Set the min pixel clock */ /* XXX Guess, need to check this */ cPtr->MinClock = 11000 / cPtr->ClockMulFactor; xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %7.3f MHz\n", (float)(cPtr->MinClock / 1000.)); /* Set the max pixel clock */ switch (cPtr->Chipset) { case CHIPS_CT65546: case CHIPS_CT65548: /* max VCLK is 80 MHz, max MCLK is 75 MHz for CT65548 */ /* It is not sure for CT65546, but it works with 60 nsec EDODRAM */ cPtr->MaxClock = 80000 / cPtr->ClockMulFactor; break; default: if ((cPtr->readXR(cPtr, 0x6C)) & 2) { /*5V Vcc */ cPtr->MaxClock = 68000 / cPtr->ClockMulFactor; } else { /*3.3V Vcc */ cPtr->MaxClock = 56000 / cPtr->ClockMulFactor; } } if (cPtr->pEnt->device->dacSpeeds[0]) { int speed = 0; switch (pScrn->bitsPerPixel) { case 1: case 4: case 8: speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP8]; break; case 16: speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP16]; break; case 24: speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP24]; break; } if (speed == 0) cPtr->MaxClock = cPtr->pEnt->device->dacSpeeds[0]; from = X_CONFIG; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "User max pixel clock of %7.3f MHz overrides %7.3f MHz limit\n", (float)(cPtr->MaxClock / 1000.), (float)(speed / 1000.)); cPtr->MaxClock = speed; } else { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Max pixel clock is %7.3f MHz\n", (float)(cPtr->MaxClock / 1000.)); } /* FP clock */ if (cPtr->ClockType & TYPE_PROGRAMMABLE) { double real = 0; switch(bytesPerPixel) { case 1: xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_8, OPTUNITS_MHZ, &real); break; case 2: xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_16, OPTUNITS_MHZ, &real); break; case 3: xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_24, OPTUNITS_MHZ, &real); break; } if (real > 0) { int val; xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "FP clock %7.3f MHz requested\n",real); val = (int) (real * 1000.); if (val && (val >= cPtr->MinClock) && (val <= cPtr->MaxClock)) cPtr->FPclock = val * cPtr->ClockMulFactor; else if (val > cPtr->MaxClock) cPtr->FPclock = (int)((float)cPtr->MaxClock * cPtr->ClockMulFactor * 0.9); else cPtr->FPclock = 0; /* special value */ } else cPtr->FPclock = 0; /* special value */ if (cPtr->FPclock) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "FP clock set to %7.3f MHz\n", (float)(cPtr->FPclock / 1000.)); } else { if (xf86IsOptionSet(cPtr->Options, OPTION_SET_MCLK)) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "FP clock option not supported for this chipset\n"); } /* Memory Clock */ if (cPtr->ClockType & TYPE_PROGRAMMABLE) { double real; switch (cPtr->Chipset) { case CHIPS_CT65546: case CHIPS_CT65548: /* max MCLK is 75 MHz for CT65548 */ cPtr->MemClock.Max = 75000; break; default: if ((cPtr->readXR(cPtr, 0x6C)) & 2) { /*5V Vcc */ cPtr->MemClock.Max = 68000; } else { /*3.3V Vcc */ cPtr->MemClock.Max = 56000; } } if (xf86GetOptValFreq(cPtr->Options, OPTION_SET_MCLK, OPTUNITS_MHZ, &real)) { int mclk = (int)(real * 1000.0); if (mclk <= cPtr->MemClock.Max) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using memory clock of %7.3f MHz\n", (float)(mclk/1000.)); cPtr->MemClock.Clk = mclk; } else { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Memory clock of %7.3f MHz exceeds limit of " "%7.3f MHz\n",(float)(mclk/1000.), (float)(cPtr->MemClock.Max/1000.)); cPtr->MemClock.Clk = cPtr->MemClock.Max * 0.9; } } else cPtr->MemClock.Clk = 0; } else if (xf86IsOptionSet(cPtr->Options, OPTION_SET_MCLK)) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Memory clock option not supported for this chipset\n"); if (xf86LoadSubModule(pScrn, "ddc")) { if (cPtr->pVbe) xf86SetDDCproperties(pScrn,xf86PrintEDID(vbeDoEDID(cPtr->pVbe, NULL))); } return TRUE; } /* Mandatory */ static Bool CHIPSEnterVT(VT_FUNC_ARGS_DECL) { SCRN_INFO_PTR(arg); CHIPSPtr cPtr = CHIPSPTR(pScrn); CHIPSEntPtr cPtrEnt; if (cPtr->Flags & ChipsDualChannelSupport) { cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex)->ptr; DUALOPEN; } /* Should we re-save the text mode on each VT enter? */ if(!chipsModeInit(pScrn, pScrn->currentMode)) return FALSE; if ((cPtr->Flags & ChipsVideoSupport) && (cPtr->Flags & ChipsLinearSupport)) CHIPSResetVideo(pScrn); /*usleep(50000);*/ chipsHWCursorOn(cPtr, pScrn); /* cursor settle delay */ usleep(50000); CHIPSAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); usleep(50000); return TRUE; } /* Mandatory */ static void CHIPSLeaveVT(VT_FUNC_ARGS_DECL) { SCRN_INFO_PTR(arg); CHIPSPtr cPtr = CHIPSPTR(pScrn); CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); CHIPSEntPtr cPtrEnt; /* Invalidate the cached acceleration registers */ cAcl->planemask = -1; cAcl->fgColor = -1; cAcl->bgColor = -1; if (cPtr->Flags & ChipsDualChannelSupport) { cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex)->ptr; if (cPtr->UseDualChannel) DUALREOPEN; DUALCLOSE; } else { chipsHWCursorOff(cPtr, pScrn); chipsRestore(pScrn, &(VGAHWPTR(pScrn))->SavedReg, &cPtr->SavedReg, TRUE); chipsLock(pScrn); } } static void chipsLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual) { vgaHWPtr hwp = VGAHWPTR(pScrn); CHIPSPtr cPtr = CHIPSPTR(pScrn); int i, index, shift ; CHIPSEntPtr cPtrEnt; shift = (pScrn->depth == 15) ? 3 : 0; if (cPtr->UseDualChannel) { cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex)->ptr; DUALREOPEN; } for (i = 0; i < numColors; i++) { index = indices[i]; hwp->writeDacWriteAddr(hwp,index << shift); DACDelay(hwp); hwp->writeDacData(hwp, colors[index].red); DACDelay(hwp); hwp->writeDacData(hwp, colors[index].green); DACDelay(hwp); hwp->writeDacData(hwp, colors[index].blue); DACDelay(hwp); } if (cPtr->UseDualChannel && (! xf86IsEntityShared(pScrn->entityList[0]))) { unsigned int IOSS, MSS; IOSS = cPtr->readIOSS(cPtr); MSS = cPtr->readMSS(cPtr); cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | IOSS_PIPE_B)); cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B)); for (i = 0; i < numColors; i++) { index = indices[i]; hwp->writeDacWriteAddr(hwp,index << shift); DACDelay(hwp); hwp->writeDacData(hwp, colors[index].red); DACDelay(hwp); hwp->writeDacData(hwp, colors[index].green); DACDelay(hwp); hwp->writeDacData(hwp, colors[index].blue); DACDelay(hwp); } cPtr->writeIOSS(cPtr, IOSS); cPtr->writeMSS(cPtr, hwp, MSS); } /* This shouldn't be necessary, but we'll play safe. */ hwp->disablePalette(hwp); } static void chipsLoadPalette16(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, VisualPtr pVisual) { vgaHWPtr hwp = VGAHWPTR(pScrn); CHIPSPtr cPtr = CHIPSPTR(pScrn); CHIPSEntPtr cPtrEnt; int i, index; if (cPtr->UseDualChannel) { cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex)->ptr; DUALREOPEN; } for (i = 0; i < numColors; i++) { index = indices[i]; hwp->writeDacWriteAddr(hwp, index << 2); DACDelay(hwp); hwp->writeDacData(hwp, colors[index >> 1].red); DACDelay(hwp); hwp->writeDacData(hwp, colors[index].green); DACDelay(hwp); hwp->writeDacData(hwp, colors[index >> 1].blue); DACDelay(hwp); } if (cPtr->UseDualChannel && (! xf86IsEntityShared(pScrn->entityList[0]))) { unsigned int IOSS, MSS; IOSS = cPtr->readIOSS(cPtr); MSS = cPtr->readMSS(cPtr); cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | IOSS_PIPE_B)); cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B)); for (i = 0; i < numColors; i++) { index = indices[i]; hwp->writeDacWriteAddr(hwp, index << 2); DACDelay(hwp); hwp->writeDacData(hwp, colors[index >> 1].red); DACDelay(hwp); hwp->writeDacData(hwp, colors[index].green); DACDelay(hwp); hwp->writeDacData(hwp, colors[index >> 1].blue); DACDelay(hwp); } cPtr->writeIOSS(cPtr, IOSS); cPtr->writeMSS(cPtr, hwp, MSS); } /* This shouldn't be necessary, but we'll play safe. */ hwp->disablePalette(hwp); } /* Mandatory */ static Bool CHIPSScreenInit(SCREEN_INIT_ARGS_DECL) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); vgaHWPtr hwp; CHIPSPtr cPtr; CHIPSACLPtr cAcl; int ret; int init_picture = 0; VisualPtr visual; int allocatebase, freespace, currentaddr; #ifndef XSERVER_LIBPCIACCESS unsigned int racflag = 0; #endif unsigned char *FBStart; int height, width, displayWidth; CHIPSEntPtr cPtrEnt = NULL; #ifdef DEBUG ErrorF("CHIPSScreenInit\n"); #endif /* * we need to get the ScrnInfoRec for this screen, so let's allocate * one first thing */ cPtr = CHIPSPTR(pScrn); cAcl = CHIPSACLPTR(pScrn); hwp = VGAHWPTR(pScrn); hwp->MapSize = 0x10000; /* Standard 64k VGA window */ /* Map the VGA memory */ if (!vgaHWMapMem(pScrn)) return FALSE; /* Map the Chips memory and possible MMIO areas */ if (!chipsMapMem(pScrn)) return FALSE; /* Setup the MMIO register access functions if need */ if (cPtr->UseFullMMIO && cPtr->MMIOBaseVGA) { CHIPSSetMmioExtFuncs(cPtr); CHIPSHWSetMmioFuncs(pScrn, cPtr->MMIOBaseVGA, 0x0); } if (cPtr->Flags & ChipsDualChannelSupport) { cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex)->ptr; DUALOPEN; } #if defined(__arm32__) && defined(__NetBSD__) if (strcmp(pScrn->currentMode->name,"PAL") == 0) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using built-in PAL TV mode\n"); cPtr->TVMode = XMODE_PAL; } else if (strcmp(pScrn->currentMode->name,"SECAM") == 0){ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using built-in SECAM TV mode\n"); cPtr->TVMode = XMODE_SECAM; } else if (strcmp(pScrn->currentMode->name,"NTSC") == 0) { xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using built-in NTSC TV mode\n"); cPtr->TVMode = XMODE_NTSC; } else cPtr->TVMode = XMODE_RGB; #endif /* * next we save the current state and setup the first mode */ if ((cPtr->Flags & ChipsDualChannelSupport) && (! xf86IsEntityShared(pScrn->entityList[0]))) { unsigned int IOSS, MSS; IOSS = cPtr->readIOSS(cPtr); MSS = cPtr->readMSS(cPtr); cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | IOSS_PIPE_A)); cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_A)); chipsSave(pScrn, &hwp->SavedReg, &cPtr->SavedReg); cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | IOSS_PIPE_B)); cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B)); chipsSave(pScrn, &cPtr->VgaSavedReg2, &cPtr->SavedReg2); cPtr->writeIOSS(cPtr, IOSS); cPtr->writeMSS(cPtr, hwp, MSS); } else chipsSave(pScrn, &hwp->SavedReg, &cPtr->SavedReg); if (!chipsModeInit(pScrn,pScrn->currentMode)) return FALSE; CHIPSSaveScreen(pScreen,SCREEN_SAVER_ON); CHIPSAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0)); /* * The next step is to setup the screen's visuals, and initialise the * framebuffer code. In cases where the framebuffer's default * choices for things like visual layouts and bits per RGB are OK, * this may be as simple as calling the framebuffer's ScreenInit() * function. If not, the visuals will need to be setup before calling * a fb ScreenInit() function and fixed up after. * * For most PC hardware at depths >= 8, the defaults that cfb uses * are not appropriate. In this driver, we fixup the visuals after. */ /* * Reset visual list. */ miClearVisualTypes(); /* Setup the visuals we support. */ if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth), pScrn->rgbBits, pScrn->defaultVisual)) return FALSE; miSetPixmapDepths (); /* * Call the framebuffer layer's ScreenInit function, and fill in other * pScreen fields. */ if ((cPtr->Flags & ChipsShadowFB) && cPtr->Rotate) { height = pScrn->virtualX; width = pScrn->virtualY; } else { width = pScrn->virtualX; height = pScrn->virtualY; } if(cPtr->Flags & ChipsShadowFB) { cPtr->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); cPtr->ShadowPtr = malloc(cPtr->ShadowPitch * height); displayWidth = cPtr->ShadowPitch / (pScrn->bitsPerPixel >> 3); FBStart = cPtr->ShadowPtr; } else { cPtr->ShadowPtr = NULL; displayWidth = pScrn->displayWidth; FBStart = cPtr->FbBase; } switch (pScrn->bitsPerPixel) { #ifdef HAVE_XF1BPP case 1: ret = xf1bppScreenInit(pScreen, FBStart, width,height, pScrn->xDpi, pScrn->yDpi, displayWidth); break; #endif #ifdef HAVE_XF4BPP case 4: ret = xf4bppScreenInit(pScreen, FBStart, width,height, pScrn->xDpi, pScrn->yDpi, displayWidth); break; #endif case 16: default: ret = fbScreenInit(pScreen, FBStart, width,height, pScrn->xDpi, pScrn->yDpi, displayWidth,pScrn->bitsPerPixel); init_picture = 1; break; } if (!ret) return FALSE; #if X_BYTE_ORDER == X_BIG_ENDIAN /* TODO : find a better way to do this */ if (pScrn->depth == 24) { int dummy ; /* Fixup RGB ordering in 24 BPP */ dummy = pScrn->offset.red ; pScrn->offset.red = pScrn->offset.blue; pScrn->offset.blue = dummy ; dummy = pScrn->mask.red ; pScrn->mask.red = pScrn->mask.blue; pScrn->mask.blue = dummy ; } #endif if (pScrn->depth > 8) { /* Fixup RGB ordering */ visual = pScreen->visuals + pScreen->numVisuals; while (--visual >= pScreen->visuals) { if ((visual->class | DynamicClass) == DirectColor) { visual->offsetRed = pScrn->offset.red; visual->offsetGreen = pScrn->offset.green; visual->offsetBlue = pScrn->offset.blue; visual->redMask = pScrn->mask.red; visual->greenMask = pScrn->mask.green; visual->blueMask = pScrn->mask.blue; } } } /* must be after RGB ordering fixed */ if (init_picture) fbPictureInit (pScreen, 0, 0); xf86SetBlackWhitePixels(pScreen); cPtr->BlockHandler = pScreen->BlockHandler; pScreen->BlockHandler = chipsBlockHandler; if ( (pScrn->depth >= 8)) CHIPSDGAInit(pScreen); cPtr->HWCursorShown = FALSE; #ifdef HAVE_ISA if (!(cPtr->Flags & ChipsLinearSupport)) { miBankInfoPtr pBankInfo; /* Setup the vga banking variables */ pBankInfo = (miBankInfoPtr)xnfcalloc(sizeof(miBankInfoRec),1); if (pBankInfo == NULL) return FALSE; #if defined(__arm32__) cPtr->Bank = -1; #endif pBankInfo->pBankA = hwp->Base; pBankInfo->pBankB = (unsigned char *)hwp->Base + 0x08000; pBankInfo->BankSize = 0x08000; pBankInfo->nBankDepth = (pScrn->depth == 4) ? 1 : pScrn->depth; if (IS_HiQV(cPtr)) { pBankInfo->pBankB = hwp->Base; pBankInfo->BankSize = 0x10000; if (pScrn->bitsPerPixel < 8) { pBankInfo->SetSourceBank = (miBankProcPtr)CHIPSHiQVSetReadWritePlanar; pBankInfo->SetDestinationBank = (miBankProcPtr)CHIPSHiQVSetReadWritePlanar; pBankInfo->SetSourceAndDestinationBanks = (miBankProcPtr)CHIPSHiQVSetReadWritePlanar; } else { pBankInfo->SetSourceBank = (miBankProcPtr)CHIPSHiQVSetReadWrite; pBankInfo->SetDestinationBank = (miBankProcPtr)CHIPSHiQVSetReadWrite; pBankInfo->SetSourceAndDestinationBanks = (miBankProcPtr)CHIPSHiQVSetReadWrite; } } else { if (IS_Wingine(cPtr)) { if (pScrn->bitsPerPixel < 8) { pBankInfo->SetSourceBank = (miBankProcPtr)CHIPSWINSetReadPlanar; pBankInfo->SetDestinationBank = (miBankProcPtr)CHIPSWINSetWritePlanar; pBankInfo->SetSourceAndDestinationBanks = (miBankProcPtr)CHIPSWINSetReadWritePlanar; } else { pBankInfo->SetSourceBank = (miBankProcPtr)CHIPSWINSetRead; pBankInfo->SetDestinationBank = (miBankProcPtr)CHIPSWINSetWrite; pBankInfo->SetSourceAndDestinationBanks = (miBankProcPtr)CHIPSWINSetReadWrite; } } else { if (pScrn->bitsPerPixel < 8) { pBankInfo->SetSourceBank = (miBankProcPtr)CHIPSSetReadPlanar; pBankInfo->SetDestinationBank = (miBankProcPtr)CHIPSSetWritePlanar; pBankInfo->SetSourceAndDestinationBanks = (miBankProcPtr)CHIPSSetReadWritePlanar; } else { pBankInfo->SetSourceBank = (miBankProcPtr)CHIPSSetRead; pBankInfo->SetDestinationBank = (miBankProcPtr)CHIPSSetWrite; pBankInfo->SetSourceAndDestinationBanks = (miBankProcPtr)CHIPSSetReadWrite; } } } if (!miInitializeBanking(pScreen, pScrn->virtualX, pScrn->virtualY, pScrn->displayWidth, pBankInfo)) { free(pBankInfo); pBankInfo = NULL; return FALSE; } xf86SetBackingStore(pScreen); /* Initialise cursor functions */ miDCInitialize (pScreen, xf86GetPointerScreenFuncs()); } else #endif /* HAVE_ISA */ { /* !!! Only support linear addressing for now. This might change */ /* Setup pointers to free space in video ram */ #define CHIPSALIGN(size, align) (currentaddr - ((currentaddr - size) & ~align)) allocatebase = (pScrn->videoRam<<10) - cPtr->FrameBufferSize; if (pScrn->bitsPerPixel < 8) freespace = allocatebase - pScrn->displayWidth * pScrn->virtualY / 2; else freespace = allocatebase - pScrn->displayWidth * pScrn->virtualY * (pScrn->bitsPerPixel >> 3); if ((cPtr->Flags & ChipsDualChannelSupport) && (cPtr->SecondCrtc == TRUE)) { currentaddr = allocatebase + cPtrEnt->masterFbMapSize; } else currentaddr = allocatebase; if (serverGeneration == 1) xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "%d bytes off-screen memory available\n", freespace); /* * Allocate video memory to store the hardware cursor. Allocate 1kB * vram to the cursor, with 1kB alignment for 6554x's and 4kb alignment * for 65550's. Wingine cursor is stored in registers and so no memory * is needed. */ if (cAcl->UseHWCursor) { cAcl->CursorAddress = -1; if (IS_HiQV(cPtr)) { if (CHIPSALIGN(1024, 0xFFF) <= freespace) { currentaddr -= CHIPSALIGN(1024, 0xFFF); freespace -= CHIPSALIGN(1024, 0xFFF); cAcl->CursorAddress = currentaddr; } } else if (IS_Wingine(cPtr)) { cAcl->CursorAddress = 0; } else if (CHIPSALIGN(1024, 0x3FF) <= freespace) { currentaddr -= CHIPSALIGN(1024, 0x3FF); freespace -= CHIPSALIGN(1024, 0x3FF); cAcl->CursorAddress = currentaddr; } if (cAcl->CursorAddress == -1) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Too little space for H/W cursor.\n"); } cAcl->CacheEnd = currentaddr; /* Setup the acceleration primitives */ /* Calculate space needed of offscreen pixmaps etc. */ if (cPtr->Flags & ChipsAccelSupport) { /* * A scratch area is now allocated in the video ram. This is used * at 8 and 16 bpp to simulate a planemask with a complex ROP, and * at 24 and 32 bpp to aid in accelerating solid fills */ cAcl->ScratchAddress = -1; switch (pScrn->bitsPerPixel) { case 8: if (CHIPSALIGN(64, 0x3F) <= freespace) { currentaddr -= CHIPSALIGN(64, 0x3F); freespace -= CHIPSALIGN(64, 0x3F); cAcl->ScratchAddress = currentaddr; } break; case 16: if (CHIPSALIGN(128, 0x7F) <= freespace) { currentaddr -= CHIPSALIGN(128, 0x7F); freespace -= CHIPSALIGN(128, 0x7F); cAcl->ScratchAddress = currentaddr; } break; case 24: /* One scanline of data used for solid fill */ if (!IS_HiQV(cPtr)) { if (CHIPSALIGN(3 * (pScrn->displayWidth + 4), 0x3) <= freespace) { currentaddr -= CHIPSALIGN(3 * (pScrn->displayWidth + 4), 0x3); freespace -= CHIPSALIGN(3 * (pScrn->displayWidth + 4), 0x3); cAcl->ScratchAddress = currentaddr; } } break; case 32: /* 16bpp 8x8 mono pattern fill for solid fill. QWORD aligned */ if (IS_HiQV(cPtr)) { if (CHIPSALIGN(8, 0x7) <= freespace) { currentaddr -= CHIPSALIGN(8, 0x7); freespace -= CHIPSALIGN(8, 0x7); cAcl->ScratchAddress = currentaddr; } } break; } /* Setup the boundaries of the pixmap cache */ cAcl->CacheStart = currentaddr - freespace; cAcl->CacheEnd = currentaddr; if (cAcl->CacheStart >= cAcl->CacheEnd) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Too little space for pixmap cache.\n"); cAcl->CacheStart = 0; cAcl->CacheEnd = 0; } if (IS_HiQV(cPtr)) cAcl->BltDataWindow = (unsigned char *)cPtr->MMIOBase + 0x10000L; else cAcl->BltDataWindow = cPtr->FbBase; } /* * Initialize FBManager: * we do even with no acceleration enabled * so that video support can allocate space. */ { BoxRec AvailFBArea; AvailFBArea.x1 = 0; AvailFBArea.y1 = 0; AvailFBArea.x2 = pScrn->displayWidth; AvailFBArea.y2 = cAcl->CacheEnd / (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3)); xf86InitFBManager(pScreen, &AvailFBArea); } if (cPtr->Flags & ChipsAccelSupport) { if (IS_HiQV(cPtr)) { CHIPSHiQVAccelInit(pScreen); } else if (cPtr->UseMMIO) { CHIPSMMIOAccelInit(pScreen); } else { CHIPSAccelInit(pScreen); } } xf86SetBackingStore(pScreen); #ifdef ENABLE_SILKEN_MOUSE xf86SetSilkenMouse(pScreen); #endif /* Initialise cursor functions */ miDCInitialize (pScreen, xf86GetPointerScreenFuncs()); if ((cAcl->UseHWCursor) && (cAcl->CursorAddress != -1)) { /* HW cursor functions */ if (!CHIPSCursorInit(pScreen)) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Hardware cursor initialization failed\n"); return FALSE; } } } if (cPtr->Flags & ChipsShadowFB) { RefreshAreaFuncPtr refreshArea = chipsRefreshArea; if(cPtr->Rotate) { if (!cPtr->PointerMoved) { cPtr->PointerMoved = pScrn->PointerMoved; pScrn->PointerMoved = chipsPointerMoved; } switch(pScrn->bitsPerPixel) { case 8: refreshArea = chipsRefreshArea8; break; case 16: refreshArea = chipsRefreshArea16; break; case 24: refreshArea = chipsRefreshArea24; break; case 32: refreshArea = chipsRefreshArea32; break; } } ShadowFBInit(pScreen, refreshArea); } /* Initialise default colourmap */ if (!miCreateDefColormap(pScreen)) return FALSE; if(!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, (pScrn->depth == 16 ? chipsLoadPalette16 : chipsLoadPalette), NULL, CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR)) return FALSE; #ifndef XSERVER_LIBPCIACCESS racflag = RAC_COLORMAP; if (cAcl->UseHWCursor) racflag |= RAC_CURSOR; racflag |= (RAC_FB | RAC_VIEWPORT); /* XXX Check if I/O and Mem flags need to be the same. */ pScrn->racIoFlags = pScrn->racMemFlags = racflag; #endif #ifdef ENABLE_SILKEN_MOUSE xf86SetSilkenMouse(pScreen); #endif if ((cPtr->Flags & ChipsVideoSupport) && (cPtr->Flags & ChipsLinearSupport)) { CHIPSInitVideo(pScreen); } pScreen->SaveScreen = CHIPSSaveScreen; /* Setup DPMS mode */ if (cPtr->Flags & ChipsDPMSSupport) xf86DPMSInit(pScreen, (DPMSSetProcPtr)chipsDisplayPowerManagementSet, 0); /* Wrap the current CloseScreen function */ cPtr->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = CHIPSCloseScreen; /* Report any unused options (only for the first generation) */ if (serverGeneration == 1) { xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); } return TRUE; } /* Mandatory */ Bool CHIPSSwitchMode(SWITCH_MODE_ARGS_DECL) { SCRN_INFO_PTR(arg); CHIPSPtr cPtr = CHIPSPTR(pScrn); CHIPSEntPtr cPtrEnt; #ifdef DEBUG ErrorF("CHIPSSwitchMode\n"); #endif if (cPtr->UseDualChannel) { cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex)->ptr; DUALREOPEN; } return chipsModeInit(pScrn, mode); } /* Mandatory */ void CHIPSAdjustFrame(ADJUST_FRAME_ARGS_DECL) { SCRN_INFO_PTR(arg); CHIPSPtr cPtr = CHIPSPTR(pScrn); CHIPSEntPtr cPtrEnt; int Base; vgaHWPtr hwp = VGAHWPTR(pScrn); unsigned char tmp; if (xf86ReturnOptValBool(cPtr->Options, OPTION_SHOWCACHE, FALSE) && y) { int lastline = cPtr->FbMapSize / ((pScrn->displayWidth * pScrn->bitsPerPixel) / 8); lastline -= pScrn->currentMode->VDisplay; y += pScrn->virtualY - 1; if (y > lastline) y = lastline; } Base = y * pScrn->displayWidth + x; /* calculate base bpp dep. */ switch (pScrn->bitsPerPixel) { case 1: case 4: Base >>= 3; break; case 16: Base >>= 1; break; case 24: if (!IS_HiQV(cPtr)) Base = (Base >> 2) * 3; else Base = (Base >> 3) * 6; /* 65550 seems to need 64bit alignment */ break; case 32: break; default: /* 8bpp */ Base >>= 2; break; } if (cPtr->UseDualChannel) { cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex)->ptr; DUALREOPEN; } /* write base to chip */ /* * These are the generic starting address registers. */ chipsFixResume(pScrn); hwp->writeCrtc(hwp, 0x0C, (Base & 0xFF00) >> 8); hwp->writeCrtc(hwp, 0x0D, Base & 0xFF); if (IS_HiQV(cPtr)) { if (((cPtr->readXR(cPtr, 0x09)) & 0x1) == 0x1) hwp->writeCrtc(hwp, 0x40, ((Base & 0x0F0000) >> 16) | 0x80); } else { tmp = cPtr->readXR(cPtr, 0x0C); cPtr->writeXR(cPtr, 0x0C, ((Base & (IS_Wingine(cPtr) ? 0x0F0000 : 0x030000)) >> 16) | (tmp & 0xF8)); } if (cPtr->UseDualChannel && (! xf86IsEntityShared(pScrn->entityList[0]))) { unsigned int IOSS, MSS; IOSS = cPtr->readIOSS(cPtr); MSS = cPtr->readMSS(cPtr); cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | IOSS_PIPE_B)); cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B)); chipsFixResume(pScrn); hwp->writeCrtc(hwp, 0x0C, (Base & 0xFF00) >> 8); hwp->writeCrtc(hwp, 0x0D, Base & 0xFF); if (((cPtr->readXR(cPtr, 0x09)) & 0x1) == 0x1) hwp->writeCrtc(hwp, 0x40, ((Base & 0x0F0000) >> 16) | 0x80); cPtr->writeIOSS(cPtr, IOSS); cPtr->writeMSS(cPtr, hwp, MSS); } } /* Mandatory */ static Bool CHIPSCloseScreen(CLOSE_SCREEN_ARGS_DECL) { ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); CHIPSPtr cPtr = CHIPSPTR(pScrn); CHIPSEntPtr cPtrEnt; if(pScrn->vtSema){ /*§§§*/ if (cPtr->Flags & ChipsDualChannelSupport) { cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex)->ptr; if (cPtr->UseDualChannel) DUALREOPEN; DUALCLOSE; } else { chipsHWCursorOff(cPtr, pScrn); chipsRestore(pScrn, &(VGAHWPTR(pScrn))->SavedReg, &cPtr->SavedReg, TRUE); chipsLock(pScrn); } chipsUnmapMem(pScrn); } if (xf86IsEntityShared(pScrn->entityList[0])) { DevUnion *pPriv; pPriv = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex); cPtrEnt = pPriv->ptr; cPtrEnt->refCount--; } #ifdef HAVE_XAA_H if (cPtr->AccelInfoRec) XAADestroyInfoRec(cPtr->AccelInfoRec); #endif if (cPtr->CursorInfoRec) xf86DestroyCursorInfoRec(cPtr->CursorInfoRec); free(cPtr->ShadowPtr); free(cPtr->DGAModes); pScrn->vtSema = FALSE; if(cPtr->BlockHandler) pScreen->BlockHandler = cPtr->BlockHandler; pScreen->CloseScreen = cPtr->CloseScreen; /*§§§*/ xf86ClearPrimInitDone(pScrn->entityList[0]); return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);/*§§§*/ } /* Optional */ static void CHIPSFreeScreen(FREE_SCREEN_ARGS_DECL) { SCRN_INFO_PTR(arg); if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) vgaHWFreeHWRec(pScrn); CHIPSFreeRec(pScrn); } /* Optional */ static ModeStatus CHIPSValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) { SCRN_INFO_PTR(arg); CHIPSPtr cPtr = CHIPSPTR(pScrn); /* The tests here need to be expanded */ if ((mode->Flags & V_INTERLACE) && (cPtr->PanelType & ChipsLCD)) return MODE_NO_INTERLACE; if ((cPtr->PanelType & ChipsLCD) && !xf86ReturnOptValBool(cPtr->Options, OPTION_PANEL_SIZE, FALSE) && ((cPtr->PanelSize.HDisplay < mode->HDisplay) || (cPtr->PanelSize.VDisplay < mode->VDisplay))) return MODE_PANEL; return MODE_OK; } /* * DPMS Control registers * * XR73 6554x and 64300 (what about 65535?) * XR61 6555x * 0 HSync Powerdown data * 1 HSync Select 1=Powerdown * 2 VSync Powerdown data * 3 VSync Select 1=Powerdown */ static void chipsDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags) { vgaHWPtr hwp = VGAHWPTR(pScrn); CHIPSPtr cPtr = CHIPSPTR(pScrn); CHIPSEntPtr cPtrEnt; unsigned char dpmsreg, seqreg, lcdoff, tmp; if (!pScrn->vtSema) return; #if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 8 xf86EnableAccess(pScrn); #endif switch (PowerManagementMode) { case DPMSModeOn: /* Screen: On; HSync: On, VSync: On */ dpmsreg = 0x00; seqreg = 0x00; lcdoff = 0x0; break; case DPMSModeStandby: /* Screen: Off; HSync: Off, VSync: On */ dpmsreg = 0x02; seqreg = 0x20; lcdoff = 0x0; break; case DPMSModeSuspend: /* Screen: Off; HSync: On, VSync: Off */ dpmsreg = 0x08; seqreg = 0x20; lcdoff = 0x1; break; case DPMSModeOff: /* Screen: Off; HSync: Off, VSync: Off */ dpmsreg = 0x0A; seqreg = 0x20; lcdoff = 0x1; break; default: return; } if (cPtr->UseDualChannel) { cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex)->ptr; DUALREOPEN; } seqreg |= hwp->readSeq(hwp, 0x01) & ~0x20; hwp->writeSeq(hwp, 0x01, seqreg); if (IS_HiQV(cPtr)) { tmp = cPtr->readXR(cPtr, 0x61); cPtr->writeXR(cPtr, 0x61, (tmp & 0xF0) | dpmsreg); } else { tmp = cPtr->readXR(cPtr, 0x73); cPtr->writeXR(cPtr, 0x73, (tmp & 0xF0) | dpmsreg); } /* Turn off the flat panel */ if (cPtr->PanelType & ChipsLCDProbed) { if (IS_HiQV(cPtr)) { if (cPtr->Chipset == CHIPS_CT69030) { #if 0 /* Where is this for the 69030?? */ tmp = cPtr->readFR(cPtr, 0x05); if (lcdoff) cPtr->writeFR(cPtr, 0x05, tmp | 0x08); else cPtr->writeFR(cPtr, 0x05, tmp & 0xF7); #endif } else { tmp = cPtr->readFR(cPtr, 0x05); if (lcdoff) cPtr->writeFR(cPtr, 0x05, tmp | 0x08); else cPtr->writeFR(cPtr, 0x05, tmp & 0xF7); } } else { tmp = cPtr->readXR(cPtr, 0x52); if (lcdoff) cPtr->writeXR(cPtr, 0x52, tmp | 0x08); else cPtr->writeXR(cPtr, 0x52, tmp & 0xF7); } } } static Bool CHIPSSaveScreen(ScreenPtr pScreen, int mode) { ScrnInfoPtr pScrn = NULL; /* §§§ */ Bool unblank; unblank = xf86IsUnblank(mode); if (pScreen != NULL) pScrn = xf86ScreenToScrn(pScreen); if (unblank) SetTimeSinceLastInputEvent(); if ((pScrn != NULL) && pScrn->vtSema) { /* §§§ */ chipsBlankScreen(pScrn, unblank); } return (TRUE); } static Bool chipsClockSelect(ScrnInfoPtr pScrn, int no) { CHIPSClockReg TmpClock; CHIPSPtr cPtr = CHIPSPTR(pScrn); switch (no) { case CLK_REG_SAVE: chipsClockSave(pScrn, &cPtr->SaveClock); break; case CLK_REG_RESTORE: chipsClockLoad(pScrn, &cPtr->SaveClock); break; default: if (!chipsClockFind(pScrn, NULL, no, &TmpClock)) return (FALSE); chipsClockLoad(pScrn, &TmpClock); } return (TRUE); } /* * * Fout = (Fref * 4 * M) / (PSN * N * (1 << P) ) * Fvco = (Fref * 4 * M) / (PSN * N) * where * M = XR31+2 * N = XR32+2 * P = XR30[3:1] * PSN = XR30[0]? 1:4 * * constraints: * 4 MHz <= Fref <= 20 MHz (typ. 14.31818 MHz) * 150 kHz <= Fref/(PSN * N) <= 2 MHz * 48 MHz <= Fvco <= 220 MHz * 2 < M < 128 * 2 < N < 128 */ static void chipsClockSave(ScrnInfoPtr pScrn, CHIPSClockPtr Clock) { unsigned char tmp; vgaHWPtr hwp = VGAHWPTR(pScrn); CHIPSPtr cPtr = CHIPSPTR(pScrn); unsigned char Type = cPtr->ClockType; CHIPSEntPtr cPtrEnt; Clock->msr = hwp->readMiscOut(hwp)&0xFE; /* save standard VGA clock reg */ switch (Type & GET_STYLE) { case HiQV_STYLE: /* save alternate clock select reg.*/ /* The 69030 FP clock select is at FR01 instead */ if (cPtr->UseDualChannel) { cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex)->ptr; DUALREOPEN; } if (cPtr->Flags & ChipsDualChannelSupport) Clock->fr03 = cPtr->readFR(cPtr, 0x01); else Clock->fr03 = cPtr->readFR(cPtr, 0x03); if (!Clock->Clock) { /* save HiQV console clock */ tmp = cPtr->CRTclkInx << 2; cPtr->CRTClk[0] = cPtr->readXR(cPtr, 0xC0 + tmp); cPtr->CRTClk[1] = cPtr->readXR(cPtr, 0xC1 + tmp); cPtr->CRTClk[2] = cPtr->readXR(cPtr, 0xC2 + tmp); cPtr->CRTClk[3] = cPtr->readXR(cPtr, 0xC3 + tmp); tmp = cPtr->FPclkInx << 2; cPtr->FPClk[0] = cPtr->readXR(cPtr, 0xC0 + tmp); cPtr->FPClk[1] = cPtr->readXR(cPtr, 0xC1 + tmp); cPtr->FPClk[2] = cPtr->readXR(cPtr, 0xC2 + tmp); cPtr->FPClk[3] = cPtr->readXR(cPtr, 0xC3 + tmp); } break; case OLD_STYLE: Clock->fcr = hwp->readFCR(hwp); Clock->xr02 = cPtr->readXR(cPtr, 0x02); Clock->xr54 = cPtr->readXR(cPtr, 0x54); /* save alternate clock select reg.*/ break; case WINGINE_1_STYLE: case WINGINE_2_STYLE: break; case NEW_STYLE: Clock->xr54 = cPtr->readXR(cPtr, 0x54); /* save alternate clock select reg.*/ Clock->xr33 = cPtr->readXR(cPtr, 0x33); /* get status of MCLK/VCLK sel reg.*/ break; } #ifdef DEBUG ErrorF("saved \n"); #endif } static Bool chipsClockFind(ScrnInfoPtr pScrn, DisplayModePtr mode, int no, CHIPSClockPtr Clock ) { vgaHWPtr hwp = VGAHWPTR(pScrn); CHIPSPtr cPtr = CHIPSPTR(pScrn); unsigned char Type = cPtr->ClockType; CHIPSEntPtr cPtrEnt; if (no > (pScrn->numClocks - 1)) return (FALSE); if (cPtr->UseDualChannel) { cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex)->ptr; DUALREOPEN; } switch (Type & GET_STYLE) { case HiQV_STYLE: Clock->msr = cPtr->CRTclkInx << 2; Clock->fr03 = cPtr->FPclkInx << 2; Clock->Clock = mode ? mode->Clock : 0; if (xf86ReturnOptValBool(cPtr->Options, OPTION_USE_MODELINE, FALSE)) { Clock->FPClock = mode ? mode->Clock : 0; } else Clock->FPClock = cPtr->FPclock; break; case NEW_STYLE: if (Type & TYPE_HW) { Clock->msr = (no == 4 ? 3 << 2: (no & 0x01) << 2); Clock->xr54 = Clock->msr; Clock->xr33 = no > 1 ? 0x80 : 0; } else { Clock->msr = 3 << 2; Clock->xr33 = 0; Clock->xr54 = Clock->msr; /* update panel type in case somebody switched. * This should be handled more generally: * On mode switch DDC should be reread, all * display dependent data should be reevaluated. * This will be built in when we start Display * HotPlug support. * Until then we have to do it here as somebody * might have switched displays on us and we only * have one programmable clock which needs to * be shared for CRT and LCD. */ chipsSetPanelType(cPtr); { Bool fp_m; if (cPtr->Options && xf86GetOptValBool(cPtr->Options, OPTION_FP_MODE, &fp_m)) { if (fp_m) cPtr->PanelType |= ChipsLCD; else cPtr->PanelType = ~ChipsLCD; } } if ((cPtr->PanelType & ChipsLCD) && cPtr->FPclock) Clock->Clock = cPtr->FPclock; else Clock->Clock = mode ? mode->SynthClock : 0; } break; case OLD_STYLE: if (no > 3) { Clock->msr = 3 << 2; Clock->fcr = no & 0x03; Clock->xr02 = 0; Clock->xr54 = Clock->msr & (Clock->fcr << 4); } else { Clock->msr = (no << 2) & 0x4; Clock->fcr = 0; Clock->xr02 = no & 0x02; Clock->xr54 = Clock->msr; } break; case WINGINE_1_STYLE: Clock->msr = no << 2; case WINGINE_2_STYLE: if (Type & TYPE_HW) { Clock->msr = (no == 2 ? 3 << 2: (no & 0x01) << 2); Clock->xr33 = 0; } else { Clock->msr = 3 << 2; Clock->xr33 = 0; Clock->Clock = mode ? mode->SynthClock : 0; } break; } Clock->msr |= (hwp->readMiscOut(hwp) & 0xF2); #ifdef DEBUG ErrorF("found\n"); #endif return (TRUE); } static int chipsGetHWClock(ScrnInfoPtr pScrn) { vgaHWPtr hwp = VGAHWPTR(pScrn); CHIPSPtr cPtr = CHIPSPTR(pScrn); unsigned char Type = cPtr->ClockType; unsigned char tmp, tmp1; if (!(Type & TYPE_HW)) return 0; /* shouldn't happen */ switch (Type & GET_STYLE) { case WINGINE_1_STYLE: return ((hwp->readMiscOut(hwp) & 0x0C) >> 2); case WINGINE_2_STYLE: tmp = ((hwp->readMiscOut(hwp) & 0x04) >> 2); return (tmp > 2) ? 2 : tmp; case OLD_STYLE: if (!(cPtr->PanelType & ChipsLCDProbed)) tmp = hwp->readMiscOut(hwp); else tmp = cPtr->readXR(cPtr, 0x54); if (tmp & 0x08) { if (!(cPtr->PanelType & ChipsLCDProbed)) tmp = hwp->readFCR(hwp) & 0x03; else tmp = (tmp >> 4) & 0x03; return (tmp + 4); } else { tmp = (tmp >> 2) & 0x01; tmp1 = cPtr->readXR(cPtr, 0x02); return (tmp + (tmp1 & 0x02)); } case NEW_STYLE: if (cPtr->PanelType & ChipsLCDProbed) { tmp = cPtr->readXR(cPtr, 0x54); } else tmp = hwp->readMiscOut(hwp); tmp = (tmp & 0x0C) >> 2; if (tmp > 1) return 4; tmp1 = cPtr->readXR(cPtr, 0x33); tmp1 = (tmp1 & 0x80) >> 6; /* iso mode 25.175/28.322 or 32/36 MHz */ return (tmp + tmp1); /* ^=0 ^=1 ^=4 ^=5 */ default: /* we should never get here */ return (0); } } static void chipsClockLoad(ScrnInfoPtr pScrn, CHIPSClockPtr Clock) { vgaHWPtr hwp = VGAHWPTR(pScrn); CHIPSPtr cPtr = CHIPSPTR(pScrn); unsigned char Type = cPtr->ClockType; volatile unsigned char tmp, tmpmsr, tmpfcr, tmp02; volatile unsigned char tmp33, tmp54, tmpf03; unsigned char vclk[3]; tmpmsr = hwp->readMiscOut(hwp); /* read msr, needed for all styles */ switch (Type & GET_STYLE) { case HiQV_STYLE: /* save alternate clock select reg. */ /* The 69030 FP clock select is at FR01 instead */ if (cPtr->Flags & ChipsDualChannelSupport) { tmpf03 = cPtr->readFR(cPtr, 0x01); } else tmpf03 = cPtr->readFR(cPtr, 0x03); /* select fixed clock 0 before tampering with VCLK select */ hwp->writeMiscOut(hwp, (tmpmsr & ~0x0D) | cPtr->SuspendHack.vgaIOBaseFlag); /* The 69030 FP clock select is at FR01 instead */ if (cPtr->Flags & ChipsDualChannelSupport) { cPtr->writeFR(cPtr, 0x01, (tmpf03 & ~0x0C) | 0x04); } else cPtr->writeFR(cPtr, 0x03, (tmpf03 & ~0x0C) | 0x04); if (!Clock->Clock) { /* Hack to load saved console clock */ tmp = cPtr->CRTclkInx << 2; cPtr->writeXR(cPtr, 0xC0 + tmp, (cPtr->CRTClk[0] & 0xFF)); cPtr->writeXR(cPtr, 0xC1 + tmp, (cPtr->CRTClk[1] & 0xFF)); cPtr->writeXR(cPtr, 0xC2 + tmp, (cPtr->CRTClk[2] & 0xFF)); cPtr->writeXR(cPtr, 0xC3 + tmp, (cPtr->CRTClk[3] & 0xFF)); if (cPtr->FPClkModified) { usleep(10000); /* let VCO stabilize */ tmp = cPtr->FPclkInx << 2; cPtr->writeXR(cPtr, 0xC0 + tmp, (cPtr->FPClk[0] & 0xFF)); cPtr->writeXR(cPtr, 0xC1 + tmp, (cPtr->FPClk[1] & 0xFF)); cPtr->writeXR(cPtr, 0xC2 + tmp, (cPtr->FPClk[2] & 0xFF)); cPtr->writeXR(cPtr, 0xC3 + tmp, (cPtr->FPClk[3] & 0xFF)); } } else { /* * Don't use the extra 2 bits in the M, N registers available * on the HiQV, so write zero to 0xCA */ chipsCalcClock(pScrn, Clock->Clock, vclk); tmp = cPtr->CRTclkInx << 2; cPtr->writeXR(cPtr, 0xC0 + tmp, (vclk[1] & 0xFF)); cPtr->writeXR(cPtr, 0xC1 + tmp, (vclk[2] & 0xFF)); cPtr->writeXR(cPtr, 0xC2 + tmp, 0x0); cPtr->writeXR(cPtr, 0xC3 + tmp, (vclk[0] & 0xFF)); if (Clock->FPClock) { usleep(10000); /* let VCO stabilize */ chipsCalcClock(pScrn, Clock->FPClock, vclk); tmp = cPtr->FPclkInx << 2; cPtr->writeXR(cPtr, 0xC0 + tmp, (vclk[1] & 0xFF)); cPtr->writeXR(cPtr, 0xC1 + tmp, (vclk[2] & 0xFF)); cPtr->writeXR(cPtr, 0xC2 + tmp, 0x0); cPtr->writeXR(cPtr, 0xC3 + tmp, (vclk[0] & 0xFF)); cPtr->FPClkModified = TRUE; } } usleep(10000); /* Let VCO stabilise */ /* The 69030 FP clock select is at FR01 instead */ if (cPtr->Flags & ChipsDualChannelSupport) { cPtr->writeFR(cPtr, 0x01, ((tmpf03 & ~0x0C) | (Clock->fr03 & 0x0C))); } else cPtr->writeFR(cPtr, 0x03, ((tmpf03 & ~0x0C) | (Clock->fr03 & 0x0C))); break; case WINGINE_1_STYLE: break; case WINGINE_2_STYLE: /* Only write to soft clock registers if we really need to */ if ((Type & GET_TYPE) == TYPE_PROGRAMMABLE) { /* select fixed clock 0 before tampering with VCLK select */ hwp->writeMiscOut(hwp, (tmpmsr & ~0x0D) | cPtr->SuspendHack.vgaIOBaseFlag); chipsCalcClock(pScrn, Clock->Clock, vclk); tmp33 = cPtr->readXR(cPtr, 0x33); /* get status of MCLK/VCLK select reg */ cPtr->writeXR(cPtr, 0x33, tmp33 & ~0x20); cPtr->writeXR(cPtr, 0x30, vclk[0]); cPtr->writeXR(cPtr, 0x31, vclk[1]); /* restore VCLK regs. */ cPtr->writeXR(cPtr, 0x32, vclk[2]); /* cPtr->writeXR(cPtr, 0x33, tmp33 & ~0x20);*/ usleep(10000); /* Let VCO stabilise */ } break; case OLD_STYLE: tmp02 = cPtr->readXR(cPtr, 0x02); tmp54 = cPtr->readXR(cPtr, 0x54); tmpfcr = hwp->readFCR(hwp); cPtr->writeXR(cPtr, 0x02, ((tmp02 & ~0x02) | (Clock->xr02 & 0x02))); cPtr->writeXR(cPtr, 0x54, ((tmp54 & 0xF0) | (Clock->xr54 & ~0xF0))); hwp->writeFCR(hwp, (tmpfcr & ~0x03) & Clock->fcr); break; case NEW_STYLE: tmp33 = cPtr->readXR(cPtr, 0x33); /* get status of MCLK/VCLK select reg */ tmp54 = cPtr->readXR(cPtr, 0x54); /* Only write to soft clock registers if we really need to */ if ((Type & GET_TYPE) == TYPE_PROGRAMMABLE) { /* select fixed clock 0 before tampering with VCLK select */ hwp->writeMiscOut(hwp, (tmpmsr & ~0x0D) | cPtr->SuspendHack.vgaIOBaseFlag); cPtr->writeXR(cPtr, 0x54, (tmp54 & 0xF3)); /* if user wants to set the memory clock, do it first */ if (cPtr->MemClock.Clk) { chipsCalcClock(pScrn, cPtr->MemClock.Clk, vclk); /* close eyes, hold breath ....*/ cPtr->writeXR(cPtr, 0x33, tmp33 | 0x20); cPtr->writeXR(cPtr, 0x30, vclk[0]); cPtr->writeXR(cPtr, 0x31, vclk[1]); cPtr->writeXR(cPtr, 0x32, vclk[2]); usleep(10000); } chipsCalcClock(pScrn, Clock->Clock, vclk); cPtr->writeXR(cPtr, 0x33, tmp33 & ~0x20); cPtr->writeXR(cPtr, 0x30, vclk[0]); cPtr->writeXR(cPtr, 0x31, vclk[1]); /* restore VCLK regs. */ cPtr->writeXR(cPtr, 0x32, vclk[2]); /* cPtr->writeXR(cPtr, 0x33, tmp33 & ~0x20);*/ usleep(10000); /* Let VCO stabilise */ } cPtr->writeXR(cPtr, 0x33, ((tmp33 & ~0x80) | (Clock->xr33 & 0x80))); cPtr->writeXR(cPtr, 0x54, ((tmp54 & 0xF3) | (Clock->xr54 & ~0xF3))); break; } hwp->writeMiscOut(hwp, (Clock->msr & 0xFE) | cPtr->SuspendHack.vgaIOBaseFlag); #ifdef DEBUG ErrorF("restored\n"); #endif } /* * This is Ken Raeburn's clock * calculation code just modified a little bit to fit in here. */ static void chipsCalcClock(ScrnInfoPtr pScrn, int Clock, unsigned char *vclk) { CHIPSPtr cPtr = CHIPSPTR(pScrn); int M, N, P = 0, PSN = 0, PSNx = 0; int bestM = 0, bestN = 0, bestP = 0, bestPSN = 0; double abest = 42; #ifdef DEBUG double bestFout = 0; #endif double target; double Fvco, Fout; double error, aerror; int M_min = 3; /* Hack to deal with problem of Toshiba 720CDT clock */ int M_max = (IS_HiQV(cPtr) && cPtr->Chipset != CHIPS_CT69000 && cPtr->Chipset != CHIPS_CT69030) ? 63 : 127; /* @@@ < CHIPS_CT690x0 ?? */ /* Other parameters available on the 65548 but not the 65545, and * not documented in the Clock Synthesizer doc in rev 1.0 of the * 65548 datasheet: * * + XR30[4] = 0, VCO divider loop uses divide by 4 (same as 65545) * 1, VCO divider loop uses divide by 16 * * + XR30[5] = 1, reference clock is divided by 5 * * Other parameters available on the 65550 and not on the 65545 * * + XRCB[2] = 0, VCO divider loop uses divide by 4 (same as 65545) * 1, VCO divider loop uses divide by 16 * * + XRCB[1] = 1, reference clock is divided by 5 * * + XRCB[7] = Vclk = Mclk * * + XRCA[0:1] = 2 MSB of a 10 bit M-Divisor * * + XRCA[4:5] = 2 MSB of a 10 bit N-Divisor * * I haven't put in any support for those here. For simplicity, * they should be set to 0 on the 65548, and left untouched on * earlier chips. * * Other parameters available on the 690x0 * * + The 690x0 has no reference clock divider, so PSN must * always be 1. * XRCB[0:1] are reserved according to the data book */ target = Clock * 1000; /* @@@ >= CHIPS_CT690x0 ?? */ for (PSNx = ((cPtr->Chipset == CHIPS_CT69000) || (cPtr->Chipset == CHIPS_CT69030)) ? 1 : 0; PSNx <= 1; PSNx++) { int low_N, high_N; double Fref4PSN; PSN = PSNx ? 1 : 4; low_N = 3; high_N = 127; while (Fref / (PSN * low_N) > (((cPtr->Chipset == CHIPS_CT69000) || (cPtr->Chipset == CHIPS_CT69030)) ? 5.0e6 : 2.0e6)) low_N++; while (Fref / (PSN * high_N) < 150.0e3) high_N--; Fref4PSN = Fref * 4 / PSN; for (N = low_N; N <= high_N; N++) { double tmp = Fref4PSN / N; /* @@@ < CHIPS_CT690x0 ?? */ for (P = (IS_HiQV(cPtr) && (cPtr->Chipset != CHIPS_CT69000) && (cPtr->Chipset != CHIPS_CT69030)) ? 1 : 0; P <= 5; P++) { /* to force post divisor on Toshiba 720CDT */ double Fvco_desired = target * (1 << P); double M_desired = Fvco_desired / tmp; /* Which way will M_desired be rounded? Do all three just to * be safe. */ int M_low = M_desired - 1; int M_hi = M_desired + 1; if (M_hi < M_min || M_low > M_max) continue; if (M_low < M_min) M_low = M_min; if (M_hi > M_max) M_hi = M_max; for (M = M_low; M <= M_hi; M++) { Fvco = tmp * M; /* @@@ >= CHIPS_CT690x0 ?? */ if (Fvco <= ((cPtr->Chipset == CHIPS_CT69000 || cPtr->Chipset == CHIPS_CT69030) ? 100.0e6 : 48.0e6)) continue; if (Fvco > 220.0e6) break; Fout = Fvco / (1 << P); error = (target - Fout) / target; aerror = (error < 0) ? -error : error; if (aerror < abest) { abest = aerror; bestM = M; bestN = N; bestP = P; bestPSN = PSN; #ifdef DEBUG bestFout = Fout; #endif } } } } } /* @@@ >= CHIPS_CT690x0 ?? */ vclk[0] = (bestP << (IS_HiQV(cPtr) ? 4 : 1)) + (((cPtr->Chipset == CHIPS_CT69000) || (cPtr->Chipset == CHIPS_CT69030)) ? 0 : (bestPSN == 1)); vclk[1] = bestM - 2; vclk[2] = bestN - 2; #ifdef DEBUG ErrorF("Freq. selected: %.2f MHz, vclk[0]=%X, vclk[1]=%X, vclk[2]=%X\n", (float)(Clock / 1000.), vclk[0], vclk[1], vclk[2]); ErrorF("Freq. set: %.2f MHz\n", bestFout / 1.0e6); #endif } static void chipsSave(ScrnInfoPtr pScrn, vgaRegPtr VgaSave, CHIPSRegPtr ChipsSave) { vgaHWPtr hwp = VGAHWPTR(pScrn); CHIPSPtr cPtr = CHIPSPTR(pScrn); int i; unsigned char tmp; #ifdef DEBUG ErrorF("chipsSave\n"); #endif /* set registers that we can program the controller */ /* bank 0 */ if (IS_HiQV(cPtr)) { cPtr->writeXR(cPtr, 0x0E, 0x00); } else { cPtr->writeXR(cPtr, 0x10, 0x00); cPtr->writeXR(cPtr, 0x11, 0x00); tmp = cPtr->readXR(cPtr, 0x0C) & ~0x50; /* WINgine stores MSB here */ cPtr->writeXR(cPtr, 0x0C, tmp); } chipsFixResume(pScrn); tmp = cPtr->readXR(cPtr, 0x02); cPtr->writeXR(cPtr, 0x02, tmp & ~0x18); /* get generic registers */ vgaHWSave(pScrn, VgaSave, VGA_SR_ALL); /* save clock */ chipsClockSave(pScrn, &ChipsSave->Clock); /* save extended registers */ if (IS_HiQV(cPtr)) { for (i = 0; i < 0xFF; i++) { #ifdef SAR04 /* Save SAR04 multimedia register correctly */ if (i == 0x4F) cPtr->writeXR(cPtr, 0x4E, 0x04); #endif ChipsSave->XR[i] = cPtr->readXR(cPtr,i); #ifdef DEBUG ErrorF("XS%X - %X\n", i, ChipsSave->XR[i]); #endif } for (i = 0; i < 0x80; i++) { ChipsSave->FR[i] = cPtr->readFR(cPtr, i); #ifdef DEBUG ErrorF("FS%X - %X\n", i, ChipsSave->FR[i]); #endif } for (i = 0; i < 0x80; i++) { ChipsSave->MR[i] = cPtr->readMR(cPtr, i); #ifdef DEBUG ErrorF("MS%X - %X\n", i, ChipsSave->FR[i]); #endif } /* Save CR0-CR40 even though we don't use them, so they can be * printed */ for (i = 0x0; i < 0x80; i++) { ChipsSave->CR[i] = hwp->readCrtc(hwp, i); #ifdef DEBUG ErrorF("CS%X - %X\n", i, ChipsSave->CR[i]); #endif } } else { for (i = 0; i < 0x7D; i++) { /* don't touch XR7D and XR7F on WINGINE */ ChipsSave->XR[i] = cPtr->readXR(cPtr, i); #ifdef DEBUG ErrorF("XS%X - %X\n", i, ChipsSave->XR[i]); #endif } } } Bool chipsModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) { CHIPSPtr cPtr = CHIPSPTR(pScrn); #ifdef DEBUG ErrorF("chipsModeInit\n"); #endif #if 0 *(int*)0xFFFFFF0 = 0; ErrorF("done\n"); #endif chipsUnlock(pScrn); chipsFixResume(pScrn); if (cPtr->Accel.UseHWCursor) cPtr->Flags |= ChipsHWCursor; else cPtr->Flags &= ~ChipsHWCursor; /* * We need to delay cursor loading after resetting the video mode * to give the engine a chance to recover. */ cPtr->cursorDelay = TRUE; if (IS_HiQV(cPtr)) return chipsModeInitHiQV(pScrn, mode); else if (IS_Wingine(cPtr)) return chipsModeInitWingine(pScrn, mode); else return chipsModeInit655xx(pScrn, mode); } /* * The timing register of the C&T FP chipsets are organized * as follows: * The chipsets have two sets of timing registers: * the standard horizontal and vertical timing registers for * display size, blank start, sync start, sync end, blank end * and total size at their default VGA locations and extensions * and the alternate horizontal and vertical timing registers for * display size, sync start, sync end and total size. * In LCD and mixed (LCD+CRT) mode the alternate timing registers * control the timing. The alternate horizontal and vertical display * size registers are set to the physical pixel size of the display. * Normally the alternalte registers are set by the BIOS to optimized * values. * While the horizontal an vertical refresh rates are fixed independent * of the visible display size to ensure optimal performace of both * displays they can be adapted to the screen resolution and CRT * requirements in CRT mode by programming the standard timing registers * in the VGA fashion. * In LCD and mixed mode the _standard_ horizontal and vertical display * size registers control the size of the _visible_ part of the display * in contast to the _physical_ size of the display which is specified * by the _alternate_ horizontal and vertical display size registers. * The size of the visible should always be equal or less than the * physical size. * For the 69030 chipsets, the CRT and LCD display channels are seperate * and so can be driven independently. */ static Bool chipsModeInitHiQV(ScrnInfoPtr pScrn, DisplayModePtr mode) { int i; int lcdHTotal, lcdHDisplay; int lcdVTotal, lcdVDisplay; int lcdHRetraceStart, lcdHRetraceEnd; int lcdVRetraceStart, lcdVRetraceEnd; int lcdHSyncStart; vgaHWPtr hwp = VGAHWPTR(pScrn); CHIPSPtr cPtr = CHIPSPTR(pScrn); CHIPSRegPtr ChipsNew; vgaRegPtr ChipsStd; unsigned int tmp; ChipsNew = &cPtr->ModeReg; ChipsStd = &hwp->ModeReg; /* * Possibly fix up the panel size, if the manufacture is stupid * enough to set it incorrectly in text modes */ if (xf86ReturnOptValBool(cPtr->Options, OPTION_PANEL_SIZE, FALSE)) { cPtr->PanelSize.HDisplay = mode->CrtcHDisplay; cPtr->PanelSize.VDisplay = mode->CrtcVDisplay; } /* generic init */ if (!vgaHWInit(pScrn, mode)) { ErrorF("bomb 1\n"); return (FALSE); } pScrn->vtSema = TRUE; /* init clock */ if (!chipsClockFind(pScrn, mode, mode->ClockIndex, &ChipsNew->Clock)) { ErrorF("bomb 2\n"); return (FALSE); } /* Give Warning if the dual display mode will cause problems */ /* Note 64bit wide memory bus assumed (as in 69000 and 69030 */ if (cPtr->UseDualChannel && ((cPtr->SecondCrtc == TRUE) || (cPtr->Flags & ChipsDualRefresh))) { if (((ChipsNew->Clock.FPClock + ChipsNew->Clock.Clock) * (max(1, pScrn->bitsPerPixel >> 3) + ((cPtr->FrameBufferSize && (cPtr->PanelType & ChipsLCD)) ? 1 : 0)) / (8 * 0.7)) > cPtr->MemClock.Max) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Memory bandwidth requirements exceeded by dual-channel\n"); xf86DrvMsg(pScrn->scrnIndex, X_WARNING, " mode. Display might be corrupted!!!\n"); } } /* get C&T Specific Registers */ for (i = 0; i < 0xFF; i++) { #ifdef SAR04 /* Save SAR04 multimedia register correctly */ if (i == 0x4F) cPtr->writeXR(cPtr, 0x4E, 0x04); #endif ChipsNew->XR[i] = cPtr->readXR(cPtr, i); } for (i = 0; i < 0x80; i++) { ChipsNew->FR[i] = cPtr->readFR(cPtr, i); } for (i = 0; i < 0x80; i++) { ChipsNew->MR[i] = cPtr->readMR(cPtr, i); } for (i = 0x30; i < 0x80; i++) { /* These are the CT extended CRT regs */ ChipsNew->CR[i] = hwp->readCrtc(hwp, i); } /* * Here all of the other fields of 'ChipsNew' get filled in, to * handle the SVGA extended registers. It is also allowable * to override generic registers whenever necessary. */ /* some generic settings */ if (pScrn->depth == 1) { ChipsStd->Attribute[0x10] = 0x03; /* mode */ } else { ChipsStd->Attribute[0x10] = 0x01; /* mode */ } ChipsStd->Attribute[0x11] = 0x00; /* overscan (border) color */ ChipsStd->Attribute[0x12] = 0x0F; /* enable all color planes */ ChipsStd->Attribute[0x13] = 0x00; /* horiz pixel panning 0 */ ChipsStd->Graphics[0x05] = 0x00; /* normal read/write mode */ /* set virtual screen width */ tmp = pScrn->displayWidth >> 3; if (pScrn->bitsPerPixel == 16) { tmp <<= 1; /* double the width of the buffer */ } else if (pScrn->bitsPerPixel == 24) { tmp += tmp << 1; } else if (pScrn->bitsPerPixel == 32) { tmp <<= 2; } else if (pScrn->bitsPerPixel < 8) { tmp >>= 1; } ChipsStd->CRTC[0x13] = tmp & 0xFF; ChipsNew->CR[0x41] = (tmp >> 8) & 0x0F; /* Set paging mode on the HiQV32 architecture, if required */ if (!(cPtr->Flags & ChipsLinearSupport) || (pScrn->bitsPerPixel < 8)) ChipsNew->XR[0x0A] |= 0x1; #if X_BYTE_ORDER == X_BIG_ENDIAN ChipsNew->XR[0x0A] &= 0xCF; if (pScrn->bitsPerPixel == 16) { if (!cPtr->dualEndianAp) ChipsNew->XR[0x0A] |= 0x10; } #endif ChipsNew->XR[0x09] |= 0x1; /* Enable extended CRT registers */ ChipsNew->XR[0x0E] = 0; /* Single map */ ChipsNew->XR[0x40] |= 0x2; /* Don't wrap at 256kb */ ChipsNew->XR[0x81] &= 0xF8; if (pScrn->bitsPerPixel >= 8) { ChipsNew->XR[0x40] |= 0x1; /* High Resolution. XR40[1] reserved? */ ChipsNew->XR[0x81] |= 0x2; /* 256 Color Video */ } ChipsNew->XR[0x80] |= 0x10; /* Enable cursor output on P0 and P1 */ if (pScrn->depth > 1) { if (pScrn->rgbBits == 8) ChipsNew->XR[0x80] |= 0x80; else ChipsNew->XR[0x80] &= ~0x80; } if (abs(cPtr->MemClock.Clk - cPtr->MemClock.ProbedClk) > 50) { /* set mem clk */ ChipsNew->XR[0xCC] = cPtr->MemClock.xrCC; ChipsNew->XR[0xCD] = cPtr->MemClock.xrCD; ChipsNew->XR[0xCE] = cPtr->MemClock.xrCE; } /* Set the 69030 dual channel settings */ if (cPtr->Flags & ChipsDualChannelSupport) { ChipsNew->FR[0x01] &= 0xFC; if ((cPtr->SecondCrtc == FALSE) && (cPtr->PanelType & ChipsLCD)) ChipsNew->FR[0x01] |= 0x02; else ChipsNew->FR[0x01] |= 0x01; ChipsNew->FR[0x02] &= 0xCC; if ((cPtr->SecondCrtc == TRUE) || (cPtr->Flags & ChipsDualRefresh)) ChipsNew->FR[0x02] |= 0x01; /* Set DAC to pipe B */ else ChipsNew->FR[0x02] &= 0xFE; /* Set DAC to pipe A */ if (cPtr->PanelType & ChipsLCD) ChipsNew->FR[0x02] |= 0x20; /* Enable the LCD output */ if (cPtr->PanelType & ChipsCRT) ChipsNew->FR[0x02] |= 0x10; /* Enable the CRT output */ } /* linear specific */ if (cPtr->Flags & ChipsLinearSupport) { ChipsNew->XR[0x0A] |= 0x02; /* Linear Addressing Mode */ ChipsNew->XR[0x20] = 0x0; /*BitBLT Draw Mode for 8 */ ChipsNew->XR[0x05] = (unsigned char)((cPtr->FbAddress >> 16) & 0xFF); ChipsNew->XR[0x06] = (unsigned char)((cPtr->FbAddress >> 24) & 0xFF); } /* panel timing */ /* By default don't set panel timings, but allow it as an option */ if (xf86ReturnOptValBool(cPtr->Options, OPTION_USE_MODELINE, FALSE)) { lcdHTotal = (mode->CrtcHTotal >> 3) - 5; lcdHDisplay = (cPtr->PanelSize.HDisplay >> 3) - 1; lcdHRetraceStart = (mode->CrtcHSyncStart >> 3); lcdHRetraceEnd = (mode->CrtcHSyncEnd >> 3); lcdHSyncStart = lcdHRetraceStart - 2; lcdVTotal = mode->CrtcVTotal - 2; lcdVDisplay = cPtr->PanelSize.VDisplay - 1; lcdVRetraceStart = mode->CrtcVSyncStart; lcdVRetraceEnd = mode->CrtcVSyncEnd; ChipsNew->FR[0x20] = lcdHDisplay & 0xFF; ChipsNew->FR[0x21] = lcdHRetraceStart & 0xFF; ChipsNew->FR[0x25] = ((lcdHRetraceStart & 0xF00) >> 4) | ((lcdHDisplay & 0xF00) >> 8); ChipsNew->FR[0x22] = lcdHRetraceEnd & 0x1F; ChipsNew->FR[0x23] = lcdHTotal & 0xFF; ChipsNew->FR[0x24] = (lcdHSyncStart >> 3) & 0xFF; ChipsNew->FR[0x26] = (ChipsNew->FR[0x26] & ~0x1F) | ((lcdHTotal & 0xF00) >> 8) | (((lcdHSyncStart >> 3) & 0x100) >> 4); ChipsNew->FR[0x27] &= 0x7F; ChipsNew->FR[0x30] = lcdVDisplay & 0xFF; ChipsNew->FR[0x31] = lcdVRetraceStart & 0xFF; ChipsNew->FR[0x35] = ((lcdVRetraceStart & 0xF00) >> 4) | ((lcdVDisplay & 0xF00) >> 8); ChipsNew->FR[0x32] = lcdVRetraceEnd & 0x0F; ChipsNew->FR[0x33] = lcdVTotal & 0xFF; ChipsNew->FR[0x34] = (lcdVTotal - lcdVRetraceStart) & 0xFF; ChipsNew->FR[0x36] = ((lcdVTotal & 0xF00) >> 8) | (((lcdVTotal - lcdVRetraceStart) & 0x700) >> 4); ChipsNew->FR[0x37] |= 0x80; } /* Set up the extended CRT registers of the HiQV32 chips */ ChipsNew->CR[0x30] = ((mode->CrtcVTotal - 2) & 0xF00) >> 8; ChipsNew->CR[0x31] = ((mode->CrtcVDisplay - 1) & 0xF00) >> 8; ChipsNew->CR[0x32] = (mode->CrtcVSyncStart & 0xF00) >> 8; ChipsNew->CR[0x33] = (mode->CrtcVBlankStart & 0xF00) >> 8; if ((cPtr->Chipset == CHIPS_CT69000) || (cPtr->Chipset == CHIPS_CT69030)) { /* The 690xx has overflow bits for the horizontal values as well */ ChipsNew->CR[0x38] = (((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8; ChipsNew->CR[0x3C] = vgaHWHBlankKGA(mode, ChipsStd, 8, 0) << 6; } else vgaHWHBlankKGA(mode, ChipsStd, 6, 0); vgaHWVBlankKGA(mode, ChipsStd, 8, 0); ChipsNew->CR[0x40] |= 0x80; /* centering/stretching */ if (!xf86ReturnOptValBool(cPtr->Options, OPTION_SUSPEND_HACK, FALSE)) { if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_STRETCH, FALSE)) { ChipsNew->FR[0x40] &= 0xDF; /* Disable Horizontal stretching */ ChipsNew->FR[0x48] &= 0xFB; /* Disable vertical stretching */ ChipsNew->XR[0xA0] = 0x10; /* Disable cursor stretching */ } else { ChipsNew->FR[0x40] |= 0x21; /* Enable Horizontal stretching */ ChipsNew->FR[0x48] |= 0x05; /* Enable vertical stretching */ ChipsNew->XR[0xA0] = 0x70; /* Enable cursor stretching */ if (cPtr->Accel.UseHWCursor && cPtr->PanelSize.HDisplay && cPtr->PanelSize.VDisplay && (cPtr->PanelSize.HDisplay != mode->CrtcHDisplay) && (cPtr->PanelSize.VDisplay != mode->CrtcVDisplay)) { if(cPtr->Accel.UseHWCursor) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Disabling HW Cursor on stretched LCD\n"); cPtr->Flags &= ~ChipsHWCursor; } } } if (xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_CENTER, TRUE)) { ChipsNew->FR[0x40] |= 0x3; /* Enable Horizontal centering */ ChipsNew->FR[0x48] |= 0x3; /* Enable Vertical centering */ } else { ChipsNew->FR[0x40] &= 0xFD; /* Disable Horizontal centering */ ChipsNew->FR[0x48] &= 0xFD; /* Disable Vertical centering */ } /* sync on green */ if (xf86ReturnOptValBool(cPtr->Options, OPTION_SYNC_ON_GREEN, FALSE)) ChipsNew->XR[0x82] |=0x02; /* software mode flag */ ChipsNew->XR[0xE2] = chipsVideoMode((pScrn->depth), (cPtr->PanelType & ChipsLCD) ? min(mode->CrtcHDisplay, cPtr->PanelSize.HDisplay) : mode->CrtcHDisplay, mode->CrtcVDisplay); #ifdef DEBUG ErrorF("VESA Mode: %Xh\n", ChipsNew->XR[0xE2]); #endif /* sync. polarities */ if ((mode->Flags & (V_PHSYNC | V_NHSYNC)) && (mode->Flags & (V_PVSYNC | V_NVSYNC))) { if (mode->Flags & (V_PHSYNC | V_NHSYNC)) { if (mode->Flags & V_PHSYNC) ChipsNew->FR[0x08] &= 0xBF; /* Alt. CRT Hsync positive */ else ChipsNew->FR[0x08] |= 0x40; /* Alt. CRT Hsync negative */ } if (mode->Flags & (V_PVSYNC | V_NVSYNC)) { if (mode->Flags & V_PVSYNC) ChipsNew->FR[0x08] &= 0x7F; /* Alt. CRT Vsync positive */ else ChipsNew->FR[0x08] |= 0x80; /* Alt. CRT Vsync negative */ } } if (mode->Flags & (V_PCSYNC | V_NCSYNC)) { ChipsNew->FR[0x0B] |= 0x20; if (mode->Flags & V_PCSYNC) { ChipsNew->FR[0x08] &= 0x7F; /* Alt. CRT Vsync positive */ ChipsNew->FR[0x08] &= 0xBF; /* Alt. CRT Hsync positive */ ChipsStd->MiscOutReg &= 0x7F; ChipsStd->MiscOutReg &= 0xBF; } else { ChipsNew->FR[0x08] |= 0x80; /* Alt. CRT Vsync negative */ ChipsNew->FR[0x08] |= 0x40; /* Alt. CRT Hsync negative */ ChipsStd->MiscOutReg |= 0x40; ChipsStd->MiscOutReg |= 0x80; } } /* bpp depend */ if (pScrn->bitsPerPixel == 16) { ChipsNew->XR[0x81] = (ChipsNew->XR[0x81] & 0xF0) | 0x4; if (cPtr->Flags & ChipsGammaSupport) ChipsNew->XR[0x82] |= 0x0C; /* 16bpp = 5-5-5 */ ChipsNew->FR[0x10] |= 0x0C; /*Colour Panel */ ChipsNew->XR[0x20] = 0x10; /*BitBLT Draw Mode for 16 bpp */ if (pScrn->weight.green != 5) ChipsNew->XR[0x81] |= 0x01; /*16bpp */ } else if (pScrn->bitsPerPixel == 24) { ChipsNew->XR[0x81] = (ChipsNew->XR[0x81] & 0xF0) | 0x6; if (cPtr->Flags & ChipsGammaSupport) ChipsNew->XR[0x82] |= 0x0C; /* 24bpp colour */ ChipsNew->XR[0x20] = 0x20; /*BitBLT Draw Mode for 24 bpp */ } else if (pScrn->bitsPerPixel == 32) { ChipsNew->XR[0x81] = (ChipsNew->XR[0x81] & 0xF0) | 0x7; if (cPtr->Flags & ChipsGammaSupport) ChipsNew->XR[0x82] |= 0x0C; /* 32bpp colour */ ChipsNew->XR[0x20] = 0x10; /*BitBLT Mode for 16bpp used at 32bpp */ } /*CRT only */ if (!(cPtr->PanelType & ChipsLCD)) { if (mode->Flags & V_INTERLACE) { ChipsNew->CR[0x70] = 0x80 /* set interlace */ | (((((mode->CrtcHDisplay >> 3) - 1) >> 1) - 6) & 0x7F); /* ** Double VDisplay to get back the full screen value, otherwise ** you only see half the picture. */ mode->CrtcVDisplay = mode->VDisplay; tmp = ChipsStd->CRTC[7] & ~0x42; ChipsStd->CRTC[7] = (tmp | ((((mode->CrtcVDisplay -1) & 0x100) >> 7 ) | (((mode->CrtcVDisplay -1) & 0x200) >> 3 ))); ChipsStd->CRTC[0x12] = (mode->CrtcVDisplay -1) & 0xFF; ChipsNew->CR[0x31] = ((mode->CrtcVDisplay - 1) & 0xF00) >> 8; } else { ChipsNew->CR[0x70] &= ~0x80; /* unset interlace */ } } #if defined(__arm32__) && defined(__NetBSD__) if (cPtr->TVMode != XMODE_RGB) { /* * Put the console into TV Out mode. */ xf86SetTVOut(cPtr->TVMode); ChipsNew->CR[0x72] = (mode->CrtcHTotal >> 1) >> 3;/* First horizontal * serration pulse */ ChipsNew->CR[0x73] = mode->CrtcHTotal >> 3; /* Second pulse */ ChipsNew->CR[0x74] = (((mode->HSyncEnd - mode->HSyncStart) >> 3) - 1) & 0x1F; /* equalization pulse */ if (cPtr->TVMode == XMODE_PAL || cPtr->TVMode == XMODE_SECAM) { ChipsNew->CR[0x71] = 0xA0; /* PAL support with blanking delay */ } else { ChipsNew->CR[0x71] = 0x20; /* NTSC support with blanking delay */ } } else { /* XMODE_RGB */ /* * Put the console into RGB Out mode. */ xf86SetRGBOut(); } #endif /* STN specific */ if (IS_STN(cPtr->PanelType)) { ChipsNew->FR[0x11] &= ~0x03; /* FRC clear */ ChipsNew->FR[0x11] &= ~0x8C; /* Dither clear */ ChipsNew->FR[0x11] |= 0x01; /* 16 frame FRC */ ChipsNew->FR[0x11] |= 0x84; /* Dither */ if ((cPtr->Flags & ChipsTMEDSupport) && !xf86ReturnOptValBool(cPtr->Options, OPTION_NO_TMED, FALSE)) { ChipsNew->FR[0x73] &= 0x4F; /* Clear TMED */ ChipsNew->FR[0x73] |= 0x80; /* Enable TMED */ ChipsNew->FR[0x73] |= 0x30; /* TMED 256 Shades of RGB */ } if (cPtr->PanelType & ChipsDD) /* Shift Clock Mask. Use to get */ ChipsNew->FR[0x12] |= 0x4; /* rid of line in DSTN screens */ } /* * The zero position of the overlay does not align with the zero * position of the display. The skew is dependent on the depth, * display type and refresh rate. Calculate the skew before setting * the X and Y dimensions of the overlay. These values are needed * both by the overlay and XvImages. So calculate and store them */ if (cPtr->PanelType & ChipsLCD) { cPtr->OverlaySkewX = (((ChipsNew->FR[0x23] & 0xFF) - (ChipsNew->FR[0x20] & 0xFF) + 3) << 3) - 1; cPtr->OverlaySkewY = (ChipsNew->FR[0x33] + ((ChipsNew->FR[0x36] & 0xF) << 8) - (ChipsNew->FR[0x31] & 0xF0) - (ChipsNew->FR[0x32] & 0x0F) - ((ChipsNew->FR[0x35] & 0xF0) << 4)); if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_STRETCH, FALSE) && xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_CENTER, TRUE)) { if (cPtr->PanelSize.HDisplay > mode->CrtcHDisplay) cPtr->OverlaySkewX += (cPtr->PanelSize.HDisplay - mode->CrtcHDisplay) / 2; if (cPtr->PanelSize.VDisplay > mode->CrtcVDisplay) cPtr->OverlaySkewY += (cPtr->PanelSize.VDisplay - mode->CrtcVDisplay) / 2; } } else { cPtr->OverlaySkewX = mode->CrtcHTotal - mode->CrtcHBlankStart - 9; cPtr->OverlaySkewY = mode->CrtcVTotal - mode->CrtcVSyncEnd - 1; if (mode->Flags & V_INTERLACE) { /* * This handles 1024 and 1280 interlaced modes only. Its * pretty arbitrary, but its what C&T recommends */ #if 0 if (mode->CrtcHDisplay == 1024) cPtr->OverlaySkewY += 5; else if (mode->CrtcHDisplay == 1280) #endif cPtr->OverlaySkewY *= 2; } } /* mask for viewport granularity */ switch (pScrn->bitsPerPixel) { case 8: cPtr->viewportMask = ~7U; break; case 16: cPtr->viewportMask = ~3U; break; case 24: cPtr->viewportMask = ~7U; break; case 32: cPtr->viewportMask = ~0U; break; default: cPtr->viewportMask = ~7U; } /* Turn off multimedia by default as it degrades performance */ ChipsNew->XR[0xD0] &= 0x0f; if (cPtr->Flags & ChipsVideoSupport) { #if 0 /* if we do this even though video isn't playing we kill performance */ ChipsNew->XR[0xD0] |= 0x10; /* Force the Multimedia engine on */ #endif #ifdef SAR04 ChipsNew->XR[0x4F] = 0x2A; /* SAR04 >352 pixel overlay width */ #endif ChipsNew->MR[0x3C] &= 0x18; /* Ensure that the overlay is off */ cPtr->VideoZoomMax = 0x100; if (cPtr->Chipset == CHIPS_CT65550) { tmp = cPtr->readXR(cPtr, 0x04); if (tmp < 0x02) /* 65550 ES0 has */ cPtr->VideoZoomMax = 0x40; /* 0x40 max zoom */ } } /* Program the registers */ /*vgaHWProtect(pScrn, TRUE);*/ if (cPtr->Chipset <= CHIPS_CT69000) { ChipsNew->FR[0x01] &= ~0x03; if (cPtr->PanelType & ChipsLCD) ChipsNew->FR[0x01] |= 0x02; else ChipsNew->FR[0x01] |= 0x01; } if ((cPtr->Flags & ChipsDualChannelSupport) && (!xf86IsEntityShared(pScrn->entityList[0]))) { unsigned char IOSS, MSS, tmpfr01; IOSS = cPtr->readIOSS(cPtr); MSS = cPtr->readMSS(cPtr); cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | IOSS_PIPE_A)); cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_A)); chipsRestore(pScrn, ChipsStd, ChipsNew, FALSE); cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | IOSS_PIPE_B)); cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B)); /* * Hack:: Force Pipe-B on for dual refresh, and off elsewise */ tmpfr01 = ChipsNew->FR[0x01]; ChipsNew->FR[0x01] &= 0xFC; if (cPtr->UseDualChannel) ChipsNew->FR[0x01] |= 0x01; chipsRestore(pScrn, ChipsStd, ChipsNew, FALSE); ChipsNew->FR[0x01] = tmpfr01; cPtr->writeIOSS(cPtr, IOSS); cPtr->writeMSS(cPtr, hwp, MSS); } else { chipsRestore(pScrn, ChipsStd, ChipsNew, FALSE); } /*vgaHWProtect(pScrn, FALSE);*/ usleep(100000); /* prevents cursor corruption seen on a TECRA 510 */ return(TRUE); } static Bool chipsModeInitWingine(ScrnInfoPtr pScrn, DisplayModePtr mode) { int i, bytesPerPixel; vgaHWPtr hwp = VGAHWPTR(pScrn); CHIPSPtr cPtr = CHIPSPTR(pScrn); CHIPSRegPtr ChipsNew; vgaRegPtr ChipsStd; unsigned int tmp; ChipsNew = &cPtr->ModeReg; ChipsStd = &hwp->ModeReg; bytesPerPixel = pScrn->bitsPerPixel >> 3; /* * This chipset seems to have problems if * HBlankEnd is choosen equals HTotal */ if (!mode->CrtcHAdjusted) mode->CrtcHBlankEnd = min(mode->CrtcHSyncEnd, mode->CrtcHTotal - 2); /* correct the timings for 16/24 bpp */ if (pScrn->bitsPerPixel == 16) { if (!mode->CrtcHAdjusted) { mode->CrtcHDisplay++; mode->CrtcHDisplay <<= 1; mode->CrtcHDisplay--; mode->CrtcHSyncStart <<= 1; mode->CrtcHSyncEnd <<= 1; mode->CrtcHBlankStart <<= 1; mode->CrtcHBlankEnd <<= 1; mode->CrtcHTotal <<= 1; mode->CrtcHAdjusted = TRUE; } } else if (pScrn->bitsPerPixel == 24) { if (!mode->CrtcHAdjusted) { mode->CrtcHDisplay++; mode->CrtcHDisplay += ((mode->CrtcHDisplay) << 1); mode->CrtcHDisplay--; mode->CrtcHSyncStart += ((mode->CrtcHSyncStart) << 1); mode->CrtcHSyncEnd += ((mode->CrtcHSyncEnd) << 1); mode->CrtcHBlankStart += ((mode->CrtcHBlankStart) << 1); mode->CrtcHBlankEnd += ((mode->CrtcHBlankEnd) << 1); mode->CrtcHTotal += ((mode->CrtcHTotal) << 1); mode->CrtcHAdjusted = TRUE; } } /* generic init */ if (!vgaHWInit(pScrn, mode)) { ErrorF("bomb 3\n"); return (FALSE); } pScrn->vtSema = TRUE; /* init clock */ if (!chipsClockFind(pScrn, mode, mode->ClockIndex, &ChipsNew->Clock)) { ErrorF("bomb 4\n"); return (FALSE); } /* get C&T Specific Registers */ for (i = 0; i < 0x7D; i++) { /* don't touch XR7D and XR7F on WINGINE */ ChipsNew->XR[i] = cPtr->readXR(cPtr, i); } /* some generic settings */ if (pScrn->bitsPerPixel == 1) { ChipsStd->Attribute[0x10] = 0x03; /* mode */ } else { ChipsStd->Attribute[0x10] = 0x01; /* mode */ } ChipsStd->Attribute[0x11] = 0x00; /* overscan (border) color */ ChipsStd->Attribute[0x12] = 0x0F; /* enable all color planes */ ChipsStd->Attribute[0x13] = 0x00; /* horiz pixel panning 0 */ ChipsStd->Graphics[0x05] = 0x00; /* normal read/write mode */ /* set virtual screen width */ if (pScrn->bitsPerPixel >= 8) ChipsStd->CRTC[0x13] = (pScrn->displayWidth * bytesPerPixel) >> 3; else ChipsStd->CRTC[0x13] = pScrn->displayWidth >> 4; /* set C&T Specific Registers */ /* set virtual screen width */ if (pScrn->bitsPerPixel >= 8) tmp = (pScrn->displayWidth >> 4) * bytesPerPixel; else tmp = (pScrn->displayWidth >> 5); ChipsNew->XR[0x0D] = (tmp & 0x80) >> 5; ChipsNew->XR[0x04] |= 4; /* enable addr counter bits 16-17 */ /* XR04: Memory control 1 */ /* bit 2: Memory Wraparound */ /* Enable CRTC addr counter bits 16-17 if set */ ChipsNew->XR[0x0B] |= 0x07; /* extended mode, dual pages enabled */ ChipsNew->XR[0x0B] &= ~0x10; /* linear mode off */ /* XR0B: CPU paging */ /* bit 0: Memory mapping mode */ /* VGA compatible if 0 (default) */ /* Extended mode (mapping for > 256 kB mem) if 1 */ /* bit 1: CPU single/dual mapping */ /* 0, CPU uses only a single map to access (default) */ /* 1, CPU uses two maps to access */ /* bit 2: CPU address divide by 4 */ ChipsNew->XR[0x10] = 0; /* XR10: Single/low map */ ChipsNew->XR[0x11] = 0; /* XR11: High map */ ChipsNew->XR[0x0C] &= ~0x50; /* MSB for XR10 & XR11 */ if (pScrn->bitsPerPixel >= 8) { ChipsNew->XR[0x28] |= 0x10; /* 256-color video */ } else { ChipsNew->XR[0x28] &= 0xEF; /* 16-color video */ } /* set up extended display timings */ /* in CRTonly mode this is simple: only set overflow for CR00-CR06 */ ChipsNew->XR[0x17] = ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8) | ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) | ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) | ((((mode->CrtcHSyncEnd >> 3)) & 0x20) >> 2) | ((((mode->CrtcHBlankStart >> 3) - 1) & 0x100) >> 4) | ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 1); ChipsNew->XR[0x16] = (((mode->CrtcVTotal -2) & 0x400) >> 10 ) | (((mode->CrtcVDisplay -1) & 0x400) >> 9 ) | ((mode->CrtcVSyncStart & 0x400) >> 8 ) | (((mode->CrtcVBlankStart) & 0x400) >> 6 ); /* set video mode */ ChipsNew->XR[0x2B] = chipsVideoMode(pScrn->depth, mode->CrtcHDisplay, mode->CrtcVDisplay); #ifdef DEBUG ErrorF("VESA Mode: %Xh\n", ChipsNew->XR[0x2B]); #endif /* set some linear specific registers */ if (cPtr->Flags & ChipsLinearSupport) { /* enable linear addressing */ ChipsNew->XR[0x0B] &= 0xFD; /* dual page clear */ ChipsNew->XR[0x0B] |= 0x10; /* linear mode on */ ChipsNew->XR[0x08] = (unsigned char)((cPtr->FbAddress >> 16) & 0xFF); ChipsNew->XR[0x09] = (unsigned char)((cPtr->FbAddress >> 24) & 0xFF); /* general setup */ ChipsNew->XR[0x40] = 0x01; /*BitBLT Draw Mode for 8 and 24 bpp */ } /* common general setup */ ChipsNew->XR[0x52] |= 0x01; /* Refresh count */ ChipsNew->XR[0x0F] &= 0xEF; /* not Hi-/True-Colour */ ChipsNew->XR[0x02] &= 0xE7; /* Attr. Cont. default access */ /* use ext. regs. for hor. in dual */ ChipsNew->XR[0x06] &= 0xF3; /* bpp clear */ /* bpp depend */ /*XR06: Palette control */ /* bit 0: Pixel Data Pin Diag, 0 for flat panel pix. data (def) */ /* bit 1: Internal DAC disable */ /* bit 3-2: Colour depth, 0 for 4 or 8 bpp, 1 for 16(5-5-5) bpp, */ /* 2 for 24 bpp, 3 for 16(5-6-5)bpp */ /* bit 4: Enable PC Video Overlay on colour key */ /* bit 5: Bypass Internal VGA palette */ /* bit 7-6: Colour reduction select, 0 for NTSC (default), */ /* 1 for Equivalent weighting, 2 for green only, */ /* 3 for Colour w/o reduction */ /* XR50 Panel Format Register 1 */ /* bit 1-0: Frame Rate Control; 00, No FRC; */ /* 01, 16-frame FRC for colour STN and monochrome */ /* 10, 2-frame FRC for colour TFT or monochrome; */ /* 11, reserved */ /* bit 3-2: Dither Enable */ /* 00, disable dithering; 01, enable dithering */ /* for 256 mode */ /* 10, enable dithering for all modes; 11, reserved */ /* bit6-4: Clock Divide (CD) */ /* 000, Shift Clock Freq = Dot Clock Freq; */ /* 001, SClk = DClk/2; 010 SClk = DClk/4; */ /* 011, SClk = DClk/8; 100 SClk = DClk/16; */ /* bit 7: TFT data width */ /* 0, 16 bit(565RGB); 1, 24bit (888RGB) */ if (pScrn->bitsPerPixel == 16) { ChipsNew->XR[0x06] |= 0xC4; /*15 or 16 bpp colour */ ChipsNew->XR[0x0F] |= 0x10; /*Hi-/True-Colour */ ChipsNew->XR[0x40] = 0x02; /*BitBLT Draw Mode for 16 bpp */ if (pScrn->weight.green != 5) ChipsNew->XR[0x06] |= 0x08; /*16bpp */ } else if (pScrn->bitsPerPixel == 24) { ChipsNew->XR[0x06] |= 0xC8; /*24 bpp colour */ ChipsNew->XR[0x0F] |= 0x10; /*Hi-/True-Colour */ } /*CRT only: interlaced mode */ if (mode->Flags & V_INTERLACE) { ChipsNew->XR[0x28] |= 0x20; /* set interlace */ /* empirical value */ tmp = ((((mode->CrtcHDisplay >> 3) - 1) >> 1) - 6 * (pScrn->bitsPerPixel >= 8 ? bytesPerPixel : 1 )); ChipsNew->XR[0x19] = tmp & 0xFF; ChipsNew->XR[0x17] |= ((tmp & 0x100) >> 1); /* overflow */ ChipsNew->XR[0x0F] &= ~0x40; /* set SW-Flag */ } else { ChipsNew->XR[0x28] &= ~0x20; /* unset interlace */ ChipsNew->XR[0x0F] |= 0x40; /* set SW-Flag */ } /* Program the registers */ /*vgaHWProtect(pScrn, TRUE);*/ chipsRestore(pScrn, ChipsStd, ChipsNew, FALSE); /*vgaHWProtect(pScrn, FALSE);*/ return (TRUE); } static Bool chipsModeInit655xx(ScrnInfoPtr pScrn, DisplayModePtr mode) { int i, bytesPerPixel; int lcdHTotal, lcdHDisplay; int lcdVTotal, lcdVDisplay; int lcdHRetraceStart, lcdHRetraceEnd; int lcdVRetraceStart, lcdVRetraceEnd; int HSyncStart, HDisplay; int CrtcHDisplay; vgaHWPtr hwp = VGAHWPTR(pScrn); CHIPSPtr cPtr = CHIPSPTR(pScrn); CHIPSRegPtr ChipsNew; vgaRegPtr ChipsStd; unsigned int tmp; ChipsNew = &cPtr->ModeReg; ChipsStd = &hwp->ModeReg; bytesPerPixel = pScrn->bitsPerPixel >> 3; /* * Possibly fix up the panel size, if the manufacture is stupid * enough to set it incorrectly in text modes */ if (xf86ReturnOptValBool(cPtr->Options, OPTION_PANEL_SIZE, FALSE)) { cPtr->PanelSize.HDisplay = mode->CrtcHDisplay; cPtr->PanelSize.VDisplay = mode->CrtcVDisplay; } /* * This chipset seems to have problems if * HBlankEnd is choosen equals HTotal */ if (!mode->CrtcHAdjusted) mode->CrtcHBlankEnd = min(mode->CrtcHSyncEnd, mode->CrtcHTotal - 2); /* correct the timings for 16/24 bpp */ if (pScrn->bitsPerPixel == 16) { if (!mode->CrtcHAdjusted) { mode->CrtcHDisplay++; mode->CrtcHDisplay <<= 1; mode->CrtcHDisplay--; mode->CrtcHSyncStart <<= 1; mode->CrtcHSyncEnd <<= 1; mode->CrtcHBlankStart <<= 1; mode->CrtcHBlankEnd <<= 1; mode->CrtcHTotal <<= 1; mode->CrtcHAdjusted = TRUE; } } else if (pScrn->bitsPerPixel == 24) { if (!mode->CrtcHAdjusted) { mode->CrtcHDisplay++; mode->CrtcHDisplay += ((mode->CrtcHDisplay) << 1); mode->CrtcHDisplay--; mode->CrtcHSyncStart += ((mode->CrtcHSyncStart) << 1); mode->CrtcHSyncEnd += ((mode->CrtcHSyncEnd) << 1); mode->CrtcHBlankStart += ((mode->CrtcHBlankStart) << 1); mode->CrtcHBlankEnd += ((mode->CrtcHBlankEnd) << 1); mode->CrtcHTotal += ((mode->CrtcHTotal) << 1); mode->CrtcHAdjusted = TRUE; } } /* store orig. HSyncStart needed for flat panel mode */ HSyncStart = mode->CrtcHSyncStart / (pScrn->bitsPerPixel >= 8 ? bytesPerPixel : 1 ) - 16; HDisplay = (mode->CrtcHDisplay + 1) / (pScrn->bitsPerPixel >= 8 ? bytesPerPixel : 1 ); /* generic init */ if (!vgaHWInit(pScrn, mode)) { ErrorF("bomb 5\n"); return (FALSE); } pScrn->vtSema = TRUE; /* init clock */ if (!chipsClockFind(pScrn, mode, mode->ClockIndex, &ChipsNew->Clock)) { ErrorF("bomb 6\n"); return (FALSE); } /* get C&T Specific Registers */ for (i = 0; i < 0x80; i++) { ChipsNew->XR[i] = cPtr->readXR(cPtr, i); } /* some generic settings */ if (pScrn->bitsPerPixel == 1) { ChipsStd->Attribute[0x10] = 0x03; /* mode */ } else { ChipsStd->Attribute[0x10] = 0x01; /* mode */ } ChipsStd->Attribute[0x11] = 0x00; /* overscan (border) color */ ChipsStd->Attribute[0x12] = 0x0F; /* enable all color planes */ ChipsStd->Attribute[0x13] = 0x00; /* horiz pixel panning 0 */ ChipsStd->Graphics[0x05] = 0x00; /* normal read/write mode */ /* set virtual screen width */ if (pScrn->bitsPerPixel >= 8) ChipsStd->CRTC[0x13] = (pScrn->displayWidth * bytesPerPixel) >> 3; else ChipsStd->CRTC[0x13] = pScrn->displayWidth >> 4; /* set C&T Specific Registers */ /* set virtual screen width */ ChipsNew->XR[0x1E] = ChipsStd->CRTC[0x13]; /* alternate offset */ /*databook is not clear about 0x1E might be needed for 65520/30 */ if (pScrn->bitsPerPixel >= 8) tmp = (pScrn->displayWidth * bytesPerPixel) >> 2; else tmp = pScrn->displayWidth >> 3; ChipsNew->XR[0x0D] = (tmp & 0x01) | ((tmp << 1) & 0x02) ; ChipsNew->XR[0x04] |= 4; /* enable addr counter bits 16-17 */ /* XR04: Memory control 1 */ /* bit 2: Memory Wraparound */ /* Enable CRTC addr counter bits 16-17 if set */ ChipsNew->XR[0x0B] |= 0x07; /* extended mode, dual pages enabled */ ChipsNew->XR[0x0B] &= ~0x10; /* linear mode off */ /* XR0B: CPU paging */ /* bit 0: Memory mapping mode */ /* VGA compatible if 0 (default) */ /* Extended mode (mapping for > 256 kB mem) if 1 */ /* bit 1: CPU single/dual mapping */ /* 0, CPU uses only a single map to access (default) */ /* 1, CPU uses two maps to access */ /* bit 2: CPU address divide by 4 */ ChipsNew->XR[0x10] = 0; /* XR10: Single/low map */ ChipsNew->XR[0x11] = 0; /* XR11: High map */ if (pScrn->bitsPerPixel >= 8) { ChipsNew->XR[0x28] |= 0x10; /* 256-color video */ } else { ChipsNew->XR[0x28] &= 0xEF; /* 16-color video */ } /* set up extended display timings */ if (!(cPtr->PanelType & ChipsLCD)) { /* in CRTonly mode this is simple: only set overflow for CR00-CR06 */ ChipsNew->XR[0x17] = ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8) | ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) | ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) | ((((mode->CrtcHSyncEnd >> 3)) & 0x20) >> 2) | ((((mode->CrtcHBlankStart >> 3) - 1) & 0x100) >> 4) | ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 1); ChipsNew->XR[0x16] = (((mode->CrtcVTotal -2) & 0x400) >> 10 ) | (((mode->CrtcVDisplay -1) & 0x400) >> 9 ) | ((mode->CrtcVSyncStart & 0x400) >> 8 ) | (((mode->CrtcVBlankStart) & 0x400) >> 6 ); } else { /* horizontal timing registers */ /* in LCD/dual mode use saved bios values to derive timing values if * not told otherwise */ if (!xf86ReturnOptValBool(cPtr->Options, OPTION_USE_MODELINE, FALSE)) { lcdHTotal = cPtr->PanelSize.HTotal; lcdHRetraceStart = cPtr->PanelSize.HRetraceStart; lcdHRetraceEnd = cPtr->PanelSize.HRetraceEnd; if (pScrn->bitsPerPixel == 16) { lcdHRetraceStart <<= 1; lcdHRetraceEnd <<= 1; lcdHTotal <<= 1; } else if (pScrn->bitsPerPixel == 24) { lcdHRetraceStart += (lcdHRetraceStart << 1); lcdHRetraceEnd += (lcdHRetraceEnd << 1); lcdHTotal += (lcdHTotal << 1); } lcdHRetraceStart -=8; /* HBlank = HRetrace - 1: for */ lcdHRetraceEnd -=8; /* compatibility with vgaHW.c */ } else { /* use modeline values if bios values don't work */ lcdHTotal = mode->CrtcHTotal; lcdHRetraceStart = mode->CrtcHSyncStart; lcdHRetraceEnd = mode->CrtcHSyncEnd; } /* The chip takes the size of the visible display area from the * CRTC values. We use bios screensize for LCD in LCD/dual mode * wether or not we use modeline for LCD. This way we can specify * always specify a smaller than default display size on LCD * by writing it to the CRTC registers. */ lcdHDisplay = cPtr->PanelSize.HDisplay; if (pScrn->bitsPerPixel == 16) { lcdHDisplay++; lcdHDisplay <<= 1; lcdHDisplay--; } else if (pScrn->bitsPerPixel == 24) { lcdHDisplay++; lcdHDisplay += (lcdHDisplay << 1); lcdHDisplay--; } lcdHTotal = (lcdHTotal >> 3) - 5; lcdHDisplay = (lcdHDisplay >> 3) - 1; lcdHRetraceStart = (lcdHRetraceStart >> 3); lcdHRetraceEnd = (lcdHRetraceEnd >> 3); /* This ugly hack is needed because CR01 and XR1C share the 8th bit!*/ CrtcHDisplay = ((mode->CrtcHDisplay >> 3) - 1); if ((lcdHDisplay & 0x100) != (CrtcHDisplay & 0x100)) { xf86ErrorF("This display configuration might cause problems !\n"); lcdHDisplay = 255; } /* now init register values */ ChipsNew->XR[0x17] = (((lcdHTotal) & 0x100) >> 8) | ((lcdHDisplay & 0x100) >> 7) | ((lcdHRetraceStart & 0x100) >> 6) | (((lcdHRetraceEnd) & 0x20) >> 2); ChipsNew->XR[0x19] = lcdHRetraceStart & 0xFF; ChipsNew->XR[0x1A] = lcdHRetraceEnd & 0x1F; /* XR1B: Alternate horizontal total */ /* used in all flat panel mode with horiz. compression disabled, */ /* CRT CGA text and graphic modes and Hercules graphics mode */ /* similar to CR00, actual value - 5 */ ChipsNew->XR[0x1B] = lcdHTotal & 0xFF; /*XR1C: Alternate horizontal blank start (CRT mode) */ /* /horizontal panel size (FP mode) */ /* FP horizontal panel size (FP mode), */ /* actual value - 1 (in characters unit) */ /* CRT horizontal blank start (CRT mode) */ /* similar to CR02, actual value - 1 */ ChipsNew->XR[0x1C] = lcdHDisplay & 0xFF; if (xf86ReturnOptValBool(cPtr->Options, OPTION_USE_MODELINE, FALSE)) { /* for ext. packed pixel mode on 64520/64530 */ /* no need to rescale: used only in 65530 */ ChipsNew->XR[0x21] = lcdHRetraceStart & 0xFF; ChipsNew->XR[0x22] = lcdHRetraceEnd & 0x1F; ChipsNew->XR[0x23] = lcdHTotal & 0xFF; /* vertical timing registers */ lcdVTotal = mode->CrtcVTotal - 2; lcdVDisplay = cPtr->PanelSize.VDisplay - 1; lcdVRetraceStart = mode->CrtcVSyncStart; lcdVRetraceEnd = mode->CrtcVSyncEnd; ChipsNew->XR[0x64] = lcdVTotal & 0xFF; ChipsNew->XR[0x66] = lcdVRetraceStart & 0xFF; ChipsNew->XR[0x67] = lcdVRetraceEnd & 0x0F; ChipsNew->XR[0x68] = lcdVDisplay & 0xFF; ChipsNew->XR[0x65] = ((lcdVTotal & 0x100) >> 8) | ((lcdVDisplay & 0x100) >> 7) | ((lcdVRetraceStart & 0x100) >> 6) | ((lcdVRetraceStart & 0x400) >> 7) | ((lcdVTotal & 0x400) >> 6) | ((lcdVTotal & 0x200) >> 4) | ((lcdVDisplay & 0x200) >> 3) | ((lcdVRetraceStart & 0x200) >> 2); /* * These are important: 0x2C specifies the numbers of lines * (hsync pulses) between vertical blank start and vertical * line total, 0x2D specifies the number of clock ticks? to * horiz. blank start ( caution ! 16bpp/24bpp modes: that's * why we need HSyncStart - can't use mode->CrtcHSyncStart) */ tmp = ((cPtr->PanelType & ChipsDD) && !(ChipsNew->XR[0x6F] & 0x02)) ? 1 : 0; /* double LP delay, FLM: 2 lines iff DD+no acc*/ /* Currently we support 2 FLM schemes: #1: FLM coincides with * VTotal ie. the delay is programmed to the difference bet- * ween lctVTotal and lcdVRetraceStart. #2: FLM coincides * lcdVRetraceStart - in this case FLM delay will be turned * off. To decide which scheme to use we compare the value of * XR2C set by the bios to the two schemes. The one that fits * better will be used. */ if (ChipsNew->XR[0x2C] < abs((cPtr->PanelSize.VTotal - cPtr->PanelSize.VRetraceStart - tmp - 1) - ChipsNew->XR[0x2C])) ChipsNew->XR[0x2F] |= 0x80; /* turn FLM delay off */ ChipsNew->XR[0x2C] = lcdVTotal - lcdVRetraceStart - tmp; /*ChipsNew->XR[0x2D] = (HSyncStart >> (3 - tmp)) & 0xFF;*/ ChipsNew->XR[0x2D] = (HDisplay >> (3 - tmp)) & 0xFF; ChipsNew->XR[0x2F] = (ChipsNew->XR[0x2F] & 0xDF) | (((HSyncStart >> (3 - tmp)) & 0x100) >> 3); } /* set stretching/centering */ if (!xf86ReturnOptValBool(cPtr->Options, OPTION_SUSPEND_HACK, FALSE)) { ChipsNew->XR[0x51] |= 0x40; /* enable FP compensation */ ChipsNew->XR[0x55] |= 0x01; /* enable horiz. compensation */ ChipsNew->XR[0x57] |= 0x01; /* enable horiz. compensation */ if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_STRETCH, FALSE)) { if (mode->CrtcHDisplay < 1489) /* HWBug */ ChipsNew->XR[0x55] |= 0x02; /* enable auto h-centering */ else { ChipsNew->XR[0x55] &= 0xFD; /* disable auto h-centering */ if (pScrn->bitsPerPixel == 24) /* ? */ ChipsNew->XR[0x56] = (lcdHDisplay - CrtcHDisplay) >> 1; } } else { ChipsNew->XR[0x55] &= 0xFD; /* disable h-centering */ ChipsNew->XR[0x56] = 0; } ChipsNew->XR[0x57] = 0x03; /* enable v-comp disable v-stretch */ if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_STRETCH, FALSE)) { ChipsNew->XR[0x55] |= 0x20; /* enable h-comp disable h-double*/ ChipsNew->XR[0x57] |= 0x60; /* Enable vertical stretching */ tmp = (mode->CrtcVDisplay / (cPtr->PanelSize.VDisplay - mode->CrtcVDisplay + 1)); if (tmp) { if (cPtr->PanelSize.HDisplay && cPtr->PanelSize.VDisplay && (cPtr->PanelSize.HDisplay != mode->CrtcHDisplay) && (cPtr->PanelSize.VDisplay != mode->CrtcVDisplay)) { /* Possible H/W bug? */ if(cPtr->Accel.UseHWCursor) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Disabling HW Cursor on stretched LCD\n"); cPtr->Flags &= ~ChipsHWCursor; } } if (cPtr->Flags & ChipsHWCursor) tmp = (tmp == 0 ? 1 : tmp); /* Bug when doubling */ ChipsNew->XR[0x5A] = tmp > 0x0F ? 0 : (unsigned char)tmp; } else { ChipsNew->XR[0x55] &= 0xDF; /* disable h-comp, h-double */ ChipsNew->XR[0x57] &= 0x9F; /* disable vertical stretching */ } } } /* set video mode */ ChipsNew->XR[0x2B] = chipsVideoMode(pScrn->depth, (cPtr->PanelType & ChipsLCD) ? min(HDisplay, cPtr->PanelSize.HDisplay) : HDisplay,cPtr->PanelSize.VDisplay); #ifdef DEBUG ErrorF("VESA Mode: %Xh\n", ChipsNew->XR[0x2B]); #endif /* set some linear specific registers */ if (cPtr->Flags & ChipsLinearSupport) { /* enable linear addressing */ ChipsNew->XR[0x0B] &= 0xFD; /* dual page clear */ ChipsNew->XR[0x0B] |= 0x10; /* linear mode on */ if (cPtr->Chipset == CHIPS_CT65535) ChipsNew->XR[0x08] = (unsigned char)(cPtr->FbAddress >> 17); else if (cPtr->Chipset > CHIPS_CT65535) ChipsNew->XR[0x08] = (unsigned char)(cPtr->FbAddress >> 20); else { /* Its probably set correctly by BIOS anyway. Leave it alone */ /* 65525 - 65530 require XR04[6] set for greater than 512k of */ /* ram. We only correct obvious bugs; VL probably uses MEMR/MEMW*/ if (cPtr->Bus == ChipsISA) ChipsNew->XR[0x04] &= ~0x40; /* A19 sceme */ if (pScrn->videoRam > 512) ChipsNew->XR[0x04] |= 0x40; /* MEMR/MEMW sceme */ } /* general setup */ ChipsNew->XR[0x03] |= 0x08; /* High bandwidth on 65548 */ ChipsNew->XR[0x40] = 0x01; /*BitBLT Draw Mode for 8 and 24 bpp */ } /* common general setup */ ChipsNew->XR[0x52] |= 0x01; /* Refresh count */ ChipsNew->XR[0x0F] &= 0xEF; /* not Hi-/True-Colour */ ChipsNew->XR[0x02] |= 0x01; /* 16bit CPU Memory Access */ ChipsNew->XR[0x02] &= 0xE3; /* Attr. Cont. default access */ /* use ext. regs. for hor. in dual */ ChipsNew->XR[0x06] &= 0xF3; /* bpp clear */ /* PCI */ if (cPtr->Bus == ChipsPCI) ChipsNew->XR[0x03] |= 0x40; /*PCI burst */ /* sync. polarities */ if ((mode->Flags & (V_PHSYNC | V_NHSYNC)) && (mode->Flags & (V_PVSYNC | V_NVSYNC))) { if (mode->Flags & (V_PHSYNC | V_NHSYNC)) { if (mode->Flags & V_PHSYNC) { ChipsNew->XR[0x55] &= 0xBF; /* CRT Hsync positive */ } else { ChipsNew->XR[0x55] |= 0x40; /* CRT Hsync negative */ } } if (mode->Flags & (V_PVSYNC | V_NVSYNC)) { if (mode->Flags & V_PVSYNC) { ChipsNew->XR[0x55] &= 0x7F; /* CRT Vsync positive */ } else { ChipsNew->XR[0x55] |= 0x80; /* CRT Vsync negative */ } } } /* bpp depend */ /*XR06: Palette control */ /* bit 0: Pixel Data Pin Diag, 0 for flat panel pix. data (def) */ /* bit 1: Internal DAC disable */ /* bit 3-2: Colour depth, 0 for 4 or 8 bpp, 1 for 16(5-5-5) bpp, */ /* 2 for 24 bpp, 3 for 16(5-6-5)bpp */ /* bit 4: Enable PC Video Overlay on colour key */ /* bit 5: Bypass Internal VGA palette */ /* bit 7-6: Colour reduction select, 0 for NTSC (default), */ /* 1 for Equivalent weighting, 2 for green only, */ /* 3 for Colour w/o reduction */ /* XR50 Panel Format Register 1 */ /* bit 1-0: Frame Rate Control; 00, No FRC; */ /* 01, 16-frame FRC for colour STN and monochrome */ /* 10, 2-frame FRC for colour TFT or monochrome; */ /* 11, reserved */ /* bit 3-2: Dither Enable */ /* 00, disable dithering; 01, enable dithering */ /* for 256 mode */ /* 10, enable dithering for all modes; 11, reserved */ /* bit6-4: Clock Divide (CD) */ /* 000, Shift Clock Freq = Dot Clock Freq; */ /* 001, SClk = DClk/2; 010 SClk = DClk/4; */ /* 011, SClk = DClk/8; 100 SClk = DClk/16; */ /* bit 7: TFT data width */ /* 0, 16 bit(565RGB); 1, 24bit (888RGB) */ if (pScrn->bitsPerPixel == 16) { ChipsNew->XR[0x06] |= 0xC4; /*15 or 16 bpp colour */ ChipsNew->XR[0x0F] |= 0x10; /*Hi-/True-Colour */ ChipsNew->XR[0x40] = 0x02; /*BitBLT Draw Mode for 16 bpp */ if (pScrn->weight.green != 5) ChipsNew->XR[0x06] |= 0x08; /*16bpp */ } else if (pScrn->bitsPerPixel == 24) { ChipsNew->XR[0x06] |= 0xC8; /*24 bpp colour */ ChipsNew->XR[0x0F] |= 0x10; /*Hi-/True-Colour */ if (xf86ReturnOptValBool(cPtr->Options, OPTION_18_BIT_BUS, FALSE)) { ChipsNew->XR[0x50] &= 0x7F; /*18 bit TFT data width */ } else { ChipsNew->XR[0x50] |= 0x80; /*24 bit TFT data width */ } } /*CRT only: interlaced mode */ if (!(cPtr->PanelType & ChipsLCD)) { if (mode->Flags & V_INTERLACE){ ChipsNew->XR[0x28] |= 0x20; /* set interlace */ /* empirical value */ tmp = ((((mode->CrtcHDisplay >> 3) - 1) >> 1) - 6 * (pScrn->bitsPerPixel >= 8 ? bytesPerPixel : 1 )); if(cPtr->Chipset < CHIPS_CT65535) ChipsNew->XR[0x19] = tmp & 0xFF; else ChipsNew->XR[0x29] = tmp & 0xFF; ChipsNew->XR[0x0F] &= ~0x40; /* set SW-Flag */ } else { ChipsNew->XR[0x28] &= ~0x20; /* unset interlace */ ChipsNew->XR[0x0F] |= 0x40; /* set SW-Flag */ } } /* STN specific */ if (IS_STN(cPtr->PanelType)) { ChipsNew->XR[0x50] &= ~0x03; /* FRC clear */ ChipsNew->XR[0x50] |= 0x01; /* 16 frame FRC */ ChipsNew->XR[0x50] &= ~0x0C; /* Dither clear */ ChipsNew->XR[0x50] |= 0x08; /* Dither all modes */ if (cPtr->Chipset == CHIPS_CT65548) { ChipsNew->XR[0x03] |= 0x20; /* CRT I/F priority */ ChipsNew->XR[0x04] |= 0x10; /* RAS precharge 65548 */ } } /* This stuff was emprically derived several years ago. Not sure its * still needed, and I'd love to get rid of it as its ugly */ switch (cPtr->Chipset) { case CHIPS_CT65545: /*jet mini *//*DEC HighNote Ultra DSTN */ ChipsNew->XR[0x03] |= 0x10; /* do not hold off CPU for palette acc*/ break; case CHIPS_CT65546: /*CT 65546, only for Toshiba */ ChipsNew->XR[0x05] |= 0x80; /* EDO RAM enable */ break; } if (cPtr->PanelType & ChipsLCD) ChipsNew->XR[0x51] |= 0x04; else ChipsNew->XR[0x51] &= ~0x04; /* Program the registers */ /*vgaHWProtect(pScrn, TRUE);*/ chipsRestore(pScrn, ChipsStd, ChipsNew, FALSE); /*vgaHWProtect(pScrn, FALSE);*/ return (TRUE); } static void chipsRestore(ScrnInfoPtr pScrn, vgaRegPtr VgaReg, CHIPSRegPtr ChipsReg, Bool restoreFonts) { vgaHWPtr hwp = VGAHWPTR(pScrn); CHIPSPtr cPtr = CHIPSPTR(pScrn); unsigned char tmp = 0; /*vgaHWProtect(pScrn, TRUE);*/ /* set registers so that we can program the controller */ if (IS_HiQV(cPtr)) { cPtr->writeXR(cPtr, 0x0E, 0x00); if (cPtr->Flags & ChipsDualChannelSupport) { tmp = cPtr->readFR(cPtr, 0x01); /* Disable pipeline */ cPtr->writeFR(cPtr, 0x01, (tmp & 0xFC)); cPtr->writeFR(cPtr, 0x02, 0x00); /* CRT/FP off */ } } else { cPtr->writeXR(cPtr, 0x10, 0x00); cPtr->writeXR(cPtr, 0x11, 0x00); tmp = cPtr->readXR(cPtr, 0x0C) & ~0x50; /* WINgine stores MSB here */ cPtr->writeXR(cPtr, 0x0C, tmp); cPtr->writeXR(cPtr, 0x15, 0x00); /* unprotect all registers */ tmp = cPtr->readXR(cPtr, 0x14); cPtr->writeXR(cPtr, 0x14, tmp & ~0x20); /* enable vsync on ST01 */ } chipsFixResume(pScrn); /* * Wait for vsync if sequencer is running - stop sequencer. * Only do if sync reset is ignored. Dual pipeline capable * chips have pipeline forced off here, so we don't care. */ if ((cPtr->SyncResetIgn) && (!(cPtr->Flags & ChipsDualChannelSupport))) { while (((hwp->readST01(hwp)) & 0x08) == 0x08); /* VSync off */ while (((hwp->readST01(hwp)) & 0x08) == 0x00); /* VSync on */ hwp->writeSeq(hwp, 0x07, 0x00); /* reset hsync - just in case... */ } /* set the clock */ chipsClockLoad(pScrn, &ChipsReg->Clock); /* chipsClockLoad() sets this so we don't want vgaHWRestore() change it */ VgaReg->MiscOutReg = inb(cPtr->PIOBase + 0x3CC); /* set extended regs */ chipsRestoreExtendedRegs(pScrn, ChipsReg); #if 0 /* if people complain about lock ups or blank screens -- reenable */ /* set CRTC registers - do it before sequencer restarts */ for (i=0; i<25; i++) hwp->writeCrtc(hwp, i, VgaReg->CRTC[i]); #endif /* set generic registers */ /* * Enabling writing to the colourmap causes 69030's to lock. * Anyone care to explain to me why ???? */ if (cPtr->Flags & ChipsDualChannelSupport) { /* Enable pipeline if needed */ cPtr->writeFR(cPtr, 0x01, ChipsReg->FR[0x01]); cPtr->writeFR(cPtr, 0x02, ChipsReg->FR[0x02]); vgaHWRestore(pScrn, VgaReg, VGA_SR_MODE | (restoreFonts ? VGA_SR_FONTS : 0)); } else { vgaHWRestore(pScrn, VgaReg, VGA_SR_MODE | VGA_SR_CMAP | (restoreFonts ? VGA_SR_FONTS : 0)); } /* set stretching registers */ if (IS_HiQV(cPtr)) { chipsRestoreStretching(pScrn, (unsigned char)ChipsReg->FR[0x40], (unsigned char)ChipsReg->FR[0x48]); #if 0 /* if people report about stretching not working -- reenable */ /* why twice ? : * sometimes the console is not well restored even if these registers * are good, re-write the registers works around it */ chipsRestoreStretching(pScrn, (unsigned char)ChipsReg->FR[0x40], (unsigned char)ChipsReg->FR[0x48]); #endif } else if (!IS_Wingine(cPtr)) chipsRestoreStretching(pScrn, (unsigned char)ChipsReg->XR[0x55], (unsigned char)ChipsReg->XR[0x57]); /* perform a synchronous reset */ if (!cPtr->SyncResetIgn) { if (!IS_HiQV(cPtr)) { /* enable syncronous reset on 655xx */ tmp = cPtr->readXR(cPtr, 0x0E); cPtr->writeXR(cPtr, 0x0E, tmp & 0x7F); } hwp->writeSeq(hwp, 0x00, 0x01); usleep(10000); hwp->writeSeq(hwp, 0x00, 0x03); if (!IS_HiQV(cPtr)) cPtr->writeXR(cPtr, 0x0E, tmp); } /* Flag valid start address, if using CRT extensions */ if (IS_HiQV(cPtr) && (ChipsReg->XR[0x09] & 0x1) == 0x1) { tmp = hwp->readCrtc(hwp, 0x40); hwp->writeCrtc(hwp, 0x40, tmp | 0x80); } /* Fix resume again here, as Nozomi seems to need it */ chipsFixResume(pScrn); /*vgaHWProtect(pScrn, FALSE);*/ #if 0 /* Enable pipeline if needed */ if (cPtr->Flags & ChipsDualChannelSupport) { cPtr->writeFR(cPtr, 0x01, ChipsReg->FR[0x01]); cPtr->writeFR(cPtr, 0x02, ChipsReg->FR[0x02]); } #endif } static void chipsRestoreExtendedRegs(ScrnInfoPtr pScrn, CHIPSRegPtr Regs) { vgaHWPtr hwp = VGAHWPTR(pScrn); CHIPSPtr cPtr = CHIPSPTR(pScrn); int i; unsigned char tmp; if (IS_HiQV(cPtr)) { /* set extended regs */ for (i = 0; i < 0x43; i++) { if ((cPtr->readXR(cPtr, i)) != Regs->XR[i]) cPtr->writeXR(cPtr, i, Regs->XR[i]); } /* Set SAR04 multimedia register correctly */ if ((cPtr->Flags & ChipsVideoSupport)) { #ifdef SAR04 cPtr->writeXR(cPtr, 0x4E, 0x04); if (cPtr->readXR(cPtr, 0x4F) != Regs->XR[0x4F]) cPtr->writeXR(cPtr, 0x4F, Regs->XR[0x4F]); #endif } /* Don't touch reserved memory control registers */ for (i = 0x50; i < 0xBF; i++) { if ((cPtr->readXR(cPtr, i)) != Regs->XR[i]) cPtr->writeXR(cPtr, i, Regs->XR[i]); } /* Don't touch VCLK regs, but fix up MClk */ /* set mem clock */ tmp = cPtr->readXR(cPtr, 0xCE); /* Select Fixed MClk before */ cPtr->writeXR(cPtr, 0xCE, tmp & 0x7F); if ((cPtr->readXR(cPtr, 0xCC)) != Regs->XR[0xCC]) cPtr->writeXR(cPtr, 0xCC, Regs->XR[0xCC]); if ((cPtr->readXR(cPtr, 0xCD)) != Regs->XR[0xCD]) cPtr->writeXR(cPtr, 0xCD, Regs->XR[0xCD]); if ((cPtr->readXR(cPtr, 0xCE)) != Regs->XR[0xCE]) cPtr->writeXR(cPtr, 0xCE, Regs->XR[0xCE]); /* set flat panel regs. */ for (i = 0xD0; i < 0xFF; i++) { if ((cPtr->readXR(cPtr, i)) != Regs->XR[i]) cPtr->writeXR(cPtr, i, Regs->XR[i]); } for (i = 0; i < 0x80; i++) { /* Don't touch alternate clock select reg. */ if ((i == 0x01) && (cPtr->Chipset == CHIPS_CT69030)) { /* restore the non clock bits */ tmp = cPtr->readFR(cPtr, 0x01); cPtr->writeFR(cPtr, 0x01, ((Regs->FR[0x01] & 0xF0) | (tmp & ~0xF0))); continue; } if ((i == 0x02) && (cPtr->Chipset == CHIPS_CT69030)) /* keep pipeline disabled till we are ready */ continue; if ((i == 0x03) && (cPtr->Chipset != CHIPS_CT69030)) { /* restore the non clock bits */ tmp = cPtr->readFR(cPtr, 0x03); cPtr->writeFR(cPtr, 0x03, ((Regs->FR[0x03] & 0xC3) | (tmp & ~0xC3))); continue; } if ((i > 0x03) && (cPtr->Chipset != CHIPS_CT69030) && (cPtr->SecondCrtc == TRUE)) continue; if ( (i == 0x40) || (i==0x48)) { /* !! set stretching but disable compensation */ cPtr->writeFR(cPtr, i, Regs->FR[i] & 0xFE); continue ; /* some registers must be set before FR40/FR48 */ } if ((cPtr->readFR(cPtr, i)) != Regs->FR[i]) { cPtr->writeFR(cPtr, i, Regs->FR[i]); } } /* set the multimedia regs */ for (i = 0x02; i < 0x80; i++) { if ( (i == 0x43) || (i == 0x44)) continue; if ((cPtr->readMR(cPtr, i)) != Regs->MR[i]) cPtr->writeMR(cPtr, i, Regs->MR[i]); } /* set extended crtc regs. */ for (i = 0x30; i < 0x80; i++) { if ((hwp->readCrtc(hwp, i)) != Regs->CR[i]) hwp->writeCrtc(hwp, i, Regs->CR[i]); } } else { /* set extended regs. */ for (i = 0; i < 0x30; i++) { if ((cPtr->readXR(cPtr, i)) != Regs->XR[i]) cPtr->writeXR(cPtr, i, Regs->XR[i]); } cPtr->writeXR(cPtr, 0x15, 0x00); /* unprotect just in case ... */ /* Don't touch MCLK/VCLK regs. */ for (i = 0x34; i < 0x54; i++) { if ((cPtr->readXR(cPtr, i)) != Regs->XR[i]) cPtr->writeXR(cPtr, i, Regs->XR[i]); } tmp = cPtr->readXR(cPtr, 0x54); /* restore the non clock bits */ cPtr->writeXR(cPtr, 0x54, ((Regs->XR[0x54] & 0xF3) | (tmp & ~0xF3))); cPtr->writeXR(cPtr, 0x55, Regs->XR[0x55] & 0xFE); /* h-comp off */ cPtr->writeXR(cPtr, 0x56, Regs->XR[0x56]); cPtr->writeXR(cPtr, 0x57, Regs->XR[0x57] & 0xFE); /* v-comp off */ for (i=0x58; i < 0x7D; i++) {/* don't touch XR7D and XR7F on WINGINE */ if ((cPtr->readXR(cPtr, i)) != Regs->XR[i]) cPtr->writeXR(cPtr, i, Regs->XR[i]); } } #ifdef DEBUG /* debug - dump out all the extended registers... */ if (IS_HiQV(cPtr)) { for (i = 0; i < 0xFF; i++) { ErrorF("XR%X - %X : %X\n", i, Regs->XR[i], cPtr->readXR(cPtr, i)); } for (i = 0; i < 0x80; i++) { ErrorF("FR%X - %X : %X\n", i, Regs->FR[i], cPtr->readFR(cPtr, i)); } } else { for (i = 0; i < 0x80; i++) { ErrorF("XR%X - %X : %X\n", i, Regs->XR[i], cPtr->readXR(cPtr, i)); } } #endif } static void chipsRestoreStretching(ScrnInfoPtr pScrn, unsigned char ctHorizontalStretch, unsigned char ctVerticalStretch) { unsigned char tmp; CHIPSPtr cPtr = CHIPSPTR(pScrn); /* write to regs. */ if (IS_HiQV(cPtr)) { tmp = cPtr->readFR(cPtr, 0x48); cPtr->writeFR(cPtr, 0x48, (tmp & 0xFE) | (ctVerticalStretch & 0x01)); tmp = cPtr->readFR(cPtr, 0x40); cPtr->writeFR(cPtr, 0x40, (tmp & 0xFE) | (ctHorizontalStretch & 0x01)); } else { tmp = cPtr->readXR(cPtr, 0x55); cPtr->writeXR(cPtr, 0x55, (tmp & 0xFE) | (ctHorizontalStretch & 0x01)); tmp = cPtr->readXR(cPtr, 0x57); cPtr->writeXR(cPtr, 0x57, (tmp & 0xFE) | (ctVerticalStretch & 0x01)); } usleep(20000); /* to be active */ } static int chipsVideoMode(int depth, int displayHSize, int displayVSize) { /* 4 bpp 8 bpp 16 bpp 18 bpp 24 bpp 32 bpp */ /* 640 0x20 0x30 0x40 - 0x50 - */ /* 800 0x22 0x32 0x42 - 0x52 - */ /*1024 0x24 0x34 0x44 - 0x54 - for 1024x768 */ /*1024 - 0x36 0x47 - 0x56 - for 1024x600 */ /*1152 0x27 0x37 0x47 - 0x57 - */ /*1280 0x28 0x38 0x49 - - - */ /*1600 0x2C 0x3C 0x4C 0x5D - - */ /*This value is only for BIOS.... */ int videoMode = 0; switch (depth) { case 1: case 4: videoMode = 0x20; break; case 8: videoMode = 0x30; break; case 15: videoMode = 0x40; break; case 16: videoMode = 0x41; break; default: videoMode = 0x50; break; } switch (displayHSize) { case 800: videoMode |= 0x02; break; case 1024: videoMode |= 0x04; if(displayVSize < 768) videoMode |= 0x02; break; case 1152: videoMode |= 0x07; break; case 1280: videoMode |= 0x08; break; case 1600: videoMode |= 0x0C; /*0x0A??*/ break; } return videoMode; } /* * Map the framebuffer and MMIO memory. */ static Bool chipsMapMem(ScrnInfoPtr pScrn) { CHIPSPtr cPtr = CHIPSPTR(pScrn); vgaHWPtr hwp = VGAHWPTR(pScrn); CHIPSEntPtr cPtrEnt; if (cPtr->Flags & ChipsLinearSupport) { if (cPtr->UseMMIO) { if (IS_HiQV(cPtr)) { #ifndef XSERVER_LIBPCIACCESS if (cPtr->pEnt->location.type == BUS_PCI) cPtr->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO_32BIT,cPtr->PciTag, cPtr->IOAddress, 0x20000L); else cPtr->MMIOBase = xf86MapVidMem(pScrn->scrnIndex, VIDMEM_MMIO_32BIT, cPtr->IOAddress, 0x20000L); #else { void** result = (void**)&cPtr->MMIOBase; int err = pci_device_map_range(cPtr->PciInfo, cPtr->IOAddress, 0x20000L, PCI_DEV_MAP_FLAG_WRITABLE, result); if (err) return FALSE; } #endif } else { #ifndef XSERVER_LIBPCIACCESS if (cPtr->pEnt->location.type == BUS_PCI) cPtr->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO_32BIT, cPtr->PciTag, cPtr->IOAddress, 0x10000L); else cPtr->MMIOBase = xf86MapVidMem(pScrn->scrnIndex, VIDMEM_MMIO_32BIT, cPtr->IOAddress, 0x10000L); #else { void** result = (void**)&cPtr->MMIOBase; int err = pci_device_map_range(cPtr->PciInfo, cPtr->IOAddress, 0x10000L, PCI_DEV_MAP_FLAG_WRITABLE, result); if (err) return FALSE; } #endif } if (cPtr->MMIOBase == NULL) return FALSE; } if (cPtr->FbMapSize) { unsigned long Addr = (unsigned long)cPtr->FbAddress; unsigned int Map = cPtr->FbMapSize; if ((cPtr->Flags & ChipsDualChannelSupport) && (xf86IsEntityShared(pScrn->entityList[0]))) { cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex)->ptr; if(cPtr->SecondCrtc == FALSE) { Addr = cPtrEnt->masterFbAddress; Map = cPtrEnt->masterFbMapSize; } else { Addr = cPtrEnt->slaveFbAddress; Map = cPtrEnt->slaveFbMapSize; } } #ifndef XSERVER_LIBPCIACCESS if (cPtr->pEnt->location.type == BUS_PCI) cPtr->FbBase = xf86MapPciMem(pScrn->scrnIndex,VIDMEM_FRAMEBUFFER, cPtr->PciTag, Addr, Map); else cPtr->FbBase = xf86MapVidMem(pScrn->scrnIndex,VIDMEM_FRAMEBUFFER, Addr, Map); #else { void** result = (void**)&cPtr->FbBase; int err = pci_device_map_range(cPtr->PciInfo, Addr, Map, PCI_DEV_MAP_FLAG_WRITABLE | PCI_DEV_MAP_FLAG_WRITE_COMBINE, result); if (err) return FALSE; } #endif if (cPtr->FbBase == NULL) return FALSE; } if (cPtr->Flags & ChipsFullMMIOSupport) { #ifndef XSERVER_LIBPCIACCESS cPtr->MMIOBaseVGA = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO,cPtr->PciTag, cPtr->IOAddress, 0x2000L); #else cPtr->MMIOBaseVGA = cPtr->MMIOBase; #endif /* 69030 MMIO Fix. * * The hardware lets us map the PipeB data registers * into the MMIO address space normally occupied by PipeA, * but it doesn't allow remapping of the index registers. * So we're forced to map a separate MMIO space for each * pipe and to toggle between them as necessary. -GHB */ if (cPtr->Flags & ChipsDualChannelSupport) #ifndef XSERVER_LIBPCIACCESS cPtr->MMIOBasePipeB = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO,cPtr->PciTag, cPtr->IOAddress + 0x800000, 0x2000L); #else { void** result = (void**)&cPtr->MMIOBasePipeB; int err = pci_device_map_range(cPtr->PciInfo, cPtr->IOAddress + 0x800000, 0x2000L, PCI_DEV_MAP_FLAG_WRITABLE, result); if (err) return FALSE; } #endif cPtr->MMIOBasePipeA = cPtr->MMIOBaseVGA; } } else { /* In paged mode Base is the VGA window at 0xA0000 */ cPtr->FbBase = hwp->Base; } return TRUE; } /* * Unmap the framebuffer and MMIO memory. */ static Bool chipsUnmapMem(ScrnInfoPtr pScrn) { CHIPSPtr cPtr = CHIPSPTR(pScrn); if (cPtr->Flags & ChipsLinearSupport) { if (IS_HiQV(cPtr)) { #ifndef XSERVER_LIBPCIACCESS if (cPtr->MMIOBase) xf86UnMapVidMem(pScrn->scrnIndex, (pointer)cPtr->MMIOBase, 0x20000); if (cPtr->MMIOBasePipeB) xf86UnMapVidMem(pScrn->scrnIndex, (pointer)cPtr->MMIOBasePipeB, 0x20000); #else if (cPtr->MMIOBase) pci_device_unmap_range(cPtr->PciInfo, cPtr->MMIOBase, 0x20000); if (cPtr->MMIOBasePipeB) pci_device_unmap_range(cPtr->PciInfo, cPtr->MMIOBasePipeB, 0x2000); #endif cPtr->MMIOBasePipeB = NULL; } else { #ifndef XSERVER_LIBPCIACCESS if (cPtr->MMIOBase) xf86UnMapVidMem(pScrn->scrnIndex, (pointer)cPtr->MMIOBase, 0x10000); #else if (cPtr->MMIOBase) pci_device_unmap_range(cPtr->PciInfo, cPtr->MMIOBase, 0x10000); #endif } cPtr->MMIOBase = NULL; #ifndef XSERVER_LIBPCIACCESS xf86UnMapVidMem(pScrn->scrnIndex, (pointer)cPtr->FbBase, cPtr->FbMapSize); #else pci_device_unmap_range(cPtr->PciInfo, cPtr->FbBase, cPtr->FbMapSize); #endif } cPtr->FbBase = NULL; return TRUE; } static void chipsProtect(ScrnInfoPtr pScrn, Bool on) { vgaHWProtect(pScrn, on); } static void chipsBlankScreen(ScrnInfoPtr pScrn, Bool unblank) { CHIPSPtr cPtr = CHIPSPTR(pScrn); vgaHWPtr hwp = VGAHWPTR(pScrn); unsigned char scrn; CHIPSEntPtr cPtrEnt; if (cPtr->UseDualChannel) { cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex)->ptr; DUALREOPEN; } /* fix things that could be messed up by suspend/resume */ if (!IS_HiQV(cPtr)) cPtr->writeXR(cPtr, 0x15, 0x00); scrn = hwp->readSeq(hwp, 0x01); if (unblank) { scrn &= 0xDF; /* enable screen */ } else { scrn |= 0x20; /* blank screen */ } /* synchronous reset - stop counters */ if (!cPtr->SyncResetIgn) { hwp->writeSeq(hwp, 0x00, 0x01); } hwp->writeSeq(hwp, 0x01, scrn); /* change mode */ /* end reset - start counters */ if (!cPtr->SyncResetIgn) { hwp->writeSeq(hwp, 0x00, 0x03); } if ((cPtr->UseDualChannel) && (! xf86IsEntityShared(pScrn->entityList[0]))) { unsigned int IOSS, MSS; IOSS = cPtr->readIOSS(cPtr); MSS = cPtr->readMSS(cPtr); cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | IOSS_PIPE_B)); cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B)); /* fix things that could be messed up by suspend/resume */ if (!IS_HiQV(cPtr)) cPtr->writeXR(cPtr, 0x15, 0x00); scrn = hwp->readSeq(hwp, 0x01); if (unblank) { scrn &= 0xDF; /* enable screen */ } else { scrn |= 0x20; /* blank screen */ } /* synchronous reset - stop counters */ if (!cPtr->SyncResetIgn) { hwp->writeSeq(hwp, 0x00, 0x01); } hwp->writeSeq(hwp, 0x01, scrn); /* change mode */ /* end reset - start counters */ if (!cPtr->SyncResetIgn) { hwp->writeSeq(hwp, 0x00, 0x03); } cPtr->writeIOSS(cPtr, IOSS); cPtr->writeMSS(cPtr, hwp, MSS); } } static void chipsLock(ScrnInfoPtr pScrn) { vgaHWPtr hwp = VGAHWPTR(pScrn); CHIPSPtr cPtr = CHIPSPTR(pScrn); unsigned char tmp; vgaHWLock(hwp); if (!IS_HiQV(cPtr)) { /* group protection attribute controller access */ cPtr->writeXR(cPtr, 0x15, cPtr->SuspendHack.xr15); tmp = cPtr->readXR(cPtr, 0x02); cPtr->writeXR(cPtr, 0x02, (tmp & ~0x18) | cPtr->SuspendHack.xr02); tmp = cPtr->readXR(cPtr, 0x14); cPtr->writeXR(cPtr, 0x14, (tmp & ~0x20) | cPtr->SuspendHack.xr14); /* reset 32 bit register access */ if (cPtr->Chipset > CHIPS_CT65540) { tmp = cPtr->readXR(cPtr, 0x03); cPtr->writeXR(cPtr, 0x03, (tmp & ~0x0A) | cPtr->SuspendHack.xr03); } } } static void chipsUnlock(ScrnInfoPtr pScrn) { vgaHWPtr hwp = VGAHWPTR(pScrn); CHIPSPtr cPtr = CHIPSPTR(pScrn); unsigned char tmp; if (!IS_HiQV(cPtr)) { /* group protection attribute controller access */ cPtr->writeXR(cPtr, 0x15, 0x00); tmp = cPtr->readXR(cPtr, 0x02); cPtr->writeXR(cPtr, 0x02, (tmp & ~0x18)); tmp = cPtr->readXR(cPtr, 0x14); cPtr->writeXR(cPtr, 0x14, (tmp & ~0x20)); /* enable 32 bit register access */ if (cPtr->Chipset > CHIPS_CT65540) { cPtr->writeXR(cPtr, 0x03, cPtr->SuspendHack.xr03 | 0x0A); } } vgaHWUnlock(hwp); } static void chipsHWCursorOn(CHIPSPtr cPtr, ScrnInfoPtr pScrn) { /* enable HW cursor */ if (cPtr->HWCursorShown) { if (IS_HiQV(cPtr)) { cPtr->writeXR(cPtr, 0xA0, cPtr->HWCursorContents & 0xFF); if (cPtr->UseDualChannel && (! xf86IsEntityShared(pScrn->entityList[0]))) { unsigned int IOSS, MSS; IOSS = cPtr->readIOSS(cPtr); MSS = cPtr->readMSS(cPtr); cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | IOSS_PIPE_B)); cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B)); cPtr->writeXR(cPtr, 0xA0, cPtr->HWCursorContents & 0xFF); cPtr->writeIOSS(cPtr, IOSS); cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), MSS); } } else { HW_DEBUG(0x8); if (cPtr->UseMMIO) { MMIOmeml(DR(0x8)) = cPtr->HWCursorContents; } else { outl(cPtr->PIOBase + DR(0x8), cPtr->HWCursorContents); } } } } static void chipsHWCursorOff(CHIPSPtr cPtr, ScrnInfoPtr pScrn) { /* disable HW cursor */ if (cPtr->HWCursorShown) { if (IS_HiQV(cPtr)) { cPtr->HWCursorContents = cPtr->readXR(cPtr, 0xA0); cPtr->writeXR(cPtr, 0xA0, cPtr->HWCursorContents & 0xF8); } else { HW_DEBUG(0x8); if (cPtr->UseMMIO) { cPtr->HWCursorContents = MMIOmeml(DR(0x8)); /* Below used to be MMIOmemw() change back if problem!!! */ /* Also see ct_cursor.c */ MMIOmeml(DR(0x8)) = cPtr->HWCursorContents & 0xFFFE; } else { cPtr->HWCursorContents = inl(cPtr->PIOBase + DR(0x8)); outw(cPtr->PIOBase + DR(0x8), cPtr->HWCursorContents & 0xFFFE); } } } } void chipsFixResume(ScrnInfoPtr pScrn) { CHIPSPtr cPtr = CHIPSPTR(pScrn); vgaHWPtr hwp = VGAHWPTR(pScrn); unsigned char tmp; /* fix things that could be messed up by suspend/resume */ if (!IS_HiQV(cPtr)) cPtr->writeXR(cPtr, 0x15, 0x00); tmp = hwp->readMiscOut(hwp); hwp->writeMiscOut(hwp, (tmp & 0xFE) | cPtr->SuspendHack.vgaIOBaseFlag); tmp = hwp->readCrtc(hwp, 0x11); hwp->writeCrtc(hwp, 0x11, (tmp & 0x7F)); } static char chipsTestDACComp(ScrnInfoPtr pScrn, unsigned char a, unsigned char b, unsigned char c) { vgaHWPtr hwp = VGAHWPTR(pScrn); unsigned char type; hwp->writeDacWriteAddr(hwp, 0x00); while ((hwp->readST01(hwp)) & 0x08){}; /* wait for vsync to end */ while (!((hwp->readST01(hwp)) & 0x08)){}; /* wait for new vsync */ hwp->writeDacData(hwp, a); /* set pattern */ hwp->writeDacData(hwp, b); hwp->writeDacData(hwp, c); while (!(hwp->readST01(hwp)) & 0x01){}; /* wait for hsync to end */ while ((hwp->readST01(hwp)) & 0x01){}; /* wait for hsync to end */ type = hwp->readST00(hwp); /* read comparator */ return (type & 0x10); } static int chipsProbeMonitor(ScrnInfoPtr pScrn) { CHIPSPtr cPtr = CHIPSPTR(pScrn); vgaHWPtr hwp = VGAHWPTR(pScrn); unsigned char dacmask; unsigned char dacdata[3]; unsigned char xr1, xr2; int type = 2; /* no monitor */ unsigned char IOSS=0, MSS=0, tmpfr02=0, tmpfr01a=0, tmpfr01b=0; /* Dual channel display, enable both pipelines */ if (cPtr->Flags & ChipsDualChannelSupport) { IOSS = cPtr->readIOSS(cPtr); MSS = cPtr->readMSS(cPtr); tmpfr02 = cPtr->readFR(cPtr,0x02); cPtr->writeFR(cPtr, 0x02, (tmpfr02 & 0xCF)); /* CRT/FP off */ usleep(1000); cPtr->writeIOSS(cPtr, ((IOSS & IOSS_MASK) | IOSS_PIPE_A)); cPtr->writeMSS(cPtr, hwp, ((MSS & MSS_MASK) | MSS_PIPE_A)); tmpfr01a = cPtr->readFR(cPtr,0x01); if ((tmpfr01a & 0x3) != 0x01) cPtr->writeFR(cPtr, 0x01, ((tmpfr01a & 0xFC) | 0x1)); cPtr->writeIOSS(cPtr, ((IOSS & IOSS_MASK) | IOSS_PIPE_B)); cPtr->writeMSS(cPtr, hwp, ((MSS & MSS_MASK) | MSS_PIPE_B)); tmpfr01b = cPtr->readFR(cPtr,0x01); if ((tmpfr01b & 0x3) != 0x01) cPtr->writeFR(cPtr, 0x01, ((tmpfr01b & 0xFC) | 0x1)); cPtr->writeIOSS(cPtr, IOSS); cPtr->writeMSS(cPtr, hwp, MSS); cPtr->writeFR(cPtr, 0x02, (tmpfr02 & 0xCF) | 0x10); /* CRT on/FP off*/ } dacmask = hwp->readDacMask(hwp); /* save registers */ hwp->writeDacMask(hwp, 0x00); hwp->writeDacReadAddr(hwp, 0x00); dacdata[0]=hwp->readDacData(hwp); dacdata[1]=hwp->readDacData(hwp); dacdata[2]=hwp->readDacData(hwp); if (!IS_HiQV(cPtr)) { xr1 = cPtr->readXR(cPtr, 0x06); xr2 = cPtr->readXR(cPtr, 0x1F); cPtr->writeXR(cPtr, 0x06, xr1 & 0xF1); /* turn on dac */ cPtr->writeXR(cPtr, 0x1F, xr2 & 0x7F); /* enable comp */ } else { xr1 = cPtr->readXR(cPtr, 0x81); xr2 = cPtr->readXR(cPtr, 0xD0); cPtr->writeXR(cPtr, 0x81,(xr1 & 0xF0)); cPtr->writeXR(cPtr, 0xD0,(xr2 | 0x03)); } if (chipsTestDACComp(pScrn, 0x12,0x12,0x12)) { /* test patterns */ if (chipsTestDACComp(pScrn,0x14,0x14,0x14)) /* taken from */ if (!chipsTestDACComp(pScrn,0x2D,0x14,0x14)) /* BIOS */ if (!chipsTestDACComp(pScrn,0x14,0x2D,0x14)) if (!chipsTestDACComp(pScrn,0x14,0x14,0x2D)) if (!chipsTestDACComp(pScrn,0x2D,0x2D,0x2D)) type = 0; /* color monitor */ } else { if (chipsTestDACComp(pScrn,0x04,0x12,0x04)) if (!chipsTestDACComp(pScrn,0x1E,0x12,0x04)) if (!chipsTestDACComp(pScrn,0x04,0x2D,0x04)) if (!chipsTestDACComp(pScrn,0x1E,0x16,0x15)) if (chipsTestDACComp(pScrn,0x00,0x00,0x00)) type = 1; /* monochrome */ } hwp->writeDacWriteAddr(hwp, 0x00); /* restore registers */ hwp->writeDacData(hwp, dacdata[0]); hwp->writeDacData(hwp, dacdata[1]); hwp->writeDacData(hwp, dacdata[2]); hwp->writeDacMask(hwp, dacmask); if (!IS_HiQV(cPtr)) { cPtr->writeXR(cPtr,0x06,xr1); cPtr->writeXR(cPtr,0x1F,xr2); } else { cPtr->writeXR(cPtr,0x81,xr1); cPtr->writeXR(cPtr,0xD0,xr2); } if (cPtr->Flags & ChipsDualChannelSupport) { cPtr->writeIOSS(cPtr, ((IOSS & IOSS_MASK) | IOSS_PIPE_A)); cPtr->writeMSS(cPtr, hwp, ((MSS & MSS_MASK) | MSS_PIPE_A)); cPtr->writeFR(cPtr, 0x01, tmpfr01a); cPtr->writeIOSS(cPtr, ((IOSS & IOSS_MASK) | IOSS_PIPE_B)); cPtr->writeMSS(cPtr, hwp, ((MSS & MSS_MASK) | MSS_PIPE_B)); cPtr->writeFR(cPtr, 0x01, tmpfr01b); usleep(1000); cPtr->writeIOSS(cPtr, IOSS); cPtr->writeMSS(cPtr, hwp, MSS); cPtr->writeFR(cPtr, 0x02, tmpfr02); } return type; } static int chipsSetMonitor(ScrnInfoPtr pScrn) { int tmp= chipsProbeMonitor(pScrn); switch (tmp) { case 0: xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Color monitor detected\n"); break; case 1: xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Monochrome monitor detected\n"); break; default: xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "No monitor detected\n"); } return (tmp); } static void chipsSetPanelType(CHIPSPtr cPtr) { CARD8 tmp; if (IS_HiQV(cPtr)) { if (cPtr->Chipset == CHIPS_CT69030) { tmp = cPtr->readFR(cPtr, 0x00); if (tmp & 0x20) { /* FR02: DISPLAY TYPE REGISTER */ /* FR02[4] = CRT, FR02[5] = FlatPanel */ tmp = cPtr->readFR(cPtr, 0x02); if (tmp & 0x10) cPtr->PanelType |= ChipsCRT; if (tmp & 0x20) cPtr->PanelType |= ChipsLCD | ChipsLCDProbed; } else { cPtr->PanelType |= ChipsCRT; } } else { /* test LCD */ /* FR01: DISPLAY TYPE REGISTER */ /* FR01[1:0]: Display Type, 01 = CRT, 10 = FlatPanel */ /* LCD */ tmp = cPtr->readFR(cPtr, 0x01); if ((tmp & 0x03) == 0x02) { cPtr->PanelType |= ChipsLCD | ChipsLCDProbed; } tmp = cPtr->readXR(cPtr,0xD0); if (tmp & 0x01) { cPtr->PanelType |= ChipsCRT; } } } else { tmp = cPtr->readXR(cPtr, 0x51); /* test LCD */ /* XR51: DISPLAY TYPE REGISTER */ /* XR51[2]: Display Type, 0 = CRT, 1 = FlatPanel */ if (tmp & 0x04) { cPtr->PanelType |= ChipsLCD | ChipsLCDProbed; } if ((cPtr->readXR(cPtr, 0x06)) & 0x02) { cPtr->PanelType |= ChipsCRT; } } } static void chipsBlockHandler (BLOCKHANDLER_ARGS_DECL) { SCREEN_PTR(arg); ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); CHIPSPtr cPtr = CHIPSPTR(pScrn); pScreen->BlockHandler = cPtr->BlockHandler; (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS); pScreen->BlockHandler = chipsBlockHandler; if(cPtr->VideoTimerCallback) { UpdateCurrentTime(); (*cPtr->VideoTimerCallback)(pScrn, currentTime.milliseconds); } }