blob: 88466a04bab2833d25adbf5bd1af0c0590411873 [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
Jean Delvare316b4d62009-09-22 16:47:49 -070036static void DAC1064_calcclock(const struct matrox_fb_info *minfo,
37 unsigned int freq, unsigned int fmax,
38 unsigned int *in, unsigned int *feed,
39 unsigned int *post)
40{
Linus Torvalds1da177e2005-04-16 15:20:36 -070041 unsigned int fvco;
42 unsigned int p;
43
Harvey Harrison5ae12172008-04-28 02:15:47 -070044 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
46 /* only for devices older than G450 */
47
Jean Delvare316b4d62009-09-22 16:47:49 -070048 fvco = PLL_calcclock(minfo, freq, fmax, in, feed, &p);
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
50 p = (1 << p) - 1;
51 if (fvco <= 100000)
52 ;
53 else if (fvco <= 140000)
54 p |= 0x08;
55 else if (fvco <= 180000)
56 p |= 0x10;
57 else
58 p |= 0x18;
59 *post = p;
60}
61
62/* they must be in POS order */
63static const unsigned char MGA1064_DAC_regs[] = {
64 M1064_XCURADDL, M1064_XCURADDH, M1064_XCURCTRL,
65 M1064_XCURCOL0RED, M1064_XCURCOL0GREEN, M1064_XCURCOL0BLUE,
66 M1064_XCURCOL1RED, M1064_XCURCOL1GREEN, M1064_XCURCOL1BLUE,
67 M1064_XCURCOL2RED, M1064_XCURCOL2GREEN, M1064_XCURCOL2BLUE,
68 DAC1064_XVREFCTRL, M1064_XMULCTRL, M1064_XPIXCLKCTRL, M1064_XGENCTRL,
69 M1064_XMISCCTRL,
70 M1064_XGENIOCTRL, M1064_XGENIODATA, M1064_XZOOMCTRL, M1064_XSENSETEST,
71 M1064_XCRCBITSEL,
72 M1064_XCOLKEYMASKL, M1064_XCOLKEYMASKH, M1064_XCOLKEYL, M1064_XCOLKEYH };
73
74static const unsigned char MGA1064_DAC[] = {
75 0x00, 0x00, M1064_XCURCTRL_DIS,
76 0x00, 0x00, 0x00, /* black */
77 0xFF, 0xFF, 0xFF, /* white */
78 0xFF, 0x00, 0x00, /* red */
79 0x00, 0,
80 M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL,
81 M1064_XGENCTRL_VS_0 | M1064_XGENCTRL_ALPHA_DIS | M1064_XGENCTRL_BLACK_0IRE | M1064_XGENCTRL_NO_SYNC_ON_GREEN,
82 M1064_XMISCCTRL_DAC_8BIT,
83 0x00, 0x00, M1064_XZOOMCTRL_1, M1064_XSENSETEST_BCOMP | M1064_XSENSETEST_GCOMP | M1064_XSENSETEST_RCOMP | M1064_XSENSETEST_PDOWN,
84 0x00,
85 0x00, 0x00, 0xFF, 0xFF};
86
Jean Delvare316b4d62009-09-22 16:47:49 -070087static void DAC1064_setpclk(struct matrox_fb_info *minfo, unsigned long fout)
88{
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 unsigned int m, n, p;
90
Harvey Harrison5ae12172008-04-28 02:15:47 -070091 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -070092
Jean Delvare316b4d62009-09-22 16:47:49 -070093 DAC1064_calcclock(minfo, fout, minfo->max_pixel_clock, &m, &n, &p);
Jean Delvarefc2d10d2009-09-22 16:47:48 -070094 minfo->hw.DACclk[0] = m;
95 minfo->hw.DACclk[1] = n;
96 minfo->hw.DACclk[2] = p;
Linus Torvalds1da177e2005-04-16 15:20:36 -070097}
98
Jean Delvare316b4d62009-09-22 16:47:49 -070099static void DAC1064_setmclk(struct matrox_fb_info *minfo, int oscinfo,
100 unsigned long fmem)
101{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102 u_int32_t mx;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700103 struct matrox_hw_state *hw = &minfo->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
Harvey Harrison5ae12172008-04-28 02:15:47 -0700105 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700107 if (minfo->devflags.noinit) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 /* read MCLK and give up... */
Jean Delvare316b4d62009-09-22 16:47:49 -0700109 hw->DACclk[3] = inDAC1064(minfo, DAC1064_XSYSPLLM);
110 hw->DACclk[4] = inDAC1064(minfo, DAC1064_XSYSPLLN);
111 hw->DACclk[5] = inDAC1064(minfo, DAC1064_XSYSPLLP);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 return;
113 }
114 mx = hw->MXoptionReg | 0x00000004;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700115 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116 mx &= ~0x000000BB;
117 if (oscinfo & DAC1064_OPT_GDIV1)
118 mx |= 0x00000008;
119 if (oscinfo & DAC1064_OPT_MDIV1)
120 mx |= 0x00000010;
121 if (oscinfo & DAC1064_OPT_RESERVED)
122 mx |= 0x00000080;
123 if ((oscinfo & DAC1064_OPT_SCLK_MASK) == DAC1064_OPT_SCLK_PLL) {
124 /* select PCI clock until we have setup oscilator... */
125 int clk;
126 unsigned int m, n, p;
127
128 /* powerup system PLL, select PCI clock */
129 mx |= 0x00000020;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700130 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131 mx &= ~0x00000004;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700132 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133
134 /* !!! you must not access device if MCLK is not running !!!
135 Doing so cause immediate PCI lockup :-( Maybe they should
136 generate ABORT or I/O (parity...) error and Linux should
137 recover from this... (kill driver/process). But world is not
138 perfect... */
139 /* (bit 2 of PCI_OPTION_REG must be 0... and bits 0,1 must not
140 select PLL... because of PLL can be stopped at this time) */
Jean Delvare316b4d62009-09-22 16:47:49 -0700141 DAC1064_calcclock(minfo, fmem, minfo->max_pixel_clock, &m, &n, &p);
142 outDAC1064(minfo, DAC1064_XSYSPLLM, hw->DACclk[3] = m);
143 outDAC1064(minfo, DAC1064_XSYSPLLN, hw->DACclk[4] = n);
144 outDAC1064(minfo, DAC1064_XSYSPLLP, hw->DACclk[5] = p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 for (clk = 65536; clk; --clk) {
Jean Delvare316b4d62009-09-22 16:47:49 -0700146 if (inDAC1064(minfo, DAC1064_XSYSPLLSTAT) & 0x40)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 break;
148 }
149 if (!clk)
150 printk(KERN_ERR "matroxfb: aiee, SYSPLL not locked\n");
151 /* select PLL */
152 mx |= 0x00000005;
153 } else {
154 /* select specified system clock source */
155 mx |= oscinfo & DAC1064_OPT_SCLK_MASK;
156 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700157 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158 mx &= ~0x00000004;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700159 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160 hw->MXoptionReg = mx;
161}
162
163#ifdef CONFIG_FB_MATROX_G
Jean Delvare316b4d62009-09-22 16:47:49 -0700164static void g450_set_plls(struct matrox_fb_info *minfo)
165{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 u_int32_t c2_ctl;
167 unsigned int pxc;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700168 struct matrox_hw_state *hw = &minfo->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169 int pixelmnp;
170 int videomnp;
171
172 c2_ctl = hw->crtc2.ctl & ~0x4007; /* Clear PLL + enable for CRTC2 */
173 c2_ctl |= 0x0001; /* Enable CRTC2 */
174 hw->DACreg[POS1064_XPWRCTRL] &= ~0x02; /* Stop VIDEO PLL */
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700175 pixelmnp = minfo->crtc1.mnp;
176 videomnp = minfo->crtc2.mnp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177 if (videomnp < 0) {
178 c2_ctl &= ~0x0001; /* Disable CRTC2 */
179 hw->DACreg[POS1064_XPWRCTRL] &= ~0x10; /* Powerdown CRTC2 */
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700180 } else if (minfo->crtc2.pixclock == minfo->features.pll.ref_freq) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181 c2_ctl |= 0x4002; /* Use reference directly */
182 } else if (videomnp == pixelmnp) {
183 c2_ctl |= 0x0004; /* Use pixel PLL */
184 } else {
185 if (0 == ((videomnp ^ pixelmnp) & 0xFFFFFF00)) {
186 /* PIXEL and VIDEO PLL must not use same frequency. We modify N
187 of PIXEL PLL in such case because of VIDEO PLL may be source
188 of TVO clocks, and chroma subcarrier is derived from its
189 pixel clocks */
190 pixelmnp += 0x000100;
191 }
192 c2_ctl |= 0x0006; /* Use video PLL */
193 hw->DACreg[POS1064_XPWRCTRL] |= 0x02;
194
Jean Delvare316b4d62009-09-22 16:47:49 -0700195 outDAC1064(minfo, M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]);
196 matroxfb_g450_setpll_cond(minfo, videomnp, M_VIDEO_PLL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 }
198
199 hw->DACreg[POS1064_XPIXCLKCTRL] &= ~M1064_XPIXCLKCTRL_PLL_UP;
200 if (pixelmnp >= 0) {
201 hw->DACreg[POS1064_XPIXCLKCTRL] |= M1064_XPIXCLKCTRL_PLL_UP;
202
Jean Delvare316b4d62009-09-22 16:47:49 -0700203 outDAC1064(minfo, M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]);
204 matroxfb_g450_setpll_cond(minfo, pixelmnp, M_PIXEL_PLL_C);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205 }
206 if (c2_ctl != hw->crtc2.ctl) {
207 hw->crtc2.ctl = c2_ctl;
208 mga_outl(0x3C10, c2_ctl);
209 }
210
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700211 pxc = minfo->crtc1.pixclock;
212 if (pxc == 0 || minfo->outputs[2].src == MATROXFB_SRC_CRTC2) {
213 pxc = minfo->crtc2.pixclock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700215 if (minfo->chip == MGA_G550) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 if (pxc < 45000) {
217 hw->DACreg[POS1064_XPANMODE] = 0x00; /* 0-50 */
218 } else if (pxc < 55000) {
219 hw->DACreg[POS1064_XPANMODE] = 0x08; /* 34-62 */
220 } else if (pxc < 70000) {
221 hw->DACreg[POS1064_XPANMODE] = 0x10; /* 42-78 */
222 } else if (pxc < 85000) {
223 hw->DACreg[POS1064_XPANMODE] = 0x18; /* 62-92 */
224 } else if (pxc < 100000) {
225 hw->DACreg[POS1064_XPANMODE] = 0x20; /* 74-108 */
226 } else if (pxc < 115000) {
227 hw->DACreg[POS1064_XPANMODE] = 0x28; /* 94-122 */
228 } else if (pxc < 125000) {
229 hw->DACreg[POS1064_XPANMODE] = 0x30; /* 108-132 */
230 } else {
231 hw->DACreg[POS1064_XPANMODE] = 0x38; /* 120-168 */
232 }
233 } else {
234 /* G450 */
235 if (pxc < 45000) {
236 hw->DACreg[POS1064_XPANMODE] = 0x00; /* 0-54 */
237 } else if (pxc < 65000) {
238 hw->DACreg[POS1064_XPANMODE] = 0x08; /* 38-70 */
239 } else if (pxc < 85000) {
240 hw->DACreg[POS1064_XPANMODE] = 0x10; /* 56-96 */
241 } else if (pxc < 105000) {
242 hw->DACreg[POS1064_XPANMODE] = 0x18; /* 80-114 */
243 } else if (pxc < 135000) {
244 hw->DACreg[POS1064_XPANMODE] = 0x20; /* 102-144 */
245 } else if (pxc < 160000) {
246 hw->DACreg[POS1064_XPANMODE] = 0x28; /* 132-166 */
247 } else if (pxc < 175000) {
248 hw->DACreg[POS1064_XPANMODE] = 0x30; /* 154-182 */
249 } else {
250 hw->DACreg[POS1064_XPANMODE] = 0x38; /* 170-204 */
251 }
252 }
253}
254#endif
255
Jean Delvare316b4d62009-09-22 16:47:49 -0700256void DAC1064_global_init(struct matrox_fb_info *minfo)
257{
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700258 struct matrox_hw_state *hw = &minfo->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259
260 hw->DACreg[POS1064_XMISCCTRL] &= M1064_XMISCCTRL_DAC_WIDTHMASK;
261 hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_LUT_EN;
262 hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL;
263#ifdef CONFIG_FB_MATROX_G
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700264 if (minfo->devflags.g450dac) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265 hw->DACreg[POS1064_XPWRCTRL] = 0x1F; /* powerup everything */
266 hw->DACreg[POS1064_XOUTPUTCONN] = 0x00; /* disable outputs */
267 hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700268 switch (minfo->outputs[0].src) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 case MATROXFB_SRC_CRTC1:
270 case MATROXFB_SRC_CRTC2:
271 hw->DACreg[POS1064_XOUTPUTCONN] |= 0x01; /* enable output; CRTC1/2 selection is in CRTC2 ctl */
272 break;
273 case MATROXFB_SRC_NONE:
274 hw->DACreg[POS1064_XMISCCTRL] &= ~M1064_XMISCCTRL_DAC_EN;
275 break;
276 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700277 switch (minfo->outputs[1].src) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 case MATROXFB_SRC_CRTC1:
279 hw->DACreg[POS1064_XOUTPUTCONN] |= 0x04;
280 break;
281 case MATROXFB_SRC_CRTC2:
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700282 if (minfo->outputs[1].mode == MATROXFB_OUTPUT_MODE_MONITOR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 hw->DACreg[POS1064_XOUTPUTCONN] |= 0x08;
284 } else {
285 hw->DACreg[POS1064_XOUTPUTCONN] |= 0x0C;
286 }
287 break;
288 case MATROXFB_SRC_NONE:
289 hw->DACreg[POS1064_XPWRCTRL] &= ~0x01; /* Poweroff DAC2 */
290 break;
291 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700292 switch (minfo->outputs[2].src) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 case MATROXFB_SRC_CRTC1:
294 hw->DACreg[POS1064_XOUTPUTCONN] |= 0x20;
295 break;
296 case MATROXFB_SRC_CRTC2:
297 hw->DACreg[POS1064_XOUTPUTCONN] |= 0x40;
298 break;
299 case MATROXFB_SRC_NONE:
300#if 0
301 /* HELP! If we boot without DFP connected to DVI, we can
302 poweroff TMDS. But if we boot with DFP connected,
303 TMDS generated clocks are used instead of ALL pixclocks
304 available... If someone knows which register
305 handles it, please reveal this secret to me... */
306 hw->DACreg[POS1064_XPWRCTRL] &= ~0x04; /* Poweroff TMDS */
307#endif
308 break;
309 }
310 /* Now set timming related variables... */
Jean Delvare316b4d62009-09-22 16:47:49 -0700311 g450_set_plls(minfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 } else
313#endif
314 {
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700315 if (minfo->outputs[1].src == MATROXFB_SRC_CRTC1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_EXT;
317 hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_MAFC12;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700318 } else if (minfo->outputs[1].src == MATROXFB_SRC_CRTC2) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_C2_MAFC12;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700320 } else if (minfo->outputs[2].src == MATROXFB_SRC_CRTC1)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_PANELLINK | G400_XMISCCTRL_VDO_MAFC12;
322 else
323 hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_DIS;
324
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700325 if (minfo->outputs[0].src != MATROXFB_SRC_NONE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326 hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN;
327 }
328}
329
Jean Delvare316b4d62009-09-22 16:47:49 -0700330void DAC1064_global_restore(struct matrox_fb_info *minfo)
331{
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700332 struct matrox_hw_state *hw = &minfo->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
Jean Delvare316b4d62009-09-22 16:47:49 -0700334 outDAC1064(minfo, M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]);
335 outDAC1064(minfo, M1064_XMISCCTRL, hw->DACreg[POS1064_XMISCCTRL]);
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700336 if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400) {
Jean Delvare316b4d62009-09-22 16:47:49 -0700337 outDAC1064(minfo, 0x20, 0x04);
338 outDAC1064(minfo, 0x1F, minfo->devflags.dfp_type);
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700339 if (minfo->devflags.g450dac) {
Jean Delvare316b4d62009-09-22 16:47:49 -0700340 outDAC1064(minfo, M1064_XSYNCCTRL, 0xCC);
341 outDAC1064(minfo, M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]);
342 outDAC1064(minfo, M1064_XPANMODE, hw->DACreg[POS1064_XPANMODE]);
343 outDAC1064(minfo, M1064_XOUTPUTCONN, hw->DACreg[POS1064_XOUTPUTCONN]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 }
345 }
346}
347
Jean Delvare316b4d62009-09-22 16:47:49 -0700348static int DAC1064_init_1(struct matrox_fb_info *minfo, struct my_timming *m)
349{
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700350 struct matrox_hw_state *hw = &minfo->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351
Harvey Harrison5ae12172008-04-28 02:15:47 -0700352 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353
354 memcpy(hw->DACreg, MGA1064_DAC, sizeof(MGA1064_DAC_regs));
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700355 switch (minfo->fbcon.var.bits_per_pixel) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 /* case 4: not supported by MGA1064 DAC */
357 case 8:
358 hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_8BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
359 break;
360 case 16:
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700361 if (minfo->fbcon.var.green.length == 5)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362 hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_15BPP_1BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
363 else
364 hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_16BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
365 break;
366 case 24:
367 hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_24BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
368 break;
369 case 32:
370 hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_32BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
371 break;
372 default:
373 return 1; /* unsupported depth */
374 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700375 hw->DACreg[POS1064_XVREFCTRL] = minfo->features.DAC1064.xvrefctrl;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 hw->DACreg[POS1064_XGENCTRL] &= ~M1064_XGENCTRL_SYNC_ON_GREEN_MASK;
377 hw->DACreg[POS1064_XGENCTRL] |= (m->sync & FB_SYNC_ON_GREEN)?M1064_XGENCTRL_SYNC_ON_GREEN:M1064_XGENCTRL_NO_SYNC_ON_GREEN;
378 hw->DACreg[POS1064_XCURADDL] = 0;
379 hw->DACreg[POS1064_XCURADDH] = 0;
380
Jean Delvare316b4d62009-09-22 16:47:49 -0700381 DAC1064_global_init(minfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 return 0;
383}
384
Jean Delvare316b4d62009-09-22 16:47:49 -0700385static int DAC1064_init_2(struct matrox_fb_info *minfo, struct my_timming *m)
386{
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700387 struct matrox_hw_state *hw = &minfo->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
Harvey Harrison5ae12172008-04-28 02:15:47 -0700389 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700391 if (minfo->fbcon.var.bits_per_pixel > 16) { /* 256 entries */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 int i;
393
394 for (i = 0; i < 256; i++) {
395 hw->DACpal[i * 3 + 0] = i;
396 hw->DACpal[i * 3 + 1] = i;
397 hw->DACpal[i * 3 + 2] = i;
398 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700399 } else if (minfo->fbcon.var.bits_per_pixel > 8) {
400 if (minfo->fbcon.var.green.length == 5) { /* 0..31, 128..159 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 int i;
402
403 for (i = 0; i < 32; i++) {
404 /* with p15 == 0 */
405 hw->DACpal[i * 3 + 0] = i << 3;
406 hw->DACpal[i * 3 + 1] = i << 3;
407 hw->DACpal[i * 3 + 2] = i << 3;
408 /* with p15 == 1 */
409 hw->DACpal[(i + 128) * 3 + 0] = i << 3;
410 hw->DACpal[(i + 128) * 3 + 1] = i << 3;
411 hw->DACpal[(i + 128) * 3 + 2] = i << 3;
412 }
413 } else {
414 int i;
415
416 for (i = 0; i < 64; i++) { /* 0..63 */
417 hw->DACpal[i * 3 + 0] = i << 3;
418 hw->DACpal[i * 3 + 1] = i << 2;
419 hw->DACpal[i * 3 + 2] = i << 3;
420 }
421 }
422 } else {
423 memset(hw->DACpal, 0, 768);
424 }
425 return 0;
426}
427
Jean Delvare316b4d62009-09-22 16:47:49 -0700428static void DAC1064_restore_1(struct matrox_fb_info *minfo)
429{
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700430 struct matrox_hw_state *hw = &minfo->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431
432 CRITFLAGS
433
Harvey Harrison5ae12172008-04-28 02:15:47 -0700434 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435
436 CRITBEGIN
437
Jean Delvare316b4d62009-09-22 16:47:49 -0700438 if ((inDAC1064(minfo, DAC1064_XSYSPLLM) != hw->DACclk[3]) ||
439 (inDAC1064(minfo, DAC1064_XSYSPLLN) != hw->DACclk[4]) ||
440 (inDAC1064(minfo, DAC1064_XSYSPLLP) != hw->DACclk[5])) {
441 outDAC1064(minfo, DAC1064_XSYSPLLM, hw->DACclk[3]);
442 outDAC1064(minfo, DAC1064_XSYSPLLN, hw->DACclk[4]);
443 outDAC1064(minfo, DAC1064_XSYSPLLP, hw->DACclk[5]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 }
445 {
446 unsigned int i;
447
448 for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) {
449 if ((i != POS1064_XPIXCLKCTRL) && (i != POS1064_XMISCCTRL))
Jean Delvare316b4d62009-09-22 16:47:49 -0700450 outDAC1064(minfo, MGA1064_DAC_regs[i], hw->DACreg[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 }
452 }
453
Jean Delvare316b4d62009-09-22 16:47:49 -0700454 DAC1064_global_restore(minfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455
456 CRITEND
457};
458
Jean Delvare316b4d62009-09-22 16:47:49 -0700459static void DAC1064_restore_2(struct matrox_fb_info *minfo)
460{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461#ifdef DEBUG
462 unsigned int i;
463#endif
464
Harvey Harrison5ae12172008-04-28 02:15:47 -0700465 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466
467#ifdef DEBUG
468 dprintk(KERN_DEBUG "DAC1064regs ");
469 for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) {
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700470 dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], minfo->hw.DACreg[i]);
Joe Perchesad361c92009-07-06 13:05:40 -0700471 if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 }
Joe Perchesad361c92009-07-06 13:05:40 -0700473 dprintk(KERN_DEBUG "DAC1064clk ");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 for (i = 0; i < 6; i++)
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700475 dprintk("C%02X=%02X ", i, minfo->hw.DACclk[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 dprintk("\n");
477#endif
478}
479
480static int m1064_compute(void* out, struct my_timming* m) {
481#define minfo ((struct matrox_fb_info*)out)
482 {
483 int i;
484 int tmout;
485 CRITFLAGS
486
Jean Delvare316b4d62009-09-22 16:47:49 -0700487 DAC1064_setpclk(minfo, m->pixclock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488
489 CRITBEGIN
490
491 for (i = 0; i < 3; i++)
Jean Delvare316b4d62009-09-22 16:47:49 -0700492 outDAC1064(minfo, M1064_XPIXPLLCM + i, minfo->hw.DACclk[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 for (tmout = 500000; tmout; tmout--) {
Jean Delvare316b4d62009-09-22 16:47:49 -0700494 if (inDAC1064(minfo, M1064_XPIXPLLSTAT) & 0x40)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 break;
496 udelay(10);
497 };
498
499 CRITEND
500
501 if (!tmout)
502 printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
503 }
504#undef minfo
505 return 0;
506}
507
508static struct matrox_altout m1064 = {
509 .name = "Primary output",
510 .compute = m1064_compute,
511};
512
513#ifdef CONFIG_FB_MATROX_G
514static int g450_compute(void* out, struct my_timming* m) {
515#define minfo ((struct matrox_fb_info*)out)
516 if (m->mnp < 0) {
Jean Delvare316b4d62009-09-22 16:47:49 -0700517 m->mnp = matroxfb_g450_setclk(minfo, m->pixclock, (m->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 if (m->mnp >= 0) {
Jean Delvare316b4d62009-09-22 16:47:49 -0700519 m->pixclock = g450_mnp2f(minfo, m->mnp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 }
521 }
522#undef minfo
523 return 0;
524}
525
526static struct matrox_altout g450out = {
527 .name = "Primary output",
528 .compute = g450_compute,
529};
530#endif
531
532#endif /* NEED_DAC1064 */
533
534#ifdef CONFIG_FB_MATROX_MYSTIQUE
Jean Delvare316b4d62009-09-22 16:47:49 -0700535static int MGA1064_init(struct matrox_fb_info *minfo, struct my_timming *m)
536{
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700537 struct matrox_hw_state *hw = &minfo->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
Harvey Harrison5ae12172008-04-28 02:15:47 -0700539 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540
Jean Delvare316b4d62009-09-22 16:47:49 -0700541 if (DAC1064_init_1(minfo, m)) return 1;
542 if (matroxfb_vgaHWinit(minfo, m)) return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543
544 hw->MiscOutReg = 0xCB;
545 if (m->sync & FB_SYNC_HOR_HIGH_ACT)
546 hw->MiscOutReg &= ~0x40;
547 if (m->sync & FB_SYNC_VERT_HIGH_ACT)
548 hw->MiscOutReg &= ~0x80;
549 if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
550 hw->CRTCEXT[3] |= 0x40;
551
Jean Delvare316b4d62009-09-22 16:47:49 -0700552 if (DAC1064_init_2(minfo, m)) return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 return 0;
554}
555#endif
556
557#ifdef CONFIG_FB_MATROX_G
Jean Delvare316b4d62009-09-22 16:47:49 -0700558static int MGAG100_init(struct matrox_fb_info *minfo, struct my_timming *m)
559{
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700560 struct matrox_hw_state *hw = &minfo->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561
Harvey Harrison5ae12172008-04-28 02:15:47 -0700562 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563
Jean Delvare316b4d62009-09-22 16:47:49 -0700564 if (DAC1064_init_1(minfo, m)) return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 hw->MXoptionReg &= ~0x2000;
Jean Delvare316b4d62009-09-22 16:47:49 -0700566 if (matroxfb_vgaHWinit(minfo, m)) return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567
568 hw->MiscOutReg = 0xEF;
569 if (m->sync & FB_SYNC_HOR_HIGH_ACT)
570 hw->MiscOutReg &= ~0x40;
571 if (m->sync & FB_SYNC_VERT_HIGH_ACT)
572 hw->MiscOutReg &= ~0x80;
573 if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
574 hw->CRTCEXT[3] |= 0x40;
575
Jean Delvare316b4d62009-09-22 16:47:49 -0700576 if (DAC1064_init_2(minfo, m)) return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 return 0;
578}
579#endif /* G */
580
581#ifdef CONFIG_FB_MATROX_MYSTIQUE
Jean Delvare316b4d62009-09-22 16:47:49 -0700582static void MGA1064_ramdac_init(struct matrox_fb_info *minfo)
583{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584
Harvey Harrison5ae12172008-04-28 02:15:47 -0700585 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700587 /* minfo->features.DAC1064.vco_freq_min = 120000; */
588 minfo->features.pll.vco_freq_min = 62000;
589 minfo->features.pll.ref_freq = 14318;
590 minfo->features.pll.feed_div_min = 100;
591 minfo->features.pll.feed_div_max = 127;
592 minfo->features.pll.in_div_min = 1;
593 minfo->features.pll.in_div_max = 31;
594 minfo->features.pll.post_shift_max = 3;
595 minfo->features.DAC1064.xvrefctrl = DAC1064_XVREFCTRL_EXTERNAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 /* maybe cmdline MCLK= ?, doc says gclk=44MHz, mclk=66MHz... it was 55/83 with old values */
Jean Delvare316b4d62009-09-22 16:47:49 -0700597 DAC1064_setmclk(minfo, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PLL, 133333);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598}
599#endif
600
601#ifdef CONFIG_FB_MATROX_G
602/* BIOS environ */
603static int x7AF4 = 0x10; /* flags, maybe 0x10 = SDRAM, 0x00 = SGRAM??? */
604 /* G100 wants 0x10, G200 SGRAM does not care... */
605#if 0
606static int def50 = 0; /* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */
607#endif
608
Jean Delvare316b4d62009-09-22 16:47:49 -0700609static void MGAG100_progPixClock(const struct matrox_fb_info *minfo, int flags,
610 int m, int n, int p)
611{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 int reg;
613 int selClk;
614 int clk;
615
Harvey Harrison5ae12172008-04-28 02:15:47 -0700616 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617
Jean Delvare316b4d62009-09-22 16:47:49 -0700618 outDAC1064(minfo, M1064_XPIXCLKCTRL, inDAC1064(minfo, M1064_XPIXCLKCTRL) | M1064_XPIXCLKCTRL_DIS |
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 M1064_XPIXCLKCTRL_PLL_UP);
620 switch (flags & 3) {
621 case 0: reg = M1064_XPIXPLLAM; break;
622 case 1: reg = M1064_XPIXPLLBM; break;
623 default: reg = M1064_XPIXPLLCM; break;
624 }
Jean Delvare316b4d62009-09-22 16:47:49 -0700625 outDAC1064(minfo, reg++, m);
626 outDAC1064(minfo, reg++, n);
627 outDAC1064(minfo, reg, p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 selClk = mga_inb(M_MISC_REG_READ) & ~0xC;
629 /* there should be flags & 0x03 & case 0/1/else */
630 /* and we should first select source and after that we should wait for PLL */
631 /* and we are waiting for PLL with oscilator disabled... Is it right? */
632 switch (flags & 0x03) {
633 case 0x00: break;
634 case 0x01: selClk |= 4; break;
635 default: selClk |= 0x0C; break;
636 }
637 mga_outb(M_MISC_REG, selClk);
638 for (clk = 500000; clk; clk--) {
Jean Delvare316b4d62009-09-22 16:47:49 -0700639 if (inDAC1064(minfo, M1064_XPIXPLLSTAT) & 0x40)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 break;
641 udelay(10);
642 };
643 if (!clk)
644 printk(KERN_ERR "matroxfb: Pixel PLL%c not locked after usual time\n", (reg-M1064_XPIXPLLAM-2)/4 + 'A');
Jean Delvare316b4d62009-09-22 16:47:49 -0700645 selClk = inDAC1064(minfo, M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_SRC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 switch (flags & 0x0C) {
647 case 0x00: selClk |= M1064_XPIXCLKCTRL_SRC_PCI; break;
648 case 0x04: selClk |= M1064_XPIXCLKCTRL_SRC_PLL; break;
649 default: selClk |= M1064_XPIXCLKCTRL_SRC_EXT; break;
650 }
Jean Delvare316b4d62009-09-22 16:47:49 -0700651 outDAC1064(minfo, M1064_XPIXCLKCTRL, selClk);
652 outDAC1064(minfo, M1064_XPIXCLKCTRL, inDAC1064(minfo, M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_DIS);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653}
654
Jean Delvare316b4d62009-09-22 16:47:49 -0700655static void MGAG100_setPixClock(const struct matrox_fb_info *minfo, int flags,
656 int freq)
657{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 unsigned int m, n, p;
659
Harvey Harrison5ae12172008-04-28 02:15:47 -0700660 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661
Jean Delvare316b4d62009-09-22 16:47:49 -0700662 DAC1064_calcclock(minfo, freq, minfo->max_pixel_clock, &m, &n, &p);
663 MGAG100_progPixClock(minfo, flags, m, n, p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664}
665#endif
666
667#ifdef CONFIG_FB_MATROX_MYSTIQUE
Jean Delvare316b4d62009-09-22 16:47:49 -0700668static int MGA1064_preinit(struct matrox_fb_info *minfo)
669{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 static const int vxres_mystique[] = { 512, 640, 768, 800, 832, 960,
671 1024, 1152, 1280, 1600, 1664, 1920,
672 2048, 0};
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700673 struct matrox_hw_state *hw = &minfo->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674
Harvey Harrison5ae12172008-04-28 02:15:47 -0700675 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700677 /* minfo->capable.cfb4 = 0; ... preinitialized by 0 */
678 minfo->capable.text = 1;
679 minfo->capable.vxres = vxres_mystique;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700681 minfo->outputs[0].output = &m1064;
682 minfo->outputs[0].src = minfo->outputs[0].default_src;
683 minfo->outputs[0].data = minfo;
684 minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700686 if (minfo->devflags.noinit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 return 0; /* do not modify settings */
688 hw->MXoptionReg &= 0xC0000100;
689 hw->MXoptionReg |= 0x00094E20;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700690 if (minfo->devflags.novga)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 hw->MXoptionReg &= ~0x00000100;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700692 if (minfo->devflags.nobios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 hw->MXoptionReg &= ~0x40000000;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700694 if (minfo->devflags.nopciretry)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 hw->MXoptionReg |= 0x20000000;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700696 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 mga_setr(M_SEQ_INDEX, 0x01, 0x20);
698 mga_outl(M_CTLWTST, 0x00000000);
699 udelay(200);
700 mga_outl(M_MACCESS, 0x00008000);
701 udelay(100);
702 mga_outl(M_MACCESS, 0x0000C000);
703 return 0;
704}
705
Jean Delvare316b4d62009-09-22 16:47:49 -0700706static void MGA1064_reset(struct matrox_fb_info *minfo)
707{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
Harvey Harrison5ae12172008-04-28 02:15:47 -0700709 DBG(__func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710
Jean Delvare316b4d62009-09-22 16:47:49 -0700711 MGA1064_ramdac_init(minfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712}
713#endif
714
715#ifdef CONFIG_FB_MATROX_G
Jean Delvare316b4d62009-09-22 16:47:49 -0700716static void g450_mclk_init(struct matrox_fb_info *minfo)
717{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 /* switch all clocks to PCI source */
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700719 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg | 4);
720 pci_write_config_dword(minfo->pcidev, PCI_OPTION3_REG, minfo->values.reg.opt3 & ~0x00300C03);
721 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
722
723 if (((minfo->values.reg.opt3 & 0x000003) == 0x000003) ||
724 ((minfo->values.reg.opt3 & 0x000C00) == 0x000C00) ||
725 ((minfo->values.reg.opt3 & 0x300000) == 0x300000)) {
Jean Delvare316b4d62009-09-22 16:47:49 -0700726 matroxfb_g450_setclk(minfo, minfo->values.pll.video, M_VIDEO_PLL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 } else {
728 unsigned long flags;
729 unsigned int pwr;
730
731 matroxfb_DAC_lock_irqsave(flags);
Jean Delvare316b4d62009-09-22 16:47:49 -0700732 pwr = inDAC1064(minfo, M1064_XPWRCTRL) & ~0x02;
733 outDAC1064(minfo, M1064_XPWRCTRL, pwr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734 matroxfb_DAC_unlock_irqrestore(flags);
735 }
Jean Delvare316b4d62009-09-22 16:47:49 -0700736 matroxfb_g450_setclk(minfo, minfo->values.pll.system, M_SYSTEM_PLL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737
738 /* switch clocks to their real PLL source(s) */
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700739 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg | 4);
740 pci_write_config_dword(minfo->pcidev, PCI_OPTION3_REG, minfo->values.reg.opt3);
741 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742
743}
744
Jean Delvare316b4d62009-09-22 16:47:49 -0700745static void g450_memory_init(struct matrox_fb_info *minfo)
746{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 /* disable memory refresh */
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700748 minfo->hw.MXoptionReg &= ~0x001F8000;
749 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750
751 /* set memory interface parameters */
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700752 minfo->hw.MXoptionReg &= ~0x00207E00;
753 minfo->hw.MXoptionReg |= 0x00207E00 & minfo->values.reg.opt;
754 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
755 pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, minfo->values.reg.opt2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700757 mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758
759 /* first set up memory interface with disabled memory interface clocks */
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700760 pci_write_config_dword(minfo->pcidev, PCI_MEMMISC_REG, minfo->values.reg.memmisc & ~0x80000000U);
761 mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
762 mga_outl(M_MACCESS, minfo->values.reg.maccess);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 /* start memory clocks */
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700764 pci_write_config_dword(minfo->pcidev, PCI_MEMMISC_REG, minfo->values.reg.memmisc | 0x80000000U);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765
766 udelay(200);
767
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700768 if (minfo->values.memory.ddr && (!minfo->values.memory.emrswen || !minfo->values.memory.dll)) {
769 mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk & ~0x1000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700771 mga_outl(M_MACCESS, minfo->values.reg.maccess | 0x8000);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772
773 udelay(200);
774
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700775 minfo->hw.MXoptionReg |= 0x001F8000 & minfo->values.reg.opt;
776 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777
778 /* value is written to memory chips only if old != new */
779 mga_outl(M_PLNWT, 0);
780 mga_outl(M_PLNWT, ~0);
781
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700782 if (minfo->values.reg.mctlwtst != minfo->values.reg.mctlwtst_core) {
783 mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst_core);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 }
785
786}
787
Jean Delvare316b4d62009-09-22 16:47:49 -0700788static void g450_preinit(struct matrox_fb_info *minfo)
789{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 u_int32_t c2ctl;
791 u_int8_t curctl;
792 u_int8_t c1ctl;
793
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700794 /* minfo->hw.MXoptionReg = minfo->values.reg.opt; */
795 minfo->hw.MXoptionReg &= 0xC0000100;
796 minfo->hw.MXoptionReg |= 0x00000020;
797 if (minfo->devflags.novga)
798 minfo->hw.MXoptionReg &= ~0x00000100;
799 if (minfo->devflags.nobios)
800 minfo->hw.MXoptionReg &= ~0x40000000;
801 if (minfo->devflags.nopciretry)
802 minfo->hw.MXoptionReg |= 0x20000000;
803 minfo->hw.MXoptionReg |= minfo->values.reg.opt & 0x03400040;
804 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805
806 /* Init system clocks */
807
808 /* stop crtc2 */
809 c2ctl = mga_inl(M_C2CTL);
810 mga_outl(M_C2CTL, c2ctl & ~1);
811 /* stop cursor */
Jean Delvare316b4d62009-09-22 16:47:49 -0700812 curctl = inDAC1064(minfo, M1064_XCURCTRL);
813 outDAC1064(minfo, M1064_XCURCTRL, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 /* stop crtc1 */
815 c1ctl = mga_readr(M_SEQ_INDEX, 1);
816 mga_setr(M_SEQ_INDEX, 1, c1ctl | 0x20);
817
Jean Delvare316b4d62009-09-22 16:47:49 -0700818 g450_mclk_init(minfo);
819 g450_memory_init(minfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820
821 /* set legacy VGA clock sources for DOSEmu or VMware... */
Jean Delvare316b4d62009-09-22 16:47:49 -0700822 matroxfb_g450_setclk(minfo, 25175, M_PIXEL_PLL_A);
823 matroxfb_g450_setclk(minfo, 28322, M_PIXEL_PLL_B);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824
825 /* restore crtc1 */
826 mga_setr(M_SEQ_INDEX, 1, c1ctl);
827
828 /* restore cursor */
Jean Delvare316b4d62009-09-22 16:47:49 -0700829 outDAC1064(minfo, M1064_XCURCTRL, curctl);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830
831 /* restore crtc2 */
832 mga_outl(M_C2CTL, c2ctl);
833
834 return;
835}
836
Jean Delvare316b4d62009-09-22 16:47:49 -0700837static int MGAG100_preinit(struct matrox_fb_info *minfo)
838{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 static const int vxres_g100[] = { 512, 640, 768, 800, 832, 960,
840 1024, 1152, 1280, 1600, 1664, 1920,
841 2048, 0};
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700842 struct matrox_hw_state *hw = &minfo->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843
844 u_int32_t reg50;
845#if 0
846 u_int32_t q;
847#endif
848
Harvey Harrison5ae12172008-04-28 02:15:47 -0700849 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850
851 /* there are some instabilities if in_div > 19 && vco < 61000 */
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700852 if (minfo->devflags.g450dac) {
853 minfo->features.pll.vco_freq_min = 130000; /* my sample: >118 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700854 } else {
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700855 minfo->features.pll.vco_freq_min = 62000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700857 if (!minfo->features.pll.ref_freq) {
858 minfo->features.pll.ref_freq = 27000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700860 minfo->features.pll.feed_div_min = 7;
861 minfo->features.pll.feed_div_max = 127;
862 minfo->features.pll.in_div_min = 1;
863 minfo->features.pll.in_div_max = 31;
864 minfo->features.pll.post_shift_max = 3;
865 minfo->features.DAC1064.xvrefctrl = DAC1064_XVREFCTRL_G100_DEFAULT;
866 /* minfo->capable.cfb4 = 0; ... preinitialized by 0 */
867 minfo->capable.text = 1;
868 minfo->capable.vxres = vxres_g100;
869 minfo->capable.plnwt = minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG100
870 ? minfo->devflags.sgram : 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871
872#ifdef CONFIG_FB_MATROX_G
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700873 if (minfo->devflags.g450dac) {
874 minfo->outputs[0].output = &g450out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 } else
876#endif
877 {
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700878 minfo->outputs[0].output = &m1064;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700880 minfo->outputs[0].src = minfo->outputs[0].default_src;
881 minfo->outputs[0].data = minfo;
882 minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700884 if (minfo->devflags.g450dac) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 /* we must do this always, BIOS does not do it for us
886 and accelerator dies without it */
887 mga_outl(0x1C0C, 0);
888 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700889 if (minfo->devflags.noinit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 return 0;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700891 if (minfo->devflags.g450dac) {
Jean Delvare316b4d62009-09-22 16:47:49 -0700892 g450_preinit(minfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 return 0;
894 }
895 hw->MXoptionReg &= 0xC0000100;
896 hw->MXoptionReg |= 0x00000020;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700897 if (minfo->devflags.novga)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 hw->MXoptionReg &= ~0x00000100;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700899 if (minfo->devflags.nobios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 hw->MXoptionReg &= ~0x40000000;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700901 if (minfo->devflags.nopciretry)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 hw->MXoptionReg |= 0x20000000;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700903 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
Jean Delvare316b4d62009-09-22 16:47:49 -0700904 DAC1064_setmclk(minfo, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PCI, 133333);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700906 if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG100) {
907 pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 reg50 &= ~0x3000;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700909 pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910
911 hw->MXoptionReg |= 0x1080;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700912 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
913 mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 udelay(100);
915 mga_outb(0x1C05, 0x00);
916 mga_outb(0x1C05, 0x80);
917 udelay(100);
918 mga_outb(0x1C05, 0x40);
919 mga_outb(0x1C05, 0xC0);
920 udelay(100);
921 reg50 &= ~0xFF;
922 reg50 |= 0x07;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700923 pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 /* it should help with G100 */
925 mga_outb(M_GRAPHICS_INDEX, 6);
926 mga_outb(M_GRAPHICS_DATA, (mga_inb(M_GRAPHICS_DATA) & 3) | 4);
927 mga_setr(M_EXTVGA_INDEX, 0x03, 0x81);
928 mga_setr(M_EXTVGA_INDEX, 0x04, 0x00);
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700929 mga_writeb(minfo->video.vbase, 0x0000, 0xAA);
930 mga_writeb(minfo->video.vbase, 0x0800, 0x55);
931 mga_writeb(minfo->video.vbase, 0x4000, 0x55);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932#if 0
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700933 if (mga_readb(minfo->video.vbase, 0x0000) != 0xAA) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 hw->MXoptionReg &= ~0x1000;
935 }
936#endif
937 hw->MXoptionReg |= 0x00078020;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700938 } else if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG200) {
939 pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 reg50 &= ~0x3000;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700941 pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700943 if (minfo->devflags.memtype == -1)
944 hw->MXoptionReg |= minfo->values.reg.opt & 0x1C00;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 else
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700946 hw->MXoptionReg |= (minfo->devflags.memtype & 7) << 10;
947 if (minfo->devflags.sgram)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 hw->MXoptionReg |= 0x4000;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700949 mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
950 mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 udelay(200);
952 mga_outl(M_MACCESS, 0x00000000);
953 mga_outl(M_MACCESS, 0x00008000);
954 udelay(100);
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700955 mga_outw(M_MEMRDBK, minfo->values.reg.memrdbk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 hw->MXoptionReg |= 0x00078020;
957 } else {
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700958 pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 reg50 &= ~0x00000100;
960 reg50 |= 0x00000000;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700961 pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700963 if (minfo->devflags.memtype == -1)
964 hw->MXoptionReg |= minfo->values.reg.opt & 0x1C00;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 else
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700966 hw->MXoptionReg |= (minfo->devflags.memtype & 7) << 10;
967 if (minfo->devflags.sgram)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 hw->MXoptionReg |= 0x4000;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700969 mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
970 mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 udelay(200);
972 mga_outl(M_MACCESS, 0x00000000);
973 mga_outl(M_MACCESS, 0x00008000);
974 udelay(100);
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700975 mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 hw->MXoptionReg |= 0x00040020;
977 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700978 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 return 0;
980}
981
Jean Delvare316b4d62009-09-22 16:47:49 -0700982static void MGAG100_reset(struct matrox_fb_info *minfo)
983{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 u_int8_t b;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700985 struct matrox_hw_state *hw = &minfo->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986
Harvey Harrison5ae12172008-04-28 02:15:47 -0700987 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988
989 {
990#ifdef G100_BROKEN_IBM_82351
991 u_int32_t d;
992
993 find 1014/22 (IBM/82351); /* if found and bridging Matrox, do some strange stuff */
994 pci_read_config_byte(ibm, PCI_SECONDARY_BUS, &b);
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700995 if (b == minfo->pcidev->bus->number) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 pci_write_config_byte(ibm, PCI_COMMAND+1, 0); /* disable back-to-back & SERR */
997 pci_write_config_byte(ibm, 0x41, 0xF4); /* ??? */
998 pci_write_config_byte(ibm, PCI_IO_BASE, 0xF0); /* ??? */
999 pci_write_config_byte(ibm, PCI_IO_LIMIT, 0x00); /* ??? */
1000 }
1001#endif
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001002 if (!minfo->devflags.noinit) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 if (x7AF4 & 8) {
1004 hw->MXoptionReg |= 0x40; /* FIXME... */
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001005 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 }
Ville Syrjäläf73195a2005-11-07 01:01:00 -08001007 mga_setr(M_EXTVGA_INDEX, 0x06, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 }
1009 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001010 if (minfo->devflags.g450dac) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 /* either leave MCLK as is... or they were set in preinit */
Jean Delvare316b4d62009-09-22 16:47:49 -07001012 hw->DACclk[3] = inDAC1064(minfo, DAC1064_XSYSPLLM);
1013 hw->DACclk[4] = inDAC1064(minfo, DAC1064_XSYSPLLN);
1014 hw->DACclk[5] = inDAC1064(minfo, DAC1064_XSYSPLLP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 } else {
Jean Delvare316b4d62009-09-22 16:47:49 -07001016 DAC1064_setmclk(minfo, DAC1064_OPT_RESERVED | DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV1 | DAC1064_OPT_SCLK_PLL, 133333);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001018 if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400) {
1019 if (minfo->devflags.dfp_type == -1) {
Jean Delvare316b4d62009-09-22 16:47:49 -07001020 minfo->devflags.dfp_type = inDAC1064(minfo, 0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 }
1022 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001023 if (minfo->devflags.noinit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 return;
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001025 if (minfo->devflags.g450dac) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 } else {
Jean Delvare316b4d62009-09-22 16:47:49 -07001027 MGAG100_setPixClock(minfo, 4, 25175);
1028 MGAG100_setPixClock(minfo, 5, 28322);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 if (x7AF4 & 0x10) {
Jean Delvare316b4d62009-09-22 16:47:49 -07001030 b = inDAC1064(minfo, M1064_XGENIODATA) & ~1;
1031 outDAC1064(minfo, M1064_XGENIODATA, b);
1032 b = inDAC1064(minfo, M1064_XGENIOCTRL) | 1;
1033 outDAC1064(minfo, M1064_XGENIOCTRL, b);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 }
1035 }
1036}
1037#endif
1038
1039#ifdef CONFIG_FB_MATROX_MYSTIQUE
Jean Delvare316b4d62009-09-22 16:47:49 -07001040static void MGA1064_restore(struct matrox_fb_info *minfo)
1041{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 int i;
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001043 struct matrox_hw_state *hw = &minfo->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044
1045 CRITFLAGS
1046
Harvey Harrison5ae12172008-04-28 02:15:47 -07001047 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048
1049 CRITBEGIN
1050
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001051 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 mga_outb(M_IEN, 0x00);
1053 mga_outb(M_CACHEFLUSH, 0x00);
1054
1055 CRITEND
1056
Jean Delvare316b4d62009-09-22 16:47:49 -07001057 DAC1064_restore_1(minfo);
1058 matroxfb_vgaHWrestore(minfo);
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001059 minfo->crtc1.panpos = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 for (i = 0; i < 6; i++)
1061 mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
Jean Delvare316b4d62009-09-22 16:47:49 -07001062 DAC1064_restore_2(minfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063}
1064#endif
1065
1066#ifdef CONFIG_FB_MATROX_G
Jean Delvare316b4d62009-09-22 16:47:49 -07001067static void MGAG100_restore(struct matrox_fb_info *minfo)
1068{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 int i;
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001070 struct matrox_hw_state *hw = &minfo->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071
1072 CRITFLAGS
1073
Harvey Harrison5ae12172008-04-28 02:15:47 -07001074 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075
1076 CRITBEGIN
1077
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001078 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 CRITEND
1080
Jean Delvare316b4d62009-09-22 16:47:49 -07001081 DAC1064_restore_1(minfo);
1082 matroxfb_vgaHWrestore(minfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083#ifdef CONFIG_FB_MATROX_32MB
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001084 if (minfo->devflags.support32MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 mga_setr(M_EXTVGA_INDEX, 8, hw->CRTCEXT[8]);
1086#endif
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001087 minfo->crtc1.panpos = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 for (i = 0; i < 6; i++)
1089 mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
Jean Delvare316b4d62009-09-22 16:47:49 -07001090 DAC1064_restore_2(minfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091}
1092#endif
1093
1094#ifdef CONFIG_FB_MATROX_MYSTIQUE
1095struct matrox_switch matrox_mystique = {
1096 MGA1064_preinit, MGA1064_reset, MGA1064_init, MGA1064_restore,
1097};
1098EXPORT_SYMBOL(matrox_mystique);
1099#endif
1100
1101#ifdef CONFIG_FB_MATROX_G
1102struct matrox_switch matrox_G100 = {
1103 MGAG100_preinit, MGAG100_reset, MGAG100_init, MGAG100_restore,
1104};
1105EXPORT_SYMBOL(matrox_G100);
1106#endif
1107
1108#ifdef NEED_DAC1064
1109EXPORT_SYMBOL(DAC1064_global_init);
1110EXPORT_SYMBOL(DAC1064_global_restore);
1111#endif
1112MODULE_LICENSE("GPL");