via_tv.c revision 983b4bf2
1/* 2 * Copyright 2005-2016 The OpenChrome Project 3 * [https://www.freedesktop.org/wiki/Openchrome] 4 * Copyright 2004-2005 The Unichrome Project [unichrome.sf.net] 5 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. 6 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sub license, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial portions 17 * of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 * DEALINGS IN THE SOFTWARE. 26 */ 27 28/* 29 * via_tv.c 30 * 31 * Handles the initialization and management of TV output related 32 * resources. 33 * 34 */ 35 36#ifdef HAVE_CONFIG_H 37#include "config.h" 38#endif 39 40#include "via_driver.h" 41#include <unistd.h> 42 43static void 44viaTVSetDisplaySource(ScrnInfoPtr pScrn, CARD8 displaySource) 45{ 46 47 vgaHWPtr hwp = VGAHWPTR(pScrn); 48 VIAPtr pVia = VIAPTR(pScrn); 49 CARD8 sr12, sr13, sr5a; 50 51 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 52 "Entered viaTVSetDisplaySource.\n")); 53 54 if ((pVia->Chipset == VIA_CX700) 55 || (pVia->Chipset == VIA_VX800) 56 || (pVia->Chipset == VIA_VX855) 57 || (pVia->Chipset == VIA_VX900)) { 58 59 sr5a = hwp->readSeq(hwp, 0x5A); 60 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 61 "SR5A: 0x%02X\n", sr5a)); 62 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 63 "Setting 3C5.5A[0] to 0.\n")); 64 ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01); 65 } 66 67 sr12 = hwp->readSeq(hwp, 0x12); 68 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 69 "SR12: 0x%02X\n", sr12)); 70 sr13 = hwp->readSeq(hwp, 0x13); 71 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 72 "SR13: 0x%02X\n", sr13)); 73 switch (pVia->Chipset) { 74 case VIA_CLE266: 75 /* 3C5.12[5] - FPD18 pin strapping 76 * 0: DIP0 (Digital Interface Port 0) is used by 77 * a TMDS transmitter (DVI) 78 * 1: DIP0 (Digital Interface Port 0) is used by 79 * a TV encoder */ 80 if (sr12 & 0x20) { 81 viaDIP0SetDisplaySource(pScrn, displaySource); 82 } else { 83 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 84 "DIP0 was not set up for " 85 "an external TV encoder use.\n"); 86 } 87 88 break; 89 case VIA_KM400: 90 case VIA_K8M800: 91 case VIA_PM800: 92 case VIA_P4M800PRO: 93 /* 3C5.13[3] - DVP0D8 pin strapping 94 * 0: AGP pins are used for AGP 95 * 1: AGP pins are used by FPDP 96 * (Flat Panel Display Port) 97 * 3C5.12[6] - DVP0D6 pin strapping 98 * 0: Disable DVP0 (Digital Video Port 0) 99 * 1: Enable DVP0 (Digital Video Port 0) 100 * 3C5.12[5] - DVP0D5 pin strapping 101 * 0: DVP0 is used by a TMDS transmitter (DVI) 102 * 1: DVP0 is used by a TV encoder 103 * 3C5.12[4] - DVP0D4 pin strapping 104 * 0: Dual 12-bit FPDP (Flat Panel Display Port) 105 * 1: 24-bit FPDP (Flat Panel Display Port) */ 106 if ((sr12 & 0x40) && (sr12 & 0x20)) { 107 viaDVP0SetDisplaySource(pScrn, displaySource); 108 } else if ((sr13 & 0x08) && (!(sr12 & 0x10))) { 109 viaDFPLowSetDisplaySource(pScrn, displaySource); 110 } else if (sr13 & 0x08) { 111 viaDVP1SetDisplaySource(pScrn, displaySource); 112 } else { 113 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 114 "None of the external ports were set up for " 115 "external TV encoder use.\n"); 116 } 117 118 break; 119 case VIA_P4M890: 120 case VIA_K8M890: 121 case VIA_P4M900: 122 /* 3C5.12[6] - FPD6 pin strapping 123 * 0: Disable DVP0 (Digital Video Port 0) 124 * 1: Enable DVP0 (Digital Video Port 0) 125 * 3C5.12[5] - FPD5 pin strapping 126 * 0: DVP0 is used by a TMDS transmitter (DVI) 127 * 1: DVP0 is used by a TV encoder 128 * 3C5.12[4] - FPD4 pin strapping 129 * 0: Dual 12-bit FPDP (Flat Panel Display Port) 130 * 1: 24-bit FPDP (Flat Panel Display Port) */ 131 if ((sr12 & 0x40) && (sr12 & 0x20) && (!(sr12 & 0x10))) { 132 viaDVP0SetDisplaySource(pScrn, displaySource); 133 } else { 134 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 135 "Unrecognized external TV encoder use.\n" 136 "Contact the developer for assistance.\n"); 137 } 138 139 break; 140 case VIA_CX700: 141 case VIA_VX800: 142 case VIA_VX855: 143 case VIA_VX900: 144 /* 3C5.13[6] - DVP1 DVP / capture port selection 145 * 0: DVP1 is used as a DVP (Digital Video Port) 146 * 1: DVP1 is used as a capture port 147 */ 148 if (!(sr13 & 0x40)) { 149 viaDVP1SetDisplaySource(pScrn, displaySource); 150 } else { 151 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 152 "DVP1 is not set up for external TV " 153 "encoder use.\n"); 154 } 155 156 break; 157 default: 158 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 159 "Unrecognized IGP for " 160 "an external TV encoder use.\n"); 161 break; 162 } 163 164 if ((pVia->Chipset == VIA_CX700) 165 || (pVia->Chipset == VIA_VX800) 166 || (pVia->Chipset == VIA_VX855) 167 || (pVia->Chipset == VIA_VX900)) { 168 169 hwp->writeSeq(hwp, 0x5A, sr5a); 170 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 171 "Restoring 3C5.5A[0].\n")); 172 } 173 174 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 175 "Exiting viaTVSetDisplaySource.\n")); 176} 177 178static void 179viaTVEnableIOPads(ScrnInfoPtr pScrn, CARD8 ioPadState) 180{ 181 vgaHWPtr hwp = VGAHWPTR(pScrn); 182 VIAPtr pVia = VIAPTR(pScrn); 183 CARD8 sr12, sr13, sr5a; 184 185 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 186 "Entered viaTVEnableIOPads.\n")); 187 188 if ((pVia->Chipset == VIA_CX700) 189 || (pVia->Chipset == VIA_VX800) 190 || (pVia->Chipset == VIA_VX855) 191 || (pVia->Chipset == VIA_VX900)) { 192 193 sr5a = hwp->readSeq(hwp, 0x5A); 194 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 195 "SR5A: 0x%02X\n", sr5a)); 196 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 197 "Setting 3C5.5A[0] to 0.\n")); 198 ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01); 199 } 200 201 sr12 = hwp->readSeq(hwp, 0x12); 202 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 203 "SR12: 0x%02X\n", sr12)); 204 sr13 = hwp->readSeq(hwp, 0x13); 205 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 206 "SR13: 0x%02X\n", sr13)); 207 switch (pVia->Chipset) { 208 case VIA_CLE266: 209 /* 3C5.12[5] - FPD18 pin strapping 210 * 0: DIP0 (Digital Interface Port 0) is used by 211 * a TMDS transmitter (DVI) 212 * 1: DIP0 (Digital Interface Port 0) is used by 213 * a TV encoder */ 214 if (sr12 & 0x20) { 215 viaDIP0EnableIOPads(pScrn, ioPadState); 216 } else { 217 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 218 "DIP0 is not set up for " 219 "an external TV encoder use.\n"); 220 } 221 222 break; 223 case VIA_KM400: 224 case VIA_K8M800: 225 case VIA_PM800: 226 case VIA_P4M800PRO: 227 /* 3C5.13[3] - DVP0D8 pin strapping 228 * 0: AGP pins are used for AGP 229 * 1: AGP pins are used by FPDP 230 * (Flat Panel Display Port) 231 * 3C5.12[6] - DVP0D6 pin strapping 232 * 0: Disable DVP0 (Digital Video Port 0) 233 * 1: Enable DVP0 (Digital Video Port 0) 234 * 3C5.12[5] - DVP0D5 pin strapping 235 * 0: DVP0 is used by a TMDS transmitter (DVI) 236 * 1: DVP0 is used by a TV encoder 237 * 3C5.12[4] - DVP0D4 pin strapping 238 * 0: Dual 12-bit FPDP (Flat Panel Display Port) 239 * 1: 24-bit FPDP (Flat Panel Display Port) */ 240 if ((sr12 & 0x40) && (sr12 & 0x20)) { 241 viaDVP0EnableIOPads(pScrn, ioPadState); 242 } else if ((sr13 & 0x08) && (!(sr12 & 0x10))) { 243 viaDFPLowEnableIOPads(pScrn, ioPadState); 244 } else if (sr13 & 0x08) { 245 viaDVP1EnableIOPads(pScrn, ioPadState); 246 } else { 247 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 248 "None of the external ports were set up for " 249 "external TV encoder use.\n"); 250 } 251 252 break; 253 case VIA_P4M890: 254 case VIA_K8M890: 255 case VIA_P4M900: 256 /* 3C5.12[6] - FPD6 pin strapping 257 * 0: Disable DVP0 (Digital Video Port 0) 258 * 1: Enable DVP0 (Digital Video Port 0) 259 * 3C5.12[5] - FPD5 pin strapping 260 * 0: DVP0 is used by a TMDS transmitter (DVI) 261 * 1: DVP0 is used by a TV encoder 262 * 3C5.12[4] - FPD4 pin strapping 263 * 0: Dual 12-bit FPDP (Flat Panel Display Port) 264 * 1: 24-bit FPDP (Flat Panel Display Port) */ 265 if ((sr12 & 0x40) && (sr12 & 0x20) && (!(sr12 & 0x10))) { 266 viaDVP0EnableIOPads(pScrn, ioPadState); 267 } else { 268 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 269 "Unrecognized external TV encoder use.\n" 270 "Contact the developer for assistance.\n"); 271 } 272 273 break; 274 case VIA_CX700: 275 case VIA_VX800: 276 case VIA_VX855: 277 case VIA_VX900: 278 /* 3C5.13[6] - DVP1 DVP / capture port selection 279 * 0: DVP1 is used as a DVP (Digital Video Port) 280 * 1: DVP1 is used as a capture port 281 */ 282 if (!(sr13 & 0x40)) { 283 viaDVP1EnableIOPads(pScrn, ioPadState); 284 } else { 285 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 286 "DVP1 is not set up for external TV " 287 "encoder use.\n"); 288 } 289 290 break; 291 default: 292 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 293 "Unrecognized IGP for " 294 "an external TV encoder use.\n"); 295 break; 296 } 297 298 if ((pVia->Chipset == VIA_CX700) 299 || (pVia->Chipset == VIA_VX800) 300 || (pVia->Chipset == VIA_VX855) 301 || (pVia->Chipset == VIA_VX900)) { 302 303 hwp->writeSeq(hwp, 0x5A, sr5a); 304 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 305 "Restoring 3C5.5A[0].\n")); 306 } 307 308 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 309 "Exiting viaTVEnableIOPads.\n")); 310} 311 312static void 313viaTVSetClockDriveStrength(ScrnInfoPtr pScrn, CARD8 clockDriveStrength) 314{ 315 vgaHWPtr hwp = VGAHWPTR(pScrn); 316 VIAPtr pVia = VIAPTR(pScrn); 317 CARD8 sr12, sr13, sr5a; 318 319 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 320 "Entered viaTVSetClockDriveStrength.\n")); 321 322 if ((pVia->Chipset == VIA_CX700) 323 || (pVia->Chipset == VIA_VX800) 324 || (pVia->Chipset == VIA_VX855) 325 || (pVia->Chipset == VIA_VX900)) { 326 327 sr5a = hwp->readSeq(hwp, 0x5A); 328 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 329 "SR5A: 0x%02X\n", sr5a)); 330 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 331 "Setting 3C5.5A[0] to 0.\n")); 332 ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01); 333 } 334 335 sr12 = hwp->readSeq(hwp, 0x12); 336 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 337 "SR12: 0x%02X\n", sr12)); 338 sr13 = hwp->readSeq(hwp, 0x13); 339 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 340 "SR13: 0x%02X\n", sr13)); 341 switch (pVia->Chipset) { 342 case VIA_CLE266: 343 /* 3C5.12[5] - FPD18 pin strapping 344 * 0: DIP0 (Digital Interface Port 0) is used by 345 * a TMDS transmitter (DVI) 346 * 1: DIP0 (Digital Interface Port 0) is used by 347 * a TV encoder */ 348 if (sr12 & 0x20) { 349 viaDIP0SetClockDriveStrength(pScrn, clockDriveStrength); 350 } 351 352 break; 353 case VIA_KM400: 354 case VIA_K8M800: 355 case VIA_PM800: 356 case VIA_P4M800PRO: 357 /* 3C5.13[3] - DVP0D8 pin strapping 358 * 0: AGP pins are used for AGP 359 * 1: AGP pins are used by FPDP 360 * (Flat Panel Display Port) 361 * 3C5.12[6] - DVP0D6 pin strapping 362 * 0: Disable DVP0 (Digital Video Port 0) 363 * 1: Enable DVP0 (Digital Video Port 0) 364 * 3C5.12[5] - DVP0D5 pin strapping 365 * 0: DVP0 is used by a TMDS transmitter (DVI) 366 * 1: DVP0 is used by a TV encoder 367 * 3C5.12[4] - DVP0D4 pin strapping 368 * 0: Dual 12-bit FPDP (Flat Panel Display Port) 369 * 1: 24-bit FPDP (Flat Panel Display Port) */ 370 if ((sr12 & 0x40) && (sr12 & 0x20)) { 371 viaDVP0SetClockDriveStrength(pScrn, clockDriveStrength); 372 } else if ((sr13 & 0x08) && (!(sr12 & 0x10))) { 373 } else if (sr13 & 0x08) { 374 viaDVP1SetClockDriveStrength(pScrn, clockDriveStrength); 375 } 376 377 break; 378 case VIA_P4M890: 379 case VIA_K8M890: 380 case VIA_P4M900: 381 /* 3C5.12[6] - FPD6 pin strapping 382 * 0: Disable DVP0 (Digital Video Port 0) 383 * 1: Enable DVP0 (Digital Video Port 0) 384 * 3C5.12[5] - FPD5 pin strapping 385 * 0: DVP0 is used by a TMDS transmitter (DVI) 386 * 1: DVP0 is used by a TV encoder 387 * 3C5.12[4] - FPD4 pin strapping 388 * 0: Dual 12-bit FPDP (Flat Panel Display Port) 389 * 1: 24-bit FPDP (Flat Panel Display Port) */ 390 if ((sr12 & 0x40) && (sr12 & 0x20) && (!(sr12 & 0x10))) { 391 viaDVP0SetClockDriveStrength(pScrn, clockDriveStrength); 392 } 393 394 break; 395 case VIA_CX700: 396 case VIA_VX800: 397 case VIA_VX855: 398 case VIA_VX900: 399 /* 3C5.13[6] - DVP1 DVP / capture port selection 400 * 0: DVP1 is used as a DVP (Digital Video Port) 401 * 1: DVP1 is used as a capture port */ 402 if (!(sr13 & 0x40)) { 403 viaDVP1SetClockDriveStrength(pScrn, clockDriveStrength); 404 } 405 406 break; 407 default: 408 break; 409 } 410 411 if ((pVia->Chipset == VIA_CX700) 412 || (pVia->Chipset == VIA_VX800) 413 || (pVia->Chipset == VIA_VX855) 414 || (pVia->Chipset == VIA_VX900)) { 415 416 hwp->writeSeq(hwp, 0x5A, sr5a); 417 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 418 "Restoring 3C5.5A[0].\n")); 419 } 420 421 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 422 "Exiting viaTVSetClockDriveStrength.\n")); 423} 424 425static void 426viaTVSetDataDriveStrength(ScrnInfoPtr pScrn, CARD8 dataDriveStrength) 427{ 428 vgaHWPtr hwp = VGAHWPTR(pScrn); 429 VIAPtr pVia = VIAPTR(pScrn); 430 CARD8 sr12, sr13, sr5a; 431 432 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 433 "Entered viaTVSetDataDriveStrength.\n")); 434 435 if ((pVia->Chipset == VIA_CX700) 436 || (pVia->Chipset == VIA_VX800) 437 || (pVia->Chipset == VIA_VX855) 438 || (pVia->Chipset == VIA_VX900)) { 439 440 sr5a = hwp->readSeq(hwp, 0x5A); 441 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 442 "SR5A: 0x%02X\n", sr5a)); 443 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 444 "Setting 3C5.5A[0] to 0.\n")); 445 ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01); 446 } 447 448 sr12 = hwp->readSeq(hwp, 0x12); 449 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 450 "SR12: 0x%02X\n", sr12)); 451 sr13 = hwp->readSeq(hwp, 0x13); 452 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 453 "SR13: 0x%02X\n", sr13)); 454 switch (pVia->Chipset) { 455 case VIA_CLE266: 456 /* 3C5.12[5] - FPD18 pin strapping 457 * 0: DIP0 (Digital Interface Port 0) is used by 458 * a TMDS transmitter (DVI) 459 * 1: DIP0 (Digital Interface Port 0) is used by 460 * a TV encoder */ 461 if (sr12 & 0x20) { 462 viaDIP0SetDataDriveStrength(pScrn, dataDriveStrength); 463 } 464 465 break; 466 case VIA_KM400: 467 case VIA_K8M800: 468 case VIA_PM800: 469 case VIA_P4M800PRO: 470 /* 3C5.13[3] - DVP0D8 pin strapping 471 * 0: AGP pins are used for AGP 472 * 1: AGP pins are used by FPDP 473 * (Flat Panel Display Port) 474 * 3C5.12[6] - DVP0D6 pin strapping 475 * 0: Disable DVP0 (Digital Video Port 0) 476 * 1: Enable DVP0 (Digital Video Port 0) 477 * 3C5.12[5] - DVP0D5 pin strapping 478 * 0: DVP0 is used by a TMDS transmitter (DVI) 479 * 1: DVP0 is used by a TV encoder 480 * 3C5.12[4] - DVP0D4 pin strapping 481 * 0: Dual 12-bit FPDP (Flat Panel Display Port) 482 * 1: 24-bit FPDP (Flat Panel Display Port) */ 483 if ((sr12 & 0x40) && (sr12 & 0x20)) { 484 viaDVP0SetDataDriveStrength(pScrn, dataDriveStrength); 485 } else if ((sr13 & 0x08) && (!(sr12 & 0x10))) { 486 } else if (sr13 & 0x08) { 487 viaDVP1SetDataDriveStrength(pScrn, dataDriveStrength); 488 } 489 490 break; 491 case VIA_P4M890: 492 case VIA_K8M890: 493 case VIA_P4M900: 494 /* 3C5.12[6] - FPD6 pin strapping 495 * 0: Disable DVP0 (Digital Video Port 0) 496 * 1: Enable DVP0 (Digital Video Port 0) 497 * 3C5.12[5] - FPD5 pin strapping 498 * 0: DVP0 is used by a TMDS transmitter (DVI) 499 * 1: DVP0 is used by a TV encoder 500 * 3C5.12[4] - FPD4 pin strapping 501 * 0: Dual 12-bit FPDP (Flat Panel Display Port) 502 * 1: 24-bit FPDP (Flat Panel Display Port) */ 503 if ((sr12 & 0x40) && (sr12 & 0x20) && (!(sr12 & 0x10))) { 504 viaDVP0SetDataDriveStrength(pScrn, dataDriveStrength); 505 } 506 507 break; 508 case VIA_CX700: 509 case VIA_VX800: 510 case VIA_VX855: 511 case VIA_VX900: 512 /* 3C5.13[6] - DVP1 DVP / capture port selection 513 * 0: DVP1 is used as a DVP (Digital Video Port) 514 * 1: DVP1 is used as a capture port */ 515 if (!(sr13 & 0x40)) { 516 viaDVP1SetDataDriveStrength(pScrn, dataDriveStrength); 517 } 518 519 break; 520 default: 521 break; 522 } 523 524 if ((pVia->Chipset == VIA_CX700) 525 || (pVia->Chipset == VIA_VX800) 526 || (pVia->Chipset == VIA_VX855) 527 || (pVia->Chipset == VIA_VX900)) { 528 529 hwp->writeSeq(hwp, 0x5A, sr5a); 530 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 531 "Restoring 3C5.5A[0].\n")); 532 } 533 534 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 535 "Exiting viaTVSetDataDriveStrength.\n")); 536} 537 538static void 539ViaTVSave(ScrnInfoPtr pScrn) 540{ 541 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 542 543 if (pBIOSInfo->TVSave) 544 pBIOSInfo->TVSave(pScrn); 545} 546 547static void 548ViaTVRestore(ScrnInfoPtr pScrn) 549{ 550 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 551 552 if (pBIOSInfo->TVRestore) 553 pBIOSInfo->TVRestore(pScrn); 554} 555 556static Bool 557ViaTVDACSense(ScrnInfoPtr pScrn) 558{ 559 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 560 561 if (pBIOSInfo->TVDACSense) 562 return pBIOSInfo->TVDACSense(pScrn); 563 return FALSE; 564} 565 566static void 567ViaTVSetMode(xf86CrtcPtr crtc, DisplayModePtr mode) 568{ 569 ScrnInfoPtr pScrn = crtc->scrn; 570 VIAPtr pVia = VIAPTR(pScrn); 571 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 572 573 if (pBIOSInfo->TVModeI2C) 574 pBIOSInfo->TVModeI2C(pScrn, mode); 575 576 if (pBIOSInfo->TVModeCrtc) 577 pBIOSInfo->TVModeCrtc(crtc, mode); 578 579 /* TV reset. */ 580 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1D, 0x00); 581 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1D, 0x80); 582} 583 584static void 585ViaTVPower(ScrnInfoPtr pScrn, Bool On) 586{ 587 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 588 589#ifdef HAVE_DEBUG 590 if (On) 591 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaTVPower: On.\n"); 592 else 593 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaTVPower: Off.\n"); 594#endif 595 596 if (pBIOSInfo->TVPower) 597 pBIOSInfo->TVPower(pScrn, On); 598} 599 600#ifdef HAVE_DEBUG 601void 602ViaTVPrintRegs(ScrnInfoPtr pScrn) 603{ 604 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 605 606 if (pBIOSInfo->TVPrintRegs) 607 pBIOSInfo->TVPrintRegs(pScrn); 608} 609#endif /* HAVE_DEBUG */ 610 611static void 612via_tv_create_resources(xf86OutputPtr output) 613{ 614} 615 616#ifdef RANDR_12_INTERFACE 617static Bool 618via_tv_set_property(xf86OutputPtr output, Atom property, 619 RRPropertyValuePtr value) 620{ 621 return TRUE; 622} 623 624static Bool 625via_tv_get_property(xf86OutputPtr output, Atom property) 626{ 627 return FALSE; 628} 629#endif 630 631static void 632via_tv_dpms(xf86OutputPtr output, int mode) 633{ 634 ScrnInfoPtr pScrn = output->scrn; 635 636 switch (mode) { 637 case DPMSModeOn: 638 ViaTVPower(pScrn, TRUE); 639 break; 640 641 case DPMSModeStandby: 642 case DPMSModeSuspend: 643 case DPMSModeOff: 644 ViaTVPower(pScrn, FALSE); 645 break; 646 } 647} 648 649static void 650via_tv_save(xf86OutputPtr output) 651{ 652 ScrnInfoPtr pScrn = output->scrn; 653 654 ViaTVSave(pScrn); 655} 656 657static void 658via_tv_restore(xf86OutputPtr output) 659{ 660 ScrnInfoPtr pScrn = output->scrn; 661 662 ViaTVRestore(pScrn); 663} 664 665static int 666via_tv_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) 667{ 668 ScrnInfoPtr pScrn = output->scrn; 669 int ret = MODE_OK; 670 671 if (!ViaModeDotClockTranslate(pScrn, pMode)) 672 return MODE_NOCLOCK; 673 674 return ret; 675} 676 677static Bool 678via_tv_mode_fixup(xf86OutputPtr output, DisplayModePtr mode, 679 DisplayModePtr adjusted_mode) 680{ 681 return TRUE; 682} 683 684static void 685via_tv_prepare(xf86OutputPtr output) 686{ 687 via_tv_dpms(output, DPMSModeOff); 688} 689 690static void 691via_tv_commit(xf86OutputPtr output) 692{ 693 via_tv_dpms(output, DPMSModeOn); 694} 695 696static void 697via_tv_mode_set(xf86OutputPtr output, DisplayModePtr mode, 698 DisplayModePtr adjusted_mode) 699{ 700 ScrnInfoPtr pScrn = output->scrn; 701 drmmode_crtc_private_ptr iga = output->crtc->driver_private; 702 VIAPtr pVia = VIAPTR(pScrn); 703 704 /* TV on FirstCrtc */ 705 if (output->crtc) { 706 viaTVSetDisplaySource(pScrn, iga->index ? 0x01 : 0x00); 707 708 /* Set I/O pads to automatic on / off mode. */ 709 viaTVEnableIOPads(pScrn, 0x03); 710 711 viaTVSetClockDriveStrength(pScrn, 0x03); 712 viaTVSetDataDriveStrength(pScrn, 0x03); 713 714 ViaTVSetMode(output->crtc, adjusted_mode); 715 } 716 717 pVia->FirstInit = FALSE; 718} 719 720static xf86OutputStatus 721via_tv_detect(xf86OutputPtr output) 722{ 723 xf86OutputStatus status = XF86OutputStatusDisconnected; 724 ScrnInfoPtr pScrn = output->scrn; 725 726 if (ViaTVDACSense(pScrn)) 727 status = XF86OutputStatusConnected; 728 return status; 729} 730 731static DisplayModePtr 732via_tv_get_modes(xf86OutputPtr output) 733{ 734 DisplayModePtr modes = NULL, mode = NULL; 735 ScrnInfoPtr pScrn = output->scrn; 736 VIAPtr pVia = VIAPTR(pScrn); 737 int i; 738 739 for (i = 0; i < pVia->pBIOSInfo->TVNumModes; i++) { 740 mode = xf86DuplicateMode(&pVia->pBIOSInfo->TVModes[i]); 741 modes = xf86ModesAdd(modes, mode); 742 } 743 return modes; 744} 745 746static void 747via_tv_destroy(xf86OutputPtr output) 748{ 749} 750 751static const xf86OutputFuncsRec via_tv_funcs = { 752 .create_resources = via_tv_create_resources, 753#ifdef RANDR_12_INTERFACE 754 .set_property = via_tv_set_property, 755#endif 756#ifdef RANDR_13_INTERFACE 757 .get_property = via_tv_get_property, 758#endif 759 .dpms = via_tv_dpms, 760 .save = via_tv_save, 761 .restore = via_tv_restore, 762 .mode_valid = via_tv_mode_valid, 763 .mode_fixup = via_tv_mode_fixup, 764 .prepare = via_tv_prepare, 765 .commit = via_tv_commit, 766 .mode_set = via_tv_mode_set, 767 .detect = via_tv_detect, 768 .get_modes = via_tv_get_modes, 769 .destroy = via_tv_destroy, 770}; 771 772/* 773 * 774 */ 775Bool 776via_tv_init(ScrnInfoPtr pScrn) 777{ 778 VIAPtr pVia = VIAPTR(pScrn); 779 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 780 xf86OutputPtr output = NULL; 781 782 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 783 "Entered via_tv_init.\n")); 784 785 /* preset some pBIOSInfo TV related values -- move up */ 786 pBIOSInfo->TVEncoder = VIA_NONETV; 787 pBIOSInfo->TVI2CDev = NULL; 788 pBIOSInfo->TVSave = NULL; 789 pBIOSInfo->TVRestore = NULL; 790 pBIOSInfo->TVDACSense = NULL; 791 pBIOSInfo->TVModeValid = NULL; 792 pBIOSInfo->TVModeI2C = NULL; 793 pBIOSInfo->TVModeCrtc = NULL; 794 pBIOSInfo->TVPower = NULL; 795 pBIOSInfo->TVModes = NULL; 796 pBIOSInfo->TVPrintRegs = NULL; 797 pBIOSInfo->LCDPower = NULL; 798 pBIOSInfo->TVNumRegs = 0; 799 800 /* 801 * On an SK43G (KM400/Ch7011), false positive detections at a VT162x 802 * chip were observed, so try to detect the Ch7011 first. 803 */ 804 if (pVia->pI2CBus2 && xf86I2CProbeAddress(pVia->pI2CBus2, 0xEC)) 805 pBIOSInfo->TVI2CDev = ViaCH7xxxDetect(pScrn, pVia->pI2CBus2, 0xEC); 806 else if (pVia->pI2CBus2 && xf86I2CProbeAddress(pVia->pI2CBus2, 0x40)) 807 pBIOSInfo->TVI2CDev = ViaVT162xDetect(pScrn, pVia->pI2CBus2, 0x40); 808 else if (pVia->pI2CBus3 && xf86I2CProbeAddress(pVia->pI2CBus3, 0x40)) 809 pBIOSInfo->TVI2CDev = ViaVT162xDetect(pScrn, pVia->pI2CBus3, 0x40); 810 else if (pVia->pI2CBus2 && xf86I2CProbeAddress(pVia->pI2CBus2, 0xEA)) 811 pBIOSInfo->TVI2CDev = ViaCH7xxxDetect(pScrn, pVia->pI2CBus2, 0xEA); 812 else if (pVia->pI2CBus3 && xf86I2CProbeAddress(pVia->pI2CBus3, 0xEA)) 813 pBIOSInfo->TVI2CDev = ViaCH7xxxDetect(pScrn, pVia->pI2CBus3, 0xEA); 814 815 if (!pBIOSInfo->TVI2CDev) { 816 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 817 "Did not detect a TV encoder.\n"); 818 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 819 "Exiting via_tv_init.\n")); 820 821 return FALSE; 822 } 823 824 switch (pBIOSInfo->TVEncoder) { 825 case VIA_VT1621: 826 case VIA_VT1622: 827 case VIA_VT1623: 828 case VIA_VT1625: 829 ViaVT162xInit(pScrn); 830 break; 831 case VIA_CH7011: 832 case VIA_CH7019A: 833 case VIA_CH7019B: 834 ViaCH7xxxInit(pScrn); 835 break; 836 default: 837 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 838 "Was not able to initialize a known TV encoder.\n"); 839 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 840 "Exiting via_tv_init.\n")); 841 return FALSE; 842 break; 843 } 844 845 if (!pBIOSInfo->TVSave || !pBIOSInfo->TVRestore 846 || !pBIOSInfo->TVDACSense || !pBIOSInfo->TVModeValid 847 || !pBIOSInfo->TVModeI2C || !pBIOSInfo->TVModeCrtc 848 || !pBIOSInfo->TVPower || !pBIOSInfo->TVModes 849 || !pBIOSInfo->TVPrintRegs) { 850 851 xf86DestroyI2CDevRec(pBIOSInfo->TVI2CDev, TRUE); 852 853 pBIOSInfo->TVI2CDev = NULL; 854 pBIOSInfo->TVOutput = TVOUTPUT_NONE; 855 pBIOSInfo->TVEncoder = VIA_NONETV; 856 pBIOSInfo->TVI2CDev = NULL; 857 pBIOSInfo->TVSave = NULL; 858 pBIOSInfo->TVRestore = NULL; 859 pBIOSInfo->TVDACSense = NULL; 860 pBIOSInfo->TVModeValid = NULL; 861 pBIOSInfo->TVModeI2C = NULL; 862 pBIOSInfo->TVModeCrtc = NULL; 863 pBIOSInfo->TVPower = NULL; 864 pBIOSInfo->TVModes = NULL; 865 pBIOSInfo->TVPrintRegs = NULL; 866 pBIOSInfo->TVNumRegs = 0; 867 868 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 869 "TV encoder was not properly initialized.\n"); 870 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 871 "Exiting via_tv_init.\n")); 872 return FALSE; 873 } 874 875 output = xf86OutputCreate(pScrn, &via_tv_funcs, "TV-1"); 876 pVia->FirstInit = TRUE; 877 878 if (output) { 879 /* Allow tv output on both crtcs, set bit 0 and 1. */ 880 output->possible_crtcs = 0x3; 881 } else { 882 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 883 "Failed to register TV-1.\n"); 884 } 885 886 pBIOSInfo->tv = output; 887 /* Save now */ 888 pBIOSInfo->TVSave(pScrn); 889 890#ifdef HAVE_DEBUG 891 if (VIAPTR(pScrn)->PrintTVRegs) 892 pBIOSInfo->TVPrintRegs(pScrn); 893#endif 894 895 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, 896 "Exiting via_tv_init.\n")); 897 return TRUE; 898} 899