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