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