eb05615134
mibstore.h defines miInitializeBackingStore() as an empty stub, and goes away in xserver 1.14.
7503 lines
230 KiB
C
7503 lines
230 KiB
C
/*
|
|
* Copyright 1993 by Jon Block <block@frc.com>
|
|
* Modified by Mike Hollick <hollick@graphics.cis.upenn.edu>
|
|
* Modified 1994 by Régis Cridlig <cridlig@dmi.ens.fr>
|
|
*
|
|
* Major Contributors to XFree86 3.2
|
|
* Modified 1995/6 by Nozomi Ytow
|
|
* Modified 1996 by Egbert Eich <eich@xfree86.org>
|
|
* Modified 1996 by David Bateman <dbateman@club-internet.fr>
|
|
* Modified 1996 by Xavier Ducoin <xavier@rd.lectra.fr>
|
|
*
|
|
* Contributors to XFree86 3.2
|
|
* Modified 1995/6 by Ken Raeburn <raeburn@raeburn.org>
|
|
* Modified 1996 by Shigehiro Nomura <nomura@sm.sony.co.jp>
|
|
* Modified 1996 by Marc de Courville <marc@courville.org>
|
|
* Modified 1996 by Adam Sulmicki <adam@cfar.umd.edu>
|
|
* Modified 1996 by Jens Maurer <jmaurer@cck.uni-kl.de>
|
|
*
|
|
* Large parts rewritten for XFree86 4.0
|
|
* Modified 1998 by David Bateman <dbateman@club-internet.fr>
|
|
* Modified 1998 by Egbert Eich <eich@xfree86.org>
|
|
* 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; i<pScrn->numEntities; 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 <raeburn@raeburn.org> 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);
|
|
}
|
|
}
|