1 /*
2 * Copyright 2016 Kevin Brace
3 * Copyright 2015-2016 The OpenChrome Project
4 * [https://www.freedesktop.org/wiki/Openchrome]
5 * Copyright 2014 SHS SERVICES GmbH
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sub license,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 */
26
27 /*
28 * via_tmds.c
29 *
30 * Handles initialization of TMDS (DVI) related resources and
31 * controls the integrated TMDS transmitter found in CX700 and
32 * later VIA Technologies chipsets.
33 *
34 */
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include <unistd.h>
41 #include "via_driver.h"
42 #include "via_vt1632.h"
43 #include "via_sii164.h"
44
45
46 /*
47 1. Formula:
48 2^13 X 0.0698uSec [1/14.318MHz] = 8192 X 0.0698uSec =572.1uSec
49 Timer = Counter x 572 uSec
50 2. Note:
51 0.0698 uSec is too small to compute for hardware. So we multiply a
52 reference value(2^13) to make it big enough to compute for hardware.
53 3. Note:
54 The meaning of the TD0~TD3 are count of the clock.
55 TD(sec) = (sec)/(per clock) x (count of clocks)
56 */
57 #define TD0 200
58 #define TD1 25
59 #define TD2 0
60 #define TD3 25
61
62
63 /*
64 * Initializes most registers related to VIA Technologies IGP
65 * integrated TMDS transmitter. Synchronization polarity and
66 * display output source need to be set separately. */
67 static void
viaTMDSInitRegisters(ScrnInfoPtr pScrn)68 viaTMDSInitRegisters(ScrnInfoPtr pScrn)
69 {
70 vgaHWPtr hwp = VGAHWPTR(pScrn);
71
72 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
73 "Entered viaTMDSInitRegisters.\n"));
74
75 /* Activate DVI + LVDS2 mode. */
76 /* 3X5.D2[5:4] - Display Channel Select
77 * 00: LVDS1 + LVDS2
78 * 01: DVI + LVDS2
79 * 10: One Dual LVDS Channel (High Resolution Pannel)
80 * 11: Single Channel DVI */
81 ViaCrtcMask(hwp, 0xD2, 0x10, 0x30);
82
83 /* Various DVI PLL settings should be set to default settings. */
84 /* 3X5.D1[7] - PLL2 Reference Clock Edge Select Bit
85 * 0: PLLCK lock to rising edge of reference clock
86 * 1: PLLCK lock to falling edge of reference clock
87 * 3X5.D1[6:5] - PLL2 Charge Pump Current Set Bits
88 * 00: ICH = 12.5 uA
89 * 01: ICH = 25.0 uA
90 * 10: ICH = 37.5 uA
91 * 11: ICH = 50.0 uA
92 * 3X5.D1[4:1] - Reserved
93 * 3X5.D1[0] - PLL2 Control Voltage Measurement Enable Bit */
94 ViaCrtcMask(hwp, 0xD1, 0x00, 0xE1);
95
96 /* Disable DVI test mode. */
97 /* 3X5.D5[7] - PD1 Enable Selection
98 * 1: Select by power flag
99 * 0: By register
100 * 3X5.D5[5] - DVI Testing Mode Enable
101 * 3X5.D5[4] - DVI Testing Format Selection
102 * 0: Half cycle
103 * 1: LFSR mode */
104 ViaCrtcMask(hwp, 0xD5, 0x00, 0xB0);
105
106 /* Disable DVI sense interrupt. */
107 /* 3C5.2B[7] - DVI Sense Interrupt Enable
108 * 0: Disable
109 * 1: Enable */
110 ViaSeqMask(hwp, 0x2B, 0x00, 0x80);
111
112 /* Clear DVI sense interrupt status. */
113 /* 3C5.2B[6] - DVI Sense Interrupt Status
114 * (This bit has a RW1C attribute.) */
115 ViaSeqMask(hwp, 0x2B, 0x40, 0x40);
116
117 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
118 "Exiting viaTMDSInitRegisters.\n"));
119 }
120
121 /*
122 * Sets the polarity of horizontal synchronization and vertical
123 * synchronization.
124 */
125 static void
viaTMDSSetSyncPolarity(ScrnInfoPtr pScrn,DisplayModePtr mode)126 viaTMDSSetSyncPolarity(ScrnInfoPtr pScrn, DisplayModePtr mode)
127 {
128 vgaHWPtr hwp = VGAHWPTR(pScrn);
129 CARD8 cr97;
130
131 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
132 "Entered viaTMDSSetSyncPolarity.\n"));
133
134 /* 3X5.97[6] - DVI (TMDS) VSYNC Polarity
135 * 0: Positive
136 * 1: Negative
137 * 3X5.97[5] - DVI (TMDS) HSYNC Polarity
138 * 0: Positive
139 * 1: Negative */
140 cr97 = hwp->readCrtc(hwp, 0x97);
141 if (mode->Flags & V_NHSYNC) {
142 cr97 |= 0x20;
143 } else {
144 cr97 &= (~0x20);
145 }
146
147 if (mode->Flags & V_NVSYNC) {
148 cr97 |= 0x40;
149 } else {
150 cr97 &= (~0x40);
151 }
152
153 ViaCrtcMask(hwp, 0x97, cr97, 0x60);
154
155 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
156 "Exiting viaTMDSSetSyncPolarity.\n"));
157 }
158
159 /*
160 * Sets IGA1 or IGA2 as the display output source for VIA Technologies IGP
161 * integrated TMDS transmitter.
162 */
163 static void
viaTMDSSetSource(ScrnInfoPtr pScrn,CARD8 displaySource)164 viaTMDSSetSource(ScrnInfoPtr pScrn, CARD8 displaySource)
165 {
166 vgaHWPtr hwp = VGAHWPTR(pScrn);
167 CARD8 temp = displaySource;
168
169 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
170 "Entered viaTMDSSetSource.\n"));
171
172 /* Set integrated TMDS transmitter display output source.
173 * The integrated TMDS transmitter appears to utilize LVDS1's data
174 * source selection bit (3X5.99[4]). */
175 /* 3X5.99[4] - LVDS Channel1 Data Source Selection
176 * 0: Primary Display
177 * 1: Secondary Display */
178 ViaCrtcMask(hwp, 0x99, temp << 4, 0x10);
179 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
180 "Integrated TMDS Transmitter Display Output Source: IGA%d\n",
181 (temp & 0x01) + 1);
182
183 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
184 "Exiting viaTMDSSetSource.\n"));
185 }
186
187 /*
188 * Returns TMDS receiver detection state for VIA Technologies IGP
189 * integrated TMDS transmitter.
190 */
191 static Bool
viaTMDSSense(ScrnInfoPtr pScrn)192 viaTMDSSense(ScrnInfoPtr pScrn)
193 {
194 vgaHWPtr hwp = VGAHWPTR(pScrn);
195 VIAPtr pVia = VIAPTR(pScrn);
196 CARD8 tmdsReceiverDetected = 0x00;
197
198 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
199 "Entered viaTMDSSense.\n"));
200
201 /* For now, faking DVI detection.*/
202 tmdsReceiverDetected = 0x01;
203
204 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
205 "Integrated TMDS transmitter %s a TMDS receiver.\n",
206 (tmdsReceiverDetected & 0x01) ? "detected" : "did not detect");
207
208 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
209 "Exiting viaTMDSSense.\n"));
210 return tmdsReceiverDetected;
211 }
212
213 static void
viaTMDSPower(ScrnInfoPtr pScrn,Bool powerState)214 viaTMDSPower(ScrnInfoPtr pScrn, Bool powerState)
215 {
216 vgaHWPtr hwp = VGAHWPTR(pScrn);
217
218 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
219 "Entered viaTMDSPower.\n"));
220
221 if (powerState) {
222 /* 3X5.91[7] - Software Direct On / Off Display Period
223 in the Panel Path
224 0: On
225 1: Off */
226 ViaCrtcMask(hwp, 0x91, 0x00, 0x80);
227
228 /* 3X5.91[0] - Hardware or Software Control Power Sequence
229 1: Software Control */
230 ViaCrtcMask(hwp, 0x91, 0x01, 0x01);
231
232 usleep(TD0);
233
234 /* 3X5.91[4] - Software VDD On
235 0: Off
236 1: On */
237 ViaCrtcMask(hwp, 0x91, 0x10, 0x10);
238
239 usleep(TD1);
240
241 /* 3X5.91[3] - Software Data On
242 0: Off
243 1: On */
244 ViaCrtcMask(hwp, 0x91, 0x08, 0x08);
245
246 /* 3X5.D2[3] - Power Down (Active High) for DVI
247 * 0: TMDS power on
248 * 1: TMDS power down */
249 ViaCrtcMask(hwp, 0xD2, 0x00, 0x08);
250 } else {
251 ViaCrtcMask(hwp, 0xD2, 0x08, 0x08);
252
253 ViaCrtcMask(hwp, 0x91, 0x00, 0x08);
254
255 usleep(TD1);
256
257 ViaCrtcMask(hwp, 0x91, 0x00, 0x10);
258 }
259
260 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
261 "Integrated TMDS (DVI) Power: %s\n",
262 powerState ? "On" : "Off");
263
264 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
265 "Exiting viaTMDSPower.\n"));
266 }
267
268 static void
viaTMDSIOPadSetting(ScrnInfoPtr pScrn,Bool ioPadOn)269 viaTMDSIOPadSetting(ScrnInfoPtr pScrn, Bool ioPadOn)
270 {
271 vgaHWPtr hwp = VGAHWPTR(pScrn);
272 VIAPtr pVia = VIAPTR(pScrn);
273 CARD8 sr12, sr13, sr5a;
274
275 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
276 "Entered viaTMDSIOPadSetting.\n"));
277
278 if ((pVia->Chipset == VIA_CX700)
279 || (pVia->Chipset == VIA_VX800)
280 || (pVia->Chipset == VIA_VX855)
281 || (pVia->Chipset == VIA_VX900)) {
282
283 sr5a = hwp->readSeq(hwp, 0x5A);
284 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
285 "SR5A: 0x%02X\n", sr5a));
286 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
287 "Setting 3C5.5A[0] to 0.\n"));
288 ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01);
289 }
290
291 sr12 = hwp->readSeq(hwp, 0x12);
292 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
293 "SR12: 0x%02X\n", sr12));
294 sr13 = hwp->readSeq(hwp, 0x13);
295 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
296 "SR13: 0x%02X\n", sr13));
297
298 switch (pVia->Chipset) {
299 case VIA_CX700:
300 case VIA_VX800:
301 case VIA_VX855:
302 case VIA_VX900:
303 /* 3C5.13[7:6] - DVP1D15 and DVP1D14 pin strappings
304 * 00: LVDS1 + LVDS2
305 * 01: DVI + LVDS2
306 * 10: Dual LVDS (LVDS1 + LVDS2 used
307 * simultaneously)
308 * 11: DVI only */
309 if ((((~(sr13 & 0x80)) && (sr13 & 0x40))
310 || ((sr13 & 0x80) && (sr13 & 0x40)))
311 || (pVia->isVIANanoBook)) {
312
313 viaLVDS1SetIOPadSetting(pScrn, ioPadOn ? 0x03 : 0x00);
314 }
315
316 break;
317 default:
318 break;
319 }
320
321 if ((pVia->Chipset == VIA_CX700)
322 || (pVia->Chipset == VIA_VX800)
323 || (pVia->Chipset == VIA_VX855)
324 || (pVia->Chipset == VIA_VX900)) {
325
326 hwp->writeSeq(hwp, 0x5A, sr5a);
327 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
328 "Restoring 3C5.5A[0].\n"));
329 }
330
331 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
332 "Exiting viaTMDSIOPadSetting.\n"));
333 }
334
335 void
viaExtTMDSSetDisplaySource(ScrnInfoPtr pScrn,CARD8 displaySource)336 viaExtTMDSSetDisplaySource(ScrnInfoPtr pScrn, CARD8 displaySource)
337 {
338 vgaHWPtr hwp = VGAHWPTR(pScrn);
339 VIAPtr pVia = VIAPTR(pScrn);
340 CARD8 sr12, sr13, sr5a;
341
342 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
343 "Entered viaExtTMDSSetDisplaySource.\n"));
344
345 if ((pVia->Chipset == VIA_CX700)
346 || (pVia->Chipset == VIA_VX800)
347 || (pVia->Chipset == VIA_VX855)
348 || (pVia->Chipset == VIA_VX900)) {
349
350 sr5a = hwp->readSeq(hwp, 0x5A);
351 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
352 "SR5A: 0x%02X\n", sr5a));
353 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
354 "Setting 3C5.5A[0] to 0.\n"));
355 ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01);
356 }
357
358 sr12 = hwp->readSeq(hwp, 0x12);
359 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
360 "SR12: 0x%02X\n", sr12));
361 sr13 = hwp->readSeq(hwp, 0x13);
362 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
363 "SR13: 0x%02X\n", sr13));
364 switch (pVia->Chipset) {
365 case VIA_CLE266:
366 /* 3C5.12[5] - FPD18 pin strapping
367 * 0: DIP0 (Digital Interface Port 0) is used by
368 * a TMDS transmitter (DVI)
369 * 1: DIP0 (Digital Interface Port 0) is used by
370 * a TV encoder */
371 if (!(sr12 & 0x20)) {
372 viaDIP0SetDisplaySource(pScrn, displaySource);
373 } else {
374 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
375 "DIP0 was not set up for "
376 "TMDS transmitter use.\n");
377 }
378
379 break;
380 case VIA_KM400:
381 case VIA_K8M800:
382 case VIA_PM800:
383 case VIA_P4M800PRO:
384 /* 3C5.13[3] - DVP0D8 pin strapping
385 * 0: AGP pins are used for AGP
386 * 1: AGP pins are used by FPDP
387 * (Flat Panel Display Port)
388 * 3C5.12[6] - DVP0D6 pin strapping
389 * 0: Disable DVP0 (Digital Video Port 0)
390 * 1: Enable DVP0 (Digital Video Port 0)
391 * 3C5.12[5] - DVP0D5 pin strapping
392 * 0: DVP0 is used by a TMDS transmitter (DVI)
393 * 1: DVP0 is used by a TV encoder
394 * 3C5.12[4] - DVP0D4 pin strapping
395 * 0: Dual 12-bit FPDP (Flat Panel Display Port)
396 * 1: 24-bit FPDP (Flat Panel Display Port) */
397 if ((sr12 & 0x40) && (!(sr12 & 0x20))) {
398 viaDVP0SetDisplaySource(pScrn, displaySource);
399 } else if ((sr13 & 0x08) && (!(sr12 & 0x10))) {
400 viaDFPLowSetDisplaySource(pScrn, displaySource);
401 } else {
402 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
403 "None of the external ports were set up for "
404 "TMDS transmitter use.\n");
405 }
406
407 break;
408 case VIA_P4M890:
409 case VIA_K8M890:
410 case VIA_P4M900:
411 /* 3C5.12[6] - FPD6 pin strapping
412 * 0: Disable DVP0 (Digital Video Port 0)
413 * 1: Enable DVP0 (Digital Video Port 0)
414 * 3C5.12[5] - FPD5 pin strapping
415 * 0: DVP0 is used by a TMDS transmitter (DVI)
416 * 1: DVP0 is used by a TV encoder */
417 if ((sr12 & 0x40) && (!(sr12 & 0x20))) {
418 viaDVP0SetDisplaySource(pScrn, displaySource);
419 } else if (!(sr12 & 0x10)) {
420 viaDFPLowSetDisplaySource(pScrn, displaySource);
421 } else {
422 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
423 "None of the external ports were set up for "
424 "TMDS transmitter use.\n");
425 }
426
427 break;
428 case VIA_CX700:
429 case VIA_VX800:
430 case VIA_VX855:
431 case VIA_VX900:
432 /* 3C5.13[6] - DVP1 DVP / capture port selection
433 * 0: DVP1 is used as a DVP (Digital Video Port)
434 * 1: DVP1 is used as a capture port
435 */
436 if (!(sr13 & 0x40)) {
437 viaDVP1SetDisplaySource(pScrn, displaySource);
438 } else {
439 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
440 "DVP1 is not set up for TMDS "
441 "transmitter use.\n");
442 }
443
444 break;
445 default:
446 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
447 "Unrecognized IGP for "
448 "TMDS transmitter use.\n");
449 break;
450 }
451
452 if ((pVia->Chipset == VIA_CX700)
453 || (pVia->Chipset == VIA_VX800)
454 || (pVia->Chipset == VIA_VX855)
455 || (pVia->Chipset == VIA_VX900)) {
456
457 hwp->writeSeq(hwp, 0x5A, sr5a);
458 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
459 "Restoring 3C5.5A[0].\n"));
460 }
461
462 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
463 "Exiting viaExtTMDSSetDisplaySource.\n"));
464 }
465
466 void
viaExtTMDSEnableIOPads(ScrnInfoPtr pScrn,CARD8 ioPadState)467 viaExtTMDSEnableIOPads(ScrnInfoPtr pScrn, CARD8 ioPadState)
468 {
469
470 vgaHWPtr hwp = VGAHWPTR(pScrn);
471 VIAPtr pVia = VIAPTR(pScrn);
472 CARD8 sr12, sr13, sr5a;
473
474 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
475 "Entered viaExtTMDSEnableIOPads.\n"));
476
477 if ((pVia->Chipset == VIA_CX700)
478 || (pVia->Chipset == VIA_VX800)
479 || (pVia->Chipset == VIA_VX855)
480 || (pVia->Chipset == VIA_VX900)) {
481
482 sr5a = hwp->readSeq(hwp, 0x5A);
483 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
484 "SR5A: 0x%02X\n", sr5a));
485 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
486 "Setting 3C5.5A[0] to 0.\n"));
487 ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01);
488 }
489
490 sr12 = hwp->readSeq(hwp, 0x12);
491 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
492 "SR12: 0x%02X\n", sr12));
493 sr13 = hwp->readSeq(hwp, 0x13);
494 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
495 "SR13: 0x%02X\n", sr13));
496 switch (pVia->Chipset) {
497 case VIA_CLE266:
498 /* 3C5.12[5] - FPD18 pin strapping
499 * 0: DIP0 (Digital Interface Port 0) is used by
500 * a TMDS transmitter (DVI)
501 * 1: DIP0 (Digital Interface Port 0) is used by
502 * a TV encoder */
503 if (!(sr12 & 0x20)) {
504 viaDIP0EnableIOPads(pScrn, ioPadState);
505 } else {
506 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
507 "DIP0 was not set up for "
508 "TMDS transmitter use.\n");
509 }
510
511 break;
512 case VIA_KM400:
513 case VIA_K8M800:
514 case VIA_PM800:
515 case VIA_P4M800PRO:
516 /* 3C5.13[3] - DVP0D8 pin strapping
517 * 0: AGP pins are used for AGP
518 * 1: AGP pins are used by FPDP
519 * (Flat Panel Display Port)
520 * 3C5.12[6] - DVP0D6 pin strapping
521 * 0: Disable DVP0 (Digital Video Port 0)
522 * 1: Enable DVP0 (Digital Video Port 0)
523 * 3C5.12[5] - DVP0D5 pin strapping
524 * 0: DVP0 is used by a TMDS transmitter (DVI)
525 * 1: DVP0 is used by a TV encoder
526 * 3C5.12[4] - DVP0D4 pin strapping
527 * 0: Dual 12-bit FPDP (Flat Panel Display Port)
528 * 1: 24-bit FPDP (Flat Panel Display Port) */
529 if ((sr12 & 0x40) && (!(sr12 & 0x20))) {
530 viaDVP0EnableIOPads(pScrn, ioPadState);
531 } else if ((sr13 & 0x08) && (!(sr12 & 0x10))) {
532 viaDFPLowEnableIOPads(pScrn, ioPadState);
533 } else {
534 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
535 "None of the external ports were set up for "
536 "TMDS transmitter use.\n");
537 }
538
539 break;
540 case VIA_P4M890:
541 case VIA_K8M890:
542 case VIA_P4M900:
543 /* 3C5.12[6] - FPD6 pin strapping
544 * 0: Disable DVP0 (Digital Video Port 0)
545 * 1: Enable DVP0 (Digital Video Port 0)
546 * 3C5.12[5] - FPD5 pin strapping
547 * 0: DVP0 is used by a TMDS transmitter (DVI)
548 * 1: DVP0 is used by a TV encoder */
549 if ((sr12 & 0x40) && (!(sr12 & 0x20))) {
550 viaDVP0EnableIOPads(pScrn, ioPadState);
551 } else if (!(sr12 & 0x10)) {
552 viaDFPLowEnableIOPads(pScrn, ioPadState);
553 } else {
554 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
555 "None of the external ports were set up for "
556 "TMDS transmitter use.\n");
557 }
558
559 break;
560 case VIA_CX700:
561 case VIA_VX800:
562 case VIA_VX855:
563 case VIA_VX900:
564 /* 3C5.13[6] - DVP1 DVP / capture port selection
565 * 0: DVP1 is used as a DVP (Digital Video Port)
566 * 1: DVP1 is used as a capture port
567 */
568 if (!(sr13 & 0x40)) {
569 viaDVP1EnableIOPads(pScrn, ioPadState);
570 } else {
571 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
572 "DVP1 is not set up for TMDS "
573 "transmitter use.\n");
574 }
575
576 break;
577 default:
578 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
579 "Unrecognized IGP for "
580 "TMDS transmitter use.\n");
581 break;
582 }
583
584 if ((pVia->Chipset == VIA_CX700)
585 || (pVia->Chipset == VIA_VX800)
586 || (pVia->Chipset == VIA_VX855)
587 || (pVia->Chipset == VIA_VX900)) {
588
589 hwp->writeSeq(hwp, 0x5A, sr5a);
590 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
591 "Restoring 3C5.5A[0].\n"));
592 }
593
594 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
595 "Exiting viaExtTMDSEnableIOPads.\n"));
596 }
597
598 void
viaExtTMDSSetClockDriveStrength(ScrnInfoPtr pScrn,CARD8 clockDriveStrength)599 viaExtTMDSSetClockDriveStrength(ScrnInfoPtr pScrn, CARD8 clockDriveStrength)
600 {
601 vgaHWPtr hwp = VGAHWPTR(pScrn);
602 VIAPtr pVia = VIAPTR(pScrn);
603 CARD8 sr12, sr13, sr5a;
604
605 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
606 "Entered viaExtTMDSSetClockDriveStrength.\n"));
607
608 if ((pVia->Chipset == VIA_CX700)
609 || (pVia->Chipset == VIA_VX800)
610 || (pVia->Chipset == VIA_VX855)
611 || (pVia->Chipset == VIA_VX900)) {
612
613 sr5a = hwp->readSeq(hwp, 0x5A);
614 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
615 "SR5A: 0x%02X\n", sr5a));
616 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
617 "Setting 3C5.5A[0] to 0.\n"));
618 ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01);
619 }
620
621 sr12 = hwp->readSeq(hwp, 0x12);
622 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
623 "SR12: 0x%02X\n", sr12));
624 sr13 = hwp->readSeq(hwp, 0x13);
625 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
626 "SR13: 0x%02X\n", sr13));
627 switch (pVia->Chipset) {
628 case VIA_CLE266:
629 /* 3C5.12[5] - FPD18 pin strapping
630 * 0: DIP0 (Digital Interface Port 0) is used by
631 * a TMDS transmitter (DVI)
632 * 1: DIP0 (Digital Interface Port 0) is used by
633 * a TV encoder */
634 if (!(sr12 & 0x20)) {
635 viaDIP0SetClockDriveStrength(pScrn, clockDriveStrength);
636 }
637
638 break;
639 case VIA_KM400:
640 case VIA_K8M800:
641 case VIA_PM800:
642 case VIA_P4M800PRO:
643 /* 3C5.12[6] - DVP0D6 pin strapping
644 * 0: Disable DVP0 (Digital Video Port 0)
645 * 1: Enable DVP0 (Digital Video Port 0)
646 * 3C5.12[5] - DVP0D5 pin strapping
647 * 0: DVP0 is used by a TMDS transmitter (DVI)
648 * 1: DVP0 is used by a TV encoder */
649 if ((sr12 & 0x40) && (!(sr12 & 0x20))) {
650 viaDVP0SetClockDriveStrength(pScrn, clockDriveStrength);
651 }
652
653 break;
654 case VIA_P4M890:
655 case VIA_K8M890:
656 case VIA_P4M900:
657 /* 3C5.12[6] - FPD6 pin strapping
658 * 0: Disable DVP0 (Digital Video Port 0)
659 * 1: Enable DVP0 (Digital Video Port 0)
660 * 3C5.12[5] - FPD5 pin strapping
661 * 0: DVP0 is used by a TMDS transmitter (DVI)
662 * 1: DVP0 is used by a TV encoder */
663 if ((sr12 & 0x40) && (!(sr12 & 0x20))) {
664 viaDVP0SetClockDriveStrength(pScrn, clockDriveStrength);
665 }
666
667 break;
668 case VIA_CX700:
669 case VIA_VX800:
670 case VIA_VX855:
671 case VIA_VX900:
672 /* 3C5.13[6] - DVP1 DVP / capture port selection
673 * 0: DVP1 is used as a DVP (Digital Video Port)
674 * 1: DVP1 is used as a capture port */
675 if (!(sr13 & 0x40)) {
676 viaDVP1SetClockDriveStrength(pScrn, clockDriveStrength);
677 }
678
679 break;
680 default:
681 break;
682 }
683
684 if ((pVia->Chipset == VIA_CX700)
685 || (pVia->Chipset == VIA_VX800)
686 || (pVia->Chipset == VIA_VX855)
687 || (pVia->Chipset == VIA_VX900)) {
688
689 hwp->writeSeq(hwp, 0x5A, sr5a);
690 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
691 "Restoring 3C5.5A[0].\n"));
692 }
693
694 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
695 "Exiting viaExtTMDSSetClockDriveStrength.\n"));
696 }
697
698 void
viaExtTMDSSetDataDriveStrength(ScrnInfoPtr pScrn,CARD8 dataDriveStrength)699 viaExtTMDSSetDataDriveStrength(ScrnInfoPtr pScrn, CARD8 dataDriveStrength)
700 {
701 vgaHWPtr hwp = VGAHWPTR(pScrn);
702 VIAPtr pVia = VIAPTR(pScrn);
703 CARD8 sr12, sr13, sr5a;
704
705 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
706 "Entered viaExtTMDSSetDataDriveStrength.\n"));
707
708 if ((pVia->Chipset == VIA_CX700)
709 || (pVia->Chipset == VIA_VX800)
710 || (pVia->Chipset == VIA_VX855)
711 || (pVia->Chipset == VIA_VX900)) {
712
713 sr5a = hwp->readSeq(hwp, 0x5A);
714 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
715 "SR5A: 0x%02X\n", sr5a));
716 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
717 "Setting 3C5.5A[0] to 0.\n"));
718 ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01);
719 }
720
721 sr12 = hwp->readSeq(hwp, 0x12);
722 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
723 "SR12: 0x%02X\n", sr12));
724 sr13 = hwp->readSeq(hwp, 0x13);
725 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
726 "SR13: 0x%02X\n", sr13));
727 switch (pVia->Chipset) {
728 case VIA_CLE266:
729 /* 3C5.12[5] - FPD18 pin strapping
730 * 0: DIP0 (Digital Interface Port 0) is used by
731 * a TMDS transmitter (DVI)
732 * 1: DIP0 (Digital Interface Port 0) is used by
733 * a TV encoder */
734 if (!(sr12 & 0x20)) {
735 viaDIP0SetDataDriveStrength(pScrn, dataDriveStrength);
736 }
737
738 break;
739 case VIA_KM400:
740 case VIA_K8M800:
741 case VIA_PM800:
742 case VIA_P4M800PRO:
743 /* 3C5.12[6] - DVP0D6 pin strapping
744 * 0: Disable DVP0 (Digital Video Port 0)
745 * 1: Enable DVP0 (Digital Video Port 0)
746 * 3C5.12[5] - DVP0D5 pin strapping
747 * 0: DVP0 is used by a TMDS transmitter (DVI)
748 * 1: DVP0 is used by a TV encoder */
749 if ((sr12 & 0x40) && (!(sr12 & 0x20))) {
750 viaDVP0SetDataDriveStrength(pScrn, dataDriveStrength);
751 }
752
753 break;
754 case VIA_P4M890:
755 case VIA_K8M890:
756 case VIA_P4M900:
757 /* 3C5.12[6] - FPD6 pin strapping
758 * 0: Disable DVP0 (Digital Video Port 0)
759 * 1: Enable DVP0 (Digital Video Port 0)
760 * 3C5.12[5] - FPD5 pin strapping
761 * 0: DVP0 is used by a TMDS transmitter (DVI)
762 * 1: DVP0 is used by a TV encoder */
763 if ((sr12 & 0x40) && (!(sr12 & 0x20))) {
764 viaDVP0SetDataDriveStrength(pScrn, dataDriveStrength);
765 }
766
767 break;
768 case VIA_CX700:
769 case VIA_VX800:
770 case VIA_VX855:
771 case VIA_VX900:
772 /* 3C5.13[6] - DVP1 DVP / capture port selection
773 * 0: DVP1 is used as a DVP (Digital Video Port)
774 * 1: DVP1 is used as a capture port */
775 if (!(sr13 & 0x40)) {
776 viaDVP1SetDataDriveStrength(pScrn, dataDriveStrength);
777 }
778
779 break;
780 default:
781 break;
782 }
783
784 if ((pVia->Chipset == VIA_CX700)
785 || (pVia->Chipset == VIA_VX800)
786 || (pVia->Chipset == VIA_VX855)
787 || (pVia->Chipset == VIA_VX900)) {
788
789 hwp->writeSeq(hwp, 0x5A, sr5a);
790 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
791 "Restoring 3C5.5A[0].\n"));
792 }
793
794 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
795 "Exiting viaExtTMDSSetDataDriveStrength.\n"));
796 }
797
798 static void
via_tmds_create_resources(xf86OutputPtr output)799 via_tmds_create_resources(xf86OutputPtr output)
800 {
801 ScrnInfoPtr pScrn = output->scrn;
802
803 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
804 "Entered via_tmds_create_resources.\n"));
805
806 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
807 "Exiting via_tmds_create_resources.\n"));
808 }
809
810 static void
via_tmds_dpms(xf86OutputPtr output,int mode)811 via_tmds_dpms(xf86OutputPtr output, int mode)
812 {
813 ScrnInfoPtr pScrn = output->scrn;
814
815 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
816 "Entered via_tmds_dpms.\n"));
817
818 switch (mode) {
819 case DPMSModeOn:
820 viaTMDSPower(pScrn, TRUE);
821 viaTMDSIOPadSetting(pScrn, TRUE);
822 break;
823 case DPMSModeStandby:
824 case DPMSModeSuspend:
825 case DPMSModeOff:
826 viaTMDSPower(pScrn, FALSE);
827 viaTMDSIOPadSetting(pScrn, FALSE);
828 break;
829 default:
830 break;
831 }
832
833 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
834 "Exiting via_tmds_dpms.\n"));
835 }
836
837 static void
via_tmds_save(xf86OutputPtr output)838 via_tmds_save(xf86OutputPtr output)
839 {
840 ScrnInfoPtr pScrn = output->scrn;
841
842 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
843 "Entered via_tmds_save.\n"));
844
845 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
846 "Exiting via_tmds_save.\n"));
847 }
848
849 static void
via_tmds_restore(xf86OutputPtr output)850 via_tmds_restore(xf86OutputPtr output)
851 {
852 ScrnInfoPtr pScrn = output->scrn;
853
854 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
855 "Entered via_tmds_restore.\n"));
856
857 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
858 "Exiting via_tmds_restore.\n"));
859 }
860
861 static int
via_tmds_mode_valid(xf86OutputPtr output,DisplayModePtr pMode)862 via_tmds_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
863 {
864 ScrnInfoPtr pScrn = output->scrn;
865 int status;
866
867 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
868 "Entered via_tmds_mode_valid.\n"));
869
870 if (!ViaModeDotClockTranslate(pScrn, pMode)) {
871 status = MODE_NOCLOCK;
872 } else {
873 status = MODE_OK;
874 }
875
876 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
877 "Exiting via_tmds_mode_valid.\n"));
878 return status;
879 }
880
881 static Bool
via_tmds_mode_fixup(xf86OutputPtr output,DisplayModePtr mode,DisplayModePtr adjusted_mode)882 via_tmds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
883 DisplayModePtr adjusted_mode)
884 {
885 ScrnInfoPtr pScrn = output->scrn;
886
887 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
888 "Entered via_tmds_mode_fixup.\n"));
889
890 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
891 "Exiting via_tmds_mode_fixup.\n"));
892 return TRUE;
893 }
894
895 static void
via_tmds_prepare(xf86OutputPtr output)896 via_tmds_prepare(xf86OutputPtr output)
897 {
898 ScrnInfoPtr pScrn = output->scrn;
899
900 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
901 "Entered via_tmds_prepare.\n"));
902
903 viaTMDSPower(pScrn, FALSE);
904 viaTMDSIOPadSetting(pScrn, FALSE);
905
906 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
907 "Exiting via_tmds_prepare.\n"));
908 }
909
910 static void
via_tmds_commit(xf86OutputPtr output)911 via_tmds_commit(xf86OutputPtr output)
912 {
913 ScrnInfoPtr pScrn = output->scrn;
914
915 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
916 "Entered via_tmds_commit.\n"));
917
918 viaTMDSPower(pScrn, TRUE);
919 viaTMDSIOPadSetting(pScrn, TRUE);
920
921 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
922 "Exiting via_tmds_commit.\n"));
923 }
924
925 static void
via_tmds_mode_set(xf86OutputPtr output,DisplayModePtr mode,DisplayModePtr adjusted_mode)926 via_tmds_mode_set(xf86OutputPtr output, DisplayModePtr mode,
927 DisplayModePtr adjusted_mode)
928 {
929 ScrnInfoPtr pScrn = output->scrn;
930 drmmode_crtc_private_ptr iga = output->crtc->driver_private;
931
932 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
933 "Entered via_tmds_mode_set.\n"));
934
935 /* Initialize VIA IGP integrated TMDS transmitter registers. */
936 viaTMDSInitRegisters(pScrn);
937
938 /* Set integrated TMDS transmitter synchronization polarity for
939 * both horizontal synchronization and vertical synchronization. */
940 viaTMDSSetSyncPolarity(pScrn, adjusted_mode);
941
942 if (output->crtc) {
943 viaTMDSSetSource(pScrn, iga->index ? 0x01 : 0x00);
944 }
945
946 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
947 "Exiting via_tmds_mode_set.\n"));
948 }
949
950 static xf86OutputStatus
via_tmds_detect(xf86OutputPtr output)951 via_tmds_detect(xf86OutputPtr output)
952 {
953 xf86MonPtr mon;
954 xf86OutputStatus status = XF86OutputStatusDisconnected;
955 ScrnInfoPtr pScrn = output->scrn;
956 VIAPtr pVia = VIAPTR(pScrn);
957
958 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
959 "Entered via_tmds_detect.\n"));
960
961 /* Check for DVI presence by sensing the TMDS receiver connected
962 * to the integrated TMDS transmitter. */
963 if (viaTMDSSense(pScrn)) {
964
965 if (!pVia->pI2CBus2) {
966 goto exit;
967 }
968
969 /* Assume that only I2C bus 2 is used for the DVI connected to the
970 * integrated TMDS transmitter. */
971 if (!xf86I2CProbeAddress(pVia->pI2CBus2, 0xA0)) {
972 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
973 "I2C device on I2C Bus 2 does not support EDID.\n");
974 goto exit;
975 }
976
977 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
978 "Obtaining EDID for DVI.\n");
979
980 /* Since DVI presence was established, access the I2C bus,
981 * in order to obtain EDID from the monitor. */
982 mon = xf86OutputGetEDID(output, pVia->pI2CBus2);
983
984 /* Is the interface type digital? */
985 if (mon && DIGITAL(mon->features.input_type)) {
986 status = XF86OutputStatusConnected;
987 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
988 "Detected a monitor connected to DVI.\n");
989 xf86OutputSetEDID(output, mon);
990 } else {
991 xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
992 "Could not obtain EDID from a monitor "
993 "connected to DVI.\n");
994 }
995 }
996
997 exit:
998 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
999 "Exiting via_tmds_detect.\n"));
1000 return status;
1001 }
1002
1003 #ifdef RANDR_12_INTERFACE
1004 static Bool
via_tmds_set_property(xf86OutputPtr output,Atom property,RRPropertyValuePtr value)1005 via_tmds_set_property(xf86OutputPtr output, Atom property,
1006 RRPropertyValuePtr value)
1007 {
1008 ScrnInfoPtr pScrn = output->scrn;
1009
1010 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1011 "Entered via_tmds_set_property.\n"));
1012
1013 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1014 "Exiting via_tmds_set_property.\n"));
1015 return TRUE;
1016 }
1017 #endif
1018
1019 #ifdef RANDR_13_INTERFACE
1020 static Bool
via_tmds_get_property(xf86OutputPtr output,Atom property)1021 via_tmds_get_property(xf86OutputPtr output, Atom property)
1022 {
1023 ScrnInfoPtr pScrn = output->scrn;
1024
1025 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1026 "Entered via_tmds_get_property.\n"));
1027
1028 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1029 "Exiting via_tmds_get_property.\n"));
1030 return FALSE;
1031 }
1032 #endif
1033
1034 static void
via_tmds_destroy(xf86OutputPtr output)1035 via_tmds_destroy(xf86OutputPtr output)
1036 {
1037 ScrnInfoPtr pScrn = output->scrn;
1038
1039 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1040 "Entered via_tmds_destroy.\n"));
1041
1042 if (output->driver_private) {
1043 free(output->driver_private);
1044 }
1045
1046 output->driver_private = NULL;
1047
1048 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1049 "Exiting via_tmds_destroy.\n"));
1050 }
1051
1052
1053
1054
1055 static const xf86OutputFuncsRec via_tmds_funcs = {
1056 .create_resources = via_tmds_create_resources,
1057 .dpms = via_tmds_dpms,
1058 .save = via_tmds_save,
1059 .restore = via_tmds_restore,
1060 .mode_valid = via_tmds_mode_valid,
1061 .mode_fixup = via_tmds_mode_fixup,
1062 .prepare = via_tmds_prepare,
1063 .commit = via_tmds_commit,
1064 .mode_set = via_tmds_mode_set,
1065 .detect = via_tmds_detect,
1066 .get_modes = xf86OutputGetEDIDModes,
1067 #ifdef RANDR_12_INTERFACE
1068 .set_property = via_tmds_set_property,
1069 #endif
1070 #ifdef RANDR_13_INTERFACE
1071 .get_property = via_tmds_get_property,
1072 #endif
1073 .destroy = via_tmds_destroy,
1074 };
1075
1076
1077 Bool
viaTMDSInit(ScrnInfoPtr pScrn)1078 viaTMDSInit(ScrnInfoPtr pScrn)
1079 {
1080 xf86OutputPtr output;
1081 vgaHWPtr hwp = VGAHWPTR(pScrn);
1082 VIAPtr pVia = VIAPTR(pScrn);
1083 VIATMDSRecPtr pVIATMDSRec = NULL;
1084 CARD8 sr13, sr5a;
1085 Bool status = FALSE;
1086 char outputNameBuffer[32];
1087
1088 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1089 "Entered viaTMDSInit.\n"));
1090
1091 sr5a = hwp->readSeq(hwp, 0x5A);
1092 ViaSeqMask(hwp, 0x5A, sr5a | 0x01, 0x01);
1093 sr13 = hwp->readSeq(hwp, 0x13);
1094 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1095 "SR13: 0x%02X\n", sr13));
1096 hwp->writeSeq(hwp, 0x5A, sr5a);
1097
1098 /* 3C5.13[7:6] - Integrated LVDS / DVI Mode Select
1099 * (DVP1D15-14 pin strapping)
1100 * 00: LVDS1 + LVDS2
1101 * 01: DVI + LVDS2
1102 * 10: Dual LVDS Channel (High Resolution Panel)
1103 * 11: One DVI only (decrease the clock jitter) */
1104 /* Check for DVI presence using pin strappings.
1105 * VIA Technologies NanoBook reference design based products
1106 * have their pin strappings set to a wrong setting to communicate
1107 * the presence of DVI, so it requires special handling here. */
1108 if ((((~(sr13 & 0x80)) && (sr13 & 0x40))
1109 || ((sr13 & 0x80) && (sr13 & 0x40)))
1110 || (pVia->isVIANanoBook)) {
1111
1112 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1113 "Integrated TMDS transmitter found via pin strapping.\n");
1114 } else {
1115 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1116 "Integrated TMDS transmitter not found.\n");
1117 goto exit;
1118 }
1119
1120 pVIATMDSRec = xnfcalloc(1, sizeof(VIATMDSRec));
1121 if (!pVIATMDSRec) {
1122 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1123 "Failed to allocate working storage for integrated "
1124 "TMDS transmitter.\n");
1125 goto exit;
1126 }
1127
1128 /* The code to dynamically designate the particular DVI (i.e., DVI-1,
1129 * DVI-2, etc.) for xrandr was borrowed from xf86-video-r128 DDX. */
1130 sprintf(outputNameBuffer, "DVI-%d", (pVia->numberDVI + 1));
1131 output = xf86OutputCreate(pScrn, &via_tmds_funcs, outputNameBuffer);
1132 if (!output) {
1133 free(pVIATMDSRec);
1134 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1135 "Failed to allocate X Server display output record for "
1136 "integrated TMDS transmitter.\n");
1137 goto exit;
1138 }
1139
1140 output->driver_private = pVIATMDSRec;
1141
1142 /* Since there are two (2) display controllers registered with the
1143 * X.Org Server and both IGA1 and IGA2 can handle DVI without any
1144 * limitations, possible_crtcs should be set to 0x3 (0b11) so that
1145 * either display controller can get assigned to handle DVI. */
1146 output->possible_crtcs = (1 << 1) | (1 << 0);
1147
1148 output->possible_clones = 0;
1149 output->interlaceAllowed = FALSE;
1150 output->doubleScanAllowed = FALSE;
1151
1152 pVia->numberDVI++;
1153 status = TRUE;
1154 exit:
1155 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1156 "Exiting viaTMDSInit.\n"));
1157 return status;
1158 }
1159
1160 void
via_dvi_init(ScrnInfoPtr pScrn)1161 via_dvi_init(ScrnInfoPtr pScrn)
1162 {
1163 VIAPtr pVia = VIAPTR(pScrn);
1164
1165 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1166 "Entered via_dvi_init.\n"));
1167
1168 if (!pVia->pI2CBus2 || !pVia->pI2CBus3) {
1169 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1170 "I2C Bus 2 or I2C Bus 3 does not exist.\n");
1171 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1172 "Exiting via_dvi_init.\n"));
1173 return;
1174 }
1175
1176 /* Check to see if we are dealing with the latest VIA chipsets. */
1177 if ((pVia->Chipset == VIA_CX700)
1178 || (pVia->Chipset == VIA_VX800)
1179 || (pVia->Chipset == VIA_VX855)
1180 || (pVia->Chipset == VIA_VX900)) {
1181
1182 if (!viaTMDSInit(pScrn)) {
1183 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1184 "Integrated TMDS transmitter for DVI not found.\n");
1185 } else {
1186 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1187 "Integrated TMDS transmitter for DVI was "
1188 "initialized successfully.\n");
1189 }
1190 }
1191
1192 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1193 "Probing I2C Bus 2 for VT1632.\n");
1194 if (!viaVT1632Init(pScrn, pVia->pI2CBus2)) {
1195 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1196 "I2C Bus 2 was not initialized for DVI use.\n");
1197 } else {
1198 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1199 "VT1632 attached to I2C Bus 2 was initialized "
1200 "successfully for DVI use.\n");
1201 }
1202
1203 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1204 "Probing I2C Bus 3 for VT1632.\n");
1205 if (!viaVT1632Init(pScrn, pVia->pI2CBus3)) {
1206 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1207 "I2C Bus 3 was not initialized for DVI use.\n");
1208 } else {
1209 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1210 "VT1632 attached to I2C Bus 3 was initialized "
1211 "successfully for DVI use.\n");
1212 }
1213
1214 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1215 "Probing I2C Bus 2 for SiI 164.\n");
1216 if (!viaSiI164Init(pScrn, pVia->pI2CBus2)) {
1217 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1218 "I2C Bus 2 was not initialized for DVI use.\n");
1219 } else {
1220 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1221 "SiI 164 attached to I2C Bus 2 was initialized "
1222 "successfully for DVI use.\n");
1223 }
1224
1225 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1226 "Probing I2C Bus 3 for SiI 164.\n");
1227 if (!viaSiI164Init(pScrn, pVia->pI2CBus3)) {
1228 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1229 "I2C Bus 3 was not initialized for DVI use.\n");
1230 } else {
1231 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1232 "SiI 164 attached to I2C Bus 3 was initialized "
1233 "successfully for DVI use.\n");
1234 }
1235
1236 DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1237 "Exiting via_dvi_init.\n"));
1238 }
1239