via_tv.c revision 983b4bf2
1983b4bf2Smrg/* 2983b4bf2Smrg * Copyright 2005-2016 The OpenChrome Project 3983b4bf2Smrg * [https://www.freedesktop.org/wiki/Openchrome] 4983b4bf2Smrg * Copyright 2004-2005 The Unichrome Project [unichrome.sf.net] 5983b4bf2Smrg * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. 6983b4bf2Smrg * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. 7983b4bf2Smrg * 8983b4bf2Smrg * Permission is hereby granted, free of charge, to any person obtaining a 9983b4bf2Smrg * copy of this software and associated documentation files (the "Software"), 10983b4bf2Smrg * to deal in the Software without restriction, including without limitation 11983b4bf2Smrg * the rights to use, copy, modify, merge, publish, distribute, sub license, 12983b4bf2Smrg * and/or sell copies of the Software, and to permit persons to whom the 13983b4bf2Smrg * Software is furnished to do so, subject to the following conditions: 14983b4bf2Smrg * 15983b4bf2Smrg * The above copyright notice and this permission notice (including the 16983b4bf2Smrg * next paragraph) shall be included in all copies or substantial portions 17983b4bf2Smrg * of the Software. 18983b4bf2Smrg * 19983b4bf2Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20983b4bf2Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21983b4bf2Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 22983b4bf2Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23983b4bf2Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24983b4bf2Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25983b4bf2Smrg * DEALINGS IN THE SOFTWARE. 26983b4bf2Smrg */ 27983b4bf2Smrg 28983b4bf2Smrg/* 29983b4bf2Smrg * via_tv.c 30983b4bf2Smrg * 31983b4bf2Smrg * Handles the initialization and management of TV output related 32983b4bf2Smrg * resources. 33983b4bf2Smrg * 34983b4bf2Smrg */ 35983b4bf2Smrg 36983b4bf2Smrg#ifdef HAVE_CONFIG_H 37983b4bf2Smrg#include "config.h" 38983b4bf2Smrg#endif 39983b4bf2Smrg 40983b4bf2Smrg#include "via_driver.h" 41983b4bf2Smrg#include <unistd.h> 42983b4bf2Smrg 43983b4bf2Smrgstatic void 44983b4bf2SmrgviaTVSetDisplaySource(ScrnInfoPtr pScrn, CARD8 displaySource) 45983b4bf2Smrg{ 46983b4bf2Smrg 47983b4bf2Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 48983b4bf2Smrg VIAPtr pVia = VIAPTR(pScrn); 49983b4bf2Smrg CARD8 sr12, sr13, sr5a; 50983b4bf2Smrg 51983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 52983b4bf2Smrg "Entered viaTVSetDisplaySource.\n")); 53983b4bf2Smrg 54983b4bf2Smrg if ((pVia->Chipset == VIA_CX700) 55983b4bf2Smrg || (pVia->Chipset == VIA_VX800) 56983b4bf2Smrg || (pVia->Chipset == VIA_VX855) 57983b4bf2Smrg || (pVia->Chipset == VIA_VX900)) { 58983b4bf2Smrg 59983b4bf2Smrg sr5a = hwp->readSeq(hwp, 0x5A); 60983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 61983b4bf2Smrg "SR5A: 0x%02X\n", sr5a)); 62983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 63983b4bf2Smrg "Setting 3C5.5A[0] to 0.\n")); 64983b4bf2Smrg ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01); 65983b4bf2Smrg } 66983b4bf2Smrg 67983b4bf2Smrg sr12 = hwp->readSeq(hwp, 0x12); 68983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 69983b4bf2Smrg "SR12: 0x%02X\n", sr12)); 70983b4bf2Smrg sr13 = hwp->readSeq(hwp, 0x13); 71983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 72983b4bf2Smrg "SR13: 0x%02X\n", sr13)); 73983b4bf2Smrg switch (pVia->Chipset) { 74983b4bf2Smrg case VIA_CLE266: 75983b4bf2Smrg /* 3C5.12[5] - FPD18 pin strapping 76983b4bf2Smrg * 0: DIP0 (Digital Interface Port 0) is used by 77983b4bf2Smrg * a TMDS transmitter (DVI) 78983b4bf2Smrg * 1: DIP0 (Digital Interface Port 0) is used by 79983b4bf2Smrg * a TV encoder */ 80983b4bf2Smrg if (sr12 & 0x20) { 81983b4bf2Smrg viaDIP0SetDisplaySource(pScrn, displaySource); 82983b4bf2Smrg } else { 83983b4bf2Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 84983b4bf2Smrg "DIP0 was not set up for " 85983b4bf2Smrg "an external TV encoder use.\n"); 86983b4bf2Smrg } 87983b4bf2Smrg 88983b4bf2Smrg break; 89983b4bf2Smrg case VIA_KM400: 90983b4bf2Smrg case VIA_K8M800: 91983b4bf2Smrg case VIA_PM800: 92983b4bf2Smrg case VIA_P4M800PRO: 93983b4bf2Smrg /* 3C5.13[3] - DVP0D8 pin strapping 94983b4bf2Smrg * 0: AGP pins are used for AGP 95983b4bf2Smrg * 1: AGP pins are used by FPDP 96983b4bf2Smrg * (Flat Panel Display Port) 97983b4bf2Smrg * 3C5.12[6] - DVP0D6 pin strapping 98983b4bf2Smrg * 0: Disable DVP0 (Digital Video Port 0) 99983b4bf2Smrg * 1: Enable DVP0 (Digital Video Port 0) 100983b4bf2Smrg * 3C5.12[5] - DVP0D5 pin strapping 101983b4bf2Smrg * 0: DVP0 is used by a TMDS transmitter (DVI) 102983b4bf2Smrg * 1: DVP0 is used by a TV encoder 103983b4bf2Smrg * 3C5.12[4] - DVP0D4 pin strapping 104983b4bf2Smrg * 0: Dual 12-bit FPDP (Flat Panel Display Port) 105983b4bf2Smrg * 1: 24-bit FPDP (Flat Panel Display Port) */ 106983b4bf2Smrg if ((sr12 & 0x40) && (sr12 & 0x20)) { 107983b4bf2Smrg viaDVP0SetDisplaySource(pScrn, displaySource); 108983b4bf2Smrg } else if ((sr13 & 0x08) && (!(sr12 & 0x10))) { 109983b4bf2Smrg viaDFPLowSetDisplaySource(pScrn, displaySource); 110983b4bf2Smrg } else if (sr13 & 0x08) { 111983b4bf2Smrg viaDVP1SetDisplaySource(pScrn, displaySource); 112983b4bf2Smrg } else { 113983b4bf2Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 114983b4bf2Smrg "None of the external ports were set up for " 115983b4bf2Smrg "external TV encoder use.\n"); 116983b4bf2Smrg } 117983b4bf2Smrg 118983b4bf2Smrg break; 119983b4bf2Smrg case VIA_P4M890: 120983b4bf2Smrg case VIA_K8M890: 121983b4bf2Smrg case VIA_P4M900: 122983b4bf2Smrg /* 3C5.12[6] - FPD6 pin strapping 123983b4bf2Smrg * 0: Disable DVP0 (Digital Video Port 0) 124983b4bf2Smrg * 1: Enable DVP0 (Digital Video Port 0) 125983b4bf2Smrg * 3C5.12[5] - FPD5 pin strapping 126983b4bf2Smrg * 0: DVP0 is used by a TMDS transmitter (DVI) 127983b4bf2Smrg * 1: DVP0 is used by a TV encoder 128983b4bf2Smrg * 3C5.12[4] - FPD4 pin strapping 129983b4bf2Smrg * 0: Dual 12-bit FPDP (Flat Panel Display Port) 130983b4bf2Smrg * 1: 24-bit FPDP (Flat Panel Display Port) */ 131983b4bf2Smrg if ((sr12 & 0x40) && (sr12 & 0x20) && (!(sr12 & 0x10))) { 132983b4bf2Smrg viaDVP0SetDisplaySource(pScrn, displaySource); 133983b4bf2Smrg } else { 134983b4bf2Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 135983b4bf2Smrg "Unrecognized external TV encoder use.\n" 136983b4bf2Smrg "Contact the developer for assistance.\n"); 137983b4bf2Smrg } 138983b4bf2Smrg 139983b4bf2Smrg break; 140983b4bf2Smrg case VIA_CX700: 141983b4bf2Smrg case VIA_VX800: 142983b4bf2Smrg case VIA_VX855: 143983b4bf2Smrg case VIA_VX900: 144983b4bf2Smrg /* 3C5.13[6] - DVP1 DVP / capture port selection 145983b4bf2Smrg * 0: DVP1 is used as a DVP (Digital Video Port) 146983b4bf2Smrg * 1: DVP1 is used as a capture port 147983b4bf2Smrg */ 148983b4bf2Smrg if (!(sr13 & 0x40)) { 149983b4bf2Smrg viaDVP1SetDisplaySource(pScrn, displaySource); 150983b4bf2Smrg } else { 151983b4bf2Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 152983b4bf2Smrg "DVP1 is not set up for external TV " 153983b4bf2Smrg "encoder use.\n"); 154983b4bf2Smrg } 155983b4bf2Smrg 156983b4bf2Smrg break; 157983b4bf2Smrg default: 158983b4bf2Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 159983b4bf2Smrg "Unrecognized IGP for " 160983b4bf2Smrg "an external TV encoder use.\n"); 161983b4bf2Smrg break; 162983b4bf2Smrg } 163983b4bf2Smrg 164983b4bf2Smrg if ((pVia->Chipset == VIA_CX700) 165983b4bf2Smrg || (pVia->Chipset == VIA_VX800) 166983b4bf2Smrg || (pVia->Chipset == VIA_VX855) 167983b4bf2Smrg || (pVia->Chipset == VIA_VX900)) { 168983b4bf2Smrg 169983b4bf2Smrg hwp->writeSeq(hwp, 0x5A, sr5a); 170983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 171983b4bf2Smrg "Restoring 3C5.5A[0].\n")); 172983b4bf2Smrg } 173983b4bf2Smrg 174983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 175983b4bf2Smrg "Exiting viaTVSetDisplaySource.\n")); 176983b4bf2Smrg} 177983b4bf2Smrg 178983b4bf2Smrgstatic void 179983b4bf2SmrgviaTVEnableIOPads(ScrnInfoPtr pScrn, CARD8 ioPadState) 180983b4bf2Smrg{ 181983b4bf2Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 182983b4bf2Smrg VIAPtr pVia = VIAPTR(pScrn); 183983b4bf2Smrg CARD8 sr12, sr13, sr5a; 184983b4bf2Smrg 185983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 186983b4bf2Smrg "Entered viaTVEnableIOPads.\n")); 187983b4bf2Smrg 188983b4bf2Smrg if ((pVia->Chipset == VIA_CX700) 189983b4bf2Smrg || (pVia->Chipset == VIA_VX800) 190983b4bf2Smrg || (pVia->Chipset == VIA_VX855) 191983b4bf2Smrg || (pVia->Chipset == VIA_VX900)) { 192983b4bf2Smrg 193983b4bf2Smrg sr5a = hwp->readSeq(hwp, 0x5A); 194983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 195983b4bf2Smrg "SR5A: 0x%02X\n", sr5a)); 196983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 197983b4bf2Smrg "Setting 3C5.5A[0] to 0.\n")); 198983b4bf2Smrg ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01); 199983b4bf2Smrg } 200983b4bf2Smrg 201983b4bf2Smrg sr12 = hwp->readSeq(hwp, 0x12); 202983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 203983b4bf2Smrg "SR12: 0x%02X\n", sr12)); 204983b4bf2Smrg sr13 = hwp->readSeq(hwp, 0x13); 205983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 206983b4bf2Smrg "SR13: 0x%02X\n", sr13)); 207983b4bf2Smrg switch (pVia->Chipset) { 208983b4bf2Smrg case VIA_CLE266: 209983b4bf2Smrg /* 3C5.12[5] - FPD18 pin strapping 210983b4bf2Smrg * 0: DIP0 (Digital Interface Port 0) is used by 211983b4bf2Smrg * a TMDS transmitter (DVI) 212983b4bf2Smrg * 1: DIP0 (Digital Interface Port 0) is used by 213983b4bf2Smrg * a TV encoder */ 214983b4bf2Smrg if (sr12 & 0x20) { 215983b4bf2Smrg viaDIP0EnableIOPads(pScrn, ioPadState); 216983b4bf2Smrg } else { 217983b4bf2Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 218983b4bf2Smrg "DIP0 is not set up for " 219983b4bf2Smrg "an external TV encoder use.\n"); 220983b4bf2Smrg } 221983b4bf2Smrg 222983b4bf2Smrg break; 223983b4bf2Smrg case VIA_KM400: 224983b4bf2Smrg case VIA_K8M800: 225983b4bf2Smrg case VIA_PM800: 226983b4bf2Smrg case VIA_P4M800PRO: 227983b4bf2Smrg /* 3C5.13[3] - DVP0D8 pin strapping 228983b4bf2Smrg * 0: AGP pins are used for AGP 229983b4bf2Smrg * 1: AGP pins are used by FPDP 230983b4bf2Smrg * (Flat Panel Display Port) 231983b4bf2Smrg * 3C5.12[6] - DVP0D6 pin strapping 232983b4bf2Smrg * 0: Disable DVP0 (Digital Video Port 0) 233983b4bf2Smrg * 1: Enable DVP0 (Digital Video Port 0) 234983b4bf2Smrg * 3C5.12[5] - DVP0D5 pin strapping 235983b4bf2Smrg * 0: DVP0 is used by a TMDS transmitter (DVI) 236983b4bf2Smrg * 1: DVP0 is used by a TV encoder 237983b4bf2Smrg * 3C5.12[4] - DVP0D4 pin strapping 238983b4bf2Smrg * 0: Dual 12-bit FPDP (Flat Panel Display Port) 239983b4bf2Smrg * 1: 24-bit FPDP (Flat Panel Display Port) */ 240983b4bf2Smrg if ((sr12 & 0x40) && (sr12 & 0x20)) { 241983b4bf2Smrg viaDVP0EnableIOPads(pScrn, ioPadState); 242983b4bf2Smrg } else if ((sr13 & 0x08) && (!(sr12 & 0x10))) { 243983b4bf2Smrg viaDFPLowEnableIOPads(pScrn, ioPadState); 244983b4bf2Smrg } else if (sr13 & 0x08) { 245983b4bf2Smrg viaDVP1EnableIOPads(pScrn, ioPadState); 246983b4bf2Smrg } else { 247983b4bf2Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 248983b4bf2Smrg "None of the external ports were set up for " 249983b4bf2Smrg "external TV encoder use.\n"); 250983b4bf2Smrg } 251983b4bf2Smrg 252983b4bf2Smrg break; 253983b4bf2Smrg case VIA_P4M890: 254983b4bf2Smrg case VIA_K8M890: 255983b4bf2Smrg case VIA_P4M900: 256983b4bf2Smrg /* 3C5.12[6] - FPD6 pin strapping 257983b4bf2Smrg * 0: Disable DVP0 (Digital Video Port 0) 258983b4bf2Smrg * 1: Enable DVP0 (Digital Video Port 0) 259983b4bf2Smrg * 3C5.12[5] - FPD5 pin strapping 260983b4bf2Smrg * 0: DVP0 is used by a TMDS transmitter (DVI) 261983b4bf2Smrg * 1: DVP0 is used by a TV encoder 262983b4bf2Smrg * 3C5.12[4] - FPD4 pin strapping 263983b4bf2Smrg * 0: Dual 12-bit FPDP (Flat Panel Display Port) 264983b4bf2Smrg * 1: 24-bit FPDP (Flat Panel Display Port) */ 265983b4bf2Smrg if ((sr12 & 0x40) && (sr12 & 0x20) && (!(sr12 & 0x10))) { 266983b4bf2Smrg viaDVP0EnableIOPads(pScrn, ioPadState); 267983b4bf2Smrg } else { 268983b4bf2Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 269983b4bf2Smrg "Unrecognized external TV encoder use.\n" 270983b4bf2Smrg "Contact the developer for assistance.\n"); 271983b4bf2Smrg } 272983b4bf2Smrg 273983b4bf2Smrg break; 274983b4bf2Smrg case VIA_CX700: 275983b4bf2Smrg case VIA_VX800: 276983b4bf2Smrg case VIA_VX855: 277983b4bf2Smrg case VIA_VX900: 278983b4bf2Smrg /* 3C5.13[6] - DVP1 DVP / capture port selection 279983b4bf2Smrg * 0: DVP1 is used as a DVP (Digital Video Port) 280983b4bf2Smrg * 1: DVP1 is used as a capture port 281983b4bf2Smrg */ 282983b4bf2Smrg if (!(sr13 & 0x40)) { 283983b4bf2Smrg viaDVP1EnableIOPads(pScrn, ioPadState); 284983b4bf2Smrg } else { 285983b4bf2Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 286983b4bf2Smrg "DVP1 is not set up for external TV " 287983b4bf2Smrg "encoder use.\n"); 288983b4bf2Smrg } 289983b4bf2Smrg 290983b4bf2Smrg break; 291983b4bf2Smrg default: 292983b4bf2Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 293983b4bf2Smrg "Unrecognized IGP for " 294983b4bf2Smrg "an external TV encoder use.\n"); 295983b4bf2Smrg break; 296983b4bf2Smrg } 297983b4bf2Smrg 298983b4bf2Smrg if ((pVia->Chipset == VIA_CX700) 299983b4bf2Smrg || (pVia->Chipset == VIA_VX800) 300983b4bf2Smrg || (pVia->Chipset == VIA_VX855) 301983b4bf2Smrg || (pVia->Chipset == VIA_VX900)) { 302983b4bf2Smrg 303983b4bf2Smrg hwp->writeSeq(hwp, 0x5A, sr5a); 304983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 305983b4bf2Smrg "Restoring 3C5.5A[0].\n")); 306983b4bf2Smrg } 307983b4bf2Smrg 308983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 309983b4bf2Smrg "Exiting viaTVEnableIOPads.\n")); 310983b4bf2Smrg} 311983b4bf2Smrg 312983b4bf2Smrgstatic void 313983b4bf2SmrgviaTVSetClockDriveStrength(ScrnInfoPtr pScrn, CARD8 clockDriveStrength) 314983b4bf2Smrg{ 315983b4bf2Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 316983b4bf2Smrg VIAPtr pVia = VIAPTR(pScrn); 317983b4bf2Smrg CARD8 sr12, sr13, sr5a; 318983b4bf2Smrg 319983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 320983b4bf2Smrg "Entered viaTVSetClockDriveStrength.\n")); 321983b4bf2Smrg 322983b4bf2Smrg if ((pVia->Chipset == VIA_CX700) 323983b4bf2Smrg || (pVia->Chipset == VIA_VX800) 324983b4bf2Smrg || (pVia->Chipset == VIA_VX855) 325983b4bf2Smrg || (pVia->Chipset == VIA_VX900)) { 326983b4bf2Smrg 327983b4bf2Smrg sr5a = hwp->readSeq(hwp, 0x5A); 328983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 329983b4bf2Smrg "SR5A: 0x%02X\n", sr5a)); 330983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 331983b4bf2Smrg "Setting 3C5.5A[0] to 0.\n")); 332983b4bf2Smrg ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01); 333983b4bf2Smrg } 334983b4bf2Smrg 335983b4bf2Smrg sr12 = hwp->readSeq(hwp, 0x12); 336983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 337983b4bf2Smrg "SR12: 0x%02X\n", sr12)); 338983b4bf2Smrg sr13 = hwp->readSeq(hwp, 0x13); 339983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 340983b4bf2Smrg "SR13: 0x%02X\n", sr13)); 341983b4bf2Smrg switch (pVia->Chipset) { 342983b4bf2Smrg case VIA_CLE266: 343983b4bf2Smrg /* 3C5.12[5] - FPD18 pin strapping 344983b4bf2Smrg * 0: DIP0 (Digital Interface Port 0) is used by 345983b4bf2Smrg * a TMDS transmitter (DVI) 346983b4bf2Smrg * 1: DIP0 (Digital Interface Port 0) is used by 347983b4bf2Smrg * a TV encoder */ 348983b4bf2Smrg if (sr12 & 0x20) { 349983b4bf2Smrg viaDIP0SetClockDriveStrength(pScrn, clockDriveStrength); 350983b4bf2Smrg } 351983b4bf2Smrg 352983b4bf2Smrg break; 353983b4bf2Smrg case VIA_KM400: 354983b4bf2Smrg case VIA_K8M800: 355983b4bf2Smrg case VIA_PM800: 356983b4bf2Smrg case VIA_P4M800PRO: 357983b4bf2Smrg /* 3C5.13[3] - DVP0D8 pin strapping 358983b4bf2Smrg * 0: AGP pins are used for AGP 359983b4bf2Smrg * 1: AGP pins are used by FPDP 360983b4bf2Smrg * (Flat Panel Display Port) 361983b4bf2Smrg * 3C5.12[6] - DVP0D6 pin strapping 362983b4bf2Smrg * 0: Disable DVP0 (Digital Video Port 0) 363983b4bf2Smrg * 1: Enable DVP0 (Digital Video Port 0) 364983b4bf2Smrg * 3C5.12[5] - DVP0D5 pin strapping 365983b4bf2Smrg * 0: DVP0 is used by a TMDS transmitter (DVI) 366983b4bf2Smrg * 1: DVP0 is used by a TV encoder 367983b4bf2Smrg * 3C5.12[4] - DVP0D4 pin strapping 368983b4bf2Smrg * 0: Dual 12-bit FPDP (Flat Panel Display Port) 369983b4bf2Smrg * 1: 24-bit FPDP (Flat Panel Display Port) */ 370983b4bf2Smrg if ((sr12 & 0x40) && (sr12 & 0x20)) { 371983b4bf2Smrg viaDVP0SetClockDriveStrength(pScrn, clockDriveStrength); 372983b4bf2Smrg } else if ((sr13 & 0x08) && (!(sr12 & 0x10))) { 373983b4bf2Smrg } else if (sr13 & 0x08) { 374983b4bf2Smrg viaDVP1SetClockDriveStrength(pScrn, clockDriveStrength); 375983b4bf2Smrg } 376983b4bf2Smrg 377983b4bf2Smrg break; 378983b4bf2Smrg case VIA_P4M890: 379983b4bf2Smrg case VIA_K8M890: 380983b4bf2Smrg case VIA_P4M900: 381983b4bf2Smrg /* 3C5.12[6] - FPD6 pin strapping 382983b4bf2Smrg * 0: Disable DVP0 (Digital Video Port 0) 383983b4bf2Smrg * 1: Enable DVP0 (Digital Video Port 0) 384983b4bf2Smrg * 3C5.12[5] - FPD5 pin strapping 385983b4bf2Smrg * 0: DVP0 is used by a TMDS transmitter (DVI) 386983b4bf2Smrg * 1: DVP0 is used by a TV encoder 387983b4bf2Smrg * 3C5.12[4] - FPD4 pin strapping 388983b4bf2Smrg * 0: Dual 12-bit FPDP (Flat Panel Display Port) 389983b4bf2Smrg * 1: 24-bit FPDP (Flat Panel Display Port) */ 390983b4bf2Smrg if ((sr12 & 0x40) && (sr12 & 0x20) && (!(sr12 & 0x10))) { 391983b4bf2Smrg viaDVP0SetClockDriveStrength(pScrn, clockDriveStrength); 392983b4bf2Smrg } 393983b4bf2Smrg 394983b4bf2Smrg break; 395983b4bf2Smrg case VIA_CX700: 396983b4bf2Smrg case VIA_VX800: 397983b4bf2Smrg case VIA_VX855: 398983b4bf2Smrg case VIA_VX900: 399983b4bf2Smrg /* 3C5.13[6] - DVP1 DVP / capture port selection 400983b4bf2Smrg * 0: DVP1 is used as a DVP (Digital Video Port) 401983b4bf2Smrg * 1: DVP1 is used as a capture port */ 402983b4bf2Smrg if (!(sr13 & 0x40)) { 403983b4bf2Smrg viaDVP1SetClockDriveStrength(pScrn, clockDriveStrength); 404983b4bf2Smrg } 405983b4bf2Smrg 406983b4bf2Smrg break; 407983b4bf2Smrg default: 408983b4bf2Smrg break; 409983b4bf2Smrg } 410983b4bf2Smrg 411983b4bf2Smrg if ((pVia->Chipset == VIA_CX700) 412983b4bf2Smrg || (pVia->Chipset == VIA_VX800) 413983b4bf2Smrg || (pVia->Chipset == VIA_VX855) 414983b4bf2Smrg || (pVia->Chipset == VIA_VX900)) { 415983b4bf2Smrg 416983b4bf2Smrg hwp->writeSeq(hwp, 0x5A, sr5a); 417983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 418983b4bf2Smrg "Restoring 3C5.5A[0].\n")); 419983b4bf2Smrg } 420983b4bf2Smrg 421983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 422983b4bf2Smrg "Exiting viaTVSetClockDriveStrength.\n")); 423983b4bf2Smrg} 424983b4bf2Smrg 425983b4bf2Smrgstatic void 426983b4bf2SmrgviaTVSetDataDriveStrength(ScrnInfoPtr pScrn, CARD8 dataDriveStrength) 427983b4bf2Smrg{ 428983b4bf2Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 429983b4bf2Smrg VIAPtr pVia = VIAPTR(pScrn); 430983b4bf2Smrg CARD8 sr12, sr13, sr5a; 431983b4bf2Smrg 432983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 433983b4bf2Smrg "Entered viaTVSetDataDriveStrength.\n")); 434983b4bf2Smrg 435983b4bf2Smrg if ((pVia->Chipset == VIA_CX700) 436983b4bf2Smrg || (pVia->Chipset == VIA_VX800) 437983b4bf2Smrg || (pVia->Chipset == VIA_VX855) 438983b4bf2Smrg || (pVia->Chipset == VIA_VX900)) { 439983b4bf2Smrg 440983b4bf2Smrg sr5a = hwp->readSeq(hwp, 0x5A); 441983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 442983b4bf2Smrg "SR5A: 0x%02X\n", sr5a)); 443983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 444983b4bf2Smrg "Setting 3C5.5A[0] to 0.\n")); 445983b4bf2Smrg ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01); 446983b4bf2Smrg } 447983b4bf2Smrg 448983b4bf2Smrg sr12 = hwp->readSeq(hwp, 0x12); 449983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 450983b4bf2Smrg "SR12: 0x%02X\n", sr12)); 451983b4bf2Smrg sr13 = hwp->readSeq(hwp, 0x13); 452983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 453983b4bf2Smrg "SR13: 0x%02X\n", sr13)); 454983b4bf2Smrg switch (pVia->Chipset) { 455983b4bf2Smrg case VIA_CLE266: 456983b4bf2Smrg /* 3C5.12[5] - FPD18 pin strapping 457983b4bf2Smrg * 0: DIP0 (Digital Interface Port 0) is used by 458983b4bf2Smrg * a TMDS transmitter (DVI) 459983b4bf2Smrg * 1: DIP0 (Digital Interface Port 0) is used by 460983b4bf2Smrg * a TV encoder */ 461983b4bf2Smrg if (sr12 & 0x20) { 462983b4bf2Smrg viaDIP0SetDataDriveStrength(pScrn, dataDriveStrength); 463983b4bf2Smrg } 464983b4bf2Smrg 465983b4bf2Smrg break; 466983b4bf2Smrg case VIA_KM400: 467983b4bf2Smrg case VIA_K8M800: 468983b4bf2Smrg case VIA_PM800: 469983b4bf2Smrg case VIA_P4M800PRO: 470983b4bf2Smrg /* 3C5.13[3] - DVP0D8 pin strapping 471983b4bf2Smrg * 0: AGP pins are used for AGP 472983b4bf2Smrg * 1: AGP pins are used by FPDP 473983b4bf2Smrg * (Flat Panel Display Port) 474983b4bf2Smrg * 3C5.12[6] - DVP0D6 pin strapping 475983b4bf2Smrg * 0: Disable DVP0 (Digital Video Port 0) 476983b4bf2Smrg * 1: Enable DVP0 (Digital Video Port 0) 477983b4bf2Smrg * 3C5.12[5] - DVP0D5 pin strapping 478983b4bf2Smrg * 0: DVP0 is used by a TMDS transmitter (DVI) 479983b4bf2Smrg * 1: DVP0 is used by a TV encoder 480983b4bf2Smrg * 3C5.12[4] - DVP0D4 pin strapping 481983b4bf2Smrg * 0: Dual 12-bit FPDP (Flat Panel Display Port) 482983b4bf2Smrg * 1: 24-bit FPDP (Flat Panel Display Port) */ 483983b4bf2Smrg if ((sr12 & 0x40) && (sr12 & 0x20)) { 484983b4bf2Smrg viaDVP0SetDataDriveStrength(pScrn, dataDriveStrength); 485983b4bf2Smrg } else if ((sr13 & 0x08) && (!(sr12 & 0x10))) { 486983b4bf2Smrg } else if (sr13 & 0x08) { 487983b4bf2Smrg viaDVP1SetDataDriveStrength(pScrn, dataDriveStrength); 488983b4bf2Smrg } 489983b4bf2Smrg 490983b4bf2Smrg break; 491983b4bf2Smrg case VIA_P4M890: 492983b4bf2Smrg case VIA_K8M890: 493983b4bf2Smrg case VIA_P4M900: 494983b4bf2Smrg /* 3C5.12[6] - FPD6 pin strapping 495983b4bf2Smrg * 0: Disable DVP0 (Digital Video Port 0) 496983b4bf2Smrg * 1: Enable DVP0 (Digital Video Port 0) 497983b4bf2Smrg * 3C5.12[5] - FPD5 pin strapping 498983b4bf2Smrg * 0: DVP0 is used by a TMDS transmitter (DVI) 499983b4bf2Smrg * 1: DVP0 is used by a TV encoder 500983b4bf2Smrg * 3C5.12[4] - FPD4 pin strapping 501983b4bf2Smrg * 0: Dual 12-bit FPDP (Flat Panel Display Port) 502983b4bf2Smrg * 1: 24-bit FPDP (Flat Panel Display Port) */ 503983b4bf2Smrg if ((sr12 & 0x40) && (sr12 & 0x20) && (!(sr12 & 0x10))) { 504983b4bf2Smrg viaDVP0SetDataDriveStrength(pScrn, dataDriveStrength); 505983b4bf2Smrg } 506983b4bf2Smrg 507983b4bf2Smrg break; 508983b4bf2Smrg case VIA_CX700: 509983b4bf2Smrg case VIA_VX800: 510983b4bf2Smrg case VIA_VX855: 511983b4bf2Smrg case VIA_VX900: 512983b4bf2Smrg /* 3C5.13[6] - DVP1 DVP / capture port selection 513983b4bf2Smrg * 0: DVP1 is used as a DVP (Digital Video Port) 514983b4bf2Smrg * 1: DVP1 is used as a capture port */ 515983b4bf2Smrg if (!(sr13 & 0x40)) { 516983b4bf2Smrg viaDVP1SetDataDriveStrength(pScrn, dataDriveStrength); 517983b4bf2Smrg } 518983b4bf2Smrg 519983b4bf2Smrg break; 520983b4bf2Smrg default: 521983b4bf2Smrg break; 522983b4bf2Smrg } 523983b4bf2Smrg 524983b4bf2Smrg if ((pVia->Chipset == VIA_CX700) 525983b4bf2Smrg || (pVia->Chipset == VIA_VX800) 526983b4bf2Smrg || (pVia->Chipset == VIA_VX855) 527983b4bf2Smrg || (pVia->Chipset == VIA_VX900)) { 528983b4bf2Smrg 529983b4bf2Smrg hwp->writeSeq(hwp, 0x5A, sr5a); 530983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 531983b4bf2Smrg "Restoring 3C5.5A[0].\n")); 532983b4bf2Smrg } 533983b4bf2Smrg 534983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 535983b4bf2Smrg "Exiting viaTVSetDataDriveStrength.\n")); 536983b4bf2Smrg} 537983b4bf2Smrg 538983b4bf2Smrgstatic void 539983b4bf2SmrgViaTVSave(ScrnInfoPtr pScrn) 540983b4bf2Smrg{ 541983b4bf2Smrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 542983b4bf2Smrg 543983b4bf2Smrg if (pBIOSInfo->TVSave) 544983b4bf2Smrg pBIOSInfo->TVSave(pScrn); 545983b4bf2Smrg} 546983b4bf2Smrg 547983b4bf2Smrgstatic void 548983b4bf2SmrgViaTVRestore(ScrnInfoPtr pScrn) 549983b4bf2Smrg{ 550983b4bf2Smrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 551983b4bf2Smrg 552983b4bf2Smrg if (pBIOSInfo->TVRestore) 553983b4bf2Smrg pBIOSInfo->TVRestore(pScrn); 554983b4bf2Smrg} 555983b4bf2Smrg 556983b4bf2Smrgstatic Bool 557983b4bf2SmrgViaTVDACSense(ScrnInfoPtr pScrn) 558983b4bf2Smrg{ 559983b4bf2Smrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 560983b4bf2Smrg 561983b4bf2Smrg if (pBIOSInfo->TVDACSense) 562983b4bf2Smrg return pBIOSInfo->TVDACSense(pScrn); 563983b4bf2Smrg return FALSE; 564983b4bf2Smrg} 565983b4bf2Smrg 566983b4bf2Smrgstatic void 567983b4bf2SmrgViaTVSetMode(xf86CrtcPtr crtc, DisplayModePtr mode) 568983b4bf2Smrg{ 569983b4bf2Smrg ScrnInfoPtr pScrn = crtc->scrn; 570983b4bf2Smrg VIAPtr pVia = VIAPTR(pScrn); 571983b4bf2Smrg VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 572983b4bf2Smrg 573983b4bf2Smrg if (pBIOSInfo->TVModeI2C) 574983b4bf2Smrg pBIOSInfo->TVModeI2C(pScrn, mode); 575983b4bf2Smrg 576983b4bf2Smrg if (pBIOSInfo->TVModeCrtc) 577983b4bf2Smrg pBIOSInfo->TVModeCrtc(crtc, mode); 578983b4bf2Smrg 579983b4bf2Smrg /* TV reset. */ 580983b4bf2Smrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1D, 0x00); 581983b4bf2Smrg xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1D, 0x80); 582983b4bf2Smrg} 583983b4bf2Smrg 584983b4bf2Smrgstatic void 585983b4bf2SmrgViaTVPower(ScrnInfoPtr pScrn, Bool On) 586983b4bf2Smrg{ 587983b4bf2Smrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 588983b4bf2Smrg 589983b4bf2Smrg#ifdef HAVE_DEBUG 590983b4bf2Smrg if (On) 591983b4bf2Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaTVPower: On.\n"); 592983b4bf2Smrg else 593983b4bf2Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaTVPower: Off.\n"); 594983b4bf2Smrg#endif 595983b4bf2Smrg 596983b4bf2Smrg if (pBIOSInfo->TVPower) 597983b4bf2Smrg pBIOSInfo->TVPower(pScrn, On); 598983b4bf2Smrg} 599983b4bf2Smrg 600983b4bf2Smrg#ifdef HAVE_DEBUG 601983b4bf2Smrgvoid 602983b4bf2SmrgViaTVPrintRegs(ScrnInfoPtr pScrn) 603983b4bf2Smrg{ 604983b4bf2Smrg VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 605983b4bf2Smrg 606983b4bf2Smrg if (pBIOSInfo->TVPrintRegs) 607983b4bf2Smrg pBIOSInfo->TVPrintRegs(pScrn); 608983b4bf2Smrg} 609983b4bf2Smrg#endif /* HAVE_DEBUG */ 610983b4bf2Smrg 611983b4bf2Smrgstatic void 612983b4bf2Smrgvia_tv_create_resources(xf86OutputPtr output) 613983b4bf2Smrg{ 614983b4bf2Smrg} 615983b4bf2Smrg 616983b4bf2Smrg#ifdef RANDR_12_INTERFACE 617983b4bf2Smrgstatic Bool 618983b4bf2Smrgvia_tv_set_property(xf86OutputPtr output, Atom property, 619983b4bf2Smrg RRPropertyValuePtr value) 620983b4bf2Smrg{ 621983b4bf2Smrg return TRUE; 622983b4bf2Smrg} 623983b4bf2Smrg 624983b4bf2Smrgstatic Bool 625983b4bf2Smrgvia_tv_get_property(xf86OutputPtr output, Atom property) 626983b4bf2Smrg{ 627983b4bf2Smrg return FALSE; 628983b4bf2Smrg} 629983b4bf2Smrg#endif 630983b4bf2Smrg 631983b4bf2Smrgstatic void 632983b4bf2Smrgvia_tv_dpms(xf86OutputPtr output, int mode) 633983b4bf2Smrg{ 634983b4bf2Smrg ScrnInfoPtr pScrn = output->scrn; 635983b4bf2Smrg 636983b4bf2Smrg switch (mode) { 637983b4bf2Smrg case DPMSModeOn: 638983b4bf2Smrg ViaTVPower(pScrn, TRUE); 639983b4bf2Smrg break; 640983b4bf2Smrg 641983b4bf2Smrg case DPMSModeStandby: 642983b4bf2Smrg case DPMSModeSuspend: 643983b4bf2Smrg case DPMSModeOff: 644983b4bf2Smrg ViaTVPower(pScrn, FALSE); 645983b4bf2Smrg break; 646983b4bf2Smrg } 647983b4bf2Smrg} 648983b4bf2Smrg 649983b4bf2Smrgstatic void 650983b4bf2Smrgvia_tv_save(xf86OutputPtr output) 651983b4bf2Smrg{ 652983b4bf2Smrg ScrnInfoPtr pScrn = output->scrn; 653983b4bf2Smrg 654983b4bf2Smrg ViaTVSave(pScrn); 655983b4bf2Smrg} 656983b4bf2Smrg 657983b4bf2Smrgstatic void 658983b4bf2Smrgvia_tv_restore(xf86OutputPtr output) 659983b4bf2Smrg{ 660983b4bf2Smrg ScrnInfoPtr pScrn = output->scrn; 661983b4bf2Smrg 662983b4bf2Smrg ViaTVRestore(pScrn); 663983b4bf2Smrg} 664983b4bf2Smrg 665983b4bf2Smrgstatic int 666983b4bf2Smrgvia_tv_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) 667983b4bf2Smrg{ 668983b4bf2Smrg ScrnInfoPtr pScrn = output->scrn; 669983b4bf2Smrg int ret = MODE_OK; 670983b4bf2Smrg 671983b4bf2Smrg if (!ViaModeDotClockTranslate(pScrn, pMode)) 672983b4bf2Smrg return MODE_NOCLOCK; 673983b4bf2Smrg 674983b4bf2Smrg return ret; 675983b4bf2Smrg} 676983b4bf2Smrg 677983b4bf2Smrgstatic Bool 678983b4bf2Smrgvia_tv_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, 679983b4bf2Smrg DisplayModePtr adjusted_mode) 680983b4bf2Smrg{ 681983b4bf2Smrg return TRUE; 682983b4bf2Smrg} 683983b4bf2Smrg 684983b4bf2Smrgstatic void 685983b4bf2Smrgvia_tv_prepare(xf86OutputPtr output) 686983b4bf2Smrg{ 687983b4bf2Smrg via_tv_dpms(output, DPMSModeOff); 688983b4bf2Smrg} 689983b4bf2Smrg 690983b4bf2Smrgstatic void 691983b4bf2Smrgvia_tv_commit(xf86OutputPtr output) 692983b4bf2Smrg{ 693983b4bf2Smrg via_tv_dpms(output, DPMSModeOn); 694983b4bf2Smrg} 695983b4bf2Smrg 696983b4bf2Smrgstatic void 697983b4bf2Smrgvia_tv_mode_set(xf86OutputPtr output, DisplayModePtr mode, 698983b4bf2Smrg DisplayModePtr adjusted_mode) 699983b4bf2Smrg{ 700983b4bf2Smrg ScrnInfoPtr pScrn = output->scrn; 701983b4bf2Smrg drmmode_crtc_private_ptr iga = output->crtc->driver_private; 702983b4bf2Smrg VIAPtr pVia = VIAPTR(pScrn); 703983b4bf2Smrg 704983b4bf2Smrg /* TV on FirstCrtc */ 705983b4bf2Smrg if (output->crtc) { 706983b4bf2Smrg viaTVSetDisplaySource(pScrn, iga->index ? 0x01 : 0x00); 707983b4bf2Smrg 708983b4bf2Smrg /* Set I/O pads to automatic on / off mode. */ 709983b4bf2Smrg viaTVEnableIOPads(pScrn, 0x03); 710983b4bf2Smrg 711983b4bf2Smrg viaTVSetClockDriveStrength(pScrn, 0x03); 712983b4bf2Smrg viaTVSetDataDriveStrength(pScrn, 0x03); 713983b4bf2Smrg 714983b4bf2Smrg ViaTVSetMode(output->crtc, adjusted_mode); 715983b4bf2Smrg } 716983b4bf2Smrg 717983b4bf2Smrg pVia->FirstInit = FALSE; 718983b4bf2Smrg} 719983b4bf2Smrg 720983b4bf2Smrgstatic xf86OutputStatus 721983b4bf2Smrgvia_tv_detect(xf86OutputPtr output) 722983b4bf2Smrg{ 723983b4bf2Smrg xf86OutputStatus status = XF86OutputStatusDisconnected; 724983b4bf2Smrg ScrnInfoPtr pScrn = output->scrn; 725983b4bf2Smrg 726983b4bf2Smrg if (ViaTVDACSense(pScrn)) 727983b4bf2Smrg status = XF86OutputStatusConnected; 728983b4bf2Smrg return status; 729983b4bf2Smrg} 730983b4bf2Smrg 731983b4bf2Smrgstatic DisplayModePtr 732983b4bf2Smrgvia_tv_get_modes(xf86OutputPtr output) 733983b4bf2Smrg{ 734983b4bf2Smrg DisplayModePtr modes = NULL, mode = NULL; 735983b4bf2Smrg ScrnInfoPtr pScrn = output->scrn; 736983b4bf2Smrg VIAPtr pVia = VIAPTR(pScrn); 737983b4bf2Smrg int i; 738983b4bf2Smrg 739983b4bf2Smrg for (i = 0; i < pVia->pBIOSInfo->TVNumModes; i++) { 740983b4bf2Smrg mode = xf86DuplicateMode(&pVia->pBIOSInfo->TVModes[i]); 741983b4bf2Smrg modes = xf86ModesAdd(modes, mode); 742983b4bf2Smrg } 743983b4bf2Smrg return modes; 744983b4bf2Smrg} 745983b4bf2Smrg 746983b4bf2Smrgstatic void 747983b4bf2Smrgvia_tv_destroy(xf86OutputPtr output) 748983b4bf2Smrg{ 749983b4bf2Smrg} 750983b4bf2Smrg 751983b4bf2Smrgstatic const xf86OutputFuncsRec via_tv_funcs = { 752983b4bf2Smrg .create_resources = via_tv_create_resources, 753983b4bf2Smrg#ifdef RANDR_12_INTERFACE 754983b4bf2Smrg .set_property = via_tv_set_property, 755983b4bf2Smrg#endif 756983b4bf2Smrg#ifdef RANDR_13_INTERFACE 757983b4bf2Smrg .get_property = via_tv_get_property, 758983b4bf2Smrg#endif 759983b4bf2Smrg .dpms = via_tv_dpms, 760983b4bf2Smrg .save = via_tv_save, 761983b4bf2Smrg .restore = via_tv_restore, 762983b4bf2Smrg .mode_valid = via_tv_mode_valid, 763983b4bf2Smrg .mode_fixup = via_tv_mode_fixup, 764983b4bf2Smrg .prepare = via_tv_prepare, 765983b4bf2Smrg .commit = via_tv_commit, 766983b4bf2Smrg .mode_set = via_tv_mode_set, 767983b4bf2Smrg .detect = via_tv_detect, 768983b4bf2Smrg .get_modes = via_tv_get_modes, 769983b4bf2Smrg .destroy = via_tv_destroy, 770983b4bf2Smrg}; 771983b4bf2Smrg 772983b4bf2Smrg/* 773983b4bf2Smrg * 774983b4bf2Smrg */ 775983b4bf2SmrgBool 776983b4bf2Smrgvia_tv_init(ScrnInfoPtr pScrn) 777983b4bf2Smrg{ 778983b4bf2Smrg VIAPtr pVia = VIAPTR(pScrn); 779983b4bf2Smrg VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 780983b4bf2Smrg xf86OutputPtr output = NULL; 781983b4bf2Smrg 782983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 783983b4bf2Smrg "Entered via_tv_init.\n")); 784983b4bf2Smrg 785983b4bf2Smrg /* preset some pBIOSInfo TV related values -- move up */ 786983b4bf2Smrg pBIOSInfo->TVEncoder = VIA_NONETV; 787983b4bf2Smrg pBIOSInfo->TVI2CDev = NULL; 788983b4bf2Smrg pBIOSInfo->TVSave = NULL; 789983b4bf2Smrg pBIOSInfo->TVRestore = NULL; 790983b4bf2Smrg pBIOSInfo->TVDACSense = NULL; 791983b4bf2Smrg pBIOSInfo->TVModeValid = NULL; 792983b4bf2Smrg pBIOSInfo->TVModeI2C = NULL; 793983b4bf2Smrg pBIOSInfo->TVModeCrtc = NULL; 794983b4bf2Smrg pBIOSInfo->TVPower = NULL; 795983b4bf2Smrg pBIOSInfo->TVModes = NULL; 796983b4bf2Smrg pBIOSInfo->TVPrintRegs = NULL; 797983b4bf2Smrg pBIOSInfo->LCDPower = NULL; 798983b4bf2Smrg pBIOSInfo->TVNumRegs = 0; 799983b4bf2Smrg 800983b4bf2Smrg /* 801983b4bf2Smrg * On an SK43G (KM400/Ch7011), false positive detections at a VT162x 802983b4bf2Smrg * chip were observed, so try to detect the Ch7011 first. 803983b4bf2Smrg */ 804983b4bf2Smrg if (pVia->pI2CBus2 && xf86I2CProbeAddress(pVia->pI2CBus2, 0xEC)) 805983b4bf2Smrg pBIOSInfo->TVI2CDev = ViaCH7xxxDetect(pScrn, pVia->pI2CBus2, 0xEC); 806983b4bf2Smrg else if (pVia->pI2CBus2 && xf86I2CProbeAddress(pVia->pI2CBus2, 0x40)) 807983b4bf2Smrg pBIOSInfo->TVI2CDev = ViaVT162xDetect(pScrn, pVia->pI2CBus2, 0x40); 808983b4bf2Smrg else if (pVia->pI2CBus3 && xf86I2CProbeAddress(pVia->pI2CBus3, 0x40)) 809983b4bf2Smrg pBIOSInfo->TVI2CDev = ViaVT162xDetect(pScrn, pVia->pI2CBus3, 0x40); 810983b4bf2Smrg else if (pVia->pI2CBus2 && xf86I2CProbeAddress(pVia->pI2CBus2, 0xEA)) 811983b4bf2Smrg pBIOSInfo->TVI2CDev = ViaCH7xxxDetect(pScrn, pVia->pI2CBus2, 0xEA); 812983b4bf2Smrg else if (pVia->pI2CBus3 && xf86I2CProbeAddress(pVia->pI2CBus3, 0xEA)) 813983b4bf2Smrg pBIOSInfo->TVI2CDev = ViaCH7xxxDetect(pScrn, pVia->pI2CBus3, 0xEA); 814983b4bf2Smrg 815983b4bf2Smrg if (!pBIOSInfo->TVI2CDev) { 816983b4bf2Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 817983b4bf2Smrg "Did not detect a TV encoder.\n"); 818983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 819983b4bf2Smrg "Exiting via_tv_init.\n")); 820983b4bf2Smrg 821983b4bf2Smrg return FALSE; 822983b4bf2Smrg } 823983b4bf2Smrg 824983b4bf2Smrg switch (pBIOSInfo->TVEncoder) { 825983b4bf2Smrg case VIA_VT1621: 826983b4bf2Smrg case VIA_VT1622: 827983b4bf2Smrg case VIA_VT1623: 828983b4bf2Smrg case VIA_VT1625: 829983b4bf2Smrg ViaVT162xInit(pScrn); 830983b4bf2Smrg break; 831983b4bf2Smrg case VIA_CH7011: 832983b4bf2Smrg case VIA_CH7019A: 833983b4bf2Smrg case VIA_CH7019B: 834983b4bf2Smrg ViaCH7xxxInit(pScrn); 835983b4bf2Smrg break; 836983b4bf2Smrg default: 837983b4bf2Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 838983b4bf2Smrg "Was not able to initialize a known TV encoder.\n"); 839983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 840983b4bf2Smrg "Exiting via_tv_init.\n")); 841983b4bf2Smrg return FALSE; 842983b4bf2Smrg break; 843983b4bf2Smrg } 844983b4bf2Smrg 845983b4bf2Smrg if (!pBIOSInfo->TVSave || !pBIOSInfo->TVRestore 846983b4bf2Smrg || !pBIOSInfo->TVDACSense || !pBIOSInfo->TVModeValid 847983b4bf2Smrg || !pBIOSInfo->TVModeI2C || !pBIOSInfo->TVModeCrtc 848983b4bf2Smrg || !pBIOSInfo->TVPower || !pBIOSInfo->TVModes 849983b4bf2Smrg || !pBIOSInfo->TVPrintRegs) { 850983b4bf2Smrg 851983b4bf2Smrg xf86DestroyI2CDevRec(pBIOSInfo->TVI2CDev, TRUE); 852983b4bf2Smrg 853983b4bf2Smrg pBIOSInfo->TVI2CDev = NULL; 854983b4bf2Smrg pBIOSInfo->TVOutput = TVOUTPUT_NONE; 855983b4bf2Smrg pBIOSInfo->TVEncoder = VIA_NONETV; 856983b4bf2Smrg pBIOSInfo->TVI2CDev = NULL; 857983b4bf2Smrg pBIOSInfo->TVSave = NULL; 858983b4bf2Smrg pBIOSInfo->TVRestore = NULL; 859983b4bf2Smrg pBIOSInfo->TVDACSense = NULL; 860983b4bf2Smrg pBIOSInfo->TVModeValid = NULL; 861983b4bf2Smrg pBIOSInfo->TVModeI2C = NULL; 862983b4bf2Smrg pBIOSInfo->TVModeCrtc = NULL; 863983b4bf2Smrg pBIOSInfo->TVPower = NULL; 864983b4bf2Smrg pBIOSInfo->TVModes = NULL; 865983b4bf2Smrg pBIOSInfo->TVPrintRegs = NULL; 866983b4bf2Smrg pBIOSInfo->TVNumRegs = 0; 867983b4bf2Smrg 868983b4bf2Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 869983b4bf2Smrg "TV encoder was not properly initialized.\n"); 870983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 871983b4bf2Smrg "Exiting via_tv_init.\n")); 872983b4bf2Smrg return FALSE; 873983b4bf2Smrg } 874983b4bf2Smrg 875983b4bf2Smrg output = xf86OutputCreate(pScrn, &via_tv_funcs, "TV-1"); 876983b4bf2Smrg pVia->FirstInit = TRUE; 877983b4bf2Smrg 878983b4bf2Smrg if (output) { 879983b4bf2Smrg /* Allow tv output on both crtcs, set bit 0 and 1. */ 880983b4bf2Smrg output->possible_crtcs = 0x3; 881983b4bf2Smrg } else { 882983b4bf2Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 883983b4bf2Smrg "Failed to register TV-1.\n"); 884983b4bf2Smrg } 885983b4bf2Smrg 886983b4bf2Smrg pBIOSInfo->tv = output; 887983b4bf2Smrg /* Save now */ 888983b4bf2Smrg pBIOSInfo->TVSave(pScrn); 889983b4bf2Smrg 890983b4bf2Smrg#ifdef HAVE_DEBUG 891983b4bf2Smrg if (VIAPTR(pScrn)->PrintTVRegs) 892983b4bf2Smrg pBIOSInfo->TVPrintRegs(pScrn); 893983b4bf2Smrg#endif 894983b4bf2Smrg 895983b4bf2Smrg DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 896983b4bf2Smrg "Exiting via_tv_init.\n")); 897983b4bf2Smrg return TRUE; 898983b4bf2Smrg} 899