1983b4bf2Smrg/*
2983b4bf2Smrg * Copyright 2016 Kevin Brace
3983b4bf2Smrg * Copyright 2015-2016 The OpenChrome Project
4983b4bf2Smrg *                     [https://www.freedesktop.org/wiki/Openchrome]
5983b4bf2Smrg * Copyright 2014 SHS SERVICES GmbH
6983b4bf2Smrg *
7983b4bf2Smrg * Permission is hereby granted, free of charge, to any person obtaining a
8983b4bf2Smrg * copy of this software and associated documentation files (the "Software"),
9983b4bf2Smrg * to deal in the Software without restriction, including without limitation
10983b4bf2Smrg * the rights to use, copy, modify, merge, publish, distribute, sub license,
11983b4bf2Smrg * and/or sell copies of the Software, and to permit persons to whom the
12983b4bf2Smrg * Software is furnished to do so, subject to the following conditions:
13983b4bf2Smrg *
14983b4bf2Smrg * The above copyright notice and this permission notice (including the
15983b4bf2Smrg * next paragraph) shall be included in all copies or substantial portions
16983b4bf2Smrg * of the Software.
17983b4bf2Smrg *
18983b4bf2Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19983b4bf2Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20983b4bf2Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21983b4bf2Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22983b4bf2Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23983b4bf2Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24983b4bf2Smrg * DEALINGS IN THE SOFTWARE.
25983b4bf2Smrg */
26983b4bf2Smrg
27983b4bf2Smrg/*
28983b4bf2Smrg * via_tmds.c
29983b4bf2Smrg *
30983b4bf2Smrg * Handles initialization of TMDS (DVI) related resources and
31983b4bf2Smrg * controls the integrated TMDS transmitter found in CX700 and
32983b4bf2Smrg * later VIA Technologies chipsets.
33983b4bf2Smrg *
34983b4bf2Smrg */
35983b4bf2Smrg
36983b4bf2Smrg#ifdef HAVE_CONFIG_H
37983b4bf2Smrg#include "config.h"
38983b4bf2Smrg#endif
39983b4bf2Smrg
40983b4bf2Smrg#include <unistd.h>
41983b4bf2Smrg#include "via_driver.h"
42983b4bf2Smrg#include "via_vt1632.h"
43983b4bf2Smrg#include "via_sii164.h"
44983b4bf2Smrg
45983b4bf2Smrg
46983b4bf2Smrg/*
47983b4bf2Smrg	1. Formula:
48983b4bf2Smrg		2^13 X 0.0698uSec [1/14.318MHz] = 8192 X 0.0698uSec =572.1uSec
49983b4bf2Smrg		Timer = Counter x 572 uSec
50983b4bf2Smrg	2. Note:
51983b4bf2Smrg		0.0698 uSec is too small to compute for hardware. So we multiply a
52983b4bf2Smrg		reference value(2^13) to make it big enough to compute for hardware.
53983b4bf2Smrg	3. Note:
54983b4bf2Smrg		The meaning of the TD0~TD3 are count of the clock.
55983b4bf2Smrg		TD(sec) = (sec)/(per clock) x (count of clocks)
56983b4bf2Smrg*/
57983b4bf2Smrg#define TD0 200
58983b4bf2Smrg#define TD1 25
59983b4bf2Smrg#define TD2 0
60983b4bf2Smrg#define TD3 25
61983b4bf2Smrg
62983b4bf2Smrg
63983b4bf2Smrg/*
64983b4bf2Smrg * Initializes most registers related to VIA Technologies IGP
65983b4bf2Smrg * integrated TMDS transmitter. Synchronization polarity and
66983b4bf2Smrg * display output source need to be set separately. */
67983b4bf2Smrgstatic void
68983b4bf2SmrgviaTMDSInitRegisters(ScrnInfoPtr pScrn)
69983b4bf2Smrg{
70983b4bf2Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
71983b4bf2Smrg
72983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
73983b4bf2Smrg                        "Entered viaTMDSInitRegisters.\n"));
74983b4bf2Smrg
75983b4bf2Smrg    /* Activate DVI + LVDS2 mode. */
76983b4bf2Smrg    /* 3X5.D2[5:4] - Display Channel Select
77983b4bf2Smrg     *               00: LVDS1 + LVDS2
78983b4bf2Smrg     *               01: DVI + LVDS2
79983b4bf2Smrg     *               10: One Dual LVDS Channel (High Resolution Pannel)
80983b4bf2Smrg     *               11: Single Channel DVI */
81983b4bf2Smrg    ViaCrtcMask(hwp, 0xD2, 0x10, 0x30);
82983b4bf2Smrg
83983b4bf2Smrg    /* Various DVI PLL settings should be set to default settings. */
84983b4bf2Smrg    /* 3X5.D1[7]   - PLL2 Reference Clock Edge Select Bit
85983b4bf2Smrg     *               0: PLLCK lock to rising edge of reference clock
86983b4bf2Smrg     *               1: PLLCK lock to falling edge of reference clock
87983b4bf2Smrg     * 3X5.D1[6:5] - PLL2 Charge Pump Current Set Bits
88983b4bf2Smrg     *               00: ICH = 12.5 uA
89983b4bf2Smrg     *               01: ICH = 25.0 uA
90983b4bf2Smrg     *               10: ICH = 37.5 uA
91983b4bf2Smrg     *               11: ICH = 50.0 uA
92983b4bf2Smrg     * 3X5.D1[4:1] - Reserved
93983b4bf2Smrg     * 3X5.D1[0]   - PLL2 Control Voltage Measurement Enable Bit */
94983b4bf2Smrg    ViaCrtcMask(hwp, 0xD1, 0x00, 0xE1);
95983b4bf2Smrg
96983b4bf2Smrg    /* Disable DVI test mode. */
97983b4bf2Smrg    /* 3X5.D5[7] - PD1 Enable Selection
98983b4bf2Smrg     *             1: Select by power flag
99983b4bf2Smrg     *             0: By register
100983b4bf2Smrg     * 3X5.D5[5] - DVI Testing Mode Enable
101983b4bf2Smrg     * 3X5.D5[4] - DVI Testing Format Selection
102983b4bf2Smrg     *             0: Half cycle
103983b4bf2Smrg     *             1: LFSR mode */
104983b4bf2Smrg    ViaCrtcMask(hwp, 0xD5, 0x00, 0xB0);
105983b4bf2Smrg
106983b4bf2Smrg    /* Disable DVI sense interrupt. */
107983b4bf2Smrg    /* 3C5.2B[7] - DVI Sense Interrupt Enable
108983b4bf2Smrg     *             0: Disable
109983b4bf2Smrg     *             1: Enable */
110983b4bf2Smrg    ViaSeqMask(hwp, 0x2B, 0x00, 0x80);
111983b4bf2Smrg
112983b4bf2Smrg    /* Clear DVI sense interrupt status. */
113983b4bf2Smrg    /* 3C5.2B[6] - DVI Sense Interrupt Status
114983b4bf2Smrg     *             (This bit has a RW1C attribute.) */
115983b4bf2Smrg    ViaSeqMask(hwp, 0x2B, 0x40, 0x40);
116983b4bf2Smrg
117983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
118983b4bf2Smrg                        "Exiting viaTMDSInitRegisters.\n"));
119983b4bf2Smrg}
120983b4bf2Smrg
121983b4bf2Smrg/*
122983b4bf2Smrg * Sets the polarity of horizontal synchronization and vertical
123983b4bf2Smrg * synchronization.
124983b4bf2Smrg */
125983b4bf2Smrgstatic void
126983b4bf2SmrgviaTMDSSetSyncPolarity(ScrnInfoPtr pScrn, DisplayModePtr mode)
127983b4bf2Smrg{
128983b4bf2Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
129983b4bf2Smrg    CARD8 cr97;
130983b4bf2Smrg
131983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
132983b4bf2Smrg                        "Entered viaTMDSSetSyncPolarity.\n"));
133983b4bf2Smrg
134983b4bf2Smrg    /* 3X5.97[6] - DVI (TMDS) VSYNC Polarity
135983b4bf2Smrg     *             0: Positive
136983b4bf2Smrg     *             1: Negative
137983b4bf2Smrg     * 3X5.97[5] - DVI (TMDS) HSYNC Polarity
138983b4bf2Smrg     *             0: Positive
139983b4bf2Smrg     *             1: Negative */
140983b4bf2Smrg    cr97 = hwp->readCrtc(hwp, 0x97);
141983b4bf2Smrg    if (mode->Flags & V_NHSYNC) {
142983b4bf2Smrg        cr97 |= 0x20;
143983b4bf2Smrg    } else {
144983b4bf2Smrg        cr97 &= (~0x20);
145983b4bf2Smrg    }
146983b4bf2Smrg
147983b4bf2Smrg    if (mode->Flags & V_NVSYNC) {
148983b4bf2Smrg        cr97 |= 0x40;
149983b4bf2Smrg    } else {
150983b4bf2Smrg        cr97 &= (~0x40);
151983b4bf2Smrg    }
152983b4bf2Smrg
153983b4bf2Smrg    ViaCrtcMask(hwp, 0x97, cr97, 0x60);
154983b4bf2Smrg
155983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
156983b4bf2Smrg                        "Exiting viaTMDSSetSyncPolarity.\n"));
157983b4bf2Smrg}
158983b4bf2Smrg
159983b4bf2Smrg/*
160983b4bf2Smrg * Sets IGA1 or IGA2 as the display output source for VIA Technologies IGP
161983b4bf2Smrg * integrated TMDS transmitter.
162983b4bf2Smrg */
163983b4bf2Smrgstatic void
164983b4bf2SmrgviaTMDSSetSource(ScrnInfoPtr pScrn, CARD8 displaySource)
165983b4bf2Smrg{
166983b4bf2Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
167983b4bf2Smrg    CARD8 temp = displaySource;
168983b4bf2Smrg
169983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
170983b4bf2Smrg                        "Entered viaTMDSSetSource.\n"));
171983b4bf2Smrg
172983b4bf2Smrg    /* Set integrated TMDS transmitter display output source.
173983b4bf2Smrg     * The integrated TMDS transmitter appears to utilize LVDS1's data
174983b4bf2Smrg     * source selection bit (3X5.99[4]). */
175983b4bf2Smrg    /* 3X5.99[4] - LVDS Channel1 Data Source Selection
176983b4bf2Smrg     *             0: Primary Display
177983b4bf2Smrg     *             1: Secondary Display */
178983b4bf2Smrg    ViaCrtcMask(hwp, 0x99, temp << 4, 0x10);
179983b4bf2Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
180983b4bf2Smrg                "Integrated TMDS Transmitter Display Output Source: IGA%d\n",
181983b4bf2Smrg                (temp & 0x01) + 1);
182983b4bf2Smrg
183983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
184983b4bf2Smrg                        "Exiting viaTMDSSetSource.\n"));
185983b4bf2Smrg}
186983b4bf2Smrg
187983b4bf2Smrg/*
188983b4bf2Smrg * Returns TMDS receiver detection state for VIA Technologies IGP
189983b4bf2Smrg * integrated TMDS transmitter.
190983b4bf2Smrg */
191983b4bf2Smrgstatic Bool
192983b4bf2SmrgviaTMDSSense(ScrnInfoPtr pScrn)
193983b4bf2Smrg{
194983b4bf2Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
195983b4bf2Smrg    VIAPtr pVia = VIAPTR(pScrn);
196983b4bf2Smrg    CARD8 tmdsReceiverDetected = 0x00;
197983b4bf2Smrg
198983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
199983b4bf2Smrg                        "Entered viaTMDSSense.\n"));
200983b4bf2Smrg
201983b4bf2Smrg    /* For now, faking DVI detection.*/
202983b4bf2Smrg    tmdsReceiverDetected = 0x01;
203983b4bf2Smrg
204983b4bf2Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
205983b4bf2Smrg                "Integrated TMDS transmitter %s a TMDS receiver.\n",
206983b4bf2Smrg                (tmdsReceiverDetected & 0x01) ? "detected" : "did not detect");
207983b4bf2Smrg
208983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
209983b4bf2Smrg                        "Exiting viaTMDSSense.\n"));
210983b4bf2Smrg    return tmdsReceiverDetected;
211983b4bf2Smrg}
212983b4bf2Smrg
213983b4bf2Smrgstatic void
214983b4bf2SmrgviaTMDSPower(ScrnInfoPtr pScrn, Bool powerState)
215983b4bf2Smrg{
216983b4bf2Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
217983b4bf2Smrg
218983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
219983b4bf2Smrg                        "Entered viaTMDSPower.\n"));
220983b4bf2Smrg
221983b4bf2Smrg    if (powerState) {
222983b4bf2Smrg        /* 3X5.91[7] - Software Direct On / Off Display Period
223983b4bf2Smrg                       in the Panel Path
224983b4bf2Smrg                       0: On
225983b4bf2Smrg                       1: Off */
226983b4bf2Smrg        ViaCrtcMask(hwp, 0x91, 0x00, 0x80);
227983b4bf2Smrg
228983b4bf2Smrg        /* 3X5.91[0] - Hardware or Software Control Power Sequence
229983b4bf2Smrg                       1: Software Control */
230983b4bf2Smrg        ViaCrtcMask(hwp, 0x91, 0x01, 0x01);
231983b4bf2Smrg
232983b4bf2Smrg        usleep(TD0);
233983b4bf2Smrg
234983b4bf2Smrg        /* 3X5.91[4] - Software VDD On
235983b4bf2Smrg                       0: Off
236983b4bf2Smrg                       1: On */
237983b4bf2Smrg        ViaCrtcMask(hwp, 0x91, 0x10, 0x10);
238983b4bf2Smrg
239983b4bf2Smrg        usleep(TD1);
240983b4bf2Smrg
241983b4bf2Smrg        /* 3X5.91[3] - Software Data On
242983b4bf2Smrg                       0: Off
243983b4bf2Smrg                       1: On */
244983b4bf2Smrg        ViaCrtcMask(hwp, 0x91, 0x08, 0x08);
245983b4bf2Smrg
246983b4bf2Smrg        /* 3X5.D2[3] - Power Down (Active High) for DVI
247983b4bf2Smrg         *             0: TMDS power on
248983b4bf2Smrg         *             1: TMDS power down */
249983b4bf2Smrg        ViaCrtcMask(hwp, 0xD2, 0x00, 0x08);
250983b4bf2Smrg    } else {
251983b4bf2Smrg        ViaCrtcMask(hwp, 0xD2, 0x08, 0x08);
252983b4bf2Smrg
253983b4bf2Smrg        ViaCrtcMask(hwp, 0x91, 0x00, 0x08);
254983b4bf2Smrg
255983b4bf2Smrg        usleep(TD1);
256983b4bf2Smrg
257983b4bf2Smrg        ViaCrtcMask(hwp, 0x91, 0x00, 0x10);
258983b4bf2Smrg    }
259983b4bf2Smrg
260983b4bf2Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
261983b4bf2Smrg                "Integrated TMDS (DVI) Power: %s\n",
262983b4bf2Smrg                powerState ? "On" : "Off");
263983b4bf2Smrg
264983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
265983b4bf2Smrg                        "Exiting viaTMDSPower.\n"));
266983b4bf2Smrg}
267983b4bf2Smrg
268983b4bf2Smrgstatic void
269983b4bf2SmrgviaTMDSIOPadSetting(ScrnInfoPtr pScrn, Bool ioPadOn)
270983b4bf2Smrg{
271983b4bf2Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
272983b4bf2Smrg    VIAPtr pVia = VIAPTR(pScrn);
273983b4bf2Smrg    CARD8 sr12, sr13, sr5a;
274983b4bf2Smrg
275983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
276983b4bf2Smrg                        "Entered viaTMDSIOPadSetting.\n"));
277983b4bf2Smrg
278983b4bf2Smrg    if ((pVia->Chipset == VIA_CX700)
279983b4bf2Smrg        || (pVia->Chipset == VIA_VX800)
280983b4bf2Smrg        || (pVia->Chipset == VIA_VX855)
281983b4bf2Smrg        || (pVia->Chipset == VIA_VX900)) {
282983b4bf2Smrg
283983b4bf2Smrg        sr5a = hwp->readSeq(hwp, 0x5A);
284983b4bf2Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
285983b4bf2Smrg                            "SR5A: 0x%02X\n", sr5a));
286983b4bf2Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
287983b4bf2Smrg                            "Setting 3C5.5A[0] to 0.\n"));
288983b4bf2Smrg        ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01);
289983b4bf2Smrg    }
290983b4bf2Smrg
291983b4bf2Smrg    sr12 = hwp->readSeq(hwp, 0x12);
292983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
293983b4bf2Smrg                        "SR12: 0x%02X\n", sr12));
294983b4bf2Smrg    sr13 = hwp->readSeq(hwp, 0x13);
295983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
296983b4bf2Smrg                        "SR13: 0x%02X\n", sr13));
297983b4bf2Smrg
298983b4bf2Smrg    switch (pVia->Chipset) {
299983b4bf2Smrg    case VIA_CX700:
300983b4bf2Smrg    case VIA_VX800:
301983b4bf2Smrg    case VIA_VX855:
302983b4bf2Smrg    case VIA_VX900:
303983b4bf2Smrg        /* 3C5.13[7:6] - DVP1D15 and DVP1D14 pin strappings
304983b4bf2Smrg         *               00: LVDS1 + LVDS2
305983b4bf2Smrg         *               01: DVI + LVDS2
306983b4bf2Smrg         *               10: Dual LVDS (LVDS1 + LVDS2 used
307983b4bf2Smrg         *                   simultaneously)
308983b4bf2Smrg         *               11: DVI only */
309983b4bf2Smrg        if ((((~(sr13 & 0x80)) && (sr13 & 0x40))
310983b4bf2Smrg             || ((sr13 & 0x80) && (sr13 & 0x40)))
311983b4bf2Smrg           || (pVia->isVIANanoBook)) {
312983b4bf2Smrg
313983b4bf2Smrg            viaLVDS1SetIOPadSetting(pScrn, ioPadOn ? 0x03 : 0x00);
314983b4bf2Smrg        }
315983b4bf2Smrg
316983b4bf2Smrg        break;
317983b4bf2Smrg    default:
318983b4bf2Smrg        break;
319983b4bf2Smrg    }
320983b4bf2Smrg
321983b4bf2Smrg    if ((pVia->Chipset == VIA_CX700)
322983b4bf2Smrg        || (pVia->Chipset == VIA_VX800)
323983b4bf2Smrg        || (pVia->Chipset == VIA_VX855)
324983b4bf2Smrg        || (pVia->Chipset == VIA_VX900)) {
325983b4bf2Smrg
326983b4bf2Smrg        hwp->writeSeq(hwp, 0x5A, sr5a);
327983b4bf2Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
328983b4bf2Smrg                            "Restoring 3C5.5A[0].\n"));
329983b4bf2Smrg    }
330983b4bf2Smrg
331983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
332983b4bf2Smrg                        "Exiting viaTMDSIOPadSetting.\n"));
333983b4bf2Smrg}
334983b4bf2Smrg
335983b4bf2Smrgvoid
336983b4bf2SmrgviaExtTMDSSetDisplaySource(ScrnInfoPtr pScrn, CARD8 displaySource)
337983b4bf2Smrg{
338983b4bf2Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
339983b4bf2Smrg    VIAPtr pVia = VIAPTR(pScrn);
340983b4bf2Smrg    CARD8 sr12, sr13, sr5a;
341983b4bf2Smrg
342983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
343983b4bf2Smrg                        "Entered viaExtTMDSSetDisplaySource.\n"));
344983b4bf2Smrg
345983b4bf2Smrg    if ((pVia->Chipset == VIA_CX700)
346983b4bf2Smrg        || (pVia->Chipset == VIA_VX800)
347983b4bf2Smrg        || (pVia->Chipset == VIA_VX855)
348983b4bf2Smrg        || (pVia->Chipset == VIA_VX900)) {
349983b4bf2Smrg
350983b4bf2Smrg        sr5a = hwp->readSeq(hwp, 0x5A);
351983b4bf2Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
352983b4bf2Smrg                            "SR5A: 0x%02X\n", sr5a));
353983b4bf2Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
354983b4bf2Smrg                            "Setting 3C5.5A[0] to 0.\n"));
355983b4bf2Smrg        ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01);
356983b4bf2Smrg    }
357983b4bf2Smrg
358983b4bf2Smrg    sr12 = hwp->readSeq(hwp, 0x12);
359983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
360983b4bf2Smrg                        "SR12: 0x%02X\n", sr12));
361983b4bf2Smrg    sr13 = hwp->readSeq(hwp, 0x13);
362983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
363983b4bf2Smrg                        "SR13: 0x%02X\n", sr13));
364983b4bf2Smrg    switch (pVia->Chipset) {
365983b4bf2Smrg    case VIA_CLE266:
366983b4bf2Smrg        /* 3C5.12[5] - FPD18 pin strapping
367983b4bf2Smrg         *             0: DIP0 (Digital Interface Port 0) is used by
368983b4bf2Smrg         *                a TMDS transmitter (DVI)
369983b4bf2Smrg         *             1: DIP0 (Digital Interface Port 0) is used by
370983b4bf2Smrg         *                a TV encoder */
371983b4bf2Smrg        if (!(sr12 & 0x20)) {
372983b4bf2Smrg            viaDIP0SetDisplaySource(pScrn, displaySource);
373983b4bf2Smrg        } else {
374983b4bf2Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
375983b4bf2Smrg                        "DIP0 was not set up for "
376983b4bf2Smrg                        "TMDS transmitter use.\n");
377983b4bf2Smrg        }
378983b4bf2Smrg
379983b4bf2Smrg        break;
380983b4bf2Smrg    case VIA_KM400:
381983b4bf2Smrg    case VIA_K8M800:
382983b4bf2Smrg    case VIA_PM800:
383983b4bf2Smrg    case VIA_P4M800PRO:
384983b4bf2Smrg        /* 3C5.13[3] - DVP0D8 pin strapping
385983b4bf2Smrg         *             0: AGP pins are used for AGP
386983b4bf2Smrg         *             1: AGP pins are used by FPDP
387983b4bf2Smrg         *                (Flat Panel Display Port)
388983b4bf2Smrg         * 3C5.12[6] - DVP0D6 pin strapping
389983b4bf2Smrg         *             0: Disable DVP0 (Digital Video Port 0)
390983b4bf2Smrg         *             1: Enable DVP0 (Digital Video Port 0)
391983b4bf2Smrg         * 3C5.12[5] - DVP0D5 pin strapping
392983b4bf2Smrg         *             0: DVP0 is used by a TMDS transmitter (DVI)
393983b4bf2Smrg         *             1: DVP0 is used by a TV encoder
394983b4bf2Smrg         * 3C5.12[4] - DVP0D4 pin strapping
395983b4bf2Smrg         *             0: Dual 12-bit FPDP (Flat Panel Display Port)
396983b4bf2Smrg         *             1: 24-bit FPDP (Flat Panel Display Port) */
397983b4bf2Smrg        if ((sr12 & 0x40) && (!(sr12 & 0x20))) {
398983b4bf2Smrg            viaDVP0SetDisplaySource(pScrn, displaySource);
399983b4bf2Smrg        } else if ((sr13 & 0x08) && (!(sr12 & 0x10))) {
400983b4bf2Smrg            viaDFPLowSetDisplaySource(pScrn, displaySource);
401983b4bf2Smrg        } else {
402983b4bf2Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
403983b4bf2Smrg                        "None of the external ports were set up for "
404983b4bf2Smrg                        "TMDS transmitter use.\n");
405983b4bf2Smrg        }
406983b4bf2Smrg
407983b4bf2Smrg        break;
408983b4bf2Smrg    case VIA_P4M890:
409983b4bf2Smrg    case VIA_K8M890:
410983b4bf2Smrg    case VIA_P4M900:
411983b4bf2Smrg        /* 3C5.12[6] - FPD6 pin strapping
412983b4bf2Smrg         *             0: Disable DVP0 (Digital Video Port 0)
413983b4bf2Smrg         *             1: Enable DVP0 (Digital Video Port 0)
414983b4bf2Smrg         * 3C5.12[5] - FPD5 pin strapping
415983b4bf2Smrg         *             0: DVP0 is used by a TMDS transmitter (DVI)
416983b4bf2Smrg         *             1: DVP0 is used by a TV encoder */
417983b4bf2Smrg        if ((sr12 & 0x40) && (!(sr12 & 0x20))) {
418983b4bf2Smrg            viaDVP0SetDisplaySource(pScrn, displaySource);
419983b4bf2Smrg        } else if (!(sr12 & 0x10)) {
420983b4bf2Smrg            viaDFPLowSetDisplaySource(pScrn, displaySource);
421983b4bf2Smrg        } else {
422983b4bf2Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
423983b4bf2Smrg                        "None of the external ports were set up for "
424983b4bf2Smrg                        "TMDS transmitter use.\n");
425983b4bf2Smrg        }
426983b4bf2Smrg
427983b4bf2Smrg        break;
428983b4bf2Smrg    case VIA_CX700:
429983b4bf2Smrg    case VIA_VX800:
430983b4bf2Smrg    case VIA_VX855:
431983b4bf2Smrg    case VIA_VX900:
432983b4bf2Smrg        /* 3C5.13[6] - DVP1 DVP / capture port selection
433983b4bf2Smrg         *             0: DVP1 is used as a DVP (Digital Video Port)
434983b4bf2Smrg         *             1: DVP1 is used as a capture port
435983b4bf2Smrg         */
436983b4bf2Smrg        if (!(sr13 & 0x40)) {
437983b4bf2Smrg            viaDVP1SetDisplaySource(pScrn, displaySource);
438983b4bf2Smrg        } else {
439983b4bf2Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
440983b4bf2Smrg                        "DVP1 is not set up for TMDS "
441983b4bf2Smrg                        "transmitter use.\n");
442983b4bf2Smrg        }
443983b4bf2Smrg
444983b4bf2Smrg        break;
445983b4bf2Smrg    default:
446983b4bf2Smrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
447983b4bf2Smrg                    "Unrecognized IGP for "
448983b4bf2Smrg                    "TMDS transmitter use.\n");
449983b4bf2Smrg        break;
450983b4bf2Smrg    }
451983b4bf2Smrg
452983b4bf2Smrg    if ((pVia->Chipset == VIA_CX700)
453983b4bf2Smrg        || (pVia->Chipset == VIA_VX800)
454983b4bf2Smrg        || (pVia->Chipset == VIA_VX855)
455983b4bf2Smrg        || (pVia->Chipset == VIA_VX900)) {
456983b4bf2Smrg
457983b4bf2Smrg        hwp->writeSeq(hwp, 0x5A, sr5a);
458983b4bf2Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
459983b4bf2Smrg                            "Restoring 3C5.5A[0].\n"));
460983b4bf2Smrg    }
461983b4bf2Smrg
462983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
463983b4bf2Smrg                        "Exiting viaExtTMDSSetDisplaySource.\n"));
464983b4bf2Smrg}
465983b4bf2Smrg
466983b4bf2Smrgvoid
467983b4bf2SmrgviaExtTMDSEnableIOPads(ScrnInfoPtr pScrn, CARD8 ioPadState)
468983b4bf2Smrg{
469983b4bf2Smrg
470983b4bf2Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
471983b4bf2Smrg    VIAPtr pVia = VIAPTR(pScrn);
472983b4bf2Smrg    CARD8 sr12, sr13, sr5a;
473983b4bf2Smrg
474983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
475983b4bf2Smrg                        "Entered viaExtTMDSEnableIOPads.\n"));
476983b4bf2Smrg
477983b4bf2Smrg    if ((pVia->Chipset == VIA_CX700)
478983b4bf2Smrg        || (pVia->Chipset == VIA_VX800)
479983b4bf2Smrg        || (pVia->Chipset == VIA_VX855)
480983b4bf2Smrg        || (pVia->Chipset == VIA_VX900)) {
481983b4bf2Smrg
482983b4bf2Smrg        sr5a = hwp->readSeq(hwp, 0x5A);
483983b4bf2Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
484983b4bf2Smrg                            "SR5A: 0x%02X\n", sr5a));
485983b4bf2Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
486983b4bf2Smrg                            "Setting 3C5.5A[0] to 0.\n"));
487983b4bf2Smrg        ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01);
488983b4bf2Smrg    }
489983b4bf2Smrg
490983b4bf2Smrg    sr12 = hwp->readSeq(hwp, 0x12);
491983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
492983b4bf2Smrg                        "SR12: 0x%02X\n", sr12));
493983b4bf2Smrg    sr13 = hwp->readSeq(hwp, 0x13);
494983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
495983b4bf2Smrg                        "SR13: 0x%02X\n", sr13));
496983b4bf2Smrg    switch (pVia->Chipset) {
497983b4bf2Smrg    case VIA_CLE266:
498983b4bf2Smrg        /* 3C5.12[5] - FPD18 pin strapping
499983b4bf2Smrg         *             0: DIP0 (Digital Interface Port 0) is used by
500983b4bf2Smrg         *                a TMDS transmitter (DVI)
501983b4bf2Smrg         *             1: DIP0 (Digital Interface Port 0) is used by
502983b4bf2Smrg         *                a TV encoder */
503983b4bf2Smrg        if (!(sr12 & 0x20)) {
504983b4bf2Smrg            viaDIP0EnableIOPads(pScrn, ioPadState);
505983b4bf2Smrg        } else {
506983b4bf2Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
507983b4bf2Smrg                        "DIP0 was not set up for "
508983b4bf2Smrg                        "TMDS transmitter use.\n");
509983b4bf2Smrg        }
510983b4bf2Smrg
511983b4bf2Smrg        break;
512983b4bf2Smrg    case VIA_KM400:
513983b4bf2Smrg    case VIA_K8M800:
514983b4bf2Smrg    case VIA_PM800:
515983b4bf2Smrg    case VIA_P4M800PRO:
516983b4bf2Smrg        /* 3C5.13[3] - DVP0D8 pin strapping
517983b4bf2Smrg         *             0: AGP pins are used for AGP
518983b4bf2Smrg         *             1: AGP pins are used by FPDP
519983b4bf2Smrg         *                (Flat Panel Display Port)
520983b4bf2Smrg         * 3C5.12[6] - DVP0D6 pin strapping
521983b4bf2Smrg         *             0: Disable DVP0 (Digital Video Port 0)
522983b4bf2Smrg         *             1: Enable DVP0 (Digital Video Port 0)
523983b4bf2Smrg         * 3C5.12[5] - DVP0D5 pin strapping
524983b4bf2Smrg         *             0: DVP0 is used by a TMDS transmitter (DVI)
525983b4bf2Smrg         *             1: DVP0 is used by a TV encoder
526983b4bf2Smrg         * 3C5.12[4] - DVP0D4 pin strapping
527983b4bf2Smrg         *             0: Dual 12-bit FPDP (Flat Panel Display Port)
528983b4bf2Smrg         *             1: 24-bit FPDP (Flat Panel Display Port) */
529983b4bf2Smrg        if ((sr12 & 0x40) && (!(sr12 & 0x20))) {
530983b4bf2Smrg            viaDVP0EnableIOPads(pScrn, ioPadState);
531983b4bf2Smrg        } else if ((sr13 & 0x08) && (!(sr12 & 0x10))) {
532983b4bf2Smrg            viaDFPLowEnableIOPads(pScrn, ioPadState);
533983b4bf2Smrg        } else {
534983b4bf2Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
535983b4bf2Smrg                        "None of the external ports were set up for "
536983b4bf2Smrg                        "TMDS transmitter use.\n");
537983b4bf2Smrg        }
538983b4bf2Smrg
539983b4bf2Smrg        break;
540983b4bf2Smrg    case VIA_P4M890:
541983b4bf2Smrg    case VIA_K8M890:
542983b4bf2Smrg    case VIA_P4M900:
543983b4bf2Smrg        /* 3C5.12[6] - FPD6 pin strapping
544983b4bf2Smrg         *             0: Disable DVP0 (Digital Video Port 0)
545983b4bf2Smrg         *             1: Enable DVP0 (Digital Video Port 0)
546983b4bf2Smrg         * 3C5.12[5] - FPD5 pin strapping
547983b4bf2Smrg         *             0: DVP0 is used by a TMDS transmitter (DVI)
548983b4bf2Smrg         *             1: DVP0 is used by a TV encoder */
549983b4bf2Smrg        if ((sr12 & 0x40) && (!(sr12 & 0x20))) {
550983b4bf2Smrg            viaDVP0EnableIOPads(pScrn, ioPadState);
551983b4bf2Smrg        } else if (!(sr12 & 0x10)) {
552983b4bf2Smrg            viaDFPLowEnableIOPads(pScrn, ioPadState);
553983b4bf2Smrg        } else {
554983b4bf2Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
555983b4bf2Smrg                        "None of the external ports were set up for "
556983b4bf2Smrg                        "TMDS transmitter use.\n");
557983b4bf2Smrg        }
558983b4bf2Smrg
559983b4bf2Smrg        break;
560983b4bf2Smrg    case VIA_CX700:
561983b4bf2Smrg    case VIA_VX800:
562983b4bf2Smrg    case VIA_VX855:
563983b4bf2Smrg    case VIA_VX900:
564983b4bf2Smrg        /* 3C5.13[6] - DVP1 DVP / capture port selection
565983b4bf2Smrg         *             0: DVP1 is used as a DVP (Digital Video Port)
566983b4bf2Smrg         *             1: DVP1 is used as a capture port
567983b4bf2Smrg         */
568983b4bf2Smrg        if (!(sr13 & 0x40)) {
569983b4bf2Smrg            viaDVP1EnableIOPads(pScrn, ioPadState);
570983b4bf2Smrg        } else {
571983b4bf2Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
572983b4bf2Smrg                        "DVP1 is not set up for TMDS "
573983b4bf2Smrg                        "transmitter use.\n");
574983b4bf2Smrg        }
575983b4bf2Smrg
576983b4bf2Smrg        break;
577983b4bf2Smrg    default:
578983b4bf2Smrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
579983b4bf2Smrg                    "Unrecognized IGP for "
580983b4bf2Smrg                    "TMDS transmitter use.\n");
581983b4bf2Smrg        break;
582983b4bf2Smrg    }
583983b4bf2Smrg
584983b4bf2Smrg    if ((pVia->Chipset == VIA_CX700)
585983b4bf2Smrg        || (pVia->Chipset == VIA_VX800)
586983b4bf2Smrg        || (pVia->Chipset == VIA_VX855)
587983b4bf2Smrg        || (pVia->Chipset == VIA_VX900)) {
588983b4bf2Smrg
589983b4bf2Smrg        hwp->writeSeq(hwp, 0x5A, sr5a);
590983b4bf2Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
591983b4bf2Smrg                            "Restoring 3C5.5A[0].\n"));
592983b4bf2Smrg    }
593983b4bf2Smrg
594983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
595983b4bf2Smrg                        "Exiting viaExtTMDSEnableIOPads.\n"));
596983b4bf2Smrg}
597983b4bf2Smrg
598983b4bf2Smrgvoid
599983b4bf2SmrgviaExtTMDSSetClockDriveStrength(ScrnInfoPtr pScrn, CARD8 clockDriveStrength)
600983b4bf2Smrg{
601983b4bf2Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
602983b4bf2Smrg    VIAPtr pVia = VIAPTR(pScrn);
603983b4bf2Smrg    CARD8 sr12, sr13, sr5a;
604983b4bf2Smrg
605983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
606983b4bf2Smrg                        "Entered viaExtTMDSSetClockDriveStrength.\n"));
607983b4bf2Smrg
608983b4bf2Smrg    if ((pVia->Chipset == VIA_CX700)
609983b4bf2Smrg        || (pVia->Chipset == VIA_VX800)
610983b4bf2Smrg        || (pVia->Chipset == VIA_VX855)
611983b4bf2Smrg        || (pVia->Chipset == VIA_VX900)) {
612983b4bf2Smrg
613983b4bf2Smrg        sr5a = hwp->readSeq(hwp, 0x5A);
614983b4bf2Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
615983b4bf2Smrg                            "SR5A: 0x%02X\n", sr5a));
616983b4bf2Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
617983b4bf2Smrg                            "Setting 3C5.5A[0] to 0.\n"));
618983b4bf2Smrg        ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01);
619983b4bf2Smrg    }
620983b4bf2Smrg
621983b4bf2Smrg    sr12 = hwp->readSeq(hwp, 0x12);
622983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
623983b4bf2Smrg                        "SR12: 0x%02X\n", sr12));
624983b4bf2Smrg    sr13 = hwp->readSeq(hwp, 0x13);
625983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
626983b4bf2Smrg                        "SR13: 0x%02X\n", sr13));
627983b4bf2Smrg    switch (pVia->Chipset) {
628983b4bf2Smrg    case VIA_CLE266:
629983b4bf2Smrg        /* 3C5.12[5] - FPD18 pin strapping
630983b4bf2Smrg         *             0: DIP0 (Digital Interface Port 0) is used by
631983b4bf2Smrg         *                a TMDS transmitter (DVI)
632983b4bf2Smrg         *             1: DIP0 (Digital Interface Port 0) is used by
633983b4bf2Smrg         *                a TV encoder */
634983b4bf2Smrg        if (!(sr12 & 0x20)) {
635983b4bf2Smrg            viaDIP0SetClockDriveStrength(pScrn, clockDriveStrength);
636983b4bf2Smrg        }
637983b4bf2Smrg
638983b4bf2Smrg        break;
639983b4bf2Smrg    case VIA_KM400:
640983b4bf2Smrg    case VIA_K8M800:
641983b4bf2Smrg    case VIA_PM800:
642983b4bf2Smrg    case VIA_P4M800PRO:
643983b4bf2Smrg        /* 3C5.12[6] - DVP0D6 pin strapping
644983b4bf2Smrg         *             0: Disable DVP0 (Digital Video Port 0)
645983b4bf2Smrg         *             1: Enable DVP0 (Digital Video Port 0)
646983b4bf2Smrg         * 3C5.12[5] - DVP0D5 pin strapping
647983b4bf2Smrg         *             0: DVP0 is used by a TMDS transmitter (DVI)
648983b4bf2Smrg         *             1: DVP0 is used by a TV encoder */
649983b4bf2Smrg        if ((sr12 & 0x40) && (!(sr12 & 0x20))) {
650983b4bf2Smrg            viaDVP0SetClockDriveStrength(pScrn, clockDriveStrength);
651983b4bf2Smrg        }
652983b4bf2Smrg
653983b4bf2Smrg        break;
654983b4bf2Smrg    case VIA_P4M890:
655983b4bf2Smrg    case VIA_K8M890:
656983b4bf2Smrg    case VIA_P4M900:
657983b4bf2Smrg        /* 3C5.12[6] - FPD6 pin strapping
658983b4bf2Smrg         *             0: Disable DVP0 (Digital Video Port 0)
659983b4bf2Smrg         *             1: Enable DVP0 (Digital Video Port 0)
660983b4bf2Smrg         * 3C5.12[5] - FPD5 pin strapping
661983b4bf2Smrg         *             0: DVP0 is used by a TMDS transmitter (DVI)
662983b4bf2Smrg         *             1: DVP0 is used by a TV encoder */
663983b4bf2Smrg        if ((sr12 & 0x40) && (!(sr12 & 0x20))) {
664983b4bf2Smrg            viaDVP0SetClockDriveStrength(pScrn, clockDriveStrength);
665983b4bf2Smrg        }
666983b4bf2Smrg
667983b4bf2Smrg        break;
668983b4bf2Smrg    case VIA_CX700:
669983b4bf2Smrg    case VIA_VX800:
670983b4bf2Smrg    case VIA_VX855:
671983b4bf2Smrg    case VIA_VX900:
672983b4bf2Smrg        /* 3C5.13[6] - DVP1 DVP / capture port selection
673983b4bf2Smrg         *             0: DVP1 is used as a DVP (Digital Video Port)
674983b4bf2Smrg         *             1: DVP1 is used as a capture port */
675983b4bf2Smrg        if (!(sr13 & 0x40)) {
676983b4bf2Smrg            viaDVP1SetClockDriveStrength(pScrn, clockDriveStrength);
677983b4bf2Smrg        }
678983b4bf2Smrg
679983b4bf2Smrg        break;
680983b4bf2Smrg    default:
681983b4bf2Smrg        break;
682983b4bf2Smrg    }
683983b4bf2Smrg
684983b4bf2Smrg    if ((pVia->Chipset == VIA_CX700)
685983b4bf2Smrg        || (pVia->Chipset == VIA_VX800)
686983b4bf2Smrg        || (pVia->Chipset == VIA_VX855)
687983b4bf2Smrg        || (pVia->Chipset == VIA_VX900)) {
688983b4bf2Smrg
689983b4bf2Smrg        hwp->writeSeq(hwp, 0x5A, sr5a);
690983b4bf2Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
691983b4bf2Smrg                            "Restoring 3C5.5A[0].\n"));
692983b4bf2Smrg    }
693983b4bf2Smrg
694983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
695983b4bf2Smrg                        "Exiting viaExtTMDSSetClockDriveStrength.\n"));
696983b4bf2Smrg}
697983b4bf2Smrg
698983b4bf2Smrgvoid
699983b4bf2SmrgviaExtTMDSSetDataDriveStrength(ScrnInfoPtr pScrn, CARD8 dataDriveStrength)
700983b4bf2Smrg{
701983b4bf2Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
702983b4bf2Smrg    VIAPtr pVia = VIAPTR(pScrn);
703983b4bf2Smrg    CARD8 sr12, sr13, sr5a;
704983b4bf2Smrg
705983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
706983b4bf2Smrg                        "Entered viaExtTMDSSetDataDriveStrength.\n"));
707983b4bf2Smrg
708983b4bf2Smrg    if ((pVia->Chipset == VIA_CX700)
709983b4bf2Smrg        || (pVia->Chipset == VIA_VX800)
710983b4bf2Smrg        || (pVia->Chipset == VIA_VX855)
711983b4bf2Smrg        || (pVia->Chipset == VIA_VX900)) {
712983b4bf2Smrg
713983b4bf2Smrg        sr5a = hwp->readSeq(hwp, 0x5A);
714983b4bf2Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
715983b4bf2Smrg                            "SR5A: 0x%02X\n", sr5a));
716983b4bf2Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
717983b4bf2Smrg                            "Setting 3C5.5A[0] to 0.\n"));
718983b4bf2Smrg        ViaSeqMask(hwp, 0x5A, sr5a & 0xFE, 0x01);
719983b4bf2Smrg    }
720983b4bf2Smrg
721983b4bf2Smrg    sr12 = hwp->readSeq(hwp, 0x12);
722983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
723983b4bf2Smrg                        "SR12: 0x%02X\n", sr12));
724983b4bf2Smrg    sr13 = hwp->readSeq(hwp, 0x13);
725983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
726983b4bf2Smrg                        "SR13: 0x%02X\n", sr13));
727983b4bf2Smrg    switch (pVia->Chipset) {
728983b4bf2Smrg    case VIA_CLE266:
729983b4bf2Smrg        /* 3C5.12[5] - FPD18 pin strapping
730983b4bf2Smrg         *             0: DIP0 (Digital Interface Port 0) is used by
731983b4bf2Smrg         *                a TMDS transmitter (DVI)
732983b4bf2Smrg         *             1: DIP0 (Digital Interface Port 0) is used by
733983b4bf2Smrg         *                a TV encoder */
734983b4bf2Smrg        if (!(sr12 & 0x20)) {
735983b4bf2Smrg            viaDIP0SetDataDriveStrength(pScrn, dataDriveStrength);
736983b4bf2Smrg        }
737983b4bf2Smrg
738983b4bf2Smrg        break;
739983b4bf2Smrg    case VIA_KM400:
740983b4bf2Smrg    case VIA_K8M800:
741983b4bf2Smrg    case VIA_PM800:
742983b4bf2Smrg    case VIA_P4M800PRO:
743983b4bf2Smrg        /* 3C5.12[6] - DVP0D6 pin strapping
744983b4bf2Smrg         *             0: Disable DVP0 (Digital Video Port 0)
745983b4bf2Smrg         *             1: Enable DVP0 (Digital Video Port 0)
746983b4bf2Smrg         * 3C5.12[5] - DVP0D5 pin strapping
747983b4bf2Smrg         *             0: DVP0 is used by a TMDS transmitter (DVI)
748983b4bf2Smrg         *             1: DVP0 is used by a TV encoder */
749983b4bf2Smrg        if ((sr12 & 0x40) && (!(sr12 & 0x20))) {
750983b4bf2Smrg            viaDVP0SetDataDriveStrength(pScrn, dataDriveStrength);
751983b4bf2Smrg        }
752983b4bf2Smrg
753983b4bf2Smrg        break;
754983b4bf2Smrg    case VIA_P4M890:
755983b4bf2Smrg    case VIA_K8M890:
756983b4bf2Smrg    case VIA_P4M900:
757983b4bf2Smrg        /* 3C5.12[6] - FPD6 pin strapping
758983b4bf2Smrg         *             0: Disable DVP0 (Digital Video Port 0)
759983b4bf2Smrg         *             1: Enable DVP0 (Digital Video Port 0)
760983b4bf2Smrg         * 3C5.12[5] - FPD5 pin strapping
761983b4bf2Smrg         *             0: DVP0 is used by a TMDS transmitter (DVI)
762983b4bf2Smrg         *             1: DVP0 is used by a TV encoder */
763983b4bf2Smrg        if ((sr12 & 0x40) && (!(sr12 & 0x20))) {
764983b4bf2Smrg            viaDVP0SetDataDriveStrength(pScrn, dataDriveStrength);
765983b4bf2Smrg        }
766983b4bf2Smrg
767983b4bf2Smrg        break;
768983b4bf2Smrg    case VIA_CX700:
769983b4bf2Smrg    case VIA_VX800:
770983b4bf2Smrg    case VIA_VX855:
771983b4bf2Smrg    case VIA_VX900:
772983b4bf2Smrg        /* 3C5.13[6] - DVP1 DVP / capture port selection
773983b4bf2Smrg         *             0: DVP1 is used as a DVP (Digital Video Port)
774983b4bf2Smrg         *             1: DVP1 is used as a capture port */
775983b4bf2Smrg        if (!(sr13 & 0x40)) {
776983b4bf2Smrg            viaDVP1SetDataDriveStrength(pScrn, dataDriveStrength);
777983b4bf2Smrg        }
778983b4bf2Smrg
779983b4bf2Smrg        break;
780983b4bf2Smrg    default:
781983b4bf2Smrg        break;
782983b4bf2Smrg    }
783983b4bf2Smrg
784983b4bf2Smrg    if ((pVia->Chipset == VIA_CX700)
785983b4bf2Smrg        || (pVia->Chipset == VIA_VX800)
786983b4bf2Smrg        || (pVia->Chipset == VIA_VX855)
787983b4bf2Smrg        || (pVia->Chipset == VIA_VX900)) {
788983b4bf2Smrg
789983b4bf2Smrg        hwp->writeSeq(hwp, 0x5A, sr5a);
790983b4bf2Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
791983b4bf2Smrg                            "Restoring 3C5.5A[0].\n"));
792983b4bf2Smrg    }
793983b4bf2Smrg
794983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
795983b4bf2Smrg                        "Exiting viaExtTMDSSetDataDriveStrength.\n"));
796983b4bf2Smrg}
797983b4bf2Smrg
798983b4bf2Smrgstatic void
799983b4bf2Smrgvia_tmds_create_resources(xf86OutputPtr output)
800983b4bf2Smrg{
801983b4bf2Smrg    ScrnInfoPtr pScrn = output->scrn;
802983b4bf2Smrg
803983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
804983b4bf2Smrg                        "Entered via_tmds_create_resources.\n"));
805983b4bf2Smrg
806983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
807983b4bf2Smrg                        "Exiting via_tmds_create_resources.\n"));
808983b4bf2Smrg}
809983b4bf2Smrg
810983b4bf2Smrgstatic void
811983b4bf2Smrgvia_tmds_dpms(xf86OutputPtr output, int mode)
812983b4bf2Smrg{
813983b4bf2Smrg    ScrnInfoPtr pScrn = output->scrn;
814983b4bf2Smrg
815983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
816983b4bf2Smrg                        "Entered via_tmds_dpms.\n"));
817983b4bf2Smrg
818983b4bf2Smrg    switch (mode) {
819983b4bf2Smrg    case DPMSModeOn:
820983b4bf2Smrg        viaTMDSPower(pScrn, TRUE);
821983b4bf2Smrg        viaTMDSIOPadSetting(pScrn, TRUE);
822983b4bf2Smrg        break;
823983b4bf2Smrg    case DPMSModeStandby:
824983b4bf2Smrg    case DPMSModeSuspend:
825983b4bf2Smrg    case DPMSModeOff:
826983b4bf2Smrg        viaTMDSPower(pScrn, FALSE);
827983b4bf2Smrg        viaTMDSIOPadSetting(pScrn, FALSE);
828983b4bf2Smrg        break;
829983b4bf2Smrg    default:
830983b4bf2Smrg        break;
831983b4bf2Smrg    }
832983b4bf2Smrg
833983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
834983b4bf2Smrg                        "Exiting via_tmds_dpms.\n"));
835983b4bf2Smrg}
836983b4bf2Smrg
837983b4bf2Smrgstatic void
838983b4bf2Smrgvia_tmds_save(xf86OutputPtr output)
839983b4bf2Smrg{
840983b4bf2Smrg    ScrnInfoPtr pScrn = output->scrn;
841983b4bf2Smrg
842983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
843983b4bf2Smrg                        "Entered via_tmds_save.\n"));
844983b4bf2Smrg
845983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
846983b4bf2Smrg                        "Exiting via_tmds_save.\n"));
847983b4bf2Smrg}
848983b4bf2Smrg
849983b4bf2Smrgstatic void
850983b4bf2Smrgvia_tmds_restore(xf86OutputPtr output)
851983b4bf2Smrg{
852983b4bf2Smrg    ScrnInfoPtr pScrn = output->scrn;
853983b4bf2Smrg
854983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
855983b4bf2Smrg                        "Entered via_tmds_restore.\n"));
856983b4bf2Smrg
857983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
858983b4bf2Smrg                        "Exiting via_tmds_restore.\n"));
859983b4bf2Smrg}
860983b4bf2Smrg
861983b4bf2Smrgstatic int
862983b4bf2Smrgvia_tmds_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
863983b4bf2Smrg{
864983b4bf2Smrg    ScrnInfoPtr pScrn = output->scrn;
865983b4bf2Smrg    int status;
866983b4bf2Smrg
867983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
868983b4bf2Smrg                        "Entered via_tmds_mode_valid.\n"));
869983b4bf2Smrg
870983b4bf2Smrg    if (!ViaModeDotClockTranslate(pScrn, pMode)) {
871983b4bf2Smrg        status = MODE_NOCLOCK;
872983b4bf2Smrg    } else {
873983b4bf2Smrg        status = MODE_OK;
874983b4bf2Smrg    }
875983b4bf2Smrg
876983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
877983b4bf2Smrg                        "Exiting via_tmds_mode_valid.\n"));
878983b4bf2Smrg    return status;
879983b4bf2Smrg}
880983b4bf2Smrg
881983b4bf2Smrgstatic Bool
882983b4bf2Smrgvia_tmds_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
883983b4bf2Smrg                      DisplayModePtr adjusted_mode)
884983b4bf2Smrg{
885983b4bf2Smrg    ScrnInfoPtr pScrn = output->scrn;
886983b4bf2Smrg
887983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
888983b4bf2Smrg                        "Entered via_tmds_mode_fixup.\n"));
889983b4bf2Smrg
890983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
891983b4bf2Smrg                        "Exiting via_tmds_mode_fixup.\n"));
892983b4bf2Smrg    return TRUE;
893983b4bf2Smrg}
894983b4bf2Smrg
895983b4bf2Smrgstatic void
896983b4bf2Smrgvia_tmds_prepare(xf86OutputPtr output)
897983b4bf2Smrg{
898983b4bf2Smrg    ScrnInfoPtr pScrn = output->scrn;
899983b4bf2Smrg
900983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
901983b4bf2Smrg                        "Entered via_tmds_prepare.\n"));
902983b4bf2Smrg
903983b4bf2Smrg    viaTMDSPower(pScrn, FALSE);
904983b4bf2Smrg    viaTMDSIOPadSetting(pScrn, FALSE);
905983b4bf2Smrg
906983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
907983b4bf2Smrg                        "Exiting via_tmds_prepare.\n"));
908983b4bf2Smrg}
909983b4bf2Smrg
910983b4bf2Smrgstatic void
911983b4bf2Smrgvia_tmds_commit(xf86OutputPtr output)
912983b4bf2Smrg{
913983b4bf2Smrg    ScrnInfoPtr pScrn = output->scrn;
914983b4bf2Smrg
915983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
916983b4bf2Smrg                        "Entered via_tmds_commit.\n"));
917983b4bf2Smrg
918983b4bf2Smrg    viaTMDSPower(pScrn, TRUE);
919983b4bf2Smrg    viaTMDSIOPadSetting(pScrn, TRUE);
920983b4bf2Smrg
921983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
922983b4bf2Smrg                        "Exiting via_tmds_commit.\n"));
923983b4bf2Smrg}
924983b4bf2Smrg
925983b4bf2Smrgstatic void
926983b4bf2Smrgvia_tmds_mode_set(xf86OutputPtr output, DisplayModePtr mode,
927983b4bf2Smrg                    DisplayModePtr adjusted_mode)
928983b4bf2Smrg{
929983b4bf2Smrg    ScrnInfoPtr pScrn = output->scrn;
930983b4bf2Smrg    drmmode_crtc_private_ptr iga = output->crtc->driver_private;
931983b4bf2Smrg
932983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
933983b4bf2Smrg                        "Entered via_tmds_mode_set.\n"));
934983b4bf2Smrg
935983b4bf2Smrg    /* Initialize VIA IGP integrated TMDS transmitter registers. */
936983b4bf2Smrg    viaTMDSInitRegisters(pScrn);
937983b4bf2Smrg
938983b4bf2Smrg    /* Set integrated TMDS transmitter synchronization polarity for
939983b4bf2Smrg     * both horizontal synchronization and vertical synchronization. */
940983b4bf2Smrg    viaTMDSSetSyncPolarity(pScrn, adjusted_mode);
941983b4bf2Smrg
942983b4bf2Smrg    if (output->crtc) {
943983b4bf2Smrg        viaTMDSSetSource(pScrn, iga->index ? 0x01 : 0x00);
944983b4bf2Smrg    }
945983b4bf2Smrg
946983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
947983b4bf2Smrg                        "Exiting via_tmds_mode_set.\n"));
948983b4bf2Smrg}
949983b4bf2Smrg
950983b4bf2Smrgstatic xf86OutputStatus
951983b4bf2Smrgvia_tmds_detect(xf86OutputPtr output)
952983b4bf2Smrg{
953983b4bf2Smrg    xf86MonPtr mon;
954983b4bf2Smrg    xf86OutputStatus status = XF86OutputStatusDisconnected;
955983b4bf2Smrg    ScrnInfoPtr pScrn = output->scrn;
956983b4bf2Smrg    VIAPtr pVia = VIAPTR(pScrn);
957983b4bf2Smrg
958983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
959983b4bf2Smrg                        "Entered via_tmds_detect.\n"));
960983b4bf2Smrg
961983b4bf2Smrg    /* Check for DVI presence by sensing the TMDS receiver connected
962983b4bf2Smrg     * to the integrated TMDS transmitter. */
963983b4bf2Smrg    if (viaTMDSSense(pScrn)) {
964983b4bf2Smrg
965983b4bf2Smrg        if (!pVia->pI2CBus2) {
966983b4bf2Smrg            goto exit;
967983b4bf2Smrg        }
968983b4bf2Smrg
969983b4bf2Smrg        /* Assume that only I2C bus 2 is used for the DVI connected to the
970983b4bf2Smrg         * integrated TMDS transmitter. */
971983b4bf2Smrg        if (!xf86I2CProbeAddress(pVia->pI2CBus2, 0xA0)) {
972983b4bf2Smrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
973983b4bf2Smrg                        "I2C device on I2C Bus 2 does not support EDID.\n");
974983b4bf2Smrg            goto exit;
975983b4bf2Smrg        }
976983b4bf2Smrg
977983b4bf2Smrg        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
978983b4bf2Smrg                    "Obtaining EDID for DVI.\n");
979983b4bf2Smrg
980983b4bf2Smrg        /* Since DVI presence was established, access the I2C bus,
981983b4bf2Smrg         * in order to obtain EDID from the monitor. */
982983b4bf2Smrg        mon = xf86OutputGetEDID(output, pVia->pI2CBus2);
983983b4bf2Smrg
984983b4bf2Smrg        /* Is the interface type digital? */
985983b4bf2Smrg        if (mon && DIGITAL(mon->features.input_type)) {
986983b4bf2Smrg            status = XF86OutputStatusConnected;
987983b4bf2Smrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
988983b4bf2Smrg                        "Detected a monitor connected to DVI.\n");
989983b4bf2Smrg            xf86OutputSetEDID(output, mon);
990983b4bf2Smrg        } else {
991983b4bf2Smrg            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
992983b4bf2Smrg                        "Could not obtain EDID from a monitor "
993983b4bf2Smrg                        "connected to DVI.\n");
994983b4bf2Smrg        }
995983b4bf2Smrg    }
996983b4bf2Smrg
997983b4bf2Smrgexit:
998983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
999983b4bf2Smrg                        "Exiting via_tmds_detect.\n"));
1000983b4bf2Smrg    return status;
1001983b4bf2Smrg}
1002983b4bf2Smrg
1003983b4bf2Smrg#ifdef RANDR_12_INTERFACE
1004983b4bf2Smrgstatic Bool
1005983b4bf2Smrgvia_tmds_set_property(xf86OutputPtr output, Atom property,
1006983b4bf2Smrg                     RRPropertyValuePtr value)
1007983b4bf2Smrg{
1008983b4bf2Smrg    ScrnInfoPtr pScrn = output->scrn;
1009983b4bf2Smrg
1010983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1011983b4bf2Smrg                        "Entered via_tmds_set_property.\n"));
1012983b4bf2Smrg
1013983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1014983b4bf2Smrg                        "Exiting via_tmds_set_property.\n"));
1015983b4bf2Smrg    return TRUE;
1016983b4bf2Smrg}
1017983b4bf2Smrg#endif
1018983b4bf2Smrg
1019983b4bf2Smrg#ifdef RANDR_13_INTERFACE
1020983b4bf2Smrgstatic Bool
1021983b4bf2Smrgvia_tmds_get_property(xf86OutputPtr output, Atom property)
1022983b4bf2Smrg{
1023983b4bf2Smrg    ScrnInfoPtr pScrn = output->scrn;
1024983b4bf2Smrg
1025983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1026983b4bf2Smrg                        "Entered via_tmds_get_property.\n"));
1027983b4bf2Smrg
1028983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1029983b4bf2Smrg                        "Exiting via_tmds_get_property.\n"));
1030983b4bf2Smrg    return FALSE;
1031983b4bf2Smrg}
1032983b4bf2Smrg#endif
1033983b4bf2Smrg
1034983b4bf2Smrgstatic void
1035983b4bf2Smrgvia_tmds_destroy(xf86OutputPtr output)
1036983b4bf2Smrg{
1037983b4bf2Smrg    ScrnInfoPtr pScrn = output->scrn;
1038983b4bf2Smrg
1039983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1040983b4bf2Smrg                        "Entered via_tmds_destroy.\n"));
1041983b4bf2Smrg
1042983b4bf2Smrg    if (output->driver_private) {
1043983b4bf2Smrg        free(output->driver_private);
1044983b4bf2Smrg    }
1045983b4bf2Smrg
1046983b4bf2Smrg    output->driver_private = NULL;
1047983b4bf2Smrg
1048983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1049983b4bf2Smrg                        "Exiting via_tmds_destroy.\n"));
1050983b4bf2Smrg}
1051983b4bf2Smrg
1052983b4bf2Smrg
1053983b4bf2Smrg
1054983b4bf2Smrg
1055983b4bf2Smrgstatic const xf86OutputFuncsRec via_tmds_funcs = {
1056983b4bf2Smrg    .create_resources   = via_tmds_create_resources,
1057983b4bf2Smrg    .dpms               = via_tmds_dpms,
1058983b4bf2Smrg    .save               = via_tmds_save,
1059983b4bf2Smrg    .restore            = via_tmds_restore,
1060983b4bf2Smrg    .mode_valid         = via_tmds_mode_valid,
1061983b4bf2Smrg    .mode_fixup         = via_tmds_mode_fixup,
1062983b4bf2Smrg    .prepare            = via_tmds_prepare,
1063983b4bf2Smrg    .commit             = via_tmds_commit,
1064983b4bf2Smrg    .mode_set           = via_tmds_mode_set,
1065983b4bf2Smrg    .detect             = via_tmds_detect,
1066983b4bf2Smrg    .get_modes          = xf86OutputGetEDIDModes,
1067983b4bf2Smrg#ifdef RANDR_12_INTERFACE
1068983b4bf2Smrg    .set_property       = via_tmds_set_property,
1069983b4bf2Smrg#endif
1070983b4bf2Smrg#ifdef RANDR_13_INTERFACE
1071983b4bf2Smrg    .get_property       = via_tmds_get_property,
1072983b4bf2Smrg#endif
1073983b4bf2Smrg    .destroy            = via_tmds_destroy,
1074983b4bf2Smrg};
1075983b4bf2Smrg
1076983b4bf2Smrg
1077983b4bf2SmrgBool
1078983b4bf2SmrgviaTMDSInit(ScrnInfoPtr pScrn)
1079983b4bf2Smrg{
1080983b4bf2Smrg    xf86OutputPtr output;
1081983b4bf2Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
1082983b4bf2Smrg    VIAPtr pVia = VIAPTR(pScrn);
1083983b4bf2Smrg    VIATMDSRecPtr pVIATMDSRec = NULL;
1084983b4bf2Smrg    CARD8 sr13, sr5a;
1085983b4bf2Smrg    Bool status = FALSE;
1086983b4bf2Smrg    char outputNameBuffer[32];
1087983b4bf2Smrg
1088983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1089983b4bf2Smrg                        "Entered viaTMDSInit.\n"));
1090983b4bf2Smrg
1091983b4bf2Smrg    sr5a = hwp->readSeq(hwp, 0x5A);
1092983b4bf2Smrg    ViaSeqMask(hwp, 0x5A, sr5a | 0x01, 0x01);
1093983b4bf2Smrg    sr13 = hwp->readSeq(hwp, 0x13);
1094983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1095983b4bf2Smrg                        "SR13: 0x%02X\n", sr13));
1096983b4bf2Smrg    hwp->writeSeq(hwp, 0x5A, sr5a);
1097983b4bf2Smrg
1098983b4bf2Smrg    /* 3C5.13[7:6] - Integrated LVDS / DVI Mode Select
1099983b4bf2Smrg     *               (DVP1D15-14 pin strapping)
1100983b4bf2Smrg     *               00: LVDS1 + LVDS2
1101983b4bf2Smrg     *               01: DVI + LVDS2
1102983b4bf2Smrg     *               10: Dual LVDS Channel (High Resolution Panel)
1103983b4bf2Smrg     *               11: One DVI only (decrease the clock jitter) */
1104983b4bf2Smrg    /* Check for DVI presence using pin strappings.
1105983b4bf2Smrg     * VIA Technologies NanoBook reference design based products
1106983b4bf2Smrg     * have their pin strappings set to a wrong setting to communicate
1107983b4bf2Smrg     * the presence of DVI, so it requires special handling here. */
1108983b4bf2Smrg    if ((((~(sr13 & 0x80)) && (sr13 & 0x40))
1109983b4bf2Smrg         || ((sr13 & 0x80) && (sr13 & 0x40)))
1110983b4bf2Smrg       || (pVia->isVIANanoBook)) {
1111983b4bf2Smrg
1112983b4bf2Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1113983b4bf2Smrg                    "Integrated TMDS transmitter found via pin strapping.\n");
1114983b4bf2Smrg    } else {
1115983b4bf2Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1116983b4bf2Smrg                    "Integrated TMDS transmitter not found.\n");
1117983b4bf2Smrg        goto exit;
1118983b4bf2Smrg    }
1119983b4bf2Smrg
1120983b4bf2Smrg    pVIATMDSRec = xnfcalloc(1, sizeof(VIATMDSRec));
1121983b4bf2Smrg    if (!pVIATMDSRec) {
1122983b4bf2Smrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1123983b4bf2Smrg                    "Failed to allocate working storage for integrated "
1124983b4bf2Smrg                    "TMDS transmitter.\n");
1125983b4bf2Smrg        goto exit;
1126983b4bf2Smrg    }
1127983b4bf2Smrg
1128983b4bf2Smrg    /* The code to dynamically designate the particular DVI (i.e., DVI-1,
1129983b4bf2Smrg     * DVI-2, etc.) for xrandr was borrowed from xf86-video-r128 DDX. */
1130983b4bf2Smrg    sprintf(outputNameBuffer, "DVI-%d", (pVia->numberDVI + 1));
1131983b4bf2Smrg    output = xf86OutputCreate(pScrn, &via_tmds_funcs, outputNameBuffer);
1132983b4bf2Smrg    if (!output) {
1133983b4bf2Smrg        free(pVIATMDSRec);
1134983b4bf2Smrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1135983b4bf2Smrg                    "Failed to allocate X Server display output record for "
1136983b4bf2Smrg                    "integrated TMDS transmitter.\n");
1137983b4bf2Smrg        goto exit;
1138983b4bf2Smrg    }
1139983b4bf2Smrg
1140983b4bf2Smrg    output->driver_private = pVIATMDSRec;
1141983b4bf2Smrg
1142983b4bf2Smrg    /* Since there are two (2) display controllers registered with the
1143983b4bf2Smrg     * X.Org Server and both IGA1 and IGA2 can handle DVI without any
1144983b4bf2Smrg     * limitations, possible_crtcs should be set to 0x3 (0b11) so that
1145983b4bf2Smrg     * either display controller can get assigned to handle DVI. */
1146983b4bf2Smrg    output->possible_crtcs = (1 << 1) | (1 << 0);
1147983b4bf2Smrg
1148983b4bf2Smrg    output->possible_clones = 0;
1149983b4bf2Smrg    output->interlaceAllowed = FALSE;
1150983b4bf2Smrg    output->doubleScanAllowed = FALSE;
1151983b4bf2Smrg
1152983b4bf2Smrg    pVia->numberDVI++;
1153983b4bf2Smrg    status = TRUE;
1154983b4bf2Smrgexit:
1155983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1156983b4bf2Smrg                        "Exiting viaTMDSInit.\n"));
1157983b4bf2Smrg    return status;
1158983b4bf2Smrg}
1159983b4bf2Smrg
1160983b4bf2Smrgvoid
1161983b4bf2Smrgvia_dvi_init(ScrnInfoPtr pScrn)
1162983b4bf2Smrg{
1163983b4bf2Smrg    VIAPtr pVia = VIAPTR(pScrn);
1164983b4bf2Smrg
1165983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1166983b4bf2Smrg                        "Entered via_dvi_init.\n"));
1167983b4bf2Smrg
1168983b4bf2Smrg    if (!pVia->pI2CBus2 || !pVia->pI2CBus3) {
1169983b4bf2Smrg        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1170983b4bf2Smrg                    "I2C Bus 2 or I2C Bus 3 does not exist.\n");
1171983b4bf2Smrg        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1172983b4bf2Smrg                    "Exiting via_dvi_init.\n"));
1173983b4bf2Smrg        return;
1174983b4bf2Smrg    }
1175983b4bf2Smrg
1176983b4bf2Smrg    /* Check to see if we are dealing with the latest VIA chipsets. */
1177983b4bf2Smrg    if ((pVia->Chipset == VIA_CX700)
1178983b4bf2Smrg        || (pVia->Chipset == VIA_VX800)
1179983b4bf2Smrg        || (pVia->Chipset == VIA_VX855)
1180983b4bf2Smrg        || (pVia->Chipset == VIA_VX900)) {
1181983b4bf2Smrg
1182983b4bf2Smrg        if (!viaTMDSInit(pScrn)) {
1183983b4bf2Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1184983b4bf2Smrg                        "Integrated TMDS transmitter for DVI not found.\n");
1185983b4bf2Smrg        } else {
1186983b4bf2Smrg            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1187983b4bf2Smrg                        "Integrated TMDS transmitter for DVI was "
1188983b4bf2Smrg                        "initialized successfully.\n");
1189983b4bf2Smrg        }
1190983b4bf2Smrg    }
1191983b4bf2Smrg
1192983b4bf2Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1193983b4bf2Smrg                "Probing I2C Bus 2 for VT1632.\n");
1194983b4bf2Smrg    if (!viaVT1632Init(pScrn, pVia->pI2CBus2)) {
1195983b4bf2Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1196983b4bf2Smrg                    "I2C Bus 2 was not initialized for DVI use.\n");
1197983b4bf2Smrg    } else {
1198983b4bf2Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1199983b4bf2Smrg                    "VT1632 attached to I2C Bus 2 was initialized "
1200983b4bf2Smrg                    "successfully for DVI use.\n");
1201983b4bf2Smrg    }
1202983b4bf2Smrg
1203983b4bf2Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1204983b4bf2Smrg                "Probing I2C Bus 3 for VT1632.\n");
1205983b4bf2Smrg    if (!viaVT1632Init(pScrn, pVia->pI2CBus3)) {
1206983b4bf2Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1207983b4bf2Smrg                    "I2C Bus 3 was not initialized for DVI use.\n");
1208983b4bf2Smrg    } else {
1209983b4bf2Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1210983b4bf2Smrg                    "VT1632 attached to I2C Bus 3 was initialized "
1211983b4bf2Smrg                    "successfully for DVI use.\n");
1212983b4bf2Smrg    }
1213983b4bf2Smrg
1214983b4bf2Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1215983b4bf2Smrg                "Probing I2C Bus 2 for SiI 164.\n");
1216983b4bf2Smrg    if (!viaSiI164Init(pScrn, pVia->pI2CBus2)) {
1217983b4bf2Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1218983b4bf2Smrg                    "I2C Bus 2 was not initialized for DVI use.\n");
1219983b4bf2Smrg    } else {
1220983b4bf2Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1221983b4bf2Smrg                    "SiI 164 attached to I2C Bus 2 was initialized "
1222983b4bf2Smrg                    "successfully for DVI use.\n");
1223983b4bf2Smrg    }
1224983b4bf2Smrg
1225983b4bf2Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1226983b4bf2Smrg                "Probing I2C Bus 3 for SiI 164.\n");
1227983b4bf2Smrg    if (!viaSiI164Init(pScrn, pVia->pI2CBus3)) {
1228983b4bf2Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1229983b4bf2Smrg                    "I2C Bus 3 was not initialized for DVI use.\n");
1230983b4bf2Smrg    } else {
1231983b4bf2Smrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1232983b4bf2Smrg                    "SiI 164 attached to I2C Bus 3 was initialized "
1233983b4bf2Smrg                    "successfully for DVI use.\n");
1234983b4bf2Smrg    }
1235983b4bf2Smrg
1236983b4bf2Smrg    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1237983b4bf2Smrg                        "Exiting via_dvi_init.\n"));
1238983b4bf2Smrg}
1239