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

source code of linux/drivers/video/fbdev/matrox/matroxfb_DAC1064.c