1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 *
4 * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
5 *
6 * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
7 *
8 * Portions Copyright (c) 2001 Matrox Graphics Inc.
9 *
10 * Version: 1.65 2002/08/14
11 *
12 * See matroxfb_base.c for contributors.
13 *
14 */
15
16
17#include "matroxfb_DAC1064.h"
18#include "matroxfb_misc.h"
19#include "matroxfb_accel.h"
20#include "g450_pll.h"
21#include <linux/matroxfb.h>
22
23#ifdef NEED_DAC1064
24#define outDAC1064 matroxfb_DAC_out
25#define inDAC1064 matroxfb_DAC_in
26
27#define DAC1064_OPT_SCLK_PCI	0x00
28#define DAC1064_OPT_SCLK_PLL	0x01
29#define DAC1064_OPT_SCLK_EXT	0x02
30#define DAC1064_OPT_SCLK_MASK	0x03
31#define DAC1064_OPT_GDIV1	0x04	/* maybe it is GDIV2 on G100 ?! */
32#define DAC1064_OPT_GDIV3	0x00
33#define DAC1064_OPT_MDIV1	0x08
34#define DAC1064_OPT_MDIV2	0x00
35#define DAC1064_OPT_RESERVED	0x10
36
37static void DAC1064_calcclock(const struct matrox_fb_info *minfo,
38			      unsigned int freq, unsigned int fmax,
39			      unsigned int *in, unsigned int *feed,
40			      unsigned int *post)
41{
42	unsigned int fvco;
43	unsigned int p;
44
45	DBG(__func__)
46
47	/* only for devices older than G450 */
48
49	fvco = PLL_calcclock(minfo, freq, fmax, in, feed, &p);
50
51	p = (1 << p) - 1;
52	if (fvco <= 100000)
53		;
54	else if (fvco <= 140000)
55		p |= 0x08;
56	else if (fvco <= 180000)
57		p |= 0x10;
58	else
59		p |= 0x18;
60	*post = p;
61}
62
63/* they must be in POS order */
64static const unsigned char MGA1064_DAC_regs[] = {
65		M1064_XCURADDL, M1064_XCURADDH, M1064_XCURCTRL,
66		M1064_XCURCOL0RED, M1064_XCURCOL0GREEN, M1064_XCURCOL0BLUE,
67		M1064_XCURCOL1RED, M1064_XCURCOL1GREEN, M1064_XCURCOL1BLUE,
68		M1064_XCURCOL2RED, M1064_XCURCOL2GREEN, M1064_XCURCOL2BLUE,
69		DAC1064_XVREFCTRL, M1064_XMULCTRL, M1064_XPIXCLKCTRL, M1064_XGENCTRL,
70		M1064_XMISCCTRL,
71		M1064_XGENIOCTRL, M1064_XGENIODATA, M1064_XZOOMCTRL, M1064_XSENSETEST,
72		M1064_XCRCBITSEL,
73		M1064_XCOLKEYMASKL, M1064_XCOLKEYMASKH, M1064_XCOLKEYL, M1064_XCOLKEYH };
74
75static const unsigned char MGA1064_DAC[] = {
76		0x00, 0x00, M1064_XCURCTRL_DIS,
77		0x00, 0x00, 0x00, 	/* black */
78		0xFF, 0xFF, 0xFF,	/* white */
79		0xFF, 0x00, 0x00,	/* red */
80		0x00, 0,
81		M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL,
82		M1064_XGENCTRL_VS_0 | M1064_XGENCTRL_ALPHA_DIS | M1064_XGENCTRL_BLACK_0IRE | M1064_XGENCTRL_NO_SYNC_ON_GREEN,
83		M1064_XMISCCTRL_DAC_8BIT,
84		0x00, 0x00, M1064_XZOOMCTRL_1, M1064_XSENSETEST_BCOMP | M1064_XSENSETEST_GCOMP | M1064_XSENSETEST_RCOMP | M1064_XSENSETEST_PDOWN,
85		0x00,
86		0x00, 0x00, 0xFF, 0xFF};
87
88static void DAC1064_setpclk(struct matrox_fb_info *minfo, unsigned long fout)
89{
90	unsigned int m, n, p;
91
92	DBG(__func__)
93
94	DAC1064_calcclock(minfo, fout, minfo->max_pixel_clock, &m, &n, &p);
95	minfo->hw.DACclk[0] = m;
96	minfo->hw.DACclk[1] = n;
97	minfo->hw.DACclk[2] = p;
98}
99
100static void DAC1064_setmclk(struct matrox_fb_info *minfo, int oscinfo,
101			    unsigned long fmem)
102{
103	u_int32_t mx;
104	struct matrox_hw_state *hw = &minfo->hw;
105
106	DBG(__func__)
107
108	if (minfo->devflags.noinit) {
109		/* read MCLK and give up... */
110		hw->DACclk[3] = inDAC1064(minfo, DAC1064_XSYSPLLM);
111		hw->DACclk[4] = inDAC1064(minfo, DAC1064_XSYSPLLN);
112		hw->DACclk[5] = inDAC1064(minfo, DAC1064_XSYSPLLP);
113		return;
114	}
115	mx = hw->MXoptionReg | 0x00000004;
116	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
117	mx &= ~0x000000BB;
118	if (oscinfo & DAC1064_OPT_GDIV1)
119		mx |= 0x00000008;
120	if (oscinfo & DAC1064_OPT_MDIV1)
121		mx |= 0x00000010;
122	if (oscinfo & DAC1064_OPT_RESERVED)
123		mx |= 0x00000080;
124	if ((oscinfo & DAC1064_OPT_SCLK_MASK) == DAC1064_OPT_SCLK_PLL) {
125		/* select PCI clock until we have setup oscilator... */
126		int clk;
127		unsigned int m, n, p;
128
129		/* powerup system PLL, select PCI clock */
130		mx |= 0x00000020;
131		pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
132		mx &= ~0x00000004;
133		pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
134
135		/* !!! you must not access device if MCLK is not running !!!
136		   Doing so cause immediate PCI lockup :-( Maybe they should
137		   generate ABORT or I/O (parity...) error and Linux should
138		   recover from this... (kill driver/process). But world is not
139		   perfect... */
140		/* (bit 2 of PCI_OPTION_REG must be 0... and bits 0,1 must not
141		   select PLL... because of PLL can be stopped at this time) */
142		DAC1064_calcclock(minfo, fmem, minfo->max_pixel_clock, &m, &n, &p);
143		outDAC1064(minfo, DAC1064_XSYSPLLM, hw->DACclk[3] = m);
144		outDAC1064(minfo, DAC1064_XSYSPLLN, hw->DACclk[4] = n);
145		outDAC1064(minfo, DAC1064_XSYSPLLP, hw->DACclk[5] = p);
146		for (clk = 65536; clk; --clk) {
147			if (inDAC1064(minfo, DAC1064_XSYSPLLSTAT) & 0x40)
148				break;
149		}
150		if (!clk)
151			printk(KERN_ERR "matroxfb: aiee, SYSPLL not locked\n");
152		/* select PLL */
153		mx |= 0x00000005;
154	} else {
155		/* select specified system clock source */
156		mx |= oscinfo & DAC1064_OPT_SCLK_MASK;
157	}
158	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
159	mx &= ~0x00000004;
160	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
161	hw->MXoptionReg = mx;
162}
163
164#ifdef CONFIG_FB_MATROX_G
165static void g450_set_plls(struct matrox_fb_info *minfo)
166{
167	u_int32_t c2_ctl;
168	unsigned int pxc;
169	struct matrox_hw_state *hw = &minfo->hw;
170	int pixelmnp;
171	int videomnp;
172
173	c2_ctl = hw->crtc2.ctl & ~0x4007;	/* Clear PLL + enable for CRTC2 */
174	c2_ctl |= 0x0001;			/* Enable CRTC2 */
175	hw->DACreg[POS1064_XPWRCTRL] &= ~0x02;	/* Stop VIDEO PLL */
176	pixelmnp = minfo->crtc1.mnp;
177	videomnp = minfo->crtc2.mnp;
178	if (videomnp < 0) {
179		c2_ctl &= ~0x0001;			/* Disable CRTC2 */
180		hw->DACreg[POS1064_XPWRCTRL] &= ~0x10;	/* Powerdown CRTC2 */
181	} else if (minfo->crtc2.pixclock == minfo->features.pll.ref_freq) {
182		c2_ctl |=  0x4002;	/* Use reference directly */
183	} else if (videomnp == pixelmnp) {
184		c2_ctl |=  0x0004;	/* Use pixel PLL */
185	} else {
186		if (0 == ((videomnp ^ pixelmnp) & 0xFFFFFF00)) {
187			/* PIXEL and VIDEO PLL must not use same frequency. We modify N
188			   of PIXEL PLL in such case because of VIDEO PLL may be source
189			   of TVO clocks, and chroma subcarrier is derived from its
190			   pixel clocks */
191			pixelmnp += 0x000100;
192		}
193		c2_ctl |=  0x0006;	/* Use video PLL */
194		hw->DACreg[POS1064_XPWRCTRL] |= 0x02;
195
196		outDAC1064(minfo, M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]);
197		matroxfb_g450_setpll_cond(minfo, videomnp, M_VIDEO_PLL);
198	}
199
200	hw->DACreg[POS1064_XPIXCLKCTRL] &= ~M1064_XPIXCLKCTRL_PLL_UP;
201	if (pixelmnp >= 0) {
202		hw->DACreg[POS1064_XPIXCLKCTRL] |= M1064_XPIXCLKCTRL_PLL_UP;
203
204		outDAC1064(minfo, M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]);
205		matroxfb_g450_setpll_cond(minfo, pixelmnp, M_PIXEL_PLL_C);
206	}
207	if (c2_ctl != hw->crtc2.ctl) {
208		hw->crtc2.ctl = c2_ctl;
209		mga_outl(0x3C10, c2_ctl);
210	}
211
212	pxc = minfo->crtc1.pixclock;
213	if (pxc == 0 || minfo->outputs[2].src == MATROXFB_SRC_CRTC2) {
214		pxc = minfo->crtc2.pixclock;
215	}
216	if (minfo->chip == MGA_G550) {
217		if (pxc < 45000) {
218			hw->DACreg[POS1064_XPANMODE] = 0x00;	/* 0-50 */
219		} else if (pxc < 55000) {
220			hw->DACreg[POS1064_XPANMODE] = 0x08;	/* 34-62 */
221		} else if (pxc < 70000) {
222			hw->DACreg[POS1064_XPANMODE] = 0x10;	/* 42-78 */
223		} else if (pxc < 85000) {
224			hw->DACreg[POS1064_XPANMODE] = 0x18;	/* 62-92 */
225		} else if (pxc < 100000) {
226			hw->DACreg[POS1064_XPANMODE] = 0x20;	/* 74-108 */
227		} else if (pxc < 115000) {
228			hw->DACreg[POS1064_XPANMODE] = 0x28;	/* 94-122 */
229		} else if (pxc < 125000) {
230			hw->DACreg[POS1064_XPANMODE] = 0x30;	/* 108-132 */
231		} else {
232			hw->DACreg[POS1064_XPANMODE] = 0x38;	/* 120-168 */
233		}
234	} else {
235		/* G450 */
236		if (pxc < 45000) {
237			hw->DACreg[POS1064_XPANMODE] = 0x00;	/* 0-54 */
238		} else if (pxc < 65000) {
239			hw->DACreg[POS1064_XPANMODE] = 0x08;	/* 38-70 */
240		} else if (pxc < 85000) {
241			hw->DACreg[POS1064_XPANMODE] = 0x10;	/* 56-96 */
242		} else if (pxc < 105000) {
243			hw->DACreg[POS1064_XPANMODE] = 0x18;	/* 80-114 */
244		} else if (pxc < 135000) {
245			hw->DACreg[POS1064_XPANMODE] = 0x20;	/* 102-144 */
246		} else if (pxc < 160000) {
247			hw->DACreg[POS1064_XPANMODE] = 0x28;	/* 132-166 */
248		} else if (pxc < 175000) {
249			hw->DACreg[POS1064_XPANMODE] = 0x30;	/* 154-182 */
250		} else {
251			hw->DACreg[POS1064_XPANMODE] = 0x38;	/* 170-204 */
252		}
253	}
254}
255#endif
256
257void DAC1064_global_init(struct matrox_fb_info *minfo)
258{
259	struct matrox_hw_state *hw = &minfo->hw;
260
261	hw->DACreg[POS1064_XMISCCTRL] &= M1064_XMISCCTRL_DAC_WIDTHMASK;
262	hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_LUT_EN;
263	hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL;
264#ifdef CONFIG_FB_MATROX_G
265	if (minfo->devflags.g450dac) {
266		hw->DACreg[POS1064_XPWRCTRL] = 0x1F;	/* powerup everything */
267		hw->DACreg[POS1064_XOUTPUTCONN] = 0x00;	/* disable outputs */
268		hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN;
269		switch (minfo->outputs[0].src) {
270			case MATROXFB_SRC_CRTC1:
271			case MATROXFB_SRC_CRTC2:
272				hw->DACreg[POS1064_XOUTPUTCONN] |= 0x01;	/* enable output; CRTC1/2 selection is in CRTC2 ctl */
273				break;
274			case MATROXFB_SRC_NONE:
275				hw->DACreg[POS1064_XMISCCTRL] &= ~M1064_XMISCCTRL_DAC_EN;
276				break;
277		}
278		switch (minfo->outputs[1].src) {
279			case MATROXFB_SRC_CRTC1:
280				hw->DACreg[POS1064_XOUTPUTCONN] |= 0x04;
281				break;
282			case MATROXFB_SRC_CRTC2:
283				if (minfo->outputs[1].mode == MATROXFB_OUTPUT_MODE_MONITOR) {
284					hw->DACreg[POS1064_XOUTPUTCONN] |= 0x08;
285				} else {
286					hw->DACreg[POS1064_XOUTPUTCONN] |= 0x0C;
287				}
288				break;
289			case MATROXFB_SRC_NONE:
290				hw->DACreg[POS1064_XPWRCTRL] &= ~0x01;		/* Poweroff DAC2 */
291				break;
292		}
293		switch (minfo->outputs[2].src) {
294			case MATROXFB_SRC_CRTC1:
295				hw->DACreg[POS1064_XOUTPUTCONN] |= 0x20;
296				break;
297			case MATROXFB_SRC_CRTC2:
298				hw->DACreg[POS1064_XOUTPUTCONN] |= 0x40;
299				break;
300			case MATROXFB_SRC_NONE:
301#if 0
302				/* HELP! If we boot without DFP connected to DVI, we can
303				   poweroff TMDS. But if we boot with DFP connected,
304				   TMDS generated clocks are used instead of ALL pixclocks
305				   available... If someone knows which register
306				   handles it, please reveal this secret to me... */
307				hw->DACreg[POS1064_XPWRCTRL] &= ~0x04;		/* Poweroff TMDS */
308#endif
309				break;
310		}
311		/* Now set timming related variables... */
312		g450_set_plls(minfo);
313	} else
314#endif
315	{
316		if (minfo->outputs[1].src == MATROXFB_SRC_CRTC1) {
317			hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_EXT;
318			hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_MAFC12;
319		} else if (minfo->outputs[1].src == MATROXFB_SRC_CRTC2) {
320			hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_C2_MAFC12;
321		} else if (minfo->outputs[2].src == MATROXFB_SRC_CRTC1)
322			hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_PANELLINK | G400_XMISCCTRL_VDO_MAFC12;
323		else
324			hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_DIS;
325
326		if (minfo->outputs[0].src != MATROXFB_SRC_NONE)
327			hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN;
328	}
329}
330
331void DAC1064_global_restore(struct matrox_fb_info *minfo)
332{
333	struct matrox_hw_state *hw = &minfo->hw;
334
335	outDAC1064(minfo, M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]);
336	outDAC1064(minfo, M1064_XMISCCTRL, hw->DACreg[POS1064_XMISCCTRL]);
337	if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400) {
338		outDAC1064(minfo, 0x20, 0x04);
339		outDAC1064(minfo, 0x1F, minfo->devflags.dfp_type);
340		if (minfo->devflags.g450dac) {
341			outDAC1064(minfo, M1064_XSYNCCTRL, 0xCC);
342			outDAC1064(minfo, M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]);
343			outDAC1064(minfo, M1064_XPANMODE, hw->DACreg[POS1064_XPANMODE]);
344			outDAC1064(minfo, M1064_XOUTPUTCONN, hw->DACreg[POS1064_XOUTPUTCONN]);
345		}
346	}
347}
348
349static int DAC1064_init_1(struct matrox_fb_info *minfo, struct my_timming *m)
350{
351	struct matrox_hw_state *hw = &minfo->hw;
352
353	DBG(__func__)
354
355	memcpy(hw->DACreg, MGA1064_DAC, sizeof(MGA1064_DAC_regs));
356	switch (minfo->fbcon.var.bits_per_pixel) {
357		/* case 4: not supported by MGA1064 DAC */
358		case 8:
359			hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_8BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
360			break;
361		case 16:
362			if (minfo->fbcon.var.green.length == 5)
363				hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_15BPP_1BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
364			else
365				hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_16BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
366			break;
367		case 24:
368			hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_24BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
369			break;
370		case 32:
371			hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_32BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
372			break;
373		default:
374			return 1;	/* unsupported depth */
375	}
376	hw->DACreg[POS1064_XVREFCTRL] = minfo->features.DAC1064.xvrefctrl;
377	hw->DACreg[POS1064_XGENCTRL] &= ~M1064_XGENCTRL_SYNC_ON_GREEN_MASK;
378	hw->DACreg[POS1064_XGENCTRL] |= (m->sync & FB_SYNC_ON_GREEN)?M1064_XGENCTRL_SYNC_ON_GREEN:M1064_XGENCTRL_NO_SYNC_ON_GREEN;
379	hw->DACreg[POS1064_XCURADDL] = 0;
380	hw->DACreg[POS1064_XCURADDH] = 0;
381
382	DAC1064_global_init(minfo);
383	return 0;
384}
385
386static int DAC1064_init_2(struct matrox_fb_info *minfo, struct my_timming *m)
387{
388	struct matrox_hw_state *hw = &minfo->hw;
389
390	DBG(__func__)
391
392	if (minfo->fbcon.var.bits_per_pixel > 16) {	/* 256 entries */
393		int i;
394
395		for (i = 0; i < 256; i++) {
396			hw->DACpal[i * 3 + 0] = i;
397			hw->DACpal[i * 3 + 1] = i;
398			hw->DACpal[i * 3 + 2] = i;
399		}
400	} else if (minfo->fbcon.var.bits_per_pixel > 8) {
401		if (minfo->fbcon.var.green.length == 5) {	/* 0..31, 128..159 */
402			int i;
403
404			for (i = 0; i < 32; i++) {
405				/* with p15 == 0 */
406				hw->DACpal[i * 3 + 0] = i << 3;
407				hw->DACpal[i * 3 + 1] = i << 3;
408				hw->DACpal[i * 3 + 2] = i << 3;
409				/* with p15 == 1 */
410				hw->DACpal[(i + 128) * 3 + 0] = i << 3;
411				hw->DACpal[(i + 128) * 3 + 1] = i << 3;
412				hw->DACpal[(i + 128) * 3 + 2] = i << 3;
413			}
414		} else {
415			int i;
416
417			for (i = 0; i < 64; i++) {		/* 0..63 */
418				hw->DACpal[i * 3 + 0] = i << 3;
419				hw->DACpal[i * 3 + 1] = i << 2;
420				hw->DACpal[i * 3 + 2] = i << 3;
421			}
422		}
423	} else {
424		memset(hw->DACpal, 0, 768);
425	}
426	return 0;
427}
428
429static void DAC1064_restore_1(struct matrox_fb_info *minfo)
430{
431	struct matrox_hw_state *hw = &minfo->hw;
432
433	CRITFLAGS
434
435	DBG(__func__)
436
437	CRITBEGIN
438
439	if ((inDAC1064(minfo, DAC1064_XSYSPLLM) != hw->DACclk[3]) ||
440	    (inDAC1064(minfo, DAC1064_XSYSPLLN) != hw->DACclk[4]) ||
441	    (inDAC1064(minfo, DAC1064_XSYSPLLP) != hw->DACclk[5])) {
442		outDAC1064(minfo, DAC1064_XSYSPLLM, hw->DACclk[3]);
443		outDAC1064(minfo, DAC1064_XSYSPLLN, hw->DACclk[4]);
444		outDAC1064(minfo, DAC1064_XSYSPLLP, hw->DACclk[5]);
445	}
446	{
447		unsigned int i;
448
449		for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) {
450			if ((i != POS1064_XPIXCLKCTRL) && (i != POS1064_XMISCCTRL))
451				outDAC1064(minfo, MGA1064_DAC_regs[i], hw->DACreg[i]);
452		}
453	}
454
455	DAC1064_global_restore(minfo);
456
457	CRITEND
458};
459
460static void DAC1064_restore_2(struct matrox_fb_info *minfo)
461{
462#ifdef DEBUG
463	unsigned int i;
464#endif
465
466	DBG(__func__)
467
468#ifdef DEBUG
469	dprintk(KERN_DEBUG "DAC1064regs ");
470	for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) {
471		dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], minfo->hw.DACreg[i]);
472		if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... ");
473	}
474	dprintk(KERN_DEBUG "DAC1064clk ");
475	for (i = 0; i < 6; i++)
476		dprintk("C%02X=%02X ", i, minfo->hw.DACclk[i]);
477	dprintk("\n");
478#endif
479}
480
481static int m1064_compute(void* out, struct my_timming* m) {
482#define minfo ((struct matrox_fb_info*)out)
483	{
484		int i;
485		int tmout;
486		CRITFLAGS
487
488		DAC1064_setpclk(minfo, m->pixclock);
489
490		CRITBEGIN
491
492		for (i = 0; i < 3; i++)
493			outDAC1064(minfo, M1064_XPIXPLLCM + i, minfo->hw.DACclk[i]);
494		for (tmout = 500000; tmout; tmout--) {
495			if (inDAC1064(minfo, M1064_XPIXPLLSTAT) & 0x40)
496				break;
497			udelay(10);
498		}
499
500		CRITEND
501
502		if (!tmout)
503			printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
504	}
505#undef minfo
506	return 0;
507}
508
509static struct matrox_altout m1064 = {
510	.name	 = "Primary output",
511	.compute = m1064_compute,
512};
513
514#ifdef CONFIG_FB_MATROX_G
515static int g450_compute(void* out, struct my_timming* m) {
516#define minfo ((struct matrox_fb_info*)out)
517	if (m->mnp < 0) {
518		m->mnp = matroxfb_g450_setclk(minfo, m->pixclock, (m->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL);
519		if (m->mnp >= 0) {
520			m->pixclock = g450_mnp2f(minfo, m->mnp);
521		}
522	}
523#undef minfo
524	return 0;
525}
526
527static struct matrox_altout g450out = {
528	.name	 = "Primary output",
529	.compute = g450_compute,
530};
531#endif
532
533#endif /* NEED_DAC1064 */
534
535#ifdef CONFIG_FB_MATROX_MYSTIQUE
536static int MGA1064_init(struct matrox_fb_info *minfo, struct my_timming *m)
537{
538	struct matrox_hw_state *hw = &minfo->hw;
539
540	DBG(__func__)
541
542	if (DAC1064_init_1(minfo, m)) return 1;
543	if (matroxfb_vgaHWinit(minfo, m)) return 1;
544
545	hw->MiscOutReg = 0xCB;
546	if (m->sync & FB_SYNC_HOR_HIGH_ACT)
547		hw->MiscOutReg &= ~0x40;
548	if (m->sync & FB_SYNC_VERT_HIGH_ACT)
549		hw->MiscOutReg &= ~0x80;
550	if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
551		hw->CRTCEXT[3] |= 0x40;
552
553	if (DAC1064_init_2(minfo, m)) return 1;
554	return 0;
555}
556#endif
557
558#ifdef CONFIG_FB_MATROX_G
559static int MGAG100_init(struct matrox_fb_info *minfo, struct my_timming *m)
560{
561	struct matrox_hw_state *hw = &minfo->hw;
562
563	DBG(__func__)
564
565	if (DAC1064_init_1(minfo, m)) return 1;
566	hw->MXoptionReg &= ~0x2000;
567	if (matroxfb_vgaHWinit(minfo, m)) return 1;
568
569	hw->MiscOutReg = 0xEF;
570	if (m->sync & FB_SYNC_HOR_HIGH_ACT)
571		hw->MiscOutReg &= ~0x40;
572	if (m->sync & FB_SYNC_VERT_HIGH_ACT)
573		hw->MiscOutReg &= ~0x80;
574	if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
575		hw->CRTCEXT[3] |= 0x40;
576
577	if (DAC1064_init_2(minfo, m)) return 1;
578	return 0;
579}
580#endif	/* G */
581
582#ifdef CONFIG_FB_MATROX_MYSTIQUE
583static void MGA1064_ramdac_init(struct matrox_fb_info *minfo)
584{
585
586	DBG(__func__)
587
588	/* minfo->features.DAC1064.vco_freq_min = 120000; */
589	minfo->features.pll.vco_freq_min = 62000;
590	minfo->features.pll.ref_freq	 = 14318;
591	minfo->features.pll.feed_div_min = 100;
592	minfo->features.pll.feed_div_max = 127;
593	minfo->features.pll.in_div_min	 = 1;
594	minfo->features.pll.in_div_max	 = 31;
595	minfo->features.pll.post_shift_max = 3;
596	minfo->features.DAC1064.xvrefctrl = DAC1064_XVREFCTRL_EXTERNAL;
597	/* maybe cmdline MCLK= ?, doc says gclk=44MHz, mclk=66MHz... it was 55/83 with old values */
598	DAC1064_setmclk(minfo, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PLL, 133333);
599}
600#endif
601
602#ifdef CONFIG_FB_MATROX_G
603/* BIOS environ */
604static int x7AF4 = 0x10;	/* flags, maybe 0x10 = SDRAM, 0x00 = SGRAM??? */
605				/* G100 wants 0x10, G200 SGRAM does not care... */
606#if 0
607static int def50 = 0;	/* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */
608#endif
609
610static void MGAG100_progPixClock(const struct matrox_fb_info *minfo, int flags,
611				 int m, int n, int p)
612{
613	int reg;
614	int selClk;
615	int clk;
616
617	DBG(__func__)
618
619	outDAC1064(minfo, M1064_XPIXCLKCTRL, inDAC1064(minfo, M1064_XPIXCLKCTRL) | M1064_XPIXCLKCTRL_DIS |
620		   M1064_XPIXCLKCTRL_PLL_UP);
621	switch (flags & 3) {
622		case 0:		reg = M1064_XPIXPLLAM; break;
623		case 1:		reg = M1064_XPIXPLLBM; break;
624		default:	reg = M1064_XPIXPLLCM; break;
625	}
626	outDAC1064(minfo, reg++, m);
627	outDAC1064(minfo, reg++, n);
628	outDAC1064(minfo, reg, p);
629	selClk = mga_inb(M_MISC_REG_READ) & ~0xC;
630	/* there should be flags & 0x03 & case 0/1/else */
631	/* and we should first select source and after that we should wait for PLL */
632	/* and we are waiting for PLL with oscilator disabled... Is it right? */
633	switch (flags & 0x03) {
634		case 0x00:	break;
635		case 0x01:	selClk |= 4; break;
636		default:	selClk |= 0x0C; break;
637	}
638	mga_outb(M_MISC_REG, selClk);
639	for (clk = 500000; clk; clk--) {
640		if (inDAC1064(minfo, M1064_XPIXPLLSTAT) & 0x40)
641			break;
642		udelay(10);
643	}
644	if (!clk)
645		printk(KERN_ERR "matroxfb: Pixel PLL%c not locked after usual time\n", (reg-M1064_XPIXPLLAM-2)/4 + 'A');
646	selClk = inDAC1064(minfo, M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_SRC_MASK;
647	switch (flags & 0x0C) {
648		case 0x00:	selClk |= M1064_XPIXCLKCTRL_SRC_PCI; break;
649		case 0x04:	selClk |= M1064_XPIXCLKCTRL_SRC_PLL; break;
650		default:	selClk |= M1064_XPIXCLKCTRL_SRC_EXT; break;
651	}
652	outDAC1064(minfo, M1064_XPIXCLKCTRL, selClk);
653	outDAC1064(minfo, M1064_XPIXCLKCTRL, inDAC1064(minfo, M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_DIS);
654}
655
656static void MGAG100_setPixClock(const struct matrox_fb_info *minfo, int flags,
657				int freq)
658{
659	unsigned int m, n, p;
660
661	DBG(__func__)
662
663	DAC1064_calcclock(minfo, freq, minfo->max_pixel_clock, &m, &n, &p);
664	MGAG100_progPixClock(minfo, flags, m, n, p);
665}
666#endif
667
668#ifdef CONFIG_FB_MATROX_MYSTIQUE
669static int MGA1064_preinit(struct matrox_fb_info *minfo)
670{
671	static const int vxres_mystique[] = { 512,        640, 768,  800,  832,  960,
672					     1024, 1152, 1280,      1600, 1664, 1920,
673					     2048,    0};
674	struct matrox_hw_state *hw = &minfo->hw;
675
676	DBG(__func__)
677
678	/* minfo->capable.cfb4 = 0; ... preinitialized by 0 */
679	minfo->capable.text = 1;
680	minfo->capable.vxres = vxres_mystique;
681
682	minfo->outputs[0].output = &m1064;
683	minfo->outputs[0].src = minfo->outputs[0].default_src;
684	minfo->outputs[0].data = minfo;
685	minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR;
686
687	if (minfo->devflags.noinit)
688		return 0;	/* do not modify settings */
689	hw->MXoptionReg &= 0xC0000100;
690	hw->MXoptionReg |= 0x00094E20;
691	if (minfo->devflags.novga)
692		hw->MXoptionReg &= ~0x00000100;
693	if (minfo->devflags.nobios)
694		hw->MXoptionReg &= ~0x40000000;
695	if (minfo->devflags.nopciretry)
696		hw->MXoptionReg |=  0x20000000;
697	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
698	mga_setr(M_SEQ_INDEX, 0x01, 0x20);
699	mga_outl(M_CTLWTST, 0x00000000);
700	udelay(200);
701	mga_outl(M_MACCESS, 0x00008000);
702	udelay(100);
703	mga_outl(M_MACCESS, 0x0000C000);
704	return 0;
705}
706
707static void MGA1064_reset(struct matrox_fb_info *minfo)
708{
709
710	DBG(__func__);
711
712	MGA1064_ramdac_init(minfo);
713}
714#endif
715
716#ifdef CONFIG_FB_MATROX_G
717static void g450_mclk_init(struct matrox_fb_info *minfo)
718{
719	/* switch all clocks to PCI source */
720	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg | 4);
721	pci_write_config_dword(minfo->pcidev, PCI_OPTION3_REG, minfo->values.reg.opt3 & ~0x00300C03);
722	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
723
724	if (((minfo->values.reg.opt3 & 0x000003) == 0x000003) ||
725	    ((minfo->values.reg.opt3 & 0x000C00) == 0x000C00) ||
726	    ((minfo->values.reg.opt3 & 0x300000) == 0x300000)) {
727		matroxfb_g450_setclk(minfo, minfo->values.pll.video, M_VIDEO_PLL);
728	} else {
729		unsigned long flags;
730		unsigned int pwr;
731
732		matroxfb_DAC_lock_irqsave(flags);
733		pwr = inDAC1064(minfo, M1064_XPWRCTRL) & ~0x02;
734		outDAC1064(minfo, M1064_XPWRCTRL, pwr);
735		matroxfb_DAC_unlock_irqrestore(flags);
736	}
737	matroxfb_g450_setclk(minfo, minfo->values.pll.system, M_SYSTEM_PLL);
738
739	/* switch clocks to their real PLL source(s) */
740	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg | 4);
741	pci_write_config_dword(minfo->pcidev, PCI_OPTION3_REG, minfo->values.reg.opt3);
742	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
743
744}
745
746static void g450_memory_init(struct matrox_fb_info *minfo)
747{
748	/* disable memory refresh */
749	minfo->hw.MXoptionReg &= ~0x001F8000;
750	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
751
752	/* set memory interface parameters */
753	minfo->hw.MXoptionReg &= ~0x00207E00;
754	minfo->hw.MXoptionReg |= 0x00207E00 & minfo->values.reg.opt;
755	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
756	pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, minfo->values.reg.opt2);
757
758	mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
759
760	/* first set up memory interface with disabled memory interface clocks */
761	pci_write_config_dword(minfo->pcidev, PCI_MEMMISC_REG, minfo->values.reg.memmisc & ~0x80000000U);
762	mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
763	mga_outl(M_MACCESS, minfo->values.reg.maccess);
764	/* start memory clocks */
765	pci_write_config_dword(minfo->pcidev, PCI_MEMMISC_REG, minfo->values.reg.memmisc | 0x80000000U);
766
767	udelay(200);
768
769	if (minfo->values.memory.ddr && (!minfo->values.memory.emrswen || !minfo->values.memory.dll)) {
770		mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk & ~0x1000);
771	}
772	mga_outl(M_MACCESS, minfo->values.reg.maccess | 0x8000);
773
774	udelay(200);
775
776	minfo->hw.MXoptionReg |= 0x001F8000 & minfo->values.reg.opt;
777	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
778
779	/* value is written to memory chips only if old != new */
780	mga_outl(M_PLNWT, 0);
781	mga_outl(M_PLNWT, ~0);
782
783	if (minfo->values.reg.mctlwtst != minfo->values.reg.mctlwtst_core) {
784		mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst_core);
785	}
786
787}
788
789static void g450_preinit(struct matrox_fb_info *minfo)
790{
791	u_int32_t c2ctl;
792	u_int8_t curctl;
793	u_int8_t c1ctl;
794
795	/* minfo->hw.MXoptionReg = minfo->values.reg.opt; */
796	minfo->hw.MXoptionReg &= 0xC0000100;
797	minfo->hw.MXoptionReg |= 0x00000020;
798	if (minfo->devflags.novga)
799		minfo->hw.MXoptionReg &= ~0x00000100;
800	if (minfo->devflags.nobios)
801		minfo->hw.MXoptionReg &= ~0x40000000;
802	if (minfo->devflags.nopciretry)
803		minfo->hw.MXoptionReg |=  0x20000000;
804	minfo->hw.MXoptionReg |= minfo->values.reg.opt & 0x03400040;
805	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
806
807	/* Init system clocks */
808
809	/* stop crtc2 */
810	c2ctl = mga_inl(M_C2CTL);
811	mga_outl(M_C2CTL, c2ctl & ~1);
812	/* stop cursor */
813	curctl = inDAC1064(minfo, M1064_XCURCTRL);
814	outDAC1064(minfo, M1064_XCURCTRL, 0);
815	/* stop crtc1 */
816	c1ctl = mga_readr(M_SEQ_INDEX, 1);
817	mga_setr(M_SEQ_INDEX, 1, c1ctl | 0x20);
818
819	g450_mclk_init(minfo);
820	g450_memory_init(minfo);
821
822	/* set legacy VGA clock sources for DOSEmu or VMware... */
823	matroxfb_g450_setclk(minfo, 25175, M_PIXEL_PLL_A);
824	matroxfb_g450_setclk(minfo, 28322, M_PIXEL_PLL_B);
825
826	/* restore crtc1 */
827	mga_setr(M_SEQ_INDEX, 1, c1ctl);
828
829	/* restore cursor */
830	outDAC1064(minfo, M1064_XCURCTRL, curctl);
831
832	/* restore crtc2 */
833	mga_outl(M_C2CTL, c2ctl);
834
835	return;
836}
837
838static int MGAG100_preinit(struct matrox_fb_info *minfo)
839{
840	static const int vxres_g100[] = {  512,        640, 768,  800,  832,  960,
841                                          1024, 1152, 1280,      1600, 1664, 1920,
842                                          2048, 0};
843	struct matrox_hw_state *hw = &minfo->hw;
844
845        u_int32_t reg50;
846#if 0
847	u_int32_t q;
848#endif
849
850	DBG(__func__)
851
852	/* there are some instabilities if in_div > 19 && vco < 61000 */
853	if (minfo->devflags.g450dac) {
854		minfo->features.pll.vco_freq_min = 130000;	/* my sample: >118 */
855	} else {
856		minfo->features.pll.vco_freq_min = 62000;
857	}
858	if (!minfo->features.pll.ref_freq) {
859		minfo->features.pll.ref_freq	 = 27000;
860	}
861	minfo->features.pll.feed_div_min = 7;
862	minfo->features.pll.feed_div_max = 127;
863	minfo->features.pll.in_div_min	 = 1;
864	minfo->features.pll.in_div_max	 = 31;
865	minfo->features.pll.post_shift_max = 3;
866	minfo->features.DAC1064.xvrefctrl = DAC1064_XVREFCTRL_G100_DEFAULT;
867	/* minfo->capable.cfb4 = 0; ... preinitialized by 0 */
868	minfo->capable.text = 1;
869	minfo->capable.vxres = vxres_g100;
870	minfo->capable.plnwt = minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG100
871			? minfo->devflags.sgram : 1;
872
873	if (minfo->devflags.g450dac) {
874		minfo->outputs[0].output = &g450out;
875	} else {
876		minfo->outputs[0].output = &m1064;
877	}
878	minfo->outputs[0].src = minfo->outputs[0].default_src;
879	minfo->outputs[0].data = minfo;
880	minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR;
881
882	if (minfo->devflags.g450dac) {
883		/* we must do this always, BIOS does not do it for us
884		   and accelerator dies without it */
885		mga_outl(0x1C0C, 0);
886	}
887	if (minfo->devflags.noinit)
888		return 0;
889	if (minfo->devflags.g450dac) {
890		g450_preinit(minfo);
891		return 0;
892	}
893	hw->MXoptionReg &= 0xC0000100;
894	hw->MXoptionReg |= 0x00000020;
895	if (minfo->devflags.novga)
896		hw->MXoptionReg &= ~0x00000100;
897	if (minfo->devflags.nobios)
898		hw->MXoptionReg &= ~0x40000000;
899	if (minfo->devflags.nopciretry)
900		hw->MXoptionReg |=  0x20000000;
901	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
902	DAC1064_setmclk(minfo, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PCI, 133333);
903
904	if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG100) {
905		pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
906		reg50 &= ~0x3000;
907		pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
908
909		hw->MXoptionReg |= 0x1080;
910		pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
911		mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
912		udelay(100);
913		mga_outb(0x1C05, 0x00);
914		mga_outb(0x1C05, 0x80);
915		udelay(100);
916		mga_outb(0x1C05, 0x40);
917		mga_outb(0x1C05, 0xC0);
918		udelay(100);
919		reg50 &= ~0xFF;
920		reg50 |=  0x07;
921		pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
922		/* it should help with G100 */
923		mga_outb(M_GRAPHICS_INDEX, 6);
924		mga_outb(M_GRAPHICS_DATA, (mga_inb(M_GRAPHICS_DATA) & 3) | 4);
925		mga_setr(M_EXTVGA_INDEX, 0x03, 0x81);
926		mga_setr(M_EXTVGA_INDEX, 0x04, 0x00);
927		mga_writeb(minfo->video.vbase, 0x0000, 0xAA);
928		mga_writeb(minfo->video.vbase, 0x0800, 0x55);
929		mga_writeb(minfo->video.vbase, 0x4000, 0x55);
930#if 0
931		if (mga_readb(minfo->video.vbase, 0x0000) != 0xAA) {
932			hw->MXoptionReg &= ~0x1000;
933		}
934#endif
935		hw->MXoptionReg |= 0x00078020;
936	} else if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG200) {
937		pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
938		reg50 &= ~0x3000;
939		pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
940
941		if (minfo->devflags.memtype == -1)
942			hw->MXoptionReg |= minfo->values.reg.opt & 0x1C00;
943		else
944			hw->MXoptionReg |= (minfo->devflags.memtype & 7) << 10;
945		if (minfo->devflags.sgram)
946			hw->MXoptionReg |= 0x4000;
947		mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
948		mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
949		udelay(200);
950		mga_outl(M_MACCESS, 0x00000000);
951		mga_outl(M_MACCESS, 0x00008000);
952		udelay(100);
953		mga_outw(M_MEMRDBK, minfo->values.reg.memrdbk);
954		hw->MXoptionReg |= 0x00078020;
955	} else {
956		pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
957		reg50 &= ~0x00000100;
958		reg50 |=  0x00000000;
959		pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
960
961		if (minfo->devflags.memtype == -1)
962			hw->MXoptionReg |= minfo->values.reg.opt & 0x1C00;
963		else
964			hw->MXoptionReg |= (minfo->devflags.memtype & 7) << 10;
965		if (minfo->devflags.sgram)
966			hw->MXoptionReg |= 0x4000;
967		mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
968		mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
969		udelay(200);
970		mga_outl(M_MACCESS, 0x00000000);
971		mga_outl(M_MACCESS, 0x00008000);
972		udelay(100);
973		mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
974		hw->MXoptionReg |= 0x00040020;
975	}
976	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
977	return 0;
978}
979
980static void MGAG100_reset(struct matrox_fb_info *minfo)
981{
982	u_int8_t b;
983	struct matrox_hw_state *hw = &minfo->hw;
984
985	DBG(__func__)
986
987	{
988#ifdef G100_BROKEN_IBM_82351
989		u_int32_t d;
990
991		find 1014/22 (IBM/82351); /* if found and bridging Matrox, do some strange stuff */
992		pci_read_config_byte(ibm, PCI_SECONDARY_BUS, &b);
993		if (b == minfo->pcidev->bus->number) {
994			pci_write_config_byte(ibm, PCI_COMMAND+1, 0);	/* disable back-to-back & SERR */
995			pci_write_config_byte(ibm, 0x41, 0xF4);		/* ??? */
996			pci_write_config_byte(ibm, PCI_IO_BASE, 0xF0);	/* ??? */
997			pci_write_config_byte(ibm, PCI_IO_LIMIT, 0x00);	/* ??? */
998		}
999#endif
1000		if (!minfo->devflags.noinit) {
1001			if (x7AF4 & 8) {
1002				hw->MXoptionReg |= 0x40;	/* FIXME... */
1003				pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
1004			}
1005			mga_setr(M_EXTVGA_INDEX, 0x06, 0x00);
1006		}
1007	}
1008	if (minfo->devflags.g450dac) {
1009		/* either leave MCLK as is... or they were set in preinit */
1010		hw->DACclk[3] = inDAC1064(minfo, DAC1064_XSYSPLLM);
1011		hw->DACclk[4] = inDAC1064(minfo, DAC1064_XSYSPLLN);
1012		hw->DACclk[5] = inDAC1064(minfo, DAC1064_XSYSPLLP);
1013	} else {
1014		DAC1064_setmclk(minfo, DAC1064_OPT_RESERVED | DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV1 | DAC1064_OPT_SCLK_PLL, 133333);
1015	}
1016	if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400) {
1017		if (minfo->devflags.dfp_type == -1) {
1018			minfo->devflags.dfp_type = inDAC1064(minfo, 0x1F);
1019		}
1020	}
1021	if (minfo->devflags.noinit)
1022		return;
1023	if (minfo->devflags.g450dac) {
1024	} else {
1025		MGAG100_setPixClock(minfo, 4, 25175);
1026		MGAG100_setPixClock(minfo, 5, 28322);
1027		if (x7AF4 & 0x10) {
1028			b = inDAC1064(minfo, M1064_XGENIODATA) & ~1;
1029			outDAC1064(minfo, M1064_XGENIODATA, b);
1030			b = inDAC1064(minfo, M1064_XGENIOCTRL) | 1;
1031			outDAC1064(minfo, M1064_XGENIOCTRL, b);
1032		}
1033	}
1034}
1035#endif
1036
1037#ifdef CONFIG_FB_MATROX_MYSTIQUE
1038static void MGA1064_restore(struct matrox_fb_info *minfo)
1039{
1040	int i;
1041	struct matrox_hw_state *hw = &minfo->hw;
1042
1043	CRITFLAGS
1044
1045	DBG(__func__)
1046
1047	CRITBEGIN
1048
1049	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
1050	mga_outb(M_IEN, 0x00);
1051	mga_outb(M_CACHEFLUSH, 0x00);
1052
1053	CRITEND
1054
1055	DAC1064_restore_1(minfo);
1056	matroxfb_vgaHWrestore(minfo);
1057	minfo->crtc1.panpos = -1;
1058	for (i = 0; i < 6; i++)
1059		mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
1060	DAC1064_restore_2(minfo);
1061}
1062#endif
1063
1064#ifdef CONFIG_FB_MATROX_G
1065static void MGAG100_restore(struct matrox_fb_info *minfo)
1066{
1067	int i;
1068	struct matrox_hw_state *hw = &minfo->hw;
1069
1070	CRITFLAGS
1071
1072	DBG(__func__)
1073
1074	CRITBEGIN
1075
1076	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
1077	CRITEND
1078
1079	DAC1064_restore_1(minfo);
1080	matroxfb_vgaHWrestore(minfo);
1081	if (minfo->devflags.support32MB)
1082		mga_setr(M_EXTVGA_INDEX, 8, hw->CRTCEXT[8]);
1083	minfo->crtc1.panpos = -1;
1084	for (i = 0; i < 6; i++)
1085		mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
1086	DAC1064_restore_2(minfo);
1087}
1088#endif
1089
1090#ifdef CONFIG_FB_MATROX_MYSTIQUE
1091struct matrox_switch matrox_mystique = {
1092	.preinit	= MGA1064_preinit,
1093	.reset		= MGA1064_reset,
1094	.init		= MGA1064_init,
1095	.restore	= MGA1064_restore,
1096};
1097EXPORT_SYMBOL(matrox_mystique);
1098#endif
1099
1100#ifdef CONFIG_FB_MATROX_G
1101struct matrox_switch matrox_G100 = {
1102	.preinit	= MGAG100_preinit,
1103	.reset		= MGAG100_reset,
1104	.init		= MGAG100_init,
1105	.restore	= MGAG100_restore,
1106};
1107EXPORT_SYMBOL(matrox_G100);
1108#endif
1109
1110#ifdef NEED_DAC1064
1111EXPORT_SYMBOL(DAC1064_global_init);
1112EXPORT_SYMBOL(DAC1064_global_restore);
1113#endif
1114MODULE_LICENSE("GPL");
1115