via_outputs.c revision 963d66ac
1/*
2 * Copyright 2005-2015 The Openchrome Project
3 *                     [http://www.freedesktop.org/wiki/Openchrome]
4 * Copyright 2004-2005 The Unichrome Project  [unichrome.sf.net]
5 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
6 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sub license,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the
16 * next paragraph) shall be included in all copies or substantial portions
17 * of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 */
27
28/*
29 * via_outputs.c
30 *
31 * Everything to do with setting and changing xf86Outputs.
32 *
33 */
34
35#ifdef HAVE_CONFIG_H
36#include "config.h"
37#endif
38
39#include "via_driver.h"
40#include <unistd.h>
41
42/*
43 * Modetable nonsense.
44 *
45 */
46#include "via_mode.h"
47
48static void
49ViaPrintMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
50{
51    xf86PrintModeline(pScrn->scrnIndex, mode);
52
53    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHDisplay: 0x%x\n",
54               mode->CrtcHDisplay);
55    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHBlankStart: 0x%x\n",
56               mode->CrtcHBlankStart);
57    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHSyncStart: 0x%x\n",
58               mode->CrtcHSyncStart);
59    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHSyncEnd: 0x%x\n",
60               mode->CrtcHSyncEnd);
61    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHBlankEnd: 0x%x\n",
62               mode->CrtcHBlankEnd);
63    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHTotal: 0x%x\n",
64               mode->CrtcHTotal);
65    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHSkew: 0x%x\n",
66               mode->CrtcHSkew);
67    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVDisplay: 0x%x\n",
68               mode->CrtcVDisplay);
69    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVBlankStart: 0x%x\n",
70               mode->CrtcVBlankStart);
71    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVSyncStart: 0x%x\n",
72               mode->CrtcVSyncStart);
73    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVSyncEnd: 0x%x\n",
74               mode->CrtcVSyncEnd);
75    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVBlankEnd: 0x%x\n",
76               mode->CrtcVBlankEnd);
77    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVTotal: 0x%x\n",
78               mode->CrtcVTotal);
79
80}
81
82/*
83 *
84 * TV specific code.
85 *
86 */
87void
88ViaTVSave(ScrnInfoPtr pScrn)
89{
90    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
91
92    if (pBIOSInfo->TVSave)
93        pBIOSInfo->TVSave(pScrn);
94}
95
96void
97ViaTVRestore(ScrnInfoPtr pScrn)
98{
99    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
100
101    if (pBIOSInfo->TVRestore)
102        pBIOSInfo->TVRestore(pScrn);
103}
104
105static Bool
106ViaTVDACSense(ScrnInfoPtr pScrn)
107{
108    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
109
110    if (pBIOSInfo->TVDACSense)
111        return pBIOSInfo->TVDACSense(pScrn);
112    return FALSE;
113}
114
115static void
116ViaTVSetMode(xf86CrtcPtr crtc, DisplayModePtr mode)
117{
118    ScrnInfoPtr pScrn = crtc->scrn;
119    VIAPtr pVia = VIAPTR(pScrn);
120    VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
121
122    if (pBIOSInfo->TVModeI2C)
123        pBIOSInfo->TVModeI2C(pScrn, mode);
124
125    if (pBIOSInfo->TVModeCrtc)
126        pBIOSInfo->TVModeCrtc(crtc, mode);
127
128    /* TV reset. */
129    xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1D, 0x00);
130    xf86I2CWriteByte(pBIOSInfo->TVI2CDev, 0x1D, 0x80);
131}
132
133void
134ViaTVPower(ScrnInfoPtr pScrn, Bool On)
135{
136    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
137
138#ifdef HAVE_DEBUG
139    if (On)
140        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaTVPower: On.\n");
141    else
142        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaTVPower: Off.\n");
143#endif
144
145    if (pBIOSInfo->TVPower)
146        pBIOSInfo->TVPower(pScrn, On);
147}
148
149#ifdef HAVE_DEBUG
150void
151ViaTVPrintRegs(ScrnInfoPtr pScrn)
152{
153    VIABIOSInfoPtr pBIOSInfo = VIAPTR(pScrn)->pBIOSInfo;
154
155    if (pBIOSInfo->TVPrintRegs)
156        pBIOSInfo->TVPrintRegs(pScrn);
157}
158#endif /* HAVE_DEBUG */
159
160static void
161via_tv_create_resources(xf86OutputPtr output)
162{
163}
164
165#ifdef RANDR_12_INTERFACE
166static Bool
167via_tv_set_property(xf86OutputPtr output, Atom property,
168                    RRPropertyValuePtr value)
169{
170    return TRUE;
171}
172
173static Bool
174via_tv_get_property(xf86OutputPtr output, Atom property)
175{
176    return FALSE;
177}
178#endif
179
180static void
181via_tv_dpms(xf86OutputPtr output, int mode)
182{
183    ScrnInfoPtr pScrn = output->scrn;
184
185    switch (mode) {
186    case DPMSModeOn:
187        ViaTVPower(pScrn, TRUE);
188        break;
189
190    case DPMSModeStandby:
191    case DPMSModeSuspend:
192    case DPMSModeOff:
193        ViaTVPower(pScrn, FALSE);
194        break;
195    }
196}
197
198static void
199via_tv_save(xf86OutputPtr output)
200{
201    ScrnInfoPtr pScrn = output->scrn;
202
203    ViaTVSave(pScrn);
204}
205
206static void
207via_tv_restore(xf86OutputPtr output)
208{
209    ScrnInfoPtr pScrn = output->scrn;
210
211    ViaTVRestore(pScrn);
212}
213
214static int
215via_tv_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
216{
217    ScrnInfoPtr pScrn = output->scrn;
218    VIAPtr pVia = VIAPTR(pScrn);
219    int ret = MODE_OK;
220
221    if (!ViaModeDotClockTranslate(pScrn, pMode))
222        return MODE_NOCLOCK;
223
224    return ret;
225}
226
227static Bool
228via_tv_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
229                  DisplayModePtr adjusted_mode)
230{
231    return TRUE;
232}
233
234static void
235via_tv_prepare(xf86OutputPtr output)
236{
237    via_tv_dpms(output, DPMSModeOff);
238}
239
240static void
241via_tv_commit(xf86OutputPtr output)
242{
243    via_tv_dpms(output, DPMSModeOn);
244}
245
246static void
247ViaDisplayEnableDVO(ScrnInfoPtr pScrn, int port)
248{
249    vgaHWPtr hwp = VGAHWPTR(pScrn);
250
251    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisplayEnableDVO, port: %d\n",
252                     port));
253    switch (port) {
254    case VIA_DI_PORT_DVP0:
255        ViaSeqMask(hwp, 0x1E, 0xC0, 0xC0);
256        break;
257    case VIA_DI_PORT_DVP1:
258        ViaSeqMask(hwp, 0x1E, 0x30, 0x30);
259        break;
260    }
261}
262
263static void
264ViaDisplayDisableDVO(ScrnInfoPtr pScrn, int port)
265{
266    vgaHWPtr hwp = VGAHWPTR(pScrn);
267
268    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisplayDisableDVO, port: %d\n",
269                     port));
270    switch (port) {
271    case VIA_DI_PORT_DVP0:
272        ViaSeqMask(hwp, 0x1E, 0x00, 0xC0);
273        break;
274    case VIA_DI_PORT_DVP1:
275        ViaSeqMask(hwp, 0x1E, 0x00, 0x30);
276        break;
277    }
278}
279
280static void
281ViaDisplaySetStreamOnDVO(ScrnInfoPtr pScrn, int port, int iga)
282{
283    vgaHWPtr hwp = VGAHWPTR(pScrn);
284    int regNum;
285
286    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisplaySetStreamOnDVO, port: %d\n",
287                     port));
288
289    switch (port) {
290        case VIA_DI_PORT_DVP0:
291            regNum = 0x96;
292            break;
293        case VIA_DI_PORT_DVP1:
294            regNum = 0x9B;
295            break;
296        case VIA_DI_PORT_DFPLOW:
297            regNum = 0x97;
298            break;
299        case VIA_DI_PORT_DFPHIGH:
300            regNum = 0x99;
301            break;
302    }
303
304    if (!iga)
305        ViaCrtcMask(hwp, regNum, 0x00, 0x10);
306    else
307        ViaCrtcMask(hwp, regNum, 0x10, 0x10);
308}
309
310static void
311via_tv_mode_set(xf86OutputPtr output, DisplayModePtr mode,
312                DisplayModePtr adjusted_mode)
313{
314    ScrnInfoPtr pScrn = output->scrn;
315    VIAPtr pVia = VIAPTR(pScrn);
316    VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
317
318    /* TV on FirstCrtc */
319    if (output->crtc) {
320        drmmode_crtc_private_ptr iga = output->crtc->driver_private;
321
322        ViaDisplaySetStreamOnDVO(pScrn, pBIOSInfo->TVDIPort, iga->index);
323    }
324    ViaDisplayEnableDVO(pScrn, pBIOSInfo->TVDIPort);
325
326    ViaTVSetMode(output->crtc, adjusted_mode);
327
328    pVia->FirstInit = FALSE;
329}
330
331static xf86OutputStatus
332via_tv_detect(xf86OutputPtr output)
333{
334    xf86OutputStatus status = XF86OutputStatusDisconnected;
335    ScrnInfoPtr pScrn = output->scrn;
336
337    if (ViaTVDACSense(pScrn))
338        status = XF86OutputStatusConnected;
339    return status;
340}
341
342static DisplayModePtr
343via_tv_get_modes(xf86OutputPtr output)
344{
345    DisplayModePtr modes = NULL, mode = NULL;
346    ScrnInfoPtr pScrn = output->scrn;
347    VIAPtr pVia = VIAPTR(pScrn);
348    int i;
349
350    for (i = 0; i < pVia->pBIOSInfo->TVNumModes; i++) {
351        mode = xf86DuplicateMode(&pVia->pBIOSInfo->TVModes[i]);
352        modes = xf86ModesAdd(modes, mode);
353    }
354    return modes;
355}
356
357static void
358via_tv_destroy(xf86OutputPtr output)
359{
360}
361
362static const xf86OutputFuncsRec via_tv_funcs = {
363    .create_resources   = via_tv_create_resources,
364#ifdef RANDR_12_INTERFACE
365    .set_property       = via_tv_set_property,
366#endif
367#ifdef RANDR_13_INTERFACE
368    .get_property       = via_tv_get_property,
369#endif
370    .dpms               = via_tv_dpms,
371    .save               = via_tv_save,
372    .restore            = via_tv_restore,
373    .mode_valid         = via_tv_mode_valid,
374    .mode_fixup         = via_tv_mode_fixup,
375    .prepare            = via_tv_prepare,
376    .commit             = via_tv_commit,
377    .mode_set           = via_tv_mode_set,
378    .detect             = via_tv_detect,
379    .get_modes          = via_tv_get_modes,
380    .destroy            = via_tv_destroy,
381};
382
383/*
384 *
385 */
386static Bool
387via_tv_init(ScrnInfoPtr pScrn)
388{
389    VIAPtr pVia = VIAPTR(pScrn);
390    VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
391    xf86OutputPtr output = NULL;
392
393    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
394                        "Entered via_tv_init.\n"));
395
396    /* preset some pBIOSInfo TV related values -- move up */
397    pBIOSInfo->TVEncoder = VIA_NONETV;
398    pBIOSInfo->TVI2CDev = NULL;
399    pBIOSInfo->TVSave = NULL;
400    pBIOSInfo->TVRestore = NULL;
401    pBIOSInfo->TVDACSense = NULL;
402    pBIOSInfo->TVModeValid = NULL;
403    pBIOSInfo->TVModeI2C = NULL;
404    pBIOSInfo->TVModeCrtc = NULL;
405    pBIOSInfo->TVPower = NULL;
406    pBIOSInfo->TVModes = NULL;
407    pBIOSInfo->TVPrintRegs = NULL;
408    pBIOSInfo->LCDPower = NULL;
409    pBIOSInfo->TVNumRegs = 0;
410
411    /*
412     * On an SK43G (KM400/Ch7011), false positive detections at a VT162x
413     * chip were observed, so try to detect the Ch7011 first.
414     */
415    if (pVia->pI2CBus2 && xf86I2CProbeAddress(pVia->pI2CBus2, 0xEC))
416        pBIOSInfo->TVI2CDev = ViaCH7xxxDetect(pScrn, pVia->pI2CBus2, 0xEC);
417    else if (pVia->pI2CBus2 && xf86I2CProbeAddress(pVia->pI2CBus2, 0x40))
418        pBIOSInfo->TVI2CDev = ViaVT162xDetect(pScrn, pVia->pI2CBus2, 0x40);
419    else if (pVia->pI2CBus3 && xf86I2CProbeAddress(pVia->pI2CBus3, 0x40))
420        pBIOSInfo->TVI2CDev = ViaVT162xDetect(pScrn, pVia->pI2CBus3, 0x40);
421    else if (pVia->pI2CBus2 && xf86I2CProbeAddress(pVia->pI2CBus2, 0xEA))
422        pBIOSInfo->TVI2CDev = ViaCH7xxxDetect(pScrn, pVia->pI2CBus2, 0xEA);
423    else if (pVia->pI2CBus3 && xf86I2CProbeAddress(pVia->pI2CBus3, 0xEA))
424        pBIOSInfo->TVI2CDev = ViaCH7xxxDetect(pScrn, pVia->pI2CBus3, 0xEA);
425
426    if (!pBIOSInfo->TVI2CDev) {
427        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
428                    "Did not detect a TV encoder.\n");
429        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
430                            "Exiting via_tv_init.\n"));
431
432        return FALSE;
433    }
434
435    switch (pBIOSInfo->TVEncoder) {
436        case VIA_VT1621:
437        case VIA_VT1622:
438        case VIA_VT1623:
439        case VIA_VT1625:
440            ViaVT162xInit(pScrn);
441            break;
442        case VIA_CH7011:
443        case VIA_CH7019A:
444        case VIA_CH7019B:
445            ViaCH7xxxInit(pScrn);
446            break;
447        default:
448            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
449                        "Was not able to initialize a known TV encoder.\n");
450            DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
451                                "Exiting via_tv_init.\n"));
452            return FALSE;
453            break;
454    }
455
456    if (!pBIOSInfo->TVSave || !pBIOSInfo->TVRestore
457        || !pBIOSInfo->TVDACSense || !pBIOSInfo->TVModeValid
458        || !pBIOSInfo->TVModeI2C || !pBIOSInfo->TVModeCrtc
459        || !pBIOSInfo->TVPower || !pBIOSInfo->TVModes
460        || !pBIOSInfo->TVPrintRegs) {
461
462        xf86DestroyI2CDevRec(pBIOSInfo->TVI2CDev, TRUE);
463
464        pBIOSInfo->TVI2CDev = NULL;
465        pBIOSInfo->TVOutput = TVOUTPUT_NONE;
466        pBIOSInfo->TVEncoder = VIA_NONETV;
467        pBIOSInfo->TVI2CDev = NULL;
468        pBIOSInfo->TVSave = NULL;
469        pBIOSInfo->TVRestore = NULL;
470        pBIOSInfo->TVDACSense = NULL;
471        pBIOSInfo->TVModeValid = NULL;
472        pBIOSInfo->TVModeI2C = NULL;
473        pBIOSInfo->TVModeCrtc = NULL;
474        pBIOSInfo->TVPower = NULL;
475        pBIOSInfo->TVModes = NULL;
476        pBIOSInfo->TVPrintRegs = NULL;
477        pBIOSInfo->TVNumRegs = 0;
478
479        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
480                   "TV encoder was not properly initialized.\n");
481        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
482                            "Exiting via_tv_init.\n"));
483        return FALSE;
484    }
485
486    output = xf86OutputCreate(pScrn, &via_tv_funcs, "TV-1");
487    pVia->FirstInit = TRUE;
488
489    if (output) {
490        /* Allow tv output on both crtcs, set bit 0 and 1. */
491        output->possible_crtcs = 0x3;
492    } else {
493        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
494                   "Failed to register TV-1.\n");
495    }
496
497    pBIOSInfo->tv = output;
498    /* Save now */
499    pBIOSInfo->TVSave(pScrn);
500
501#ifdef HAVE_DEBUG
502    if (VIAPTR(pScrn)->PrintTVRegs)
503        pBIOSInfo->TVPrintRegs(pScrn);
504#endif
505
506    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
507                        "Exiting via_tv_init.\n"));
508    return TRUE;
509}
510
511/*
512 * Enables CRT using DPMS registers.
513 */
514static void
515ViaDisplayEnableCRT(ScrnInfoPtr pScrn)
516{
517    vgaHWPtr hwp = VGAHWPTR(pScrn);
518
519    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisplayEnableCRT\n"));
520    ViaCrtcMask(hwp, 0x36, 0x00, 0x30);
521}
522
523/*
524 * Disables CRT using DPMS registers.
525 */
526static void
527ViaDisplayDisableCRT(ScrnInfoPtr pScrn)
528{
529    vgaHWPtr hwp = VGAHWPTR(pScrn);
530
531    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisplayDisableCRT\n"));
532    ViaCrtcMask(hwp, 0x36, 0x30, 0x30);
533}
534
535static void
536via_analog_create_resources(xf86OutputPtr output)
537{
538}
539
540#ifdef RANDR_12_INTERFACE
541static Bool
542via_analog_set_property(xf86OutputPtr output, Atom property,
543                        RRPropertyValuePtr value)
544{
545    return TRUE;
546}
547
548static Bool
549via_analog_get_property(xf86OutputPtr output, Atom property)
550{
551    return FALSE;
552}
553#endif
554
555static void
556via_analog_dpms(xf86OutputPtr output, int mode)
557{
558    ScrnInfoPtr pScrn = output->scrn;
559
560    switch (mode) {
561    case DPMSModeOn:
562        ViaDisplayEnableCRT(pScrn);
563        break;
564
565    case DPMSModeStandby:
566    case DPMSModeSuspend:
567    case DPMSModeOff:
568        ViaDisplayDisableCRT(pScrn);
569        break;
570    }
571}
572
573static void
574via_analog_save(xf86OutputPtr output)
575{
576}
577
578static void
579via_analog_restore(xf86OutputPtr output)
580{
581}
582
583static int
584via_analog_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
585{
586    ScrnInfoPtr pScrn = output->scrn;
587
588    if (!ViaModeDotClockTranslate(pScrn, pMode))
589        return MODE_NOCLOCK;
590    return MODE_OK;
591}
592
593static Bool
594via_analog_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
595                      DisplayModePtr adjusted_mode)
596{
597    return TRUE;
598}
599
600static void
601via_analog_prepare(xf86OutputPtr output)
602{
603    via_analog_dpms(output, DPMSModeOff);
604}
605
606static void
607via_analog_commit(xf86OutputPtr output)
608{
609    via_analog_dpms(output, DPMSModeOn);
610}
611
612static void
613via_analog_mode_set(xf86OutputPtr output, DisplayModePtr mode,
614                    DisplayModePtr adjusted_mode)
615{
616    ScrnInfoPtr pScrn = output->scrn;
617
618    if (output->crtc) {
619        drmmode_crtc_private_ptr iga = output->crtc->driver_private;
620        CARD8 value = 0x00; /* Value for IGA 1 */
621        vgaHWPtr hwp = VGAHWPTR(pScrn);
622
623        /* IGA 2 */
624        if (iga->index)
625            value = 0x40;
626        ViaSeqMask(hwp, 0x16, value, 0x40);
627    }
628    ViaDisplayEnableCRT(pScrn);
629}
630
631static xf86OutputStatus
632via_analog_detect(xf86OutputPtr output)
633{
634    xf86OutputStatus status = XF86OutputStatusDisconnected;
635    ScrnInfoPtr pScrn = output->scrn;
636    VIAPtr pVia = VIAPTR(pScrn);
637    xf86MonPtr mon;
638
639    /* Probe I2C Bus 1 to see if a VGA monitor is connected. */
640    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
641                "Probing for a VGA monitor on I2C Bus 1.\n");
642    mon = xf86OutputGetEDID(output, pVia->pI2CBus1);
643    if (mon && (!mon->features.input_type)) {
644        xf86OutputSetEDID(output, mon);
645        status = XF86OutputStatusConnected;
646        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
647                    "Detected a VGA monitor on I2C Bus 1.\n");
648    } else {
649        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
650                    "Did not detect a VGA monitor on I2C Bus 1.\n");
651
652        /* Probe I2C Bus 2 to see if a VGA monitor is connected. */
653        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
654                    "Probing for a VGA monitor on I2C Bus 2.\n");
655        mon = xf86OutputGetEDID(output, pVia->pI2CBus2);
656        if (mon && (!mon->features.input_type)) {
657            xf86OutputSetEDID(output, mon);
658            status = XF86OutputStatusConnected;
659            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
660                        "Detected a VGA monitor on I2C Bus 2.\n");
661        } else {
662            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
663                        "Did not detect a VGA monitor on I2C Bus 2.\n");
664
665            /* Perform manual detection of a VGA monitor since */
666            /* it was not detected via I2C buses. */
667            xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
668                        "Now perform manual detection of a VGA "
669                        "monitor.\n");
670            vgaHWPtr hwp = VGAHWPTR(pScrn);
671            CARD8 SR01 = hwp->readSeq(hwp, 0x01);
672            CARD8 SR40 = hwp->readSeq(hwp, 0x40);
673            CARD8 CR36 = hwp->readCrtc(hwp, 0x36);
674
675            /* We have to power on the display to detect it */
676            ViaSeqMask(hwp, 0x01, 0x00, 0x20);
677            ViaCrtcMask(hwp, 0x36, 0x00, 0xF0);
678
679            /* Wait for vblank */
680            usleep(16);
681
682            /* Detect the load on pins */
683            ViaSeqMask(hwp, 0x40, 0x80, 0x80);
684
685            if ((VIA_CX700 == pVia->Chipset) ||
686                (VIA_VX800 == pVia->Chipset) ||
687                (VIA_VX855 == pVia->Chipset) ||
688                (VIA_VX900 == pVia->Chipset))
689                ViaSeqMask(hwp, 0x40, 0x00, 0x80);
690
691            if (ViaVgahwIn(hwp, 0x3C2) & 0x20) {
692                status = XF86OutputStatusConnected;
693                xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
694                            "Detected a VGA monitor using manual "
695                            "detection method.\n");
696            }
697
698            if ((VIA_CX700 == pVia->Chipset) ||
699                (VIA_VX800 == pVia->Chipset) ||
700                (VIA_VX855 == pVia->Chipset) ||
701                (VIA_VX900 == pVia->Chipset))
702                ViaSeqMask(hwp, 0x40, 0x00, 0x80);
703
704            /* Restore previous state */
705            hwp->writeSeq(hwp, 0x40, SR40);
706            hwp->writeSeq(hwp, 0x01, SR01);
707            hwp->writeCrtc(hwp, 0x36, CR36);
708        }
709    }
710
711    return status;
712}
713
714static void
715via_analog_destroy(xf86OutputPtr output)
716{
717}
718
719static const xf86OutputFuncsRec via_analog_funcs = {
720    .create_resources   = via_analog_create_resources,
721#ifdef RANDR_12_INTERFACE
722    .set_property       = via_analog_set_property,
723#endif
724#ifdef RANDR_13_INTERFACE
725    .get_property       = via_analog_get_property,
726#endif
727    .dpms               = via_analog_dpms,
728    .save               = via_analog_save,
729    .restore            = via_analog_restore,
730    .mode_valid         = via_analog_mode_valid,
731    .mode_fixup         = via_analog_mode_fixup,
732    .prepare            = via_analog_prepare,
733    .commit             = via_analog_commit,
734    .mode_set           = via_analog_mode_set,
735    .detect             = via_analog_detect,
736    .get_modes          = xf86OutputGetEDIDModes,
737    .destroy            = via_analog_destroy,
738};
739
740void
741via_analog_init(ScrnInfoPtr pScrn)
742{
743    VIAPtr pVia = VIAPTR(pScrn);
744    VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
745    xf86OutputPtr output = NULL;
746
747    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
748                        "Entered via_analog_init.\n"));
749
750    if (!pVia->pI2CBus1 || !pVia->pI2CBus2) {
751        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
752                    "I2C Bus 1 or I2C Bus 2 does not exist.\n");
753        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
754                            "Exiting via_analog_init.\n"));
755        return;
756    }
757
758    output = xf86OutputCreate(pScrn, &via_analog_funcs, "VGA-1");
759
760    output->possible_crtcs = 0x3;
761    output->possible_clones = 0;
762    output->interlaceAllowed = TRUE;
763    output->doubleScanAllowed = FALSE;
764    pBIOSInfo->analog = output;
765
766    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
767                        "Exiting via_analog_init.\n"));
768}
769
770static void
771via_dvi_create_resources(xf86OutputPtr output)
772{
773}
774
775#ifdef RANDR_12_INTERFACE
776static Bool
777via_dvi_set_property(xf86OutputPtr output, Atom property,
778                     RRPropertyValuePtr value)
779{
780    return TRUE;
781}
782
783static Bool
784via_dvi_get_property(xf86OutputPtr output, Atom property)
785{
786    return FALSE;
787}
788#endif
789
790static void
791via_dvi_dpms(xf86OutputPtr output, int mode)
792{
793    ScrnInfoPtr pScrn = output->scrn;
794
795    switch (mode) {
796    case DPMSModeOn:
797        ViaDFPPower(pScrn, TRUE);
798        break;
799
800    case DPMSModeStandby:
801    case DPMSModeSuspend:
802    case DPMSModeOff:
803        ViaDFPPower(pScrn, FALSE);
804        break;
805    }
806
807}
808
809static void
810via_dvi_save(xf86OutputPtr output)
811{
812    via_vt1632_save(output);
813}
814
815static void
816via_dvi_restore(xf86OutputPtr output)
817{
818    via_vt1632_restore(output);
819}
820
821static int
822via_dvi_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
823{
824    return via_vt1632_mode_valid(output, pMode);
825}
826
827static Bool
828via_dvi_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
829                   DisplayModePtr adjusted_mode)
830{
831    return TRUE;
832}
833
834static void
835via_dvi_prepare(xf86OutputPtr output)
836{
837}
838
839static void
840via_dvi_commit(xf86OutputPtr output)
841{
842}
843
844static void
845via_dvi_mode_set(xf86OutputPtr output, DisplayModePtr mode,
846                 DisplayModePtr adjusted_mode)
847{
848    ScrnInfoPtr pScrn = output->scrn;
849    vgaHWPtr hwp = VGAHWPTR(pScrn);
850
851    via_vt1632_power(output, FALSE);
852    ViaModeSecondCRTC(pScrn, mode);
853    via_vt1632_mode_set(output, mode, adjusted_mode);
854    via_vt1632_power(output, TRUE);
855}
856
857static xf86OutputStatus
858via_dvi_detect(xf86OutputPtr output)
859{
860    xf86OutputStatus status = XF86OutputStatusDisconnected;
861    ScrnInfoPtr pScrn = output->scrn;
862    VIAPtr pVia = VIAPTR(pScrn);
863    xf86MonPtr mon;
864
865    mon = xf86OutputGetEDID(output, pVia->pI2CBus2);
866    if (mon && DIGITAL(mon->features.input_type)) {
867        xf86OutputSetEDID(output, mon);
868        status = XF86OutputStatusConnected;
869    } else {
870        status = via_vt1632_detect(output);
871    }
872    return status;
873}
874
875static void
876via_dvi_destroy(xf86OutputPtr output)
877{
878}
879
880static const xf86OutputFuncsRec via_dvi_funcs = {
881    .create_resources   = via_dvi_create_resources,
882#ifdef RANDR_12_INTERFACE
883    .set_property       = via_dvi_set_property,
884#endif
885#ifdef RANDR_13_INTERFACE
886    .get_property       = via_dvi_get_property,
887#endif
888    .dpms               = via_dvi_dpms,
889    .save               = via_dvi_save,
890    .restore            = via_dvi_restore,
891    .mode_valid         = via_dvi_mode_valid,
892    .mode_fixup         = via_dvi_mode_fixup,
893    .prepare            = via_dvi_prepare,
894    .commit             = via_dvi_commit,
895    .mode_set           = via_dvi_mode_set,
896    .detect             = via_dvi_detect,
897    .get_modes          = xf86OutputGetEDIDModes,
898    .destroy            = via_dvi_destroy,
899};
900
901void
902via_dvi_init(ScrnInfoPtr pScrn)
903{
904    VIAPtr pVia = VIAPTR(pScrn);
905    xf86OutputPtr output = NULL;
906    struct ViaVT1632PrivateData *private_data = NULL;
907    I2CBusPtr pBus = NULL;
908    I2CDevPtr pDev = NULL;
909    I2CSlaveAddr addr = 0x10;
910
911    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
912                        "Entered via_dvi_init.\n"));
913
914    if (!pVia->pI2CBus2 || !pVia->pI2CBus3) {
915        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
916                    "I2C Bus 2 or I2C Bus 3 does not exist.\n");
917        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
918                    "Exiting via_dvi_init.\n"));
919        return;
920    }
921
922    if (xf86I2CProbeAddress(pVia->pI2CBus3, addr)) {
923        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
924                            "Will probe I2C Bus 3 for a possible "
925                            "external TMDS transmitter.\n"));
926        pBus = pVia->pI2CBus3;
927    } else if (xf86I2CProbeAddress(pVia->pI2CBus2, addr)) {
928        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
929                            "Will probe I2C Bus 2 for a possible "
930                            "external TMDS transmitter.\n"));
931        pBus = pVia->pI2CBus2;
932    } else {
933        xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
934                    "Did not find a possible external TMDS transmitter "
935                    "on I2C Bus 2 or I2C Bus 3.\n");
936        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
937                            "Exiting via_dvi_init.\n"));
938        return;
939    }
940
941    pDev = xf86CreateI2CDevRec();
942    if (!pDev) {
943        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
944                    "Failed to create an I2C bus structure.\n");
945        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
946                            "Exiting via_dvi_init.\n"));
947        return;
948    }
949
950    pDev->DevName = "VT1632A";
951    pDev->SlaveAddr = addr;
952    pDev->pI2CBus = pBus;
953    if (!xf86I2CDevInit(pDev)) {
954        xf86DestroyI2CDevRec(pDev, TRUE);
955        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
956                    "Failed to initialize a device on I2C bus.\n");
957        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
958                            "Exiting via_dvi_init.\n"));
959        return;
960    }
961
962    if (!via_vt1632_probe(pScrn, pDev)) {
963        xf86DestroyI2CDevRec(pDev, TRUE);
964        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
965                            "Exiting via_dvi_init.\n"));
966        return;
967    }
968
969    private_data = via_vt1632_init(pScrn, pDev);
970    if (!private_data) {
971        xf86DestroyI2CDevRec(pDev, TRUE);
972        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
973                            "Exiting via_dvi_init.\n"));
974        return;
975    }
976
977    output = xf86OutputCreate(pScrn, &via_dvi_funcs, "DVI-1");
978    if (output) {
979        output->driver_private = private_data;
980        output->possible_crtcs = 0x2;
981        output->possible_clones = 0;
982        output->interlaceAllowed = FALSE;
983        output->doubleScanAllowed = FALSE;
984    }
985
986    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
987                        "Exiting via_dvi_init.\n"));
988}
989
990void
991ViaOutputsDetect(ScrnInfoPtr pScrn)
992{
993    VIAPtr pVia = VIAPTR(pScrn);
994    VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
995
996    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
997                        "Entered ViaOutputsDetect.\n"));
998
999    pBIOSInfo->analog = NULL;
1000
1001    /* LVDS */
1002    via_lvds_init(pScrn);
1003
1004    /* VGA */
1005    via_analog_init(pScrn);
1006
1007    /* TV */
1008    via_tv_init(pScrn);
1009
1010    /*
1011     * via_dvi_init function to initialize VT1632A TMDS transmitter
1012     * is disabled for now.
1013     */
1014    /* External TMDS Transmitter (DVI) */
1015/*
1016    via_dvi_init(pScrn);
1017*/
1018
1019    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1020                        "Exiting ViaOutputsDetect.\n"));
1021}
1022
1023#ifdef HAVE_DEBUG
1024/*
1025 * Returns:
1026 *   Bit[7] 2nd Path
1027 *   Bit[6] 1/0 MHS Enable/Disable
1028 *   Bit[5] 0 = Bypass Callback, 1 = Enable Callback
1029 *   Bit[4] 0 = Hot-Key Sequence Control (OEM Specific)
1030 *   Bit[3] LCD
1031 *   Bit[2] TV
1032 *   Bit[1] CRT
1033 *   Bit[0] DVI
1034 */
1035static CARD8
1036VIAGetActiveDisplay(ScrnInfoPtr pScrn)
1037{
1038    vgaHWPtr hwp = VGAHWPTR(pScrn);
1039    CARD8 tmp;
1040
1041    tmp = (hwp->readCrtc(hwp, 0x3E) >> 4);
1042    tmp |= ((hwp->readCrtc(hwp, 0x3B) & 0x18) << 3);
1043
1044    return tmp;
1045}
1046#endif /* HAVE_DEBUG */
1047
1048/*
1049 *
1050 */
1051CARD32
1052ViaGetMemoryBandwidth(ScrnInfoPtr pScrn)
1053{
1054    VIAPtr pVia = VIAPTR(pScrn);
1055
1056    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1057                     "ViaGetMemoryBandwidth. Memory type: %d\n",
1058                     pVia->MemClk));
1059
1060    switch (pVia->MemClk) {
1061        case VIA_MEM_SDR66:
1062        case VIA_MEM_SDR100:
1063        case VIA_MEM_SDR133:
1064            return VIA_BW_MIN;
1065        case VIA_MEM_DDR200:
1066            return VIA_BW_DDR200;
1067        case VIA_MEM_DDR266:
1068        case VIA_MEM_DDR333:
1069        case VIA_MEM_DDR400:
1070            return VIA_BW_DDR400;
1071        case VIA_MEM_DDR533:
1072        case VIA_MEM_DDR667:
1073            return VIA_BW_DDR667;
1074        case VIA_MEM_DDR800:
1075        case VIA_MEM_DDR1066:
1076            return VIA_BW_DDR1066;
1077        default:
1078            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1079                       "ViaBandwidthAllowed: Unknown memory type: %d\n",
1080                       pVia->MemClk);
1081            return VIA_BW_MIN;
1082    }
1083}
1084
1085/*
1086 *
1087 * Some very common abstractions.
1088 *
1089 */
1090
1091/*
1092 * Standard vga call really.
1093 * Needs to be called to reset the dotclock (after SR40:2/1 reset)
1094 */
1095void
1096ViaSetUseExternalClock(vgaHWPtr hwp)
1097{
1098    CARD8 data;
1099
1100    DEBUG(xf86DrvMsg(hwp->pScrn->scrnIndex, X_INFO,
1101                     "ViaSetUseExternalClock\n"));
1102
1103    data = hwp->readMiscOut(hwp);
1104    hwp->writeMiscOut(hwp, data | 0x0C);
1105}
1106
1107/*
1108 *
1109 */
1110static void
1111ViaSetDotclock(ScrnInfoPtr pScrn, CARD32 clock, int base, int probase)
1112{
1113    vgaHWPtr hwp = VGAHWPTR(pScrn);
1114    VIAPtr pVia = VIAPTR(pScrn);
1115
1116    DEBUG(xf86DrvMsg(hwp->pScrn->scrnIndex, X_INFO,
1117                     "ViaSetDotclock to 0x%06x\n", (unsigned)clock));
1118
1119    if ((pVia->Chipset == VIA_CLE266) || (pVia->Chipset == VIA_KM400)) {
1120        hwp->writeSeq(hwp, base, clock >> 8);
1121        hwp->writeSeq(hwp, base+1, clock & 0xFF);
1122    } else {  /* unichrome pro */
1123        union pllparams pll;
1124        int dtz, dr, dn, dm;
1125        pll.packed = clock;
1126        dtz = pll.params.dtz;
1127        dr  = pll.params.dr;
1128        dn  = pll.params.dn;
1129        dm  = pll.params.dm;
1130
1131        /* The VX855 and VX900 do not modify dm/dn, but earlier chipsets do. */
1132        if ((pVia->Chipset != VIA_VX855) && (pVia->Chipset != VIA_VX900)) {
1133            dm -= 2;
1134            dn -= 2;
1135        }
1136
1137        hwp->writeSeq(hwp, probase, dm & 0xff);
1138        hwp->writeSeq(hwp, probase+1,
1139                      ((dm >> 8) & 0x03) | (dr << 2) | ((dtz & 1) << 7));
1140        hwp->writeSeq(hwp, probase+2, (dn & 0x7f) | ((dtz & 2) << 6));
1141    }
1142}
1143
1144/*
1145 *
1146 */
1147static void
1148ViaSetPrimaryDotclock(ScrnInfoPtr pScrn, CARD32 clock)
1149{
1150    vgaHWPtr hwp = VGAHWPTR(pScrn);
1151
1152    ViaSetDotclock(pScrn, clock, 0x46, 0x44);
1153
1154    ViaSeqMask(hwp, 0x40, 0x02, 0x02);
1155    ViaSeqMask(hwp, 0x40, 0x00, 0x02);
1156}
1157
1158/*
1159 *
1160 */
1161void
1162ViaSetSecondaryDotclock(ScrnInfoPtr pScrn, CARD32 clock)
1163{
1164    vgaHWPtr hwp = VGAHWPTR(pScrn);
1165
1166    ViaSetDotclock(pScrn, clock, 0x44, 0x4A);
1167
1168    ViaSeqMask(hwp, 0x40, 0x04, 0x04);
1169    ViaSeqMask(hwp, 0x40, 0x00, 0x04);
1170}
1171
1172/*
1173 *
1174 */
1175static void
1176ViaSetECKDotclock(ScrnInfoPtr pScrn, CARD32 clock)
1177{
1178    /* Does the non-pro chip have an ECK clock ? */
1179    ViaSetDotclock(pScrn, clock, 0, 0x47);
1180}
1181
1182static CARD32
1183ViaComputeDotClock(unsigned clock)
1184{
1185    double fout, fref, err, minErr;
1186    CARD32 dr, dn, dm, maxdm, maxdn;
1187    CARD32 factual, best;
1188
1189    fref = 14.31818e6;
1190    fout = (double)clock * 1.e3;
1191
1192    factual = ~0;
1193    maxdm = 127;
1194    maxdn = 7;
1195    minErr = 1e10;
1196    best = 0;
1197
1198    for (dr = 0; dr < 4; ++dr) {
1199        for (dn = (dr == 0) ? 2 : 1; dn <= maxdn; ++dn) {
1200            for (dm = 1; dm <= maxdm; ++dm) {
1201                factual = fref * dm;
1202                factual /= (dn << dr);
1203                err = fabs((double)factual / fout - 1.);
1204                if (err < minErr) {
1205                    minErr = err;
1206                    best = (dm & 127) | ((dn & 31) << 8) | (dr << 14);
1207                }
1208            }
1209        }
1210    }
1211    return best;
1212}
1213
1214static CARD32
1215ViaComputeProDotClock(unsigned clock)
1216{
1217    double fvco, fout, fref, err, minErr;
1218    CARD32 dr = 0, dn, dm, maxdm, maxdn;
1219    CARD32 factual;
1220    union pllparams bestClock;
1221
1222    fref = 14.318e6;
1223    fout = (double)clock * 1.e3;
1224
1225    factual = ~0;
1226    maxdm = factual / 14318000U;
1227    minErr = 1.e10;
1228    bestClock.packed = 0U;
1229
1230    do {
1231        fvco = fout * (1 << dr);
1232    } while (fvco < 300.e6 && dr++ < 8);
1233
1234    if (dr == 8) {
1235        return 0;
1236    }
1237
1238    if (clock < 30000)
1239        maxdn = 8;
1240    else if (clock < 45000)
1241        maxdn = 7;
1242    else if (clock < 170000)
1243        maxdn = 6;
1244    else
1245        maxdn = 5;
1246
1247    for (dn = 2; dn < maxdn; ++dn) {
1248        for (dm = 2; dm < maxdm; ++dm) {
1249            factual = 14318000U * dm;
1250            factual /= dn << dr;
1251            if ((err = fabs((double)factual / fout - 1.)) < 0.005) {
1252                if (err < minErr) {
1253                    minErr = err;
1254                    bestClock.params.dtz = 1;
1255                    bestClock.params.dr = dr;
1256                    bestClock.params.dn = dn;
1257                    bestClock.params.dm = dm;
1258                }
1259            }
1260        }
1261    }
1262
1263    return bestClock.packed;
1264}
1265
1266/*
1267 *
1268 */
1269CARD32
1270ViaModeDotClockTranslate(ScrnInfoPtr pScrn, DisplayModePtr mode)
1271{
1272    VIAPtr pVia = VIAPTR(pScrn);
1273    int i;
1274
1275    if ((pVia->Chipset == VIA_CLE266) || (pVia->Chipset == VIA_KM400)) {
1276        CARD32 best1 = 0, best2;
1277
1278        for (i = 0; ViaDotClocks[i].DotClock; i++)
1279            if (ViaDotClocks[i].DotClock == mode->Clock) {
1280                best1 = ViaDotClocks[i].UniChrome;
1281                break;
1282            }
1283
1284        best2 = ViaComputeDotClock(mode->Clock);
1285
1286        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1287                         "ViaComputeDotClock %d : %04x : %04x\n",
1288                         mode->Clock, (unsigned int)best1,
1289                         (unsigned int)best2));
1290
1291        return best2;
1292    } else {
1293        for (i = 0; ViaDotClocks[i].DotClock; i++)
1294            if (ViaDotClocks[i].DotClock == mode->Clock)
1295                return ViaDotClocks[i].UniChromePro.packed;
1296        return ViaComputeProDotClock(mode->Clock);
1297    }
1298
1299    return 0;
1300}
1301
1302void
1303ViaDFPPower(ScrnInfoPtr pScrn, Bool On)
1304{
1305#ifdef HAVE_DEBUG
1306    if (On)
1307        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDFPPower: On.\n");
1308    else
1309        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDFPPower: Off.\n");
1310#endif
1311    vgaHWPtr hwp = VGAHWPTR(pScrn);
1312
1313    /* Display Channel Select */
1314    ViaCrtcMask(hwp, 0xD2, 0x30, 0x30);
1315
1316    if (On)
1317        /* Power on TMDS */
1318        ViaCrtcMask(hwp, 0xD2, 0x00, 0x08);
1319    else
1320        /* Power off TMDS */
1321        ViaCrtcMask(hwp, 0xD2, 0x08, 0x08);
1322}
1323
1324void
1325ViaModeFirstCRTC(ScrnInfoPtr pScrn, DisplayModePtr mode)
1326{
1327    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaModeFirstCRTC\n");
1328    vgaHWPtr hwp = VGAHWPTR(pScrn);
1329    VIAPtr pVia = VIAPTR(pScrn);
1330    VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
1331
1332    /* Turn off Screen */
1333    ViaCrtcMask(hwp, 0x17, 0x00, 0x80);
1334
1335    ViaFirstCRTCSetMode(pScrn, mode);
1336    pBIOSInfo->Clock = ViaModeDotClockTranslate(pScrn, mode);
1337    pBIOSInfo->ClockExternal = FALSE;
1338
1339    /* Enable Extended Mode Memory Access. */
1340    ViaSeqMask(hwp, 0x1A, 0x08, 0x08);
1341
1342    ViaSetPrimaryFIFO(pScrn, mode);
1343
1344    ViaSetPrimaryDotclock(pScrn, pBIOSInfo->Clock);
1345    ViaSetUseExternalClock(hwp);
1346    ViaCrtcMask(hwp, 0x6B, 0x00, 0x01);
1347
1348    hwp->disablePalette(hwp);
1349
1350    /* Turn on Screen */
1351    ViaCrtcMask(hwp, 0x17, 0x80, 0x80);
1352}
1353
1354void
1355ViaModeSecondCRTC(ScrnInfoPtr pScrn, DisplayModePtr mode)
1356{
1357    VIAPtr pVia = VIAPTR(pScrn);
1358    VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
1359    vgaHWPtr hwp = VGAHWPTR(pScrn);
1360    DisplayModePtr realMode = mode;
1361
1362    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaModeSecondCRTC\n"));
1363
1364    ViaSecondCRTCSetMode(pScrn, realMode);
1365    ViaSetSecondaryFIFO(pScrn, realMode);
1366    pBIOSInfo->Clock = ViaModeDotClockTranslate(pScrn, realMode);
1367
1368    /* Fix LCD scaling */
1369    ViaSecondCRTCHorizontalQWCount(pScrn, mode->CrtcHDisplay);
1370
1371    pBIOSInfo->ClockExternal = FALSE;
1372    ViaSetSecondaryDotclock(pScrn, pBIOSInfo->Clock);
1373    ViaSetUseExternalClock(hwp);
1374
1375    hwp->disablePalette(hwp);
1376}
1377
1378