via_vt162x.c revision 7e6fb56f
17e6fb56fSmrg/*
27e6fb56fSmrg * Copyright 2004-2005 The Unichrome Project  [unichrome.sf.net]
37e6fb56fSmrg * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
47e6fb56fSmrg * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
57e6fb56fSmrg *
67e6fb56fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
77e6fb56fSmrg * copy of this software and associated documentation files (the "Software"),
87e6fb56fSmrg * to deal in the Software without restriction, including without limitation
97e6fb56fSmrg * the rights to use, copy, modify, merge, publish, distribute, sub license,
107e6fb56fSmrg * and/or sell copies of the Software, and to permit persons to whom the
117e6fb56fSmrg * Software is furnished to do so, subject to the following conditions:
127e6fb56fSmrg *
137e6fb56fSmrg * The above copyright notice and this permission notice (including the
147e6fb56fSmrg * next paragraph) shall be included in all copies or substantial portions
157e6fb56fSmrg * of the Software.
167e6fb56fSmrg *
177e6fb56fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
187e6fb56fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
197e6fb56fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
207e6fb56fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
217e6fb56fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
227e6fb56fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
237e6fb56fSmrg * DEALINGS IN THE SOFTWARE.
247e6fb56fSmrg */
257e6fb56fSmrg
267e6fb56fSmrg#ifdef HAVE_CONFIG_H
277e6fb56fSmrg#include "config.h"
287e6fb56fSmrg#endif
297e6fb56fSmrg
307e6fb56fSmrg#include "via_driver.h"
317e6fb56fSmrg#include "via_vgahw.h"
327e6fb56fSmrg#include "via_vt162x.h"
337e6fb56fSmrg#include "via_id.h"
347e6fb56fSmrg
357e6fb56fSmrgstatic void
367e6fb56fSmrgViaSetTVClockSource(ScrnInfoPtr pScrn)
377e6fb56fSmrg{
387e6fb56fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaSetTVClockSource\n"));
397e6fb56fSmrg
407e6fb56fSmrg    VIAPtr pVia = VIAPTR(pScrn);
417e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
427e6fb56fSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
437e6fb56fSmrg
447e6fb56fSmrg    /* External TV: */
457e6fb56fSmrg    switch(pVia->Chipset) {
467e6fb56fSmrg        case VIA_CX700:
477e6fb56fSmrg        case VIA_VX800:
487e6fb56fSmrg            if (pBIOSInfo->FirstCRTC->IsActive) {
497e6fb56fSmrg                if(pBIOSInfo->TVDIPort == VIA_DI_PORT_DVP1)
507e6fb56fSmrg                    ViaCrtcMask(hwp, 0x6C, 0xB0, 0xF0);
517e6fb56fSmrg                else if(pBIOSInfo->TVDIPort == VIA_DI_PORT_DVP0)
527e6fb56fSmrg                    ViaCrtcMask(hwp, 0x6C, 0x90, 0xF0);
537e6fb56fSmrg            } else {
547e6fb56fSmrg                /* IGA2 */
557e6fb56fSmrg                if(pBIOSInfo->TVDIPort == VIA_DI_PORT_DVP1)
567e6fb56fSmrg                    ViaCrtcMask(hwp, 0x6C, 0x0B, 0x0F);
577e6fb56fSmrg                else if(pBIOSInfo->TVDIPort == VIA_DI_PORT_DVP0)
587e6fb56fSmrg                    ViaCrtcMask(hwp, 0x6C, 0x09, 0x0F);
597e6fb56fSmrg            }
607e6fb56fSmrg            break;
617e6fb56fSmrg        default:
627e6fb56fSmrg            if (pBIOSInfo->FirstCRTC->IsActive)
637e6fb56fSmrg                ViaCrtcMask(hwp, 0x6C, 0x21, 0x21);
647e6fb56fSmrg            else
657e6fb56fSmrg                ViaCrtcMask(hwp, 0x6C, 0xA1, 0xA1);
667e6fb56fSmrg            break;
677e6fb56fSmrg    }
687e6fb56fSmrg}
697e6fb56fSmrg
707e6fb56fSmrgstatic void
717e6fb56fSmrgVT162xPrintRegs(ScrnInfoPtr pScrn)
727e6fb56fSmrg{
737e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
747e6fb56fSmrg    CARD8 i, buf;
757e6fb56fSmrg
767e6fb56fSmrg
777e6fb56fSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Printing registers for %s\n",
787e6fb56fSmrg               pBIOSInfo->TVI2CDev->DevName);
797e6fb56fSmrg
807e6fb56fSmrg    for (i = 0; i < pBIOSInfo->TVNumRegs; i++) {
817e6fb56fSmrg        xf86I2CReadByte(pBIOSInfo->TVI2CDev, i, &buf);
827e6fb56fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV%02X: 0x%02X\n", i, buf);
837e6fb56fSmrg    }
847e6fb56fSmrg
857e6fb56fSmrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of TV registers.\n");
867e6fb56fSmrg}
877e6fb56fSmrg
887e6fb56fSmrg
897e6fb56fSmrgI2CDevPtr
907e6fb56fSmrgViaVT162xDetect(ScrnInfoPtr pScrn, I2CBusPtr pBus, CARD8 Address)
917e6fb56fSmrg{
927e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
937e6fb56fSmrg    I2CDevPtr pDev = xf86CreateI2CDevRec();
947e6fb56fSmrg    CARD8 buf;
957e6fb56fSmrg
967e6fb56fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaVT162xDetect\n"));
977e6fb56fSmrg
987e6fb56fSmrg    pDev->DevName = "VT162x";
997e6fb56fSmrg    pDev->SlaveAddr = Address;
1007e6fb56fSmrg    pDev->pI2CBus = pBus;
1017e6fb56fSmrg
1027e6fb56fSmrg    if (!xf86I2CDevInit(pDev)) {
1037e6fb56fSmrg        xf86DestroyI2CDevRec(pDev, TRUE);
1047e6fb56fSmrg        return NULL;
1057e6fb56fSmrg    }
1067e6fb56fSmrg
1077e6fb56fSmrg    if (!xf86I2CReadByte(pDev, 0x1B, &buf)) {
1087e6fb56fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1097e6fb56fSmrg                   "Unable to read from %s Slave %d.\n",
1107e6fb56fSmrg                   pBus->BusName, Address);
1117e6fb56fSmrg        xf86DestroyI2CDevRec(pDev, TRUE);
1127e6fb56fSmrg        return NULL;
1137e6fb56fSmrg    }
1147e6fb56fSmrg
1157e6fb56fSmrg    switch (buf) {
1167e6fb56fSmrg        case 0x02:
1177e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1187e6fb56fSmrg                       "Detected VIA Technologies VT1621 TV Encoder\n");
1197e6fb56fSmrg            pBIOSInfo->TVEncoder = VIA_VT1621;
1207e6fb56fSmrg            pDev->DevName = "VT1621";
1217e6fb56fSmrg            break;
1227e6fb56fSmrg        case 0x03:
1237e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1247e6fb56fSmrg                       "Detected VIA Technologies VT1622 TV Encoder\n");
1257e6fb56fSmrg            pBIOSInfo->TVEncoder = VIA_VT1622;
1267e6fb56fSmrg            pDev->DevName = "VT1622";
1277e6fb56fSmrg            break;
1287e6fb56fSmrg        case 0x10:
1297e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1307e6fb56fSmrg                       "Detected VIA Technologies VT1622A/VT1623 TV Encoder\n");
1317e6fb56fSmrg            pBIOSInfo->TVEncoder = VIA_VT1623;
1327e6fb56fSmrg            pDev->DevName = "VT1623";
1337e6fb56fSmrg            break;
1347e6fb56fSmrg        case 0x50:
1357e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1367e6fb56fSmrg                       "Detected VIA Technologies VT1625 TV Encoder\n");
1377e6fb56fSmrg            pBIOSInfo->TVEncoder = VIA_VT1625;
1387e6fb56fSmrg            pDev->DevName = "VT1625";
1397e6fb56fSmrg            break;
1407e6fb56fSmrg        default:
1417e6fb56fSmrg            pBIOSInfo->TVEncoder = VIA_NONETV;
1427e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1437e6fb56fSmrg                       "Unknown TV Encoder found at %s %X.\n",
1447e6fb56fSmrg                       pBus->BusName, Address);
1457e6fb56fSmrg            xf86DestroyI2CDevRec(pDev, TRUE);
1467e6fb56fSmrg            pDev = NULL;
1477e6fb56fSmrg            break;
1487e6fb56fSmrg    }
1497e6fb56fSmrg
1507e6fb56fSmrg    return pDev;
1517e6fb56fSmrg}
1527e6fb56fSmrg
1537e6fb56fSmrg
1547e6fb56fSmrgstatic void
1557e6fb56fSmrgVT162xSave(ScrnInfoPtr pScrn)
1567e6fb56fSmrg{
1577e6fb56fSmrg    int i;
1587e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
1597e6fb56fSmrg
1607e6fb56fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT162xSave\n"));
1617e6fb56fSmrg
1627e6fb56fSmrg    for (i = 0; i < pBIOSInfo->TVNumRegs; i++)
1637e6fb56fSmrg        xf86I2CReadByte(pBIOSInfo->TVI2CDev, i, &(pBIOSInfo->TVRegs[i]));
1647e6fb56fSmrg
1657e6fb56fSmrg}
1667e6fb56fSmrg
1677e6fb56fSmrgstatic void
1687e6fb56fSmrgVT162xRestore(ScrnInfoPtr pScrn)
1697e6fb56fSmrg{
1707e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
1717e6fb56fSmrg    int i;
1727e6fb56fSmrg
1737e6fb56fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT162xRestore\n"));
1747e6fb56fSmrg
1757e6fb56fSmrg    for (i = 0; i < pBIOSInfo->TVNumRegs; i++)
1767e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, pBIOSInfo->TVRegs[i]);
1777e6fb56fSmrg}
1787e6fb56fSmrg
1797e6fb56fSmrg
1807e6fb56fSmrg/*
1817e6fb56fSmrg * For VT1621 the same as for VT1622/VT1622A/VT1623, but result is different.
1827e6fb56fSmrg * Still needs testing on VT1621, of course.
1837e6fb56fSmrg */
1847e6fb56fSmrgstatic CARD8
1857e6fb56fSmrgVT162xDACSenseI2C(I2CDevPtr pDev)
1867e6fb56fSmrg{
1877e6fb56fSmrg    CARD8 save, sense;
1887e6fb56fSmrg
1897e6fb56fSmrg    xf86I2CReadByte(pDev, 0x0E, &save);
1907e6fb56fSmrg    xf86I2CWriteByte(pDev, 0x0E, 0x00);
1917e6fb56fSmrg    xf86I2CWriteByte(pDev, 0x0E, 0x80);
1927e6fb56fSmrg    xf86I2CWriteByte(pDev, 0x0E, 0x00);
1937e6fb56fSmrg    xf86I2CReadByte(pDev, 0x0F, &sense);
1947e6fb56fSmrg    xf86I2CWriteByte(pDev, 0x0E, save);
1957e6fb56fSmrg
1967e6fb56fSmrg    return (sense & 0x0F);
1977e6fb56fSmrg}
1987e6fb56fSmrg
1997e6fb56fSmrg/*
2007e6fb56fSmrg * VT1625 moves DACa through DACd from bits 0-3 to 2-5.
2017e6fb56fSmrg */
2027e6fb56fSmrgstatic CARD8
2037e6fb56fSmrgVT1625DACSenseI2C(I2CDevPtr pDev)
2047e6fb56fSmrg{
2057e6fb56fSmrg    CARD8 save, sense;
2067e6fb56fSmrg
2077e6fb56fSmrg    xf86I2CReadByte(pDev, 0x0E, &save);
2087e6fb56fSmrg    xf86I2CWriteByte(pDev, 0x0E, 0x00);
2097e6fb56fSmrg    xf86I2CWriteByte(pDev, 0x0E, 0x80);
2107e6fb56fSmrg    xf86I2CWriteByte(pDev, 0x0E, 0x00);
2117e6fb56fSmrg    xf86I2CReadByte(pDev, 0x0F, &sense);
2127e6fb56fSmrg    xf86I2CWriteByte(pDev, 0x0E, save);
2137e6fb56fSmrg
2147e6fb56fSmrg    return (sense & 0x3F);
2157e6fb56fSmrg}
2167e6fb56fSmrg
2177e6fb56fSmrg/*
2187e6fb56fSmrg * VT1621 only knows composite and s-video.
2197e6fb56fSmrg */
2207e6fb56fSmrgstatic Bool
2217e6fb56fSmrgVT1621DACSense(ScrnInfoPtr pScrn)
2227e6fb56fSmrg{
2237e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
2247e6fb56fSmrg    CARD8 sense;
2257e6fb56fSmrg
2267e6fb56fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621DACSense\n"));
2277e6fb56fSmrg
2287e6fb56fSmrg    sense = VT162xDACSenseI2C(pBIOSInfo->TVI2CDev);
2297e6fb56fSmrg    switch (sense) {
2307e6fb56fSmrg        case 0x00:
2317e6fb56fSmrg            pBIOSInfo->TVOutput = TVOUTPUT_SC;
2327e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2337e6fb56fSmrg                       "VT1621: S-Video & Composite connected.\n");
2347e6fb56fSmrg            return TRUE;
2357e6fb56fSmrg        case 0x01:
2367e6fb56fSmrg            pBIOSInfo->TVOutput = TVOUTPUT_COMPOSITE;
2377e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2387e6fb56fSmrg                       "VT1621: Composite connected.\n");
2397e6fb56fSmrg            return TRUE;
2407e6fb56fSmrg        case 0x02:
2417e6fb56fSmrg            pBIOSInfo->TVOutput = TVOUTPUT_SVIDEO;
2427e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2437e6fb56fSmrg                       "VT1621: S-Video connected.\n");
2447e6fb56fSmrg            return TRUE;
2457e6fb56fSmrg        case 0x03:
2467e6fb56fSmrg            pBIOSInfo->TVOutput = TVOUTPUT_NONE;
2477e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2487e6fb56fSmrg                       "VT1621: Nothing connected.\n");
2497e6fb56fSmrg            return FALSE;
2507e6fb56fSmrg        default:
2517e6fb56fSmrg            pBIOSInfo->TVOutput = TVOUTPUT_NONE;
2527e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
2537e6fb56fSmrg                       "VT1621: Unknown cable combination: 0x0%2X.\n", sense);
2547e6fb56fSmrg            return FALSE;
2557e6fb56fSmrg    }
2567e6fb56fSmrg}
2577e6fb56fSmrg
2587e6fb56fSmrg/*
2597e6fb56fSmrg * VT1622, VT1622A and VT1623 know composite, s-video, RGB and YCBCR.
2607e6fb56fSmrg */
2617e6fb56fSmrgstatic Bool
2627e6fb56fSmrgVT1622DACSense(ScrnInfoPtr pScrn)
2637e6fb56fSmrg{
2647e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
2657e6fb56fSmrg    CARD8 sense;
2667e6fb56fSmrg
2677e6fb56fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622DACSense\n"));
2687e6fb56fSmrg
2697e6fb56fSmrg    sense = VT162xDACSenseI2C(pBIOSInfo->TVI2CDev);
2707e6fb56fSmrg    switch (sense) {
2717e6fb56fSmrg        case 0x00:  /* DAC A,B,C,D */
2727e6fb56fSmrg            pBIOSInfo->TVOutput = TVOUTPUT_RGB;
2737e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2747e6fb56fSmrg                       "VT162x: RGB connected.\n");
2757e6fb56fSmrg            return TRUE;
2767e6fb56fSmrg        case 0x01:  /* DAC A,B,C */
2777e6fb56fSmrg            pBIOSInfo->TVOutput = TVOUTPUT_SC;
2787e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2797e6fb56fSmrg                       "VT162x: S-Video & Composite connected.\n");
2807e6fb56fSmrg            return TRUE;
2817e6fb56fSmrg        case 0x07:  /* DAC A */
2827e6fb56fSmrg            pBIOSInfo->TVOutput = TVOUTPUT_COMPOSITE;
2837e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2847e6fb56fSmrg                       "VT162x: Composite connected.\n");
2857e6fb56fSmrg            return TRUE;
2867e6fb56fSmrg        case 0x08:  /* DAC B,C,D */
2877e6fb56fSmrg            pBIOSInfo->TVOutput = TVOUTPUT_YCBCR;
2887e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2897e6fb56fSmrg                       "VT162x: YcBcR connected.\n");
2907e6fb56fSmrg            return TRUE;
2917e6fb56fSmrg        case 0x09:  /* DAC B,C */
2927e6fb56fSmrg            pBIOSInfo->TVOutput = TVOUTPUT_SVIDEO;
2937e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2947e6fb56fSmrg                       "VT162x: S-Video connected.\n");
2957e6fb56fSmrg            return TRUE;
2967e6fb56fSmrg        case 0x0F:
2977e6fb56fSmrg            pBIOSInfo->TVOutput = TVOUTPUT_NONE;
2987e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2997e6fb56fSmrg                       "VT162x: Nothing connected.\n");
3007e6fb56fSmrg            return FALSE;
3017e6fb56fSmrg        default:
3027e6fb56fSmrg            pBIOSInfo->TVOutput = TVOUTPUT_NONE;
3037e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
3047e6fb56fSmrg                       "VT162x: Unknown cable combination: 0x0%2X.\n", sense);
3057e6fb56fSmrg            return FALSE;
3067e6fb56fSmrg    }
3077e6fb56fSmrg}
3087e6fb56fSmrg
3097e6fb56fSmrg/*
3107e6fb56fSmrg * VT1625 knows composite, s-video, RGB and YCBCR.
3117e6fb56fSmrg */
3127e6fb56fSmrgstatic Bool
3137e6fb56fSmrgVT1625DACSense(ScrnInfoPtr pScrn)
3147e6fb56fSmrg{
3157e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
3167e6fb56fSmrg    CARD8 sense;
3177e6fb56fSmrg
3187e6fb56fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1625DACSense\n"));
3197e6fb56fSmrg
3207e6fb56fSmrg    sense = VT1625DACSenseI2C(pBIOSInfo->TVI2CDev);
3217e6fb56fSmrg    switch (sense) {
3227e6fb56fSmrg        case 0x00:  /* DAC A,B,C,D,E,F */
3237e6fb56fSmrg            pBIOSInfo->TVOutput = TVOUTPUT_RGB;
3247e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
3257e6fb56fSmrg                       "VT1625: RGB connected.\n");
3267e6fb56fSmrg            return TRUE;
3277e6fb56fSmrg        case 0x07:  /* DAC A,B,C */
3287e6fb56fSmrg            pBIOSInfo->TVOutput = TVOUTPUT_SC;
3297e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
3307e6fb56fSmrg                       "VT1625: S-Video & Composite connected.\n");
3317e6fb56fSmrg            return TRUE;
3327e6fb56fSmrg        case 0x37:  /* DAC C */
3337e6fb56fSmrg            pBIOSInfo->TVOutput = TVOUTPUT_COMPOSITE;
3347e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
3357e6fb56fSmrg                       "VT1625: Composite connected.\n");
3367e6fb56fSmrg            return TRUE;
3377e6fb56fSmrg        case 0x38:  /* DAC D,E,F */
3387e6fb56fSmrg            pBIOSInfo->TVOutput = TVOUTPUT_YCBCR;
3397e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
3407e6fb56fSmrg                       "VT1625: YCbCr connected.\n");
3417e6fb56fSmrg            return TRUE;
3427e6fb56fSmrg        case 0x0F:  /* DAC A,B */
3437e6fb56fSmrg            pBIOSInfo->TVOutput = TVOUTPUT_SVIDEO;
3447e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
3457e6fb56fSmrg                       "VT1625: S-Video connected.\n");
3467e6fb56fSmrg            return TRUE;
3477e6fb56fSmrg        case 0x3F:
3487e6fb56fSmrg            pBIOSInfo->TVOutput = TVOUTPUT_NONE;
3497e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
3507e6fb56fSmrg                       "VT1625: Nothing connected.\n");
3517e6fb56fSmrg            return FALSE;
3527e6fb56fSmrg        default:
3537e6fb56fSmrg            pBIOSInfo->TVOutput = TVOUTPUT_NONE;
3547e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
3557e6fb56fSmrg                       "VT1625: Unknown cable combination: 0x0%2X.\n", sense);
3567e6fb56fSmrg            return FALSE;
3577e6fb56fSmrg    }
3587e6fb56fSmrg}
3597e6fb56fSmrg
3607e6fb56fSmrgstatic CARD8
3617e6fb56fSmrgVT1621ModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode)
3627e6fb56fSmrg{
3637e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
3647e6fb56fSmrg    int i;
3657e6fb56fSmrg
3667e6fb56fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621ModeIndex\n"));
3677e6fb56fSmrg
3687e6fb56fSmrg    for (i = 0; VT1621Table[i].Width; i++) {
3697e6fb56fSmrg        if ((VT1621Table[i].Width == mode->CrtcHDisplay) &&
3707e6fb56fSmrg            (VT1621Table[i].Height == mode->CrtcVDisplay) &&
3717e6fb56fSmrg            (VT1621Table[i].Standard == pBIOSInfo->TVType) &&
3727e6fb56fSmrg            !(strcmp(VT1621Table[i].name, mode->name)))
3737e6fb56fSmrg            return i;
3747e6fb56fSmrg    }
3757e6fb56fSmrg    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VT1621ModeIndex:"
3767e6fb56fSmrg               " Mode \"%s\" not found in Table\n", mode->name);
3777e6fb56fSmrg    return 0xFF;
3787e6fb56fSmrg}
3797e6fb56fSmrg
3807e6fb56fSmrgstatic ModeStatus
3817e6fb56fSmrgVT1621ModeValid(ScrnInfoPtr pScrn, DisplayModePtr mode)
3827e6fb56fSmrg{
3837e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
3847e6fb56fSmrg
3857e6fb56fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621ModeValid\n"));
3867e6fb56fSmrg
3877e6fb56fSmrg    if ((mode->PrivSize != sizeof(struct VT162xModePrivate)) ||
3887e6fb56fSmrg        ((mode->Private != (void *)&VT162xModePrivateNTSC) &&
3897e6fb56fSmrg         (mode->Private != (void *)&VT162xModePrivatePAL))) {
3907e6fb56fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3917e6fb56fSmrg                   "Not a mode defined by the TV Encoder.\n");
3927e6fb56fSmrg        return MODE_BAD;
3937e6fb56fSmrg    }
3947e6fb56fSmrg
3957e6fb56fSmrg    if ((pBIOSInfo->TVType == TVTYPE_NTSC) &&
3967e6fb56fSmrg        (mode->Private != (void *)&VT162xModePrivateNTSC)) {
3977e6fb56fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3987e6fb56fSmrg                   "TV standard is NTSC. This is a PAL mode.\n");
3997e6fb56fSmrg        return MODE_BAD;
4007e6fb56fSmrg    } else if ((pBIOSInfo->TVType == TVTYPE_PAL) &&
4017e6fb56fSmrg               (mode->Private != (void *)&VT162xModePrivatePAL)) {
4027e6fb56fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4037e6fb56fSmrg                   "TV standard is PAL. This is a NTSC mode.\n");
4047e6fb56fSmrg        return MODE_BAD;
4057e6fb56fSmrg    }
4067e6fb56fSmrg
4077e6fb56fSmrg    if (VT1621ModeIndex(pScrn, mode) != 0xFF)
4087e6fb56fSmrg        return MODE_OK;
4097e6fb56fSmrg    return MODE_BAD;
4107e6fb56fSmrg}
4117e6fb56fSmrg
4127e6fb56fSmrgstatic CARD8
4137e6fb56fSmrgVT1622ModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode)
4147e6fb56fSmrg{
4157e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
4167e6fb56fSmrg    struct VT162XTableRec *Table;
4177e6fb56fSmrg    int i;
4187e6fb56fSmrg
4197e6fb56fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622ModeIndex\n"));
4207e6fb56fSmrg
4217e6fb56fSmrg    if (pBIOSInfo->TVEncoder == VIA_VT1622)
4227e6fb56fSmrg        Table = VT1622Table;
4237e6fb56fSmrg    else if (pBIOSInfo->TVEncoder == VIA_VT1625)
4247e6fb56fSmrg        Table = VT1625Table;
4257e6fb56fSmrg    else
4267e6fb56fSmrg        Table = VT1623Table;
4277e6fb56fSmrg
4287e6fb56fSmrg    for (i = 0; Table[i].Width; i++) {
4297e6fb56fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
4307e6fb56fSmrg                   "width=%d:%d, height=%d:%d, std=%d:%d, name=%s:%s.\n",
4317e6fb56fSmrg                   Table[i].Width, mode->CrtcHDisplay,
4327e6fb56fSmrg                   Table[i].Height, mode->CrtcVDisplay,
4337e6fb56fSmrg                   Table[i].Standard, pBIOSInfo->TVType,
4347e6fb56fSmrg                   Table[i].name, mode->name);
4357e6fb56fSmrg
4367e6fb56fSmrg        if ((Table[i].Width == mode->CrtcHDisplay) &&
4377e6fb56fSmrg            (Table[i].Height == mode->CrtcVDisplay) &&
4387e6fb56fSmrg            (Table[i].Standard == pBIOSInfo->TVType) &&
4397e6fb56fSmrg            !strcmp(Table[i].name, mode->name))
4407e6fb56fSmrg            return i;
4417e6fb56fSmrg    }
4427e6fb56fSmrg    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VT1622ModeIndex:"
4437e6fb56fSmrg               " Mode \"%s\" not found in Table\n", mode->name);
4447e6fb56fSmrg    return 0xFF;
4457e6fb56fSmrg}
4467e6fb56fSmrg
4477e6fb56fSmrgstatic ModeStatus
4487e6fb56fSmrgVT1622ModeValid(ScrnInfoPtr pScrn, DisplayModePtr mode)
4497e6fb56fSmrg{
4507e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
4517e6fb56fSmrg
4527e6fb56fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622ModeValid\n"));
4537e6fb56fSmrg
4547e6fb56fSmrg    if ((mode->PrivSize != sizeof(struct VT162xModePrivate)) ||
4557e6fb56fSmrg        ((mode->Private != (void *)&VT162xModePrivateNTSC) &&
4567e6fb56fSmrg         (mode->Private != (void *)&VT162xModePrivatePAL))) {
4577e6fb56fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4587e6fb56fSmrg                   "Not a mode defined by the TV Encoder.\n");
4597e6fb56fSmrg        return MODE_BAD;
4607e6fb56fSmrg    }
4617e6fb56fSmrg
4627e6fb56fSmrg    if ((pBIOSInfo->TVType == TVTYPE_NTSC) &&
4637e6fb56fSmrg        (mode->Private != (void *)&VT162xModePrivateNTSC)) {
4647e6fb56fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4657e6fb56fSmrg                   "TV standard is NTSC. This is a PAL mode.\n");
4667e6fb56fSmrg        return MODE_BAD;
4677e6fb56fSmrg    } else if ((pBIOSInfo->TVType == TVTYPE_PAL) &&
4687e6fb56fSmrg               (mode->Private != (void *)&VT162xModePrivatePAL)) {
4697e6fb56fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4707e6fb56fSmrg                   "TV standard is PAL. This is a NTSC mode.\n");
4717e6fb56fSmrg        return MODE_BAD;
4727e6fb56fSmrg    }
4737e6fb56fSmrg
4747e6fb56fSmrg    if (VT1622ModeIndex(pScrn, mode) != 0xFF)
4757e6fb56fSmrg        return MODE_OK;
4767e6fb56fSmrg    return MODE_BAD;
4777e6fb56fSmrg}
4787e6fb56fSmrg
4797e6fb56fSmrgstatic ModeStatus
4807e6fb56fSmrgVT1625ModeValid(ScrnInfoPtr pScrn, DisplayModePtr mode)
4817e6fb56fSmrg{
4827e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
4837e6fb56fSmrg
4847e6fb56fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1625ModeValid\n"));
4857e6fb56fSmrg
4867e6fb56fSmrg    if ((mode->PrivSize != sizeof(struct VT162xModePrivate)) ||
4877e6fb56fSmrg        ((mode->Private != (void *)&VT162xModePrivateNTSC) &&
4887e6fb56fSmrg         (mode->Private != (void *)&VT162xModePrivatePAL) &&
4897e6fb56fSmrg         (mode->Private != (void *)&VT162xModePrivate480P) &&
4907e6fb56fSmrg         (mode->Private != (void *)&VT162xModePrivate576P) &&
4917e6fb56fSmrg         (mode->Private != (void *)&VT162xModePrivate720P) &&
4927e6fb56fSmrg         (mode->Private != (void *)&VT162xModePrivate1080I))) {
4937e6fb56fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4947e6fb56fSmrg                   "Not a mode defined by the TV Encoder.\n");
4957e6fb56fSmrg        return MODE_BAD;
4967e6fb56fSmrg    }
4977e6fb56fSmrg
4987e6fb56fSmrg    if ((pBIOSInfo->TVType == TVTYPE_NTSC) &&
4997e6fb56fSmrg        (mode->Private != (void *)&VT162xModePrivateNTSC)) {
5007e6fb56fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
5017e6fb56fSmrg                   "TV standard is NTSC. This is an incompatible mode.\n");
5027e6fb56fSmrg        return MODE_BAD;
5037e6fb56fSmrg    } else if ((pBIOSInfo->TVType == TVTYPE_PAL) &&
5047e6fb56fSmrg               (mode->Private != (void *)&VT162xModePrivatePAL)) {
5057e6fb56fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
5067e6fb56fSmrg                   "TV standard is PAL. This is an incompatible mode.\n");
5077e6fb56fSmrg        return MODE_BAD;
5087e6fb56fSmrg    } else if ((pBIOSInfo->TVType == TVTYPE_480P) &&
5097e6fb56fSmrg               (mode->Private != (void *)&VT162xModePrivate480P)) {
5107e6fb56fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
5117e6fb56fSmrg                   "TV standard is 480P. This is an incompatible mode.\n");
5127e6fb56fSmrg        return MODE_BAD;
5137e6fb56fSmrg    } else if ((pBIOSInfo->TVType == TVTYPE_576P) &&
5147e6fb56fSmrg               (mode->Private != (void *)&VT162xModePrivate576P)) {
5157e6fb56fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
5167e6fb56fSmrg                   "TV standard is 576P. This is an incompatible mode.\n");
5177e6fb56fSmrg        return MODE_BAD;
5187e6fb56fSmrg    } else if ((pBIOSInfo->TVType == TVTYPE_720P) &&
5197e6fb56fSmrg               (mode->Private != (void *)&VT162xModePrivate720P)) {
5207e6fb56fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
5217e6fb56fSmrg                   "TV standard is 720P. This is an incompatible mode.\n");
5227e6fb56fSmrg        return MODE_BAD;
5237e6fb56fSmrg    } else if ((pBIOSInfo->TVType == TVTYPE_1080I) &&
5247e6fb56fSmrg               (mode->Private != (void *)&VT162xModePrivate1080I)) {
5257e6fb56fSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
5267e6fb56fSmrg                   "TV standard is 1080I. This is an incompatible mode.\n");
5277e6fb56fSmrg        return MODE_BAD;
5287e6fb56fSmrg    }
5297e6fb56fSmrg
5307e6fb56fSmrg    if (VT1622ModeIndex(pScrn, mode) != 0xFF)
5317e6fb56fSmrg        return MODE_OK;
5327e6fb56fSmrg    return MODE_BAD;
5337e6fb56fSmrg}
5347e6fb56fSmrg
5357e6fb56fSmrg
5367e6fb56fSmrgstatic void
5377e6fb56fSmrgVT162xSetSubCarrier(I2CDevPtr pDev, CARD32 SubCarrier)
5387e6fb56fSmrg{
5397e6fb56fSmrg    xf86I2CWriteByte(pDev, 0x16, SubCarrier & 0xFF);
5407e6fb56fSmrg    xf86I2CWriteByte(pDev, 0x17, (SubCarrier >> 8) & 0xFF);
5417e6fb56fSmrg    xf86I2CWriteByte(pDev, 0x18, (SubCarrier >> 16) & 0xFF);
5427e6fb56fSmrg    xf86I2CWriteByte(pDev, 0x19, (SubCarrier >> 24) & 0xFF);
5437e6fb56fSmrg}
5447e6fb56fSmrg
5457e6fb56fSmrgstatic void
5467e6fb56fSmrgVT1621ModeI2C(ScrnInfoPtr pScrn, DisplayModePtr mode)
5477e6fb56fSmrg{
5487e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
5497e6fb56fSmrg    struct VT1621TableRec Table = VT1621Table[VT1621ModeIndex(pScrn, mode)];
5507e6fb56fSmrg    CARD8 i;
5517e6fb56fSmrg
5527e6fb56fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621ModeI2C\n"));
5537e6fb56fSmrg
5547e6fb56fSmrg    for (i = 0; i < 0x16; i++)
5557e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV[i]);
5567e6fb56fSmrg
5577e6fb56fSmrg    VT162xSetSubCarrier(pBIOSInfo->TVI2CDev, Table.SubCarrier);
5587e6fb56fSmrg
5597e6fb56fSmrg    /* Skip reserved (1A) and version ID (1B). */
5607e6fb56fSmrg    xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1C, Table.TV[0x1C]);
5617e6fb56fSmrg
5627e6fb56fSmrg    /* Skip software reset (1D). */
5637e6fb56fSmrg    for (i = 0x1E; i < 0x24; i++)
5647e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV[i]);
5657e6fb56fSmrg
5667e6fb56fSmrg    /* Write some zeroes? */
5677e6fb56fSmrg    xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x24, 0x00);
5687e6fb56fSmrg    for (i = 0; i < 0x08; i++)
5697e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4A + i, 0x00);
5707e6fb56fSmrg
5717e6fb56fSmrg    if (pBIOSInfo->TVOutput == TVOUTPUT_COMPOSITE)
5727e6fb56fSmrg        for (i = 0; i < 0x10; i++)
5737e6fb56fSmrg            xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x52 + i, Table.TVC[i]);
5747e6fb56fSmrg    else
5757e6fb56fSmrg        for (i = 0; i < 0x10; i++)
5767e6fb56fSmrg            xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x52 + i, Table.TVS[i]);
5777e6fb56fSmrg
5787e6fb56fSmrg    /* Turn on all Composite and S-Video output. */
5797e6fb56fSmrg    xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00);
5807e6fb56fSmrg
5817e6fb56fSmrg    if (pBIOSInfo->TVDotCrawl) {
5827e6fb56fSmrg        if (Table.DotCrawlSubCarrier) {
5837e6fb56fSmrg            xf86I2CReadByte(pBIOSInfo->TVI2CDev, 0x11, &i);
5847e6fb56fSmrg            xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x11, i | 0x08);
5857e6fb56fSmrg
5867e6fb56fSmrg            VT162xSetSubCarrier(pBIOSInfo->TVI2CDev, Table.DotCrawlSubCarrier);
5877e6fb56fSmrg        } else
5887e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "This mode does not currently "
5897e6fb56fSmrg                       "support DotCrawl suppression.\n");
5907e6fb56fSmrg    }
5917e6fb56fSmrg}
5927e6fb56fSmrg
5937e6fb56fSmrgstatic void
5947e6fb56fSmrgVT1621ModeCrtc(ScrnInfoPtr pScrn, DisplayModePtr mode)
5957e6fb56fSmrg{
5967e6fb56fSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
5977e6fb56fSmrg    VIAPtr pVia = VIAPTR(pScrn);
5987e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
5997e6fb56fSmrg    struct VT1621TableRec Table = VT1621Table[VT1621ModeIndex(pScrn, mode)];
6007e6fb56fSmrg
6017e6fb56fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621ModeCrtc\n"));
6027e6fb56fSmrg
6037e6fb56fSmrg    if (pVia->IsSecondary) {
6047e6fb56fSmrg        hwp->writeCrtc(hwp, 0x6A, 0x80);
6057e6fb56fSmrg        hwp->writeCrtc(hwp, 0x6B, 0x20);
6067e6fb56fSmrg        hwp->writeCrtc(hwp, 0x6C, 0x80);
6077e6fb56fSmrg
6087e6fb56fSmrg        /* Disable LCD Scaling */
6097e6fb56fSmrg        if (!pVia->SAMM || pVia->FirstInit)
6107e6fb56fSmrg            hwp->writeCrtc(hwp, 0x79, 0x00);
6117e6fb56fSmrg
6127e6fb56fSmrg    } else {
6137e6fb56fSmrg        hwp->writeCrtc(hwp, 0x6A, 0x00);
6147e6fb56fSmrg        hwp->writeCrtc(hwp, 0x6B, 0x80);
6157e6fb56fSmrg        hwp->writeCrtc(hwp, 0x6C, Table.PrimaryCR6C);
6167e6fb56fSmrg    }
6177e6fb56fSmrg    pBIOSInfo->ClockExternal = TRUE;
6187e6fb56fSmrg    ViaCrtcMask(hwp, 0x6A, 0x40, 0x40);
6197e6fb56fSmrg    ViaCrtcMask(hwp, 0x6C, 0x01, 0x01);
6207e6fb56fSmrg}
6217e6fb56fSmrg
6227e6fb56fSmrg/*
6237e6fb56fSmrg * Also suited for VT1622A, VT1623, VT1625.
6247e6fb56fSmrg */
6257e6fb56fSmrgstatic void
6267e6fb56fSmrgVT1622ModeI2C(ScrnInfoPtr pScrn, DisplayModePtr mode)
6277e6fb56fSmrg{
6287e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
6297e6fb56fSmrg    struct VT162XTableRec Table;
6307e6fb56fSmrg    CARD8 save, i;
6317e6fb56fSmrg
6327e6fb56fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622ModeI2C\n"));
6337e6fb56fSmrg
6347e6fb56fSmrg    if (pBIOSInfo->TVEncoder == VIA_VT1622)
6357e6fb56fSmrg        Table = VT1622Table[VT1622ModeIndex(pScrn, mode)];
6367e6fb56fSmrg    else if (pBIOSInfo->TVEncoder == VIA_VT1625)
6377e6fb56fSmrg        Table = VT1625Table[VT1622ModeIndex(pScrn, mode)];
6387e6fb56fSmrg    else        /* VT1622A/VT1623 */
6397e6fb56fSmrg        Table = VT1623Table[VT1622ModeIndex(pScrn, mode)];
6407e6fb56fSmrg
6417e6fb56fSmrg    /* TV reset. */
6427e6fb56fSmrg    xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1D, 0x00);
6437e6fb56fSmrg    xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1D, 0x80);
6447e6fb56fSmrg
6457e6fb56fSmrg    for (i = 0; i < 0x16; i++)
6467e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV1[i]);
6477e6fb56fSmrg
6487e6fb56fSmrg    VT162xSetSubCarrier(pBIOSInfo->TVI2CDev, Table.SubCarrier);
6497e6fb56fSmrg
6507e6fb56fSmrg    xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1A, Table.TV1[0x1A]);
6517e6fb56fSmrg
6527e6fb56fSmrg    /* Skip version ID. */
6537e6fb56fSmrg    xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1C, Table.TV1[0x1C]);
6547e6fb56fSmrg
6557e6fb56fSmrg    /* Skip software reset. */
6567e6fb56fSmrg    for (i = 0x1E; i < 0x30; i++)
6577e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV1[i]);
6587e6fb56fSmrg
6597e6fb56fSmrg    for (i = 0; i < 0x1B; i++)
6607e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4A + i, Table.TV2[i]);
6617e6fb56fSmrg
6627e6fb56fSmrg    /* Turn on all Composite and S-Video output. */
6637e6fb56fSmrg    xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00);
6647e6fb56fSmrg
6657e6fb56fSmrg    if (pBIOSInfo->TVDotCrawl) {
6667e6fb56fSmrg        if (Table.DotCrawlSubCarrier) {
6677e6fb56fSmrg            xf86I2CReadByte(pBIOSInfo->TVI2CDev, 0x11, &save);
6687e6fb56fSmrg            xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x11, save | 0x08);
6697e6fb56fSmrg
6707e6fb56fSmrg            VT162xSetSubCarrier(pBIOSInfo->TVI2CDev, Table.DotCrawlSubCarrier);
6717e6fb56fSmrg        } else
6727e6fb56fSmrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO, "This mode does not currently "
6737e6fb56fSmrg                       "support DotCrawl suppression.\n");
6747e6fb56fSmrg    }
6757e6fb56fSmrg
6767e6fb56fSmrg    if (pBIOSInfo->TVOutput == TVOUTPUT_RGB) {
6777e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x2A);
6787e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x65, Table.RGB[0]);
6797e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x66, Table.RGB[1]);
6807e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x67, Table.RGB[2]);
6817e6fb56fSmrg        if (Table.RGB[3])
6827e6fb56fSmrg            xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x27, Table.RGB[3]);
6837e6fb56fSmrg        if (Table.RGB[4])
6847e6fb56fSmrg            xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x2B, Table.RGB[4]);
6857e6fb56fSmrg        if (Table.RGB[5])
6867e6fb56fSmrg            xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x2C, Table.RGB[5]);
6877e6fb56fSmrg        if (pBIOSInfo->TVEncoder == VIA_VT1625) {
6887e6fb56fSmrg            if (pBIOSInfo->TVType < TVTYPE_480P) {
6897e6fb56fSmrg                xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x12);
6907e6fb56fSmrg                xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x23, 0x7E);
6917e6fb56fSmrg                xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4A, 0x85);
6927e6fb56fSmrg                xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4B, 0x0A);
6937e6fb56fSmrg                xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4E, 0x00);
6947e6fb56fSmrg            } else {
6957e6fb56fSmrg                xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x12);
6967e6fb56fSmrg                xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4A, 0x85);
6977e6fb56fSmrg                xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4B, 0x0A);
6987e6fb56fSmrg            }
6997e6fb56fSmrg        }
7007e6fb56fSmrg    } else if (pBIOSInfo->TVOutput == TVOUTPUT_YCBCR) {
7017e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x03);
7027e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x65, Table.YCbCr[0]);
7037e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x66, Table.YCbCr[1]);
7047e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x67, Table.YCbCr[2]);
7057e6fb56fSmrg        if (pBIOSInfo->TVEncoder == VIA_VT1625) {
7067e6fb56fSmrg            if (pBIOSInfo->TVType < TVTYPE_480P) {
7077e6fb56fSmrg                xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x23, 0x7E);
7087e6fb56fSmrg                xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4E, 0x00);
7097e6fb56fSmrg            }
7107e6fb56fSmrg        }
7117e6fb56fSmrg    }
7127e6fb56fSmrg
7137e6fb56fSmrg    /* Configure flicker filter. */
7147e6fb56fSmrg    xf86I2CReadByte(pBIOSInfo->TVI2CDev, 0x03, &save);
7157e6fb56fSmrg    save &= 0xFC;
7167e6fb56fSmrg    if (pBIOSInfo->TVDeflicker == 1)
7177e6fb56fSmrg        save |= 0x01;
7187e6fb56fSmrg    else if (pBIOSInfo->TVDeflicker == 2)
7197e6fb56fSmrg        save |= 0x02;
7207e6fb56fSmrg    xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x03, save);
7217e6fb56fSmrg}
7227e6fb56fSmrg
7237e6fb56fSmrg/*
7247e6fb56fSmrg * Also suited for VT1622A, VT1623, VT1625.
7257e6fb56fSmrg */
7267e6fb56fSmrgstatic void
7277e6fb56fSmrgVT1622ModeCrtc(ScrnInfoPtr pScrn, DisplayModePtr mode)
7287e6fb56fSmrg{
7297e6fb56fSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
7307e6fb56fSmrg    VIAPtr pVia = VIAPTR(pScrn);
7317e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
7327e6fb56fSmrg    struct VT162XTableRec Table;
7337e6fb56fSmrg
7347e6fb56fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622ModeCrtc\n"));
7357e6fb56fSmrg
7367e6fb56fSmrg    if (pBIOSInfo->TVEncoder == VIA_VT1622)
7377e6fb56fSmrg        Table = VT1622Table[VT1622ModeIndex(pScrn, mode)];
7387e6fb56fSmrg    else if (pBIOSInfo->TVEncoder == VIA_VT1625)
7397e6fb56fSmrg        Table = VT1625Table[VT1622ModeIndex(pScrn, mode)];
7407e6fb56fSmrg    else        /* VT1622A/VT1623 */
7417e6fb56fSmrg        Table = VT1623Table[VT1622ModeIndex(pScrn, mode)];
7427e6fb56fSmrg
7437e6fb56fSmrg    hwp->writeCrtc(hwp, 0x6A, 0x00);
7447e6fb56fSmrg    hwp->writeCrtc(hwp, 0x6B, 0x00);
7457e6fb56fSmrg    hwp->writeCrtc(hwp, 0x6C, 0x00);
7467e6fb56fSmrg
7477e6fb56fSmrg    if (pVia->IsSecondary) {
7487e6fb56fSmrg        hwp->writeCrtc(hwp, 0x6C, Table.SecondaryCR6C);
7497e6fb56fSmrg
7507e6fb56fSmrg        ViaCrtcMask(hwp, 0x6A, 0x80, 0x80);
7517e6fb56fSmrg        ViaCrtcMask(hwp, 0x6C, 0x80, 0x80);
7527e6fb56fSmrg
7537e6fb56fSmrg        /* CLE266Ax use 2x XCLK. */
7547e6fb56fSmrg        if ((pVia->Chipset == VIA_CLE266) && CLE266_REV_IS_AX(pVia->ChipRev)) {
7557e6fb56fSmrg            ViaCrtcMask(hwp, 0x6B, 0x20, 0x20);
7567e6fb56fSmrg
7577e6fb56fSmrg            /* Fix TV clock polarity for CLE266A2. */
7587e6fb56fSmrg            if (pVia->ChipRev == 0x02)
7597e6fb56fSmrg                ViaCrtcMask(hwp, 0x6C, 0x1C, 0x1C);
7607e6fb56fSmrg        }
7617e6fb56fSmrg
7627e6fb56fSmrg        /* Disable LCD scaling. */
7637e6fb56fSmrg        if (!pVia->SAMM || pVia->FirstInit)
7647e6fb56fSmrg            hwp->writeCrtc(hwp, 0x79, 0x00);
7657e6fb56fSmrg
7667e6fb56fSmrg    } else {
7677e6fb56fSmrg        if ((pVia->Chipset == VIA_CLE266) && CLE266_REV_IS_AX(pVia->ChipRev)) {
7687e6fb56fSmrg            ViaCrtcMask(hwp, 0x6B, 0x80, 0x80);
7697e6fb56fSmrg
7707e6fb56fSmrg            /* Fix TV clock polarity for CLE266A2. */
7717e6fb56fSmrg            if (pVia->ChipRev == 0x02)
7727e6fb56fSmrg                hwp->writeCrtc(hwp, 0x6C, Table.PrimaryCR6C);
7737e6fb56fSmrg        }
7747e6fb56fSmrg    }
7757e6fb56fSmrg    pBIOSInfo->ClockExternal = TRUE;
7767e6fb56fSmrg    ViaCrtcMask(hwp, 0x6A, 0x40, 0x40);
7777e6fb56fSmrg    ViaSetTVClockSource(pScrn);
7787e6fb56fSmrg}
7797e6fb56fSmrg
7807e6fb56fSmrg
7817e6fb56fSmrgstatic void
7827e6fb56fSmrgVT1621Power(ScrnInfoPtr pScrn, Bool On)
7837e6fb56fSmrg{
7847e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
7857e6fb56fSmrg
7867e6fb56fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621Power\n"));
7877e6fb56fSmrg
7887e6fb56fSmrg    if (On)
7897e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00);
7907e6fb56fSmrg    else
7917e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x03);
7927e6fb56fSmrg}
7937e6fb56fSmrg
7947e6fb56fSmrgstatic void
7957e6fb56fSmrgVT1622Power(ScrnInfoPtr pScrn, Bool On)
7967e6fb56fSmrg{
7977e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
7987e6fb56fSmrg
7997e6fb56fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622Power\n"));
8007e6fb56fSmrg
8017e6fb56fSmrg    if (On)
8027e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00);
8037e6fb56fSmrg    else
8047e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x0F);
8057e6fb56fSmrg}
8067e6fb56fSmrg
8077e6fb56fSmrgstatic void
8087e6fb56fSmrgVT1625Power(ScrnInfoPtr pScrn, Bool On)
8097e6fb56fSmrg{
8107e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
8117e6fb56fSmrg
8127e6fb56fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1625Power\n"));
8137e6fb56fSmrg
8147e6fb56fSmrg    if (On)
8157e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00);
8167e6fb56fSmrg    else
8177e6fb56fSmrg        xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x3F);
8187e6fb56fSmrg}
8197e6fb56fSmrg
8207e6fb56fSmrg
8217e6fb56fSmrgvoid
8227e6fb56fSmrgViaVT162xInit(ScrnInfoPtr pScrn)
8237e6fb56fSmrg{
8247e6fb56fSmrg    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
8257e6fb56fSmrg
8267e6fb56fSmrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaVT162xInit\n"));
8277e6fb56fSmrg
8287e6fb56fSmrg    switch (pBIOSInfo->TVEncoder) {
8297e6fb56fSmrg        case VIA_VT1621:
8307e6fb56fSmrg            pBIOSInfo->TVSave = VT162xSave;
8317e6fb56fSmrg            pBIOSInfo->TVRestore = VT162xRestore;
8327e6fb56fSmrg            pBIOSInfo->TVDACSense = VT1621DACSense;
8337e6fb56fSmrg            pBIOSInfo->TVModeValid = VT1621ModeValid;
8347e6fb56fSmrg            pBIOSInfo->TVModeI2C = VT1621ModeI2C;
8357e6fb56fSmrg            pBIOSInfo->TVModeCrtc = VT1621ModeCrtc;
8367e6fb56fSmrg            pBIOSInfo->TVPower = VT1621Power;
8377e6fb56fSmrg            pBIOSInfo->TVModes = VT1621Modes;
8387e6fb56fSmrg            pBIOSInfo->TVPrintRegs = VT162xPrintRegs;
8397e6fb56fSmrg            pBIOSInfo->TVNumRegs = 0x68;
8407e6fb56fSmrg            break;
8417e6fb56fSmrg        case VIA_VT1622:
8427e6fb56fSmrg            pBIOSInfo->TVSave = VT162xSave;
8437e6fb56fSmrg            pBIOSInfo->TVRestore = VT162xRestore;
8447e6fb56fSmrg            pBIOSInfo->TVDACSense = VT1622DACSense;
8457e6fb56fSmrg            pBIOSInfo->TVModeValid = VT1622ModeValid;
8467e6fb56fSmrg            pBIOSInfo->TVModeI2C = VT1622ModeI2C;
8477e6fb56fSmrg            pBIOSInfo->TVModeCrtc = VT1622ModeCrtc;
8487e6fb56fSmrg            pBIOSInfo->TVPower = VT1622Power;
8497e6fb56fSmrg            pBIOSInfo->TVModes = VT1622Modes;
8507e6fb56fSmrg            pBIOSInfo->TVPrintRegs = VT162xPrintRegs;
8517e6fb56fSmrg            pBIOSInfo->TVNumRegs = 0x68;
8527e6fb56fSmrg            break;
8537e6fb56fSmrg        case VIA_VT1623:
8547e6fb56fSmrg            pBIOSInfo->TVSave = VT162xSave;
8557e6fb56fSmrg            pBIOSInfo->TVRestore = VT162xRestore;
8567e6fb56fSmrg            pBIOSInfo->TVDACSense = VT1622DACSense;
8577e6fb56fSmrg            pBIOSInfo->TVModeValid = VT1622ModeValid;
8587e6fb56fSmrg            pBIOSInfo->TVModeI2C = VT1622ModeI2C;
8597e6fb56fSmrg            pBIOSInfo->TVModeCrtc = VT1622ModeCrtc;
8607e6fb56fSmrg            pBIOSInfo->TVPower = VT1622Power;
8617e6fb56fSmrg            pBIOSInfo->TVModes = VT1623Modes;
8627e6fb56fSmrg            pBIOSInfo->TVPrintRegs = VT162xPrintRegs;
8637e6fb56fSmrg            pBIOSInfo->TVNumRegs = 0x6C;
8647e6fb56fSmrg            break;
8657e6fb56fSmrg        case VIA_VT1625:
8667e6fb56fSmrg            pBIOSInfo->TVSave = VT162xSave;
8677e6fb56fSmrg            pBIOSInfo->TVRestore = VT162xRestore;
8687e6fb56fSmrg            pBIOSInfo->TVDACSense = VT1625DACSense;
8697e6fb56fSmrg            pBIOSInfo->TVModeValid = VT1625ModeValid;
8707e6fb56fSmrg            pBIOSInfo->TVModeI2C = VT1622ModeI2C;
8717e6fb56fSmrg            pBIOSInfo->TVModeCrtc = VT1622ModeCrtc;
8727e6fb56fSmrg            pBIOSInfo->TVPower = VT1625Power;
8737e6fb56fSmrg            pBIOSInfo->TVModes = VT1625Modes;
8747e6fb56fSmrg            pBIOSInfo->TVPrintRegs = VT162xPrintRegs;
8757e6fb56fSmrg            pBIOSInfo->TVNumRegs = 0x6C;
8767e6fb56fSmrg            break;
8777e6fb56fSmrg        default:
8787e6fb56fSmrg            break;
8797e6fb56fSmrg    }
8807e6fb56fSmrg}
881