via_display.c revision 861b9fee
1/*
2 * Copyright 2015-2016 Kevin Brace
3 * Copyright 2005-2016 The OpenChrome Project
4 *                     [https://www.freedesktop.org/wiki/Openchrome]
5 * Copyright 2004-2005 The Unichrome Project  [unichrome.sf.net]
6 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
7 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sub license,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 */
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include <stdint.h>
33#include "via_driver.h"
34
35static ViaExpireNumberTable CLE266AExpireNumber[] = {
36    {1280, 768,32,0x03,0x3}, {1280,1024,32,0x03,0x4}, {1280,1024,32,0x04,0x3},
37    {1600,1200,16,0x03,0x4}, {1600,1200,32,0x04,0x4}, {1024, 768,32,0x03,0xA},
38    {1400,1050,16,0x03,0x3}, {1400,1050,32,0x03,0x4}, {1400,1050,32,0x04,0x4},
39    { 800, 600,32,0x03,0xA}, {   0,   0, 0,   0,  0}
40};
41
42static ViaExpireNumberTable CLE266CExpireNumber[] = {
43    {1280, 768,32,0x03,0x3}, {1280,1024,32,0x03,0x4}, {1280,1024,32,0x04,0x4},
44    {1600,1200,32,0x03,0x3}, {1600,1200,32,0x04,0x4}, {1024, 768,32,0x03,0xA},
45    {1400,1050,32,0x03,0x4}, {1400,1050,32,0x04,0x4},
46    { 800, 600,32,0x03,0xA}, {   0,   0, 0,   0,  0}
47};
48
49static ViaExpireNumberTable KM400ExpireNumber[]={
50    {1280,1024,32,0x03,0x3}, {1280,1024,32,0x04,0x9}, {1280, 768,32,0x03,0x3},
51    {1280, 768,32,0x04,0x9}, {1400,1050,32,0x03,0x3}, {1400,1050,32,0x04,0x9},
52    {1600,1200,32,0x03,0x4}, {1600,1200,32,0x04,0xA}, {   0,   0, 0,   0,  0}
53};
54
55
56static void
57ViaPrintMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
58{
59    xf86PrintModeline(pScrn->scrnIndex, mode);
60
61    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHDisplay: 0x%x\n",
62               mode->CrtcHDisplay);
63    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHBlankStart: 0x%x\n",
64               mode->CrtcHBlankStart);
65    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHSyncStart: 0x%x\n",
66               mode->CrtcHSyncStart);
67    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHSyncEnd: 0x%x\n",
68               mode->CrtcHSyncEnd);
69    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHBlankEnd: 0x%x\n",
70               mode->CrtcHBlankEnd);
71    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHTotal: 0x%x\n",
72               mode->CrtcHTotal);
73    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcHSkew: 0x%x\n",
74               mode->CrtcHSkew);
75    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVDisplay: 0x%x\n",
76               mode->CrtcVDisplay);
77    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVBlankStart: 0x%x\n",
78               mode->CrtcVBlankStart);
79    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVSyncStart: 0x%x\n",
80               mode->CrtcVSyncStart);
81    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVSyncEnd: 0x%x\n",
82               mode->CrtcVSyncEnd);
83    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVBlankEnd: 0x%x\n",
84               mode->CrtcVBlankEnd);
85    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "CrtcVTotal: 0x%x\n",
86               mode->CrtcVTotal);
87
88}
89
90/*
91 * Sets IGA1 or IGA2 for palette LUT access.
92 * This function should be called before changing the
93 * contents of the palette.
94 */
95static void
96viaSetPaletteLUTAccess(ScrnInfoPtr pScrn, CARD8 displaySource)
97{
98    vgaHWPtr hwp = VGAHWPTR(pScrn);
99
100    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
101                        "Entered viaSetPaletteLUTAccess.\n"));
102
103    ViaSeqMask(hwp, 0x1A, displaySource, 0x01);
104    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
105                "Palette LUT Access: IGA%d\n",
106                (displaySource & 0x01) + 1);
107
108    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
109                        "Exiting viaSetPaletteLUTAccess.\n"));
110}
111
112/*
113 * Resets IGA1 hardware.
114 */
115static void
116viaIGA1HWReset(ScrnInfoPtr pScrn, CARD8 resetState)
117{
118    vgaHWPtr hwp = VGAHWPTR(pScrn);
119
120    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
121                        "Entered viaIGA1HWReset.\n"));
122
123    /* 3X5.17[7] - IGA1 HW Reset
124     *             0: Reset
125     *             1: Normal Operation */
126    ViaCrtcMask(hwp, 0x17, resetState << 7, 0x80);
127    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
128                "IGA1 HW Reset: %s\n",
129                (resetState & 0x01) ? "Off" : "On");
130
131    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
132                        "Exiting viaIGA1HWReset.\n"));
133}
134
135/*
136 * Controls IGA1 DPMS State.
137 */
138static void
139viaIGA1DPMSControl(ScrnInfoPtr pScrn, CARD8 dpmsControl)
140{
141    vgaHWPtr hwp = VGAHWPTR(pScrn);
142
143    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
144                        "Entered viaIGA1DPMSControl.\n"));
145
146    /* 3X5.36[5:4] - DPMS Control
147     *               00: On
148     *               01: Stand-by
149     *               10: Suspend
150     *               11: Off */
151    ViaCrtcMask(hwp, 0x36, dpmsControl << 4, 0x30);
152
153    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
154                        "Exiting viaIGA1DPMSControl.\n"));
155}
156
157/*
158 * Sets IGA1 color depth.
159 */
160static void
161viaIGA1SetColorDepth(ScrnInfoPtr pScrn, CARD8 bitsPerPixel)
162{
163    vgaHWPtr hwp = VGAHWPTR(pScrn);
164
165    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
166                        "Entered viaIGA1SetColorDepth.\n"));
167
168    /* Set the color depth for IGA1. */
169    switch (bitsPerPixel) {
170    case 8:
171        /* 3C5.15[4]   - Hi Color Mode Select
172         *               0: 555
173         *               1: 565
174         * 3C5.15[3:2] - Display Color Depth Select
175         *               00: 8bpp
176         *               01: 16bpp
177         *               10: 30bpp
178         *               11: 32bpp */
179        ViaSeqMask(hwp, 0x15, 0x00, 0x1C);
180        break;
181    case 16:
182        ViaSeqMask(hwp, 0x15, 0x14, 0x1C);
183        break;
184    case 24:
185    case 32:
186        ViaSeqMask(hwp, 0x15, 0x1C, 0x1C);
187        break;
188    default:
189        break;
190    }
191
192    if ((bitsPerPixel == 8)
193        || (bitsPerPixel == 16)
194        || (bitsPerPixel == 24)
195        || (bitsPerPixel == 32)) {
196
197        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
198                    "IGA1 Color Depth: %d bit\n",
199                    bitsPerPixel);
200    } else {
201        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
202                    "Unsupported IGA1 Color Depth: %d bit\n",
203                    bitsPerPixel);
204    }
205
206    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
207                        "Exiting viaIGA1SetColorDepth.\n"));
208}
209
210/*
211 * Sets IGA1 palette LUT resolution. (6-bit or 8-bit)
212 */
213static void
214viaIGA1SetPaletteLUTResolution(ScrnInfoPtr pScrn, CARD8 paletteLUT)
215{
216    vgaHWPtr hwp = VGAHWPTR(pScrn);
217
218    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
219                        "Entered viaIGA1SetPaletteLUTResolution.\n"));
220
221    /* Set the palette LUT resolution for IGA1. */
222    /* 3C5.15[7] - IGA1 6 / 8 Bit LUT
223     *             0: 6-bit
224     *             1: 8-bit */
225    ViaSeqMask(hwp, 0x15, paletteLUT << 7, 0x80);
226    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
227                "IGA1 Palette LUT Resolution: %s bit\n",
228                (paletteLUT & 0x01) ? "8" : "6");
229
230    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
231                        "Exiting viaIGA1SetPaletteLUTResolution.\n"));
232}
233
234/*
235 * Controls IGA1 gamma correction state.
236 */
237static void
238viaIGA1SetGamma(ScrnInfoPtr pScrn, CARD8 gammaCorrection)
239{
240    VIAPtr pVia = VIAPTR(pScrn);
241    vgaHWPtr hwp = VGAHWPTR(pScrn);
242
243    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
244                        "Entered viaIGA1SetGamma.\n"));
245
246    switch (pVia->Chipset) {
247    case VIA_CLE266:
248    case VIA_KM400:
249        /* 3C5.16[7] - IGA1 Gamma Correction
250         *             0: Disable
251         *             1: Enable */
252        ViaSeqMask(hwp, 0x16, gammaCorrection << 7, 0x80);
253        break;
254    default:
255        /* 3X5.33[7] - IGA1 Gamma Correction
256         *             0: Disable
257         *             1: Enable */
258        ViaCrtcMask(hwp, 0x33, gammaCorrection << 7, 0x80);
259        break;
260    }
261
262    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
263                "IGA1 Gamma Correction: %s\n",
264                (gammaCorrection & 0x01) ? "On" : "Off");
265
266    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
267                        "Exiting viaIGA1SetGamma.\n"));
268}
269
270static void
271viaIGA1InitHI(ScrnInfoPtr pScrn)
272{
273    VIAPtr pVia = VIAPTR(pScrn);
274
275    switch(pVia->Chipset) {
276    case VIA_PM800:
277    case VIA_CX700:
278    case VIA_P4M890:
279    case VIA_P4M900:
280    case VIA_VX800:
281    case VIA_VX855:
282    case VIA_VX900:
283        VIASETREG(PRIM_HI_TRANSCOLOR, 0x00000000);
284        VIASETREG(PRIM_HI_INVTCOLOR, 0x00FFFFFF);
285
286        /* Not setting up V327_HI_INVTCOLOR register contributes to
287         * an X Server boot time crash. */
288        VIASETREG(V327_HI_INVTCOLOR, 0x00FFFFFF);
289        VIASETREG(PRIM_HI_FIFO, 0x0D000D0F);
290        VIASETREG(PRIM_HI_CTRL, 0x36000004);
291        break;
292    default:
293        VIASETREG(HI_TRANSPARENT_COLOR, 0x00000000);
294        VIASETREG(HI_INVTCOLOR, 0x00FFFFFF);
295        VIASETREG(ALPHA_V3_PREFIFO_CONTROL, 0x000E0000);
296        VIASETREG(ALPHA_V3_FIFO_CONTROL, 0xE0F0000);
297        VIASETREG(HI_CONTROL, 0x76000004);
298        break;
299    }
300}
301
302static void
303viaIGA1SetHIStartingAddress(xf86CrtcPtr crtc)
304{
305
306    drmmode_crtc_private_ptr iga = crtc->driver_private;
307    ScrnInfoPtr pScrn = crtc->scrn;
308    VIAPtr pVia = VIAPTR(pScrn);
309
310    switch(pVia->Chipset) {
311    case VIA_PM800:
312    case VIA_CX700:
313    case VIA_P4M890:
314    case VIA_P4M900:
315    case VIA_VX800:
316    case VIA_VX855:
317    case VIA_VX900:
318        VIASETREG(PRIM_HI_FBOFFSET, iga->cursor_bo->offset);
319        break;
320    default:
321        /* Mono Cursor Display Path [bit31]: Primary */
322        VIASETREG(HI_FBOFFSET, iga->cursor_bo->offset);
323        break;
324    }
325}
326
327/*
328 * This function displays or hides IGA1 hardware icon (HI).
329 */
330static void
331viaIGA1DisplayHI(ScrnInfoPtr pScrn, Bool HI_Status)
332{
333    VIAPtr pVia = VIAPTR(pScrn);
334    CARD32 temp;
335
336    switch(pVia->Chipset) {
337    case VIA_PM800:
338    case VIA_CX700:
339    case VIA_P4M890:
340    case VIA_P4M900:
341    case VIA_VX800:
342    case VIA_VX855:
343    case VIA_VX900:
344        temp = VIAGETREG(PRIM_HI_CTRL);
345        temp &= 0xFFFFFFFE;
346        temp |= HI_Status ? 0x00000001 : 0x00000000;
347
348        /* PRIM_HI_CTRL[0] - Hardware Icon (HI) Enable */
349        VIASETREG(PRIM_HI_CTRL, temp);
350        break;
351    default:
352        temp = VIAGETREG(HI_CONTROL);
353        temp &= 0xFFFFFFFE;
354        temp |= HI_Status ? 0x00000001 : 0x00000000;
355
356        /* HI_CONTROL[0] - Hardware Icon (HI) Enable */
357        VIASETREG(HI_CONTROL, temp);
358        break;
359    }
360}
361
362static void
363viaIGA1SetHIDisplayLocation(ScrnInfoPtr pScrn,
364                            int x, unsigned int xoff,
365                            int y, unsigned int yoff)
366{
367    VIAPtr pVia = VIAPTR(pScrn);
368
369    switch(pVia->Chipset) {
370    case VIA_PM800:
371    case VIA_CX700:
372    case VIA_P4M890:
373    case VIA_P4M900:
374    case VIA_VX800:
375    case VIA_VX855:
376    case VIA_VX900:
377        VIASETREG(PRIM_HI_POSSTART,     ((x    << 16) | (y    & 0x07ff)));
378        VIASETREG(PRIM_HI_CENTEROFFSET, ((xoff << 16) | (yoff & 0x07ff)));
379        break;
380    default:
381        VIASETREG(HI_POSSTART,     ((x    << 16) | (y    & 0x07ff)));
382        VIASETREG(HI_CENTEROFFSET, ((xoff << 16) | (yoff & 0x07ff)));
383        break;
384    }
385}
386
387/*
388 * Resets IGA2 hardware.
389 */
390static void
391viaIGA2HWReset(ScrnInfoPtr pScrn, CARD8 resetState)
392{
393    vgaHWPtr hwp = VGAHWPTR(pScrn);
394
395    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
396                        "Entered viaIGA2HWReset.\n"));
397
398    /* 3X5.6A[6] - Second Display Channel Reset
399     *             0: Reset
400     *             1: Normal Operation */
401    ViaCrtcMask(hwp, 0x6A, resetState << 6, 0x40);
402    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
403                "IGA2 HW Reset: %s\n",
404                (resetState & 0x01) ? "Off" : "On");
405
406    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
407                        "Exiting viaIGA2HWReset.\n"));
408}
409
410/*
411 * Controls IGA2 display output on or off state.
412 */
413static void
414viaIGA2DisplayOutput(ScrnInfoPtr pScrn, Bool outputState)
415{
416    vgaHWPtr hwp = VGAHWPTR(pScrn);
417
418    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
419                        "Entered viaIGA2DisplayOutput.\n"));
420
421    /* 3X5.6B[2] - IGA2 Screen Off
422     *             0: Screen on
423     *             1: Screen off */
424    ViaCrtcMask(hwp, 0x6B, outputState ? 0x00 : 0x04, 0x04);
425    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
426                "IGA2 Display Output: %s\n",
427                outputState ? "On" : "Off");
428
429    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
430                        "Exiting viaIGA2DisplayOutput.\n"));
431}
432
433/*
434 * Controls IGA2 display channel state.
435 */
436void
437viaIGA2DisplayChannel(ScrnInfoPtr pScrn, Bool channelState)
438{
439    vgaHWPtr hwp = VGAHWPTR(pScrn);
440
441    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
442                        "Entered viaIGA2DisplayChannel.\n"));
443
444    /* 3X5.6A[7] - Second Display Channel Enable */
445    ViaCrtcMask(hwp, 0x6A, channelState << 7, 0x80);
446
447    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
448                "IGA2 Display Channel: %s\n",
449                channelState ? "On" : "Off");
450
451    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
452                        "Exiting viaIGA2DisplayChannel.\n"));
453}
454
455/*
456 * Sets IGA2 color depth.
457 */
458static void
459viaIGA2SetColorDepth(ScrnInfoPtr pScrn, CARD8 bitsPerPixel)
460{
461    vgaHWPtr hwp = VGAHWPTR(pScrn);
462
463    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
464                        "Entered viaIGA2SetColorDepth.\n"));
465
466    /* Set the color depth for IGA2. */
467    switch (pScrn->bitsPerPixel) {
468        case 8:
469            /* 3X5.67[7:6] - Display Color Depth Select
470             *               00: 8bpp
471             *               01: 16bpp
472             *               10: 30bpp
473             *               11: 32bpp */
474            ViaCrtcMask(hwp, 0x67, 0x00, 0xC0);
475            break;
476        case 16:
477            ViaCrtcMask(hwp, 0x67, 0x40, 0xC0);
478            break;
479        case 24:
480        case 32:
481            ViaCrtcMask(hwp, 0x67, 0xC0, 0xC0);
482            break;
483        default:
484            break;
485    }
486
487    if ((bitsPerPixel == 8)
488        || (bitsPerPixel == 16)
489        || (bitsPerPixel == 24)
490        || (bitsPerPixel == 32)) {
491
492        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
493                    "IGA2 Color Depth: %d bit\n",
494                    bitsPerPixel);
495    } else {
496        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
497                    "Unsupported IGA2 Color Depth: %d bit\n",
498                    bitsPerPixel);
499    }
500
501    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
502                        "Exiting viaIGA2SetColorDepth.\n"));
503}
504
505/*
506 * Sets IGA2 palette LUT resolution. (6-bit or 8-bit)
507 */
508static void
509viaIGA2SetPaletteLUTResolution(ScrnInfoPtr pScrn, CARD8 paletteLUT)
510{
511    vgaHWPtr hwp = VGAHWPTR(pScrn);
512
513    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
514                        "Entered viaIGA2SetPaletteLUTResolution.\n"));
515
516    /* Set the palette LUT resolution for IGA2. */
517    /* 3X5.6A[5] - IGA2 6 / 8 Bit LUT
518     *             0: 6-bit
519     *             1: 8-bit */
520    ViaCrtcMask(hwp, 0x6A, paletteLUT << 5, 0x20);
521    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
522                "IGA2 Palette LUT Resolution: %s bit\n",
523                (paletteLUT & 0x01) ? "8" : "6");
524
525    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
526                        "Exiting viaIGA2SetPaletteLUTResolution.\n"));
527}
528
529/*
530 * Controls IGA2 gamma correction state.
531 */
532static void
533viaIGA2SetGamma(ScrnInfoPtr pScrn, CARD8 gammaCorrection)
534{
535    vgaHWPtr hwp = VGAHWPTR(pScrn);
536
537    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
538                        "Entered viaIGA2SetGamma.\n"));
539
540    /* 3X5.6A[1] - IGA2 Gamma Correction
541     *             0: Disable
542     *             1: Enable */
543    ViaCrtcMask(hwp, 0x6A, gammaCorrection << 1, 0x02);
544    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
545                "IGA2 Gamma Correction: %s\n",
546                (gammaCorrection & 0x01) ? "On" : "Off");
547
548    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
549                        "Exiting viaIGA2SetGamma.\n"));
550}
551
552static void
553viaIGA2InitHI(ScrnInfoPtr pScrn)
554{
555    VIAPtr pVia = VIAPTR(pScrn);
556
557    switch(pVia->Chipset) {
558    case VIA_PM800:
559    case VIA_CX700:
560    case VIA_P4M890:
561    case VIA_P4M900:
562    case VIA_VX800:
563    case VIA_VX855:
564    case VIA_VX900:
565        VIASETREG(HI_TRANSPARENT_COLOR, 0x00000000);
566        VIASETREG(HI_INVTCOLOR, 0x00FFFFFF);
567        VIASETREG(ALPHA_V3_PREFIFO_CONTROL, 0x000E0000);
568        VIASETREG(ALPHA_V3_FIFO_CONTROL, 0x0E0F0000);
569        VIASETREG(HI_CONTROL, 0xB6000004);
570        break;
571    default:
572        VIASETREG(HI_TRANSPARENT_COLOR, 0x00000000);
573        VIASETREG(HI_INVTCOLOR, 0X00FFFFFF);
574        VIASETREG(ALPHA_V3_PREFIFO_CONTROL, 0x000E0000);
575        VIASETREG(ALPHA_V3_FIFO_CONTROL, 0xE0F0000);
576        VIASETREG(HI_CONTROL, 0xF6000004);
577        break;
578    }
579}
580
581static void
582viaIGA2SetHIStartingAddress(xf86CrtcPtr crtc)
583{
584    drmmode_crtc_private_ptr iga = crtc->driver_private;
585    ScrnInfoPtr pScrn = crtc->scrn;
586    VIAPtr pVia = VIAPTR(pScrn);
587
588    VIASETREG(HI_FBOFFSET, iga->cursor_bo->offset);
589}
590
591/*
592 * This function displays or hides IGA2 hardware icon (HI).
593 */
594static void
595viaIGA2DisplayHI(ScrnInfoPtr pScrn, Bool HI_Status)
596{
597    VIAPtr pVia = VIAPTR(pScrn);
598    CARD32 temp;
599
600    switch(pVia->Chipset) {
601    case VIA_PM800:
602    case VIA_CX700:
603    case VIA_P4M890:
604    case VIA_P4M900:
605    case VIA_VX800:
606    case VIA_VX855:
607    case VIA_VX900:
608        temp = VIAGETREG(HI_CONTROL);
609        temp &= 0xFFFFFFFE;
610        temp |= HI_Status ? 0x00000001 : 0x00000000;
611
612        /* HI_CONTROL[0] - Hardware Icon (HI) Enable */
613        VIASETREG(HI_CONTROL, temp);
614        break;
615    default:
616        temp = VIAGETREG(HI_CONTROL);
617        temp &= 0xFFFFFFFE;
618        temp |= HI_Status ? 0x00000001 : 0x00000000;
619
620        /* HI_CONTROL[0] - Hardware Icon (HI) Enable */
621        VIASETREG(HI_CONTROL, temp);
622        break;
623    }
624}
625
626static void
627viaIGA2SetHIDisplayLocation(ScrnInfoPtr pScrn,
628                            int x, unsigned int xoff,
629                            int y, unsigned int yoff)
630{
631    VIAPtr pVia = VIAPTR(pScrn);
632
633    switch(pVia->Chipset) {
634    case VIA_PM800:
635    case VIA_CX700:
636    case VIA_P4M890:
637    case VIA_P4M900:
638    case VIA_VX800:
639    case VIA_VX855:
640    case VIA_VX900:
641        VIASETREG(HI_POSSTART,     ((x    << 16) | (y    & 0x07FF)));
642        VIASETREG(HI_CENTEROFFSET, ((xoff << 16) | (yoff & 0x07FF)));
643        break;
644    default:
645        VIASETREG(HI_POSSTART,     ((x    << 16) | (y    & 0x07FF)));
646        VIASETREG(HI_CENTEROFFSET, ((xoff << 16) | (yoff & 0x07FF)));
647        break;
648    }
649}
650
651/*
652 * Initial settings for displays.
653 */
654void
655viaDisplayInit(ScrnInfoPtr pScrn)
656{
657    VIAPtr pVia = VIAPTR(pScrn);
658    vgaHWPtr hwp = VGAHWPTR(pScrn);
659
660    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
661                        "Entered viaDisplayInit.\n"));
662
663    ViaCrtcMask(hwp, 0x6A, 0x00, 0x3D);
664    hwp->writeCrtc(hwp, 0x6B, 0x00);
665    hwp->writeCrtc(hwp, 0x6C, 0x00);
666    hwp->writeCrtc(hwp, 0x79, 0x00);
667
668    /* (IGA1 Timing Plus 2, added in VT3259 A3 or later) */
669    if (pVia->Chipset != VIA_CLE266 && pVia->Chipset != VIA_KM400)
670        ViaCrtcMask(hwp, 0x47, 0x00, 0xC8);
671
672    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
673                        "Exiting viaDisplayInit.\n"));
674}
675
676/*
677 * Sets the primary or secondary display stream on internal TMDS.
678 */
679void
680ViaDisplaySetStreamOnDFP(ScrnInfoPtr pScrn, Bool primary)
681{
682    vgaHWPtr hwp = VGAHWPTR(pScrn);
683
684    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisplaySetStreamOnDFP\n"));
685
686    if (primary)
687        ViaCrtcMask(hwp, 0x99, 0x00, 0x10);
688    else
689        ViaCrtcMask(hwp, 0x99, 0x10, 0x10);
690}
691
692void
693VIALoadRgbLut(ScrnInfoPtr pScrn, int start, int numColors, LOCO *colors)
694{
695    vgaHWPtr hwp = VGAHWPTR(pScrn);
696    int i, j;
697
698    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIALoadRgbLut\n"));
699
700    hwp->enablePalette(hwp);
701    hwp->writeDacMask(hwp, 0xFF);
702
703    /* We need the same palette contents for both 16 and 24 bits, but X doesn't
704     * play: X's colormap handling is hopelessly intertwined with almost every
705     * X subsystem.  So we just space out RGB values over the 256*3. */
706
707    switch (pScrn->bitsPerPixel) {
708        case 15:
709            for (i = start; i < numColors; i++) {
710                hwp->writeDacWriteAddr(hwp, i * 4);
711                for (j = 0; j < 4; j++) {
712                    hwp->writeDacData(hwp, colors[i / 2].red);
713                    hwp->writeDacData(hwp, colors[i].green);
714                    hwp->writeDacData(hwp, colors[i / 2].blue);
715                }
716            }
717            break;
718        case 8:
719        case 16:
720        case 24:
721        case 32:
722            for (i = start; i < numColors; i++) {
723                hwp->writeDacWriteAddr(hwp, i);
724                hwp->writeDacData(hwp, colors[i].red);
725                hwp->writeDacData(hwp, colors[i].green);
726                hwp->writeDacData(hwp, colors[i].blue);
727            }
728            break;
729        default:
730            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
731                       "Unsupported bitdepth: %d\n", pScrn->bitsPerPixel);
732            break;
733    }
734    hwp->disablePalette(hwp);
735}
736
737void
738ViaGammaDisable(ScrnInfoPtr pScrn)
739{
740    VIAPtr pVia = VIAPTR(pScrn);
741    vgaHWPtr hwp = VGAHWPTR(pScrn);
742
743    switch (pVia->Chipset) {
744        case VIA_CLE266:
745        case VIA_KM400:
746            ViaSeqMask(hwp, 0x16, 0x00, 0x80);
747            break;
748        default:
749            ViaCrtcMask(hwp, 0x33, 0x00, 0x80);
750            break;
751    }
752
753    /* Disable gamma on secondary */
754    /* This is needed or the hardware will lockup */
755    ViaSeqMask(hwp, 0x1A, 0x00, 0x01);
756    ViaCrtcMask(hwp, 0x6A, 0x00, 0x02);
757    switch (pVia->Chipset) {
758        case VIA_CLE266:
759        case VIA_KM400:
760        case VIA_K8M800:
761        case VIA_PM800:
762            break;
763        default:
764            ViaCrtcMask(hwp, 0x6A, 0x00, 0x20);
765            break;
766    }
767}
768
769/*
770 * Initialize common IGA (Integrated Graphics Accelerator) registers.
771 */
772void
773viaIGAInitCommon(ScrnInfoPtr pScrn)
774{
775    vgaHWPtr hwp = VGAHWPTR(pScrn);
776    VIAPtr pVia = VIAPTR(pScrn);
777    CARD8 i;
778#ifdef HAVE_DEBUG
779    CARD8 temp;
780#endif
781
782    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
783                        "Entered viaIGAInitCommon.\n"));
784
785    temp = hwp->readEnable(hwp);
786    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
787                        "Enable Register: 0x%02X\n", temp));
788    hwp->writeEnable(hwp, temp | 0x01);
789
790    temp = hwp->readMiscOut(hwp);
791    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
792                        "Misc. Register: 0x%02X\n", temp));
793    hwp->writeMiscOut(hwp, temp | 0x22);
794
795    temp = hwp->readEnable(hwp);
796    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
797                        "Enable Register: 0x%02X\n", temp));
798    temp = hwp->readMiscOut(hwp);
799    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
800                        "Misc. Register: 0x%02X\n", temp));
801
802
803    /* Sequencer Registers */
804    ViaSeqMask(hwp, 0x00, 0x03, 0x03);
805    ViaSeqMask(hwp, 0x01, 0x01, 0x35);
806    ViaSeqMask(hwp, 0x02, 0x0F, 0x0F);
807    ViaSeqMask(hwp, 0x03, 0x00, 0x3F);
808    ViaSeqMask(hwp, 0x04, 0x0E, 0x0E);
809
810
811    /* Graphics Registers */
812    hwp->writeGr(hwp, 0x00, 0x00);
813    hwp->writeGr(hwp, 0x01, 0x00);
814    hwp->writeGr(hwp, 0x02, 0x00);
815    hwp->writeGr(hwp, 0x03, 0x00);
816    hwp->writeGr(hwp, 0x04, 0x00);
817    hwp->writeGr(hwp, 0x05, 0x40);
818    hwp->writeGr(hwp, 0x06, 0x05);
819    hwp->writeGr(hwp, 0x07, 0x0F);
820    hwp->writeGr(hwp, 0x08, 0xFF);
821
822
823    /* Attribute Registers */
824    for (i = 0; i <= 15; i++) {
825        hwp->writeAttr(hwp, i, i);
826    }
827
828    hwp->writeAttr(hwp, 0x10, 0x41);
829    hwp->writeAttr(hwp, 0x11, 0xFF);
830    hwp->writeAttr(hwp, 0x12, 0x0F);
831    hwp->writeAttr(hwp, 0x13, 0x00);
832    hwp->writeAttr(hwp, 0x14, 0x00);
833
834
835    /* Unlock VIA Technologies extended VGA registers. */
836    /* 3C5.10[0] - Unlock Accessing of I/O Space
837     *             0: Disable
838     *             1: Enable */
839    ViaSeqMask(hwp, 0x10, 0x01, 0x01);
840
841    switch (pVia->Chipset) {
842    case VIA_CLE266:
843    case VIA_KM400:
844    case VIA_K8M800:
845    case VIA_PM800:
846    case VIA_P4M800PRO:
847    case VIA_CX700:
848    case VIA_P4M890:
849    case VIA_K8M890:
850    case VIA_P4M900:
851    case VIA_VX800:
852        /* 3X5.47[7] - IGA1 Timing Plus 2 VCK
853         * 3X5.47[6] - IGA1 Timing Plus 4 VCK
854         * 3X5.47[5] - Peep at the PCI-bus
855         *             0: Disable
856         *             1: Enable
857         * 3X5.47[4] - Reserved
858         * 3X5.47[3] - IGA1 Timing Plus 6 VCK
859         * 3X5.47[2] - DACOFF Backdoor Register
860         * 3X5.47[1] - LCD Simultaneous Mode Backdoor Register for
861         *             8/9 Dot Clocks
862         * 3X5.47[0] - LCD Simultaneous Mode Backdoor Register for
863         *             Clock Select and CRTC Register Protect */
864        ViaCrtcMask(hwp, 0x47, 0x00, 0x01);
865        break;
866    case VIA_VX855:
867    case VIA_VX900:
868        /* 3X5.47[7] - IGA1 Timing Plus 2 VCK
869         * 3X5.47[6] - IGA1 Timing Plus 4 VCK
870         * 3X5.47[5] - Peep at the PCI-bus
871         *             0: Disable
872         *             1: Enable
873         * 3X5.47[4] - CRT Timing Register Protect
874         * 3X5.47[3] - IGA1 Timing Plus 6 VCK
875         * 3X5.47[2] - DACOFF Backdoor Register
876         * 3X5.47[1] - LCD Simultaneous Mode Backdoor Register for
877         *             8/9 Dot Clocks
878         * 3X5.47[0] - LCD Simultaneous Mode Backdoor Register for
879         *             Clock Select */
880        ViaCrtcMask(hwp, 0x47, 0x00, 0x10);
881        break;
882    default:
883        break;
884    }
885
886#ifdef HAVE_DEBUG
887    temp = hwp->readSeq(hwp, 0x15);
888    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
889                        "SR15: 0x%02X\n", temp));
890    temp = hwp->readSeq(hwp, 0x19);
891    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
892                        "SR19: 0x%02X\n", temp));
893    temp = hwp->readSeq(hwp, 0x1A);
894    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
895                        "SR1A: 0x%02X\n", temp));
896    temp = hwp->readSeq(hwp, 0x1E);
897    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
898                        "SR1E: 0x%02X\n", temp));
899    temp = hwp->readSeq(hwp, 0x2D);
900    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
901                        "SR2D: 0x%02X\n", temp));
902    temp = hwp->readSeq(hwp, 0x2E);
903    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
904                        "SR2E: 0x%02X\n", temp));
905    temp = hwp->readSeq(hwp, 0x3F);
906    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
907                        "SR3F: 0x%02X\n", temp));
908    temp = hwp->readCrtc(hwp, 0x36);
909    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
910                        "CR36: 0x%02X\n", temp));
911    temp = hwp->readCrtc(hwp, 0x3B);
912    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
913                        "CR3B: 0x%02X\n", temp));
914    temp = hwp->readCrtc(hwp, 0x3C);
915    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
916                        "CR3C: 0x%02X\n", temp));
917    temp = hwp->readCrtc(hwp, 0x3D);
918    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
919                        "CR3D: 0x%02X\n", temp));
920    temp = hwp->readCrtc(hwp, 0x3E);
921    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
922                        "CR3E: 0x%02X\n", temp));
923    temp = hwp->readCrtc(hwp, 0x3F);
924    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
925                        "CR3F: 0x%02X\n", temp));
926    temp = hwp->readCrtc(hwp, 0x47);
927    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
928                        "CR47: 0x%02X\n", temp));
929    temp = hwp->readCrtc(hwp, 0x6B);
930    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
931                        "CR6B: 0x%02X\n", temp));
932
933    if (pVia->Chipset == VIA_CLE266) {
934        temp = hwp->readCrtc(hwp, 0x6C);
935        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
936                            "CR6C: 0x%02X\n", temp));
937    }
938
939#endif
940
941
942    /* VIA Technologies Chrome Extended Graphics Registers */
943    ViaGrMask(hwp, 0x20, 0, 0xFF);
944    ViaGrMask(hwp, 0x21, 0, 0xFF);
945    ViaGrMask(hwp, 0x22, 0, 0xFF);
946
947
948    /* Be careful with 3C5.15[5] - Wrap Around Disable.
949     * It must be set to 1 for correct operation. */
950    /* 3C5.15[7]   - 8/6 Bits LUT
951     *               0: 6-bit
952     *               1: 8-bit
953     * 3C5.15[6]   - Text Column Control
954     *               0: 80 column
955     *               1: 132 column
956     * 3C5.15[5]   - Wrap Around Disable
957     *               0: Disable (For Mode 0-13)
958     *               1: Enable
959     * 3C5.15[4]   - Hi Color Mode Select
960     *               0: 555
961     *               1: 565
962     * 3C5.15[3:2] - Display Color Depth Select
963     *               00: 8bpp
964     *               01: 16bpp
965     *               10: 30bpp
966     *               11: 32bpp
967     * 3C5.15[1]   - Extended Display Mode Enable
968     *               0: Disable
969     *               1: Enable
970     * 3C5.15[0]   - Reserved */
971    ViaSeqMask(hwp, 0x15, 0x22, 0x62);
972
973    /* 3C5.19[7] - Reserved
974     * 3C5.19[6] - MIU/AGP Interface Clock Control
975     *             0: Clocks always on
976     *             1: Enable clock gating
977     * 3C5.19[5] - P-Arbiter Interface Clock Control
978     *             0: Clocks always on
979     *             1: Enable clock gating
980     * 3C5.19[4] - AGP Interface Clock Control
981     *             0: Clocks always on
982     *             1: Enable clock gating
983     * 3C5.19[3] - Typical Arbiter Interface Clock Control
984     *             0: Clocks always on
985     *             1: Enable clock gating
986     * 3C5.19[2] - MC Interface Clock Control
987     *             0: Clocks always on
988     *             1: Enable clock gating
989     * 3C5.19[1] - Display Interface Clock Control
990     *             0: Clocks always on
991     *             1: Enable clock gating
992     * 3C5.19[0] - CPU Interface Clock Control
993     *             0: Clocks always on
994     *             1: Enable clock gating */
995    ViaSeqMask(hwp, 0x19, 0x7F, 0x7F);
996
997    /* 3C5.1A[7] - Read Cache Enable
998     *             0: Disable
999     *             1: Enable
1000     * 3C5.1A[6] - Software Reset
1001     *             0: Default value
1002     *             1: Reset
1003     * 3C5.1A[5] - DVI Sense
1004     *             0: No connect
1005     *             1: Connected
1006     * 3C5.1A[4] - Second DVI Sense
1007     *             0: No connect
1008     *             1: Connected
1009     * 3C5.1A[3] - Extended Mode Memory Access Enable
1010     *             0: Disable
1011     *             1: Enable
1012     * 3C5.1A[2] - PCI Burst Write Wait State Select
1013     *             0: 0 Wait state
1014     *             1: 1 Wait state
1015     * 3C5.1A[1] - Reserved
1016     * 3C5.1A[0] - LUT Shadow Access
1017     *             0: 3C6/3C7/3C8/3C9 addresses map to
1018     *                Primary Display’s LUT
1019     *             1: 3C6/3C7/3C8/3C9 addresses map to
1020     *                Secondary Display’s LUT */
1021    ViaSeqMask(hwp, 0x1A, 0x88, 0xC8);
1022
1023    /* 3C5.1E[3]   - Spread Spectrum On/Off
1024     *               0: Off
1025     *               1: On
1026     * 3C5.1E[1]   - Replace ECK by MCK
1027     *               For BIST purpose.
1028     * 3C5.1E[0]   - On/Off ROC ECK
1029     *               0: Off
1030     *               1: On */
1031    ViaSeqMask(hwp, 0x1E, 0x01, 0x09);
1032
1033    /* 3C5.2D[7:6] - E3_ECK_N Selection
1034     *               00: E3_ECK_N
1035     *               01: E3_ECK
1036     *               10: delayed E3_ECK_N
1037     *               11: delayed E3_ECK
1038     * 3C5.2D[5:4] - VCK (Primary Display Clock) PLL Power Control
1039     *               0x: PLL power-off
1040     *               10: PLL always on
1041     *               11: PLL on/off according to the PMS
1042     * 3C5.2D[3:2] - LCK (Secondary Display Clock) PLL Power Control
1043     *               0x: PLL power-off
1044     *               10: PLL always on
1045     *               11: PLL on/off according to the PMS
1046     * 3C5.2D[1:0] - ECK (Engine Clock) PLL Power Control
1047     *               0x: PLL power-off
1048     *               10: PLL always on
1049     *               11: PLL on/off according to the PMS */
1050    ViaSeqMask(hwp, 0x2D, 0x03, 0xC3);
1051
1052    /* In Wyse X class mobile thin client, it was observed that setting
1053     * SR2E[3:2] (3C5.2E[3:2]; PCI Master / DMA) to 0b11 (clock on / off
1054     * according to the engine IDLE status) causes an X.Org Server boot
1055     * failure. Setting this register to 0b10 (clock always on) corrects
1056     * the problem. */
1057    /* 3C5.2E[7:6] - Capturer (Gated Clock <ECK>)
1058     *               0x: Clock off
1059     *               10: Clock always on
1060     *               11: Clock on/off according to the engine IDLE status
1061     * 3C5.2E[5:4] - Video Processor (Gated Clock <ECK>)
1062     *               0x: Clock off
1063     *               10: Clock always on
1064     *               11: Clock on/off according to the engine IDLE status
1065     * 3C5.2E[3:2] - PCI Master/DMA (Gated Clock <ECK/CPUCK>)
1066     *               0x: Clock off
1067     *               10: Clock always on
1068     *               11: Clock on/off according to the engine IDLE status
1069     * 3C5.2E[1:0] - Video Playback Engine (V3/V4 Gated Clock <VCK>)
1070     *               0x: Clock off
1071     *               10: Clock always on
1072     *               11: Clock on/off according to the engine IDLE status */
1073    ViaSeqMask(hwp, 0x2E, 0xFB, 0xFF);
1074
1075    /* 3C5.3F[7:6] - CR Clock Control (Gated Clock <ECK>)
1076     *               0x: Clock off
1077     *               10: Clock always on
1078     *               11: Clock on/off according to the engine IDLE status
1079     * 3C5.3F[5:4] - 3D Clock Control (Gated Clock <ECK>)
1080     *               0x: Clock off
1081     *               10: Clock always on
1082     *               11: Clock on/off according to the engine IDLE status
1083     * 3C5.3F[3:2] - 2D Clock Control (Gated Clock <ECK/CPUCK>)
1084     *               0x: Clock off
1085     *               10: Clock always on
1086     *               11: Clock on/off according to the engine IDLE status
1087     * 3C5.3F[1:0] - Video Clock Control (Gated Clock <ECK>)
1088     *               0x: Clock off
1089     *               10: Clock always on
1090     *               11: Clock on/off according to each engine IDLE status */
1091    ViaSeqMask(hwp, 0x3F, 0xFF, 0xFF);
1092
1093    /* 3X5.36[7]   - DPMS VSYNC Output
1094     * 3X5.36[6]   - DPMS HSYNC Output
1095     * 3X5.36[5:4] - DPMS Control
1096     *               00: On
1097     *               01: Stand-by
1098     *               10: Suspend
1099     *               11: Off
1100     *               When the DPMS state is off, both HSYNC and VSYNC
1101     *               are grounded, saving monitor power consumption.
1102     * 3X5.36[3]   - Horizontal Total Bit [8]
1103     * 3X5.36[2:1] - Reserved
1104     * 3X5.36[0]   - PCI Power Management Control
1105     *               0: Disable
1106     *               1: Enable */
1107    ViaCrtcMask(hwp, 0x36, 0x01, 0x01);
1108
1109    /* 3X5.3B through 3X5.3F are scratch pad registers. */
1110    ViaCrtcMask(hwp, 0x3B, pVia->originalCR3B, 0xFF);
1111    ViaCrtcMask(hwp, 0x3C, pVia->originalCR3C, 0xFF);
1112    ViaCrtcMask(hwp, 0x3D, pVia->originalCR3D, 0xFF);
1113    ViaCrtcMask(hwp, 0x3E, pVia->originalCR3E, 0xFF);
1114    ViaCrtcMask(hwp, 0x3F, pVia->originalCR3F, 0xFF);
1115
1116    /* 3X5.47[5] - Peep at the PCI-bus
1117     *             0: Disable
1118     *             1: Enable
1119     * 3X5.47[1] - LCD Simultaneous Mode Backdoor Register for
1120     *             8/9 Dot Clocks
1121     * 3X5.47[0] - LCD Simultaneous Mode Backdoor Register for
1122     *             Clock Select and CRTC Register Protect */
1123    ViaCrtcMask(hwp, 0x47, 0x00, 0x23);
1124
1125    /* 3X5.6B[3] - Simultaneous Display Enable
1126     *             0: Disable
1127     *             1: Enable */
1128    ViaCrtcMask(hwp, 0x6B, 0x00, 0x08);
1129
1130    /* CLE266 only. */
1131    if (pVia->Chipset == VIA_CLE266) {
1132        /* The following register fields are for CLE266 only. */
1133        /* 3X5.6C - Digital Interface Port 0 (DIP0) Control
1134         * 3X5.6C[7]   - DIP0 Source
1135         *               0: IGA1
1136         *               1: IGA2
1137         * 3X5.6C[4:2] - Appears to be related to DIP0 signal polarity
1138         *               control. Used by CLE266A2 to workaround a bug when
1139         *               it is utilizing an external TV encoder.
1140         * 3X5.6C[1]   - Appears to be utilized when CLE266 is utilizing an
1141         *               external TV encoder.
1142         * 3X5.6C[0]   - Appears to be a bit to control internal / external
1143         *               clock source or whether or not the VCK (IGA1 clock
1144         *               source) comes from VCK PLL or from an external
1145         *               source. This bit should be set to 1 when TV encoder
1146         *               is in use. */
1147        ViaCrtcMask(hwp, 0x6C, 0x00, 0x01);
1148    }
1149
1150    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1151                        "Exiting viaIGAInitCommon.\n"));
1152}
1153
1154/*
1155 * Initialize IGA1 (Integrated Graphics Accelerator) registers.
1156 */
1157void
1158viaIGA1Init(ScrnInfoPtr pScrn)
1159{
1160    vgaHWPtr hwp = VGAHWPTR(pScrn);
1161    VIAPtr pVia = VIAPTR(pScrn);
1162#ifdef HAVE_DEBUG
1163    CARD8 temp;
1164#endif
1165
1166    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1167                        "Entered viaIGA1Init.\n"));
1168
1169#ifdef HAVE_DEBUG
1170    temp = hwp->readSeq(hwp, 0x1B);
1171    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1172                        "SR1B: 0x%02X\n", temp));
1173    temp = hwp->readSeq(hwp, 0x2D);
1174    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1175                        "SR2D: 0x%02X\n", temp));
1176    temp = hwp->readCrtc(hwp, 0x32);
1177    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1178                        "CR32: 0x%02X\n", temp));
1179    temp = hwp->readCrtc(hwp, 0x33);
1180    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1181                        "CR33: 0x%02X\n", temp));
1182
1183    /* For UniChrome Pro and Chrome9. */
1184    if ((pVia->Chipset != VIA_CLE266)
1185        && (pVia->Chipset != VIA_KM400)) {
1186        temp = hwp->readCrtc(hwp, 0x47);
1187        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1188                            "CR47: 0x%02X\n", temp));
1189    }
1190
1191    temp = hwp->readCrtc(hwp, 0x6B);
1192    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1193                        "CR6B: 0x%02X\n", temp));
1194
1195    /* For UniChrome Pro and Chrome9. */
1196    if ((pVia->Chipset != VIA_CLE266)
1197        && (pVia->Chipset != VIA_KM400)) {
1198        temp = hwp->readCrtc(hwp, 0x6C);
1199        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1200                            "CR6C: 0x%02X\n", temp));
1201    }
1202
1203#endif
1204
1205    /* 3C5.1B[7:6] - Secondary Display Engine (Gated Clock <LCK>)
1206     *               0x: Clock always off
1207     *               10: Clock always on
1208     *               11: Clock on/off according to the
1209     *                   Power Management Status (PMS)
1210     * 3C5.1B[5:4] - Primary Display Engine (Gated Clock <VCK>)
1211     *               0x: Clock always off
1212     *               10: Clock always on
1213     *               11: Clock on/off according to the PMS
1214     * 3C5.1B[3:1] - Reserved
1215     * 3C5.1B[0]   - Primary Display’s LUT On/Off
1216     *               0: On
1217     *               1: Off */
1218    ViaSeqMask(hwp, 0x1B, 0x30, 0x31);
1219
1220    /* 3C5.2D[7:6] - E3_ECK_N Selection
1221     *               00: E3_ECK_N
1222     *               01: E3_ECK
1223     *               10: delayed E3_ECK_N
1224     *               11: delayed E3_ECK
1225     * 3C5.2D[5:4] - VCK (Primary Display Clock) PLL Power Control
1226     *               0x: PLL power-off
1227     *               10: PLL always on
1228     *               11: PLL on/off according to the PMS
1229     * 3C5.2D[3:2] - LCK (Secondary Display Clock) PLL Power Control
1230     *               0x: PLL power-off
1231     *               10: PLL always on
1232     *               11: PLL on/off according to the PMS
1233     * 3C5.2D[1:0] - ECK (Engine Clock) PLL Power Control
1234     *               0x: PLL power-off
1235     *               10: PLL always on
1236     *               11: PLL on/off according to the PMS */
1237    ViaSeqMask(hwp, 0x2D, 0x30, 0x30);
1238
1239    /* 3X5.32[7:5] - HSYNC Delay Number by VCLK
1240     *               000: No delay
1241     *               001: Delay + 4 VCKs
1242     *               010: Delay + 8 VCKs
1243     *               011: Delay + 12 VCKs
1244     *               100: Delay + 16 VCKs
1245     *               101: Delay + 20 VCKs
1246     *               Others: Undefined
1247     * 3X5.32[4]   - Reserved
1248     * 3X5.32[3]   - CRT SYNC Driving Selection
1249     *               0: Low
1250     *               1: High
1251     * 3X5.32[2]   - Display End Blanking Enable
1252     *               0: Disable
1253     *               1: Enable
1254     * 3X5.32[1]   - Digital Video Port (DVP) Gamma Correction
1255     *               If the gamma correction of primary display is
1256     *               turned on, the gamma correction in DVP can be
1257     *               enabled / disabled by this bit.
1258     *               0: Disable
1259     *               1: Enable
1260     * 3X5.32[0]   - Real-Time Flipping
1261     *               0: Flip by the frame
1262     *               1: Flip by each scan line */
1263    ViaCrtcMask(hwp, 0x32, 0x04, 0xEF);
1264
1265    /* Keep interlace mode off.
1266     * No shift for HSYNC.*/
1267    /* 3X5.33[7]   - Primary Display Gamma Correction
1268     *               0: Disable
1269     *               1: Enable
1270     * 3X5.33[6]   - Primary Display Interlace Mode
1271     *               0: Disable
1272     *               1: Enable
1273     * 3X5.33[5]   - Horizontal Blanking End Bit [6]
1274     * 3X5.33[4]   - Horizontal Synchronization Start Bit [8]
1275     * 3X5.33[3]   - Prefetch Mode
1276     *               0: Disable
1277     *               1: Enable
1278     * 3X5.33[2:0] - The Value will Shift the HSYNC to be Early than Planned
1279     *               000: Shift to early time by 3 characters
1280     *                    (VGA mode suggested value; default value)
1281     *               001: Shift to early time by 4 characters
1282     *               010: Shift to early time by 5 characters
1283     *               011: Shift to early time by 6 characters
1284     *               100: Shift to early time by 7 characters
1285     *               101: Shift to early time by 0 character
1286     *                    (Non-VGA mode suggested value)
1287     *               110: Shift to early time by 1 character
1288     *               111: Shift to early time by 2 characters */
1289    ViaCrtcMask(hwp, 0x33, 0x05, 0xCF);
1290
1291    /* For UniChrome Pro and Chrome9. */
1292    if ((pVia->Chipset != VIA_CLE266)
1293        && (pVia->Chipset != VIA_KM400)) {
1294        /* 3X5.47[7] - IGA1 Timing Plus 2 VCK
1295         * 3X5.47[6] - IGA1 Timing Plus 4 VCK
1296         * 3X5.47[5] - Peep at the PCI-bus
1297         *             0: Disable
1298         *             1: Enable
1299         * 3X5.47[4] - Reserved
1300         * 3X5.47[3] - IGA1 Timing Plus 6 VCK
1301         * 3X5.47[2] - DACOFF Backdoor Register
1302         * 3X5.47[1] - LCD Simultaneous Mode Backdoor Register for
1303         *             8/9 Dot Clocks
1304         * 3X5.47[0] - LCD Simultaneous Mode Backdoor Register for
1305         *             Clock Select and CRTC Register Protect */
1306        ViaCrtcMask(hwp, 0x47, 0x00, 0xCC);
1307    }
1308
1309    /* TV out uses division by 2 mode.
1310     * Other devices like analog (VGA), DVI, flat panel, etc.,
1311     * use normal mode. */
1312    /* 3X5.6B[7:6] - First Display Channel Clock Mode Selection
1313     *               0x: Normal
1314     *               1x: Division by 2 */
1315    ViaCrtcMask(hwp, 0x6B, 0x00, 0xC0);
1316
1317    /* For UniChrome Pro and Chrome9. */
1318    if ((pVia->Chipset != VIA_CLE266)
1319        && (pVia->Chipset != VIA_KM400)) {
1320        /* The following register fields are for UniChrome Pro and Chrome9. */
1321        /* 3X5.6C[7:5] - VCK PLL Reference Clock Source Selection
1322         *               000: From XI pin
1323         *               001: From TVXI
1324         *               01x: From TVPLL
1325         *               100: DVP0TVCLKR
1326         *               101: DVP1TVCLKR
1327         *               110: CAP0 Clock
1328         *               111: CAP1 Clock
1329         * 3X5.6C[4]   - VCK Source Selection
1330         *               0: VCK PLL output clock
1331         *               1: VCK PLL reference clock */
1332        ViaCrtcMask(hwp, 0x6C, 0x00, 0xF0);
1333    }
1334
1335    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1336                        "Exiting viaIGA1Init.\n"));
1337}
1338
1339void
1340viaIGA1SetFBStartingAddress(xf86CrtcPtr crtc, int x, int y)
1341{
1342    ScrnInfoPtr pScrn = crtc->scrn;
1343    VIAPtr pVia = VIAPTR(pScrn);
1344    vgaHWPtr hwp = VGAHWPTR(pScrn);
1345    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
1346    drmmode_ptr drmmode = drmmode_crtc->drmmode;
1347    CARD32 Base;
1348    CARD8 cr0c, cr0d, cr34, cr48;
1349
1350    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1351                        "Entered viaIGA1SetFBStartingAddress.\n"));
1352
1353    Base = (y * pScrn->displayWidth + x) * (pScrn->bitsPerPixel / 8);
1354    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1355                        "Base Address: 0x%"PRIx32"x\n",
1356                        (uint32_t)Base));
1357    Base = (Base + drmmode->front_bo->offset) >> 1;
1358    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1359                "DRI Base Address: 0x%"PRIx32"\n",
1360                (uint32_t)Base);
1361
1362    hwp->writeCrtc(hwp, 0x0D, Base & 0xFF);
1363    hwp->writeCrtc(hwp, 0x0C, (Base & 0xFF00) >> 8);
1364
1365    if (!(pVia->Chipset == VIA_CLE266 && CLE266_REV_IS_AX(pVia->ChipRev))) {
1366        ViaCrtcMask(hwp, 0x48, Base >> 24, 0x1F);
1367    }
1368
1369    /* CR34 are fire bits. Must be written after CR0C, CR0D, and CR48. */
1370    hwp->writeCrtc(hwp, 0x34, (Base & 0xFF0000) >> 16);
1371
1372#ifdef HAVE_DEBUG
1373    cr0d = hwp->readCrtc(hwp, 0x0D);
1374    cr0c = hwp->readCrtc(hwp, 0x0C);
1375    cr34 = hwp->readCrtc(hwp, 0x34);
1376    if (!(pVia->Chipset == VIA_CLE266 && CLE266_REV_IS_AX(pVia->ChipRev))) {
1377        cr48 = hwp->readCrtc(hwp, 0x48);
1378    }
1379
1380    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1381                        "CR0D: 0x%02X\n", cr0d));
1382    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1383                        "CR0C: 0x%02X\n", cr0c));
1384    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1385                        "CR34: 0x%02X\n", cr34));
1386    if (!(pVia->Chipset == VIA_CLE266 && CLE266_REV_IS_AX(pVia->ChipRev))) {
1387        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1388                            "CR48: 0x%02X\n", cr48));
1389    }
1390
1391#endif
1392
1393    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1394                        "Exiting viaIGA1SetFBStartingAddress.\n"));
1395}
1396
1397void
1398viaIGA1SetDisplayRegister(ScrnInfoPtr pScrn, DisplayModePtr mode)
1399{
1400    vgaHWPtr hwp = VGAHWPTR(pScrn);
1401    VIAPtr pVia = VIAPTR(pScrn);
1402    CARD16 temp;
1403
1404    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1405                        "Entered viaIGA1SetDisplayRegister.\n"));
1406
1407    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1408                "IGA1 Requested Screen Mode: %s\n", mode->name);
1409
1410    if (mode->Flags & V_CLKDIV2) {
1411        ViaSeqMask(hwp, 0x01, 0x08, 0x08);
1412    } else {
1413        ViaSeqMask(hwp, 0x01, 0x00, 0x08);
1414    }
1415
1416    ViaCrtcMask(hwp, 0x03, 0x80, 0x80); /* enable vertical retrace access */
1417
1418    /* Setting maximum scan line to 0. */
1419    /* 3X5.09[4:0] - Maximum Scan Line */
1420    ViaCrtcMask(hwp, 0x09, 0x00, 0x1F);
1421
1422    ViaCrtcMask(hwp, 0x11, 0x00, 0x80); /* modify starting address */
1423
1424    /* 3X5.14[6]   - Double Word Mode
1425     *               Allows normal addressing or double-word addressing.
1426     *               0: Normal word addressing
1427     *               1: Double word addressing
1428     * 3X5.14[4:0] - Underline Location */
1429    ViaCrtcMask(hwp, 0x14, 0x00, 0x5F);
1430
1431
1432    /* We are not using the split screen feature so line compare register
1433     * should be set to 0x7FF. */
1434    temp = 0x7FF;
1435
1436    /* 3X5.18[7:0] - Line Compare Bits [7:0] */
1437    hwp->writeCrtc(hwp, 0x18, temp & 0xFF);
1438
1439    /* 3X5.07[4] - Line Compare Bit [8] */
1440    ViaCrtcMask(hwp, 0x07, temp >> 4, 0x10);
1441
1442    /* 3X5.09[6] - Line Compare Bit [9] */
1443    ViaCrtcMask(hwp, 0x09, temp >> 3, 0x40);
1444
1445    /* 3X5.35[4] - Line Compare Bit [10] */
1446    ViaCrtcMask(hwp, 0x35, temp >> 6, 0x10);
1447
1448
1449    /* 3X5.32[7:5] - HSYNC Delay Number by VCLK
1450     *               000: No delay
1451     *               001: Delay + 4 VCKs
1452     *               010: Delay + 8 VCKs
1453     *               011: Delay + 12 VCKs
1454     *               100: Delay + 16 VCKs
1455     *               101: Delay + 20 VCKs
1456     *               Others: Undefined
1457     * 3X5.32[4]   - Reserved
1458     * 3X5.32[3]   - CRT SYNC Driving Selection
1459     *               0: Low
1460     *               1: High
1461     * 3X5.32[2]   - Display End Blanking Enable
1462     *               0: Disable
1463     *               1: Enable
1464     * 3X5.32[1]   - Digital Video Port (DVP) Gamma Correction
1465     *               If the gamma correction of primary display is
1466     *               turned on, the gamma correction in DVP can be
1467     *               enabled / disabled by this bit.
1468     *               0: Disable
1469     *               1: Enable
1470     * 3X5.32[0]   - Real-Time Flipping
1471     *               0: Flip by the frame
1472     *               1: Flip by each scan line */
1473    ViaCrtcMask(hwp, 0x32, 0x04, 0xEC);
1474
1475    /* Keep interlace mode off.
1476     * No shift for HSYNC.*/
1477    /* 3X5.33[7]   - Primary Display Gamma Correction
1478     *               0: Disable
1479     *               1: Enable
1480     * 3X5.33[6]   - Primary Display Interlace Mode
1481     *               0: Disable
1482     *               1: Enable
1483     * 3X5.33[5]   - Horizontal Blanking End Bit [6]
1484     * 3X5.33[4]   - Horizontal Synchronization Start Bit [8]
1485     * 3X5.33[3]   - Prefetch Mode
1486     *               0: Disable
1487     *               1: Enable
1488     * 3X5.33[2:0] - The Value will Shift the HSYNC to be Early than Planned
1489     *               000: Shift to early time by 3 characters
1490     *                    (VGA mode suggested value; default value)
1491     *               001: Shift to early time by 4 characters
1492     *               010: Shift to early time by 5 characters
1493     *               011: Shift to early time by 6 characters
1494     *               100: Shift to early time by 7 characters
1495     *               101: Shift to early time by 0 character
1496     *                    (Non-VGA mode suggested value)
1497     *               110: Shift to early time by 1 character
1498     *               111: Shift to early time by 2 characters */
1499    ViaCrtcMask(hwp, 0x33, 0x05, 0x4F);
1500
1501    /* UniChrome Pro or later */
1502    if ((pVia->Chipset != VIA_CLE266) && (pVia->Chipset != VIA_KM400)) {
1503        /* Set IGA1 to linear mode. */
1504        /* 3X5.43[2]  - IGA1 Address Mode Selection
1505         *              0: Linear
1506         *              1: Tile */
1507        ViaCrtcMask(hwp, 0x43, 0x00, 0x04);
1508    }
1509
1510    /* Set IGA1 horizontal total.*/
1511    /* Due to IGA1 horizontal total being only 9 bits wide,
1512     * the adjusted horizontal total needs to be shifted by
1513     * 3 bit positions to the right.
1514     * In addition to that, this particular register requires the
1515     * value to be 5 less than the actual value being written. */
1516    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1517                        "IGA1 CrtcHTotal: %d\n", mode->CrtcHTotal));
1518    temp = (mode->CrtcHTotal >> 3) - 5;
1519
1520    /* 3X5.00[7:0] - Horizontal Total Bits [7:0] */
1521    hwp->writeCrtc(hwp, 0x00, temp & 0xFF);
1522
1523    /* 3X5.36[3] - Horizontal Total Bit [8] */
1524    ViaCrtcMask(hwp, 0x36, temp >> 5, 0x08);
1525
1526
1527    /* Set IGA1 horizontal display end. */
1528    /* Due to IGA1 horizontal display end being only 8 bits
1529     * or 9 bits (for VX900 chipset) wide, the adjusted horizontal
1530     * display end needs to be shifted by 3 bit positions to the right.
1531     * In addition to that, this particular register requires the
1532     * value to be 1 less than the actual value being written. */
1533    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1534                        "IGA1 CrtcHDisplay: %d\n", mode->CrtcHDisplay));
1535    temp = (mode->CrtcHDisplay >> 3) - 1;
1536
1537    /* 3X5.01[7:0] - Horizontal Display End Bits [7:0] */
1538    hwp->writeCrtc(hwp, 0x01, temp & 0xFF);
1539
1540    if (pVia->Chipset == VIA_VX900) {
1541        /* 3X5.45[1] - Horizontal Display End Bit [8] */
1542        ViaCrtcMask(hwp, 0x45, temp >> 7, 0x02);
1543    }
1544
1545
1546    /* Set IGA1 horizontal blank start. */
1547    /* Due to IGA1 horizontal blank start being only 8 bits or
1548     * 9 bits (for VX900 chipset) wide, the adjusted horizontal
1549     * blank start needs to be shifted by 3 bit positions to the
1550     * right. */
1551    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1552                        "IGA1 CrtcHBlankStart: %d\n", mode->CrtcHBlankStart));
1553    temp = mode->CrtcHBlankStart >> 3;
1554
1555    /* 3X5.02[7:0] - Horizontal Blanking Start Bits [7:0] */
1556     hwp->writeCrtc(hwp, 0x02, temp & 0xFF);
1557
1558     if (pVia->Chipset == VIA_VX900) {
1559         /* 3X5.45[2] - Horizontal Blanking Start Bit [8] */
1560         ViaCrtcMask(hwp, 0x45, temp >> 6, 0x04);
1561     }
1562
1563
1564    /* Set IGA1 horizontal blank end. */
1565    /* After shifting horizontal blank end by 3 bit positions to the
1566     * right, the 7 least significant bits are actually used.
1567     * In addition to that, this particular register requires the
1568     * value to be 1 less than the actual value being written. */
1569    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1570                        "IGA1 CrtcHBlankEnd: %d\n", mode->CrtcHBlankEnd));
1571    temp = (mode->CrtcHBlankEnd >> 3) - 1;
1572
1573    /* 3X5.03[4:0] - Horizontal Blanking End Bits [4:0] */
1574    ViaCrtcMask(hwp, 0x03, temp, 0x1F);
1575
1576    /* 3X5.05[7] - Horizontal Blanking End Bit [5] */
1577    ViaCrtcMask(hwp, 0x05, temp << 2, 0x80);
1578
1579    /* 3X5.33[5] - Horizontal Blanking End Bit [6] */
1580    ViaCrtcMask(hwp, 0x33, temp >> 1, 0x20);
1581
1582
1583    /* Set IGA1 horizontal synchronization start. */
1584    /* Due to IGA1 horizontal synchronization start being only 9 bits wide,
1585     * the adjusted horizontal synchronization start needs to be shifted by
1586     * 3 bit positions to the right. */
1587    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1588                        "IGA1 CrtcHSyncStart: %d\n", mode->CrtcHSyncStart));
1589    temp = mode->CrtcHSyncStart >> 3;
1590
1591    /* 3X5.04[7:0] - Horizontal Retrace Start Bits [7:0] */
1592    hwp->writeCrtc(hwp, 0x04, temp & 0xFF);
1593
1594    /* 3X5.33[4] - Horizontal Retrace Start Bit [8] */
1595    ViaCrtcMask(hwp, 0x33, temp >> 4, 0x10);
1596
1597
1598    /* Set IGA1 horizontal synchronization end. */
1599    /* After shifting horizontal synchronization end by 3 bit positions
1600     * to the right, the 5 least significant bits are actually used.
1601     * In addition to that, this particular register requires the
1602     * value to be 1 less than the actual value being written. */
1603    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1604                        "IGA1 CrtcHSyncEnd: %d\n", mode->CrtcHSyncEnd));
1605    temp = (mode->CrtcHSyncEnd >> 3) - 1;
1606
1607    /* 3X5.05[4:0] - Horizontal Retrace End Bits [4:0] */
1608    ViaCrtcMask(hwp, 0x05, temp, 0x1F);
1609
1610
1611    /* Set IGA1 vertical total. */
1612    /* Vertical total requires the value to be 2 less
1613     * than the actual value being written. */
1614    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1615                        "IGA1 CrtcVTotal: %d\n", mode->CrtcVTotal));
1616    temp = mode->CrtcVTotal - 2;
1617
1618    /* 3X5.06[7:0] - Vertical Total Period Bits [7:0] */
1619    hwp->writeCrtc(hwp, 0x06, temp & 0xFF);
1620
1621    /* 3X5.07[0] - Vertical Total Period Bit [8] */
1622    ViaCrtcMask(hwp, 0x07, temp >> 8, 0x01);
1623
1624    /* 3X5.07[5] - Vertical Total Period Bit [9] */
1625    ViaCrtcMask(hwp, 0x07, temp >> 4, 0x20);
1626
1627    /* 3X5.35[0] - Vertical Total Period Bit [10] */
1628    ViaCrtcMask(hwp, 0x35, temp >> 10, 0x01);
1629
1630
1631    /* Set IGA1 vertical display end. */
1632    /* Vertical display end requires the value to be 1 less
1633     * than the actual value being written. */
1634    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1635                        "IGA1 CrtcVDisplay: %d\n", mode->CrtcVDisplay));
1636    temp = mode->CrtcVDisplay - 1;
1637
1638    /* 3X5.12[7:0] - Vertical Active Data Period Bits [7:0] */
1639    hwp->writeCrtc(hwp, 0x12, temp & 0xFF);
1640
1641    /* 3X5.07[1] - Vertical Active Data Period Bit [8] */
1642    ViaCrtcMask(hwp, 0x07, temp >> 7, 0x02);
1643
1644    /* 3X5.07[6] - Vertical Active Data Period Bit [9] */
1645    ViaCrtcMask(hwp, 0x07, temp >> 3, 0x40);
1646
1647    /* 3X5.35[2] - Vertical Active Data Period Bit [10] */
1648    ViaCrtcMask(hwp, 0x35, temp >> 8, 0x04);
1649
1650
1651    /* Set IGA1 vertical blank start. */
1652    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1653                        "IGA1 CrtcVBlankStart: %d\n", mode->CrtcVBlankStart));
1654    temp = mode->CrtcVBlankStart;
1655
1656    /* 3X5.15[7:0] - Vertical Blanking Start Bits [7:0] */
1657    hwp->writeCrtc(hwp, 0x15, temp & 0xFF);
1658
1659    /* 3X5.07[3] - Vertical Blanking Start Bit [8] */
1660    ViaCrtcMask(hwp, 0x07, temp >> 5, 0x08);
1661
1662    /* 3X5.09[5] - Vertical Blanking Start Bit [9] */
1663    ViaCrtcMask(hwp, 0x09, temp >> 4, 0x20);
1664
1665    /* 3X5.35[3] - Vertical Blanking Start Bit [10] */
1666    ViaCrtcMask(hwp, 0x35, temp >> 7, 0x08);
1667
1668
1669    /* Set IGA1 vertical blank end. */
1670    /* Vertical blank end requires the value to be 1 less
1671     * than the actual value being written, and 8 LSB
1672     * (Least Significant Bits) are written straight into the
1673     * relevant register. */
1674    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1675                        "IGA1 CrtcVBlankEnd: %d\n", mode->CrtcVBlankEnd));
1676    temp = mode->CrtcVBlankEnd - 1;
1677
1678    /* 3X5.16[7:0] - Vertical Blanking End Bits [7:0] */
1679    hwp->writeCrtc(hwp, 0x16, temp & 0xFF);
1680
1681
1682    /* Set IGA1 vertical synchronization start. */
1683    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1684                        "IGA1 CrtcVSyncStart: %d\n", mode->CrtcVSyncStart));
1685    temp = mode->CrtcVSyncStart;
1686
1687    /* 3X5.10[7:0] - Vertical Retrace Start Bits [7:0] */
1688    hwp->writeCrtc(hwp, 0x10, temp & 0xFF);
1689
1690    /* 3X5.07[2] - Vertical Retrace Start Bit [8] */
1691    ViaCrtcMask(hwp, 0x07, temp >> 6, 0x04);
1692
1693    /* 3X5.07[7] - Vertical Retrace Start Bit [9] */
1694    ViaCrtcMask(hwp, 0x07, temp >> 2, 0x80);
1695
1696    /* 3X5.35[1] - Vertical Retrace Start Bit [10] */
1697    ViaCrtcMask(hwp, 0x35, temp >> 9, 0x02);
1698
1699
1700    /* Set IGA1 vertical synchronization end. */
1701    /* Vertical synchronization end requires the value to be 1 less
1702     * than the actual value being written, and 4 LSB
1703     * (Least Significant Bits) are written straight into the
1704     * relevant register. */
1705    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1706                        "IGA1 CrtcVSyncEnd: %d\n", mode->CrtcVSyncEnd));
1707    temp = mode->CrtcVSyncEnd - 1;
1708
1709    /*3X5.11[3:0] - Vertical Retrace End Bits [3:0] */
1710    ViaCrtcMask(hwp, 0x11, temp & 0x0F, 0x0F);
1711
1712
1713    /* Set IGA1 horizontal offset adjustment. */
1714    temp = (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3)) >> 3;
1715
1716    /* 3X5.13[7:0] - Primary Display Horizontal Offset Bits [7:0] */
1717    hwp->writeCrtc(hwp, 0x13, temp & 0xFF);
1718
1719    /* 3X5.35[7:5] - Primary Display Horizontal Offset Bits [10:8] */
1720    ViaCrtcMask(hwp, 0x35, temp >> 3, 0xE0);
1721
1722
1723    /* Set IGA1 horizontal display fetch (read) count. */
1724    temp = (mode->CrtcHDisplay * (pScrn->bitsPerPixel >> 3)) >> 4;
1725
1726    /* 3C5.1C[7:0] - Primary Display Horizontal Display
1727     *               Fetch Count Data Bits [7:0] */
1728    hwp->writeSeq(hwp, 0x1C, temp & 0xFF);
1729
1730    /* 3C5.1D[1:0] - Primary Display Horizontal Display
1731     *               Fetch Count Data Bits [9:8] */
1732    ViaSeqMask(hwp, 0x1D, temp >> 8, 0x03);
1733
1734
1735    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1736                        "Exiting viaIGA1SetDisplayRegister.\n"));
1737}
1738
1739/*
1740 * Checks for limitations imposed by the available VGA timing registers.
1741 */
1742static ModeStatus
1743viaIGA1ModeValid(ScrnInfoPtr pScrn, DisplayModePtr mode)
1744{
1745    VIAPtr pVia = VIAPTR(pScrn);
1746
1747    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1748                        "Entered viaIGA1ModeValid.\n"));
1749
1750    /* Note that horizontal total being written to VGA registers is
1751     * shifted to the right by 3 bit positions since only 9 bits are
1752     * available, and then 5 is subtracted from it. Hence, to check if
1753     * the screen can even be valid, opposite of that needs to happen.
1754     * That being said, to check if the number is within an acceptable range,
1755     * 1 is subtracted from 5, hence, 4 (5 - 1) is multiplied with 8 (i.e.,
1756     * 1 is shifted 3 bit positions to the left), and the resulting 32 is
1757     * added to 4096 (9 + 3 bits) to calculate the maximum horizontal total
1758     * IGA1 can handle. Ultimately, 4128 is the largest number VIA IGP's
1759     * IGA1 can handle. */
1760    if (mode->CrtcHTotal > (4096 + ((1 << 3) * (5 - 1))))
1761        return MODE_BAD_HVALUE;
1762
1763    if (((pVia->Chipset != VIA_VX900)
1764            && (mode->CrtcHDisplay > 2048))
1765        || ((pVia->Chipset == VIA_VX900)
1766            && (mode->CrtcHDisplay > 4096)))
1767        return MODE_BAD_HVALUE;
1768
1769    if (((pVia->Chipset != VIA_VX900)
1770            && (mode->CrtcHBlankStart > 2048))
1771        || ((pVia->Chipset == VIA_VX900)
1772            && (mode->CrtcHBlankStart > 4096)))
1773        return MODE_BAD_HVALUE;
1774
1775    if ((mode->CrtcHBlankEnd - mode->CrtcHBlankStart) > 1025)
1776        return MODE_HBLANK_WIDE;
1777
1778    if (mode->CrtcHSyncStart > 4095)
1779        return MODE_BAD_HVALUE;
1780
1781    if ((mode->CrtcHSyncEnd - mode->CrtcHSyncStart) > 256)
1782        return MODE_HSYNC_WIDE;
1783
1784    if (mode->CrtcVTotal > 2049)
1785        return MODE_BAD_VVALUE;
1786
1787    if (mode->CrtcVDisplay > 2048)
1788        return MODE_BAD_VVALUE;
1789
1790    if (mode->CrtcVSyncStart > 2047)
1791        return MODE_BAD_VVALUE;
1792
1793    if ((mode->CrtcVSyncEnd - mode->CrtcVSyncStart) > 16)
1794        return MODE_VSYNC_WIDE;
1795
1796    if (mode->CrtcVBlankStart > 2048)
1797        return MODE_BAD_VVALUE;
1798
1799    if ((mode->CrtcVBlankEnd - mode->CrtcVBlankStart) > 257)
1800        return MODE_VBLANK_WIDE;
1801
1802    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1803                        "Exiting viaIGA1ModeValid.\n"));
1804    return MODE_OK;
1805}
1806
1807static void
1808ViaSetCLE266APrimaryFIFO(ScrnInfoPtr pScrn, Bool Enable)
1809{
1810    VIAPtr pVia = VIAPTR(pScrn);
1811    CARD32 dwGE230, dwGE298;
1812
1813    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1814                     "ViaSetCLE266APrimaryFIFO: %d\n", Enable));
1815
1816    dwGE298 = VIAGETREG(0x298);
1817    VIASETREG(0x298, dwGE298 | 0x20000000);
1818
1819    dwGE230 = VIAGETREG(0x230);
1820    if (Enable)
1821        dwGE230 |= 0x00200000;
1822    else
1823        dwGE230 &= ~0x00200000;
1824    VIASETREG(0x230, dwGE230);
1825
1826    dwGE298 = VIAGETREG(0x298);
1827    VIASETREG(0x298, dwGE298 & ~0x20000000);
1828}
1829
1830static void
1831ViaSetPrimaryExpireNumber(ScrnInfoPtr pScrn, DisplayModePtr mode,
1832                          ViaExpireNumberTable *Expire)
1833{
1834    vgaHWPtr hwp = VGAHWPTR(pScrn);
1835    VIAPtr pVia = VIAPTR(pScrn);
1836
1837    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaSetPrimaryExpireNumber\n"));
1838
1839    for (; Expire->X; Expire++)
1840        if ((Expire->X == mode->CrtcHDisplay) &&
1841            (Expire->Y == mode->CrtcVDisplay) &&
1842            (Expire->Bpp == pScrn->bitsPerPixel) &&
1843            (Expire->bRamClock == pVia->MemClk)) {
1844            ViaSeqMask(hwp, 0x22, Expire->bTuningValue, 0x1F);
1845            return;
1846        }
1847}
1848
1849static void
1850ViaSetPrimaryFIFO(ScrnInfoPtr pScrn, DisplayModePtr mode)
1851{
1852    vgaHWPtr hwp = VGAHWPTR(pScrn);
1853    VIAPtr pVia = VIAPTR(pScrn);
1854
1855    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaSetPrimaryFIFO\n"));
1856
1857    /* Standard values. */
1858    ViaSeqMask(hwp, 0x17, 0x1F, 0xFF);
1859
1860    if (mode->CrtcHDisplay >= 1600) {
1861        ViaSeqMask(hwp, 0x16, 0x0F, 0xBF);
1862        ViaSeqMask(hwp, 0x18, 0x4F, 0xFF);
1863    } else if (mode->CrtcHDisplay >= 1024) {
1864        ViaSeqMask(hwp, 0x16, 0x0C, 0xBF);
1865        ViaSeqMask(hwp, 0x18, 0x4C, 0xFF);
1866    } else {
1867        ViaSeqMask(hwp, 0x16, 0x08, 0xBF);
1868        ViaSeqMask(hwp, 0x18, 0x4E, 0xFF);
1869    }
1870
1871    switch (pVia->Chipset) {
1872        case VIA_CLE266:
1873            if (CLE266_REV_IS_CX(pVia->ChipRev)) {
1874                if (pVia->HasSecondary) {       /* SAMM or DuoView case */
1875                    if (mode->HDisplay >= 1024) {
1876                        ViaSeqMask(hwp, 0x16, 0x1C, 0x3F);  /* 28 */
1877                        hwp->writeSeq(hwp, 0x17, 0x3F);     /* 63 */
1878                        hwp->writeSeq(hwp, 0x18, 0x57);     /* 23 */
1879                    }
1880                } else {        /* Single view or Simultaneous case */
1881#if 0
1882                    if (mode->HDisplay > 1024) {
1883                        ViaSeqMask(hwp, 0x16, 0x17, 0x3F);  /* 23 */
1884                        hwp->writeSeq(hwp, 0x17, 0x2F);     /* 47 */
1885                        hwp->writeSeq(hwp, 0x18, 0x57);     /* 23 */
1886                    }
1887#endif
1888                }
1889                ViaSetPrimaryExpireNumber(pScrn, mode, CLE266CExpireNumber);
1890            } else {
1891                if ((mode->HDisplay > 1024) && pVia->HasSecondary) {
1892                    ViaSetCLE266APrimaryFIFO(pScrn, TRUE);
1893
1894                    ViaSeqMask(hwp, 0x16, 0x17, 0x3F);  /* 23 */
1895                    hwp->writeSeq(hwp, 0x17, 0x2F);     /* 47 */
1896                    hwp->writeSeq(hwp, 0x18, 0x57);     /* 23 */
1897                }
1898                ViaSetPrimaryExpireNumber(pScrn, mode, CLE266AExpireNumber);
1899            }
1900            break;
1901        case VIA_KM400:
1902            if (pVia->HasSecondary) {   /* SAMM or DuoView case */
1903                if ((mode->HDisplay >= 1600) &&
1904                    (pVia->MemClk <= VIA_MEM_DDR200)) {
1905                    ViaSeqMask(hwp, 0x16, 0x09, 0x3F);  /* 9 */
1906                    hwp->writeSeq(hwp, 0x17, 0x1C);     /* 28 */
1907                } else {
1908                    ViaSeqMask(hwp, 0x16, 0x1C, 0x3F);  /* 28 */
1909                    hwp->writeSeq(hwp, 0x17, 0x3F);     /* 63 */
1910                }
1911            } else {
1912                if ((mode->HDisplay > 1280))
1913                    ViaSeqMask(hwp, 0x16, 0x1C, 0x3F);  /* 28 */
1914                else if (mode->HDisplay > 1024)
1915                    ViaSeqMask(hwp, 0x16, 0x17, 0x3F);  /* 23 */
1916                else
1917                    ViaSeqMask(hwp, 0x16, 0x10, 0x3F);  /* 16 */
1918                hwp->writeSeq(hwp, 0x17, 0x3F);  /* 63 */
1919            }
1920            hwp->writeSeq(hwp, 0x18, 0x57);  /* 23 */
1921            ViaSetPrimaryExpireNumber(pScrn, mode, KM400ExpireNumber);
1922            break;
1923        case VIA_K8M800:
1924            hwp->writeSeq(hwp, 0x17, 0xBF);     /* 384/2 - 1 = 191 */
1925            ViaSeqMask(hwp, 0x16, 0x92, 0xBF);  /* 328/4 = 82 = 0x52 */
1926            ViaSeqMask(hwp, 0x18, 0x8a, 0xBF);  /* 74 */
1927
1928            if ((mode->HDisplay >= 1400) && (pScrn->bitsPerPixel == 32))
1929                ViaSeqMask(hwp, 0x22, 0x10, 0x1F);  /* 64/4 = 16 */
1930            else
1931                ViaSeqMask(hwp, 0x22, 0x00, 0x1F);  /* 128/4 = overflow = 0 */
1932            break;
1933        /* PM800/PM880/CN400 */
1934        case VIA_PM800:
1935            hwp->writeSeq(hwp, 0x17, 0x5F);     /* 95 */
1936            ViaSeqMask(hwp, 0x16, 0x20, 0xBF);  /* 32 */
1937            ViaSeqMask(hwp, 0x18, 0x10, 0xBF);  /* 16 */
1938
1939            if ((mode->HDisplay >= 1400) && (pScrn->bitsPerPixel == 32))
1940                ViaSeqMask(hwp, 0x22, 0x10, 0x1F);  /* 64/4 = 16 */
1941            else
1942                ViaSeqMask(hwp, 0x22, 0x1F, 0x1F);  /* 31 */
1943            break;
1944        /* P4M800 Pro/VN800/CN700 */
1945        case VIA_P4M800PRO:
1946            hwp->writeSeq(hwp, 0x17, 0x2F);
1947            ViaSeqMask(hwp, 0x16, 0x14, 0xBF);  /* 80/4    = 20  = 0x14 */
1948            ViaSeqMask(hwp, 0x18, 0x08, 0xBF);
1949
1950            if ((mode->HDisplay >= 1400) && (pScrn->bitsPerPixel == 32))
1951                ViaSeqMask(hwp, 0x22, 0x10, 0x1F);
1952            else
1953                ViaSeqMask(hwp, 0x22, 0x00, 0x1F);
1954            break;
1955        case VIA_K8M890:
1956            /* depth location: {SR17,0,7} */
1957            hwp->writeSeq(hwp, 0x17, 0xB3);    /* 360/2-1 = 179 = 0xB3 */
1958            /* Formula (x & 0x3F) | ((x & 0x40) << 1) */
1959            /* threshold location: {SR16,0,5},{SR16,7,7} */
1960            ViaSeqMask(hwp, 0x16, 0x92, 0xBF); /* 328/4   = 82  = 0x52 */
1961            /* high threshold location: {SR18,0,5},{SR18,7,7} */
1962            ViaSeqMask(hwp, 0x18, 0x8A, 0xBF); /* 296/4   = 74  = 0x4A */
1963            /* display queue expire num location: {SR22,0,4}. */
1964            ViaSeqMask(hwp, 0x22, 0x1F, 0x1F); /* 124/4   = 31  = 0x1F */
1965            break;
1966        case VIA_P4M900:
1967            /* location: {SR17,0,7} */
1968            hwp->writeSeq(hwp, 0x17, 0x2F);    /* 96/2-1  = 47  = 0x2F */
1969            /* location: {SR16,0,5},{SR16,7,7} */
1970            ViaSeqMask(hwp, 0x16, 0x13, 0xBF); /* 76/4    = 19  = 0x13 */
1971            /* location: {SR18,0,5},{SR18,7,7} */
1972            ViaSeqMask(hwp, 0x18, 0x13, 0xBF); /* 76/4    = 19  = 0x13 */
1973            /* location: {SR22,0,4}. */
1974            ViaSeqMask(hwp, 0x22, 0x08, 0x1F); /* 32/4    = 8   = 0x08 */
1975            break;
1976        case VIA_P4M890:
1977            hwp->writeSeq(hwp, 0x17, 0x2F);      /* 96/2-1  = 47  = 0x2F */
1978            ViaSeqMask(hwp, 0x16, 0x13, 0xBF);   /* 76/4    = 19  = 0x13 */
1979            ViaSeqMask(hwp, 0x18, 0x10, 0xBF);   /* 64/4    = 16  = 0x10 */
1980            ViaSeqMask(hwp, 0x22, 0x08, 0x1F);   /* 32/4    = 8   = 0x08 */
1981            break;
1982        case VIA_CX700:
1983            hwp->writeSeq(hwp, 0x17, 0x5F);
1984            ViaSeqMask(hwp, 0x16, 0x20, 0xBF);   /* 128/4  = 32  = 0x20 */
1985            ViaSeqMask(hwp, 0x18, 0x20, 0xBF);   /* 128/4  = 32  = 0x20 */
1986            ViaSeqMask(hwp, 0x22, 0x1F, 0x1F);   /* 124/4  = 31  = 0x1F */
1987            break;
1988        case VIA_VX800:
1989            hwp->writeSeq(hwp, 0x17, 0x5F); /* 192/2-1 = 95   = 0x5F */
1990            hwp->writeSeq(hwp, 0x16, 0x26); /* 152/4   = 38   = 0x26 */
1991            hwp->writeSeq(hwp, 0x18, 0x26); /* 152/4   = 38 */
1992            hwp->writeSeq(hwp, 0x22, 0x10); /*  64/4   = 16 */
1993            break;
1994        case VIA_VX855:
1995            hwp->writeSeq(hwp, 0x17, 0xC7); /* 400/2-1 = 199  = 0xC7 */
1996            /* Formula for {SR16,0,5},{SR16,7,7} is: (0x50 & 0x3F) | ((0x50 & 0x40) << 1) = 0x90 */
1997            hwp->writeSeq(hwp, 0x16, 0x90); /* 320/4   = 80   = 0x50 */
1998            /* Formula for {SR18,0,5},{SR18,7,7} is: (0x50 & 0x3F) | ((0x50 & 0x40) << 1) = 0x90 */
1999            hwp->writeSeq(hwp, 0x18, 0x90); /* 320/4   = 80   = 0x50 */
2000            hwp->writeSeq(hwp, 0x22, 0x28); /* 160/4   = 40   = 0x28 */
2001            break;
2002        case VIA_VX900:
2003            hwp->writeSeq(hwp, 0x17, 0xC7); /* 400/2-1 = 199  = 0xC7 */
2004            /* Formula for {SR16,0,5},{SR16,7,7} is: (0x50 & 0x3F) | ((0x50 & 0x40) << 1) = 0x90 */
2005            hwp->writeSeq(hwp, 0x16, 0x90); /* 320/4   = 80   = 0x50 */
2006            /* Formula for {SR18,0,5},{SR18,7,7} is: (0x50 & 0x3F) | ((0x50 & 0x40) << 1) = 0x90 */
2007            hwp->writeSeq(hwp, 0x18, 0x90); /* 320/4   = 80   = 0x50 */
2008            hwp->writeSeq(hwp, 0x22, 0x28); /* 160/4   = 40   = 0x28 */
2009            break;
2010        default:
2011            xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ViaSetPrimaryFIFO: "
2012                       "Chipset %d not implemented\n", pVia->Chipset);
2013            break;
2014    }
2015}
2016
2017/*
2018 * Turn off the primary FIFO only for CLE266A.
2019 */
2020static void
2021ViaDisablePrimaryFIFO(ScrnInfoPtr pScrn)
2022{
2023    VIAPtr pVia = VIAPTR(pScrn);
2024
2025    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaDisablePrimaryFIFO\n"));
2026
2027    /* Needed because exiting from X-Window will dump back register values.
2028     * Other chipsets have no need to set extended FIFO values. */
2029    if ((pVia->Chipset == VIA_CLE266) && CLE266_REV_IS_AX(pVia->ChipRev) &&
2030        ((pScrn->currentMode->HDisplay > 1024) || pVia->HasSecondary))
2031        ViaSetCLE266APrimaryFIFO(pScrn, FALSE);
2032}
2033
2034void
2035viaIGA1Save(ScrnInfoPtr pScrn)
2036{
2037    vgaHWPtr hwp = VGAHWPTR(pScrn);
2038    VIAPtr pVia = VIAPTR(pScrn);
2039    VIARegPtr Regs = &pVia->SavedReg;
2040
2041    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2042                        "Entered viaIGA1Save.\n"));
2043
2044    vgaHWProtect(pScrn, TRUE);
2045
2046    vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_ALL);
2047
2048    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2049                        "Saving sequencer registers.\n"));
2050
2051    /* Unlock extended registers. */
2052    hwp->writeSeq(hwp, 0x10, 0x01);
2053
2054    Regs->SR[0x14] = hwp->readSeq(hwp, 0x14);
2055    Regs->SR[0x15] = hwp->readSeq(hwp, 0x15);
2056    Regs->SR[0x16] = hwp->readSeq(hwp, 0x16);
2057    Regs->SR[0x17] = hwp->readSeq(hwp, 0x17);
2058    Regs->SR[0x18] = hwp->readSeq(hwp, 0x18);
2059    Regs->SR[0x19] = hwp->readSeq(hwp, 0x19);
2060
2061    /* PCI Bus Control */
2062    Regs->SR[0x1A] = hwp->readSeq(hwp, 0x1A);
2063
2064    Regs->SR[0x1B] = hwp->readSeq(hwp, 0x1B);
2065    Regs->SR[0x1C] = hwp->readSeq(hwp, 0x1C);
2066    Regs->SR[0x1D] = hwp->readSeq(hwp, 0x1D);
2067    Regs->SR[0x1E] = hwp->readSeq(hwp, 0x1E);
2068    Regs->SR[0x1F] = hwp->readSeq(hwp, 0x1F);
2069
2070    Regs->SR[0x20] = hwp->readSeq(hwp, 0x20);
2071    Regs->SR[0x21] = hwp->readSeq(hwp, 0x21);
2072    Regs->SR[0x22] = hwp->readSeq(hwp, 0x22);
2073
2074    /* Registers 3C5.23 through 3C5.25 are not used by Chrome9.
2075     * Registers 3C5.27 through 3C5.29 are not used by Chrome9. */
2076    switch (pVia->Chipset) {
2077    case VIA_CLE266:
2078    case VIA_KM400:
2079    case VIA_PM800:
2080    case VIA_K8M800:
2081    case VIA_P4M800PRO:
2082    case VIA_CX700:
2083    case VIA_P4M890:
2084        Regs->SR[0x23] = hwp->readSeq(hwp, 0x23);
2085        Regs->SR[0x24] = hwp->readSeq(hwp, 0x24);
2086        Regs->SR[0x25] = hwp->readSeq(hwp, 0x25);
2087
2088        Regs->SR[0x27] = hwp->readSeq(hwp, 0x27);
2089        Regs->SR[0x28] = hwp->readSeq(hwp, 0x28);
2090        Regs->SR[0x29] = hwp->readSeq(hwp, 0x29);
2091        break;
2092    default:
2093        break;
2094    }
2095
2096    Regs->SR[0x26] = hwp->readSeq(hwp, 0x26);
2097
2098    Regs->SR[0x2A] = hwp->readSeq(hwp, 0x2A);
2099    Regs->SR[0x2B] = hwp->readSeq(hwp, 0x2B);
2100    Regs->SR[0x2D] = hwp->readSeq(hwp, 0x2D);
2101    Regs->SR[0x2E] = hwp->readSeq(hwp, 0x2E);
2102
2103    /* Save PCI Configuration Memory Base Shadow 0 and 1.
2104     * These registers are available only in UniChrome, UniChrome Pro,
2105     * and UniChrome Pro II. */
2106    switch (pVia->Chipset) {
2107    case VIA_CLE266:
2108    case VIA_KM400:
2109    case VIA_PM800:
2110    case VIA_K8M800:
2111    case VIA_P4M800PRO:
2112    case VIA_CX700:
2113    case VIA_P4M890:
2114        Regs->SR[0x2F] = hwp->readSeq(hwp, 0x2F);
2115        Regs->SR[0x30] = hwp->readSeq(hwp, 0x30);
2116        break;
2117    default:
2118        break;
2119    }
2120
2121    /* Save PLL settings and several miscellaneous registers.
2122     * For UniChrome, register 3C5.44 through 3C5.4B are saved.
2123     * For UniChrome Pro and Chrome9, register 3C5.44 through 3C5.4C
2124     * are saved. */
2125    Regs->SR[0x44] = hwp->readSeq(hwp, 0x44);
2126    Regs->SR[0x45] = hwp->readSeq(hwp, 0x45);
2127    Regs->SR[0x46] = hwp->readSeq(hwp, 0x46);
2128    Regs->SR[0x47] = hwp->readSeq(hwp, 0x47);
2129    Regs->SR[0x48] = hwp->readSeq(hwp, 0x48);
2130    Regs->SR[0x49] = hwp->readSeq(hwp, 0x49);
2131    Regs->SR[0x4A] = hwp->readSeq(hwp, 0x4A);
2132    Regs->SR[0x4B] = hwp->readSeq(hwp, 0x4B);
2133
2134    switch (pVia->Chipset) {
2135    case VIA_PM800:
2136    case VIA_K8M800:
2137    case VIA_P4M800PRO:
2138    case VIA_CX700:
2139    case VIA_P4M890:
2140    case VIA_K8M890:
2141    case VIA_P4M900:
2142    case VIA_VX800:
2143    case VIA_VX855:
2144    case VIA_VX900:
2145        Regs->SR[0x4C] = hwp->readSeq(hwp, 0x4C);
2146
2147        /* Save register 3C5.4D.
2148         * According to CX700 / VX700 (UniChrome Pro II) Open Graphics
2149         * Programming Manual Part I: Graphics Core / 2D,
2150         * this register is called Dual Channel Memory Control.
2151         * According to VX800 / VX855 / VX900 (Chrome9 HC3 / HCM / HD)
2152         * Open Graphics Programming Manual Part I: Graphics Core / 2D,
2153         * this register is called Preemptive Arbiter Control.
2154         * It is likely that this register is also supported in UniChrome Pro. */
2155        Regs->SR[0x4D] = hwp->readSeq(hwp, 0x4D);
2156
2157        Regs->SR[0x4E] = hwp->readSeq(hwp, 0x4E);
2158        Regs->SR[0x4F] = hwp->readSeq(hwp, 0x4F);
2159        break;
2160    default:
2161        break;
2162    }
2163
2164    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2165                        "Finished saving sequencer registers.\n"));
2166
2167    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2168                        "Saving IGA1 registers.\n"));
2169
2170    /* UniChrome Pro or later */
2171    switch (pVia->Chipset) {
2172    case VIA_PM800:
2173    case VIA_K8M800:
2174    case VIA_P4M800PRO:
2175    case VIA_CX700:
2176    case VIA_P4M890:
2177    case VIA_K8M890:
2178    case VIA_P4M900:
2179    case VIA_VX800:
2180    case VIA_VX855:
2181    case VIA_VX900:
2182        /* Display Fetch Blocking Control */
2183        Regs->CR[0x30] = hwp->readCrtc(hwp, 0x30);
2184
2185        /* Half Line Position */
2186        Regs->CR[0x31] = hwp->readCrtc(hwp, 0x31);
2187        break;
2188    default:
2189        break;
2190    }
2191
2192    Regs->CR[0x32] = hwp->readCrtc(hwp, 0x32);
2193    Regs->CR[0x33] = hwp->readCrtc(hwp, 0x33);
2194    Regs->CR[0x35] = hwp->readCrtc(hwp, 0x35);
2195    Regs->CR[0x36] = hwp->readCrtc(hwp, 0x36);
2196
2197    /* UniChrome Pro or later */
2198    switch (pVia->Chipset) {
2199    case VIA_PM800:
2200    case VIA_K8M800:
2201    case VIA_P4M800PRO:
2202    case VIA_CX700:
2203    case VIA_P4M890:
2204    case VIA_K8M890:
2205    case VIA_P4M900:
2206    case VIA_VX800:
2207    case VIA_VX855:
2208    case VIA_VX900:
2209        /* DAC Control Register */
2210        Regs->CR[0x37] = hwp->readCrtc(hwp, 0x37);
2211        break;
2212    default:
2213        break;
2214    }
2215
2216    Regs->CR[0x38] = hwp->readCrtc(hwp, 0x38);
2217    Regs->CR[0x39] = hwp->readCrtc(hwp, 0x39);
2218    Regs->CR[0x3A] = hwp->readCrtc(hwp, 0x3A);
2219    Regs->CR[0x3B] = hwp->readCrtc(hwp, 0x3B);
2220    Regs->CR[0x3C] = hwp->readCrtc(hwp, 0x3C);
2221    Regs->CR[0x3D] = hwp->readCrtc(hwp, 0x3D);
2222    Regs->CR[0x3E] = hwp->readCrtc(hwp, 0x3E);
2223    Regs->CR[0x3F] = hwp->readCrtc(hwp, 0x3F);
2224
2225    Regs->CR[0x40] = hwp->readCrtc(hwp, 0x40);
2226
2227    /* UniChrome Pro or later */
2228    switch (pVia->Chipset) {
2229    case VIA_PM800:
2230    case VIA_K8M800:
2231    case VIA_P4M800PRO:
2232    case VIA_CX700:
2233    case VIA_P4M890:
2234    case VIA_K8M890:
2235    case VIA_P4M900:
2236    case VIA_VX800:
2237    case VIA_VX855:
2238    case VIA_VX900:
2239        Regs->CR[0x43] = hwp->readCrtc(hwp, 0x43);
2240        Regs->CR[0x45] = hwp->readCrtc(hwp, 0x45);
2241        break;
2242    default:
2243        break;
2244    }
2245
2246    Regs->CR[0x46] = hwp->readCrtc(hwp, 0x46);
2247    Regs->CR[0x47] = hwp->readCrtc(hwp, 0x47);
2248
2249    /* Starting Address */
2250    /* Start Address High */
2251    Regs->CR[0x0C] = hwp->readCrtc(hwp, 0x0C);
2252
2253    /* Start Address Low */
2254    Regs->CR[0x0D] = hwp->readCrtc(hwp, 0x0D);
2255
2256    /* UniChrome Pro or later */
2257    switch (pVia->Chipset) {
2258    case VIA_PM800:
2259    case VIA_K8M800:
2260    case VIA_P4M800PRO:
2261    case VIA_CX700:
2262    case VIA_P4M890:
2263    case VIA_K8M890:
2264    case VIA_P4M900:
2265    case VIA_VX800:
2266    case VIA_VX855:
2267    case VIA_VX900:
2268        /* Starting Address Overflow[28:24] */
2269        Regs->CR[0x48] = hwp->readCrtc(hwp, 0x48);
2270        break;
2271    default:
2272        break;
2273    }
2274
2275    /* Starting Address Overflow[23:16] */
2276    Regs->CR[0x34] = hwp->readCrtc(hwp, 0x34);
2277
2278    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2279                        "Finished saving IGA1 registers.\n"));
2280
2281    vgaHWProtect(pScrn, FALSE);
2282
2283    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2284                        "Exiting viaIGA1Save.\n"));
2285}
2286
2287void
2288viaIGA1Restore(ScrnInfoPtr pScrn)
2289{
2290    vgaHWPtr hwp = VGAHWPTR(pScrn);
2291    VIAPtr pVia = VIAPTR(pScrn);
2292    VIARegPtr Regs = &pVia->SavedReg;
2293
2294    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2295                        "Entered viaIGA1Restore.\n"));
2296
2297    vgaHWProtect(pScrn, TRUE);
2298
2299    vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_ALL);
2300
2301    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2302                        "Restoring sequencer registers.\n"));
2303
2304    /* Unlock extended registers. */
2305    hwp->writeSeq(hwp, 0x10, 0x01);
2306
2307    hwp->writeSeq(hwp, 0x15, Regs->SR[0x15]);
2308    hwp->writeSeq(hwp, 0x16, Regs->SR[0x16]);
2309    hwp->writeSeq(hwp, 0x17, Regs->SR[0x17]);
2310    hwp->writeSeq(hwp, 0x18, Regs->SR[0x18]);
2311    hwp->writeSeq(hwp, 0x19, Regs->SR[0x19]);
2312    hwp->writeSeq(hwp, 0x1A, Regs->SR[0x1A]);
2313
2314    hwp->writeSeq(hwp, 0x1B, Regs->SR[0x1B]);
2315    hwp->writeSeq(hwp, 0x1C, Regs->SR[0x1C]);
2316    hwp->writeSeq(hwp, 0x1D, Regs->SR[0x1D]);
2317    hwp->writeSeq(hwp, 0x1E, Regs->SR[0x1E]);
2318    hwp->writeSeq(hwp, 0x1F, Regs->SR[0x1F]);
2319
2320    hwp->writeSeq(hwp, 0x20, Regs->SR[0x20]);
2321    hwp->writeSeq(hwp, 0x21, Regs->SR[0x21]);
2322    hwp->writeSeq(hwp, 0x22, Regs->SR[0x22]);
2323
2324    /* Registers 3C5.23 through 3C5.25 are not used by Chrome9.
2325     * Registers 3C5.27 through 3C5.29 are not used by Chrome9. */
2326    switch (pVia->Chipset) {
2327    case VIA_CLE266:
2328    case VIA_KM400:
2329    case VIA_PM800:
2330    case VIA_K8M800:
2331    case VIA_P4M800PRO:
2332    case VIA_CX700:
2333    case VIA_P4M890:
2334        hwp->writeSeq(hwp, 0x23, Regs->SR[0x23]);
2335        hwp->writeSeq(hwp, 0x24, Regs->SR[0x24]);
2336        hwp->writeSeq(hwp, 0x25, Regs->SR[0x25]);
2337
2338        hwp->writeSeq(hwp, 0x27, Regs->SR[0x27]);
2339        hwp->writeSeq(hwp, 0x28, Regs->SR[0x28]);
2340        hwp->writeSeq(hwp, 0x29, Regs->SR[0x29]);
2341        break;
2342    default:
2343        break;
2344    }
2345
2346    hwp->writeSeq(hwp, 0x26, Regs->SR[0x26]);
2347
2348    hwp->writeSeq(hwp, 0x2A, Regs->SR[0x2A]);
2349    hwp->writeSeq(hwp, 0x2B, Regs->SR[0x2B]);
2350
2351    hwp->writeSeq(hwp, 0x2D, Regs->SR[0x2D]);
2352    hwp->writeSeq(hwp, 0x2E, Regs->SR[0x2E]);
2353
2354    /* Restore PCI Configuration Memory Base Shadow 0 and 1.
2355     * These registers are available only in UniChrome, UniChrome Pro,
2356     * and UniChrome Pro II. */
2357    switch (pVia->Chipset) {
2358    case VIA_CLE266:
2359    case VIA_KM400:
2360    case VIA_PM800:
2361    case VIA_K8M800:
2362    case VIA_P4M800PRO:
2363    case VIA_CX700:
2364    case VIA_P4M890:
2365        hwp->writeSeq(hwp, 0x2F, Regs->SR[0x2F]);
2366        hwp->writeSeq(hwp, 0x30, Regs->SR[0x30]);
2367        break;
2368    default:
2369        break;
2370    }
2371
2372    /* Restore PLL settings and several miscellaneous registers.
2373     * For UniChrome, register 3C5.44 through 3C5.4B are restored.
2374     * For UniChrome Pro and Chrome 9, register 3C5.44 through 3C5.4C
2375     * are restored. */
2376    switch (pVia->Chipset) {
2377    case VIA_CLE266:
2378    case VIA_KM400:
2379        /* Engine Clock (ECK) PLL settings */
2380        hwp->writeSeq(hwp, 0x48, Regs->SR[0x48]);
2381        hwp->writeSeq(hwp, 0x49, Regs->SR[0x49]);
2382
2383        /* Memory Clock (MCK) PLL settings */
2384        hwp->writeSeq(hwp, 0x4a, Regs->SR[0x4A]);
2385        hwp->writeSeq(hwp, 0x4b, Regs->SR[0x4B]);
2386
2387        /* Primary Display Clock (VCK) PLL settings */
2388        hwp->writeSeq(hwp, 0x46, Regs->SR[0x46]);
2389        hwp->writeSeq(hwp, 0x47, Regs->SR[0x47]);
2390
2391        /* Secondary Display Clock (LCDCK) PLL settings */
2392        hwp->writeSeq(hwp, 0x44, Regs->SR[0x44]);
2393        hwp->writeSeq(hwp, 0x45, Regs->SR[0x45]);
2394        break;
2395    default:
2396        /* Engine Clock (ECK) PLL settings */
2397        hwp->writeSeq(hwp, 0x47, Regs->SR[0x47]);
2398        hwp->writeSeq(hwp, 0x48, Regs->SR[0x48]);
2399        hwp->writeSeq(hwp, 0x49, Regs->SR[0x49]);
2400
2401        /* Reset ECK PLL. */
2402        hwp->writeSeq(hwp, 0x40, hwp->readSeq(hwp, 0x40) | 0x01); /* Set SR40[0] to 1 */
2403        hwp->writeSeq(hwp, 0x40, hwp->readSeq(hwp, 0x40) & (~0x01)); /* Set SR40[0] to 0 */
2404
2405
2406        /* Primary Display Clock (VCK) PLL settings */
2407        hwp->writeSeq(hwp, 0x44, Regs->SR[0x44]);
2408        hwp->writeSeq(hwp, 0x45, Regs->SR[0x45]);
2409        hwp->writeSeq(hwp, 0x46, Regs->SR[0x46]);
2410
2411        /* Reset VCK PLL. */
2412        hwp->writeSeq(hwp, 0x40, hwp->readSeq(hwp, 0x40) | 0x02); /* Set SR40[1] to 1 */
2413        hwp->writeSeq(hwp, 0x40, hwp->readSeq(hwp, 0x40) & (~0x02)); /* Set SR40[1] to 0 */
2414
2415
2416        /* Secondary Display Clock (LCDCK) PLL settings */
2417        hwp->writeSeq(hwp, 0x4A, Regs->SR[0x4A]);
2418        hwp->writeSeq(hwp, 0x4B, Regs->SR[0x4B]);
2419        hwp->writeSeq(hwp, 0x4C, Regs->SR[0x4C]);
2420
2421        /* Reset LCDCK PLL. */
2422        hwp->writeSeq(hwp, 0x40, hwp->readSeq(hwp, 0x40) | 0x04); /* Set SR40[2] to 1 */
2423        hwp->writeSeq(hwp, 0x40, hwp->readSeq(hwp, 0x40) & (~0x04)); /* Set SR40[2] to 0 */
2424        break;
2425    }
2426
2427    switch (pVia->Chipset) {
2428    case VIA_PM800:
2429    case VIA_K8M800:
2430    case VIA_P4M800PRO:
2431    case VIA_CX700:
2432    case VIA_P4M890:
2433    case VIA_K8M890:
2434    case VIA_P4M900:
2435    case VIA_VX800:
2436    case VIA_VX855:
2437    case VIA_VX900:
2438        /* Restore register 3C5.4D.
2439         * According to CX700 / VX700 (UniChrome Pro II) Open Graphics
2440         * Programming Manual Part I: Graphics Core / 2D,
2441         * this register is called Dual Channel Memory Control.
2442         * According to VX800 / VX855 / VX900 (Chrome9 HC3 / HCM / HD)
2443         * Open Graphics Programming Manual Part I: Graphics Core / 2D,
2444         * this register is called Preemptive Arbiter Control.
2445         * It is likely that this register is also supported in UniChrome Pro. */
2446        hwp->writeSeq(hwp, 0x4D, Regs->SR[0x4D]);
2447
2448        hwp->writeSeq(hwp, 0x4E, Regs->SR[0x4E]);
2449        hwp->writeSeq(hwp, 0x4F, Regs->SR[0x4F]);
2450        break;
2451    default:
2452        break;
2453    }
2454
2455    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2456                        "Finished restoring sequencer registers.\n"));
2457
2458    /* Reset dot clocks. */
2459    ViaSeqMask(hwp, 0x40, 0x06, 0x06);
2460    ViaSeqMask(hwp, 0x40, 0x00, 0x06);
2461
2462    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2463                        "Restoring IGA1 registers.\n"));
2464
2465    /*  later */
2466    switch (pVia->Chipset) {
2467    case VIA_PM800:
2468    case VIA_K8M800:
2469    case VIA_P4M800PRO:
2470    case VIA_CX700:
2471    case VIA_P4M890:
2472    case VIA_K8M890:
2473    case VIA_P4M900:
2474    case VIA_VX800:
2475    case VIA_VX855:
2476    case VIA_VX900:
2477        /* Display Fetch Blocking Control */
2478        hwp->writeCrtc(hwp, 0x30, Regs->CR[0x30]);
2479
2480        /* Half Line Position */
2481        hwp->writeCrtc(hwp, 0x31, Regs->CR[0x31]);
2482        break;
2483    default:
2484        break;
2485    }
2486
2487    /* Restore CRTC controller extended registers. */
2488    /* Mode Control */
2489    hwp->writeCrtc(hwp, 0x32, Regs->CR[0x32]);
2490
2491    /* HSYNCH Adjuster */
2492    hwp->writeCrtc(hwp, 0x33, Regs->CR[0x33]);
2493
2494    /* Extended Overflow */
2495    hwp->writeCrtc(hwp, 0x35, Regs->CR[0x35]);
2496
2497    /* Power Management 3 (Monitor Control) */
2498    hwp->writeCrtc(hwp, 0x36, Regs->CR[0x36]);
2499
2500/* UniChrome Pro or later */
2501    switch (pVia->Chipset) {
2502    case VIA_PM800:
2503    case VIA_K8M800:
2504    case VIA_P4M800PRO:
2505    case VIA_CX700:
2506    case VIA_P4M890:
2507    case VIA_K8M890:
2508    case VIA_P4M900:
2509    case VIA_VX800:
2510    case VIA_VX855:
2511    case VIA_VX900:
2512        /* DAC control Register */
2513        hwp->writeCrtc(hwp, 0x37, Regs->CR[0x37]);
2514        break;
2515    default:
2516        break;
2517    }
2518
2519    hwp->writeCrtc(hwp, 0x38, Regs->CR[0x38]);
2520    hwp->writeCrtc(hwp, 0x39, Regs->CR[0x39]);
2521    hwp->writeCrtc(hwp, 0x3A, Regs->CR[0x3A]);
2522    hwp->writeCrtc(hwp, 0x3B, Regs->CR[0x3B]);
2523    hwp->writeCrtc(hwp, 0x3C, Regs->CR[0x3C]);
2524    hwp->writeCrtc(hwp, 0x3D, Regs->CR[0x3D]);
2525    hwp->writeCrtc(hwp, 0x3E, Regs->CR[0x3E]);
2526    hwp->writeCrtc(hwp, 0x3F, Regs->CR[0x3F]);
2527
2528    hwp->writeCrtc(hwp, 0x40, Regs->CR[0x40]);
2529
2530    /* UniChrome Pro or later */
2531    switch (pVia->Chipset) {
2532    case VIA_PM800:
2533    case VIA_K8M800:
2534    case VIA_P4M800PRO:
2535    case VIA_CX700:
2536    case VIA_P4M890:
2537    case VIA_K8M890:
2538    case VIA_P4M900:
2539    case VIA_VX800:
2540    case VIA_VX855:
2541    case VIA_VX900:
2542        hwp->writeCrtc(hwp, 0x43, Regs->CR[0x43]);
2543        hwp->writeCrtc(hwp, 0x45, Regs->CR[0x45]);
2544        break;
2545    default:
2546        break;
2547    }
2548
2549    hwp->writeCrtc(hwp, 0x46, Regs->CR[0x46]);
2550    hwp->writeCrtc(hwp, 0x47, Regs->CR[0x47]);
2551
2552    /* Starting Address */
2553    /* Start Address High */
2554    hwp->writeCrtc(hwp, 0x0C, Regs->CR[0x0C]);
2555
2556    /* Start Address Low */
2557    hwp->writeCrtc(hwp, 0x0D, Regs->CR[0x0D]);
2558
2559    /* UniChrome Pro or later */
2560    switch (pVia->Chipset) {
2561    case VIA_PM800:
2562    case VIA_K8M800:
2563    case VIA_P4M800PRO:
2564    case VIA_CX700:
2565    case VIA_P4M890:
2566    case VIA_K8M890:
2567    case VIA_P4M900:
2568    case VIA_VX800:
2569    case VIA_VX855:
2570    case VIA_VX900:
2571        /* Starting Address Overflow[28:24] */
2572        hwp->writeCrtc(hwp, 0x48, Regs->CR[0x48]);
2573        break;
2574    default:
2575        break;
2576    }
2577
2578    /* CR34 is fire bits. Must be written after CR0C, CR0D, and CR48.
2579     * Starting Address Overflow[23:16] */
2580    hwp->writeCrtc(hwp, 0x34, Regs->CR[0x34]);
2581
2582    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2583                        "Finished restoring IGA1 registers.\n"));
2584
2585    ViaDisablePrimaryFIFO(pScrn);
2586
2587    vgaHWProtect(pScrn, FALSE);
2588
2589    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2590                        "Exiting viaIGA1Restore.\n"));
2591}
2592
2593/*
2594 * Initialize IGA2 (Integrated Graphics Accelerator) registers.
2595 */
2596void
2597viaIGA2Init(ScrnInfoPtr pScrn)
2598{
2599    vgaHWPtr hwp = VGAHWPTR(pScrn);
2600    VIAPtr pVia = VIAPTR(pScrn);
2601#ifdef HAVE_DEBUG
2602    CARD8 temp;
2603#endif
2604
2605    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2606                        "Entered viaIGA2Init.\n"));
2607
2608#ifdef HAVE_DEBUG
2609    temp = hwp->readSeq(hwp, 0x1B);
2610    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2611                        "SR1B: 0x%02X\n", temp));
2612    temp = hwp->readSeq(hwp, 0x2D);
2613    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2614                        "SR2D: 0x%02X\n", temp));
2615    temp = hwp->readCrtc(hwp, 0x6A);
2616    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2617                        "CR6A: 0x%02X\n", temp));
2618    temp = hwp->readCrtc(hwp, 0x6B);
2619    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2620                        "CR6B: 0x%02X\n", temp));
2621
2622    /* For UniChrome Pro and Chrome9. */
2623    if ((pVia->Chipset != VIA_CLE266)
2624        && (pVia->Chipset != VIA_KM400)) {
2625        temp = hwp->readCrtc(hwp, 0x6C);
2626        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2627                            "CR6C: 0x%02X\n", temp));
2628    }
2629
2630    temp = hwp->readCrtc(hwp, 0x79);
2631    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2632                        "CR79: 0x%02X\n", temp));
2633
2634#endif
2635
2636    /* 3C5.1B[7:6] - Secondary Display Engine (Gated Clock <LCK>)
2637     *               0x: Clock always off
2638     *               10: Clock always on
2639     *               11: Clock on/off according to the
2640     *                   Power Management Status (PMS)
2641     * 3C5.1B[5:4] - Primary Display Engine (Gated Clock <VCK>)
2642     *               0x: Clock always off
2643     *               10: Clock always on
2644     *               11: Clock on/off according to the PMS
2645     * 3C5.1B[3:1] - Reserved
2646     * 3C5.1B[0]   - Primary Display’s LUT On/Off
2647     *               0: On
2648     *               1: Off */
2649    ViaSeqMask(hwp, 0x1B, 0xC0, 0xC0);
2650
2651    /* 3C5.2D[7:6] - E3_ECK_N Selection
2652     *               00: E3_ECK_N
2653     *               01: E3_ECK
2654     *               10: delayed E3_ECK_N
2655     *               11: delayed E3_ECK
2656     * 3C5.2D[5:4] - VCK (Primary Display Clock) PLL Power Control
2657     *               0x: PLL power-off
2658     *               10: PLL always on
2659     *               11: PLL on/off according to the PMS
2660     * 3C5.2D[3:2] - LCK (Secondary Display Clock) PLL Power Control
2661     *               0x: PLL power-off
2662     *               10: PLL always on
2663     *               11: PLL on/off according to the PMS
2664     * 3C5.2D[1:0] - ECK (Engine Clock) PLL Power Control
2665     *               0x: PLL power-off
2666     *               10: PLL always on
2667     *               11: PLL on/off according to the PMS */
2668    ViaSeqMask(hwp, 0x2D, 0x0C, 0x0C);
2669
2670    /* 3X5.6A[7] - Second Display Channel Enable
2671     *             0: Disable
2672     *             1: Enable
2673     * 3X5.6A[6] - Second Display Channel Reset
2674     *             0: Reset
2675     * 3X5.6A[5] - Second Display 8/6 Bits LUT
2676     *             0: 6-bit
2677     *             1: 8-bit
2678     * 3X5.6A[4] - Horizontal Count by 2
2679     *             0: Disable
2680     *             1: Enable
2681     * 3X5.6A[1] - LCD Gamma Enable
2682     *             0: Disable
2683     *             1: Enable
2684     * 3X5.6A[0] - LCD Pre-fetch Mode Enable
2685     *             0: Disable
2686     *             1: Enable */
2687    ViaCrtcMask(hwp, 0x6A, 0x80, 0xC1);
2688
2689    /* TV out uses division by 2 mode.
2690     * Other devices like analog (VGA), DVI, flat panel, etc.,
2691     * use normal mode. */
2692    /* 3X5.6B[5:4] - Second Display Channel Clock Mode Selection
2693     *               0x: Normal
2694     *               1x: Division by 2
2695     * 3X5.6B[2]   - IGA2 Screen Off
2696     *               0: Normal
2697     *               1: Screen off
2698     * 3X5.6B[1]   - IGA2 Screen Off Selection Method
2699     *               0: IGA2 Screen off
2700     *               1: IGA1 Screen off */
2701    ViaCrtcMask(hwp, 0x6B, 0x00, 0x36);
2702
2703    /* For UniChrome Pro and Chrome9. */
2704    if ((pVia->Chipset != VIA_CLE266)
2705        && (pVia->Chipset != VIA_KM400)) {
2706        /* The following register fields are for UniChrome Pro and Chrome9. */
2707        /* 3X5.6C[3:1] - LCDCK PLL Reference Clock Source Selection
2708         *               000: From XI pin
2709         *               001: From TVXI
2710         *               01x: From TVPLL
2711         *               100: DVP0TVCLKR
2712         *               101: DVP1TVCLKR
2713         *               110: CAP0 Clock
2714         *               111: CAP1 Clock
2715         * 3X5.6C[0]   - LCDCK Source Selection
2716         *               0: LCDCK PLL output clock
2717         *               1: LCDCK PLL reference clock */
2718        ViaCrtcMask(hwp, 0x6C, 0x00, 0x0F);
2719    }
2720
2721    /* Disable LCD scaling */
2722    /* 3X5.79[0] - LCD Scaling Enable
2723     *             0: Disable
2724     *             1: Enable */
2725    ViaCrtcMask(hwp, 0x79, 0x00, 0x01);
2726
2727    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2728                        "Exiting viaIGA2Init.\n"));
2729}
2730
2731void
2732viaIGA2SetFBStartingAddress(xf86CrtcPtr crtc, int x, int y)
2733{
2734    ScrnInfoPtr pScrn = crtc->scrn;
2735    vgaHWPtr hwp = VGAHWPTR(pScrn);
2736    drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
2737    drmmode_ptr drmmode = drmmode_crtc->drmmode;
2738    CARD32 Base, tmp;
2739    CARD8 cr62, cr63, cr64, cra3;
2740
2741    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2742                        "Entered viaIGA2SetFBStartingAddress.\n"));
2743
2744    Base = (y * pScrn->displayWidth + x) * (pScrn->bitsPerPixel / 8);
2745    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2746                        "Base Address: 0x%"PRIx32"\n",
2747                        (uint32_t)Base));
2748    Base = (Base + drmmode->front_bo->offset) >> 3;
2749    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2750                "DRI Base Address: 0x%"PRIx32"\n",
2751                (uint32_t)Base);
2752
2753    tmp = hwp->readCrtc(hwp, 0x62) & 0x01;
2754    tmp |= (Base & 0x7F) << 1;
2755    hwp->writeCrtc(hwp, 0x62, tmp);
2756
2757    hwp->writeCrtc(hwp, 0x63, (Base & 0x7F80) >> 7);
2758    hwp->writeCrtc(hwp, 0x64, (Base & 0x7F8000) >> 15);
2759    hwp->writeCrtc(hwp, 0xA3, (Base & 0x03800000) >> 23);
2760
2761#ifdef HAVE_DEBUG
2762    cr62 = hwp->readCrtc(hwp, 0x62);
2763    cr63 = hwp->readCrtc(hwp, 0x63);
2764    cr64 = hwp->readCrtc(hwp, 0x64);
2765    cra3 = hwp->readCrtc(hwp, 0xA3);
2766
2767    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2768                        "CR62: 0x%02X\n", cr62));
2769    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2770                        "CR63: 0x%02X\n", cr63));
2771    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2772                        "CR64: 0x%02X\n", cr64));
2773    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2774                        "CRA3: 0x%02X\n", cra3));
2775#endif
2776
2777    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2778                        "Exiting viaIGA2SetFBStartingAddress.\n"));
2779}
2780
2781void
2782viaIGA2SetDisplayRegister(ScrnInfoPtr pScrn, DisplayModePtr mode)
2783{
2784    VIAPtr pVia = VIAPTR(pScrn);
2785    vgaHWPtr hwp = VGAHWPTR(pScrn);
2786    CARD16 temp;
2787
2788    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2789                        "Entered viaIGA2SetDisplayRegister.\n"));
2790
2791    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2792                "Requested Screen Mode: %s\n", mode->name);
2793
2794    /* UniChrome Pro or later */
2795    if ((pVia->Chipset != VIA_CLE266) && (pVia->Chipset != VIA_KM400)) {
2796        /* Set IGA2 to linear mode. */
2797        /* 3X5.62[0] - IGA2 Address Mode Selection
2798         *             0: Linear
2799         *             1: Tile */
2800        ViaCrtcMask(hwp, 0x62, 0x00, 0x01);
2801    }
2802
2803    /* Keep interlace mode off. */
2804    /* 3X5.67[5] - Second Display Interlace Mode
2805     *             0: Off
2806     *             1: On */
2807    ViaCrtcMask(hwp, 0x67, 0x00, 0x20);
2808
2809
2810    /* Set IGA2 horizontal total pixels.*/
2811    /* Horizontal Total Period: 4096 - 1 (max) */
2812    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2813                        "IGA2 CrtcHTotal: %d\n", mode->CrtcHTotal));
2814    temp = mode->CrtcHTotal - 1;
2815
2816    /* 3X5.50[7:0] - Horizontal Total Period Bits [7:0] */
2817    hwp->writeCrtc(hwp, 0x50, temp & 0xFF);
2818
2819    /* 3X5.55[3:0] - Horizontal Total Period Bits [11:8] */
2820    ViaCrtcMask(hwp, 0x55, temp >> 8, 0x0F);
2821
2822
2823    /* Set IGA2 horizontal display end position. */
2824    /* Horizontal Active Data Period: 2048 - 1 (max) */
2825    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2826                        "IGA2 CrtcHDisplay: %d\n", mode->CrtcHDisplay));
2827    temp = mode->CrtcHDisplay - 1;
2828
2829    /* 3X5.51[7:0] - Horizontal Active Data Period Bits [7:0] */
2830    hwp->writeCrtc(hwp, 0x51, temp & 0xFF);
2831
2832    /* 3X5.55[6:4] - Horizontal Active Data Period Bits [10:8] */
2833    ViaCrtcMask(hwp, 0x55, temp >> 4, 0x70);
2834
2835    if (pVia->Chipset == VIA_VX900) {
2836        /* 3X5.55[7] - Horizontal Active Data Period Bits [11] */
2837        ViaCrtcMask(hwp, 0x55, temp >> 4, 0x80);
2838    }
2839
2840
2841    /* Set IGA2 horizontal blank start. */
2842    /* Subtracting 1 from CrtcHBlankStart appears to suppress some
2843     * monitors from reporting horizontal resolution that is 1 more
2844     * than the desired horizontal
2845     * resolution. (i.e., 1601 rather than 1600) */
2846    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2847                        "IGA2 CrtcHBlankStart: %d\n", mode->CrtcHBlankStart));
2848    temp = mode->CrtcHBlankStart - 1;
2849
2850    /* 3X5.52[7:0] - Horizontal Blanking Start Bits [7:0] */
2851    hwp->writeCrtc(hwp, 0x52, temp & 0xFF);
2852
2853    /* 3X5.54[2:0] - Horizontal Blanking Start Bits [10:8] */
2854    ViaCrtcMask(hwp, 0x54, temp >> 8, 0x07);
2855
2856    if (pVia->Chipset == VIA_VX900) {
2857        /* 3X5.6B[0] - Horizontal Blanking Start Bit [11] */
2858        ViaCrtcMask(hwp, 0x6B, temp >> 11, 0x01);
2859    }
2860
2861
2862    /* Set IGA2 horizontal blank end. */
2863    /* Horizontal Blanking End: 4096 - 1 (max) */
2864    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2865                        "IGA2 CrtcHBlankEnd: %d\n", mode->CrtcHBlankEnd));
2866    temp = mode->CrtcHBlankEnd - 1;
2867
2868    /* 3X5.53[7:0] - Horizontal Blanking End Bits [7:0] */
2869    hwp->writeCrtc(hwp, 0x53, temp & 0xFF);
2870
2871    /* 3X5.54[5:3] - Horizontal Blanking End Bits [10:8] */
2872    ViaCrtcMask(hwp, 0x54, temp >> 5, 0x38);
2873
2874    /* 3X5.5D[6] - Horizontal Blanking End Bit [11] */
2875    ViaCrtcMask(hwp, 0x5D, temp >> 5, 0x40);
2876
2877
2878    /* Set IGA2 horizontal synchronization start. */
2879    /* Horizontal Retrace Start: 2047 (max, UniChrome),
2880     *                           4095 (max, UniChrome Pro and Chrome9) */
2881    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2882                        "IGA2 CrtcHSyncStart: %d\n", mode->CrtcHSyncStart));
2883    temp = mode->CrtcHSyncStart;
2884
2885    /* 3X5.56[7:0] - Horizontal Retrace Start Bits [7:0] */
2886    hwp->writeCrtc(hwp, 0x56, temp & 0xFF);
2887
2888    /* 3X5.54[7:6] - Horizontal Retrace Start Bits [9:8] */
2889    ViaCrtcMask(hwp, 0x54, temp >> 2, 0xC0);
2890
2891    /* 3X5.5C[7] - Horizontal Retrace Start Bit [10] */
2892    ViaCrtcMask(hwp, 0x5C, temp >> 3, 0x80);
2893
2894    /* For UniChrome Pro and Chrome9. */
2895    if ((pVia->Chipset != VIA_CLE266)
2896        && (pVia->Chipset != VIA_KM400)) {
2897
2898        /* 3X5.5D[7] - Horizontal Retrace Start Bit [11] */
2899        ViaCrtcMask(hwp, 0x5D, temp >> 4, 0x80);
2900    }
2901
2902
2903    /* Set IGA2 horizontal synchronization end. */
2904    /* Horizontal Retrace End: 511 (max) */
2905    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2906                        "IGA2 CrtcHSyncEnd: %d\n", mode->CrtcHSyncEnd));
2907    temp = mode->CrtcHSyncEnd - 1;
2908
2909    /* 3X5.57[7:0] - Horizontal Retrace End Bits [7:0] */
2910    hwp->writeCrtc(hwp, 0x57, temp & 0xFF);
2911
2912    /* 3X5.5C[6] - Horizontal Retrace End Bit [8] */
2913    ViaCrtcMask(hwp, 0x5C, temp >> 2, 0x40);
2914
2915
2916    /* Set IGA2 vertical total pixels. */
2917    /* Vertical Total Period: 2048 - 1 (max) */
2918    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2919                        "IGA2 CrtcVTotal: %d\n", mode->CrtcVTotal));
2920    temp = mode->CrtcVTotal - 1;
2921
2922    /* 3X5.58[7:0] - Vertical Total Period Bits [7:0] */
2923    hwp->writeCrtc(hwp, 0x58, temp & 0xFF);
2924
2925    /* 3X5.5D[2:0] - Vertical Total Period Bits [10:8] */
2926    ViaCrtcMask(hwp, 0x5D, temp >> 8, 0x07);
2927
2928
2929    /* Set IGA2 vertical display end position. */
2930    /* Vertical Active Data Period: 2048 - 1 (max) */
2931    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2932                        "IGA2 CrtcVDisplay: %d\n", mode->CrtcVDisplay));
2933    temp = mode->CrtcVDisplay - 1;
2934
2935    /* 3X5.59[7:0] - Vertical Active Data Period Bits [7:0] */
2936    hwp->writeCrtc(hwp, 0x59, temp & 0xFF);
2937
2938    /* 3X5.5D[5:3] - Vertical Active Data Period Bits [10:8] */
2939    ViaCrtcMask(hwp, 0x5D, temp >> 5, 0x38);
2940
2941
2942    /* Set IGA2 vertical blank start. */
2943    /* Subtracting 1 from CrtcVBlankStart appears to suppress some
2944     * monitors from reporting vertical resolution that is 1 more
2945     * than the desired vertical resolution. (i.e., 1201 rather
2946     * than 1200) */
2947    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2948                        "IGA2 CrtcVBlankStart: %d\n", mode->CrtcVBlankStart));
2949    temp = mode->CrtcVBlankStart - 1;
2950
2951    /* 3X5.5A[7:0] - Vertical Blanking Start Bits [7:0] */
2952    hwp->writeCrtc(hwp, 0x5A, temp & 0xFF);
2953
2954    /* 3X5.5C[2:0] - Vertical Blanking Start Bits [10:8] */
2955    ViaCrtcMask(hwp, 0x5C, temp >> 8, 0x07);
2956
2957
2958    /* Set IGA2 vertical blank end. */
2959    /* Vertical Blanking End: 4096 - 1 (max) */
2960    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2961                        "IGA2 CrtcVBlankEnd: %d\n", mode->CrtcVBlankEnd));
2962    temp = mode->CrtcVBlankEnd - 1;
2963
2964    /* 3X5.5B[7:0] - Vertical Blanking End Bits [7:0] */
2965    hwp->writeCrtc(hwp, 0x5B, temp & 0xFF);
2966
2967    /* 3X5.5C[5:3] - Vertical Blanking End Bits [10:8] */
2968    ViaCrtcMask(hwp, 0x5C, temp >> 5, 0x38);
2969
2970
2971    /* Set IGA2 vertical synchronization start. */
2972    /* Horizontal Retrace Start: 2047 (max) */
2973    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2974                        "IGA2 CrtcVSyncStart: %d\n", mode->CrtcVSyncStart));
2975    temp = mode->CrtcVSyncStart;
2976
2977    /* 3X5.5E[7:0] - Vertical Retrace Start Bits [7:0] */
2978    hwp->writeCrtc(hwp, 0x5E, temp & 0xFF);
2979
2980    /* 3X5.5F[7:5] - Vertical Retrace Start Bits [10:8] */
2981    ViaCrtcMask(hwp, 0x5F, temp >> 3, 0xE0);
2982
2983
2984    /* Set IGA2 vertical synchronization end. */
2985    /* Vertical Retrace End: 32 (max) */
2986    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2987                        "IGA2 CrtcVSyncEnd: %d\n", mode->CrtcVSyncEnd));
2988    temp = mode->CrtcVSyncEnd - 1;
2989
2990    /*3X5.5F[4:0] - Vertical Retrace End Bits [4:0] */
2991    ViaCrtcMask(hwp, 0x5F, temp & 0x1F, 0x1F);
2992
2993
2994    /* Set IGA2 horizontal offset adjustment. */
2995    temp = (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3)) >> 3;
2996
2997    /* 3X5.66[7:0] - Second Display Horizontal Offset Bits [7:0] */
2998    hwp->writeCrtc(hwp, 0x66, temp & 0xFF);
2999
3000    /* 3X5.67[1:0] - Second Display Horizontal Offset Bits [9:8] */
3001    ViaCrtcMask(hwp, 0x67, temp >> 8, 0x03);
3002
3003
3004    /* Set IGA2 fetch count. */
3005    temp = (mode->CrtcHDisplay * (pScrn->bitsPerPixel >> 3)) >> 4;
3006
3007    /* 3X5.65[7:0] - Second Display Horizontal
3008     *               2-Quadword Count Data Bits [7:0] */
3009    hwp->writeCrtc(hwp, 0x65, temp & 0xFF);
3010
3011    /* 3X5.67[3:2] - Second Display Horizontal
3012     *               2-Quadword Count Data Bits [9:8] */
3013    ViaCrtcMask(hwp, 0x67, temp >> 6, 0x0C);
3014
3015    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3016                        "Exiting viaIGA2SetDisplayRegister.\n"));
3017}
3018
3019static ModeStatus
3020viaIGA2ModeValid(ScrnInfoPtr pScrn, DisplayModePtr mode)
3021{
3022    VIAPtr pVia = VIAPTR(pScrn);
3023
3024    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3025                        "Entered viaIGA2ModeValid.\n"));
3026
3027    if (mode->CrtcHTotal > 4096)
3028        return MODE_BAD_HVALUE;
3029
3030    if (((pVia->Chipset != VIA_VX900)
3031            && (mode->CrtcHDisplay > 2048))
3032        || ((pVia->Chipset == VIA_VX900)
3033            && (mode->CrtcHDisplay > 4096)))
3034        return MODE_BAD_HVALUE;
3035
3036    if (((pVia->Chipset != VIA_VX900)
3037            && (mode->CrtcHBlankStart > 2048))
3038        || ((pVia->Chipset == VIA_VX900)
3039            && (mode->CrtcHBlankStart > 4096)))
3040        return MODE_BAD_HVALUE;
3041
3042    if (mode->CrtcHBlankEnd > 4096)
3043        return MODE_HBLANK_WIDE;
3044
3045    if ((((pVia->Chipset == VIA_CLE266) || (pVia->Chipset == VIA_KM400))
3046            && (mode->CrtcHSyncStart > 2048))
3047        || (((pVia->Chipset != VIA_CLE266) && (pVia->Chipset != VIA_KM400))
3048            && (mode->CrtcHSyncStart > 4096)))
3049        return MODE_BAD_HVALUE;
3050
3051    if ((mode->CrtcHSyncEnd - mode->CrtcHSyncStart) > 512)
3052        return MODE_HSYNC_WIDE;
3053
3054    if (mode->CrtcVTotal > 2048)
3055        return MODE_BAD_VVALUE;
3056
3057    if (mode->CrtcVDisplay > 2048)
3058        return MODE_BAD_VVALUE;
3059
3060    if (mode->CrtcVBlankStart > 2048)
3061        return MODE_BAD_VVALUE;
3062
3063    if (mode->CrtcVBlankEnd > 2048)
3064        return MODE_VBLANK_WIDE;
3065
3066    if (mode->CrtcVSyncStart > 2048)
3067        return MODE_BAD_VVALUE;
3068
3069    if ((mode->CrtcVSyncEnd - mode->CrtcVSyncStart) > 32)
3070        return MODE_VSYNC_WIDE;
3071
3072    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3073                        "Exiting viaIGA2ModeValid.\n"));
3074    return MODE_OK;
3075}
3076
3077/*
3078 * I've thrown out the LCD requirement. Size > 1024 is not supported
3079 * by any currently known TV encoder anyway. -- Luc.
3080 *
3081 */
3082static void
3083ViaSetSecondaryFIFO(ScrnInfoPtr pScrn, DisplayModePtr mode)
3084{
3085    vgaHWPtr hwp = VGAHWPTR(pScrn);
3086    VIAPtr pVia = VIAPTR(pScrn);
3087
3088    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaSetSecondaryFIFO\n"));
3089
3090    switch (pVia->Chipset) {
3091        case VIA_CLE266:
3092            if (CLE266_REV_IS_CX(pVia->ChipRev)) {
3093                if (mode->HDisplay >= 1024) {
3094                    ViaCrtcMask(hwp, 0x6A, 0x20, 0x20);
3095                    hwp->writeCrtc(hwp, 0x68, 0xAB);/* depth 10, threshold 11 */
3096                } else {
3097                    ViaCrtcMask(hwp, 0x6A, 0x00, 0x20);
3098                    hwp->writeCrtc(hwp, 0x68, 0x67);/* depth 6, threshold 7 */
3099                }
3100            } else {
3101                if ((pScrn->bitsPerPixel >= 24)
3102                    && (((mode->VDisplay > 768)
3103                         && (pVia->MemClk <= VIA_MEM_DDR200)) ||
3104                        ((mode->HDisplay > 1280)
3105                         && (pVia->MemClk <= VIA_MEM_DDR266)))) {
3106                    ViaCrtcMask(hwp, 0x6A, 0x20, 0x20);
3107                    hwp->writeCrtc(hwp, 0x68, 0xAB);/* depth 10, threshold 11 */
3108                } else {
3109                    ViaCrtcMask(hwp, 0x6A, 0x00, 0x20);
3110                    hwp->writeCrtc(hwp, 0x68, 0x67);/* depth 6, threshold 7 */
3111                }
3112            }
3113            break;
3114        case VIA_KM400:
3115            if ((mode->HDisplay >= 1600) && (pVia->MemClk <= VIA_MEM_DDR200)) {
3116                ViaCrtcMask(hwp, 0x6A, 0x20, 0x20);
3117                hwp->writeCrtc(hwp, 0x68, 0xEB);  /* depth 14, threshold 11 */
3118            } else if ((pScrn->bitsPerPixel == 32)
3119                       && (((mode->HDisplay > 1024)
3120                            && (pVia->MemClk <= VIA_MEM_DDR333)) ||
3121                           ((mode->HDisplay >= 1024)
3122                            && (pVia->MemClk <= VIA_MEM_DDR200)))) {
3123                ViaCrtcMask(hwp, 0x6A, 0x20, 0x20);
3124                hwp->writeCrtc(hwp, 0x68, 0xCA);  /* depth 12, threshold 10 */
3125            } else if ((pScrn->bitsPerPixel == 16)
3126                       && (((mode->HDisplay > 1280)
3127                            && (pVia->MemClk <= VIA_MEM_DDR333)) ||
3128                           ((mode->HDisplay >= 1280)
3129                            && (pVia->MemClk <= VIA_MEM_DDR200)))) {
3130                ViaCrtcMask(hwp, 0x6A, 0x20, 0x20);
3131                hwp->writeCrtc(hwp, 0x68, 0xAB);  /* depth 10, threshold 11 */
3132            } else {
3133                ViaCrtcMask(hwp, 0x6A, 0x00, 0x20);
3134                hwp->writeCrtc(hwp, 0x68, 0x67);  /* depth 6, threshold 7 */
3135            }
3136            break;
3137        case VIA_K8M800:
3138            /* depth: (384 /8 -1 -1) = 46 = 0x2E */
3139            ViaCrtcMask(hwp, 0x68, 0xE0, 0xF0);
3140            ViaCrtcMask(hwp, 0x94, 0x00, 0x80);
3141            ViaCrtcMask(hwp, 0x95, 0x80, 0x80);
3142
3143            /* threshold: (328/4) = 82 = 0x52 */
3144            ViaCrtcMask(hwp, 0x68, 0x02, 0x0F);
3145            ViaCrtcMask(hwp, 0x95, 0x50, 0x70);
3146
3147            /* preq: 74 = 0x4A */
3148            ViaCrtcMask(hwp, 0x92, 0x0A, 0x0F);
3149            ViaCrtcMask(hwp, 0x95, 0x04, 0x07);
3150
3151            if ((mode->HDisplay >= 1400) && (pScrn->bitsPerPixel == 32))
3152                ViaCrtcMask(hwp, 0x94, 0x10, 0x7F);  /* 64/4 */
3153            else
3154                ViaCrtcMask(hwp, 0x94, 0x20, 0x7F);  /* 128/4 */
3155            break;
3156        case VIA_PM800:
3157            /* depth: 12 - 1 = 0x0B */
3158            ViaCrtcMask(hwp, 0x68, 0xB0, 0xF0);
3159            ViaCrtcMask(hwp, 0x94, 0x00, 0x80);
3160            ViaCrtcMask(hwp, 0x95, 0x00, 0x80);
3161
3162            /* threshold: 16 = 0x10 */
3163            ViaCrtcMask(hwp, 0x68, 0x00, 0x0F);
3164            ViaCrtcMask(hwp, 0x95, 0x10, 0x70);
3165
3166            /* preq: 8 = 0x08 */
3167            ViaCrtcMask(hwp, 0x92, 0x08, 0x0F);
3168            ViaCrtcMask(hwp, 0x95, 0x00, 0x07);
3169
3170            if ((mode->HDisplay >= 1400) && (pScrn->bitsPerPixel == 32))
3171                ViaCrtcMask(hwp, 0x94, 0x10, 0x7F);  /* 64/4 */
3172            else
3173                ViaCrtcMask(hwp, 0x94, 0x20, 0x7F);  /* 128/4 */
3174            break;
3175        case VIA_P4M800PRO:
3176            ViaCrtcMask(hwp, 0x68, 0xA0, 0xF0);
3177            ViaCrtcMask(hwp, 0x94, 0x00, 0x80);
3178            ViaCrtcMask(hwp, 0x95, 0x00, 0x80);
3179
3180            ViaCrtcMask(hwp, 0x68, 0x04, 0x0F);
3181            ViaCrtcMask(hwp, 0x95, 0x10, 0x70);
3182
3183            ViaCrtcMask(hwp, 0x92, 0x08, 0x0F);
3184            ViaCrtcMask(hwp, 0x95, 0x00, 0x07);
3185
3186            if ((mode->HDisplay >= 1400) && (pScrn->bitsPerPixel == 32))
3187                ViaCrtcMask(hwp, 0x94, 0x10, 0x7F);
3188            else
3189                ViaCrtcMask(hwp, 0x94, 0x20, 0x7F);
3190            break;
3191        case VIA_P4M890:
3192            /* depth location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
3193            ViaCrtcMask(hwp, 0x68, 0xB0, 0xF0); /* 96/8-1 = 11  = 0x0B */
3194            ViaCrtcMask(hwp, 0x94, 0x00, 0x80);
3195            ViaCrtcMask(hwp, 0x95, 0x00, 0x80);
3196
3197            /* location: {CR68,0,3},{CR95,4,6} */
3198            ViaCrtcMask(hwp, 0x68, 0x03, 0x0F); /* 76/4   = 19  = 0x13 */
3199            ViaCrtcMask(hwp, 0x95, 0x10, 0x70);
3200
3201            /* location: {CR92,0,3},{CR95,0,2} */
3202            ViaCrtcMask(hwp, 0x92, 0x00, 0x0F); /* 64/4   = 16  = 0x10 */
3203            ViaCrtcMask(hwp, 0x95, 0x01, 0x07);
3204
3205            /* location: {CR94,0,6} */
3206            ViaCrtcMask(hwp, 0x94, 0x08, 0x7F); /* 32/4   = 8   = 0x08 */
3207            break;
3208        case VIA_K8M890:
3209            /* Display Queue Depth, location: {CR68,4,7},{CR94,7,7},{CR95,7,7} */
3210            ViaCrtcMask(hwp, 0x68, 0xC0, 0xF0); /* 360/8-1 = 44  = 0x2C; 0x2C << 4 = 0xC0 */
3211            ViaCrtcMask(hwp, 0x94, 0x00, 0x80); /* 0x2C << 3 = 0x00 */
3212            ViaCrtcMask(hwp, 0x95, 0x80, 0x80); /* 0x2C << 2 = 0x80 */
3213
3214            /* Display Queue Read Threshold 1, location: {CR68,0,3},{CR95,4,6} */
3215            ViaCrtcMask(hwp, 0x68, 0x02, 0x0F); /* 328/4   = 82  = 0x52 */
3216            ViaCrtcMask(hwp, 0x95, 0x50, 0x70);
3217
3218            /* location: {CR92,0,3},{CR95,0,2} */
3219            ViaCrtcMask(hwp, 0x92, 0x0A, 0x0F); /* 296/4   = 74  = 0x4A */
3220            ViaCrtcMask(hwp, 0x95, 0x04, 0x07); /* 0x4A >> 4 = 0x04 */
3221
3222            /* Display Expire Number Bits, location: {CR94,0,6} */
3223            ViaCrtcMask(hwp, 0x94, 0x1F, 0x7F); /* 124/4   = 31  = 0x1F */
3224            break;
3225        case VIA_P4M900:
3226            ViaCrtcMask(hwp, 0x68, 0xB0, 0xF0);
3227            ViaCrtcMask(hwp, 0x94, 0x00, 0x80);
3228            ViaCrtcMask(hwp, 0x95, 0x00, 0x80);
3229
3230            ViaCrtcMask(hwp, 0x68, 0x03, 0x0F);
3231            ViaCrtcMask(hwp, 0x95, 0x10, 0x70);
3232            ViaCrtcMask(hwp, 0x92, 0x03, 0x0F);
3233            ViaCrtcMask(hwp, 0x95, 0x01, 0x07);
3234            ViaCrtcMask(hwp, 0x94, 0x08, 0x7F);
3235            break;
3236        case VIA_CX700:
3237            ViaCrtcMask(hwp, 0x68, 0xA0, 0xF0);
3238            ViaCrtcMask(hwp, 0x94, 0x00, 0x80);
3239            ViaCrtcMask(hwp, 0x95, 0x00, 0x80);
3240
3241            ViaCrtcMask(hwp, 0x68, 0x04, 0x0F);
3242            ViaCrtcMask(hwp, 0x95, 0x10, 0x70);
3243
3244            ViaCrtcMask(hwp, 0x92, 0x08, 0x0F);
3245            ViaCrtcMask(hwp, 0x95, 0x00, 0x07);
3246
3247            if ((mode->HDisplay >= 1400) && (pScrn->bitsPerPixel == 32))
3248                ViaCrtcMask(hwp, 0x94, 0x10, 0x7F);
3249            else
3250                ViaCrtcMask(hwp, 0x94, 0x20, 0x7F);
3251            break;
3252        case VIA_VX800:
3253            /* {CR68,4,7},{CR94,7,7},{CR95,7,7} : 96/8-1 = 0x0B */
3254            ViaCrtcMask(hwp, 0x68, 0xB0, 0xF0); /* ((0x0B & 0x0F) << 4)) = 0xB0 */
3255            ViaCrtcMask(hwp, 0x94, 0x00, 0x80); /* ((0x0B & 0x10) << 3)) = 0x00 */
3256            ViaCrtcMask(hwp, 0x95, 0x00, 0x80);
3257            /* {CR68,0,3},{CR95,4,6} : 64/4 = 0x10 */
3258            ViaCrtcMask(hwp, 0x68, 0x04, 0x0F);
3259            ViaCrtcMask(hwp, 0x95, 0x10, 0x70);
3260            /* {CR92,0,3},{CR95,0,2} : 32/4 = 0x08 */
3261            ViaCrtcMask(hwp, 0x92, 0x08, 0x0F);
3262            ViaCrtcMask(hwp, 0x95, 0x00, 0x07);
3263            /* {CR94,0,6} : 128/4 = 0x20 */
3264            if ((mode->HDisplay >= 1400) && (pScrn->bitsPerPixel == 32))
3265                ViaCrtcMask(hwp, 0x94, 0x10, 0x7F);
3266            else
3267                ViaCrtcMask(hwp, 0x94, 0x20, 0x7F);
3268            break;
3269        case VIA_VX855:
3270            /* {CR68,4,7},{CR94,7,7},{CR95,7,7} : 200/8-1 = 24 = 0x18 */
3271            ViaCrtcMask(hwp, 0x68, 0x80, 0xF0); /* ((0x18 & 0x0F) << 4)) = 0x80 */
3272            ViaCrtcMask(hwp, 0x94, 0x80, 0x80); /* ((0x18 & 0x10) << 3)) = 0x80 */
3273            ViaCrtcMask(hwp, 0x95, 0x00, 0x80); /* ((0x18 & 0x20) << 2)) = 0x00 */
3274            /* {CR68,0,3},{CR95,4,6} : 160/4 = 0x28 */
3275            ViaCrtcMask(hwp, 0x68, 0x08, 0x0F); /* (0x28 & 0x0F) = 0x08 */
3276            ViaCrtcMask(hwp, 0x95, 0x20, 0x70); /* (0x28 & 0x70) = 0x20 */
3277            /* {CR92,0,3},{CR95,0,2} : 160/4 = 0x28 */
3278            ViaCrtcMask(hwp, 0x92, 0x08, 0x08); /* (0x28 & 0x0F) = 0x08 */
3279            ViaCrtcMask(hwp, 0x95, 0x02, 0x07); /* ((0x28 & 0x70) >> 4)) = 0x02 */
3280            /* {CR94,0,6} : 320/4 = 0x50 */
3281            if ((mode->HDisplay >= 1400) && (pScrn->bitsPerPixel == 32))
3282                ViaCrtcMask(hwp, 0x94, 0x08, 0x7F);
3283            else
3284                ViaCrtcMask(hwp, 0x94, 0x08, 0x7F);
3285            break;
3286        case VIA_VX900:
3287            /* {CR68,4,7},{CR94,7,7},{CR95,7,7} : 192/8-1 = 23 = 0x17 */
3288            ViaCrtcMask(hwp, 0x68, 0x70, 0xF0); /* ((0x17 & 0x0F) << 4)) = 0x70 */
3289            ViaCrtcMask(hwp, 0x94, 0x80, 0x80); /* ((0x17 & 0x10) << 3)) = 0x80 */
3290            ViaCrtcMask(hwp, 0x95, 0x00, 0x80); /* ((0x17 & 0x20) << 2)) = 0x00 */
3291            /* {CR68,0,3},{CR95,4,6} : 160/4 = 0x28 */
3292            ViaCrtcMask(hwp, 0x68, 0x08, 0x0F); /* (0x28 & 0x0F) = 0x08 */
3293            ViaCrtcMask(hwp, 0x95, 0x20, 0x70); /* (0x28 & 0x70) = 0x20 */
3294            /* {CR92,0,3},{CR95,0,2} : 160/4 = 0x28 */
3295            ViaCrtcMask(hwp, 0x92, 0x08, 0x08); /* (0x28 & 0x0F) = 0x08 */
3296            ViaCrtcMask(hwp, 0x95, 0x02, 0x07); /* ((0x28 & 0x70) >> 4)) = 0x2 */
3297            /* {CR94,0,6} : 320/4 = 0x50 */
3298            if ((mode->HDisplay >= 1400) && (pScrn->bitsPerPixel == 32))
3299                ViaCrtcMask(hwp, 0x94, 0x08, 0x7F);
3300            else
3301                ViaCrtcMask(hwp, 0x94, 0x08, 0x7F);
3302            break;
3303        default:
3304            xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ViaSetSecondaryFIFO: "
3305                       "Chipset %d not implemented\n", pVia->Chipset);
3306            break;
3307    }
3308}
3309
3310void
3311viaIGA2Save(ScrnInfoPtr pScrn)
3312{
3313    vgaHWPtr hwp = VGAHWPTR(pScrn);
3314    VIAPtr pVia = VIAPTR(pScrn);
3315    VIARegPtr Regs = &pVia->SavedReg;
3316    int i;
3317
3318    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3319                        "Entered viaIGA2Save.\n"));
3320
3321    vgaHWProtect(pScrn, TRUE);
3322
3323    vgaHWSave(pScrn, &hwp->SavedReg, VGA_SR_ALL);
3324
3325    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3326                        "Saving IGA2 registers.\n"));
3327
3328    /* Unlock extended registers. */
3329    hwp->writeSeq(hwp, 0x10, 0x01);
3330
3331    for (i = 0; i < (0x88 - 0x50 + 1); i++) {
3332        Regs->CR[i + 0x50] = hwp->readCrtc(hwp, i + 0x50);
3333    }
3334
3335    for (i = 0; i < (0x92 - 0x8A + 1); i++) {
3336        Regs->CR[i + 0x8A] = hwp->readCrtc(hwp, i + 0x8A);
3337    }
3338
3339    for (i = 0; i < (0xA3 - 0x94 + 1); i++) {
3340        Regs->CR[i + 0x94] = hwp->readCrtc(hwp, i + 0x94);
3341    }
3342
3343    Regs->CR[0xA4] = hwp->readCrtc(hwp, 0xA4);
3344
3345    for (i = 0; i < (0xAC - 0xA5 + 1); i++) {
3346        Regs->CR[i + 0xA5] = hwp->readCrtc(hwp, i + 0xA5);
3347    }
3348
3349    /* Chrome 9 */
3350    switch (pVia->Chipset) {
3351    case VIA_K8M890:
3352    case VIA_P4M900:
3353    case VIA_VX800:
3354    case VIA_VX855:
3355    case VIA_VX900:
3356        Regs->CR[0xAF] = hwp->readCrtc(hwp, 0xAF);
3357        break;
3358    default:
3359        break;
3360    }
3361
3362    /* Chrome 9, Chrome 9 HC, and Chrome 9 HC3 */
3363    switch (pVia->Chipset) {
3364    case VIA_K8M890:
3365    case VIA_P4M900:
3366    case VIA_VX800:
3367        for (i = 0; i < (0xCD - 0xB0 + 1); i++) {
3368            Regs->CR[i + 0xB0] = hwp->readCrtc(hwp, i + 0xB0);
3369        }
3370
3371        break;
3372    default:
3373        break;
3374    }
3375
3376    switch (pVia->Chipset) {
3377
3378    /* UniChrome Pro and UniChrome Pro II */
3379    case VIA_PM800:
3380    case VIA_K8M800:
3381    case VIA_P4M800PRO:
3382    case VIA_CX700:
3383    case VIA_P4M890:
3384        for (i = 0; i < (0xD7 - 0xD0 + 1); i++) {
3385            Regs->CR[i + 0xD0] = hwp->readCrtc(hwp, i + 0xD0);
3386        }
3387
3388        break;
3389
3390    /* Chrome 9 */
3391    case VIA_K8M890:
3392    case VIA_P4M900:
3393    case VIA_VX800:
3394    case VIA_VX855:
3395    case VIA_VX900:
3396        for (i = 0; i < (0xEC - 0xD0 + 1); i++) {
3397            Regs->CR[i + 0xD0] = hwp->readCrtc(hwp, i + 0xD0);
3398        }
3399
3400        break;
3401    default:
3402        break;
3403    }
3404
3405    /* Chrome 9 */
3406    switch (pVia->Chipset) {
3407    case VIA_K8M890:
3408    case VIA_P4M900:
3409    case VIA_VX800:
3410    case VIA_VX855:
3411    case VIA_VX900:
3412        for (i = 0; i < (0xF5 - 0xF0 + 1); i++) {
3413            Regs->CR[i + 0xF0] = hwp->readCrtc(hwp, i + 0xF0);
3414        }
3415
3416        break;
3417    default:
3418        break;
3419    }
3420
3421    /* Chrome 9 HCM and Chrome 9 HD */
3422    if ((pVia->Chipset == VIA_VX855) || (pVia->Chipset == VIA_VX900)) {
3423        for (i = 0; i < (0xFC - 0xF6 + 1); i++) {
3424            Regs->CR[i + 0xF6] = hwp->readCrtc(hwp, i + 0xF6);
3425        }
3426    }
3427
3428    /* Chrome 9 HD */
3429    if (pVia->Chipset == VIA_VX900) {
3430        Regs->CR[0xFD] = hwp->readCrtc(hwp, 0xFD);
3431    }
3432
3433    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3434                        "Finished saving IGA2 registers.\n"));
3435
3436    vgaHWProtect(pScrn, FALSE);
3437
3438    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3439                        "Exiting viaIGA2Save.\n"));
3440}
3441
3442void
3443viaIGA2Restore(ScrnInfoPtr pScrn)
3444{
3445    vgaHWPtr hwp = VGAHWPTR(pScrn);
3446    VIAPtr pVia = VIAPTR(pScrn);
3447    VIARegPtr Regs = &pVia->SavedReg;
3448    int i;
3449
3450    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3451                        "Entered viaIGA2Restore.\n"));
3452
3453    vgaHWProtect(pScrn, TRUE);
3454
3455    vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_ALL);
3456
3457    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3458                        "Restoring IGA2 registers.\n"));
3459
3460    /* Unlock extended registers. */
3461    hwp->writeSeq(hwp, 0x10, 0x01);
3462
3463    for (i = 0; i < (0x5F - 0x50 + 1); i++) {
3464        hwp->writeCrtc(hwp, i + 0x50, Regs->CR[i + 0x50]);
3465    }
3466
3467    for (i = 0; i < (0x69 - 0x62 + 1); i++) {
3468        hwp->writeCrtc(hwp, i + 0x62, Regs->CR[i + 0x62]);
3469    }
3470
3471    hwp->writeCrtc(hwp, 0x6A, Regs->CR[0x6A]);
3472    hwp->writeCrtc(hwp, 0x6B, Regs->CR[0x6B]);
3473    hwp->writeCrtc(hwp, 0x6C, Regs->CR[0x6C]);
3474
3475    for (i = 0; i < (0x88 - 0x6D + 1); i++) {
3476        hwp->writeCrtc(hwp, i + 0x6D, Regs->CR[i + 0x6D]);
3477    }
3478
3479    for (i = 0; i < (0x92 - 0x8A + 1); i++) {
3480        hwp->writeCrtc(hwp, i + 0x8A, Regs->CR[i + 0x8A]);
3481    }
3482
3483    for (i = 0; i < (0xA3 - 0x94 + 1); i++) {
3484        hwp->writeCrtc(hwp, i + 0x94, Regs->CR[i + 0x94]);
3485    }
3486
3487    /* UniChrome Pro and UniChrome Pro II */
3488    switch (pVia->Chipset) {
3489    case VIA_PM800:
3490    case VIA_K8M800:
3491    case VIA_P4M800PRO:
3492    case VIA_CX700:
3493    case VIA_P4M890:
3494        hwp->writeCrtc(hwp, 0xA4, Regs->CR[0xA4]);
3495        break;
3496    default:
3497        break;
3498    }
3499
3500    for (i = 0; i < (0xAC - 0xA5 + 1); i++) {
3501        hwp->writeCrtc(hwp, i + 0xA5, Regs->CR[i + 0xA5]);
3502    }
3503
3504    /* Chrome 9 */
3505    switch (pVia->Chipset) {
3506    case VIA_K8M890:
3507    case VIA_P4M900:
3508    case VIA_VX800:
3509    case VIA_VX855:
3510    case VIA_VX900:
3511        hwp->writeCrtc(hwp, 0xAF, Regs->CR[0xAF]);
3512        break;
3513    default:
3514        break;
3515    }
3516
3517    /* Chrome 9, Chrome 9 HC, and Chrome 9 HC3 */
3518    switch (pVia->Chipset) {
3519    case VIA_K8M890:
3520    case VIA_P4M900:
3521    case VIA_VX800:
3522        for (i = 0; i < (0xCD - 0xB0 + 1); i++) {
3523            hwp->writeCrtc(hwp, i + 0xB0, Regs->CR[i + 0xB0]);
3524        }
3525
3526        break;
3527    default:
3528        break;
3529    }
3530
3531    switch (pVia->Chipset) {
3532    /* UniChrome Pro and UniChrome Pro II */
3533    case VIA_PM800:
3534    case VIA_K8M800:
3535    case VIA_P4M800PRO:
3536    case VIA_CX700:
3537    case VIA_P4M890:
3538        for (i = 0; i < (0xD7 - 0xD0 + 1); i++) {
3539            hwp->writeCrtc(hwp, i + 0xD0, Regs->CR[i + 0xD0]);
3540        }
3541
3542        break;
3543
3544    /* Chrome 9 */
3545    case VIA_K8M890:
3546    case VIA_P4M900:
3547    case VIA_VX800:
3548    case VIA_VX855:
3549    case VIA_VX900:
3550        for (i = 0; i < (0xEC - 0xD0 + 1); i++) {
3551            hwp->writeCrtc(hwp, i + 0xD0, Regs->CR[i + 0xD0]);
3552        }
3553
3554        break;
3555    default:
3556        break;
3557    }
3558
3559    /* Chrome 9 */
3560    switch (pVia->Chipset) {
3561    case VIA_K8M890:
3562    case VIA_P4M900:
3563    case VIA_VX800:
3564    case VIA_VX855:
3565    case VIA_VX900:
3566        for (i = 0; i < (0xF5 - 0xF0 + 1); i++) {
3567            hwp->writeCrtc(hwp, i + 0xF0, Regs->CR[i + 0xF0]);
3568        }
3569
3570        break;
3571    default:
3572        break;
3573    }
3574
3575    /* Chrome 9 HCM and Chrome 9 HD */
3576    if ((pVia->Chipset == VIA_VX855) || (pVia->Chipset == VIA_VX900)) {
3577        for (i = 0; i < (0xFC - 0xF6 + 1); i++) {
3578            hwp->writeCrtc(hwp, i + 0xF6, Regs->CR[i + 0xF6]);
3579        }
3580    }
3581
3582    /* Chrome 9 HD */
3583    if (pVia->Chipset == VIA_VX900) {
3584        hwp->writeCrtc(hwp, 0xFD, Regs->CR[0xFD]);
3585    }
3586
3587    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3588                        "Finished restoring IGA2 registers.\n"));
3589
3590    vgaHWProtect(pScrn, FALSE);
3591
3592    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3593                        "Exiting viaIGA2Restore.\n"));
3594}
3595
3596/*
3597 * Not tested yet
3598 */
3599void
3600ViaShadowCRTCSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
3601{
3602    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ViaShadowCRTCSetMode\n"));
3603
3604    vgaHWPtr hwp = VGAHWPTR(pScrn);
3605    CARD16 temp;
3606
3607    temp = (mode->CrtcHTotal >> 3) - 5;
3608    hwp->writeCrtc(hwp, 0x6D, temp & 0xFF);
3609    ViaCrtcMask(hwp, 0x71, temp >> 5, 0x08);
3610
3611    temp = (mode->CrtcHBlankEnd >> 3) - 1;
3612    hwp->writeCrtc(hwp, 0x6E, temp & 0xFF);
3613
3614    temp = mode->CrtcVTotal - 2;
3615    hwp->writeCrtc(hwp, 0x6F, temp & 0xFF);
3616    ViaCrtcMask(hwp, 0x71, temp >> 8, 0x07);
3617
3618    temp = mode->CrtcVDisplay - 1;
3619    hwp->writeCrtc(hwp, 0x70, temp & 0xFF);
3620    ViaCrtcMask(hwp, 0x71, temp >> 4, 0x70);
3621
3622    temp = mode->CrtcVBlankStart - 1;
3623    hwp->writeCrtc(hwp, 0x72, temp & 0xFF);
3624    ViaCrtcMask(hwp, 0x74, temp >> 4, 0x70);
3625
3626    temp = mode->CrtcVTotal - 1;
3627    hwp->writeCrtc(hwp, 0x73, temp & 0xFF);
3628    ViaCrtcMask(hwp, 0x74, temp >> 8, 0x07);
3629
3630    ViaCrtcMask(hwp, 0x76, mode->CrtcVSyncEnd, 0x0F);
3631
3632    temp = mode->CrtcVSyncStart;
3633    hwp->writeCrtc(hwp, 0x75, temp & 0xFF);
3634    ViaCrtcMask(hwp, 0x76, temp >> 4, 0x70);
3635}
3636
3637static void
3638iga1_crtc_dpms(xf86CrtcPtr crtc, int mode)
3639{
3640    ScrnInfoPtr pScrn = crtc->scrn;
3641
3642    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3643                        "Entered iga1_crtc_dpms.\n"));
3644
3645    switch (mode) {
3646    case DPMSModeOn:
3647        viaIGA1DPMSControl(pScrn, 0x00);
3648        break;
3649
3650    case DPMSModeStandby:
3651        viaIGA1DPMSControl(pScrn, 0x01);
3652        break;
3653
3654    case DPMSModeSuspend:
3655        viaIGA1DPMSControl(pScrn, 0x02);
3656        break;
3657
3658    case DPMSModeOff:
3659        viaIGA1DPMSControl(pScrn, 0x03);
3660        break;
3661
3662    default:
3663        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid DPMS Mode: %d\n",
3664                    mode);
3665        break;
3666    }
3667    //vgaHWSaveScreen(pScrn->pScreen, mode);
3668
3669    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3670                        "Exiting iga1_crtc_dpms.\n"));
3671}
3672
3673static void
3674iga1_crtc_save(xf86CrtcPtr crtc)
3675{
3676    ScrnInfoPtr pScrn = crtc->scrn;
3677
3678    viaIGA1Save(pScrn);
3679}
3680
3681static void
3682iga1_crtc_restore(xf86CrtcPtr crtc)
3683{
3684    ScrnInfoPtr pScrn = crtc->scrn;
3685
3686    viaIGA1Restore(pScrn);
3687}
3688
3689static Bool
3690iga1_crtc_lock(xf86CrtcPtr crtc)
3691{
3692    return FALSE;
3693}
3694
3695static void
3696iga1_crtc_unlock(xf86CrtcPtr crtc)
3697{
3698}
3699
3700static Bool
3701iga1_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
3702                        DisplayModePtr adjusted_mode)
3703{
3704    ScrnInfoPtr pScrn = crtc->scrn;
3705    VIAPtr pVia = VIAPTR(pScrn);
3706    CARD32 temp;
3707    ModeStatus modestatus;
3708
3709    if ((mode->Clock < pScrn->clockRanges->minClock) ||
3710        (mode->Clock > pScrn->clockRanges->maxClock)) {
3711        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3712                   "Clock for mode \"%s\" outside of allowed range (%u (%u - %u))\n",
3713                   mode->name, mode->Clock, pScrn->clockRanges->minClock,
3714                   pScrn->clockRanges->maxClock);
3715        return FALSE;
3716    }
3717
3718    modestatus = viaIGA1ModeValid(pScrn, mode);
3719    if (modestatus != MODE_OK) {
3720        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Not using mode \"%s\" : %s.\n",
3721                   mode->name, xf86ModeStatusToString(modestatus));
3722        return FALSE;
3723    }
3724
3725    temp = mode->CrtcHDisplay * mode->CrtcVDisplay * mode->VRefresh *
3726            (pScrn->bitsPerPixel >> 3);
3727    if (pVia->pBIOSInfo->Bandwidth < temp) {
3728        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3729                    "Required bandwidth is not available. (%u > %u)\n",
3730                    (unsigned)temp, (unsigned)pVia->pBIOSInfo->Bandwidth);
3731        return FALSE;
3732    }
3733
3734    if (!pScrn->bitsPerPixel) {
3735        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3736                    "Invalid bpp information.\n");
3737        return FALSE;
3738    }
3739
3740    /* 16 is the Chrome IGP display controller memory alignment. */
3741    if (crtc->x % (16 / ((pScrn->bitsPerPixel + 7) >> 3))) {
3742        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3743                    "The X location specified is not properly aligned "
3744                    "to Chrome IGP's memory alignment.\n");
3745        return FALSE;
3746    }
3747
3748    return TRUE;
3749}
3750
3751static void
3752iga1_crtc_prepare(xf86CrtcPtr crtc)
3753{
3754    ScrnInfoPtr pScrn = crtc->scrn;
3755
3756    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3757                        "Entered iga1_crtc_prepare.\n"));
3758
3759    /* Turn off IGA1. */
3760    viaIGA1DPMSControl(pScrn, 0x03);
3761
3762    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3763                        "Exiting iga1_crtc_prepare.\n"));
3764}
3765
3766static void
3767iga1_crtc_set_origin(xf86CrtcPtr crtc, int x, int y)
3768{
3769    ScrnInfoPtr pScrn = crtc->scrn;
3770
3771    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3772                        "Entered iga1_crtc_set_origin.\n"));
3773
3774    viaIGA1SetFBStartingAddress(crtc, x, y);
3775    VIAVidAdjustFrame(pScrn, x, y);
3776
3777    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3778                        "Exiting iga1_crtc_set_origin.\n"));
3779}
3780
3781static void
3782iga1_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
3783                    DisplayModePtr adjusted_mode,
3784                    int x, int y)
3785{
3786    ScrnInfoPtr pScrn = crtc->scrn;
3787    vgaHWPtr hwp = VGAHWPTR(pScrn);
3788    VIAPtr pVia = VIAPTR(pScrn);
3789    VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
3790
3791    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3792                        "Entered iga1_crtc_mode_set.\n"));
3793
3794    /* Put IGA1 into a reset state. */
3795    viaIGA1HWReset(pScrn, 0x00);
3796
3797    if (!vgaHWInit(pScrn, adjusted_mode)) {
3798        DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3799                            "vgaHWInit failed.\n"));
3800        goto exit;
3801    }
3802
3803    viaIGAInitCommon(pScrn);
3804    viaIGA1Init(pScrn);
3805
3806    /* Disable IGA1 */
3807    ViaSeqMask(hwp, 0x59, 0x00, 0x80);
3808
3809    ViaPrintMode(pScrn, adjusted_mode);
3810
3811    /* Set color depth. */
3812    viaIGA1SetColorDepth(pScrn, pScrn->bitsPerPixel);
3813
3814    /* Set display controller screen parameters. */
3815    viaIGA1SetDisplayRegister(pScrn, adjusted_mode);
3816
3817    ViaSetPrimaryFIFO(pScrn, adjusted_mode);
3818
3819    pBIOSInfo->Clock = ViaModeDotClockTranslate(pScrn, adjusted_mode);
3820    pBIOSInfo->ClockExternal = FALSE;
3821    ViaSetPrimaryDotclock(pScrn, pBIOSInfo->Clock);
3822    ViaSetUseExternalClock(hwp);
3823    ViaCrtcMask(hwp, 0x6B, 0x00, 0x01);
3824
3825    /* Enable IGA1 */
3826    ViaSeqMask(hwp, 0x59, 0x80, 0x80);
3827
3828    viaIGA1SetFBStartingAddress(crtc, x, y);
3829    VIAVidAdjustFrame(pScrn, x, y);
3830
3831exit:
3832    /* Put IGA1 back into a normal operating state. */
3833    viaIGA1HWReset(pScrn, 0x01);
3834
3835    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3836                        "Exiting iga1_crtc_mode_set.\n"));
3837}
3838
3839static void
3840iga1_crtc_commit(xf86CrtcPtr crtc)
3841{
3842    ScrnInfoPtr pScrn = crtc->scrn;
3843    VIAPtr pVia = VIAPTR(pScrn);
3844
3845    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3846                        "Entering iga1_crtc_commit.\n"));
3847
3848    if (crtc->scrn->pScreen != NULL && pVia->drmmode.hwcursor)
3849#ifdef HAVE_XF86_CURSOR_RESET_CURSOR
3850        xf86CursorResetCursor(crtc->scrn->pScreen);
3851#else
3852        xf86_reload_cursors(crtc->scrn->pScreen);
3853#endif
3854
3855    /* Turn on IGA1. */
3856    viaIGA1DPMSControl(pScrn, 0x00);
3857
3858    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3859                        "Exiting iga1_crtc_commit.\n"));
3860}
3861
3862static void
3863iga1_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
3864                    int size)
3865{
3866    ScrnInfoPtr pScrn = crtc->scrn;
3867    LOCO colors[size];
3868    int i;
3869
3870    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3871                        "Entering iga1_crtc_gamma_set.\n"));
3872
3873    for (i = 0; i < size; i++) {
3874        colors[i].red = red[i] >> 8;
3875        colors[i].green = green[i] >> 8;
3876        colors[i].blue = blue[i] >> 8;
3877    }
3878
3879    /* Set palette LUT to 8-bit mode. */
3880    viaIGA1SetPaletteLUTResolution(pScrn, 0x01);
3881
3882    switch (pScrn->bitsPerPixel) {
3883    case 8:
3884        /* IGA1 will access the palette LUT. */
3885        viaSetPaletteLUTAccess(pScrn, 0x00);
3886
3887        VIALoadRgbLut(pScrn, 0, size, colors);
3888
3889        /* Turn gamma correction off. */
3890        viaIGA1SetGamma(pScrn, FALSE);
3891        break;
3892    case 16:
3893        /* IGA1 will access the palette LUT. */
3894        viaSetPaletteLUTAccess(pScrn, 0x00);
3895
3896        VIALoadRgbLut(pScrn, 0, size, colors);
3897
3898        /* Turn gamma correction off. */
3899        viaIGA1SetGamma(pScrn, FALSE);
3900        break;
3901    case 24:
3902    case 32:
3903        /* IGA1 will access the palette LUT. */
3904        viaSetPaletteLUTAccess(pScrn, 0x00);
3905
3906        VIALoadRgbLut(pScrn, 0, size, colors);
3907
3908        /* Turn gamma correction off. */
3909        viaIGA1SetGamma(pScrn, FALSE);
3910        break;
3911    default:
3912        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3913                    "Unsupported color depth: %d\n",
3914                    pScrn->bitsPerPixel);
3915        break;
3916    }
3917
3918    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3919                        "Exiting iga1_crtc_gamma_set.\n"));
3920}
3921
3922static void *
3923iga1_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
3924{
3925    return NULL;
3926}
3927
3928static PixmapPtr
3929iga1_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
3930{
3931    return NULL;
3932}
3933
3934static void
3935iga1_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
3936{
3937}
3938
3939/*
3940    Set the cursor foreground and background colors.  In 8bpp, fg and
3941    bg are indices into the current colormap unless the
3942    HARDWARE_CURSOR_TRUECOLOR_AT_8BPP flag is set.  In that case
3943    and in all other bpps the fg and bg are in 8-8-8 RGB format.
3944*/
3945static void
3946iga1_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
3947{
3948    ScrnInfoPtr pScrn = crtc->scrn;
3949    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
3950
3951    if (xf86_config->cursor_fg)
3952        return;
3953
3954    /* Don't recolour the image if we don't have to. */
3955    if (fg == xf86_config->cursor_fg && bg == xf86_config->cursor_bg)
3956        return;
3957
3958    viaIGA1DisplayHI(pScrn, FALSE);
3959
3960    xf86_config->cursor_fg = fg;
3961    xf86_config->cursor_bg = bg;
3962}
3963
3964static void
3965iga1_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
3966{
3967    ScrnInfoPtr pScrn = crtc->scrn;
3968    unsigned xoff, yoff;
3969
3970    if (x < 0) {
3971        xoff = ((-x) & 0xFE);
3972        x = 0;
3973    } else {
3974        xoff = 0;
3975    }
3976
3977    if (y < 0) {
3978        yoff = ((-y) & 0xFE);
3979        y = 0;
3980    } else {
3981        yoff = 0;
3982    }
3983
3984    viaIGA1SetHIDisplayLocation(pScrn, x, xoff, y, yoff);
3985}
3986
3987static void
3988iga1_crtc_show_cursor(xf86CrtcPtr crtc)
3989{
3990    ScrnInfoPtr pScrn = crtc->scrn;
3991
3992    viaIGA1DisplayHI(pScrn, TRUE);
3993}
3994
3995static void
3996iga1_crtc_hide_cursor(xf86CrtcPtr crtc)
3997{
3998    ScrnInfoPtr pScrn = crtc->scrn;
3999
4000    viaIGA1DisplayHI(pScrn, FALSE);
4001}
4002
4003static void
4004iga1_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
4005{
4006    drmmode_crtc_private_ptr iga = crtc->driver_private;
4007    ScrnInfoPtr pScrn = crtc->scrn;
4008    void *dst;
4009
4010    dst = drm_bo_map(pScrn, iga->cursor_bo);
4011    memset(dst, 0x00, iga->cursor_bo->size);
4012    memcpy(dst, image, iga->cursor_bo->size);
4013    drm_bo_unmap(pScrn, iga->cursor_bo);
4014
4015    viaIGA1InitHI(pScrn);
4016    viaIGA1SetHIStartingAddress(crtc);
4017}
4018
4019static void
4020iga_crtc_destroy(xf86CrtcPtr crtc)
4021{
4022    if (crtc->driver_private)
4023        free(crtc->driver_private);
4024}
4025
4026const xf86CrtcFuncsRec iga1_crtc_funcs = {
4027    .dpms                   = iga1_crtc_dpms,
4028    .save                   = iga1_crtc_save,
4029    .restore                = iga1_crtc_restore,
4030    .lock                   = iga1_crtc_lock,
4031    .unlock                 = iga1_crtc_unlock,
4032    .mode_fixup             = iga1_crtc_mode_fixup,
4033    .prepare                = iga1_crtc_prepare,
4034    .mode_set               = iga1_crtc_mode_set,
4035    .commit                 = iga1_crtc_commit,
4036    .gamma_set              = iga1_crtc_gamma_set,
4037    .shadow_create          = iga1_crtc_shadow_create,
4038    .shadow_allocate        = iga1_crtc_shadow_allocate,
4039    .shadow_destroy         = iga1_crtc_shadow_destroy,
4040    .set_cursor_colors      = iga1_crtc_set_cursor_colors,
4041    .set_cursor_position    = iga1_crtc_set_cursor_position,
4042    .show_cursor            = iga1_crtc_show_cursor,
4043    .hide_cursor            = iga1_crtc_hide_cursor,
4044    .load_cursor_argb       = iga1_crtc_load_cursor_argb,
4045#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) > 2
4046    .set_origin             = iga1_crtc_set_origin,
4047#endif
4048    .destroy                = iga_crtc_destroy,
4049};
4050
4051static void
4052iga2_crtc_dpms(xf86CrtcPtr crtc, int mode)
4053{
4054    ScrnInfoPtr pScrn = crtc->scrn;
4055
4056    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4057                        "Entered iga2_crtc_dpms.\n"));
4058
4059    switch (mode) {
4060    case DPMSModeOn:
4061        viaIGA2DisplayOutput(pScrn, TRUE);
4062        break;
4063
4064    case DPMSModeStandby:
4065    case DPMSModeSuspend:
4066    case DPMSModeOff:
4067        viaIGA2DisplayOutput(pScrn, FALSE);
4068        break;
4069
4070    default:
4071        xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid DPMS mode: %d\n",
4072                    mode);
4073        break;
4074    }
4075    //vgaHWSaveScreen(pScrn->pScreen, mode);
4076
4077    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4078                        "Exiting iga2_crtc_dpms.\n"));
4079}
4080
4081static void
4082iga2_crtc_save(xf86CrtcPtr crtc)
4083{
4084    ScrnInfoPtr pScrn = crtc->scrn;
4085
4086    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4087                        "Entered iga2_crtc_save.\n"));
4088
4089    viaIGA2Save(pScrn);
4090
4091    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4092                        "Exiting iga2_crtc_save.\n"));
4093}
4094
4095static void
4096iga2_crtc_restore(xf86CrtcPtr crtc)
4097{
4098    ScrnInfoPtr pScrn = crtc->scrn;
4099
4100    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4101                        "Entered iga2_crtc_restore.\n"));
4102
4103    viaIGA2Restore(pScrn);
4104
4105    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4106                        "Exiting iga2_crtc_restore.\n"));
4107}
4108
4109static Bool
4110iga2_crtc_lock(xf86CrtcPtr crtc)
4111{
4112    return FALSE;
4113}
4114
4115static void
4116iga2_crtc_unlock(xf86CrtcPtr crtc)
4117{
4118}
4119
4120static Bool
4121iga2_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
4122                        DisplayModePtr adjusted_mode)
4123{
4124    ScrnInfoPtr pScrn = crtc->scrn;
4125    VIAPtr pVia = VIAPTR(pScrn);
4126    CARD32 temp;
4127    ModeStatus modestatus;
4128
4129    if ((mode->Clock < pScrn->clockRanges->minClock) ||
4130        (mode->Clock > pScrn->clockRanges->maxClock)) {
4131        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4132                   "Clock for mode \"%s\" outside of allowed range (%u (%u - %u))\n",
4133                   mode->name, mode->Clock, pScrn->clockRanges->minClock,
4134                   pScrn->clockRanges->maxClock);
4135        return FALSE;
4136    }
4137
4138    modestatus = viaIGA2ModeValid(pScrn, mode);
4139    if (modestatus != MODE_OK) {
4140        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Not using mode \"%s\" : %s.\n",
4141                   mode->name, xf86ModeStatusToString(modestatus));
4142        return FALSE;
4143    }
4144
4145    temp = mode->CrtcHDisplay * mode->CrtcVDisplay * mode->VRefresh *
4146            (pScrn->bitsPerPixel >> 3);
4147    if (pVia->pBIOSInfo->Bandwidth < temp) {
4148        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4149                    "Required bandwidth is not available. (%u > %u)\n",
4150                    (unsigned)temp, (unsigned)pVia->pBIOSInfo->Bandwidth);
4151        return FALSE;
4152    }
4153
4154    if (!pScrn->bitsPerPixel) {
4155        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4156                    "Invalid bpp information.\n");
4157        return FALSE;
4158    }
4159
4160    /* 16 is the Chrome IGP display controller memory alignment. */
4161    if (crtc->x % (16 / ((pScrn->bitsPerPixel + 7) >> 3))) {
4162        xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4163                    "The X location specified is not properly aligned "
4164                    "to Chrome IGP's memory alignment.\n");
4165        return FALSE;
4166    }
4167
4168    return TRUE;
4169}
4170
4171static void
4172iga2_crtc_prepare(xf86CrtcPtr crtc)
4173{
4174    ScrnInfoPtr pScrn = crtc->scrn;
4175
4176    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4177                        "Entered iga2_crtc_prepare.\n"));
4178
4179    /* Turn off IGA2. */
4180    viaIGA2DisplayOutput(pScrn, FALSE);
4181
4182    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4183                        "Exiting iga2_crtc_prepare.\n"));
4184}
4185
4186static void
4187iga2_crtc_set_origin(xf86CrtcPtr crtc, int x, int y)
4188{
4189    ScrnInfoPtr pScrn = crtc->scrn;
4190
4191    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4192                        "Entered iga2_crtc_set_origin.\n"));
4193
4194    viaIGA2SetFBStartingAddress(crtc, x, y);
4195    VIAVidAdjustFrame(pScrn, x, y);
4196
4197    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4198                        "Exiting iga2_crtc_set_origin.\n"));
4199}
4200
4201static void
4202iga2_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
4203                    DisplayModePtr adjusted_mode, int x, int y)
4204{
4205    ScrnInfoPtr pScrn = crtc->scrn;
4206    vgaHWPtr hwp = VGAHWPTR(pScrn);
4207    VIAPtr pVia = VIAPTR(pScrn);
4208    VIABIOSInfoPtr pBIOSInfo = pVia->pBIOSInfo;
4209
4210    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4211                        "Entered iga2_crtc_mode_set.\n"));
4212
4213    /* Put IGA2 into a reset state. */
4214    viaIGA2HWReset(pScrn, 0x00);
4215
4216    /* Disable IGA2 display channel. */
4217    viaIGA2DisplayChannel(pScrn, FALSE);
4218
4219    viaIGAInitCommon(pScrn);
4220    viaIGA2Init(pScrn);
4221
4222    ViaPrintMode(pScrn, adjusted_mode);
4223
4224    /* Set color depth. */
4225    viaIGA2SetColorDepth(pScrn, pScrn->bitsPerPixel);
4226
4227    /* Set display controller screen parameters. */
4228    viaIGA2SetDisplayRegister(pScrn, adjusted_mode);
4229
4230    ViaSetSecondaryFIFO(pScrn, adjusted_mode);
4231    pBIOSInfo->Clock = ViaModeDotClockTranslate(pScrn, adjusted_mode);
4232    pBIOSInfo->ClockExternal = FALSE;
4233    ViaSetSecondaryDotclock(pScrn, pBIOSInfo->Clock);
4234    ViaSetUseExternalClock(hwp);
4235
4236    viaIGA2SetFBStartingAddress(crtc, x, y);
4237    VIAVidAdjustFrame(pScrn, x, y);
4238
4239    /* Enable IGA2 display channel. */
4240    viaIGA2DisplayChannel(pScrn, TRUE);
4241
4242    /* Put IGA2 back into a normal operating state. */
4243    viaIGA2HWReset(pScrn, 0x01);
4244
4245    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4246                        "Exiting iga2_crtc_mode_set.\n"));
4247}
4248
4249static void
4250iga2_crtc_commit(xf86CrtcPtr crtc)
4251{
4252    ScrnInfoPtr pScrn = crtc->scrn;
4253    VIAPtr pVia = VIAPTR(pScrn);
4254
4255    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4256                        "Entering iga2_crtc_commit.\n"));
4257
4258    if (crtc->scrn->pScreen != NULL && pVia->drmmode.hwcursor)
4259#ifdef HAVE_XF86_CURSOR_RESET_CURSOR
4260	xf86CursorResetCursor(crtc->scrn->pScreen);
4261#else
4262        xf86_reload_cursors(crtc->scrn->pScreen);
4263#endif
4264
4265    /* Turn on IGA2. */
4266    viaIGA2DisplayOutput(pScrn, TRUE);
4267
4268    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4269                        "Exiting iga2_crtc_commit.\n"));
4270}
4271
4272static void
4273iga2_crtc_gamma_set(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
4274                    int size)
4275{
4276    ScrnInfoPtr pScrn = crtc->scrn;
4277    LOCO colors[size];
4278    int i;
4279
4280    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4281                        "Entering iga2_crtc_gamma_set.\n"));
4282
4283    for (i = 0; i < size; i++) {
4284        colors[i].red = red[i] >> 8;
4285        colors[i].green = green[i] >> 8;
4286        colors[i].blue = blue[i] >> 8;
4287    }
4288
4289    /* Set palette LUT to 8-bit mode. */
4290    viaIGA2SetPaletteLUTResolution(pScrn, 0x01);
4291
4292    switch (pScrn->bitsPerPixel) {
4293    case 8:
4294        /* IGA2 will access the palette LUT. */
4295        viaSetPaletteLUTAccess(pScrn, 0x01);
4296
4297        VIALoadRgbLut(pScrn, 0, size, colors);
4298
4299        /* Turn gamma correction off. */
4300        viaIGA2SetGamma(pScrn, FALSE);
4301        break;
4302    case 16:
4303        /* IGA2 will access the palette LUT. */
4304        viaSetPaletteLUTAccess(pScrn, 0x01);
4305
4306        VIALoadRgbLut(pScrn, 0, size, colors);
4307
4308        /* Turn gamma correction off. */
4309        viaIGA2SetGamma(pScrn, FALSE);
4310        break;
4311    case 24:
4312    case 32:
4313        /* IGA2 will access the palette LUT. */
4314        viaSetPaletteLUTAccess(pScrn, 0x01);
4315
4316        VIALoadRgbLut(pScrn, 0, size, colors);
4317
4318        /* Turn gamma correction off. */
4319        viaIGA2SetGamma(pScrn, FALSE);
4320        break;
4321    default:
4322        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
4323                    "Unsupported color depth: %d\n",
4324                    pScrn->bitsPerPixel);
4325        break;
4326    }
4327
4328    DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO,
4329                        "Exiting iga2_crtc_gamma_set.\n"));
4330}
4331
4332static void *
4333iga2_crtc_shadow_allocate (xf86CrtcPtr crtc, int width, int height)
4334{
4335    return NULL;
4336}
4337
4338static PixmapPtr
4339iga2_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
4340{
4341    return NULL;
4342}
4343
4344static void
4345iga2_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data)
4346{
4347}
4348
4349/*
4350    Set the cursor foreground and background colors.  In 8bpp, fg and
4351    bg are indices into the current colormap unless the
4352    HARDWARE_CURSOR_TRUECOLOR_AT_8BPP flag is set.  In that case
4353    and in all other bpps the fg and bg are in 8-8-8 RGB format.
4354*/
4355static void
4356iga2_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
4357{
4358    drmmode_crtc_private_ptr iga = crtc->driver_private;
4359    ScrnInfoPtr pScrn = crtc->scrn;
4360    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
4361    int height = 64, width = 64, i;
4362    CARD32 pixel, *dst;
4363
4364    if (xf86_config->cursor_fg)
4365        return;
4366
4367    fg |= 0xff000000;
4368    bg |= 0xff000000;
4369
4370    /* Don't recolour the image if we don't have to. */
4371    if (fg == xf86_config->cursor_fg && bg == xf86_config->cursor_bg)
4372        return;
4373
4374    viaIGA2DisplayHI(pScrn, FALSE);
4375
4376    dst = drm_bo_map(pScrn, iga->cursor_bo);
4377    for (i = 0; i < width * height; i++, dst++)
4378        if ((pixel = *dst))
4379            *dst = (pixel == xf86_config->cursor_fg) ? fg : bg;
4380    drm_bo_unmap(pScrn, iga->cursor_bo);
4381
4382    xf86_config->cursor_fg = fg;
4383    xf86_config->cursor_bg = bg;
4384}
4385
4386static void
4387iga2_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
4388{
4389    ScrnInfoPtr pScrn = crtc->scrn;
4390    unsigned xoff, yoff;
4391
4392    if (x < 0) {
4393        xoff = ((-x) & 0xFE);
4394        x = 0;
4395    } else {
4396        xoff = 0;
4397    }
4398
4399    if (y < 0) {
4400        yoff = ((-y) & 0xFE);
4401        y = 0;
4402    } else {
4403        yoff = 0;
4404    }
4405
4406    viaIGA2SetHIDisplayLocation(pScrn, x, xoff, y, yoff);
4407}
4408
4409static void
4410iga2_crtc_show_cursor(xf86CrtcPtr crtc)
4411{
4412    ScrnInfoPtr pScrn = crtc->scrn;
4413
4414    viaIGA2DisplayHI(pScrn, TRUE);
4415}
4416
4417static void
4418iga2_crtc_hide_cursor(xf86CrtcPtr crtc)
4419{
4420    ScrnInfoPtr pScrn = crtc->scrn;
4421
4422    viaIGA2DisplayHI(pScrn, FALSE);
4423}
4424
4425static void
4426iga2_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
4427{
4428    drmmode_crtc_private_ptr iga = crtc->driver_private;
4429    ScrnInfoPtr pScrn = crtc->scrn;
4430    void *dst;
4431
4432    dst = drm_bo_map(pScrn, iga->cursor_bo);
4433    memset(dst, 0x00, iga->cursor_bo->size);
4434    memcpy(dst, image, iga->cursor_bo->size);
4435    drm_bo_unmap(pScrn, iga->cursor_bo);
4436
4437    viaIGA2InitHI(pScrn);
4438    viaIGA2SetHIStartingAddress(crtc);
4439}
4440
4441const xf86CrtcFuncsRec iga2_crtc_funcs = {
4442    .dpms                   = iga2_crtc_dpms,
4443    .save                   = iga2_crtc_save,
4444    .restore                = iga2_crtc_restore,
4445    .lock                   = iga2_crtc_lock,
4446    .unlock                 = iga2_crtc_unlock,
4447    .mode_fixup             = iga2_crtc_mode_fixup,
4448    .prepare                = iga2_crtc_prepare,
4449    .mode_set               = iga2_crtc_mode_set,
4450    .commit                 = iga2_crtc_commit,
4451    .gamma_set              = iga2_crtc_gamma_set,
4452    .shadow_create          = iga2_crtc_shadow_create,
4453    .shadow_allocate        = iga2_crtc_shadow_allocate,
4454    .shadow_destroy         = iga2_crtc_shadow_destroy,
4455    .set_cursor_colors      = iga2_crtc_set_cursor_colors,
4456    .set_cursor_position    = iga2_crtc_set_cursor_position,
4457    .show_cursor            = iga2_crtc_show_cursor,
4458    .hide_cursor            = iga2_crtc_hide_cursor,
4459    .load_cursor_argb       = iga2_crtc_load_cursor_argb,
4460#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) > 2
4461    .set_origin             = iga2_crtc_set_origin,
4462#endif
4463    .destroy                = iga_crtc_destroy,
4464};
4465