cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

matroxfb_DAC1064.c (33895B)


      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");