File Index
Files and directories
Sign in
FILE

matroxfb_DAC1064.c

File preview with syntax highlighting.

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