diff options
Diffstat (limited to 'drivers/video/matrox/matroxfb_DAC1064.c')
-rw-r--r-- | drivers/video/matrox/matroxfb_DAC1064.c | 1086 |
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 | |||
38 | static 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 */ | ||
61 | static 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 | |||
72 | static 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 | |||
85 | static 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 | |||
96 | static 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 | ||
159 | static 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 | |||
250 | void 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 | |||
323 | void 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 | |||
340 | static 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 | |||
376 | static 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 | |||
418 | static 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 | |||
448 | static 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 | |||
468 | static 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 | |||
496 | static struct matrox_altout m1064 = { | ||
497 | .name = "Primary output", | ||
498 | .compute = m1064_compute, | ||
499 | }; | ||
500 | |||
501 | #ifdef CONFIG_FB_MATROX_G | ||
502 | static 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 | |||
514 | static 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 | ||
523 | static 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 | ||
545 | static 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 | ||
568 | static 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 */ | ||
588 | static int x7AF4 = 0x10; /* flags, maybe 0x10 = SDRAM, 0x00 = SGRAM??? */ | ||
589 | /* G100 wants 0x10, G200 SGRAM does not care... */ | ||
590 | #if 0 | ||
591 | static int def50 = 0; /* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */ | ||
592 | #endif | ||
593 | |||
594 | static 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 | |||
638 | static 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 | ||
649 | static 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 | |||
687 | static void MGA1064_reset(WPMINFO2) { | ||
688 | |||
689 | DBG(__FUNCTION__); | ||
690 | |||
691 | MGA1064_ramdac_init(PMINFO2); | ||
692 | } | ||
693 | #endif | ||
694 | |||
695 | #ifdef CONFIG_FB_MATROX_G | ||
696 | static 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 | |||
724 | static 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 | |||
766 | static 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 | |||
814 | static 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, ®50); | ||
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, ®50); | ||
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, ®50); | ||
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 | |||
959 | static 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 | ||
1016 | static 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 | ||
1042 | static 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 | ||
1069 | struct matrox_switch matrox_mystique = { | ||
1070 | MGA1064_preinit, MGA1064_reset, MGA1064_init, MGA1064_restore, | ||
1071 | }; | ||
1072 | EXPORT_SYMBOL(matrox_mystique); | ||
1073 | #endif | ||
1074 | |||
1075 | #ifdef CONFIG_FB_MATROX_G | ||
1076 | struct matrox_switch matrox_G100 = { | ||
1077 | MGAG100_preinit, MGAG100_reset, MGAG100_init, MGAG100_restore, | ||
1078 | }; | ||
1079 | EXPORT_SYMBOL(matrox_G100); | ||
1080 | #endif | ||
1081 | |||
1082 | #ifdef NEED_DAC1064 | ||
1083 | EXPORT_SYMBOL(DAC1064_global_init); | ||
1084 | EXPORT_SYMBOL(DAC1064_global_restore); | ||
1085 | #endif | ||
1086 | MODULE_LICENSE("GPL"); | ||