via_display.c revision 90b17f1b
1/*
2 * Copyright 2005-2011 The Openchrome Project [openchrome.org]
3 * Copyright 2004-2005 The Unichrome Project  [unichrome.sf.net]
4 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
5 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sub license,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 */
26#ifdef HAVE_CONFIG_H
27#include "config.h"
28#endif
29
30#include "via_driver.h"
31
32/*
33 * Enables the second display channel.
34 */
35void
36ViaSecondDisplayChannelEnable(ScrnInfoPtr pScrn)
37{
38    vgaHWPtr hwp = VGAHWPTR(pScrn);
39
40    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
41                     "ViaSecondDisplayChannelEnable\n"));
42    ViaCrtcMask(hwp, 0x6A, 0x00, 1 << 6);
43    ViaCrtcMask(hwp, 0x6A, 1 << 7, 1 << 7);
44    ViaCrtcMask(hwp, 0x6A, 1 << 6, 1 << 6);
45}
46
47/*
48 * Disables the second display channel.
49 */
50void
51ViaSecondDisplayChannelDisable(ScrnInfoPtr pScrn)
52{
53    vgaHWPtr hwp = VGAHWPTR(pScrn);
54
55    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
56                     "ViaSecondDisplayChannelDisable\n"));
57
58    ViaCrtcMask(hwp, 0x6A, 0x00, 1 << 6);
59    ViaCrtcMask(hwp, 0x6A, 0x00, 1 << 7);
60    ViaCrtcMask(hwp, 0x6A, 1 << 6, 1 << 6);
61}
62
63/*
64 * Initial settings for displays.
65 */
66void
67ViaDisplayInit(ScrnInfoPtr pScrn)
68{
69    VIAPtr pVia = VIAPTR(pScrn);
70    vgaHWPtr hwp = VGAHWPTR(pScrn);
71
72    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisplayInit\n"));
73
74    ViaSecondDisplayChannelDisable(pScrn);
75    ViaCrtcMask(hwp, 0x6A, 0x00, 0x3D);
76
77    hwp->writeCrtc(hwp, 0x6B, 0x00);
78    hwp->writeCrtc(hwp, 0x6C, 0x00);
79    hwp->writeCrtc(hwp, 0x79, 0x00);
80
81    /* (IGA1 Timing Plus 2, added in VT3259 A3 or later) */
82    if (pVia->Chipset != VIA_CLE266 && pVia->Chipset != VIA_KM400)
83        ViaCrtcMask(hwp, 0x47, 0x00, 0xC8);
84}
85
86/*
87 * Enables simultaneous mode.
88 */
89void
90ViaDisplayEnableSimultaneous(ScrnInfoPtr pScrn)
91{
92    vgaHWPtr hwp = VGAHWPTR(pScrn);
93
94    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
95                     "ViaDisplayEnableSimultaneous\n"));
96    ViaCrtcMask(hwp, 0x6B, 0x08, 0x08);
97}
98
99/*
100 * Disables simultaneous mode.
101 */
102void
103ViaDisplayDisableSimultaneous(ScrnInfoPtr pScrn)
104{
105    vgaHWPtr hwp = VGAHWPTR(pScrn);
106
107    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
108                     "ViaDisplayDisableSimultaneous\n"));
109    ViaCrtcMask(hwp, 0x6B, 0x00, 0x08);
110}
111
112/*
113 * Sets the primary or secondary display stream on internal TMDS.
114 */
115void
116ViaDisplaySetStreamOnDFP(ScrnInfoPtr pScrn, Bool primary)
117{
118    vgaHWPtr hwp = VGAHWPTR(pScrn);
119
120    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisplaySetStreamOnDFP\n"));
121
122    if (primary)
123        ViaCrtcMask(hwp, 0x99, 0x00, 0x10);
124    else
125        ViaCrtcMask(hwp, 0x99, 0x10, 0x10);
126}
127
128static void
129ViaCRTCSetGraphicsRegisters(ScrnInfoPtr pScrn)
130{
131    vgaHWPtr hwp = VGAHWPTR(pScrn);
132
133    /* graphics registers */
134    hwp->writeGr(hwp, 0x00, 0x00);
135    hwp->writeGr(hwp, 0x01, 0x00);
136    hwp->writeGr(hwp, 0x02, 0x00);
137    hwp->writeGr(hwp, 0x03, 0x00);
138    hwp->writeGr(hwp, 0x04, 0x00);
139    hwp->writeGr(hwp, 0x05, 0x40);
140    hwp->writeGr(hwp, 0x06, 0x05);
141    hwp->writeGr(hwp, 0x07, 0x0F);
142    hwp->writeGr(hwp, 0x08, 0xFF);
143
144    ViaGrMask(hwp, 0x20, 0, 0xFF);
145    ViaGrMask(hwp, 0x21, 0, 0xFF);
146    ViaGrMask(hwp, 0x22, 0, 0xFF);
147}
148
149static void
150ViaCRTCSetAttributeRegisters(ScrnInfoPtr pScrn)
151{
152    vgaHWPtr hwp = VGAHWPTR(pScrn);
153    CARD8 i;
154
155    /* attribute registers */
156    for (i = 0; i <= 0xF; i++) {
157        hwp->writeAttr(hwp, i, i);
158    }
159    hwp->writeAttr(hwp, 0x10, 0x41);
160    hwp->writeAttr(hwp, 0x11, 0xFF);
161    hwp->writeAttr(hwp, 0x12, 0x0F);
162    hwp->writeAttr(hwp, 0x13, 0x00);
163    hwp->writeAttr(hwp, 0x14, 0x00);
164}
165
166void
167VIALoadRgbLut(ScrnInfoPtr pScrn, int start, int numColors, LOCO *colors)
168{
169    vgaHWPtr hwp = VGAHWPTR(pScrn);
170    int i, j;
171
172    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIALoadRgbLut\n"));
173
174    hwp->enablePalette(hwp);
175    hwp->writeDacMask(hwp, 0xFF);
176
177    /* We need the same palette contents for both 16 and 24 bits, but X doesn't
178     * play: X's colormap handling is hopelessly intertwined with almost every
179     * X subsystem.  So we just space out RGB values over the 256*3. */
180
181    switch (pScrn->bitsPerPixel) {
182        case 16:
183            for (i = start; i < numColors; i++) {
184                hwp->writeDacWriteAddr(hwp, i * 4);
185                for (j = 0; j < 4; j++) {
186                    hwp->writeDacData(hwp, colors[i / 2].red);
187                    hwp->writeDacData(hwp, colors[i].green);
188                    hwp->writeDacData(hwp, colors[i / 2].blue);
189                }
190            }
191            break;
192        case 8:
193        case 24:
194        case 32:
195            for (i = start; i < numColors; i++) {
196                hwp->writeDacWriteAddr(hwp, i);
197                hwp->writeDacData(hwp, colors[i].red);
198                hwp->writeDacData(hwp, colors[i].green);
199                hwp->writeDacData(hwp, colors[i].blue);
200            }
201            break;
202        default:
203            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
204                       "Unsupported bitdepth: %d\n", pScrn->bitsPerPixel);
205            break;
206    }
207    hwp->disablePalette(hwp);
208}
209
210void
211ViaGammaDisable(ScrnInfoPtr pScrn)
212{
213    VIAPtr pVia = VIAPTR(pScrn);
214    vgaHWPtr hwp = VGAHWPTR(pScrn);
215
216    switch (pVia->Chipset) {
217        case VIA_CLE266:
218        case VIA_KM400:
219            ViaSeqMask(hwp, 0x16, 0x00, 0x80);
220            break;
221        default:
222            ViaCrtcMask(hwp, 0x33, 0x00, 0x80);
223            break;
224    }
225
226    /* Disable gamma on secondary */
227    /* This is needed or the hardware will lockup */
228    ViaSeqMask(hwp, 0x1A, 0x00, 0x01);
229    ViaCrtcMask(hwp, 0x6A, 0x00, 0x02);
230    switch (pVia->Chipset) {
231        case VIA_CLE266:
232        case VIA_KM400:
233        case VIA_K8M800:
234        case VIA_PM800:
235            break;
236        default:
237            ViaCrtcMask(hwp, 0x6A, 0x00, 0x20);
238            break;
239    }
240}
241
242void
243ViaCRTCInit(ScrnInfoPtr pScrn)
244{
245    vgaHWPtr hwp = VGAHWPTR(pScrn);
246
247    hwp->writeSeq(hwp, 0x10, 0x01); /* unlock extended registers */
248    ViaCrtcMask(hwp, 0x47, 0x00, 0x01); /* unlock CRT registers */
249    ViaCRTCSetGraphicsRegisters(pScrn);
250    ViaCRTCSetAttributeRegisters(pScrn);
251}
252
253void
254ViaFirstCRTCSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
255{
256    vgaHWPtr hwp = VGAHWPTR(pScrn);
257    VIAPtr pVia = VIAPTR(pScrn);
258    CARD16 temp;
259
260    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaFirstCRTCSetMode\n"));
261
262    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting up %s\n", mode->name));
263
264    ViaCrtcMask(hwp, 0x11, 0x00, 0x80); /* modify starting address */
265    ViaCrtcMask(hwp, 0x03, 0x80, 0x80); /* enable vertical retrace access */
266
267    /* Set Misc Register */
268    temp = 0x23;
269    if (mode->Flags & V_NHSYNC)
270        temp |= 0x40;
271    if (mode->Flags & V_NVSYNC)
272        temp |= 0x80;
273    temp |= 0x0C; /* Undefined/external clock */
274    hwp->writeMiscOut(hwp, temp);
275
276    /* Sequence registers */
277    hwp->writeSeq(hwp, 0x00, 0x00);
278
279#if 0
280    if (mode->Flags & V_CLKDIV2)
281        hwp->writeSeq(hwp, 0x01, 0x09);
282    else
283#endif
284        hwp->writeSeq(hwp, 0x01, 0x01);
285
286    hwp->writeSeq(hwp, 0x02, 0x0F);
287    hwp->writeSeq(hwp, 0x03, 0x00);
288    hwp->writeSeq(hwp, 0x04, 0x0E);
289
290    ViaSeqMask(hwp, 0x15, 0x02, 0x02);
291
292    /* bpp */
293    switch (pScrn->bitsPerPixel) {
294        case 8:
295            /* Only CLE266.AX use 6bits LUT. */
296            if (pVia->Chipset == VIA_CLE266 && pVia->ChipRev < 15)
297                ViaSeqMask(hwp, 0x15, 0x22, 0xFE);
298            else
299                ViaSeqMask(hwp, 0x15, 0xA2, 0xFE);
300            break;
301        case 16:
302            ViaSeqMask(hwp, 0x15, 0xB6, 0xFE);
303            break;
304        case 24:
305        case 32:
306            ViaSeqMask(hwp, 0x15, 0xAE, 0xFE);
307            break;
308        default:
309            xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled bitdepth: %d\n",
310                       pScrn->bitsPerPixel);
311            break;
312    }
313
314    switch (pVia->ChipId) {
315        case VIA_K8M890:
316        case VIA_CX700:
317        case VIA_P4M900:
318        case VIA_VX800:
319        case VIA_VX855:
320        case VIA_VX900:
321            break;
322        default:
323            ViaSeqMask(hwp, 0x16, 0x08, 0xBF);
324            ViaSeqMask(hwp, 0x17, 0x1F, 0xFF);
325            ViaSeqMask(hwp, 0x18, 0x4E, 0xFF);
326            ViaSeqMask(hwp, 0x1A, 0x08, 0xFD);
327            break;
328    }
329
330    /* Crtc registers */
331    /* horizontal total : 4100 */
332    temp = (mode->CrtcHTotal >> 3) - 5;
333    hwp->writeCrtc(hwp, 0x00, temp & 0xFF);
334    ViaCrtcMask(hwp, 0x36, temp >> 5, 0x08);
335
336    /* horizontal address : 2048 */
337    temp = (mode->CrtcHDisplay >> 3) - 1;
338    hwp->writeCrtc(hwp, 0x01, temp & 0xFF);
339
340    /* horizontal blanking start : 2048 */
341    /* temp = (mode->CrtcHDisplay >> 3) - 1; */
342    temp = (mode->CrtcHBlankStart >> 3) - 1;
343    hwp->writeCrtc(hwp, 0x02, temp & 0xFF);
344    /* If HblankStart has more bits anywhere, add them here */
345
346    /* horizontal blanking end : start + 1025 */
347    /* temp = (mode->CrtcHTotal >> 3) - 1; */
348    temp = (mode->CrtcHBlankEnd >> 3) - 1;
349    ViaCrtcMask(hwp, 0x03, temp, 0x1F);
350    ViaCrtcMask(hwp, 0x05, temp << 2, 0x80);
351    ViaCrtcMask(hwp, 0x33, temp >> 1, 0x20);
352
353    /* CrtcHSkew ??? */
354
355    /* horizontal sync start : 4095 */
356    temp = mode->CrtcHSyncStart >> 3;
357    hwp->writeCrtc(hwp, 0x04, temp & 0xFF);
358    ViaCrtcMask(hwp, 0x33, temp >> 4, 0x10);
359
360    /* horizontal sync end : start + 256 */
361    temp = mode->CrtcHSyncEnd >> 3;
362    ViaCrtcMask(hwp, 0x05, temp, 0x1F);
363
364    /* vertical total : 2049 */
365    temp = mode->CrtcVTotal - 2;
366    hwp->writeCrtc(hwp, 0x06, temp & 0xFF);
367    ViaCrtcMask(hwp, 0x07, temp >> 8, 0x01);
368    ViaCrtcMask(hwp, 0x07, temp >> 4, 0x20);
369    ViaCrtcMask(hwp, 0x35, temp >> 10, 0x01);
370
371    /* vertical address : 2048 */
372    temp = mode->CrtcVDisplay - 1;
373    hwp->writeCrtc(hwp, 0x12, temp & 0xFF);
374    ViaCrtcMask(hwp, 0x07, temp >> 7, 0x02);
375    ViaCrtcMask(hwp, 0x07, temp >> 3, 0x40);
376    ViaCrtcMask(hwp, 0x35, temp >> 8, 0x04);
377
378    /* Primary starting address -> 0x00, adjustframe does the rest */
379    hwp->writeCrtc(hwp, 0x0C, 0x00);
380    hwp->writeCrtc(hwp, 0x0D, 0x00);
381    ViaCrtcMask(hwp, 0x48, 0x00, 0x03); /* is this even possible on CLE266A ? */
382    hwp->writeCrtc(hwp, 0x34, 0x00);
383
384    /* vertical sync start : 2047 */
385    temp = mode->CrtcVSyncStart;
386    hwp->writeCrtc(hwp, 0x10, temp & 0xFF);
387    ViaCrtcMask(hwp, 0x07, temp >> 6, 0x04);
388    ViaCrtcMask(hwp, 0x07, temp >> 2, 0x80);
389    ViaCrtcMask(hwp, 0x35, temp >> 9, 0x02);
390
391    /* vertical sync end : start + 16 -- other bits someplace? */
392    ViaCrtcMask(hwp, 0x11, mode->CrtcVSyncEnd, 0x0F);
393
394    /* line compare: We are not doing splitscreen so 0x3FFF */
395    hwp->writeCrtc(hwp, 0x18, 0xFF);
396    ViaCrtcMask(hwp, 0x07, 0x10, 0x10);
397    ViaCrtcMask(hwp, 0x09, 0x40, 0x40);
398    ViaCrtcMask(hwp, 0x33, 0x06, 0x07);
399    ViaCrtcMask(hwp, 0x35, 0x10, 0x10);
400
401    /* zero Maximum scan line */
402    ViaCrtcMask(hwp, 0x09, 0x00, 0x1F);
403    hwp->writeCrtc(hwp, 0x14, 0x00);
404
405    /* vertical blanking start : 2048 */
406    /* temp = mode->CrtcVDisplay - 1; */
407    temp = mode->CrtcVBlankStart - 1;
408    hwp->writeCrtc(hwp, 0x15, temp & 0xFF);
409    ViaCrtcMask(hwp, 0x07, temp >> 5, 0x08);
410    ViaCrtcMask(hwp, 0x09, temp >> 4, 0x20);
411    ViaCrtcMask(hwp, 0x35, temp >> 7, 0x08);
412
413    /* vertical blanking end : start + 257 */
414    /* temp = mode->CrtcVTotal - 1; */
415    temp = mode->CrtcVBlankEnd - 1;
416    hwp->writeCrtc(hwp, 0x16, temp);
417
418    /* FIXME: check if this is really necessary here */
419    switch (pVia->ChipId) {
420        case VIA_K8M890:
421        case VIA_CX700:
422        case VIA_P4M900:
423        case VIA_VX800:
424        case VIA_VX855:
425        case VIA_VX900:
426            break;
427        default:
428            /* some leftovers */
429            hwp->writeCrtc(hwp, 0x08, 0x00);
430            ViaCrtcMask(hwp, 0x32, 0, 0xFF);  /* ? */
431            ViaCrtcMask(hwp, 0x33, 0, 0xC8);
432            break;
433    }
434
435    /* offset */
436    temp = (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3)) >> 3;
437    /* Make sure that this is 32-byte aligned. */
438    if (temp & 0x03) {
439        temp += 0x03;
440        temp &= ~0x03;
441    }
442    hwp->writeCrtc(hwp, 0x13, temp & 0xFF);
443    ViaCrtcMask(hwp, 0x35, temp >> 3, 0xE0);
444
445    /* fetch count */
446    temp = (mode->CrtcHDisplay * (pScrn->bitsPerPixel >> 3)) >> 3;
447    /* Make sure that this is 32-byte aligned. */
448    if (temp & 0x03) {
449        temp += 0x03;
450        temp &= ~0x03;
451    }
452
453    hwp->writeSeq(hwp, 0x1C, ((temp >> 1)+1) & 0xFF);
454    ViaSeqMask(hwp, 0x1D, temp >> 9, 0x03);
455
456    switch (pVia->ChipId) {
457        case VIA_K8M890:
458        case VIA_CX700:
459        case VIA_P4M900:
460        case VIA_VX800:
461        case VIA_VX855:
462        case VIA_VX900:
463            break;
464        default:
465            /* some leftovers */
466            ViaCrtcMask(hwp, 0x32, 0, 0xFF);
467            ViaCrtcMask(hwp, 0x33, 0, 0xC8);
468            break;
469    }
470}
471
472void
473ViaFirstCRTCSetStartingAddress(xf86CrtcPtr crtc, int x, int y)
474{
475    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
476    drmmode_ptr drmmode = drmmode_crtc->drmmode;
477    ScrnInfoPtr pScrn = crtc->scrn;
478    VIAPtr pVia = VIAPTR(pScrn);
479    vgaHWPtr hwp = VGAHWPTR(pScrn);
480    CARD32 Base;
481
482    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaFirstCRTCSetStartingAddress\n"));
483
484    Base = (y * pScrn->displayWidth + x) * (pScrn->bitsPerPixel / 8);
485    Base = (Base + drmmode->front_bo->offset) >> 1;
486
487    hwp->writeCrtc(hwp, 0x0C, (Base & 0xFF00) >> 8);
488    hwp->writeCrtc(hwp, 0x0D, Base & 0xFF);
489    /* FIXME The proper starting address for CR48 is 0x1F - Bits[28:24] */
490    if (!(pVia->Chipset == VIA_CLE266 && CLE266_REV_IS_AX(pVia->ChipRev)))
491        ViaCrtcMask(hwp, 0x48, Base >> 24, 0x0F);
492    /* CR34 are fire bits. Must be written after CR0C CR0D CR48.  */
493    hwp->writeCrtc(hwp, 0x34, (Base & 0xFF0000) >> 16);
494}
495
496void
497ViaSecondCRTCSetStartingAddress(xf86CrtcPtr crtc, int x, int y)
498{
499    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
500    drmmode_ptr drmmode = drmmode_crtc->drmmode;
501    ScrnInfoPtr pScrn = crtc->scrn;
502    vgaHWPtr hwp = VGAHWPTR(pScrn);
503    CARD32 Base, tmp;
504
505    Base = (y * pScrn->displayWidth + x) * (pScrn->bitsPerPixel / 8);
506    Base = (Base + drmmode->front_bo->offset) >> 3;
507
508    tmp = hwp->readCrtc(hwp, 0x62) & 0x01;
509    tmp |= (Base & 0x7F) << 1;
510    hwp->writeCrtc(hwp, 0x62, tmp);
511
512    hwp->writeCrtc(hwp, 0x63, (Base & 0x7F80) >> 7);
513    hwp->writeCrtc(hwp, 0x64, (Base & 0x7F8000) >> 15);
514    hwp->writeCrtc(hwp, 0xA3, (Base & 0x03800000) >> 23);
515}
516
517void
518ViaSecondCRTCHorizontalQWCount(ScrnInfoPtr pScrn, int width)
519{
520    vgaHWPtr hwp = VGAHWPTR(pScrn);
521    CARD16 temp;
522
523    /* fetch count */
524    temp = (width * (pScrn->bitsPerPixel >> 3)) >> 3;
525    /* Make sure that this is 32-byte aligned. */
526    if (temp & 0x03) {
527        temp += 0x03;
528        temp &= ~0x03;
529    }
530    hwp->writeCrtc(hwp, 0x65, (temp >> 1) & 0xFF);
531    ViaCrtcMask(hwp, 0x67, temp >> 7, 0x0C);
532}
533
534void
535ViaSecondCRTCHorizontalOffset(ScrnInfoPtr pScrn)
536{
537    vgaHWPtr hwp = VGAHWPTR(pScrn);
538    CARD16 temp;
539
540    /* offset */
541    temp = (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3)) >> 3;
542    /* Make sure that this is 32-byte aligned. */
543    if (temp & 0x03) {
544        temp += 0x03;
545        temp &= ~0x03;
546        }
547
548    hwp->writeCrtc(hwp, 0x66, temp & 0xFF);
549    ViaCrtcMask(hwp, 0x67, temp >> 8, 0x03);
550}
551
552void
553ViaSecondCRTCSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
554{
555    VIAPtr pVia = VIAPTR(pScrn);
556    vgaHWPtr hwp = VGAHWPTR(pScrn);
557    CARD16 temp;
558
559    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "mode: %p\n", mode);
560    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "mode->name: %p\n", mode->name);
561    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "mode->name: %s\n", mode->name);
562
563
564    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaSecondCRTCSetMode\n"));
565    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting up %s\n", mode->name));
566    /* bpp */
567    switch (pScrn->bitsPerPixel) {
568        case 8:
569            ViaCrtcMask(hwp, 0x67, 0x00, 0xC0);
570            break;
571        case 16:
572            ViaCrtcMask(hwp, 0x67, 0x40, 0xC0);
573            break;
574        case 24:
575        case 32:
576            ViaCrtcMask(hwp, 0x67, 0xC0, 0xC0);
577            break;
578        default:
579            xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Unhandled bitdepth: %d\n",
580                       pScrn->bitsPerPixel);
581            break;
582    }
583
584    switch (pVia->ChipId) {
585        case VIA_K8M890:
586        case VIA_CX700:
587        case VIA_P4M900:
588        case VIA_VX800:
589        case VIA_VX855:
590        case VIA_VX900:
591            break;
592        default:
593            ViaSeqMask(hwp, 0x16, 0x08, 0xBF);
594            ViaSeqMask(hwp, 0x17, 0x1F, 0xFF);
595            ViaSeqMask(hwp, 0x18, 0x4E, 0xFF);
596            ViaSeqMask(hwp, 0x1A, 0x08, 0xFD);
597            break;
598    }
599
600    /* Crtc registers */
601    /* horizontal total : 4096 */
602    temp = mode->CrtcHTotal - 1;
603    hwp->writeCrtc(hwp, 0x50, temp & 0xFF);
604    ViaCrtcMask(hwp, 0x55, temp >> 8, 0x0F);
605
606    /* horizontal address : 2048 */
607    temp = mode->CrtcHDisplay - 1;
608    hwp->writeCrtc(hwp, 0x51, temp & 0xFF);
609    ViaCrtcMask(hwp, 0x55, temp >> 4, 0x70);
610
611    /* horizontal blanking start : 2048 */
612    /* temp = mode->CrtcHDisplay - 1; */
613    temp = mode->CrtcHBlankStart - 1;
614    hwp->writeCrtc(hwp, 0x52, temp & 0xFF);
615    ViaCrtcMask(hwp, 0x54, temp >> 8, 0x07);
616
617    /* horizontal blanking end : 4096 */
618    /* temp = mode->CrtcHTotal - 1; */
619    temp = mode->CrtcHBlankEnd - 1;
620    hwp->writeCrtc(hwp, 0x53, temp & 0xFF);
621    ViaCrtcMask(hwp, 0x54, temp >> 5, 0x38);
622    ViaCrtcMask(hwp, 0x5D, temp >> 5, 0x40);
623
624    /* horizontal sync start : 2047 */
625    temp = mode->CrtcHSyncStart;
626    hwp->writeCrtc(hwp, 0x56, temp & 0xFF);
627    ViaCrtcMask(hwp, 0x54, temp >> 2, 0xC0);
628    ViaCrtcMask(hwp, 0x5C, temp >> 3, 0x80);
629
630    if (pVia->ChipId != VIA_CLE266 && pVia->ChipId != VIA_KM400)
631        ViaCrtcMask(hwp, 0x5D, temp >> 4, 0x80);
632
633    /* horizontal sync end : sync start + 512 */
634    temp = mode->CrtcHSyncEnd;
635    hwp->writeCrtc(hwp, 0x57, temp & 0xFF);
636    ViaCrtcMask(hwp, 0x5C, temp >> 2, 0x40);
637
638    /* vertical total : 2048 */
639    temp = mode->CrtcVTotal - 1;
640    hwp->writeCrtc(hwp, 0x58, temp & 0xFF);
641    ViaCrtcMask(hwp, 0x5D, temp >> 8, 0x07);
642
643
644    /* vertical address : 2048 */
645    temp = mode->CrtcVDisplay - 1;
646    hwp->writeCrtc(hwp, 0x59, temp & 0xFF);
647    ViaCrtcMask(hwp, 0x5D, temp >> 5, 0x38);
648
649    /* vertical blanking start : 2048 */
650    /* temp = mode->CrtcVDisplay - 1; */
651    temp = mode->CrtcVBlankStart - 1;
652    hwp->writeCrtc(hwp, 0x5A, temp & 0xFF);
653    ViaCrtcMask(hwp, 0x5C, temp >> 8, 0x07);
654
655    /* vertical blanking end : 2048 */
656    /* temp = mode->CrtcVTotal - 1; */
657    temp = mode->CrtcVBlankEnd - 1;
658    hwp->writeCrtc(hwp, 0x5B, temp & 0xFF);
659    ViaCrtcMask(hwp, 0x5C, temp >> 5, 0x38);
660
661    /* vertical sync start : 2047 */
662    temp = mode->CrtcVSyncStart;
663    hwp->writeCrtc(hwp, 0x5E, temp & 0xFF);
664    ViaCrtcMask(hwp, 0x5F, temp >> 3, 0xE0);
665
666    /* vertical sync end : start + 32 */
667    temp = mode->CrtcVSyncEnd;
668    ViaCrtcMask(hwp, 0x5F, temp, 0x1F);
669
670    switch (pVia->ChipId) {
671        case VIA_K8M890:
672        case VIA_CX700:
673        case VIA_P4M900:
674        case VIA_VX800:
675        case VIA_VX855:
676        case VIA_VX900:
677            break;
678        default:
679            /* some leftovers */
680            hwp->writeCrtc(hwp, 0x08, 0x00);
681            ViaCrtcMask(hwp, 0x32, 0, 0xFF);  /* ? */
682            ViaCrtcMask(hwp, 0x33, 0, 0xC8);
683            break;
684    }
685
686    ViaSecondCRTCHorizontalOffset(pScrn);
687    ViaSecondCRTCHorizontalQWCount(pScrn, mode->CrtcHDisplay);
688}
689
690/*
691 * Checks for limitations imposed by the available VGA timing registers.
692 */
693static ModeStatus
694ViaFirstCRTCModeValid(ScrnInfoPtr pScrn, DisplayModePtr mode)
695{
696    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaFirstCRTCModeValid\n"));
697
698    if (mode->CrtcHTotal > 4100)
699        return MODE_BAD_HVALUE;
700
701    if (mode->CrtcHDisplay > 2048)
702        return MODE_BAD_HVALUE;
703
704    if (mode->CrtcHBlankStart > 2048)
705        return MODE_BAD_HVALUE;
706
707    if ((mode->CrtcHBlankEnd - mode->CrtcHBlankStart) > 1025)
708        return MODE_HBLANK_WIDE;
709
710    if (mode->CrtcHSyncStart > 4095)
711        return MODE_BAD_HVALUE;
712
713    if ((mode->CrtcHSyncEnd - mode->CrtcHSyncStart) > 256)
714        return MODE_HSYNC_WIDE;
715
716    if (mode->CrtcVTotal > 2049)
717        return MODE_BAD_VVALUE;
718
719    if (mode->CrtcVDisplay > 2048)
720        return MODE_BAD_VVALUE;
721
722    if (mode->CrtcVSyncStart > 2047)
723        return MODE_BAD_VVALUE;
724
725    if ((mode->CrtcVSyncEnd - mode->CrtcVSyncStart) > 16)
726        return MODE_VSYNC_WIDE;
727
728    if (mode->CrtcVBlankStart > 2048)
729        return MODE_BAD_VVALUE;
730
731    if ((mode->CrtcVBlankEnd - mode->CrtcVBlankStart) > 257)
732        return MODE_VBLANK_WIDE;
733
734    return MODE_OK;
735}
736
737static ModeStatus
738ViaSecondCRTCModeValid(ScrnInfoPtr pScrn, DisplayModePtr mode)
739{
740    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaSecondCRTCModeValid\n"));
741
742    if (mode->CrtcHTotal > 4096)
743        return MODE_BAD_HVALUE;
744
745    if (mode->CrtcHDisplay > 2048)
746        return MODE_BAD_HVALUE;
747
748    if (mode->CrtcHBlankStart > 2048)
749        return MODE_BAD_HVALUE;
750
751    if (mode->CrtcHBlankEnd > 4096)
752        return MODE_HBLANK_WIDE;
753
754    if (mode->CrtcHSyncStart > 2047)
755        return MODE_BAD_HVALUE;
756
757    if ((mode->CrtcHSyncEnd - mode->CrtcHSyncStart) > 512)
758        return MODE_HSYNC_WIDE;
759
760    if (mode->CrtcVTotal > 2048)
761        return MODE_BAD_VVALUE;
762
763    if (mode->CrtcVDisplay > 2048)
764        return MODE_BAD_VVALUE;
765
766    if (mode->CrtcVBlankStart > 2048)
767        return MODE_BAD_VVALUE;
768
769    if (mode->CrtcVBlankEnd > 2048)
770        return MODE_VBLANK_WIDE;
771
772    if (mode->CrtcVSyncStart > 2047)
773        return MODE_BAD_VVALUE;
774
775    if ((mode->CrtcVSyncEnd - mode->CrtcVSyncStart) > 32)
776        return MODE_VSYNC_WIDE;
777
778    return MODE_OK;
779}
780
781/*
782 * Not tested yet
783 */
784void
785ViaShadowCRTCSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
786{
787    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaShadowCRTCSetMode\n"));
788
789    vgaHWPtr hwp = VGAHWPTR(pScrn);
790    CARD16 temp;
791
792    temp = (mode->CrtcHTotal >> 3) - 5;
793    hwp->writeCrtc(hwp, 0x6D, temp & 0xFF);
794    ViaCrtcMask(hwp, 0x71, temp >> 5, 0x08);
795
796    temp = (mode->CrtcHBlankEnd >> 3) - 1;
797    hwp->writeCrtc(hwp, 0x6E, temp & 0xFF);
798
799    temp = mode->CrtcVTotal - 2;
800    hwp->writeCrtc(hwp, 0x6F, temp & 0xFF);
801    ViaCrtcMask(hwp, 0x71, temp >> 8, 0x07);
802
803    temp = mode->CrtcVDisplay - 1;
804    hwp->writeCrtc(hwp, 0x70, temp & 0xFF);
805    ViaCrtcMask(hwp, 0x71, temp >> 4, 0x70);
806
807    temp = mode->CrtcVBlankStart - 1;
808    hwp->writeCrtc(hwp, 0x72, temp & 0xFF);
809    ViaCrtcMask(hwp, 0x74, temp >> 4, 0x70);
810
811    temp = mode->CrtcVTotal - 1;
812    hwp->writeCrtc(hwp, 0x73, temp & 0xFF);
813    ViaCrtcMask(hwp, 0x74, temp >> 8, 0x07);
814
815    ViaCrtcMask(hwp, 0x76, mode->CrtcVSyncEnd, 0x0F);
816
817    temp = mode->CrtcVSyncStart;
818    hwp->writeCrtc(hwp, 0x75, temp & 0xFF);
819    ViaCrtcMask(hwp, 0x76, temp >> 4, 0x70);
820}
821
822static void
823iga1_crtc_dpms(xf86CrtcPtr crtc, int mode)
824{
825    ScrnInfoPtr pScrn = crtc->scrn;
826    VIAPtr pVia = VIAPTR(pScrn);
827    VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
828
829    if (pVia->pVbe) {
830        ViaVbeDPMS(pScrn, mode);
831    } else {
832        switch (mode) {
833        case DPMSModeOn:
834            if (pBIOSInfo->SimultaneousEnabled)
835                ViaDisplayEnableSimultaneous(pScrn);
836            break;
837
838        case DPMSModeStandby:
839        case DPMSModeSuspend:
840        case DPMSModeOff:
841            if (pBIOSInfo->SimultaneousEnabled)
842                ViaDisplayDisableSimultaneous(pScrn);
843            break;
844
845		default:
846            xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid DPMS mode %d\n",
847                        mode);
848            break;
849        }
850        //vgaHWSaveScreen(pScrn->pScreen, mode);
851    }
852}
853
854static void
855iga1_crtc_save(xf86CrtcPtr crtc)
856{
857    ScrnInfoPtr pScrn = crtc->scrn;
858    vgaHWPtr hwp = VGAHWPTR(pScrn);
859    VIAPtr pVia = VIAPTR(pScrn);
860
861    if (pVia->pVbe && pVia->vbeSR) {
862        ViaVbeSaveRestore(pScrn, MODE_SAVE);
863    } else {
864        VIASave(pScrn);
865    }
866
867    vgaHWUnlock(hwp);
868}
869
870static void
871iga1_crtc_restore(xf86CrtcPtr crtc)
872{
873    ScrnInfoPtr pScrn = crtc->scrn;
874    vgaHWPtr hwp = VGAHWPTR(pScrn);
875    VIAPtr pVia = VIAPTR(pScrn);
876
877    if (pVia->pVbe && pVia->vbeSR)
878        ViaVbeSaveRestore(pScrn, MODE_RESTORE);
879    else
880        VIARestore(pScrn);
881
882    /* A soft reset helps to avoid a 3D hang on VT switch. */
883    switch (pVia->Chipset) {
884    case VIA_K8M890:
885    case VIA_P4M900:
886    case VIA_VX800:
887    case VIA_VX855:
888    case VIA_VX900:
889        break;
890
891    default:
892        hwp->writeSeq(hwp, 0x1A, pVia->SavedReg.SR1A | 0x40);
893        break;
894    }
895    vgaHWLock(hwp);
896}
897
898static Bool
899iga1_crtc_lock(xf86CrtcPtr crtc)
900{
901    return FALSE;
902}
903
904static void
905iga1_crtc_unlock(xf86CrtcPtr crtc)
906{
907}
908
909static Bool
910iga1_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
911                        DisplayModePtr adjusted_mode)
912{
913    ScrnInfoPtr pScrn = crtc->scrn;
914    VIAPtr pVia = VIAPTR(pScrn);
915    CARD32 temp;
916    ModeStatus modestatus;
917
918    if (pVia->pVbe)
919        return TRUE;
920
921    if ((mode->Clock < pScrn->clockRanges->minClock) ||
922        (mode->Clock > pScrn->clockRanges->maxClock)) {
923        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
924                   "Clock for mode \"%s\" outside of allowed range (%u (%u - %u))\n",
925                   mode->name, mode->Clock, pScrn->clockRanges->minClock,
926                   pScrn->clockRanges->maxClock);
927        return FALSE;
928    }
929
930    modestatus = ViaFirstCRTCModeValid(pScrn, mode);
931    if (modestatus != MODE_OK) {
932        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Not using mode \"%s\" : %s.\n",
933                   mode->name, xf86ModeStatusToString(modestatus));
934        return FALSE;
935    }
936
937    temp = mode->CrtcHDisplay * mode->CrtcVDisplay * mode->VRefresh *
938            (pScrn->bitsPerPixel >> 3);
939    if (pVia->pBIOSInfo->Bandwidth < temp) {
940        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
941                    "Required bandwidth is not available. (%u > %u)\n",
942                    (unsigned)temp, (unsigned)pVia->pBIOSInfo->Bandwidth);
943        return FALSE;
944    }
945    return TRUE;
946}
947
948static void
949iga1_crtc_prepare (xf86CrtcPtr crtc)
950{
951}
952
953static void
954iga1_crtc_set_origin(xf86CrtcPtr crtc, int x, int y)
955{
956    ScrnInfoPtr pScrn = crtc->scrn;
957    VIAPtr pVia = VIAPTR(pScrn);
958
959    if (pVia->pVbe) {
960        ViaVbeAdjustFrame(pScrn, x, y);
961    } else {
962        ViaFirstCRTCSetStartingAddress(crtc, x, y);
963    }
964    VIAVidAdjustFrame(pScrn, x, y);
965}
966
967static void
968iga1_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
969					DisplayModePtr adjusted_mode,
970					int x, int y)
971{
972    ScrnInfoPtr pScrn = crtc->scrn;
973    VIAPtr pVia = VIAPTR(pScrn);
974
975    if (!pVia->pVbe) {
976        if (!vgaHWInit(pScrn, adjusted_mode))
977            return;
978
979        if (pVia->UseLegacyModeSwitch) {
980            ViaModePrimaryLegacy(crtc, adjusted_mode);
981        } else {
982            ViaCRTCInit(pScrn);
983            ViaModeFirstCRTC(pScrn, adjusted_mode);
984
985            if (pVia->pBIOSInfo->SimultaneousEnabled)
986                ViaDisplayEnableSimultaneous(pScrn);
987            else
988                ViaDisplayDisableSimultaneous(pScrn);
989        }
990    } else {
991        if (!ViaVbeSetMode(pScrn, adjusted_mode))
992            return;
993    }
994    iga1_crtc_set_origin(crtc, crtc->x, crtc->y);
995}
996
997static void
998iga1_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
999					int size)
1000{
1001    ScrnInfoPtr pScrn = crtc->scrn;
1002    vgaHWPtr hwp = VGAHWPTR(pScrn);
1003    VIAPtr pVia = VIAPTR(pScrn);
1004    int SR1A, SR1B, CR67, CR6A;
1005    LOCO colors[size];
1006    int i;
1007
1008    for (i = 0; i < size; i++) {
1009        colors[i].red = red[i] >> 8;
1010        colors[i].green = green[i] >> 8;
1011        colors[i].blue = blue[i] >> 8;
1012    }
1013
1014    if (pScrn->bitsPerPixel != 8) {
1015        switch (pVia->Chipset) {
1016        case VIA_CLE266:
1017        case VIA_KM400:
1018            ViaSeqMask(hwp, 0x16, 0x80, 0x80);
1019            break;
1020        default:
1021            ViaCrtcMask(hwp, 0x33, 0x80, 0x80);
1022            break;
1023        }
1024
1025        ViaSeqMask(hwp, 0x1A, 0x00, 0x01);
1026        VIALoadRgbLut(pScrn, 0, size, colors);
1027
1028    } else {
1029
1030        SR1A = hwp->readSeq(hwp, 0x1A);
1031        SR1B = hwp->readSeq(hwp, 0x1B);
1032        CR67 = hwp->readCrtc(hwp, 0x67);
1033        CR6A = hwp->readCrtc(hwp, 0x6A);
1034
1035        for (i = 0; i < size; i++) {
1036            hwp->writeDacWriteAddr(hwp, i);
1037            hwp->writeDacData(hwp, colors[i].red);
1038            hwp->writeDacData(hwp, colors[i].green);
1039            hwp->writeDacData(hwp, colors[i].blue);
1040        }
1041    }
1042}
1043
1044static void *
1045iga1_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
1046{
1047    return NULL;
1048}
1049
1050static PixmapPtr
1051iga1_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
1052{
1053    return NULL;
1054}
1055
1056static void
1057iga1_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
1058{
1059}
1060
1061/*
1062    Set the cursor foreground and background colors.  In 8bpp, fg and
1063    bg are indices into the current colormap unless the
1064    HARDWARE_CURSOR_TRUECOLOR_AT_8BPP flag is set.  In that case
1065    and in all other bpps the fg and bg are in 8-8-8 RGB format.
1066*/
1067static void
1068iga1_crtc_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
1069{
1070    ScrnInfoPtr pScrn = crtc->scrn;
1071    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1072    VIAPtr pVia = VIAPTR(pScrn);
1073    CARD32 temp;
1074
1075    if (xf86_config->cursor_fg)
1076        return;
1077
1078    /* Don't recolour the image if we don't have to. */
1079    if (fg == xf86_config->cursor_fg && bg == xf86_config->cursor_bg)
1080        return;
1081
1082    switch(pVia->Chipset) {
1083    case VIA_CX700:
1084    case VIA_P4M890:
1085    case VIA_P4M900:
1086    case VIA_VX800:
1087    case VIA_VX855:
1088    case VIA_VX900:
1089        temp = VIAGETREG(PRIM_HI_CTRL);
1090        VIASETREG(PRIM_HI_CTRL, temp & 0xFFFFFFFE);
1091        break;
1092
1093    default:
1094        temp = VIAGETREG(HI_CONTROL);
1095        VIASETREG(HI_CONTROL, temp & 0xFFFFFFFE);
1096        break;
1097    }
1098
1099    xf86_config->cursor_fg = fg;
1100    xf86_config->cursor_bg = bg;
1101}
1102
1103static void
1104iga1_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
1105{
1106    ScrnInfoPtr pScrn = crtc->scrn;
1107    VIAPtr pVia = VIAPTR(pScrn);
1108    unsigned xoff, yoff;
1109
1110    if (x < 0) {
1111        xoff = ((-x) & 0xFE);
1112        x = 0;
1113    } else {
1114        xoff = 0;
1115    }
1116
1117    if (y < 0) {
1118        yoff = ((-y) & 0xFE);
1119        y = 0;
1120    } else {
1121        yoff = 0;
1122    }
1123
1124    switch(pVia->Chipset) {
1125    case VIA_CX700:
1126    case VIA_P4M890:
1127    case VIA_P4M900:
1128    case VIA_VX800:
1129    case VIA_VX855:
1130    case VIA_VX900:
1131        VIASETREG(PRIM_HI_POSSTART,    ((x    << 16) | (y    & 0x07ff)));
1132        VIASETREG(PRIM_HI_CENTEROFFSET, ((xoff << 16) | (yoff & 0x07ff)));
1133        break;
1134
1135    default:
1136        VIASETREG(HI_POSSTART,    ((x    << 16) | (y    & 0x07ff)));
1137        VIASETREG(HI_CENTEROFFSET, ((xoff << 16) | (yoff & 0x07ff)));
1138        break;
1139    }
1140}
1141
1142static void
1143iga1_crtc_show_cursor (xf86CrtcPtr crtc)
1144{
1145    drmmode_crtc_private_ptr iga = crtc->driver_private;
1146    ScrnInfoPtr pScrn = crtc->scrn;
1147    VIAPtr pVia = VIAPTR(pScrn);
1148
1149    switch(pVia->Chipset) {
1150    case VIA_CX700:
1151    case VIA_P4M890:
1152    case VIA_P4M900:
1153    case VIA_VX800:
1154    case VIA_VX855:
1155    case VIA_VX900:
1156        VIASETREG(PRIM_HI_FBOFFSET, iga->cursor_bo->offset);
1157        VIASETREG(PRIM_HI_CTRL, 0x36000005);
1158        break;
1159
1160    default:
1161        /* Mono Cursor Display Path [bit31]: Primary */
1162        VIASETREG(HI_FBOFFSET, iga->cursor_bo->offset);
1163        VIASETREG(HI_CONTROL, 0x76000005);
1164        break;
1165    }
1166}
1167
1168static void
1169iga1_crtc_hide_cursor (xf86CrtcPtr crtc)
1170{
1171    ScrnInfoPtr pScrn = crtc->scrn;
1172    VIAPtr pVia = VIAPTR(pScrn);
1173    CARD32 temp;
1174
1175    switch(pVia->Chipset) {
1176    case VIA_CX700:
1177    case VIA_P4M890:
1178    case VIA_P4M900:
1179    case VIA_VX800:
1180    case VIA_VX855:
1181    case VIA_VX900:
1182        temp = VIAGETREG(PRIM_HI_CTRL);
1183        VIASETREG(PRIM_HI_CTRL, temp & 0xFFFFFFFA);
1184        break;
1185
1186    default:
1187        temp = VIAGETREG(HI_CONTROL);
1188        /* Hardware cursor disable [bit0] */
1189        VIASETREG(HI_CONTROL, temp & 0xFFFFFFFA);
1190        break;
1191    }
1192}
1193
1194static void
1195iga_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
1196{
1197    drmmode_crtc_private_ptr iga = crtc->driver_private;
1198    ScrnInfoPtr pScrn = crtc->scrn;
1199    void *dst;
1200
1201    dst = drm_bo_map(pScrn, iga->cursor_bo);
1202    memset(dst, 0x00, iga->cursor_bo->size);
1203    memcpy(dst, image, iga->cursor_bo->size);
1204    drm_bo_unmap(pScrn, iga->cursor_bo);
1205}
1206
1207static void
1208iga_crtc_commit(xf86CrtcPtr crtc)
1209{
1210    ScrnInfoPtr pScrn = crtc->scrn;
1211    VIAPtr pVia = VIAPTR(pScrn);
1212
1213    if (crtc->scrn->pScreen != NULL && pVia->drmmode.hwcursor)
1214        xf86_reload_cursors(crtc->scrn->pScreen);
1215}
1216
1217static void
1218iga_crtc_destroy(xf86CrtcPtr crtc)
1219{
1220    if (crtc->driver_private)
1221        free(crtc->driver_private);
1222}
1223
1224static const xf86CrtcFuncsRec iga1_crtc_funcs = {
1225    .dpms                   = iga1_crtc_dpms,
1226    .save                   = iga1_crtc_save,
1227    .restore                = iga1_crtc_restore,
1228    .lock                   = iga1_crtc_lock,
1229    .unlock                 = iga1_crtc_unlock,
1230    .mode_fixup             = iga1_crtc_mode_fixup,
1231    .prepare                = iga1_crtc_prepare,
1232    .mode_set               = iga1_crtc_mode_set,
1233    .commit                 = iga_crtc_commit,
1234    .gamma_set              = iga1_crtc_gamma_set,
1235    .shadow_create          = iga1_crtc_shadow_create,
1236    .shadow_allocate        = iga1_crtc_shadow_allocate,
1237    .shadow_destroy         = iga1_crtc_shadow_destroy,
1238    .set_cursor_colors      = iga1_crtc_set_cursor_colors,
1239    .set_cursor_position    = iga1_crtc_set_cursor_position,
1240    .show_cursor            = iga1_crtc_show_cursor,
1241    .hide_cursor            = iga1_crtc_hide_cursor,
1242    .load_cursor_argb       = iga_crtc_load_cursor_argb,
1243#ifdef RANDR_12_INTERFACE
1244    .set_origin             = iga1_crtc_set_origin,
1245#endif
1246    .destroy                = iga_crtc_destroy,
1247};
1248
1249static void
1250iga2_crtc_dpms(xf86CrtcPtr crtc, int mode)
1251{
1252    ScrnInfoPtr pScrn = crtc->scrn;
1253    VIAPtr pVia = VIAPTR(pScrn);
1254    VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
1255
1256    if (pVia->pVbe) {
1257        ViaVbeDPMS(pScrn, mode);
1258    } else {
1259        switch (mode) {
1260        case DPMSModeOn:
1261            if (pBIOSInfo->SimultaneousEnabled)
1262                ViaDisplayEnableSimultaneous(pScrn);
1263            break;
1264
1265        case DPMSModeStandby:
1266        case DPMSModeSuspend:
1267        case DPMSModeOff:
1268            if (pBIOSInfo->SimultaneousEnabled)
1269                ViaDisplayDisableSimultaneous(pScrn);
1270            break;
1271
1272        default:
1273            xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid DPMS mode %d\n",
1274                        mode);
1275            break;
1276        }
1277        //vgaHWSaveScreen(pScrn->pScreen, mode);
1278    }
1279}
1280
1281static void
1282iga2_crtc_save(xf86CrtcPtr crtc)
1283{
1284    ScrnInfoPtr pScrn = crtc->scrn;
1285    vgaHWPtr hwp = VGAHWPTR(pScrn);
1286    VIAPtr pVia = VIAPTR(pScrn);
1287
1288    if (pVia->pVbe && pVia->vbeSR)
1289        ViaVbeSaveRestore(pScrn, MODE_SAVE);
1290    else
1291        VIASave(pScrn);
1292	vgaHWUnlock(hwp);
1293}
1294
1295static void
1296iga2_crtc_restore(xf86CrtcPtr crtc)
1297{
1298    ScrnInfoPtr pScrn = crtc->scrn;
1299    vgaHWPtr hwp = VGAHWPTR(pScrn);
1300    VIAPtr pVia = VIAPTR(pScrn);
1301
1302    if (pVia->pVbe && pVia->vbeSR)
1303        ViaVbeSaveRestore(pScrn, MODE_RESTORE);
1304    else
1305        VIARestore(pScrn);
1306    vgaHWLock(hwp);
1307}
1308
1309static Bool
1310iga2_crtc_lock(xf86CrtcPtr crtc)
1311{
1312    return FALSE;
1313}
1314
1315static void
1316iga2_crtc_unlock(xf86CrtcPtr crtc)
1317{
1318}
1319
1320static Bool
1321iga2_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
1322                        DisplayModePtr adjusted_mode)
1323{
1324    ScrnInfoPtr pScrn = crtc->scrn;
1325    VIAPtr pVia = VIAPTR(pScrn);
1326    CARD32 temp;
1327    ModeStatus modestatus;
1328
1329    if (pVia->pVbe)
1330        return TRUE;
1331
1332    if ((mode->Clock < pScrn->clockRanges->minClock) ||
1333        (mode->Clock > pScrn->clockRanges->maxClock)) {
1334        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1335                   "Clock for mode \"%s\" outside of allowed range (%u (%u - %u))\n",
1336                   mode->name, mode->Clock, pScrn->clockRanges->minClock,
1337                   pScrn->clockRanges->maxClock);
1338        return FALSE;
1339    }
1340
1341    modestatus = ViaFirstCRTCModeValid(pScrn, mode);
1342    if (modestatus != MODE_OK) {
1343        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Not using mode \"%s\" : %s.\n",
1344                   mode->name, xf86ModeStatusToString(modestatus));
1345        return FALSE;
1346    }
1347
1348    temp = mode->CrtcHDisplay * mode->CrtcVDisplay * mode->VRefresh *
1349            (pScrn->bitsPerPixel >> 3);
1350    if (pVia->pBIOSInfo->Bandwidth < temp) {
1351        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1352                    "Required bandwidth is not available. (%u > %u)\n",
1353			        (unsigned)temp, (unsigned)pVia->pBIOSInfo->Bandwidth);
1354        return FALSE;
1355    }
1356    return TRUE;
1357}
1358
1359static void
1360iga2_crtc_prepare (xf86CrtcPtr crtc)
1361{
1362}
1363
1364static void
1365iga2_crtc_set_origin(xf86CrtcPtr crtc, int x, int y)
1366{
1367    ScrnInfoPtr pScrn = crtc->scrn;
1368    VIAPtr pVia = VIAPTR(pScrn);
1369
1370    if (pVia->pVbe) {
1371        ViaVbeAdjustFrame(pScrn, x, y);
1372    } else {
1373        ViaSecondCRTCSetStartingAddress(crtc, x, y);
1374    }
1375    VIAVidAdjustFrame(pScrn, x, y);
1376}
1377
1378static void
1379iga2_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
1380                    DisplayModePtr adjusted_mode, int x, int y)
1381{
1382    ScrnInfoPtr pScrn = crtc->scrn;
1383    VIAPtr pVia = VIAPTR(pScrn);
1384
1385    if (pVia->pVbe) {
1386        if (!ViaVbeSetMode(pScrn, adjusted_mode))
1387            return;
1388    } else {
1389        if (!vgaHWInit(pScrn, adjusted_mode))
1390            return;
1391
1392        if (pVia->UseLegacyModeSwitch) {
1393            ViaModeSecondaryLegacy(crtc, adjusted_mode);
1394        } else {
1395            ViaCRTCInit(pScrn);
1396            ViaModeSecondCRTC(pScrn, adjusted_mode);
1397            ViaSecondDisplayChannelEnable(pScrn);
1398
1399            if (pVia->pBIOSInfo->SimultaneousEnabled)
1400                ViaDisplayEnableSimultaneous(pScrn);
1401            else
1402                ViaDisplayDisableSimultaneous(pScrn);
1403        }
1404    }
1405    iga2_crtc_set_origin(crtc, crtc->x, crtc->y);
1406}
1407
1408static void
1409iga2_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
1410					int size)
1411{
1412    ScrnInfoPtr pScrn = crtc->scrn;
1413    vgaHWPtr hwp = VGAHWPTR(pScrn);
1414    VIAPtr pVia = VIAPTR(pScrn);
1415    int SR1A, SR1B, CR67, CR6A;
1416    LOCO colors[size];
1417    int i;
1418
1419    for (i = 0; i < size; i++) {
1420        colors[i].red = red[i] >> 8;
1421        colors[i].green = green[i] >> 8;
1422        colors[i].blue = blue[i] >> 8;
1423    }
1424
1425    if (pScrn->bitsPerPixel != 8) {
1426        if (!(pVia->Chipset == VIA_CLE266 &&
1427            CLE266_REV_IS_AX(pVia->ChipRev))) {
1428            ViaSeqMask(hwp, 0x1A, 0x01, 0x01);
1429            ViaCrtcMask(hwp, 0x6A, 0x02, 0x02);
1430
1431            switch (pVia->Chipset) {
1432            case VIA_CLE266:
1433            case VIA_KM400:
1434            case VIA_K8M800:
1435            case VIA_PM800:
1436                break;
1437
1438            default:
1439                ViaCrtcMask(hwp, 0x6A, 0x20, 0x20);
1440                break;
1441            }
1442            VIALoadRgbLut(pScrn, 0, size, colors);
1443        }
1444    } else {
1445        SR1A = hwp->readSeq(hwp, 0x1A);
1446        SR1B = hwp->readSeq(hwp, 0x1B);
1447        CR67 = hwp->readCrtc(hwp, 0x67);
1448        CR6A = hwp->readCrtc(hwp, 0x6A);
1449
1450        ViaSeqMask(hwp, 0x1A, 0x01, 0x01);
1451        ViaSeqMask(hwp, 0x1B, 0x80, 0x80);
1452        ViaCrtcMask(hwp, 0x67, 0x00, 0xC0);
1453        ViaCrtcMask(hwp, 0x6A, 0xC0, 0xC0);
1454
1455        for (i = 0; i < size; i++) {
1456            hwp->writeDacWriteAddr(hwp, i);
1457            hwp->writeDacData(hwp, colors[i].red);
1458            hwp->writeDacData(hwp, colors[i].green);
1459            hwp->writeDacData(hwp, colors[i].blue);
1460        }
1461
1462        hwp->writeSeq(hwp, 0x1A, SR1A);
1463        hwp->writeSeq(hwp, 0x1B, SR1B);
1464        hwp->writeCrtc(hwp, 0x67, CR67);
1465        hwp->writeCrtc(hwp, 0x6A, CR6A);
1466
1467        /* Screen 0 palette was changed by mode setting of Screen 1,
1468         * so load it again. */
1469        for (i = 0; i < size; i++) {
1470            hwp->writeDacWriteAddr(hwp, i);
1471            hwp->writeDacData(hwp, colors[i].red);
1472            hwp->writeDacData(hwp, colors[i].green);
1473            hwp->writeDacData(hwp, colors[i].blue);
1474        }
1475    }
1476}
1477
1478static void *
1479iga2_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
1480{
1481    return NULL;
1482}
1483
1484static PixmapPtr
1485iga2_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
1486{
1487    return NULL;
1488}
1489
1490static void
1491iga2_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
1492{
1493}
1494
1495/*
1496    Set the cursor foreground and background colors.  In 8bpp, fg and
1497    bg are indices into the current colormap unless the
1498    HARDWARE_CURSOR_TRUECOLOR_AT_8BPP flag is set.  In that case
1499    and in all other bpps the fg and bg are in 8-8-8 RGB format.
1500*/
1501static void
1502iga2_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
1503{
1504    drmmode_crtc_private_ptr iga = crtc->driver_private;
1505    ScrnInfoPtr pScrn = crtc->scrn;
1506    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1507    int height = 64, width = 64, i;
1508    VIAPtr pVia = VIAPTR(pScrn);
1509    CARD32 pixel, temp, *dst;
1510
1511    if (xf86_config->cursor_fg)
1512        return;
1513
1514    fg |= 0xff000000;
1515    bg |= 0xff000000;
1516
1517    /* Don't recolour the image if we don't have to. */
1518    if (fg == xf86_config->cursor_fg && bg == xf86_config->cursor_bg)
1519        return;
1520
1521    switch(pVia->Chipset) {
1522    case VIA_CX700:
1523    case VIA_P4M890:
1524    case VIA_P4M900:
1525    case VIA_VX800:
1526    case VIA_VX855:
1527    case VIA_VX900:
1528        temp = VIAGETREG(HI_CONTROL);
1529        VIASETREG(HI_CONTROL, temp & 0xFFFFFFFE);
1530        break;
1531
1532    default:
1533        temp = VIAGETREG(HI_CONTROL);
1534        VIASETREG(HI_CONTROL, temp & 0xFFFFFFFE);
1535        height = width = 32;
1536        break;
1537    }
1538
1539    dst = drm_bo_map(pScrn, iga->cursor_bo);
1540    for (i = 0; i < width * height; i++, dst++)
1541        if ((pixel = *dst))
1542            *dst = (pixel == xf86_config->cursor_fg) ? fg : bg;
1543    drm_bo_unmap(pScrn, iga->cursor_bo);
1544
1545    xf86_config->cursor_fg = fg;
1546    xf86_config->cursor_bg = bg;
1547}
1548
1549static void
1550iga2_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
1551{
1552    ScrnInfoPtr pScrn = crtc->scrn;
1553    VIAPtr pVia = VIAPTR(pScrn);
1554    unsigned xoff, yoff;
1555
1556    if (x < 0) {
1557        xoff = ((-x) & 0xFE);
1558        x = 0;
1559    } else {
1560        xoff = 0;
1561    }
1562
1563    if (y < 0) {
1564        yoff = ((-y) & 0xFE);
1565        y = 0;
1566    } else {
1567        yoff = 0;
1568    }
1569
1570    switch(pVia->Chipset) {
1571    case VIA_CX700:
1572    case VIA_P4M890:
1573    case VIA_P4M900:
1574    case VIA_VX800:
1575    case VIA_VX855:
1576    case VIA_VX900:
1577        VIASETREG(HI_POSSTART,    ((x    << 16) | (y    & 0x07ff)));
1578        VIASETREG(HI_CENTEROFFSET, ((xoff << 16) | (yoff & 0x07ff)));
1579        break;
1580
1581    default:
1582        VIASETREG(HI_POSSTART,    ((x    << 16) | (y    & 0x07ff)));
1583        VIASETREG(HI_CENTEROFFSET, ((xoff << 16) | (yoff & 0x07ff)));
1584        break;
1585    }
1586}
1587
1588static void
1589iga2_crtc_show_cursor(xf86CrtcPtr crtc)
1590{
1591    drmmode_crtc_private_ptr iga = crtc->driver_private;
1592    ScrnInfoPtr pScrn = crtc->scrn;
1593    VIAPtr pVia = VIAPTR(pScrn);
1594
1595    switch(pVia->Chipset) {
1596    case VIA_CX700:
1597    case VIA_P4M890:
1598    case VIA_P4M900:
1599    case VIA_VX800:
1600    case VIA_VX855:
1601    case VIA_VX900:
1602        VIASETREG(HI_FBOFFSET, iga->cursor_bo->offset);
1603        VIASETREG(HI_CONTROL, 0xB6000005);
1604        break;
1605
1606    default:
1607        /* Mono Cursor Display Path [bit31]: Secondary */
1608        /* FIXME For CLE266 and KM400 try to enable 32x32 cursor size [bit1] */
1609        VIASETREG(HI_FBOFFSET, iga->cursor_bo->offset);
1610        VIASETREG(HI_CONTROL, 0xF6000005);
1611        break;
1612    }
1613}
1614
1615static void
1616iga2_crtc_hide_cursor(xf86CrtcPtr crtc)
1617{
1618    ScrnInfoPtr pScrn = crtc->scrn;
1619    VIAPtr pVia = VIAPTR(pScrn);
1620    CARD32 temp;
1621
1622    switch(pVia->Chipset) {
1623    case VIA_CX700:
1624    case VIA_P4M890:
1625    case VIA_P4M900:
1626    case VIA_VX800:
1627    case VIA_VX855:
1628    case VIA_VX900:
1629	    temp = VIAGETREG(HI_CONTROL);
1630        VIASETREG(HI_CONTROL, temp & 0xFFFFFFFA);
1631        break;
1632
1633    default:
1634        temp = VIAGETREG(HI_CONTROL);
1635        /* Hardware cursor disable [bit0] */
1636        VIASETREG(HI_CONTROL, temp & 0xFFFFFFFA);
1637        break;
1638	}
1639}
1640
1641static const xf86CrtcFuncsRec iga2_crtc_funcs = {
1642    .dpms                   = iga2_crtc_dpms,
1643    .save                   = iga2_crtc_save,
1644    .restore                = iga2_crtc_restore,
1645    .lock                   = iga2_crtc_lock,
1646    .unlock                 = iga2_crtc_unlock,
1647    .mode_fixup             = iga2_crtc_mode_fixup,
1648    .prepare                = iga2_crtc_prepare,
1649    .mode_set               = iga2_crtc_mode_set,
1650    .commit                 = iga_crtc_commit,
1651    .gamma_set              = iga2_crtc_gamma_set,
1652    .shadow_create          = iga2_crtc_shadow_create,
1653    .shadow_allocate        = iga2_crtc_shadow_allocate,
1654    .shadow_destroy         = iga2_crtc_shadow_destroy,
1655    .set_cursor_colors      = iga2_crtc_set_cursor_colors,
1656    .set_cursor_position    = iga2_crtc_set_cursor_position,
1657    .show_cursor            = iga2_crtc_show_cursor,
1658    .hide_cursor            = iga2_crtc_hide_cursor,
1659    .load_cursor_argb       = iga_crtc_load_cursor_argb,
1660#ifdef RANDR_12_INTERFACE
1661    .set_origin             = iga2_crtc_set_origin,
1662#endif
1663    .destroy                = iga_crtc_destroy,
1664};
1665
1666Bool
1667UMSCrtcInit(ScrnInfoPtr pScrn)
1668{
1669    drmmode_crtc_private_ptr iga1_rec = NULL, iga2_rec = NULL;
1670    vgaHWPtr hwp = VGAHWPTR(pScrn);
1671    VIAPtr pVia = VIAPTR(pScrn);
1672    ClockRangePtr clockRanges;
1673    int max_pitch, max_height;
1674    VIABIOSInfoPtr pBIOSInfo;
1675    xf86CrtcPtr iga1, iga2;
1676
1677    /* Read memory bandwidth from registers. */
1678    pVia->MemClk = hwp->readCrtc(hwp, 0x3D) >> 4;
1679    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1680                     "Detected MemClk %d\n", pVia->MemClk));
1681    if (pVia->MemClk >= VIA_MEM_END) {
1682        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1683                   "Unknown Memory clock: %d\n", pVia->MemClk);
1684        pVia->MemClk = VIA_MEM_END - 1;
1685    }
1686    pBIOSInfo = pVia->pBIOSInfo;
1687    pBIOSInfo->Bandwidth = ViaGetMemoryBandwidth(pScrn);
1688
1689    if (pBIOSInfo->TVType == TVTYPE_NONE) {
1690        /* Use jumper to determine TV type. */
1691        if (hwp->readCrtc(hwp, 0x3B) & 0x02) {
1692            pBIOSInfo->TVType = TVTYPE_PAL;
1693            DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1694                             "Detected TV standard: PAL.\n"));
1695        } else {
1696            pBIOSInfo->TVType = TVTYPE_NTSC;
1697            DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1698                             "Detected TV standard: NTSC.\n"));
1699        }
1700    }
1701
1702    if (pVia->drmmode.hwcursor) {
1703        if (!xf86LoadSubModule(pScrn, "ramdac"))
1704            return FALSE;
1705    }
1706
1707    if (!xf86LoadSubModule(pScrn, "i2c"))
1708        return FALSE;
1709    else
1710        ViaI2CInit(pScrn);
1711
1712    if (!xf86LoadSubModule(pScrn, "ddc"))
1713        return FALSE;
1714
1715    pVia->pVbe = NULL;
1716    if (pVia->useVBEModes) {
1717        /* VBE doesn't properly initialise int10 itself. */
1718        if (xf86LoadSubModule(pScrn, "int10") &&
1719            xf86LoadSubModule(pScrn, "vbe")) {
1720            pVia->pVbe = VBEExtendedInit(NULL, pVia->EntityIndex,
1721                                        SET_BIOS_SCRATCH |
1722                                        RESTORE_BIOS_SCRATCH);
1723        }
1724
1725        if (!pVia->pVbe)
1726            xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VBE initialisation failed."
1727                        " Using builtin code to set modes.\n");
1728        else
1729            ConfiguredMonitor = vbeDoEDID(pVia->pVbe, NULL);
1730    }
1731
1732    /*
1733     * Set up ClockRanges, which describe what clock ranges are
1734     * available, and what sort of modes they can be used for.
1735     */
1736    clockRanges = xnfalloc(sizeof(ClockRange));
1737    clockRanges->next = NULL;
1738    clockRanges->minClock = 20000;
1739    clockRanges->maxClock = 230000;
1740
1741    clockRanges->clockIndex = -1;
1742    clockRanges->interlaceAllowed = TRUE;
1743    clockRanges->doubleScanAllowed = FALSE;
1744    pScrn->clockRanges = clockRanges;
1745
1746    /*
1747     * Now handle the outputs
1748     */
1749    iga1_rec = (drmmode_crtc_private_ptr) xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
1750    if (!iga1_rec) {
1751        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "IGA1 Rec allocation failed.\n");
1752        return FALSE;
1753    }
1754
1755    iga1 = xf86CrtcCreate(pScrn, &iga1_crtc_funcs);
1756    if (!iga1) {
1757        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86CrtcCreate failed.\n");
1758        free(iga1_rec);
1759        return FALSE;
1760    }
1761    iga1_rec->drmmode = &pVia->drmmode;
1762    iga1_rec->index = 0;
1763    iga1->driver_private = iga1_rec;
1764
1765    iga2_rec = (drmmode_crtc_private_ptr) xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
1766    if (!iga2_rec) {
1767        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "IGA1 Rec allocation failed.\n");
1768        xf86CrtcDestroy(iga1);
1769        return FALSE;
1770    }
1771
1772    iga2 = xf86CrtcCreate(pScrn, &iga2_crtc_funcs);
1773    if (!iga2) {
1774        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86CrtcCreate failed.\n");
1775        xf86CrtcDestroy(iga1);
1776        free(iga2_rec);
1777        return FALSE;
1778    }
1779    iga2_rec->drmmode = &pVia->drmmode;
1780    iga2_rec->index = 1;
1781    iga2->driver_private = iga2_rec;
1782
1783    /*
1784     * CLE266A:
1785     *   Max Line Pitch: 4080, (FB corruption when higher, driver problem?)
1786     *   Max Height: 4096 (and beyond)
1787     *
1788     * CLE266A: primary AdjustFrame can use only 24 bits, so we are limited
1789     * to 12x11 bits; 4080x2048 (~2:1), 3344x2508 (4:3), or 2896x2896 (1:1).
1790     * TODO Test CLE266Cx, KM400, KM400A, K8M800, CN400 please.
1791     *
1792     * We should be able to limit the memory available for a mode to 32 MB,
1793     * but miScanLineWidth fails to catch this properly (apertureSize).
1794     */
1795    switch (pVia->Chipset) {
1796    case VIA_CLE266:
1797    case VIA_KM400:
1798    case VIA_K8M800:
1799    case VIA_PM800:
1800    case VIA_VM800:
1801        max_pitch = 3344;
1802        max_height = 2508;
1803        break;
1804
1805    case VIA_CX700:
1806    case VIA_K8M890:
1807    case VIA_P4M890:
1808    case VIA_P4M900:
1809        max_pitch = 8192/(pScrn->bitsPerPixel >> 3)-1;
1810        max_height = max_pitch;
1811        break;
1812
1813    default:
1814        max_pitch = 16384/(pScrn->bitsPerPixel >> 3)-1;
1815        max_height = max_pitch;
1816        break;
1817    }
1818
1819    /* Init HI_X0 for cursor */
1820    switch (pVia->Chipset) {
1821    case VIA_CX700:
1822    /* case VIA_CN750: */
1823    case VIA_P4M890:
1824    case VIA_P4M900:
1825    case VIA_VX800:
1826    case VIA_VX855:
1827    case VIA_VX900:
1828        /* set 0 as transparent color key for IGA 2 */
1829        VIASETREG(HI_TRANSPARENT_COLOR, 0);
1830        VIASETREG(HI_INVTCOLOR, 0X00FFFFFF);
1831        VIASETREG(ALPHA_V3_PREFIFO_CONTROL, 0xE0000);
1832        VIASETREG(ALPHA_V3_FIFO_CONTROL, 0xE0F0000);
1833
1834        /* set 0 as transparent color key for IGA 1 */
1835        VIASETREG(PRIM_HI_TRANSCOLOR, 0);
1836        VIASETREG(PRIM_HI_FIFO, 0x0D000D0F);
1837        VIASETREG(PRIM_HI_INVTCOLOR, 0x00FFFFFF);
1838        VIASETREG(V327_HI_INVTCOLOR, 0x00FFFFFF);
1839        break;
1840
1841    default:
1842        VIASETREG(HI_TRANSPARENT_COLOR, 0);
1843        VIASETREG(HI_INVTCOLOR, 0X00FFFFFF);
1844        VIASETREG(ALPHA_V3_PREFIFO_CONTROL, 0xE0000);
1845        VIASETREG(ALPHA_V3_FIFO_CONTROL, 0xE0F0000);
1846        break;
1847    }
1848
1849    xf86CrtcSetSizeRange(pScrn, 320, 200, max_pitch, max_height);
1850
1851    ViaOutputsDetect(pScrn);
1852
1853    if (pVia->pVbe) {
1854        if (!ViaVbeModePreInit(pScrn))
1855            return FALSE;
1856    }
1857    return TRUE;
1858}
1859