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