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 */
40 static void
CH7xxxPrintRegs(ScrnInfoPtr pScrn)41 CH7xxxPrintRegs(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 */
61 I2CDevPtr
ViaCH7xxxDetect(ScrnInfoPtr pScrn,I2CBusPtr pBus,CARD8 Address)62 ViaCH7xxxDetect(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
139 static void
CH7xxxSave(ScrnInfoPtr pScrn)140 CH7xxxSave(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
152 static void
CH7xxxRestore(ScrnInfoPtr pScrn)153 CH7xxxRestore(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
164 static CARD8
CH7xxxDACSenseI2C(I2CDevPtr pDev)165 CH7xxxDACSenseI2C(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
201 static Bool
CH7xxxDACSense(ScrnInfoPtr pScrn)202 CH7xxxDACSense(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
249 static CARD8
CH7011ModeIndex(ScrnInfoPtr pScrn,DisplayModePtr mode)250 CH7011ModeIndex(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
268 static CARD8
CH7019ModeIndex(ScrnInfoPtr pScrn,DisplayModePtr mode)269 CH7019ModeIndex(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 */
290 static ModeStatus
CH7xxxModeValid(ScrnInfoPtr pScrn,DisplayModePtr mode)291 CH7xxxModeValid(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
327 static void
CH7xxxModeI2C(ScrnInfoPtr pScrn,DisplayModePtr mode)328 CH7xxxModeI2C(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
402 static void
CH7xxxModeCrtc(xf86CrtcPtr crtc,DisplayModePtr mode)403 CH7xxxModeCrtc(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 */
508 static void
CH7xxxTVPower(ScrnInfoPtr pScrn,Bool On)509 CH7xxxTVPower(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
523 static void
CH7019LCDPower(ScrnInfoPtr pScrn,Bool On)524 CH7019LCDPower(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 */
600 void
ViaCH7xxxInit(ScrnInfoPtr pScrn)601 ViaCH7xxxInit(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