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_vt162x.h" 327e6fb56fSmrg 337e6fb56fSmrgstatic void 3490b17f1bSmrgViaSetTVClockSource(xf86CrtcPtr crtc) 357e6fb56fSmrg{ 3690b17f1bSmrg drmmode_crtc_private_ptr iga = crtc->driver_private; 3790b17f1bSmrg ScrnInfoPtr pScrn = crtc->scrn; 3890b17f1bSmrg VIAPtr pVia = VIAPTR(pScrn); 3990b17f1bSmrg VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 4090b17f1bSmrg vgaHWPtr hwp = VGAHWPTR(pScrn); 4190b17f1bSmrg 4290b17f1bSmrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaSetTVClockSource\n")); 4390b17f1bSmrg 4490b17f1bSmrg switch(pBIOSInfo->TVEncoder) { 4590b17f1bSmrg case VIA_VT1625: 4690b17f1bSmrg /* External TV: */ 4790b17f1bSmrg switch(pVia->Chipset) { 4890b17f1bSmrg case VIA_CX700: 4990b17f1bSmrg case VIA_VX800: 5090b17f1bSmrg case VIA_VX855: 51983b4bf2Smrg case VIA_VX900: 52983b4bf2Smrg /* IGA1 */ 5390b17f1bSmrg if (!iga->index) { 54983b4bf2Smrg /* Fixing it to DVP1 for IGA1. */ 55983b4bf2Smrg ViaCrtcMask(hwp, 0x6C, 0xB0, 0xF0); 56983b4bf2Smrg /* IGA2 */ 5790b17f1bSmrg } else { 58983b4bf2Smrg /* Fixing it to DVP1 for IGA2. */ 59983b4bf2Smrg ViaCrtcMask(hwp, 0x6C, 0x0B, 0x0F); 6090b17f1bSmrg } 6190b17f1bSmrg break; 6290b17f1bSmrg default: 6390b17f1bSmrg if (!iga->index) 6490b17f1bSmrg ViaCrtcMask(hwp, 0x6C, 0x21, 0x21); 6590b17f1bSmrg else 6690b17f1bSmrg ViaCrtcMask(hwp, 0x6C, 0xA1, 0xA1); 6790b17f1bSmrg break; 687e6fb56fSmrg } 697e6fb56fSmrg break; 707e6fb56fSmrg default: 7190b17f1bSmrg if (!iga->index) 7290b17f1bSmrg ViaCrtcMask(hwp, 0x6C, 0x50, 0xF0); 7390b17f1bSmrg else 7490b17f1bSmrg ViaCrtcMask(hwp, 0x6C, 0x05, 0x0F); 757e6fb56fSmrg break; 767e6fb56fSmrg } 7790b17f1bSmrg 787e6fb56fSmrg} 797e6fb56fSmrg 807e6fb56fSmrgstatic void 817e6fb56fSmrgVT162xPrintRegs(ScrnInfoPtr pScrn) 827e6fb56fSmrg{ 837e6fb56fSmrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 847e6fb56fSmrg CARD8 i, buf; 857e6fb56fSmrg 867e6fb56fSmrg 877e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Printing registers for %s\n", 887e6fb56fSmrg pBIOSInfo->TVI2CDev->DevName); 897e6fb56fSmrg 907e6fb56fSmrg for (i = 0; i < pBIOSInfo->TVNumRegs; i++) { 917e6fb56fSmrg xf86I2CReadByte(pBIOSInfo->TVI2CDev, i, &buf); 927e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV%02X: 0x%02X\n", i, buf); 937e6fb56fSmrg } 947e6fb56fSmrg 957e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of TV registers.\n"); 967e6fb56fSmrg} 977e6fb56fSmrg 987e6fb56fSmrg 997e6fb56fSmrgI2CDevPtr 1007e6fb56fSmrgViaVT162xDetect(ScrnInfoPtr pScrn, I2CBusPtr pBus, CARD8 Address) 1017e6fb56fSmrg{ 1027e6fb56fSmrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 1037e6fb56fSmrg I2CDevPtr pDev = xf86CreateI2CDevRec(); 1047e6fb56fSmrg CARD8 buf; 1057e6fb56fSmrg 1067e6fb56fSmrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaVT162xDetect\n")); 1077e6fb56fSmrg 1087e6fb56fSmrg pDev->DevName = "VT162x"; 1097e6fb56fSmrg pDev->SlaveAddr = Address; 1107e6fb56fSmrg pDev->pI2CBus = pBus; 1117e6fb56fSmrg 1127e6fb56fSmrg if (!xf86I2CDevInit(pDev)) { 1137e6fb56fSmrg xf86DestroyI2CDevRec(pDev, TRUE); 1147e6fb56fSmrg return NULL; 1157e6fb56fSmrg } 1167e6fb56fSmrg 1177e6fb56fSmrg if (!xf86I2CReadByte(pDev, 0x1B, &buf)) { 1187e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1197e6fb56fSmrg "Unable to read from %s Slave %d.\n", 1207e6fb56fSmrg pBus->BusName, Address); 1217e6fb56fSmrg xf86DestroyI2CDevRec(pDev, TRUE); 1227e6fb56fSmrg return NULL; 1237e6fb56fSmrg } 1247e6fb56fSmrg 1257e6fb56fSmrg switch (buf) { 1267e6fb56fSmrg case 0x02: 1277e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1287e6fb56fSmrg "Detected VIA Technologies VT1621 TV Encoder\n"); 1297e6fb56fSmrg pBIOSInfo->TVEncoder = VIA_VT1621; 1307e6fb56fSmrg pDev->DevName = "VT1621"; 1317e6fb56fSmrg break; 1327e6fb56fSmrg case 0x03: 1337e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1347e6fb56fSmrg "Detected VIA Technologies VT1622 TV Encoder\n"); 1357e6fb56fSmrg pBIOSInfo->TVEncoder = VIA_VT1622; 1367e6fb56fSmrg pDev->DevName = "VT1622"; 1377e6fb56fSmrg break; 1387e6fb56fSmrg case 0x10: 1397e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1407e6fb56fSmrg "Detected VIA Technologies VT1622A/VT1623 TV Encoder\n"); 1417e6fb56fSmrg pBIOSInfo->TVEncoder = VIA_VT1623; 1427e6fb56fSmrg pDev->DevName = "VT1623"; 1437e6fb56fSmrg break; 1447e6fb56fSmrg case 0x50: 1457e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 1467e6fb56fSmrg "Detected VIA Technologies VT1625 TV Encoder\n"); 1477e6fb56fSmrg pBIOSInfo->TVEncoder = VIA_VT1625; 1487e6fb56fSmrg pDev->DevName = "VT1625"; 1497e6fb56fSmrg break; 1507e6fb56fSmrg default: 1517e6fb56fSmrg pBIOSInfo->TVEncoder = VIA_NONETV; 1527e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1537e6fb56fSmrg "Unknown TV Encoder found at %s %X.\n", 1547e6fb56fSmrg pBus->BusName, Address); 1557e6fb56fSmrg xf86DestroyI2CDevRec(pDev, TRUE); 1567e6fb56fSmrg pDev = NULL; 1577e6fb56fSmrg break; 1587e6fb56fSmrg } 1597e6fb56fSmrg 1607e6fb56fSmrg return pDev; 1617e6fb56fSmrg} 1627e6fb56fSmrg 1637e6fb56fSmrg 1647e6fb56fSmrgstatic void 1657e6fb56fSmrgVT162xSave(ScrnInfoPtr pScrn) 1667e6fb56fSmrg{ 1677e6fb56fSmrg int i; 1687e6fb56fSmrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 1697e6fb56fSmrg 1707e6fb56fSmrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT162xSave\n")); 1717e6fb56fSmrg 1727e6fb56fSmrg for (i = 0; i < pBIOSInfo->TVNumRegs; i++) 1737e6fb56fSmrg xf86I2CReadByte(pBIOSInfo->TVI2CDev, i, &(pBIOSInfo->TVRegs[i])); 1747e6fb56fSmrg 1757e6fb56fSmrg} 1767e6fb56fSmrg 1777e6fb56fSmrgstatic void 1787e6fb56fSmrgVT162xRestore(ScrnInfoPtr pScrn) 1797e6fb56fSmrg{ 1807e6fb56fSmrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 1817e6fb56fSmrg int i; 1827e6fb56fSmrg 1837e6fb56fSmrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT162xRestore\n")); 1847e6fb56fSmrg 1857e6fb56fSmrg for (i = 0; i < pBIOSInfo->TVNumRegs; i++) 1867e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, pBIOSInfo->TVRegs[i]); 1877e6fb56fSmrg} 1887e6fb56fSmrg 1897e6fb56fSmrg 1907e6fb56fSmrg/* 1917e6fb56fSmrg * For VT1621 the same as for VT1622/VT1622A/VT1623, but result is different. 1927e6fb56fSmrg * Still needs testing on VT1621, of course. 1937e6fb56fSmrg */ 1947e6fb56fSmrgstatic CARD8 1957e6fb56fSmrgVT162xDACSenseI2C(I2CDevPtr pDev) 1967e6fb56fSmrg{ 1977e6fb56fSmrg CARD8 save, sense; 1987e6fb56fSmrg 1997e6fb56fSmrg xf86I2CReadByte(pDev, 0x0E, &save); 2007e6fb56fSmrg xf86I2CWriteByte(pDev, 0x0E, 0x00); 2017e6fb56fSmrg xf86I2CWriteByte(pDev, 0x0E, 0x80); 2027e6fb56fSmrg xf86I2CWriteByte(pDev, 0x0E, 0x00); 2037e6fb56fSmrg xf86I2CReadByte(pDev, 0x0F, &sense); 2047e6fb56fSmrg xf86I2CWriteByte(pDev, 0x0E, save); 2057e6fb56fSmrg 2067e6fb56fSmrg return (sense & 0x0F); 2077e6fb56fSmrg} 2087e6fb56fSmrg 2097e6fb56fSmrg/* 21090b17f1bSmrg * VT1625/VT1625S sense connected TV outputs. 21190b17f1bSmrg * 21290b17f1bSmrg * The lower six bits of the return byte stand for each of the six DACs: 21390b17f1bSmrg * - bit 0: DACf (Cb) 21490b17f1bSmrg * - bit 1: DACe (Cr) 21590b17f1bSmrg * - bit 2: DACd (Y) 21690b17f1bSmrg * - bit 3: DACc (Composite) 21790b17f1bSmrg * - bit 4: DACb (S-Video C) 21890b17f1bSmrg * - bit 5: DACa (S-Video Y) 21990b17f1bSmrg * 22090b17f1bSmrg * If a bit is 0 it means a cable is connected. Note the VT1625S only has 22190b17f1bSmrg * four DACs, corresponding to bit 0-3 above. 2227e6fb56fSmrg */ 2237e6fb56fSmrgstatic CARD8 2247e6fb56fSmrgVT1625DACSenseI2C(I2CDevPtr pDev) 2257e6fb56fSmrg{ 22690b17f1bSmrg CARD8 power, status, overflow, dacPresent; 22790b17f1bSmrg 22890b17f1bSmrg xf86I2CReadByte(pDev, 0x0E, &power); // save power state 22990b17f1bSmrg 23090b17f1bSmrg // VT1625S will always report 0 for bits 4 and 5 of the status register as 23190b17f1bSmrg // it only has four DACs instead of six. This will result in a false 23290b17f1bSmrg // positive for the S-Video cable. It will also do this on the power 23390b17f1bSmrg // register, which is abused to check which DACs are actually present. 23490b17f1bSmrg xf86I2CWriteByte(pDev, 0x0E, 0xFF); 23590b17f1bSmrg xf86I2CReadByte(pDev, 0x0E, &dacPresent); 23690b17f1bSmrg 23790b17f1bSmrg xf86I2CWriteByte(pDev, 0x0E, 0x00); // power on DACs/circuits 23890b17f1bSmrg xf86I2CReadByte(pDev, 0x1C, &overflow); // save overflow reg 23990b17f1bSmrg // (DAC sense bit should be off) 24090b17f1bSmrg xf86I2CWriteByte(pDev, 0x1C, 0x80); // enable DAC sense bit 24190b17f1bSmrg xf86I2CWriteByte(pDev, 0x1C, overflow); // disable DAC sense bit 24290b17f1bSmrg xf86I2CReadByte(pDev, 0x0F, &status); // read connection status 24390b17f1bSmrg xf86I2CWriteByte(pDev, 0x0E, power); // restore power state 24490b17f1bSmrg status |= ~dacPresent; 24590b17f1bSmrg 24690b17f1bSmrg return (status & 0x3F); 2477e6fb56fSmrg} 2487e6fb56fSmrg 2497e6fb56fSmrg/* 2507e6fb56fSmrg * VT1621 only knows composite and s-video. 2517e6fb56fSmrg */ 2527e6fb56fSmrgstatic Bool 2537e6fb56fSmrgVT1621DACSense(ScrnInfoPtr pScrn) 2547e6fb56fSmrg{ 2557e6fb56fSmrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 2567e6fb56fSmrg CARD8 sense; 2577e6fb56fSmrg 2587e6fb56fSmrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621DACSense\n")); 2597e6fb56fSmrg 2607e6fb56fSmrg sense = VT162xDACSenseI2C(pBIOSInfo->TVI2CDev); 2617e6fb56fSmrg switch (sense) { 2627e6fb56fSmrg case 0x00: 2637e6fb56fSmrg pBIOSInfo->TVOutput = TVOUTPUT_SC; 2647e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2657e6fb56fSmrg "VT1621: S-Video & Composite connected.\n"); 2667e6fb56fSmrg return TRUE; 2677e6fb56fSmrg case 0x01: 2687e6fb56fSmrg pBIOSInfo->TVOutput = TVOUTPUT_COMPOSITE; 2697e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2707e6fb56fSmrg "VT1621: Composite connected.\n"); 2717e6fb56fSmrg return TRUE; 2727e6fb56fSmrg case 0x02: 2737e6fb56fSmrg pBIOSInfo->TVOutput = TVOUTPUT_SVIDEO; 2747e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2757e6fb56fSmrg "VT1621: S-Video connected.\n"); 2767e6fb56fSmrg return TRUE; 2777e6fb56fSmrg case 0x03: 2787e6fb56fSmrg pBIOSInfo->TVOutput = TVOUTPUT_NONE; 2797e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2807e6fb56fSmrg "VT1621: Nothing connected.\n"); 2817e6fb56fSmrg return FALSE; 2827e6fb56fSmrg default: 2837e6fb56fSmrg pBIOSInfo->TVOutput = TVOUTPUT_NONE; 2847e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2857e6fb56fSmrg "VT1621: Unknown cable combination: 0x0%2X.\n", sense); 2867e6fb56fSmrg return FALSE; 2877e6fb56fSmrg } 2887e6fb56fSmrg} 2897e6fb56fSmrg 2907e6fb56fSmrg/* 2917e6fb56fSmrg * VT1622, VT1622A and VT1623 know composite, s-video, RGB and YCBCR. 2927e6fb56fSmrg */ 2937e6fb56fSmrgstatic Bool 2947e6fb56fSmrgVT1622DACSense(ScrnInfoPtr pScrn) 2957e6fb56fSmrg{ 2967e6fb56fSmrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 2977e6fb56fSmrg CARD8 sense; 2987e6fb56fSmrg 2997e6fb56fSmrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622DACSense\n")); 3007e6fb56fSmrg 3017e6fb56fSmrg sense = VT162xDACSenseI2C(pBIOSInfo->TVI2CDev); 3027e6fb56fSmrg switch (sense) { 3037e6fb56fSmrg case 0x00: /* DAC A,B,C,D */ 3047e6fb56fSmrg pBIOSInfo->TVOutput = TVOUTPUT_RGB; 3057e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3067e6fb56fSmrg "VT162x: RGB connected.\n"); 3077e6fb56fSmrg return TRUE; 3087e6fb56fSmrg case 0x01: /* DAC A,B,C */ 3097e6fb56fSmrg pBIOSInfo->TVOutput = TVOUTPUT_SC; 3107e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3117e6fb56fSmrg "VT162x: S-Video & Composite connected.\n"); 3127e6fb56fSmrg return TRUE; 3137e6fb56fSmrg case 0x07: /* DAC A */ 3147e6fb56fSmrg pBIOSInfo->TVOutput = TVOUTPUT_COMPOSITE; 3157e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3167e6fb56fSmrg "VT162x: Composite connected.\n"); 3177e6fb56fSmrg return TRUE; 3187e6fb56fSmrg case 0x08: /* DAC B,C,D */ 3197e6fb56fSmrg pBIOSInfo->TVOutput = TVOUTPUT_YCBCR; 3207e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3217e6fb56fSmrg "VT162x: YcBcR connected.\n"); 3227e6fb56fSmrg return TRUE; 3237e6fb56fSmrg case 0x09: /* DAC B,C */ 3247e6fb56fSmrg pBIOSInfo->TVOutput = TVOUTPUT_SVIDEO; 3257e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3267e6fb56fSmrg "VT162x: S-Video connected.\n"); 3277e6fb56fSmrg return TRUE; 3287e6fb56fSmrg case 0x0F: 3297e6fb56fSmrg pBIOSInfo->TVOutput = TVOUTPUT_NONE; 3307e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3317e6fb56fSmrg "VT162x: Nothing connected.\n"); 3327e6fb56fSmrg return FALSE; 3337e6fb56fSmrg default: 3347e6fb56fSmrg pBIOSInfo->TVOutput = TVOUTPUT_NONE; 3357e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3367e6fb56fSmrg "VT162x: Unknown cable combination: 0x0%2X.\n", sense); 3377e6fb56fSmrg return FALSE; 3387e6fb56fSmrg } 3397e6fb56fSmrg} 3407e6fb56fSmrg 3417e6fb56fSmrg/* 3427e6fb56fSmrg * VT1625 knows composite, s-video, RGB and YCBCR. 3437e6fb56fSmrg */ 3447e6fb56fSmrgstatic Bool 3457e6fb56fSmrgVT1625DACSense(ScrnInfoPtr pScrn) 3467e6fb56fSmrg{ 3477e6fb56fSmrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 3487e6fb56fSmrg CARD8 sense; 3497e6fb56fSmrg 3507e6fb56fSmrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1625DACSense\n")); 3517e6fb56fSmrg 3527e6fb56fSmrg sense = VT1625DACSenseI2C(pBIOSInfo->TVI2CDev); 3537e6fb56fSmrg switch (sense) { 3547e6fb56fSmrg case 0x00: /* DAC A,B,C,D,E,F */ 3557e6fb56fSmrg pBIOSInfo->TVOutput = TVOUTPUT_RGB; 3567e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3577e6fb56fSmrg "VT1625: RGB connected.\n"); 3587e6fb56fSmrg return TRUE; 3597e6fb56fSmrg case 0x07: /* DAC A,B,C */ 3607e6fb56fSmrg pBIOSInfo->TVOutput = TVOUTPUT_SC; 3617e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3627e6fb56fSmrg "VT1625: S-Video & Composite connected.\n"); 3637e6fb56fSmrg return TRUE; 3647e6fb56fSmrg case 0x37: /* DAC C */ 3657e6fb56fSmrg pBIOSInfo->TVOutput = TVOUTPUT_COMPOSITE; 3667e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3677e6fb56fSmrg "VT1625: Composite connected.\n"); 3687e6fb56fSmrg return TRUE; 3697e6fb56fSmrg case 0x38: /* DAC D,E,F */ 3707e6fb56fSmrg pBIOSInfo->TVOutput = TVOUTPUT_YCBCR; 3717e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3727e6fb56fSmrg "VT1625: YCbCr connected.\n"); 3737e6fb56fSmrg return TRUE; 3747e6fb56fSmrg case 0x0F: /* DAC A,B */ 3757e6fb56fSmrg pBIOSInfo->TVOutput = TVOUTPUT_SVIDEO; 3767e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3777e6fb56fSmrg "VT1625: S-Video connected.\n"); 3787e6fb56fSmrg return TRUE; 3797e6fb56fSmrg case 0x3F: 3807e6fb56fSmrg pBIOSInfo->TVOutput = TVOUTPUT_NONE; 3817e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3827e6fb56fSmrg "VT1625: Nothing connected.\n"); 3837e6fb56fSmrg return FALSE; 3847e6fb56fSmrg default: 3857e6fb56fSmrg pBIOSInfo->TVOutput = TVOUTPUT_NONE; 3867e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3877e6fb56fSmrg "VT1625: Unknown cable combination: 0x0%2X.\n", sense); 3887e6fb56fSmrg return FALSE; 3897e6fb56fSmrg } 3907e6fb56fSmrg} 3917e6fb56fSmrg 3927e6fb56fSmrgstatic CARD8 3937e6fb56fSmrgVT1621ModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode) 3947e6fb56fSmrg{ 3957e6fb56fSmrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 3967e6fb56fSmrg int i; 3977e6fb56fSmrg 3987e6fb56fSmrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621ModeIndex\n")); 3997e6fb56fSmrg 4007e6fb56fSmrg for (i = 0; VT1621Table[i].Width; i++) { 4017e6fb56fSmrg if ((VT1621Table[i].Width == mode->CrtcHDisplay) && 4027e6fb56fSmrg (VT1621Table[i].Height == mode->CrtcVDisplay) && 4037e6fb56fSmrg (VT1621Table[i].Standard == pBIOSInfo->TVType) && 4047e6fb56fSmrg !(strcmp(VT1621Table[i].name, mode->name))) 4057e6fb56fSmrg return i; 4067e6fb56fSmrg } 4077e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VT1621ModeIndex:" 4087e6fb56fSmrg " Mode \"%s\" not found in Table\n", mode->name); 4097e6fb56fSmrg return 0xFF; 4107e6fb56fSmrg} 4117e6fb56fSmrg 4127e6fb56fSmrgstatic ModeStatus 4137e6fb56fSmrgVT1621ModeValid(ScrnInfoPtr pScrn, DisplayModePtr mode) 4147e6fb56fSmrg{ 4157e6fb56fSmrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 4167e6fb56fSmrg 4177e6fb56fSmrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621ModeValid\n")); 4187e6fb56fSmrg 4197e6fb56fSmrg if ((mode->PrivSize != sizeof(struct VT162xModePrivate)) || 4207e6fb56fSmrg ((mode->Private != (void *)&VT162xModePrivateNTSC) && 4217e6fb56fSmrg (mode->Private != (void *)&VT162xModePrivatePAL))) { 4227e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4237e6fb56fSmrg "Not a mode defined by the TV Encoder.\n"); 4247e6fb56fSmrg return MODE_BAD; 4257e6fb56fSmrg } 4267e6fb56fSmrg 4277e6fb56fSmrg if ((pBIOSInfo->TVType == TVTYPE_NTSC) && 4287e6fb56fSmrg (mode->Private != (void *)&VT162xModePrivateNTSC)) { 4297e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4307e6fb56fSmrg "TV standard is NTSC. This is a PAL mode.\n"); 4317e6fb56fSmrg return MODE_BAD; 4327e6fb56fSmrg } else if ((pBIOSInfo->TVType == TVTYPE_PAL) && 4337e6fb56fSmrg (mode->Private != (void *)&VT162xModePrivatePAL)) { 4347e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4357e6fb56fSmrg "TV standard is PAL. This is a NTSC mode.\n"); 4367e6fb56fSmrg return MODE_BAD; 4377e6fb56fSmrg } 4387e6fb56fSmrg 4397e6fb56fSmrg if (VT1621ModeIndex(pScrn, mode) != 0xFF) 4407e6fb56fSmrg return MODE_OK; 4417e6fb56fSmrg return MODE_BAD; 4427e6fb56fSmrg} 4437e6fb56fSmrg 4447e6fb56fSmrgstatic CARD8 4457e6fb56fSmrgVT1622ModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode) 4467e6fb56fSmrg{ 4477e6fb56fSmrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 4487e6fb56fSmrg struct VT162XTableRec *Table; 4497e6fb56fSmrg int i; 4507e6fb56fSmrg 4517e6fb56fSmrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622ModeIndex\n")); 4527e6fb56fSmrg 4537e6fb56fSmrg if (pBIOSInfo->TVEncoder == VIA_VT1622) 4547e6fb56fSmrg Table = VT1622Table; 4557e6fb56fSmrg else if (pBIOSInfo->TVEncoder == VIA_VT1625) 4567e6fb56fSmrg Table = VT1625Table; 4577e6fb56fSmrg else 4587e6fb56fSmrg Table = VT1623Table; 4597e6fb56fSmrg 4607e6fb56fSmrg for (i = 0; Table[i].Width; i++) { 4617e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 4627e6fb56fSmrg "width=%d:%d, height=%d:%d, std=%d:%d, name=%s:%s.\n", 4637e6fb56fSmrg Table[i].Width, mode->CrtcHDisplay, 4647e6fb56fSmrg Table[i].Height, mode->CrtcVDisplay, 4657e6fb56fSmrg Table[i].Standard, pBIOSInfo->TVType, 4667e6fb56fSmrg Table[i].name, mode->name); 4677e6fb56fSmrg 4687e6fb56fSmrg if ((Table[i].Width == mode->CrtcHDisplay) && 4697e6fb56fSmrg (Table[i].Height == mode->CrtcVDisplay) && 4707e6fb56fSmrg (Table[i].Standard == pBIOSInfo->TVType) && 4717e6fb56fSmrg !strcmp(Table[i].name, mode->name)) 4727e6fb56fSmrg return i; 4737e6fb56fSmrg } 4747e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VT1622ModeIndex:" 4757e6fb56fSmrg " Mode \"%s\" not found in Table\n", mode->name); 4767e6fb56fSmrg return 0xFF; 4777e6fb56fSmrg} 4787e6fb56fSmrg 4797e6fb56fSmrgstatic ModeStatus 4807e6fb56fSmrgVT1622ModeValid(ScrnInfoPtr pScrn, DisplayModePtr mode) 4817e6fb56fSmrg{ 4827e6fb56fSmrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 4837e6fb56fSmrg 4847e6fb56fSmrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622ModeValid\n")); 4857e6fb56fSmrg 4867e6fb56fSmrg if ((mode->PrivSize != sizeof(struct VT162xModePrivate)) || 4877e6fb56fSmrg ((mode->Private != (void *)&VT162xModePrivateNTSC) && 4887e6fb56fSmrg (mode->Private != (void *)&VT162xModePrivatePAL))) { 4897e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4907e6fb56fSmrg "Not a mode defined by the TV Encoder.\n"); 4917e6fb56fSmrg return MODE_BAD; 4927e6fb56fSmrg } 4937e6fb56fSmrg 4947e6fb56fSmrg if ((pBIOSInfo->TVType == TVTYPE_NTSC) && 4957e6fb56fSmrg (mode->Private != (void *)&VT162xModePrivateNTSC)) { 4967e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 4977e6fb56fSmrg "TV standard is NTSC. This is a PAL mode.\n"); 4987e6fb56fSmrg return MODE_BAD; 4997e6fb56fSmrg } else if ((pBIOSInfo->TVType == TVTYPE_PAL) && 5007e6fb56fSmrg (mode->Private != (void *)&VT162xModePrivatePAL)) { 5017e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5027e6fb56fSmrg "TV standard is PAL. This is a NTSC mode.\n"); 5037e6fb56fSmrg return MODE_BAD; 5047e6fb56fSmrg } 5057e6fb56fSmrg 5067e6fb56fSmrg if (VT1622ModeIndex(pScrn, mode) != 0xFF) 5077e6fb56fSmrg return MODE_OK; 5087e6fb56fSmrg return MODE_BAD; 5097e6fb56fSmrg} 5107e6fb56fSmrg 5117e6fb56fSmrgstatic ModeStatus 5127e6fb56fSmrgVT1625ModeValid(ScrnInfoPtr pScrn, DisplayModePtr mode) 5137e6fb56fSmrg{ 5147e6fb56fSmrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 5157e6fb56fSmrg 5167e6fb56fSmrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1625ModeValid\n")); 5177e6fb56fSmrg 5187e6fb56fSmrg if ((mode->PrivSize != sizeof(struct VT162xModePrivate)) || 5197e6fb56fSmrg ((mode->Private != (void *)&VT162xModePrivateNTSC) && 5207e6fb56fSmrg (mode->Private != (void *)&VT162xModePrivatePAL) && 5217e6fb56fSmrg (mode->Private != (void *)&VT162xModePrivate480P) && 5227e6fb56fSmrg (mode->Private != (void *)&VT162xModePrivate576P) && 5237e6fb56fSmrg (mode->Private != (void *)&VT162xModePrivate720P) && 5247e6fb56fSmrg (mode->Private != (void *)&VT162xModePrivate1080I))) { 5257e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5267e6fb56fSmrg "Not a mode defined by the TV Encoder.\n"); 5277e6fb56fSmrg return MODE_BAD; 5287e6fb56fSmrg } 5297e6fb56fSmrg 5307e6fb56fSmrg if ((pBIOSInfo->TVType == TVTYPE_NTSC) && 5317e6fb56fSmrg (mode->Private != (void *)&VT162xModePrivateNTSC)) { 5327e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5337e6fb56fSmrg "TV standard is NTSC. This is an incompatible mode.\n"); 5347e6fb56fSmrg return MODE_BAD; 5357e6fb56fSmrg } else if ((pBIOSInfo->TVType == TVTYPE_PAL) && 5367e6fb56fSmrg (mode->Private != (void *)&VT162xModePrivatePAL)) { 5377e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5387e6fb56fSmrg "TV standard is PAL. This is an incompatible mode.\n"); 5397e6fb56fSmrg return MODE_BAD; 5407e6fb56fSmrg } else if ((pBIOSInfo->TVType == TVTYPE_480P) && 5417e6fb56fSmrg (mode->Private != (void *)&VT162xModePrivate480P)) { 5427e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5437e6fb56fSmrg "TV standard is 480P. This is an incompatible mode.\n"); 5447e6fb56fSmrg return MODE_BAD; 5457e6fb56fSmrg } else if ((pBIOSInfo->TVType == TVTYPE_576P) && 5467e6fb56fSmrg (mode->Private != (void *)&VT162xModePrivate576P)) { 5477e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5487e6fb56fSmrg "TV standard is 576P. This is an incompatible mode.\n"); 5497e6fb56fSmrg return MODE_BAD; 5507e6fb56fSmrg } else if ((pBIOSInfo->TVType == TVTYPE_720P) && 5517e6fb56fSmrg (mode->Private != (void *)&VT162xModePrivate720P)) { 5527e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5537e6fb56fSmrg "TV standard is 720P. This is an incompatible mode.\n"); 5547e6fb56fSmrg return MODE_BAD; 5557e6fb56fSmrg } else if ((pBIOSInfo->TVType == TVTYPE_1080I) && 5567e6fb56fSmrg (mode->Private != (void *)&VT162xModePrivate1080I)) { 5577e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 5587e6fb56fSmrg "TV standard is 1080I. This is an incompatible mode.\n"); 5597e6fb56fSmrg return MODE_BAD; 5607e6fb56fSmrg } 5617e6fb56fSmrg 5627e6fb56fSmrg if (VT1622ModeIndex(pScrn, mode) != 0xFF) 5637e6fb56fSmrg return MODE_OK; 5647e6fb56fSmrg return MODE_BAD; 5657e6fb56fSmrg} 5667e6fb56fSmrg 5677e6fb56fSmrg 5687e6fb56fSmrgstatic void 5697e6fb56fSmrgVT162xSetSubCarrier(I2CDevPtr pDev, CARD32 SubCarrier) 5707e6fb56fSmrg{ 5717e6fb56fSmrg xf86I2CWriteByte(pDev, 0x16, SubCarrier & 0xFF); 5727e6fb56fSmrg xf86I2CWriteByte(pDev, 0x17, (SubCarrier >> 8) & 0xFF); 5737e6fb56fSmrg xf86I2CWriteByte(pDev, 0x18, (SubCarrier >> 16) & 0xFF); 5747e6fb56fSmrg xf86I2CWriteByte(pDev, 0x19, (SubCarrier >> 24) & 0xFF); 5757e6fb56fSmrg} 5767e6fb56fSmrg 5777e6fb56fSmrgstatic void 5787e6fb56fSmrgVT1621ModeI2C(ScrnInfoPtr pScrn, DisplayModePtr mode) 5797e6fb56fSmrg{ 5807e6fb56fSmrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 5817e6fb56fSmrg struct VT1621TableRec Table = VT1621Table[VT1621ModeIndex(pScrn, mode)]; 5827e6fb56fSmrg CARD8 i; 5837e6fb56fSmrg 5847e6fb56fSmrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621ModeI2C\n")); 5857e6fb56fSmrg 5867e6fb56fSmrg for (i = 0; i < 0x16; i++) 5877e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV[i]); 5887e6fb56fSmrg 5897e6fb56fSmrg VT162xSetSubCarrier(pBIOSInfo->TVI2CDev, Table.SubCarrier); 5907e6fb56fSmrg 5917e6fb56fSmrg /* Skip reserved (1A) and version ID (1B). */ 5927e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1C, Table.TV[0x1C]); 5937e6fb56fSmrg 5947e6fb56fSmrg /* Skip software reset (1D). */ 5957e6fb56fSmrg for (i = 0x1E; i < 0x24; i++) 5967e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV[i]); 5977e6fb56fSmrg 5987e6fb56fSmrg /* Write some zeroes? */ 5997e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x24, 0x00); 6007e6fb56fSmrg for (i = 0; i < 0x08; i++) 6017e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4A + i, 0x00); 6027e6fb56fSmrg 6037e6fb56fSmrg if (pBIOSInfo->TVOutput == TVOUTPUT_COMPOSITE) 6047e6fb56fSmrg for (i = 0; i < 0x10; i++) 6057e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x52 + i, Table.TVC[i]); 6067e6fb56fSmrg else 6077e6fb56fSmrg for (i = 0; i < 0x10; i++) 6087e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x52 + i, Table.TVS[i]); 6097e6fb56fSmrg 6107e6fb56fSmrg /* Turn on all Composite and S-Video output. */ 6117e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00); 6127e6fb56fSmrg 6137e6fb56fSmrg if (pBIOSInfo->TVDotCrawl) { 6147e6fb56fSmrg if (Table.DotCrawlSubCarrier) { 6157e6fb56fSmrg xf86I2CReadByte(pBIOSInfo->TVI2CDev, 0x11, &i); 6167e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x11, i | 0x08); 6177e6fb56fSmrg 6187e6fb56fSmrg VT162xSetSubCarrier(pBIOSInfo->TVI2CDev, Table.DotCrawlSubCarrier); 6197e6fb56fSmrg } else 6207e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "This mode does not currently " 6217e6fb56fSmrg "support DotCrawl suppression.\n"); 6227e6fb56fSmrg } 6237e6fb56fSmrg} 6247e6fb56fSmrg 6257e6fb56fSmrgstatic void 62690b17f1bSmrgVT1621ModeCrtc(xf86CrtcPtr crtc, DisplayModePtr mode) 6277e6fb56fSmrg{ 62890b17f1bSmrg ScrnInfoPtr pScrn = crtc->scrn; 62990b17f1bSmrg vgaHWPtr hwp = VGAHWPTR(pScrn); 63090b17f1bSmrg VIAPtr pVia = VIAPTR(pScrn); 63190b17f1bSmrg VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 63290b17f1bSmrg struct VT1621TableRec Table = VT1621Table[VT1621ModeIndex(pScrn, mode)]; 6337e6fb56fSmrg 6347e6fb56fSmrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621ModeCrtc\n")); 6357e6fb56fSmrg 6367e6fb56fSmrg if (pVia->IsSecondary) { 6377e6fb56fSmrg hwp->writeCrtc(hwp, 0x6A, 0x80); 6387e6fb56fSmrg hwp->writeCrtc(hwp, 0x6B, 0x20); 6397e6fb56fSmrg hwp->writeCrtc(hwp, 0x6C, 0x80); 6407e6fb56fSmrg 6417e6fb56fSmrg /* Disable LCD Scaling */ 6427e6fb56fSmrg if (!pVia->SAMM || pVia->FirstInit) 6437e6fb56fSmrg hwp->writeCrtc(hwp, 0x79, 0x00); 6447e6fb56fSmrg 6457e6fb56fSmrg } else { 6467e6fb56fSmrg hwp->writeCrtc(hwp, 0x6A, 0x00); 6477e6fb56fSmrg hwp->writeCrtc(hwp, 0x6B, 0x80); 6487e6fb56fSmrg hwp->writeCrtc(hwp, 0x6C, Table.PrimaryCR6C); 6497e6fb56fSmrg } 6507e6fb56fSmrg pBIOSInfo->ClockExternal = TRUE; 6517e6fb56fSmrg ViaCrtcMask(hwp, 0x6A, 0x40, 0x40); 6527e6fb56fSmrg ViaCrtcMask(hwp, 0x6C, 0x01, 0x01); 6537e6fb56fSmrg} 6547e6fb56fSmrg 6557e6fb56fSmrg/* 6567e6fb56fSmrg * Also suited for VT1622A, VT1623, VT1625. 6577e6fb56fSmrg */ 6587e6fb56fSmrgstatic void 6597e6fb56fSmrgVT1622ModeI2C(ScrnInfoPtr pScrn, DisplayModePtr mode) 6607e6fb56fSmrg{ 6617e6fb56fSmrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 6627e6fb56fSmrg struct VT162XTableRec Table; 6637e6fb56fSmrg CARD8 save, i; 6647e6fb56fSmrg 6657e6fb56fSmrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622ModeI2C\n")); 6667e6fb56fSmrg 6677e6fb56fSmrg if (pBIOSInfo->TVEncoder == VIA_VT1622) 6687e6fb56fSmrg Table = VT1622Table[VT1622ModeIndex(pScrn, mode)]; 6697e6fb56fSmrg else if (pBIOSInfo->TVEncoder == VIA_VT1625) 6707e6fb56fSmrg Table = VT1625Table[VT1622ModeIndex(pScrn, mode)]; 6717e6fb56fSmrg else /* VT1622A/VT1623 */ 6727e6fb56fSmrg Table = VT1623Table[VT1622ModeIndex(pScrn, mode)]; 6737e6fb56fSmrg 6747e6fb56fSmrg /* TV reset. */ 6757e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1D, 0x00); 6767e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1D, 0x80); 6777e6fb56fSmrg 6787e6fb56fSmrg for (i = 0; i < 0x16; i++) 6797e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV1[i]); 6807e6fb56fSmrg 6817e6fb56fSmrg VT162xSetSubCarrier(pBIOSInfo->TVI2CDev, Table.SubCarrier); 6827e6fb56fSmrg 6837e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1A, Table.TV1[0x1A]); 6847e6fb56fSmrg 6857e6fb56fSmrg /* Skip version ID. */ 6867e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1C, Table.TV1[0x1C]); 6877e6fb56fSmrg 6887e6fb56fSmrg /* Skip software reset. */ 6897e6fb56fSmrg for (i = 0x1E; i < 0x30; i++) 6907e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV1[i]); 6917e6fb56fSmrg 6927e6fb56fSmrg for (i = 0; i < 0x1B; i++) 6937e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4A + i, Table.TV2[i]); 6947e6fb56fSmrg 6957e6fb56fSmrg /* Turn on all Composite and S-Video output. */ 6967e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00); 6977e6fb56fSmrg 6987e6fb56fSmrg if (pBIOSInfo->TVDotCrawl) { 6997e6fb56fSmrg if (Table.DotCrawlSubCarrier) { 7007e6fb56fSmrg xf86I2CReadByte(pBIOSInfo->TVI2CDev, 0x11, &save); 7017e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x11, save | 0x08); 7027e6fb56fSmrg 7037e6fb56fSmrg VT162xSetSubCarrier(pBIOSInfo->TVI2CDev, Table.DotCrawlSubCarrier); 7047e6fb56fSmrg } else 7057e6fb56fSmrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "This mode does not currently " 7067e6fb56fSmrg "support DotCrawl suppression.\n"); 7077e6fb56fSmrg } 7087e6fb56fSmrg 7097e6fb56fSmrg if (pBIOSInfo->TVOutput == TVOUTPUT_RGB) { 7107e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x2A); 7117e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x65, Table.RGB[0]); 7127e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x66, Table.RGB[1]); 7137e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x67, Table.RGB[2]); 7147e6fb56fSmrg if (Table.RGB[3]) 7157e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x27, Table.RGB[3]); 7167e6fb56fSmrg if (Table.RGB[4]) 7177e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x2B, Table.RGB[4]); 7187e6fb56fSmrg if (Table.RGB[5]) 7197e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x2C, Table.RGB[5]); 7207e6fb56fSmrg if (pBIOSInfo->TVEncoder == VIA_VT1625) { 7217e6fb56fSmrg if (pBIOSInfo->TVType < TVTYPE_480P) { 7227e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x12); 7237e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x23, 0x7E); 7247e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4A, 0x85); 7257e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4B, 0x0A); 7267e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4E, 0x00); 7277e6fb56fSmrg } else { 7287e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x12); 7297e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4A, 0x85); 7307e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4B, 0x0A); 7317e6fb56fSmrg } 7327e6fb56fSmrg } 7337e6fb56fSmrg } else if (pBIOSInfo->TVOutput == TVOUTPUT_YCBCR) { 7347e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x03); 7357e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x65, Table.YCbCr[0]); 7367e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x66, Table.YCbCr[1]); 7377e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x67, Table.YCbCr[2]); 7387e6fb56fSmrg if (pBIOSInfo->TVEncoder == VIA_VT1625) { 7397e6fb56fSmrg if (pBIOSInfo->TVType < TVTYPE_480P) { 7407e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x23, 0x7E); 7417e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4E, 0x00); 7427e6fb56fSmrg } 7437e6fb56fSmrg } 7447e6fb56fSmrg } 7457e6fb56fSmrg 7467e6fb56fSmrg /* Configure flicker filter. */ 7477e6fb56fSmrg xf86I2CReadByte(pBIOSInfo->TVI2CDev, 0x03, &save); 7487e6fb56fSmrg save &= 0xFC; 7497e6fb56fSmrg if (pBIOSInfo->TVDeflicker == 1) 7507e6fb56fSmrg save |= 0x01; 7517e6fb56fSmrg else if (pBIOSInfo->TVDeflicker == 2) 7527e6fb56fSmrg save |= 0x02; 7537e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x03, save); 7547e6fb56fSmrg} 7557e6fb56fSmrg 7567e6fb56fSmrg/* 7577e6fb56fSmrg * Also suited for VT1622A, VT1623, VT1625. 7587e6fb56fSmrg */ 7597e6fb56fSmrgstatic void 76090b17f1bSmrgVT1622ModeCrtc(xf86CrtcPtr crtc, DisplayModePtr mode) 7617e6fb56fSmrg{ 76290b17f1bSmrg ScrnInfoPtr pScrn = crtc->scrn; 76390b17f1bSmrg vgaHWPtr hwp = VGAHWPTR(pScrn); 76490b17f1bSmrg VIAPtr pVia = VIAPTR(pScrn); 76590b17f1bSmrg VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 76690b17f1bSmrg struct VT162XTableRec Table; 7677e6fb56fSmrg 7687e6fb56fSmrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622ModeCrtc\n")); 7697e6fb56fSmrg 7707e6fb56fSmrg if (pBIOSInfo->TVEncoder == VIA_VT1622) 7717e6fb56fSmrg Table = VT1622Table[VT1622ModeIndex(pScrn, mode)]; 7727e6fb56fSmrg else if (pBIOSInfo->TVEncoder == VIA_VT1625) 7737e6fb56fSmrg Table = VT1625Table[VT1622ModeIndex(pScrn, mode)]; 7747e6fb56fSmrg else /* VT1622A/VT1623 */ 7757e6fb56fSmrg Table = VT1623Table[VT1622ModeIndex(pScrn, mode)]; 7767e6fb56fSmrg 7777e6fb56fSmrg hwp->writeCrtc(hwp, 0x6A, 0x00); 7787e6fb56fSmrg hwp->writeCrtc(hwp, 0x6B, 0x00); 7797e6fb56fSmrg hwp->writeCrtc(hwp, 0x6C, 0x00); 7807e6fb56fSmrg 7817e6fb56fSmrg if (pVia->IsSecondary) { 7827e6fb56fSmrg hwp->writeCrtc(hwp, 0x6C, Table.SecondaryCR6C); 7837e6fb56fSmrg 7847e6fb56fSmrg ViaCrtcMask(hwp, 0x6A, 0x80, 0x80); 7857e6fb56fSmrg ViaCrtcMask(hwp, 0x6C, 0x80, 0x80); 7867e6fb56fSmrg 7877e6fb56fSmrg /* CLE266Ax use 2x XCLK. */ 7887e6fb56fSmrg if ((pVia->Chipset == VIA_CLE266) && CLE266_REV_IS_AX(pVia->ChipRev)) { 7897e6fb56fSmrg ViaCrtcMask(hwp, 0x6B, 0x20, 0x20); 7907e6fb56fSmrg 7917e6fb56fSmrg /* Fix TV clock polarity for CLE266A2. */ 7927e6fb56fSmrg if (pVia->ChipRev == 0x02) 7937e6fb56fSmrg ViaCrtcMask(hwp, 0x6C, 0x1C, 0x1C); 7947e6fb56fSmrg } 7957e6fb56fSmrg 7967e6fb56fSmrg /* Disable LCD scaling. */ 7977e6fb56fSmrg if (!pVia->SAMM || pVia->FirstInit) 7987e6fb56fSmrg hwp->writeCrtc(hwp, 0x79, 0x00); 7997e6fb56fSmrg 8007e6fb56fSmrg } else { 8017e6fb56fSmrg if ((pVia->Chipset == VIA_CLE266) && CLE266_REV_IS_AX(pVia->ChipRev)) { 8027e6fb56fSmrg ViaCrtcMask(hwp, 0x6B, 0x80, 0x80); 8037e6fb56fSmrg 8047e6fb56fSmrg /* Fix TV clock polarity for CLE266A2. */ 8057e6fb56fSmrg if (pVia->ChipRev == 0x02) 8067e6fb56fSmrg hwp->writeCrtc(hwp, 0x6C, Table.PrimaryCR6C); 8077e6fb56fSmrg } 8087e6fb56fSmrg } 8097e6fb56fSmrg pBIOSInfo->ClockExternal = TRUE; 8107e6fb56fSmrg ViaCrtcMask(hwp, 0x6A, 0x40, 0x40); 81190b17f1bSmrg ViaSetTVClockSource(crtc); 8127e6fb56fSmrg} 8137e6fb56fSmrg 8147e6fb56fSmrg 8157e6fb56fSmrgstatic void 8167e6fb56fSmrgVT1621Power(ScrnInfoPtr pScrn, Bool On) 8177e6fb56fSmrg{ 8187e6fb56fSmrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 8197e6fb56fSmrg 8207e6fb56fSmrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621Power\n")); 8217e6fb56fSmrg 8227e6fb56fSmrg if (On) 8237e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00); 8247e6fb56fSmrg else 8257e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x03); 8267e6fb56fSmrg} 8277e6fb56fSmrg 8287e6fb56fSmrgstatic void 8297e6fb56fSmrgVT1622Power(ScrnInfoPtr pScrn, Bool On) 8307e6fb56fSmrg{ 8317e6fb56fSmrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 8327e6fb56fSmrg 8337e6fb56fSmrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622Power\n")); 8347e6fb56fSmrg 8357e6fb56fSmrg if (On) 8367e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00); 8377e6fb56fSmrg else 8387e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x0F); 8397e6fb56fSmrg} 8407e6fb56fSmrg 8417e6fb56fSmrgstatic void 8427e6fb56fSmrgVT1625Power(ScrnInfoPtr pScrn, Bool On) 8437e6fb56fSmrg{ 8447e6fb56fSmrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 8457e6fb56fSmrg 8467e6fb56fSmrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1625Power\n")); 8477e6fb56fSmrg 8487e6fb56fSmrg if (On) 8497e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00); 8507e6fb56fSmrg else 8517e6fb56fSmrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x3F); 8527e6fb56fSmrg} 8537e6fb56fSmrg 8547e6fb56fSmrg 8557e6fb56fSmrgvoid 8567e6fb56fSmrgViaVT162xInit(ScrnInfoPtr pScrn) 8577e6fb56fSmrg{ 8587e6fb56fSmrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 8597e6fb56fSmrg 8607e6fb56fSmrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaVT162xInit\n")); 8617e6fb56fSmrg 8627e6fb56fSmrg switch (pBIOSInfo->TVEncoder) { 8637e6fb56fSmrg case VIA_VT1621: 8647e6fb56fSmrg pBIOSInfo->TVSave = VT162xSave; 8657e6fb56fSmrg pBIOSInfo->TVRestore = VT162xRestore; 8667e6fb56fSmrg pBIOSInfo->TVDACSense = VT1621DACSense; 8677e6fb56fSmrg pBIOSInfo->TVModeValid = VT1621ModeValid; 8687e6fb56fSmrg pBIOSInfo->TVModeI2C = VT1621ModeI2C; 8697e6fb56fSmrg pBIOSInfo->TVModeCrtc = VT1621ModeCrtc; 8707e6fb56fSmrg pBIOSInfo->TVPower = VT1621Power; 8717e6fb56fSmrg pBIOSInfo->TVModes = VT1621Modes; 87290b17f1bSmrg pBIOSInfo->TVNumModes = sizeof(VT1621Modes) / sizeof(DisplayModeRec); 8737e6fb56fSmrg pBIOSInfo->TVPrintRegs = VT162xPrintRegs; 8747e6fb56fSmrg pBIOSInfo->TVNumRegs = 0x68; 8757e6fb56fSmrg break; 8767e6fb56fSmrg case VIA_VT1622: 8777e6fb56fSmrg pBIOSInfo->TVSave = VT162xSave; 8787e6fb56fSmrg pBIOSInfo->TVRestore = VT162xRestore; 8797e6fb56fSmrg pBIOSInfo->TVDACSense = VT1622DACSense; 8807e6fb56fSmrg pBIOSInfo->TVModeValid = VT1622ModeValid; 8817e6fb56fSmrg pBIOSInfo->TVModeI2C = VT1622ModeI2C; 8827e6fb56fSmrg pBIOSInfo->TVModeCrtc = VT1622ModeCrtc; 8837e6fb56fSmrg pBIOSInfo->TVPower = VT1622Power; 8847e6fb56fSmrg pBIOSInfo->TVModes = VT1622Modes; 88590b17f1bSmrg pBIOSInfo->TVNumModes = sizeof(VT1622Modes) / sizeof(DisplayModeRec); 8867e6fb56fSmrg pBIOSInfo->TVPrintRegs = VT162xPrintRegs; 8877e6fb56fSmrg pBIOSInfo->TVNumRegs = 0x68; 8887e6fb56fSmrg break; 8897e6fb56fSmrg case VIA_VT1623: 8907e6fb56fSmrg pBIOSInfo->TVSave = VT162xSave; 8917e6fb56fSmrg pBIOSInfo->TVRestore = VT162xRestore; 8927e6fb56fSmrg pBIOSInfo->TVDACSense = VT1622DACSense; 8937e6fb56fSmrg pBIOSInfo->TVModeValid = VT1622ModeValid; 8947e6fb56fSmrg pBIOSInfo->TVModeI2C = VT1622ModeI2C; 8957e6fb56fSmrg pBIOSInfo->TVModeCrtc = VT1622ModeCrtc; 8967e6fb56fSmrg pBIOSInfo->TVPower = VT1622Power; 8977e6fb56fSmrg pBIOSInfo->TVModes = VT1623Modes; 89890b17f1bSmrg pBIOSInfo->TVNumModes = sizeof(VT1623Modes) / sizeof(DisplayModeRec); 8997e6fb56fSmrg pBIOSInfo->TVPrintRegs = VT162xPrintRegs; 9007e6fb56fSmrg pBIOSInfo->TVNumRegs = 0x6C; 9017e6fb56fSmrg break; 9027e6fb56fSmrg case VIA_VT1625: 9037e6fb56fSmrg pBIOSInfo->TVSave = VT162xSave; 9047e6fb56fSmrg pBIOSInfo->TVRestore = VT162xRestore; 9057e6fb56fSmrg pBIOSInfo->TVDACSense = VT1625DACSense; 9067e6fb56fSmrg pBIOSInfo->TVModeValid = VT1625ModeValid; 9077e6fb56fSmrg pBIOSInfo->TVModeI2C = VT1622ModeI2C; 9087e6fb56fSmrg pBIOSInfo->TVModeCrtc = VT1622ModeCrtc; 9097e6fb56fSmrg pBIOSInfo->TVPower = VT1625Power; 9107e6fb56fSmrg pBIOSInfo->TVModes = VT1625Modes; 91190b17f1bSmrg pBIOSInfo->TVNumModes = sizeof(VT1625Modes) / sizeof(DisplayModeRec); 9127e6fb56fSmrg pBIOSInfo->TVPrintRegs = VT162xPrintRegs; 91390b17f1bSmrg pBIOSInfo->TVNumRegs = 0x82; 9147e6fb56fSmrg break; 9157e6fb56fSmrg default: 9167e6fb56fSmrg break; 9177e6fb56fSmrg } 9187e6fb56fSmrg} 919