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