via_display.c revision 5b405e1a
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;
1006    int i;
1007
1008    colors = malloc(size * sizeof(*colors));
1009    if (colors == NULL)
1010	return;
1011
1012    for (i = 0; i < size; i++) {
1013        colors[i].red = red[i] >> 8;
1014        colors[i].green = green[i] >> 8;
1015        colors[i].blue = blue[i] >> 8;
1016    }
1017
1018    if (pScrn->bitsPerPixel != 8) {
1019        switch (pVia->Chipset) {
1020        case VIA_CLE266:
1021        case VIA_KM400:
1022            ViaSeqMask(hwp, 0x16, 0x80, 0x80);
1023            break;
1024        default:
1025            ViaCrtcMask(hwp, 0x33, 0x80, 0x80);
1026            break;
1027        }
1028
1029        ViaSeqMask(hwp, 0x1A, 0x00, 0x01);
1030        VIALoadRgbLut(pScrn, 0, size, colors);
1031
1032    } else {
1033
1034        SR1A = hwp->readSeq(hwp, 0x1A);
1035        SR1B = hwp->readSeq(hwp, 0x1B);
1036        CR67 = hwp->readCrtc(hwp, 0x67);
1037        CR6A = hwp->readCrtc(hwp, 0x6A);
1038
1039        for (i = 0; i < size; i++) {
1040            hwp->writeDacWriteAddr(hwp, i);
1041            hwp->writeDacData(hwp, colors[i].red);
1042            hwp->writeDacData(hwp, colors[i].green);
1043            hwp->writeDacData(hwp, colors[i].blue);
1044        }
1045    }
1046    free(colors);
1047}
1048
1049static void *
1050iga1_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
1051{
1052    return NULL;
1053}
1054
1055static PixmapPtr
1056iga1_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
1057{
1058    return NULL;
1059}
1060
1061static void
1062iga1_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
1063{
1064}
1065
1066/*
1067    Set the cursor foreground and background colors.  In 8bpp, fg and
1068    bg are indices into the current colormap unless the
1069    HARDWARE_CURSOR_TRUECOLOR_AT_8BPP flag is set.  In that case
1070    and in all other bpps the fg and bg are in 8-8-8 RGB format.
1071*/
1072static void
1073iga1_crtc_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
1074{
1075    ScrnInfoPtr pScrn = crtc->scrn;
1076    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1077    VIAPtr pVia = VIAPTR(pScrn);
1078    CARD32 temp;
1079
1080    if (xf86_config->cursor_fg)
1081        return;
1082
1083    /* Don't recolour the image if we don't have to. */
1084    if (fg == xf86_config->cursor_fg && bg == xf86_config->cursor_bg)
1085        return;
1086
1087    switch(pVia->Chipset) {
1088    case VIA_CX700:
1089    case VIA_P4M890:
1090    case VIA_P4M900:
1091    case VIA_VX800:
1092    case VIA_VX855:
1093    case VIA_VX900:
1094        temp = VIAGETREG(PRIM_HI_CTRL);
1095        VIASETREG(PRIM_HI_CTRL, temp & 0xFFFFFFFE);
1096        break;
1097
1098    default:
1099        temp = VIAGETREG(HI_CONTROL);
1100        VIASETREG(HI_CONTROL, temp & 0xFFFFFFFE);
1101        break;
1102    }
1103
1104    xf86_config->cursor_fg = fg;
1105    xf86_config->cursor_bg = bg;
1106}
1107
1108static void
1109iga1_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
1110{
1111    ScrnInfoPtr pScrn = crtc->scrn;
1112    VIAPtr pVia = VIAPTR(pScrn);
1113    unsigned xoff, yoff;
1114
1115    if (x < 0) {
1116        xoff = ((-x) & 0xFE);
1117        x = 0;
1118    } else {
1119        xoff = 0;
1120    }
1121
1122    if (y < 0) {
1123        yoff = ((-y) & 0xFE);
1124        y = 0;
1125    } else {
1126        yoff = 0;
1127    }
1128
1129    switch(pVia->Chipset) {
1130    case VIA_CX700:
1131    case VIA_P4M890:
1132    case VIA_P4M900:
1133    case VIA_VX800:
1134    case VIA_VX855:
1135    case VIA_VX900:
1136        VIASETREG(PRIM_HI_POSSTART,    ((x    << 16) | (y    & 0x07ff)));
1137        VIASETREG(PRIM_HI_CENTEROFFSET, ((xoff << 16) | (yoff & 0x07ff)));
1138        break;
1139
1140    default:
1141        VIASETREG(HI_POSSTART,    ((x    << 16) | (y    & 0x07ff)));
1142        VIASETREG(HI_CENTEROFFSET, ((xoff << 16) | (yoff & 0x07ff)));
1143        break;
1144    }
1145}
1146
1147static void
1148iga1_crtc_show_cursor (xf86CrtcPtr crtc)
1149{
1150    drmmode_crtc_private_ptr iga = crtc->driver_private;
1151    ScrnInfoPtr pScrn = crtc->scrn;
1152    VIAPtr pVia = VIAPTR(pScrn);
1153
1154    switch(pVia->Chipset) {
1155    case VIA_CX700:
1156    case VIA_P4M890:
1157    case VIA_P4M900:
1158    case VIA_VX800:
1159    case VIA_VX855:
1160    case VIA_VX900:
1161        VIASETREG(PRIM_HI_FBOFFSET, iga->cursor_bo->offset);
1162        VIASETREG(PRIM_HI_CTRL, 0x36000005);
1163        break;
1164
1165    default:
1166        /* Mono Cursor Display Path [bit31]: Primary */
1167        VIASETREG(HI_FBOFFSET, iga->cursor_bo->offset);
1168        VIASETREG(HI_CONTROL, 0x76000005);
1169        break;
1170    }
1171}
1172
1173static void
1174iga1_crtc_hide_cursor (xf86CrtcPtr crtc)
1175{
1176    ScrnInfoPtr pScrn = crtc->scrn;
1177    VIAPtr pVia = VIAPTR(pScrn);
1178    CARD32 temp;
1179
1180    switch(pVia->Chipset) {
1181    case VIA_CX700:
1182    case VIA_P4M890:
1183    case VIA_P4M900:
1184    case VIA_VX800:
1185    case VIA_VX855:
1186    case VIA_VX900:
1187        temp = VIAGETREG(PRIM_HI_CTRL);
1188        VIASETREG(PRIM_HI_CTRL, temp & 0xFFFFFFFA);
1189        break;
1190
1191    default:
1192        temp = VIAGETREG(HI_CONTROL);
1193        /* Hardware cursor disable [bit0] */
1194        VIASETREG(HI_CONTROL, temp & 0xFFFFFFFA);
1195        break;
1196    }
1197}
1198
1199static void
1200iga_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
1201{
1202    drmmode_crtc_private_ptr iga = crtc->driver_private;
1203    ScrnInfoPtr pScrn = crtc->scrn;
1204    void *dst;
1205
1206    dst = drm_bo_map(pScrn, iga->cursor_bo);
1207    memset(dst, 0x00, iga->cursor_bo->size);
1208    memcpy(dst, image, iga->cursor_bo->size);
1209    drm_bo_unmap(pScrn, iga->cursor_bo);
1210}
1211
1212static void
1213iga_crtc_commit(xf86CrtcPtr crtc)
1214{
1215    ScrnInfoPtr pScrn = crtc->scrn;
1216    VIAPtr pVia = VIAPTR(pScrn);
1217
1218    if (crtc->scrn->pScreen != NULL && pVia->drmmode.hwcursor)
1219        xf86_reload_cursors(crtc->scrn->pScreen);
1220}
1221
1222static void
1223iga_crtc_destroy(xf86CrtcPtr crtc)
1224{
1225    if (crtc->driver_private)
1226        free(crtc->driver_private);
1227}
1228
1229static const xf86CrtcFuncsRec iga1_crtc_funcs = {
1230    .dpms                   = iga1_crtc_dpms,
1231    .save                   = iga1_crtc_save,
1232    .restore                = iga1_crtc_restore,
1233    .lock                   = iga1_crtc_lock,
1234    .unlock                 = iga1_crtc_unlock,
1235    .mode_fixup             = iga1_crtc_mode_fixup,
1236    .prepare                = iga1_crtc_prepare,
1237    .mode_set               = iga1_crtc_mode_set,
1238    .commit                 = iga_crtc_commit,
1239    .gamma_set              = iga1_crtc_gamma_set,
1240    .shadow_create          = iga1_crtc_shadow_create,
1241    .shadow_allocate        = iga1_crtc_shadow_allocate,
1242    .shadow_destroy         = iga1_crtc_shadow_destroy,
1243    .set_cursor_colors      = iga1_crtc_set_cursor_colors,
1244    .set_cursor_position    = iga1_crtc_set_cursor_position,
1245    .show_cursor            = iga1_crtc_show_cursor,
1246    .hide_cursor            = iga1_crtc_hide_cursor,
1247    .load_cursor_argb       = iga_crtc_load_cursor_argb,
1248#ifdef RANDR_12_INTERFACE
1249    .set_origin             = iga1_crtc_set_origin,
1250#endif
1251    .destroy                = iga_crtc_destroy,
1252};
1253
1254static void
1255iga2_crtc_dpms(xf86CrtcPtr crtc, int mode)
1256{
1257    ScrnInfoPtr pScrn = crtc->scrn;
1258    VIAPtr pVia = VIAPTR(pScrn);
1259    VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
1260
1261    if (pVia->pVbe) {
1262        ViaVbeDPMS(pScrn, mode);
1263    } else {
1264        switch (mode) {
1265        case DPMSModeOn:
1266            if (pBIOSInfo->SimultaneousEnabled)
1267                ViaDisplayEnableSimultaneous(pScrn);
1268            break;
1269
1270        case DPMSModeStandby:
1271        case DPMSModeSuspend:
1272        case DPMSModeOff:
1273            if (pBIOSInfo->SimultaneousEnabled)
1274                ViaDisplayDisableSimultaneous(pScrn);
1275            break;
1276
1277        default:
1278            xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid DPMS mode %d\n",
1279                        mode);
1280            break;
1281        }
1282        //vgaHWSaveScreen(pScrn->pScreen, mode);
1283    }
1284}
1285
1286static void
1287iga2_crtc_save(xf86CrtcPtr crtc)
1288{
1289    ScrnInfoPtr pScrn = crtc->scrn;
1290    vgaHWPtr hwp = VGAHWPTR(pScrn);
1291    VIAPtr pVia = VIAPTR(pScrn);
1292
1293    if (pVia->pVbe && pVia->vbeSR)
1294        ViaVbeSaveRestore(pScrn, MODE_SAVE);
1295    else
1296        VIASave(pScrn);
1297	vgaHWUnlock(hwp);
1298}
1299
1300static void
1301iga2_crtc_restore(xf86CrtcPtr crtc)
1302{
1303    ScrnInfoPtr pScrn = crtc->scrn;
1304    vgaHWPtr hwp = VGAHWPTR(pScrn);
1305    VIAPtr pVia = VIAPTR(pScrn);
1306
1307    if (pVia->pVbe && pVia->vbeSR)
1308        ViaVbeSaveRestore(pScrn, MODE_RESTORE);
1309    else
1310        VIARestore(pScrn);
1311    vgaHWLock(hwp);
1312}
1313
1314static Bool
1315iga2_crtc_lock(xf86CrtcPtr crtc)
1316{
1317    return FALSE;
1318}
1319
1320static void
1321iga2_crtc_unlock(xf86CrtcPtr crtc)
1322{
1323}
1324
1325static Bool
1326iga2_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
1327                        DisplayModePtr adjusted_mode)
1328{
1329    ScrnInfoPtr pScrn = crtc->scrn;
1330    VIAPtr pVia = VIAPTR(pScrn);
1331    CARD32 temp;
1332    ModeStatus modestatus;
1333
1334    if (pVia->pVbe)
1335        return TRUE;
1336
1337    if ((mode->Clock < pScrn->clockRanges->minClock) ||
1338        (mode->Clock > pScrn->clockRanges->maxClock)) {
1339        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1340                   "Clock for mode \"%s\" outside of allowed range (%u (%u - %u))\n",
1341                   mode->name, mode->Clock, pScrn->clockRanges->minClock,
1342                   pScrn->clockRanges->maxClock);
1343        return FALSE;
1344    }
1345
1346    modestatus = ViaFirstCRTCModeValid(pScrn, mode);
1347    if (modestatus != MODE_OK) {
1348        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Not using mode \"%s\" : %s.\n",
1349                   mode->name, xf86ModeStatusToString(modestatus));
1350        return FALSE;
1351    }
1352
1353    temp = mode->CrtcHDisplay * mode->CrtcVDisplay * mode->VRefresh *
1354            (pScrn->bitsPerPixel >> 3);
1355    if (pVia->pBIOSInfo->Bandwidth < temp) {
1356        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1357                    "Required bandwidth is not available. (%u > %u)\n",
1358			        (unsigned)temp, (unsigned)pVia->pBIOSInfo->Bandwidth);
1359        return FALSE;
1360    }
1361    return TRUE;
1362}
1363
1364static void
1365iga2_crtc_prepare (xf86CrtcPtr crtc)
1366{
1367}
1368
1369static void
1370iga2_crtc_set_origin(xf86CrtcPtr crtc, int x, int y)
1371{
1372    ScrnInfoPtr pScrn = crtc->scrn;
1373    VIAPtr pVia = VIAPTR(pScrn);
1374
1375    if (pVia->pVbe) {
1376        ViaVbeAdjustFrame(pScrn, x, y);
1377    } else {
1378        ViaSecondCRTCSetStartingAddress(crtc, x, y);
1379    }
1380    VIAVidAdjustFrame(pScrn, x, y);
1381}
1382
1383static void
1384iga2_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
1385                    DisplayModePtr adjusted_mode, int x, int y)
1386{
1387    ScrnInfoPtr pScrn = crtc->scrn;
1388    VIAPtr pVia = VIAPTR(pScrn);
1389
1390    if (pVia->pVbe) {
1391        if (!ViaVbeSetMode(pScrn, adjusted_mode))
1392            return;
1393    } else {
1394        if (!vgaHWInit(pScrn, adjusted_mode))
1395            return;
1396
1397        if (pVia->UseLegacyModeSwitch) {
1398            ViaModeSecondaryLegacy(crtc, adjusted_mode);
1399        } else {
1400            ViaCRTCInit(pScrn);
1401            ViaModeSecondCRTC(pScrn, adjusted_mode);
1402            ViaSecondDisplayChannelEnable(pScrn);
1403
1404            if (pVia->pBIOSInfo->SimultaneousEnabled)
1405                ViaDisplayEnableSimultaneous(pScrn);
1406            else
1407                ViaDisplayDisableSimultaneous(pScrn);
1408        }
1409    }
1410    iga2_crtc_set_origin(crtc, crtc->x, crtc->y);
1411}
1412
1413static void
1414iga2_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
1415					int size)
1416{
1417    ScrnInfoPtr pScrn = crtc->scrn;
1418    vgaHWPtr hwp = VGAHWPTR(pScrn);
1419    VIAPtr pVia = VIAPTR(pScrn);
1420    int SR1A, SR1B, CR67, CR6A;
1421    int i;
1422    LOCO *colors;
1423
1424    colors = malloc(size * sizeof(*colors));
1425    if (colors == NULL)
1426	return;
1427
1428    for (i = 0; i < size; i++) {
1429        colors[i].red = red[i] >> 8;
1430        colors[i].green = green[i] >> 8;
1431        colors[i].blue = blue[i] >> 8;
1432    }
1433
1434    if (pScrn->bitsPerPixel != 8) {
1435        if (!(pVia->Chipset == VIA_CLE266 &&
1436            CLE266_REV_IS_AX(pVia->ChipRev))) {
1437            ViaSeqMask(hwp, 0x1A, 0x01, 0x01);
1438            ViaCrtcMask(hwp, 0x6A, 0x02, 0x02);
1439
1440            switch (pVia->Chipset) {
1441            case VIA_CLE266:
1442            case VIA_KM400:
1443            case VIA_K8M800:
1444            case VIA_PM800:
1445                break;
1446
1447            default:
1448                ViaCrtcMask(hwp, 0x6A, 0x20, 0x20);
1449                break;
1450            }
1451            VIALoadRgbLut(pScrn, 0, size, colors);
1452        }
1453    } else {
1454        SR1A = hwp->readSeq(hwp, 0x1A);
1455        SR1B = hwp->readSeq(hwp, 0x1B);
1456        CR67 = hwp->readCrtc(hwp, 0x67);
1457        CR6A = hwp->readCrtc(hwp, 0x6A);
1458
1459        ViaSeqMask(hwp, 0x1A, 0x01, 0x01);
1460        ViaSeqMask(hwp, 0x1B, 0x80, 0x80);
1461        ViaCrtcMask(hwp, 0x67, 0x00, 0xC0);
1462        ViaCrtcMask(hwp, 0x6A, 0xC0, 0xC0);
1463
1464        for (i = 0; i < size; i++) {
1465            hwp->writeDacWriteAddr(hwp, i);
1466            hwp->writeDacData(hwp, colors[i].red);
1467            hwp->writeDacData(hwp, colors[i].green);
1468            hwp->writeDacData(hwp, colors[i].blue);
1469        }
1470
1471        hwp->writeSeq(hwp, 0x1A, SR1A);
1472        hwp->writeSeq(hwp, 0x1B, SR1B);
1473        hwp->writeCrtc(hwp, 0x67, CR67);
1474        hwp->writeCrtc(hwp, 0x6A, CR6A);
1475
1476        /* Screen 0 palette was changed by mode setting of Screen 1,
1477         * so load it again. */
1478        for (i = 0; i < size; i++) {
1479            hwp->writeDacWriteAddr(hwp, i);
1480            hwp->writeDacData(hwp, colors[i].red);
1481            hwp->writeDacData(hwp, colors[i].green);
1482            hwp->writeDacData(hwp, colors[i].blue);
1483        }
1484    }
1485    free(colors);
1486}
1487
1488static void *
1489iga2_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
1490{
1491    return NULL;
1492}
1493
1494static PixmapPtr
1495iga2_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
1496{
1497    return NULL;
1498}
1499
1500static void
1501iga2_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
1502{
1503}
1504
1505/*
1506    Set the cursor foreground and background colors.  In 8bpp, fg and
1507    bg are indices into the current colormap unless the
1508    HARDWARE_CURSOR_TRUECOLOR_AT_8BPP flag is set.  In that case
1509    and in all other bpps the fg and bg are in 8-8-8 RGB format.
1510*/
1511static void
1512iga2_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
1513{
1514    drmmode_crtc_private_ptr iga = crtc->driver_private;
1515    ScrnInfoPtr pScrn = crtc->scrn;
1516    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
1517    int height = 64, width = 64, i;
1518    VIAPtr pVia = VIAPTR(pScrn);
1519    CARD32 pixel, temp, *dst;
1520
1521    if (xf86_config->cursor_fg)
1522        return;
1523
1524    fg |= 0xff000000;
1525    bg |= 0xff000000;
1526
1527    /* Don't recolour the image if we don't have to. */
1528    if (fg == xf86_config->cursor_fg && bg == xf86_config->cursor_bg)
1529        return;
1530
1531    switch(pVia->Chipset) {
1532    case VIA_CX700:
1533    case VIA_P4M890:
1534    case VIA_P4M900:
1535    case VIA_VX800:
1536    case VIA_VX855:
1537    case VIA_VX900:
1538        temp = VIAGETREG(HI_CONTROL);
1539        VIASETREG(HI_CONTROL, temp & 0xFFFFFFFE);
1540        break;
1541
1542    default:
1543        temp = VIAGETREG(HI_CONTROL);
1544        VIASETREG(HI_CONTROL, temp & 0xFFFFFFFE);
1545        height = width = 32;
1546        break;
1547    }
1548
1549    dst = drm_bo_map(pScrn, iga->cursor_bo);
1550    for (i = 0; i < width * height; i++, dst++)
1551        if ((pixel = *dst))
1552            *dst = (pixel == xf86_config->cursor_fg) ? fg : bg;
1553    drm_bo_unmap(pScrn, iga->cursor_bo);
1554
1555    xf86_config->cursor_fg = fg;
1556    xf86_config->cursor_bg = bg;
1557}
1558
1559static void
1560iga2_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
1561{
1562    ScrnInfoPtr pScrn = crtc->scrn;
1563    VIAPtr pVia = VIAPTR(pScrn);
1564    unsigned xoff, yoff;
1565
1566    if (x < 0) {
1567        xoff = ((-x) & 0xFE);
1568        x = 0;
1569    } else {
1570        xoff = 0;
1571    }
1572
1573    if (y < 0) {
1574        yoff = ((-y) & 0xFE);
1575        y = 0;
1576    } else {
1577        yoff = 0;
1578    }
1579
1580    switch(pVia->Chipset) {
1581    case VIA_CX700:
1582    case VIA_P4M890:
1583    case VIA_P4M900:
1584    case VIA_VX800:
1585    case VIA_VX855:
1586    case VIA_VX900:
1587        VIASETREG(HI_POSSTART,    ((x    << 16) | (y    & 0x07ff)));
1588        VIASETREG(HI_CENTEROFFSET, ((xoff << 16) | (yoff & 0x07ff)));
1589        break;
1590
1591    default:
1592        VIASETREG(HI_POSSTART,    ((x    << 16) | (y    & 0x07ff)));
1593        VIASETREG(HI_CENTEROFFSET, ((xoff << 16) | (yoff & 0x07ff)));
1594        break;
1595    }
1596}
1597
1598static void
1599iga2_crtc_show_cursor(xf86CrtcPtr crtc)
1600{
1601    drmmode_crtc_private_ptr iga = crtc->driver_private;
1602    ScrnInfoPtr pScrn = crtc->scrn;
1603    VIAPtr pVia = VIAPTR(pScrn);
1604
1605    switch(pVia->Chipset) {
1606    case VIA_CX700:
1607    case VIA_P4M890:
1608    case VIA_P4M900:
1609    case VIA_VX800:
1610    case VIA_VX855:
1611    case VIA_VX900:
1612        VIASETREG(HI_FBOFFSET, iga->cursor_bo->offset);
1613        VIASETREG(HI_CONTROL, 0xB6000005);
1614        break;
1615
1616    default:
1617        /* Mono Cursor Display Path [bit31]: Secondary */
1618        /* FIXME For CLE266 and KM400 try to enable 32x32 cursor size [bit1] */
1619        VIASETREG(HI_FBOFFSET, iga->cursor_bo->offset);
1620        VIASETREG(HI_CONTROL, 0xF6000005);
1621        break;
1622    }
1623}
1624
1625static void
1626iga2_crtc_hide_cursor(xf86CrtcPtr crtc)
1627{
1628    ScrnInfoPtr pScrn = crtc->scrn;
1629    VIAPtr pVia = VIAPTR(pScrn);
1630    CARD32 temp;
1631
1632    switch(pVia->Chipset) {
1633    case VIA_CX700:
1634    case VIA_P4M890:
1635    case VIA_P4M900:
1636    case VIA_VX800:
1637    case VIA_VX855:
1638    case VIA_VX900:
1639	    temp = VIAGETREG(HI_CONTROL);
1640        VIASETREG(HI_CONTROL, temp & 0xFFFFFFFA);
1641        break;
1642
1643    default:
1644        temp = VIAGETREG(HI_CONTROL);
1645        /* Hardware cursor disable [bit0] */
1646        VIASETREG(HI_CONTROL, temp & 0xFFFFFFFA);
1647        break;
1648	}
1649}
1650
1651static const xf86CrtcFuncsRec iga2_crtc_funcs = {
1652    .dpms                   = iga2_crtc_dpms,
1653    .save                   = iga2_crtc_save,
1654    .restore                = iga2_crtc_restore,
1655    .lock                   = iga2_crtc_lock,
1656    .unlock                 = iga2_crtc_unlock,
1657    .mode_fixup             = iga2_crtc_mode_fixup,
1658    .prepare                = iga2_crtc_prepare,
1659    .mode_set               = iga2_crtc_mode_set,
1660    .commit                 = iga_crtc_commit,
1661    .gamma_set              = iga2_crtc_gamma_set,
1662    .shadow_create          = iga2_crtc_shadow_create,
1663    .shadow_allocate        = iga2_crtc_shadow_allocate,
1664    .shadow_destroy         = iga2_crtc_shadow_destroy,
1665    .set_cursor_colors      = iga2_crtc_set_cursor_colors,
1666    .set_cursor_position    = iga2_crtc_set_cursor_position,
1667    .show_cursor            = iga2_crtc_show_cursor,
1668    .hide_cursor            = iga2_crtc_hide_cursor,
1669    .load_cursor_argb       = iga_crtc_load_cursor_argb,
1670#ifdef RANDR_12_INTERFACE
1671    .set_origin             = iga2_crtc_set_origin,
1672#endif
1673    .destroy                = iga_crtc_destroy,
1674};
1675
1676Bool
1677UMSCrtcInit(ScrnInfoPtr pScrn)
1678{
1679    drmmode_crtc_private_ptr iga1_rec = NULL, iga2_rec = NULL;
1680    vgaHWPtr hwp = VGAHWPTR(pScrn);
1681    VIAPtr pVia = VIAPTR(pScrn);
1682    ClockRangePtr clockRanges;
1683    int max_pitch, max_height;
1684    VIABIOSInfoPtr pBIOSInfo;
1685    xf86CrtcPtr iga1, iga2;
1686
1687    /* Read memory bandwidth from registers. */
1688    pVia->MemClk = hwp->readCrtc(hwp, 0x3D) >> 4;
1689    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1690                     "Detected MemClk %d\n", pVia->MemClk));
1691    if (pVia->MemClk >= VIA_MEM_END) {
1692        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1693                   "Unknown Memory clock: %d\n", pVia->MemClk);
1694        pVia->MemClk = VIA_MEM_END - 1;
1695    }
1696    pBIOSInfo = pVia->pBIOSInfo;
1697    pBIOSInfo->Bandwidth = ViaGetMemoryBandwidth(pScrn);
1698
1699    if (pBIOSInfo->TVType == TVTYPE_NONE) {
1700        /* Use jumper to determine TV type. */
1701        if (hwp->readCrtc(hwp, 0x3B) & 0x02) {
1702            pBIOSInfo->TVType = TVTYPE_PAL;
1703            DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1704                             "Detected TV standard: PAL.\n"));
1705        } else {
1706            pBIOSInfo->TVType = TVTYPE_NTSC;
1707            DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1708                             "Detected TV standard: NTSC.\n"));
1709        }
1710    }
1711
1712    if (pVia->drmmode.hwcursor) {
1713        if (!xf86LoadSubModule(pScrn, "ramdac"))
1714            return FALSE;
1715    }
1716
1717    if (!xf86LoadSubModule(pScrn, "i2c"))
1718        return FALSE;
1719    else
1720        ViaI2CInit(pScrn);
1721
1722    if (!xf86LoadSubModule(pScrn, "ddc"))
1723        return FALSE;
1724
1725    pVia->pVbe = NULL;
1726    if (pVia->useVBEModes) {
1727        /* VBE doesn't properly initialise int10 itself. */
1728        if (xf86LoadSubModule(pScrn, "int10") &&
1729            xf86LoadSubModule(pScrn, "vbe")) {
1730            pVia->pVbe = VBEExtendedInit(NULL, pVia->EntityIndex,
1731                                        SET_BIOS_SCRATCH |
1732                                        RESTORE_BIOS_SCRATCH);
1733        }
1734
1735        if (!pVia->pVbe)
1736            xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VBE initialisation failed."
1737                        " Using builtin code to set modes.\n");
1738        else
1739            ConfiguredMonitor = vbeDoEDID(pVia->pVbe, NULL);
1740    }
1741
1742    /*
1743     * Set up ClockRanges, which describe what clock ranges are
1744     * available, and what sort of modes they can be used for.
1745     */
1746    clockRanges = xnfalloc(sizeof(ClockRange));
1747    clockRanges->next = NULL;
1748    clockRanges->minClock = 20000;
1749    clockRanges->maxClock = 230000;
1750
1751    clockRanges->clockIndex = -1;
1752    clockRanges->interlaceAllowed = TRUE;
1753    clockRanges->doubleScanAllowed = FALSE;
1754    pScrn->clockRanges = clockRanges;
1755
1756    /*
1757     * Now handle the outputs
1758     */
1759    iga1_rec = (drmmode_crtc_private_ptr) xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
1760    if (!iga1_rec) {
1761        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "IGA1 Rec allocation failed.\n");
1762        return FALSE;
1763    }
1764
1765    iga1 = xf86CrtcCreate(pScrn, &iga1_crtc_funcs);
1766    if (!iga1) {
1767        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86CrtcCreate failed.\n");
1768        free(iga1_rec);
1769        return FALSE;
1770    }
1771    iga1_rec->drmmode = &pVia->drmmode;
1772    iga1_rec->index = 0;
1773    iga1->driver_private = iga1_rec;
1774
1775    iga2_rec = (drmmode_crtc_private_ptr) xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
1776    if (!iga2_rec) {
1777        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "IGA1 Rec allocation failed.\n");
1778        xf86CrtcDestroy(iga1);
1779        return FALSE;
1780    }
1781
1782    iga2 = xf86CrtcCreate(pScrn, &iga2_crtc_funcs);
1783    if (!iga2) {
1784        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86CrtcCreate failed.\n");
1785        xf86CrtcDestroy(iga1);
1786        free(iga2_rec);
1787        return FALSE;
1788    }
1789    iga2_rec->drmmode = &pVia->drmmode;
1790    iga2_rec->index = 1;
1791    iga2->driver_private = iga2_rec;
1792
1793    /*
1794     * CLE266A:
1795     *   Max Line Pitch: 4080, (FB corruption when higher, driver problem?)
1796     *   Max Height: 4096 (and beyond)
1797     *
1798     * CLE266A: primary AdjustFrame can use only 24 bits, so we are limited
1799     * to 12x11 bits; 4080x2048 (~2:1), 3344x2508 (4:3), or 2896x2896 (1:1).
1800     * TODO Test CLE266Cx, KM400, KM400A, K8M800, CN400 please.
1801     *
1802     * We should be able to limit the memory available for a mode to 32 MB,
1803     * but miScanLineWidth fails to catch this properly (apertureSize).
1804     */
1805    switch (pVia->Chipset) {
1806    case VIA_CLE266:
1807    case VIA_KM400:
1808    case VIA_K8M800:
1809    case VIA_PM800:
1810    case VIA_VM800:
1811        max_pitch = 3344;
1812        max_height = 2508;
1813        break;
1814
1815    case VIA_CX700:
1816    case VIA_K8M890:
1817    case VIA_P4M890:
1818    case VIA_P4M900:
1819        max_pitch = 8192/(pScrn->bitsPerPixel >> 3)-1;
1820        max_height = max_pitch;
1821        break;
1822
1823    default:
1824        max_pitch = 16384/(pScrn->bitsPerPixel >> 3)-1;
1825        max_height = max_pitch;
1826        break;
1827    }
1828
1829    /* Init HI_X0 for cursor */
1830    switch (pVia->Chipset) {
1831    case VIA_CX700:
1832    /* case VIA_CN750: */
1833    case VIA_P4M890:
1834    case VIA_P4M900:
1835    case VIA_VX800:
1836    case VIA_VX855:
1837    case VIA_VX900:
1838        /* set 0 as transparent color key for IGA 2 */
1839        VIASETREG(HI_TRANSPARENT_COLOR, 0);
1840        VIASETREG(HI_INVTCOLOR, 0X00FFFFFF);
1841        VIASETREG(ALPHA_V3_PREFIFO_CONTROL, 0xE0000);
1842        VIASETREG(ALPHA_V3_FIFO_CONTROL, 0xE0F0000);
1843
1844        /* set 0 as transparent color key for IGA 1 */
1845        VIASETREG(PRIM_HI_TRANSCOLOR, 0);
1846        VIASETREG(PRIM_HI_FIFO, 0x0D000D0F);
1847        VIASETREG(PRIM_HI_INVTCOLOR, 0x00FFFFFF);
1848        VIASETREG(V327_HI_INVTCOLOR, 0x00FFFFFF);
1849        break;
1850
1851    default:
1852        VIASETREG(HI_TRANSPARENT_COLOR, 0);
1853        VIASETREG(HI_INVTCOLOR, 0X00FFFFFF);
1854        VIASETREG(ALPHA_V3_PREFIFO_CONTROL, 0xE0000);
1855        VIASETREG(ALPHA_V3_FIFO_CONTROL, 0xE0F0000);
1856        break;
1857    }
1858
1859    xf86CrtcSetSizeRange(pScrn, 320, 200, max_pitch, max_height);
1860
1861    ViaOutputsDetect(pScrn);
1862
1863    if (pVia->pVbe) {
1864        if (!ViaVbeModePreInit(pScrn))
1865            return FALSE;
1866    }
1867    return TRUE;
1868}
1869