brintos

brintos / linux-shallow public Read only

0
0
Text · 33.2 KiB · 398b703 Raw
1116 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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/1411 *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_DAC106424#define outDAC1064 matroxfb_DAC_out25#define inDAC1064 matroxfb_DAC_in26 27#define DAC1064_OPT_SCLK_PCI	0x0028#define DAC1064_OPT_SCLK_PLL	0x0129#define DAC1064_OPT_SCLK_EXT	0x0230#define DAC1064_OPT_SCLK_MASK	0x0331#define DAC1064_OPT_GDIV1	0x04	/* maybe it is GDIV2 on G100 ?! */32#define DAC1064_OPT_GDIV3	0x0033#define DAC1064_OPT_MDIV1	0x0834#define DAC1064_OPT_MDIV2	0x0035#define DAC1064_OPT_RESERVED	0x1036 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	else59		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 should137		   generate ABORT or I/O (parity...) error and Linux should138		   recover from this... (kill driver/process). But world is not139		   perfect... */140		/* (bit 2 of PCI_OPTION_REG must be 0... and bits 0,1 must not141		   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_G165static 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 N188			   of PIXEL PLL in such case because of VIDEO PLL may be source189			   of TVO clocks, and chroma subcarrier is derived from its190			   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#endif256 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_G265	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 0302				/* HELP! If we boot without DFP connected to DVI, we can303				   poweroff TMDS. But if we boot with DFP connected,304				   TMDS generated clocks are used instead of ALL pixclocks305				   available... If someone knows which register306				   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	} else314#endif315	{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		else324			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			else365				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	CRITFLAGS434 435	DBG(__func__)436 437	CRITBEGIN438 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	CRITEND458};459 460static void DAC1064_restore_2(struct matrox_fb_info *minfo)461{462#ifdef DEBUG463	unsigned int i;464#endif465 466	DBG(__func__)467 468#ifdef DEBUG469	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#endif479}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		CRITFLAGS487 488		DAC1064_setpclk(minfo, m->pixclock);489 490		CRITBEGIN491 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		CRITEND501 502		if (!tmout)503			printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");504	}505#undef minfo506	return 0;507}508 509static struct matrox_altout m1064 = {510	.name	 = "Primary output",511	.compute = m1064_compute,512};513 514#ifdef CONFIG_FB_MATROX_G515static 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 minfo524	return 0;525}526 527static struct matrox_altout g450out = {528	.name	 = "Primary output",529	.compute = g450_compute,530};531#endif532 533#endif /* NEED_DAC1064 */534 535#ifdef CONFIG_FB_MATROX_MYSTIQUE536static 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#endif557 558#ifdef CONFIG_FB_MATROX_G559static 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_MYSTIQUE583static 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#endif601 602#ifdef CONFIG_FB_MATROX_G603/* BIOS environ */604static int x7AF4 = 0x10;	/* flags, maybe 0x10 = SDRAM, 0x00 = SGRAM??? */605				/* G100 wants 0x10, G200 SGRAM does not care... */606#if 0607static int def50 = 0;	/* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */608#endif609 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#endif667 668#ifdef CONFIG_FB_MATROX_MYSTIQUE669static 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#endif715 716#ifdef CONFIG_FB_MATROX_G717static 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 0847	u_int32_t q;848#endif849 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_MGAG100871			? 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 us884		   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 0931		if (mga_readb(minfo->video.vbase, 0x0000) != 0xAA) {932			hw->MXoptionReg &= ~0x1000;933		}934#endif935		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		else944			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		else964			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_82351989		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#endif1000		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#endif1036 1037#ifdef CONFIG_FB_MATROX_MYSTIQUE1038static void MGA1064_restore(struct matrox_fb_info *minfo)1039{1040	int i;1041	struct matrox_hw_state *hw = &minfo->hw;1042 1043	CRITFLAGS1044 1045	DBG(__func__)1046 1047	CRITBEGIN1048 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	CRITEND1054 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#endif1063 1064#ifdef CONFIG_FB_MATROX_G1065static void MGAG100_restore(struct matrox_fb_info *minfo)1066{1067	int i;1068	struct matrox_hw_state *hw = &minfo->hw;1069 1070	CRITFLAGS1071 1072	DBG(__func__)1073 1074	CRITBEGIN1075 1076	pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);1077	CRITEND1078 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#endif1089 1090#ifdef CONFIG_FB_MATROX_MYSTIQUE1091struct 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#endif1099 1100#ifdef CONFIG_FB_MATROX_G1101struct 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#endif1109 1110#ifdef NEED_DAC10641111EXPORT_SYMBOL(DAC1064_global_init);1112EXPORT_SYMBOL(DAC1064_global_restore);1113#endif1114MODULE_DESCRIPTION("Matrox Mystique/G100 output driver");1115MODULE_LICENSE("GPL");1116