mga_dac3026.c revision cc92fc76
1/*
2 * Copyright 1994 by Robin Cutshaw <robin@XFree86.org>
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Robin Cutshaw not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  Robin Cutshaw makes no representations
11 * about the suitability of this software for any purpose.  It is provided
12 * "as is" without express or implied warranty.
13 *
14 * ROBIN CUTSHAW DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL ROBIN CUTSHAW BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 *
22 *
23 * Modified for TVP3026 by Harald Koenig <koenig@tat.physik.uni-tuebingen.de>
24 *
25 * Modified for MGA Millennium by Xavier Ducoin <xavier@rd.lectra.fr>
26 *
27 * Doug Merritt <doug@netcom.com>
28 * 24bpp: fixed high res stripe glitches, clock glitches on all res
29 *
30 */
31
32#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
36/*
37 * This is a first cut at a non-accelerated version to work with the
38 * new server design (DHD).
39 */
40
41/* All drivers should typically include these */
42#include "xf86.h"
43#include "xf86_OSproc.h"
44
45/* Drivers that need to access the PCI config space directly need this */
46#include "xf86Pci.h"
47
48#include "mga_reg.h"
49#include "mga.h"
50#include "mga_macros.h"
51
52#include "xf86DDC.h"
53
54/*
55 * Only change these bits in the Option register.  Make sure that the
56 * vgaioen bit is never in this mask because it is controlled elsewhere
57 */
58#define OPTION_MASK 0xFFEFFEFF	/* ~(eepromwt | vgaioen) */
59
60static void MGA3026LoadPalette(ScrnInfoPtr, int, int*, LOCO*, VisualPtr);
61static void MGA3026SavePalette(ScrnInfoPtr, unsigned char*);
62static void MGA3026RestorePalette(ScrnInfoPtr, unsigned char*);
63static void MGA3026RamdacInit(ScrnInfoPtr);
64static void MGA3026Save(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool);
65static void MGA3026Restore(ScrnInfoPtr, vgaRegPtr, MGARegPtr, Bool);
66static Bool MGA3026Init(ScrnInfoPtr, DisplayModePtr);
67static Bool MGA3026_i2cInit(ScrnInfoPtr pScrn);
68
69
70/*
71 * implementation
72 */
73
74/*
75 * indexes to ti3026 registers (the order is important)
76 */
77const static unsigned char MGADACregs[] = {
78	0x0F, 0x18, 0x19, 0x1A, 0x1C,   0x1D, 0x1E, 0x2A, 0x2B, 0x30,
79	0x31, 0x32, 0x33, 0x34, 0x35,   0x36, 0x37, 0x38, 0x39, 0x3A,
80	0x06
81};
82
83/* note: to fix a cursor hw glitch, register 0x37 (blue color key) needs
84   to be set to magic numbers, even though they are "never" used because
85   blue keying disabled in 0x38.
86
87   Matrox sez:
88
89   ...The more precise statement of the software workaround is to insure
90   that bits 7-5 of register 0x37 (Blue Color Key High) and bits 7-5 of
91   register 0x38 (HZOOM)are the same...
92*/
93
94/* also note: the values of the MUX control register 0x19 (index [2]) can be
95   found in table 2-17 of the 3026 manual. If interlace is set, the values
96   listed here are incremented by one.
97*/
98
99#define DACREGSIZE sizeof(MGADACregs)
100/*
101 * initial values of ti3026 registers
102 */
103const static unsigned char MGADACbpp8[DACREGSIZE] = {
104	0x06, 0x80, 0x4b, 0x25, 0x00,   0x00, 0x0C, 0x00, 0x1E, 0xFF,
105	0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0x00, 0x00,    0, 0x00,
106	0x00
107};
108const static unsigned char MGADACbpp16[DACREGSIZE] = {
109	0x07, 0x45, 0x53, 0x15, 0x00,   0x00, 0x2C, 0x00, 0x1E, 0xFF,
110	0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0x00, 0x10,    0, 0x00,
111	0x00
112};
113/*
114 * [0] value was 0x07, but changed to 0x06 by Doug Merrit to fix high res
115 * stripe glitches and clock glitches at 24bpp.
116 */
117/* [0] value is now set inside of MGA3026Init, based on the silicon revision
118   It is still set to 7 or 6 based on the revision, though, since setting to
119   8 as in the documentation makes (some?) revB chips get the colors wrong...
120   maybe BGR instead of RGB? This only applies to 24bpp, since it is the only
121   one documented as depending on revision.
122 */
123
124const static unsigned char MGADACbpp24[DACREGSIZE] = {
125	0x06, 0x56, 0x5b, 0x25, 0x00,   0x00, 0x2C, 0x00, 0x1E, 0xFF,
126	0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0x00, 0x10,    0, 0x00,
127	0x00
128};
129const static unsigned char MGADACbpp32[DACREGSIZE] = {
130	0x07, 0x46, 0x5b, 0x05, 0x00,   0x00, 0x2C, 0x00, 0x1E, 0xFF,
131	0xFF, 0xFF, 0xFF, 0xFF, 0xFF,   0xFF, 0x00, 0x10,    0, 0x00,
132	0x00
133};
134
135
136/*
137 * Read/write to the DAC via MMIO
138 */
139
140/*
141 * These were functions.  Use macros instead to avoid the need to
142 * pass pMga to them.
143 */
144
145#define inTi3026dreg(reg) INREG8(RAMDAC_OFFSET + (reg))
146
147#define outTi3026dreg(reg, val) OUTREG8(RAMDAC_OFFSET + (reg), val)
148
149#define inTi3026(reg) \
150	(outTi3026dreg(TVP3026_INDEX, reg), inTi3026dreg(TVP3026_DATA))
151
152#define outTi3026(reg, mask, val) \
153	do { /* note: mask and reg may get evaluated twice */ \
154	    unsigned char tmp = (mask) ? (inTi3026(reg) & (mask)) : 0; \
155	    outTi3026dreg(TVP3026_INDEX, reg); \
156	    outTi3026dreg(TVP3026_DATA, tmp | (val)); \
157	} while (0)
158
159
160/*
161 * MGATi3026CalcClock - Calculate the PLL settings (m, n, p).
162 *
163 * DESCRIPTION
164 *   For more information, refer to the Texas Instruments
165 *   "TVP3026 Data Manual" (document SLAS098B).
166 *     Section 2.4 "PLL Clock Generators"
167 *     Appendix A "Frequency Synthesis PLL Register Settings"
168 *     Appendix B "PLL Programming Examples"
169 *
170 * PARAMETERS
171 *   f_out		IN	Desired clock frequency.
172 *   f_max		IN	Maximum allowed clock frequency.
173 *   m			OUT	Value of PLL 'm' register.
174 *   n			OUT	Value of PLL 'n' register.
175 *   p			OUT	Value of PLL 'p' register.
176 *
177 * HISTORY
178 *   January 11, 1997 - [aem] Andrew E. Mileski
179 *   Split off from MGATi3026SetClock.
180 */
181
182/* The following values are in kHz */
183#define TI_MIN_VCO_FREQ  110000
184#define TI_MAX_VCO_FREQ  220000
185#define TI_MAX_MCLK_FREQ 100000
186#define TI_REF_FREQ      14318.18
187
188static double
189MGATi3026CalcClock (
190   long f_out, long f_max,
191   int *m, int *n, int *p
192){
193	int best_m = 0, best_n = 0;
194	double f_pll, f_vco;
195	double m_err, inc_m, calc_m;
196
197	/* Make sure that f_min <= f_out <= f_max */
198	if ( f_out < ( TI_MIN_VCO_FREQ / 8 ))
199		f_out = TI_MIN_VCO_FREQ / 8;
200	if ( f_out > f_max )
201		f_out = f_max;
202
203	/*
204	 * f_pll = f_vco / 2 ^ p
205	 * Choose p so that TI_MIN_VCO_FREQ <= f_vco <= TI_MAX_VCO_FREQ
206	 * Note that since TI_MAX_VCO_FREQ = 2 * TI_MIN_VCO_FREQ
207	 * we don't have to bother checking for this maximum limit.
208	 */
209	f_vco = ( double ) f_out;
210	for ( *p = 0; *p < 3 && f_vco < TI_MIN_VCO_FREQ; ( *p )++ )
211		f_vco *= 2.0;
212
213	/*
214	 * We avoid doing multiplications by ( 65 - n ),
215	 * and add an increment instead - this keeps any error small.
216	 */
217	inc_m = f_vco / ( TI_REF_FREQ * 8.0 );
218
219	/* Initial value of calc_m for the loop */
220	calc_m = inc_m + inc_m + inc_m;
221
222	/* Initial amount of error for an integer - impossibly large */
223	m_err = 2.0;
224
225	/* Search for the closest INTEGER value of ( 65 - m ) */
226	for ( *n = 3; *n <= 25; ( *n )++, calc_m += inc_m ) {
227
228		/* Ignore values of ( 65 - m ) which we can't use */
229		if ( calc_m < 3.0 || calc_m > 64.0 )
230			continue;
231
232		/*
233		 * Pick the closest INTEGER (has smallest fractional part).
234		 * The optimizer should clean this up for us.
235		 */
236		if (( calc_m - ( int ) calc_m ) < m_err ) {
237			m_err = calc_m - ( int ) calc_m;
238			best_m = ( int ) calc_m;
239			best_n = *n;
240		}
241	}
242
243	/* 65 - ( 65 - x ) = x */
244	*m = 65 - best_m;
245	*n = 65 - best_n;
246
247	/* Now all the calculations can be completed */
248	f_vco = 8.0 * TI_REF_FREQ * best_m / best_n;
249	f_pll = f_vco / ( 1 << *p );
250
251#ifdef DEBUG
252	ErrorF( "f_out=%ld f_pll=%.1f f_vco=%.1f n=%d m=%d p=%d\n",
253		f_out, f_pll, f_vco, *n, *m, *p );
254#endif
255
256	return f_pll;
257}
258
259/*
260 * MGATi3026SetMCLK - Set the memory clock (MCLK) PLL.
261 *
262 * HISTORY
263 *   January 11, 1997 - [aem] Andrew E. Mileski
264 *   Written and tested.
265 */
266static void
267MGATi3026SetMCLK( ScrnInfoPtr pScrn, long f_out )
268{
269	int mclk_m, mclk_n, mclk_p;
270	int pclk_m, pclk_n, pclk_p;
271	int mclk_ctl;
272	MGAPtr pMga = MGAPTR(pScrn);
273
274	MGATi3026CalcClock(f_out, TI_MAX_MCLK_FREQ, &mclk_m, &mclk_n, &mclk_p);
275
276	/* Save PCLK settings */
277	outTi3026( TVP3026_PLL_ADDR, 0, 0xfc );
278	pclk_n = inTi3026( TVP3026_PIX_CLK_DATA );
279	outTi3026( TVP3026_PLL_ADDR, 0, 0xfd );
280	pclk_m = inTi3026( TVP3026_PIX_CLK_DATA );
281	outTi3026( TVP3026_PLL_ADDR, 0, 0xfe );
282	pclk_p = inTi3026( TVP3026_PIX_CLK_DATA );
283
284	/* Stop PCLK (PLLEN = 0, PCLKEN = 0) */
285	outTi3026( TVP3026_PLL_ADDR, 0, 0xfe );
286	outTi3026( TVP3026_PIX_CLK_DATA, 0, 0x00 );
287
288	/* Set PCLK to the new MCLK frequency (PLLEN = 1, PCLKEN = 0 ) */
289	outTi3026( TVP3026_PLL_ADDR, 0, 0xfc );
290	outTi3026( TVP3026_PIX_CLK_DATA, 0, ( mclk_n & 0x3f ) | 0xc0 );
291	outTi3026( TVP3026_PIX_CLK_DATA, 0, mclk_m & 0x3f );
292	outTi3026( TVP3026_PIX_CLK_DATA, 0, ( mclk_p & 0x03 ) | 0xb0 );
293
294	/* Wait for PCLK PLL to lock on frequency */
295	while (( inTi3026( TVP3026_PIX_CLK_DATA ) & 0x40 ) == 0 ) {
296		;
297	}
298
299	/* Output PCLK on MCLK pin */
300	mclk_ctl = inTi3026( TVP3026_MCLK_CTL );
301	outTi3026( TVP3026_MCLK_CTL, 0, mclk_ctl & 0xe7 );
302	outTi3026( TVP3026_MCLK_CTL, 0, ( mclk_ctl & 0xe7 ) | 0x08 );
303
304	/* Stop MCLK (PLLEN = 0 ) */
305	outTi3026( TVP3026_PLL_ADDR, 0, 0xfb );
306	outTi3026( TVP3026_MEM_CLK_DATA, 0, 0x00 );
307
308	/* Set MCLK to the new frequency (PLLEN = 1) */
309	outTi3026( TVP3026_PLL_ADDR, 0, 0xf3 );
310	outTi3026( TVP3026_MEM_CLK_DATA, 0, ( mclk_n & 0x3f ) | 0xc0 );
311	outTi3026( TVP3026_MEM_CLK_DATA, 0, mclk_m & 0x3f );
312	outTi3026( TVP3026_MEM_CLK_DATA, 0, ( mclk_p & 0x03 ) | 0xb0 );
313
314	/* Wait for MCLK PLL to lock on frequency */
315	while (( inTi3026( TVP3026_MEM_CLK_DATA ) & 0x40 ) == 0 ) {
316		;
317	}
318
319	/* Output MCLK PLL on MCLK pin */
320	outTi3026( TVP3026_MCLK_CTL, 0, ( mclk_ctl & 0xe7 ) | 0x10 );
321	outTi3026( TVP3026_MCLK_CTL, 0, ( mclk_ctl & 0xe7 ) | 0x18 );
322
323	/* Stop PCLK (PLLEN = 0, PCLKEN = 0 ) */
324	outTi3026( TVP3026_PLL_ADDR, 0, 0xfe );
325	outTi3026( TVP3026_PIX_CLK_DATA, 0, 0x00 );
326
327	/* Restore PCLK (PLLEN = ?, PCLKEN = ?) */
328	outTi3026( TVP3026_PLL_ADDR, 0, 0xfc );
329	outTi3026( TVP3026_PIX_CLK_DATA, 0, pclk_n );
330	outTi3026( TVP3026_PIX_CLK_DATA, 0, pclk_m );
331	outTi3026( TVP3026_PIX_CLK_DATA, 0, pclk_p );
332
333	/* Wait for PCLK PLL to lock on frequency */
334	while (( inTi3026( TVP3026_PIX_CLK_DATA ) & 0x40 ) == 0 ) {
335		;
336	}
337}
338
339/*
340 * MGATi3026SetPCLK - Set the pixel (PCLK) and loop (LCLK) clocks.
341 *
342 * PARAMETERS
343 *   f_pll			IN	Pixel clock PLL frequencly in kHz.
344 *   bpp			IN	Bytes per pixel.
345 *
346 * HISTORY
347 *   January 11, 1997 - [aem] Andrew E. Mileski
348 *   Split to simplify code for MCLK (=GCLK) setting.
349 *
350 *   December 14, 1996 - [aem] Andrew E. Mileski
351 *   Fixed loop clock to be based on the calculated, not requested,
352 *   pixel clock. Added f_max = maximum f_vco frequency.
353 *
354 *   October 19, 1996 - [aem] Andrew E. Mileski
355 *   Commented the loop clock code (wow, I understand everything now),
356 *   and simplified it a bit. This should really be two separate functions.
357 *
358 *   October 1, 1996 - [aem] Andrew E. Mileski
359 *   Optimized the m & n picking algorithm. Added maxClock detection.
360 *   Low speed pixel clock fix (per the docs). Documented what I understand.
361 *
362 *   ?????, ??, ???? - [???] ????????????
363 *   Based on the TVP3026 code in the S3 driver.
364 */
365
366static void
367MGATi3026SetPCLK( ScrnInfoPtr pScrn, long f_out, int bpp )
368{
369	/* Pixel clock values */
370	int m, n, p;
371
372	/* Loop clock values */
373	int lm, ln, lp, lq;
374	double z;
375
376	/* The actual frequency output by the clock */
377	double f_pll;
378
379	long f_max = TI_MAX_VCO_FREQ;
380
381	MGAPtr pMga = MGAPTR(pScrn);
382	MGARegPtr pReg = &pMga->ModeReg;
383
384	/* Get the maximum pixel clock frequency */
385	if ( pMga->MaxClock > TI_MAX_VCO_FREQ )
386		f_max = pMga->MaxClock;
387
388	/* Do the calculations for m, n, and p */
389	f_pll = MGATi3026CalcClock( f_out, f_max, & m, & n, & p );
390
391	/* Values for the pixel clock PLL registers */
392	pReg->DacClk[ 0 ] = ( n & 0x3f ) | 0xc0;
393	pReg->DacClk[ 1 ] = ( m & 0x3f );
394	pReg->DacClk[ 2 ] = ( p & 0x03 ) | 0xb0;
395
396	/*
397	 * Now that the pixel clock PLL is setup,
398	 * the loop clock PLL must be setup.
399	 */
400
401	/*
402	 * First we figure out lm, ln, and z.
403	 * Things are different in packed pixel mode (24bpp) though.
404	 */
405	 if ( pMga->CurrentLayout.bitsPerPixel == 24 ) {
406
407		/* ln:lm = ln:3 */
408		lm = 65 - 3;
409
410		/* Check for interleaved mode */
411		if ( bpp == 2 )
412			/* ln:lm = 4:3 */
413			ln = 65 - 4;
414		else
415			/* ln:lm = 8:3 */
416			ln = 65 - 8;
417
418		/* Note: this is actually 100 * z for more precision */
419		z = ( 11000 * ( 65 - ln )) / (( f_pll / 1000 ) * ( 65 - lm ));
420	}
421	else {
422		/* ln:lm = ln:4 */
423		lm = 65 - 4;
424
425		/* Note: bpp = bytes per pixel */
426		ln = 65 - 4 * ( 64 / 8 ) / bpp;
427
428		/* Note: this is actually 100 * z for more precision */
429		z = (( 11000 / 4 ) * ( 65 - ln )) / ( f_pll / 1000 );
430	}
431
432	/*
433	 * Now we choose dividers lp and lq so that the VCO frequency
434	 * is within the operating range of 110 MHz to 220 MHz.
435	 */
436
437	/* Assume no lq divider */
438	lq = 0;
439
440	/* Note: z is actually 100 * z for more precision */
441	if ( z <= 200.0 )
442		lp = 0;
443	else if ( z <= 400.0 )
444		lp = 1;
445	else if ( z <= 800.0 )
446		lp = 2;
447	else if ( z <= 1600.0 )
448		lp = 3;
449	else {
450		lp = 3;
451		lq = ( int )( z / 1600.0 );
452	}
453
454	/* Values for the loop clock PLL registers */
455	if ( pMga->CurrentLayout.bitsPerPixel == 24 ) {
456		/* Packed pixel mode values */
457		pReg->DacClk[ 3 ] = ( ln & 0x3f ) | 0x80;
458		pReg->DacClk[ 4 ] = ( lm & 0x3f ) | 0x80;
459		pReg->DacClk[ 5 ] = ( lp & 0x03 ) | 0xf8;
460 	} else {
461		/* Non-packed pixel mode values */
462		pReg->DacClk[ 3 ] = ( ln & 0x3f ) | 0xc0;
463		pReg->DacClk[ 4 ] = ( lm & 0x3f );
464		pReg->DacClk[ 5 ] = ( lp & 0x03 ) | 0xf0;
465	}
466	pReg->DacRegs[ 18 ] = lq | 0x38;
467
468#ifdef DEBUG
469	ErrorF( "bpp=%d z=%.1f ln=%d lm=%d lp=%d lq=%d\n",
470		bpp, z, ln, lm, lp, lq );
471#endif
472}
473
474/*
475 * MGA3026Init -- for mga2064 with ti3026
476 *
477 * The 'mode' parameter describes the video mode.	The 'mode' structure
478 * as well as the 'vga256InfoRec' structure can be dereferenced for
479 * information that is needed to initialize the mode.	The 'new' macro
480 * (see definition above) is used to simply fill in the structure.
481 */
482static Bool
483MGA3026Init(ScrnInfoPtr pScrn, DisplayModePtr mode)
484{
485	int hd, hs, he, ht, vd, vs, ve, vt, wd;
486	int i, BppShift, index_1d = 0;
487	const unsigned char* initDAC;
488	MGAPtr pMga = MGAPTR(pScrn);
489	MGARamdacPtr MGAdac = &pMga->Dac;
490	MGAFBLayout *pLayout = &pMga->CurrentLayout;
491	MGARegPtr pReg = &pMga->ModeReg;
492	vgaRegPtr pVga = &VGAHWPTR(pScrn)->ModeReg;
493
494	BppShift = pMga->BppShifts[(pLayout->bitsPerPixel >> 3) - 1];
495
496	switch(pLayout->bitsPerPixel)
497	{
498	case 8:
499		initDAC = MGADACbpp8;
500		break;
501	case 16:
502		initDAC = MGADACbpp16;
503		break;
504	case 24:
505		initDAC = MGADACbpp24;
506		break;
507	case 32:
508	    initDAC = MGADACbpp32;
509	    break;
510	default:
511		FatalError("MGA: unsupported bits per pixel\n");
512	}
513
514	/* Allocate the DacRegs space if not done already */
515	if (pReg->DacRegs == NULL) {
516		pReg->DacRegs = xnfcalloc(DACREGSIZE, 1);
517	}
518	for (i = 0; i < DACREGSIZE; i++) {
519	    pReg->DacRegs[i] = initDAC[i];
520	    if (MGADACregs[i] == 0x1D)
521		index_1d = i;
522	}
523
524	if ( (pLayout->bitsPerPixel == 16) && (pLayout->weight.red == 5)
525	    && (pLayout->weight.green == 5) && (pLayout->weight.blue == 5) ) {
526	    pReg->DacRegs[1] &= ~0x01;
527	}
528	if (pMga->Interleave ) 	pReg->DacRegs[2] += 1;
529
530
531	if ( pLayout->bitsPerPixel == 24 ) {
532	  int silicon_rev;
533	  /* we need to set DacRegs[0] differently based on the silicon
534	   * revision of the 3026 RAMDAC, as per page 2-14 of tvp3026.pdf.
535	   * If we have rev A silicon, we want 0x07; rev B silicon wants
536	   * 0x06.
537	   */
538	  silicon_rev = inTi3026(TVP3026_SILICON_REV);
539
540#ifdef DEBUG
541	    ErrorF("TVP3026 revision 0x%x (rev %s)\n",
542		   silicon_rev, (silicon_rev <= 0x20) ? "A" : "B");
543#endif
544
545	    if(silicon_rev <= 0x20) {
546	      /* rev A */
547	      pReg->DacRegs[0] = 0x07;
548	    } else {
549	      /* rev B */
550	      pReg->DacRegs[0] = 0x06;
551	    }
552	}
553
554	/*
555	 * This will initialize all of the generic VGA registers.
556	 */
557	if (!vgaHWInit(pScrn, mode))
558		return(FALSE);
559
560	/*
561	 * Here all of the MGA registers get filled in.
562	 */
563	hd = (mode->CrtcHDisplay	>> 3)	- 1;
564	hs = (mode->CrtcHSyncStart	>> 3)	- 1;
565	he = (mode->CrtcHSyncEnd	>> 3)	- 1;
566	ht = (mode->CrtcHTotal		>> 3)	- 1;
567	vd = mode->CrtcVDisplay			- 1;
568	vs = mode->CrtcVSyncStart		- 1;
569	ve = mode->CrtcVSyncEnd			- 1;
570	vt = mode->CrtcVTotal			- 2;
571
572        /* HTOTAL & 0x7 equal to 0x6 in 8bpp or 0x4 in 24bpp causes strange
573         * vertical stripes
574         */
575        if((ht & 0x07) == 0x06 || (ht & 0x07) == 0x04)
576                ht++;
577
578        if (pLayout->bitsPerPixel == 24)
579		wd = (pLayout->displayWidth * 3) >> (4 - BppShift);
580	else
581		wd = pLayout->displayWidth >> (4 - BppShift);
582
583	pReg->ExtVga[0] = 0;
584	pReg->ExtVga[5] = 0;
585
586	if (mode->Flags & V_INTERLACE)
587	{
588		pReg->ExtVga[0] = 0x80;
589		pReg->ExtVga[5] = (hs + he - ht) >> 1;
590		wd <<= 1;
591		vt &= 0xFFFE;
592
593		/* enable interlaced cursor */
594		pReg->DacRegs[20] |= 0x20;
595	}
596
597	pReg->ExtVga[0]	|= (wd & 0x300) >> 4;
598	pReg->ExtVga[1]	= (((ht - 4) & 0x100) >> 8) |
599				((hd & 0x100) >> 7) |
600				((hs & 0x100) >> 6) |
601				(ht & 0x40);
602	pReg->ExtVga[2]	= ((vt & 0xc00) >> 10) |
603				((vd & 0x400) >> 8) |
604				((vd & 0xc00) >> 7) |
605				((vs & 0xc00) >> 5);
606	if (pLayout->bitsPerPixel == 24)
607		pReg->ExtVga[3]	= (((1 << BppShift) * 3) - 1) | 0x80;
608	else
609		pReg->ExtVga[3]	= ((1 << BppShift) - 1) | 0x80;
610
611	/* Set viddelay (CRTCEXT3 Bits 3-4). */
612	pReg->ExtVga[3] |= (pScrn->videoRam == 8192 ? 0x10
613			     : pScrn->videoRam == 2048 ? 0x08 : 0x00);
614
615	pReg->ExtVga[4]	= 0;
616
617	pVga->CRTC[0]	= ht - 4;
618	pVga->CRTC[1]	= hd;
619	pVga->CRTC[2]	= hd;
620	pVga->CRTC[3]	= (ht & 0x1F) | 0x80;
621	pVga->CRTC[4]	= hs;
622	pVga->CRTC[5]	= ((ht & 0x20) << 2) | (he & 0x1F);
623	pVga->CRTC[6]	= vt & 0xFF;
624	pVga->CRTC[7]	= ((vt & 0x100) >> 8 ) |
625				((vd & 0x100) >> 7 ) |
626				((vs & 0x100) >> 6 ) |
627				((vd & 0x100) >> 5 ) |
628				0x10 |
629				((vt & 0x200) >> 4 ) |
630				((vd & 0x200) >> 3 ) |
631				((vs & 0x200) >> 2 );
632	pVga->CRTC[9]	= ((vd & 0x200) >> 4) | 0x40;
633	pVga->CRTC[16] = vs & 0xFF;
634	pVga->CRTC[17] = (ve & 0x0F) | 0x20;
635	pVga->CRTC[18] = vd & 0xFF;
636	pVga->CRTC[19] = wd & 0xFF;
637	pVga->CRTC[21] = vd & 0xFF;
638	pVga->CRTC[22] = (vt + 1) & 0xFF;
639
640	if (mode->Flags & V_DBLSCAN)
641		pVga->CRTC[9] |= 0x80;
642
643	/* Per DDK vid.c line 75, sync polarity should be controlled
644	 * via the TVP3026 RAMDAC register 1D and so MISC Output Register
645	 * should always have bits 6 and 7 set. */
646
647	pVga->MiscOutReg |= 0xC0;
648	if ((mode->Flags & (V_PHSYNC | V_NHSYNC)) &&
649	    (mode->Flags & (V_PVSYNC | V_NVSYNC)))
650	{
651	    if (mode->Flags & V_PHSYNC)
652		pReg->DacRegs[index_1d] |= 0x01;
653	    if (mode->Flags & V_PVSYNC)
654		pReg->DacRegs[index_1d] |= 0x02;
655	}
656	else
657	{
658	  int VDisplay = mode->VDisplay;
659	  if (mode->Flags & V_DBLSCAN)
660	    VDisplay *= 2;
661	  if      (VDisplay < 400)
662		  pReg->DacRegs[index_1d] |= 0x01; /* +hsync -vsync */
663	  else if (VDisplay < 480)
664		  pReg->DacRegs[index_1d] |= 0x02; /* -hsync +vsync */
665	  else if (VDisplay < 768)
666		  pReg->DacRegs[index_1d] |= 0x00; /* -hsync -vsync */
667	  else
668		  pReg->DacRegs[index_1d] |= 0x03; /* +hsync +vsync */
669	}
670
671	if (pMga->SyncOnGreen)
672	    pReg->DacRegs[index_1d] |= 0x20;
673
674	pReg->Option = 0x402C0100;  /* fine for 2064 and 2164 */
675
676	if (pMga->Interleave)
677	  pReg->Option |= 0x1000;
678	else
679	  pReg->Option &= ~0x1000;
680
681	/* must always have the pci retries on but rely on
682	   polling to keep them from occuring */
683	pReg->Option &= ~0x20000000;
684
685	pVga->MiscOutReg |= 0x0C;
686	/* XXX Need to check the first argument */
687	MGATi3026SetPCLK( pScrn, mode->Clock, 1 << BppShift );
688
689	/* this one writes registers rather than writing to the
690	   mgaReg->ModeReg and letting Restore write to the hardware
691	   but that's no big deal since we will Restore right after
692	   this function */
693
694	MGA_NOT_HAL(MGATi3026SetMCLK(pScrn, MGAdac->MemoryClock));
695
696#ifdef DEBUG
697	ErrorF("%6ld: %02X %02X %02X	%02X %02X %02X	%08lX\n", mode->Clock,
698		pReg->DacClk[0], pReg->DacClk[1], pReg->DacClk[2], pReg->DacClk[3], pReg->DacClk[4], pReg->DacClk[5], pReg->Option);
699	for (i=0; i<sizeof(MGADACregs); i++) ErrorF("%02X ", pReg->DacRegs[i]);
700	for (i=0; i<6; i++) ErrorF(" %02X", pReg->ExtVga[i]);
701	ErrorF("\n");
702#endif
703
704	/* This disables the VGA memory aperture */
705	pVga->MiscOutReg &= ~0x02;
706	return(TRUE);
707}
708
709/*
710 * MGA3026Restore -- for mga2064 with ti3026
711 *
712 * This function restores a video mode.	 It basically writes out all of
713 * the registers that have previously been saved in the vgaMGARec data
714 * structure.
715 */
716static void
717MGA3026Restore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg,
718	       Bool restoreFonts)
719{
720	int i;
721	MGAPtr pMga = MGAPTR(pScrn);
722
723	/*
724	 * Code is needed to get things back to bank zero.
725	 */
726	for (i = 0; i < 6; i++)
727		OUTREG16(0x1FDE, (mgaReg->ExtVga[i] << 8) | i);
728
729#ifdef XSERVER_LIBPCIACCESS
730	pci_device_cfg_write_bits(pMga->PciInfo, OPTION_MASK, mgaReg->Option,
731				  PCI_OPTION_REG);
732#else
733	pciSetBitsLong(pMga->PciTag, PCI_OPTION_REG, OPTION_MASK,
734		       mgaReg->Option);
735#endif
736
737	MGA_NOT_HAL(
738	/* select pixel clock PLL as clock source */
739	outTi3026(TVP3026_CLK_SEL, 0, mgaReg->DacRegs[3]);
740
741	/* set loop and pixel clock PLL PLLEN bits to 0 */
742	outTi3026(TVP3026_PLL_ADDR, 0, 0x2A);
743	outTi3026(TVP3026_LOAD_CLK_DATA, 0, 0);
744	outTi3026(TVP3026_PIX_CLK_DATA, 0, 0);
745	);	/* MGA_NOT_HAL */
746
747	/*
748	 * This function handles restoring the generic VGA registers.
749	 */
750	vgaHWRestore(pScrn, vgaReg,
751			VGA_SR_MODE | (restoreFonts ? VGA_SR_FONTS : 0));
752	MGA3026RestorePalette(pScrn, vgaReg->DAC);
753
754	/*
755	 * Code to restore SVGA registers that have been saved/modified
756	 * goes here.
757	 */
758
759	MGA_NOT_HAL(
760	/* program pixel clock PLL */
761	outTi3026(TVP3026_PLL_ADDR, 0, 0x00);
762	for (i = 0; i < 3; i++)
763		outTi3026(TVP3026_PIX_CLK_DATA, 0, mgaReg->DacClk[i]);
764
765	if (vgaReg->MiscOutReg & 0x08) {
766		/* poll until pixel clock PLL LOCK bit is set */
767		outTi3026(TVP3026_PLL_ADDR, 0, 0x3F);
768		while ( ! (inTi3026(TVP3026_PIX_CLK_DATA) & 0x40) );
769	}
770
771	/* set Q divider for loop clock PLL */
772	outTi3026(TVP3026_MCLK_CTL, 0, mgaReg->DacRegs[18]);
773	);	/* MGA_NOT_HAL */
774
775	/* program loop PLL */
776	outTi3026(TVP3026_PLL_ADDR, 0, 0x00);
777	for (i = 3; i < 6; i++)
778		outTi3026(TVP3026_LOAD_CLK_DATA, 0, mgaReg->DacClk[i]);
779
780	MGA_NOT_HAL(
781	if ((vgaReg->MiscOutReg & 0x08) && ((mgaReg->DacClk[3] & 0xC0) == 0xC0) ) {
782		/* poll until loop PLL LOCK bit is set */
783		outTi3026(TVP3026_PLL_ADDR, 0, 0x3F);
784		while ( ! (inTi3026(TVP3026_LOAD_CLK_DATA) & 0x40) );
785	}
786	);	/* MGA_NOT_HAL */
787
788	/*
789	 * restore other DAC registers
790	 */
791	for (i = 0; i < DACREGSIZE; i++)
792		outTi3026(MGADACregs[i], 0, mgaReg->DacRegs[i]);
793
794#ifdef DEBUG
795	ErrorF("PCI retry (0-enabled / 1-disabled): %d\n",
796		!!(mgaReg->Option & 0x20000000));
797#endif
798}
799
800/*
801 * MGA3026Save -- for mga2064 with ti3026
802 *
803 * This function saves the video state.
804 */
805static void
806MGA3026Save(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, MGARegPtr mgaReg,
807	    Bool saveFonts)
808{
809	int i;
810	MGAPtr pMga = MGAPTR(pScrn);
811
812	/* Allocate the DacRegs space if not done already */
813	if (mgaReg->DacRegs == NULL) {
814		mgaReg->DacRegs = xnfcalloc(DACREGSIZE, 1);
815	}
816
817	/*
818	 * Code is needed to get back to bank zero.
819	 */
820	OUTREG16(0x1FDE, 0x0004);
821
822	/*
823	 * This function will handle creating the data structure and filling
824	 * in the generic VGA portion.
825	 */
826	vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | (saveFonts ? VGA_SR_FONTS : 0));
827	MGA3026SavePalette(pScrn, vgaReg->DAC);
828
829	/*
830	 * The port I/O code necessary to read in the extended registers
831	 * into the fields of the vgaMGARec structure.
832	 */
833	for (i = 0; i < 6; i++)
834	{
835		OUTREG8(0x1FDE, i);
836		mgaReg->ExtVga[i] = INREG8(0x1FDF);
837	}
838
839	MGA_NOT_HAL(
840	outTi3026(TVP3026_PLL_ADDR, 0, 0x00);
841	for (i = 0; i < 3; i++)
842		outTi3026(TVP3026_PIX_CLK_DATA, 0, mgaReg->DacClk[i] =
843					inTi3026(TVP3026_PIX_CLK_DATA));
844
845	outTi3026(TVP3026_PLL_ADDR, 0, 0x00);
846	for (i = 3; i < 6; i++)
847		outTi3026(TVP3026_LOAD_CLK_DATA, 0, mgaReg->DacClk[i] =
848					inTi3026(TVP3026_LOAD_CLK_DATA));
849	);	/* MGA_NOT_HAL */
850
851	for (i = 0; i < DACREGSIZE; i++)
852		mgaReg->DacRegs[i]	 = inTi3026(MGADACregs[i]);
853
854#ifdef XSERVER_LIBPCIACCESS
855	pci_device_cfg_read_u32(pMga->PciInfo, & mgaReg->Option,
856				PCI_OPTION_REG);
857#else
858	mgaReg->Option = pciReadLong(pMga->PciTag, PCI_OPTION_REG);
859#endif
860
861#ifdef DEBUG
862	ErrorF("read: %02X %02X %02X	%02X %02X %02X	%08lX\n",
863		mgaReg->DacClk[0], mgaReg->DacClk[1], mgaReg->DacClk[2], mgaReg->DacClk[3], mgaReg->DacClk[4], mgaReg->DacClk[5], mgaReg->Option);
864	for (i=0; i<sizeof(MGADACregs); i++) ErrorF("%02X ", mgaReg->DacRegs[i]);
865	for (i=0; i<6; i++) ErrorF(" %02X", mgaReg->ExtVga[i]);
866	ErrorF("\n");
867#endif
868}
869
870
871static void
872MGA3026LoadCursorImage(
873    ScrnInfoPtr pScrn,
874    unsigned char *src
875)
876{
877    MGAPtr pMga = MGAPTR(pScrn);
878    int i = 1024;
879
880    outTi3026(TVP3026_CURSOR_CTL, 0xf3, 0x00); /* reset A9,A8 */
881    /* reset cursor RAM load address A7..A0 */
882    outTi3026dreg(TVP3026_WADR_PAL, 0x00);
883
884    while(i--) {
885	while (INREG8(0x1FDA) & 0x01);
886	while (!(INREG8(0x1FDA) & 0x01));
887        outTi3026dreg(TVP3026_CUR_RAM, *(src++));
888    }
889}
890
891
892static void
893MGA3026ShowCursor(ScrnInfoPtr pScrn)
894{
895    MGAPtr pMga = MGAPTR(pScrn);
896    /* Enable cursor - X11 mode */
897    outTi3026(TVP3026_CURSOR_CTL, 0x6c, 0x13);
898}
899
900static void
901MGA3026HideCursor(ScrnInfoPtr pScrn)
902{
903    MGAPtr pMga = MGAPTR(pScrn);
904    /* Disable cursor */
905    outTi3026(TVP3026_CURSOR_CTL, 0xfc, 0x00);
906}
907
908static void
909MGA3026SetCursorPosition(
910   ScrnInfoPtr pScrn,
911   int x, int y
912)
913{
914    MGAPtr pMga = MGAPTR(pScrn);
915    x += 64;
916    y += 64;
917
918    /* Output position - "only" 12 bits of location documented */
919
920    outTi3026dreg(TVP3026_CUR_XLOW, x & 0xFF);
921    outTi3026dreg(TVP3026_CUR_XHI, (x >> 8) & 0x0F);
922    outTi3026dreg(TVP3026_CUR_YLOW, y & 0xFF);
923    outTi3026dreg(TVP3026_CUR_YHI, (y >> 8) & 0x0F);
924}
925
926static void
927MGA3026SetCursorColors(
928   ScrnInfoPtr pScrn,
929   int bg, int fg
930)
931{
932    MGAPtr pMga = MGAPTR(pScrn);
933    /* The TI 3026 cursor is always 8 bits so shift 8, not 10 */
934
935    /* Background color */
936    outTi3026dreg(TVP3026_CUR_COL_ADDR, 1);
937    outTi3026dreg(TVP3026_CUR_COL_DATA, (bg & 0x00FF0000) >> 16);
938    outTi3026dreg(TVP3026_CUR_COL_DATA, (bg & 0x0000FF00) >> 8);
939    outTi3026dreg(TVP3026_CUR_COL_DATA, (bg & 0x000000FF));
940
941    /* Foreground color */
942    outTi3026dreg(TVP3026_CUR_COL_ADDR, 2);
943    outTi3026dreg(TVP3026_CUR_COL_DATA, (fg & 0x00FF0000) >> 16);
944    outTi3026dreg(TVP3026_CUR_COL_DATA, (fg & 0x0000FF00) >> 8);
945    outTi3026dreg(TVP3026_CUR_COL_DATA, (fg & 0x000000FF));
946}
947
948static Bool
949MGA3026UseHWCursor(ScreenPtr pScrn, CursorPtr pCurs)
950{
951    if( XF86SCRNINFO(pScrn)->currentMode->Flags & V_DBLSCAN )
952    	return FALSE;
953    return TRUE;
954}
955
956static const int DDC_SDA_MASK = 1 << 2;
957static const int DDC_SCL_MASK = 1 << 4;
958
959static unsigned int
960MGA3026_ddc1Read(ScrnInfoPtr pScrn)
961{
962  MGAPtr pMga = MGAPTR(pScrn);
963
964  /* Define the SDA as an input */
965  outTi3026(TVP3026_GEN_IO_CTL, 0xfb, 0);
966
967  /* wait for Vsync */
968  while( INREG( MGAREG_Status ) & 0x08 );
969  while( ! (INREG( MGAREG_Status ) & 0x08) );
970
971  /* Get the result */
972  return (inTi3026(TVP3026_GEN_IO_DATA) & DDC_SDA_MASK) >> 2 ;
973}
974
975static void
976MGA3026_I2CGetBits(I2CBusPtr b, int *clock, int *data)
977{
978  ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
979  MGAPtr pMga = MGAPTR(pScrn);
980  unsigned char val;
981
982  /* Get the result. */
983  val = inTi3026(TVP3026_GEN_IO_DATA);
984  *clock = (val & DDC_SCL_MASK) != 0;
985  *data  = (val & DDC_SDA_MASK) != 0;
986
987#ifdef DEBUG
988	 ErrorF("MGA3026_I2CGetBits(%p,...) val=0x%x, returns clock %d, data %d\n", b, val, *clock, *data);
989#endif
990}
991
992/*
993 * ATTENTION! - the DATA and CLOCK lines need to be tri-stated when
994 * high. Therefore turn off output driver for the line to set line
995 * to high. High signal is maintained by a 15k Ohm pll-up resistor.
996 */
997static void
998MGA3026_I2CPutBits(I2CBusPtr b, int clock, int data)
999{
1000  ScrnInfoPtr pScrn = xf86Screens[b->scrnIndex];
1001  MGAPtr pMga = MGAPTR(pScrn);
1002  unsigned char val,drv;
1003
1004  /* Write the values */
1005  val = (clock ? DDC_SCL_MASK : 0) | (data ? DDC_SDA_MASK : 0);
1006  drv = ((!clock) ? DDC_SCL_MASK : 0) | ((!data) ? DDC_SDA_MASK : 0);
1007  /* Define the SDA (Data) and SCL (clock) as outputs */
1008  outTi3026(TVP3026_GEN_IO_CTL, ~(DDC_SDA_MASK | DDC_SCL_MASK), drv);
1009  outTi3026(TVP3026_GEN_IO_DATA, ~(DDC_SDA_MASK | DDC_SCL_MASK), val);
1010
1011#ifdef DEBUG
1012  ErrorF("MGA3026_I2CPutBits(%p, %d, %d) val=0x%x\n", b, clock, data, val);
1013#endif
1014
1015}
1016
1017
1018Bool
1019MGA3026_i2cInit(ScrnInfoPtr pScrn)
1020{
1021    MGAPtr pMga = MGAPTR(pScrn);
1022    I2CBusPtr I2CPtr;
1023
1024    I2CPtr = xf86CreateI2CBusRec();
1025    if(!I2CPtr) return FALSE;
1026
1027    pMga->DDC_Bus1 = I2CPtr;
1028
1029    I2CPtr->BusName    = "DDC";
1030    I2CPtr->scrnIndex  = pScrn->scrnIndex;
1031    I2CPtr->I2CPutBits = MGA3026_I2CPutBits;
1032    I2CPtr->I2CGetBits = MGA3026_I2CGetBits;
1033
1034    /* I2CPutByte is timing out, experimenting with AcknTimeout
1035     * default is 2CPtr->AcknTimeout = 5;
1036     */
1037    /* I2CPtr->AcknTimeout = 10; */
1038
1039    if (!xf86I2CBusInit(I2CPtr)) {
1040	return FALSE;
1041    }
1042    return TRUE;
1043}
1044
1045static void
1046MGA3026RamdacInit(ScrnInfoPtr pScrn)
1047{
1048    MGAPtr pMga;
1049    MGARamdacPtr MGAdac;
1050
1051    pMga = MGAPTR(pScrn);
1052    MGAdac = &pMga->Dac;
1053
1054    MGAdac->isHwCursor		= TRUE;
1055    MGAdac->CursorMaxWidth	= 64;
1056    MGAdac->CursorMaxHeight	= 64;
1057    MGAdac->SetCursorColors	= MGA3026SetCursorColors;
1058    MGAdac->SetCursorPosition	= MGA3026SetCursorPosition;
1059    MGAdac->LoadCursorImage	= MGA3026LoadCursorImage;
1060    MGAdac->HideCursor		= MGA3026HideCursor;
1061    MGAdac->ShowCursor		= MGA3026ShowCursor;
1062    MGAdac->UseHWCursor		= MGA3026UseHWCursor;
1063    MGAdac->CursorFlags		=
1064#if X_BYTE_ORDER == X_LITTLE_ENDIAN
1065				HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
1066#endif
1067				HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
1068				HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED;
1069
1070    MGAdac->LoadPalette 	= MGA3026LoadPalette;
1071    MGAdac->RestorePalette	= MGA3026RestorePalette;
1072
1073    MGAdac->maxPixelClock = pMga->bios.pixel.max_freq;
1074    MGAdac->ClockFrom = X_PROBED;
1075
1076    MGAdac->MemoryClock = pMga->bios.mem_clock;
1077    MGAdac->MemClkFrom = X_PROBED;
1078    MGAdac->SetMemClk = TRUE;
1079
1080
1081    /* safety check */
1082    if ( (MGAdac->MemoryClock < 40000) ||
1083         (MGAdac->MemoryClock > 70000) )
1084	MGAdac->MemoryClock = 50000;
1085
1086    /*
1087     * Should initialise a sane default when the probed value is
1088     * obviously garbage.
1089     */
1090
1091    /* Check if interleaving can be used and set the rounding value */
1092    if (pScrn->videoRam > 2048)
1093        pMga->Interleave = TRUE;
1094    else {
1095        pMga->Interleave = FALSE;
1096        pMga->BppShifts[0]++;
1097        pMga->BppShifts[1]++;
1098        pMga->BppShifts[2]++;
1099        pMga->BppShifts[3]++;
1100    }
1101
1102    pMga->Roundings[0] = 128 >> pMga->BppShifts[0];
1103    pMga->Roundings[1] = 128 >> pMga->BppShifts[1];
1104    pMga->Roundings[2] = 128 >> pMga->BppShifts[2];
1105    pMga->Roundings[3] = 128 >> pMga->BppShifts[3];
1106
1107    /* Set Fast bitblt flag */
1108    pMga->HasFBitBlt = pMga->bios.fast_bitblt;
1109}
1110
1111void MGA3026LoadPalette(
1112    ScrnInfoPtr pScrn,
1113    int numColors,
1114    int *indices,
1115    LOCO *colors,
1116    VisualPtr pVisual
1117){
1118    MGAPtr pMga = MGAPTR(pScrn);
1119    int i, index;
1120
1121    if (pVisual->nplanes == 16) {
1122	for(i = 0; i < numColors; i++) {
1123	    index = indices[i];
1124            outTi3026dreg(MGA1064_WADR_PAL, index << 2);
1125            outTi3026dreg(MGA1064_COL_PAL, colors[index >> 1].red);
1126            outTi3026dreg(MGA1064_COL_PAL, colors[index].green);
1127            outTi3026dreg(MGA1064_COL_PAL, colors[index >> 1].blue);
1128
1129	/* we have to write 2 indices since the pixel X on the
1130	   TVP3026 has green colors at different locations from
1131	   the red and blue colors */
1132	    if(index <= 31) {
1133		outTi3026dreg(MGA1064_WADR_PAL, index << 3);
1134		outTi3026dreg(MGA1064_COL_PAL, colors[index].red);
1135		outTi3026dreg(MGA1064_COL_PAL, colors[(index << 1) + 1].green);
1136		outTi3026dreg(MGA1064_COL_PAL, colors[index].blue);
1137	    }
1138	}
1139    } else {
1140	int shift = (pVisual->nplanes == 15) ? 3 : 0;
1141
1142	for(i = 0; i < numColors; i++) {
1143	    index = indices[i];
1144            outTi3026dreg(MGA1064_WADR_PAL, index << shift);
1145            outTi3026dreg(MGA1064_COL_PAL, colors[index].red);
1146            outTi3026dreg(MGA1064_COL_PAL, colors[index].green);
1147            outTi3026dreg(MGA1064_COL_PAL, colors[index].blue);
1148	}
1149    }
1150}
1151
1152
1153static void
1154MGA3026SavePalette(ScrnInfoPtr pScrn, unsigned char* pntr)
1155{
1156    MGAPtr pMga = MGAPTR(pScrn);
1157    int i = 768;
1158
1159    outTi3026dreg(TVP3026_RADR_PAL, 0x00);
1160    while(i--)
1161        *(pntr++) = inTi3026dreg(TVP3026_COL_PAL);
1162}
1163
1164static void
1165MGA3026RestorePalette(ScrnInfoPtr pScrn, unsigned char* pntr)
1166{
1167    MGAPtr pMga = MGAPTR(pScrn);
1168    int i = 768;
1169
1170    outTi3026dreg(TVP3026_WADR_PAL, 0x00);
1171    while(i--)
1172        outTi3026dreg(TVP3026_COL_PAL, *(pntr++));
1173}
1174
1175
1176void MGA2064SetupFuncs(ScrnInfoPtr pScrn)
1177{
1178    MGAPtr pMga = MGAPTR(pScrn);
1179
1180    pMga->PreInit = MGA3026RamdacInit;
1181    pMga->Save = MGA3026Save;
1182    pMga->Restore = MGA3026Restore;
1183    pMga->ModeInit = MGA3026Init;
1184    pMga->ddc1Read = MGA3026_ddc1Read;
1185    /* vgaHWddc1SetSpeed will only work if the card is in VGA mode */
1186    pMga->DDC1SetSpeed = vgaHWddc1SetSpeedWeak();
1187    pMga->i2cInit = MGA3026_i2cInit;
1188}
1189