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