summaryrefslogtreecommitdiff
path: root/src/via_driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/via_driver.c')
-rw-r--r--src/via_driver.c3276
1 files changed, 3276 insertions, 0 deletions
diff --git a/src/via_driver.c b/src/via_driver.c
new file mode 100644
index 0000000..c442134
--- /dev/null
+++ b/src/via_driver.c
@@ -0,0 +1,3276 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/via/via_driver.c,v 1.16 2003/10/31 17:19:35 tsi Exp $ */
+/*
+ * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
+ * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/*************************************************************************
+ *
+ * File: via_driver.c
+ * Content: XFree86 4.0 for VIA/S3G UniChrom
+ *
+ ************************************************************************/
+
+#include "xf86RAC.h"
+#include "shadowfb.h"
+
+#include "globals.h"
+#define DPMS_SERVER
+#include "extensions/dpms.h"
+
+
+#include "via_driver.h"
+#include "via_video.h"
+#include "videodev.h"
+#include "via_swov.h"
+
+#include "ddmpeg.h"
+#include "via_capture.h"
+#include "via.h"
+#ifdef XF86DRI
+#include "dri.h"
+#endif
+
+/*
+ * prototypes
+ */
+
+static void VIAIdentify(int flags);
+static Bool VIAProbe(DriverPtr drv, int flags);
+static Bool VIAPreInit(ScrnInfoPtr pScrn, int flags);
+static Bool VIAEnterVT(int scrnIndex, int flags);
+static void VIALeaveVT(int scrnIndex, int flags);
+static void VIASave(ScrnInfoPtr pScrn);
+static void VIAWriteMode(ScrnInfoPtr pScrn, vgaRegPtr, VIARegPtr);
+static Bool VIAModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
+static Bool VIACloseScreen(int scrnIndex, ScreenPtr pScreen);
+static Bool VIASaveScreen(ScreenPtr pScreen, int mode);
+static void VIALoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies,
+ LOCO *colors, VisualPtr pVisual);
+static Bool VIAScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
+ char **argv);
+static int VIAInternalScreenInit(int scrnIndex, ScreenPtr pScreen);
+static void VIAFreeScreen(int scrnIndex, int flags);
+static ModeStatus VIAValidMode(int index, DisplayModePtr mode,
+ Bool verbose, int flags);
+static void VIADPMS(ScrnInfoPtr pScrn, int mode, int flags);
+static const OptionInfoRec * VIAAvailableOptions(int chipid, int busid);
+
+
+static void VIAEnableMMIO(ScrnInfoPtr pScrn);
+static void VIADisableMMIO(ScrnInfoPtr pScrn);
+static Bool VIAMapMMIO(ScrnInfoPtr pScrn);
+static Bool VIAMapFB(ScrnInfoPtr pScrn);
+static void VIAUnmapMem(ScrnInfoPtr pScrn);
+static int VIAGetMemSize(void);
+Bool VIADeviceSelection(ScrnInfoPtr pScrn);
+Bool VIADeviceDispatch(ScrnInfoPtr pScrn);
+
+#ifdef XF86DRI
+void VIAInitialize3DEngine(ScrnInfoPtr pScrn);
+#endif
+
+DriverRec VIA =
+{
+ VIA_VERSION,
+ DRIVER_NAME,
+ VIAIdentify,
+ VIAProbe,
+ VIAAvailableOptions,
+ NULL,
+ 0
+};
+
+
+/* Supported chipsets */
+
+static SymTabRec VIAChipsets[] = {
+ {VIA_CLE266, "CLE266"},
+ {VIA_KM400, "KM400"},
+ {VIA_K8M800, "K8M800"},
+ {-1, NULL }
+};
+
+
+/* This table maps a PCI device ID to a chipset family identifier. */
+
+static PciChipsets VIAPciChipsets[] = {
+ {VIA_CLE266, PCI_CHIP_CLE3122, RES_SHARED_VGA},
+ {VIA_CLE266, PCI_CHIP_CLE3022, RES_SHARED_VGA},
+ {VIA_KM400, PCI_CHIP_VT7205, RES_SHARED_VGA},
+ {VIA_KM400, PCI_CHIP_VT3205, RES_SHARED_VGA},
+ {VIA_K8M800, PCI_CHIP_VT7204, RES_SHARED_VGA},
+ {VIA_K8M800, PCI_CHIP_VT3204, RES_SHARED_VGA},
+ {-1, -1, RES_UNDEFINED}
+};
+
+int gVIAEntityIndex = -1;
+
+typedef enum {
+ OPTION_A2,
+ OPTION_PCI_BURST,
+ OPTION_PCI_RETRY,
+ OPTION_NOACCEL,
+ OPTION_SWCURSOR,
+ OPTION_HWCURSOR,
+ OPTION_SHADOW_FB,
+ OPTION_ROTATE,
+ OPTION_USEBIOS,
+ OPTION_VIDEORAM,
+ OPTION_ACTIVEDEVICE,
+ OPTION_LCDDUALEDGE,
+ OPTION_BUSWIDTH,
+ OPTION_CENTER,
+ OPTION_PANELSIZE,
+ OPTION_TVDOTCRAWL,
+ OPTION_TVTYPE,
+ OPTION_TVOUTPUT,
+ OPTION_TVVSCAN,
+ OPTION_TVHSCALE,
+ OPTION_TVENCODER,
+ OPTION_REFRESH,
+ OPTION_DISABLEVQ,
+ OPTION_NODDCVALUE,
+ OPTION_CAP0_DEINTERLACE,
+ OPTION_CAP1_DEINTERLACE,
+ OPTION_CAP0_FIELDSWAP,
+ OPTION_DRIXINERAMA
+} VIAOpts;
+
+
+static OptionInfoRec VIAOptions[] =
+{
+ {OPTION_A2, "A2", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_HWCURSOR, "HWCursor", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_SWCURSOR, "SWCursor", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE},
+ {OPTION_USEBIOS, "UseBIOS", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_VIDEORAM, "VideoRAM", OPTV_INTEGER, {0}, FALSE},
+ {OPTION_ACTIVEDEVICE, "ActiveDevice", OPTV_ANYSTR, {0}, FALSE},
+ {OPTION_LCDDUALEDGE, "LCDDualEdge", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_BUSWIDTH, "BusWidth", OPTV_ANYSTR, {0}, FALSE},
+ {OPTION_CENTER, "Center", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_PANELSIZE, "PanelSize", OPTV_ANYSTR, {0}, FALSE},
+ {OPTION_TVDOTCRAWL, "TVDotCrawl", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_TVTYPE, "TVType", OPTV_ANYSTR, {0}, FALSE},
+ {OPTION_TVOUTPUT, "TVOutput", OPTV_ANYSTR, {0}, FALSE},
+ {OPTION_TVVSCAN, "TVVScan", OPTV_ANYSTR, {0}, FALSE},
+ {OPTION_TVHSCALE, "TVHScale", OPTV_ANYSTR, {0}, FALSE},
+ {OPTION_TVENCODER, "TVEncoder", OPTV_ANYSTR, {0}, FALSE},
+ {OPTION_REFRESH, "Refresh", OPTV_INTEGER, {0}, FALSE},
+ {OPTION_DISABLEVQ, "DisableVQ", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_NODDCVALUE, "NoDDCValue", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_CAP0_DEINTERLACE, "Cap0Deinterlace", OPTV_ANYSTR, {0}, FALSE},
+ {OPTION_CAP1_DEINTERLACE, "Cap1Deinterlace", OPTV_ANYSTR, {0}, FALSE},
+ {OPTION_CAP0_FIELDSWAP, "Cap0FieldSwap", OPTV_BOOLEAN, {0}, FALSE},
+ {OPTION_DRIXINERAMA, "DRIXINERAMA", OPTV_BOOLEAN, {0}, FALSE},
+ {-1, NULL, OPTV_NONE, {0}, FALSE}
+};
+
+
+static const char *vgaHWSymbols[] = {
+ "vgaHWGetHWRec",
+ "vgaHWSetMmioFuncs",
+ "vgaHWSetStdFuncs",
+ "vgaHWGetIOBase",
+ "vgaHWSave",
+ "vgaHWProtect",
+ "vgaHWRestore",
+ "vgaHWMapMem",
+ "vgaHWUnmapMem",
+ "vgaHWInit",
+ "vgaHWSaveScreen",
+ "vgaHWLock",
+ "vgaHWUnlock",
+ "vgaHWFreeHWRec",
+ NULL
+};
+
+
+static const char *ramdacSymbols[] = {
+ "xf86InitCursor",
+ "xf86CreateCursorInfoRec",
+ "xf86DestroyCursorInfoRec",
+ NULL
+};
+
+static const char *vbeSymbols[] = {
+ "VBEInit",
+ "vbeDoEDID",
+ "vbeFree",
+ NULL
+};
+
+static const char *ddcSymbols[] = {
+ "xf86InterpretEDID",
+ "xf86PrintEDID",
+ "xf86DoEDID_DDC1",
+ "xf86DoEDID_DDC2",
+ "xf86SetDDCproperties",
+ NULL
+};
+
+
+static const char *i2cSymbols[] = {
+ "xf86CreateI2CBusRec",
+ "xf86I2CBusInit",
+ "xf86CreateI2CDevRec",
+ "xf86I2CDevInit",
+ "xf86I2CWriteRead",
+ "xf86DestroyI2CDevRec",
+ NULL
+};
+
+static const char *xaaSymbols[] = {
+ "XAACopyROP",
+ "XAACopyROP_PM",
+ "XAAPatternROP",
+ "XAACreateInfoRec",
+ "XAADestroyInfoRec",
+ "XAAInit",
+ "XAAFillSolidRects",
+ NULL
+};
+
+static const char *int10Symbols[] = {
+ "xf86FreeInt10",
+ "xf86InitInt10",
+ NULL
+};
+
+static const char *shadowSymbols[] = {
+ "ShadowFBInit",
+ NULL
+};
+
+#ifdef USE_FB
+static const char *fbSymbols[] = {
+ "fbScreenInit",
+ "fbPictureInit",
+ NULL
+};
+#else
+static const char *cfbSymbols[] = {
+ "cfbScreenInit",
+ "cfb16ScreenInit",
+ "cfb24ScreenInit",
+ "cfb24_32ScreenInit",
+ "cfb32ScreenInit",
+ "cfb16BresS",
+ "cfb24BresS",
+ NULL
+};
+#endif
+
+#ifdef XFree86LOADER
+#ifdef XF86DRI
+static const char *drmSymbols[] = {
+ "drmAddBufs",
+ "drmAddMap",
+ "drmAgpAcquire",
+ "drmAgpAlloc",
+ "drmAgpBase",
+ "drmAgpBind",
+ "drmAgpDeviceId",
+ "drmAgpEnable",
+ "drmAgpFree",
+ "drmAgpGetMode",
+ "drmAgpRelease",
+ "drmAgpVendorId",
+ "drmCtlInstHandler",
+ "drmCtlUninstHandler",
+ "drmCommandNone",
+ "drmCommandWrite",
+ "drmFreeVersion",
+ "drmGetInterruptFromBusID",
+ "drmGetLibVersion",
+ "drmGetVersion",
+ "drmMap",
+ "drmMapBufs",
+ "drmUnmap",
+ "drmUnmapBufs",
+ NULL
+};
+
+static const char *driSymbols[] = {
+ "DRICloseScreen",
+ "DRICreateInfoRec",
+ "DRIDestroyInfoRec",
+ "DRIFinishScreenInit",
+ "DRIGetSAREAPrivate",
+ "DRILock",
+ "DRIQueryVersion",
+ "DRIScreenInit",
+ "DRIUnlock",
+ "GlxSetVisualConfigs",
+ NULL
+};
+#endif
+
+static MODULESETUPPROTO(VIASetup);
+
+static XF86ModuleVersionInfo VIAVersRec = {
+ "via",
+ MODULEVENDORSTRING,
+ MODINFOSTRING1,
+ MODINFOSTRING2,
+ XF86_VERSION_CURRENT,
+ VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL,
+ ABI_CLASS_VIDEODRV,
+ ABI_VIDEODRV_VERSION,
+ MOD_CLASS_VIDEODRV,
+ {0, 0, 0, 0}
+};
+
+XF86ModuleData viaModuleData = {&VIAVersRec, VIASetup, NULL};
+
+
+static pointer VIASetup(pointer module, pointer opts, int *errmaj, int *errmin)
+{
+ static Bool setupDone = FALSE;
+
+ if (!setupDone) {
+ setupDone = TRUE;
+ xf86AddDriver(&VIA, module, 0);
+ LoaderRefSymLists(vgaHWSymbols,
+#ifdef USE_FB
+ fbSymbols,
+#else
+ cfbSymbols,
+#endif
+ ramdacSymbols,
+ xaaSymbols,
+ shadowSymbols,
+ vbeSymbols,
+ i2cSymbols,
+ ddcSymbols,
+ /*
+ mpegSymbols,
+ */
+#ifdef XF86DRI
+ drmSymbols,
+ driSymbols,
+#endif
+ NULL);
+
+ return (pointer) 1;
+ }
+ else {
+ if (errmaj)
+ *errmaj = LDR_ONCEONLY;
+
+ return NULL;
+ }
+} /* VIASetup */
+
+#endif /* XFree86LOADER */
+
+static void viaFillGraphicInfo(ScrnInfoPtr pScrn)
+{
+ VIAPtr pVia = VIAPTR(pScrn);
+ VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+
+ pVia->graphicInfo.TotalVRAM = pVia->videoRambytes;
+ pVia->graphicInfo.VideoHeapBase = (unsigned long) pVia->FBFreeStart;
+ pVia->graphicInfo.VideoHeapEnd = (unsigned long) (pVia->FBFreeEnd - 1);
+ pVia->graphicInfo.dwWidth = pBIOSInfo->CrtcHDisplay;
+ pVia->graphicInfo.dwHeight = pBIOSInfo->CrtcVDisplay;
+ pVia->graphicInfo.dwBPP = pScrn->bitsPerPixel;
+ pVia->graphicInfo.dwPitch = (((pScrn->virtualX) + 15) & ~15) * (pScrn->bitsPerPixel) / 8;
+ pVia->graphicInfo.dwRefreshRate = (unsigned long)pBIOSInfo->FoundRefresh;
+ pVia->graphicInfo.dwDVIOn = pBIOSInfo->DVIAttach;
+ pVia->graphicInfo.dwExpand = pBIOSInfo->scaleY;
+ pVia->graphicInfo.dwPanelWidth = pBIOSInfo->panelX;
+ pVia->graphicInfo.dwPanelHeight = pBIOSInfo->panelY;
+ pVia->graphicInfo.Cap0_Deinterlace = pVia->Cap0_Deinterlace;
+ pVia->graphicInfo.Cap1_Deinterlace = pVia->Cap1_Deinterlace;
+ pVia->graphicInfo.Cap0_FieldSwap = pVia->Cap0_FieldSwap;
+ pVia->graphicInfo.RevisionID = pVia->ChipRev;
+
+ /* for SAMM mode passing screen info */
+ pVia->graphicInfo.HasSecondary = pBIOSInfo->HasSecondary;
+ pVia->graphicInfo.IsSecondary = pBIOSInfo->IsSecondary;
+
+ /* Added to pass DRM info to V4L */
+#ifdef XF86DRI
+ pVia->graphicInfo.DRMEnabled = pVia->directRenderingEnabled;
+#endif
+}
+
+static int
+WaitIdleCLE266(VIAPtr pVia)
+{
+ int loop = 0;
+
+ mem_barrier();
+
+ while (!(VIAGETREG(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && (loop++ < MAXLOOP))
+ ;
+
+ while ((VIAGETREG(VIA_REG_STATUS) &
+ (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY)) &&
+ (loop++ < MAXLOOP))
+ ;
+
+ return loop >= MAXLOOP;
+}
+
+
+static Bool VIAGetRec(ScrnInfoPtr pScrn)
+{
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAGetRec\n"));
+ if (pScrn->driverPrivate)
+ return TRUE;
+
+ pScrn->driverPrivate = xnfcalloc(sizeof(VIARec), 1);
+ ((VIARec *)(pScrn->driverPrivate))->pBIOSInfo =
+ xnfcalloc(sizeof(VIABIOSInfoRec), 1);
+ ((VIARec *)(pScrn->driverPrivate))->pBIOSInfo->pModeTable =
+ xnfcalloc(sizeof(VIAModeTableRec), 1);
+
+ /* initial value in VIARec */
+ ((VIARec *)(pScrn->driverPrivate))->SavedReg.mode = 0xFF;
+ ((VIARec *)(pScrn->driverPrivate))->ModeReg.mode = 0xFF;
+
+ ((VIARec *)(pScrn->driverPrivate))->pBIOSInfo->FirstInit = TRUE;
+
+ return TRUE;
+
+} /* VIAGetRec */
+
+
+static void VIAFreeRec(ScrnInfoPtr pScrn)
+{
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAFreeRec\n"));
+ if (!pScrn->driverPrivate)
+ return;
+
+ xfree(((VIARec *)(pScrn->driverPrivate))->pBIOSInfo->pModeTable);
+ xfree(((VIARec *)(pScrn->driverPrivate))->pBIOSInfo);
+ xfree(pScrn->driverPrivate);
+ pScrn->driverPrivate = NULL;
+
+ VIAUnmapMem(pScrn);
+
+} /* VIAFreeRec */
+
+
+static const OptionInfoRec * VIAAvailableOptions(int chipid, int busid)
+{
+
+ return VIAOptions;
+
+} /* VIAAvailableOptions */
+
+
+static void VIAIdentify(int flags)
+{
+ xf86PrintChipsets(DRIVER_NAME,
+ "driver for VIA chipsets",
+ VIAChipsets);
+} /* VIAIdentify */
+
+
+static Bool VIAProbe(DriverPtr drv, int flags)
+{
+ GDevPtr *devSections;
+ int *usedChips;
+ int numDevSections;
+ int numUsed;
+ Bool foundScreen = FALSE;
+ int i;
+
+ /* sanity checks */
+ if ((numDevSections = xf86MatchDevice(DRIVER_NAME, &devSections)) <= 0)
+ return FALSE;
+
+ if (xf86GetPciVideoInfo() == NULL)
+ return FALSE;
+
+ numUsed = xf86MatchPciInstances(DRIVER_NAME,
+ PCI_VIA_VENDOR_ID,
+ VIAChipsets,
+ VIAPciChipsets,
+ devSections,
+ numDevSections,
+ drv,
+ &usedChips);
+ xfree(devSections);
+
+ if (numUsed <= 0)
+ return FALSE;
+
+ if (flags & PROBE_DETECT) {
+ foundScreen = TRUE;
+ }
+ else {
+ for (i = 0; i < numUsed; i++) {
+ ScrnInfoPtr pScrn = xf86AllocateScreen(drv, 0);
+ EntityInfoPtr pEnt;
+ if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i],
+ VIAPciChipsets, 0, 0, 0, 0, 0)))
+ {
+ pScrn->driverVersion = VIA_VERSION;
+ pScrn->driverName = DRIVER_NAME;
+ pScrn->name = DRIVER_NAME;
+ pScrn->Probe = VIAProbe;
+ pScrn->PreInit = VIAPreInit;
+ pScrn->ScreenInit = VIAScreenInit;
+ pScrn->SwitchMode = VIASwitchMode;
+ pScrn->AdjustFrame = VIAAdjustFrame;
+ pScrn->EnterVT = VIAEnterVT;
+ pScrn->LeaveVT = VIALeaveVT;
+ pScrn->FreeScreen = VIAFreeScreen;
+ pScrn->ValidMode = VIAValidMode;
+ foundScreen = TRUE;
+ }
+ /*
+ xf86ConfigActivePciEntity(pScrn,
+ usedChips[i],
+ VIAPciChipsets,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ */
+
+ pEnt = xf86GetEntityInfo(usedChips[i]);
+
+ /* CLE266 card support Dual-Head, mark the entity as sharable*/
+ if(pEnt->chipset == VIA_CLE266 || pEnt->chipset == VIA_KM400)
+ {
+ static int instance = 0;
+ DevUnion* pPriv;
+
+ xf86SetEntitySharable(usedChips[i]);
+ xf86SetEntityInstanceForScreen(pScrn,
+ pScrn->entityList[0], instance);
+
+ if(gVIAEntityIndex < 0)
+ {
+ gVIAEntityIndex = xf86AllocateEntityPrivateIndex();
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
+ gVIAEntityIndex);
+
+ if (!pPriv->ptr)
+ {
+ VIAEntPtr pVIAEnt;
+ pPriv->ptr = xnfcalloc(sizeof(VIAEntRec), 1);
+ pVIAEnt = pPriv->ptr;
+ pVIAEnt->IsDRIEnabled = FALSE;
+ pVIAEnt->BypassSecondary = FALSE;
+ pVIAEnt->HasSecondary = FALSE;
+ pVIAEnt->IsSecondaryRestored = FALSE;
+ }
+ }
+ instance++;
+ }
+ xfree(pEnt);
+ }
+ }
+
+ xfree(usedChips);
+
+ return foundScreen;
+
+} /* VIAProbe */
+
+
+static int LookupChipID(PciChipsets* pset, int ChipID)
+{
+ /* Is there a function to do this for me? */
+ while (pset->numChipset >= 0)
+ {
+ if (pset->PCIid == ChipID)
+ return pset->numChipset;
+
+ pset++;
+ }
+
+ return -1;
+
+} /* LookupChipID */
+
+
+static unsigned int
+VIAddc1Read(ScrnInfoPtr pScrn)
+{
+ register vgaHWPtr hwp = VGAHWPTR(pScrn);
+ VIAPtr pVia = VIAPTR(pScrn);
+ register CARD8 tmp;
+
+ while (hwp->readST01(hwp)&0x8) {};
+ while (!(hwp->readST01(hwp)&0x8)) {};
+
+ VGAOUT8(0x3c4, 0x26);
+ tmp = VGAIN8(0x3c5);
+ return ((unsigned int) ((tmp & 0x08) >> 3));
+}
+
+static Bool
+VIAddc1(int scrnIndex)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ VIAPtr pVia = VIAPTR(pScrn);
+ xf86MonPtr pMon;
+ CARD8 tmp;
+ Bool success = FALSE;
+
+ /* initialize chipset */
+ VGAOUT8(0x3c4, 0x26);
+ tmp = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x26);
+ VGAOUT8(0x3c5, (tmp | 0x11));
+
+ if ((pMon = xf86PrintEDID(
+ xf86DoEDID_DDC1(scrnIndex,vgaHWddc1SetSpeed,VIAddc1Read))) != NULL)
+ success = TRUE;
+ xf86SetDDCproperties(pScrn,pMon);
+
+ /* undo initialization */
+ VGAOUT8(0x3c4, 0x26);
+ VGAOUT8(0x3c5, tmp);
+ return success;
+}
+
+static Bool
+VIAddc2(int scrnIndex)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ VIAPtr pVia = VIAPTR(pScrn);
+ xf86MonPtr pMon;
+ CARD8 tmp;
+ Bool success = FALSE;
+
+ VGAOUT8(0x3c4, 0x26);
+ tmp = VGAIN8(0x3c5);
+ pMon = xf86DoEDID_DDC2(pScrn->scrnIndex, pVia->I2C_Port1);
+ if (pMon)
+ success = TRUE;
+ pVia->DDC1 = pMon;
+ xf86PrintEDID(pMon);
+ xf86SetDDCproperties(pScrn, pMon);
+ VGAOUT8(0x3c4, 0x26);
+ VGAOUT8(0x3c5, tmp);
+
+ return success;
+}
+
+static void
+VIAProbeDDC(ScrnInfoPtr pScrn, int index)
+{
+ vbeInfoPtr pVbe;
+
+ if (xf86LoadSubModule(pScrn, "vbe")) {
+ pVbe = VBEInit(NULL,index);
+ ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
+ }
+}
+
+
+static Bool VIAPreInit(ScrnInfoPtr pScrn, int flags)
+{
+ EntityInfoPtr pEnt;
+ VIAPtr pVia;
+ VIABIOSInfoPtr pBIOSInfo;
+ MessageType from = X_DEFAULT;
+ ClockRangePtr clockRanges;
+ char *s = NULL;
+#ifndef USE_FB
+ char *mod = NULL;
+ const char *reqSym = NULL;
+#endif
+ vgaHWPtr hwp;
+ int i, bMemSize = 0, tmp;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAPreInit\n"));
+
+ if (pScrn->numEntities > 1)
+ return FALSE;
+
+ if (flags & PROBE_DETECT)
+ return FALSE;
+
+ if (!xf86LoadSubModule(pScrn, "vgahw"))
+ return FALSE;
+
+ xf86LoaderReqSymLists(vgaHWSymbols, NULL);
+ if (!vgaHWGetHWRec(pScrn))
+ return FALSE;
+
+#if 0
+ /* Here we can alter the number of registers saved and restored by the
+ * standard vgaHWSave and Restore routines.
+ */
+ vgaHWSetRegCounts(pScrn, VGA_NUM_CRTC, VGA_NUM_SEQ, VGA_NUM_GFX, VGA_NUM_ATTR);
+#endif
+
+ if (!VIAGetRec(pScrn)) {
+ return FALSE;
+ }
+
+ pVia = VIAPTR(pScrn);
+ pBIOSInfo = pVia->pBIOSInfo;
+
+ pVia->IsSecondary = FALSE;
+ pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
+ if (pEnt->resources) {
+ xfree(pEnt);
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+
+ pVia->EntityIndex = pEnt->index;
+
+ if(xf86IsEntityShared(pScrn->entityList[0]))
+ {
+ if(xf86IsPrimInitDone(pScrn->entityList[0]))
+ {
+ DevUnion* pPriv;
+ VIAEntPtr pVIAEnt;
+ VIAPtr pVia1;
+
+ pVia->IsSecondary = TRUE;
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
+ gVIAEntityIndex);
+ pVIAEnt = pPriv->ptr;
+ if(pVIAEnt->BypassSecondary) return FALSE;
+ pVIAEnt->pSecondaryScrn = pScrn;
+ pVIAEnt->HasSecondary = TRUE;
+ pVia1 = VIAPTR(pVIAEnt->pPrimaryScrn);
+ pVia1->HasSecondary = TRUE;
+ pVia->sharedData = pVia1->sharedData;
+ }
+ else
+ {
+ DevUnion* pPriv;
+ VIAEntPtr pVIAEnt;
+
+ xf86SetPrimInitDone(pScrn->entityList[0]);
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
+ gVIAEntityIndex);
+ pVia->sharedData = xnfcalloc(sizeof(ViaSharedRec),1);
+ pVIAEnt = pPriv->ptr;
+ pVIAEnt->pPrimaryScrn = pScrn;
+ pVIAEnt->IsDRIEnabled = FALSE;
+ pVIAEnt->BypassSecondary = FALSE;
+ pVIAEnt->HasSecondary = FALSE;
+ pVIAEnt->RestorePrimary = FALSE;
+ pVIAEnt->IsSecondaryRestored = FALSE;
+ }
+ } else {
+ pVia->sharedData = xnfcalloc(sizeof(ViaSharedRec),1);
+ }
+
+ if (flags & PROBE_DETECT) {
+ VIAProbeDDC(pScrn, pVia->EntityIndex);
+ return TRUE;
+ }
+
+ pScrn->monitor = pScrn->confScreen->monitor;
+
+ /*
+ * We support depths of 8, 16 and 24.
+ * We support bpp of 8, 16, and 32.
+ */
+
+ if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb)) {
+ return FALSE;
+ }
+ else {
+ switch (pScrn->depth) {
+ case 8:
+ 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);
+
+ if (pScrn->depth == 32) {
+ pScrn->depth = 24;
+ }
+
+ if (pScrn->depth > 8) {
+ rgb zeros = {0, 0, 0};
+
+ if (!xf86SetWeight(pScrn, zeros, zeros))
+ return FALSE;
+ else {
+ /* TODO check weight returned is supported */
+ ;
+ }
+ }
+
+ if (!xf86SetDefaultVisual(pScrn, -1)) {
+ return FALSE;
+ }
+ else {
+ /* We don't currently support DirectColor at > 8bpp */
+ if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
+ " (%s) is not supported at depth %d\n",
+ xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
+ return FALSE;
+ }
+ }
+
+ /* We use a programmable clock */
+ pScrn->progClock = TRUE;
+
+ xf86CollectOptions(pScrn, NULL);
+
+ /* Set the bits per RGB for 8bpp mode */
+ if (pScrn->depth == 8)
+ pScrn->rgbBits = 6;
+
+ xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, VIAOptions);
+
+#ifdef XF86DRI
+ pVia->drixinerama = FALSE;
+ if (xf86IsOptionSet(VIAOptions, OPTION_DRIXINERAMA))
+ pVia->drixinerama = TRUE;
+#else
+ if (xf86IsOptionSet(VIAOptions, OPTION_DRIXINERAMA))
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Option: drixinerama ignored, no DRI support compiled into driver.\n");
+#endif
+ if (xf86ReturnOptValBool(VIAOptions, OPTION_PCI_BURST, FALSE)) {
+ pVia->pci_burst = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Option: pci_burst - PCI burst read enabled\n");
+ }
+ else {
+ pVia->pci_burst = FALSE;
+ }
+
+ pVia->NoPCIRetry = 1; /* default */
+ if (xf86ReturnOptValBool(VIAOptions, OPTION_PCI_RETRY, FALSE)) {
+ if (xf86ReturnOptValBool(VIAOptions, OPTION_PCI_BURST, FALSE)) {
+ pVia->NoPCIRetry = 0;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: pci_retry\n");
+ }
+ else {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "\"pci_retry\" option requires \"pci_burst\"\n");
+ }
+ }
+
+ if (xf86IsOptionSet(VIAOptions, OPTION_SHADOW_FB)) {
+ pVia->shadowFB = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: ShadowFB %s.\n",
+ pVia->shadowFB ? "enabled" : "disabled");
+ }
+ else {
+ pVia->shadowFB = FALSE;
+ }
+
+ if ((s = xf86GetOptValString(VIAOptions, OPTION_ROTATE))) {
+ if (!xf86NameCmp(s, "CW")) {
+ /* accel is disabled below for shadowFB */
+ pVia->shadowFB = TRUE;
+ pVia->rotate = 1;
+ pVia->hwcursor = FALSE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Rotating screen clockwise - acceleration disabled\n");
+ }
+ else if(!xf86NameCmp(s, "CCW")) {
+ pVia->shadowFB = TRUE;
+ pVia->rotate = -1;
+ pVia->hwcursor = FALSE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen"
+ "counter clockwise - acceleration disabled\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");
+ }
+ }
+
+ if (xf86ReturnOptValBool(VIAOptions, OPTION_NOACCEL, FALSE)) {
+ pVia->NoAccel = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Option: NoAccel -Acceleration Disabled\n");
+ }
+ else {
+ pVia->NoAccel = FALSE;
+ }
+
+ if (pVia->shadowFB && !pVia->NoAccel) {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "HW acceleration not supported with \"shadowFB\".\n");
+ pVia->NoAccel = TRUE;
+ }
+
+ /*
+ * The SWCursor setting takes priority over HWCursor. The default
+ * if neither is specified is HW.
+ */
+
+ from = X_DEFAULT;
+ pVia->hwcursor = pVia->shadowFB ? FALSE : TRUE;
+ if (xf86GetOptValBool(VIAOptions, OPTION_HWCURSOR, &pVia->hwcursor))
+ from = X_CONFIG;
+
+ if (xf86ReturnOptValBool(VIAOptions, OPTION_SWCURSOR, FALSE)) {
+ pVia->hwcursor = FALSE;
+ from = X_CONFIG;
+ }
+
+ if (pVia->IsSecondary) pVia->hwcursor = FALSE;
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
+ pVia->hwcursor ? "HW" : "SW");
+
+ if (xf86ReturnOptValBool(VIAOptions, OPTION_A2, FALSE)) {
+ pBIOSInfo->A2 = TRUE;
+ }
+ else {
+ pBIOSInfo->A2 = FALSE;
+ }
+
+ from = X_DEFAULT;
+ if (xf86ReturnOptValBool(VIAOptions, OPTION_USEBIOS, FALSE)) {
+ from = X_CONFIG;
+ pBIOSInfo->UseBIOS = TRUE;
+ }
+ else {
+ pBIOSInfo->UseBIOS = FALSE;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "%ssing video BIOS to set modes\n",
+ pBIOSInfo->UseBIOS ? "U" : "Not u" );
+
+ pScrn->videoRam = 0;
+ if(xf86GetOptValInteger(VIAOptions, OPTION_VIDEORAM, &pScrn->videoRam)) {
+ xf86DrvMsg( pScrn->scrnIndex, X_CONFIG,
+ "Option: VideoRAM %dkB\n", pScrn->videoRam );
+ }
+
+ if (xf86ReturnOptValBool(VIAOptions, OPTION_DISABLEVQ, FALSE)) {
+ pVia->VQEnable = FALSE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Option: DisableVQ -VQ Disabled\n");
+ }
+ else {
+ pVia->VQEnable = TRUE;
+ }
+
+ /* ActiveDevice Option for device selection */
+ pBIOSInfo->ActiveDevice = 0x00;
+ if ((s = xf86GetOptValString(VIAOptions, OPTION_ACTIVEDEVICE))) {
+ if (!xf86NameCmp(s, "CRT,TV") || !xf86NameCmp(s, "TV,CRT")) {
+ pBIOSInfo->ActiveDevice = VIA_DEVICE_CRT1 | VIA_DEVICE_TV;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Active Device is CRT and TV.\n");
+ }
+ else if(!xf86NameCmp(s, "CRT,LCD") || !xf86NameCmp(s, "LCD,CRT")) {
+ pBIOSInfo->ActiveDevice = VIA_DEVICE_CRT1 | VIA_DEVICE_LCD;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Active Device is CRT and LCD.\n");
+ }
+ else if(!xf86NameCmp(s, "CRT,DFP") || !xf86NameCmp(s, "DFP,CRT")
+ || !xf86NameCmp(s, "CRT,DVI") || !xf86NameCmp(s, "DVI,CRT")) {
+ pBIOSInfo->ActiveDevice = VIA_DEVICE_CRT1 | VIA_DEVICE_DFP;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Active Device is CRT and DFP.\n");
+ }
+ else if(!xf86NameCmp(s, "TV,DFP") || !xf86NameCmp(s, "DFP,TV")
+ || !xf86NameCmp(s, "TV,DVI") || !xf86NameCmp(s, "DVI,TV")) {
+ pBIOSInfo->ActiveDevice = VIA_DEVICE_TV | VIA_DEVICE_DFP;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Active Device is TV and DFP.\n");
+ }
+#if 0
+ else if(!xf86NameCmp(s, "DFP,LCD") || !xf86NameCmp(s, "LCD,DFP")
+ || !xf86NameCmp(s, "LCD,DVI") || !xf86NameCmp(s, "DVI,LCD")) {
+ pBIOSInfo->ActiveDevice = VIA_DEVICE_DFP | VIA_DEVICE_LCD;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Active Device is DFP and LCD.\n");
+ }
+#endif
+ else if(!xf86NameCmp(s, "CRT") || !xf86NameCmp(s, "CRT ONLY")) {
+ pBIOSInfo->ActiveDevice = VIA_DEVICE_CRT1;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Active Device is CRT Only.\n");
+ }
+ else if(!xf86NameCmp(s, "LCD") || !xf86NameCmp(s, "LCD ONLY")) {
+ pBIOSInfo->ActiveDevice = VIA_DEVICE_LCD;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Active Device is LCD Only.\n");
+ }
+ else if(!xf86NameCmp(s, "TV") || !xf86NameCmp(s, "TV ONLY")) {
+ pBIOSInfo->ActiveDevice = VIA_DEVICE_TV;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Active Device is TV Only.\n");
+ }
+ else if(!xf86NameCmp(s, "DFP") || !xf86NameCmp(s, "DFP ONLY")
+ || !xf86NameCmp(s, "DVI") || !xf86NameCmp(s, "DVI ONLY")) {
+ pBIOSInfo->ActiveDevice = VIA_DEVICE_DFP;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Active Device is DFP Only.\n");
+ }
+ else {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option \"%s\" can't recognize!, Active Device by default.\n", s);
+ }
+ }
+
+ /* NoDDCValue Option */
+ if (xf86ReturnOptValBool(VIAOptions, OPTION_NODDCVALUE, FALSE)) {
+ pVia->NoDDCValue = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Option: Not using DDC probed value to set HorizSync & VertRefresh\n");
+ }
+ else {
+ pVia->NoDDCValue = FALSE;
+ }
+
+ /* LCDDualEdge Option */
+ pBIOSInfo->LCDDualEdge = FALSE;
+ if (xf86ReturnOptValBool(VIAOptions, OPTION_LCDDUALEDGE, FALSE)) {
+ pBIOSInfo->LCDDualEdge = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Option: Using Dual Edge mode to set LCD\n");
+ }
+ else {
+ pBIOSInfo->LCDDualEdge = FALSE;
+ }
+
+ /* Digital Output Bus Width Option */
+ pBIOSInfo->BusWidth = VIA_DI_12BIT;
+ if ((s = xf86GetOptValString(VIAOptions, OPTION_BUSWIDTH))) {
+ if (!xf86NameCmp(s, "12BIT")) {
+ pBIOSInfo->BusWidth = VIA_DI_12BIT;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Digital Output Bus Width is 12BIT\n");
+ }
+ else if (!xf86NameCmp(s, "24BIT")) {
+ pBIOSInfo->BusWidth = VIA_DI_24BIT;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Digital Output Bus Width is 24BIT\n");
+ }
+ }
+
+ /* LCD Center/Expend Option */
+ if (xf86ReturnOptValBool(VIAOptions, OPTION_CENTER, FALSE)) {
+ pBIOSInfo->Center = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DVI Center is On\n");
+ }
+ else {
+ pBIOSInfo->Center = FALSE;
+ }
+
+ /* Panel Size Option */
+ pBIOSInfo->PanelSize = VIA_PANEL_INVALID;
+ if ((s = xf86GetOptValString(VIAOptions, OPTION_PANELSIZE))) {
+ if (!xf86NameCmp(s, "640x480")) {
+ pBIOSInfo->PanelSize = VIA_PANEL6X4;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Selected Panel Size is 640x480\n");
+ }
+ else if (!xf86NameCmp(s, "800x600")) {
+ pBIOSInfo->PanelSize = VIA_PANEL8X6;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Selected Panel Size is 800x600\n");
+ }
+ else if(!xf86NameCmp(s, "1024x768")) {
+ pBIOSInfo->PanelSize = VIA_PANEL10X7;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Selected Panel Size is 1024x768\n");
+ }
+ else if (!xf86NameCmp(s, "1280x768")) {
+ pBIOSInfo->PanelSize = VIA_PANEL12X7;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Selected Panel Size is 1280x768\n");
+ }
+ else if (!xf86NameCmp(s, "1280x1024")) {
+ pBIOSInfo->PanelSize = VIA_PANEL12X10;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Selected Panel Size is 1280x1024\n");
+ }
+ else if (!xf86NameCmp(s, "1400x1050")) {
+ pBIOSInfo->PanelSize = VIA_PANEL14X10;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Selected Panel Size is 1400x1050\n");
+ }
+ }
+
+ /* TV DotCrawl Enable Option */
+ if (xf86ReturnOptValBool(VIAOptions, OPTION_TVDOTCRAWL, FALSE)) {
+ pBIOSInfo->TVDotCrawl = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "DotCrawl is Enable\n");
+ }
+ else {
+ pBIOSInfo->TVDotCrawl = FALSE;
+ }
+
+ pBIOSInfo->TVType = TVTYPE_NONE;
+ if ((s = xf86GetOptValString(VIAOptions, OPTION_TVTYPE))) {
+ if (!xf86NameCmp(s, "NTSC")) {
+ pBIOSInfo->TVType = TVTYPE_NTSC;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "TV Type is NTSC\n");
+ }
+ else if(!xf86NameCmp(s, "PAL")) {
+ pBIOSInfo->TVType = TVTYPE_PAL;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "TV Type is PAL\n");
+ }
+ }
+
+ /* TV out put signal Option */
+ pBIOSInfo->TVOutput = TVOUTPUT_NONE;
+ if ((s = xf86GetOptValString(VIAOptions, OPTION_TVOUTPUT))) {
+ if (!xf86NameCmp(s, "S-Video")) {
+ pBIOSInfo->TVOutput = TVOUTPUT_SVIDEO;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "TV Output Signal is S-Video\n");
+ }
+ else if(!xf86NameCmp(s, "Composite")) {
+ pBIOSInfo->TVOutput = TVOUTPUT_COMPOSITE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "TV Output Signal is Composite\n");
+ }
+ else if(!xf86NameCmp(s, "SC")) {
+ pBIOSInfo->TVOutput = TVOUTPUT_SC;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "TV Output Signal is SC\n");
+ }
+ else if(!xf86NameCmp(s, "RGB")) {
+ pBIOSInfo->TVOutput = TVOUTPUT_RGB;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "TV Output Signal is RGB\n");
+ }
+ else if(!xf86NameCmp(s, "YCbCr")) {
+ pBIOSInfo->TVOutput = TVOUTPUT_YCBCR;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "TV Output Signal is YCbCr\n");
+ }
+ }
+
+ /* TV Standard Option */
+ pBIOSInfo->TVVScan = VIA_TVNORMAL;
+ if ((s = xf86GetOptValString(VIAOptions, OPTION_TVVSCAN))) {
+ if (!xf86NameCmp(s, "under")) {
+ pBIOSInfo->TVVScan = VIA_TVNORMAL;
+ }
+ else if (!xf86NameCmp(s, "over")) {
+ pBIOSInfo->TVVScan = VIA_TVOVER;
+ }
+ }
+
+ pBIOSInfo->TVHScale = VIA_NO_TVHSCALE;
+ if ((s = xf86GetOptValString(VIAOptions, OPTION_TVHSCALE))) {
+#if 0
+ if (!xf86NameCmp(s, "0")) {
+ pBIOSInfo->TVHScale = VIA_TVHSCALE0;
+ }
+ else if (!xf86NameCmp(s, "1")) {
+ pBIOSInfo->TVHScale = VIA_TVHSCALE1;
+ }
+ else if(!xf86NameCmp(s, "2")) {
+ pBIOSInfo->TVHScale = VIA_TVHSCALE2;
+ }
+ else if (!xf86NameCmp(s, "3")) {
+ pBIOSInfo->TVHScale = VIA_TVHSCALE3;
+ }
+ else if (!xf86NameCmp(s, "4")) {
+ pBIOSInfo->TVHScale = VIA_TVHSCALE4;
+ }
+#endif
+ }
+
+ /* TV Encoder Type Option */
+ pBIOSInfo->TVEncoder = VIA_NONETV;
+ if ((s = xf86GetOptValString(VIAOptions, OPTION_TVENCODER))) {
+ if (!xf86NameCmp(s, "VT1621")) {
+ pBIOSInfo->TVEncoder = VIA_TV2PLUS;
+ pBIOSInfo->TVI2CAdd = 0x40;
+ }
+ else if(!xf86NameCmp(s, "VT1622")) {
+ pBIOSInfo->TVEncoder = VIA_TV3;
+ pBIOSInfo->TVI2CAdd = 0x40;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "TV Encoder is VT1622!\n");
+ }
+ else if(!xf86NameCmp(s, "VT1622A")) {
+ pBIOSInfo->TVEncoder = VIA_VT1622A;
+ pBIOSInfo->TVI2CAdd = 0x40;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "TV Encoder is VT1622!\n");
+ }
+ else if(!xf86NameCmp(s, "CH7019")) {
+ pBIOSInfo->TVEncoder = VIA_CH7019;
+ pBIOSInfo->TVI2CAdd = 0xEA;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "TV Encoder is CH7019!\n");
+ }
+ else if(!xf86NameCmp(s, "SAA7108")) {
+ pBIOSInfo->TVEncoder = VIA_SAA7108;
+ pBIOSInfo->TVI2CAdd = 0x88;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "TV Encoder is SAA7108!\n");
+ }
+ else if(!xf86NameCmp(s, "FS454")) {
+ pBIOSInfo->TVEncoder = VIA_FS454;
+ pBIOSInfo->TVI2CAdd = 0xD4;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "TV Encoder is FS453/FS454!\n");
+ }
+ }
+
+ if (xf86GetOptValInteger(VIAOptions, OPTION_REFRESH, &(pBIOSInfo->OptRefresh))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Refresh is %d\n", pBIOSInfo->OptRefresh);
+ }
+
+ if (xf86LoadSubModule(pScrn, "int10")) {
+ xf86LoaderReqSymLists(int10Symbols, NULL);
+ pVia->pInt10 = xf86InitInt10(pEnt->index);
+ }
+
+ if (pVia->pInt10 && xf86LoadSubModule(pScrn, "vbe")) {
+ xf86LoaderReqSymLists(vbeSymbols, NULL);
+ pVia->pVbe = VBEInit(pVia->pInt10, pVia->EntityIndex);
+ }
+
+ pVia->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
+ xf86RegisterResources(pEnt->index, NULL, ResNone);
+ /*
+ xf86SetOperatingState(RES_SHARED_VGA, pEnt->index, ResUnusedOpr);
+ xf86SetOperatingState(resVgaMemShared, pEnt->index, ResDisableOpr);
+ */
+
+ if (pEnt->device->chipset && *pEnt->device->chipset) {
+ pScrn->chipset = pEnt->device->chipset;
+ pVia->ChipId = pEnt->device->chipID;
+ pVia->Chipset = xf86StringToToken(VIAChipsets, pScrn->chipset);
+ from = X_CONFIG;
+ } else if (pEnt->device->chipID >= 0) {
+ pVia->ChipId = pEnt->device->chipID;
+ pVia->Chipset = LookupChipID(VIAPciChipsets, pVia->ChipId);
+ pScrn->chipset = (char *)xf86TokenToString(VIAChipsets,
+ pVia->Chipset);
+ from = X_CONFIG;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
+ pEnt->device->chipID);
+ } else {
+ from = X_PROBED;
+ pVia->ChipId = pVia->PciInfo->chipType;
+ pVia->Chipset = LookupChipID(VIAPciChipsets, pVia->ChipId);
+ pScrn->chipset = (char *)xf86TokenToString(VIAChipsets,
+ pVia->Chipset);
+ }
+
+ if (pEnt->device->chipRev >= 0) {
+ pVia->ChipRev = pEnt->device->chipRev;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
+ pVia->ChipRev);
+ }
+ else {
+ /*pVia->ChipRev = pVia->PciInfo->chipRev;*/
+ /* Read PCI bus 0, dev 0, function 0, index 0xF6 to get chip rev. */
+ pVia->ChipRev = pciReadByte(pciTag(0, 0, 0), 0xF6);
+ }
+
+ if (pEnt->device->videoRam != 0) {
+ if (!pScrn->videoRam)
+ pScrn->videoRam = pEnt->device->videoRam;
+ else {
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Video Memory Size in Option is %d KB, Detect is %d KB!",
+ pScrn->videoRam, pEnt->device->videoRam);
+ }
+ }
+ pBIOSInfo->Chipset = pVia->Chipset;
+ pBIOSInfo->ChipRev = pVia->ChipRev;
+
+ xfree(pEnt);
+
+ VIAvfInitHWDiff(pVia);
+
+ /* maybe throw in some more sanity checks here */
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset);
+
+ pVia->PciTag = pciTag(pVia->PciInfo->bus, pVia->PciInfo->device,
+ pVia->PciInfo->func);
+
+ switch (pVia->ChipRev) {
+ case 2:
+ pBIOSInfo->A2 = TRUE;
+ break;
+ default:
+ pBIOSInfo->A2 = FALSE;
+ break;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, from, "Chipset Rev.: %d\n", pVia->ChipRev);
+
+ hwp = VGAHWPTR(pScrn);
+ vgaHWGetIOBase(hwp);
+
+ if (!VIAMapMMIO(pScrn)) {
+ vbeFree(pVia->pVbe);
+ return FALSE;
+ }
+
+ /* Get BIOS ver. From BIOS Call Function */
+ tmp = VIABIOS_GetBIOSVersion(pScrn);
+ pBIOSInfo->BIOSMajorVersion = tmp >> 8;
+ pBIOSInfo->BIOSMinorVersion = tmp & 0xFF;
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS Version is = %d.%d\n", pBIOSInfo->BIOSMajorVersion, pBIOSInfo->BIOSMinorVersion));
+ VIABIOS_GetBIOSDate(pScrn);
+
+ if (pBIOSInfo->TVType == TVTYPE_NONE) {
+ /* use jumper to determine TV Type */
+ VGAOUT8(0x3D4, 0x3B);
+ if (VGAIN8(0x3D5) & 0x02) {
+ pBIOSInfo->TVType = TVTYPE_PAL;
+ }
+ else {
+ pBIOSInfo->TVType = TVTYPE_NTSC;
+ }
+ }
+
+ {
+ Gamma zeros = {0.0, 0.0, 0.0};
+
+ if (!xf86SetGamma(pScrn, zeros)) {
+ vbeFree(pVia->pVbe);
+ return FALSE;
+ }
+ }
+
+ /* Next go on to detect amount of installed ram */
+ if (pScrn->videoRam < 16384 || pScrn->videoRam > 65536) {
+ bMemSize = VIABIOS_GetVideoMemSize(pScrn);
+ if (bMemSize) {
+ pScrn->videoRam = bMemSize << 6;
+ }
+ else {
+ VGAOUT8(0x3C4, 0x34); /* Was 0x39 */
+ bMemSize = VGAIN8(0x3c5);
+ if (bMemSize > 16 && bMemSize <= 128) {
+ pScrn->videoRam = (bMemSize + 1) << 9;
+ }
+ else if (bMemSize > 0 && bMemSize < 31){
+ pScrn->videoRam = bMemSize << 12;
+ }
+ else {
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "bMemSize = %d\nGet Video Memory Size by default.\n", bMemSize));
+ pScrn->videoRam = VIAGetMemSize();
+ }
+ }
+ }
+
+ /* Split FB for SAMM */
+ /* FIXME: For now, split FB into two equal sections. This should
+ * be able to be adjusted by user with a config option. */
+ if (pVia->IsSecondary) {
+ DevUnion* pPriv;
+ VIAEntPtr pVIAEnt;
+ VIAPtr pVia1;
+
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
+ gVIAEntityIndex);
+ pVIAEnt = pPriv->ptr;
+ pScrn->videoRam = pScrn->videoRam >> 1;
+ pVIAEnt->pPrimaryScrn->videoRam = pScrn->videoRam;
+ pVia1 = VIAPTR(pVIAEnt->pPrimaryScrn);
+ pVia1->videoRambytes = pScrn->videoRam << 10;
+ pVia->FrameBufferBase += (pScrn->videoRam << 10);
+ }
+
+ pVia->videoRambytes = pScrn->videoRam << 10;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,"videoram = %dk\n",
+ pScrn->videoRam);
+
+ /* Set status word positions based on chip type. */
+
+ switch (pVia->Chipset) {
+ case VIA_CLE266:
+ pVia->myWaitIdle = WaitIdleCLE266;
+ break;
+ default:
+ pVia->myWaitIdle = WaitIdleCLE266;
+ break;
+ }
+
+ if (!xf86LoadSubModule(pScrn, "i2c")) {
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+ else {
+ xf86LoaderReqSymLists(i2cSymbols,NULL);
+ VIAI2CInit(pScrn);
+ }
+
+ if (!xf86LoadSubModule(pScrn, "ddc")) {
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+ else {
+ xf86MonPtr pMon = NULL;
+
+ xf86LoaderReqSymLists(ddcSymbols, NULL);
+ if ((pVia->pVbe)
+ && ((pMon = xf86PrintEDID(vbeDoEDID(pVia->pVbe, NULL))) != NULL)) {
+ pVia->DDC1 = pMon;
+ xf86SetDDCproperties(pScrn,pMon);
+ }
+ else if (!VIAddc2(pScrn->scrnIndex)) {
+ VIAddc1(pScrn->scrnIndex);
+ }
+ }
+
+ /* Reset HorizSync & VertRefresh Rang Using DDC Value */
+ if (pVia->DDC1 && !pVia->NoDDCValue) {
+ int i;
+ int h = 0;
+ int v = 0;
+
+ for (i = 0; i < DET_TIMINGS; i++) {
+ if (pVia->DDC1->det_mon[i].type == DS_RANGES) {
+ pScrn->monitor->hsync[h].lo
+ = pVia->DDC1->det_mon[i].section.ranges.min_h;
+ pScrn->monitor->hsync[h++].hi
+ = pVia->DDC1->det_mon[i].section.ranges.max_h;
+ pScrn->monitor->vrefresh[v].lo
+ = pVia->DDC1->det_mon[i].section.ranges.min_v;
+ pScrn->monitor->vrefresh[v++].hi
+ = pVia->DDC1->det_mon[i].section.ranges.max_v;
+ break;
+ }
+ }
+ pScrn->monitor->nHsync = h;
+ pScrn->monitor->nVrefresh = v;
+ }
+
+ /*
+ * Setup the ClockRanges, which describe what clock ranges are available,
+ * and what sort of modes they can be used for.
+ */
+
+ clockRanges = xnfalloc(sizeof(ClockRange));
+ clockRanges->next = NULL;
+ clockRanges->minClock = 20000;
+ clockRanges->maxClock = 230000;
+
+ clockRanges->clockIndex = -1;
+ clockRanges->interlaceAllowed = TRUE;
+ clockRanges->doubleScanAllowed = FALSE;
+
+
+ /*
+ * xf86ValidateModes will check that the mode HTotal and VTotal values
+ * don't exceed the chipset's limit if pScrn->maxHValue and
+ * pScrn->maxVValue are set. Since our VIAValidMode() already takes
+ * care of this, we don't worry about setting them here.
+ */
+
+ /* Select valid modes from those available */
+ i = xf86ValidateModes(pScrn,
+ pScrn->monitor->Modes, /* availModes */
+ pScrn->display->modes, /* modeNames */
+ clockRanges, /* list of clock ranges */
+ NULL, /* list of line pitches */
+ 256, /* mini line pitch */
+ 2048, /* max line pitch */
+ 16 * pScrn->bitsPerPixel, /* pitch inc (bits) */
+ 128, /* min height */
+ 2048, /* max height */
+ pScrn->display->virtualX, /* virtual width */
+ pScrn->display->virtualY, /* virutal height */
+ pVia->videoRambytes, /* size of video memory */
+ LOOKUP_BEST_REFRESH); /* lookup mode flags */
+
+ if (i == -1) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86ValidateModes failure\n");
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+
+ xf86PruneDriverModes(pScrn);
+
+ if (i == 0 || pScrn->modes == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+
+ /* Set up screen parameters. */
+ pVia->Bpp = pScrn->bitsPerPixel >> 3;
+ pVia->Bpl = pScrn->displayWidth * pVia->Bpp;
+
+ if (!VIAGetBIOSTable(pBIOSInfo)) {
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+
+ pBIOSInfo->I2C_Port1 = pVia->I2C_Port1;
+ pBIOSInfo->I2C_Port2 = pVia->I2C_Port2;
+ pBIOSInfo->DDC1 = pVia->DDC1;
+ pBIOSInfo->DDC2 = pVia->DDC2;
+
+ /* Detect TV Encoder */
+ if (!pBIOSInfo->TVEncoder) {
+ pBIOSInfo->TVEncoder = VIACheckTVExist(pBIOSInfo);
+ }
+ /* Detect TMDS/LVDS Encoder */
+ VIAPostDVI(pBIOSInfo);
+ /*VIAGetPanelInfo(pBIOSInfo);*/
+ pBIOSInfo->ConnectedDevice = VIAGetDeviceDetect(pBIOSInfo);
+
+ xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
+ pScrn->currentMode = pScrn->modes;
+ xf86PrintModes(pScrn);
+ xf86SetDpi(pScrn, 0, 0);
+
+#ifdef USE_FB
+ if (xf86LoadSubModule(pScrn, "fb") == NULL) {
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+
+ xf86LoaderReqSymLists(fbSymbols, NULL);
+
+#else
+ /* load bpp-specific modules */
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ mod = "cfb";
+ reqSym = "cfbScreenInit";
+ break;
+ case 16:
+ mod = "cfb16";
+ reqSym = "cfb16ScreenInit";
+ break;
+ case 32:
+ mod = "cfb32";
+ reqSym = "cfb32ScreenInit";
+ break;
+ }
+
+ if (mod && xf86LoadSubModule(pScrn, mod) == NULL) {
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+
+ xf86LoaderReqSymbols(reqSym, NULL);
+#endif
+
+ if (!pVia->NoAccel) {
+ if(!xf86LoadSubModule(pScrn, "xaa")) {
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(xaaSymbols, NULL);
+ }
+
+ if (pVia->hwcursor) {
+ if (!xf86LoadSubModule(pScrn, "ramdac")) {
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(ramdacSymbols, NULL);
+ }
+
+ if (pVia->shadowFB) {
+ if (!xf86LoadSubModule(pScrn, "shadowfb")) {
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+ xf86LoaderReqSymLists(shadowSymbols, NULL);
+ }
+
+ /* Capture option parameter */
+ pVia->Cap0_Deinterlace = CAP_BOB;
+ if ((s = xf86GetOptValString(VIAOptions, OPTION_CAP0_DEINTERLACE))) {
+ if (!xf86NameCmp(s, "Bob")) {
+ pVia->Cap0_Deinterlace = CAP_BOB;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Capture 0 de-interlace mode is Bob\n");
+ }
+ else if(!xf86NameCmp(s, "Weave")) {
+ pVia->Cap0_Deinterlace = CAP_WEAVE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Capture 0 de-interlace mode is Weave\n");
+ }
+ }
+
+ pVia->Cap1_Deinterlace = CAP_BOB;
+ if ((s = xf86GetOptValString(VIAOptions, OPTION_CAP1_DEINTERLACE))) {
+ if (!xf86NameCmp(s, "Bob")) {
+ pVia->Cap1_Deinterlace = CAP_BOB;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Capture 1 de-interlace mode is Bob\n");
+ }
+ else if(!xf86NameCmp(s, "Weave")) {
+ pVia->Cap1_Deinterlace = CAP_WEAVE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Capture 1 de-interlace mode is Weave\n");
+ }
+ }
+
+ if (xf86ReturnOptValBool(VIAOptions, OPTION_CAP0_FIELDSWAP, FALSE)) {
+ pVia->Cap0_FieldSwap = TRUE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Option: Cap0_FieldSwap Enabled\n");
+ }
+ else {
+ pVia->Cap0_FieldSwap = FALSE;
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ "Option: Cap0_FieldSwap Disabled\n");
+ }
+
+ /* xf86LoaderReqSymLists(mpegSymbols, NULL); */
+
+ VIADeviceSelection(pScrn);
+ if (pVia->IsSecondary) {
+ if (pBIOSInfo->SAMM)
+ VIADeviceDispatch(pScrn);
+ else
+ return FALSE;
+ }
+
+ VIAUnmapMem(pScrn);
+
+ return TRUE;
+}
+
+
+static Bool VIAEnterVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ VIAPtr pVia = VIAPTR(pScrn);
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ Bool ret;
+
+ /* FIXME: Rebind AGP memory here */
+ /* FIXME: Unlock DRI here */
+ DEBUG(xf86DrvMsg(scrnIndex, X_INFO, "VIAEnterVT\n"));
+ VIASave(pScrn);
+ vgaHWUnlock(hwp);
+
+ ret = VIAModeInit(pScrn, pScrn->currentMode);
+
+ /* Patch for APM suspend resume, HWCursor has garbage */
+ if (pVia->hwcursor && pVia->CursorImage) {
+ DEBUG(xf86DrvMsg(scrnIndex, X_INFO, "Restore Cursor Image!\n"));
+ memcpy(pVia->FBBase + pVia->CursorStart, pVia->CursorImage, 0x1000);
+ VIASETREG(VIA_REG_CURSOR_FG, pVia->CursorFG);
+ VIASETREG(VIA_REG_CURSOR_BG, pVia->CursorBG);
+ VIASETREG(VIA_REG_CURSOR_MODE, pVia->CursorMC);
+ xfree(pVia->CursorImage);
+ /*VIALoadCursorImage(pScrn, *pVia->CursorImage);*/
+ }
+
+ /* retore video status */
+ if (!pVia->IsSecondary)
+ viaRestoreVideo(pScrn);
+
+ VIAAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+ return ret;
+}
+
+
+static void VIALeaveVT(int scrnIndex, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ VIAPtr pVia = VIAPTR(pScrn);
+ vgaRegPtr vgaSavePtr = &hwp->SavedReg;
+ VIARegPtr viaSavePtr = &pVia->SavedReg;
+
+ DEBUG(xf86DrvMsg(scrnIndex, X_INFO, "VIALeaveVT\n"));
+
+ /* FIXME: take the DRI lock here to avoid accidents */
+ /* FIXME: unbind the AGP memory ? */
+
+ /* Wait Hardware Engine idle to exit graphicd mode */
+ WaitIdle();
+
+ if (pVia->VQEnable) {
+ /* if we use VQ, disable it before we exit */
+ VIASETREG(0x43c, 0x00fe0000);
+ VIASETREG(0x440, 0x00000004);
+ }
+
+ /* Save video status and turn off all video activities */
+ if (!pVia->IsSecondary)
+ viaSaveVideo(pScrn);
+
+ if (pVia->hwcursor) {
+ pVia->CursorImage = xcalloc(1, 0x1000);
+ memcpy(pVia->CursorImage, pVia->FBBase + pVia->CursorStart, 0x1000);
+ pVia->CursorFG = (CARD32)VIAGETREG(VIA_REG_CURSOR_FG);
+ pVia->CursorBG = (CARD32)VIAGETREG(VIA_REG_CURSOR_BG);
+ pVia->CursorMC = (CARD32)VIAGETREG(VIA_REG_CURSOR_MODE);
+ }
+
+ VIAWriteMode(pScrn, vgaSavePtr, viaSavePtr);
+ vgaHWLock(hwp);
+}
+
+
+static void VIASave(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ vgaRegPtr vgaSavePtr = &hwp->SavedReg;
+ VIAPtr pVia = VIAPTR(pScrn);
+ VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+ VIARegPtr save = &pVia->SavedReg;
+ int vgaCRIndex, vgaCRReg, vgaIOBase;
+ int i;
+ I2CDevPtr dev;
+ unsigned char W_Buffer[1];
+ unsigned char TVRegs[0xFF];
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIASave\n"));
+
+ if(pVia->IsSecondary)
+ {
+ DevUnion* pPriv;
+ VIAEntPtr pVIAEnt;
+ VIAPtr pVia1;
+ vgaHWPtr hwp1;
+ pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
+ gVIAEntityIndex);
+ pVIAEnt = pPriv->ptr;
+ hwp1 = VGAHWPTR(pVIAEnt->pPrimaryScrn);
+ pVia1 = VIAPTR(pVIAEnt->pPrimaryScrn);
+ hwp->SavedReg = hwp1->SavedReg;
+ pVia->SavedReg = pVia1->SavedReg;
+ }
+ else {
+ vgaHWProtect(pScrn, TRUE);
+
+ if (xf86IsPrimaryPci(pVia->PciInfo)) {
+ vgaHWSave(pScrn, vgaSavePtr, VGA_SR_ALL);
+ }
+ else {
+ vgaHWSave(pScrn, vgaSavePtr, VGA_SR_MODE);
+ }
+
+ vgaIOBase = hwp->IOBase;
+ vgaCRReg = vgaIOBase + 5;
+ vgaCRIndex = vgaIOBase + 4;
+
+ /* Unlock Extended Regs */
+ outb(0x3c4, 0x10);
+ outb(0x3c5, 0x01);
+
+ VGAOUT8(0x3c4, 0x14);
+ save->SR14 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x15);
+ save->SR15 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x16);
+ save->SR16 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x17);
+ save->SR17 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x18);
+ save->SR18 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x19);
+ save->SR19 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x1a);
+ save->SR1A = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x1b);
+ save->SR1B = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x1c);
+ save->SR1C = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x1d);
+ save->SR1D = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x1e);
+ save->SR1E = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x1f);
+ save->SR1F = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x22);
+ save->SR22 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x23);
+ save->SR23 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x24);
+ save->SR24 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x25);
+ save->SR25 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x26);
+ save->SR26 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x27);
+ save->SR27 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x28);
+ save->SR28 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x29);
+ save->SR29 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x2a);
+ save->SR2A = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x2b);
+ save->SR2B = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x2e);
+ save->SR2E = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x44);
+ save->SR44 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x45);
+ save->SR45 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x46);
+ save->SR46 = VGAIN8(0x3c5);
+ VGAOUT8(0x3c4, 0x47);
+ save->SR47 = VGAIN8(0x3c5);
+
+ VGAOUT8(vgaCRIndex, 0x13);
+ save->CR13 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x32);
+ save->CR32 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x33);
+ save->CR33 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x34);
+ save->CR34 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x35);
+ save->CR35 = VGAIN8(vgaCRReg);
+ VGAOUT8(vgaCRIndex, 0x36);
+ save->CR36 = VGAIN8(vgaCRReg);
+
+ /* Saving TV register status before set mode */
+ switch (pBIOSInfo->TVEncoder) {
+ case VIA_NONETV:
+ break;
+ case VIA_VT1623:
+ VIAGPIOI2C_Initial(pBIOSInfo, 0x40);
+ for (i = 0; i < 0x6C; i++) {
+ VIAGPIOI2C_ReadByte(pBIOSInfo, i, (TVRegs + i));
+ save->TVRegs[i] = TVRegs[i];
+ /*DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Save TV Register[%d]0x%X\n", i, save->TVRegs[i]));*/
+ }
+ break;
+ default:
+ if (xf86I2CProbeAddress(pVia->I2C_Port2, pBIOSInfo->TVI2CAdd)) {
+ dev = xf86CreateI2CDevRec();
+ dev->DevName = "TV";
+ dev->SlaveAddr = pBIOSInfo->TVI2CAdd;
+ dev->pI2CBus = pVia->I2C_Port2;
+
+ if (xf86I2CDevInit(dev)) {
+ W_Buffer[0] = 0;
+ xf86I2CWriteRead(dev, W_Buffer,1, TVRegs, 0xFF);
+ for (i = 0; i < 0xFF; i++) {
+ save->TVRegs[i] = TVRegs[i];
+ }
+ xf86DestroyI2CDevRec(dev,TRUE);
+ }
+ else
+ xf86DestroyI2CDevRec(dev,TRUE);
+ }
+ break;
+ }
+
+ /* Saving LVDS register status before set mode
+ if (pBIOSInfo->LVDS == VIA_CH7019LVDS) {
+ dev = xf86CreateI2CDevRec();
+ dev->DevName = "LVDS";
+ dev->SlaveAddr = 0xEA;
+ dev->pI2CBus = pVia->I2C_Port2;
+
+ if (xf86I2CDevInit(dev)) {
+ for (i = 0; i < 0x40; i++) {
+ W_Buffer[0] = i + 0x40;
+ xf86I2CWriteRead(dev, W_Buffer, 1, save->LCDRegs + i, 1);
+ }
+ xf86DestroyI2CDevRec(dev,TRUE);
+ }
+ else
+ xf86DestroyI2CDevRec(dev,TRUE);
+ }*/
+
+ /* Save LCD control regs */
+ for (i = 0; i < 68; i++) {
+ VGAOUT8(vgaCRIndex, i + 0x50);
+ save->CRTCRegs[i] = VGAIN8(vgaCRReg);
+ }
+
+ if (!pVia->ModeStructInit) {
+ vgaHWCopyReg(&hwp->ModeReg, vgaSavePtr);
+ memcpy(&pVia->ModeReg, save, sizeof(VIARegRec));
+ pVia->ModeStructInit = TRUE;
+ }
+ vgaHWProtect(pScrn, FALSE);
+ }
+ return;
+}
+
+
+static void VIAWriteMode(ScrnInfoPtr pScrn, vgaRegPtr vgaSavePtr,
+ VIARegPtr restore)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ VIAPtr pVia = VIAPTR(pScrn);
+ VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+ int vgaCRIndex, vgaCRReg, vgaIOBase;
+/* Bool graphicsMode = FALSE;*/
+ int i;
+ unsigned char W_Buffer[3];
+ I2CDevPtr dev = NULL;
+ CARD8 tmp
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAWriteMode\n"));
+ vgaIOBase = hwp->IOBase;
+ vgaCRIndex = vgaIOBase + 4;
+ vgaCRReg = vgaIOBase + 5;
+
+ /*
+ * If we figured out a VESA mode number for this timing, just use
+ * the VGA BIOS to do the switching, with a few additional tweaks.
+ */
+ if (restore->mode != 0xFF)
+ {
+ /* Set up the mode. Don't clear video RAM. */
+ if (!pVia->IsSecondary)
+ VIASetModeUseBIOSTable(pBIOSInfo);
+ else
+ VIASetModeForMHS(pBIOSInfo);
+
+ /* Restore the DAC.*/
+ if (pBIOSInfo->FirstInit ) {
+ vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_CMAP);
+ }
+ /*else {
+ vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_MODE);
+ }
+ vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_CMAP);*/
+ pBIOSInfo->FirstInit = FALSE;
+ /* Enable the graphics engine. */
+ if (!pVia->NoAccel)
+ VIAInitialize2DEngine(pScrn);
+
+#ifdef XF86DRI
+ VIAInitialize3DEngine(pScrn);
+#endif
+ return;
+ }
+ vgaHWProtect(pScrn, TRUE);
+ /* Unlock Extended Regs */
+ outb(0x3c4, 0x10);
+ outb(0x3c5, 0x01);
+
+ /* How can we know the mode is graphical mode or not ? */
+ /* graphicsMode = (restore->mode == 0xFF) ? FALSE : TRUE; */
+
+ VGAOUT8(vgaCRIndex, 0x6a);
+ VGAOUT8(vgaCRReg, 0);
+ VGAOUT8(vgaCRIndex, 0x6b);
+ VGAOUT8(vgaCRReg, 0);
+ VGAOUT8(vgaCRIndex, 0x6c);
+ VGAOUT8(vgaCRReg, 0);
+
+ switch (pBIOSInfo->TVEncoder) {
+ case VIA_TV2PLUS:
+ case VIA_TV3:
+ case VIA_CH7009:
+ case VIA_CH7019:
+ case VIA_SAA7108:
+ case VIA_CH7005:
+ case VIA_VT1622A:
+ dev = xf86CreateI2CDevRec();
+ dev->DevName = "TV";
+ dev->SlaveAddr = pBIOSInfo->TVI2CAdd;
+ dev->pI2CBus = pVia->I2C_Port2;
+ if (xf86I2CDevInit(dev)) {
+ for (i = 0; i < 0xFF; i++) {
+ W_Buffer[0] = (unsigned char)(i);
+ W_Buffer[1] = (unsigned char)(restore->TVRegs[i]);
+ xf86I2CWriteRead(dev, W_Buffer, 2, NULL,0);
+ }
+ xf86DestroyI2CDevRec(dev,TRUE);
+ }
+ else
+ xf86DestroyI2CDevRec(dev,TRUE);
+ break;
+ case VIA_FS454:
+ dev = xf86CreateI2CDevRec();
+ dev->DevName = "TV";
+ dev->SlaveAddr = pBIOSInfo->TVI2CAdd;
+ dev->pI2CBus = pVia->I2C_Port2;
+ if (xf86I2CDevInit(dev)) {
+
+ /* QPR programming */
+ W_Buffer[0] = 0xC4;
+ W_Buffer[1] = (unsigned char)(restore->TVRegs[0xC4]);
+ W_Buffer[2] = (unsigned char)(restore->TVRegs[0xC5]);
+ xf86I2CWriteRead(dev, W_Buffer,3, NULL,0);
+
+ /* Restore TV Regs */
+ for (i = 0; i < 0xFF; i++) {
+ W_Buffer[0] = (unsigned char)(i);
+ W_Buffer[1] = (unsigned char)(restore->TVRegs[i]);
+ if (i == 0xC4)
+ i++;
+ else
+ xf86I2CWriteRead(dev, W_Buffer, 2, NULL,0);
+ }
+ xf86DestroyI2CDevRec(dev,TRUE);
+ }
+ else
+ xf86DestroyI2CDevRec(dev,TRUE);
+ break;
+ case VIA_VT1623:
+ VIAGPIOI2C_Initial(pBIOSInfo, 0x40);
+ for (i = 0; i < 0x6C; i++) {
+ VIAGPIOI2C_Write(pBIOSInfo, i, restore->TVRegs[i]);
+ /*DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Write Back Register[%d]:0x%X\n", i, restore->TVRegs[i]));*/
+ }
+ break;
+ default:
+ break;
+ }
+
+ /* restore the standard vga regs */
+ if (xf86IsPrimaryPci(pVia->PciInfo))
+ vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_ALL);
+ else
+ vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_MODE);
+
+ /* restore extended regs */
+ VGAOUT8(0x3c4, 0x14);
+ VGAOUT8(0x3c5, restore->SR14);
+ VGAOUT8(0x3c4, 0x15);
+ VGAOUT8(0x3c5, restore->SR15);
+ VGAOUT8(0x3c4, 0x16);
+ VGAOUT8(0x3c5, restore->SR16);
+ VGAOUT8(0x3c4, 0x17);
+ VGAOUT8(0x3c5, restore->SR17);
+ VGAOUT8(0x3c4, 0x18);
+ VGAOUT8(0x3c5, restore->SR18);
+ VGAOUT8(0x3c4, 0x19);
+ VGAOUT8(0x3c5, restore->SR19);
+ VGAOUT8(0x3c4, 0x1a);
+ VGAOUT8(0x3c5, restore->SR1A);
+ VGAOUT8(0x3c4, 0x1b);
+ VGAOUT8(0x3c5, restore->SR1B);
+ VGAOUT8(0x3c4, 0x1c);
+ VGAOUT8(0x3c5, restore->SR1C);
+ VGAOUT8(0x3c4, 0x1d);
+ VGAOUT8(0x3c5, restore->SR1D);
+ VGAOUT8(0x3c4, 0x1e);
+ VGAOUT8(0x3c5, restore->SR1E);
+ VGAOUT8(0x3c4, 0x1f);
+ VGAOUT8(0x3c5, restore->SR1F);
+ VGAOUT8(0x3c4, 0x22);
+ VGAOUT8(0x3c5, restore->SR22);
+ VGAOUT8(0x3c4, 0x23);
+ VGAOUT8(0x3c5, restore->SR23);
+ VGAOUT8(0x3c4, 0x24);
+ VGAOUT8(0x3c5, restore->SR24);
+ VGAOUT8(0x3c4, 0x25);
+ VGAOUT8(0x3c5, restore->SR25);
+ VGAOUT8(0x3c4, 0x26);
+ VGAOUT8(0x3c5, restore->SR26);
+ VGAOUT8(0x3c4, 0x27);
+ VGAOUT8(0x3c5, restore->SR27);
+ VGAOUT8(0x3c4, 0x28);
+ VGAOUT8(0x3c5, restore->SR28);
+ VGAOUT8(0x3c4, 0x29);
+ VGAOUT8(0x3c5, restore->SR29);
+ VGAOUT8(0x3c4, 0x2a);
+ VGAOUT8(0x3c5, restore->SR2A);
+ VGAOUT8(0x3c4, 0x2b);
+ VGAOUT8(0x3c5, restore->SR2B);
+ VGAOUT8(0x3c4, 0x2e);
+ VGAOUT8(0x3c5, restore->SR2E);
+ VGAOUT8(0x3c4, 0x44);
+ VGAOUT8(0x3c5, restore->SR44);
+ VGAOUT8(0x3c4, 0x45);
+ VGAOUT8(0x3c5, restore->SR45);
+ VGAOUT8(0x3c4, 0x46);
+ VGAOUT8(0x3c5, restore->SR46);
+ VGAOUT8(0x3c4, 0x47);
+ VGAOUT8(0x3c5, restore->SR47);
+
+ VGAOUT8(vgaCRIndex, 0x13);
+ VGAOUT8(vgaCRReg, restore->CR13);
+ VGAOUT8(vgaCRIndex, 0x32);
+ VGAOUT8(vgaCRReg, restore->CR32);
+ VGAOUT8(vgaCRIndex, 0x33);
+ VGAOUT8(vgaCRReg, restore->CR33);
+ VGAOUT8(vgaCRIndex, 0x34);
+ VGAOUT8(vgaCRReg, restore->CR34);
+ VGAOUT8(vgaCRIndex, 0x35);
+ VGAOUT8(vgaCRReg, restore->CR35);
+ VGAOUT8(vgaCRIndex, 0x36);
+ VGAOUT8(vgaCRReg, restore->CR36);
+
+ /* Restore LCD control regs */
+ for (i = 0; i < 68; i++) {
+ VGAOUT8(vgaCRIndex, i + 0x50);
+ VGAOUT8(vgaCRReg, restore->CRTCRegs[i]);
+ }
+
+ /*if (pBIOSInfo->LVDS == VIA_CH7019LVDS) {
+ dev = xf86CreateI2CDevRec();
+ dev->DevName = "LVDS";
+ dev->SlaveAddr = 0xEA;
+ dev->pI2CBus = pVia->I2C_Port2;
+
+ if (xf86I2CDevInit(dev)) {
+ for (i = 0; i < 0x40; i++) {
+ W_Buffer[0] = (unsigned char)(i + 0x40);
+ W_Buffer[1] = (unsigned char)(restore->LCDRegs[i]);
+ xf86I2CWriteRead(dev, W_Buffer, 2, NULL,0);
+ }
+
+ xf86DestroyI2CDevRec(dev,TRUE);
+ }
+ else
+ xf86DestroyI2CDevRec(dev,TRUE);
+
+ ActiveDevice = VIABIOS_GetActiveDevice(pScrn);
+ }*/
+ if (pBIOSInfo->DefaultActiveDevice & VIA_DEVICE_LCD)
+ VIAEnableLCD(pBIOSInfo);
+
+ VIADisabledExtendedFIFO(pBIOSInfo);
+ /* Reset clock */
+ tmp = VGAIN8(0x3cc);
+ VGAOUT8(0x3c2, tmp);
+
+ /* If we're going into graphics mode and acceleration was enabled, */
+/*
+ if (graphicsMode && (!pVia->NoAccel)) {
+ VIAInitialize2DEngine(pScrn);
+ }
+*/
+ vgaHWProtect(pScrn, FALSE);
+ return;
+}
+
+
+static Bool VIAMapMMIO(ScrnInfoPtr pScrn)
+{
+ VIAPtr pVia = VIAPTR(pScrn);
+ VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+ vgaHWPtr hwp;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAMapMMIO\n"));
+
+ pVia->FrameBufferBase = pVia->PciInfo->memBase[0];
+ pVia->MmioBase = pVia->PciInfo->memBase[1];
+
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "mapping MMIO @ 0x%lx with size 0x%x\n",
+ pVia->MmioBase, VIA_MMIO_REGSIZE);
+
+ pVia->MapBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pVia->PciTag,
+ pVia->MmioBase,
+ VIA_MMIO_REGSIZE);
+ pBIOSInfo->MapBase = pVia->MapBase;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "mapping BitBlt MMIO @ 0x%lx with size 0x%x\n",
+ pVia->MmioBase + VIA_MMIO_BLTBASE, VIA_MMIO_BLTSIZE);
+
+ pVia->BltBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pVia->PciTag,
+ pVia->MmioBase + VIA_MMIO_BLTBASE,
+ VIA_MMIO_BLTSIZE);
+/*
+ pVia->FBFreeStart += 0x300000;
+ ErrorF("After 3M FBFreeStart = 0x%x\n",pVia->FBFreeStart);
+*/
+ if (!pVia->MapBase || !pVia->BltBase) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Internal error: cound not map registers\n");
+ return FALSE;
+ }
+
+ /* Memory mapped IO for Video Engine */
+ pVia->VidMapBase = pVia->MapBase + 0x200;
+
+ VIAEnableMMIO(pScrn);
+ hwp = VGAHWPTR(pScrn);
+ vgaHWGetIOBase(hwp);
+
+ return TRUE;
+}
+
+
+static Bool VIAMapFB(ScrnInfoPtr pScrn)
+{
+ VIAPtr pVia = VIAPTR(pScrn);
+ VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAMapFB\n"));
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "mapping framebuffer @ 0x%lx with size 0x%lx\n",
+ pVia->FrameBufferBase, pVia->videoRambytes);
+
+ if (pVia->videoRambytes) {
+ pVia->FBBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
+ pVia->PciTag, pVia->FrameBufferBase,
+ pVia->videoRambytes);
+ pBIOSInfo->FBBase = pVia->FBBase;
+ pBIOSInfo->videoRambytes = pVia->videoRambytes;
+
+ if (!pVia->FBBase) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Internal error: could not map framebuffer\n");
+ return FALSE;
+ }
+
+ pVia->FBStart = pVia->FBBase;
+ pVia->FBFreeStart = (pScrn->displayWidth * pScrn->bitsPerPixel >> 3) *
+ pScrn->virtualY;
+ pVia->FBFreeEnd = pVia->videoRambytes;
+
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Frame buffer start: %p, free start: 0x%x end: 0x%x\n",
+ pVia->FBStart, pVia->FBFreeStart, pVia->FBFreeEnd);
+ }
+
+ pScrn->memPhysBase = pVia->PciInfo->memBase[0];
+ pScrn->fbOffset = 0;
+ if(pVia->IsSecondary) pScrn->fbOffset = pScrn->videoRam << 10;
+
+ return TRUE;
+}
+
+
+static void VIAUnmapMem(ScrnInfoPtr pScrn)
+{
+ VIAPtr pVia;
+
+ pVia = VIAPTR(pScrn);
+
+ VIADisableMMIO(pScrn);
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAUnmapMem\n"));
+
+ if (pVia->MapBase) {
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pVia->MapBase,
+ VIA_MMIO_REGSIZE);
+ }
+
+ if (pVia->BltBase) {
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pVia->BltBase,
+ VIA_MMIO_BLTSIZE);
+ }
+
+ if (pVia->FBBase) {
+ xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pVia->FBBase,
+ pVia->videoRambytes);
+ }
+
+ return;
+}
+
+
+static Bool VIAScreenInit(int scrnIndex, ScreenPtr pScreen,
+ int argc, char **argv)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ VIAPtr pVia = VIAPTR(pScrn);
+ int ret;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAScreenInit\n"));
+ vgaHWUnlock(hwp);
+
+ if (!VIAMapFB(pScrn))
+ return FALSE;
+
+ if (!VIAMapMMIO(pScrn))
+ return FALSE;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Mem Mapped\n"));
+
+ VIASave(pScrn);
+
+ vgaHWBlankScreen(pScrn, FALSE);
+
+ if (!VIAModeInit(pScrn, pScrn->currentMode))
+ return FALSE;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- State saved\n"));
+
+ /* Darken the screen for aesthetic reasons and set the viewport */
+ VIASaveScreen(pScreen, SCREEN_SAVER_ON);
+ pScrn->AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Blanked\n"));
+
+ miClearVisualTypes();
+
+ if (pScrn->bitsPerPixel > 8 && !pVia->IsSecondary) {
+ if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
+ pScrn->rgbBits, pScrn->defaultVisual))
+ return FALSE;
+ if (!miSetPixmapDepths())
+ return FALSE;
+ } else {
+ if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
+ pScrn->rgbBits, pScrn->defaultVisual))
+ return FALSE;
+ if (!miSetPixmapDepths())
+ return FALSE;
+ }
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Visuals set up\n"));
+
+ ret = VIAInternalScreenInit(scrnIndex, pScreen);
+
+ if (!ret)
+ return FALSE;
+
+ xf86SetBlackWhitePixels(pScreen);
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- B & W\n"));
+
+ if (pScrn->bitsPerPixel > 8) {
+ VisualPtr visual;
+
+ 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;
+ }
+ }
+ }
+
+#ifdef USE_FB
+ /* must be after RGB ordering fixed */
+ fbPictureInit(pScreen, 0, 0);
+#endif
+
+ if (!pVia->NoAccel)
+ VIAInitAccel(pScreen);
+
+ miInitializeBackingStore(pScreen);
+ xf86SetBackingStore(pScreen);
+ /*xf86SetSilkenMouse(pScreen);*/
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Backing store set up\n"));
+
+ if(!pVia->shadowFB) /* hardware cursor needs to wrap this layer */
+ VIADGAInit(pScreen);
+
+ miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- SW cursor set up\n"));
+
+ if (pVia->hwcursor) {
+ if (!VIAHWCursorInit(pScreen)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Hardware cursor initialization failed\n");
+ }
+ }
+
+ if (pVia->shadowFB) {
+ RefreshAreaFuncPtr refreshArea = VIARefreshArea;
+
+ if(pVia->rotate) {
+ if (!pVia->PointerMoved) {
+ pVia->PointerMoved = pScrn->PointerMoved;
+ pScrn->PointerMoved = VIAPointerMoved;
+ }
+
+ switch(pScrn->bitsPerPixel) {
+ case 8:
+ refreshArea = VIARefreshArea8;
+ break;
+ case 16:
+ refreshArea = VIARefreshArea16;
+ break;
+ case 32:
+ refreshArea = VIARefreshArea32;
+ break;
+ }
+ }
+
+ ShadowFBInit(pScreen, refreshArea);
+ }
+
+ if (!miCreateDefColormap(pScreen))
+ return FALSE;
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Def Color map set up\n"));
+
+ if (!xf86HandleColormaps(pScreen, 256, 6, VIALoadPalette, NULL,
+ CMAP_RELOAD_ON_MODE_SWITCH
+ | CMAP_PALETTED_TRUECOLOR))
+ return FALSE;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Palette loaded\n"));
+
+ vgaHWBlankScreen(pScrn, TRUE);
+
+ pVia->CloseScreen = pScreen->CloseScreen;
+ pScreen->SaveScreen = VIASaveScreen;
+ pScreen->CloseScreen = VIACloseScreen;
+
+ xf86DPMSInit(pScreen, VIADPMS, 0);
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- DPMS set up\n"));
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Color maps etc. set up\n"));
+
+#ifdef XF86DRI
+ pVia->directRenderingEnabled = VIADRIScreenInit(pScreen);
+
+ if (pVia->directRenderingEnabled) {
+ pVia->directRenderingEnabled = VIADRIFinishScreenInit(pScreen);
+ }
+ if (pVia->directRenderingEnabled) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering enabled\n");
+ }
+ else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "direct rendering disabled\n");
+ }
+#endif
+
+ if (VIA_SERIES(pVia->Chipset) && !pVia->IsSecondary) {
+ viaFillGraphicInfo(pScrn);
+ /* There is alas not enough bandwidth to do 1600x1200x16 with video overlay */
+/* if(pScrn->bitsPerPixel * pScrn->virtualX *pScrn->virtualY <= 1400 * 1050 * 16) */
+ viaInitVideo(pScreen);
+/* else
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "video overlay disabled (%dx%d@%d exceeds bandwidth)\n",
+ pScrn->virtualX, pScrn->virtualY, pScrn->bitsPerPixel);*/
+ }
+
+ if (serverGeneration == 1)
+ xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Done\n"));
+ return TRUE;
+}
+
+
+static int VIAInternalScreenInit(int scrnIndex, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn;
+ VIAPtr pVia;
+ int width, height, displayWidth;
+ unsigned char *FBStart;
+ int ret = TRUE;
+
+ xf86DrvMsg(scrnIndex, X_INFO, "VIAInternalScreenInit\n");
+
+ pScrn = xf86Screens[pScreen->myNum];
+ pVia = VIAPTR(pScrn);
+
+ displayWidth = pScrn->displayWidth;
+
+ if (pVia->rotate) {
+ height = pScrn->virtualX;
+ width = pScrn->virtualY;
+ } else {
+ width = pScrn->virtualX;
+ height = pScrn->virtualY;
+ }
+
+ if (pVia->shadowFB) {
+ pVia->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
+ pVia->ShadowPtr = xalloc(pVia->ShadowPitch * height);
+ displayWidth = pVia->ShadowPitch / (pScrn->bitsPerPixel >> 3);
+ FBStart = pVia->ShadowPtr;
+ }
+ else {
+ pVia->ShadowPtr = NULL;
+ FBStart = pVia->FBStart;
+ }
+
+#ifdef USE_FB
+ ret = fbScreenInit(pScreen, FBStart, width, height,
+ pScrn->xDpi, pScrn->yDpi, displayWidth,
+ pScrn->bitsPerPixel);
+#else
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ ret = cfbScreenInit(pScreen, FBStart, width, height, pScrn->xDpi,
+ pScrn->yDpi, displayWidth);
+ break;
+
+ case 16:
+ ret = cfb16ScreenInit(pScreen, FBStart, width, height, pScrn->xDpi,
+ pScrn->yDpi, displayWidth);
+ break;
+
+ case 32:
+ ret = cfb32ScreenInit(pScreen, FBStart, width, height, pScrn->xDpi,
+ pScrn->yDpi, displayWidth);
+ break;
+
+ default:
+ xf86DrvMsg(scrnIndex, X_ERROR,
+ "Internal error: invalid bpp (%d) in SavageScreenInit\n",
+ pScrn->bitsPerPixel);
+ ret = FALSE;
+ break;
+ }
+#endif
+
+ return ret;
+}
+
+
+static ModeStatus VIAValidMode(int scrnIndex, DisplayModePtr mode,
+ Bool verbose, int flags)
+{
+ DEBUG(xf86DrvMsg(scrnIndex, X_INFO, "VIAValidMode\n"));
+ /* TODO check modes */
+ return MODE_OK;
+}
+
+
+static void VIABIOSInit(VIAPtr pVia, ScrnInfoPtr pScrn, DisplayModePtr pMode)
+{
+ int i;
+ VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+
+ pBIOSInfo->bitsPerPixel = pScrn->bitsPerPixel;
+ pBIOSInfo->displayWidth = pScrn->displayWidth;
+ pBIOSInfo->frameX1 = pScrn->frameX1;
+ pBIOSInfo->frameY1 = pScrn->frameY1;
+ pBIOSInfo->scrnIndex = pScrn->scrnIndex;
+
+ pBIOSInfo->Clock = pMode->Clock;
+ pBIOSInfo->HTotal = pMode->HTotal;
+ pBIOSInfo->VTotal = pMode->VTotal;
+ pBIOSInfo->HDisplay = pMode->HDisplay;
+ pBIOSInfo->VDisplay = pMode->VDisplay;
+ pBIOSInfo->CrtcHDisplay = pMode->CrtcHDisplay;
+ pBIOSInfo->CrtcVDisplay = pMode->CrtcVDisplay;
+ if (pBIOSInfo->FirstInit) {
+ pBIOSInfo->SaveframeX1 = pScrn->frameX1;
+ pBIOSInfo->SaveframeY1 = pScrn->frameY1;
+ pBIOSInfo->SaveHDisplay = pMode->HDisplay;
+ pBIOSInfo->SaveVDisplay = pMode->VDisplay;
+ pBIOSInfo->SaveCrtcHDisplay = pMode->CrtcHDisplay;
+ pBIOSInfo->SaveCrtcVDisplay = pMode->CrtcVDisplay;
+ }
+
+ pBIOSInfo->IsSecondary = pVia->IsSecondary;
+ pBIOSInfo->HasSecondary = pVia->HasSecondary;
+
+ for (i = 0; i < 0xFF; i++) {
+ pBIOSInfo->TVRegs[i] = pVia->SavedReg.TVRegs[i];
+ }
+}
+
+
+static void VIAPostFindMode(VIAPtr pVia, ScrnInfoPtr pScrn, DisplayModePtr pMode)
+{
+ VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+
+ pVia->ModeReg.mode = pBIOSInfo->mode;
+ pVia->ModeReg.resMode = pBIOSInfo->resMode;
+ pVia->ModeReg.refresh = pBIOSInfo->refresh;
+ pVia->ModeReg.offsetWidthByQWord = pBIOSInfo->offsetWidthByQWord;
+ pVia->ModeReg.countWidthByQWord = pBIOSInfo->countWidthByQWord;
+
+ pScrn->frameX1 = pBIOSInfo->frameX1;
+ pScrn->frameY1 = pBIOSInfo->frameY1;
+ pMode->HDisplay = pBIOSInfo->HDisplay;
+ pMode->VDisplay = pBIOSInfo->VDisplay;
+
+}
+
+
+static Bool VIAModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ VIAPtr pVia = VIAPTR(pScrn);
+ VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+ VIARegPtr new = &pVia->ModeReg;
+ vgaRegPtr vganew = &hwp->ModeReg;
+ /* DDUPDATEOVERLAY UpdateOverlay; */
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAModeInit\n"));
+
+
+ if (!vgaHWInit(pScrn, mode)) {
+ vgaHWBlankScreen(pScrn, TRUE);
+ return FALSE;
+ }
+
+ pScrn->vtSema = TRUE;
+
+ VIABIOSInit(pVia, pScrn, mode);
+
+ if (!VIAFindModeUseBIOSTable(pBIOSInfo)) {
+ vgaHWBlankScreen(pScrn, TRUE);
+ VIAFreeRec(pScrn);
+ return FALSE;
+ }
+
+ VIAPostFindMode(pVia, pScrn, mode);
+
+ /* FIXME - need DRI lock for this bit - see i810 */
+ /* do it! */
+ VIAWriteMode(pScrn, vganew, new);
+
+ /* pass graphic info to via_v4l kernel module */
+ /* Coz mode changes, some member in pVia->graphicInfo need to modify */
+ if (VIA_SERIES(pVia->Chipset) && !pVia->IsSecondary)
+ {
+ viaFillGraphicInfo(pScrn);
+
+ DBG_DD(ErrorF("SWOV: VIAVidSet2DInfo\n"));
+
+ /* Save MCLK value*/
+ VGAOUT8(0x3C4, 0x16); pVia->swov.Save_3C4_16 = VGAIN8(0x3C5);
+ DBG_DD(ErrorF(" 3c4.16 : %08x \n",VGAIN8(0x3C5)));
+ VGAOUT8(0x3C4, 0x17); pVia->swov.Save_3C4_17 = VGAIN8(0x3C5);
+ DBG_DD(ErrorF(" 3c4.17 : %08x \n",VGAIN8(0x3C5)));
+ VGAOUT8(0x3C4, 0x18); pVia->swov.Save_3C4_18 = VGAIN8(0x3C5);
+ DBG_DD(ErrorF(" 3c4.18 : %08x \n",VGAIN8(0x3C5)));
+ }
+ VIAAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
+ return TRUE;
+}
+
+
+static Bool VIACloseScreen(int scrnIndex, ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ VIAPtr pVia = VIAPTR(pScrn);
+ vgaRegPtr vgaSavePtr = &hwp->SavedReg;
+ VIARegPtr viaSavePtr = &pVia->SavedReg;
+ CARD32 dwCursorMode;
+
+ DEBUG(xf86DrvMsg(scrnIndex, X_INFO, "VIACloseScreen\n"));
+
+ /* Is the display currently visible ? */
+ if(pScrn->vtSema)
+ {
+ /* Wait Hardware Engine idle to exit graphical mode */
+ WaitIdle();
+
+ /* Patch for normal log out and restart X, 3D application will hang */
+ VIAWriteMode(pScrn, vgaSavePtr, viaSavePtr);
+
+ if (!pVia->IsSecondary) {
+ /* Turn off all video activities */
+ viaExitVideo(pScrn);
+ /* Diable Hardware Cursor */
+ dwCursorMode = VIAGETREG(VIA_REG_CURSOR_MODE);
+ VIASETREG(VIA_REG_CURSOR_MODE, dwCursorMode & 0xFFFFFFFE);
+ }
+
+ if (pVia->VQEnable) {
+ /* if we use VQ, disable it before we exit */
+ VIASETREG(0x43c, 0x00fe0000);
+ VIASETREG(0x440, 0x00000004);
+ }
+ }
+ if (pVia->AccelInfoRec) {
+ XAADestroyInfoRec(pVia->AccelInfoRec);
+ pVia->AccelInfoRec = NULL;
+ }
+ if (pVia->CursorInfoRec) {
+ xf86DestroyCursorInfoRec(pVia->CursorInfoRec);
+ pVia->CursorInfoRec = NULL;
+ }
+ if (pVia->ShadowPtr) {
+ xfree(pVia->ShadowPtr);
+ pVia->ShadowPtr = NULL;
+ }
+ if (pVia->DGAModes) {
+ xfree(pVia->DGAModes);
+ pVia->DGAModes = NULL;
+ }
+ if(pVia->pInt10) {
+ xf86FreeInt10(pVia->pInt10);
+ pVia->pInt10 = NULL;
+ }
+
+ if (pScrn->vtSema) {
+ VIAWriteMode(pScrn, vgaSavePtr, viaSavePtr);
+ vgaHWLock(hwp);
+ VIAUnmapMem(pScrn);
+ }
+ pScrn->vtSema = FALSE;
+ pScreen->CloseScreen = pVia->CloseScreen;
+ return (*pScreen->CloseScreen)(scrnIndex, pScreen);
+}
+
+/*
+ * This only gets called when a screen is being deleted. It does not
+ * get called routinely at the end of a server generation.
+ */
+static void VIAFreeScreen(int scrnIndex, int flags)
+{
+ DEBUG(xf86DrvMsg(scrnIndex, X_INFO, "VIAFreeScreen\n"));
+ if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
+ vgaHWFreeHWRec(xf86Screens[scrnIndex]);
+ VIAFreeRec(xf86Screens[scrnIndex]);
+}
+
+static Bool VIASaveScreen(ScreenPtr pScreen, int mode)
+{
+ return vgaHWSaveScreen(pScreen, mode);
+}
+
+
+void VIAAdjustFrame(int scrnIndex, int x, int y, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ VIAPtr pVia = VIAPTR(pScrn);
+ int Base, tmp;
+ int vgaCRIndex, vgaCRReg, vgaIOBase;
+ DDLOCK ddLock;
+ LPDDLOCK lpddLock = &ddLock;
+ DDUPDATEOVERLAY UpdateOverlay;
+ ADJUSTFRAME AdjustFrame;
+
+ DEBUG(xf86DrvMsg(scrnIndex, X_INFO, "VIAAdjustFrame\n"));
+ vgaIOBase = hwp->IOBase;
+ vgaCRIndex = vgaIOBase + 4;
+ vgaCRReg = vgaIOBase + 5;
+
+ Base = (y * pScrn->displayWidth + x) * (pScrn->bitsPerPixel / 8);
+
+ /* now program the start address registers */
+ if (pVia->IsSecondary) {
+ Base = (Base + pScrn->fbOffset) >> 3;
+ VGAOUT8(vgaCRIndex, 0x62);
+ tmp = VGAIN8(vgaCRReg) & 0x01;
+ tmp |= (Base & 0x7F) << 1;
+ VGAOUT8(vgaCRReg, tmp);
+ VGAOUT8(vgaCRIndex, 0x63);
+ VGAOUT8(vgaCRReg, ((Base & 0x7F80) >> 7));
+ VGAOUT8(vgaCRIndex, 0x64);
+ VGAOUT8(vgaCRReg, ((Base & 0x7F8000) >> 15));
+ }
+ else {
+ Base = Base >> 1;
+ VGAOUT16(vgaCRIndex, (Base & 0x00ff00) | 0x0c);
+ VGAOUT16(vgaCRIndex, ((Base & 0x00ff) << 8) | 0x0d);
+ VGAOUT16(vgaCRIndex, ((Base & 0xff0000) >> 8) | 0x34);
+ }
+
+ /* Pass Panning (x, y) info to V4L */
+ AdjustFrame.x = x;
+ AdjustFrame.y = y;
+
+ VIAVidAdjustFrame(pScrn,&AdjustFrame);
+
+ /* Check if HW mpeg engine active */
+ if (pVia->Video.VideoStatus & SW_VIDEO_ON) /* SW video case */
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
+ " Call SW MPEG UpdateOverlay at panning mode.\n");
+
+ ddLock.dwFourCC = FOURCC_YUY2;
+
+ VIAVidLockSurface(pScrn, &ddLock);
+
+ UpdateOverlay.dwFlags = DDOVER_SHOW | DDOVER_KEYDEST;
+ UpdateOverlay.dwColorSpaceLowValue = VIAGETREG(0x220);
+ UpdateOverlay.rSrc.left = 0;
+ UpdateOverlay.rSrc.top = 0;
+ UpdateOverlay.rSrc.right = 720;
+ UpdateOverlay.rSrc.bottom = 480;
+
+ UpdateOverlay.rDest.left = (int) lpddLock->SWDevice.gdwSWDstLeft;
+ UpdateOverlay.rDest.top = (int) lpddLock->SWDevice.gdwSWDstTop;
+ UpdateOverlay.rDest.right = UpdateOverlay.rDest.left + lpddLock->SWDevice.gdwSWDstWidth;
+ UpdateOverlay.rDest.bottom = UpdateOverlay.rDest.top + lpddLock->SWDevice.gdwSWDstHeight;
+
+ VIAVidUpdateOverlay(pScrn, &UpdateOverlay);
+ }
+ else if (VIAGETREG(0x310) & 0x1) /* capture 0 (TV0) case */
+ {
+ ddLock.dwFourCC = FOURCC_TV0;
+
+ VIAVidLockSurface(pScrn, &ddLock);
+ }
+
+ if (VIAGETREG(0x354) & 0x1) /* capture 1 (TV1) case */
+ {
+ ddLock.dwFourCC = FOURCC_TV1;
+
+ VIAVidLockSurface(pScrn, &ddLock);
+ }
+
+ return;
+}
+
+
+Bool VIASwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+{
+ ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+ VIAPtr pVia = VIAPTR(pScrn);
+
+ DEBUG(xf86DrvMsg(scrnIndex, X_INFO, "VIASwitchMode\n"));
+ /* Wait Hardware Engine idle to switch graphicd mode */
+ WaitIdle();
+
+ if (pVia->VQEnable) {
+ /* if we use VQ, disable it before we exit */
+ VIASETREG(0x43c, 0x00fe0000);
+ VIASETREG(0x440, 0x00000004);
+ }
+
+ return VIAModeInit(xf86Screens[scrnIndex], mode);
+}
+
+
+void VIAEnableMMIO(ScrnInfoPtr pScrn)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ VIAPtr pVia = VIAPTR(pScrn);
+ unsigned char val;
+
+ if (xf86IsPrimaryPci(pVia->PciInfo)) {
+ /* If we are primary card, we still use std vga port. If we use
+ * MMIO, system will hang in vgaHWSave when our card used in
+ * PLE and KLE (integrated Trident MVP4)
+ */
+ vgaHWSetStdFuncs(hwp);
+ }
+ else {
+ vgaHWSetMmioFuncs(hwp, pVia->MapBase, 0x8000);
+ }
+
+ val = VGAIN8(0x3c3);
+ VGAOUT8(0x3c3, val | 0x01);
+ val = VGAIN8(VGA_MISC_OUT_R);
+ VGAOUT8(VGA_MISC_OUT_W, val | 0x01);
+
+ /* Unlock Extended IO Space */
+ VGAOUT8(0x3c4, 0x10);
+ VGAOUT8(0x3c5, 0x01);
+
+ /* Enable MMIO */
+ if(!pVia->IsSecondary) {
+ VGAOUT8(0x3c4, 0x1a);
+ val = VGAIN8(0x3c5);
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "primary val = %x\n", val));
+ VGAOUT8(0x3c5, val | 0x68);
+ }
+ else {
+ VGAOUT8(0x3c4, 0x1a);
+ val = VGAIN8(0x3c5);
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "secondary val = %x\n", val));
+ VGAOUT8(0x3c5, val | 0x38);
+ }
+
+ return;
+}
+
+
+void VIADisableMMIO(ScrnInfoPtr pScrn)
+{
+ VIAPtr pVia = VIAPTR(pScrn);
+ unsigned char val;
+
+ VGAOUT8(0x3c4, 0x1a);
+ val = VGAIN8(0x3c5);
+ VGAOUT8(0x3c5, val & 0x97);
+
+ return;
+}
+
+
+void VIALoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies,
+ LOCO *colors, VisualPtr pVisual)
+{
+ VIAPtr pVia = VIAPTR(pScrn);
+ int i, index;
+ int sr1a, sr1b, cr67, cr6a;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIALoadPalette\n"));
+
+ if (pScrn->bitsPerPixel != 8)
+ return;
+ VGAOUT8(0x3C4, 0x1A);
+ sr1a = VGAIN8(0x3C5);
+ VGAOUT8(0x3C4, 0x1B);
+ sr1b = VGAIN8(0x3C5);
+ VGAOUT8(0x3D4, 0x67);
+ cr67 = VGAIN8(0x3D5);
+ VGAOUT8(0x3D4, 0x6A);
+ cr6a = VGAIN8(0x3D5);
+
+ if (pVia->IsSecondary) {
+ VGAOUT8(0x3C4, 0x1A);
+ VGAOUT8(0x3C5, sr1a | 0x01);
+ VGAOUT8(0x3C4, 0x1B);
+ VGAOUT8(0x3C5, sr1b | 0x80);
+ VGAOUT8(0x3D4, 0x67);
+ VGAOUT8(0x3D5, cr67 & 0x3F);
+ VGAOUT8(0x3D4, 0x6A);
+ VGAOUT8(0x3D5, cr6a | 0xC0);
+ }
+
+ for (i = 0; i < numColors; i++) {
+ index = indicies[i];
+ VGAOUT8(0x3c8, index);
+ VGAOUT8(0x3c9, colors[index].red);
+ VGAOUT8(0x3c9, colors[index].green);
+ VGAOUT8(0x3c9, colors[index].blue);
+ }
+
+ if (pVia->IsSecondary) {
+ VGAOUT8(0x3C4, 0x1A);
+ VGAOUT8(0x3C5, sr1a);
+ VGAOUT8(0x3C4, 0x1B);
+ VGAOUT8(0x3C5, sr1b);
+ VGAOUT8(0x3D4, 0x67);
+ VGAOUT8(0x3D5, cr67);
+ VGAOUT8(0x3D4, 0x6A);
+ VGAOUT8(0x3D5, cr6a);
+
+ /* Screen 0 palette was changed by mode setting of Screen 1,
+ * so load again */
+ for (i = 0; i < numColors; i++) {
+ index = indicies[i];
+ VGAOUT8(0x3c8, index);
+ VGAOUT8(0x3c9, colors[index].red);
+ VGAOUT8(0x3c9, colors[index].green);
+ VGAOUT8(0x3c9, colors[index].blue);
+ }
+
+ }
+
+}
+
+
+static void VIADPMS(ScrnInfoPtr pScrn, int mode, int flags)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ VIAPtr pVia = VIAPTR(pScrn);
+ VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+ int vgaCRIndex, vgaCRReg;
+ CARD8 val;
+
+ I2CDevPtr dev;
+ unsigned char W_Buffer[2];
+
+ vgaCRIndex = hwp->IOBase + 4;
+ vgaCRReg = hwp->IOBase + 5;
+
+ /* Clear DPMS setting */
+ VGAOUT8(vgaCRIndex, 0x36);
+ val = VGAIN8(vgaCRReg);
+ val &= 0xCF;
+ /* Turn Off CRT, if user doesn't want crt on */
+ if (!pVia->IsSecondary && !(pBIOSInfo->ActiveDevice & VIA_DEVICE_CRT1)) {
+ val |= 0x30;
+ }
+
+ switch (mode) {
+ case DPMSModeOn:
+ if (pBIOSInfo->ActiveDevice & (VIA_DEVICE_DFP | VIA_DEVICE_LCD)) {
+ /* Enable LCD */
+ VIAEnableLCD(pBIOSInfo);
+ }
+
+ if (pBIOSInfo->ActiveDevice & VIA_DEVICE_TV) {
+ dev = xf86CreateI2CDevRec();
+ dev->DevName = "TV";
+ dev->SlaveAddr = pBIOSInfo->TVI2CAdd;
+ dev->pI2CBus = pBIOSInfo->I2C_Port2;
+ if (xf86I2CDevInit(dev)) {
+ switch (pBIOSInfo->TVEncoder) {
+ case VIA_TV2PLUS:
+ case VIA_TV3:
+ case VIA_VT1622A:
+ W_Buffer[0] = 0x0E;
+ W_Buffer[1] = 0x0;
+ xf86I2CWriteRead(dev, W_Buffer,2, NULL,0);
+ break;
+ case VIA_VT1623:
+ VIAGPIOI2C_Initial(pBIOSInfo, 0x40);
+ VIAGPIOI2C_Write(pBIOSInfo, 0x0E, 0);
+ break;
+ case VIA_CH7019:
+ W_Buffer[0] = 0x49;
+ W_Buffer[1] = 0x20;
+ xf86I2CWriteRead(dev, W_Buffer,2, NULL,0);
+ /*W_Buffer[0] = 0x1E;
+ W_Buffer[1] = 0xD0;
+ xf86I2CWriteRead(dev, W_Buffer,2, NULL,0);*/
+ break;
+ case VIA_SAA7108:
+ W_Buffer[0] = 0x2D;
+ switch (pBIOSInfo->TVOutput) {
+ case TVOUTPUT_COMPOSITE:
+ case TVOUTPUT_SVIDEO:
+ W_Buffer[1] = 0xB4;
+ break;
+ case TVOUTPUT_RGB:
+ W_Buffer[1] = 0;
+ break;
+ case TVOUTPUT_YCBCR:
+ W_Buffer[1] = 0x84;
+ break;
+ default:
+ W_Buffer[1] = 0x08;
+ break;
+ }
+ xf86I2CWriteRead(dev, W_Buffer,2, NULL,0);
+ break;
+ default:
+ break;
+ }
+ xf86DestroyI2CDevRec(dev,TRUE);
+ }
+ else
+ xf86DestroyI2CDevRec(dev,TRUE);
+ }
+ VGAOUT8(vgaCRIndex, 0x36);
+ VGAOUT8(vgaCRReg, val);
+ break;
+ case DPMSModeStandby:
+ case DPMSModeSuspend:
+ case DPMSModeOff:
+ if (pBIOSInfo->ActiveDevice & (VIA_DEVICE_DFP | VIA_DEVICE_LCD)) {
+ VIADisableLCD(pBIOSInfo);
+ }
+ if (pBIOSInfo->ActiveDevice & VIA_DEVICE_TV) {
+ dev = xf86CreateI2CDevRec();
+ dev->DevName = "TV";
+ dev->SlaveAddr = pBIOSInfo->TVI2CAdd;
+ dev->pI2CBus = pBIOSInfo->I2C_Port2;
+ if (xf86I2CDevInit(dev)) {
+ switch (pBIOSInfo->TVEncoder) {
+ case VIA_TV2PLUS:
+ W_Buffer[0] = 0x0E;
+ W_Buffer[1] = 0x03;
+ xf86I2CWriteRead(dev, W_Buffer,2, NULL,0);
+ break;
+ case VIA_TV3:
+ case VIA_VT1622A:
+ W_Buffer[0] = 0x0E;
+ W_Buffer[1] = 0x0F;
+ xf86I2CWriteRead(dev, W_Buffer,2, NULL,0);
+ break;
+ case VIA_VT1623:
+ VIAGPIOI2C_Initial(pBIOSInfo, 0x40);
+ VIAGPIOI2C_Write(pBIOSInfo, 0x0E, 0x0F);
+ break;
+ case VIA_CH7019:
+ W_Buffer[0] = 0x49;
+ W_Buffer[1] = 0x3E;
+ xf86I2CWriteRead(dev, W_Buffer,2, NULL,0);
+ W_Buffer[0] = 0x1E;
+ W_Buffer[1] = 0xD0;
+ xf86I2CWriteRead(dev, W_Buffer,2, NULL,0);
+ break;
+ case VIA_SAA7108:
+ W_Buffer[0] = 0x2D;
+ W_Buffer[1] = 0x08;
+ xf86I2CWriteRead(dev, W_Buffer,2, NULL,0);
+ break;
+ default:
+ break;
+ }
+ xf86DestroyI2CDevRec(dev,TRUE);
+ }
+ else
+ xf86DestroyI2CDevRec(dev,TRUE);
+ }
+
+ val |= 0x30;
+ VGAOUT8(vgaCRIndex, 0x36);
+ VGAOUT8(vgaCRReg, val);
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid DPMS mode %d\n", mode);
+ break;
+ }
+ return;
+}
+
+
+int VIAGetMemSize()
+{
+ /* TODO: Do memory sizing */
+
+ /* Default 16MB */
+ return (16 << 10);
+}
+
+/* Active Device according connected status */
+Bool VIADeviceSelection(ScrnInfoPtr pScrn)
+{
+ VIAPtr pVia = VIAPTR(pScrn);
+ VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+ /*unsigned int i;
+ unsigned char numDevice;*/
+ pBIOSInfo->SAMM = FALSE;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIADeviceSelection\n"));
+ pBIOSInfo->DefaultActiveDevice = VIABIOS_GetActiveDevice(pScrn);
+ /* if XF86Config Option "ActiveDevice" hasn't set, active device according CMOS */
+ if (!pBIOSInfo->ActiveDevice) {
+ pBIOSInfo->ActiveDevice = pBIOSInfo->DefaultActiveDevice;
+ }
+ /* if XF86Config-4 set SAMM, and only active one device, active device according CMOS */
+ else if (pVia->IsSecondary && (pBIOSInfo->ActiveDevice == VIA_DEVICE_CRT1 ||
+ pBIOSInfo->ActiveDevice == VIA_DEVICE_LCD ||
+ pBIOSInfo->ActiveDevice == VIA_DEVICE_TV ||
+ pBIOSInfo->ActiveDevice == VIA_DEVICE_DFP ||
+ pBIOSInfo->ActiveDevice == VIA_DEVICE_CRT2)){
+ pBIOSInfo->ActiveDevice = VIABIOS_GetActiveDevice(pScrn);
+ }
+ if (((pBIOSInfo->ActiveDevice & pBIOSInfo->ConnectedDevice) == pBIOSInfo->ActiveDevice)
+ && (pVia->IsSecondary)) {
+ pBIOSInfo->SAMM = TRUE;
+ }
+ pBIOSInfo->ActiveDevice &= pBIOSInfo->ConnectedDevice;
+ pVia->ActiveDevice = pBIOSInfo->ActiveDevice;
+
+ /*if (pBIOSInfo->ActiveDevice & VIA_DEVICE_LCD) {
+ pBIOSInfo->DVIEncoder = VIA_VT3191;
+ numDevice = 0x02;
+ i = VIABIOS_GetDisplayDeviceInfo(pScrn, &numDevice);
+ if (i != 0xFFFF) {
+ if (pBIOSInfo->PanelSize == VIA_PANEL_INVALID)
+ pBIOSInfo->PanelSize = numDevice;
+ }*/
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Connected Device is %d\n", pBIOSInfo->ConnectedDevice));
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Active Device is %d\n", pBIOSInfo->ActiveDevice));
+
+ return TRUE;
+}
+
+/* SAMM device dispatch */
+Bool VIADeviceDispatch(ScrnInfoPtr pScrn)
+{
+ DevUnion* pPriv = xf86GetEntityPrivate(pScrn->entityList[0], gVIAEntityIndex);
+ VIAEntPtr pVIAEnt = pPriv->ptr;
+ VIAPtr pVia1 = VIAPTR(pScrn), pVia0 = VIAPTR(pVIAEnt->pPrimaryScrn);
+ VIABIOSInfoPtr pBIOSInfo1 = pVia1->pBIOSInfo, pBIOSInfo0 = pVia0->pBIOSInfo;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIADeviceDispatch\n"));
+ pBIOSInfo0->SAMM = TRUE;
+ switch (pBIOSInfo1->ActiveDevice) {
+ case (VIA_DEVICE_CRT1 | VIA_DEVICE_LCD) : /* If CRT + LCD, CRT is IGA1 */
+ pBIOSInfo0->ActiveDevice = VIA_DEVICE_CRT1;
+ pBIOSInfo1->ActiveDevice = VIA_DEVICE_LCD;
+ break;
+ case (VIA_DEVICE_CRT1 | VIA_DEVICE_TV) : /* If CRT + TV, CRT is IGA1 */
+ pBIOSInfo0->ActiveDevice = VIA_DEVICE_CRT1;
+ pBIOSInfo1->ActiveDevice = VIA_DEVICE_TV;
+ break;
+ case (VIA_DEVICE_CRT1 | VIA_DEVICE_DFP) : /* If CRT + DFP, CRT is IGA1 */
+ pBIOSInfo0->ActiveDevice = VIA_DEVICE_CRT1;
+ pBIOSInfo1->ActiveDevice = VIA_DEVICE_DFP;
+ break;
+ case (VIA_DEVICE_LCD | VIA_DEVICE_TV) : /* If LCD + TV, TV is IGA1 */
+ pBIOSInfo0->ActiveDevice = VIA_DEVICE_TV;
+ pBIOSInfo1->ActiveDevice = VIA_DEVICE_LCD;
+ break;
+ case (VIA_DEVICE_LCD | VIA_DEVICE_DFP) : /* If LCD + DFP, DFP is IGA1 */
+ pBIOSInfo0->ActiveDevice = VIA_DEVICE_DFP;
+ pBIOSInfo1->ActiveDevice = VIA_DEVICE_LCD;
+ break;
+ case (VIA_DEVICE_TV | VIA_DEVICE_DFP) : /* If TV + DFP, TV is IGA1 */
+ pBIOSInfo0->ActiveDevice = VIA_DEVICE_TV;
+ pBIOSInfo1->ActiveDevice = VIA_DEVICE_DFP;
+ break;
+ default :
+ return FALSE;
+ break;
+ }
+ DEBUG(xf86DrvMsg(pVIAEnt->pPrimaryScrn->scrnIndex, X_INFO, "Active Device is %d\n", pBIOSInfo0->ActiveDevice));
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Active Device is %d\n", pBIOSInfo1->ActiveDevice));
+ return TRUE;
+}
+
+#ifdef XF86DRI
+void
+VIAInitialize3DEngine(ScrnInfoPtr pScrn)
+{
+ VIAPtr pVia = VIAPTR(pScrn);
+ int i;
+
+ if (!pVia->sharedData->b3DRegsInitialized)
+ {
+
+ VIASETREG(0x43C, 0x00010000);
+
+ for (i = 0; i <= 0x7D; i++)
+ {
+ VIASETREG(0x440, (CARD32) i << 24);
+ }
+
+ VIASETREG(0x43C, 0x00020000);
+
+ for (i = 0; i <= 0x94; i++)
+ {
+ VIASETREG(0x440, (CARD32) i << 24);
+ }
+
+ VIASETREG(0x440, 0x82400000);
+
+ VIASETREG(0x43C, 0x01020000);
+
+
+ for (i = 0; i <= 0x94; i++)
+ {
+ VIASETREG(0x440, (CARD32) i << 24);
+ }
+
+ VIASETREG(0x440, 0x82400000);
+ VIASETREG(0x43C, 0xfe020000);
+
+ for (i = 0; i <= 0x03; i++)
+ {
+ VIASETREG(0x440, (CARD32) i << 24);
+ }
+
+ VIASETREG(0x43C, 0x00030000);
+
+ for (i = 0; i <= 0xff; i++)
+ {
+ VIASETREG(0x440, 0);
+ }
+ VIASETREG(0x43C, 0x00100000);
+ VIASETREG(0x440, 0x00333004);
+ VIASETREG(0x440, 0x10000002);
+ VIASETREG(0x440, 0x60000000);
+ VIASETREG(0x440, 0x61000000);
+ VIASETREG(0x440, 0x62000000);
+ VIASETREG(0x440, 0x63000000);
+ VIASETREG(0x440, 0x64000000);
+
+ VIASETREG(0x43C, 0x00fe0000);
+
+ if (pVia->ChipRev >= 3 )
+ VIASETREG(0x440,0x40008c0f);
+ else
+ VIASETREG(0x440,0x4000800f);
+
+ VIASETREG(0x440,0x44000000);
+ VIASETREG(0x440,0x45080C04);
+ VIASETREG(0x440,0x46800408);
+ VIASETREG(0x440,0x50000000);
+ VIASETREG(0x440,0x51000000);
+ VIASETREG(0x440,0x52000000);
+ VIASETREG(0x440,0x53000000);
+
+ pVia->sharedData->b3DRegsInitialized = 1;
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "3D Register has been initilized !\n");
+ }
+
+ VIASETREG(0x43C,0x00fe0000);
+ VIASETREG(0x440,0x08000001);
+ VIASETREG(0x440,0x0A000183);
+ VIASETREG(0x440,0x0B00019F);
+ VIASETREG(0x440,0x0C00018B);
+ VIASETREG(0x440,0x0D00019B);
+ VIASETREG(0x440,0x0E000000);
+ VIASETREG(0x440,0x0F000000);
+ VIASETREG(0x440,0x10000000);
+ VIASETREG(0x440,0x11000000);
+ VIASETREG(0x440,0x20000000);
+}
+#endif