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