blob: a01147fdf270f5e15416d163a614f1f3db810051 [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);
Joe Perchescf6ac4ce2013-10-08 16:23:24 -0700497 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498
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);
Joe Perchescf6ac4ce2013-10-08 16:23:24 -0700642 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 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
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700872 if (minfo->devflags.g450dac) {
873 minfo->outputs[0].output = &g450out;
Christian Dietrich09b599d2010-10-27 15:33:23 -0700874 } else {
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700875 minfo->outputs[0].output = &m1064;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700877 minfo->outputs[0].src = minfo->outputs[0].default_src;
878 minfo->outputs[0].data = minfo;
879 minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700881 if (minfo->devflags.g450dac) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 /* we must do this always, BIOS does not do it for us
883 and accelerator dies without it */
884 mga_outl(0x1C0C, 0);
885 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700886 if (minfo->devflags.noinit)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 return 0;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700888 if (minfo->devflags.g450dac) {
Jean Delvare316b4d62009-09-22 16:47:49 -0700889 g450_preinit(minfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 return 0;
891 }
892 hw->MXoptionReg &= 0xC0000100;
893 hw->MXoptionReg |= 0x00000020;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700894 if (minfo->devflags.novga)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 hw->MXoptionReg &= ~0x00000100;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700896 if (minfo->devflags.nobios)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 hw->MXoptionReg &= ~0x40000000;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700898 if (minfo->devflags.nopciretry)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 hw->MXoptionReg |= 0x20000000;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700900 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
Jean Delvare316b4d62009-09-22 16:47:49 -0700901 DAC1064_setmclk(minfo, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PCI, 133333);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700903 if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG100) {
904 pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 reg50 &= ~0x3000;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700906 pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907
908 hw->MXoptionReg |= 0x1080;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700909 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
910 mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 udelay(100);
912 mga_outb(0x1C05, 0x00);
913 mga_outb(0x1C05, 0x80);
914 udelay(100);
915 mga_outb(0x1C05, 0x40);
916 mga_outb(0x1C05, 0xC0);
917 udelay(100);
918 reg50 &= ~0xFF;
919 reg50 |= 0x07;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700920 pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 /* it should help with G100 */
922 mga_outb(M_GRAPHICS_INDEX, 6);
923 mga_outb(M_GRAPHICS_DATA, (mga_inb(M_GRAPHICS_DATA) & 3) | 4);
924 mga_setr(M_EXTVGA_INDEX, 0x03, 0x81);
925 mga_setr(M_EXTVGA_INDEX, 0x04, 0x00);
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700926 mga_writeb(minfo->video.vbase, 0x0000, 0xAA);
927 mga_writeb(minfo->video.vbase, 0x0800, 0x55);
928 mga_writeb(minfo->video.vbase, 0x4000, 0x55);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929#if 0
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700930 if (mga_readb(minfo->video.vbase, 0x0000) != 0xAA) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 hw->MXoptionReg &= ~0x1000;
932 }
933#endif
934 hw->MXoptionReg |= 0x00078020;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700935 } else if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG200) {
936 pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 reg50 &= ~0x3000;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700938 pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700940 if (minfo->devflags.memtype == -1)
941 hw->MXoptionReg |= minfo->values.reg.opt & 0x1C00;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 else
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700943 hw->MXoptionReg |= (minfo->devflags.memtype & 7) << 10;
944 if (minfo->devflags.sgram)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 hw->MXoptionReg |= 0x4000;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700946 mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
947 mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 udelay(200);
949 mga_outl(M_MACCESS, 0x00000000);
950 mga_outl(M_MACCESS, 0x00008000);
951 udelay(100);
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700952 mga_outw(M_MEMRDBK, minfo->values.reg.memrdbk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 hw->MXoptionReg |= 0x00078020;
954 } else {
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700955 pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 reg50 &= ~0x00000100;
957 reg50 |= 0x00000000;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700958 pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700960 if (minfo->devflags.memtype == -1)
961 hw->MXoptionReg |= minfo->values.reg.opt & 0x1C00;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 else
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700963 hw->MXoptionReg |= (minfo->devflags.memtype & 7) << 10;
964 if (minfo->devflags.sgram)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 hw->MXoptionReg |= 0x4000;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700966 mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
967 mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 udelay(200);
969 mga_outl(M_MACCESS, 0x00000000);
970 mga_outl(M_MACCESS, 0x00008000);
971 udelay(100);
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700972 mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 hw->MXoptionReg |= 0x00040020;
974 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700975 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 return 0;
977}
978
Jean Delvare316b4d62009-09-22 16:47:49 -0700979static void MGAG100_reset(struct matrox_fb_info *minfo)
980{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 u_int8_t b;
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700982 struct matrox_hw_state *hw = &minfo->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983
Harvey Harrison5ae12172008-04-28 02:15:47 -0700984 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985
986 {
987#ifdef G100_BROKEN_IBM_82351
988 u_int32_t d;
989
990 find 1014/22 (IBM/82351); /* if found and bridging Matrox, do some strange stuff */
991 pci_read_config_byte(ibm, PCI_SECONDARY_BUS, &b);
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700992 if (b == minfo->pcidev->bus->number) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 pci_write_config_byte(ibm, PCI_COMMAND+1, 0); /* disable back-to-back & SERR */
994 pci_write_config_byte(ibm, 0x41, 0xF4); /* ??? */
995 pci_write_config_byte(ibm, PCI_IO_BASE, 0xF0); /* ??? */
996 pci_write_config_byte(ibm, PCI_IO_LIMIT, 0x00); /* ??? */
997 }
998#endif
Jean Delvarefc2d10d2009-09-22 16:47:48 -0700999 if (!minfo->devflags.noinit) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 if (x7AF4 & 8) {
1001 hw->MXoptionReg |= 0x40; /* FIXME... */
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001002 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 }
Ville Syrjäläf73195a2005-11-07 01:01:00 -08001004 mga_setr(M_EXTVGA_INDEX, 0x06, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 }
1006 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001007 if (minfo->devflags.g450dac) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 /* either leave MCLK as is... or they were set in preinit */
Jean Delvare316b4d62009-09-22 16:47:49 -07001009 hw->DACclk[3] = inDAC1064(minfo, DAC1064_XSYSPLLM);
1010 hw->DACclk[4] = inDAC1064(minfo, DAC1064_XSYSPLLN);
1011 hw->DACclk[5] = inDAC1064(minfo, DAC1064_XSYSPLLP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 } else {
Jean Delvare316b4d62009-09-22 16:47:49 -07001013 DAC1064_setmclk(minfo, DAC1064_OPT_RESERVED | DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV1 | DAC1064_OPT_SCLK_PLL, 133333);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001015 if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400) {
1016 if (minfo->devflags.dfp_type == -1) {
Jean Delvare316b4d62009-09-22 16:47:49 -07001017 minfo->devflags.dfp_type = inDAC1064(minfo, 0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 }
1019 }
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001020 if (minfo->devflags.noinit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 return;
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001022 if (minfo->devflags.g450dac) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 } else {
Jean Delvare316b4d62009-09-22 16:47:49 -07001024 MGAG100_setPixClock(minfo, 4, 25175);
1025 MGAG100_setPixClock(minfo, 5, 28322);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 if (x7AF4 & 0x10) {
Jean Delvare316b4d62009-09-22 16:47:49 -07001027 b = inDAC1064(minfo, M1064_XGENIODATA) & ~1;
1028 outDAC1064(minfo, M1064_XGENIODATA, b);
1029 b = inDAC1064(minfo, M1064_XGENIOCTRL) | 1;
1030 outDAC1064(minfo, M1064_XGENIOCTRL, b);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 }
1032 }
1033}
1034#endif
1035
1036#ifdef CONFIG_FB_MATROX_MYSTIQUE
Jean Delvare316b4d62009-09-22 16:47:49 -07001037static void MGA1064_restore(struct matrox_fb_info *minfo)
1038{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 int i;
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001040 struct matrox_hw_state *hw = &minfo->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041
1042 CRITFLAGS
1043
Harvey Harrison5ae12172008-04-28 02:15:47 -07001044 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045
1046 CRITBEGIN
1047
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001048 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 mga_outb(M_IEN, 0x00);
1050 mga_outb(M_CACHEFLUSH, 0x00);
1051
1052 CRITEND
1053
Jean Delvare316b4d62009-09-22 16:47:49 -07001054 DAC1064_restore_1(minfo);
1055 matroxfb_vgaHWrestore(minfo);
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001056 minfo->crtc1.panpos = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 for (i = 0; i < 6; i++)
1058 mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
Jean Delvare316b4d62009-09-22 16:47:49 -07001059 DAC1064_restore_2(minfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060}
1061#endif
1062
1063#ifdef CONFIG_FB_MATROX_G
Jean Delvare316b4d62009-09-22 16:47:49 -07001064static void MGAG100_restore(struct matrox_fb_info *minfo)
1065{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 int i;
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001067 struct matrox_hw_state *hw = &minfo->hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068
1069 CRITFLAGS
1070
Harvey Harrison5ae12172008-04-28 02:15:47 -07001071 DBG(__func__)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072
1073 CRITBEGIN
1074
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001075 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 CRITEND
1077
Jean Delvare316b4d62009-09-22 16:47:49 -07001078 DAC1064_restore_1(minfo);
1079 matroxfb_vgaHWrestore(minfo);
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001080 if (minfo->devflags.support32MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 mga_setr(M_EXTVGA_INDEX, 8, hw->CRTCEXT[8]);
Jean Delvarefc2d10d2009-09-22 16:47:48 -07001082 minfo->crtc1.panpos = -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 for (i = 0; i < 6; i++)
1084 mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
Jean Delvare316b4d62009-09-22 16:47:49 -07001085 DAC1064_restore_2(minfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086}
1087#endif
1088
1089#ifdef CONFIG_FB_MATROX_MYSTIQUE
1090struct matrox_switch matrox_mystique = {
1091 MGA1064_preinit, MGA1064_reset, MGA1064_init, MGA1064_restore,
1092};
1093EXPORT_SYMBOL(matrox_mystique);
1094#endif
1095
1096#ifdef CONFIG_FB_MATROX_G
1097struct matrox_switch matrox_G100 = {
1098 MGAG100_preinit, MGAG100_reset, MGAG100_init, MGAG100_restore,
1099};
1100EXPORT_SYMBOL(matrox_G100);
1101#endif
1102
1103#ifdef NEED_DAC1064
1104EXPORT_SYMBOL(DAC1064_global_init);
1105EXPORT_SYMBOL(DAC1064_global_restore);
1106#endif
1107MODULE_LICENSE("GPL");