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