via_tmds.c revision 983b4bf2
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. */
67static void
68viaTMDSInitRegisters(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 */
125static void
126viaTMDSSetSyncPolarity(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 */
163static void
164viaTMDSSetSource(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 */
191static Bool
192viaTMDSSense(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
213static void
214viaTMDSPower(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
268static void
269viaTMDSIOPadSetting(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
335void
336viaExtTMDSSetDisplaySource(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
466void
467viaExtTMDSEnableIOPads(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
598void
599viaExtTMDSSetClockDriveStrength(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
698void
699viaExtTMDSSetDataDriveStrength(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
798static void
799via_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
810static void
811via_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
837static void
838via_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
849static void
850via_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
861static int
862via_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
881static Bool
882via_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
895static void
896via_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
910static void
911via_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
925static void
926via_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
950static xf86OutputStatus
951via_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
997exit:
998    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
999                        "Exiting via_tmds_detect.\n"));
1000    return status;
1001}
1002
1003#ifdef RANDR_12_INTERFACE
1004static Bool
1005via_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
1020static Bool
1021via_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
1034static void
1035via_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
1055static 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
1077Bool
1078viaTMDSInit(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;
1154exit:
1155    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1156                        "Exiting viaTMDSInit.\n"));
1157    return status;
1158}
1159
1160void
1161via_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