1/* 2 * Copyright 2004-2005 The Unichrome Project [unichrome.sf.net] 3 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved. 4 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sub license, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 * DEALINGS IN THE SOFTWARE. 24 */ 25 26#ifdef HAVE_CONFIG_H 27#include "config.h" 28#endif 29 30#include "via_driver.h" 31#include "via_vt162x.h" 32 33static void 34ViaSetTVClockSource(xf86CrtcPtr crtc) 35{ 36 drmmode_crtc_private_ptr iga = crtc->driver_private; 37 ScrnInfoPtr pScrn = crtc->scrn; 38 VIAPtr pVia = VIAPTR(pScrn); 39 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 40 vgaHWPtr hwp = VGAHWPTR(pScrn); 41 42 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaSetTVClockSource\n")); 43 44 switch(pBIOSInfo->TVEncoder) { 45 case VIA_VT1625: 46 /* External TV: */ 47 switch(pVia->Chipset) { 48 case VIA_CX700: 49 case VIA_VX800: 50 case VIA_VX855: 51 case VIA_VX900: 52 /* IGA1 */ 53 if (!iga->index) { 54 /* Fixing it to DVP1 for IGA1. */ 55 ViaCrtcMask(hwp, 0x6C, 0xB0, 0xF0); 56 /* IGA2 */ 57 } else { 58 /* Fixing it to DVP1 for IGA2. */ 59 ViaCrtcMask(hwp, 0x6C, 0x0B, 0x0F); 60 } 61 break; 62 default: 63 if (!iga->index) 64 ViaCrtcMask(hwp, 0x6C, 0x21, 0x21); 65 else 66 ViaCrtcMask(hwp, 0x6C, 0xA1, 0xA1); 67 break; 68 } 69 break; 70 default: 71 if (!iga->index) 72 ViaCrtcMask(hwp, 0x6C, 0x50, 0xF0); 73 else 74 ViaCrtcMask(hwp, 0x6C, 0x05, 0x0F); 75 break; 76 } 77 78} 79 80static void 81VT162xPrintRegs(ScrnInfoPtr pScrn) 82{ 83 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 84 CARD8 i, buf; 85 86 87 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Printing registers for %s\n", 88 pBIOSInfo->TVI2CDev->DevName); 89 90 for (i = 0; i < pBIOSInfo->TVNumRegs; i++) { 91 xf86I2CReadByte(pBIOSInfo->TVI2CDev, i, &buf); 92 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV%02X: 0x%02X\n", i, buf); 93 } 94 95 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of TV registers.\n"); 96} 97 98 99I2CDevPtr 100ViaVT162xDetect(ScrnInfoPtr pScrn, I2CBusPtr pBus, CARD8 Address) 101{ 102 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 103 I2CDevPtr pDev = xf86CreateI2CDevRec(); 104 CARD8 buf; 105 106 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaVT162xDetect\n")); 107 108 pDev->DevName = "VT162x"; 109 pDev->SlaveAddr = Address; 110 pDev->pI2CBus = pBus; 111 112 if (!xf86I2CDevInit(pDev)) { 113 xf86DestroyI2CDevRec(pDev, TRUE); 114 return NULL; 115 } 116 117 if (!xf86I2CReadByte(pDev, 0x1B, &buf)) { 118 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 119 "Unable to read from %s Slave %d.\n", 120 pBus->BusName, Address); 121 xf86DestroyI2CDevRec(pDev, TRUE); 122 return NULL; 123 } 124 125 switch (buf) { 126 case 0x02: 127 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 128 "Detected VIA Technologies VT1621 TV Encoder\n"); 129 pBIOSInfo->TVEncoder = VIA_VT1621; 130 pDev->DevName = "VT1621"; 131 break; 132 case 0x03: 133 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 134 "Detected VIA Technologies VT1622 TV Encoder\n"); 135 pBIOSInfo->TVEncoder = VIA_VT1622; 136 pDev->DevName = "VT1622"; 137 break; 138 case 0x10: 139 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 140 "Detected VIA Technologies VT1622A/VT1623 TV Encoder\n"); 141 pBIOSInfo->TVEncoder = VIA_VT1623; 142 pDev->DevName = "VT1623"; 143 break; 144 case 0x50: 145 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 146 "Detected VIA Technologies VT1625 TV Encoder\n"); 147 pBIOSInfo->TVEncoder = VIA_VT1625; 148 pDev->DevName = "VT1625"; 149 break; 150 default: 151 pBIOSInfo->TVEncoder = VIA_NONETV; 152 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 153 "Unknown TV Encoder found at %s %X.\n", 154 pBus->BusName, Address); 155 xf86DestroyI2CDevRec(pDev, TRUE); 156 pDev = NULL; 157 break; 158 } 159 160 return pDev; 161} 162 163 164static void 165VT162xSave(ScrnInfoPtr pScrn) 166{ 167 int i; 168 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 169 170 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT162xSave\n")); 171 172 for (i = 0; i < pBIOSInfo->TVNumRegs; i++) 173 xf86I2CReadByte(pBIOSInfo->TVI2CDev, i, &(pBIOSInfo->TVRegs[i])); 174 175} 176 177static void 178VT162xRestore(ScrnInfoPtr pScrn) 179{ 180 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 181 int i; 182 183 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT162xRestore\n")); 184 185 for (i = 0; i < pBIOSInfo->TVNumRegs; i++) 186 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, pBIOSInfo->TVRegs[i]); 187} 188 189 190/* 191 * For VT1621 the same as for VT1622/VT1622A/VT1623, but result is different. 192 * Still needs testing on VT1621, of course. 193 */ 194static CARD8 195VT162xDACSenseI2C(I2CDevPtr pDev) 196{ 197 CARD8 save, sense; 198 199 xf86I2CReadByte(pDev, 0x0E, &save); 200 xf86I2CWriteByte(pDev, 0x0E, 0x00); 201 xf86I2CWriteByte(pDev, 0x0E, 0x80); 202 xf86I2CWriteByte(pDev, 0x0E, 0x00); 203 xf86I2CReadByte(pDev, 0x0F, &sense); 204 xf86I2CWriteByte(pDev, 0x0E, save); 205 206 return (sense & 0x0F); 207} 208 209/* 210 * VT1625/VT1625S sense connected TV outputs. 211 * 212 * The lower six bits of the return byte stand for each of the six DACs: 213 * - bit 0: DACf (Cb) 214 * - bit 1: DACe (Cr) 215 * - bit 2: DACd (Y) 216 * - bit 3: DACc (Composite) 217 * - bit 4: DACb (S-Video C) 218 * - bit 5: DACa (S-Video Y) 219 * 220 * If a bit is 0 it means a cable is connected. Note the VT1625S only has 221 * four DACs, corresponding to bit 0-3 above. 222 */ 223static CARD8 224VT1625DACSenseI2C(I2CDevPtr pDev) 225{ 226 CARD8 power, status, overflow, dacPresent; 227 228 xf86I2CReadByte(pDev, 0x0E, &power); // save power state 229 230 // VT1625S will always report 0 for bits 4 and 5 of the status register as 231 // it only has four DACs instead of six. This will result in a false 232 // positive for the S-Video cable. It will also do this on the power 233 // register, which is abused to check which DACs are actually present. 234 xf86I2CWriteByte(pDev, 0x0E, 0xFF); 235 xf86I2CReadByte(pDev, 0x0E, &dacPresent); 236 237 xf86I2CWriteByte(pDev, 0x0E, 0x00); // power on DACs/circuits 238 xf86I2CReadByte(pDev, 0x1C, &overflow); // save overflow reg 239 // (DAC sense bit should be off) 240 xf86I2CWriteByte(pDev, 0x1C, 0x80); // enable DAC sense bit 241 xf86I2CWriteByte(pDev, 0x1C, overflow); // disable DAC sense bit 242 xf86I2CReadByte(pDev, 0x0F, &status); // read connection status 243 xf86I2CWriteByte(pDev, 0x0E, power); // restore power state 244 status |= ~dacPresent; 245 246 return (status & 0x3F); 247} 248 249/* 250 * VT1621 only knows composite and s-video. 251 */ 252static Bool 253VT1621DACSense(ScrnInfoPtr pScrn) 254{ 255 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 256 CARD8 sense; 257 258 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621DACSense\n")); 259 260 sense = VT162xDACSenseI2C(pBIOSInfo->TVI2CDev); 261 switch (sense) { 262 case 0x00: 263 pBIOSInfo->TVOutput = TVOUTPUT_SC; 264 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 265 "VT1621: S-Video & Composite connected.\n"); 266 return TRUE; 267 case 0x01: 268 pBIOSInfo->TVOutput = TVOUTPUT_COMPOSITE; 269 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 270 "VT1621: Composite connected.\n"); 271 return TRUE; 272 case 0x02: 273 pBIOSInfo->TVOutput = TVOUTPUT_SVIDEO; 274 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 275 "VT1621: S-Video connected.\n"); 276 return TRUE; 277 case 0x03: 278 pBIOSInfo->TVOutput = TVOUTPUT_NONE; 279 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 280 "VT1621: Nothing connected.\n"); 281 return FALSE; 282 default: 283 pBIOSInfo->TVOutput = TVOUTPUT_NONE; 284 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 285 "VT1621: Unknown cable combination: 0x0%2X.\n", sense); 286 return FALSE; 287 } 288} 289 290/* 291 * VT1622, VT1622A and VT1623 know composite, s-video, RGB and YCBCR. 292 */ 293static Bool 294VT1622DACSense(ScrnInfoPtr pScrn) 295{ 296 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 297 CARD8 sense; 298 299 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622DACSense\n")); 300 301 sense = VT162xDACSenseI2C(pBIOSInfo->TVI2CDev); 302 switch (sense) { 303 case 0x00: /* DAC A,B,C,D */ 304 pBIOSInfo->TVOutput = TVOUTPUT_RGB; 305 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 306 "VT162x: RGB connected.\n"); 307 return TRUE; 308 case 0x01: /* DAC A,B,C */ 309 pBIOSInfo->TVOutput = TVOUTPUT_SC; 310 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 311 "VT162x: S-Video & Composite connected.\n"); 312 return TRUE; 313 case 0x07: /* DAC A */ 314 pBIOSInfo->TVOutput = TVOUTPUT_COMPOSITE; 315 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 316 "VT162x: Composite connected.\n"); 317 return TRUE; 318 case 0x08: /* DAC B,C,D */ 319 pBIOSInfo->TVOutput = TVOUTPUT_YCBCR; 320 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 321 "VT162x: YcBcR connected.\n"); 322 return TRUE; 323 case 0x09: /* DAC B,C */ 324 pBIOSInfo->TVOutput = TVOUTPUT_SVIDEO; 325 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 326 "VT162x: S-Video connected.\n"); 327 return TRUE; 328 case 0x0F: 329 pBIOSInfo->TVOutput = TVOUTPUT_NONE; 330 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 331 "VT162x: Nothing connected.\n"); 332 return FALSE; 333 default: 334 pBIOSInfo->TVOutput = TVOUTPUT_NONE; 335 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 336 "VT162x: Unknown cable combination: 0x0%2X.\n", sense); 337 return FALSE; 338 } 339} 340 341/* 342 * VT1625 knows composite, s-video, RGB and YCBCR. 343 */ 344static Bool 345VT1625DACSense(ScrnInfoPtr pScrn) 346{ 347 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 348 CARD8 sense; 349 350 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1625DACSense\n")); 351 352 sense = VT1625DACSenseI2C(pBIOSInfo->TVI2CDev); 353 switch (sense) { 354 case 0x00: /* DAC A,B,C,D,E,F */ 355 pBIOSInfo->TVOutput = TVOUTPUT_RGB; 356 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 357 "VT1625: RGB connected.\n"); 358 return TRUE; 359 case 0x07: /* DAC A,B,C */ 360 pBIOSInfo->TVOutput = TVOUTPUT_SC; 361 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 362 "VT1625: S-Video & Composite connected.\n"); 363 return TRUE; 364 case 0x37: /* DAC C */ 365 pBIOSInfo->TVOutput = TVOUTPUT_COMPOSITE; 366 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 367 "VT1625: Composite connected.\n"); 368 return TRUE; 369 case 0x38: /* DAC D,E,F */ 370 pBIOSInfo->TVOutput = TVOUTPUT_YCBCR; 371 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 372 "VT1625: YCbCr connected.\n"); 373 return TRUE; 374 case 0x0F: /* DAC A,B */ 375 pBIOSInfo->TVOutput = TVOUTPUT_SVIDEO; 376 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 377 "VT1625: S-Video connected.\n"); 378 return TRUE; 379 case 0x3F: 380 pBIOSInfo->TVOutput = TVOUTPUT_NONE; 381 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 382 "VT1625: Nothing connected.\n"); 383 return FALSE; 384 default: 385 pBIOSInfo->TVOutput = TVOUTPUT_NONE; 386 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 387 "VT1625: Unknown cable combination: 0x0%2X.\n", sense); 388 return FALSE; 389 } 390} 391 392static CARD8 393VT1621ModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode) 394{ 395 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 396 int i; 397 398 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621ModeIndex\n")); 399 400 for (i = 0; VT1621Table[i].Width; i++) { 401 if ((VT1621Table[i].Width == mode->CrtcHDisplay) && 402 (VT1621Table[i].Height == mode->CrtcVDisplay) && 403 (VT1621Table[i].Standard == pBIOSInfo->TVType) && 404 !(strcmp(VT1621Table[i].name, mode->name))) 405 return i; 406 } 407 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VT1621ModeIndex:" 408 " Mode \"%s\" not found in Table\n", mode->name); 409 return 0xFF; 410} 411 412static ModeStatus 413VT1621ModeValid(ScrnInfoPtr pScrn, DisplayModePtr mode) 414{ 415 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 416 417 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621ModeValid\n")); 418 419 if ((mode->PrivSize != sizeof(struct VT162xModePrivate)) || 420 ((mode->Private != (void *)&VT162xModePrivateNTSC) && 421 (mode->Private != (void *)&VT162xModePrivatePAL))) { 422 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 423 "Not a mode defined by the TV Encoder.\n"); 424 return MODE_BAD; 425 } 426 427 if ((pBIOSInfo->TVType == TVTYPE_NTSC) && 428 (mode->Private != (void *)&VT162xModePrivateNTSC)) { 429 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 430 "TV standard is NTSC. This is a PAL mode.\n"); 431 return MODE_BAD; 432 } else if ((pBIOSInfo->TVType == TVTYPE_PAL) && 433 (mode->Private != (void *)&VT162xModePrivatePAL)) { 434 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 435 "TV standard is PAL. This is a NTSC mode.\n"); 436 return MODE_BAD; 437 } 438 439 if (VT1621ModeIndex(pScrn, mode) != 0xFF) 440 return MODE_OK; 441 return MODE_BAD; 442} 443 444static CARD8 445VT1622ModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode) 446{ 447 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 448 struct VT162XTableRec *Table; 449 int i; 450 451 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622ModeIndex\n")); 452 453 if (pBIOSInfo->TVEncoder == VIA_VT1622) 454 Table = VT1622Table; 455 else if (pBIOSInfo->TVEncoder == VIA_VT1625) 456 Table = VT1625Table; 457 else 458 Table = VT1623Table; 459 460 for (i = 0; Table[i].Width; i++) { 461 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 462 "width=%d:%d, height=%d:%d, std=%d:%d, name=%s:%s.\n", 463 Table[i].Width, mode->CrtcHDisplay, 464 Table[i].Height, mode->CrtcVDisplay, 465 Table[i].Standard, pBIOSInfo->TVType, 466 Table[i].name, mode->name); 467 468 if ((Table[i].Width == mode->CrtcHDisplay) && 469 (Table[i].Height == mode->CrtcVDisplay) && 470 (Table[i].Standard == pBIOSInfo->TVType) && 471 !strcmp(Table[i].name, mode->name)) 472 return i; 473 } 474 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VT1622ModeIndex:" 475 " Mode \"%s\" not found in Table\n", mode->name); 476 return 0xFF; 477} 478 479static ModeStatus 480VT1622ModeValid(ScrnInfoPtr pScrn, DisplayModePtr mode) 481{ 482 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 483 484 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622ModeValid\n")); 485 486 if ((mode->PrivSize != sizeof(struct VT162xModePrivate)) || 487 ((mode->Private != (void *)&VT162xModePrivateNTSC) && 488 (mode->Private != (void *)&VT162xModePrivatePAL))) { 489 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 490 "Not a mode defined by the TV Encoder.\n"); 491 return MODE_BAD; 492 } 493 494 if ((pBIOSInfo->TVType == TVTYPE_NTSC) && 495 (mode->Private != (void *)&VT162xModePrivateNTSC)) { 496 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 497 "TV standard is NTSC. This is a PAL mode.\n"); 498 return MODE_BAD; 499 } else if ((pBIOSInfo->TVType == TVTYPE_PAL) && 500 (mode->Private != (void *)&VT162xModePrivatePAL)) { 501 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 502 "TV standard is PAL. This is a NTSC mode.\n"); 503 return MODE_BAD; 504 } 505 506 if (VT1622ModeIndex(pScrn, mode) != 0xFF) 507 return MODE_OK; 508 return MODE_BAD; 509} 510 511static ModeStatus 512VT1625ModeValid(ScrnInfoPtr pScrn, DisplayModePtr mode) 513{ 514 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 515 516 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1625ModeValid\n")); 517 518 if ((mode->PrivSize != sizeof(struct VT162xModePrivate)) || 519 ((mode->Private != (void *)&VT162xModePrivateNTSC) && 520 (mode->Private != (void *)&VT162xModePrivatePAL) && 521 (mode->Private != (void *)&VT162xModePrivate480P) && 522 (mode->Private != (void *)&VT162xModePrivate576P) && 523 (mode->Private != (void *)&VT162xModePrivate720P) && 524 (mode->Private != (void *)&VT162xModePrivate1080I))) { 525 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 526 "Not a mode defined by the TV Encoder.\n"); 527 return MODE_BAD; 528 } 529 530 if ((pBIOSInfo->TVType == TVTYPE_NTSC) && 531 (mode->Private != (void *)&VT162xModePrivateNTSC)) { 532 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 533 "TV standard is NTSC. This is an incompatible mode.\n"); 534 return MODE_BAD; 535 } else if ((pBIOSInfo->TVType == TVTYPE_PAL) && 536 (mode->Private != (void *)&VT162xModePrivatePAL)) { 537 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 538 "TV standard is PAL. This is an incompatible mode.\n"); 539 return MODE_BAD; 540 } else if ((pBIOSInfo->TVType == TVTYPE_480P) && 541 (mode->Private != (void *)&VT162xModePrivate480P)) { 542 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 543 "TV standard is 480P. This is an incompatible mode.\n"); 544 return MODE_BAD; 545 } else if ((pBIOSInfo->TVType == TVTYPE_576P) && 546 (mode->Private != (void *)&VT162xModePrivate576P)) { 547 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 548 "TV standard is 576P. This is an incompatible mode.\n"); 549 return MODE_BAD; 550 } else if ((pBIOSInfo->TVType == TVTYPE_720P) && 551 (mode->Private != (void *)&VT162xModePrivate720P)) { 552 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 553 "TV standard is 720P. This is an incompatible mode.\n"); 554 return MODE_BAD; 555 } else if ((pBIOSInfo->TVType == TVTYPE_1080I) && 556 (mode->Private != (void *)&VT162xModePrivate1080I)) { 557 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 558 "TV standard is 1080I. This is an incompatible mode.\n"); 559 return MODE_BAD; 560 } 561 562 if (VT1622ModeIndex(pScrn, mode) != 0xFF) 563 return MODE_OK; 564 return MODE_BAD; 565} 566 567 568static void 569VT162xSetSubCarrier(I2CDevPtr pDev, CARD32 SubCarrier) 570{ 571 xf86I2CWriteByte(pDev, 0x16, SubCarrier & 0xFF); 572 xf86I2CWriteByte(pDev, 0x17, (SubCarrier >> 8) & 0xFF); 573 xf86I2CWriteByte(pDev, 0x18, (SubCarrier >> 16) & 0xFF); 574 xf86I2CWriteByte(pDev, 0x19, (SubCarrier >> 24) & 0xFF); 575} 576 577static void 578VT1621ModeI2C(ScrnInfoPtr pScrn, DisplayModePtr mode) 579{ 580 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 581 struct VT1621TableRec Table = VT1621Table[VT1621ModeIndex(pScrn, mode)]; 582 CARD8 i; 583 584 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621ModeI2C\n")); 585 586 for (i = 0; i < 0x16; i++) 587 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV[i]); 588 589 VT162xSetSubCarrier(pBIOSInfo->TVI2CDev, Table.SubCarrier); 590 591 /* Skip reserved (1A) and version ID (1B). */ 592 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1C, Table.TV[0x1C]); 593 594 /* Skip software reset (1D). */ 595 for (i = 0x1E; i < 0x24; i++) 596 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV[i]); 597 598 /* Write some zeroes? */ 599 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x24, 0x00); 600 for (i = 0; i < 0x08; i++) 601 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4A + i, 0x00); 602 603 if (pBIOSInfo->TVOutput == TVOUTPUT_COMPOSITE) 604 for (i = 0; i < 0x10; i++) 605 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x52 + i, Table.TVC[i]); 606 else 607 for (i = 0; i < 0x10; i++) 608 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x52 + i, Table.TVS[i]); 609 610 /* Turn on all Composite and S-Video output. */ 611 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00); 612 613 if (pBIOSInfo->TVDotCrawl) { 614 if (Table.DotCrawlSubCarrier) { 615 xf86I2CReadByte(pBIOSInfo->TVI2CDev, 0x11, &i); 616 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x11, i | 0x08); 617 618 VT162xSetSubCarrier(pBIOSInfo->TVI2CDev, Table.DotCrawlSubCarrier); 619 } else 620 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "This mode does not currently " 621 "support DotCrawl suppression.\n"); 622 } 623} 624 625static void 626VT1621ModeCrtc(xf86CrtcPtr crtc, DisplayModePtr mode) 627{ 628 ScrnInfoPtr pScrn = crtc->scrn; 629 vgaHWPtr hwp = VGAHWPTR(pScrn); 630 VIAPtr pVia = VIAPTR(pScrn); 631 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 632 struct VT1621TableRec Table = VT1621Table[VT1621ModeIndex(pScrn, mode)]; 633 634 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621ModeCrtc\n")); 635 636 if (pVia->IsSecondary) { 637 hwp->writeCrtc(hwp, 0x6A, 0x80); 638 hwp->writeCrtc(hwp, 0x6B, 0x20); 639 hwp->writeCrtc(hwp, 0x6C, 0x80); 640 641 /* Disable LCD Scaling */ 642 if (!pVia->SAMM || pVia->FirstInit) 643 hwp->writeCrtc(hwp, 0x79, 0x00); 644 645 } else { 646 hwp->writeCrtc(hwp, 0x6A, 0x00); 647 hwp->writeCrtc(hwp, 0x6B, 0x80); 648 hwp->writeCrtc(hwp, 0x6C, Table.PrimaryCR6C); 649 } 650 pBIOSInfo->ClockExternal = TRUE; 651 ViaCrtcMask(hwp, 0x6A, 0x40, 0x40); 652 ViaCrtcMask(hwp, 0x6C, 0x01, 0x01); 653} 654 655/* 656 * Also suited for VT1622A, VT1623, VT1625. 657 */ 658static void 659VT1622ModeI2C(ScrnInfoPtr pScrn, DisplayModePtr mode) 660{ 661 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 662 struct VT162XTableRec Table; 663 CARD8 save, i; 664 665 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622ModeI2C\n")); 666 667 if (pBIOSInfo->TVEncoder == VIA_VT1622) 668 Table = VT1622Table[VT1622ModeIndex(pScrn, mode)]; 669 else if (pBIOSInfo->TVEncoder == VIA_VT1625) 670 Table = VT1625Table[VT1622ModeIndex(pScrn, mode)]; 671 else /* VT1622A/VT1623 */ 672 Table = VT1623Table[VT1622ModeIndex(pScrn, mode)]; 673 674 /* TV reset. */ 675 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1D, 0x00); 676 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1D, 0x80); 677 678 for (i = 0; i < 0x16; i++) 679 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV1[i]); 680 681 VT162xSetSubCarrier(pBIOSInfo->TVI2CDev, Table.SubCarrier); 682 683 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1A, Table.TV1[0x1A]); 684 685 /* Skip version ID. */ 686 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1C, Table.TV1[0x1C]); 687 688 /* Skip software reset. */ 689 for (i = 0x1E; i < 0x30; i++) 690 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV1[i]); 691 692 for (i = 0; i < 0x1B; i++) 693 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4A + i, Table.TV2[i]); 694 695 /* Turn on all Composite and S-Video output. */ 696 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00); 697 698 if (pBIOSInfo->TVDotCrawl) { 699 if (Table.DotCrawlSubCarrier) { 700 xf86I2CReadByte(pBIOSInfo->TVI2CDev, 0x11, &save); 701 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x11, save | 0x08); 702 703 VT162xSetSubCarrier(pBIOSInfo->TVI2CDev, Table.DotCrawlSubCarrier); 704 } else 705 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "This mode does not currently " 706 "support DotCrawl suppression.\n"); 707 } 708 709 if (pBIOSInfo->TVOutput == TVOUTPUT_RGB) { 710 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x2A); 711 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x65, Table.RGB[0]); 712 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x66, Table.RGB[1]); 713 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x67, Table.RGB[2]); 714 if (Table.RGB[3]) 715 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x27, Table.RGB[3]); 716 if (Table.RGB[4]) 717 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x2B, Table.RGB[4]); 718 if (Table.RGB[5]) 719 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x2C, Table.RGB[5]); 720 if (pBIOSInfo->TVEncoder == VIA_VT1625) { 721 if (pBIOSInfo->TVType < TVTYPE_480P) { 722 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x12); 723 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x23, 0x7E); 724 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4A, 0x85); 725 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4B, 0x0A); 726 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4E, 0x00); 727 } else { 728 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x12); 729 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4A, 0x85); 730 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4B, 0x0A); 731 } 732 } 733 } else if (pBIOSInfo->TVOutput == TVOUTPUT_YCBCR) { 734 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x02, 0x03); 735 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x65, Table.YCbCr[0]); 736 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x66, Table.YCbCr[1]); 737 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x67, Table.YCbCr[2]); 738 if (pBIOSInfo->TVEncoder == VIA_VT1625) { 739 if (pBIOSInfo->TVType < TVTYPE_480P) { 740 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x23, 0x7E); 741 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x4E, 0x00); 742 } 743 } 744 } 745 746 /* Configure flicker filter. */ 747 xf86I2CReadByte(pBIOSInfo->TVI2CDev, 0x03, &save); 748 save &= 0xFC; 749 if (pBIOSInfo->TVDeflicker == 1) 750 save |= 0x01; 751 else if (pBIOSInfo->TVDeflicker == 2) 752 save |= 0x02; 753 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x03, save); 754} 755 756/* 757 * Also suited for VT1622A, VT1623, VT1625. 758 */ 759static void 760VT1622ModeCrtc(xf86CrtcPtr crtc, DisplayModePtr mode) 761{ 762 ScrnInfoPtr pScrn = crtc->scrn; 763 vgaHWPtr hwp = VGAHWPTR(pScrn); 764 VIAPtr pVia = VIAPTR(pScrn); 765 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 766 struct VT162XTableRec Table; 767 768 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622ModeCrtc\n")); 769 770 if (pBIOSInfo->TVEncoder == VIA_VT1622) 771 Table = VT1622Table[VT1622ModeIndex(pScrn, mode)]; 772 else if (pBIOSInfo->TVEncoder == VIA_VT1625) 773 Table = VT1625Table[VT1622ModeIndex(pScrn, mode)]; 774 else /* VT1622A/VT1623 */ 775 Table = VT1623Table[VT1622ModeIndex(pScrn, mode)]; 776 777 hwp->writeCrtc(hwp, 0x6A, 0x00); 778 hwp->writeCrtc(hwp, 0x6B, 0x00); 779 hwp->writeCrtc(hwp, 0x6C, 0x00); 780 781 if (pVia->IsSecondary) { 782 hwp->writeCrtc(hwp, 0x6C, Table.SecondaryCR6C); 783 784 ViaCrtcMask(hwp, 0x6A, 0x80, 0x80); 785 ViaCrtcMask(hwp, 0x6C, 0x80, 0x80); 786 787 /* CLE266Ax use 2x XCLK. */ 788 if ((pVia->Chipset == VIA_CLE266) && CLE266_REV_IS_AX(pVia->ChipRev)) { 789 ViaCrtcMask(hwp, 0x6B, 0x20, 0x20); 790 791 /* Fix TV clock polarity for CLE266A2. */ 792 if (pVia->ChipRev == 0x02) 793 ViaCrtcMask(hwp, 0x6C, 0x1C, 0x1C); 794 } 795 796 /* Disable LCD scaling. */ 797 if (!pVia->SAMM || pVia->FirstInit) 798 hwp->writeCrtc(hwp, 0x79, 0x00); 799 800 } else { 801 if ((pVia->Chipset == VIA_CLE266) && CLE266_REV_IS_AX(pVia->ChipRev)) { 802 ViaCrtcMask(hwp, 0x6B, 0x80, 0x80); 803 804 /* Fix TV clock polarity for CLE266A2. */ 805 if (pVia->ChipRev == 0x02) 806 hwp->writeCrtc(hwp, 0x6C, Table.PrimaryCR6C); 807 } 808 } 809 pBIOSInfo->ClockExternal = TRUE; 810 ViaCrtcMask(hwp, 0x6A, 0x40, 0x40); 811 ViaSetTVClockSource(crtc); 812} 813 814 815static void 816VT1621Power(ScrnInfoPtr pScrn, Bool On) 817{ 818 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 819 820 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1621Power\n")); 821 822 if (On) 823 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00); 824 else 825 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x03); 826} 827 828static void 829VT1622Power(ScrnInfoPtr pScrn, Bool On) 830{ 831 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 832 833 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1622Power\n")); 834 835 if (On) 836 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00); 837 else 838 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x0F); 839} 840 841static void 842VT1625Power(ScrnInfoPtr pScrn, Bool On) 843{ 844 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 845 846 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VT1625Power\n")); 847 848 if (On) 849 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x00); 850 else 851 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x0E, 0x3F); 852} 853 854 855void 856ViaVT162xInit(ScrnInfoPtr pScrn) 857{ 858 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 859 860 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaVT162xInit\n")); 861 862 switch (pBIOSInfo->TVEncoder) { 863 case VIA_VT1621: 864 pBIOSInfo->TVSave = VT162xSave; 865 pBIOSInfo->TVRestore = VT162xRestore; 866 pBIOSInfo->TVDACSense = VT1621DACSense; 867 pBIOSInfo->TVModeValid = VT1621ModeValid; 868 pBIOSInfo->TVModeI2C = VT1621ModeI2C; 869 pBIOSInfo->TVModeCrtc = VT1621ModeCrtc; 870 pBIOSInfo->TVPower = VT1621Power; 871 pBIOSInfo->TVModes = VT1621Modes; 872 pBIOSInfo->TVNumModes = sizeof(VT1621Modes) / sizeof(DisplayModeRec); 873 pBIOSInfo->TVPrintRegs = VT162xPrintRegs; 874 pBIOSInfo->TVNumRegs = 0x68; 875 break; 876 case VIA_VT1622: 877 pBIOSInfo->TVSave = VT162xSave; 878 pBIOSInfo->TVRestore = VT162xRestore; 879 pBIOSInfo->TVDACSense = VT1622DACSense; 880 pBIOSInfo->TVModeValid = VT1622ModeValid; 881 pBIOSInfo->TVModeI2C = VT1622ModeI2C; 882 pBIOSInfo->TVModeCrtc = VT1622ModeCrtc; 883 pBIOSInfo->TVPower = VT1622Power; 884 pBIOSInfo->TVModes = VT1622Modes; 885 pBIOSInfo->TVNumModes = sizeof(VT1622Modes) / sizeof(DisplayModeRec); 886 pBIOSInfo->TVPrintRegs = VT162xPrintRegs; 887 pBIOSInfo->TVNumRegs = 0x68; 888 break; 889 case VIA_VT1623: 890 pBIOSInfo->TVSave = VT162xSave; 891 pBIOSInfo->TVRestore = VT162xRestore; 892 pBIOSInfo->TVDACSense = VT1622DACSense; 893 pBIOSInfo->TVModeValid = VT1622ModeValid; 894 pBIOSInfo->TVModeI2C = VT1622ModeI2C; 895 pBIOSInfo->TVModeCrtc = VT1622ModeCrtc; 896 pBIOSInfo->TVPower = VT1622Power; 897 pBIOSInfo->TVModes = VT1623Modes; 898 pBIOSInfo->TVNumModes = sizeof(VT1623Modes) / sizeof(DisplayModeRec); 899 pBIOSInfo->TVPrintRegs = VT162xPrintRegs; 900 pBIOSInfo->TVNumRegs = 0x6C; 901 break; 902 case VIA_VT1625: 903 pBIOSInfo->TVSave = VT162xSave; 904 pBIOSInfo->TVRestore = VT162xRestore; 905 pBIOSInfo->TVDACSense = VT1625DACSense; 906 pBIOSInfo->TVModeValid = VT1625ModeValid; 907 pBIOSInfo->TVModeI2C = VT1622ModeI2C; 908 pBIOSInfo->TVModeCrtc = VT1622ModeCrtc; 909 pBIOSInfo->TVPower = VT1625Power; 910 pBIOSInfo->TVModes = VT1625Modes; 911 pBIOSInfo->TVNumModes = sizeof(VT1625Modes) / sizeof(DisplayModeRec); 912 pBIOSInfo->TVPrintRegs = VT162xPrintRegs; 913 pBIOSInfo->TVNumRegs = 0x82; 914 break; 915 default: 916 break; 917 } 918} 919