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