blob: 0ce3b0a8979805333158d8cd67f44a304ab9f43c [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
Linus Torvalds1da177e2005-04-16 15:20:36 -070015
16#include "matroxfb_DAC1064.h"
17#include "matroxfb_misc.h"
18#include "matroxfb_accel.h"
19#include "g450_pll.h"
20#include <linux/matroxfb.h>
21
22#ifdef NEED_DAC1064
23#define outDAC1064 matroxfb_DAC_out
24#define inDAC1064 matroxfb_DAC_in
25
26#define DAC1064_OPT_SCLK_PCI 0x00
27#define DAC1064_OPT_SCLK_PLL 0x01
28#define DAC1064_OPT_SCLK_EXT 0x02
29#define DAC1064_OPT_SCLK_MASK 0x03
30#define DAC1064_OPT_GDIV1 0x04 /* maybe it is GDIV2 on G100 ?! */
31#define DAC1064_OPT_GDIV3 0x00
32#define DAC1064_OPT_MDIV1 0x08
33#define DAC1064_OPT_MDIV2 0x00
34#define DAC1064_OPT_RESERVED 0x10
35
36static 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;
39
Harvey Harrison5ae12172008-04-28 02:15:47 -070040 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
42 /* only for devices older than G450 */
43
44 fvco = PLL_calcclock(PMINFO freq, fmax, in, feed, &p);
45
46 p = (1 << p) - 1;
47 if (fvco <= 100000)
48 ;
49 else if (fvco <= 140000)
50 p |= 0x08;
51 else if (fvco <= 180000)
52 p |= 0x10;
53 else
54 p |= 0x18;
55 *post = p;
56}
57
58/* they must be in POS order */
59static 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 };
69
70static 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};
82
83static void DAC1064_setpclk(WPMINFO unsigned long fout) {
84 unsigned int m, n, p;
85
Harvey Harrison5ae12172008-04-28 02:15:47 -070086 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
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;
92}
93
94static void DAC1064_setmclk(WPMINFO int oscinfo, unsigned long fmem) {
95 u_int32_t mx;
96 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
97
Harvey Harrison5ae12172008-04-28 02:15:47 -070098 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
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;
106 }
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;
120
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);
126
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;
141 }
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;
149 }
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;
154}
155
156#ifdef CONFIG_FB_MATROX_G
157static 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;
163
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;
183 }
184 c2_ctl |= 0x0006; /* Use video PLL */
185 hw->DACreg[POS1064_XPWRCTRL] |= 0x02;
186
187 outDAC1064(PMINFO M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]);
188 matroxfb_g450_setpll_cond(PMINFO videomnp, M_VIDEO_PLL);
189 }
190
191 hw->DACreg[POS1064_XPIXCLKCTRL] &= ~M1064_XPIXCLKCTRL_PLL_UP;
192 if (pixelmnp >= 0) {
193 hw->DACreg[POS1064_XPIXCLKCTRL] |= M1064_XPIXCLKCTRL_PLL_UP;
194
195 outDAC1064(PMINFO M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]);
196 matroxfb_g450_setpll_cond(PMINFO pixelmnp, M_PIXEL_PLL_C);
197 }
198 if (c2_ctl != hw->crtc2.ctl) {
199 hw->crtc2.ctl = c2_ctl;
200 mga_outl(0x3C10, c2_ctl);
201 }
202
203 pxc = ACCESS_FBINFO(crtc1).pixclock;
204 if (pxc == 0 || ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC2) {
205 pxc = ACCESS_FBINFO(crtc2).pixclock;
206 }
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 */
224 }
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 */
243 }
244 }
245}
246#endif
247
248void DAC1064_global_init(WPMINFO2) {
249 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
250
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;
267 }
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;
277 }
278 break;
279 case MATROXFB_SRC_NONE:
280 hw->DACreg[POS1064_XPWRCTRL] &= ~0x01; /* Poweroff DAC2 */
281 break;
282 }
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;
300 }
301 /* Now set timming related variables... */
302 g450_set_plls(PMINFO2);
303 } else
304#endif
305 {
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;
315
316 if (ACCESS_FBINFO(outputs[0]).src != MATROXFB_SRC_NONE)
317 hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN;
318 }
319}
320
321void DAC1064_global_restore(WPMINFO2) {
322 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
323
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]);
334 }
335 }
336}
337
338static int DAC1064_init_1(WPMINFO struct my_timming* m) {
339 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
340
Harvey Harrison5ae12172008-04-28 02:15:47 -0700341 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342
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 */
363 }
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;
369
370 DAC1064_global_init(PMINFO2);
371 return 0;
372}
373
374static int DAC1064_init_2(WPMINFO struct my_timming* m) {
375 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
376
Harvey Harrison5ae12172008-04-28 02:15:47 -0700377 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
379 if (ACCESS_FBINFO(fbcon).var.bits_per_pixel > 16) { /* 256 entries */
380 int i;
381
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;
386 }
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;
390
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;
400 }
401 } else {
402 int i;
403
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;
408 }
409 }
410 } else {
411 memset(hw->DACpal, 0, 768);
412 }
413 return 0;
414}
415
416static void DAC1064_restore_1(WPMINFO2) {
417 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
418
419 CRITFLAGS
420
Harvey Harrison5ae12172008-04-28 02:15:47 -0700421 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422
423 CRITBEGIN
424
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]);
431 }
432 {
433 unsigned int i;
434
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]);
438 }
439 }
440
441 DAC1064_global_restore(PMINFO2);
442
443 CRITEND
444};
445
446static void DAC1064_restore_2(WPMINFO2) {
447#ifdef DEBUG
448 unsigned int i;
449#endif
450
Harvey Harrison5ae12172008-04-28 02:15:47 -0700451 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452
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... ");
458 }
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
464}
465
466static int m1064_compute(void* out, struct my_timming* m) {
467#define minfo ((struct matrox_fb_info*)out)
468 {
469 int i;
470 int tmout;
471 CRITFLAGS
472
473 DAC1064_setpclk(PMINFO m->pixclock);
474
475 CRITBEGIN
476
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);
483 };
484
485 CRITEND
486
487 if (!tmout)
488 printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
489 }
490#undef minfo
491 return 0;
492}
493
494static struct matrox_altout m1064 = {
495 .name = "Primary output",
496 .compute = m1064_compute,
497};
498
499#ifdef CONFIG_FB_MATROX_G
500static 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);
506 }
507 }
508#undef minfo
509 return 0;
510}
511
512static struct matrox_altout g450out = {
513 .name = "Primary output",
514 .compute = g450_compute,
515};
516#endif
517
518#endif /* NEED_DAC1064 */
519
520#ifdef CONFIG_FB_MATROX_MYSTIQUE
521static int MGA1064_init(WPMINFO struct my_timming* m) {
522 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
523
Harvey Harrison5ae12172008-04-28 02:15:47 -0700524 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525
526 if (DAC1064_init_1(PMINFO m)) return 1;
527 if (matroxfb_vgaHWinit(PMINFO m)) return 1;
528
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;
536
537 if (DAC1064_init_2(PMINFO m)) return 1;
538 return 0;
539}
540#endif
541
542#ifdef CONFIG_FB_MATROX_G
543static int MGAG100_init(WPMINFO struct my_timming* m) {
544 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
545
Harvey Harrison5ae12172008-04-28 02:15:47 -0700546 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547
548 if (DAC1064_init_1(PMINFO m)) return 1;
549 hw->MXoptionReg &= ~0x2000;
550 if (matroxfb_vgaHWinit(PMINFO m)) return 1;
551
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;
559
560 if (DAC1064_init_2(PMINFO m)) return 1;
561 return 0;
562}
563#endif /* G */
564
565#ifdef CONFIG_FB_MATROX_MYSTIQUE
566static void MGA1064_ramdac_init(WPMINFO2) {
567
Harvey Harrison5ae12172008-04-28 02:15:47 -0700568 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569
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);
581}
582#endif
583
584#ifdef CONFIG_FB_MATROX_G
585/* BIOS environ */
586static int x7AF4 = 0x10; /* flags, maybe 0x10 = SDRAM, 0x00 = SGRAM??? */
587 /* G100 wants 0x10, G200 SGRAM does not care... */
588#if 0
589static int def50 = 0; /* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */
590#endif
591
592static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p) {
593 int reg;
594 int selClk;
595 int clk;
596
Harvey Harrison5ae12172008-04-28 02:15:47 -0700597 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598
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;
605 }
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;
617 }
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);
623 };
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;
631 }
632 outDAC1064(PMINFO M1064_XPIXCLKCTRL, selClk);
633 outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_DIS);
634}
635
636static void MGAG100_setPixClock(CPMINFO int flags, int freq) {
637 unsigned int m, n, p;
638
Harvey Harrison5ae12172008-04-28 02:15:47 -0700639 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
641 DAC1064_calcclock(PMINFO freq, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p);
642 MGAG100_progPixClock(PMINFO flags, m, n, p);
643}
644#endif
645
646#ifdef CONFIG_FB_MATROX_MYSTIQUE
647static 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);
652
Harvey Harrison5ae12172008-04-28 02:15:47 -0700653 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654
655 /* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */
656 ACCESS_FBINFO(capable.text) = 1;
657 ACCESS_FBINFO(capable.vxres) = vxres_mystique;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658
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;
663
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;
682}
683
684static void MGA1064_reset(WPMINFO2) {
685
Harvey Harrison5ae12172008-04-28 02:15:47 -0700686 DBG(__func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687
688 MGA1064_ramdac_init(PMINFO2);
689}
690#endif
691
692#ifdef CONFIG_FB_MATROX_G
693static 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);
698
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;
706
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);
711 }
712 matroxfb_g450_setclk(PMINFO ACCESS_FBINFO(values.pll.system), M_SYSTEM_PLL);
713
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);
718
719}
720
721static 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);
725
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);
731
732 mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst);
733
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);
740
741 udelay(200);
742
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);
745 }
746 mga_outl(M_MACCESS, ACCESS_FBINFO(values).reg.maccess | 0x8000);
747
748 udelay(200);
749
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);
752
753 /* value is written to memory chips only if old != new */
754 mga_outl(M_PLNWT, 0);
755 mga_outl(M_PLNWT, ~0);
756
757 if (ACCESS_FBINFO(values).reg.mctlwtst != ACCESS_FBINFO(values).reg.mctlwtst_core) {
758 mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst_core);
759 }
760
761}
762
763static void g450_preinit(WPMINFO2) {
764 u_int32_t c2ctl;
765 u_int8_t curctl;
766 u_int8_t c1ctl;
767
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);
779
780 /* Init system clocks */
781
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);
791
792 g450_mclk_init(PMINFO2);
793 g450_memory_init(PMINFO2);
794
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);
798
799 /* restore crtc1 */
800 mga_setr(M_SEQ_INDEX, 1, c1ctl);
801
802 /* restore cursor */
803 outDAC1064(PMINFO M1064_XCURCTRL, curctl);
804
805 /* restore crtc2 */
806 mga_outl(M_C2CTL, c2ctl);
807
808 return;
809}
810
811static 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);
816
817 u_int32_t reg50;
818#if 0
819 u_int32_t q;
820#endif
821
Harvey Harrison5ae12172008-04-28 02:15:47 -0700822 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823
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;
829 }
830 if (!ACCESS_FBINFO(features.pll.ref_freq)) {
831 ACCESS_FBINFO(features.pll.ref_freq) = 27000;
832 }
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;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 ACCESS_FBINFO(capable.plnwt) = ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100
843 ? ACCESS_FBINFO(devflags.sgram) : 1;
844
845#ifdef CONFIG_FB_MATROX_G
846 if (ACCESS_FBINFO(devflags.g450dac)) {
847 ACCESS_FBINFO(outputs[0]).output = &g450out;
848 } else
849#endif
850 {
851 ACCESS_FBINFO(outputs[0]).output = &m1064;
852 }
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;
856
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);
861 }
862 if (ACCESS_FBINFO(devflags.noinit))
863 return 0;
864 if (ACCESS_FBINFO(devflags.g450dac)) {
865 g450_preinit(PMINFO2);
866 return 0;
867 }
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);
878
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);
883
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;
908 }
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);
915
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);
935
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;
950 }
951 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
952 return 0;
953}
954
955static void MGAG100_reset(WPMINFO2) {
956 u_int8_t b;
957 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
958
Harvey Harrison5ae12172008-04-28 02:15:47 -0700959 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960
961 {
962#ifdef G100_BROKEN_IBM_82351
963 u_int32_t d;
964
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); /* ??? */
972 }
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);
978 }
Ville Syrjäläf73195a2005-11-07 01:01:00 -0800979 mga_setr(M_EXTVGA_INDEX, 0x06, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 }
981 }
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);
989 }
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);
993 }
994 }
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);
1006 }
1007 }
1008}
1009#endif
1010
1011#ifdef CONFIG_FB_MATROX_MYSTIQUE
1012static void MGA1064_restore(WPMINFO2) {
1013 int i;
1014 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
1015
1016 CRITFLAGS
1017
Harvey Harrison5ae12172008-04-28 02:15:47 -07001018 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019
1020 CRITBEGIN
1021
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);
1025
1026 CRITEND
1027
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);
1034}
1035#endif
1036
1037#ifdef CONFIG_FB_MATROX_G
1038static void MGAG100_restore(WPMINFO2) {
1039 int i;
1040 struct matrox_hw_state* hw = &ACCESS_FBINFO(hw);
1041
1042 CRITFLAGS
1043
Harvey Harrison5ae12172008-04-28 02:15:47 -07001044 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045
1046 CRITBEGIN
1047
1048 pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
1049 CRITEND
1050
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);
1061}
1062#endif
1063
1064#ifdef CONFIG_FB_MATROX_MYSTIQUE
1065struct matrox_switch matrox_mystique = {
1066 MGA1064_preinit, MGA1064_reset, MGA1064_init, MGA1064_restore,
1067};
1068EXPORT_SYMBOL(matrox_mystique);
1069#endif
1070
1071#ifdef CONFIG_FB_MATROX_G
1072struct matrox_switch matrox_G100 = {
1073 MGAG100_preinit, MGAG100_reset, MGAG100_init, MGAG100_restore,
1074};
1075EXPORT_SYMBOL(matrox_G100);
1076#endif
1077
1078#ifdef NEED_DAC1064
1079EXPORT_SYMBOL(DAC1064_global_init);
1080EXPORT_SYMBOL(DAC1064_global_restore);
1081#endif
1082MODULE_LICENSE("GPL");