1/* 2 * Copyright 2005 Terry Lewis. All Rights Reserved. 3 * Copyright 2005 Philip Langdale. All Rights Reserved. (CH7011 additions) 4 * Copyright 2004 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 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 * DEALINGS IN THE SOFTWARE. 26 */ 27 28#ifdef HAVE_CONFIG_H 29#include "config.h" 30#endif 31 32#include "via_driver.h" 33#include "via_ch7xxx.h" 34#include <unistd.h> 35 36#ifdef HAVE_DEBUG 37/* 38 * 39 */ 40static void 41CH7xxxPrintRegs(ScrnInfoPtr pScrn) 42{ 43 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 44 CARD8 i, buf; 45 46 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Printing registers for %s\n", 47 pBIOSInfo->TVI2CDev->DevName); 48 49 for (i = 0; i < pBIOSInfo->TVNumRegs; i++) { 50 xf86I2CReadByte(pBIOSInfo->TVI2CDev, i, &buf); 51 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV%02X: 0x%02X\n", i, buf); 52 } 53 54 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "End of TV registers.\n"); 55} 56#endif /* HAVE_DEBUG */ 57 58/* 59 * 60 */ 61I2CDevPtr 62ViaCH7xxxDetect(ScrnInfoPtr pScrn, I2CBusPtr pBus, CARD8 Address) 63{ 64 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 65 I2CDevPtr pDev = xf86CreateI2CDevRec(); 66 CARD8 buf; 67 68 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaCH7xxxDetect\n")); 69 70 pDev->DevName = "CH7xxx"; 71 pDev->SlaveAddr = Address; 72 pDev->pI2CBus = pBus; 73 74 if (!xf86I2CDevInit(pDev)) { 75 xf86DestroyI2CDevRec(pDev, TRUE); 76 return NULL; 77 } 78 79 if (!xf86I2CReadByte(pDev, 0x4B, &buf)) { 80 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unable to read from %s Slave %d.\n", 81 pBus->BusName, Address); 82 xf86DestroyI2CDevRec(pDev, TRUE); 83 return NULL; 84 } 85 86 switch (buf) { 87 case 0x17: 88 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected Chrontel CH7011 TV Encoder\n"); 89 pBIOSInfo->TVEncoder = VIA_CH7011; 90 pDev->DevName="CH7011"; 91 break; 92 case 0x19: 93 xf86I2CReadByte(pDev, 0x4A, &buf); 94 if (buf == 0x81) { 95 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected Chrontel CH7019A LVDS Transmitter/TV Encoder\n"); 96 pBIOSInfo->TVEncoder = VIA_CH7019A; 97 pDev->DevName="CH7019A"; 98 } else { 99 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected Chrontel CH7019B LVDS Transmitter/TV Encoder\n"); 100 pBIOSInfo->TVEncoder = VIA_CH7019B; 101 pDev->DevName="CH7019B"; 102 } 103 break; 104 case 0x1B: 105 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected Chrontel CH7017 LVDS Transmitter\n"); 106 pBIOSInfo->TVEncoder = VIA_CH7017; 107 pDev->DevName="CH7017"; 108 break; 109 case 0x3A: 110 /* single init table --> single channel LVDS transmitter ? */ 111 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected Chrontel CH7304 LVDS Transmitter\n"); 112 pBIOSInfo->TVEncoder = VIA_CH7304; 113 pDev->DevName="CH7304"; 114 break; 115 case 0x3B: 116 /* dual init table --> dual channel LVDS transmitter ? */ 117 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected Chrontel CH7305 LVDS Transmitter\n"); 118 pBIOSInfo->TVEncoder = VIA_CH7305; 119 pDev->DevName="CH7305"; 120 break; 121 default: 122 pBIOSInfo->TVEncoder = VIA_NONETV; 123 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown CH7xxx" 124 " device found. [%x:0x1B contains %x]\n", 125 Address, buf); 126 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Unknown CH7xxx encoder found\n"); 127 128 xf86DestroyI2CDevRec(pDev,TRUE); 129 pDev = NULL; 130 break; 131 } 132 return pDev; 133} 134 135/* 136 * 137 */ 138 139static void 140CH7xxxSave(ScrnInfoPtr pScrn) 141{ 142 int i; 143 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 144 145 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CH7xxxSave\n")); 146 147 for (i = 0; i < pBIOSInfo->TVNumRegs; i++) 148 xf86I2CReadByte(pBIOSInfo->TVI2CDev, i, &(pBIOSInfo->TVRegs[i])); 149} 150 151 152static void 153CH7xxxRestore(ScrnInfoPtr pScrn) 154{ 155 int i; 156 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 157 158 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CH7xxxRestore\n")); 159 160 for (i = 0; i < pBIOSInfo->TVNumRegs; i++) 161 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, pBIOSInfo->TVRegs[i]); 162} 163 164static CARD8 165CH7xxxDACSenseI2C(I2CDevPtr pDev) 166{ 167 CARD8 save, sense; 168 169 /* Turn all DACP on*/ 170 xf86I2CWriteByte(pDev, 0x49, 0x20); 171 172 /* Make sure Bypass mode is disabled (DACBP) bit0 is set to '0' */ 173 xf86I2CReadByte(pDev, 0x21, &save); 174 xf86I2CWriteByte(pDev, 0x21, save & ~0x01); 175 176 /* Set Sense bit0 to '1' */ 177 xf86I2CReadByte(pDev, 0x20, &save); 178 xf86I2CWriteByte(pDev, 0x20, save | 0x01); 179 180 /* Set Sense bit0 back to '0' */ 181 xf86I2CReadByte(pDev, 0x20, &save); 182 xf86I2CWriteByte(pDev, 0x20, save & ~0x01); 183 184 /* Read DACT status bits */ 185 xf86I2CReadByte(pDev, 0x20, &sense); 186 187 return (sense & 0x1F); 188} 189 190/* 191 * A CH7xxx hack. (T. Lewis. S-Video fixed by P. Langdale) 192 * 193 * CH7xxx Cable types (C+S and YcBcR untested and almost certainly wrong) 194 * 0x10 = Composite 195 * 0x0C = S-Video 196 * 0x02 = Composite+S-Video 197 * 0x04 = YcBcR 198 * 0x00 = Nothing Connected 199 */ 200 201static Bool 202CH7xxxDACSense(ScrnInfoPtr pScrn) 203{ 204 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 205 CARD8 sense; 206 207 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CH7xxxDACDetect\n")); 208 209 /* is this needed? IH */ 210 if (!pBIOSInfo->TVI2CDev || 211 !pBIOSInfo->TVEncoder) 212 return FALSE; 213 214 sense = CH7xxxDACSenseI2C(pBIOSInfo->TVI2CDev); 215 216 /* I'm sure these case values are correct, 217 * but we should get something in any case. 218 * 0x10 (Composite), 0x0C (S-Video) and 0x00 (Nothing connected) 219 * seem to be correct however. 220 */ 221 switch (sense) { 222 case 0x10: 223 pBIOSInfo->TVOutput = TVOUTPUT_COMPOSITE; 224 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CH7xxx: Composite connected.\n"); 225 return TRUE; 226 case 0x0C: 227 pBIOSInfo->TVOutput = TVOUTPUT_SVIDEO; 228 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CH7xxx: S-Video connected.\n"); 229 return TRUE; 230 case 0x02: 231 pBIOSInfo->TVOutput = TVOUTPUT_SC; 232 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CHxxx: Composite+S-Video connected.\n"); 233 return TRUE; 234 case 0x04: 235 pBIOSInfo->TVOutput = TVOUTPUT_YCBCR; 236 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CHxxx: YcBcR Connected.\n"); 237 return TRUE; 238 case 0x00: 239 pBIOSInfo->TVOutput = TVOUTPUT_NONE; 240 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CH7xxx: Nothing connected.\n"); 241 return FALSE; 242 default: 243 pBIOSInfo->TVOutput = TVOUTPUT_NONE; 244 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "CH7xxx: Unknown cable combination: 0x0%2X.\n",sense); 245 return FALSE; 246 } 247} 248 249static CARD8 250CH7011ModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode) 251{ 252 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 253 int i; 254 255 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CH7011ModeIndex\n")); 256 for (i = 0; CH7011Table[i].Width; i++) { 257 if ((CH7011Table[i].Width == mode->CrtcHDisplay) && 258 (CH7011Table[i].Height == mode->CrtcVDisplay) && 259 (CH7011Table[i].Standard == pBIOSInfo->TVType) && 260 !(strcmp(CH7011Table[i].name, mode->name))) 261 return i; 262 } 263 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "CH7011ModeIndex:" 264 " Mode \"%s\" not found in Table\n", mode->name); 265 return 0xFF; 266} 267 268static CARD8 269CH7019ModeIndex(ScrnInfoPtr pScrn, DisplayModePtr mode) 270{ 271 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 272 int i; 273 274 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CH7019ModeIndex\n")); 275 for (i = 0; CH7019Table[i].Width; i++) { 276 if ((CH7019Table[i].Width == mode->CrtcHDisplay) && 277 (CH7019Table[i].Height == mode->CrtcVDisplay) && 278 (CH7019Table[i].Standard == pBIOSInfo->TVType) && 279 !(strcmp(CH7019Table[i].name, mode->name))) 280 return i; 281 } 282 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "CH7019ModeIndex:" 283 " Mode \"%s\" not found in Table\n", mode->name); 284 return 0xFF; 285} 286 287/* 288 * 289 */ 290static ModeStatus 291CH7xxxModeValid(ScrnInfoPtr pScrn, DisplayModePtr mode) 292{ 293 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 294 295 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CH7xxxModeValid\n")); 296 297 if ((mode->PrivSize != sizeof(struct CH7xxxModePrivate)) || 298 ((mode->Private != (void *) &CH7xxxModePrivateNTSC) && 299 (mode->Private != (void *) &CH7xxxModePrivatePAL))) { 300 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Not a mode defined by the TV Encoder.\n"); 301 return MODE_BAD; 302 } 303 304 if ((pBIOSInfo->TVType == TVTYPE_NTSC) && 305 (mode->Private != (void *) &CH7xxxModePrivateNTSC)) { 306 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standard is NTSC. This is a PAL mode.\n"); 307 return MODE_BAD; 308 } else if ((pBIOSInfo->TVType == TVTYPE_PAL) && 309 (mode->Private != (void *) &CH7xxxModePrivatePAL)) { 310 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "TV standard is PAL. This is a NTSC mode.\n"); 311 return MODE_BAD; 312 } 313 314 if (pBIOSInfo->TVEncoder == VIA_CH7011) 315 { 316 if (CH7011ModeIndex(pScrn, mode) != 0xFF) 317 return MODE_OK; 318 } 319 else 320 { 321 if (CH7019ModeIndex(pScrn, mode) != 0xFF) 322 return MODE_OK; 323 } 324 return MODE_BAD; 325} 326 327static void 328CH7xxxModeI2C(ScrnInfoPtr pScrn, DisplayModePtr mode) 329{ 330 VIAPtr pVia = VIAPTR(pScrn); 331 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 332 333 CARD8 i, j; 334 335 VIABIOSTVMASKTableRec Mask; 336 struct CH7xxxTableRec Table; 337 338 if (pBIOSInfo->TVEncoder == VIA_CH7011) 339 { 340 Table = CH7011Table[CH7011ModeIndex(pScrn, mode)]; 341 Mask = ch7011MaskTable; 342 } 343 else 344 { 345 Table = CH7019Table[CH7019ModeIndex(pScrn, mode)]; 346 Mask = ch7019MaskTable; 347 } 348 349 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CH7011ModeI2C\n")); 350 351 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x49, 0x3E); 352 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1E, 0xD0); 353 354 for (i = 0,j = 0; (j < Mask.numTV) && (i < VIA_BIOS_TABLE_NUM_TV_REG); i++) { 355 if (Mask.TV[i] == 0xFF) { 356 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, Table.TV[i]); 357 j++; 358 } else { 359 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, i, pBIOSInfo->TVRegs[i]); 360 } 361 } 362 363 if ((pBIOSInfo->TVType == TVTYPE_NTSC) && pBIOSInfo->TVDotCrawl) { 364 CARD16 *DotCrawl = Table.DotCrawlNTSC; 365 CARD8 address, save; 366 367 for (i = 1; i < (DotCrawl[0] + 1); i++) { 368 address = (CARD8)(DotCrawl[i] & 0xFF); 369 370 save = (CARD8)(DotCrawl[i] >> 8); 371 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, address, save); 372 } 373 } 374 375 /* 376 * Only Composite and SVideo have been tested. 377 */ 378 switch(pBIOSInfo->TVOutput){ 379 case TVOUTPUT_COMPOSITE: 380 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x49, 0x2E); 381 break; 382 case TVOUTPUT_SVIDEO: 383 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x49, 0x32); 384 break; 385 case TVOUTPUT_SC: 386 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x49, 0x3C); 387 break; 388 case TVOUTPUT_YCBCR: 389 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x49, 0x3A); 390 break; 391 default: 392 break; 393 } 394 395 if (pVia->IsSecondary) { /* Patch as setting 2nd path */ 396 j = (CARD8)(Mask.misc2 >> 5); 397 for (i = 0; i < j; i++) 398 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, Table.Patch2[i] & 0xFF, Table.Patch2[i] >> 8); 399 } 400} 401 402static void 403CH7xxxModeCrtc(xf86CrtcPtr crtc, DisplayModePtr mode) 404{ 405 ScrnInfoPtr pScrn = crtc->scrn; 406 vgaHWPtr hwp = VGAHWPTR(pScrn); 407 VIAPtr pVia = VIAPTR(pScrn); 408 VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo; 409 CARD8 *CRTC, *Misc; 410 int i, j; 411 412 VIABIOSTVMASKTableRec Mask; 413 struct CH7xxxTableRec Table; 414 415 if (pBIOSInfo->TVEncoder == VIA_CH7011) 416 { 417 Table = CH7011Table[CH7011ModeIndex(pScrn, mode)]; 418 Mask = ch7011MaskTable; 419 } 420 else 421 { 422 Table = CH7019Table[CH7019ModeIndex(pScrn, mode)]; 423 Mask = ch7019MaskTable; 424 } 425 426 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CH7xxxModeCrtc\n")); 427 428 if (pVia->IsSecondary) { 429 switch (pScrn->bitsPerPixel) { 430 case 16: 431 CRTC = Table.CRTC2_16BPP; 432 break; 433 case 24: 434 case 32: 435 CRTC = Table.CRTC2_32BPP; 436 break; 437 case 8: 438 default: 439 CRTC = Table.CRTC2_8BPP; 440 break; 441 } 442 Misc = Table.Misc2; 443 444 for (i = 0, j = 0; i < Mask.numCRTC2; j++) { 445 if (Mask.CRTC2[j] == 0xFF) { 446 hwp->writeCrtc(hwp, j + 0x50, CRTC[j]); 447 i++; 448 } 449 } 450 451 if (Mask.misc2 & 0x18) { 452 pBIOSInfo->Clock = (Misc[3] << 8) & Misc[4]; 453 /* VIASetUseExternalClock(hwp); */ 454 } 455 456 ViaCrtcMask(hwp, 0x6A, 0xC0, 0xC0); 457 ViaCrtcMask(hwp, 0x6B, 0x01, 0x01); 458 ViaCrtcMask(hwp, 0x6C, 0x01, 0x01); 459 460 /* Disable LCD Scaling */ 461 if (!pVia->SAMM || pVia->FirstInit) 462 hwp->writeCrtc(hwp, 0x79, 0x00);} 463 else { 464 465 CRTC = Table.CRTC1; 466 Misc = Table.Misc1; 467 468 for (i = 0, j = 0; i < Mask.numCRTC1; j++) { 469 if (Mask.CRTC1[j] == 0xFF) { 470 hwp->writeCrtc(hwp, j, CRTC[j]); 471 i++; 472 } 473 } 474 475 ViaCrtcMask(hwp, 0x33, Misc[0], 0x20); 476 hwp->writeCrtc(hwp, 0x6A, Misc[1]); 477 478 if ((pVia->Chipset == VIA_CLE266) && 479 CLE266_REV_IS_AX(pVia->ChipRev)) { 480 hwp->writeCrtc(hwp, 0x6B, Misc[2] | 0x81); 481 /* Fix TV clock Polarity for CLE266A2 */ 482 if (pVia->ChipRev == 0x02) 483 hwp->writeCrtc(hwp, 0x6C, Misc[3] | 0x01); 484 } else 485 hwp->writeCrtc(hwp, 0x6B, Misc[2] | 0x01); 486 487 if (Mask.misc1 & 0x30) { 488 /* CLE266Ax use 2x XCLK */ 489 if ((pVia->Chipset == VIA_CLE266) && 490 CLE266_REV_IS_AX(pVia->ChipRev)) 491 pBIOSInfo->Clock = 0x471C; 492 else 493 pBIOSInfo->Clock = (Misc[4] << 8) | Misc[5]; 494 } 495 496 ViaCrtcMask(hwp, 0x6A, 0x40, 0x40); 497 ViaCrtcMask(hwp, 0x6B, 0x01, 0x01); 498 ViaCrtcMask(hwp, 0x6C, 0x01, 0x01); 499 } 500 501 ViaSeqMask(hwp, 0x1E, 0xC0, 0xC0); /* Enable DI0/DVP0 */ 502} 503 504 505/* 506 * 507 */ 508static void 509CH7xxxTVPower(ScrnInfoPtr pScrn, Bool On) 510{ 511 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 512 513 if (On){ 514 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CH7xxxTVPower: On\n")); 515 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x49, 0x20); 516 }else{ 517 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CH7xxxTVPower: Off\n")); 518 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x49, 0x3E); 519 xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1E, 0xD0); 520 } 521} 522 523static void 524CH7019LCDPower(ScrnInfoPtr pScrn, Bool On) 525{ 526 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 527 CARD8 W_Buffer[2], R_Buffer[1]; 528 int i; 529 530 if (On){ 531 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CH7xxxLCDPower: On\n")); 532 W_Buffer[0] = 0x63; 533 W_Buffer[1] = 0x4B; 534 xf86I2CWriteRead(pBIOSInfo->TVI2CDev, W_Buffer,2, NULL,0); 535 W_Buffer[0] = 0x66; 536 W_Buffer[1] = 0x20; 537 xf86I2CWriteRead(pBIOSInfo->TVI2CDev, W_Buffer,2, NULL,0); 538 539 for (i = 0; i < 10; i++) { 540 W_Buffer[0] = 0x63; 541 xf86I2CWriteRead(pBIOSInfo->TVI2CDev, W_Buffer,1, R_Buffer,1); 542 usleep(100); 543 W_Buffer[0] = 0x63; 544 W_Buffer[1] = (R_Buffer[0] | 0x40); 545 xf86I2CWriteRead(pBIOSInfo->TVI2CDev, W_Buffer,2, NULL,0); 546 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 547 "CH7xxxLCDPower: [%d]write 0x63 = %X!\n", i+1, W_Buffer[1])); 548 usleep(1); 549 W_Buffer[0] = 0x63; 550 W_Buffer[1] &= ~0x40; 551 xf86I2CWriteRead(pBIOSInfo->TVI2CDev, W_Buffer,2, NULL,0); 552 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 553 "CH7xxxLCDPower: [%d]write 0x63 = %X!\n", i+1, W_Buffer[1])); 554 usleep(100); 555 W_Buffer[0] = 0x66; 556 xf86I2CWriteRead(pBIOSInfo->TVI2CDev, W_Buffer,1, R_Buffer,1); 557 558 if (((R_Buffer[0] & 0x44) == 0x44) || (i >= 9)) { 559 /* PLL lock OK, Turn on VDD */ 560 usleep(500); 561 W_Buffer[1] = R_Buffer[0] | 0x01; 562 xf86I2CWriteRead(pBIOSInfo->TVI2CDev, W_Buffer,2, NULL,0); 563 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 564 "CH7xxxLCDPower: CH7019 PLL lock ok!\n")); 565 /* reset data path */ 566 W_Buffer[0] = 0x48; 567 xf86I2CWriteRead(pBIOSInfo->TVI2CDev, W_Buffer,1, R_Buffer,1); 568 W_Buffer[1] = R_Buffer[0] & ~0x08; 569 xf86I2CWriteRead(pBIOSInfo->TVI2CDev, W_Buffer,2, NULL,0); 570 usleep(1); 571 W_Buffer[1] = R_Buffer[0]; 572 xf86I2CWriteRead(pBIOSInfo->TVI2CDev, W_Buffer,2, NULL,0); 573 break; 574 } 575 576 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 577 "CH7xxxLCDPower: [%d]CH7019 PLL lock fail!\n", i+1)); 578 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 579 "CH7xxxLCDPower: [%d]0x66 = %X!\n", i+1, R_Buffer[0])); 580 } 581 }else{ 582 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CH7xxxLCDPower: Off\n")); 583 /* Turn off VDD (Turn off backlignt only) */ 584 W_Buffer[0] = 0x66; 585 xf86I2CWriteRead(pBIOSInfo->TVI2CDev, W_Buffer,1, R_Buffer,1); 586 W_Buffer[1] &= ~0x01; 587 xf86I2CWriteRead(pBIOSInfo->TVI2CDev, W_Buffer,2, NULL,0); 588 usleep(100); 589 /* Turn off LVDS path */ 590 W_Buffer[0] = 0x63; 591 xf86I2CWriteRead(pBIOSInfo->TVI2CDev, W_Buffer,1, R_Buffer,1); 592 W_Buffer[1] = (R_Buffer[0] | 0x40); 593 xf86I2CWriteRead(pBIOSInfo->TVI2CDev, W_Buffer,2, NULL,0); 594 } 595} 596 597/* 598 * 599 */ 600void 601ViaCH7xxxInit(ScrnInfoPtr pScrn) 602{ 603 VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo; 604 605 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaCH7xxxInit\n")); 606 607 switch (pBIOSInfo->TVEncoder) { 608 case VIA_CH7011: 609 pBIOSInfo->TVSave = CH7xxxSave; 610 pBIOSInfo->TVRestore = CH7xxxRestore; 611 pBIOSInfo->TVDACSense = CH7xxxDACSense; 612 pBIOSInfo->TVModeValid = CH7xxxModeValid; 613 pBIOSInfo->TVModeI2C = CH7xxxModeI2C; 614 pBIOSInfo->TVModeCrtc = CH7xxxModeCrtc; 615 pBIOSInfo->TVPower = CH7xxxTVPower; 616 pBIOSInfo->TVModes = CH7011Modes; 617 pBIOSInfo->TVNumModes = sizeof(CH7011Modes) / sizeof(DisplayModeRec); 618 pBIOSInfo->LCDPower = NULL; 619 pBIOSInfo->TVNumRegs = CH_7011_MAX_NUM_REG; 620#ifdef HAVE_DEBUG 621 pBIOSInfo->TVPrintRegs = CH7xxxPrintRegs; 622#endif 623 break; 624 case VIA_CH7019A: 625 case VIA_CH7019B: 626 pBIOSInfo->TVDACSense = CH7xxxDACSense; 627 pBIOSInfo->TVSave = CH7xxxSave; 628 pBIOSInfo->TVRestore = CH7xxxRestore; 629 pBIOSInfo->TVModeValid = CH7xxxModeValid; 630 pBIOSInfo->TVModeI2C = CH7xxxModeI2C; 631 pBIOSInfo->TVModeCrtc = CH7xxxModeCrtc; 632 pBIOSInfo->TVPower = CH7xxxTVPower; 633 pBIOSInfo->TVModes = CH7019Modes; 634 pBIOSInfo->TVNumModes = sizeof(CH7019Modes) / sizeof(DisplayModeRec); 635 pBIOSInfo->LCDPower = CH7019LCDPower; 636 pBIOSInfo->TVNumRegs = CH_7019_MAX_NUM_REG; 637#ifdef HAVE_DEBUG 638 pBIOSInfo->TVPrintRegs = CH7xxxPrintRegs; 639#endif 640 break; 641 default: 642 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ViaCH7xxxInit missing\n")); 643 break; 644 } 645 646 /* Save before continuing */ 647 if (pBIOSInfo->TVSave) 648 pBIOSInfo->TVSave(pScrn); 649} 650