mga_dacG.c revision fe5e51b7
1fe5e51b7Smrg/*
2fe5e51b7Smrg * MGA-1064, MGA-G100, MGA-G200, MGA-G400, MGA-G550 RAMDAC driver
3fe5e51b7Smrg */
4fe5e51b7Smrg
5fe5e51b7Smrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/mga/mga_dacG.c,v 1.54tsi Exp $ */
6fe5e51b7Smrg
7fe5e51b7Smrg/*
8fe5e51b7Smrg * This is a first cut at a non-accelerated version to work with the
9fe5e51b7Smrg * new server design (DHD).
10fe5e51b7Smrg */
11fe5e51b7Smrg
12fe5e51b7Smrg#ifdef HAVE_CONFIG_H
13fe5e51b7Smrg#include "config.h"
14fe5e51b7Smrg#endif
15fe5e51b7Smrg
16fe5e51b7Smrg#include "colormapst.h"
17fe5e51b7Smrg
18fe5e51b7Smrg/* All drivers should typically include these */
19fe5e51b7Smrg#include "xf86.h"
20fe5e51b7Smrg#include "xf86_OSproc.h"
21fe5e51b7Smrg
22fe5e51b7Smrg/* Drivers for PCI hardware need this */
23fe5e51b7Smrg#include "xf86PciInfo.h"
24fe5e51b7Smrg
25fe5e51b7Smrg/* Drivers that need to access the PCI config space directly need this */
26fe5e51b7Smrg#include "xf86Pci.h"
27fe5e51b7Smrg
28fe5e51b7Smrg#include "mga_reg.h"
29fe5e51b7Smrg#include "mga.h"
30fe5e51b7Smrg#include "mga_macros.h"
31fe5e51b7Smrg#include "mga_maven.h"
32fe5e51b7Smrg
33fe5e51b7Smrg#include "xf86DDC.h"
34fe5e51b7Smrg
35fe5e51b7Smrg#include <stdlib.h>
36fe5e51b7Smrg#include <unistd.h>
37fe5e51b7Smrg
38fe5e51b7Smrg/*
39fe5e51b7Smrg * implementation
40fe5e51b7Smrg */
41fe5e51b7Smrg
42fe5e51b7Smrg#define DACREGSIZE 0x50
43fe5e51b7Smrg
44fe5e51b7Smrg/*
45fe5e51b7Smrg * Only change bits shown in this mask.  Ideally reserved bits should be
46fe5e51b7Smrg * zeroed here.  Also, don't change the vgaioen bit here since it is
47fe5e51b7Smrg * controlled elsewhere.
48fe5e51b7Smrg *
49fe5e51b7Smrg * XXX These settings need to be checked.
50fe5e51b7Smrg */
51fe5e51b7Smrg#define OPTION1_MASK	0xFFFFFEFF
52fe5e51b7Smrg#define OPTION2_MASK	0xFFFFFFFF
53fe5e51b7Smrg#define OPTION3_MASK	0xFFFFFFFF
54fe5e51b7Smrg
55fe5e51b7Smrg#define OPTION1_MASK_PRIMARY	0xFFFC0FF
56fe5e51b7Smrg
57fe5e51b7Smrgstatic void MGAGRamdacInit(ScrnInfoPtr);
58fe5e51b7Smrgstatic void MGAGSave(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool);
59fe5e51b7Smrgstatic void MGAGRestore(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool);
60fe5e51b7Smrgstatic Bool MGAGInit(ScrnInfoPtr, DisplayModePtr);
61fe5e51b7Smrgstatic void MGAGLoadPalette(ScrnInfoPtr, int, int*, LOCO*, VisualPtr);
62fe5e51b7Smrgstatic Bool MGAG_i2cInit(ScrnInfoPtr pScrn);
63fe5e51b7Smrg
64fe5e51b7Smrgstatic void
65fe5e51b7SmrgMGAG200SEComputePLLParam(ScrnInfoPtr pScrn, long lFo, int *M, int *N, int *P)
66fe5e51b7Smrg{
67fe5e51b7Smrg    unsigned int ulComputedFo;
68fe5e51b7Smrg    unsigned int ulFDelta;
69fe5e51b7Smrg    unsigned int ulFPermitedDelta;
70fe5e51b7Smrg    unsigned int ulFTmpDelta;
71fe5e51b7Smrg    unsigned int ulVCOMax, ulVCOMin;
72fe5e51b7Smrg    unsigned int ulTestP;
73fe5e51b7Smrg    unsigned int ulTestM;
74fe5e51b7Smrg    unsigned int ulTestN;
75fe5e51b7Smrg    unsigned int ulPLLFreqRef;
76fe5e51b7Smrg
77fe5e51b7Smrg    ulVCOMax        = 320000;
78fe5e51b7Smrg    ulVCOMin        = 160000;
79fe5e51b7Smrg    ulPLLFreqRef    = 25000;
80fe5e51b7Smrg
81fe5e51b7Smrg    ulFDelta = 0xFFFFFFFF;
82fe5e51b7Smrg    /* Permited delta is 0.5% as VESA Specification */
83fe5e51b7Smrg    ulFPermitedDelta = lFo * 5 / 1000;
84fe5e51b7Smrg
85fe5e51b7Smrg    /* Then we need to minimize the M while staying within 0.5% */
86fe5e51b7Smrg    for (ulTestP = 8; ulTestP > 0; ulTestP >>= 1) {
87fe5e51b7Smrg	if ((lFo * ulTestP) > ulVCOMax) continue;
88fe5e51b7Smrg	if ((lFo * ulTestP) < ulVCOMin) continue;
89fe5e51b7Smrg
90fe5e51b7Smrg	for (ulTestN = 17; ulTestN <= 256; ulTestN++) {
91fe5e51b7Smrg	    for (ulTestM = 1; ulTestM <= 32; ulTestM++) {
92fe5e51b7Smrg		ulComputedFo = (ulPLLFreqRef * ulTestN) / (ulTestM * ulTestP);
93fe5e51b7Smrg		if (ulComputedFo > lFo)
94fe5e51b7Smrg		    ulFTmpDelta = ulComputedFo - lFo;
95fe5e51b7Smrg		else
96fe5e51b7Smrg		    ulFTmpDelta = lFo - ulComputedFo;
97fe5e51b7Smrg
98fe5e51b7Smrg		if (ulFTmpDelta < ulFDelta) {
99fe5e51b7Smrg		    ulFDelta = ulFTmpDelta;
100fe5e51b7Smrg		    *M = ulTestM - 1;
101fe5e51b7Smrg		    *N = ulTestN - 1;
102fe5e51b7Smrg		    *P = ulTestP - 1;
103fe5e51b7Smrg		}
104fe5e51b7Smrg	    }
105fe5e51b7Smrg	}
106fe5e51b7Smrg    }
107fe5e51b7Smrg}
108fe5e51b7Smrg
109fe5e51b7Smrg
110fe5e51b7Smrg/**
111fe5e51b7Smrg * Calculate the PLL settings (m, n, p, s).
112fe5e51b7Smrg *
113fe5e51b7Smrg * For more information, refer to the Matrox "MGA1064SG Developer
114fe5e51b7Smrg * Specification" (document 10524-MS-0100).  chapter 5.7.8. "PLLs Clocks
115fe5e51b7Smrg * Generators"
116fe5e51b7Smrg *
117fe5e51b7Smrg * \param f_out   Desired clock frequency, measured in kHz.
118fe5e51b7Smrg * \param best_m  Value of PLL 'm' register.
119fe5e51b7Smrg * \param best_n  Value of PLL 'n' register.
120fe5e51b7Smrg * \param p       Value of PLL 'p' register.
121fe5e51b7Smrg * \param s       Value of PLL 's' filter register (pix pll clock only).
122fe5e51b7Smrg */
123fe5e51b7Smrg
124fe5e51b7Smrgstatic void
125fe5e51b7SmrgMGAGCalcClock ( ScrnInfoPtr pScrn, long f_out,
126fe5e51b7Smrg		int *best_m, int *best_n, int *p, int *s )
127fe5e51b7Smrg{
128fe5e51b7Smrg	MGAPtr pMga = MGAPTR(pScrn);
129fe5e51b7Smrg	int m, n;
130fe5e51b7Smrg	double f_vco;
131fe5e51b7Smrg	double m_err, calc_f;
132fe5e51b7Smrg	const double ref_freq = (double) pMga->bios.pll_ref_freq;
133fe5e51b7Smrg	const int feed_div_max = 127;
134fe5e51b7Smrg	const int in_div_min = 1;
135fe5e51b7Smrg	const int post_div_max = 7;
136fe5e51b7Smrg	int feed_div_min;
137fe5e51b7Smrg	int in_div_max;
138fe5e51b7Smrg
139fe5e51b7Smrg
140fe5e51b7Smrg	switch( pMga->Chipset )
141fe5e51b7Smrg	{
142fe5e51b7Smrg	case PCI_CHIP_MGA1064:
143fe5e51b7Smrg		feed_div_min = 100;
144fe5e51b7Smrg		in_div_max   = 31;
145fe5e51b7Smrg		break;
146fe5e51b7Smrg	case PCI_CHIP_MGAG400:
147fe5e51b7Smrg	case PCI_CHIP_MGAG550:
148fe5e51b7Smrg		feed_div_min = 7;
149fe5e51b7Smrg		in_div_max   = 31;
150fe5e51b7Smrg		break;
151fe5e51b7Smrg	case PCI_CHIP_MGAG200_SE_A_PCI:
152fe5e51b7Smrg	case PCI_CHIP_MGAG200_SE_B_PCI:
153fe5e51b7Smrg	case PCI_CHIP_MGAG100:
154fe5e51b7Smrg	case PCI_CHIP_MGAG100_PCI:
155fe5e51b7Smrg	case PCI_CHIP_MGAG200:
156fe5e51b7Smrg	case PCI_CHIP_MGAG200_PCI:
157fe5e51b7Smrg	default:
158fe5e51b7Smrg		feed_div_min = 7;
159fe5e51b7Smrg		in_div_max   = 6;
160fe5e51b7Smrg		break;
161fe5e51b7Smrg	}
162fe5e51b7Smrg
163fe5e51b7Smrg	/* Make sure that f_min <= f_out */
164fe5e51b7Smrg	if ( f_out < ( pMga->bios.pixel.min_freq / 8))
165fe5e51b7Smrg		f_out = pMga->bios.pixel.min_freq / 8;
166fe5e51b7Smrg
167fe5e51b7Smrg	/*
168fe5e51b7Smrg	 * f_pll = f_vco / (p+1)
169fe5e51b7Smrg	 * Choose p so that
170fe5e51b7Smrg	 * pMga->bios.pixel.min_freq <= f_vco <= pMga->bios.pixel.max_freq
171fe5e51b7Smrg	 * we don't have to bother checking for this maximum limit.
172fe5e51b7Smrg	 */
173fe5e51b7Smrg	f_vco = ( double ) f_out;
174fe5e51b7Smrg	for ( *p = 0; *p <= post_div_max && f_vco < pMga->bios.pixel.min_freq;
175fe5e51b7Smrg		*p = *p * 2 + 1, f_vco *= 2.0);
176fe5e51b7Smrg
177fe5e51b7Smrg	/* Initial amount of error for frequency maximum */
178fe5e51b7Smrg	m_err = f_out;
179fe5e51b7Smrg
180fe5e51b7Smrg	/* Search for the different values of ( m ) */
181fe5e51b7Smrg	for ( m = in_div_min ; m <= in_div_max ; m++ )
182fe5e51b7Smrg	{
183fe5e51b7Smrg		/* see values of ( n ) which we can't use */
184fe5e51b7Smrg		for ( n = feed_div_min; n <= feed_div_max; n++ )
185fe5e51b7Smrg		{
186fe5e51b7Smrg			calc_f = ref_freq * (n + 1) / (m + 1) ;
187fe5e51b7Smrg
188fe5e51b7Smrg			/*
189fe5e51b7Smrg			 * Pick the closest frequency.
190fe5e51b7Smrg			 */
191fe5e51b7Smrg			if ( abs(calc_f - f_vco) < m_err ) {
192fe5e51b7Smrg				m_err = abs(calc_f - f_vco);
193fe5e51b7Smrg				*best_m = m;
194fe5e51b7Smrg				*best_n = n;
195fe5e51b7Smrg			}
196fe5e51b7Smrg		}
197fe5e51b7Smrg	}
198fe5e51b7Smrg
199fe5e51b7Smrg	/* Now all the calculations can be completed */
200fe5e51b7Smrg	f_vco = ref_freq * (*best_n + 1) / (*best_m + 1);
201fe5e51b7Smrg
202fe5e51b7Smrg	/* Adjustments for filtering pll feed back */
203fe5e51b7Smrg	if ( (50000.0 <= f_vco)
204fe5e51b7Smrg	&& (f_vco < 100000.0) )
205fe5e51b7Smrg		*s = 0;
206fe5e51b7Smrg	if ( (100000.0 <= f_vco)
207fe5e51b7Smrg	&& (f_vco < 140000.0) )
208fe5e51b7Smrg		*s = 1;
209fe5e51b7Smrg	if ( (140000.0 <= f_vco)
210fe5e51b7Smrg	&& (f_vco < 180000.0) )
211fe5e51b7Smrg		*s = 2;
212fe5e51b7Smrg	if ( (180000.0 <= f_vco) )
213fe5e51b7Smrg		*s = 3;
214fe5e51b7Smrg
215fe5e51b7Smrg#ifdef DEBUG
216fe5e51b7Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
217fe5e51b7Smrg		   "f_out_requ =%ld f_pll_real=%.1f f_vco=%.1f n=0x%x m=0x%x p=0x%x s=0x%x\n",
218fe5e51b7Smrg		   f_out, (f_vco / (*p + 1)), f_vco, *best_n, *best_m, *p, *s );
219fe5e51b7Smrg#endif
220fe5e51b7Smrg}
221fe5e51b7Smrg
222fe5e51b7Smrg/*
223fe5e51b7Smrg * MGAGSetPCLK - Set the pixel (PCLK) clock.
224fe5e51b7Smrg */
225fe5e51b7Smrgstatic void
226fe5e51b7SmrgMGAGSetPCLK( ScrnInfoPtr pScrn, long f_out )
227fe5e51b7Smrg{
228fe5e51b7Smrg	MGAPtr pMga = MGAPTR(pScrn);
229fe5e51b7Smrg	MGARegPtr pReg = &pMga->ModeReg;
230fe5e51b7Smrg
231fe5e51b7Smrg	/* Pixel clock values */
232fe5e51b7Smrg	int m, n, p, s;
233fe5e51b7Smrg
234fe5e51b7Smrg	if(MGAISGx50(pMga)) {
235fe5e51b7Smrg	    pReg->Clock = f_out;
236fe5e51b7Smrg	    return;
237fe5e51b7Smrg	}
238fe5e51b7Smrg
239fe5e51b7Smrg	if (pMga->is_G200SE) {
240fe5e51b7Smrg	    MGAG200SEComputePLLParam(pScrn, f_out, &m, &n, &p);
241fe5e51b7Smrg
242fe5e51b7Smrg	    pReg->DacRegs[ MGA1064_PIX_PLLC_M ] = m;
243fe5e51b7Smrg	    pReg->DacRegs[ MGA1064_PIX_PLLC_N ] = n;
244fe5e51b7Smrg	    pReg->DacRegs[ MGA1064_PIX_PLLC_P ] = p;
245fe5e51b7Smrg	} else {
246fe5e51b7Smrg	    /* Do the calculations for m, n, p and s */
247fe5e51b7Smrg	    MGAGCalcClock( pScrn, f_out, &m, &n, &p, &s );
248fe5e51b7Smrg
249fe5e51b7Smrg	    /* Values for the pixel clock PLL registers */
250fe5e51b7Smrg	    pReg->DacRegs[ MGA1064_PIX_PLLC_M ] = m & 0x1F;
251fe5e51b7Smrg	    pReg->DacRegs[ MGA1064_PIX_PLLC_N ] = n & 0x7F;
252fe5e51b7Smrg	    pReg->DacRegs[ MGA1064_PIX_PLLC_P ] = (p & 0x07) |
253fe5e51b7Smrg						  ((s & 0x03) << 3);
254fe5e51b7Smrg	}
255fe5e51b7Smrg}
256fe5e51b7Smrg
257fe5e51b7Smrg/*
258fe5e51b7Smrg * MGAGInit
259fe5e51b7Smrg */
260fe5e51b7Smrgstatic Bool
261fe5e51b7SmrgMGAGInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
262fe5e51b7Smrg{
263fe5e51b7Smrg	/*
264fe5e51b7Smrg	 * initial values of the DAC registers
265fe5e51b7Smrg	 */
266fe5e51b7Smrg	const static unsigned char initDAC[] = {
267fe5e51b7Smrg	/* 0x00: */	   0,    0,    0,    0,    0,    0, 0x00,    0,
268fe5e51b7Smrg	/* 0x08: */	   0,    0,    0,    0,    0,    0,    0,    0,
269fe5e51b7Smrg	/* 0x10: */	   0,    0,    0,    0,    0,    0,    0,    0,
270fe5e51b7Smrg	/* 0x18: */	0x00,    0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
271fe5e51b7Smrg	/* 0x20: */	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272fe5e51b7Smrg	/* 0x28: */	0x00, 0x00, 0x00, 0x00,    0,    0,    0, 0x40,
273fe5e51b7Smrg	/* 0x30: */	0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
274fe5e51b7Smrg	/* 0x38: */	0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
275fe5e51b7Smrg	/* 0x40: */	   0,    0,    0,    0,    0,    0,    0,    0,
276fe5e51b7Smrg	/* 0x48: */	   0,    0,    0,    0,    0,    0,    0,    0
277fe5e51b7Smrg	};
278fe5e51b7Smrg
279fe5e51b7Smrg	int i;
280fe5e51b7Smrg	int hd, hs, he, ht, vd, vs, ve, vt, wd;
281fe5e51b7Smrg	int BppShift;
282fe5e51b7Smrg	MGAPtr pMga;
283fe5e51b7Smrg	MGARegPtr pReg;
284fe5e51b7Smrg	vgaRegPtr pVga;
285fe5e51b7Smrg	MGAFBLayout *pLayout;
286fe5e51b7Smrg	xMODEINFO ModeInfo;
287fe5e51b7Smrg
288fe5e51b7Smrg	ModeInfo.ulDispWidth = mode->HDisplay;
289fe5e51b7Smrg        ModeInfo.ulDispHeight = mode->VDisplay;
290fe5e51b7Smrg        ModeInfo.ulFBPitch = mode->HDisplay;
291fe5e51b7Smrg        ModeInfo.ulBpp = pScrn->bitsPerPixel;
292fe5e51b7Smrg        ModeInfo.flSignalMode = 0;
293fe5e51b7Smrg        ModeInfo.ulPixClock = mode->Clock;
294fe5e51b7Smrg        ModeInfo.ulHFPorch = mode->HSyncStart - mode->HDisplay;
295fe5e51b7Smrg        ModeInfo.ulHSync = mode->HSyncEnd - mode->HSyncStart;
296fe5e51b7Smrg        ModeInfo.ulHBPorch = mode->HTotal - mode->HSyncEnd;
297fe5e51b7Smrg        ModeInfo.ulVFPorch = mode->VSyncStart - mode->VDisplay;
298fe5e51b7Smrg        ModeInfo.ulVSync = mode->VSyncEnd - mode->VSyncStart;
299fe5e51b7Smrg        ModeInfo.ulVBPorch = mode->VTotal - mode->VSyncEnd;
300fe5e51b7Smrg
301fe5e51b7Smrg	pMga = MGAPTR(pScrn);
302fe5e51b7Smrg	pReg = &pMga->ModeReg;
303fe5e51b7Smrg	pVga = &VGAHWPTR(pScrn)->ModeReg;
304fe5e51b7Smrg	pLayout = &pMga->CurrentLayout;
305fe5e51b7Smrg
306fe5e51b7Smrg	BppShift = pMga->BppShifts[(pLayout->bitsPerPixel >> 3) - 1];
307fe5e51b7Smrg
308fe5e51b7Smrg	MGA_NOT_HAL(
309fe5e51b7Smrg	/* Allocate the DacRegs space if not done already */
310fe5e51b7Smrg	if (pReg->DacRegs == NULL) {
311fe5e51b7Smrg		pReg->DacRegs = xnfcalloc(DACREGSIZE, 1);
312fe5e51b7Smrg	}
313fe5e51b7Smrg	for (i = 0; i < DACREGSIZE; i++) {
314fe5e51b7Smrg	    pReg->DacRegs[i] = initDAC[i];
315fe5e51b7Smrg	}
316fe5e51b7Smrg	);	/* MGA_NOT_HAL */
317fe5e51b7Smrg
318fe5e51b7Smrg	switch(pMga->Chipset)
319fe5e51b7Smrg	{
320fe5e51b7Smrg	case PCI_CHIP_MGA1064:
321fe5e51b7Smrg		pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x04;
322fe5e51b7Smrg		pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x44;
323fe5e51b7Smrg		pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18;
324fe5e51b7Smrg		pReg->Option  = 0x5F094F21;
325fe5e51b7Smrg		pReg->Option2 = 0x00000000;
326fe5e51b7Smrg		break;
327fe5e51b7Smrg	case PCI_CHIP_MGAG100:
328fe5e51b7Smrg	case PCI_CHIP_MGAG100_PCI:
329fe5e51b7Smrg                pReg->DacRegs[MGA1064_VREF_CTL] = 0x03;
330fe5e51b7Smrg
331fe5e51b7Smrg		if(pMga->HasSDRAM) {
332fe5e51b7Smrg		    if(pMga->OverclockMem) {
333fe5e51b7Smrg                        /* 220 Mhz */
334fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x06;
335fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x38;
336fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18;
337fe5e51b7Smrg		    } else {
338fe5e51b7Smrg                        /* 203 Mhz */
339fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x01;
340fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x0E;
341fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18;
342fe5e51b7Smrg		    }
343fe5e51b7Smrg		    pReg->Option = 0x404991a9;
344fe5e51b7Smrg		} else {
345fe5e51b7Smrg		    if(pMga->OverclockMem) {
346fe5e51b7Smrg                        /* 143 Mhz */
347fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x06;
348fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x24;
349fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x10;
350fe5e51b7Smrg		    } else {
351fe5e51b7Smrg		        /* 124 Mhz */
352fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x04;
353fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x16;
354fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x08;
355fe5e51b7Smrg		    }
356fe5e51b7Smrg		    pReg->Option = 0x4049d121;
357fe5e51b7Smrg		}
358fe5e51b7Smrg		pReg->Option2 = 0x0000007;
359fe5e51b7Smrg		break;
360fe5e51b7Smrg	case PCI_CHIP_MGAG400:
361fe5e51b7Smrg	case PCI_CHIP_MGAG550:
362fe5e51b7Smrg#ifdef USEMGAHAL
363fe5e51b7Smrg	       MGA_HAL(break;);
364fe5e51b7Smrg#endif
365fe5e51b7Smrg	       if (MGAISGx50(pMga))
366fe5e51b7Smrg		       break;
367fe5e51b7Smrg
368fe5e51b7Smrg	       if(pMga->Dac.maxPixelClock == 360000) {  /* G400 MAX */
369fe5e51b7Smrg	           if(pMga->OverclockMem) {
370fe5e51b7Smrg			/* 150/200  */
371fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x05;
372fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x42;
373fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18;
374fe5e51b7Smrg			pReg->Option3 = 0x019B8419;
375fe5e51b7Smrg			pReg->Option = 0x50574120;
376fe5e51b7Smrg		   } else {
377fe5e51b7Smrg			/* 125/166  */
378fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x02;
379fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x1B;
380fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18;
381fe5e51b7Smrg			pReg->Option3 = 0x019B8419;
382fe5e51b7Smrg			pReg->Option = 0x5053C120;
383fe5e51b7Smrg		   }
384fe5e51b7Smrg		} else {
385fe5e51b7Smrg	           if(pMga->OverclockMem) {
386fe5e51b7Smrg			/* 125/166  */
387fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x02;
388fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x1B;
389fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x18;
390fe5e51b7Smrg			pReg->Option3 = 0x019B8419;
391fe5e51b7Smrg			pReg->Option = 0x5053C120;
392fe5e51b7Smrg		   } else {
393fe5e51b7Smrg			/* 110/166  */
394fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x13;
395fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x7A;
396fe5e51b7Smrg			pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x08;
397fe5e51b7Smrg			pReg->Option3 = 0x0190a421;
398fe5e51b7Smrg			pReg->Option = 0x50044120;
399fe5e51b7Smrg		   }
400fe5e51b7Smrg		}
401fe5e51b7Smrg		if(pMga->HasSDRAM)
402fe5e51b7Smrg		   pReg->Option &= ~(1 << 14);
403fe5e51b7Smrg		pReg->Option2 = 0x01003000;
404fe5e51b7Smrg		break;
405fe5e51b7Smrg	case PCI_CHIP_MGAG200_SE_A_PCI:
406fe5e51b7Smrg	case PCI_CHIP_MGAG200_SE_B_PCI:
407fe5e51b7Smrg#ifdef USEMGAHAL
408fe5e51b7Smrg		MGA_HAL(break;);
409fe5e51b7Smrg#endif
410fe5e51b7Smrg        pReg->DacRegs[ MGA1064_VREF_CTL ] = 0x03;
411fe5e51b7Smrg                pReg->DacRegs[MGA1064_PIX_CLK_CTL] =
412fe5e51b7Smrg                    MGA1064_PIX_CLK_CTL_SEL_PLL;
413fe5e51b7Smrg
414fe5e51b7Smrg                pReg->DacRegs[MGA1064_MISC_CTL] =
415fe5e51b7Smrg                    MGA1064_MISC_CTL_DAC_EN |
416fe5e51b7Smrg                    MGA1064_MISC_CTL_VGA8 |
417fe5e51b7Smrg                    MGA1064_MISC_CTL_DAC_RAM_CS;
418fe5e51b7Smrg
419fe5e51b7Smrg		if (pMga->HasSDRAM)
420fe5e51b7Smrg		    pReg->Option = 0x40049120;
421fe5e51b7Smrg	        pReg->Option2 = 0x00008000;
422fe5e51b7Smrg		break;
423fe5e51b7Smrg	case PCI_CHIP_MGAG200:
424fe5e51b7Smrg	case PCI_CHIP_MGAG200_PCI:
425fe5e51b7Smrg	default:
426fe5e51b7Smrg#ifdef USEMGAHAL
427fe5e51b7Smrg		MGA_HAL(break;);
428fe5e51b7Smrg#endif
429fe5e51b7Smrg		if(pMga->OverclockMem) {
430fe5e51b7Smrg                     /* 143 Mhz */
431fe5e51b7Smrg		    pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x06;
432fe5e51b7Smrg		    pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x24;
433fe5e51b7Smrg		    pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x10;
434fe5e51b7Smrg		} else {
435fe5e51b7Smrg		    /* 124 Mhz */
436fe5e51b7Smrg		    pReg->DacRegs[ MGA1064_SYS_PLL_M ] = 0x04;
437fe5e51b7Smrg		    pReg->DacRegs[ MGA1064_SYS_PLL_N ] = 0x2D;
438fe5e51b7Smrg		    pReg->DacRegs[ MGA1064_SYS_PLL_P ] = 0x19;
439fe5e51b7Smrg		}
440fe5e51b7Smrg	        pReg->Option2 = 0x00008000;
441fe5e51b7Smrg		if(pMga->HasSDRAM)
442fe5e51b7Smrg		    pReg->Option = 0x40499121;
443fe5e51b7Smrg		else
444fe5e51b7Smrg		    pReg->Option = 0x4049cd21;
445fe5e51b7Smrg		break;
446fe5e51b7Smrg	}
447fe5e51b7Smrg
448fe5e51b7Smrg	MGA_NOT_HAL(
449fe5e51b7Smrg	/* must always have the pci retries on but rely on
450fe5e51b7Smrg	   polling to keep them from occuring */
451fe5e51b7Smrg	pReg->Option &= ~0x20000000;
452fe5e51b7Smrg
453fe5e51b7Smrg	switch(pLayout->bitsPerPixel)
454fe5e51b7Smrg	{
455fe5e51b7Smrg	case 8:
456fe5e51b7Smrg		pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_8bits;
457fe5e51b7Smrg		break;
458fe5e51b7Smrg	case 16:
459fe5e51b7Smrg		pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_16bits;
460fe5e51b7Smrg		if ( (pLayout->weight.red == 5) && (pLayout->weight.green == 5)
461fe5e51b7Smrg					&& (pLayout->weight.blue == 5) ) {
462fe5e51b7Smrg		    pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_15bits;
463fe5e51b7Smrg		}
464fe5e51b7Smrg		break;
465fe5e51b7Smrg	case 24:
466fe5e51b7Smrg		pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_24bits;
467fe5e51b7Smrg		break;
468fe5e51b7Smrg	case 32:
469fe5e51b7Smrg		if(pLayout->Overlay8Plus24) {
470fe5e51b7Smrg		   pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_32bits;
471fe5e51b7Smrg		   pReg->DacRegs[ MGA1064_COL_KEY_MSK_LSB ] = 0xFF;
472fe5e51b7Smrg		   pReg->DacRegs[ MGA1064_COL_KEY_LSB ] = pMga->colorKey;
473fe5e51b7Smrg		} else
474fe5e51b7Smrg		   pReg->DacRegs[ MGA1064_MUL_CTL ] = MGA1064_MUL_CTL_32_24bits;
475fe5e51b7Smrg		break;
476fe5e51b7Smrg	default:
477fe5e51b7Smrg		FatalError("MGA: unsupported depth\n");
478fe5e51b7Smrg	}
479fe5e51b7Smrg	);	/* MGA_NOT_HAL */
480fe5e51b7Smrg
481fe5e51b7Smrg	/*
482fe5e51b7Smrg	 * This will initialize all of the generic VGA registers.
483fe5e51b7Smrg	 */
484fe5e51b7Smrg	if (!vgaHWInit(pScrn, mode))
485fe5e51b7Smrg		return(FALSE);
486fe5e51b7Smrg
487fe5e51b7Smrg	/*
488fe5e51b7Smrg	 * Here all of the MGA registers get filled in.
489fe5e51b7Smrg	 */
490fe5e51b7Smrg	hd = (mode->CrtcHDisplay	>> 3)	- 1;
491fe5e51b7Smrg	hs = (mode->CrtcHSyncStart	>> 3)	- 1;
492fe5e51b7Smrg	he = (mode->CrtcHSyncEnd	>> 3)	- 1;
493fe5e51b7Smrg	ht = (mode->CrtcHTotal		>> 3)	- 1;
494fe5e51b7Smrg	vd = mode->CrtcVDisplay			- 1;
495fe5e51b7Smrg	vs = mode->CrtcVSyncStart		- 1;
496fe5e51b7Smrg	ve = mode->CrtcVSyncEnd			- 1;
497fe5e51b7Smrg	vt = mode->CrtcVTotal			- 2;
498fe5e51b7Smrg
499fe5e51b7Smrg	/* HTOTAL & 0x7 equal to 0x6 in 8bpp or 0x4 in 24bpp causes strange
500fe5e51b7Smrg	 * vertical stripes
501fe5e51b7Smrg	 */
502fe5e51b7Smrg	if((ht & 0x07) == 0x06 || (ht & 0x07) == 0x04)
503fe5e51b7Smrg		ht++;
504fe5e51b7Smrg
505fe5e51b7Smrg	if (pLayout->bitsPerPixel == 24)
506fe5e51b7Smrg		wd = (pLayout->displayWidth * 3) >> (4 - BppShift);
507fe5e51b7Smrg	else
508fe5e51b7Smrg		wd = pLayout->displayWidth >> (4 - BppShift);
509fe5e51b7Smrg
510fe5e51b7Smrg	pReg->ExtVga[0] = 0;
511fe5e51b7Smrg	pReg->ExtVga[5] = 0;
512fe5e51b7Smrg
513fe5e51b7Smrg	if (mode->Flags & V_INTERLACE)
514fe5e51b7Smrg	{
515fe5e51b7Smrg		pReg->ExtVga[0] = 0x80;
516fe5e51b7Smrg		pReg->ExtVga[5] = (hs + he - ht) >> 1;
517fe5e51b7Smrg		wd <<= 1;
518fe5e51b7Smrg		vt &= 0xFFFE;
519fe5e51b7Smrg	}
520fe5e51b7Smrg
521fe5e51b7Smrg	pReg->ExtVga[0]	|= (wd & 0x300) >> 4;
522fe5e51b7Smrg	pReg->ExtVga[1]	= (((ht - 4) & 0x100) >> 8) |
523fe5e51b7Smrg				((hd & 0x100) >> 7) |
524fe5e51b7Smrg				((hs & 0x100) >> 6) |
525fe5e51b7Smrg				(ht & 0x40);
526fe5e51b7Smrg	pReg->ExtVga[2]	= ((vt & 0xc00) >> 10) |
527fe5e51b7Smrg				((vd & 0x400) >> 8) |
528fe5e51b7Smrg				((vd & 0xc00) >> 7) |
529fe5e51b7Smrg				((vs & 0xc00) >> 5) |
530fe5e51b7Smrg				((vd & 0x400) >> 3); /* linecomp */
531fe5e51b7Smrg	if (pLayout->bitsPerPixel == 24)
532fe5e51b7Smrg		pReg->ExtVga[3]	= (((1 << BppShift) * 3) - 1) | 0x80;
533fe5e51b7Smrg	else
534fe5e51b7Smrg		pReg->ExtVga[3]	= ((1 << BppShift) - 1) | 0x80;
535fe5e51b7Smrg
536fe5e51b7Smrg	pReg->ExtVga[4]	= 0;
537fe5e51b7Smrg
538fe5e51b7Smrg	pVga->CRTC[0]	= ht - 4;
539fe5e51b7Smrg	pVga->CRTC[1]	= hd;
540fe5e51b7Smrg	pVga->CRTC[2]	= hd;
541fe5e51b7Smrg	pVga->CRTC[3]	= (ht & 0x1F) | 0x80;
542fe5e51b7Smrg	pVga->CRTC[4]	= hs;
543fe5e51b7Smrg	pVga->CRTC[5]	= ((ht & 0x20) << 2) | (he & 0x1F);
544fe5e51b7Smrg	pVga->CRTC[6]	= vt & 0xFF;
545fe5e51b7Smrg	pVga->CRTC[7]	= ((vt & 0x100) >> 8 ) |
546fe5e51b7Smrg				((vd & 0x100) >> 7 ) |
547fe5e51b7Smrg				((vs & 0x100) >> 6 ) |
548fe5e51b7Smrg				((vd & 0x100) >> 5 ) |
549fe5e51b7Smrg				((vd & 0x100) >> 4 ) | /* linecomp */
550fe5e51b7Smrg				((vt & 0x200) >> 4 ) |
551fe5e51b7Smrg				((vd & 0x200) >> 3 ) |
552fe5e51b7Smrg				((vs & 0x200) >> 2 );
553fe5e51b7Smrg	pVga->CRTC[9]	= ((vd & 0x200) >> 4) |
554fe5e51b7Smrg			  ((vd & 0x200) >> 3); /* linecomp */
555fe5e51b7Smrg	pVga->CRTC[16] = vs & 0xFF;
556fe5e51b7Smrg	pVga->CRTC[17] = (ve & 0x0F) | 0x20;
557fe5e51b7Smrg	pVga->CRTC[18] = vd & 0xFF;
558fe5e51b7Smrg	pVga->CRTC[19] = wd & 0xFF;
559fe5e51b7Smrg	pVga->CRTC[21] = vd & 0xFF;
560fe5e51b7Smrg	pVga->CRTC[22] = (vt + 1) & 0xFF;
561fe5e51b7Smrg	pVga->CRTC[24] = vd & 0xFF; /* linecomp */
562fe5e51b7Smrg
563fe5e51b7Smrg	MGA_NOT_HAL(pReg->DacRegs[MGA1064_CURSOR_BASE_ADR_LOW] = pMga->FbCursorOffset >> 10);
564fe5e51b7Smrg	MGA_NOT_HAL(pReg->DacRegs[MGA1064_CURSOR_BASE_ADR_HI] = pMga->FbCursorOffset >> 18);
565fe5e51b7Smrg
566fe5e51b7Smrg	if (pMga->SyncOnGreen) {
567fe5e51b7Smrg	    MGA_NOT_HAL(
568fe5e51b7Smrg                pReg->DacRegs[MGA1064_GEN_CTL] &=
569fe5e51b7Smrg                    ~MGA1064_GEN_CTL_SYNC_ON_GREEN_DIS;
570fe5e51b7Smrg            );
571fe5e51b7Smrg
572fe5e51b7Smrg	    pReg->ExtVga[3] |= 0x40;
573fe5e51b7Smrg	}
574fe5e51b7Smrg
575fe5e51b7Smrg	/* select external clock */
576fe5e51b7Smrg	pVga->MiscOutReg |= 0x0C;
577fe5e51b7Smrg
578fe5e51b7Smrg	MGA_NOT_HAL(
579fe5e51b7Smrg	if (mode->Flags & V_DBLSCAN)
580fe5e51b7Smrg		pVga->CRTC[9] |= 0x80;
581fe5e51b7Smrg
582fe5e51b7Smrg	if(MGAISGx50(pMga)) {
583fe5e51b7Smrg		OUTREG(MGAREG_ZORG, 0);
584fe5e51b7Smrg	}
585fe5e51b7Smrg
586fe5e51b7Smrg  	MGAGSetPCLK(pScrn, mode->Clock);
587fe5e51b7Smrg	);	/* MGA_NOT_HAL */
588fe5e51b7Smrg
589fe5e51b7Smrg	/* This disables the VGA memory aperture */
590fe5e51b7Smrg	pVga->MiscOutReg &= ~0x02;
591fe5e51b7Smrg
592fe5e51b7Smrg	/* Urgh. Why do we define our own xMODEINFO structure instead
593fe5e51b7Smrg	 * of just passing the blinkin' DisplayModePtr? If we're going to
594fe5e51b7Smrg	 * just cut'n'paste routines from the HALlib, it would be better
595fe5e51b7Smrg	 * just to strip the MacroVision stuff out of the HALlib and release
596fe5e51b7Smrg	 * that, surely?
597fe5e51b7Smrg	 */
598fe5e51b7Smrg        /*********************  Second Crtc programming **************/
599fe5e51b7Smrg        /* Writing values to crtc2[] array */
600fe5e51b7Smrg        if (pMga->SecondCrtc)
601fe5e51b7Smrg        {
602fe5e51b7Smrg            MGACRTC2Get(pScrn, &ModeInfo);
603fe5e51b7Smrg            MGACRTC2GetPitch(pScrn, &ModeInfo);
604fe5e51b7Smrg            MGACRTC2GetDisplayStart(pScrn, &ModeInfo,0,0,0);
605fe5e51b7Smrg        }
606fe5e51b7Smrg
607fe5e51b7Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN
608fe5e51b7Smrg	/* Disable byte-swapping for big-endian architectures - the XFree
609fe5e51b7Smrg	   driver seems to like a little-endian framebuffer -ReneR */
610fe5e51b7Smrg	/* pReg->Option |= 0x80000000; */
611fe5e51b7Smrg	pReg->Option &= ~0x80000000;
612fe5e51b7Smrg#endif
613fe5e51b7Smrg
614fe5e51b7Smrg	return(TRUE);
615fe5e51b7Smrg}
616fe5e51b7Smrg
617fe5e51b7Smrg/*
618fe5e51b7Smrg * MGAGLoadPalette
619fe5e51b7Smrg */
620fe5e51b7Smrg
621fe5e51b7Smrgstatic void
622fe5e51b7SmrgMGAPaletteLoadCallback(ScrnInfoPtr pScrn)
623fe5e51b7Smrg{
624fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
625fe5e51b7Smrg    MGAPaletteInfo *pal = pMga->palinfo;
626fe5e51b7Smrg    int i;
627fe5e51b7Smrg
628fe5e51b7Smrg    while (!(INREG8(0x1FDA) & 0x08));
629fe5e51b7Smrg
630fe5e51b7Smrg    for(i = 0; i < 256; i++) {
631fe5e51b7Smrg	if(pal->update) {
632fe5e51b7Smrg	    outMGAdreg(MGA1064_WADR_PAL, i);
633fe5e51b7Smrg            outMGAdreg(MGA1064_COL_PAL, pal->red);
634fe5e51b7Smrg            outMGAdreg(MGA1064_COL_PAL, pal->green);
635fe5e51b7Smrg            outMGAdreg(MGA1064_COL_PAL, pal->blue);
636fe5e51b7Smrg	    pal->update = FALSE;
637fe5e51b7Smrg	}
638fe5e51b7Smrg	pal++;
639fe5e51b7Smrg    }
640fe5e51b7Smrg    pMga->PaletteLoadCallback = NULL;
641fe5e51b7Smrg}
642fe5e51b7Smrg
643fe5e51b7Smrgvoid MGAGLoadPalette(
644fe5e51b7Smrg    ScrnInfoPtr pScrn,
645fe5e51b7Smrg    int numColors,
646fe5e51b7Smrg    int *indices,
647fe5e51b7Smrg    LOCO *colors,
648fe5e51b7Smrg    VisualPtr pVisual
649fe5e51b7Smrg){
650fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
651fe5e51b7Smrg
652fe5e51b7Smrg    if((pMga->CurrentLayout.Overlay8Plus24) && (pVisual->nplanes != 8))
653fe5e51b7Smrg	return;
654fe5e51b7Smrg
655fe5e51b7Smrg     if(pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550){
656fe5e51b7Smrg	 /* load them at the retrace in the block handler instead to
657fe5e51b7Smrg	    work around some problems with static on the screen */
658fe5e51b7Smrg	while(numColors--) {
659fe5e51b7Smrg	    pMga->palinfo[*indices].update = TRUE;
660fe5e51b7Smrg	    pMga->palinfo[*indices].red   = colors[*indices].red;
661fe5e51b7Smrg	    pMga->palinfo[*indices].green = colors[*indices].green;
662fe5e51b7Smrg	    pMga->palinfo[*indices].blue  = colors[*indices].blue;
663fe5e51b7Smrg	    indices++;
664fe5e51b7Smrg	}
665fe5e51b7Smrg	pMga->PaletteLoadCallback = MGAPaletteLoadCallback;
666fe5e51b7Smrg	return;
667fe5e51b7Smrg    } else {
668fe5e51b7Smrg	while(numColors--) {
669fe5e51b7Smrg            outMGAdreg(MGA1064_WADR_PAL, *indices);
670fe5e51b7Smrg            outMGAdreg(MGA1064_COL_PAL, colors[*indices].red);
671fe5e51b7Smrg            outMGAdreg(MGA1064_COL_PAL, colors[*indices].green);
672fe5e51b7Smrg            outMGAdreg(MGA1064_COL_PAL, colors[*indices].blue);
673fe5e51b7Smrg	    indices++;
674fe5e51b7Smrg	}
675fe5e51b7Smrg    }
676fe5e51b7Smrg}
677fe5e51b7Smrg
678fe5e51b7Smrg/*
679fe5e51b7Smrg * MGAGRestorePalette
680fe5e51b7Smrg */
681fe5e51b7Smrg
682fe5e51b7Smrgstatic void
683fe5e51b7SmrgMGAGRestorePalette(ScrnInfoPtr pScrn, unsigned char* pntr)
684fe5e51b7Smrg{
685fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
686fe5e51b7Smrg    int i = 768;
687fe5e51b7Smrg
688fe5e51b7Smrg    outMGAdreg(MGA1064_WADR_PAL, 0x00);
689fe5e51b7Smrg    while(i--)
690fe5e51b7Smrg	outMGAdreg(MGA1064_COL_PAL, *(pntr++));
691fe5e51b7Smrg}
692fe5e51b7Smrg
693fe5e51b7Smrg/*
694fe5e51b7Smrg * MGAGSavePalette
695fe5e51b7Smrg */
696fe5e51b7Smrgstatic void
697fe5e51b7SmrgMGAGSavePalette(ScrnInfoPtr pScrn, unsigned char* pntr)
698fe5e51b7Smrg{
699fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
700fe5e51b7Smrg    int i = 768;
701fe5e51b7Smrg
702fe5e51b7Smrg    outMGAdreg(MGA1064_RADR_PAL, 0x00);
703fe5e51b7Smrg    while(i--)
704fe5e51b7Smrg	*(pntr++) = inMGAdreg(MGA1064_COL_PAL);
705fe5e51b7Smrg}
706fe5e51b7Smrg
707fe5e51b7Smrg/*
708fe5e51b7Smrg * MGAGRestore
709fe5e51b7Smrg *
710fe5e51b7Smrg * This function restores a video mode.	 It basically writes out all of
711fe5e51b7Smrg * the registers that have previously been saved.
712fe5e51b7Smrg */
713fe5e51b7Smrgstatic void
714fe5e51b7SmrgMGAGRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg,
715fe5e51b7Smrg	       Bool restoreFonts)
716fe5e51b7Smrg{
717fe5e51b7Smrg	int i;
718fe5e51b7Smrg	MGAPtr pMga = MGAPTR(pScrn);
719fe5e51b7Smrg	CARD32 optionMask;
720fe5e51b7Smrg
721fe5e51b7Smrg	/*
722fe5e51b7Smrg	 * Pixel Clock needs to be restored regardless if we use
723fe5e51b7Smrg	 * HALLib or not. HALlib doesn't do a good job restoring
724fe5e51b7Smrg	 * VESA modes. MATROX: hint, hint.
725fe5e51b7Smrg	 */
726fe5e51b7Smrg	if (MGAISGx50(pMga) && mgaReg->Clock) {
727fe5e51b7Smrg	    /*
728fe5e51b7Smrg	     * With HALlib program only when restoring to console!
729fe5e51b7Smrg	     * To test this we check for Clock == 0.
730fe5e51b7Smrg	     */
731fe5e51b7Smrg	    MGAG450SetPLLFreq(pScrn, mgaReg->Clock);
732fe5e51b7Smrg	    mgaReg->PIXPLLCSaved = FALSE;
733fe5e51b7Smrg	}
734fe5e51b7Smrg
735fe5e51b7Smrg        if(!pMga->SecondCrtc) {
736fe5e51b7Smrg           /* Do not set the memory config for primary cards as it
737fe5e51b7Smrg              should be correct already. Only on little endian architectures
738fe5e51b7Smrg              since we need to modify the byteswap bit. -ReneR */
739fe5e51b7Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN
740fe5e51b7Smrg           optionMask = OPTION1_MASK;
741fe5e51b7Smrg#else
742fe5e51b7Smrg           optionMask = (pMga->Primary) ? OPTION1_MASK_PRIMARY : OPTION1_MASK;
743fe5e51b7Smrg#endif
744fe5e51b7Smrg
745fe5e51b7SmrgMGA_NOT_HAL(
746fe5e51b7Smrg	   /*
747fe5e51b7Smrg	    * Code is needed to get things back to bank zero.
748fe5e51b7Smrg	    */
749fe5e51b7Smrg
750fe5e51b7Smrg	   /* restore DAC registers
751fe5e51b7Smrg	    * according to the docs we shouldn't write to reserved regs*/
752fe5e51b7Smrg	   for (i = 0; i < DACREGSIZE; i++) {
753fe5e51b7Smrg	      if( (i <= 0x03) ||
754fe5e51b7Smrg		  (i == 0x07) ||
755fe5e51b7Smrg		  (i == 0x0b) ||
756fe5e51b7Smrg		  (i == 0x0f) ||
757fe5e51b7Smrg		  ((i >= 0x13) && (i <= 0x17)) ||
758fe5e51b7Smrg		  (i == 0x1b) ||
759fe5e51b7Smrg		  (i == 0x1c) ||
760fe5e51b7Smrg		  ((i >= 0x1f) && (i <= 0x29)) ||
761fe5e51b7Smrg		  ((i >= 0x30) && (i <= 0x37)) ||
762fe5e51b7Smrg                  (MGAISGx50(pMga) && !mgaReg->PIXPLLCSaved &&
763fe5e51b7Smrg		   ((i == 0x2c) || (i == 0x2d) || (i == 0x2e) ||
764fe5e51b7Smrg		    (i == 0x4c) || (i == 0x4d) || (i == 0x4e))))
765fe5e51b7Smrg		 continue;
766fe5e51b7Smrg	      if (pMga->is_G200SE
767fe5e51b7Smrg		  && ((i == 0x2C) || (i == 0x2D) || (i == 0x2E)))
768fe5e51b7Smrg	         continue;
769fe5e51b7Smrg	      outMGAdac(i, mgaReg->DacRegs[i]);
770fe5e51b7Smrg	   }
771fe5e51b7Smrg
772fe5e51b7Smrg	   if (!MGAISGx50(pMga)) {
773fe5e51b7Smrg	       /* restore pci_option register */
774fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
775fe5e51b7Smrg	       pci_device_cfg_write_bits(pMga->PciInfo, optionMask,
776fe5e51b7Smrg					 mgaReg->Option, PCI_OPTION_REG);
777fe5e51b7Smrg
778fe5e51b7Smrg	      if (pMga->Chipset != PCI_CHIP_MGA1064) {
779fe5e51b7Smrg		  pci_device_cfg_write_bits(pMga->PciInfo, OPTION2_MASK,
780fe5e51b7Smrg					    mgaReg->Option2, PCI_MGA_OPTION2);
781fe5e51b7Smrg
782fe5e51b7Smrg		  if (pMga->Chipset == PCI_CHIP_MGAG400
783fe5e51b7Smrg		      || pMga->Chipset == PCI_CHIP_MGAG550) {
784fe5e51b7Smrg		      pci_device_cfg_write_bits(pMga->PciInfo, OPTION3_MASK,
785fe5e51b7Smrg						mgaReg->Option3,
786fe5e51b7Smrg						PCI_MGA_OPTION3);
787fe5e51b7Smrg		  }
788fe5e51b7Smrg	      }
789fe5e51b7Smrg#else
790fe5e51b7Smrg	      /* restore pci_option register */
791fe5e51b7Smrg	      pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, optionMask,
792fe5e51b7Smrg			     mgaReg->Option);
793fe5e51b7Smrg	      if (pMga->Chipset != PCI_CHIP_MGA1064)
794fe5e51b7Smrg		 pciSetBitsLong(pMga->PciTag, PCI_MGA_OPTION2, OPTION2_MASK,
795fe5e51b7Smrg				mgaReg->Option2);
796fe5e51b7Smrg	      if (pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550)
797fe5e51b7Smrg		 pciSetBitsLong(pMga->PciTag, PCI_MGA_OPTION3, OPTION3_MASK,
798fe5e51b7Smrg				mgaReg->Option3);
799fe5e51b7Smrg#endif
800fe5e51b7Smrg	   }
801fe5e51b7Smrg);	/* MGA_NOT_HAL */
802fe5e51b7Smrg#ifdef USEMGAHAL
803fe5e51b7Smrg          /*
804fe5e51b7Smrg	   * Work around another bug in HALlib: it doesn't restore the
805fe5e51b7Smrg	   * DAC width register correctly. MATROX: hint, hint.
806fe5e51b7Smrg	   */
807fe5e51b7Smrg           MGA_HAL(
808fe5e51b7Smrg    	       outMGAdac(MGA1064_MUL_CTL,mgaReg->DacRegs[0]);
809fe5e51b7Smrg  	       outMGAdac(MGA1064_MISC_CTL,mgaReg->DacRegs[1]);
810fe5e51b7Smrg	       if (!MGAISGx50(pMga)) {
811fe5e51b7Smrg		   outMGAdac(MGA1064_PIX_PLLC_M,mgaReg->DacRegs[2]);
812fe5e51b7Smrg		   outMGAdac(MGA1064_PIX_PLLC_N,mgaReg->DacRegs[3]);
813fe5e51b7Smrg		   outMGAdac(MGA1064_PIX_PLLC_P,mgaReg->DacRegs[4]);
814fe5e51b7Smrg	       }
815fe5e51b7Smrg	       );
816fe5e51b7Smrg#endif
817fe5e51b7Smrg	   /* restore CRTCEXT regs */
818fe5e51b7Smrg           for (i = 0; i < 6; i++)
819fe5e51b7Smrg	      OUTREG16(MGAREG_CRTCEXT_INDEX, (mgaReg->ExtVga[i] << 8) | i);
820fe5e51b7Smrg
821fe5e51b7Smrg	   /* This handles restoring the generic VGA registers. */
822fe5e51b7Smrg	   if (pMga->is_G200SE) {
823fe5e51b7Smrg 	      MGAG200SERestoreMode(pScrn, vgaReg);
824fe5e51b7Smrg	      if (restoreFonts)
825fe5e51b7Smrg	         MGAG200SERestoreFonts(pScrn, vgaReg);
826fe5e51b7Smrg	   } else {
827fe5e51b7Smrg	      vgaHWRestore(pScrn, vgaReg,
828fe5e51b7Smrg			VGA_SR_MODE | (restoreFonts ? VGA_SR_FONTS : 0));
829fe5e51b7Smrg	   }
830fe5e51b7Smrg  	   MGAGRestorePalette(pScrn, vgaReg->DAC);
831fe5e51b7Smrg
832fe5e51b7Smrg	   /*
833fe5e51b7Smrg	    * this is needed to properly restore start address
834fe5e51b7Smrg	    */
835fe5e51b7Smrg	   OUTREG16(MGAREG_CRTCEXT_INDEX, (mgaReg->ExtVga[0] << 8) | 0);
836fe5e51b7Smrg	} else {
837fe5e51b7Smrg	   /* Second Crtc */
838fe5e51b7Smrg	   xMODEINFO ModeInfo;
839fe5e51b7Smrg
840fe5e51b7SmrgMGA_NOT_HAL(
841fe5e51b7Smrg	   /* Enable Dual Head */
842fe5e51b7Smrg	   MGACRTC2Set(pScrn, &ModeInfo);
843fe5e51b7Smrg	   MGAEnableSecondOutPut(pScrn, &ModeInfo);
844fe5e51b7Smrg	   MGACRTC2SetPitch(pScrn, &ModeInfo);
845fe5e51b7Smrg	   MGACRTC2SetDisplayStart(pScrn, &ModeInfo,0,0,0);
846fe5e51b7Smrg
847fe5e51b7Smrg	   for (i = 0x80; i <= 0xa0; i ++) {
848fe5e51b7Smrg                if (i== 0x8d) {
849fe5e51b7Smrg		   i = 0x8f;
850fe5e51b7Smrg		   continue;
851fe5e51b7Smrg		}
852fe5e51b7Smrg                outMGAdac(i,   mgaReg->dac2[ i - 0x80]);
853fe5e51b7Smrg	   }
854fe5e51b7Smrg); /* MGA_NOT_HAL */
855fe5e51b7Smrg
856fe5e51b7Smrg        }
857fe5e51b7Smrg
858fe5e51b7Smrg#ifdef DEBUG
859fe5e51b7Smrg	ErrorF("Setting DAC:");
860fe5e51b7Smrg	for (i=0; i<DACREGSIZE; i++) {
861fe5e51b7Smrg#if 1
862fe5e51b7Smrg		if(!(i%16)) ErrorF("\n%02X: ",i);
863fe5e51b7Smrg		ErrorF("%02X ", mgaReg->DacRegs[i]);
864fe5e51b7Smrg#else
865fe5e51b7Smrg		if(!(i%8)) ErrorF("\n%02X: ",i);
866fe5e51b7Smrg		ErrorF("0x%02X, ", mgaReg->DacRegs[i]);
867fe5e51b7Smrg#endif
868fe5e51b7Smrg	}
869fe5e51b7Smrg	ErrorF("\nOPTION  = %08lX\n", mgaReg->Option);
870fe5e51b7Smrg	ErrorF("OPTION2 = %08lX\n", mgaReg->Option2);
871fe5e51b7Smrg	ErrorF("CRTCEXT:");
872fe5e51b7Smrg	for (i=0; i<6; i++) ErrorF(" %02X", mgaReg->ExtVga[i]);
873fe5e51b7Smrg	ErrorF("\n");
874fe5e51b7Smrg#endif
875fe5e51b7Smrg
876fe5e51b7Smrg}
877fe5e51b7Smrg
878fe5e51b7Smrg/*
879fe5e51b7Smrg * MGAGSave
880fe5e51b7Smrg *
881fe5e51b7Smrg * This function saves the video state.
882fe5e51b7Smrg */
883fe5e51b7Smrgstatic void
884fe5e51b7SmrgMGAGSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg,
885fe5e51b7Smrg	    Bool saveFonts)
886fe5e51b7Smrg{
887fe5e51b7Smrg	int i;
888fe5e51b7Smrg	MGAPtr pMga = MGAPTR(pScrn);
889fe5e51b7Smrg
890fe5e51b7Smrg	/*
891fe5e51b7Smrg	 * Pixel Clock needs to be restored regardless if we use
892fe5e51b7Smrg	 * HALLib or not. HALlib doesn't do a good job restoring
893fe5e51b7Smrg	 * VESA modes (s.o.). MATROX: hint, hint.
894fe5e51b7Smrg	 */
895fe5e51b7Smrg	if (MGAISGx50(pMga)) {
896fe5e51b7Smrg	    mgaReg->Clock = MGAG450SavePLLFreq(pScrn);
897fe5e51b7Smrg	}
898fe5e51b7Smrg
899fe5e51b7Smrg	if(pMga->SecondCrtc == TRUE) {
900fe5e51b7Smrg	   for(i = 0x80; i < 0xa0; i++)
901fe5e51b7Smrg	      mgaReg->dac2[i-0x80] = inMGAdac(i);
902fe5e51b7Smrg
903fe5e51b7Smrg	   return;
904fe5e51b7Smrg	}
905fe5e51b7Smrg
906fe5e51b7Smrg	MGA_NOT_HAL(
907fe5e51b7Smrg	/* Allocate the DacRegs space if not done already */
908fe5e51b7Smrg	if (mgaReg->DacRegs == NULL) {
909fe5e51b7Smrg		mgaReg->DacRegs = xnfcalloc(DACREGSIZE, 1);
910fe5e51b7Smrg	}
911fe5e51b7Smrg	);	/* MGA_NOT_HAL */
912fe5e51b7Smrg
913fe5e51b7Smrg	/*
914fe5e51b7Smrg	 * Code is needed to get back to bank zero.
915fe5e51b7Smrg	 */
916fe5e51b7Smrg	OUTREG16(MGAREG_CRTCEXT_INDEX, 0x0004);
917fe5e51b7Smrg
918fe5e51b7Smrg	/*
919fe5e51b7Smrg	 * This function will handle creating the data structure and filling
920fe5e51b7Smrg	 * in the generic VGA portion.
921fe5e51b7Smrg	 */
922fe5e51b7Smrg	if (pMga->is_G200SE) {
923fe5e51b7Smrg 	    MGAG200SESaveMode(pScrn, vgaReg);
924fe5e51b7Smrg	    if (saveFonts)
925fe5e51b7Smrg		MGAG200SESaveFonts(pScrn, vgaReg);
926fe5e51b7Smrg	} else {
927fe5e51b7Smrg	    vgaHWSave(pScrn, vgaReg, VGA_SR_MODE |
928fe5e51b7Smrg				     (saveFonts ? VGA_SR_FONTS : 0));
929fe5e51b7Smrg	}
930fe5e51b7Smrg	MGAGSavePalette(pScrn, vgaReg->DAC);
931fe5e51b7Smrg	/*
932fe5e51b7Smrg	 * Work around another bug in HALlib: it doesn't restore the
933fe5e51b7Smrg	 * DAC width register correctly.
934fe5e51b7Smrg	 */
935fe5e51b7Smrg
936fe5e51b7Smrg#ifdef USEMGAHAL
937fe5e51b7Smrg	/*
938fe5e51b7Smrg	 * Work around another bug in HALlib: it doesn't restore the
939fe5e51b7Smrg	 * DAC width register correctly (s.o.). MATROX: hint, hint.
940fe5e51b7Smrg	 */
941fe5e51b7Smrg  	MGA_HAL(
942fe5e51b7Smrg  	    if (mgaReg->DacRegs == NULL) {
943fe5e51b7Smrg  		mgaReg->DacRegs = xnfcalloc(MGAISGx50(pMga) ? 2 : 5, 1);
944fe5e51b7Smrg  	    }
945fe5e51b7Smrg    	    mgaReg->DacRegs[0] = inMGAdac(MGA1064_MUL_CTL);
946fe5e51b7Smrg  	    mgaReg->DacRegs[1] = inMGAdac(MGA1064_MISC_CTL);
947fe5e51b7Smrg	    if (!MGAISGx50(pMga)) {
948fe5e51b7Smrg		mgaReg->DacRegs[2] = inMGAdac(MGA1064_PIX_PLLC_M);
949fe5e51b7Smrg		mgaReg->DacRegs[3] = inMGAdac(MGA1064_PIX_PLLC_N);
950fe5e51b7Smrg		mgaReg->DacRegs[4] = inMGAdac(MGA1064_PIX_PLLC_P);
951fe5e51b7Smrg	    }
952fe5e51b7Smrg  	);
953fe5e51b7Smrg#endif
954fe5e51b7Smrg	MGA_NOT_HAL(
955fe5e51b7Smrg	/*
956fe5e51b7Smrg	 * The port I/O code necessary to read in the extended registers.
957fe5e51b7Smrg	 */
958fe5e51b7Smrg	for (i = 0; i < DACREGSIZE; i++)
959fe5e51b7Smrg		mgaReg->DacRegs[i] = inMGAdac(i);
960fe5e51b7Smrg
961fe5e51b7Smrg        mgaReg->PIXPLLCSaved = TRUE;
962fe5e51b7Smrg
963fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
964fe5e51b7Smrg	pci_device_cfg_read_u32(pMga->PciInfo, & mgaReg->Option,
965fe5e51b7Smrg				PCI_OPTION_REG);
966fe5e51b7Smrg	pci_device_cfg_read_u32(pMga->PciInfo, & mgaReg->Option2,
967fe5e51b7Smrg				PCI_MGA_OPTION2);
968fe5e51b7Smrg#else
969fe5e51b7Smrg	mgaReg->Option = pciReadLong(pMga->PciTag, PCI_OPTION_REG);
970fe5e51b7Smrg
971fe5e51b7Smrg	mgaReg->Option2 = pciReadLong(pMga->PciTag, PCI_MGA_OPTION2);
972fe5e51b7Smrg#endif
973fe5e51b7Smrg	if (pMga->Chipset == PCI_CHIP_MGAG400 || pMga->Chipset == PCI_CHIP_MGAG550)
974fe5e51b7Smrg#ifdef XSERVER_LIBPCIACCESS
975fe5e51b7Smrg		    pci_device_cfg_read_u32(pMga->PciInfo, & mgaReg->Option3,
976fe5e51b7Smrg					    PCI_MGA_OPTION3);
977fe5e51b7Smrg#else
978fe5e51b7Smrg	    mgaReg->Option3 = pciReadLong(pMga->PciTag, PCI_MGA_OPTION3);
979fe5e51b7Smrg#endif
980fe5e51b7Smrg	);	/* MGA_NOT_HAL */
981fe5e51b7Smrg
982fe5e51b7Smrg	for (i = 0; i < 6; i++)
983fe5e51b7Smrg	{
984fe5e51b7Smrg		OUTREG8(MGAREG_CRTCEXT_INDEX, i);
985fe5e51b7Smrg		mgaReg->ExtVga[i] = INREG8(MGAREG_CRTCEXT_DATA);
986fe5e51b7Smrg	}
987fe5e51b7Smrg
988fe5e51b7Smrg#ifdef DEBUG
989fe5e51b7Smrg	ErrorF("Saved values:\nDAC:");
990fe5e51b7Smrg	for (i=0; i<DACREGSIZE; i++) {
991fe5e51b7Smrg#if 1
992fe5e51b7Smrg		if(!(i%16)) ErrorF("\n%02X: ",i);
993fe5e51b7Smrg		ErrorF("%02X ", mgaReg->DacRegs[i]);
994fe5e51b7Smrg#else
995fe5e51b7Smrg		if(!(i%8)) ErrorF("\n%02X: ",i);
996fe5e51b7Smrg		ErrorF("0x%02X, ", mgaReg->DacRegs[i]);
997fe5e51b7Smrg#endif
998fe5e51b7Smrg	}
999fe5e51b7Smrg	ErrorF("\nOPTION  = %08lX\n:", mgaReg->Option);
1000fe5e51b7Smrg	ErrorF("OPTION2 = %08lX\nCRTCEXT:", mgaReg->Option2);
1001fe5e51b7Smrg	for (i=0; i<6; i++) ErrorF(" %02X", mgaReg->ExtVga[i]);
1002fe5e51b7Smrg	ErrorF("\n");
1003fe5e51b7Smrg#endif
1004fe5e51b7Smrg}
1005fe5e51b7Smrg
1006fe5e51b7Smrg/****
1007fe5e51b7Smrg ***  HW Cursor
1008fe5e51b7Smrg */
1009fe5e51b7Smrgstatic void
1010fe5e51b7SmrgMGAGLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
1011fe5e51b7Smrg{
1012fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1013fe5e51b7Smrg    CARD32 *dst = (CARD32*)(pMga->FbBase + pMga->FbCursorOffset);
1014fe5e51b7Smrg    int i = 128;
1015fe5e51b7Smrg
1016fe5e51b7Smrg    /* swap bytes in each line */
1017fe5e51b7Smrg    while( i-- ) {
1018fe5e51b7Smrg        *dst++ = (src[4] << 24) | (src[5] << 16) | (src[6] << 8) | src[7];
1019fe5e51b7Smrg        *dst++ = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
1020fe5e51b7Smrg        src += 8;
1021fe5e51b7Smrg    }
1022fe5e51b7Smrg}
1023fe5e51b7Smrg
1024fe5e51b7Smrgstatic void
1025fe5e51b7SmrgMGAGShowCursor(ScrnInfoPtr pScrn)
1026fe5e51b7Smrg{
1027fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1028fe5e51b7Smrg    /* Enable cursor - X-Windows mode */
1029fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_CTL, 0x03);
1030fe5e51b7Smrg}
1031fe5e51b7Smrg
1032fe5e51b7Smrgstatic void
1033fe5e51b7SmrgMGAGShowCursorG100(ScrnInfoPtr pScrn)
1034fe5e51b7Smrg{
1035fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1036fe5e51b7Smrg    /* Enable cursor - X-Windows mode */
1037fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_CTL, 0x01);
1038fe5e51b7Smrg}
1039fe5e51b7Smrg
1040fe5e51b7Smrgstatic void
1041fe5e51b7SmrgMGAGHideCursor(ScrnInfoPtr pScrn)
1042fe5e51b7Smrg{
1043fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1044fe5e51b7Smrg    /* Disable cursor */
1045fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_CTL, 0x00);
1046fe5e51b7Smrg}
1047fe5e51b7Smrg
1048fe5e51b7Smrgstatic void
1049fe5e51b7SmrgMGAGSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
1050fe5e51b7Smrg{
1051fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1052fe5e51b7Smrg    x += 64;
1053fe5e51b7Smrg    y += 64;
1054fe5e51b7Smrg
1055fe5e51b7Smrg#ifdef USEMGAHAL
1056fe5e51b7Smrg    MGA_HAL(
1057fe5e51b7Smrg	    x += pMga->HALGranularityOffX;
1058fe5e51b7Smrg	    y += pMga->HALGranularityOffY;
1059fe5e51b7Smrg    );
1060fe5e51b7Smrg#endif
1061fe5e51b7Smrg    /* cursor update must never occurs during a retrace period (pp 4-160) */
1062fe5e51b7Smrg    while( INREG( MGAREG_Status ) & 0x08 );
1063fe5e51b7Smrg
1064fe5e51b7Smrg    /* Output position - "only" 12 bits of location documented */
1065fe5e51b7Smrg    OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_XLOW, (x & 0xFF));
1066fe5e51b7Smrg    OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_XHI, (x & 0xF00) >> 8);
1067fe5e51b7Smrg    OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_YLOW, (y & 0xFF));
1068fe5e51b7Smrg    OUTREG8( RAMDAC_OFFSET + MGA1064_CUR_YHI, (y & 0xF00) >> 8);
1069fe5e51b7Smrg}
1070fe5e51b7Smrg
1071fe5e51b7Smrg
1072fe5e51b7Smrgstatic void
1073fe5e51b7SmrgMGAGSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
1074fe5e51b7Smrg{
1075fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1076fe5e51b7Smrg
1077fe5e51b7Smrg    /* Background color */
1078fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL0_RED,   (bg & 0x00FF0000) >> 16);
1079fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL0_GREEN, (bg & 0x0000FF00) >> 8);
1080fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL0_BLUE,  (bg & 0x000000FF));
1081fe5e51b7Smrg
1082fe5e51b7Smrg    /* Foreground color */
1083fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL1_RED,   (fg & 0x00FF0000) >> 16);
1084fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL1_GREEN, (fg & 0x0000FF00) >> 8);
1085fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL1_BLUE,  (fg & 0x000000FF));
1086fe5e51b7Smrg}
1087fe5e51b7Smrg
1088fe5e51b7Smrgstatic void
1089fe5e51b7SmrgMGAGSetCursorColorsG100(ScrnInfoPtr pScrn, int bg, int fg)
1090fe5e51b7Smrg{
1091fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1092fe5e51b7Smrg
1093fe5e51b7Smrg    /* Background color */
1094fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL1_RED,   (bg & 0x00FF0000) >> 16);
1095fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL1_GREEN, (bg & 0x0000FF00) >> 8);
1096fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL1_BLUE,  (bg & 0x000000FF));
1097fe5e51b7Smrg
1098fe5e51b7Smrg    /* Foreground color */
1099fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL2_RED,   (fg & 0x00FF0000) >> 16);
1100fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL2_GREEN, (fg & 0x0000FF00) >> 8);
1101fe5e51b7Smrg    outMGAdac(MGA1064_CURSOR_COL2_BLUE,  (fg & 0x000000FF));
1102fe5e51b7Smrg}
1103fe5e51b7Smrg
1104fe5e51b7Smrgstatic Bool
1105fe5e51b7SmrgMGAGUseHWCursor(ScreenPtr pScrn, CursorPtr pCurs)
1106fe5e51b7Smrg{
1107fe5e51b7Smrg    MGAPtr pMga = MGAPTR(xf86Screens[pScrn->myNum]);
1108fe5e51b7Smrg   /* This needs to detect if its on the second dac */
1109fe5e51b7Smrg    if( XF86SCRNINFO(pScrn)->currentMode->Flags & V_DBLSCAN )
1110fe5e51b7Smrg    	return FALSE;
1111fe5e51b7Smrg    if( pMga->SecondCrtc == TRUE )
1112fe5e51b7Smrg     	return FALSE;
1113fe5e51b7Smrg    return TRUE;
1114fe5e51b7Smrg}
1115fe5e51b7Smrg
1116fe5e51b7Smrg
1117fe5e51b7Smrg/*
1118fe5e51b7Smrg * According to mga-1064g.pdf pp215-216 (4-179 & 4-180) the low bits of
1119fe5e51b7Smrg * XGENIODATA and XGENIOCTL are connected to the 4 DDC pins, but don't say
1120fe5e51b7Smrg * which VGA line is connected to each DDC pin, so I've had to guess.
1121fe5e51b7Smrg *
1122fe5e51b7Smrg * DDC1 support only requires DDC_SDA_MASK,
1123fe5e51b7Smrg * DDC2 support requires DDC_SDA_MASK and DDC_SCL_MASK
1124fe5e51b7Smrg *
1125fe5e51b7Smrg * If we want DDC on second head (P2) then we must use DDC2 protocol (I2C)
1126fe5e51b7Smrg *
1127fe5e51b7Smrg * Be careful, DDC1 and DDC2 refer to protocols, DDC_P1 and DDC_P2 refer to
1128fe5e51b7Smrg * DDC data coming in on which videoport on the card
1129fe5e51b7Smrg */
1130fe5e51b7Smrgstatic const int DDC_P1_SDA_MASK = (1 << 1);
1131fe5e51b7Smrgstatic const int DDC_P1_SCL_MASK = (1 << 3);
1132fe5e51b7Smrgstatic const int DDC_P2_SDA_MASK = (1 << 0);
1133fe5e51b7Smrgstatic const int DDC_P2_SCL_MASK = (1 << 2);
1134fe5e51b7Smrgstatic const int MAVEN_SDA_MASK = (1 << 4);
1135fe5e51b7Smrgstatic const int MAVEN_SCL_MASK = (1 << 5);
1136fe5e51b7Smrg
1137fe5e51b7Smrgstatic unsigned int
1138fe5e51b7SmrgMGAG_ddc1Read(ScrnInfoPtr pScrn)
1139fe5e51b7Smrg{
1140fe5e51b7Smrg  MGAPtr pMga = MGAPTR(pScrn);
1141fe5e51b7Smrg  unsigned char val;
1142fe5e51b7Smrg
1143fe5e51b7Smrg  /* Define the SDA as an input */
1144fe5e51b7Smrg  outMGAdacmsk(MGA1064_GEN_IO_CTL, ~(DDC_P1_SCL_MASK | DDC_P1_SDA_MASK), 0);
1145fe5e51b7Smrg
1146fe5e51b7Smrg  /* wait for Vsync */
1147fe5e51b7Smrg  if (pMga->is_G200SE) {
1148fe5e51b7Smrg    usleep(4);
1149fe5e51b7Smrg  } else {
1150fe5e51b7Smrg    while( INREG( MGAREG_Status ) & 0x08 );
1151fe5e51b7Smrg    while( ! (INREG( MGAREG_Status ) & 0x08) );
1152fe5e51b7Smrg  }
1153fe5e51b7Smrg
1154fe5e51b7Smrg  /* Get the result */
1155fe5e51b7Smrg  val = (inMGAdac(MGA1064_GEN_IO_DATA) & DDC_P1_SDA_MASK);
1156fe5e51b7Smrg  return val;
1157fe5e51b7Smrg}
1158fe5e51b7Smrg
1159fe5e51b7Smrgstatic void
1160fe5e51b7SmrgMGAG_I2CGetBits(I2CBusPtr b, int *clock, int *data, int my_scl_mask, int my_sda_mask)
1161fe5e51b7Smrg{
1162fe5e51b7Smrg  ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
1163fe5e51b7Smrg  MGAPtr pMga = MGAPTR(pScrn);
1164fe5e51b7Smrg  unsigned char val;
1165fe5e51b7Smrg
1166fe5e51b7Smrg   /* Get the result. */
1167fe5e51b7Smrg   val = inMGAdac(MGA1064_GEN_IO_DATA);
1168fe5e51b7Smrg
1169fe5e51b7Smrg   *clock = (val & my_scl_mask) != 0;
1170fe5e51b7Smrg   *data  = (val & my_sda_mask) != 0;
1171fe5e51b7Smrg#ifdef DEBUG
1172fe5e51b7Smrg  ErrorF("MGAG_I2CGetBits(%p,...) val=0x%x, returns clock %d, data %d\n", b, val, *clock, *data);
1173fe5e51b7Smrg#endif
1174fe5e51b7Smrg}
1175fe5e51b7Smrg
1176fe5e51b7Smrg/*
1177fe5e51b7Smrg * ATTENTION! - the DATA and CLOCK lines need to be tri-stated when
1178fe5e51b7Smrg * high. Therefore turn off output driver for the line to set line
1179fe5e51b7Smrg * to high. High signal is maintained by a 15k Ohm pull-up resistor.
1180fe5e51b7Smrg */
1181fe5e51b7Smrgstatic void
1182fe5e51b7SmrgMGAG_I2CPutBits(I2CBusPtr b, int clock, int data, int my_scl_mask, int my_sda_mask)
1183fe5e51b7Smrg{
1184fe5e51b7Smrg  ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
1185fe5e51b7Smrg  MGAPtr pMga = MGAPTR(pScrn);
1186fe5e51b7Smrg  unsigned char drv, val;
1187fe5e51b7Smrg
1188fe5e51b7Smrg  val = (clock ? my_scl_mask : 0) | (data ? my_sda_mask : 0);
1189fe5e51b7Smrg  drv = ((!clock) ? my_scl_mask : 0) | ((!data) ? my_sda_mask : 0);
1190fe5e51b7Smrg
1191fe5e51b7Smrg  /* Write the values */
1192fe5e51b7Smrg  outMGAdacmsk(MGA1064_GEN_IO_CTL, ~(my_scl_mask | my_sda_mask) , drv);
1193fe5e51b7Smrg  outMGAdacmsk(MGA1064_GEN_IO_DATA, ~(my_scl_mask | my_sda_mask) , val);
1194fe5e51b7Smrg#ifdef DEBUG
1195fe5e51b7Smrg  ErrorF("MGAG_I2CPutBits(%p, %d, %d) val=0x%x\n", b, clock, data, val);
1196fe5e51b7Smrg#endif
1197fe5e51b7Smrg}
1198fe5e51b7Smrg
1199fe5e51b7Smrg/* FIXME, can we use some neater way besides these silly stubs? */
1200fe5e51b7Smrg
1201fe5e51b7Smrgstatic void
1202fe5e51b7SmrgMGAG_DDC_P1_I2CPutBits(I2CBusPtr b, int clock, int data)
1203fe5e51b7Smrg{
1204fe5e51b7Smrg	MGAG_I2CPutBits(b, clock, data, DDC_P1_SCL_MASK, DDC_P1_SDA_MASK);
1205fe5e51b7Smrg}
1206fe5e51b7Smrgstatic void
1207fe5e51b7SmrgMGAG_DDC_P2_I2CPutBits(I2CBusPtr b, int clock, int data)
1208fe5e51b7Smrg{
1209fe5e51b7Smrg	MGAG_I2CPutBits(b, clock, data, DDC_P2_SCL_MASK, DDC_P2_SDA_MASK);
1210fe5e51b7Smrg}
1211fe5e51b7Smrgstatic void
1212fe5e51b7SmrgMGAG_MAVEN_I2CPutBits(I2CBusPtr b, int clock, int data)
1213fe5e51b7Smrg{
1214fe5e51b7Smrg	MGAG_I2CPutBits(b, clock, data, MAVEN_SCL_MASK, MAVEN_SDA_MASK);
1215fe5e51b7Smrg}
1216fe5e51b7Smrg
1217fe5e51b7Smrgstatic void
1218fe5e51b7SmrgMGAG_DDC_P1_I2CGetBits(I2CBusPtr b, int *clock, int *data)
1219fe5e51b7Smrg{
1220fe5e51b7Smrg	MGAG_I2CGetBits(b, clock, data, DDC_P1_SCL_MASK, DDC_P1_SDA_MASK);
1221fe5e51b7Smrg}
1222fe5e51b7Smrgstatic void
1223fe5e51b7SmrgMGAG_DDC_P2_I2CGetBits(I2CBusPtr b, int *clock, int *data)
1224fe5e51b7Smrg{
1225fe5e51b7Smrg	MGAG_I2CGetBits(b, clock, data, DDC_P2_SCL_MASK, DDC_P2_SDA_MASK);
1226fe5e51b7Smrg}
1227fe5e51b7Smrgstatic void
1228fe5e51b7SmrgMGAG_MAVEN_I2CGetBits(I2CBusPtr b, int *clock, int *data)
1229fe5e51b7Smrg{
1230fe5e51b7Smrg	MGAG_I2CGetBits(b, clock, data, MAVEN_SCL_MASK, MAVEN_SDA_MASK);
1231fe5e51b7Smrg}
1232fe5e51b7Smrg
1233fe5e51b7SmrgBool
1234fe5e51b7SmrgMGAG_i2cInit(ScrnInfoPtr pScrn)
1235fe5e51b7Smrg{
1236fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1237fe5e51b7Smrg    I2CBusPtr I2CPtr;
1238fe5e51b7Smrg
1239fe5e51b7Smrg    if (pMga->SecondCrtc == FALSE) {
1240fe5e51b7Smrg	    I2CPtr = xf86CreateI2CBusRec();
1241fe5e51b7Smrg	    if(!I2CPtr) return FALSE;
1242fe5e51b7Smrg
1243fe5e51b7Smrg	    pMga->DDC_Bus1 = I2CPtr;
1244fe5e51b7Smrg
1245fe5e51b7Smrg	    I2CPtr->BusName    = "DDC P1";
1246fe5e51b7Smrg	    I2CPtr->scrnIndex  = pScrn->scrnIndex;
1247fe5e51b7Smrg	    I2CPtr->I2CPutBits = MGAG_DDC_P1_I2CPutBits;
1248fe5e51b7Smrg	    I2CPtr->I2CGetBits = MGAG_DDC_P1_I2CGetBits;
1249fe5e51b7Smrg	    I2CPtr->AcknTimeout = 5;
1250fe5e51b7Smrg
1251fe5e51b7Smrg	    if (!xf86I2CBusInit(I2CPtr)) {
1252fe5e51b7Smrg		xf86DestroyI2CBusRec(pMga->DDC_Bus1, TRUE, TRUE);
1253fe5e51b7Smrg		pMga->DDC_Bus1 = NULL;
1254fe5e51b7Smrg		return FALSE;
1255fe5e51b7Smrg	    }
1256fe5e51b7Smrg    }
1257fe5e51b7Smrg    else {
1258fe5e51b7Smrg    /* We have a dual head setup on G-series, set up DDC #2. */
1259fe5e51b7Smrg	    I2CPtr = xf86CreateI2CBusRec();
1260fe5e51b7Smrg	    if(!I2CPtr) return FALSE;
1261fe5e51b7Smrg
1262fe5e51b7Smrg	    pMga->DDC_Bus2 = I2CPtr;
1263fe5e51b7Smrg
1264fe5e51b7Smrg	    I2CPtr->BusName    = "DDC P2";
1265fe5e51b7Smrg	    I2CPtr->scrnIndex  = pScrn->scrnIndex;
1266fe5e51b7Smrg	    I2CPtr->I2CPutBits = MGAG_DDC_P2_I2CPutBits;
1267fe5e51b7Smrg	    I2CPtr->I2CGetBits = MGAG_DDC_P2_I2CGetBits;
1268fe5e51b7Smrg	    I2CPtr->AcknTimeout = 5;
1269fe5e51b7Smrg
1270fe5e51b7Smrg	    if (!xf86I2CBusInit(I2CPtr)) {
1271fe5e51b7Smrg		    xf86DestroyI2CBusRec(pMga->DDC_Bus2, TRUE, TRUE);
1272fe5e51b7Smrg		    pMga->DDC_Bus2 = NULL;
1273fe5e51b7Smrg	    }
1274fe5e51b7Smrg	    else {
1275fe5e51b7Smrg		    if (!xf86I2CProbeAddress(pMga->DDC_Bus2, 0xA0)) {  /* 0xA0 is DDC EEPROM address */
1276fe5e51b7Smrg			    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "DDC #2 unavailable -> TV cable connected or no monitor connected!\n");
1277fe5e51b7Smrg			    pMga->Crtc2IsTV = TRUE;  /* assume for now.  We need to fix HAL interactions. */
1278fe5e51b7Smrg		    }
1279fe5e51b7Smrg	    }
1280fe5e51b7Smrg
1281fe5e51b7Smrg	/* Then try to set up MAVEN bus. */
1282fe5e51b7Smrg
1283fe5e51b7Smrg	    I2CPtr = xf86CreateI2CBusRec();
1284fe5e51b7Smrg	    if(!I2CPtr) return FALSE;
1285fe5e51b7Smrg	    pMga->Maven_Bus = I2CPtr;
1286fe5e51b7Smrg
1287fe5e51b7Smrg	    I2CPtr->BusName    = "MAVEN";
1288fe5e51b7Smrg	    I2CPtr->scrnIndex  = pScrn->scrnIndex;
1289fe5e51b7Smrg	    I2CPtr->I2CPutBits = MGAG_MAVEN_I2CPutBits;
1290fe5e51b7Smrg	    I2CPtr->I2CGetBits = MGAG_MAVEN_I2CGetBits;
1291fe5e51b7Smrg	    I2CPtr->StartTimeout = 5;
1292fe5e51b7Smrg
1293fe5e51b7Smrg	    if (!xf86I2CBusInit(I2CPtr)) {
1294fe5e51b7Smrg		    xf86DestroyI2CBusRec(pMga->Maven_Bus, TRUE, TRUE);
1295fe5e51b7Smrg		    pMga->Maven_Bus = NULL;
1296fe5e51b7Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to register MAVEN I2C bus!\n");
1297fe5e51b7Smrg	    }
1298fe5e51b7Smrg	    else {
1299fe5e51b7Smrg		    Bool failed = FALSE;
1300fe5e51b7Smrg			/* Try to detect the MAVEN. */
1301fe5e51b7Smrg		    if (xf86I2CProbeAddress(pMga->Maven_Bus, MAVEN_READ) == TRUE) {
1302fe5e51b7Smrg			I2CDevPtr dp = xf86CreateI2CDevRec();
1303fe5e51b7Smrg			if (dp) {
1304fe5e51b7Smrg				I2CByte maven_ver;
1305fe5e51b7Smrg
1306fe5e51b7Smrg				pMga->Maven = dp;
1307fe5e51b7Smrg				dp->DevName = "MGA-TVO";
1308fe5e51b7Smrg				dp->SlaveAddr = MAVEN_WRITE;
1309fe5e51b7Smrg				dp->pI2CBus = pMga->Maven_Bus;
1310fe5e51b7Smrg				if (!xf86I2CDevInit(dp)) {
1311fe5e51b7Smrg					xf86DestroyI2CDevRec(dp, TRUE);
1312fe5e51b7Smrg					pMga->Maven = NULL;
1313fe5e51b7Smrg					failed = TRUE;
1314fe5e51b7Smrg				}
1315fe5e51b7Smrg				if (MGAMavenRead(pScrn, 0xB2, &maven_ver)) {
1316fe5e51b7Smrg					if (maven_ver < 0x14) {  /* heuristic stolen from matroxfb */
1317fe5e51b7Smrg						xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MAVEN revision MGA-TVO-B detected (0x%x)\n", maven_ver);
1318fe5e51b7Smrg						pMga->Maven_Version = 'B';
1319fe5e51b7Smrg					}
1320fe5e51b7Smrg					else {
1321fe5e51b7Smrg						xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MAVEN revision MGA-TVO-C detected (0x%x)\n", maven_ver);
1322fe5e51b7Smrg						pMga->Maven_Version = 'C';
1323fe5e51b7Smrg					}
1324fe5e51b7Smrg				}
1325fe5e51b7Smrg				else {
1326fe5e51b7Smrg					xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to determine MAVEN hardware version!\n");
1327fe5e51b7Smrg				}
1328fe5e51b7Smrg			}
1329fe5e51b7Smrg			else {
1330fe5e51b7Smrg				failed = TRUE;
1331fe5e51b7Smrg			}
1332fe5e51b7Smrg		    }
1333fe5e51b7Smrg		    else {
1334fe5e51b7Smrg			    failed = TRUE;
1335fe5e51b7Smrg		    }
1336fe5e51b7Smrg
1337fe5e51b7Smrg		    if (failed) {
1338fe5e51b7Smrg		    	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Failed to register MGA-TVO I2C device!\n");
1339fe5e51b7Smrg			pMga->Maven = NULL;
1340fe5e51b7Smrg			pMga->Maven_Version = 0;
1341fe5e51b7Smrg		   }
1342fe5e51b7Smrg	    }
1343fe5e51b7Smrg    }
1344fe5e51b7Smrg
1345fe5e51b7Smrg    return TRUE;
1346fe5e51b7Smrg}
1347fe5e51b7Smrg
1348fe5e51b7Smrg
1349fe5e51b7Smrg/*
1350fe5e51b7Smrg * MGAGRamdacInit
1351fe5e51b7Smrg * Handle broken G100 special.
1352fe5e51b7Smrg */
1353fe5e51b7Smrgstatic void
1354fe5e51b7SmrgMGAGRamdacInit(ScrnInfoPtr pScrn)
1355fe5e51b7Smrg{
1356fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1357fe5e51b7Smrg    MGARamdacPtr MGAdac = &pMga->Dac;
1358fe5e51b7Smrg
1359fe5e51b7Smrg    MGAdac->isHwCursor             = TRUE;
1360fe5e51b7Smrg    MGAdac->CursorOffscreenMemSize = 1024;
1361fe5e51b7Smrg    MGAdac->CursorMaxWidth         = 64;
1362fe5e51b7Smrg    MGAdac->CursorMaxHeight        = 64;
1363fe5e51b7Smrg    MGAdac->SetCursorPosition      = MGAGSetCursorPosition;
1364fe5e51b7Smrg    MGAdac->LoadCursorImage        = MGAGLoadCursorImage;
1365fe5e51b7Smrg    MGAdac->HideCursor             = MGAGHideCursor;
1366fe5e51b7Smrg    if ((pMga->Chipset == PCI_CHIP_MGAG100)
1367fe5e51b7Smrg	|| (pMga->Chipset == PCI_CHIP_MGAG100)) {
1368fe5e51b7Smrg      MGAdac->SetCursorColors        = MGAGSetCursorColorsG100;
1369fe5e51b7Smrg      MGAdac->ShowCursor             = MGAGShowCursorG100;
1370fe5e51b7Smrg    } else {
1371fe5e51b7Smrg      MGAdac->SetCursorColors        = MGAGSetCursorColors;
1372fe5e51b7Smrg      MGAdac->ShowCursor             = MGAGShowCursor;
1373fe5e51b7Smrg    }
1374fe5e51b7Smrg    MGAdac->UseHWCursor            = MGAGUseHWCursor;
1375fe5e51b7Smrg    MGAdac->CursorFlags            =
1376fe5e51b7Smrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN
1377fe5e51b7Smrg    				HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
1378fe5e51b7Smrg#endif
1379fe5e51b7Smrg    				HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
1380fe5e51b7Smrg    				HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;
1381fe5e51b7Smrg
1382fe5e51b7Smrg    MGAdac->LoadPalette 	   = MGAGLoadPalette;
1383fe5e51b7Smrg    MGAdac->RestorePalette	   = MGAGRestorePalette;
1384fe5e51b7Smrg
1385fe5e51b7Smrg
1386fe5e51b7Smrg    MGAdac->maxPixelClock = pMga->bios.pixel.max_freq;
1387fe5e51b7Smrg    MGAdac->ClockFrom = X_PROBED;
1388fe5e51b7Smrg
1389fe5e51b7Smrg    /* Disable interleaving and set the rounding value */
1390fe5e51b7Smrg    pMga->Interleave = FALSE;
1391fe5e51b7Smrg
1392fe5e51b7Smrg    pMga->Roundings[0] = 64;
1393fe5e51b7Smrg    pMga->Roundings[1] = 32;
1394fe5e51b7Smrg    pMga->Roundings[2] = 64;
1395fe5e51b7Smrg    pMga->Roundings[3] = 32;
1396fe5e51b7Smrg
1397fe5e51b7Smrg    /* Clear Fast bitblt flag */
1398fe5e51b7Smrg    pMga->HasFBitBlt = FALSE;
1399fe5e51b7Smrg}
1400fe5e51b7Smrg
1401fe5e51b7Smrgvoid MGAGSetupFuncs(ScrnInfoPtr pScrn)
1402fe5e51b7Smrg{
1403fe5e51b7Smrg    MGAPtr pMga = MGAPTR(pScrn);
1404fe5e51b7Smrg
1405fe5e51b7Smrg    pMga->PreInit = MGAGRamdacInit;
1406fe5e51b7Smrg    pMga->Save = MGAGSave;
1407fe5e51b7Smrg    pMga->Restore = MGAGRestore;
1408fe5e51b7Smrg    pMga->ModeInit = MGAGInit;
1409fe5e51b7Smrg    pMga->ddc1Read = MGAG_ddc1Read;
1410fe5e51b7Smrg    /* vgaHWddc1SetSpeed will only work if the card is in VGA mode */
1411fe5e51b7Smrg    pMga->DDC1SetSpeed = vgaHWddc1SetSpeedWeak();
1412fe5e51b7Smrg    pMga->i2cInit = MGAG_i2cInit;
1413fe5e51b7Smrg}
1414fe5e51b7Smrg
1415