summaryrefslogtreecommitdiff
path: root/trunk/src/via_vt162x.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/via_vt162x.c')
-rw-r--r--trunk/src/via_vt162x.c846
1 files changed, 846 insertions, 0 deletions
diff --git a/trunk/src/via_vt162x.c b/trunk/src/via_vt162x.c
new file mode 100644
index 000000000000..ac01a92a3b91
--- /dev/null
+++ b/trunk/src/via_vt162x.c
@@ -0,0 +1,846 @@
+/*
+ * Copyright 2004-2005 The Unichrome Project [unichrome.sf.net]
+ * 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
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "via_driver.h"
+#include "via_vgahw.h"
+#include "via_vt162x.h"
+#include "via_id.h"
+
+/*
+ *
+ */
+static void
+VT162xPrintRegs(ScrnInfoPtr pScrn)
+{
+ VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
+ CARD8 i, buf;
+
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Printing registers for %s\n",
+ pBIOSInfo->TVI2CDev->DevName);
+
+ for (i = 0; i < pBIOSInfo->TVNumRegs; i++) {
+ xf86I2CReadByte(pBIOSInfo->TVI2CDev, i, &buf);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV%02X: 0x%02X\n", i, buf);
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of TV registers.\n");
+}
+
+/*
+ *
+ */
+I2CDevPtr
+ViaVT162xDetect(ScrnInfoPtr pScrn, I2CBusPtr pBus, CARD8 Address)
+{
+ VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
+ I2CDevPtr pDev = xf86CreateI2CDevRec();
+ CARD8 buf;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaVT162xDetect\n"));
+
+ pDev->DevName = "VT162x";
+ pDev->SlaveAddr = Address;
+ pDev->pI2CBus = pBus;
+
+ if (!xf86I2CDevInit(pDev)) {
+ xf86DestroyI2CDevRec(pDev, TRUE);
+ return NULL;
+ }
+
+ if (!xf86I2CReadByte(pDev, 0x1B, &buf)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to read from %s Slave %d.\n",
+ pBus->BusName, Address);
+ xf86DestroyI2CDevRec(pDev, TRUE);
+ return NULL;
+ }
+
+ switch (buf) {
+ case 0x02:
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Detected VIA Technologies VT1621 TV Encoder\n");
+ pBIOSInfo->TVEncoder = VIA_VT1621;
+ pDev->DevName = "VT1621";
+ break;
+ case 0x03:
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Detected VIA Technologies VT1622 TV Encoder\n");
+ pBIOSInfo->TVEncoder = VIA_VT1622;
+ pDev->DevName = "VT1622";
+ break;
+ case 0x10:
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Detected VIA Technologies VT1622A/VT1623 TV Encoder\n");
+ pBIOSInfo->TVEncoder = VIA_VT1623;
+ pDev->DevName = "VT1623";
+ break;
+ case 0x50:
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "Detected VIA Technologies VT1625 TV Encoder\n");
+ pBIOSInfo->TVEncoder = VIA_VT1625;
+ pDev->DevName = "VT1625";
+ break;
+ default:
+ pBIOSInfo->TVEncoder = VIA_NONETV;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Unknown TV Encoder found at %s %X.\n", pBus->BusName, Address);
+ xf86DestroyI2CDevRec(pDev,TRUE);
+ pDev = NULL;
+ break;
+ }
+
+ return pDev;
+}
+
+/*
+ *
+ */
+static void
+VT162xSave(ScrnInfoPtr pScrn)
+{
+ int i;
+ VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT162xSave\n"));
+
+ for (i = 0; i < pBIOSInfo->TVNumRegs; i++)
+ xf86I2CReadByte(pBIOSInfo->TVI2CDev, i, &(pBIOSInfo->TVRegs[i]));
+
+}
+
+/*
+ *
+ */
+static void
+VT162xRestore(ScrnInfoPtr pScrn)
+{
+ VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
+ int i;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT162xRestore\n"));
+
+ for (i = 0; i < pBIOSInfo->TVNumRegs; i++)
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, pBIOSInfo->TVRegs[i]);
+}
+
+/*
+ * the same for VT1621 as for VT1622/VT1622A/VT1623, result is different though
+ * still needs testing on vt1621 of course.
+ */
+static CARD8
+VT162xDACSenseI2C(I2CDevPtr pDev)
+{
+ CARD8 save, sense;
+
+ xf86I2CReadByte(pDev, 0x0E, &save);
+ xf86I2CWriteByte(pDev, 0x0E, 0x00);
+ xf86I2CWriteByte(pDev, 0x0E, 0x80);
+ xf86I2CWriteByte(pDev, 0x0E, 0x00);
+ xf86I2CReadByte(pDev, 0x0F, &sense);
+ xf86I2CWriteByte(pDev, 0x0E, save);
+
+ return (sense & 0x0F);
+}
+
+/*
+ * VT1625 moves DACa through DACd from bits 0-3 to 2-5
+ */
+static CARD8
+VT1625DACSenseI2C(I2CDevPtr pDev)
+{
+ CARD8 save, sense;
+
+ xf86I2CReadByte(pDev, 0x0E, &save);
+ xf86I2CWriteByte(pDev, 0x0E, 0x00);
+ xf86I2CWriteByte(pDev, 0x0E, 0x80);
+ xf86I2CWriteByte(pDev, 0x0E, 0x00);
+ xf86I2CReadByte(pDev, 0x0F, &sense);
+ xf86I2CWriteByte(pDev, 0x0E, save);
+
+ return (sense & 0x3F);
+}
+
+/*
+ * VT1621 only knows composite and s-video
+ */
+static Bool
+VT1621DACSense(ScrnInfoPtr pScrn)
+{
+ VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
+ CARD8 sense;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621DACSense\n"));
+
+ sense = VT162xDACSenseI2C(pBIOSInfo->TVI2CDev);
+ switch (sense) {
+ case 0x00:
+ pBIOSInfo->TVOutput = TVOUTPUT_SC;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VT1621: S-Video & Composite connected.\n");
+ return TRUE;
+ case 0x01:
+ pBIOSInfo->TVOutput = TVOUTPUT_COMPOSITE;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VT1621: Composite connected.\n");
+ return TRUE;
+ case 0x02:
+ pBIOSInfo->TVOutput = TVOUTPUT_SVIDEO;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VT1621: S-Video connected.\n");
+ return TRUE;
+ case 0x03:
+ pBIOSInfo->TVOutput = TVOUTPUT_NONE;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VT1621: Nothing connected.\n");
+ return FALSE;
+ default:
+ pBIOSInfo->TVOutput = TVOUTPUT_NONE;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VT1621: Unknown cable combination: 0x0%2X.\n",
+ sense);
+ return FALSE;
+ }
+}
+
+
+/*
+ * VT1622, VT1622A and VT1623 know composite, s-video, RGB and YCBCR
+ */
+static Bool
+VT1622DACSense(ScrnInfoPtr pScrn)
+{
+ VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
+ CARD8 sense;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622DACSense\n"));
+
+ sense = VT162xDACSenseI2C(pBIOSInfo->TVI2CDev);
+ switch (sense) {
+ case 0x00: /* DAC A,B,C,D */
+ pBIOSInfo->TVOutput = TVOUTPUT_RGB;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VT162x: RGB connected.\n");
+ return TRUE;
+ case 0x01: /* DAC A,B,C */
+ pBIOSInfo->TVOutput = TVOUTPUT_SC;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VT162x: S-Video & Composite connected.\n");
+ return TRUE;
+ case 0x07: /* DAC A */
+ pBIOSInfo->TVOutput = TVOUTPUT_COMPOSITE;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VT162x: Composite connected.\n");
+ return TRUE;
+ case 0x08: /* DAC B,C,D */
+ pBIOSInfo->TVOutput = TVOUTPUT_YCBCR;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VT162x: YcBcR connected.\n");
+ return TRUE;
+ case 0x09: /* DAC B,C */
+ pBIOSInfo->TVOutput = TVOUTPUT_SVIDEO;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VT162x: S-Video connected.\n");
+ return TRUE;
+ case 0x0F:
+ pBIOSInfo->TVOutput = TVOUTPUT_NONE;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VT162x: Nothing connected.\n");
+ return FALSE;
+ default:
+ pBIOSInfo->TVOutput = TVOUTPUT_NONE;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VT162x: Unknown cable combination: 0x0%2X.\n",
+ sense);
+ return FALSE;
+ }
+}
+
+/*
+ * VT1625 knows composite, s-video, RGB and YCBCR
+ */
+static Bool
+VT1625DACSense(ScrnInfoPtr pScrn)
+{
+ VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
+ CARD8 sense;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1625DACSense\n"));
+
+ sense = VT1625DACSenseI2C(pBIOSInfo->TVI2CDev);
+ switch (sense) {
+ case 0x00: /* DAC A,B,C,D,E,F */
+ pBIOSInfo->TVOutput = TVOUTPUT_RGB;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VT1625: RGB connected.\n");
+ return TRUE;
+ case 0x07: /* DAC A,B,C */
+ pBIOSInfo->TVOutput = TVOUTPUT_SC;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "VT1625: S-Video & Composite connected.\n");
+ return TRUE;
+ case 0x37: /* DAC C */
+ pBIOSInfo->TVOutput = TVOUTPUT_COMPOSITE;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "VT1625: Composite connected.\n");
+ return TRUE;
+ case 0x38: /* DAC D,E,F */
+ pBIOSInfo->TVOutput = TVOUTPUT_YCBCR;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VT1625: YCbCr connected.\n");
+ return TRUE;
+ case 0x0F: /* DAC A,B */
+ pBIOSInfo->TVOutput = TVOUTPUT_SVIDEO;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VT1625: S-Video connected.\n");
+ return TRUE;
+ case 0x3F:
+ pBIOSInfo->TVOutput = TVOUTPUT_NONE;
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VT1625: Nothing connected.\n");
+ return FALSE;
+ default:
+ pBIOSInfo->TVOutput = TVOUTPUT_NONE;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "VT1625: Unknown cable combination: 0x0%2X.\n",
+ sense);
+ return FALSE;
+ }
+}
+
+/*
+ *
+ */
+static CARD8
+VT1621ModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
+ int i;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621ModeIndex\n"));
+
+ for (i = 0; VT1621Table[i].Width; i++) {
+ if ((VT1621Table[i].Width == mode->CrtcHDisplay) &&
+ (VT1621Table[i].Height == mode->CrtcVDisplay) &&
+ (VT1621Table[i].Standard == pBIOSInfo->TVType) &&
+ !(strcmp(VT1621Table[i].name, mode->name)))
+ return i;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VT1621ModeIndex:"
+ " Mode \"%s\" not found in Table\n", mode->name);
+ return 0xFF;
+}
+
+/*
+ *
+ */
+static ModeStatus
+VT1621ModeValid(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621ModeValid\n"));
+
+ if ((mode->PrivSize != sizeof(struct VT162xModePrivate)) ||
+ ((mode->Private != (void *) &VT162xModePrivateNTSC) &&
+ (mode->Private != (void *) &VT162xModePrivatePAL))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Not a mode defined by the TV Encoder.\n");
+ return MODE_BAD;
+ }
+
+ if ((pBIOSInfo->TVType == TVTYPE_NTSC) &&
+ (mode->Private != (void *) &VT162xModePrivateNTSC)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standard is NTSC. This is a PAL mode.\n");
+ return MODE_BAD;
+ } else if ((pBIOSInfo->TVType == TVTYPE_PAL) &&
+ (mode->Private != (void *) &VT162xModePrivatePAL)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standard is PAL. This is a NTSC mode.\n");
+ return MODE_BAD;
+ }
+
+ if (VT1621ModeIndex(pScrn, mode) != 0xFF)
+ return MODE_OK;
+ return MODE_BAD;
+}
+
+/*
+ *
+ */
+static CARD8
+VT1622ModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
+ struct VT162XTableRec *Table;
+ int i;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622ModeIndex\n"));
+
+ if (pBIOSInfo->TVEncoder == VIA_VT1622)
+ Table = VT1622Table;
+ else if (pBIOSInfo->TVEncoder == VIA_VT1625)
+ Table = VT1625Table;
+ else
+ Table = VT1623Table;
+
+ for (i = 0; Table[i].Width; i++) {
+
+xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "width=%d:%d, height=%d:%d, std=%d:%d, name=%s:%s.\n",
+Table[i].Width, mode->CrtcHDisplay,
+Table[i].Height, mode->CrtcVDisplay,
+Table[i].Standard, pBIOSInfo->TVType,
+Table[i].name, mode->name);
+
+ if ((Table[i].Width == mode->CrtcHDisplay) &&
+ (Table[i].Height == mode->CrtcVDisplay) &&
+ (Table[i].Standard == pBIOSInfo->TVType) &&
+ !strcmp(Table[i].name, mode->name))
+ return i;
+ }
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VT1622ModeIndex:"
+ " Mode \"%s\" not found in Table\n", mode->name);
+ return 0xFF;
+}
+
+/*
+ *
+ */
+static ModeStatus
+VT1622ModeValid(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622ModeValid\n"));
+
+ if ((mode->PrivSize != sizeof(struct VT162xModePrivate)) ||
+ ((mode->Private != (void *) &VT162xModePrivateNTSC) &&
+ (mode->Private != (void *) &VT162xModePrivatePAL))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Not a mode defined by the TV Encoder.\n");
+ return MODE_BAD;
+ }
+
+ if ((pBIOSInfo->TVType == TVTYPE_NTSC) &&
+ (mode->Private != (void *) &VT162xModePrivateNTSC)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standard is NTSC. This is a PAL mode.\n");
+ return MODE_BAD;
+ } else if ((pBIOSInfo->TVType == TVTYPE_PAL) &&
+ (mode->Private != (void *) &VT162xModePrivatePAL)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standard is PAL. This is a NTSC mode.\n");
+ return MODE_BAD;
+ }
+
+ if (VT1622ModeIndex(pScrn, mode) != 0xFF)
+ return MODE_OK;
+ return MODE_BAD;
+}
+
+static ModeStatus
+VT1625ModeValid(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1625ModeValid\n"));
+
+ if ((mode->PrivSize != sizeof(struct VT162xModePrivate)) ||
+ ((mode->Private != (void *) &VT162xModePrivateNTSC) &&
+ (mode->Private != (void *) &VT162xModePrivatePAL) &&
+ (mode->Private != (void *) &VT162xModePrivate480P) &&
+ (mode->Private != (void *) &VT162xModePrivate576P) &&
+ (mode->Private != (void *) &VT162xModePrivate720P) &&
+ (mode->Private != (void *) &VT162xModePrivate1080I))) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Not a mode defined by the TV Encoder.\n");
+ return MODE_BAD;
+ }
+
+ if ((pBIOSInfo->TVType == TVTYPE_NTSC) &&
+ (mode->Private != (void *) &VT162xModePrivateNTSC)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standard is NTSC. This is an incompatible mode.\n");
+ return MODE_BAD;
+ } else if ((pBIOSInfo->TVType == TVTYPE_PAL) &&
+ (mode->Private != (void *) &VT162xModePrivatePAL)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standard is PAL. This is an incompatible mode.\n");
+ return MODE_BAD;
+ } else if ((pBIOSInfo->TVType == TVTYPE_480P) &&
+ (mode->Private != (void *) &VT162xModePrivate480P)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standard is 480P. This is an incompatible mode.\n");
+ return MODE_BAD;
+ } else if ((pBIOSInfo->TVType == TVTYPE_576P) &&
+ (mode->Private != (void *) &VT162xModePrivate576P)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standard is 576P. This is an incompatible mode.\n");
+ return MODE_BAD;
+ } else if ((pBIOSInfo->TVType == TVTYPE_720P) &&
+ (mode->Private != (void *) &VT162xModePrivate720P)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standard is 720P. This is an incompatible mode.\n");
+ return MODE_BAD;
+ } else if ((pBIOSInfo->TVType == TVTYPE_1080I) &&
+ (mode->Private != (void *) &VT162xModePrivate1080I)) {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standard is 1080I. This is an incompatible mode.\n");
+ return MODE_BAD;
+ }
+
+
+
+ if (VT1622ModeIndex(pScrn, mode) != 0xFF)
+ return MODE_OK;
+ return MODE_BAD;
+}
+
+
+/*
+ *
+ */
+static void
+VT162xSetSubCarrier(I2CDevPtr pDev, CARD32 SubCarrier)
+{
+ xf86I2CWriteByte(pDev, 0x16, SubCarrier & 0xFF);
+ xf86I2CWriteByte(pDev, 0x17, (SubCarrier >> 8) & 0xFF);
+ xf86I2CWriteByte(pDev, 0x18, (SubCarrier >> 16) & 0xFF);
+ xf86I2CWriteByte(pDev, 0x19, (SubCarrier >> 24) & 0xFF);
+}
+
+/*
+ *
+ */
+static void
+VT1621ModeI2C(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
+ struct VT1621TableRec Table = VT1621Table[VT1621ModeIndex(pScrn, mode)];
+ CARD8 i;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621ModeI2C\n"));
+
+ for (i = 0; i < 0x16; i++)
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV[i]);
+
+ VT162xSetSubCarrier(pBIOSInfo->TVI2CDev, Table.SubCarrier);
+
+ /* skip reserved (1A) and version id (1B). */
+
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1C, Table.TV[0x1C]);
+
+ /* skip software reset (1D) */
+
+ for (i = 0x1E; i < 0x24; i++)
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV[i]);
+
+ /* write some zeroes? */
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x24, 0x00);
+ for (i = 0; i < 0x08; i++)
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4A + i, 0x00);
+
+ if (pBIOSInfo->TVOutput == TVOUTPUT_COMPOSITE)
+ for (i = 0; i < 0x10; i++)
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x52 + i, Table.TVC[i]);
+ else
+ for (i = 0; i < 0x10; i++)
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x52 + i, Table.TVS[i]);
+
+ /* Turn on all Composite and S-Video output */
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00);
+
+ if (pBIOSInfo->TVDotCrawl) {
+ if (Table.DotCrawlSubCarrier) {
+ xf86I2CReadByte(pBIOSInfo->TVI2CDev, 0x11, &i);
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x11, i | 0x08);
+
+ VT162xSetSubCarrier(pBIOSInfo->TVI2CDev, Table.DotCrawlSubCarrier);
+ } else
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "This mode does not currently "
+ "support DotCrawl suppression.\n");
+ }
+}
+
+/*
+ *
+ */
+static void
+VT1621ModeCrtc(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ VIAPtr pVia = VIAPTR(pScrn);
+ VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+ struct VT1621TableRec Table = VT1621Table[VT1621ModeIndex(pScrn, mode)];
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621ModeCrtc\n"));
+
+ if (pVia->IsSecondary) {
+ hwp->writeCrtc(hwp, 0x6A, 0x80);
+ hwp->writeCrtc(hwp, 0x6B, 0x20);
+ hwp->writeCrtc(hwp, 0x6C, 0x80);
+
+ /* Disable LCD Scaling */
+ if (!pVia->SAMM || pVia->FirstInit)
+ hwp->writeCrtc(hwp, 0x79, 0x00);
+
+ } else {
+ hwp->writeCrtc(hwp, 0x6A, 0x00);
+ hwp->writeCrtc(hwp, 0x6B, 0x80);
+ hwp->writeCrtc(hwp, 0x6C, Table.PrimaryCR6C);
+ }
+ pBIOSInfo->ClockExternal = TRUE;
+ ViaCrtcMask(hwp, 0x6A, 0x40, 0x40);
+ ViaCrtcMask(hwp, 0x6C, 0x01, 0x01);
+}
+
+/*
+ * also suited for VT1622A, VT1623, VT1625
+ */
+static void
+VT1622ModeI2C(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
+ struct VT162XTableRec Table;
+ CARD8 save, i;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622ModeI2C\n"));
+
+ if (pBIOSInfo->TVEncoder == VIA_VT1622)
+ Table = VT1622Table[VT1622ModeIndex(pScrn, mode)];
+ else if (pBIOSInfo->TVEncoder == VIA_VT1625)
+ Table = VT1625Table[VT1622ModeIndex(pScrn, mode)];
+ else /* VT1622A/VT1623 */
+ Table = VT1623Table[VT1622ModeIndex(pScrn, mode)];
+
+ /* TV Reset */
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1D, 0x00);
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1D, 0x80);
+
+ for (i = 0; i < 0x16; i++)
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV1[i]);
+
+ VT162xSetSubCarrier(pBIOSInfo->TVI2CDev, Table.SubCarrier);
+
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1A, Table.TV1[0x1A]);
+
+ /* skip version id */
+
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1C, Table.TV1[0x1C]);
+
+ /* skip software reset */
+
+ for (i = 0x1E; i < 0x30; i++)
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV1[i]);
+
+ for (i = 0; i < 0x1B; i++)
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4A + i, Table.TV2[i]);
+
+ /* Turn on all Composite and S-Video output */
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00);
+
+ if (pBIOSInfo->TVDotCrawl) {
+ if (Table.DotCrawlSubCarrier) {
+ xf86I2CReadByte(pBIOSInfo->TVI2CDev, 0x11, &save);
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x11, save | 0x08);
+
+ VT162xSetSubCarrier(pBIOSInfo->TVI2CDev, Table.DotCrawlSubCarrier);
+ } else
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "This mode does not currently "
+ "support DotCrawl suppression.\n");
+ }
+
+ if (pBIOSInfo->TVOutput == TVOUTPUT_RGB) {
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x2A);
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x65, Table.RGB[0]);
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x66, Table.RGB[1]);
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x67, Table.RGB[2]);
+ if (Table.RGB[3])
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x27, Table.RGB[3]);
+ if (Table.RGB[4])
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x2B, Table.RGB[4]);
+ if (Table.RGB[5])
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x2C, Table.RGB[5]);
+ } else if (pBIOSInfo->TVOutput == TVOUTPUT_YCBCR) {
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x03);
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x65, Table.YCbCr[0]);
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x66, Table.YCbCr[1]);
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x67, Table.YCbCr[2]);
+ }
+
+ /* Configure flicker filter */
+ xf86I2CReadByte(pBIOSInfo->TVI2CDev, 0x03, &save);
+ save &= 0xFC;
+ if (pBIOSInfo->TVDeflicker == 1)
+ save |= 0x01;
+ else if (pBIOSInfo->TVDeflicker == 2)
+ save |= 0x02;
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x03, save);
+}
+
+/*
+ * Also suited for VT1622A, VT1623, VT1625
+ */
+static void
+VT1622ModeCrtc(ScrnInfoPtr pScrn, DisplayModePtr mode)
+{
+ vgaHWPtr hwp = VGAHWPTR(pScrn);
+ VIAPtr pVia = VIAPTR(pScrn);
+ VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
+ struct VT162XTableRec Table;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622ModeCrtc\n"));
+
+ if (pBIOSInfo->TVEncoder == VIA_VT1622)
+ Table = VT1622Table[VT1622ModeIndex(pScrn, mode)];
+ else if (pBIOSInfo->TVEncoder == VIA_VT1625)
+ Table = VT1625Table[VT1622ModeIndex(pScrn, mode)];
+ else /* VT1622A/VT1623 */
+ Table = VT1623Table[VT1622ModeIndex(pScrn, mode)];
+
+ hwp->writeCrtc(hwp, 0x6A, 0x00);
+ hwp->writeCrtc(hwp, 0x6B, 0x00);
+ hwp->writeCrtc(hwp, 0x6C, 0x00);
+
+ if (pVia->IsSecondary) {
+ hwp->writeCrtc(hwp, 0x6C, Table.SecondaryCR6C);
+
+ ViaCrtcMask(hwp, 0x6A, 0x80, 0x80);
+ ViaCrtcMask(hwp, 0x6C, 0x80, 0x80);
+
+ /* CLE266Ax use 2x XCLK */
+ if ((pVia->Chipset == VIA_CLE266) && CLE266_REV_IS_AX(pVia->ChipRev)) {
+ ViaCrtcMask(hwp, 0x6B, 0x20, 0x20);
+
+ /* Fix TV clock Polarity for CLE266A2 */
+ if (pVia->ChipRev == 0x02)
+ ViaCrtcMask(hwp, 0x6C, 0x1C, 0x1C);
+ }
+
+ /* Disable LCD Scaling */
+ if (!pVia->SAMM || pVia->FirstInit)
+ hwp->writeCrtc(hwp, 0x79, 0x00);
+
+ } else {
+ if ((pVia->Chipset == VIA_CLE266) && CLE266_REV_IS_AX(pVia->ChipRev)) {
+ ViaCrtcMask(hwp, 0x6B, 0x80, 0x80);
+
+ /* Fix TV clock Polarity for CLE266A2 */
+ if (pVia->ChipRev == 0x02)
+ hwp->writeCrtc(hwp, 0x6C, Table.PrimaryCR6C);
+ }
+ }
+ pBIOSInfo->ClockExternal = TRUE;
+ ViaCrtcMask(hwp, 0x6A, 0x40, 0x40);
+ ViaCrtcMask(hwp, 0x6C, 0x01, 0x01);
+ ViaSeqMask(hwp, 0x1E, 0xF0, 0xF0); /* Enable DI0/DVP0 */
+}
+
+/*
+ *
+ */
+static void
+VT1621Power(ScrnInfoPtr pScrn, Bool On)
+{
+ VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621Power\n"));
+
+ if (On)
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00);
+ else
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x03);
+}
+
+/*
+ *
+ */
+static void
+VT1622Power(ScrnInfoPtr pScrn, Bool On)
+{
+ VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622Power\n"));
+
+ if (On)
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00);
+ else
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x0F);
+}
+
+/*
+ *
+ */
+static void
+VT1625Power(ScrnInfoPtr pScrn, Bool On)
+{
+ VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1625Power\n"));
+
+ if (On)
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00);
+ else
+ xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x3F);
+}
+
+/*
+ *
+ */
+void
+ViaVT162xInit(ScrnInfoPtr pScrn)
+{
+ VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
+
+ DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaVT162xInit\n"));
+
+ switch (pBIOSInfo->TVEncoder) {
+ case VIA_VT1621:
+ pBIOSInfo->TVSave = VT162xSave;
+ pBIOSInfo->TVRestore = VT162xRestore;
+ pBIOSInfo->TVDACSense = VT1621DACSense;
+ pBIOSInfo->TVModeValid = VT1621ModeValid;
+ pBIOSInfo->TVModeI2C = VT1621ModeI2C;
+ pBIOSInfo->TVModeCrtc = VT1621ModeCrtc;
+ pBIOSInfo->TVPower = VT1621Power;
+ pBIOSInfo->TVModes = VT1621Modes;
+ pBIOSInfo->TVPrintRegs = VT162xPrintRegs;
+ pBIOSInfo->TVNumRegs = 0x68;
+ break;
+ case VIA_VT1622:
+ pBIOSInfo->TVSave = VT162xSave;
+ pBIOSInfo->TVRestore = VT162xRestore;
+ pBIOSInfo->TVDACSense = VT1622DACSense;
+ pBIOSInfo->TVModeValid = VT1622ModeValid;
+ pBIOSInfo->TVModeI2C = VT1622ModeI2C;
+ pBIOSInfo->TVModeCrtc = VT1622ModeCrtc;
+ pBIOSInfo->TVPower = VT1622Power;
+ pBIOSInfo->TVModes = VT1622Modes;
+ pBIOSInfo->TVPrintRegs = VT162xPrintRegs;
+ pBIOSInfo->TVNumRegs = 0x68;
+ break;
+ case VIA_VT1623:
+ pBIOSInfo->TVSave = VT162xSave;
+ pBIOSInfo->TVRestore = VT162xRestore;
+ pBIOSInfo->TVDACSense = VT1622DACSense;
+ pBIOSInfo->TVModeValid = VT1622ModeValid;
+ pBIOSInfo->TVModeI2C = VT1622ModeI2C;
+ pBIOSInfo->TVModeCrtc = VT1622ModeCrtc;
+ pBIOSInfo->TVPower = VT1622Power;
+ pBIOSInfo->TVModes = VT1623Modes;
+ pBIOSInfo->TVPrintRegs = VT162xPrintRegs;
+ pBIOSInfo->TVNumRegs = 0x6C;
+ break;
+ case VIA_VT1625:
+ pBIOSInfo->TVSave = VT162xSave;
+ pBIOSInfo->TVRestore = VT162xRestore;
+ pBIOSInfo->TVDACSense = VT1625DACSense;
+ pBIOSInfo->TVModeValid = VT1625ModeValid;
+ pBIOSInfo->TVModeI2C = VT1622ModeI2C;
+ pBIOSInfo->TVModeCrtc = VT1622ModeCrtc;
+ pBIOSInfo->TVPower = VT1625Power;
+ pBIOSInfo->TVModes = VT1625Modes;
+ pBIOSInfo->TVPrintRegs = VT162xPrintRegs;
+ pBIOSInfo->TVNumRegs = 0x6C;
+ break;
+ default:
+ break;
+ }
+}