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