aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/fbdev/matrox
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/fbdev/matrox')
-rw-r--r--drivers/video/fbdev/matrox/Makefile11
-rw-r--r--drivers/video/fbdev/matrox/g450_pll.c539
-rw-r--r--drivers/video/fbdev/matrox/g450_pll.h12
-rw-r--r--drivers/video/fbdev/matrox/i2c-matroxfb.c238
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_DAC1064.c1107
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_DAC1064.h179
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_Ti3026.c745
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_Ti3026.h11
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_accel.c519
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_accel.h8
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_base.c2584
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_base.h735
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_crtc2.c739
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_crtc2.h34
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_g450.c640
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_g450.h14
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_maven.c1301
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_maven.h20
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_misc.c815
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_misc.h21
20 files changed, 10272 insertions, 0 deletions
diff --git a/drivers/video/fbdev/matrox/Makefile b/drivers/video/fbdev/matrox/Makefile
new file mode 100644
index 000000000000..f9c00ebe2530
--- /dev/null
+++ b/drivers/video/fbdev/matrox/Makefile
@@ -0,0 +1,11 @@
1# Makefile for the Linux video drivers.
2# 5 Aug 1999, James Simmons, <mailto:jsimmons@edgeglobal.com>
3# Rewritten to use lists instead of if-statements.
4
5# Each configuration option enables a list of files.
6
7my-obj-$(CONFIG_FB_MATROX_G) += g450_pll.o matroxfb_g450.o matroxfb_crtc2.o
8
9obj-$(CONFIG_FB_MATROX) += matroxfb_base.o matroxfb_accel.o matroxfb_DAC1064.o matroxfb_Ti3026.o matroxfb_misc.o $(my-obj-y)
10obj-$(CONFIG_FB_MATROX_I2C) += i2c-matroxfb.o
11obj-$(CONFIG_FB_MATROX_MAVEN) += matroxfb_maven.o matroxfb_crtc2.o
diff --git a/drivers/video/fbdev/matrox/g450_pll.c b/drivers/video/fbdev/matrox/g450_pll.c
new file mode 100644
index 000000000000..c15f8a57498e
--- /dev/null
+++ b/drivers/video/fbdev/matrox/g450_pll.c
@@ -0,0 +1,539 @@
1/*
2 *
3 * Hardware accelerated Matrox PCI cards - G450/G550 PLL control.
4 *
5 * (c) 2001-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
6 *
7 * Portions Copyright (c) 2001 Matrox Graphics Inc.
8 *
9 * Version: 1.64 2002/06/10
10 *
11 * This file is subject to the terms and conditions of the GNU General Public
12 * License. See the file COPYING in the main directory of this archive for
13 * more details.
14 *
15 */
16
17#include "g450_pll.h"
18#include "matroxfb_DAC1064.h"
19
20static inline unsigned int g450_vco2f(unsigned char p, unsigned int fvco) {
21 return (p & 0x40) ? fvco : fvco >> ((p & 3) + 1);
22}
23
24static inline unsigned int g450_f2vco(unsigned char p, unsigned int fin) {
25 return (p & 0x40) ? fin : fin << ((p & 3) + 1);
26}
27
28static unsigned int g450_mnp2vco(const struct matrox_fb_info *minfo,
29 unsigned int mnp)
30{
31 unsigned int m, n;
32
33 m = ((mnp >> 16) & 0x0FF) + 1;
34 n = ((mnp >> 7) & 0x1FE) + 4;
35 return (minfo->features.pll.ref_freq * n + (m >> 1)) / m;
36}
37
38unsigned int g450_mnp2f(const struct matrox_fb_info *minfo, unsigned int mnp)
39{
40 return g450_vco2f(mnp, g450_mnp2vco(minfo, mnp));
41}
42
43static inline unsigned int pll_freq_delta(unsigned int f1, unsigned int f2) {
44 if (f2 < f1) {
45 f2 = f1 - f2;
46 } else {
47 f2 = f2 - f1;
48 }
49 return f2;
50}
51
52#define NO_MORE_MNP 0x01FFFFFF
53#define G450_MNP_FREQBITS (0xFFFFFF43) /* do not mask high byte so we'll catch NO_MORE_MNP */
54
55static unsigned int g450_nextpll(const struct matrox_fb_info *minfo,
56 const struct matrox_pll_limits *pi,
57 unsigned int *fvco, unsigned int mnp)
58{
59 unsigned int m, n, p;
60 unsigned int tvco = *fvco;
61
62 m = (mnp >> 16) & 0xFF;
63 p = mnp & 0xFF;
64
65 do {
66 if (m == 0 || m == 0xFF) {
67 if (m == 0) {
68 if (p & 0x40) {
69 return NO_MORE_MNP;
70 }
71 if (p & 3) {
72 p--;
73 } else {
74 p = 0x40;
75 }
76 tvco >>= 1;
77 if (tvco < pi->vcomin) {
78 return NO_MORE_MNP;
79 }
80 *fvco = tvco;
81 }
82
83 p &= 0x43;
84 if (tvco < 550000) {
85/* p |= 0x00; */
86 } else if (tvco < 700000) {
87 p |= 0x08;
88 } else if (tvco < 1000000) {
89 p |= 0x10;
90 } else if (tvco < 1150000) {
91 p |= 0x18;
92 } else {
93 p |= 0x20;
94 }
95 m = 9;
96 } else {
97 m--;
98 }
99 n = ((tvco * (m+1) + minfo->features.pll.ref_freq) / (minfo->features.pll.ref_freq * 2)) - 2;
100 } while (n < 0x03 || n > 0x7A);
101 return (m << 16) | (n << 8) | p;
102}
103
104static unsigned int g450_firstpll(const struct matrox_fb_info *minfo,
105 const struct matrox_pll_limits *pi,
106 unsigned int *vco, unsigned int fout)
107{
108 unsigned int p;
109 unsigned int vcomax;
110
111 vcomax = pi->vcomax;
112 if (fout > (vcomax / 2)) {
113 if (fout > vcomax) {
114 *vco = vcomax;
115 } else {
116 *vco = fout;
117 }
118 p = 0x40;
119 } else {
120 unsigned int tvco;
121
122 p = 3;
123 tvco = g450_f2vco(p, fout);
124 while (p && (tvco > vcomax)) {
125 p--;
126 tvco >>= 1;
127 }
128 if (tvco < pi->vcomin) {
129 tvco = pi->vcomin;
130 }
131 *vco = tvco;
132 }
133 return g450_nextpll(minfo, pi, vco, 0xFF0000 | p);
134}
135
136static inline unsigned int g450_setpll(const struct matrox_fb_info *minfo,
137 unsigned int mnp, unsigned int pll)
138{
139 switch (pll) {
140 case M_PIXEL_PLL_A:
141 matroxfb_DAC_out(minfo, M1064_XPIXPLLAM, mnp >> 16);
142 matroxfb_DAC_out(minfo, M1064_XPIXPLLAN, mnp >> 8);
143 matroxfb_DAC_out(minfo, M1064_XPIXPLLAP, mnp);
144 return M1064_XPIXPLLSTAT;
145
146 case M_PIXEL_PLL_B:
147 matroxfb_DAC_out(minfo, M1064_XPIXPLLBM, mnp >> 16);
148 matroxfb_DAC_out(minfo, M1064_XPIXPLLBN, mnp >> 8);
149 matroxfb_DAC_out(minfo, M1064_XPIXPLLBP, mnp);
150 return M1064_XPIXPLLSTAT;
151
152 case M_PIXEL_PLL_C:
153 matroxfb_DAC_out(minfo, M1064_XPIXPLLCM, mnp >> 16);
154 matroxfb_DAC_out(minfo, M1064_XPIXPLLCN, mnp >> 8);
155 matroxfb_DAC_out(minfo, M1064_XPIXPLLCP, mnp);
156 return M1064_XPIXPLLSTAT;
157
158 case M_SYSTEM_PLL:
159 matroxfb_DAC_out(minfo, DAC1064_XSYSPLLM, mnp >> 16);
160 matroxfb_DAC_out(minfo, DAC1064_XSYSPLLN, mnp >> 8);
161 matroxfb_DAC_out(minfo, DAC1064_XSYSPLLP, mnp);
162 return DAC1064_XSYSPLLSTAT;
163
164 case M_VIDEO_PLL:
165 matroxfb_DAC_out(minfo, M1064_XVIDPLLM, mnp >> 16);
166 matroxfb_DAC_out(minfo, M1064_XVIDPLLN, mnp >> 8);
167 matroxfb_DAC_out(minfo, M1064_XVIDPLLP, mnp);
168 return M1064_XVIDPLLSTAT;
169 }
170 return 0;
171}
172
173static inline unsigned int g450_cmppll(const struct matrox_fb_info *minfo,
174 unsigned int mnp, unsigned int pll)
175{
176 unsigned char m = mnp >> 16;
177 unsigned char n = mnp >> 8;
178 unsigned char p = mnp;
179
180 switch (pll) {
181 case M_PIXEL_PLL_A:
182 return (matroxfb_DAC_in(minfo, M1064_XPIXPLLAM) != m ||
183 matroxfb_DAC_in(minfo, M1064_XPIXPLLAN) != n ||
184 matroxfb_DAC_in(minfo, M1064_XPIXPLLAP) != p);
185
186 case M_PIXEL_PLL_B:
187 return (matroxfb_DAC_in(minfo, M1064_XPIXPLLBM) != m ||
188 matroxfb_DAC_in(minfo, M1064_XPIXPLLBN) != n ||
189 matroxfb_DAC_in(minfo, M1064_XPIXPLLBP) != p);
190
191 case M_PIXEL_PLL_C:
192 return (matroxfb_DAC_in(minfo, M1064_XPIXPLLCM) != m ||
193 matroxfb_DAC_in(minfo, M1064_XPIXPLLCN) != n ||
194 matroxfb_DAC_in(minfo, M1064_XPIXPLLCP) != p);
195
196 case M_SYSTEM_PLL:
197 return (matroxfb_DAC_in(minfo, DAC1064_XSYSPLLM) != m ||
198 matroxfb_DAC_in(minfo, DAC1064_XSYSPLLN) != n ||
199 matroxfb_DAC_in(minfo, DAC1064_XSYSPLLP) != p);
200
201 case M_VIDEO_PLL:
202 return (matroxfb_DAC_in(minfo, M1064_XVIDPLLM) != m ||
203 matroxfb_DAC_in(minfo, M1064_XVIDPLLN) != n ||
204 matroxfb_DAC_in(minfo, M1064_XVIDPLLP) != p);
205 }
206 return 1;
207}
208
209static inline int g450_isplllocked(const struct matrox_fb_info *minfo,
210 unsigned int regidx)
211{
212 unsigned int j;
213
214 for (j = 0; j < 1000; j++) {
215 if (matroxfb_DAC_in(minfo, regidx) & 0x40) {
216 unsigned int r = 0;
217 int i;
218
219 for (i = 0; i < 100; i++) {
220 r += matroxfb_DAC_in(minfo, regidx) & 0x40;
221 }
222 return r >= (90 * 0x40);
223 }
224 /* udelay(1)... but DAC_in is much slower... */
225 }
226 return 0;
227}
228
229static int g450_testpll(const struct matrox_fb_info *minfo, unsigned int mnp,
230 unsigned int pll)
231{
232 return g450_isplllocked(minfo, g450_setpll(minfo, mnp, pll));
233}
234
235static void updatehwstate_clk(struct matrox_hw_state* hw, unsigned int mnp, unsigned int pll) {
236 switch (pll) {
237 case M_SYSTEM_PLL:
238 hw->DACclk[3] = mnp >> 16;
239 hw->DACclk[4] = mnp >> 8;
240 hw->DACclk[5] = mnp;
241 break;
242 }
243}
244
245void matroxfb_g450_setpll_cond(struct matrox_fb_info *minfo, unsigned int mnp,
246 unsigned int pll)
247{
248 if (g450_cmppll(minfo, mnp, pll)) {
249 g450_setpll(minfo, mnp, pll);
250 }
251}
252
253static inline unsigned int g450_findworkingpll(struct matrox_fb_info *minfo,
254 unsigned int pll,
255 unsigned int *mnparray,
256 unsigned int mnpcount)
257{
258 unsigned int found = 0;
259 unsigned int idx;
260 unsigned int mnpfound = mnparray[0];
261
262 for (idx = 0; idx < mnpcount; idx++) {
263 unsigned int sarray[3];
264 unsigned int *sptr;
265 {
266 unsigned int mnp;
267
268 sptr = sarray;
269 mnp = mnparray[idx];
270 if (mnp & 0x38) {
271 *sptr++ = mnp - 8;
272 }
273 if ((mnp & 0x38) != 0x38) {
274 *sptr++ = mnp + 8;
275 }
276 *sptr = mnp;
277 }
278 while (sptr >= sarray) {
279 unsigned int mnp = *sptr--;
280
281 if (g450_testpll(minfo, mnp - 0x0300, pll) &&
282 g450_testpll(minfo, mnp + 0x0300, pll) &&
283 g450_testpll(minfo, mnp - 0x0200, pll) &&
284 g450_testpll(minfo, mnp + 0x0200, pll) &&
285 g450_testpll(minfo, mnp - 0x0100, pll) &&
286 g450_testpll(minfo, mnp + 0x0100, pll)) {
287 if (g450_testpll(minfo, mnp, pll)) {
288 return mnp;
289 }
290 } else if (!found && g450_testpll(minfo, mnp, pll)) {
291 mnpfound = mnp;
292 found = 1;
293 }
294 }
295 }
296 g450_setpll(minfo, mnpfound, pll);
297 return mnpfound;
298}
299
300static void g450_addcache(struct matrox_pll_cache* ci, unsigned int mnp_key, unsigned int mnp_value) {
301 if (++ci->valid > ARRAY_SIZE(ci->data)) {
302 ci->valid = ARRAY_SIZE(ci->data);
303 }
304 memmove(ci->data + 1, ci->data, (ci->valid - 1) * sizeof(*ci->data));
305 ci->data[0].mnp_key = mnp_key & G450_MNP_FREQBITS;
306 ci->data[0].mnp_value = mnp_value;
307}
308
309static int g450_checkcache(struct matrox_fb_info *minfo,
310 struct matrox_pll_cache *ci, unsigned int mnp_key)
311{
312 unsigned int i;
313
314 mnp_key &= G450_MNP_FREQBITS;
315 for (i = 0; i < ci->valid; i++) {
316 if (ci->data[i].mnp_key == mnp_key) {
317 unsigned int mnp;
318
319 mnp = ci->data[i].mnp_value;
320 if (i) {
321 memmove(ci->data + 1, ci->data, i * sizeof(*ci->data));
322 ci->data[0].mnp_key = mnp_key;
323 ci->data[0].mnp_value = mnp;
324 }
325 return mnp;
326 }
327 }
328 return NO_MORE_MNP;
329}
330
331static int __g450_setclk(struct matrox_fb_info *minfo, unsigned int fout,
332 unsigned int pll, unsigned int *mnparray,
333 unsigned int *deltaarray)
334{
335 unsigned int mnpcount;
336 unsigned int pixel_vco;
337 const struct matrox_pll_limits* pi;
338 struct matrox_pll_cache* ci;
339
340 pixel_vco = 0;
341 switch (pll) {
342 case M_PIXEL_PLL_A:
343 case M_PIXEL_PLL_B:
344 case M_PIXEL_PLL_C:
345 {
346 u_int8_t tmp, xpwrctrl;
347 unsigned long flags;
348
349 matroxfb_DAC_lock_irqsave(flags);
350
351 xpwrctrl = matroxfb_DAC_in(minfo, M1064_XPWRCTRL);
352 matroxfb_DAC_out(minfo, M1064_XPWRCTRL, xpwrctrl & ~M1064_XPWRCTRL_PANELPDN);
353 mga_outb(M_SEQ_INDEX, M_SEQ1);
354 mga_outb(M_SEQ_DATA, mga_inb(M_SEQ_DATA) | M_SEQ1_SCROFF);
355 tmp = matroxfb_DAC_in(minfo, M1064_XPIXCLKCTRL);
356 tmp |= M1064_XPIXCLKCTRL_DIS;
357 if (!(tmp & M1064_XPIXCLKCTRL_PLL_UP)) {
358 tmp |= M1064_XPIXCLKCTRL_PLL_UP;
359 }
360 matroxfb_DAC_out(minfo, M1064_XPIXCLKCTRL, tmp);
361 /* DVI PLL preferred for frequencies up to
362 panel link max, standard PLL otherwise */
363 if (fout >= minfo->max_pixel_clock_panellink)
364 tmp = 0;
365 else tmp =
366 M1064_XDVICLKCTRL_DVIDATAPATHSEL |
367 M1064_XDVICLKCTRL_C1DVICLKSEL |
368 M1064_XDVICLKCTRL_C1DVICLKEN |
369 M1064_XDVICLKCTRL_DVILOOPCTL |
370 M1064_XDVICLKCTRL_P1LOOPBWDTCTL;
371 /* Setting this breaks PC systems so don't do it */
372 /* matroxfb_DAC_out(minfo, M1064_XDVICLKCTRL, tmp); */
373 matroxfb_DAC_out(minfo, M1064_XPWRCTRL,
374 xpwrctrl);
375
376 matroxfb_DAC_unlock_irqrestore(flags);
377 }
378 {
379 u_int8_t misc;
380
381 misc = mga_inb(M_MISC_REG_READ) & ~0x0C;
382 switch (pll) {
383 case M_PIXEL_PLL_A:
384 break;
385 case M_PIXEL_PLL_B:
386 misc |= 0x04;
387 break;
388 default:
389 misc |= 0x0C;
390 break;
391 }
392 mga_outb(M_MISC_REG, misc);
393 }
394 pi = &minfo->limits.pixel;
395 ci = &minfo->cache.pixel;
396 break;
397 case M_SYSTEM_PLL:
398 {
399 u_int32_t opt;
400
401 pci_read_config_dword(minfo->pcidev, PCI_OPTION_REG, &opt);
402 if (!(opt & 0x20)) {
403 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, opt | 0x20);
404 }
405 }
406 pi = &minfo->limits.system;
407 ci = &minfo->cache.system;
408 break;
409 case M_VIDEO_PLL:
410 {
411 u_int8_t tmp;
412 unsigned int mnp;
413 unsigned long flags;
414
415 matroxfb_DAC_lock_irqsave(flags);
416 tmp = matroxfb_DAC_in(minfo, M1064_XPWRCTRL);
417 if (!(tmp & 2)) {
418 matroxfb_DAC_out(minfo, M1064_XPWRCTRL, tmp | 2);
419 }
420
421 mnp = matroxfb_DAC_in(minfo, M1064_XPIXPLLCM) << 16;
422 mnp |= matroxfb_DAC_in(minfo, M1064_XPIXPLLCN) << 8;
423 pixel_vco = g450_mnp2vco(minfo, mnp);
424 matroxfb_DAC_unlock_irqrestore(flags);
425 }
426 pi = &minfo->limits.video;
427 ci = &minfo->cache.video;
428 break;
429 default:
430 return -EINVAL;
431 }
432
433 mnpcount = 0;
434 {
435 unsigned int mnp;
436 unsigned int xvco;
437
438 for (mnp = g450_firstpll(minfo, pi, &xvco, fout); mnp != NO_MORE_MNP; mnp = g450_nextpll(minfo, pi, &xvco, mnp)) {
439 unsigned int idx;
440 unsigned int vco;
441 unsigned int delta;
442
443 vco = g450_mnp2vco(minfo, mnp);
444#if 0
445 if (pll == M_VIDEO_PLL) {
446 unsigned int big, small;
447
448 if (vco < pixel_vco) {
449 small = vco;
450 big = pixel_vco;
451 } else {
452 small = pixel_vco;
453 big = vco;
454 }
455 while (big > small) {
456 big >>= 1;
457 }
458 if (big == small) {
459 continue;
460 }
461 }
462#endif
463 delta = pll_freq_delta(fout, g450_vco2f(mnp, vco));
464 for (idx = mnpcount; idx > 0; idx--) {
465 /* == is important; due to nextpll algorithm we get
466 sorted equally good frequencies from lower VCO
467 frequency to higher - with <= lowest wins, while
468 with < highest one wins */
469 if (delta <= deltaarray[idx-1]) {
470 /* all else being equal except VCO,
471 * choose VCO not near (within 1/16th or so) VCOmin
472 * (freqs near VCOmin aren't as stable)
473 */
474 if (delta == deltaarray[idx-1]
475 && vco != g450_mnp2vco(minfo, mnparray[idx-1])
476 && vco < (pi->vcomin * 17 / 16)) {
477 break;
478 }
479 mnparray[idx] = mnparray[idx-1];
480 deltaarray[idx] = deltaarray[idx-1];
481 } else {
482 break;
483 }
484 }
485 mnparray[idx] = mnp;
486 deltaarray[idx] = delta;
487 mnpcount++;
488 }
489 }
490 /* VideoPLL and PixelPLL matched: do nothing... In all other cases we should get at least one frequency */
491 if (!mnpcount) {
492 return -EBUSY;
493 }
494 {
495 unsigned long flags;
496 unsigned int mnp;
497
498 matroxfb_DAC_lock_irqsave(flags);
499 mnp = g450_checkcache(minfo, ci, mnparray[0]);
500 if (mnp != NO_MORE_MNP) {
501 matroxfb_g450_setpll_cond(minfo, mnp, pll);
502 } else {
503 mnp = g450_findworkingpll(minfo, pll, mnparray, mnpcount);
504 g450_addcache(ci, mnparray[0], mnp);
505 }
506 updatehwstate_clk(&minfo->hw, mnp, pll);
507 matroxfb_DAC_unlock_irqrestore(flags);
508 return mnp;
509 }
510}
511
512/* It must be greater than number of possible PLL values.
513 * Currently there is 5(p) * 10(m) = 50 possible values. */
514#define MNP_TABLE_SIZE 64
515
516int matroxfb_g450_setclk(struct matrox_fb_info *minfo, unsigned int fout,
517 unsigned int pll)
518{
519 unsigned int* arr;
520
521 arr = kmalloc(sizeof(*arr) * MNP_TABLE_SIZE * 2, GFP_KERNEL);
522 if (arr) {
523 int r;
524
525 r = __g450_setclk(minfo, fout, pll, arr, arr + MNP_TABLE_SIZE);
526 kfree(arr);
527 return r;
528 }
529 return -ENOMEM;
530}
531
532EXPORT_SYMBOL(matroxfb_g450_setclk);
533EXPORT_SYMBOL(g450_mnp2f);
534EXPORT_SYMBOL(matroxfb_g450_setpll_cond);
535
536MODULE_AUTHOR("(c) 2001-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
537MODULE_DESCRIPTION("Matrox G450/G550 PLL driver");
538
539MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/matrox/g450_pll.h b/drivers/video/fbdev/matrox/g450_pll.h
new file mode 100644
index 000000000000..aac615d18440
--- /dev/null
+++ b/drivers/video/fbdev/matrox/g450_pll.h
@@ -0,0 +1,12 @@
1#ifndef __G450_PLL_H__
2#define __G450_PLL_H__
3
4#include "matroxfb_base.h"
5
6int matroxfb_g450_setclk(struct matrox_fb_info *minfo, unsigned int fout,
7 unsigned int pll);
8unsigned int g450_mnp2f(const struct matrox_fb_info *minfo, unsigned int mnp);
9void matroxfb_g450_setpll_cond(struct matrox_fb_info *minfo, unsigned int mnp,
10 unsigned int pll);
11
12#endif /* __G450_PLL_H__ */
diff --git a/drivers/video/fbdev/matrox/i2c-matroxfb.c b/drivers/video/fbdev/matrox/i2c-matroxfb.c
new file mode 100644
index 000000000000..0fb280ead3dc
--- /dev/null
+++ b/drivers/video/fbdev/matrox/i2c-matroxfb.c
@@ -0,0 +1,238 @@
1/*
2 *
3 * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
4 *
5 * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
6 *
7 * Version: 1.64 2002/06/10
8 *
9 * See matroxfb_base.c for contributors.
10 *
11 */
12
13#include "matroxfb_base.h"
14#include "matroxfb_maven.h"
15#include <linux/i2c.h>
16#include <linux/slab.h>
17#include <linux/i2c-algo-bit.h>
18
19/* MGA-TVO I2C for G200, G400 */
20#define MAT_CLK 0x20
21#define MAT_DATA 0x10
22/* primary head DDC for Mystique(?), G100, G200, G400 */
23#define DDC1_CLK 0x08
24#define DDC1_DATA 0x02
25/* primary head DDC for Millennium, Millennium II */
26#define DDC1B_CLK 0x10
27#define DDC1B_DATA 0x04
28/* secondary head DDC for G400 */
29#define DDC2_CLK 0x04
30#define DDC2_DATA 0x01
31
32/******************************************************/
33
34struct matroxfb_dh_maven_info {
35 struct i2c_bit_adapter maven;
36 struct i2c_bit_adapter ddc1;
37 struct i2c_bit_adapter ddc2;
38};
39
40static int matroxfb_read_gpio(struct matrox_fb_info* minfo) {
41 unsigned long flags;
42 int v;
43
44 matroxfb_DAC_lock_irqsave(flags);
45 v = matroxfb_DAC_in(minfo, DAC_XGENIODATA);
46 matroxfb_DAC_unlock_irqrestore(flags);
47 return v;
48}
49
50static void matroxfb_set_gpio(struct matrox_fb_info* minfo, int mask, int val) {
51 unsigned long flags;
52 int v;
53
54 matroxfb_DAC_lock_irqsave(flags);
55 v = (matroxfb_DAC_in(minfo, DAC_XGENIOCTRL) & mask) | val;
56 matroxfb_DAC_out(minfo, DAC_XGENIOCTRL, v);
57 /* We must reset GENIODATA very often... XFree plays with this register */
58 matroxfb_DAC_out(minfo, DAC_XGENIODATA, 0x00);
59 matroxfb_DAC_unlock_irqrestore(flags);
60}
61
62/* software I2C functions */
63static inline void matroxfb_i2c_set(struct matrox_fb_info* minfo, int mask, int state) {
64 if (state)
65 state = 0;
66 else
67 state = mask;
68 matroxfb_set_gpio(minfo, ~mask, state);
69}
70
71static void matroxfb_gpio_setsda(void* data, int state) {
72 struct i2c_bit_adapter* b = data;
73 matroxfb_i2c_set(b->minfo, b->mask.data, state);
74}
75
76static void matroxfb_gpio_setscl(void* data, int state) {
77 struct i2c_bit_adapter* b = data;
78 matroxfb_i2c_set(b->minfo, b->mask.clock, state);
79}
80
81static int matroxfb_gpio_getsda(void* data) {
82 struct i2c_bit_adapter* b = data;
83 return (matroxfb_read_gpio(b->minfo) & b->mask.data) ? 1 : 0;
84}
85
86static int matroxfb_gpio_getscl(void* data) {
87 struct i2c_bit_adapter* b = data;
88 return (matroxfb_read_gpio(b->minfo) & b->mask.clock) ? 1 : 0;
89}
90
91static const struct i2c_algo_bit_data matrox_i2c_algo_template =
92{
93 .setsda = matroxfb_gpio_setsda,
94 .setscl = matroxfb_gpio_setscl,
95 .getsda = matroxfb_gpio_getsda,
96 .getscl = matroxfb_gpio_getscl,
97 .udelay = 10,
98 .timeout = 100,
99};
100
101static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo,
102 unsigned int data, unsigned int clock, const char *name,
103 int class)
104{
105 int err;
106
107 b->minfo = minfo;
108 b->mask.data = data;
109 b->mask.clock = clock;
110 b->adapter.owner = THIS_MODULE;
111 snprintf(b->adapter.name, sizeof(b->adapter.name), name,
112 minfo->fbcon.node);
113 i2c_set_adapdata(&b->adapter, b);
114 b->adapter.class = class;
115 b->adapter.algo_data = &b->bac;
116 b->adapter.dev.parent = &minfo->pcidev->dev;
117 b->bac = matrox_i2c_algo_template;
118 b->bac.data = b;
119 err = i2c_bit_add_bus(&b->adapter);
120 b->initialized = !err;
121 return err;
122}
123
124static void i2c_bit_bus_del(struct i2c_bit_adapter* b) {
125 if (b->initialized) {
126 i2c_del_adapter(&b->adapter);
127 b->initialized = 0;
128 }
129}
130
131static inline void i2c_maven_done(struct matroxfb_dh_maven_info* minfo2) {
132 i2c_bit_bus_del(&minfo2->maven);
133}
134
135static inline void i2c_ddc1_done(struct matroxfb_dh_maven_info* minfo2) {
136 i2c_bit_bus_del(&minfo2->ddc1);
137}
138
139static inline void i2c_ddc2_done(struct matroxfb_dh_maven_info* minfo2) {
140 i2c_bit_bus_del(&minfo2->ddc2);
141}
142
143static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) {
144 int err;
145 unsigned long flags;
146 struct matroxfb_dh_maven_info* m2info;
147
148 m2info = kzalloc(sizeof(*m2info), GFP_KERNEL);
149 if (!m2info)
150 return NULL;
151
152 matroxfb_DAC_lock_irqsave(flags);
153 matroxfb_DAC_out(minfo, DAC_XGENIODATA, 0xFF);
154 matroxfb_DAC_out(minfo, DAC_XGENIOCTRL, 0x00);
155 matroxfb_DAC_unlock_irqrestore(flags);
156
157 switch (minfo->chip) {
158 case MGA_2064:
159 case MGA_2164:
160 err = i2c_bus_reg(&m2info->ddc1, minfo,
161 DDC1B_DATA, DDC1B_CLK,
162 "DDC:fb%u #0", I2C_CLASS_DDC);
163 break;
164 default:
165 err = i2c_bus_reg(&m2info->ddc1, minfo,
166 DDC1_DATA, DDC1_CLK,
167 "DDC:fb%u #0", I2C_CLASS_DDC);
168 break;
169 }
170 if (err)
171 goto fail_ddc1;
172 if (minfo->devflags.dualhead) {
173 err = i2c_bus_reg(&m2info->ddc2, minfo,
174 DDC2_DATA, DDC2_CLK,
175 "DDC:fb%u #1", I2C_CLASS_DDC);
176 if (err == -ENODEV) {
177 printk(KERN_INFO "i2c-matroxfb: VGA->TV plug detected, DDC unavailable.\n");
178 } else if (err)
179 printk(KERN_INFO "i2c-matroxfb: Could not register secondary output i2c bus. Continuing anyway.\n");
180 /* Register maven bus even on G450/G550 */
181 err = i2c_bus_reg(&m2info->maven, minfo,
182 MAT_DATA, MAT_CLK, "MAVEN:fb%u", 0);
183 if (err)
184 printk(KERN_INFO "i2c-matroxfb: Could not register Maven i2c bus. Continuing anyway.\n");
185 else {
186 struct i2c_board_info maven_info = {
187 I2C_BOARD_INFO("maven", 0x1b),
188 };
189 unsigned short const addr_list[2] = {
190 0x1b, I2C_CLIENT_END
191 };
192
193 i2c_new_probed_device(&m2info->maven.adapter,
194 &maven_info, addr_list, NULL);
195 }
196 }
197 return m2info;
198fail_ddc1:;
199 kfree(m2info);
200 printk(KERN_ERR "i2c-matroxfb: Could not register primary adapter DDC bus.\n");
201 return NULL;
202}
203
204static void i2c_matroxfb_remove(struct matrox_fb_info* minfo, void* data) {
205 struct matroxfb_dh_maven_info* m2info = data;
206
207 i2c_maven_done(m2info);
208 i2c_ddc2_done(m2info);
209 i2c_ddc1_done(m2info);
210 kfree(m2info);
211}
212
213static struct matroxfb_driver i2c_matroxfb = {
214 .node = LIST_HEAD_INIT(i2c_matroxfb.node),
215 .name = "i2c-matroxfb",
216 .probe = i2c_matroxfb_probe,
217 .remove = i2c_matroxfb_remove,
218};
219
220static int __init i2c_matroxfb_init(void) {
221 if (matroxfb_register_driver(&i2c_matroxfb)) {
222 printk(KERN_ERR "i2c-matroxfb: failed to register driver\n");
223 return -ENXIO;
224 }
225 return 0;
226}
227
228static void __exit i2c_matroxfb_exit(void) {
229 matroxfb_unregister_driver(&i2c_matroxfb);
230}
231
232MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
233MODULE_DESCRIPTION("Support module providing I2C buses present on Matrox videocards");
234
235module_init(i2c_matroxfb_init);
236module_exit(i2c_matroxfb_exit);
237/* no __setup required */
238MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/matrox/matroxfb_DAC1064.c b/drivers/video/fbdev/matrox/matroxfb_DAC1064.c
new file mode 100644
index 000000000000..a01147fdf270
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_DAC1064.c
@@ -0,0 +1,1107 @@
1/*
2 *
3 * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
4 *
5 * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
6 *
7 * Portions Copyright (c) 2001 Matrox Graphics Inc.
8 *
9 * Version: 1.65 2002/08/14
10 *
11 * See matroxfb_base.c for contributors.
12 *
13 */
14
15
16#include "matroxfb_DAC1064.h"
17#include "matroxfb_misc.h"
18#include "matroxfb_accel.h"
19#include "g450_pll.h"
20#include <linux/matroxfb.h>
21
22#ifdef NEED_DAC1064
23#define outDAC1064 matroxfb_DAC_out
24#define inDAC1064 matroxfb_DAC_in
25
26#define DAC1064_OPT_SCLK_PCI 0x00
27#define DAC1064_OPT_SCLK_PLL 0x01
28#define DAC1064_OPT_SCLK_EXT 0x02
29#define DAC1064_OPT_SCLK_MASK 0x03
30#define DAC1064_OPT_GDIV1 0x04 /* maybe it is GDIV2 on G100 ?! */
31#define DAC1064_OPT_GDIV3 0x00
32#define DAC1064_OPT_MDIV1 0x08
33#define DAC1064_OPT_MDIV2 0x00
34#define DAC1064_OPT_RESERVED 0x10
35
36static void DAC1064_calcclock(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{
41 unsigned int fvco;
42 unsigned int p;
43
44 DBG(__func__)
45
46 /* only for devices older than G450 */
47
48 fvco = PLL_calcclock(minfo, freq, fmax, in, feed, &p);
49
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
87static void DAC1064_setpclk(struct matrox_fb_info *minfo, unsigned long fout)
88{
89 unsigned int m, n, p;
90
91 DBG(__func__)
92
93 DAC1064_calcclock(minfo, fout, minfo->max_pixel_clock, &m, &n, &p);
94 minfo->hw.DACclk[0] = m;
95 minfo->hw.DACclk[1] = n;
96 minfo->hw.DACclk[2] = p;
97}
98
99static void DAC1064_setmclk(struct matrox_fb_info *minfo, int oscinfo,
100 unsigned long fmem)
101{
102 u_int32_t mx;
103 struct matrox_hw_state *hw = &minfo->hw;
104
105 DBG(__func__)
106
107 if (minfo->devflags.noinit) {
108 /* read MCLK and give up... */
109 hw->DACclk[3] = inDAC1064(minfo, DAC1064_XSYSPLLM);
110 hw->DACclk[4] = inDAC1064(minfo, DAC1064_XSYSPLLN);
111 hw->DACclk[5] = inDAC1064(minfo, DAC1064_XSYSPLLP);
112 return;
113 }
114 mx = hw->MXoptionReg | 0x00000004;
115 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
116 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;
130 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
131 mx &= ~0x00000004;
132 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
133
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) */
141 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);
145 for (clk = 65536; clk; --clk) {
146 if (inDAC1064(minfo, DAC1064_XSYSPLLSTAT) & 0x40)
147 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 }
157 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
158 mx &= ~0x00000004;
159 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mx);
160 hw->MXoptionReg = mx;
161}
162
163#ifdef CONFIG_FB_MATROX_G
164static void g450_set_plls(struct matrox_fb_info *minfo)
165{
166 u_int32_t c2_ctl;
167 unsigned int pxc;
168 struct matrox_hw_state *hw = &minfo->hw;
169 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 */
175 pixelmnp = minfo->crtc1.mnp;
176 videomnp = minfo->crtc2.mnp;
177 if (videomnp < 0) {
178 c2_ctl &= ~0x0001; /* Disable CRTC2 */
179 hw->DACreg[POS1064_XPWRCTRL] &= ~0x10; /* Powerdown CRTC2 */
180 } else if (minfo->crtc2.pixclock == minfo->features.pll.ref_freq) {
181 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
195 outDAC1064(minfo, M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]);
196 matroxfb_g450_setpll_cond(minfo, videomnp, M_VIDEO_PLL);
197 }
198
199 hw->DACreg[POS1064_XPIXCLKCTRL] &= ~M1064_XPIXCLKCTRL_PLL_UP;
200 if (pixelmnp >= 0) {
201 hw->DACreg[POS1064_XPIXCLKCTRL] |= M1064_XPIXCLKCTRL_PLL_UP;
202
203 outDAC1064(minfo, M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]);
204 matroxfb_g450_setpll_cond(minfo, pixelmnp, M_PIXEL_PLL_C);
205 }
206 if (c2_ctl != hw->crtc2.ctl) {
207 hw->crtc2.ctl = c2_ctl;
208 mga_outl(0x3C10, c2_ctl);
209 }
210
211 pxc = minfo->crtc1.pixclock;
212 if (pxc == 0 || minfo->outputs[2].src == MATROXFB_SRC_CRTC2) {
213 pxc = minfo->crtc2.pixclock;
214 }
215 if (minfo->chip == MGA_G550) {
216 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
256void DAC1064_global_init(struct matrox_fb_info *minfo)
257{
258 struct matrox_hw_state *hw = &minfo->hw;
259
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
264 if (minfo->devflags.g450dac) {
265 hw->DACreg[POS1064_XPWRCTRL] = 0x1F; /* powerup everything */
266 hw->DACreg[POS1064_XOUTPUTCONN] = 0x00; /* disable outputs */
267 hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN;
268 switch (minfo->outputs[0].src) {
269 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 }
277 switch (minfo->outputs[1].src) {
278 case MATROXFB_SRC_CRTC1:
279 hw->DACreg[POS1064_XOUTPUTCONN] |= 0x04;
280 break;
281 case MATROXFB_SRC_CRTC2:
282 if (minfo->outputs[1].mode == MATROXFB_OUTPUT_MODE_MONITOR) {
283 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 }
292 switch (minfo->outputs[2].src) {
293 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... */
311 g450_set_plls(minfo);
312 } else
313#endif
314 {
315 if (minfo->outputs[1].src == MATROXFB_SRC_CRTC1) {
316 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;
318 } else if (minfo->outputs[1].src == MATROXFB_SRC_CRTC2) {
319 hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_MAFC | G400_XMISCCTRL_VDO_C2_MAFC12;
320 } else if (minfo->outputs[2].src == MATROXFB_SRC_CRTC1)
321 hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_PANELLINK | G400_XMISCCTRL_VDO_MAFC12;
322 else
323 hw->DACreg[POS1064_XMISCCTRL] |= GX00_XMISCCTRL_MFC_DIS;
324
325 if (minfo->outputs[0].src != MATROXFB_SRC_NONE)
326 hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN;
327 }
328}
329
330void DAC1064_global_restore(struct matrox_fb_info *minfo)
331{
332 struct matrox_hw_state *hw = &minfo->hw;
333
334 outDAC1064(minfo, M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]);
335 outDAC1064(minfo, M1064_XMISCCTRL, hw->DACreg[POS1064_XMISCCTRL]);
336 if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400) {
337 outDAC1064(minfo, 0x20, 0x04);
338 outDAC1064(minfo, 0x1F, minfo->devflags.dfp_type);
339 if (minfo->devflags.g450dac) {
340 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]);
344 }
345 }
346}
347
348static int DAC1064_init_1(struct matrox_fb_info *minfo, struct my_timming *m)
349{
350 struct matrox_hw_state *hw = &minfo->hw;
351
352 DBG(__func__)
353
354 memcpy(hw->DACreg, MGA1064_DAC, sizeof(MGA1064_DAC_regs));
355 switch (minfo->fbcon.var.bits_per_pixel) {
356 /* 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:
361 if (minfo->fbcon.var.green.length == 5)
362 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 }
375 hw->DACreg[POS1064_XVREFCTRL] = minfo->features.DAC1064.xvrefctrl;
376 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
381 DAC1064_global_init(minfo);
382 return 0;
383}
384
385static int DAC1064_init_2(struct matrox_fb_info *minfo, struct my_timming *m)
386{
387 struct matrox_hw_state *hw = &minfo->hw;
388
389 DBG(__func__)
390
391 if (minfo->fbcon.var.bits_per_pixel > 16) { /* 256 entries */
392 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 }
399 } else if (minfo->fbcon.var.bits_per_pixel > 8) {
400 if (minfo->fbcon.var.green.length == 5) { /* 0..31, 128..159 */
401 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
428static void DAC1064_restore_1(struct matrox_fb_info *minfo)
429{
430 struct matrox_hw_state *hw = &minfo->hw;
431
432 CRITFLAGS
433
434 DBG(__func__)
435
436 CRITBEGIN
437
438 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]);
444 }
445 {
446 unsigned int i;
447
448 for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) {
449 if ((i != POS1064_XPIXCLKCTRL) && (i != POS1064_XMISCCTRL))
450 outDAC1064(minfo, MGA1064_DAC_regs[i], hw->DACreg[i]);
451 }
452 }
453
454 DAC1064_global_restore(minfo);
455
456 CRITEND
457};
458
459static void DAC1064_restore_2(struct matrox_fb_info *minfo)
460{
461#ifdef DEBUG
462 unsigned int i;
463#endif
464
465 DBG(__func__)
466
467#ifdef DEBUG
468 dprintk(KERN_DEBUG "DAC1064regs ");
469 for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) {
470 dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], minfo->hw.DACreg[i]);
471 if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... ");
472 }
473 dprintk(KERN_DEBUG "DAC1064clk ");
474 for (i = 0; i < 6; i++)
475 dprintk("C%02X=%02X ", i, minfo->hw.DACclk[i]);
476 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
487 DAC1064_setpclk(minfo, m->pixclock);
488
489 CRITBEGIN
490
491 for (i = 0; i < 3; i++)
492 outDAC1064(minfo, M1064_XPIXPLLCM + i, minfo->hw.DACclk[i]);
493 for (tmout = 500000; tmout; tmout--) {
494 if (inDAC1064(minfo, M1064_XPIXPLLSTAT) & 0x40)
495 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) {
517 m->mnp = matroxfb_g450_setclk(minfo, m->pixclock, (m->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL);
518 if (m->mnp >= 0) {
519 m->pixclock = g450_mnp2f(minfo, m->mnp);
520 }
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
535static int MGA1064_init(struct matrox_fb_info *minfo, struct my_timming *m)
536{
537 struct matrox_hw_state *hw = &minfo->hw;
538
539 DBG(__func__)
540
541 if (DAC1064_init_1(minfo, m)) return 1;
542 if (matroxfb_vgaHWinit(minfo, m)) return 1;
543
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
552 if (DAC1064_init_2(minfo, m)) return 1;
553 return 0;
554}
555#endif
556
557#ifdef CONFIG_FB_MATROX_G
558static int MGAG100_init(struct matrox_fb_info *minfo, struct my_timming *m)
559{
560 struct matrox_hw_state *hw = &minfo->hw;
561
562 DBG(__func__)
563
564 if (DAC1064_init_1(minfo, m)) return 1;
565 hw->MXoptionReg &= ~0x2000;
566 if (matroxfb_vgaHWinit(minfo, m)) return 1;
567
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
576 if (DAC1064_init_2(minfo, m)) return 1;
577 return 0;
578}
579#endif /* G */
580
581#ifdef CONFIG_FB_MATROX_MYSTIQUE
582static void MGA1064_ramdac_init(struct matrox_fb_info *minfo)
583{
584
585 DBG(__func__)
586
587 /* 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;
596 /* maybe cmdline MCLK= ?, doc says gclk=44MHz, mclk=66MHz... it was 55/83 with old values */
597 DAC1064_setmclk(minfo, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PLL, 133333);
598}
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
609static void MGAG100_progPixClock(const struct matrox_fb_info *minfo, int flags,
610 int m, int n, int p)
611{
612 int reg;
613 int selClk;
614 int clk;
615
616 DBG(__func__)
617
618 outDAC1064(minfo, M1064_XPIXCLKCTRL, inDAC1064(minfo, M1064_XPIXCLKCTRL) | M1064_XPIXCLKCTRL_DIS |
619 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 }
625 outDAC1064(minfo, reg++, m);
626 outDAC1064(minfo, reg++, n);
627 outDAC1064(minfo, reg, p);
628 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--) {
639 if (inDAC1064(minfo, M1064_XPIXPLLSTAT) & 0x40)
640 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');
645 selClk = inDAC1064(minfo, M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_SRC_MASK;
646 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 }
651 outDAC1064(minfo, M1064_XPIXCLKCTRL, selClk);
652 outDAC1064(minfo, M1064_XPIXCLKCTRL, inDAC1064(minfo, M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_DIS);
653}
654
655static void MGAG100_setPixClock(const struct matrox_fb_info *minfo, int flags,
656 int freq)
657{
658 unsigned int m, n, p;
659
660 DBG(__func__)
661
662 DAC1064_calcclock(minfo, freq, minfo->max_pixel_clock, &m, &n, &p);
663 MGAG100_progPixClock(minfo, flags, m, n, p);
664}
665#endif
666
667#ifdef CONFIG_FB_MATROX_MYSTIQUE
668static int MGA1064_preinit(struct matrox_fb_info *minfo)
669{
670 static const int vxres_mystique[] = { 512, 640, 768, 800, 832, 960,
671 1024, 1152, 1280, 1600, 1664, 1920,
672 2048, 0};
673 struct matrox_hw_state *hw = &minfo->hw;
674
675 DBG(__func__)
676
677 /* minfo->capable.cfb4 = 0; ... preinitialized by 0 */
678 minfo->capable.text = 1;
679 minfo->capable.vxres = vxres_mystique;
680
681 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;
685
686 if (minfo->devflags.noinit)
687 return 0; /* do not modify settings */
688 hw->MXoptionReg &= 0xC0000100;
689 hw->MXoptionReg |= 0x00094E20;
690 if (minfo->devflags.novga)
691 hw->MXoptionReg &= ~0x00000100;
692 if (minfo->devflags.nobios)
693 hw->MXoptionReg &= ~0x40000000;
694 if (minfo->devflags.nopciretry)
695 hw->MXoptionReg |= 0x20000000;
696 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
697 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
706static void MGA1064_reset(struct matrox_fb_info *minfo)
707{
708
709 DBG(__func__);
710
711 MGA1064_ramdac_init(minfo);
712}
713#endif
714
715#ifdef CONFIG_FB_MATROX_G
716static void g450_mclk_init(struct matrox_fb_info *minfo)
717{
718 /* switch all clocks to PCI source */
719 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)) {
726 matroxfb_g450_setclk(minfo, minfo->values.pll.video, M_VIDEO_PLL);
727 } else {
728 unsigned long flags;
729 unsigned int pwr;
730
731 matroxfb_DAC_lock_irqsave(flags);
732 pwr = inDAC1064(minfo, M1064_XPWRCTRL) & ~0x02;
733 outDAC1064(minfo, M1064_XPWRCTRL, pwr);
734 matroxfb_DAC_unlock_irqrestore(flags);
735 }
736 matroxfb_g450_setclk(minfo, minfo->values.pll.system, M_SYSTEM_PLL);
737
738 /* switch clocks to their real PLL source(s) */
739 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);
742
743}
744
745static void g450_memory_init(struct matrox_fb_info *minfo)
746{
747 /* disable memory refresh */
748 minfo->hw.MXoptionReg &= ~0x001F8000;
749 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
750
751 /* set memory interface parameters */
752 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);
756
757 mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
758
759 /* first set up memory interface with disabled memory interface clocks */
760 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);
763 /* start memory clocks */
764 pci_write_config_dword(minfo->pcidev, PCI_MEMMISC_REG, minfo->values.reg.memmisc | 0x80000000U);
765
766 udelay(200);
767
768 if (minfo->values.memory.ddr && (!minfo->values.memory.emrswen || !minfo->values.memory.dll)) {
769 mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk & ~0x1000);
770 }
771 mga_outl(M_MACCESS, minfo->values.reg.maccess | 0x8000);
772
773 udelay(200);
774
775 minfo->hw.MXoptionReg |= 0x001F8000 & minfo->values.reg.opt;
776 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
777
778 /* value is written to memory chips only if old != new */
779 mga_outl(M_PLNWT, 0);
780 mga_outl(M_PLNWT, ~0);
781
782 if (minfo->values.reg.mctlwtst != minfo->values.reg.mctlwtst_core) {
783 mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst_core);
784 }
785
786}
787
788static void g450_preinit(struct matrox_fb_info *minfo)
789{
790 u_int32_t c2ctl;
791 u_int8_t curctl;
792 u_int8_t c1ctl;
793
794 /* 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);
805
806 /* Init system clocks */
807
808 /* stop crtc2 */
809 c2ctl = mga_inl(M_C2CTL);
810 mga_outl(M_C2CTL, c2ctl & ~1);
811 /* stop cursor */
812 curctl = inDAC1064(minfo, M1064_XCURCTRL);
813 outDAC1064(minfo, M1064_XCURCTRL, 0);
814 /* stop crtc1 */
815 c1ctl = mga_readr(M_SEQ_INDEX, 1);
816 mga_setr(M_SEQ_INDEX, 1, c1ctl | 0x20);
817
818 g450_mclk_init(minfo);
819 g450_memory_init(minfo);
820
821 /* set legacy VGA clock sources for DOSEmu or VMware... */
822 matroxfb_g450_setclk(minfo, 25175, M_PIXEL_PLL_A);
823 matroxfb_g450_setclk(minfo, 28322, M_PIXEL_PLL_B);
824
825 /* restore crtc1 */
826 mga_setr(M_SEQ_INDEX, 1, c1ctl);
827
828 /* restore cursor */
829 outDAC1064(minfo, M1064_XCURCTRL, curctl);
830
831 /* restore crtc2 */
832 mga_outl(M_C2CTL, c2ctl);
833
834 return;
835}
836
837static int MGAG100_preinit(struct matrox_fb_info *minfo)
838{
839 static const int vxres_g100[] = { 512, 640, 768, 800, 832, 960,
840 1024, 1152, 1280, 1600, 1664, 1920,
841 2048, 0};
842 struct matrox_hw_state *hw = &minfo->hw;
843
844 u_int32_t reg50;
845#if 0
846 u_int32_t q;
847#endif
848
849 DBG(__func__)
850
851 /* there are some instabilities if in_div > 19 && vco < 61000 */
852 if (minfo->devflags.g450dac) {
853 minfo->features.pll.vco_freq_min = 130000; /* my sample: >118 */
854 } else {
855 minfo->features.pll.vco_freq_min = 62000;
856 }
857 if (!minfo->features.pll.ref_freq) {
858 minfo->features.pll.ref_freq = 27000;
859 }
860 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;
871
872 if (minfo->devflags.g450dac) {
873 minfo->outputs[0].output = &g450out;
874 } else {
875 minfo->outputs[0].output = &m1064;
876 }
877 minfo->outputs[0].src = minfo->outputs[0].default_src;
878 minfo->outputs[0].data = minfo;
879 minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR;
880
881 if (minfo->devflags.g450dac) {
882 /* we must do this always, BIOS does not do it for us
883 and accelerator dies without it */
884 mga_outl(0x1C0C, 0);
885 }
886 if (minfo->devflags.noinit)
887 return 0;
888 if (minfo->devflags.g450dac) {
889 g450_preinit(minfo);
890 return 0;
891 }
892 hw->MXoptionReg &= 0xC0000100;
893 hw->MXoptionReg |= 0x00000020;
894 if (minfo->devflags.novga)
895 hw->MXoptionReg &= ~0x00000100;
896 if (minfo->devflags.nobios)
897 hw->MXoptionReg &= ~0x40000000;
898 if (minfo->devflags.nopciretry)
899 hw->MXoptionReg |= 0x20000000;
900 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
901 DAC1064_setmclk(minfo, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PCI, 133333);
902
903 if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG100) {
904 pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
905 reg50 &= ~0x3000;
906 pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
907
908 hw->MXoptionReg |= 0x1080;
909 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
910 mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
911 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;
920 pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
921 /* 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);
926 mga_writeb(minfo->video.vbase, 0x0000, 0xAA);
927 mga_writeb(minfo->video.vbase, 0x0800, 0x55);
928 mga_writeb(minfo->video.vbase, 0x4000, 0x55);
929#if 0
930 if (mga_readb(minfo->video.vbase, 0x0000) != 0xAA) {
931 hw->MXoptionReg &= ~0x1000;
932 }
933#endif
934 hw->MXoptionReg |= 0x00078020;
935 } else if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG200) {
936 pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
937 reg50 &= ~0x3000;
938 pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
939
940 if (minfo->devflags.memtype == -1)
941 hw->MXoptionReg |= minfo->values.reg.opt & 0x1C00;
942 else
943 hw->MXoptionReg |= (minfo->devflags.memtype & 7) << 10;
944 if (minfo->devflags.sgram)
945 hw->MXoptionReg |= 0x4000;
946 mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
947 mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
948 udelay(200);
949 mga_outl(M_MACCESS, 0x00000000);
950 mga_outl(M_MACCESS, 0x00008000);
951 udelay(100);
952 mga_outw(M_MEMRDBK, minfo->values.reg.memrdbk);
953 hw->MXoptionReg |= 0x00078020;
954 } else {
955 pci_read_config_dword(minfo->pcidev, PCI_OPTION2_REG, &reg50);
956 reg50 &= ~0x00000100;
957 reg50 |= 0x00000000;
958 pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, reg50);
959
960 if (minfo->devflags.memtype == -1)
961 hw->MXoptionReg |= minfo->values.reg.opt & 0x1C00;
962 else
963 hw->MXoptionReg |= (minfo->devflags.memtype & 7) << 10;
964 if (minfo->devflags.sgram)
965 hw->MXoptionReg |= 0x4000;
966 mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst);
967 mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
968 udelay(200);
969 mga_outl(M_MACCESS, 0x00000000);
970 mga_outl(M_MACCESS, 0x00008000);
971 udelay(100);
972 mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk);
973 hw->MXoptionReg |= 0x00040020;
974 }
975 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
976 return 0;
977}
978
979static void MGAG100_reset(struct matrox_fb_info *minfo)
980{
981 u_int8_t b;
982 struct matrox_hw_state *hw = &minfo->hw;
983
984 DBG(__func__)
985
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);
992 if (b == minfo->pcidev->bus->number) {
993 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
999 if (!minfo->devflags.noinit) {
1000 if (x7AF4 & 8) {
1001 hw->MXoptionReg |= 0x40; /* FIXME... */
1002 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
1003 }
1004 mga_setr(M_EXTVGA_INDEX, 0x06, 0x00);
1005 }
1006 }
1007 if (minfo->devflags.g450dac) {
1008 /* either leave MCLK as is... or they were set in preinit */
1009 hw->DACclk[3] = inDAC1064(minfo, DAC1064_XSYSPLLM);
1010 hw->DACclk[4] = inDAC1064(minfo, DAC1064_XSYSPLLN);
1011 hw->DACclk[5] = inDAC1064(minfo, DAC1064_XSYSPLLP);
1012 } else {
1013 DAC1064_setmclk(minfo, DAC1064_OPT_RESERVED | DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV1 | DAC1064_OPT_SCLK_PLL, 133333);
1014 }
1015 if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400) {
1016 if (minfo->devflags.dfp_type == -1) {
1017 minfo->devflags.dfp_type = inDAC1064(minfo, 0x1F);
1018 }
1019 }
1020 if (minfo->devflags.noinit)
1021 return;
1022 if (minfo->devflags.g450dac) {
1023 } else {
1024 MGAG100_setPixClock(minfo, 4, 25175);
1025 MGAG100_setPixClock(minfo, 5, 28322);
1026 if (x7AF4 & 0x10) {
1027 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);
1031 }
1032 }
1033}
1034#endif
1035
1036#ifdef CONFIG_FB_MATROX_MYSTIQUE
1037static void MGA1064_restore(struct matrox_fb_info *minfo)
1038{
1039 int i;
1040 struct matrox_hw_state *hw = &minfo->hw;
1041
1042 CRITFLAGS
1043
1044 DBG(__func__)
1045
1046 CRITBEGIN
1047
1048 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
1049 mga_outb(M_IEN, 0x00);
1050 mga_outb(M_CACHEFLUSH, 0x00);
1051
1052 CRITEND
1053
1054 DAC1064_restore_1(minfo);
1055 matroxfb_vgaHWrestore(minfo);
1056 minfo->crtc1.panpos = -1;
1057 for (i = 0; i < 6; i++)
1058 mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
1059 DAC1064_restore_2(minfo);
1060}
1061#endif
1062
1063#ifdef CONFIG_FB_MATROX_G
1064static void MGAG100_restore(struct matrox_fb_info *minfo)
1065{
1066 int i;
1067 struct matrox_hw_state *hw = &minfo->hw;
1068
1069 CRITFLAGS
1070
1071 DBG(__func__)
1072
1073 CRITBEGIN
1074
1075 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
1076 CRITEND
1077
1078 DAC1064_restore_1(minfo);
1079 matroxfb_vgaHWrestore(minfo);
1080 if (minfo->devflags.support32MB)
1081 mga_setr(M_EXTVGA_INDEX, 8, hw->CRTCEXT[8]);
1082 minfo->crtc1.panpos = -1;
1083 for (i = 0; i < 6; i++)
1084 mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
1085 DAC1064_restore_2(minfo);
1086}
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");
diff --git a/drivers/video/fbdev/matrox/matroxfb_DAC1064.h b/drivers/video/fbdev/matrox/matroxfb_DAC1064.h
new file mode 100644
index 000000000000..1e6e45b57b78
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_DAC1064.h
@@ -0,0 +1,179 @@
1#ifndef __MATROXFB_DAC1064_H__
2#define __MATROXFB_DAC1064_H__
3
4
5#include "matroxfb_base.h"
6
7#ifdef CONFIG_FB_MATROX_MYSTIQUE
8extern struct matrox_switch matrox_mystique;
9#endif
10#ifdef CONFIG_FB_MATROX_G
11extern struct matrox_switch matrox_G100;
12#endif
13#ifdef NEED_DAC1064
14void DAC1064_global_init(struct matrox_fb_info *minfo);
15void DAC1064_global_restore(struct matrox_fb_info *minfo);
16#endif
17
18#define M1064_INDEX 0x00
19#define M1064_PALWRADD 0x00
20#define M1064_PALDATA 0x01
21#define M1064_PIXRDMSK 0x02
22#define M1064_PALRDADD 0x03
23#define M1064_X_DATAREG 0x0A
24#define M1064_CURPOSXL 0x0C /* can be accessed as DWORD */
25#define M1064_CURPOSXH 0x0D
26#define M1064_CURPOSYL 0x0E
27#define M1064_CURPOSYH 0x0F
28
29#define M1064_XCURADDL 0x04
30#define M1064_XCURADDH 0x05
31#define M1064_XCURCTRL 0x06
32#define M1064_XCURCTRL_DIS 0x00 /* transparent, transparent, transparent, transparent */
33#define M1064_XCURCTRL_3COLOR 0x01 /* transparent, 0, 1, 2 */
34#define M1064_XCURCTRL_XGA 0x02 /* 0, 1, transparent, complement */
35#define M1064_XCURCTRL_XWIN 0x03 /* transparent, transparent, 0, 1 */
36 /* drive DVI by standard(0)/DVI(1) PLL */
37 /* if set(1), C?DVICLKEN and C?DVICLKSEL must be set(1) */
38#define M1064_XDVICLKCTRL_DVIDATAPATHSEL 0x01
39 /* drive CRTC1 by standard(0)/DVI(1) PLL */
40#define M1064_XDVICLKCTRL_C1DVICLKSEL 0x02
41 /* drive CRTC2 by standard(0)/DVI(1) PLL */
42#define M1064_XDVICLKCTRL_C2DVICLKSEL 0x04
43 /* pixel clock allowed to(0)/blocked from(1) driving CRTC1 */
44#define M1064_XDVICLKCTRL_C1DVICLKEN 0x08
45 /* DVI PLL loop filter bandwidth selection bits */
46#define M1064_XDVICLKCTRL_DVILOOPCTL 0x30
47 /* CRTC2 pixel clock allowed to(0)/blocked from(1) driving CRTC2 */
48#define M1064_XDVICLKCTRL_C2DVICLKEN 0x40
49 /* P1PLL loop filter bandwidth selection */
50#define M1064_XDVICLKCTRL_P1LOOPBWDTCTL 0x80
51#define M1064_XCURCOL0RED 0x08
52#define M1064_XCURCOL0GREEN 0x09
53#define M1064_XCURCOL0BLUE 0x0A
54#define M1064_XCURCOL1RED 0x0C
55#define M1064_XCURCOL1GREEN 0x0D
56#define M1064_XCURCOL1BLUE 0x0E
57#define M1064_XDVICLKCTRL 0x0F
58#define M1064_XCURCOL2RED 0x10
59#define M1064_XCURCOL2GREEN 0x11
60#define M1064_XCURCOL2BLUE 0x12
61#define DAC1064_XVREFCTRL 0x18
62#define DAC1064_XVREFCTRL_INTERNAL 0x3F
63#define DAC1064_XVREFCTRL_EXTERNAL 0x00
64#define DAC1064_XVREFCTRL_G100_DEFAULT 0x03
65#define M1064_XMULCTRL 0x19
66#define M1064_XMULCTRL_DEPTH_8BPP 0x00 /* 8 bpp paletized */
67#define M1064_XMULCTRL_DEPTH_15BPP_1BPP 0x01 /* 15 bpp paletized + 1 bpp overlay */
68#define M1064_XMULCTRL_DEPTH_16BPP 0x02 /* 16 bpp paletized */
69#define M1064_XMULCTRL_DEPTH_24BPP 0x03 /* 24 bpp paletized */
70#define M1064_XMULCTRL_DEPTH_24BPP_8BPP 0x04 /* 24 bpp direct + 8 bpp overlay paletized */
71#define M1064_XMULCTRL_2G8V16 0x05 /* 15 bpp video direct, half xres, 8bpp paletized */
72#define M1064_XMULCTRL_G16V16 0x06 /* 15 bpp video, 15bpp graphics, one of them paletized */
73#define M1064_XMULCTRL_DEPTH_32BPP 0x07 /* 24 bpp paletized + 8 bpp unused */
74#define M1064_XMULCTRL_GRAPHICS_PALETIZED 0x00
75#define M1064_XMULCTRL_VIDEO_PALETIZED 0x08
76#define M1064_XPIXCLKCTRL 0x1A
77#define M1064_XPIXCLKCTRL_SRC_PCI 0x00
78#define M1064_XPIXCLKCTRL_SRC_PLL 0x01
79#define M1064_XPIXCLKCTRL_SRC_EXT 0x02
80#define M1064_XPIXCLKCTRL_SRC_SYS 0x03 /* G200/G400 */
81#define M1064_XPIXCLKCTRL_SRC_PLL2 0x03 /* G450 */
82#define M1064_XPIXCLKCTRL_SRC_MASK 0x03
83#define M1064_XPIXCLKCTRL_EN 0x00
84#define M1064_XPIXCLKCTRL_DIS 0x04
85#define M1064_XPIXCLKCTRL_PLL_DOWN 0x00
86#define M1064_XPIXCLKCTRL_PLL_UP 0x08
87#define M1064_XGENCTRL 0x1D
88#define M1064_XGENCTRL_VS_0 0x00
89#define M1064_XGENCTRL_VS_1 0x01
90#define M1064_XGENCTRL_ALPHA_DIS 0x00
91#define M1064_XGENCTRL_ALPHA_EN 0x02
92#define M1064_XGENCTRL_BLACK_0IRE 0x00
93#define M1064_XGENCTRL_BLACK_75IRE 0x10
94#define M1064_XGENCTRL_SYNC_ON_GREEN 0x00
95#define M1064_XGENCTRL_NO_SYNC_ON_GREEN 0x20
96#define M1064_XGENCTRL_SYNC_ON_GREEN_MASK 0x20
97#define M1064_XMISCCTRL 0x1E
98#define M1064_XMISCCTRL_DAC_DIS 0x00
99#define M1064_XMISCCTRL_DAC_EN 0x01
100#define M1064_XMISCCTRL_MFC_VGA 0x00
101#define M1064_XMISCCTRL_MFC_MAFC 0x02
102#define M1064_XMISCCTRL_MFC_DIS 0x06
103#define GX00_XMISCCTRL_MFC_MAFC 0x02
104#define GX00_XMISCCTRL_MFC_PANELLINK 0x04
105#define GX00_XMISCCTRL_MFC_DIS 0x06
106#define GX00_XMISCCTRL_MFC_MASK 0x06
107#define M1064_XMISCCTRL_DAC_6BIT 0x00
108#define M1064_XMISCCTRL_DAC_8BIT 0x08
109#define M1064_XMISCCTRL_DAC_WIDTHMASK 0x08
110#define M1064_XMISCCTRL_LUT_DIS 0x00
111#define M1064_XMISCCTRL_LUT_EN 0x10
112#define G400_XMISCCTRL_VDO_MAFC12 0x00
113#define G400_XMISCCTRL_VDO_BYPASS656 0x40
114#define G400_XMISCCTRL_VDO_C2_MAFC12 0x80
115#define G400_XMISCCTRL_VDO_C2_BYPASS656 0xC0
116#define G400_XMISCCTRL_VDO_MASK 0xE0
117#define M1064_XGENIOCTRL 0x2A
118#define M1064_XGENIODATA 0x2B
119#define DAC1064_XSYSPLLM 0x2C
120#define DAC1064_XSYSPLLN 0x2D
121#define DAC1064_XSYSPLLP 0x2E
122#define DAC1064_XSYSPLLSTAT 0x2F
123#define M1064_XZOOMCTRL 0x38
124#define M1064_XZOOMCTRL_1 0x00
125#define M1064_XZOOMCTRL_2 0x01
126#define M1064_XZOOMCTRL_4 0x03
127#define M1064_XSENSETEST 0x3A
128#define M1064_XSENSETEST_BCOMP 0x01
129#define M1064_XSENSETEST_GCOMP 0x02
130#define M1064_XSENSETEST_RCOMP 0x04
131#define M1064_XSENSETEST_PDOWN 0x00
132#define M1064_XSENSETEST_PUP 0x80
133#define M1064_XCRCREML 0x3C
134#define M1064_XCRCREMH 0x3D
135#define M1064_XCRCBITSEL 0x3E
136#define M1064_XCOLKEYMASKL 0x40
137#define M1064_XCOLKEYMASKH 0x41
138#define M1064_XCOLKEYL 0x42
139#define M1064_XCOLKEYH 0x43
140#define M1064_XPIXPLLAM 0x44
141#define M1064_XPIXPLLAN 0x45
142#define M1064_XPIXPLLAP 0x46
143#define M1064_XPIXPLLBM 0x48
144#define M1064_XPIXPLLBN 0x49
145#define M1064_XPIXPLLBP 0x4A
146#define M1064_XPIXPLLCM 0x4C
147#define M1064_XPIXPLLCN 0x4D
148#define M1064_XPIXPLLCP 0x4E
149#define M1064_XPIXPLLSTAT 0x4F
150
151#define M1064_XTVO_IDX 0x87
152#define M1064_XTVO_DATA 0x88
153
154#define M1064_XOUTPUTCONN 0x8A
155#define M1064_XSYNCCTRL 0x8B
156#define M1064_XVIDPLLSTAT 0x8C
157#define M1064_XVIDPLLP 0x8D
158#define M1064_XVIDPLLM 0x8E
159#define M1064_XVIDPLLN 0x8F
160
161#define M1064_XPWRCTRL 0xA0
162#define M1064_XPWRCTRL_PANELPDN 0x04
163
164#define M1064_XPANMODE 0xA2
165
166enum POS1064 {
167 POS1064_XCURADDL=0, POS1064_XCURADDH, POS1064_XCURCTRL,
168 POS1064_XCURCOL0RED, POS1064_XCURCOL0GREEN, POS1064_XCURCOL0BLUE,
169 POS1064_XCURCOL1RED, POS1064_XCURCOL1GREEN, POS1064_XCURCOL1BLUE,
170 POS1064_XCURCOL2RED, POS1064_XCURCOL2GREEN, POS1064_XCURCOL2BLUE,
171 POS1064_XVREFCTRL, POS1064_XMULCTRL, POS1064_XPIXCLKCTRL, POS1064_XGENCTRL,
172 POS1064_XMISCCTRL,
173 POS1064_XGENIOCTRL, POS1064_XGENIODATA, POS1064_XZOOMCTRL, POS1064_XSENSETEST,
174 POS1064_XCRCBITSEL,
175 POS1064_XCOLKEYMASKL, POS1064_XCOLKEYMASKH, POS1064_XCOLKEYL, POS1064_XCOLKEYH,
176 POS1064_XOUTPUTCONN, POS1064_XPANMODE, POS1064_XPWRCTRL };
177
178
179#endif /* __MATROXFB_DAC1064_H__ */
diff --git a/drivers/video/fbdev/matrox/matroxfb_Ti3026.c b/drivers/video/fbdev/matrox/matroxfb_Ti3026.c
new file mode 100644
index 000000000000..195ad7cac1ba
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_Ti3026.c
@@ -0,0 +1,745 @@
1/*
2 *
3 * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
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 * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
12 *
13 * Contributors: "menion?" <menion@mindless.com>
14 * Betatesting, fixes, ideas
15 *
16 * "Kurt Garloff" <garloff@suse.de>
17 * Betatesting, fixes, ideas, videomodes, videomodes timmings
18 *
19 * "Tom Rini" <trini@kernel.crashing.org>
20 * MTRR stuff, PPC cleanups, betatesting, fixes, ideas
21 *
22 * "Bibek Sahu" <scorpio@dodds.net>
23 * Access device through readb|w|l and write b|w|l
24 * Extensive debugging stuff
25 *
26 * "Daniel Haun" <haund@usa.net>
27 * Testing, hardware cursor fixes
28 *
29 * "Scott Wood" <sawst46+@pitt.edu>
30 * Fixes
31 *
32 * "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
33 * Betatesting
34 *
35 * "Kelly French" <targon@hazmat.com>
36 * "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
37 * Betatesting, bug reporting
38 *
39 * "Pablo Bianucci" <pbian@pccp.com.ar>
40 * Fixes, ideas, betatesting
41 *
42 * "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
43 * Fixes, enhandcements, ideas, betatesting
44 *
45 * "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
46 * PPC betatesting, PPC support, backward compatibility
47 *
48 * "Paul Womar" <Paul@pwomar.demon.co.uk>
49 * "Owen Waller" <O.Waller@ee.qub.ac.uk>
50 * PPC betatesting
51 *
52 * "Thomas Pornin" <pornin@bolet.ens.fr>
53 * Alpha betatesting
54 *
55 * "Pieter van Leuven" <pvl@iae.nl>
56 * "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
57 * G100 testing
58 *
59 * "H. Peter Arvin" <hpa@transmeta.com>
60 * Ideas
61 *
62 * "Cort Dougan" <cort@cs.nmt.edu>
63 * CHRP fixes and PReP cleanup
64 *
65 * "Mark Vojkovich" <mvojkovi@ucsd.edu>
66 * G400 support
67 *
68 * (following author is not in any relation with this code, but his code
69 * is included in this driver)
70 *
71 * Based on framebuffer driver for VBE 2.0 compliant graphic boards
72 * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
73 *
74 * (following author is not in any relation with this code, but his ideas
75 * were used when writing this driver)
76 *
77 * FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
78 *
79 */
80
81
82#include "matroxfb_Ti3026.h"
83#include "matroxfb_misc.h"
84#include "matroxfb_accel.h"
85#include <linux/matroxfb.h>
86
87#ifdef CONFIG_FB_MATROX_MILLENIUM
88#define outTi3026 matroxfb_DAC_out
89#define inTi3026 matroxfb_DAC_in
90
91#define TVP3026_INDEX 0x00
92#define TVP3026_PALWRADD 0x00
93#define TVP3026_PALDATA 0x01
94#define TVP3026_PIXRDMSK 0x02
95#define TVP3026_PALRDADD 0x03
96#define TVP3026_CURCOLWRADD 0x04
97#define TVP3026_CLOVERSCAN 0x00
98#define TVP3026_CLCOLOR0 0x01
99#define TVP3026_CLCOLOR1 0x02
100#define TVP3026_CLCOLOR2 0x03
101#define TVP3026_CURCOLDATA 0x05
102#define TVP3026_CURCOLRDADD 0x07
103#define TVP3026_CURCTRL 0x09
104#define TVP3026_X_DATAREG 0x0A
105#define TVP3026_CURRAMDATA 0x0B
106#define TVP3026_CURPOSXL 0x0C
107#define TVP3026_CURPOSXH 0x0D
108#define TVP3026_CURPOSYL 0x0E
109#define TVP3026_CURPOSYH 0x0F
110
111#define TVP3026_XSILICONREV 0x01
112#define TVP3026_XCURCTRL 0x06
113#define TVP3026_XCURCTRL_DIS 0x00 /* transparent, transparent, transparent, transparent */
114#define TVP3026_XCURCTRL_3COLOR 0x01 /* transparent, 0, 1, 2 */
115#define TVP3026_XCURCTRL_XGA 0x02 /* 0, 1, transparent, complement */
116#define TVP3026_XCURCTRL_XWIN 0x03 /* transparent, transparent, 0, 1 */
117#define TVP3026_XCURCTRL_BLANK2048 0x00
118#define TVP3026_XCURCTRL_BLANK4096 0x10
119#define TVP3026_XCURCTRL_INTERLACED 0x20
120#define TVP3026_XCURCTRL_ODD 0x00 /* ext.signal ODD/\EVEN */
121#define TVP3026_XCURCTRL_EVEN 0x40 /* ext.signal EVEN/\ODD */
122#define TVP3026_XCURCTRL_INDIRECT 0x00
123#define TVP3026_XCURCTRL_DIRECT 0x80
124#define TVP3026_XLATCHCTRL 0x0F
125#define TVP3026_XLATCHCTRL_1_1 0x06
126#define TVP3026_XLATCHCTRL_2_1 0x07
127#define TVP3026_XLATCHCTRL_4_1 0x06
128#define TVP3026_XLATCHCTRL_8_1 0x06
129#define TVP3026_XLATCHCTRL_16_1 0x06
130#define TVP3026A_XLATCHCTRL_4_3 0x06 /* ??? do not understand... but it works... !!! */
131#define TVP3026A_XLATCHCTRL_8_3 0x07
132#define TVP3026B_XLATCHCTRL_4_3 0x08
133#define TVP3026B_XLATCHCTRL_8_3 0x06 /* ??? do not understand... but it works... !!! */
134#define TVP3026_XTRUECOLORCTRL 0x18
135#define TVP3026_XTRUECOLORCTRL_VRAM_SHIFT_ACCEL 0x00
136#define TVP3026_XTRUECOLORCTRL_VRAM_SHIFT_TVP 0x20
137#define TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR 0x80
138#define TVP3026_XTRUECOLORCTRL_TRUECOLOR 0x40 /* paletized */
139#define TVP3026_XTRUECOLORCTRL_DIRECTCOLOR 0x00
140#define TVP3026_XTRUECOLORCTRL_24_ALTERNATE 0x08 /* 5:4/5:2 instead of 4:3/8:3 */
141#define TVP3026_XTRUECOLORCTRL_RGB_888 0x16 /* 4:3/8:3 (or 5:4/5:2) */
142#define TVP3026_XTRUECOLORCTRL_BGR_888 0x17
143#define TVP3026_XTRUECOLORCTRL_ORGB_8888 0x06
144#define TVP3026_XTRUECOLORCTRL_BGRO_8888 0x07
145#define TVP3026_XTRUECOLORCTRL_RGB_565 0x05
146#define TVP3026_XTRUECOLORCTRL_ORGB_1555 0x04
147#define TVP3026_XTRUECOLORCTRL_RGB_664 0x03
148#define TVP3026_XTRUECOLORCTRL_RGBO_4444 0x01
149#define TVP3026_XMUXCTRL 0x19
150#define TVP3026_XMUXCTRL_MEMORY_8BIT 0x01 /* - */
151#define TVP3026_XMUXCTRL_MEMORY_16BIT 0x02 /* - */
152#define TVP3026_XMUXCTRL_MEMORY_32BIT 0x03 /* 2MB RAM, 512K * 4 */
153#define TVP3026_XMUXCTRL_MEMORY_64BIT 0x04 /* >2MB RAM, 512K * 8 & more */
154#define TVP3026_XMUXCTRL_PIXEL_4BIT 0x40 /* L0,H0,L1,H1... */
155#define TVP3026_XMUXCTRL_PIXEL_4BIT_SWAPPED 0x60 /* H0,L0,H1,L1... */
156#define TVP3026_XMUXCTRL_PIXEL_8BIT 0x48
157#define TVP3026_XMUXCTRL_PIXEL_16BIT 0x50
158#define TVP3026_XMUXCTRL_PIXEL_32BIT 0x58
159#define TVP3026_XMUXCTRL_VGA 0x98 /* VGA MEMORY, 8BIT PIXEL */
160#define TVP3026_XCLKCTRL 0x1A
161#define TVP3026_XCLKCTRL_DIV1 0x00
162#define TVP3026_XCLKCTRL_DIV2 0x10
163#define TVP3026_XCLKCTRL_DIV4 0x20
164#define TVP3026_XCLKCTRL_DIV8 0x30
165#define TVP3026_XCLKCTRL_DIV16 0x40
166#define TVP3026_XCLKCTRL_DIV32 0x50
167#define TVP3026_XCLKCTRL_DIV64 0x60
168#define TVP3026_XCLKCTRL_CLKSTOPPED 0x70
169#define TVP3026_XCLKCTRL_SRC_CLK0 0x00
170#define TVP3026_XCLKCTRL_SRC_CLK1 0x01
171#define TVP3026_XCLKCTRL_SRC_CLK2 0x02 /* CLK2 is TTL source*/
172#define TVP3026_XCLKCTRL_SRC_NCLK2 0x03 /* not CLK2 is TTL source */
173#define TVP3026_XCLKCTRL_SRC_ECLK2 0x04 /* CLK2 and not CLK2 is ECL source */
174#define TVP3026_XCLKCTRL_SRC_PLL 0x05
175#define TVP3026_XCLKCTRL_SRC_DIS 0x06 /* disable & poweroff internal clock */
176#define TVP3026_XCLKCTRL_SRC_CLK0VGA 0x07
177#define TVP3026_XPALETTEPAGE 0x1C
178#define TVP3026_XGENCTRL 0x1D
179#define TVP3026_XGENCTRL_HSYNC_POS 0x00
180#define TVP3026_XGENCTRL_HSYNC_NEG 0x01
181#define TVP3026_XGENCTRL_VSYNC_POS 0x00
182#define TVP3026_XGENCTRL_VSYNC_NEG 0x02
183#define TVP3026_XGENCTRL_LITTLE_ENDIAN 0x00
184#define TVP3026_XGENCTRL_BIG_ENDIAN 0x08
185#define TVP3026_XGENCTRL_BLACK_0IRE 0x00
186#define TVP3026_XGENCTRL_BLACK_75IRE 0x10
187#define TVP3026_XGENCTRL_NO_SYNC_ON_GREEN 0x00
188#define TVP3026_XGENCTRL_SYNC_ON_GREEN 0x20
189#define TVP3026_XGENCTRL_OVERSCAN_DIS 0x00
190#define TVP3026_XGENCTRL_OVERSCAN_EN 0x40
191#define TVP3026_XMISCCTRL 0x1E
192#define TVP3026_XMISCCTRL_DAC_PUP 0x00
193#define TVP3026_XMISCCTRL_DAC_PDOWN 0x01
194#define TVP3026_XMISCCTRL_DAC_EXT 0x00 /* or 8, bit 3 is ignored */
195#define TVP3026_XMISCCTRL_DAC_6BIT 0x04
196#define TVP3026_XMISCCTRL_DAC_8BIT 0x0C
197#define TVP3026_XMISCCTRL_PSEL_DIS 0x00
198#define TVP3026_XMISCCTRL_PSEL_EN 0x10
199#define TVP3026_XMISCCTRL_PSEL_LOW 0x00 /* PSEL high selects directcolor */
200#define TVP3026_XMISCCTRL_PSEL_HIGH 0x20 /* PSEL high selects truecolor or pseudocolor */
201#define TVP3026_XGENIOCTRL 0x2A
202#define TVP3026_XGENIODATA 0x2B
203#define TVP3026_XPLLADDR 0x2C
204#define TVP3026_XPLLADDR_X(LOOP,MCLK,PIX) (((LOOP)<<4) | ((MCLK)<<2) | (PIX))
205#define TVP3026_XPLLDATA_N 0x00
206#define TVP3026_XPLLDATA_M 0x01
207#define TVP3026_XPLLDATA_P 0x02
208#define TVP3026_XPLLDATA_STAT 0x03
209#define TVP3026_XPIXPLLDATA 0x2D
210#define TVP3026_XMEMPLLDATA 0x2E
211#define TVP3026_XLOOPPLLDATA 0x2F
212#define TVP3026_XCOLKEYOVRMIN 0x30
213#define TVP3026_XCOLKEYOVRMAX 0x31
214#define TVP3026_XCOLKEYREDMIN 0x32
215#define TVP3026_XCOLKEYREDMAX 0x33
216#define TVP3026_XCOLKEYGREENMIN 0x34
217#define TVP3026_XCOLKEYGREENMAX 0x35
218#define TVP3026_XCOLKEYBLUEMIN 0x36
219#define TVP3026_XCOLKEYBLUEMAX 0x37
220#define TVP3026_XCOLKEYCTRL 0x38
221#define TVP3026_XCOLKEYCTRL_OVR_EN 0x01
222#define TVP3026_XCOLKEYCTRL_RED_EN 0x02
223#define TVP3026_XCOLKEYCTRL_GREEN_EN 0x04
224#define TVP3026_XCOLKEYCTRL_BLUE_EN 0x08
225#define TVP3026_XCOLKEYCTRL_NEGATE 0x10
226#define TVP3026_XCOLKEYCTRL_ZOOM1 0x00
227#define TVP3026_XCOLKEYCTRL_ZOOM2 0x20
228#define TVP3026_XCOLKEYCTRL_ZOOM4 0x40
229#define TVP3026_XCOLKEYCTRL_ZOOM8 0x60
230#define TVP3026_XCOLKEYCTRL_ZOOM16 0x80
231#define TVP3026_XCOLKEYCTRL_ZOOM32 0xA0
232#define TVP3026_XMEMPLLCTRL 0x39
233#define TVP3026_XMEMPLLCTRL_DIV(X) (((X)-1)>>1) /* 2,4,6,8,10,12,14,16, division applied to LOOP PLL after divide by 2^P */
234#define TVP3026_XMEMPLLCTRL_STROBEMKC4 0x08
235#define TVP3026_XMEMPLLCTRL_MCLK_DOTCLOCK 0x00 /* MKC4 */
236#define TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL 0x10 /* MKC4 */
237#define TVP3026_XMEMPLLCTRL_RCLK_PIXPLL 0x00
238#define TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL 0x20
239#define TVP3026_XMEMPLLCTRL_RCLK_DOTDIVN 0x40 /* dot clock divided by loop pclk N prescaler */
240#define TVP3026_XSENSETEST 0x3A
241#define TVP3026_XTESTMODEDATA 0x3B
242#define TVP3026_XCRCREML 0x3C
243#define TVP3026_XCRCREMH 0x3D
244#define TVP3026_XCRCBITSEL 0x3E
245#define TVP3026_XID 0x3F
246
247static const unsigned char DACseq[] =
248{ TVP3026_XLATCHCTRL, TVP3026_XTRUECOLORCTRL,
249 TVP3026_XMUXCTRL, TVP3026_XCLKCTRL,
250 TVP3026_XPALETTEPAGE,
251 TVP3026_XGENCTRL,
252 TVP3026_XMISCCTRL,
253 TVP3026_XGENIOCTRL,
254 TVP3026_XGENIODATA,
255 TVP3026_XCOLKEYOVRMIN, TVP3026_XCOLKEYOVRMAX, TVP3026_XCOLKEYREDMIN, TVP3026_XCOLKEYREDMAX,
256 TVP3026_XCOLKEYGREENMIN, TVP3026_XCOLKEYGREENMAX, TVP3026_XCOLKEYBLUEMIN, TVP3026_XCOLKEYBLUEMAX,
257 TVP3026_XCOLKEYCTRL,
258 TVP3026_XMEMPLLCTRL, TVP3026_XSENSETEST, TVP3026_XCURCTRL };
259
260#define POS3026_XLATCHCTRL 0
261#define POS3026_XTRUECOLORCTRL 1
262#define POS3026_XMUXCTRL 2
263#define POS3026_XCLKCTRL 3
264#define POS3026_XGENCTRL 5
265#define POS3026_XMISCCTRL 6
266#define POS3026_XMEMPLLCTRL 18
267#define POS3026_XCURCTRL 20
268
269static const unsigned char MGADACbpp32[] =
270{ TVP3026_XLATCHCTRL_2_1, TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_8888,
271 0x00, TVP3026_XCLKCTRL_DIV1 | TVP3026_XCLKCTRL_SRC_PLL,
272 0x00,
273 TVP3026_XGENCTRL_HSYNC_POS | TVP3026_XGENCTRL_VSYNC_POS | TVP3026_XGENCTRL_LITTLE_ENDIAN | TVP3026_XGENCTRL_BLACK_0IRE | TVP3026_XGENCTRL_NO_SYNC_ON_GREEN | TVP3026_XGENCTRL_OVERSCAN_DIS,
274 TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_HIGH,
275 0x00,
276 0x1E,
277 0xFF, 0xFF, 0xFF, 0xFF,
278 0xFF, 0xFF, 0xFF, 0xFF,
279 TVP3026_XCOLKEYCTRL_ZOOM1,
280 0x00, 0x00, TVP3026_XCURCTRL_DIS };
281
282static int Ti3026_calcclock(const struct matrox_fb_info *minfo,
283 unsigned int freq, unsigned int fmax, int *in,
284 int *feed, int *post)
285{
286 unsigned int fvco;
287 unsigned int lin, lfeed, lpost;
288
289 DBG(__func__)
290
291 fvco = PLL_calcclock(minfo, freq, fmax, &lin, &lfeed, &lpost);
292 fvco >>= (*post = lpost);
293 *in = 64 - lin;
294 *feed = 64 - lfeed;
295 return fvco;
296}
297
298static int Ti3026_setpclk(struct matrox_fb_info *minfo, int clk)
299{
300 unsigned int f_pll;
301 unsigned int pixfeed, pixin, pixpost;
302 struct matrox_hw_state *hw = &minfo->hw;
303
304 DBG(__func__)
305
306 f_pll = Ti3026_calcclock(minfo, clk, minfo->max_pixel_clock, &pixin, &pixfeed, &pixpost);
307
308 hw->DACclk[0] = pixin | 0xC0;
309 hw->DACclk[1] = pixfeed;
310 hw->DACclk[2] = pixpost | 0xB0;
311
312 {
313 unsigned int loopfeed, loopin, looppost, loopdiv, z;
314 unsigned int Bpp;
315
316 Bpp = minfo->curr.final_bppShift;
317
318 if (minfo->fbcon.var.bits_per_pixel == 24) {
319 loopfeed = 3; /* set lm to any possible value */
320 loopin = 3 * 32 / Bpp;
321 } else {
322 loopfeed = 4;
323 loopin = 4 * 32 / Bpp;
324 }
325 z = (110000 * loopin) / (f_pll * loopfeed);
326 loopdiv = 0; /* div 2 */
327 if (z < 2)
328 looppost = 0;
329 else if (z < 4)
330 looppost = 1;
331 else if (z < 8)
332 looppost = 2;
333 else {
334 looppost = 3;
335 loopdiv = z/16;
336 }
337 if (minfo->fbcon.var.bits_per_pixel == 24) {
338 hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
339 hw->DACclk[4] = (65 - loopfeed) | 0x80;
340 if (minfo->accel.ramdac_rev > 0x20) {
341 if (isInterleave(minfo))
342 hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_8_3;
343 else {
344 hw->DACclk[4] &= ~0xC0;
345 hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_4_3;
346 }
347 } else {
348 if (isInterleave(minfo))
349 ; /* default... */
350 else {
351 hw->DACclk[4] ^= 0xC0; /* change from 0x80 to 0x40 */
352 hw->DACreg[POS3026_XLATCHCTRL] = TVP3026A_XLATCHCTRL_4_3;
353 }
354 }
355 hw->DACclk[5] = looppost | 0xF8;
356 if (minfo->devflags.mga_24bpp_fix)
357 hw->DACclk[5] ^= 0x40;
358 } else {
359 hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
360 hw->DACclk[4] = 65 - loopfeed;
361 hw->DACclk[5] = looppost | 0xF0;
362 }
363 hw->DACreg[POS3026_XMEMPLLCTRL] = loopdiv | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL;
364 }
365 return 0;
366}
367
368static int Ti3026_init(struct matrox_fb_info *minfo, struct my_timming *m)
369{
370 u_int8_t muxctrl = isInterleave(minfo) ? TVP3026_XMUXCTRL_MEMORY_64BIT : TVP3026_XMUXCTRL_MEMORY_32BIT;
371 struct matrox_hw_state *hw = &minfo->hw;
372
373 DBG(__func__)
374
375 memcpy(hw->DACreg, MGADACbpp32, sizeof(hw->DACreg));
376 switch (minfo->fbcon.var.bits_per_pixel) {
377 case 4: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_16_1; /* or _8_1, they are same */
378 hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
379 hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_4BIT;
380 hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV8;
381 hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW;
382 break;
383 case 8: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_8_1; /* or _4_1, they are same */
384 hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
385 hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_8BIT;
386 hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV4;
387 hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_8BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW;
388 break;
389 case 16:
390 /* XLATCHCTRL should be _4_1 / _2_1... Why is not? (_2_1 is used every time) */
391 hw->DACreg[POS3026_XTRUECOLORCTRL] = (minfo->fbcon.var.green.length == 5) ? (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_1555) : (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_565);
392 hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_16BIT;
393 hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV2;
394 break;
395 case 24:
396 /* XLATCHCTRL is: for (A) use _4_3 (?_8_3 is same? TBD), for (B) it is set in setpclk */
397 hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_888;
398 hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_32BIT;
399 hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV4;
400 break;
401 case 32:
402 /* XLATCHCTRL should be _2_1 / _1_1... Why is not? (_2_1 is used every time) */
403 hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_32BIT;
404 break;
405 default:
406 return 1; /* TODO: failed */
407 }
408 if (matroxfb_vgaHWinit(minfo, m)) return 1;
409
410 /* set SYNC */
411 hw->MiscOutReg = 0xCB;
412 if (m->sync & FB_SYNC_HOR_HIGH_ACT)
413 hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_HSYNC_NEG;
414 if (m->sync & FB_SYNC_VERT_HIGH_ACT)
415 hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_VSYNC_NEG;
416 if (m->sync & FB_SYNC_ON_GREEN)
417 hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_SYNC_ON_GREEN;
418
419 /* set DELAY */
420 if (minfo->video.len < 0x400000)
421 hw->CRTCEXT[3] |= 0x08;
422 else if (minfo->video.len > 0x400000)
423 hw->CRTCEXT[3] |= 0x10;
424
425 /* set HWCURSOR */
426 if (m->interlaced) {
427 hw->DACreg[POS3026_XCURCTRL] |= TVP3026_XCURCTRL_INTERLACED;
428 }
429 if (m->HTotal >= 1536)
430 hw->DACreg[POS3026_XCURCTRL] |= TVP3026_XCURCTRL_BLANK4096;
431
432 /* set interleaving */
433 hw->MXoptionReg &= ~0x00001000;
434 if (isInterleave(minfo)) hw->MXoptionReg |= 0x00001000;
435
436 /* set DAC */
437 Ti3026_setpclk(minfo, m->pixclock);
438 return 0;
439}
440
441static void ti3026_setMCLK(struct matrox_fb_info *minfo, int fout)
442{
443 unsigned int f_pll;
444 unsigned int pclk_m, pclk_n, pclk_p;
445 unsigned int mclk_m, mclk_n, mclk_p;
446 unsigned int rfhcnt, mclk_ctl;
447 int tmout;
448
449 DBG(__func__)
450
451 f_pll = Ti3026_calcclock(minfo, fout, minfo->max_pixel_clock, &mclk_n, &mclk_m, &mclk_p);
452
453 /* save pclk */
454 outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
455 pclk_n = inTi3026(minfo, TVP3026_XPIXPLLDATA);
456 outTi3026(minfo, TVP3026_XPLLADDR, 0xFD);
457 pclk_m = inTi3026(minfo, TVP3026_XPIXPLLDATA);
458 outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
459 pclk_p = inTi3026(minfo, TVP3026_XPIXPLLDATA);
460
461 /* stop pclk */
462 outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
463 outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00);
464
465 /* set pclk to new mclk */
466 outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
467 outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_n | 0xC0);
468 outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_m);
469 outTi3026(minfo, TVP3026_XPIXPLLDATA, mclk_p | 0xB0);
470
471 /* wait for PLL to lock */
472 for (tmout = 500000; tmout; tmout--) {
473 if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
474 break;
475 udelay(10);
476 }
477 if (!tmout)
478 printk(KERN_ERR "matroxfb: Temporary pixel PLL not locked after 5 secs\n");
479
480 /* output pclk on mclk pin */
481 mclk_ctl = inTi3026(minfo, TVP3026_XMEMPLLCTRL);
482 outTi3026(minfo, TVP3026_XMEMPLLCTRL, mclk_ctl & 0xE7);
483 outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_STROBEMKC4);
484
485 /* stop MCLK */
486 outTi3026(minfo, TVP3026_XPLLADDR, 0xFB);
487 outTi3026(minfo, TVP3026_XMEMPLLDATA, 0x00);
488
489 /* set mclk to new freq */
490 outTi3026(minfo, TVP3026_XPLLADDR, 0xF3);
491 outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_n | 0xC0);
492 outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_m);
493 outTi3026(minfo, TVP3026_XMEMPLLDATA, mclk_p | 0xB0);
494
495 /* wait for PLL to lock */
496 for (tmout = 500000; tmout; tmout--) {
497 if (inTi3026(minfo, TVP3026_XMEMPLLDATA) & 0x40)
498 break;
499 udelay(10);
500 }
501 if (!tmout)
502 printk(KERN_ERR "matroxfb: Memory PLL not locked after 5 secs\n");
503
504 f_pll = f_pll * 333 / (10000 << mclk_p);
505 if (isMilleniumII(minfo)) {
506 rfhcnt = (f_pll - 128) / 256;
507 if (rfhcnt > 15)
508 rfhcnt = 15;
509 } else {
510 rfhcnt = (f_pll - 64) / 128;
511 if (rfhcnt > 15)
512 rfhcnt = 0;
513 }
514 minfo->hw.MXoptionReg = (minfo->hw.MXoptionReg & ~0x000F0000) | (rfhcnt << 16);
515 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg);
516
517 /* output MCLK to MCLK pin */
518 outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL);
519 outTi3026(minfo, TVP3026_XMEMPLLCTRL, (mclk_ctl ) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_STROBEMKC4);
520
521 /* stop PCLK */
522 outTi3026(minfo, TVP3026_XPLLADDR, 0xFE);
523 outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00);
524
525 /* restore pclk */
526 outTi3026(minfo, TVP3026_XPLLADDR, 0xFC);
527 outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_n);
528 outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_m);
529 outTi3026(minfo, TVP3026_XPIXPLLDATA, pclk_p);
530
531 /* wait for PLL to lock */
532 for (tmout = 500000; tmout; tmout--) {
533 if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
534 break;
535 udelay(10);
536 }
537 if (!tmout)
538 printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
539}
540
541static void ti3026_ramdac_init(struct matrox_fb_info *minfo)
542{
543 DBG(__func__)
544
545 minfo->features.pll.vco_freq_min = 110000;
546 minfo->features.pll.ref_freq = 114545;
547 minfo->features.pll.feed_div_min = 2;
548 minfo->features.pll.feed_div_max = 24;
549 minfo->features.pll.in_div_min = 2;
550 minfo->features.pll.in_div_max = 63;
551 minfo->features.pll.post_shift_max = 3;
552 if (minfo->devflags.noinit)
553 return;
554 ti3026_setMCLK(minfo, 60000);
555}
556
557static void Ti3026_restore(struct matrox_fb_info *minfo)
558{
559 int i;
560 unsigned char progdac[6];
561 struct matrox_hw_state *hw = &minfo->hw;
562 CRITFLAGS
563
564 DBG(__func__)
565
566#ifdef DEBUG
567 dprintk(KERN_INFO "EXTVGA regs: ");
568 for (i = 0; i < 6; i++)
569 dprintk("%02X:", hw->CRTCEXT[i]);
570 dprintk("\n");
571#endif
572
573 CRITBEGIN
574
575 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
576
577 CRITEND
578
579 matroxfb_vgaHWrestore(minfo);
580
581 CRITBEGIN
582
583 minfo->crtc1.panpos = -1;
584 for (i = 0; i < 6; i++)
585 mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
586
587 for (i = 0; i < 21; i++) {
588 outTi3026(minfo, DACseq[i], hw->DACreg[i]);
589 }
590
591 outTi3026(minfo, TVP3026_XPLLADDR, 0x00);
592 progdac[0] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
593 progdac[3] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);
594 outTi3026(minfo, TVP3026_XPLLADDR, 0x15);
595 progdac[1] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
596 progdac[4] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);
597 outTi3026(minfo, TVP3026_XPLLADDR, 0x2A);
598 progdac[2] = inTi3026(minfo, TVP3026_XPIXPLLDATA);
599 progdac[5] = inTi3026(minfo, TVP3026_XLOOPPLLDATA);
600
601 CRITEND
602 if (memcmp(hw->DACclk, progdac, 6)) {
603 /* agrhh... setting up PLL is very slow on Millennium... */
604 /* Mystique PLL is locked in few ms, but Millennium PLL lock takes about 0.15 s... */
605 /* Maybe even we should call schedule() ? */
606
607 CRITBEGIN
608 outTi3026(minfo, TVP3026_XCLKCTRL, hw->DACreg[POS3026_XCLKCTRL]);
609 outTi3026(minfo, TVP3026_XPLLADDR, 0x2A);
610 outTi3026(minfo, TVP3026_XLOOPPLLDATA, 0);
611 outTi3026(minfo, TVP3026_XPIXPLLDATA, 0);
612
613 outTi3026(minfo, TVP3026_XPLLADDR, 0x00);
614 for (i = 0; i < 3; i++)
615 outTi3026(minfo, TVP3026_XPIXPLLDATA, hw->DACclk[i]);
616 /* wait for PLL only if PLL clock requested (always for PowerMode, never for VGA) */
617 if (hw->MiscOutReg & 0x08) {
618 int tmout;
619 outTi3026(minfo, TVP3026_XPLLADDR, 0x3F);
620 for (tmout = 500000; tmout; --tmout) {
621 if (inTi3026(minfo, TVP3026_XPIXPLLDATA) & 0x40)
622 break;
623 udelay(10);
624 }
625
626 CRITEND
627
628 if (!tmout)
629 printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
630 else
631 dprintk(KERN_INFO "PixelPLL: %d\n", 500000-tmout);
632 CRITBEGIN
633 }
634 outTi3026(minfo, TVP3026_XMEMPLLCTRL, hw->DACreg[POS3026_XMEMPLLCTRL]);
635 outTi3026(minfo, TVP3026_XPLLADDR, 0x00);
636 for (i = 3; i < 6; i++)
637 outTi3026(minfo, TVP3026_XLOOPPLLDATA, hw->DACclk[i]);
638 CRITEND
639 if ((hw->MiscOutReg & 0x08) && ((hw->DACclk[5] & 0x80) == 0x80)) {
640 int tmout;
641
642 CRITBEGIN
643 outTi3026(minfo, TVP3026_XPLLADDR, 0x3F);
644 for (tmout = 500000; tmout; --tmout) {
645 if (inTi3026(minfo, TVP3026_XLOOPPLLDATA) & 0x40)
646 break;
647 udelay(10);
648 }
649 CRITEND
650 if (!tmout)
651 printk(KERN_ERR "matroxfb: Loop PLL not locked after 5 secs\n");
652 else
653 dprintk(KERN_INFO "LoopPLL: %d\n", 500000-tmout);
654 }
655 }
656
657#ifdef DEBUG
658 dprintk(KERN_DEBUG "3026DACregs ");
659 for (i = 0; i < 21; i++) {
660 dprintk("R%02X=%02X ", DACseq[i], hw->DACreg[i]);
661 if ((i & 0x7) == 0x7) dprintk(KERN_DEBUG "continuing... ");
662 }
663 dprintk(KERN_DEBUG "DACclk ");
664 for (i = 0; i < 6; i++)
665 dprintk("C%02X=%02X ", i, hw->DACclk[i]);
666 dprintk("\n");
667#endif
668}
669
670static void Ti3026_reset(struct matrox_fb_info *minfo)
671{
672 DBG(__func__)
673
674 ti3026_ramdac_init(minfo);
675}
676
677static struct matrox_altout ti3026_output = {
678 .name = "Primary output",
679};
680
681static int Ti3026_preinit(struct matrox_fb_info *minfo)
682{
683 static const int vxres_mill2[] = { 512, 640, 768, 800, 832, 960,
684 1024, 1152, 1280, 1600, 1664, 1920,
685 2048, 0};
686 static const int vxres_mill1[] = { 640, 768, 800, 960,
687 1024, 1152, 1280, 1600, 1920,
688 2048, 0};
689 struct matrox_hw_state *hw = &minfo->hw;
690
691 DBG(__func__)
692
693 minfo->millenium = 1;
694 minfo->milleniumII = (minfo->pcidev->device != PCI_DEVICE_ID_MATROX_MIL);
695 minfo->capable.cfb4 = 1;
696 minfo->capable.text = 1; /* isMilleniumII(minfo); */
697 minfo->capable.vxres = isMilleniumII(minfo) ? vxres_mill2 : vxres_mill1;
698
699 minfo->outputs[0].data = minfo;
700 minfo->outputs[0].output = &ti3026_output;
701 minfo->outputs[0].src = minfo->outputs[0].default_src;
702 minfo->outputs[0].mode = MATROXFB_OUTPUT_MODE_MONITOR;
703
704 if (minfo->devflags.noinit)
705 return 0;
706 /* preserve VGA I/O, BIOS and PPC */
707 hw->MXoptionReg &= 0xC0000100;
708 hw->MXoptionReg |= 0x002C0000;
709 if (minfo->devflags.novga)
710 hw->MXoptionReg &= ~0x00000100;
711 if (minfo->devflags.nobios)
712 hw->MXoptionReg &= ~0x40000000;
713 if (minfo->devflags.nopciretry)
714 hw->MXoptionReg |= 0x20000000;
715 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, hw->MXoptionReg);
716
717 minfo->accel.ramdac_rev = inTi3026(minfo, TVP3026_XSILICONREV);
718
719 outTi3026(minfo, TVP3026_XCLKCTRL, TVP3026_XCLKCTRL_SRC_CLK0VGA | TVP3026_XCLKCTRL_CLKSTOPPED);
720 outTi3026(minfo, TVP3026_XTRUECOLORCTRL, TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR);
721 outTi3026(minfo, TVP3026_XMUXCTRL, TVP3026_XMUXCTRL_VGA);
722
723 outTi3026(minfo, TVP3026_XPLLADDR, 0x2A);
724 outTi3026(minfo, TVP3026_XLOOPPLLDATA, 0x00);
725 outTi3026(minfo, TVP3026_XPIXPLLDATA, 0x00);
726
727 mga_outb(M_MISC_REG, 0x67);
728
729 outTi3026(minfo, TVP3026_XMEMPLLCTRL, TVP3026_XMEMPLLCTRL_STROBEMKC4 | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL);
730
731 mga_outl(M_RESET, 1);
732 udelay(250);
733 mga_outl(M_RESET, 0);
734 udelay(250);
735 mga_outl(M_MACCESS, 0x00008000);
736 udelay(10);
737 return 0;
738}
739
740struct matrox_switch matrox_millennium = {
741 Ti3026_preinit, Ti3026_reset, Ti3026_init, Ti3026_restore
742};
743EXPORT_SYMBOL(matrox_millennium);
744#endif
745MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/matrox/matroxfb_Ti3026.h b/drivers/video/fbdev/matrox/matroxfb_Ti3026.h
new file mode 100644
index 000000000000..27872aaa0a17
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_Ti3026.h
@@ -0,0 +1,11 @@
1#ifndef __MATROXFB_TI3026_H__
2#define __MATROXFB_TI3026_H__
3
4
5#include "matroxfb_base.h"
6
7#ifdef CONFIG_FB_MATROX_MILLENIUM
8extern struct matrox_switch matrox_millennium;
9#endif
10
11#endif /* __MATROXFB_TI3026_H__ */
diff --git a/drivers/video/fbdev/matrox/matroxfb_accel.c b/drivers/video/fbdev/matrox/matroxfb_accel.c
new file mode 100644
index 000000000000..0d5cb85d071a
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_accel.c
@@ -0,0 +1,519 @@
1/*
2 *
3 * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
4 *
5 * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
6 *
7 * Version: 1.65 2002/08/14
8 *
9 * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
10 *
11 * Contributors: "menion?" <menion@mindless.com>
12 * Betatesting, fixes, ideas
13 *
14 * "Kurt Garloff" <garloff@suse.de>
15 * Betatesting, fixes, ideas, videomodes, videomodes timmings
16 *
17 * "Tom Rini" <trini@kernel.crashing.org>
18 * MTRR stuff, PPC cleanups, betatesting, fixes, ideas
19 *
20 * "Bibek Sahu" <scorpio@dodds.net>
21 * Access device through readb|w|l and write b|w|l
22 * Extensive debugging stuff
23 *
24 * "Daniel Haun" <haund@usa.net>
25 * Testing, hardware cursor fixes
26 *
27 * "Scott Wood" <sawst46+@pitt.edu>
28 * Fixes
29 *
30 * "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
31 * Betatesting
32 *
33 * "Kelly French" <targon@hazmat.com>
34 * "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
35 * Betatesting, bug reporting
36 *
37 * "Pablo Bianucci" <pbian@pccp.com.ar>
38 * Fixes, ideas, betatesting
39 *
40 * "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
41 * Fixes, enhandcements, ideas, betatesting
42 *
43 * "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
44 * PPC betatesting, PPC support, backward compatibility
45 *
46 * "Paul Womar" <Paul@pwomar.demon.co.uk>
47 * "Owen Waller" <O.Waller@ee.qub.ac.uk>
48 * PPC betatesting
49 *
50 * "Thomas Pornin" <pornin@bolet.ens.fr>
51 * Alpha betatesting
52 *
53 * "Pieter van Leuven" <pvl@iae.nl>
54 * "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
55 * G100 testing
56 *
57 * "H. Peter Arvin" <hpa@transmeta.com>
58 * Ideas
59 *
60 * "Cort Dougan" <cort@cs.nmt.edu>
61 * CHRP fixes and PReP cleanup
62 *
63 * "Mark Vojkovich" <mvojkovi@ucsd.edu>
64 * G400 support
65 *
66 * (following author is not in any relation with this code, but his code
67 * is included in this driver)
68 *
69 * Based on framebuffer driver for VBE 2.0 compliant graphic boards
70 * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
71 *
72 * (following author is not in any relation with this code, but his ideas
73 * were used when writing this driver)
74 *
75 * FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
76 *
77 */
78
79#include "matroxfb_accel.h"
80#include "matroxfb_DAC1064.h"
81#include "matroxfb_Ti3026.h"
82#include "matroxfb_misc.h"
83
84#define curr_ydstorg(x) ((x)->curr.ydstorg.pixels)
85
86#define mga_ydstlen(y,l) mga_outl(M_YDSTLEN | M_EXEC, ((y) << 16) | (l))
87
88static inline void matrox_cfb4_pal(u_int32_t* pal) {
89 unsigned int i;
90
91 for (i = 0; i < 16; i++) {
92 pal[i] = i * 0x11111111U;
93 }
94}
95
96static inline void matrox_cfb8_pal(u_int32_t* pal) {
97 unsigned int i;
98
99 for (i = 0; i < 16; i++) {
100 pal[i] = i * 0x01010101U;
101 }
102}
103
104static void matroxfb_copyarea(struct fb_info* info, const struct fb_copyarea* area);
105static void matroxfb_fillrect(struct fb_info* info, const struct fb_fillrect* rect);
106static void matroxfb_imageblit(struct fb_info* info, const struct fb_image* image);
107static void matroxfb_cfb4_fillrect(struct fb_info* info, const struct fb_fillrect* rect);
108static void matroxfb_cfb4_copyarea(struct fb_info* info, const struct fb_copyarea* area);
109
110void matrox_cfbX_init(struct matrox_fb_info *minfo)
111{
112 u_int32_t maccess;
113 u_int32_t mpitch;
114 u_int32_t mopmode;
115 int accel;
116
117 DBG(__func__)
118
119 mpitch = minfo->fbcon.var.xres_virtual;
120
121 minfo->fbops.fb_copyarea = cfb_copyarea;
122 minfo->fbops.fb_fillrect = cfb_fillrect;
123 minfo->fbops.fb_imageblit = cfb_imageblit;
124 minfo->fbops.fb_cursor = NULL;
125
126 accel = (minfo->fbcon.var.accel_flags & FB_ACCELF_TEXT) == FB_ACCELF_TEXT;
127
128 switch (minfo->fbcon.var.bits_per_pixel) {
129 case 4: maccess = 0x00000000; /* accelerate as 8bpp video */
130 mpitch = (mpitch >> 1) | 0x8000; /* disable linearization */
131 mopmode = M_OPMODE_4BPP;
132 matrox_cfb4_pal(minfo->cmap);
133 if (accel && !(mpitch & 1)) {
134 minfo->fbops.fb_copyarea = matroxfb_cfb4_copyarea;
135 minfo->fbops.fb_fillrect = matroxfb_cfb4_fillrect;
136 }
137 break;
138 case 8: maccess = 0x00000000;
139 mopmode = M_OPMODE_8BPP;
140 matrox_cfb8_pal(minfo->cmap);
141 if (accel) {
142 minfo->fbops.fb_copyarea = matroxfb_copyarea;
143 minfo->fbops.fb_fillrect = matroxfb_fillrect;
144 minfo->fbops.fb_imageblit = matroxfb_imageblit;
145 }
146 break;
147 case 16: if (minfo->fbcon.var.green.length == 5)
148 maccess = 0xC0000001;
149 else
150 maccess = 0x40000001;
151 mopmode = M_OPMODE_16BPP;
152 if (accel) {
153 minfo->fbops.fb_copyarea = matroxfb_copyarea;
154 minfo->fbops.fb_fillrect = matroxfb_fillrect;
155 minfo->fbops.fb_imageblit = matroxfb_imageblit;
156 }
157 break;
158 case 24: maccess = 0x00000003;
159 mopmode = M_OPMODE_24BPP;
160 if (accel) {
161 minfo->fbops.fb_copyarea = matroxfb_copyarea;
162 minfo->fbops.fb_fillrect = matroxfb_fillrect;
163 minfo->fbops.fb_imageblit = matroxfb_imageblit;
164 }
165 break;
166 case 32: maccess = 0x00000002;
167 mopmode = M_OPMODE_32BPP;
168 if (accel) {
169 minfo->fbops.fb_copyarea = matroxfb_copyarea;
170 minfo->fbops.fb_fillrect = matroxfb_fillrect;
171 minfo->fbops.fb_imageblit = matroxfb_imageblit;
172 }
173 break;
174 default: maccess = 0x00000000;
175 mopmode = 0x00000000;
176 break; /* turn off acceleration!!! */
177 }
178 mga_fifo(8);
179 mga_outl(M_PITCH, mpitch);
180 mga_outl(M_YDSTORG, curr_ydstorg(minfo));
181 if (minfo->capable.plnwt)
182 mga_outl(M_PLNWT, -1);
183 if (minfo->capable.srcorg) {
184 mga_outl(M_SRCORG, 0);
185 mga_outl(M_DSTORG, 0);
186 }
187 mga_outl(M_OPMODE, mopmode);
188 mga_outl(M_CXBNDRY, 0xFFFF0000);
189 mga_outl(M_YTOP, 0);
190 mga_outl(M_YBOT, 0x01FFFFFF);
191 mga_outl(M_MACCESS, maccess);
192 minfo->accel.m_dwg_rect = M_DWG_TRAP | M_DWG_SOLID | M_DWG_ARZERO | M_DWG_SGNZERO | M_DWG_SHIFTZERO;
193 if (isMilleniumII(minfo)) minfo->accel.m_dwg_rect |= M_DWG_TRANSC;
194 minfo->accel.m_opmode = mopmode;
195 minfo->accel.m_access = maccess;
196 minfo->accel.m_pitch = mpitch;
197}
198
199EXPORT_SYMBOL(matrox_cfbX_init);
200
201static void matrox_accel_restore_maccess(struct matrox_fb_info *minfo)
202{
203 mga_outl(M_MACCESS, minfo->accel.m_access);
204 mga_outl(M_PITCH, minfo->accel.m_pitch);
205}
206
207static void matrox_accel_bmove(struct matrox_fb_info *minfo, int vxres, int sy,
208 int sx, int dy, int dx, int height, int width)
209{
210 int start, end;
211 CRITFLAGS
212
213 DBG(__func__)
214
215 CRITBEGIN
216
217 if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
218 mga_fifo(4);
219 matrox_accel_restore_maccess(minfo);
220 mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
221 M_DWG_BFCOL | M_DWG_REPLACE);
222 mga_outl(M_AR5, vxres);
223 width--;
224 start = sy*vxres+sx+curr_ydstorg(minfo);
225 end = start+width;
226 } else {
227 mga_fifo(5);
228 matrox_accel_restore_maccess(minfo);
229 mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
230 mga_outl(M_SGN, 5);
231 mga_outl(M_AR5, -vxres);
232 width--;
233 end = (sy+height-1)*vxres+sx+curr_ydstorg(minfo);
234 start = end+width;
235 dy += height-1;
236 }
237 mga_fifo(6);
238 matrox_accel_restore_maccess(minfo);
239 mga_outl(M_AR0, end);
240 mga_outl(M_AR3, start);
241 mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
242 mga_ydstlen(dy, height);
243 WaitTillIdle();
244
245 CRITEND
246}
247
248static void matrox_accel_bmove_lin(struct matrox_fb_info *minfo, int vxres,
249 int sy, int sx, int dy, int dx, int height,
250 int width)
251{
252 int start, end;
253 CRITFLAGS
254
255 DBG(__func__)
256
257 CRITBEGIN
258
259 if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
260 mga_fifo(4);
261 matrox_accel_restore_maccess(minfo);
262 mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
263 M_DWG_BFCOL | M_DWG_REPLACE);
264 mga_outl(M_AR5, vxres);
265 width--;
266 start = sy*vxres+sx+curr_ydstorg(minfo);
267 end = start+width;
268 } else {
269 mga_fifo(5);
270 matrox_accel_restore_maccess(minfo);
271 mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
272 mga_outl(M_SGN, 5);
273 mga_outl(M_AR5, -vxres);
274 width--;
275 end = (sy+height-1)*vxres+sx+curr_ydstorg(minfo);
276 start = end+width;
277 dy += height-1;
278 }
279 mga_fifo(7);
280 matrox_accel_restore_maccess(minfo);
281 mga_outl(M_AR0, end);
282 mga_outl(M_AR3, start);
283 mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
284 mga_outl(M_YDST, dy*vxres >> 5);
285 mga_outl(M_LEN | M_EXEC, height);
286 WaitTillIdle();
287
288 CRITEND
289}
290
291static void matroxfb_cfb4_copyarea(struct fb_info* info, const struct fb_copyarea* area) {
292 struct matrox_fb_info *minfo = info2minfo(info);
293
294 if ((area->sx | area->dx | area->width) & 1)
295 cfb_copyarea(info, area);
296 else
297 matrox_accel_bmove_lin(minfo, minfo->fbcon.var.xres_virtual >> 1, area->sy, area->sx >> 1, area->dy, area->dx >> 1, area->height, area->width >> 1);
298}
299
300static void matroxfb_copyarea(struct fb_info* info, const struct fb_copyarea* area) {
301 struct matrox_fb_info *minfo = info2minfo(info);
302
303 matrox_accel_bmove(minfo, minfo->fbcon.var.xres_virtual, area->sy, area->sx, area->dy, area->dx, area->height, area->width);
304}
305
306static void matroxfb_accel_clear(struct matrox_fb_info *minfo, u_int32_t color,
307 int sy, int sx, int height, int width)
308{
309 CRITFLAGS
310
311 DBG(__func__)
312
313 CRITBEGIN
314
315 mga_fifo(7);
316 matrox_accel_restore_maccess(minfo);
317 mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE);
318 mga_outl(M_FCOL, color);
319 mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
320 mga_ydstlen(sy, height);
321 WaitTillIdle();
322
323 CRITEND
324}
325
326static void matroxfb_fillrect(struct fb_info* info, const struct fb_fillrect* rect) {
327 struct matrox_fb_info *minfo = info2minfo(info);
328
329 switch (rect->rop) {
330 case ROP_COPY:
331 matroxfb_accel_clear(minfo, ((u_int32_t *)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width);
332 break;
333 }
334}
335
336static void matroxfb_cfb4_clear(struct matrox_fb_info *minfo, u_int32_t bgx,
337 int sy, int sx, int height, int width)
338{
339 int whattodo;
340 CRITFLAGS
341
342 DBG(__func__)
343
344 CRITBEGIN
345
346 whattodo = 0;
347 if (sx & 1) {
348 sx ++;
349 if (!width) return;
350 width --;
351 whattodo = 1;
352 }
353 if (width & 1) {
354 whattodo |= 2;
355 }
356 width >>= 1;
357 sx >>= 1;
358 if (width) {
359 mga_fifo(7);
360 matrox_accel_restore_maccess(minfo);
361 mga_outl(M_DWGCTL, minfo->accel.m_dwg_rect | M_DWG_REPLACE2);
362 mga_outl(M_FCOL, bgx);
363 mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
364 mga_outl(M_YDST, sy * minfo->fbcon.var.xres_virtual >> 6);
365 mga_outl(M_LEN | M_EXEC, height);
366 WaitTillIdle();
367 }
368 if (whattodo) {
369 u_int32_t step = minfo->fbcon.var.xres_virtual >> 1;
370 vaddr_t vbase = minfo->video.vbase;
371 if (whattodo & 1) {
372 unsigned int uaddr = sy * step + sx - 1;
373 u_int32_t loop;
374 u_int8_t bgx2 = bgx & 0xF0;
375 for (loop = height; loop > 0; loop --) {
376 mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0x0F) | bgx2);
377 uaddr += step;
378 }
379 }
380 if (whattodo & 2) {
381 unsigned int uaddr = sy * step + sx + width;
382 u_int32_t loop;
383 u_int8_t bgx2 = bgx & 0x0F;
384 for (loop = height; loop > 0; loop --) {
385 mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0xF0) | bgx2);
386 uaddr += step;
387 }
388 }
389 }
390
391 CRITEND
392}
393
394static void matroxfb_cfb4_fillrect(struct fb_info* info, const struct fb_fillrect* rect) {
395 struct matrox_fb_info *minfo = info2minfo(info);
396
397 switch (rect->rop) {
398 case ROP_COPY:
399 matroxfb_cfb4_clear(minfo, ((u_int32_t *)info->pseudo_palette)[rect->color], rect->dy, rect->dx, rect->height, rect->width);
400 break;
401 }
402}
403
404static void matroxfb_1bpp_imageblit(struct matrox_fb_info *minfo, u_int32_t fgx,
405 u_int32_t bgx, const u_int8_t *chardata,
406 int width, int height, int yy, int xx)
407{
408 u_int32_t step;
409 u_int32_t ydstlen;
410 u_int32_t xlen;
411 u_int32_t ar0;
412 u_int32_t charcell;
413 u_int32_t fxbndry;
414 vaddr_t mmio;
415 int easy;
416 CRITFLAGS
417
418 DBG_HEAVY(__func__);
419
420 step = (width + 7) >> 3;
421 charcell = height * step;
422 xlen = (charcell + 3) & ~3;
423 ydstlen = (yy << 16) | height;
424 if (width == step << 3) {
425 ar0 = height * width - 1;
426 easy = 1;
427 } else {
428 ar0 = width - 1;
429 easy = 0;
430 }
431
432 CRITBEGIN
433
434 mga_fifo(5);
435 matrox_accel_restore_maccess(minfo);
436 if (easy)
437 mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
438 else
439 mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_REPLACE);
440 mga_outl(M_FCOL, fgx);
441 mga_outl(M_BCOL, bgx);
442 fxbndry = ((xx + width - 1) << 16) | xx;
443 mmio = minfo->mmio.vbase;
444
445 mga_fifo(8);
446 matrox_accel_restore_maccess(minfo);
447 mga_writel(mmio, M_FXBNDRY, fxbndry);
448 mga_writel(mmio, M_AR0, ar0);
449 mga_writel(mmio, M_AR3, 0);
450 if (easy) {
451 mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen);
452 mga_memcpy_toio(mmio, chardata, xlen);
453 } else {
454 mga_writel(mmio, M_AR5, 0);
455 mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen);
456 if ((step & 3) == 0) {
457 /* Great. Source has 32bit aligned lines, so we can feed them
458 directly to the accelerator. */
459 mga_memcpy_toio(mmio, chardata, charcell);
460 } else if (step == 1) {
461 /* Special case for 1..8bit widths */
462 while (height--) {
463#if defined(__BIG_ENDIAN)
464 fb_writel((*chardata) << 24, mmio.vaddr);
465#else
466 fb_writel(*chardata, mmio.vaddr);
467#endif
468 chardata++;
469 }
470 } else if (step == 2) {
471 /* Special case for 9..15bit widths */
472 while (height--) {
473#if defined(__BIG_ENDIAN)
474 fb_writel((*(u_int16_t*)chardata) << 16, mmio.vaddr);
475#else
476 fb_writel(*(u_int16_t*)chardata, mmio.vaddr);
477#endif
478 chardata += 2;
479 }
480 } else {
481 /* Tell... well, why bother... */
482 while (height--) {
483 size_t i;
484
485 for (i = 0; i < step; i += 4) {
486 /* Hope that there are at least three readable bytes beyond the end of bitmap */
487 fb_writel(get_unaligned((u_int32_t*)(chardata + i)),mmio.vaddr);
488 }
489 chardata += step;
490 }
491 }
492 }
493 WaitTillIdle();
494 CRITEND
495}
496
497
498static void matroxfb_imageblit(struct fb_info* info, const struct fb_image* image) {
499 struct matrox_fb_info *minfo = info2minfo(info);
500
501 DBG_HEAVY(__func__);
502
503 if (image->depth == 1) {
504 u_int32_t fgx, bgx;
505
506 fgx = ((u_int32_t*)info->pseudo_palette)[image->fg_color];
507 bgx = ((u_int32_t*)info->pseudo_palette)[image->bg_color];
508 matroxfb_1bpp_imageblit(minfo, fgx, bgx, image->data, image->width, image->height, image->dy, image->dx);
509 } else {
510 /* Danger! image->depth is useless: logo painting code always
511 passes framebuffer color depth here, although logo data are
512 always 8bpp and info->pseudo_palette is changed to contain
513 logo palette to be used (but only for true/direct-color... sic...).
514 So do it completely in software... */
515 cfb_imageblit(info, image);
516 }
517}
518
519MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/matrox/matroxfb_accel.h b/drivers/video/fbdev/matrox/matroxfb_accel.h
new file mode 100644
index 000000000000..1e418e62c22d
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_accel.h
@@ -0,0 +1,8 @@
1#ifndef __MATROXFB_ACCEL_H__
2#define __MATROXFB_ACCEL_H__
3
4#include "matroxfb_base.h"
5
6void matrox_cfbX_init(struct matrox_fb_info *minfo);
7
8#endif
diff --git a/drivers/video/fbdev/matrox/matroxfb_base.c b/drivers/video/fbdev/matrox/matroxfb_base.c
new file mode 100644
index 000000000000..7116c5309c7d
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_base.c
@@ -0,0 +1,2584 @@
1/*
2 *
3 * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
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 * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
12 *
13 * Contributors: "menion?" <menion@mindless.com>
14 * Betatesting, fixes, ideas
15 *
16 * "Kurt Garloff" <garloff@suse.de>
17 * Betatesting, fixes, ideas, videomodes, videomodes timmings
18 *
19 * "Tom Rini" <trini@kernel.crashing.org>
20 * MTRR stuff, PPC cleanups, betatesting, fixes, ideas
21 *
22 * "Bibek Sahu" <scorpio@dodds.net>
23 * Access device through readb|w|l and write b|w|l
24 * Extensive debugging stuff
25 *
26 * "Daniel Haun" <haund@usa.net>
27 * Testing, hardware cursor fixes
28 *
29 * "Scott Wood" <sawst46+@pitt.edu>
30 * Fixes
31 *
32 * "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
33 * Betatesting
34 *
35 * "Kelly French" <targon@hazmat.com>
36 * "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
37 * Betatesting, bug reporting
38 *
39 * "Pablo Bianucci" <pbian@pccp.com.ar>
40 * Fixes, ideas, betatesting
41 *
42 * "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
43 * Fixes, enhandcements, ideas, betatesting
44 *
45 * "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
46 * PPC betatesting, PPC support, backward compatibility
47 *
48 * "Paul Womar" <Paul@pwomar.demon.co.uk>
49 * "Owen Waller" <O.Waller@ee.qub.ac.uk>
50 * PPC betatesting
51 *
52 * "Thomas Pornin" <pornin@bolet.ens.fr>
53 * Alpha betatesting
54 *
55 * "Pieter van Leuven" <pvl@iae.nl>
56 * "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
57 * G100 testing
58 *
59 * "H. Peter Arvin" <hpa@transmeta.com>
60 * Ideas
61 *
62 * "Cort Dougan" <cort@cs.nmt.edu>
63 * CHRP fixes and PReP cleanup
64 *
65 * "Mark Vojkovich" <mvojkovi@ucsd.edu>
66 * G400 support
67 *
68 * "Samuel Hocevar" <sam@via.ecp.fr>
69 * Fixes
70 *
71 * "Anton Altaparmakov" <AntonA@bigfoot.com>
72 * G400 MAX/non-MAX distinction
73 *
74 * "Ken Aaker" <kdaaker@rchland.vnet.ibm.com>
75 * memtype extension (needed for GXT130P RS/6000 adapter)
76 *
77 * "Uns Lider" <unslider@miranda.org>
78 * G100 PLNWT fixes
79 *
80 * "Denis Zaitsev" <zzz@cd-club.ru>
81 * Fixes
82 *
83 * "Mike Pieper" <mike@pieper-family.de>
84 * TVOut enhandcements, V4L2 control interface.
85 *
86 * "Diego Biurrun" <diego@biurrun.de>
87 * DFP testing
88 *
89 * (following author is not in any relation with this code, but his code
90 * is included in this driver)
91 *
92 * Based on framebuffer driver for VBE 2.0 compliant graphic boards
93 * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
94 *
95 * (following author is not in any relation with this code, but his ideas
96 * were used when writing this driver)
97 *
98 * FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
99 *
100 */
101
102#include <linux/version.h>
103
104#include "matroxfb_base.h"
105#include "matroxfb_misc.h"
106#include "matroxfb_accel.h"
107#include "matroxfb_DAC1064.h"
108#include "matroxfb_Ti3026.h"
109#include "matroxfb_maven.h"
110#include "matroxfb_crtc2.h"
111#include "matroxfb_g450.h"
112#include <linux/matroxfb.h>
113#include <linux/interrupt.h>
114#include <linux/slab.h>
115#include <linux/uaccess.h>
116
117#ifdef CONFIG_PPC_PMAC
118#include <asm/machdep.h>
119unsigned char nvram_read_byte(int);
120static int default_vmode = VMODE_NVRAM;
121static int default_cmode = CMODE_NVRAM;
122#endif
123
124static void matroxfb_unregister_device(struct matrox_fb_info* minfo);
125
126/* --------------------------------------------------------------------- */
127
128/*
129 * card parameters
130 */
131
132/* --------------------------------------------------------------------- */
133
134static struct fb_var_screeninfo vesafb_defined = {
135 640,480,640,480,/* W,H, W, H (virtual) load xres,xres_virtual*/
136 0,0, /* virtual -> visible no offset */
137 8, /* depth -> load bits_per_pixel */
138 0, /* greyscale ? */
139 {0,0,0}, /* R */
140 {0,0,0}, /* G */
141 {0,0,0}, /* B */
142 {0,0,0}, /* transparency */
143 0, /* standard pixel format */
144 FB_ACTIVATE_NOW,
145 -1,-1,
146 FB_ACCELF_TEXT, /* accel flags */
147 39721L,48L,16L,33L,10L,
148 96L,2L,~0, /* No sync info */
149 FB_VMODE_NONINTERLACED,
150};
151
152
153
154/* --------------------------------------------------------------------- */
155static void update_crtc2(struct matrox_fb_info *minfo, unsigned int pos)
156{
157 struct matroxfb_dh_fb_info *info = minfo->crtc2.info;
158
159 /* Make sure that displays are compatible */
160 if (info && (info->fbcon.var.bits_per_pixel == minfo->fbcon.var.bits_per_pixel)
161 && (info->fbcon.var.xres_virtual == minfo->fbcon.var.xres_virtual)
162 && (info->fbcon.var.green.length == minfo->fbcon.var.green.length)
163 ) {
164 switch (minfo->fbcon.var.bits_per_pixel) {
165 case 16:
166 case 32:
167 pos = pos * 8;
168 if (info->interlaced) {
169 mga_outl(0x3C2C, pos);
170 mga_outl(0x3C28, pos + minfo->fbcon.var.xres_virtual * minfo->fbcon.var.bits_per_pixel / 8);
171 } else {
172 mga_outl(0x3C28, pos);
173 }
174 break;
175 }
176 }
177}
178
179static void matroxfb_crtc1_panpos(struct matrox_fb_info *minfo)
180{
181 if (minfo->crtc1.panpos >= 0) {
182 unsigned long flags;
183 int panpos;
184
185 matroxfb_DAC_lock_irqsave(flags);
186 panpos = minfo->crtc1.panpos;
187 if (panpos >= 0) {
188 unsigned int extvga_reg;
189
190 minfo->crtc1.panpos = -1; /* No update pending anymore */
191 extvga_reg = mga_inb(M_EXTVGA_INDEX);
192 mga_setr(M_EXTVGA_INDEX, 0x00, panpos);
193 if (extvga_reg != 0x00) {
194 mga_outb(M_EXTVGA_INDEX, extvga_reg);
195 }
196 }
197 matroxfb_DAC_unlock_irqrestore(flags);
198 }
199}
200
201static irqreturn_t matrox_irq(int irq, void *dev_id)
202{
203 u_int32_t status;
204 int handled = 0;
205 struct matrox_fb_info *minfo = dev_id;
206
207 status = mga_inl(M_STATUS);
208
209 if (status & 0x20) {
210 mga_outl(M_ICLEAR, 0x20);
211 minfo->crtc1.vsync.cnt++;
212 matroxfb_crtc1_panpos(minfo);
213 wake_up_interruptible(&minfo->crtc1.vsync.wait);
214 handled = 1;
215 }
216 if (status & 0x200) {
217 mga_outl(M_ICLEAR, 0x200);
218 minfo->crtc2.vsync.cnt++;
219 wake_up_interruptible(&minfo->crtc2.vsync.wait);
220 handled = 1;
221 }
222 return IRQ_RETVAL(handled);
223}
224
225int matroxfb_enable_irq(struct matrox_fb_info *minfo, int reenable)
226{
227 u_int32_t bm;
228
229 if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400)
230 bm = 0x220;
231 else
232 bm = 0x020;
233
234 if (!test_and_set_bit(0, &minfo->irq_flags)) {
235 if (request_irq(minfo->pcidev->irq, matrox_irq,
236 IRQF_SHARED, "matroxfb", minfo)) {
237 clear_bit(0, &minfo->irq_flags);
238 return -EINVAL;
239 }
240 /* Clear any pending field interrupts */
241 mga_outl(M_ICLEAR, bm);
242 mga_outl(M_IEN, mga_inl(M_IEN) | bm);
243 } else if (reenable) {
244 u_int32_t ien;
245
246 ien = mga_inl(M_IEN);
247 if ((ien & bm) != bm) {
248 printk(KERN_DEBUG "matroxfb: someone disabled IRQ [%08X]\n", ien);
249 mga_outl(M_IEN, ien | bm);
250 }
251 }
252 return 0;
253}
254
255static void matroxfb_disable_irq(struct matrox_fb_info *minfo)
256{
257 if (test_and_clear_bit(0, &minfo->irq_flags)) {
258 /* Flush pending pan-at-vbl request... */
259 matroxfb_crtc1_panpos(minfo);
260 if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400)
261 mga_outl(M_IEN, mga_inl(M_IEN) & ~0x220);
262 else
263 mga_outl(M_IEN, mga_inl(M_IEN) & ~0x20);
264 free_irq(minfo->pcidev->irq, minfo);
265 }
266}
267
268int matroxfb_wait_for_sync(struct matrox_fb_info *minfo, u_int32_t crtc)
269{
270 struct matrox_vsync *vs;
271 unsigned int cnt;
272 int ret;
273
274 switch (crtc) {
275 case 0:
276 vs = &minfo->crtc1.vsync;
277 break;
278 case 1:
279 if (minfo->devflags.accelerator != FB_ACCEL_MATROX_MGAG400) {
280 return -ENODEV;
281 }
282 vs = &minfo->crtc2.vsync;
283 break;
284 default:
285 return -ENODEV;
286 }
287 ret = matroxfb_enable_irq(minfo, 0);
288 if (ret) {
289 return ret;
290 }
291
292 cnt = vs->cnt;
293 ret = wait_event_interruptible_timeout(vs->wait, cnt != vs->cnt, HZ/10);
294 if (ret < 0) {
295 return ret;
296 }
297 if (ret == 0) {
298 matroxfb_enable_irq(minfo, 1);
299 return -ETIMEDOUT;
300 }
301 return 0;
302}
303
304/* --------------------------------------------------------------------- */
305
306static void matrox_pan_var(struct matrox_fb_info *minfo,
307 struct fb_var_screeninfo *var)
308{
309 unsigned int pos;
310 unsigned short p0, p1, p2;
311 unsigned int p3;
312 int vbl;
313 unsigned long flags;
314
315 CRITFLAGS
316
317 DBG(__func__)
318
319 if (minfo->dead)
320 return;
321
322 minfo->fbcon.var.xoffset = var->xoffset;
323 minfo->fbcon.var.yoffset = var->yoffset;
324 pos = (minfo->fbcon.var.yoffset * minfo->fbcon.var.xres_virtual + minfo->fbcon.var.xoffset) * minfo->curr.final_bppShift / 32;
325 pos += minfo->curr.ydstorg.chunks;
326 p0 = minfo->hw.CRTC[0x0D] = pos & 0xFF;
327 p1 = minfo->hw.CRTC[0x0C] = (pos & 0xFF00) >> 8;
328 p2 = minfo->hw.CRTCEXT[0] = (minfo->hw.CRTCEXT[0] & 0xB0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40);
329 p3 = minfo->hw.CRTCEXT[8] = pos >> 21;
330
331 /* FB_ACTIVATE_VBL and we can acquire interrupts? Honor FB_ACTIVATE_VBL then... */
332 vbl = (var->activate & FB_ACTIVATE_VBL) && (matroxfb_enable_irq(minfo, 0) == 0);
333
334 CRITBEGIN
335
336 matroxfb_DAC_lock_irqsave(flags);
337 mga_setr(M_CRTC_INDEX, 0x0D, p0);
338 mga_setr(M_CRTC_INDEX, 0x0C, p1);
339 if (minfo->devflags.support32MB)
340 mga_setr(M_EXTVGA_INDEX, 0x08, p3);
341 if (vbl) {
342 minfo->crtc1.panpos = p2;
343 } else {
344 /* Abort any pending change */
345 minfo->crtc1.panpos = -1;
346 mga_setr(M_EXTVGA_INDEX, 0x00, p2);
347 }
348 matroxfb_DAC_unlock_irqrestore(flags);
349
350 update_crtc2(minfo, pos);
351
352 CRITEND
353}
354
355static void matroxfb_remove(struct matrox_fb_info *minfo, int dummy)
356{
357 /* Currently we are holding big kernel lock on all dead & usecount updates.
358 * Destroy everything after all users release it. Especially do not unregister
359 * framebuffer and iounmap memory, neither fbmem nor fbcon-cfb* does not check
360 * for device unplugged when in use.
361 * In future we should point mmio.vbase & video.vbase somewhere where we can
362 * write data without causing too much damage...
363 */
364
365 minfo->dead = 1;
366 if (minfo->usecount) {
367 /* destroy it later */
368 return;
369 }
370 matroxfb_unregister_device(minfo);
371 unregister_framebuffer(&minfo->fbcon);
372 matroxfb_g450_shutdown(minfo);
373#ifdef CONFIG_MTRR
374 if (minfo->mtrr.vram_valid)
375 mtrr_del(minfo->mtrr.vram, minfo->video.base, minfo->video.len);
376#endif
377 mga_iounmap(minfo->mmio.vbase);
378 mga_iounmap(minfo->video.vbase);
379 release_mem_region(minfo->video.base, minfo->video.len_maximum);
380 release_mem_region(minfo->mmio.base, 16384);
381 kfree(minfo);
382}
383
384 /*
385 * Open/Release the frame buffer device
386 */
387
388static int matroxfb_open(struct fb_info *info, int user)
389{
390 struct matrox_fb_info *minfo = info2minfo(info);
391
392 DBG_LOOP(__func__)
393
394 if (minfo->dead) {
395 return -ENXIO;
396 }
397 minfo->usecount++;
398 if (user) {
399 minfo->userusecount++;
400 }
401 return(0);
402}
403
404static int matroxfb_release(struct fb_info *info, int user)
405{
406 struct matrox_fb_info *minfo = info2minfo(info);
407
408 DBG_LOOP(__func__)
409
410 if (user) {
411 if (0 == --minfo->userusecount) {
412 matroxfb_disable_irq(minfo);
413 }
414 }
415 if (!(--minfo->usecount) && minfo->dead) {
416 matroxfb_remove(minfo, 0);
417 }
418 return(0);
419}
420
421static int matroxfb_pan_display(struct fb_var_screeninfo *var,
422 struct fb_info* info) {
423 struct matrox_fb_info *minfo = info2minfo(info);
424
425 DBG(__func__)
426
427 matrox_pan_var(minfo, var);
428 return 0;
429}
430
431static int matroxfb_get_final_bppShift(const struct matrox_fb_info *minfo,
432 int bpp)
433{
434 int bppshft2;
435
436 DBG(__func__)
437
438 bppshft2 = bpp;
439 if (!bppshft2) {
440 return 8;
441 }
442 if (isInterleave(minfo))
443 bppshft2 >>= 1;
444 if (minfo->devflags.video64bits)
445 bppshft2 >>= 1;
446 return bppshft2;
447}
448
449static int matroxfb_test_and_set_rounding(const struct matrox_fb_info *minfo,
450 int xres, int bpp)
451{
452 int over;
453 int rounding;
454
455 DBG(__func__)
456
457 switch (bpp) {
458 case 0: return xres;
459 case 4: rounding = 128;
460 break;
461 case 8: rounding = 64; /* doc says 64; 32 is OK for G400 */
462 break;
463 case 16: rounding = 32;
464 break;
465 case 24: rounding = 64; /* doc says 64; 32 is OK for G400 */
466 break;
467 default: rounding = 16;
468 /* on G400, 16 really does not work */
469 if (minfo->devflags.accelerator == FB_ACCEL_MATROX_MGAG400)
470 rounding = 32;
471 break;
472 }
473 if (isInterleave(minfo)) {
474 rounding *= 2;
475 }
476 over = xres % rounding;
477 if (over)
478 xres += rounding-over;
479 return xres;
480}
481
482static int matroxfb_pitch_adjust(const struct matrox_fb_info *minfo, int xres,
483 int bpp)
484{
485 const int* width;
486 int xres_new;
487
488 DBG(__func__)
489
490 if (!bpp) return xres;
491
492 width = minfo->capable.vxres;
493
494 if (minfo->devflags.precise_width) {
495 while (*width) {
496 if ((*width >= xres) && (matroxfb_test_and_set_rounding(minfo, *width, bpp) == *width)) {
497 break;
498 }
499 width++;
500 }
501 xres_new = *width;
502 } else {
503 xres_new = matroxfb_test_and_set_rounding(minfo, xres, bpp);
504 }
505 return xres_new;
506}
507
508static int matroxfb_get_cmap_len(struct fb_var_screeninfo *var) {
509
510 DBG(__func__)
511
512 switch (var->bits_per_pixel) {
513 case 4:
514 return 16; /* pseudocolor... 16 entries HW palette */
515 case 8:
516 return 256; /* pseudocolor... 256 entries HW palette */
517 case 16:
518 return 16; /* directcolor... 16 entries SW palette */
519 /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
520 case 24:
521 return 16; /* directcolor... 16 entries SW palette */
522 /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
523 case 32:
524 return 16; /* directcolor... 16 entries SW palette */
525 /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
526 }
527 return 16; /* return something reasonable... or panic()? */
528}
529
530static int matroxfb_decode_var(const struct matrox_fb_info *minfo,
531 struct fb_var_screeninfo *var, int *visual,
532 int *video_cmap_len, unsigned int* ydstorg)
533{
534 struct RGBT {
535 unsigned char bpp;
536 struct {
537 unsigned char offset,
538 length;
539 } red,
540 green,
541 blue,
542 transp;
543 signed char visual;
544 };
545 static const struct RGBT table[]= {
546 { 8,{ 0,8},{0,8},{0,8},{ 0,0},MX_VISUAL_PSEUDOCOLOR},
547 {15,{10,5},{5,5},{0,5},{15,1},MX_VISUAL_DIRECTCOLOR},
548 {16,{11,5},{5,6},{0,5},{ 0,0},MX_VISUAL_DIRECTCOLOR},
549 {24,{16,8},{8,8},{0,8},{ 0,0},MX_VISUAL_DIRECTCOLOR},
550 {32,{16,8},{8,8},{0,8},{24,8},MX_VISUAL_DIRECTCOLOR}
551 };
552 struct RGBT const *rgbt;
553 unsigned int bpp = var->bits_per_pixel;
554 unsigned int vramlen;
555 unsigned int memlen;
556
557 DBG(__func__)
558
559 switch (bpp) {
560 case 4: if (!minfo->capable.cfb4) return -EINVAL;
561 break;
562 case 8: break;
563 case 16: break;
564 case 24: break;
565 case 32: break;
566 default: return -EINVAL;
567 }
568 *ydstorg = 0;
569 vramlen = minfo->video.len_usable;
570 if (var->yres_virtual < var->yres)
571 var->yres_virtual = var->yres;
572 if (var->xres_virtual < var->xres)
573 var->xres_virtual = var->xres;
574
575 var->xres_virtual = matroxfb_pitch_adjust(minfo, var->xres_virtual, bpp);
576 memlen = var->xres_virtual * bpp * var->yres_virtual / 8;
577 if (memlen > vramlen) {
578 var->yres_virtual = vramlen * 8 / (var->xres_virtual * bpp);
579 memlen = var->xres_virtual * bpp * var->yres_virtual / 8;
580 }
581 /* There is hardware bug that no line can cross 4MB boundary */
582 /* give up for CFB24, it is impossible to easy workaround it */
583 /* for other try to do something */
584 if (!minfo->capable.cross4MB && (memlen > 0x400000)) {
585 if (bpp == 24) {
586 /* sorry */
587 } else {
588 unsigned int linelen;
589 unsigned int m1 = linelen = var->xres_virtual * bpp / 8;
590 unsigned int m2 = PAGE_SIZE; /* or 128 if you do not need PAGE ALIGNED address */
591 unsigned int max_yres;
592
593 while (m1) {
594 int t;
595
596 while (m2 >= m1) m2 -= m1;
597 t = m1;
598 m1 = m2;
599 m2 = t;
600 }
601 m2 = linelen * PAGE_SIZE / m2;
602 *ydstorg = m2 = 0x400000 % m2;
603 max_yres = (vramlen - m2) / linelen;
604 if (var->yres_virtual > max_yres)
605 var->yres_virtual = max_yres;
606 }
607 }
608 /* YDSTLEN contains only signed 16bit value */
609 if (var->yres_virtual > 32767)
610 var->yres_virtual = 32767;
611 /* we must round yres/xres down, we already rounded y/xres_virtual up
612 if it was possible. We should return -EINVAL, but I disagree */
613 if (var->yres_virtual < var->yres)
614 var->yres = var->yres_virtual;
615 if (var->xres_virtual < var->xres)
616 var->xres = var->xres_virtual;
617 if (var->xoffset + var->xres > var->xres_virtual)
618 var->xoffset = var->xres_virtual - var->xres;
619 if (var->yoffset + var->yres > var->yres_virtual)
620 var->yoffset = var->yres_virtual - var->yres;
621
622 if (bpp == 16 && var->green.length == 5) {
623 bpp--; /* an artificial value - 15 */
624 }
625
626 for (rgbt = table; rgbt->bpp < bpp; rgbt++);
627#define SETCLR(clr)\
628 var->clr.offset = rgbt->clr.offset;\
629 var->clr.length = rgbt->clr.length
630 SETCLR(red);
631 SETCLR(green);
632 SETCLR(blue);
633 SETCLR(transp);
634#undef SETCLR
635 *visual = rgbt->visual;
636
637 if (bpp > 8)
638 dprintk("matroxfb: truecolor: "
639 "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n",
640 var->transp.length, var->red.length, var->green.length, var->blue.length,
641 var->transp.offset, var->red.offset, var->green.offset, var->blue.offset);
642
643 *video_cmap_len = matroxfb_get_cmap_len(var);
644 dprintk(KERN_INFO "requested %d*%d/%dbpp (%d*%d)\n", var->xres, var->yres, var->bits_per_pixel,
645 var->xres_virtual, var->yres_virtual);
646 return 0;
647}
648
649static int matroxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
650 unsigned blue, unsigned transp,
651 struct fb_info *fb_info)
652{
653 struct matrox_fb_info* minfo = container_of(fb_info, struct matrox_fb_info, fbcon);
654
655 DBG(__func__)
656
657 /*
658 * Set a single color register. The values supplied are
659 * already rounded down to the hardware's capabilities
660 * (according to the entries in the `var' structure). Return
661 * != 0 for invalid regno.
662 */
663
664 if (regno >= minfo->curr.cmap_len)
665 return 1;
666
667 if (minfo->fbcon.var.grayscale) {
668 /* gray = 0.30*R + 0.59*G + 0.11*B */
669 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
670 }
671
672 red = CNVT_TOHW(red, minfo->fbcon.var.red.length);
673 green = CNVT_TOHW(green, minfo->fbcon.var.green.length);
674 blue = CNVT_TOHW(blue, minfo->fbcon.var.blue.length);
675 transp = CNVT_TOHW(transp, minfo->fbcon.var.transp.length);
676
677 switch (minfo->fbcon.var.bits_per_pixel) {
678 case 4:
679 case 8:
680 mga_outb(M_DAC_REG, regno);
681 mga_outb(M_DAC_VAL, red);
682 mga_outb(M_DAC_VAL, green);
683 mga_outb(M_DAC_VAL, blue);
684 break;
685 case 16:
686 if (regno >= 16)
687 break;
688 {
689 u_int16_t col =
690 (red << minfo->fbcon.var.red.offset) |
691 (green << minfo->fbcon.var.green.offset) |
692 (blue << minfo->fbcon.var.blue.offset) |
693 (transp << minfo->fbcon.var.transp.offset); /* for 1:5:5:5 */
694 minfo->cmap[regno] = col | (col << 16);
695 }
696 break;
697 case 24:
698 case 32:
699 if (regno >= 16)
700 break;
701 minfo->cmap[regno] =
702 (red << minfo->fbcon.var.red.offset) |
703 (green << minfo->fbcon.var.green.offset) |
704 (blue << minfo->fbcon.var.blue.offset) |
705 (transp << minfo->fbcon.var.transp.offset); /* 8:8:8:8 */
706 break;
707 }
708 return 0;
709}
710
711static void matroxfb_init_fix(struct matrox_fb_info *minfo)
712{
713 struct fb_fix_screeninfo *fix = &minfo->fbcon.fix;
714 DBG(__func__)
715
716 strcpy(fix->id,"MATROX");
717
718 fix->xpanstep = 8; /* 8 for 8bpp, 4 for 16bpp, 2 for 32bpp */
719 fix->ypanstep = 1;
720 fix->ywrapstep = 0;
721 fix->mmio_start = minfo->mmio.base;
722 fix->mmio_len = minfo->mmio.len;
723 fix->accel = minfo->devflags.accelerator;
724}
725
726static void matroxfb_update_fix(struct matrox_fb_info *minfo)
727{
728 struct fb_fix_screeninfo *fix = &minfo->fbcon.fix;
729 DBG(__func__)
730
731 mutex_lock(&minfo->fbcon.mm_lock);
732 fix->smem_start = minfo->video.base + minfo->curr.ydstorg.bytes;
733 fix->smem_len = minfo->video.len_usable - minfo->curr.ydstorg.bytes;
734 mutex_unlock(&minfo->fbcon.mm_lock);
735}
736
737static int matroxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
738{
739 int err;
740 int visual;
741 int cmap_len;
742 unsigned int ydstorg;
743 struct matrox_fb_info *minfo = info2minfo(info);
744
745 if (minfo->dead) {
746 return -ENXIO;
747 }
748 if ((err = matroxfb_decode_var(minfo, var, &visual, &cmap_len, &ydstorg)) != 0)
749 return err;
750 return 0;
751}
752
753static int matroxfb_set_par(struct fb_info *info)
754{
755 int err;
756 int visual;
757 int cmap_len;
758 unsigned int ydstorg;
759 struct fb_var_screeninfo *var;
760 struct matrox_fb_info *minfo = info2minfo(info);
761
762 DBG(__func__)
763
764 if (minfo->dead) {
765 return -ENXIO;
766 }
767
768 var = &info->var;
769 if ((err = matroxfb_decode_var(minfo, var, &visual, &cmap_len, &ydstorg)) != 0)
770 return err;
771 minfo->fbcon.screen_base = vaddr_va(minfo->video.vbase) + ydstorg;
772 matroxfb_update_fix(minfo);
773 minfo->fbcon.fix.visual = visual;
774 minfo->fbcon.fix.type = FB_TYPE_PACKED_PIXELS;
775 minfo->fbcon.fix.type_aux = 0;
776 minfo->fbcon.fix.line_length = (var->xres_virtual * var->bits_per_pixel) >> 3;
777 {
778 unsigned int pos;
779
780 minfo->curr.cmap_len = cmap_len;
781 ydstorg += minfo->devflags.ydstorg;
782 minfo->curr.ydstorg.bytes = ydstorg;
783 minfo->curr.ydstorg.chunks = ydstorg >> (isInterleave(minfo) ? 3 : 2);
784 if (var->bits_per_pixel == 4)
785 minfo->curr.ydstorg.pixels = ydstorg;
786 else
787 minfo->curr.ydstorg.pixels = (ydstorg * 8) / var->bits_per_pixel;
788 minfo->curr.final_bppShift = matroxfb_get_final_bppShift(minfo, var->bits_per_pixel);
789 { struct my_timming mt;
790 struct matrox_hw_state* hw;
791 int out;
792
793 matroxfb_var2my(var, &mt);
794 mt.crtc = MATROXFB_SRC_CRTC1;
795 /* CRTC1 delays */
796 switch (var->bits_per_pixel) {
797 case 0: mt.delay = 31 + 0; break;
798 case 16: mt.delay = 21 + 8; break;
799 case 24: mt.delay = 17 + 8; break;
800 case 32: mt.delay = 16 + 8; break;
801 default: mt.delay = 31 + 8; break;
802 }
803
804 hw = &minfo->hw;
805
806 down_read(&minfo->altout.lock);
807 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
808 if (minfo->outputs[out].src == MATROXFB_SRC_CRTC1 &&
809 minfo->outputs[out].output->compute) {
810 minfo->outputs[out].output->compute(minfo->outputs[out].data, &mt);
811 }
812 }
813 up_read(&minfo->altout.lock);
814 minfo->crtc1.pixclock = mt.pixclock;
815 minfo->crtc1.mnp = mt.mnp;
816 minfo->hw_switch->init(minfo, &mt);
817 pos = (var->yoffset * var->xres_virtual + var->xoffset) * minfo->curr.final_bppShift / 32;
818 pos += minfo->curr.ydstorg.chunks;
819
820 hw->CRTC[0x0D] = pos & 0xFF;
821 hw->CRTC[0x0C] = (pos & 0xFF00) >> 8;
822 hw->CRTCEXT[0] = (hw->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40);
823 hw->CRTCEXT[8] = pos >> 21;
824 minfo->hw_switch->restore(minfo);
825 update_crtc2(minfo, pos);
826 down_read(&minfo->altout.lock);
827 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
828 if (minfo->outputs[out].src == MATROXFB_SRC_CRTC1 &&
829 minfo->outputs[out].output->program) {
830 minfo->outputs[out].output->program(minfo->outputs[out].data);
831 }
832 }
833 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
834 if (minfo->outputs[out].src == MATROXFB_SRC_CRTC1 &&
835 minfo->outputs[out].output->start) {
836 minfo->outputs[out].output->start(minfo->outputs[out].data);
837 }
838 }
839 up_read(&minfo->altout.lock);
840 matrox_cfbX_init(minfo);
841 }
842 }
843 minfo->initialized = 1;
844 return 0;
845}
846
847static int matroxfb_get_vblank(struct matrox_fb_info *minfo,
848 struct fb_vblank *vblank)
849{
850 unsigned int sts1;
851
852 matroxfb_enable_irq(minfo, 0);
853 memset(vblank, 0, sizeof(*vblank));
854 vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VSYNC |
855 FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_HBLANK;
856 sts1 = mga_inb(M_INSTS1);
857 vblank->vcount = mga_inl(M_VCOUNT);
858 /* BTW, on my PIII/450 with G400, reading M_INSTS1
859 byte makes this call about 12% slower (1.70 vs. 2.05 us
860 per ioctl()) */
861 if (sts1 & 1)
862 vblank->flags |= FB_VBLANK_HBLANKING;
863 if (sts1 & 8)
864 vblank->flags |= FB_VBLANK_VSYNCING;
865 if (vblank->vcount >= minfo->fbcon.var.yres)
866 vblank->flags |= FB_VBLANK_VBLANKING;
867 if (test_bit(0, &minfo->irq_flags)) {
868 vblank->flags |= FB_VBLANK_HAVE_COUNT;
869 /* Only one writer, aligned int value...
870 it should work without lock and without atomic_t */
871 vblank->count = minfo->crtc1.vsync.cnt;
872 }
873 return 0;
874}
875
876static struct matrox_altout panellink_output = {
877 .name = "Panellink output",
878};
879
880static int matroxfb_ioctl(struct fb_info *info,
881 unsigned int cmd, unsigned long arg)
882{
883 void __user *argp = (void __user *)arg;
884 struct matrox_fb_info *minfo = info2minfo(info);
885
886 DBG(__func__)
887
888 if (minfo->dead) {
889 return -ENXIO;
890 }
891
892 switch (cmd) {
893 case FBIOGET_VBLANK:
894 {
895 struct fb_vblank vblank;
896 int err;
897
898 err = matroxfb_get_vblank(minfo, &vblank);
899 if (err)
900 return err;
901 if (copy_to_user(argp, &vblank, sizeof(vblank)))
902 return -EFAULT;
903 return 0;
904 }
905 case FBIO_WAITFORVSYNC:
906 {
907 u_int32_t crt;
908
909 if (get_user(crt, (u_int32_t __user *)arg))
910 return -EFAULT;
911
912 return matroxfb_wait_for_sync(minfo, crt);
913 }
914 case MATROXFB_SET_OUTPUT_MODE:
915 {
916 struct matroxioc_output_mode mom;
917 struct matrox_altout *oproc;
918 int val;
919
920 if (copy_from_user(&mom, argp, sizeof(mom)))
921 return -EFAULT;
922 if (mom.output >= MATROXFB_MAX_OUTPUTS)
923 return -ENXIO;
924 down_read(&minfo->altout.lock);
925 oproc = minfo->outputs[mom.output].output;
926 if (!oproc) {
927 val = -ENXIO;
928 } else if (!oproc->verifymode) {
929 if (mom.mode == MATROXFB_OUTPUT_MODE_MONITOR) {
930 val = 0;
931 } else {
932 val = -EINVAL;
933 }
934 } else {
935 val = oproc->verifymode(minfo->outputs[mom.output].data, mom.mode);
936 }
937 if (!val) {
938 if (minfo->outputs[mom.output].mode != mom.mode) {
939 minfo->outputs[mom.output].mode = mom.mode;
940 val = 1;
941 }
942 }
943 up_read(&minfo->altout.lock);
944 if (val != 1)
945 return val;
946 switch (minfo->outputs[mom.output].src) {
947 case MATROXFB_SRC_CRTC1:
948 matroxfb_set_par(info);
949 break;
950 case MATROXFB_SRC_CRTC2:
951 {
952 struct matroxfb_dh_fb_info* crtc2;
953
954 down_read(&minfo->crtc2.lock);
955 crtc2 = minfo->crtc2.info;
956 if (crtc2)
957 crtc2->fbcon.fbops->fb_set_par(&crtc2->fbcon);
958 up_read(&minfo->crtc2.lock);
959 }
960 break;
961 }
962 return 0;
963 }
964 case MATROXFB_GET_OUTPUT_MODE:
965 {
966 struct matroxioc_output_mode mom;
967 struct matrox_altout *oproc;
968 int val;
969
970 if (copy_from_user(&mom, argp, sizeof(mom)))
971 return -EFAULT;
972 if (mom.output >= MATROXFB_MAX_OUTPUTS)
973 return -ENXIO;
974 down_read(&minfo->altout.lock);
975 oproc = minfo->outputs[mom.output].output;
976 if (!oproc) {
977 val = -ENXIO;
978 } else {
979 mom.mode = minfo->outputs[mom.output].mode;
980 val = 0;
981 }
982 up_read(&minfo->altout.lock);
983 if (val)
984 return val;
985 if (copy_to_user(argp, &mom, sizeof(mom)))
986 return -EFAULT;
987 return 0;
988 }
989 case MATROXFB_SET_OUTPUT_CONNECTION:
990 {
991 u_int32_t tmp;
992 int i;
993 int changes;
994
995 if (copy_from_user(&tmp, argp, sizeof(tmp)))
996 return -EFAULT;
997 for (i = 0; i < 32; i++) {
998 if (tmp & (1 << i)) {
999 if (i >= MATROXFB_MAX_OUTPUTS)
1000 return -ENXIO;
1001 if (!minfo->outputs[i].output)
1002 return -ENXIO;
1003 switch (minfo->outputs[i].src) {
1004 case MATROXFB_SRC_NONE:
1005 case MATROXFB_SRC_CRTC1:
1006 break;
1007 default:
1008 return -EBUSY;
1009 }
1010 }
1011 }
1012 if (minfo->devflags.panellink) {
1013 if (tmp & MATROXFB_OUTPUT_CONN_DFP) {
1014 if (tmp & MATROXFB_OUTPUT_CONN_SECONDARY)
1015 return -EINVAL;
1016 for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
1017 if (minfo->outputs[i].src == MATROXFB_SRC_CRTC2) {
1018 return -EBUSY;
1019 }
1020 }
1021 }
1022 }
1023 changes = 0;
1024 for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
1025 if (tmp & (1 << i)) {
1026 if (minfo->outputs[i].src != MATROXFB_SRC_CRTC1) {
1027 changes = 1;
1028 minfo->outputs[i].src = MATROXFB_SRC_CRTC1;
1029 }
1030 } else if (minfo->outputs[i].src == MATROXFB_SRC_CRTC1) {
1031 changes = 1;
1032 minfo->outputs[i].src = MATROXFB_SRC_NONE;
1033 }
1034 }
1035 if (!changes)
1036 return 0;
1037 matroxfb_set_par(info);
1038 return 0;
1039 }
1040 case MATROXFB_GET_OUTPUT_CONNECTION:
1041 {
1042 u_int32_t conn = 0;
1043 int i;
1044
1045 for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
1046 if (minfo->outputs[i].src == MATROXFB_SRC_CRTC1) {
1047 conn |= 1 << i;
1048 }
1049 }
1050 if (put_user(conn, (u_int32_t __user *)arg))
1051 return -EFAULT;
1052 return 0;
1053 }
1054 case MATROXFB_GET_AVAILABLE_OUTPUTS:
1055 {
1056 u_int32_t conn = 0;
1057 int i;
1058
1059 for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
1060 if (minfo->outputs[i].output) {
1061 switch (minfo->outputs[i].src) {
1062 case MATROXFB_SRC_NONE:
1063 case MATROXFB_SRC_CRTC1:
1064 conn |= 1 << i;
1065 break;
1066 }
1067 }
1068 }
1069 if (minfo->devflags.panellink) {
1070 if (conn & MATROXFB_OUTPUT_CONN_DFP)
1071 conn &= ~MATROXFB_OUTPUT_CONN_SECONDARY;
1072 if (conn & MATROXFB_OUTPUT_CONN_SECONDARY)
1073 conn &= ~MATROXFB_OUTPUT_CONN_DFP;
1074 }
1075 if (put_user(conn, (u_int32_t __user *)arg))
1076 return -EFAULT;
1077 return 0;
1078 }
1079 case MATROXFB_GET_ALL_OUTPUTS:
1080 {
1081 u_int32_t conn = 0;
1082 int i;
1083
1084 for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
1085 if (minfo->outputs[i].output) {
1086 conn |= 1 << i;
1087 }
1088 }
1089 if (put_user(conn, (u_int32_t __user *)arg))
1090 return -EFAULT;
1091 return 0;
1092 }
1093 case VIDIOC_QUERYCAP:
1094 {
1095 struct v4l2_capability r;
1096
1097 memset(&r, 0, sizeof(r));
1098 strcpy(r.driver, "matroxfb");
1099 strcpy(r.card, "Matrox");
1100 sprintf(r.bus_info, "PCI:%s", pci_name(minfo->pcidev));
1101 r.version = KERNEL_VERSION(1,0,0);
1102 r.capabilities = V4L2_CAP_VIDEO_OUTPUT;
1103 if (copy_to_user(argp, &r, sizeof(r)))
1104 return -EFAULT;
1105 return 0;
1106
1107 }
1108 case VIDIOC_QUERYCTRL:
1109 {
1110 struct v4l2_queryctrl qctrl;
1111 int err;
1112
1113 if (copy_from_user(&qctrl, argp, sizeof(qctrl)))
1114 return -EFAULT;
1115
1116 down_read(&minfo->altout.lock);
1117 if (!minfo->outputs[1].output) {
1118 err = -ENXIO;
1119 } else if (minfo->outputs[1].output->getqueryctrl) {
1120 err = minfo->outputs[1].output->getqueryctrl(minfo->outputs[1].data, &qctrl);
1121 } else {
1122 err = -EINVAL;
1123 }
1124 up_read(&minfo->altout.lock);
1125 if (err >= 0 &&
1126 copy_to_user(argp, &qctrl, sizeof(qctrl)))
1127 return -EFAULT;
1128 return err;
1129 }
1130 case VIDIOC_G_CTRL:
1131 {
1132 struct v4l2_control ctrl;
1133 int err;
1134
1135 if (copy_from_user(&ctrl, argp, sizeof(ctrl)))
1136 return -EFAULT;
1137
1138 down_read(&minfo->altout.lock);
1139 if (!minfo->outputs[1].output) {
1140 err = -ENXIO;
1141 } else if (minfo->outputs[1].output->getctrl) {
1142 err = minfo->outputs[1].output->getctrl(minfo->outputs[1].data, &ctrl);
1143 } else {
1144 err = -EINVAL;
1145 }
1146 up_read(&minfo->altout.lock);
1147 if (err >= 0 &&
1148 copy_to_user(argp, &ctrl, sizeof(ctrl)))
1149 return -EFAULT;
1150 return err;
1151 }
1152 case VIDIOC_S_CTRL:
1153 {
1154 struct v4l2_control ctrl;
1155 int err;
1156
1157 if (copy_from_user(&ctrl, argp, sizeof(ctrl)))
1158 return -EFAULT;
1159
1160 down_read(&minfo->altout.lock);
1161 if (!minfo->outputs[1].output) {
1162 err = -ENXIO;
1163 } else if (minfo->outputs[1].output->setctrl) {
1164 err = minfo->outputs[1].output->setctrl(minfo->outputs[1].data, &ctrl);
1165 } else {
1166 err = -EINVAL;
1167 }
1168 up_read(&minfo->altout.lock);
1169 return err;
1170 }
1171 }
1172 return -ENOTTY;
1173}
1174
1175/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
1176
1177static int matroxfb_blank(int blank, struct fb_info *info)
1178{
1179 int seq;
1180 int crtc;
1181 CRITFLAGS
1182 struct matrox_fb_info *minfo = info2minfo(info);
1183
1184 DBG(__func__)
1185
1186 if (minfo->dead)
1187 return 1;
1188
1189 switch (blank) {
1190 case FB_BLANK_NORMAL: seq = 0x20; crtc = 0x00; break; /* works ??? */
1191 case FB_BLANK_VSYNC_SUSPEND: seq = 0x20; crtc = 0x10; break;
1192 case FB_BLANK_HSYNC_SUSPEND: seq = 0x20; crtc = 0x20; break;
1193 case FB_BLANK_POWERDOWN: seq = 0x20; crtc = 0x30; break;
1194 default: seq = 0x00; crtc = 0x00; break;
1195 }
1196
1197 CRITBEGIN
1198
1199 mga_outb(M_SEQ_INDEX, 1);
1200 mga_outb(M_SEQ_DATA, (mga_inb(M_SEQ_DATA) & ~0x20) | seq);
1201 mga_outb(M_EXTVGA_INDEX, 1);
1202 mga_outb(M_EXTVGA_DATA, (mga_inb(M_EXTVGA_DATA) & ~0x30) | crtc);
1203
1204 CRITEND
1205 return 0;
1206}
1207
1208static struct fb_ops matroxfb_ops = {
1209 .owner = THIS_MODULE,
1210 .fb_open = matroxfb_open,
1211 .fb_release = matroxfb_release,
1212 .fb_check_var = matroxfb_check_var,
1213 .fb_set_par = matroxfb_set_par,
1214 .fb_setcolreg = matroxfb_setcolreg,
1215 .fb_pan_display =matroxfb_pan_display,
1216 .fb_blank = matroxfb_blank,
1217 .fb_ioctl = matroxfb_ioctl,
1218/* .fb_fillrect = <set by matrox_cfbX_init>, */
1219/* .fb_copyarea = <set by matrox_cfbX_init>, */
1220/* .fb_imageblit = <set by matrox_cfbX_init>, */
1221/* .fb_cursor = <set by matrox_cfbX_init>, */
1222};
1223
1224#define RSDepth(X) (((X) >> 8) & 0x0F)
1225#define RS8bpp 0x1
1226#define RS15bpp 0x2
1227#define RS16bpp 0x3
1228#define RS32bpp 0x4
1229#define RS4bpp 0x5
1230#define RS24bpp 0x6
1231#define RSText 0x7
1232#define RSText8 0x8
1233/* 9-F */
1234static struct { struct fb_bitfield red, green, blue, transp; int bits_per_pixel; } colors[] = {
1235 { { 0, 8, 0}, { 0, 8, 0}, { 0, 8, 0}, { 0, 0, 0}, 8 },
1236 { { 10, 5, 0}, { 5, 5, 0}, { 0, 5, 0}, { 15, 1, 0}, 16 },
1237 { { 11, 5, 0}, { 5, 6, 0}, { 0, 5, 0}, { 0, 0, 0}, 16 },
1238 { { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, { 24, 8, 0}, 32 },
1239 { { 0, 8, 0}, { 0, 8, 0}, { 0, 8, 0}, { 0, 0, 0}, 4 },
1240 { { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, { 0, 0, 0}, 24 },
1241 { { 0, 6, 0}, { 0, 6, 0}, { 0, 6, 0}, { 0, 0, 0}, 0 }, /* textmode with (default) VGA8x16 */
1242 { { 0, 6, 0}, { 0, 6, 0}, { 0, 6, 0}, { 0, 0, 0}, 0 }, /* textmode hardwired to VGA8x8 */
1243};
1244
1245/* initialized by setup, see explanation at end of file (search for MODULE_PARM_DESC) */
1246static unsigned int mem; /* "matroxfb:mem:xxxxxM" */
1247static int option_precise_width = 1; /* cannot be changed, option_precise_width==0 must imply noaccel */
1248static int inv24; /* "matroxfb:inv24" */
1249static int cross4MB = -1; /* "matroxfb:cross4MB" */
1250static int disabled; /* "matroxfb:disabled" */
1251static int noaccel; /* "matroxfb:noaccel" */
1252static int nopan; /* "matroxfb:nopan" */
1253static int no_pci_retry; /* "matroxfb:nopciretry" */
1254static int novga; /* "matroxfb:novga" */
1255static int nobios; /* "matroxfb:nobios" */
1256static int noinit = 1; /* "matroxfb:init" */
1257static int inverse; /* "matroxfb:inverse" */
1258static int sgram; /* "matroxfb:sgram" */
1259#ifdef CONFIG_MTRR
1260static int mtrr = 1; /* "matroxfb:nomtrr" */
1261#endif
1262static int grayscale; /* "matroxfb:grayscale" */
1263static int dev = -1; /* "matroxfb:dev:xxxxx" */
1264static unsigned int vesa = ~0; /* "matroxfb:vesa:xxxxx" */
1265static int depth = -1; /* "matroxfb:depth:xxxxx" */
1266static unsigned int xres; /* "matroxfb:xres:xxxxx" */
1267static unsigned int yres; /* "matroxfb:yres:xxxxx" */
1268static unsigned int upper = ~0; /* "matroxfb:upper:xxxxx" */
1269static unsigned int lower = ~0; /* "matroxfb:lower:xxxxx" */
1270static unsigned int vslen; /* "matroxfb:vslen:xxxxx" */
1271static unsigned int left = ~0; /* "matroxfb:left:xxxxx" */
1272static unsigned int right = ~0; /* "matroxfb:right:xxxxx" */
1273static unsigned int hslen; /* "matroxfb:hslen:xxxxx" */
1274static unsigned int pixclock; /* "matroxfb:pixclock:xxxxx" */
1275static int sync = -1; /* "matroxfb:sync:xxxxx" */
1276static unsigned int fv; /* "matroxfb:fv:xxxxx" */
1277static unsigned int fh; /* "matroxfb:fh:xxxxxk" */
1278static unsigned int maxclk; /* "matroxfb:maxclk:xxxxM" */
1279static int dfp; /* "matroxfb:dfp */
1280static int dfp_type = -1; /* "matroxfb:dfp:xxx */
1281static int memtype = -1; /* "matroxfb:memtype:xxx" */
1282static char outputs[8]; /* "matroxfb:outputs:xxx" */
1283
1284#ifndef MODULE
1285static char videomode[64]; /* "matroxfb:mode:xxxxx" or "matroxfb:xxxxx" */
1286#endif
1287
1288static int matroxfb_getmemory(struct matrox_fb_info *minfo,
1289 unsigned int maxSize, unsigned int *realSize)
1290{
1291 vaddr_t vm;
1292 unsigned int offs;
1293 unsigned int offs2;
1294 unsigned char orig;
1295 unsigned char bytes[32];
1296 unsigned char* tmp;
1297
1298 DBG(__func__)
1299
1300 vm = minfo->video.vbase;
1301 maxSize &= ~0x1FFFFF; /* must be X*2MB (really it must be 2 or X*4MB) */
1302 /* at least 2MB */
1303 if (maxSize < 0x0200000) return 0;
1304 if (maxSize > 0x2000000) maxSize = 0x2000000;
1305
1306 mga_outb(M_EXTVGA_INDEX, 0x03);
1307 orig = mga_inb(M_EXTVGA_DATA);
1308 mga_outb(M_EXTVGA_DATA, orig | 0x80);
1309
1310 tmp = bytes;
1311 for (offs = 0x100000; offs < maxSize; offs += 0x200000)
1312 *tmp++ = mga_readb(vm, offs);
1313 for (offs = 0x100000; offs < maxSize; offs += 0x200000)
1314 mga_writeb(vm, offs, 0x02);
1315 mga_outb(M_CACHEFLUSH, 0x00);
1316 for (offs = 0x100000; offs < maxSize; offs += 0x200000) {
1317 if (mga_readb(vm, offs) != 0x02)
1318 break;
1319 mga_writeb(vm, offs, mga_readb(vm, offs) - 0x02);
1320 if (mga_readb(vm, offs))
1321 break;
1322 }
1323 tmp = bytes;
1324 for (offs2 = 0x100000; offs2 < maxSize; offs2 += 0x200000)
1325 mga_writeb(vm, offs2, *tmp++);
1326
1327 mga_outb(M_EXTVGA_INDEX, 0x03);
1328 mga_outb(M_EXTVGA_DATA, orig);
1329
1330 *realSize = offs - 0x100000;
1331#ifdef CONFIG_FB_MATROX_MILLENIUM
1332 minfo->interleave = !(!isMillenium(minfo) || ((offs - 0x100000) & 0x3FFFFF));
1333#endif
1334 return 1;
1335}
1336
1337struct video_board {
1338 int maxvram;
1339 int maxdisplayable;
1340 int accelID;
1341 struct matrox_switch* lowlevel;
1342 };
1343#ifdef CONFIG_FB_MATROX_MILLENIUM
1344static struct video_board vbMillennium = {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGA2064W, &matrox_millennium};
1345static struct video_board vbMillennium2 = {0x1000000, 0x0800000, FB_ACCEL_MATROX_MGA2164W, &matrox_millennium};
1346static struct video_board vbMillennium2A = {0x1000000, 0x0800000, FB_ACCEL_MATROX_MGA2164W_AGP, &matrox_millennium};
1347#endif /* CONFIG_FB_MATROX_MILLENIUM */
1348#ifdef CONFIG_FB_MATROX_MYSTIQUE
1349static struct video_board vbMystique = {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGA1064SG, &matrox_mystique};
1350#endif /* CONFIG_FB_MATROX_MYSTIQUE */
1351#ifdef CONFIG_FB_MATROX_G
1352static struct video_board vbG100 = {0x0800000, 0x0800000, FB_ACCEL_MATROX_MGAG100, &matrox_G100};
1353static struct video_board vbG200 = {0x1000000, 0x1000000, FB_ACCEL_MATROX_MGAG200, &matrox_G100};
1354/* from doc it looks like that accelerator can draw only to low 16MB :-( Direct accesses & displaying are OK for
1355 whole 32MB */
1356static struct video_board vbG400 = {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG400, &matrox_G100};
1357#endif
1358
1359#define DEVF_VIDEO64BIT 0x0001
1360#define DEVF_SWAPS 0x0002
1361#define DEVF_SRCORG 0x0004
1362#define DEVF_DUALHEAD 0x0008
1363#define DEVF_CROSS4MB 0x0010
1364#define DEVF_TEXT4B 0x0020
1365/* #define DEVF_recycled 0x0040 */
1366/* #define DEVF_recycled 0x0080 */
1367#define DEVF_SUPPORT32MB 0x0100
1368#define DEVF_ANY_VXRES 0x0200
1369#define DEVF_TEXT16B 0x0400
1370#define DEVF_CRTC2 0x0800
1371#define DEVF_MAVEN_CAPABLE 0x1000
1372#define DEVF_PANELLINK_CAPABLE 0x2000
1373#define DEVF_G450DAC 0x4000
1374
1375#define DEVF_GCORE (DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB)
1376#define DEVF_G2CORE (DEVF_GCORE | DEVF_ANY_VXRES | DEVF_MAVEN_CAPABLE | DEVF_PANELLINK_CAPABLE | DEVF_SRCORG | DEVF_DUALHEAD)
1377#define DEVF_G100 (DEVF_GCORE) /* no doc, no vxres... */
1378#define DEVF_G200 (DEVF_G2CORE)
1379#define DEVF_G400 (DEVF_G2CORE | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2)
1380/* if you'll find how to drive DFP... */
1381#define DEVF_G450 (DEVF_GCORE | DEVF_ANY_VXRES | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2 | DEVF_G450DAC | DEVF_SRCORG | DEVF_DUALHEAD)
1382#define DEVF_G550 (DEVF_G450)
1383
1384static struct board {
1385 unsigned short vendor, device, rev, svid, sid;
1386 unsigned int flags;
1387 unsigned int maxclk;
1388 enum mga_chip chip;
1389 struct video_board* base;
1390 const char* name;
1391 } dev_list[] = {
1392#ifdef CONFIG_FB_MATROX_MILLENIUM
1393 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL, 0xFF,
1394 0, 0,
1395 DEVF_TEXT4B,
1396 230000,
1397 MGA_2064,
1398 &vbMillennium,
1399 "Millennium (PCI)"},
1400 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2, 0xFF,
1401 0, 0,
1402 DEVF_SWAPS,
1403 220000,
1404 MGA_2164,
1405 &vbMillennium2,
1406 "Millennium II (PCI)"},
1407 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2_AGP, 0xFF,
1408 0, 0,
1409 DEVF_SWAPS,
1410 250000,
1411 MGA_2164,
1412 &vbMillennium2A,
1413 "Millennium II (AGP)"},
1414#endif
1415#ifdef CONFIG_FB_MATROX_MYSTIQUE
1416 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS, 0x02,
1417 0, 0,
1418 DEVF_VIDEO64BIT | DEVF_CROSS4MB,
1419 180000,
1420 MGA_1064,
1421 &vbMystique,
1422 "Mystique (PCI)"},
1423 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS, 0xFF,
1424 0, 0,
1425 DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
1426 220000,
1427 MGA_1164,
1428 &vbMystique,
1429 "Mystique 220 (PCI)"},
1430 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS_AGP, 0x02,
1431 0, 0,
1432 DEVF_VIDEO64BIT | DEVF_CROSS4MB,
1433 180000,
1434 MGA_1064,
1435 &vbMystique,
1436 "Mystique (AGP)"},
1437 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS_AGP, 0xFF,
1438 0, 0,
1439 DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
1440 220000,
1441 MGA_1164,
1442 &vbMystique,
1443 "Mystique 220 (AGP)"},
1444#endif
1445#ifdef CONFIG_FB_MATROX_G
1446 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_MM, 0xFF,
1447 0, 0,
1448 DEVF_G100,
1449 230000,
1450 MGA_G100,
1451 &vbG100,
1452 "MGA-G100 (PCI)"},
1453 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF,
1454 0, 0,
1455 DEVF_G100,
1456 230000,
1457 MGA_G100,
1458 &vbG100,
1459 "MGA-G100 (AGP)"},
1460 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI, 0xFF,
1461 0, 0,
1462 DEVF_G200,
1463 250000,
1464 MGA_G200,
1465 &vbG200,
1466 "MGA-G200 (PCI)"},
1467 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
1468 PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_GENERIC,
1469 DEVF_G200,
1470 220000,
1471 MGA_G200,
1472 &vbG200,
1473 "MGA-G200 (AGP)"},
1474 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
1475 PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MYSTIQUE_G200_AGP,
1476 DEVF_G200,
1477 230000,
1478 MGA_G200,
1479 &vbG200,
1480 "Mystique G200 (AGP)"},
1481 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
1482 PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MILLENIUM_G200_AGP,
1483 DEVF_G200,
1484 250000,
1485 MGA_G200,
1486 &vbG200,
1487 "Millennium G200 (AGP)"},
1488 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
1489 PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MARVEL_G200_AGP,
1490 DEVF_G200,
1491 230000,
1492 MGA_G200,
1493 &vbG200,
1494 "Marvel G200 (AGP)"},
1495 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
1496 PCI_SS_VENDOR_ID_SIEMENS_NIXDORF, PCI_SS_ID_SIEMENS_MGA_G200_AGP,
1497 DEVF_G200,
1498 230000,
1499 MGA_G200,
1500 &vbG200,
1501 "MGA-G200 (AGP)"},
1502 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
1503 0, 0,
1504 DEVF_G200,
1505 230000,
1506 MGA_G200,
1507 &vbG200,
1508 "G200 (AGP)"},
1509 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400, 0x80,
1510 PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MILLENNIUM_G400_MAX_AGP,
1511 DEVF_G400,
1512 360000,
1513 MGA_G400,
1514 &vbG400,
1515 "Millennium G400 MAX (AGP)"},
1516 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400, 0x80,
1517 0, 0,
1518 DEVF_G400,
1519 300000,
1520 MGA_G400,
1521 &vbG400,
1522 "G400 (AGP)"},
1523 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400, 0xFF,
1524 0, 0,
1525 DEVF_G450,
1526 360000,
1527 MGA_G450,
1528 &vbG400,
1529 "G450"},
1530 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G550, 0xFF,
1531 0, 0,
1532 DEVF_G550,
1533 360000,
1534 MGA_G550,
1535 &vbG400,
1536 "G550"},
1537#endif
1538 {0, 0, 0xFF,
1539 0, 0,
1540 0,
1541 0,
1542 0,
1543 NULL,
1544 NULL}};
1545
1546#ifndef MODULE
1547static struct fb_videomode defaultmode = {
1548 /* 640x480 @ 60Hz, 31.5 kHz */
1549 NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
1550 0, FB_VMODE_NONINTERLACED
1551};
1552#endif /* !MODULE */
1553
1554static int hotplug = 0;
1555
1556static void setDefaultOutputs(struct matrox_fb_info *minfo)
1557{
1558 unsigned int i;
1559 const char* ptr;
1560
1561 minfo->outputs[0].default_src = MATROXFB_SRC_CRTC1;
1562 if (minfo->devflags.g450dac) {
1563 minfo->outputs[1].default_src = MATROXFB_SRC_CRTC1;
1564 minfo->outputs[2].default_src = MATROXFB_SRC_CRTC1;
1565 } else if (dfp) {
1566 minfo->outputs[2].default_src = MATROXFB_SRC_CRTC1;
1567 }
1568 ptr = outputs;
1569 for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) {
1570 char c = *ptr++;
1571
1572 if (c == 0) {
1573 break;
1574 }
1575 if (c == '0') {
1576 minfo->outputs[i].default_src = MATROXFB_SRC_NONE;
1577 } else if (c == '1') {
1578 minfo->outputs[i].default_src = MATROXFB_SRC_CRTC1;
1579 } else if (c == '2' && minfo->devflags.crtc2) {
1580 minfo->outputs[i].default_src = MATROXFB_SRC_CRTC2;
1581 } else {
1582 printk(KERN_ERR "matroxfb: Unknown outputs setting\n");
1583 break;
1584 }
1585 }
1586 /* Nullify this option for subsequent adapters */
1587 outputs[0] = 0;
1588}
1589
1590static int initMatrox2(struct matrox_fb_info *minfo, struct board *b)
1591{
1592 unsigned long ctrlptr_phys = 0;
1593 unsigned long video_base_phys = 0;
1594 unsigned int memsize;
1595 int err;
1596
1597 static struct pci_device_id intel_82437[] = {
1598 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437) },
1599 { },
1600 };
1601
1602 DBG(__func__)
1603
1604 /* set default values... */
1605 vesafb_defined.accel_flags = FB_ACCELF_TEXT;
1606
1607 minfo->hw_switch = b->base->lowlevel;
1608 minfo->devflags.accelerator = b->base->accelID;
1609 minfo->max_pixel_clock = b->maxclk;
1610
1611 printk(KERN_INFO "matroxfb: Matrox %s detected\n", b->name);
1612 minfo->capable.plnwt = 1;
1613 minfo->chip = b->chip;
1614 minfo->capable.srcorg = b->flags & DEVF_SRCORG;
1615 minfo->devflags.video64bits = b->flags & DEVF_VIDEO64BIT;
1616 if (b->flags & DEVF_TEXT4B) {
1617 minfo->devflags.vgastep = 4;
1618 minfo->devflags.textmode = 4;
1619 minfo->devflags.text_type_aux = FB_AUX_TEXT_MGA_STEP16;
1620 } else if (b->flags & DEVF_TEXT16B) {
1621 minfo->devflags.vgastep = 16;
1622 minfo->devflags.textmode = 1;
1623 minfo->devflags.text_type_aux = FB_AUX_TEXT_MGA_STEP16;
1624 } else {
1625 minfo->devflags.vgastep = 8;
1626 minfo->devflags.textmode = 1;
1627 minfo->devflags.text_type_aux = FB_AUX_TEXT_MGA_STEP8;
1628 }
1629 minfo->devflags.support32MB = (b->flags & DEVF_SUPPORT32MB) != 0;
1630 minfo->devflags.precise_width = !(b->flags & DEVF_ANY_VXRES);
1631 minfo->devflags.crtc2 = (b->flags & DEVF_CRTC2) != 0;
1632 minfo->devflags.maven_capable = (b->flags & DEVF_MAVEN_CAPABLE) != 0;
1633 minfo->devflags.dualhead = (b->flags & DEVF_DUALHEAD) != 0;
1634 minfo->devflags.dfp_type = dfp_type;
1635 minfo->devflags.g450dac = (b->flags & DEVF_G450DAC) != 0;
1636 minfo->devflags.textstep = minfo->devflags.vgastep * minfo->devflags.textmode;
1637 minfo->devflags.textvram = 65536 / minfo->devflags.textmode;
1638 setDefaultOutputs(minfo);
1639 if (b->flags & DEVF_PANELLINK_CAPABLE) {
1640 minfo->outputs[2].data = minfo;
1641 minfo->outputs[2].output = &panellink_output;
1642 minfo->outputs[2].src = minfo->outputs[2].default_src;
1643 minfo->outputs[2].mode = MATROXFB_OUTPUT_MODE_MONITOR;
1644 minfo->devflags.panellink = 1;
1645 }
1646
1647 if (minfo->capable.cross4MB < 0)
1648 minfo->capable.cross4MB = b->flags & DEVF_CROSS4MB;
1649 if (b->flags & DEVF_SWAPS) {
1650 ctrlptr_phys = pci_resource_start(minfo->pcidev, 1);
1651 video_base_phys = pci_resource_start(minfo->pcidev, 0);
1652 minfo->devflags.fbResource = PCI_BASE_ADDRESS_0;
1653 } else {
1654 ctrlptr_phys = pci_resource_start(minfo->pcidev, 0);
1655 video_base_phys = pci_resource_start(minfo->pcidev, 1);
1656 minfo->devflags.fbResource = PCI_BASE_ADDRESS_1;
1657 }
1658 err = -EINVAL;
1659 if (!ctrlptr_phys) {
1660 printk(KERN_ERR "matroxfb: control registers are not available, matroxfb disabled\n");
1661 goto fail;
1662 }
1663 if (!video_base_phys) {
1664 printk(KERN_ERR "matroxfb: video RAM is not available in PCI address space, matroxfb disabled\n");
1665 goto fail;
1666 }
1667 memsize = b->base->maxvram;
1668 if (!request_mem_region(ctrlptr_phys, 16384, "matroxfb MMIO")) {
1669 goto fail;
1670 }
1671 if (!request_mem_region(video_base_phys, memsize, "matroxfb FB")) {
1672 goto failCtrlMR;
1673 }
1674 minfo->video.len_maximum = memsize;
1675 /* convert mem (autodetect k, M) */
1676 if (mem < 1024) mem *= 1024;
1677 if (mem < 0x00100000) mem *= 1024;
1678
1679 if (mem && (mem < memsize))
1680 memsize = mem;
1681 err = -ENOMEM;
1682 if (mga_ioremap(ctrlptr_phys, 16384, MGA_IOREMAP_MMIO, &minfo->mmio.vbase)) {
1683 printk(KERN_ERR "matroxfb: cannot ioremap(%lX, 16384), matroxfb disabled\n", ctrlptr_phys);
1684 goto failVideoMR;
1685 }
1686 minfo->mmio.base = ctrlptr_phys;
1687 minfo->mmio.len = 16384;
1688 minfo->video.base = video_base_phys;
1689 if (mga_ioremap(video_base_phys, memsize, MGA_IOREMAP_FB, &minfo->video.vbase)) {
1690 printk(KERN_ERR "matroxfb: cannot ioremap(%lX, %d), matroxfb disabled\n",
1691 video_base_phys, memsize);
1692 goto failCtrlIO;
1693 }
1694 {
1695 u_int32_t cmd;
1696 u_int32_t mga_option;
1697
1698 pci_read_config_dword(minfo->pcidev, PCI_OPTION_REG, &mga_option);
1699 pci_read_config_dword(minfo->pcidev, PCI_COMMAND, &cmd);
1700 mga_option &= 0x7FFFFFFF; /* clear BIG_ENDIAN */
1701 mga_option |= MX_OPTION_BSWAP;
1702 /* disable palette snooping */
1703 cmd &= ~PCI_COMMAND_VGA_PALETTE;
1704 if (pci_dev_present(intel_82437)) {
1705 if (!(mga_option & 0x20000000) && !minfo->devflags.nopciretry) {
1706 printk(KERN_WARNING "matroxfb: Disabling PCI retries due to i82437 present\n");
1707 }
1708 mga_option |= 0x20000000;
1709 minfo->devflags.nopciretry = 1;
1710 }
1711 pci_write_config_dword(minfo->pcidev, PCI_COMMAND, cmd);
1712 pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, mga_option);
1713 minfo->hw.MXoptionReg = mga_option;
1714
1715 /* select non-DMA memory for PCI_MGA_DATA, otherwise dump of PCI cfg space can lock PCI bus */
1716 /* maybe preinit() candidate, but it is same... for all devices... at this time... */
1717 pci_write_config_dword(minfo->pcidev, PCI_MGA_INDEX, 0x00003C00);
1718 }
1719
1720 err = -ENXIO;
1721 matroxfb_read_pins(minfo);
1722 if (minfo->hw_switch->preinit(minfo)) {
1723 goto failVideoIO;
1724 }
1725
1726 err = -ENOMEM;
1727 if (!matroxfb_getmemory(minfo, memsize, &minfo->video.len) || !minfo->video.len) {
1728 printk(KERN_ERR "matroxfb: cannot determine memory size\n");
1729 goto failVideoIO;
1730 }
1731 minfo->devflags.ydstorg = 0;
1732
1733 minfo->video.base = video_base_phys;
1734 minfo->video.len_usable = minfo->video.len;
1735 if (minfo->video.len_usable > b->base->maxdisplayable)
1736 minfo->video.len_usable = b->base->maxdisplayable;
1737#ifdef CONFIG_MTRR
1738 if (mtrr) {
1739 minfo->mtrr.vram = mtrr_add(video_base_phys, minfo->video.len, MTRR_TYPE_WRCOMB, 1);
1740 minfo->mtrr.vram_valid = 1;
1741 printk(KERN_INFO "matroxfb: MTRR's turned on\n");
1742 }
1743#endif /* CONFIG_MTRR */
1744
1745 if (!minfo->devflags.novga)
1746 request_region(0x3C0, 32, "matrox");
1747 matroxfb_g450_connect(minfo);
1748 minfo->hw_switch->reset(minfo);
1749
1750 minfo->fbcon.monspecs.hfmin = 0;
1751 minfo->fbcon.monspecs.hfmax = fh;
1752 minfo->fbcon.monspecs.vfmin = 0;
1753 minfo->fbcon.monspecs.vfmax = fv;
1754 minfo->fbcon.monspecs.dpms = 0; /* TBD */
1755
1756 /* static settings */
1757 vesafb_defined.red = colors[depth-1].red;
1758 vesafb_defined.green = colors[depth-1].green;
1759 vesafb_defined.blue = colors[depth-1].blue;
1760 vesafb_defined.bits_per_pixel = colors[depth-1].bits_per_pixel;
1761 vesafb_defined.grayscale = grayscale;
1762 vesafb_defined.vmode = 0;
1763 if (noaccel)
1764 vesafb_defined.accel_flags &= ~FB_ACCELF_TEXT;
1765
1766 minfo->fbops = matroxfb_ops;
1767 minfo->fbcon.fbops = &minfo->fbops;
1768 minfo->fbcon.pseudo_palette = minfo->cmap;
1769 /* after __init time we are like module... no logo */
1770 minfo->fbcon.flags = hotplug ? FBINFO_FLAG_MODULE : FBINFO_FLAG_DEFAULT;
1771 minfo->fbcon.flags |= FBINFO_PARTIAL_PAN_OK | /* Prefer panning for scroll under MC viewer/edit */
1772 FBINFO_HWACCEL_COPYAREA | /* We have hw-assisted bmove */
1773 FBINFO_HWACCEL_FILLRECT | /* And fillrect */
1774 FBINFO_HWACCEL_IMAGEBLIT | /* And imageblit */
1775 FBINFO_HWACCEL_XPAN | /* And we support both horizontal */
1776 FBINFO_HWACCEL_YPAN | /* And vertical panning */
1777 FBINFO_READS_FAST;
1778 minfo->video.len_usable &= PAGE_MASK;
1779 fb_alloc_cmap(&minfo->fbcon.cmap, 256, 1);
1780
1781#ifndef MODULE
1782 /* mode database is marked __init!!! */
1783 if (!hotplug) {
1784 fb_find_mode(&vesafb_defined, &minfo->fbcon, videomode[0] ? videomode : NULL,
1785 NULL, 0, &defaultmode, vesafb_defined.bits_per_pixel);
1786 }
1787#endif /* !MODULE */
1788
1789 /* mode modifiers */
1790 if (hslen)
1791 vesafb_defined.hsync_len = hslen;
1792 if (vslen)
1793 vesafb_defined.vsync_len = vslen;
1794 if (left != ~0)
1795 vesafb_defined.left_margin = left;
1796 if (right != ~0)
1797 vesafb_defined.right_margin = right;
1798 if (upper != ~0)
1799 vesafb_defined.upper_margin = upper;
1800 if (lower != ~0)
1801 vesafb_defined.lower_margin = lower;
1802 if (xres)
1803 vesafb_defined.xres = xres;
1804 if (yres)
1805 vesafb_defined.yres = yres;
1806 if (sync != -1)
1807 vesafb_defined.sync = sync;
1808 else if (vesafb_defined.sync == ~0) {
1809 vesafb_defined.sync = 0;
1810 if (yres < 400)
1811 vesafb_defined.sync |= FB_SYNC_HOR_HIGH_ACT;
1812 else if (yres < 480)
1813 vesafb_defined.sync |= FB_SYNC_VERT_HIGH_ACT;
1814 }
1815
1816 /* fv, fh, maxclk limits was specified */
1817 {
1818 unsigned int tmp;
1819
1820 if (fv) {
1821 tmp = fv * (vesafb_defined.upper_margin + vesafb_defined.yres
1822 + vesafb_defined.lower_margin + vesafb_defined.vsync_len);
1823 if ((tmp < fh) || (fh == 0)) fh = tmp;
1824 }
1825 if (fh) {
1826 tmp = fh * (vesafb_defined.left_margin + vesafb_defined.xres
1827 + vesafb_defined.right_margin + vesafb_defined.hsync_len);
1828 if ((tmp < maxclk) || (maxclk == 0)) maxclk = tmp;
1829 }
1830 tmp = (maxclk + 499) / 500;
1831 if (tmp) {
1832 tmp = (2000000000 + tmp) / tmp;
1833 if (tmp > pixclock) pixclock = tmp;
1834 }
1835 }
1836 if (pixclock) {
1837 if (pixclock < 2000) /* > 500MHz */
1838 pixclock = 4000; /* 250MHz */
1839 if (pixclock > 1000000)
1840 pixclock = 1000000; /* 1MHz */
1841 vesafb_defined.pixclock = pixclock;
1842 }
1843
1844 /* FIXME: Where to move this?! */
1845#if defined(CONFIG_PPC_PMAC)
1846#ifndef MODULE
1847 if (machine_is(powermac)) {
1848 struct fb_var_screeninfo var;
1849 if (default_vmode <= 0 || default_vmode > VMODE_MAX)
1850 default_vmode = VMODE_640_480_60;
1851#ifdef CONFIG_NVRAM
1852 if (default_cmode == CMODE_NVRAM)
1853 default_cmode = nvram_read_byte(NV_CMODE);
1854#endif
1855 if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
1856 default_cmode = CMODE_8;
1857 if (!mac_vmode_to_var(default_vmode, default_cmode, &var)) {
1858 var.accel_flags = vesafb_defined.accel_flags;
1859 var.xoffset = var.yoffset = 0;
1860 /* Note: mac_vmode_to_var() does not set all parameters */
1861 vesafb_defined = var;
1862 }
1863 }
1864#endif /* !MODULE */
1865#endif /* CONFIG_PPC_PMAC */
1866 vesafb_defined.xres_virtual = vesafb_defined.xres;
1867 if (nopan) {
1868 vesafb_defined.yres_virtual = vesafb_defined.yres;
1869 } else {
1870 vesafb_defined.yres_virtual = 65536; /* large enough to be INF, but small enough
1871 to yres_virtual * xres_virtual < 2^32 */
1872 }
1873 matroxfb_init_fix(minfo);
1874 minfo->fbcon.screen_base = vaddr_va(minfo->video.vbase);
1875 /* Normalize values (namely yres_virtual) */
1876 matroxfb_check_var(&vesafb_defined, &minfo->fbcon);
1877 /* And put it into "current" var. Do NOT program hardware yet, or we'll not take over
1878 * vgacon correctly. fbcon_startup will call fb_set_par for us, WITHOUT check_var,
1879 * and unfortunately it will do it BEFORE vgacon contents is saved, so it won't work
1880 * anyway. But we at least tried... */
1881 minfo->fbcon.var = vesafb_defined;
1882 err = -EINVAL;
1883
1884 printk(KERN_INFO "matroxfb: %dx%dx%dbpp (virtual: %dx%d)\n",
1885 vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel,
1886 vesafb_defined.xres_virtual, vesafb_defined.yres_virtual);
1887 printk(KERN_INFO "matroxfb: framebuffer at 0x%lX, mapped to 0x%p, size %d\n",
1888 minfo->video.base, vaddr_va(minfo->video.vbase), minfo->video.len);
1889
1890/* We do not have to set currcon to 0... register_framebuffer do it for us on first console
1891 * and we do not want currcon == 0 for subsequent framebuffers */
1892
1893 minfo->fbcon.device = &minfo->pcidev->dev;
1894 if (register_framebuffer(&minfo->fbcon) < 0) {
1895 goto failVideoIO;
1896 }
1897 fb_info(&minfo->fbcon, "%s frame buffer device\n", minfo->fbcon.fix.id);
1898
1899 /* there is no console on this fb... but we have to initialize hardware
1900 * until someone tells me what is proper thing to do */
1901 if (!minfo->initialized) {
1902 fb_info(&minfo->fbcon, "initializing hardware\n");
1903 /* We have to use FB_ACTIVATE_FORCE, as we had to put vesafb_defined to the fbcon.var
1904 * already before, so register_framebuffer works correctly. */
1905 vesafb_defined.activate |= FB_ACTIVATE_FORCE;
1906 fb_set_var(&minfo->fbcon, &vesafb_defined);
1907 }
1908
1909 return 0;
1910failVideoIO:;
1911 matroxfb_g450_shutdown(minfo);
1912 mga_iounmap(minfo->video.vbase);
1913failCtrlIO:;
1914 mga_iounmap(minfo->mmio.vbase);
1915failVideoMR:;
1916 release_mem_region(video_base_phys, minfo->video.len_maximum);
1917failCtrlMR:;
1918 release_mem_region(ctrlptr_phys, 16384);
1919fail:;
1920 return err;
1921}
1922
1923static LIST_HEAD(matroxfb_list);
1924static LIST_HEAD(matroxfb_driver_list);
1925
1926#define matroxfb_l(x) list_entry(x, struct matrox_fb_info, next_fb)
1927#define matroxfb_driver_l(x) list_entry(x, struct matroxfb_driver, node)
1928int matroxfb_register_driver(struct matroxfb_driver* drv) {
1929 struct matrox_fb_info* minfo;
1930
1931 list_add(&drv->node, &matroxfb_driver_list);
1932 for (minfo = matroxfb_l(matroxfb_list.next);
1933 minfo != matroxfb_l(&matroxfb_list);
1934 minfo = matroxfb_l(minfo->next_fb.next)) {
1935 void* p;
1936
1937 if (minfo->drivers_count == MATROXFB_MAX_FB_DRIVERS)
1938 continue;
1939 p = drv->probe(minfo);
1940 if (p) {
1941 minfo->drivers_data[minfo->drivers_count] = p;
1942 minfo->drivers[minfo->drivers_count++] = drv;
1943 }
1944 }
1945 return 0;
1946}
1947
1948void matroxfb_unregister_driver(struct matroxfb_driver* drv) {
1949 struct matrox_fb_info* minfo;
1950
1951 list_del(&drv->node);
1952 for (minfo = matroxfb_l(matroxfb_list.next);
1953 minfo != matroxfb_l(&matroxfb_list);
1954 minfo = matroxfb_l(minfo->next_fb.next)) {
1955 int i;
1956
1957 for (i = 0; i < minfo->drivers_count; ) {
1958 if (minfo->drivers[i] == drv) {
1959 if (drv && drv->remove)
1960 drv->remove(minfo, minfo->drivers_data[i]);
1961 minfo->drivers[i] = minfo->drivers[--minfo->drivers_count];
1962 minfo->drivers_data[i] = minfo->drivers_data[minfo->drivers_count];
1963 } else
1964 i++;
1965 }
1966 }
1967}
1968
1969static void matroxfb_register_device(struct matrox_fb_info* minfo) {
1970 struct matroxfb_driver* drv;
1971 int i = 0;
1972 list_add(&minfo->next_fb, &matroxfb_list);
1973 for (drv = matroxfb_driver_l(matroxfb_driver_list.next);
1974 drv != matroxfb_driver_l(&matroxfb_driver_list);
1975 drv = matroxfb_driver_l(drv->node.next)) {
1976 if (drv && drv->probe) {
1977 void *p = drv->probe(minfo);
1978 if (p) {
1979 minfo->drivers_data[i] = p;
1980 minfo->drivers[i++] = drv;
1981 if (i == MATROXFB_MAX_FB_DRIVERS)
1982 break;
1983 }
1984 }
1985 }
1986 minfo->drivers_count = i;
1987}
1988
1989static void matroxfb_unregister_device(struct matrox_fb_info* minfo) {
1990 int i;
1991
1992 list_del(&minfo->next_fb);
1993 for (i = 0; i < minfo->drivers_count; i++) {
1994 struct matroxfb_driver* drv = minfo->drivers[i];
1995
1996 if (drv && drv->remove)
1997 drv->remove(minfo, minfo->drivers_data[i]);
1998 }
1999}
2000
2001static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dummy) {
2002 struct board* b;
2003 u_int16_t svid;
2004 u_int16_t sid;
2005 struct matrox_fb_info* minfo;
2006 int err;
2007 u_int32_t cmd;
2008 DBG(__func__)
2009
2010 svid = pdev->subsystem_vendor;
2011 sid = pdev->subsystem_device;
2012 for (b = dev_list; b->vendor; b++) {
2013 if ((b->vendor != pdev->vendor) || (b->device != pdev->device) || (b->rev < pdev->revision)) continue;
2014 if (b->svid)
2015 if ((b->svid != svid) || (b->sid != sid)) continue;
2016 break;
2017 }
2018 /* not match... */
2019 if (!b->vendor)
2020 return -ENODEV;
2021 if (dev > 0) {
2022 /* not requested one... */
2023 dev--;
2024 return -ENODEV;
2025 }
2026 pci_read_config_dword(pdev, PCI_COMMAND, &cmd);
2027 if (pci_enable_device(pdev)) {
2028 return -1;
2029 }
2030
2031 minfo = kzalloc(sizeof(*minfo), GFP_KERNEL);
2032 if (!minfo)
2033 return -1;
2034
2035 minfo->pcidev = pdev;
2036 minfo->dead = 0;
2037 minfo->usecount = 0;
2038 minfo->userusecount = 0;
2039
2040 pci_set_drvdata(pdev, minfo);
2041 /* DEVFLAGS */
2042 minfo->devflags.memtype = memtype;
2043 if (memtype != -1)
2044 noinit = 0;
2045 if (cmd & PCI_COMMAND_MEMORY) {
2046 minfo->devflags.novga = novga;
2047 minfo->devflags.nobios = nobios;
2048 minfo->devflags.noinit = noinit;
2049 /* subsequent heads always needs initialization and must not enable BIOS */
2050 novga = 1;
2051 nobios = 1;
2052 noinit = 0;
2053 } else {
2054 minfo->devflags.novga = 1;
2055 minfo->devflags.nobios = 1;
2056 minfo->devflags.noinit = 0;
2057 }
2058
2059 minfo->devflags.nopciretry = no_pci_retry;
2060 minfo->devflags.mga_24bpp_fix = inv24;
2061 minfo->devflags.precise_width = option_precise_width;
2062 minfo->devflags.sgram = sgram;
2063 minfo->capable.cross4MB = cross4MB;
2064
2065 spin_lock_init(&minfo->lock.DAC);
2066 spin_lock_init(&minfo->lock.accel);
2067 init_rwsem(&minfo->crtc2.lock);
2068 init_rwsem(&minfo->altout.lock);
2069 mutex_init(&minfo->fbcon.mm_lock);
2070 minfo->irq_flags = 0;
2071 init_waitqueue_head(&minfo->crtc1.vsync.wait);
2072 init_waitqueue_head(&minfo->crtc2.vsync.wait);
2073 minfo->crtc1.panpos = -1;
2074
2075 err = initMatrox2(minfo, b);
2076 if (!err) {
2077 matroxfb_register_device(minfo);
2078 return 0;
2079 }
2080 kfree(minfo);
2081 return -1;
2082}
2083
2084static void pci_remove_matrox(struct pci_dev* pdev) {
2085 struct matrox_fb_info* minfo;
2086
2087 minfo = pci_get_drvdata(pdev);
2088 matroxfb_remove(minfo, 1);
2089}
2090
2091static struct pci_device_id matroxfb_devices[] = {
2092#ifdef CONFIG_FB_MATROX_MILLENIUM
2093 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL,
2094 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2095 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2,
2096 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2097 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2_AGP,
2098 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2099#endif
2100#ifdef CONFIG_FB_MATROX_MYSTIQUE
2101 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS,
2102 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2103#endif
2104#ifdef CONFIG_FB_MATROX_G
2105 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_MM,
2106 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2107 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP,
2108 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2109 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI,
2110 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2111 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP,
2112 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2113 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400,
2114 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2115 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G550,
2116 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2117#endif
2118 {0, 0,
2119 0, 0, 0, 0, 0}
2120};
2121
2122MODULE_DEVICE_TABLE(pci, matroxfb_devices);
2123
2124
2125static struct pci_driver matroxfb_driver = {
2126 .name = "matroxfb",
2127 .id_table = matroxfb_devices,
2128 .probe = matroxfb_probe,
2129 .remove = pci_remove_matrox,
2130};
2131
2132/* **************************** init-time only **************************** */
2133
2134#define RSResolution(X) ((X) & 0x0F)
2135#define RS640x400 1
2136#define RS640x480 2
2137#define RS800x600 3
2138#define RS1024x768 4
2139#define RS1280x1024 5
2140#define RS1600x1200 6
2141#define RS768x576 7
2142#define RS960x720 8
2143#define RS1152x864 9
2144#define RS1408x1056 10
2145#define RS640x350 11
2146#define RS1056x344 12 /* 132 x 43 text */
2147#define RS1056x400 13 /* 132 x 50 text */
2148#define RS1056x480 14 /* 132 x 60 text */
2149#define RSNoxNo 15
2150/* 10-FF */
2151static struct { int xres, yres, left, right, upper, lower, hslen, vslen, vfreq; } timmings[] __initdata = {
2152 { 640, 400, 48, 16, 39, 8, 96, 2, 70 },
2153 { 640, 480, 48, 16, 33, 10, 96, 2, 60 },
2154 { 800, 600, 144, 24, 28, 8, 112, 6, 60 },
2155 { 1024, 768, 160, 32, 30, 4, 128, 4, 60 },
2156 { 1280, 1024, 224, 32, 32, 4, 136, 4, 60 },
2157 { 1600, 1200, 272, 48, 32, 5, 152, 5, 60 },
2158 { 768, 576, 144, 16, 28, 6, 112, 4, 60 },
2159 { 960, 720, 144, 24, 28, 8, 112, 4, 60 },
2160 { 1152, 864, 192, 32, 30, 4, 128, 4, 60 },
2161 { 1408, 1056, 256, 40, 32, 5, 144, 5, 60 },
2162 { 640, 350, 48, 16, 39, 8, 96, 2, 70 },
2163 { 1056, 344, 96, 24, 59, 44, 160, 2, 70 },
2164 { 1056, 400, 96, 24, 39, 8, 160, 2, 70 },
2165 { 1056, 480, 96, 24, 36, 12, 160, 3, 60 },
2166 { 0, 0, ~0, ~0, ~0, ~0, 0, 0, 0 }
2167};
2168
2169#define RSCreate(X,Y) ((X) | ((Y) << 8))
2170static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __initdata = {
2171/* default must be first */
2172 { ~0, RSCreate(RSNoxNo, RS8bpp ) },
2173 { 0x101, RSCreate(RS640x480, RS8bpp ) },
2174 { 0x100, RSCreate(RS640x400, RS8bpp ) },
2175 { 0x180, RSCreate(RS768x576, RS8bpp ) },
2176 { 0x103, RSCreate(RS800x600, RS8bpp ) },
2177 { 0x188, RSCreate(RS960x720, RS8bpp ) },
2178 { 0x105, RSCreate(RS1024x768, RS8bpp ) },
2179 { 0x190, RSCreate(RS1152x864, RS8bpp ) },
2180 { 0x107, RSCreate(RS1280x1024, RS8bpp ) },
2181 { 0x198, RSCreate(RS1408x1056, RS8bpp ) },
2182 { 0x11C, RSCreate(RS1600x1200, RS8bpp ) },
2183 { 0x110, RSCreate(RS640x480, RS15bpp) },
2184 { 0x181, RSCreate(RS768x576, RS15bpp) },
2185 { 0x113, RSCreate(RS800x600, RS15bpp) },
2186 { 0x189, RSCreate(RS960x720, RS15bpp) },
2187 { 0x116, RSCreate(RS1024x768, RS15bpp) },
2188 { 0x191, RSCreate(RS1152x864, RS15bpp) },
2189 { 0x119, RSCreate(RS1280x1024, RS15bpp) },
2190 { 0x199, RSCreate(RS1408x1056, RS15bpp) },
2191 { 0x11D, RSCreate(RS1600x1200, RS15bpp) },
2192 { 0x111, RSCreate(RS640x480, RS16bpp) },
2193 { 0x182, RSCreate(RS768x576, RS16bpp) },
2194 { 0x114, RSCreate(RS800x600, RS16bpp) },
2195 { 0x18A, RSCreate(RS960x720, RS16bpp) },
2196 { 0x117, RSCreate(RS1024x768, RS16bpp) },
2197 { 0x192, RSCreate(RS1152x864, RS16bpp) },
2198 { 0x11A, RSCreate(RS1280x1024, RS16bpp) },
2199 { 0x19A, RSCreate(RS1408x1056, RS16bpp) },
2200 { 0x11E, RSCreate(RS1600x1200, RS16bpp) },
2201 { 0x1B2, RSCreate(RS640x480, RS24bpp) },
2202 { 0x184, RSCreate(RS768x576, RS24bpp) },
2203 { 0x1B5, RSCreate(RS800x600, RS24bpp) },
2204 { 0x18C, RSCreate(RS960x720, RS24bpp) },
2205 { 0x1B8, RSCreate(RS1024x768, RS24bpp) },
2206 { 0x194, RSCreate(RS1152x864, RS24bpp) },
2207 { 0x1BB, RSCreate(RS1280x1024, RS24bpp) },
2208 { 0x19C, RSCreate(RS1408x1056, RS24bpp) },
2209 { 0x1BF, RSCreate(RS1600x1200, RS24bpp) },
2210 { 0x112, RSCreate(RS640x480, RS32bpp) },
2211 { 0x183, RSCreate(RS768x576, RS32bpp) },
2212 { 0x115, RSCreate(RS800x600, RS32bpp) },
2213 { 0x18B, RSCreate(RS960x720, RS32bpp) },
2214 { 0x118, RSCreate(RS1024x768, RS32bpp) },
2215 { 0x193, RSCreate(RS1152x864, RS32bpp) },
2216 { 0x11B, RSCreate(RS1280x1024, RS32bpp) },
2217 { 0x19B, RSCreate(RS1408x1056, RS32bpp) },
2218 { 0x11F, RSCreate(RS1600x1200, RS32bpp) },
2219 { 0x010, RSCreate(RS640x350, RS4bpp ) },
2220 { 0x012, RSCreate(RS640x480, RS4bpp ) },
2221 { 0x102, RSCreate(RS800x600, RS4bpp ) },
2222 { 0x104, RSCreate(RS1024x768, RS4bpp ) },
2223 { 0x106, RSCreate(RS1280x1024, RS4bpp ) },
2224 { 0, 0 }};
2225
2226static void __init matroxfb_init_params(void) {
2227 /* fh from kHz to Hz */
2228 if (fh < 1000)
2229 fh *= 1000; /* 1kHz minimum */
2230 /* maxclk */
2231 if (maxclk < 1000) maxclk *= 1000; /* kHz -> Hz, MHz -> kHz */
2232 if (maxclk < 1000000) maxclk *= 1000; /* kHz -> Hz, 1MHz minimum */
2233 /* fix VESA number */
2234 if (vesa != ~0)
2235 vesa &= 0x1DFF; /* mask out clearscreen, acceleration and so on */
2236
2237 /* static settings */
2238 for (RSptr = vesamap; RSptr->vesa; RSptr++) {
2239 if (RSptr->vesa == vesa) break;
2240 }
2241 if (!RSptr->vesa) {
2242 printk(KERN_ERR "Invalid vesa mode 0x%04X\n", vesa);
2243 RSptr = vesamap;
2244 }
2245 {
2246 int res = RSResolution(RSptr->info)-1;
2247 if (left == ~0)
2248 left = timmings[res].left;
2249 if (!xres)
2250 xres = timmings[res].xres;
2251 if (right == ~0)
2252 right = timmings[res].right;
2253 if (!hslen)
2254 hslen = timmings[res].hslen;
2255 if (upper == ~0)
2256 upper = timmings[res].upper;
2257 if (!yres)
2258 yres = timmings[res].yres;
2259 if (lower == ~0)
2260 lower = timmings[res].lower;
2261 if (!vslen)
2262 vslen = timmings[res].vslen;
2263 if (!(fv||fh||maxclk||pixclock))
2264 fv = timmings[res].vfreq;
2265 if (depth == -1)
2266 depth = RSDepth(RSptr->info);
2267 }
2268}
2269
2270static int __init matrox_init(void) {
2271 int err;
2272
2273 matroxfb_init_params();
2274 err = pci_register_driver(&matroxfb_driver);
2275 dev = -1; /* accept all new devices... */
2276 return err;
2277}
2278
2279/* **************************** exit-time only **************************** */
2280
2281static void __exit matrox_done(void) {
2282 pci_unregister_driver(&matroxfb_driver);
2283}
2284
2285#ifndef MODULE
2286
2287/* ************************* init in-kernel code ************************** */
2288
2289static int __init matroxfb_setup(char *options) {
2290 char *this_opt;
2291
2292 DBG(__func__)
2293
2294 if (!options || !*options)
2295 return 0;
2296
2297 while ((this_opt = strsep(&options, ",")) != NULL) {
2298 if (!*this_opt) continue;
2299
2300 dprintk("matroxfb_setup: option %s\n", this_opt);
2301
2302 if (!strncmp(this_opt, "dev:", 4))
2303 dev = simple_strtoul(this_opt+4, NULL, 0);
2304 else if (!strncmp(this_opt, "depth:", 6)) {
2305 switch (simple_strtoul(this_opt+6, NULL, 0)) {
2306 case 0: depth = RSText; break;
2307 case 4: depth = RS4bpp; break;
2308 case 8: depth = RS8bpp; break;
2309 case 15:depth = RS15bpp; break;
2310 case 16:depth = RS16bpp; break;
2311 case 24:depth = RS24bpp; break;
2312 case 32:depth = RS32bpp; break;
2313 default:
2314 printk(KERN_ERR "matroxfb: unsupported color depth\n");
2315 }
2316 } else if (!strncmp(this_opt, "xres:", 5))
2317 xres = simple_strtoul(this_opt+5, NULL, 0);
2318 else if (!strncmp(this_opt, "yres:", 5))
2319 yres = simple_strtoul(this_opt+5, NULL, 0);
2320 else if (!strncmp(this_opt, "vslen:", 6))
2321 vslen = simple_strtoul(this_opt+6, NULL, 0);
2322 else if (!strncmp(this_opt, "hslen:", 6))
2323 hslen = simple_strtoul(this_opt+6, NULL, 0);
2324 else if (!strncmp(this_opt, "left:", 5))
2325 left = simple_strtoul(this_opt+5, NULL, 0);
2326 else if (!strncmp(this_opt, "right:", 6))
2327 right = simple_strtoul(this_opt+6, NULL, 0);
2328 else if (!strncmp(this_opt, "upper:", 6))
2329 upper = simple_strtoul(this_opt+6, NULL, 0);
2330 else if (!strncmp(this_opt, "lower:", 6))
2331 lower = simple_strtoul(this_opt+6, NULL, 0);
2332 else if (!strncmp(this_opt, "pixclock:", 9))
2333 pixclock = simple_strtoul(this_opt+9, NULL, 0);
2334 else if (!strncmp(this_opt, "sync:", 5))
2335 sync = simple_strtoul(this_opt+5, NULL, 0);
2336 else if (!strncmp(this_opt, "vesa:", 5))
2337 vesa = simple_strtoul(this_opt+5, NULL, 0);
2338 else if (!strncmp(this_opt, "maxclk:", 7))
2339 maxclk = simple_strtoul(this_opt+7, NULL, 0);
2340 else if (!strncmp(this_opt, "fh:", 3))
2341 fh = simple_strtoul(this_opt+3, NULL, 0);
2342 else if (!strncmp(this_opt, "fv:", 3))
2343 fv = simple_strtoul(this_opt+3, NULL, 0);
2344 else if (!strncmp(this_opt, "mem:", 4))
2345 mem = simple_strtoul(this_opt+4, NULL, 0);
2346 else if (!strncmp(this_opt, "mode:", 5))
2347 strlcpy(videomode, this_opt+5, sizeof(videomode));
2348 else if (!strncmp(this_opt, "outputs:", 8))
2349 strlcpy(outputs, this_opt+8, sizeof(outputs));
2350 else if (!strncmp(this_opt, "dfp:", 4)) {
2351 dfp_type = simple_strtoul(this_opt+4, NULL, 0);
2352 dfp = 1;
2353 }
2354#ifdef CONFIG_PPC_PMAC
2355 else if (!strncmp(this_opt, "vmode:", 6)) {
2356 unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
2357 if (vmode > 0 && vmode <= VMODE_MAX)
2358 default_vmode = vmode;
2359 } else if (!strncmp(this_opt, "cmode:", 6)) {
2360 unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
2361 switch (cmode) {
2362 case 0:
2363 case 8:
2364 default_cmode = CMODE_8;
2365 break;
2366 case 15:
2367 case 16:
2368 default_cmode = CMODE_16;
2369 break;
2370 case 24:
2371 case 32:
2372 default_cmode = CMODE_32;
2373 break;
2374 }
2375 }
2376#endif
2377 else if (!strcmp(this_opt, "disabled")) /* nodisabled does not exist */
2378 disabled = 1;
2379 else if (!strcmp(this_opt, "enabled")) /* noenabled does not exist */
2380 disabled = 0;
2381 else if (!strcmp(this_opt, "sgram")) /* nosgram == sdram */
2382 sgram = 1;
2383 else if (!strcmp(this_opt, "sdram"))
2384 sgram = 0;
2385 else if (!strncmp(this_opt, "memtype:", 8))
2386 memtype = simple_strtoul(this_opt+8, NULL, 0);
2387 else {
2388 int value = 1;
2389
2390 if (!strncmp(this_opt, "no", 2)) {
2391 value = 0;
2392 this_opt += 2;
2393 }
2394 if (! strcmp(this_opt, "inverse"))
2395 inverse = value;
2396 else if (!strcmp(this_opt, "accel"))
2397 noaccel = !value;
2398 else if (!strcmp(this_opt, "pan"))
2399 nopan = !value;
2400 else if (!strcmp(this_opt, "pciretry"))
2401 no_pci_retry = !value;
2402 else if (!strcmp(this_opt, "vga"))
2403 novga = !value;
2404 else if (!strcmp(this_opt, "bios"))
2405 nobios = !value;
2406 else if (!strcmp(this_opt, "init"))
2407 noinit = !value;
2408#ifdef CONFIG_MTRR
2409 else if (!strcmp(this_opt, "mtrr"))
2410 mtrr = value;
2411#endif
2412 else if (!strcmp(this_opt, "inv24"))
2413 inv24 = value;
2414 else if (!strcmp(this_opt, "cross4MB"))
2415 cross4MB = value;
2416 else if (!strcmp(this_opt, "grayscale"))
2417 grayscale = value;
2418 else if (!strcmp(this_opt, "dfp"))
2419 dfp = value;
2420 else {
2421 strlcpy(videomode, this_opt, sizeof(videomode));
2422 }
2423 }
2424 }
2425 return 0;
2426}
2427
2428static int __initdata initialized = 0;
2429
2430static int __init matroxfb_init(void)
2431{
2432 char *option = NULL;
2433 int err = 0;
2434
2435 DBG(__func__)
2436
2437 if (fb_get_options("matroxfb", &option))
2438 return -ENODEV;
2439 matroxfb_setup(option);
2440
2441 if (disabled)
2442 return -ENXIO;
2443 if (!initialized) {
2444 initialized = 1;
2445 err = matrox_init();
2446 }
2447 hotplug = 1;
2448 /* never return failure, user can hotplug matrox later... */
2449 return err;
2450}
2451
2452module_init(matroxfb_init);
2453
2454#else
2455
2456/* *************************** init module code **************************** */
2457
2458MODULE_AUTHOR("(c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
2459MODULE_DESCRIPTION("Accelerated FBDev driver for Matrox Millennium/Mystique/G100/G200/G400/G450/G550");
2460MODULE_LICENSE("GPL");
2461
2462module_param(mem, int, 0);
2463MODULE_PARM_DESC(mem, "Size of available memory in MB, KB or B (2,4,8,12,16MB, default=autodetect)");
2464module_param(disabled, int, 0);
2465MODULE_PARM_DESC(disabled, "Disabled (0 or 1=disabled) (default=0)");
2466module_param(noaccel, int, 0);
2467MODULE_PARM_DESC(noaccel, "Do not use accelerating engine (0 or 1=disabled) (default=0)");
2468module_param(nopan, int, 0);
2469MODULE_PARM_DESC(nopan, "Disable pan on startup (0 or 1=disabled) (default=0)");
2470module_param(no_pci_retry, int, 0);
2471MODULE_PARM_DESC(no_pci_retry, "PCI retries enabled (0 or 1=disabled) (default=0)");
2472module_param(novga, int, 0);
2473MODULE_PARM_DESC(novga, "VGA I/O (0x3C0-0x3DF) disabled (0 or 1=disabled) (default=0)");
2474module_param(nobios, int, 0);
2475MODULE_PARM_DESC(nobios, "Disables ROM BIOS (0 or 1=disabled) (default=do not change BIOS state)");
2476module_param(noinit, int, 0);
2477MODULE_PARM_DESC(noinit, "Disables W/SG/SD-RAM and bus interface initialization (0 or 1=do not initialize) (default=0)");
2478module_param(memtype, int, 0);
2479MODULE_PARM_DESC(memtype, "Memory type for G200/G400 (see Documentation/fb/matroxfb.txt for explanation) (default=3 for G200, 0 for G400)");
2480#ifdef CONFIG_MTRR
2481module_param(mtrr, int, 0);
2482MODULE_PARM_DESC(mtrr, "This speeds up video memory accesses (0=disabled or 1) (default=1)");
2483#endif
2484module_param(sgram, int, 0);
2485MODULE_PARM_DESC(sgram, "Indicates that G100/G200/G400 has SGRAM memory (0=SDRAM, 1=SGRAM) (default=0)");
2486module_param(inv24, int, 0);
2487MODULE_PARM_DESC(inv24, "Inverts clock polarity for 24bpp and loop frequency > 100MHz (default=do not invert polarity)");
2488module_param(inverse, int, 0);
2489MODULE_PARM_DESC(inverse, "Inverse (0 or 1) (default=0)");
2490module_param(dev, int, 0);
2491MODULE_PARM_DESC(dev, "Multihead support, attach to device ID (0..N) (default=all working)");
2492module_param(vesa, int, 0);
2493MODULE_PARM_DESC(vesa, "Startup videomode (0x000-0x1FF) (default=0x101)");
2494module_param(xres, int, 0);
2495MODULE_PARM_DESC(xres, "Horizontal resolution (px), overrides xres from vesa (default=vesa)");
2496module_param(yres, int, 0);
2497MODULE_PARM_DESC(yres, "Vertical resolution (scans), overrides yres from vesa (default=vesa)");
2498module_param(upper, int, 0);
2499MODULE_PARM_DESC(upper, "Upper blank space (scans), overrides upper from vesa (default=vesa)");
2500module_param(lower, int, 0);
2501MODULE_PARM_DESC(lower, "Lower blank space (scans), overrides lower from vesa (default=vesa)");
2502module_param(vslen, int, 0);
2503MODULE_PARM_DESC(vslen, "Vertical sync length (scans), overrides lower from vesa (default=vesa)");
2504module_param(left, int, 0);
2505MODULE_PARM_DESC(left, "Left blank space (px), overrides left from vesa (default=vesa)");
2506module_param(right, int, 0);
2507MODULE_PARM_DESC(right, "Right blank space (px), overrides right from vesa (default=vesa)");
2508module_param(hslen, int, 0);
2509MODULE_PARM_DESC(hslen, "Horizontal sync length (px), overrides hslen from vesa (default=vesa)");
2510module_param(pixclock, int, 0);
2511MODULE_PARM_DESC(pixclock, "Pixelclock (ns), overrides pixclock from vesa (default=vesa)");
2512module_param(sync, int, 0);
2513MODULE_PARM_DESC(sync, "Sync polarity, overrides sync from vesa (default=vesa)");
2514module_param(depth, int, 0);
2515MODULE_PARM_DESC(depth, "Color depth (0=text,8,15,16,24,32) (default=vesa)");
2516module_param(maxclk, int, 0);
2517MODULE_PARM_DESC(maxclk, "Startup maximal clock, 0-999MHz, 1000-999999kHz, 1000000-INF Hz");
2518module_param(fh, int, 0);
2519MODULE_PARM_DESC(fh, "Startup horizontal frequency, 0-999kHz, 1000-INF Hz");
2520module_param(fv, int, 0);
2521MODULE_PARM_DESC(fv, "Startup vertical frequency, 0-INF Hz\n"
2522"You should specify \"fv:max_monitor_vsync,fh:max_monitor_hsync,maxclk:max_monitor_dotclock\"");
2523module_param(grayscale, int, 0);
2524MODULE_PARM_DESC(grayscale, "Sets display into grayscale. Works perfectly with paletized videomode (4, 8bpp), some limitations apply to 16, 24 and 32bpp videomodes (default=nograyscale)");
2525module_param(cross4MB, int, 0);
2526MODULE_PARM_DESC(cross4MB, "Specifies that 4MB boundary can be in middle of line. (default=autodetected)");
2527module_param(dfp, int, 0);
2528MODULE_PARM_DESC(dfp, "Specifies whether to use digital flat panel interface of G200/G400 (0 or 1) (default=0)");
2529module_param(dfp_type, int, 0);
2530MODULE_PARM_DESC(dfp_type, "Specifies DFP interface type (0 to 255) (default=read from hardware)");
2531module_param_string(outputs, outputs, sizeof(outputs), 0);
2532MODULE_PARM_DESC(outputs, "Specifies which CRTC is mapped to which output (string of up to three letters, consisting of 0 (disabled), 1 (CRTC1), 2 (CRTC2)) (default=111 for Gx50, 101 for G200/G400 with DFP, and 100 for all other devices)");
2533#ifdef CONFIG_PPC_PMAC
2534module_param_named(vmode, default_vmode, int, 0);
2535MODULE_PARM_DESC(vmode, "Specify the vmode mode number that should be used (640x480 default)");
2536module_param_named(cmode, default_cmode, int, 0);
2537MODULE_PARM_DESC(cmode, "Specify the video depth that should be used (8bit default)");
2538#endif
2539
2540int __init init_module(void){
2541
2542 DBG(__func__)
2543
2544 if (disabled)
2545 return -ENXIO;
2546
2547 if (depth == 0)
2548 depth = RSText;
2549 else if (depth == 4)
2550 depth = RS4bpp;
2551 else if (depth == 8)
2552 depth = RS8bpp;
2553 else if (depth == 15)
2554 depth = RS15bpp;
2555 else if (depth == 16)
2556 depth = RS16bpp;
2557 else if (depth == 24)
2558 depth = RS24bpp;
2559 else if (depth == 32)
2560 depth = RS32bpp;
2561 else if (depth != -1) {
2562 printk(KERN_ERR "matroxfb: depth %d is not supported, using default\n", depth);
2563 depth = -1;
2564 }
2565 matrox_init();
2566 /* never return failure; user can hotplug matrox later... */
2567 return 0;
2568}
2569#endif /* MODULE */
2570
2571module_exit(matrox_done);
2572EXPORT_SYMBOL(matroxfb_register_driver);
2573EXPORT_SYMBOL(matroxfb_unregister_driver);
2574EXPORT_SYMBOL(matroxfb_wait_for_sync);
2575EXPORT_SYMBOL(matroxfb_enable_irq);
2576
2577/*
2578 * Overrides for Emacs so that we follow Linus's tabbing style.
2579 * ---------------------------------------------------------------------------
2580 * Local variables:
2581 * c-basic-offset: 8
2582 * End:
2583 */
2584
diff --git a/drivers/video/fbdev/matrox/matroxfb_base.h b/drivers/video/fbdev/matrox/matroxfb_base.h
new file mode 100644
index 000000000000..556d96ce40bf
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_base.h
@@ -0,0 +1,735 @@
1/*
2 *
3 * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450
4 *
5 * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
6 *
7 */
8#ifndef __MATROXFB_H__
9#define __MATROXFB_H__
10
11/* general, but fairly heavy, debugging */
12#undef MATROXFB_DEBUG
13
14/* heavy debugging: */
15/* -- logs putc[s], so every time a char is displayed, it's logged */
16#undef MATROXFB_DEBUG_HEAVY
17
18/* This one _could_ cause infinite loops */
19/* It _does_ cause lots and lots of messages during idle loops */
20#undef MATROXFB_DEBUG_LOOP
21
22/* Debug register calls, too? */
23#undef MATROXFB_DEBUG_REG
24
25/* Guard accelerator accesses with spin_lock_irqsave... */
26#undef MATROXFB_USE_SPINLOCKS
27
28#include <linux/module.h>
29#include <linux/kernel.h>
30#include <linux/errno.h>
31#include <linux/string.h>
32#include <linux/mm.h>
33#include <linux/slab.h>
34#include <linux/delay.h>
35#include <linux/fb.h>
36#include <linux/console.h>
37#include <linux/selection.h>
38#include <linux/ioport.h>
39#include <linux/init.h>
40#include <linux/timer.h>
41#include <linux/pci.h>
42#include <linux/spinlock.h>
43#include <linux/kd.h>
44
45#include <asm/io.h>
46#include <asm/unaligned.h>
47#ifdef CONFIG_MTRR
48#include <asm/mtrr.h>
49#endif
50
51#if defined(CONFIG_PPC_PMAC)
52#include <asm/prom.h>
53#include <asm/pci-bridge.h>
54#include "../macmodes.h"
55#endif
56
57#ifdef MATROXFB_DEBUG
58
59#define DEBUG
60#define DBG(x) printk(KERN_DEBUG "matroxfb: %s\n", (x));
61
62#ifdef MATROXFB_DEBUG_HEAVY
63#define DBG_HEAVY(x) DBG(x)
64#else /* MATROXFB_DEBUG_HEAVY */
65#define DBG_HEAVY(x) /* DBG_HEAVY */
66#endif /* MATROXFB_DEBUG_HEAVY */
67
68#ifdef MATROXFB_DEBUG_LOOP
69#define DBG_LOOP(x) DBG(x)
70#else /* MATROXFB_DEBUG_LOOP */
71#define DBG_LOOP(x) /* DBG_LOOP */
72#endif /* MATROXFB_DEBUG_LOOP */
73
74#ifdef MATROXFB_DEBUG_REG
75#define DBG_REG(x) DBG(x)
76#else /* MATROXFB_DEBUG_REG */
77#define DBG_REG(x) /* DBG_REG */
78#endif /* MATROXFB_DEBUG_REG */
79
80#else /* MATROXFB_DEBUG */
81
82#define DBG(x) /* DBG */
83#define DBG_HEAVY(x) /* DBG_HEAVY */
84#define DBG_REG(x) /* DBG_REG */
85#define DBG_LOOP(x) /* DBG_LOOP */
86
87#endif /* MATROXFB_DEBUG */
88
89#ifdef DEBUG
90#define dprintk(X...) printk(X)
91#else
92#define dprintk(X...)
93#endif
94
95#ifndef PCI_SS_VENDOR_ID_SIEMENS_NIXDORF
96#define PCI_SS_VENDOR_ID_SIEMENS_NIXDORF 0x110A
97#endif
98#ifndef PCI_SS_VENDOR_ID_MATROX
99#define PCI_SS_VENDOR_ID_MATROX PCI_VENDOR_ID_MATROX
100#endif
101
102#ifndef PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP
103#define PCI_SS_ID_MATROX_GENERIC 0xFF00
104#define PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP 0xFF01
105#define PCI_SS_ID_MATROX_MYSTIQUE_G200_AGP 0xFF02
106#define PCI_SS_ID_MATROX_MILLENIUM_G200_AGP 0xFF03
107#define PCI_SS_ID_MATROX_MARVEL_G200_AGP 0xFF04
108#define PCI_SS_ID_MATROX_MGA_G100_PCI 0xFF05
109#define PCI_SS_ID_MATROX_MGA_G100_AGP 0x1001
110#define PCI_SS_ID_MATROX_MILLENNIUM_G400_MAX_AGP 0x2179
111#define PCI_SS_ID_SIEMENS_MGA_G100_AGP 0x001E /* 30 */
112#define PCI_SS_ID_SIEMENS_MGA_G200_AGP 0x0032 /* 50 */
113#endif
114
115#define MX_VISUAL_TRUECOLOR FB_VISUAL_DIRECTCOLOR
116#define MX_VISUAL_DIRECTCOLOR FB_VISUAL_TRUECOLOR
117#define MX_VISUAL_PSEUDOCOLOR FB_VISUAL_PSEUDOCOLOR
118
119#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
120
121/* G-series and Mystique have (almost) same DAC */
122#undef NEED_DAC1064
123#if defined(CONFIG_FB_MATROX_MYSTIQUE) || defined(CONFIG_FB_MATROX_G)
124#define NEED_DAC1064 1
125#endif
126
127typedef struct {
128 void __iomem* vaddr;
129} vaddr_t;
130
131static inline unsigned int mga_readb(vaddr_t va, unsigned int offs) {
132 return readb(va.vaddr + offs);
133}
134
135static inline void mga_writeb(vaddr_t va, unsigned int offs, u_int8_t value) {
136 writeb(value, va.vaddr + offs);
137}
138
139static inline void mga_writew(vaddr_t va, unsigned int offs, u_int16_t value) {
140 writew(value, va.vaddr + offs);
141}
142
143static inline u_int32_t mga_readl(vaddr_t va, unsigned int offs) {
144 return readl(va.vaddr + offs);
145}
146
147static inline void mga_writel(vaddr_t va, unsigned int offs, u_int32_t value) {
148 writel(value, va.vaddr + offs);
149}
150
151static inline void mga_memcpy_toio(vaddr_t va, const void* src, int len) {
152#if defined(__alpha__) || defined(__i386__) || defined(__x86_64__)
153 /*
154 * iowrite32_rep works for us if:
155 * (1) Copies data as 32bit quantities, not byte after byte,
156 * (2) Performs LE ordered stores, and
157 * (3) It copes with unaligned source (destination is guaranteed to be page
158 * aligned and length is guaranteed to be multiple of 4).
159 */
160 iowrite32_rep(va.vaddr, src, len >> 2);
161#else
162 u_int32_t __iomem* addr = va.vaddr;
163
164 if ((unsigned long)src & 3) {
165 while (len >= 4) {
166 fb_writel(get_unaligned((u32 *)src), addr);
167 addr++;
168 len -= 4;
169 src += 4;
170 }
171 } else {
172 while (len >= 4) {
173 fb_writel(*(u32 *)src, addr);
174 addr++;
175 len -= 4;
176 src += 4;
177 }
178 }
179#endif
180}
181
182static inline void vaddr_add(vaddr_t* va, unsigned long offs) {
183 va->vaddr += offs;
184}
185
186static inline void __iomem* vaddr_va(vaddr_t va) {
187 return va.vaddr;
188}
189
190#define MGA_IOREMAP_NORMAL 0
191#define MGA_IOREMAP_NOCACHE 1
192
193#define MGA_IOREMAP_FB MGA_IOREMAP_NOCACHE
194#define MGA_IOREMAP_MMIO MGA_IOREMAP_NOCACHE
195static inline int mga_ioremap(unsigned long phys, unsigned long size, int flags, vaddr_t* virt) {
196 if (flags & MGA_IOREMAP_NOCACHE)
197 virt->vaddr = ioremap_nocache(phys, size);
198 else
199 virt->vaddr = ioremap(phys, size);
200 return (virt->vaddr == NULL); /* 0, !0... 0, error_code in future */
201}
202
203static inline void mga_iounmap(vaddr_t va) {
204 iounmap(va.vaddr);
205}
206
207struct my_timming {
208 unsigned int pixclock;
209 int mnp;
210 unsigned int crtc;
211 unsigned int HDisplay;
212 unsigned int HSyncStart;
213 unsigned int HSyncEnd;
214 unsigned int HTotal;
215 unsigned int VDisplay;
216 unsigned int VSyncStart;
217 unsigned int VSyncEnd;
218 unsigned int VTotal;
219 unsigned int sync;
220 int dblscan;
221 int interlaced;
222 unsigned int delay; /* CRTC delay */
223};
224
225enum { M_SYSTEM_PLL, M_PIXEL_PLL_A, M_PIXEL_PLL_B, M_PIXEL_PLL_C, M_VIDEO_PLL };
226
227struct matrox_pll_cache {
228 unsigned int valid;
229 struct {
230 unsigned int mnp_key;
231 unsigned int mnp_value;
232 } data[4];
233};
234
235struct matrox_pll_limits {
236 unsigned int vcomin;
237 unsigned int vcomax;
238};
239
240struct matrox_pll_features {
241 unsigned int vco_freq_min;
242 unsigned int ref_freq;
243 unsigned int feed_div_min;
244 unsigned int feed_div_max;
245 unsigned int in_div_min;
246 unsigned int in_div_max;
247 unsigned int post_shift_max;
248};
249
250struct matroxfb_par
251{
252 unsigned int final_bppShift;
253 unsigned int cmap_len;
254 struct {
255 unsigned int bytes;
256 unsigned int pixels;
257 unsigned int chunks;
258 } ydstorg;
259};
260
261struct matrox_fb_info;
262
263struct matrox_DAC1064_features {
264 u_int8_t xvrefctrl;
265 u_int8_t xmiscctrl;
266};
267
268/* current hardware status */
269struct mavenregs {
270 u_int8_t regs[256];
271 int mode;
272 int vlines;
273 int xtal;
274 int fv;
275
276 u_int16_t htotal;
277 u_int16_t hcorr;
278};
279
280struct matrox_crtc2 {
281 u_int32_t ctl;
282};
283
284struct matrox_hw_state {
285 u_int32_t MXoptionReg;
286 unsigned char DACclk[6];
287 unsigned char DACreg[80];
288 unsigned char MiscOutReg;
289 unsigned char DACpal[768];
290 unsigned char CRTC[25];
291 unsigned char CRTCEXT[9];
292 unsigned char SEQ[5];
293 /* unused for MGA mode, but who knows... */
294 unsigned char GCTL[9];
295 /* unused for MGA mode, but who knows... */
296 unsigned char ATTR[21];
297
298 /* TVOut only */
299 struct mavenregs maven;
300
301 struct matrox_crtc2 crtc2;
302};
303
304struct matrox_accel_data {
305#ifdef CONFIG_FB_MATROX_MILLENIUM
306 unsigned char ramdac_rev;
307#endif
308 u_int32_t m_dwg_rect;
309 u_int32_t m_opmode;
310 u_int32_t m_access;
311 u_int32_t m_pitch;
312};
313
314struct v4l2_queryctrl;
315struct v4l2_control;
316
317struct matrox_altout {
318 const char *name;
319 int (*compute)(void* altout_dev, struct my_timming* input);
320 int (*program)(void* altout_dev);
321 int (*start)(void* altout_dev);
322 int (*verifymode)(void* altout_dev, u_int32_t mode);
323 int (*getqueryctrl)(void* altout_dev,
324 struct v4l2_queryctrl* ctrl);
325 int (*getctrl)(void* altout_dev,
326 struct v4l2_control* ctrl);
327 int (*setctrl)(void* altout_dev,
328 struct v4l2_control* ctrl);
329};
330
331#define MATROXFB_SRC_NONE 0
332#define MATROXFB_SRC_CRTC1 1
333#define MATROXFB_SRC_CRTC2 2
334
335enum mga_chip { MGA_2064, MGA_2164, MGA_1064, MGA_1164, MGA_G100, MGA_G200, MGA_G400, MGA_G450, MGA_G550 };
336
337struct matrox_bios {
338 unsigned int bios_valid : 1;
339 unsigned int pins_len;
340 unsigned char pins[128];
341 struct {
342 unsigned char vMaj, vMin, vRev;
343 } version;
344 struct {
345 unsigned char state, tvout;
346 } output;
347};
348
349struct matrox_switch;
350struct matroxfb_driver;
351struct matroxfb_dh_fb_info;
352
353struct matrox_vsync {
354 wait_queue_head_t wait;
355 unsigned int cnt;
356};
357
358struct matrox_fb_info {
359 struct fb_info fbcon;
360
361 struct list_head next_fb;
362
363 int dead;
364 int initialized;
365 unsigned int usecount;
366
367 unsigned int userusecount;
368 unsigned long irq_flags;
369
370 struct matroxfb_par curr;
371 struct matrox_hw_state hw;
372
373 struct matrox_accel_data accel;
374
375 struct pci_dev* pcidev;
376
377 struct {
378 struct matrox_vsync vsync;
379 unsigned int pixclock;
380 int mnp;
381 int panpos;
382 } crtc1;
383 struct {
384 struct matrox_vsync vsync;
385 unsigned int pixclock;
386 int mnp;
387 struct matroxfb_dh_fb_info* info;
388 struct rw_semaphore lock;
389 } crtc2;
390 struct {
391 struct rw_semaphore lock;
392 struct {
393 int brightness, contrast, saturation, hue, gamma;
394 int testout, deflicker;
395 } tvo_params;
396 } altout;
397#define MATROXFB_MAX_OUTPUTS 3
398 struct {
399 unsigned int src;
400 struct matrox_altout* output;
401 void* data;
402 unsigned int mode;
403 unsigned int default_src;
404 } outputs[MATROXFB_MAX_OUTPUTS];
405
406#define MATROXFB_MAX_FB_DRIVERS 5
407 struct matroxfb_driver* (drivers[MATROXFB_MAX_FB_DRIVERS]);
408 void* (drivers_data[MATROXFB_MAX_FB_DRIVERS]);
409 unsigned int drivers_count;
410
411 struct {
412 unsigned long base; /* physical */
413 vaddr_t vbase; /* CPU view */
414 unsigned int len;
415 unsigned int len_usable;
416 unsigned int len_maximum;
417 } video;
418
419 struct {
420 unsigned long base; /* physical */
421 vaddr_t vbase; /* CPU view */
422 unsigned int len;
423 } mmio;
424
425 unsigned int max_pixel_clock;
426 unsigned int max_pixel_clock_panellink;
427
428 struct matrox_switch* hw_switch;
429
430 struct {
431 struct matrox_pll_features pll;
432 struct matrox_DAC1064_features DAC1064;
433 } features;
434 struct {
435 spinlock_t DAC;
436 spinlock_t accel;
437 } lock;
438
439 enum mga_chip chip;
440
441 int interleave;
442 int millenium;
443 int milleniumII;
444 struct {
445 int cfb4;
446 const int* vxres;
447 int cross4MB;
448 int text;
449 int plnwt;
450 int srcorg;
451 } capable;
452#ifdef CONFIG_MTRR
453 struct {
454 int vram;
455 int vram_valid;
456 } mtrr;
457#endif
458 struct {
459 int precise_width;
460 int mga_24bpp_fix;
461 int novga;
462 int nobios;
463 int nopciretry;
464 int noinit;
465 int sgram;
466 int support32MB;
467
468 int accelerator;
469 int text_type_aux;
470 int video64bits;
471 int crtc2;
472 int maven_capable;
473 unsigned int vgastep;
474 unsigned int textmode;
475 unsigned int textstep;
476 unsigned int textvram; /* character cells */
477 unsigned int ydstorg; /* offset in bytes from video start to usable memory */
478 /* 0 except for 6MB Millenium */
479 int memtype;
480 int g450dac;
481 int dfp_type;
482 int panellink; /* G400 DFP possible (not G450/G550) */
483 int dualhead;
484 unsigned int fbResource;
485 } devflags;
486 struct fb_ops fbops;
487 struct matrox_bios bios;
488 struct {
489 struct matrox_pll_limits pixel;
490 struct matrox_pll_limits system;
491 struct matrox_pll_limits video;
492 } limits;
493 struct {
494 struct matrox_pll_cache pixel;
495 struct matrox_pll_cache system;
496 struct matrox_pll_cache video;
497 } cache;
498 struct {
499 struct {
500 unsigned int video;
501 unsigned int system;
502 } pll;
503 struct {
504 u_int32_t opt;
505 u_int32_t opt2;
506 u_int32_t opt3;
507 u_int32_t mctlwtst;
508 u_int32_t mctlwtst_core;
509 u_int32_t memmisc;
510 u_int32_t memrdbk;
511 u_int32_t maccess;
512 } reg;
513 struct {
514 unsigned int ddr:1,
515 emrswen:1,
516 dll:1;
517 } memory;
518 } values;
519 u_int32_t cmap[16];
520};
521
522#define info2minfo(info) container_of(info, struct matrox_fb_info, fbcon)
523
524struct matrox_switch {
525 int (*preinit)(struct matrox_fb_info *minfo);
526 void (*reset)(struct matrox_fb_info *minfo);
527 int (*init)(struct matrox_fb_info *minfo, struct my_timming*);
528 void (*restore)(struct matrox_fb_info *minfo);
529};
530
531struct matroxfb_driver {
532 struct list_head node;
533 char* name;
534 void* (*probe)(struct matrox_fb_info* info);
535 void (*remove)(struct matrox_fb_info* info, void* data);
536};
537
538int matroxfb_register_driver(struct matroxfb_driver* drv);
539void matroxfb_unregister_driver(struct matroxfb_driver* drv);
540
541#define PCI_OPTION_REG 0x40
542#define PCI_OPTION_ENABLE_ROM 0x40000000
543
544#define PCI_MGA_INDEX 0x44
545#define PCI_MGA_DATA 0x48
546#define PCI_OPTION2_REG 0x50
547#define PCI_OPTION3_REG 0x54
548#define PCI_MEMMISC_REG 0x58
549
550#define M_DWGCTL 0x1C00
551#define M_MACCESS 0x1C04
552#define M_CTLWTST 0x1C08
553
554#define M_PLNWT 0x1C1C
555
556#define M_BCOL 0x1C20
557#define M_FCOL 0x1C24
558
559#define M_SGN 0x1C58
560#define M_LEN 0x1C5C
561#define M_AR0 0x1C60
562#define M_AR1 0x1C64
563#define M_AR2 0x1C68
564#define M_AR3 0x1C6C
565#define M_AR4 0x1C70
566#define M_AR5 0x1C74
567#define M_AR6 0x1C78
568
569#define M_CXBNDRY 0x1C80
570#define M_FXBNDRY 0x1C84
571#define M_YDSTLEN 0x1C88
572#define M_PITCH 0x1C8C
573#define M_YDST 0x1C90
574#define M_YDSTORG 0x1C94
575#define M_YTOP 0x1C98
576#define M_YBOT 0x1C9C
577
578/* mystique only */
579#define M_CACHEFLUSH 0x1FFF
580
581#define M_EXEC 0x0100
582
583#define M_DWG_TRAP 0x04
584#define M_DWG_BITBLT 0x08
585#define M_DWG_ILOAD 0x09
586
587#define M_DWG_LINEAR 0x0080
588#define M_DWG_SOLID 0x0800
589#define M_DWG_ARZERO 0x1000
590#define M_DWG_SGNZERO 0x2000
591#define M_DWG_SHIFTZERO 0x4000
592
593#define M_DWG_REPLACE 0x000C0000
594#define M_DWG_REPLACE2 (M_DWG_REPLACE | 0x40)
595#define M_DWG_XOR 0x00060010
596
597#define M_DWG_BFCOL 0x04000000
598#define M_DWG_BMONOWF 0x08000000
599
600#define M_DWG_TRANSC 0x40000000
601
602#define M_FIFOSTATUS 0x1E10
603#define M_STATUS 0x1E14
604#define M_ICLEAR 0x1E18
605#define M_IEN 0x1E1C
606
607#define M_VCOUNT 0x1E20
608
609#define M_RESET 0x1E40
610#define M_MEMRDBK 0x1E44
611
612#define M_AGP2PLL 0x1E4C
613
614#define M_OPMODE 0x1E54
615#define M_OPMODE_DMA_GEN_WRITE 0x00
616#define M_OPMODE_DMA_BLIT 0x04
617#define M_OPMODE_DMA_VECTOR_WRITE 0x08
618#define M_OPMODE_DMA_LE 0x0000 /* little endian - no transformation */
619#define M_OPMODE_DMA_BE_8BPP 0x0000
620#define M_OPMODE_DMA_BE_16BPP 0x0100
621#define M_OPMODE_DMA_BE_32BPP 0x0200
622#define M_OPMODE_DIR_LE 0x000000 /* little endian - no transformation */
623#define M_OPMODE_DIR_BE_8BPP 0x000000
624#define M_OPMODE_DIR_BE_16BPP 0x010000
625#define M_OPMODE_DIR_BE_32BPP 0x020000
626
627#define M_ATTR_INDEX 0x1FC0
628#define M_ATTR_DATA 0x1FC1
629
630#define M_MISC_REG 0x1FC2
631#define M_3C2_RD 0x1FC2
632
633#define M_SEQ_INDEX 0x1FC4
634#define M_SEQ_DATA 0x1FC5
635#define M_SEQ1 0x01
636#define M_SEQ1_SCROFF 0x20
637
638#define M_MISC_REG_READ 0x1FCC
639
640#define M_GRAPHICS_INDEX 0x1FCE
641#define M_GRAPHICS_DATA 0x1FCF
642
643#define M_CRTC_INDEX 0x1FD4
644
645#define M_ATTR_RESET 0x1FDA
646#define M_3DA_WR 0x1FDA
647#define M_INSTS1 0x1FDA
648
649#define M_EXTVGA_INDEX 0x1FDE
650#define M_EXTVGA_DATA 0x1FDF
651
652/* G200 only */
653#define M_SRCORG 0x2CB4
654#define M_DSTORG 0x2CB8
655
656#define M_RAMDAC_BASE 0x3C00
657
658/* fortunately, same on TVP3026 and MGA1064 */
659#define M_DAC_REG (M_RAMDAC_BASE+0)
660#define M_DAC_VAL (M_RAMDAC_BASE+1)
661#define M_PALETTE_MASK (M_RAMDAC_BASE+2)
662
663#define M_X_INDEX 0x00
664#define M_X_DATAREG 0x0A
665
666#define DAC_XGENIOCTRL 0x2A
667#define DAC_XGENIODATA 0x2B
668
669#define M_C2CTL 0x3C10
670
671#define MX_OPTION_BSWAP 0x00000000
672
673#ifdef __LITTLE_ENDIAN
674#define M_OPMODE_4BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
675#define M_OPMODE_8BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
676#define M_OPMODE_16BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
677#define M_OPMODE_24BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
678#define M_OPMODE_32BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT)
679#else
680#ifdef __BIG_ENDIAN
681#define M_OPMODE_4BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_LE | M_OPMODE_DMA_BLIT) /* TODO */
682#define M_OPMODE_8BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_BE_8BPP | M_OPMODE_DMA_BLIT)
683#define M_OPMODE_16BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_BE_16BPP | M_OPMODE_DMA_BLIT)
684#define M_OPMODE_24BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_BE_8BPP | M_OPMODE_DMA_BLIT) /* TODO, ?32 */
685#define M_OPMODE_32BPP (M_OPMODE_DMA_LE | M_OPMODE_DIR_BE_32BPP | M_OPMODE_DMA_BLIT)
686#else
687#error "Byte ordering have to be defined. Cannot continue."
688#endif
689#endif
690
691#define mga_inb(addr) mga_readb(minfo->mmio.vbase, (addr))
692#define mga_inl(addr) mga_readl(minfo->mmio.vbase, (addr))
693#define mga_outb(addr,val) mga_writeb(minfo->mmio.vbase, (addr), (val))
694#define mga_outw(addr,val) mga_writew(minfo->mmio.vbase, (addr), (val))
695#define mga_outl(addr,val) mga_writel(minfo->mmio.vbase, (addr), (val))
696#define mga_readr(port,idx) (mga_outb((port),(idx)), mga_inb((port)+1))
697#define mga_setr(addr,port,val) mga_outw(addr, ((val)<<8) | (port))
698
699#define mga_fifo(n) do {} while ((mga_inl(M_FIFOSTATUS) & 0xFF) < (n))
700
701#define WaitTillIdle() do {} while (mga_inl(M_STATUS) & 0x10000)
702
703/* code speedup */
704#ifdef CONFIG_FB_MATROX_MILLENIUM
705#define isInterleave(x) (x->interleave)
706#define isMillenium(x) (x->millenium)
707#define isMilleniumII(x) (x->milleniumII)
708#else
709#define isInterleave(x) (0)
710#define isMillenium(x) (0)
711#define isMilleniumII(x) (0)
712#endif
713
714#define matroxfb_DAC_lock() spin_lock(&minfo->lock.DAC)
715#define matroxfb_DAC_unlock() spin_unlock(&minfo->lock.DAC)
716#define matroxfb_DAC_lock_irqsave(flags) spin_lock_irqsave(&minfo->lock.DAC, flags)
717#define matroxfb_DAC_unlock_irqrestore(flags) spin_unlock_irqrestore(&minfo->lock.DAC, flags)
718extern void matroxfb_DAC_out(const struct matrox_fb_info *minfo, int reg,
719 int val);
720extern int matroxfb_DAC_in(const struct matrox_fb_info *minfo, int reg);
721extern void matroxfb_var2my(struct fb_var_screeninfo* fvsi, struct my_timming* mt);
722extern int matroxfb_wait_for_sync(struct matrox_fb_info *minfo, u_int32_t crtc);
723extern int matroxfb_enable_irq(struct matrox_fb_info *minfo, int reenable);
724
725#ifdef MATROXFB_USE_SPINLOCKS
726#define CRITBEGIN spin_lock_irqsave(&minfo->lock.accel, critflags);
727#define CRITEND spin_unlock_irqrestore(&minfo->lock.accel, critflags);
728#define CRITFLAGS unsigned long critflags;
729#else
730#define CRITBEGIN
731#define CRITEND
732#define CRITFLAGS
733#endif
734
735#endif /* __MATROXFB_H__ */
diff --git a/drivers/video/fbdev/matrox/matroxfb_crtc2.c b/drivers/video/fbdev/matrox/matroxfb_crtc2.c
new file mode 100644
index 000000000000..02796a4317a9
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_crtc2.c
@@ -0,0 +1,739 @@
1/*
2 *
3 * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
4 *
5 * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
6 *
7 * Portions Copyright (c) 2001 Matrox Graphics Inc.
8 *
9 * Version: 1.65 2002/08/14
10 *
11 */
12
13#include "matroxfb_maven.h"
14#include "matroxfb_crtc2.h"
15#include "matroxfb_misc.h"
16#include "matroxfb_DAC1064.h"
17#include <linux/matroxfb.h>
18#include <linux/slab.h>
19#include <linux/uaccess.h>
20
21/* **************************************************** */
22
23static int mem = 8192;
24
25module_param(mem, int, 0);
26MODULE_PARM_DESC(mem, "Memory size reserved for dualhead (default=8MB)");
27
28/* **************************************************** */
29
30static int matroxfb_dh_setcolreg(unsigned regno, unsigned red, unsigned green,
31 unsigned blue, unsigned transp, struct fb_info* info) {
32 u_int32_t col;
33#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
34
35 if (regno >= 16)
36 return 1;
37 if (m2info->fbcon.var.grayscale) {
38 /* gray = 0.30*R + 0.59*G + 0.11*B */
39 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
40 }
41 red = CNVT_TOHW(red, m2info->fbcon.var.red.length);
42 green = CNVT_TOHW(green, m2info->fbcon.var.green.length);
43 blue = CNVT_TOHW(blue, m2info->fbcon.var.blue.length);
44 transp = CNVT_TOHW(transp, m2info->fbcon.var.transp.length);
45
46 col = (red << m2info->fbcon.var.red.offset) |
47 (green << m2info->fbcon.var.green.offset) |
48 (blue << m2info->fbcon.var.blue.offset) |
49 (transp << m2info->fbcon.var.transp.offset);
50
51 switch (m2info->fbcon.var.bits_per_pixel) {
52 case 16:
53 m2info->cmap[regno] = col | (col << 16);
54 break;
55 case 32:
56 m2info->cmap[regno] = col;
57 break;
58 }
59 return 0;
60#undef m2info
61}
62
63static void matroxfb_dh_restore(struct matroxfb_dh_fb_info* m2info,
64 struct my_timming* mt,
65 int mode,
66 unsigned int pos) {
67 u_int32_t tmp;
68 u_int32_t datactl;
69 struct matrox_fb_info *minfo = m2info->primary_dev;
70
71 switch (mode) {
72 case 15:
73 tmp = 0x00200000;
74 break;
75 case 16:
76 tmp = 0x00400000;
77 break;
78/* case 32: */
79 default:
80 tmp = 0x00800000;
81 break;
82 }
83 tmp |= 0x00000001; /* enable CRTC2 */
84 datactl = 0;
85 if (minfo->outputs[1].src == MATROXFB_SRC_CRTC2) {
86 if (minfo->devflags.g450dac) {
87 tmp |= 0x00000006; /* source from secondary pixel PLL */
88 /* no vidrst when in monitor mode */
89 if (minfo->outputs[1].mode != MATROXFB_OUTPUT_MODE_MONITOR) {
90 tmp |= 0xC0001000; /* Enable H/V vidrst */
91 }
92 } else {
93 tmp |= 0x00000002; /* source from VDOCLK */
94 tmp |= 0xC0000000; /* enable vvidrst & hvidrst */
95 /* MGA TVO is our clock source */
96 }
97 } else if (minfo->outputs[0].src == MATROXFB_SRC_CRTC2) {
98 tmp |= 0x00000004; /* source from pixclock */
99 /* PIXPLL is our clock source */
100 }
101 if (minfo->outputs[0].src == MATROXFB_SRC_CRTC2) {
102 tmp |= 0x00100000; /* connect CRTC2 to DAC */
103 }
104 if (mt->interlaced) {
105 tmp |= 0x02000000; /* interlaced, second field is bigger, as G450 apparently ignores it */
106 mt->VDisplay >>= 1;
107 mt->VSyncStart >>= 1;
108 mt->VSyncEnd >>= 1;
109 mt->VTotal >>= 1;
110 }
111 if ((mt->HTotal & 7) == 2) {
112 datactl |= 0x00000010;
113 mt->HTotal &= ~7;
114 }
115 tmp |= 0x10000000; /* 0x10000000 is VIDRST polarity */
116 mga_outl(0x3C14, ((mt->HDisplay - 8) << 16) | (mt->HTotal - 8));
117 mga_outl(0x3C18, ((mt->HSyncEnd - 8) << 16) | (mt->HSyncStart - 8));
118 mga_outl(0x3C1C, ((mt->VDisplay - 1) << 16) | (mt->VTotal - 1));
119 mga_outl(0x3C20, ((mt->VSyncEnd - 1) << 16) | (mt->VSyncStart - 1));
120 mga_outl(0x3C24, ((mt->VSyncStart) << 16) | (mt->HSyncStart)); /* preload */
121 {
122 u_int32_t linelen = m2info->fbcon.var.xres_virtual * (m2info->fbcon.var.bits_per_pixel >> 3);
123 if (tmp & 0x02000000) {
124 /* field #0 is smaller, so... */
125 mga_outl(0x3C2C, pos); /* field #1 vmemory start */
126 mga_outl(0x3C28, pos + linelen); /* field #0 vmemory start */
127 linelen <<= 1;
128 m2info->interlaced = 1;
129 } else {
130 mga_outl(0x3C28, pos); /* vmemory start */
131 m2info->interlaced = 0;
132 }
133 mga_outl(0x3C40, linelen);
134 }
135 mga_outl(0x3C4C, datactl); /* data control */
136 if (tmp & 0x02000000) {
137 int i;
138
139 mga_outl(0x3C10, tmp & ~0x02000000);
140 for (i = 0; i < 2; i++) {
141 unsigned int nl;
142 unsigned int lastl = 0;
143
144 while ((nl = mga_inl(0x3C48) & 0xFFF) >= lastl) {
145 lastl = nl;
146 }
147 }
148 }
149 mga_outl(0x3C10, tmp);
150 minfo->hw.crtc2.ctl = tmp;
151
152 tmp = mt->VDisplay << 16; /* line compare */
153 if (mt->sync & FB_SYNC_HOR_HIGH_ACT)
154 tmp |= 0x00000100;
155 if (mt->sync & FB_SYNC_VERT_HIGH_ACT)
156 tmp |= 0x00000200;
157 mga_outl(0x3C44, tmp);
158}
159
160static void matroxfb_dh_disable(struct matroxfb_dh_fb_info* m2info) {
161 struct matrox_fb_info *minfo = m2info->primary_dev;
162
163 mga_outl(0x3C10, 0x00000004); /* disable CRTC2, CRTC1->DAC1, PLL as clock source */
164 minfo->hw.crtc2.ctl = 0x00000004;
165}
166
167static void matroxfb_dh_pan_var(struct matroxfb_dh_fb_info* m2info,
168 struct fb_var_screeninfo* var) {
169 unsigned int pos;
170 unsigned int linelen;
171 unsigned int pixelsize;
172 struct matrox_fb_info *minfo = m2info->primary_dev;
173
174 m2info->fbcon.var.xoffset = var->xoffset;
175 m2info->fbcon.var.yoffset = var->yoffset;
176 pixelsize = m2info->fbcon.var.bits_per_pixel >> 3;
177 linelen = m2info->fbcon.var.xres_virtual * pixelsize;
178 pos = m2info->fbcon.var.yoffset * linelen + m2info->fbcon.var.xoffset * pixelsize;
179 pos += m2info->video.offbase;
180 if (m2info->interlaced) {
181 mga_outl(0x3C2C, pos);
182 mga_outl(0x3C28, pos + linelen);
183 } else {
184 mga_outl(0x3C28, pos);
185 }
186}
187
188static int matroxfb_dh_decode_var(struct matroxfb_dh_fb_info* m2info,
189 struct fb_var_screeninfo* var,
190 int *visual,
191 int *video_cmap_len,
192 int *mode) {
193 unsigned int mask;
194 unsigned int memlen;
195 unsigned int vramlen;
196
197 switch (var->bits_per_pixel) {
198 case 16: mask = 0x1F;
199 break;
200 case 32: mask = 0x0F;
201 break;
202 default: return -EINVAL;
203 }
204 vramlen = m2info->video.len_usable;
205 if (var->yres_virtual < var->yres)
206 var->yres_virtual = var->yres;
207 if (var->xres_virtual < var->xres)
208 var->xres_virtual = var->xres;
209 var->xres_virtual = (var->xres_virtual + mask) & ~mask;
210 if (var->yres_virtual > 32767)
211 return -EINVAL;
212 memlen = var->xres_virtual * var->yres_virtual * (var->bits_per_pixel >> 3);
213 if (memlen > vramlen)
214 return -EINVAL;
215 if (var->xoffset + var->xres > var->xres_virtual)
216 var->xoffset = var->xres_virtual - var->xres;
217 if (var->yoffset + var->yres > var->yres_virtual)
218 var->yoffset = var->yres_virtual - var->yres;
219
220 var->xres &= ~7;
221 var->left_margin &= ~7;
222 var->right_margin &= ~7;
223 var->hsync_len &= ~7;
224
225 *mode = var->bits_per_pixel;
226 if (var->bits_per_pixel == 16) {
227 if (var->green.length == 5) {
228 var->red.offset = 10;
229 var->red.length = 5;
230 var->green.offset = 5;
231 var->green.length = 5;
232 var->blue.offset = 0;
233 var->blue.length = 5;
234 var->transp.offset = 15;
235 var->transp.length = 1;
236 *mode = 15;
237 } else {
238 var->red.offset = 11;
239 var->red.length = 5;
240 var->green.offset = 5;
241 var->green.length = 6;
242 var->blue.offset = 0;
243 var->blue.length = 5;
244 var->transp.offset = 0;
245 var->transp.length = 0;
246 }
247 } else {
248 var->red.offset = 16;
249 var->red.length = 8;
250 var->green.offset = 8;
251 var->green.length = 8;
252 var->blue.offset = 0;
253 var->blue.length = 8;
254 var->transp.offset = 24;
255 var->transp.length = 8;
256 }
257 *visual = FB_VISUAL_TRUECOLOR;
258 *video_cmap_len = 16;
259 return 0;
260}
261
262static int matroxfb_dh_open(struct fb_info* info, int user) {
263#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
264 struct matrox_fb_info *minfo = m2info->primary_dev;
265
266 if (minfo) {
267 int err;
268
269 if (minfo->dead) {
270 return -ENXIO;
271 }
272 err = minfo->fbops.fb_open(&minfo->fbcon, user);
273 if (err) {
274 return err;
275 }
276 }
277 return 0;
278#undef m2info
279}
280
281static int matroxfb_dh_release(struct fb_info* info, int user) {
282#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
283 int err = 0;
284 struct matrox_fb_info *minfo = m2info->primary_dev;
285
286 if (minfo) {
287 err = minfo->fbops.fb_release(&minfo->fbcon, user);
288 }
289 return err;
290#undef m2info
291}
292
293/*
294 * This function is called before the register_framebuffer so
295 * no locking is needed.
296 */
297static void matroxfb_dh_init_fix(struct matroxfb_dh_fb_info *m2info)
298{
299 struct fb_fix_screeninfo *fix = &m2info->fbcon.fix;
300
301 strcpy(fix->id, "MATROX DH");
302
303 fix->smem_start = m2info->video.base;
304 fix->smem_len = m2info->video.len_usable;
305 fix->ypanstep = 1;
306 fix->ywrapstep = 0;
307 fix->xpanstep = 8; /* TBD */
308 fix->mmio_start = m2info->mmio.base;
309 fix->mmio_len = m2info->mmio.len;
310 fix->accel = 0; /* no accel... */
311}
312
313static int matroxfb_dh_check_var(struct fb_var_screeninfo* var, struct fb_info* info) {
314#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
315 int visual;
316 int cmap_len;
317 int mode;
318
319 return matroxfb_dh_decode_var(m2info, var, &visual, &cmap_len, &mode);
320#undef m2info
321}
322
323static int matroxfb_dh_set_par(struct fb_info* info) {
324#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
325 int visual;
326 int cmap_len;
327 int mode;
328 int err;
329 struct fb_var_screeninfo* var = &info->var;
330 struct matrox_fb_info *minfo = m2info->primary_dev;
331
332 if ((err = matroxfb_dh_decode_var(m2info, var, &visual, &cmap_len, &mode)) != 0)
333 return err;
334 /* cmap */
335 {
336 m2info->fbcon.screen_base = vaddr_va(m2info->video.vbase);
337 m2info->fbcon.fix.visual = visual;
338 m2info->fbcon.fix.type = FB_TYPE_PACKED_PIXELS;
339 m2info->fbcon.fix.type_aux = 0;
340 m2info->fbcon.fix.line_length = (var->xres_virtual * var->bits_per_pixel) >> 3;
341 }
342 {
343 struct my_timming mt;
344 unsigned int pos;
345 int out;
346 int cnt;
347
348 matroxfb_var2my(&m2info->fbcon.var, &mt);
349 mt.crtc = MATROXFB_SRC_CRTC2;
350 /* CRTC2 delay */
351 mt.delay = 34;
352
353 pos = (m2info->fbcon.var.yoffset * m2info->fbcon.var.xres_virtual + m2info->fbcon.var.xoffset) * m2info->fbcon.var.bits_per_pixel >> 3;
354 pos += m2info->video.offbase;
355 cnt = 0;
356 down_read(&minfo->altout.lock);
357 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
358 if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2) {
359 cnt++;
360 if (minfo->outputs[out].output->compute) {
361 minfo->outputs[out].output->compute(minfo->outputs[out].data, &mt);
362 }
363 }
364 }
365 minfo->crtc2.pixclock = mt.pixclock;
366 minfo->crtc2.mnp = mt.mnp;
367 up_read(&minfo->altout.lock);
368 if (cnt) {
369 matroxfb_dh_restore(m2info, &mt, mode, pos);
370 } else {
371 matroxfb_dh_disable(m2info);
372 }
373 DAC1064_global_init(minfo);
374 DAC1064_global_restore(minfo);
375 down_read(&minfo->altout.lock);
376 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
377 if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2 &&
378 minfo->outputs[out].output->program) {
379 minfo->outputs[out].output->program(minfo->outputs[out].data);
380 }
381 }
382 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
383 if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2 &&
384 minfo->outputs[out].output->start) {
385 minfo->outputs[out].output->start(minfo->outputs[out].data);
386 }
387 }
388 up_read(&minfo->altout.lock);
389 }
390 m2info->initialized = 1;
391 return 0;
392#undef m2info
393}
394
395static int matroxfb_dh_pan_display(struct fb_var_screeninfo* var, struct fb_info* info) {
396#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
397 matroxfb_dh_pan_var(m2info, var);
398 return 0;
399#undef m2info
400}
401
402static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, struct fb_vblank* vblank) {
403 struct matrox_fb_info *minfo = m2info->primary_dev;
404
405 matroxfb_enable_irq(minfo, 0);
406 memset(vblank, 0, sizeof(*vblank));
407 vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VBLANK;
408 /* mask out reserved bits + field number (odd/even) */
409 vblank->vcount = mga_inl(0x3C48) & 0x000007FF;
410 /* compatibility stuff */
411 if (vblank->vcount >= m2info->fbcon.var.yres)
412 vblank->flags |= FB_VBLANK_VBLANKING;
413 if (test_bit(0, &minfo->irq_flags)) {
414 vblank->flags |= FB_VBLANK_HAVE_COUNT;
415 /* Only one writer, aligned int value...
416 it should work without lock and without atomic_t */
417 vblank->count = minfo->crtc2.vsync.cnt;
418 }
419 return 0;
420}
421
422static int matroxfb_dh_ioctl(struct fb_info *info,
423 unsigned int cmd,
424 unsigned long arg)
425{
426#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
427 struct matrox_fb_info *minfo = m2info->primary_dev;
428
429 DBG(__func__)
430
431 switch (cmd) {
432 case FBIOGET_VBLANK:
433 {
434 struct fb_vblank vblank;
435 int err;
436
437 err = matroxfb_dh_get_vblank(m2info, &vblank);
438 if (err)
439 return err;
440 if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank)))
441 return -EFAULT;
442 return 0;
443 }
444 case FBIO_WAITFORVSYNC:
445 {
446 u_int32_t crt;
447
448 if (get_user(crt, (u_int32_t __user *)arg))
449 return -EFAULT;
450
451 if (crt != 0)
452 return -ENODEV;
453 return matroxfb_wait_for_sync(minfo, 1);
454 }
455 case MATROXFB_SET_OUTPUT_MODE:
456 case MATROXFB_GET_OUTPUT_MODE:
457 case MATROXFB_GET_ALL_OUTPUTS:
458 {
459 return minfo->fbcon.fbops->fb_ioctl(&minfo->fbcon, cmd, arg);
460 }
461 case MATROXFB_SET_OUTPUT_CONNECTION:
462 {
463 u_int32_t tmp;
464 int out;
465 int changes;
466
467 if (get_user(tmp, (u_int32_t __user *)arg))
468 return -EFAULT;
469 for (out = 0; out < 32; out++) {
470 if (tmp & (1 << out)) {
471 if (out >= MATROXFB_MAX_OUTPUTS)
472 return -ENXIO;
473 if (!minfo->outputs[out].output)
474 return -ENXIO;
475 switch (minfo->outputs[out].src) {
476 case MATROXFB_SRC_NONE:
477 case MATROXFB_SRC_CRTC2:
478 break;
479 default:
480 return -EBUSY;
481 }
482 }
483 }
484 if (minfo->devflags.panellink) {
485 if (tmp & MATROXFB_OUTPUT_CONN_DFP)
486 return -EINVAL;
487 if ((minfo->outputs[2].src == MATROXFB_SRC_CRTC1) && tmp)
488 return -EBUSY;
489 }
490 changes = 0;
491 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
492 if (tmp & (1 << out)) {
493 if (minfo->outputs[out].src != MATROXFB_SRC_CRTC2) {
494 changes = 1;
495 minfo->outputs[out].src = MATROXFB_SRC_CRTC2;
496 }
497 } else if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2) {
498 changes = 1;
499 minfo->outputs[out].src = MATROXFB_SRC_NONE;
500 }
501 }
502 if (!changes)
503 return 0;
504 matroxfb_dh_set_par(info);
505 return 0;
506 }
507 case MATROXFB_GET_OUTPUT_CONNECTION:
508 {
509 u_int32_t conn = 0;
510 int out;
511
512 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
513 if (minfo->outputs[out].src == MATROXFB_SRC_CRTC2) {
514 conn |= 1 << out;
515 }
516 }
517 if (put_user(conn, (u_int32_t __user *)arg))
518 return -EFAULT;
519 return 0;
520 }
521 case MATROXFB_GET_AVAILABLE_OUTPUTS:
522 {
523 u_int32_t tmp = 0;
524 int out;
525
526 for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {
527 if (minfo->outputs[out].output) {
528 switch (minfo->outputs[out].src) {
529 case MATROXFB_SRC_NONE:
530 case MATROXFB_SRC_CRTC2:
531 tmp |= 1 << out;
532 break;
533 }
534 }
535 }
536 if (minfo->devflags.panellink) {
537 tmp &= ~MATROXFB_OUTPUT_CONN_DFP;
538 if (minfo->outputs[2].src == MATROXFB_SRC_CRTC1) {
539 tmp = 0;
540 }
541 }
542 if (put_user(tmp, (u_int32_t __user *)arg))
543 return -EFAULT;
544 return 0;
545 }
546 }
547 return -ENOTTY;
548#undef m2info
549}
550
551static int matroxfb_dh_blank(int blank, struct fb_info* info) {
552#define m2info (container_of(info, struct matroxfb_dh_fb_info, fbcon))
553 switch (blank) {
554 case 1:
555 case 2:
556 case 3:
557 case 4:
558 default:;
559 }
560 /* do something... */
561 return 0;
562#undef m2info
563}
564
565static struct fb_ops matroxfb_dh_ops = {
566 .owner = THIS_MODULE,
567 .fb_open = matroxfb_dh_open,
568 .fb_release = matroxfb_dh_release,
569 .fb_check_var = matroxfb_dh_check_var,
570 .fb_set_par = matroxfb_dh_set_par,
571 .fb_setcolreg = matroxfb_dh_setcolreg,
572 .fb_pan_display =matroxfb_dh_pan_display,
573 .fb_blank = matroxfb_dh_blank,
574 .fb_ioctl = matroxfb_dh_ioctl,
575 .fb_fillrect = cfb_fillrect,
576 .fb_copyarea = cfb_copyarea,
577 .fb_imageblit = cfb_imageblit,
578};
579
580static struct fb_var_screeninfo matroxfb_dh_defined = {
581 640,480,640,480,/* W,H, virtual W,H */
582 0,0, /* offset */
583 32, /* depth */
584 0, /* gray */
585 {0,0,0}, /* R */
586 {0,0,0}, /* G */
587 {0,0,0}, /* B */
588 {0,0,0}, /* alpha */
589 0, /* nonstd */
590 FB_ACTIVATE_NOW,
591 -1,-1, /* display size */
592 0, /* accel flags */
593 39721L,48L,16L,33L,10L,
594 96L,2,0, /* no sync info */
595 FB_VMODE_NONINTERLACED,
596};
597
598static int matroxfb_dh_regit(const struct matrox_fb_info *minfo,
599 struct matroxfb_dh_fb_info *m2info)
600{
601#define minfo (m2info->primary_dev)
602 void* oldcrtc2;
603
604 m2info->fbcon.fbops = &matroxfb_dh_ops;
605 m2info->fbcon.flags = FBINFO_FLAG_DEFAULT;
606 m2info->fbcon.flags |= FBINFO_HWACCEL_XPAN |
607 FBINFO_HWACCEL_YPAN;
608 m2info->fbcon.pseudo_palette = m2info->cmap;
609 fb_alloc_cmap(&m2info->fbcon.cmap, 256, 1);
610
611 if (mem < 64)
612 mem *= 1024;
613 if (mem < 64*1024)
614 mem *= 1024;
615 mem &= ~0x00000FFF; /* PAGE_MASK? */
616 if (minfo->video.len_usable + mem <= minfo->video.len)
617 m2info->video.offbase = minfo->video.len - mem;
618 else if (minfo->video.len < mem) {
619 return -ENOMEM;
620 } else { /* check yres on first head... */
621 m2info->video.borrowed = mem;
622 minfo->video.len_usable -= mem;
623 m2info->video.offbase = minfo->video.len_usable;
624 }
625 m2info->video.base = minfo->video.base + m2info->video.offbase;
626 m2info->video.len = m2info->video.len_usable = m2info->video.len_maximum = mem;
627 m2info->video.vbase.vaddr = vaddr_va(minfo->video.vbase) + m2info->video.offbase;
628 m2info->mmio.base = minfo->mmio.base;
629 m2info->mmio.vbase = minfo->mmio.vbase;
630 m2info->mmio.len = minfo->mmio.len;
631
632 matroxfb_dh_init_fix(m2info);
633 if (register_framebuffer(&m2info->fbcon)) {
634 return -ENXIO;
635 }
636 if (!m2info->initialized)
637 fb_set_var(&m2info->fbcon, &matroxfb_dh_defined);
638 down_write(&minfo->crtc2.lock);
639 oldcrtc2 = minfo->crtc2.info;
640 minfo->crtc2.info = m2info;
641 up_write(&minfo->crtc2.lock);
642 if (oldcrtc2) {
643 printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 already present: %p\n",
644 oldcrtc2);
645 }
646 return 0;
647#undef minfo
648}
649
650/* ************************** */
651
652static int matroxfb_dh_registerfb(struct matroxfb_dh_fb_info* m2info) {
653#define minfo (m2info->primary_dev)
654 if (matroxfb_dh_regit(minfo, m2info)) {
655 printk(KERN_ERR "matroxfb_crtc2: secondary head failed to register\n");
656 return -1;
657 }
658 printk(KERN_INFO "matroxfb_crtc2: secondary head of fb%u was registered as fb%u\n",
659 minfo->fbcon.node, m2info->fbcon.node);
660 m2info->fbcon_registered = 1;
661 return 0;
662#undef minfo
663}
664
665static void matroxfb_dh_deregisterfb(struct matroxfb_dh_fb_info* m2info) {
666#define minfo (m2info->primary_dev)
667 if (m2info->fbcon_registered) {
668 int id;
669 struct matroxfb_dh_fb_info* crtc2;
670
671 down_write(&minfo->crtc2.lock);
672 crtc2 = minfo->crtc2.info;
673 if (crtc2 == m2info)
674 minfo->crtc2.info = NULL;
675 up_write(&minfo->crtc2.lock);
676 if (crtc2 != m2info) {
677 printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 mismatch at unload: %p != %p\n",
678 crtc2, m2info);
679 printk(KERN_ERR "matroxfb_crtc2: Expect kernel crash after module unload.\n");
680 return;
681 }
682 id = m2info->fbcon.node;
683 unregister_framebuffer(&m2info->fbcon);
684 /* return memory back to primary head */
685 minfo->video.len_usable += m2info->video.borrowed;
686 printk(KERN_INFO "matroxfb_crtc2: fb%u unregistered\n", id);
687 m2info->fbcon_registered = 0;
688 }
689#undef minfo
690}
691
692static void* matroxfb_crtc2_probe(struct matrox_fb_info* minfo) {
693 struct matroxfb_dh_fb_info* m2info;
694
695 /* hardware is CRTC2 incapable... */
696 if (!minfo->devflags.crtc2)
697 return NULL;
698 m2info = kzalloc(sizeof(*m2info), GFP_KERNEL);
699 if (!m2info) {
700 printk(KERN_ERR "matroxfb_crtc2: Not enough memory for CRTC2 control structs\n");
701 return NULL;
702 }
703 m2info->primary_dev = minfo;
704 if (matroxfb_dh_registerfb(m2info)) {
705 kfree(m2info);
706 printk(KERN_ERR "matroxfb_crtc2: CRTC2 framebuffer failed to register\n");
707 return NULL;
708 }
709 return m2info;
710}
711
712static void matroxfb_crtc2_remove(struct matrox_fb_info* minfo, void* crtc2) {
713 matroxfb_dh_deregisterfb(crtc2);
714 kfree(crtc2);
715}
716
717static struct matroxfb_driver crtc2 = {
718 .name = "Matrox G400 CRTC2",
719 .probe = matroxfb_crtc2_probe,
720 .remove = matroxfb_crtc2_remove };
721
722static int matroxfb_crtc2_init(void) {
723 if (fb_get_options("matrox_crtc2fb", NULL))
724 return -ENODEV;
725
726 matroxfb_register_driver(&crtc2);
727 return 0;
728}
729
730static void matroxfb_crtc2_exit(void) {
731 matroxfb_unregister_driver(&crtc2);
732}
733
734MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
735MODULE_DESCRIPTION("Matrox G400 CRTC2 driver");
736MODULE_LICENSE("GPL");
737module_init(matroxfb_crtc2_init);
738module_exit(matroxfb_crtc2_exit);
739/* we do not have __setup() yet */
diff --git a/drivers/video/fbdev/matrox/matroxfb_crtc2.h b/drivers/video/fbdev/matrox/matroxfb_crtc2.h
new file mode 100644
index 000000000000..1005582e843e
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_crtc2.h
@@ -0,0 +1,34 @@
1#ifndef __MATROXFB_CRTC2_H__
2#define __MATROXFB_CRTC2_H__
3
4#include <linux/ioctl.h>
5#include "matroxfb_base.h"
6
7struct matroxfb_dh_fb_info {
8 struct fb_info fbcon;
9 int fbcon_registered;
10 int initialized;
11
12 struct matrox_fb_info* primary_dev;
13
14 struct {
15 unsigned long base; /* physical */
16 vaddr_t vbase; /* virtual */
17 unsigned int len;
18 unsigned int len_usable;
19 unsigned int len_maximum;
20 unsigned int offbase;
21 unsigned int borrowed;
22 } video;
23 struct {
24 unsigned long base;
25 vaddr_t vbase;
26 unsigned int len;
27 } mmio;
28
29 unsigned int interlaced:1;
30
31 u_int32_t cmap[16];
32};
33
34#endif /* __MATROXFB_CRTC2_H__ */
diff --git a/drivers/video/fbdev/matrox/matroxfb_g450.c b/drivers/video/fbdev/matrox/matroxfb_g450.c
new file mode 100644
index 000000000000..cff0546ea6fd
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_g450.c
@@ -0,0 +1,640 @@
1/*
2 *
3 * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
4 *
5 * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
6 *
7 * Portions Copyright (c) 2001 Matrox Graphics Inc.
8 *
9 * Version: 1.65 2002/08/14
10 *
11 * See matroxfb_base.c for contributors.
12 *
13 */
14
15#include "matroxfb_base.h"
16#include "matroxfb_misc.h"
17#include "matroxfb_DAC1064.h"
18#include "g450_pll.h"
19#include <linux/matroxfb.h>
20#include <asm/div64.h>
21
22#include "matroxfb_g450.h"
23
24/* Definition of the various controls */
25struct mctl {
26 struct v4l2_queryctrl desc;
27 size_t control;
28};
29
30#define BLMIN 0xF3
31#define WLMAX 0x3FF
32
33static const struct mctl g450_controls[] =
34{ { { V4L2_CID_BRIGHTNESS, V4L2_CTRL_TYPE_INTEGER,
35 "brightness",
36 0, WLMAX-BLMIN, 1, 370-BLMIN,
37 0,
38 }, offsetof(struct matrox_fb_info, altout.tvo_params.brightness) },
39 { { V4L2_CID_CONTRAST, V4L2_CTRL_TYPE_INTEGER,
40 "contrast",
41 0, 1023, 1, 127,
42 0,
43 }, offsetof(struct matrox_fb_info, altout.tvo_params.contrast) },
44 { { V4L2_CID_SATURATION, V4L2_CTRL_TYPE_INTEGER,
45 "saturation",
46 0, 255, 1, 165,
47 0,
48 }, offsetof(struct matrox_fb_info, altout.tvo_params.saturation) },
49 { { V4L2_CID_HUE, V4L2_CTRL_TYPE_INTEGER,
50 "hue",
51 0, 255, 1, 0,
52 0,
53 }, offsetof(struct matrox_fb_info, altout.tvo_params.hue) },
54 { { MATROXFB_CID_TESTOUT, V4L2_CTRL_TYPE_BOOLEAN,
55 "test output",
56 0, 1, 1, 0,
57 0,
58 }, offsetof(struct matrox_fb_info, altout.tvo_params.testout) },
59};
60
61#define G450CTRLS ARRAY_SIZE(g450_controls)
62
63/* Return: positive number: id found
64 -EINVAL: id not found, return failure
65 -ENOENT: id not found, create fake disabled control */
66static int get_ctrl_id(__u32 v4l2_id) {
67 int i;
68
69 for (i = 0; i < G450CTRLS; i++) {
70 if (v4l2_id < g450_controls[i].desc.id) {
71 if (g450_controls[i].desc.id == 0x08000000) {
72 return -EINVAL;
73 }
74 return -ENOENT;
75 }
76 if (v4l2_id == g450_controls[i].desc.id) {
77 return i;
78 }
79 }
80 return -EINVAL;
81}
82
83static inline int *get_ctrl_ptr(struct matrox_fb_info *minfo, unsigned int idx)
84{
85 return (int*)((char*)minfo + g450_controls[idx].control);
86}
87
88static void tvo_fill_defaults(struct matrox_fb_info *minfo)
89{
90 unsigned int i;
91
92 for (i = 0; i < G450CTRLS; i++) {
93 *get_ctrl_ptr(minfo, i) = g450_controls[i].desc.default_value;
94 }
95}
96
97static int cve2_get_reg(struct matrox_fb_info *minfo, int reg)
98{
99 unsigned long flags;
100 int val;
101
102 matroxfb_DAC_lock_irqsave(flags);
103 matroxfb_DAC_out(minfo, 0x87, reg);
104 val = matroxfb_DAC_in(minfo, 0x88);
105 matroxfb_DAC_unlock_irqrestore(flags);
106 return val;
107}
108
109static void cve2_set_reg(struct matrox_fb_info *minfo, int reg, int val)
110{
111 unsigned long flags;
112
113 matroxfb_DAC_lock_irqsave(flags);
114 matroxfb_DAC_out(minfo, 0x87, reg);
115 matroxfb_DAC_out(minfo, 0x88, val);
116 matroxfb_DAC_unlock_irqrestore(flags);
117}
118
119static void cve2_set_reg10(struct matrox_fb_info *minfo, int reg, int val)
120{
121 unsigned long flags;
122
123 matroxfb_DAC_lock_irqsave(flags);
124 matroxfb_DAC_out(minfo, 0x87, reg);
125 matroxfb_DAC_out(minfo, 0x88, val >> 2);
126 matroxfb_DAC_out(minfo, 0x87, reg + 1);
127 matroxfb_DAC_out(minfo, 0x88, val & 3);
128 matroxfb_DAC_unlock_irqrestore(flags);
129}
130
131static void g450_compute_bwlevel(const struct matrox_fb_info *minfo, int *bl,
132 int *wl)
133{
134 const int b = minfo->altout.tvo_params.brightness + BLMIN;
135 const int c = minfo->altout.tvo_params.contrast;
136
137 *bl = max(b - c, BLMIN);
138 *wl = min(b + c, WLMAX);
139}
140
141static int g450_query_ctrl(void* md, struct v4l2_queryctrl *p) {
142 int i;
143
144 i = get_ctrl_id(p->id);
145 if (i >= 0) {
146 *p = g450_controls[i].desc;
147 return 0;
148 }
149 if (i == -ENOENT) {
150 static const struct v4l2_queryctrl disctrl =
151 { .flags = V4L2_CTRL_FLAG_DISABLED };
152
153 i = p->id;
154 *p = disctrl;
155 p->id = i;
156 sprintf(p->name, "Ctrl #%08X", i);
157 return 0;
158 }
159 return -EINVAL;
160}
161
162static int g450_set_ctrl(void* md, struct v4l2_control *p) {
163 int i;
164 struct matrox_fb_info *minfo = md;
165
166 i = get_ctrl_id(p->id);
167 if (i < 0) return -EINVAL;
168
169 /*
170 * Check if changed.
171 */
172 if (p->value == *get_ctrl_ptr(minfo, i)) return 0;
173
174 /*
175 * Check limits.
176 */
177 if (p->value > g450_controls[i].desc.maximum) return -EINVAL;
178 if (p->value < g450_controls[i].desc.minimum) return -EINVAL;
179
180 /*
181 * Store new value.
182 */
183 *get_ctrl_ptr(minfo, i) = p->value;
184
185 switch (p->id) {
186 case V4L2_CID_BRIGHTNESS:
187 case V4L2_CID_CONTRAST:
188 {
189 int blacklevel, whitelevel;
190 g450_compute_bwlevel(minfo, &blacklevel, &whitelevel);
191 cve2_set_reg10(minfo, 0x0e, blacklevel);
192 cve2_set_reg10(minfo, 0x1e, whitelevel);
193 }
194 break;
195 case V4L2_CID_SATURATION:
196 cve2_set_reg(minfo, 0x20, p->value);
197 cve2_set_reg(minfo, 0x22, p->value);
198 break;
199 case V4L2_CID_HUE:
200 cve2_set_reg(minfo, 0x25, p->value);
201 break;
202 case MATROXFB_CID_TESTOUT:
203 {
204 unsigned char val = cve2_get_reg(minfo, 0x05);
205 if (p->value) val |= 0x02;
206 else val &= ~0x02;
207 cve2_set_reg(minfo, 0x05, val);
208 }
209 break;
210 }
211
212
213 return 0;
214}
215
216static int g450_get_ctrl(void* md, struct v4l2_control *p) {
217 int i;
218 struct matrox_fb_info *minfo = md;
219
220 i = get_ctrl_id(p->id);
221 if (i < 0) return -EINVAL;
222 p->value = *get_ctrl_ptr(minfo, i);
223 return 0;
224}
225
226struct output_desc {
227 unsigned int h_vis;
228 unsigned int h_f_porch;
229 unsigned int h_sync;
230 unsigned int h_b_porch;
231 unsigned long long int chromasc;
232 unsigned int burst;
233 unsigned int v_total;
234};
235
236static void computeRegs(struct matrox_fb_info *minfo, struct mavenregs *r,
237 struct my_timming *mt, const struct output_desc *outd)
238{
239 u_int32_t chromasc;
240 u_int32_t hlen;
241 u_int32_t hsl;
242 u_int32_t hbp;
243 u_int32_t hfp;
244 u_int32_t hvis;
245 unsigned int pixclock;
246 unsigned long long piic;
247 int mnp;
248 int over;
249
250 r->regs[0x80] = 0x03; /* | 0x40 for SCART */
251
252 hvis = ((mt->HDisplay << 1) + 3) & ~3;
253
254 if (hvis >= 2048) {
255 hvis = 2044;
256 }
257
258 piic = 1000000000ULL * hvis;
259 do_div(piic, outd->h_vis);
260
261 dprintk(KERN_DEBUG "Want %u kHz pixclock\n", (unsigned int)piic);
262
263 mnp = matroxfb_g450_setclk(minfo, piic, M_VIDEO_PLL);
264
265 mt->mnp = mnp;
266 mt->pixclock = g450_mnp2f(minfo, mnp);
267
268 dprintk(KERN_DEBUG "MNP=%08X\n", mnp);
269
270 pixclock = 1000000000U / mt->pixclock;
271
272 dprintk(KERN_DEBUG "Got %u ps pixclock\n", pixclock);
273
274 piic = outd->chromasc;
275 do_div(piic, mt->pixclock);
276 chromasc = piic;
277
278 dprintk(KERN_DEBUG "Chroma is %08X\n", chromasc);
279
280 r->regs[0] = piic >> 24;
281 r->regs[1] = piic >> 16;
282 r->regs[2] = piic >> 8;
283 r->regs[3] = piic >> 0;
284 hbp = (((outd->h_b_porch + pixclock) / pixclock)) & ~1;
285 hfp = (((outd->h_f_porch + pixclock) / pixclock)) & ~1;
286 hsl = (((outd->h_sync + pixclock) / pixclock)) & ~1;
287 hlen = hvis + hfp + hsl + hbp;
288 over = hlen & 0x0F;
289
290 dprintk(KERN_DEBUG "WL: vis=%u, hf=%u, hs=%u, hb=%u, total=%u\n", hvis, hfp, hsl, hbp, hlen);
291
292 if (over) {
293 hfp -= over;
294 hlen -= over;
295 if (over <= 2) {
296 } else if (over < 10) {
297 hfp += 4;
298 hlen += 4;
299 } else {
300 hfp += 16;
301 hlen += 16;
302 }
303 }
304
305 /* maybe cve2 has requirement 800 < hlen < 1184 */
306 r->regs[0x08] = hsl;
307 r->regs[0x09] = (outd->burst + pixclock - 1) / pixclock; /* burst length */
308 r->regs[0x0A] = hbp;
309 r->regs[0x2C] = hfp;
310 r->regs[0x31] = hvis / 8;
311 r->regs[0x32] = hvis & 7;
312
313 dprintk(KERN_DEBUG "PG: vis=%04X, hf=%02X, hs=%02X, hb=%02X, total=%04X\n", hvis, hfp, hsl, hbp, hlen);
314
315 r->regs[0x84] = 1; /* x sync point */
316 r->regs[0x85] = 0;
317 hvis = hvis >> 1;
318 hlen = hlen >> 1;
319
320 dprintk(KERN_DEBUG "hlen=%u hvis=%u\n", hlen, hvis);
321
322 mt->interlaced = 1;
323
324 mt->HDisplay = hvis & ~7;
325 mt->HSyncStart = mt->HDisplay + 8;
326 mt->HSyncEnd = (hlen & ~7) - 8;
327 mt->HTotal = hlen;
328
329 {
330 int upper;
331 unsigned int vtotal;
332 unsigned int vsyncend;
333 unsigned int vdisplay;
334
335 vtotal = mt->VTotal;
336 vsyncend = mt->VSyncEnd;
337 vdisplay = mt->VDisplay;
338 if (vtotal < outd->v_total) {
339 unsigned int yovr = outd->v_total - vtotal;
340
341 vsyncend += yovr >> 1;
342 } else if (vtotal > outd->v_total) {
343 vdisplay = outd->v_total - 4;
344 vsyncend = outd->v_total;
345 }
346 upper = (outd->v_total - vsyncend) >> 1; /* in field lines */
347 r->regs[0x17] = outd->v_total / 4;
348 r->regs[0x18] = outd->v_total & 3;
349 r->regs[0x33] = upper - 1; /* upper blanking */
350 r->regs[0x82] = upper; /* y sync point */
351 r->regs[0x83] = upper >> 8;
352
353 mt->VDisplay = vdisplay;
354 mt->VSyncStart = outd->v_total - 2;
355 mt->VSyncEnd = outd->v_total;
356 mt->VTotal = outd->v_total;
357 }
358}
359
360static void cve2_init_TVdata(int norm, struct mavenregs* data, const struct output_desc** outd) {
361 static const struct output_desc paloutd = {
362 .h_vis = 52148148, // ps
363 .h_f_porch = 1407407, // ps
364 .h_sync = 4666667, // ps
365 .h_b_porch = 5777778, // ps
366 .chromasc = 19042247534182ULL, // 4433618.750 Hz
367 .burst = 2518518, // ps
368 .v_total = 625,
369 };
370 static const struct output_desc ntscoutd = {
371 .h_vis = 52888889, // ps
372 .h_f_porch = 1333333, // ps
373 .h_sync = 4666667, // ps
374 .h_b_porch = 4666667, // ps
375 .chromasc = 15374030659475ULL, // 3579545.454 Hz
376 .burst = 2418418, // ps
377 .v_total = 525, // lines
378 };
379
380 static const struct mavenregs palregs = { {
381 0x2A, 0x09, 0x8A, 0xCB, /* 00: chroma subcarrier */
382 0x00,
383 0x00, /* test */
384 0xF9, /* modified by code (F9 written...) */
385 0x00, /* ? not written */
386 0x7E, /* 08 */
387 0x44, /* 09 */
388 0x9C, /* 0A */
389 0x2E, /* 0B */
390 0x21, /* 0C */
391 0x00, /* ? not written */
392// 0x3F, 0x03, /* 0E-0F */
393 0x3C, 0x03,
394 0x3C, 0x03, /* 10-11 */
395 0x1A, /* 12 */
396 0x2A, /* 13 */
397 0x1C, 0x3D, 0x14, /* 14-16 */
398 0x9C, 0x01, /* 17-18 */
399 0x00, /* 19 */
400 0xFE, /* 1A */
401 0x7E, /* 1B */
402 0x60, /* 1C */
403 0x05, /* 1D */
404// 0x89, 0x03, /* 1E-1F */
405 0xAD, 0x03,
406// 0x72, /* 20 */
407 0xA5,
408 0x07, /* 21 */
409// 0x72, /* 22 */
410 0xA5,
411 0x00, /* 23 */
412 0x00, /* 24 */
413 0x00, /* 25 */
414 0x08, /* 26 */
415 0x04, /* 27 */
416 0x00, /* 28 */
417 0x1A, /* 29 */
418 0x55, 0x01, /* 2A-2B */
419 0x26, /* 2C */
420 0x07, 0x7E, /* 2D-2E */
421 0x02, 0x54, /* 2F-30 */
422 0xB0, 0x00, /* 31-32 */
423 0x14, /* 33 */
424 0x49, /* 34 */
425 0x00, /* 35 written multiple times */
426 0x00, /* 36 not written */
427 0xA3, /* 37 */
428 0xC8, /* 38 */
429 0x22, /* 39 */
430 0x02, /* 3A */
431 0x22, /* 3B */
432 0x3F, 0x03, /* 3C-3D */
433 0x00, /* 3E written multiple times */
434 0x00, /* 3F not written */
435 } };
436 static struct mavenregs ntscregs = { {
437 0x21, 0xF0, 0x7C, 0x1F, /* 00: chroma subcarrier */
438 0x00,
439 0x00, /* test */
440 0xF9, /* modified by code (F9 written...) */
441 0x00, /* ? not written */
442 0x7E, /* 08 */
443 0x43, /* 09 */
444 0x7E, /* 0A */
445 0x3D, /* 0B */
446 0x00, /* 0C */
447 0x00, /* ? not written */
448 0x41, 0x00, /* 0E-0F */
449 0x3C, 0x00, /* 10-11 */
450 0x17, /* 12 */
451 0x21, /* 13 */
452 0x1B, 0x1B, 0x24, /* 14-16 */
453 0x83, 0x01, /* 17-18 */
454 0x00, /* 19 */
455 0x0F, /* 1A */
456 0x0F, /* 1B */
457 0x60, /* 1C */
458 0x05, /* 1D */
459 //0x89, 0x02, /* 1E-1F */
460 0xC0, 0x02, /* 1E-1F */
461 //0x5F, /* 20 */
462 0x9C, /* 20 */
463 0x04, /* 21 */
464 //0x5F, /* 22 */
465 0x9C, /* 22 */
466 0x01, /* 23 */
467 0x02, /* 24 */
468 0x00, /* 25 */
469 0x0A, /* 26 */
470 0x05, /* 27 */
471 0x00, /* 28 */
472 0x10, /* 29 */
473 0xFF, 0x03, /* 2A-2B */
474 0x24, /* 2C */
475 0x0F, 0x78, /* 2D-2E */
476 0x00, 0x00, /* 2F-30 */
477 0xB2, 0x04, /* 31-32 */
478 0x14, /* 33 */
479 0x02, /* 34 */
480 0x00, /* 35 written multiple times */
481 0x00, /* 36 not written */
482 0xA3, /* 37 */
483 0xC8, /* 38 */
484 0x15, /* 39 */
485 0x05, /* 3A */
486 0x3B, /* 3B */
487 0x3C, 0x00, /* 3C-3D */
488 0x00, /* 3E written multiple times */
489 0x00, /* never written */
490 } };
491
492 if (norm == MATROXFB_OUTPUT_MODE_PAL) {
493 *data = palregs;
494 *outd = &paloutd;
495 } else {
496 *data = ntscregs;
497 *outd = &ntscoutd;
498 }
499 return;
500}
501
502#define LR(x) cve2_set_reg(minfo, (x), m->regs[(x)])
503static void cve2_init_TV(struct matrox_fb_info *minfo,
504 const struct mavenregs *m)
505{
506 int i;
507
508 LR(0x80);
509 LR(0x82); LR(0x83);
510 LR(0x84); LR(0x85);
511
512 cve2_set_reg(minfo, 0x3E, 0x01);
513
514 for (i = 0; i < 0x3E; i++) {
515 LR(i);
516 }
517 cve2_set_reg(minfo, 0x3E, 0x00);
518}
519
520static int matroxfb_g450_compute(void* md, struct my_timming* mt) {
521 struct matrox_fb_info *minfo = md;
522
523 dprintk(KERN_DEBUG "Computing, mode=%u\n", minfo->outputs[1].mode);
524
525 if (mt->crtc == MATROXFB_SRC_CRTC2 &&
526 minfo->outputs[1].mode != MATROXFB_OUTPUT_MODE_MONITOR) {
527 const struct output_desc* outd;
528
529 cve2_init_TVdata(minfo->outputs[1].mode, &minfo->hw.maven, &outd);
530 {
531 int blacklevel, whitelevel;
532 g450_compute_bwlevel(minfo, &blacklevel, &whitelevel);
533 minfo->hw.maven.regs[0x0E] = blacklevel >> 2;
534 minfo->hw.maven.regs[0x0F] = blacklevel & 3;
535 minfo->hw.maven.regs[0x1E] = whitelevel >> 2;
536 minfo->hw.maven.regs[0x1F] = whitelevel & 3;
537
538 minfo->hw.maven.regs[0x20] =
539 minfo->hw.maven.regs[0x22] = minfo->altout.tvo_params.saturation;
540
541 minfo->hw.maven.regs[0x25] = minfo->altout.tvo_params.hue;
542
543 if (minfo->altout.tvo_params.testout) {
544 minfo->hw.maven.regs[0x05] |= 0x02;
545 }
546 }
547 computeRegs(minfo, &minfo->hw.maven, mt, outd);
548 } else if (mt->mnp < 0) {
549 /* We must program clocks before CRTC2, otherwise interlaced mode
550 startup may fail */
551 mt->mnp = matroxfb_g450_setclk(minfo, mt->pixclock, (mt->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL);
552 mt->pixclock = g450_mnp2f(minfo, mt->mnp);
553 }
554 dprintk(KERN_DEBUG "Pixclock = %u\n", mt->pixclock);
555 return 0;
556}
557
558static int matroxfb_g450_program(void* md) {
559 struct matrox_fb_info *minfo = md;
560
561 if (minfo->outputs[1].mode != MATROXFB_OUTPUT_MODE_MONITOR) {
562 cve2_init_TV(minfo, &minfo->hw.maven);
563 }
564 return 0;
565}
566
567static int matroxfb_g450_verify_mode(void* md, u_int32_t arg) {
568 switch (arg) {
569 case MATROXFB_OUTPUT_MODE_PAL:
570 case MATROXFB_OUTPUT_MODE_NTSC:
571 case MATROXFB_OUTPUT_MODE_MONITOR:
572 return 0;
573 }
574 return -EINVAL;
575}
576
577static int g450_dvi_compute(void* md, struct my_timming* mt) {
578 struct matrox_fb_info *minfo = md;
579
580 if (mt->mnp < 0) {
581 mt->mnp = matroxfb_g450_setclk(minfo, mt->pixclock, (mt->crtc == MATROXFB_SRC_CRTC1) ? M_PIXEL_PLL_C : M_VIDEO_PLL);
582 mt->pixclock = g450_mnp2f(minfo, mt->mnp);
583 }
584 return 0;
585}
586
587static struct matrox_altout matroxfb_g450_altout = {
588 .name = "Secondary output",
589 .compute = matroxfb_g450_compute,
590 .program = matroxfb_g450_program,
591 .verifymode = matroxfb_g450_verify_mode,
592 .getqueryctrl = g450_query_ctrl,
593 .getctrl = g450_get_ctrl,
594 .setctrl = g450_set_ctrl,
595};
596
597static struct matrox_altout matroxfb_g450_dvi = {
598 .name = "DVI output",
599 .compute = g450_dvi_compute,
600};
601
602void matroxfb_g450_connect(struct matrox_fb_info *minfo)
603{
604 if (minfo->devflags.g450dac) {
605 down_write(&minfo->altout.lock);
606 tvo_fill_defaults(minfo);
607 minfo->outputs[1].src = minfo->outputs[1].default_src;
608 minfo->outputs[1].data = minfo;
609 minfo->outputs[1].output = &matroxfb_g450_altout;
610 minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR;
611 minfo->outputs[2].src = minfo->outputs[2].default_src;
612 minfo->outputs[2].data = minfo;
613 minfo->outputs[2].output = &matroxfb_g450_dvi;
614 minfo->outputs[2].mode = MATROXFB_OUTPUT_MODE_MONITOR;
615 up_write(&minfo->altout.lock);
616 }
617}
618
619void matroxfb_g450_shutdown(struct matrox_fb_info *minfo)
620{
621 if (minfo->devflags.g450dac) {
622 down_write(&minfo->altout.lock);
623 minfo->outputs[1].src = MATROXFB_SRC_NONE;
624 minfo->outputs[1].output = NULL;
625 minfo->outputs[1].data = NULL;
626 minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR;
627 minfo->outputs[2].src = MATROXFB_SRC_NONE;
628 minfo->outputs[2].output = NULL;
629 minfo->outputs[2].data = NULL;
630 minfo->outputs[2].mode = MATROXFB_OUTPUT_MODE_MONITOR;
631 up_write(&minfo->altout.lock);
632 }
633}
634
635EXPORT_SYMBOL(matroxfb_g450_connect);
636EXPORT_SYMBOL(matroxfb_g450_shutdown);
637
638MODULE_AUTHOR("(c) 2000-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
639MODULE_DESCRIPTION("Matrox G450/G550 output driver");
640MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/matrox/matroxfb_g450.h b/drivers/video/fbdev/matrox/matroxfb_g450.h
new file mode 100644
index 000000000000..3a3e654444b8
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_g450.h
@@ -0,0 +1,14 @@
1#ifndef __MATROXFB_G450_H__
2#define __MATROXFB_G450_H__
3
4#include "matroxfb_base.h"
5
6#ifdef CONFIG_FB_MATROX_G
7void matroxfb_g450_connect(struct matrox_fb_info *minfo);
8void matroxfb_g450_shutdown(struct matrox_fb_info *minfo);
9#else
10static inline void matroxfb_g450_connect(struct matrox_fb_info *minfo) { };
11static inline void matroxfb_g450_shutdown(struct matrox_fb_info *minfo) { };
12#endif
13
14#endif /* __MATROXFB_G450_H__ */
diff --git a/drivers/video/fbdev/matrox/matroxfb_maven.c b/drivers/video/fbdev/matrox/matroxfb_maven.c
new file mode 100644
index 000000000000..ee41a0f276b2
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_maven.c
@@ -0,0 +1,1301 @@
1/*
2 *
3 * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
4 *
5 * (c) 1998-2002 Petr Vandrovec <vandrove@vc.cvut.cz>
6 *
7 * Portions Copyright (c) 2001 Matrox Graphics Inc.
8 *
9 * Version: 1.65 2002/08/14
10 *
11 * See matroxfb_base.c for contributors.
12 *
13 */
14
15#include "matroxfb_maven.h"
16#include "matroxfb_misc.h"
17#include "matroxfb_DAC1064.h"
18#include <linux/i2c.h>
19#include <linux/matroxfb.h>
20#include <linux/slab.h>
21#include <asm/div64.h>
22
23#define MGATVO_B 1
24#define MGATVO_C 2
25
26static const struct maven_gamma {
27 unsigned char reg83;
28 unsigned char reg84;
29 unsigned char reg85;
30 unsigned char reg86;
31 unsigned char reg87;
32 unsigned char reg88;
33 unsigned char reg89;
34 unsigned char reg8a;
35 unsigned char reg8b;
36} maven_gamma[] = {
37 { 131, 57, 223, 15, 117, 212, 251, 91, 156},
38 { 133, 61, 128, 63, 180, 147, 195, 100, 180},
39 { 131, 19, 63, 31, 50, 66, 171, 64, 176},
40 { 0, 0, 0, 31, 16, 16, 16, 100, 200},
41 { 8, 23, 47, 73, 147, 244, 220, 80, 195},
42 { 22, 43, 64, 80, 147, 115, 58, 85, 168},
43 { 34, 60, 80, 214, 147, 212, 188, 85, 167},
44 { 45, 77, 96, 216, 147, 99, 91, 85, 159},
45 { 56, 76, 112, 107, 147, 212, 148, 64, 144},
46 { 65, 91, 128, 137, 147, 196, 17, 69, 148},
47 { 72, 104, 136, 138, 147, 180, 245, 73, 147},
48 { 87, 116, 143, 126, 16, 83, 229, 77, 144},
49 { 95, 119, 152, 254, 244, 83, 221, 77, 151},
50 { 100, 129, 159, 156, 244, 148, 197, 77, 160},
51 { 105, 141, 167, 247, 244, 132, 181, 84, 166},
52 { 105, 147, 168, 247, 244, 245, 181, 90, 170},
53 { 120, 153, 175, 248, 212, 229, 165, 90, 180},
54 { 119, 156, 176, 248, 244, 229, 84, 74, 160},
55 { 119, 158, 183, 248, 244, 229, 149, 78, 165}
56};
57
58/* Definition of the various controls */
59struct mctl {
60 struct v4l2_queryctrl desc;
61 size_t control;
62};
63
64#define BLMIN 0x0FF
65#define WLMAX 0x3FF
66
67static const struct mctl maven_controls[] =
68{ { { V4L2_CID_BRIGHTNESS, V4L2_CTRL_TYPE_INTEGER,
69 "brightness",
70 0, WLMAX - BLMIN, 1, 379 - BLMIN,
71 0,
72 }, offsetof(struct matrox_fb_info, altout.tvo_params.brightness) },
73 { { V4L2_CID_CONTRAST, V4L2_CTRL_TYPE_INTEGER,
74 "contrast",
75 0, 1023, 1, 127,
76 0,
77 }, offsetof(struct matrox_fb_info, altout.tvo_params.contrast) },
78 { { V4L2_CID_SATURATION, V4L2_CTRL_TYPE_INTEGER,
79 "saturation",
80 0, 255, 1, 155,
81 0,
82 }, offsetof(struct matrox_fb_info, altout.tvo_params.saturation) },
83 { { V4L2_CID_HUE, V4L2_CTRL_TYPE_INTEGER,
84 "hue",
85 0, 255, 1, 0,
86 0,
87 }, offsetof(struct matrox_fb_info, altout.tvo_params.hue) },
88 { { V4L2_CID_GAMMA, V4L2_CTRL_TYPE_INTEGER,
89 "gamma",
90 0, ARRAY_SIZE(maven_gamma) - 1, 1, 3,
91 0,
92 }, offsetof(struct matrox_fb_info, altout.tvo_params.gamma) },
93 { { MATROXFB_CID_TESTOUT, V4L2_CTRL_TYPE_BOOLEAN,
94 "test output",
95 0, 1, 1, 0,
96 0,
97 }, offsetof(struct matrox_fb_info, altout.tvo_params.testout) },
98 { { MATROXFB_CID_DEFLICKER, V4L2_CTRL_TYPE_INTEGER,
99 "deflicker mode",
100 0, 2, 1, 0,
101 0,
102 }, offsetof(struct matrox_fb_info, altout.tvo_params.deflicker) },
103
104};
105
106#define MAVCTRLS ARRAY_SIZE(maven_controls)
107
108/* Return: positive number: id found
109 -EINVAL: id not found, return failure
110 -ENOENT: id not found, create fake disabled control */
111static int get_ctrl_id(__u32 v4l2_id) {
112 int i;
113
114 for (i = 0; i < MAVCTRLS; i++) {
115 if (v4l2_id < maven_controls[i].desc.id) {
116 if (maven_controls[i].desc.id == 0x08000000) {
117 return -EINVAL;
118 }
119 return -ENOENT;
120 }
121 if (v4l2_id == maven_controls[i].desc.id) {
122 return i;
123 }
124 }
125 return -EINVAL;
126}
127
128struct maven_data {
129 struct matrox_fb_info* primary_head;
130 struct i2c_client *client;
131 int version;
132};
133
134static int* get_ctrl_ptr(struct maven_data* md, int idx) {
135 return (int*)((char*)(md->primary_head) + maven_controls[idx].control);
136}
137
138static int maven_get_reg(struct i2c_client* c, char reg) {
139 char dst;
140 struct i2c_msg msgs[] = {
141 {
142 .addr = c->addr,
143 .flags = I2C_M_REV_DIR_ADDR,
144 .len = sizeof(reg),
145 .buf = &reg
146 },
147 {
148 .addr = c->addr,
149 .flags = I2C_M_RD | I2C_M_NOSTART,
150 .len = sizeof(dst),
151 .buf = &dst
152 }
153 };
154 s32 err;
155
156 err = i2c_transfer(c->adapter, msgs, 2);
157 if (err < 0)
158 printk(KERN_INFO "ReadReg(%d) failed\n", reg);
159 return dst & 0xFF;
160}
161
162static int maven_set_reg(struct i2c_client* c, int reg, int val) {
163 s32 err;
164
165 err = i2c_smbus_write_byte_data(c, reg, val);
166 if (err)
167 printk(KERN_INFO "WriteReg(%d) failed\n", reg);
168 return err;
169}
170
171static int maven_set_reg_pair(struct i2c_client* c, int reg, int val) {
172 s32 err;
173
174 err = i2c_smbus_write_word_data(c, reg, val);
175 if (err)
176 printk(KERN_INFO "WriteRegPair(%d) failed\n", reg);
177 return err;
178}
179
180static const struct matrox_pll_features maven_pll = {
181 50000,
182 27000,
183 4, 127,
184 2, 31,
185 3
186};
187
188struct matrox_pll_features2 {
189 unsigned int vco_freq_min;
190 unsigned int vco_freq_max;
191 unsigned int feed_div_min;
192 unsigned int feed_div_max;
193 unsigned int in_div_min;
194 unsigned int in_div_max;
195 unsigned int post_shift_max;
196};
197
198struct matrox_pll_ctl {
199 unsigned int ref_freq;
200 unsigned int den;
201};
202
203static const struct matrox_pll_features2 maven1000_pll = {
204 50000000,
205 300000000,
206 5, 128,
207 3, 32,
208 3
209};
210
211static const struct matrox_pll_ctl maven_PAL = {
212 540000,
213 50
214};
215
216static const struct matrox_pll_ctl maven_NTSC = {
217 450450, /* 27027000/60 == 27000000/59.94005994 */
218 60
219};
220
221static int matroxfb_PLL_mavenclock(const struct matrox_pll_features2* pll,
222 const struct matrox_pll_ctl* ctl,
223 unsigned int htotal, unsigned int vtotal,
224 unsigned int* in, unsigned int* feed, unsigned int* post,
225 unsigned int* h2) {
226 unsigned int besth2 = 0;
227 unsigned int fxtal = ctl->ref_freq;
228 unsigned int fmin = pll->vco_freq_min / ctl->den;
229 unsigned int fwant;
230 unsigned int p;
231 unsigned int scrlen;
232 unsigned int fmax;
233
234 DBG(__func__)
235
236 scrlen = htotal * (vtotal - 1);
237 fwant = htotal * vtotal;
238 fmax = pll->vco_freq_max / ctl->den;
239
240 dprintk(KERN_DEBUG "want: %u, xtal: %u, h: %u, v: %u, fmax: %u\n",
241 fwant, fxtal, htotal, vtotal, fmax);
242 for (p = 1; p <= pll->post_shift_max; p++) {
243 if (fwant * 2 > fmax)
244 break;
245 fwant *= 2;
246 }
247 if (fwant > fmax)
248 return 0;
249 for (; p-- > 0; fwant >>= 1) {
250 unsigned int m;
251
252 if (fwant < fmin) break;
253 for (m = pll->in_div_min; m <= pll->in_div_max; m++) {
254 unsigned int n;
255 unsigned int dvd;
256 unsigned int ln;
257
258 n = (fwant * m) / fxtal;
259 if (n < pll->feed_div_min)
260 continue;
261 if (n > pll->feed_div_max)
262 break;
263
264 ln = fxtal * n;
265 dvd = m << p;
266
267 if (ln % dvd)
268 continue;
269 ln = ln / dvd;
270
271 if (ln < scrlen + 2)
272 continue;
273 ln = ln - scrlen;
274 if (ln > htotal)
275 continue;
276 dprintk(KERN_DEBUG "Match: %u / %u / %u / %u\n", n, m, p, ln);
277 if (ln > besth2) {
278 dprintk(KERN_DEBUG "Better...\n");
279 *h2 = besth2 = ln;
280 *post = p;
281 *in = m;
282 *feed = n;
283 }
284 }
285 }
286
287 /* if h2/post/in/feed have not been assigned, return zero (error) */
288 if (besth2 < 2)
289 return 0;
290
291 dprintk(KERN_ERR "clk: %02X %02X %02X %d %d\n", *in, *feed, *post, fxtal, fwant);
292 return fxtal * (*feed) / (*in) * ctl->den;
293}
294
295static int matroxfb_mavenclock(const struct matrox_pll_ctl *ctl,
296 unsigned int htotal, unsigned int vtotal,
297 unsigned int* in, unsigned int* feed, unsigned int* post,
298 unsigned int* htotal2) {
299 unsigned int fvco;
300 unsigned int uninitialized_var(p);
301
302 fvco = matroxfb_PLL_mavenclock(&maven1000_pll, ctl, htotal, vtotal, in, feed, &p, htotal2);
303 if (!fvco)
304 return -EINVAL;
305 p = (1 << p) - 1;
306 if (fvco <= 100000000)
307 ;
308 else if (fvco <= 140000000)
309 p |= 0x08;
310 else if (fvco <= 180000000)
311 p |= 0x10;
312 else
313 p |= 0x18;
314 *post = p;
315 return 0;
316}
317
318static void DAC1064_calcclock(unsigned int freq, unsigned int fmax,
319 unsigned int* in, unsigned int* feed, unsigned int* post) {
320 unsigned int fvco;
321 unsigned int p;
322
323 fvco = matroxfb_PLL_calcclock(&maven_pll, freq, fmax, in, feed, &p);
324 p = (1 << p) - 1;
325 if (fvco <= 100000)
326 ;
327 else if (fvco <= 140000)
328 p |= 0x08;
329 else if (fvco <= 180000)
330 p |= 0x10;
331 else
332 p |= 0x18;
333 *post = p;
334 return;
335}
336
337static unsigned char maven_compute_deflicker (const struct maven_data* md) {
338 unsigned char df;
339
340 df = (md->version == MGATVO_B?0x40:0x00);
341 switch (md->primary_head->altout.tvo_params.deflicker) {
342 case 0:
343/* df |= 0x00; */
344 break;
345 case 1:
346 df |= 0xB1;
347 break;
348 case 2:
349 df |= 0xA2;
350 break;
351 }
352 return df;
353}
354
355static void maven_compute_bwlevel (const struct maven_data* md,
356 int *bl, int *wl) {
357 const int b = md->primary_head->altout.tvo_params.brightness + BLMIN;
358 const int c = md->primary_head->altout.tvo_params.contrast;
359
360 *bl = max(b - c, BLMIN);
361 *wl = min(b + c, WLMAX);
362}
363
364static const struct maven_gamma* maven_compute_gamma (const struct maven_data* md) {
365 return maven_gamma + md->primary_head->altout.tvo_params.gamma;
366}
367
368
369static void maven_init_TVdata(const struct maven_data* md, struct mavenregs* data) {
370 static struct mavenregs palregs = { {
371 0x2A, 0x09, 0x8A, 0xCB, /* 00: chroma subcarrier */
372 0x00,
373 0x00, /* ? not written */
374 0x00, /* modified by code (F9 written...) */
375 0x00, /* ? not written */
376 0x7E, /* 08 */
377 0x44, /* 09 */
378 0x9C, /* 0A */
379 0x2E, /* 0B */
380 0x21, /* 0C */
381 0x00, /* ? not written */
382 0x3F, 0x03, /* 0E-0F */
383 0x3F, 0x03, /* 10-11 */
384 0x1A, /* 12 */
385 0x2A, /* 13 */
386 0x1C, 0x3D, 0x14, /* 14-16 */
387 0x9C, 0x01, /* 17-18 */
388 0x00, /* 19 */
389 0xFE, /* 1A */
390 0x7E, /* 1B */
391 0x60, /* 1C */
392 0x05, /* 1D */
393 0x89, 0x03, /* 1E-1F */
394 0x72, /* 20 */
395 0x07, /* 21 */
396 0x72, /* 22 */
397 0x00, /* 23 */
398 0x00, /* 24 */
399 0x00, /* 25 */
400 0x08, /* 26 */
401 0x04, /* 27 */
402 0x00, /* 28 */
403 0x1A, /* 29 */
404 0x55, 0x01, /* 2A-2B */
405 0x26, /* 2C */
406 0x07, 0x7E, /* 2D-2E */
407 0x02, 0x54, /* 2F-30 */
408 0xB0, 0x00, /* 31-32 */
409 0x14, /* 33 */
410 0x49, /* 34 */
411 0x00, /* 35 written multiple times */
412 0x00, /* 36 not written */
413 0xA3, /* 37 */
414 0xC8, /* 38 */
415 0x22, /* 39 */
416 0x02, /* 3A */
417 0x22, /* 3B */
418 0x3F, 0x03, /* 3C-3D */
419 0x00, /* 3E written multiple times */
420 0x00, /* 3F not written */
421 }, MATROXFB_OUTPUT_MODE_PAL, 625, 50 };
422 static struct mavenregs ntscregs = { {
423 0x21, 0xF0, 0x7C, 0x1F, /* 00: chroma subcarrier */
424 0x00,
425 0x00, /* ? not written */
426 0x00, /* modified by code (F9 written...) */
427 0x00, /* ? not written */
428 0x7E, /* 08 */
429 0x43, /* 09 */
430 0x7E, /* 0A */
431 0x3D, /* 0B */
432 0x00, /* 0C */
433 0x00, /* ? not written */
434 0x41, 0x00, /* 0E-0F */
435 0x3C, 0x00, /* 10-11 */
436 0x17, /* 12 */
437 0x21, /* 13 */
438 0x1B, 0x1B, 0x24, /* 14-16 */
439 0x83, 0x01, /* 17-18 */
440 0x00, /* 19 */
441 0x0F, /* 1A */
442 0x0F, /* 1B */
443 0x60, /* 1C */
444 0x05, /* 1D */
445 0x89, 0x02, /* 1E-1F */
446 0x5F, /* 20 */
447 0x04, /* 21 */
448 0x5F, /* 22 */
449 0x01, /* 23 */
450 0x02, /* 24 */
451 0x00, /* 25 */
452 0x0A, /* 26 */
453 0x05, /* 27 */
454 0x00, /* 28 */
455 0x10, /* 29 */
456 0xFF, 0x03, /* 2A-2B */
457 0x24, /* 2C */
458 0x0F, 0x78, /* 2D-2E */
459 0x00, 0x00, /* 2F-30 */
460 0xB2, 0x04, /* 31-32 */
461 0x14, /* 33 */
462 0x02, /* 34 */
463 0x00, /* 35 written multiple times */
464 0x00, /* 36 not written */
465 0xA3, /* 37 */
466 0xC8, /* 38 */
467 0x15, /* 39 */
468 0x05, /* 3A */
469 0x3B, /* 3B */
470 0x3C, 0x00, /* 3C-3D */
471 0x00, /* 3E written multiple times */
472 0x00, /* never written */
473 }, MATROXFB_OUTPUT_MODE_NTSC, 525, 60 };
474 struct matrox_fb_info *minfo = md->primary_head;
475
476 if (minfo->outputs[1].mode == MATROXFB_OUTPUT_MODE_PAL)
477 *data = palregs;
478 else
479 *data = ntscregs;
480
481 /* Set deflicker */
482 data->regs[0x93] = maven_compute_deflicker(md);
483
484 /* set gamma */
485 {
486 const struct maven_gamma* g;
487 g = maven_compute_gamma(md);
488 data->regs[0x83] = g->reg83;
489 data->regs[0x84] = g->reg84;
490 data->regs[0x85] = g->reg85;
491 data->regs[0x86] = g->reg86;
492 data->regs[0x87] = g->reg87;
493 data->regs[0x88] = g->reg88;
494 data->regs[0x89] = g->reg89;
495 data->regs[0x8A] = g->reg8a;
496 data->regs[0x8B] = g->reg8b;
497 }
498
499 /* Set contrast / brightness */
500 {
501 int bl, wl;
502 maven_compute_bwlevel (md, &bl, &wl);
503 data->regs[0x0e] = bl >> 2;
504 data->regs[0x0f] = bl & 3;
505 data->regs[0x1e] = wl >> 2;
506 data->regs[0x1f] = wl & 3;
507 }
508
509 /* Set saturation */
510 {
511 data->regs[0x20] =
512 data->regs[0x22] = minfo->altout.tvo_params.saturation;
513 }
514
515 /* Set HUE */
516 data->regs[0x25] = minfo->altout.tvo_params.hue;
517 return;
518}
519
520#define LR(x) maven_set_reg(c, (x), m->regs[(x)])
521#define LRP(x) maven_set_reg_pair(c, (x), m->regs[(x)] | (m->regs[(x)+1] << 8))
522static void maven_init_TV(struct i2c_client* c, const struct mavenregs* m) {
523 int val;
524
525
526 maven_set_reg(c, 0x3E, 0x01);
527 maven_get_reg(c, 0x82); /* fetch oscillator state? */
528 maven_set_reg(c, 0x8C, 0x00);
529 maven_get_reg(c, 0x94); /* get 0x82 */
530 maven_set_reg(c, 0x94, 0xA2);
531 /* xmiscctrl */
532
533 maven_set_reg_pair(c, 0x8E, 0x1EFF);
534 maven_set_reg(c, 0xC6, 0x01);
535
536 /* removed code... */
537
538 maven_get_reg(c, 0x06);
539 maven_set_reg(c, 0x06, 0xF9); /* or read |= 0xF0 ? */
540
541 /* removed code here... */
542
543 /* real code begins here? */
544 /* chroma subcarrier */
545 LR(0x00); LR(0x01); LR(0x02); LR(0x03);
546
547 LR(0x04);
548
549 LR(0x2C);
550 LR(0x08);
551 LR(0x0A);
552 LR(0x09);
553 LR(0x29);
554 LRP(0x31);
555 LRP(0x17);
556 LR(0x0B);
557 LR(0x0C);
558 if (m->mode == MATROXFB_OUTPUT_MODE_PAL) {
559 maven_set_reg(c, 0x35, 0x10); /* ... */
560 } else {
561 maven_set_reg(c, 0x35, 0x0F); /* ... */
562 }
563
564 LRP(0x10);
565
566 LRP(0x0E);
567 LRP(0x1E);
568
569 LR(0x20); /* saturation #1 */
570 LR(0x22); /* saturation #2 */
571 LR(0x25); /* hue */
572 LR(0x34);
573 LR(0x33);
574 LR(0x19);
575 LR(0x12);
576 LR(0x3B);
577 LR(0x13);
578 LR(0x39);
579 LR(0x1D);
580 LR(0x3A);
581 LR(0x24);
582 LR(0x14);
583 LR(0x15);
584 LR(0x16);
585 LRP(0x2D);
586 LRP(0x2F);
587 LR(0x1A);
588 LR(0x1B);
589 LR(0x1C);
590 LR(0x23);
591 LR(0x26);
592 LR(0x28);
593 LR(0x27);
594 LR(0x21);
595 LRP(0x2A);
596 if (m->mode == MATROXFB_OUTPUT_MODE_PAL)
597 maven_set_reg(c, 0x35, 0x1D); /* ... */
598 else
599 maven_set_reg(c, 0x35, 0x1C);
600
601 LRP(0x3C);
602 LR(0x37);
603 LR(0x38);
604 maven_set_reg(c, 0xB3, 0x01);
605
606 maven_get_reg(c, 0xB0); /* read 0x80 */
607 maven_set_reg(c, 0xB0, 0x08); /* ugh... */
608 maven_get_reg(c, 0xB9); /* read 0x7C */
609 maven_set_reg(c, 0xB9, 0x78);
610 maven_get_reg(c, 0xBF); /* read 0x00 */
611 maven_set_reg(c, 0xBF, 0x02);
612 maven_get_reg(c, 0x94); /* read 0x82 */
613 maven_set_reg(c, 0x94, 0xB3);
614
615 LR(0x80); /* 04 1A 91 or 05 21 91 */
616 LR(0x81);
617 LR(0x82);
618
619 maven_set_reg(c, 0x8C, 0x20);
620 maven_get_reg(c, 0x8D);
621 maven_set_reg(c, 0x8D, 0x10);
622
623 LR(0x90); /* 4D 50 52 or 4E 05 45 */
624 LR(0x91);
625 LR(0x92);
626
627 LRP(0x9A); /* 0049 or 004F */
628 LRP(0x9C); /* 0004 or 0004 */
629 LRP(0x9E); /* 0458 or 045E */
630 LRP(0xA0); /* 05DA or 051B */
631 LRP(0xA2); /* 00CC or 00CF */
632 LRP(0xA4); /* 007D or 007F */
633 LRP(0xA6); /* 007C or 007E */
634 LRP(0xA8); /* 03CB or 03CE */
635 LRP(0x98); /* 0000 or 0000 */
636 LRP(0xAE); /* 0044 or 003A */
637 LRP(0x96); /* 05DA or 051B */
638 LRP(0xAA); /* 04BC or 046A */
639 LRP(0xAC); /* 004D or 004E */
640
641 LR(0xBE);
642 LR(0xC2);
643
644 maven_get_reg(c, 0x8D);
645 maven_set_reg(c, 0x8D, 0x04);
646
647 LR(0x20); /* saturation #1 */
648 LR(0x22); /* saturation #2 */
649 LR(0x93); /* whoops */
650 LR(0x20); /* oh, saturation #1 again */
651 LR(0x22); /* oh, saturation #2 again */
652 LR(0x25); /* hue */
653 LRP(0x0E);
654 LRP(0x1E);
655 LRP(0x0E); /* problems with memory? */
656 LRP(0x1E); /* yes, matrox must have problems in memory area... */
657
658 /* load gamma correction stuff */
659 LR(0x83);
660 LR(0x84);
661 LR(0x85);
662 LR(0x86);
663 LR(0x87);
664 LR(0x88);
665 LR(0x89);
666 LR(0x8A);
667 LR(0x8B);
668
669 val = maven_get_reg(c, 0x8D);
670 val &= 0x14; /* 0x10 or anything ored with it */
671 maven_set_reg(c, 0x8D, val);
672
673 LR(0x33);
674 LR(0x19);
675 LR(0x12);
676 LR(0x3B);
677 LR(0x13);
678 LR(0x39);
679 LR(0x1D);
680 LR(0x3A);
681 LR(0x24);
682 LR(0x14);
683 LR(0x15);
684 LR(0x16);
685 LRP(0x2D);
686 LRP(0x2F);
687 LR(0x1A);
688 LR(0x1B);
689 LR(0x1C);
690 LR(0x23);
691 LR(0x26);
692 LR(0x28);
693 LR(0x27);
694 LR(0x21);
695 LRP(0x2A);
696 if (m->mode == MATROXFB_OUTPUT_MODE_PAL)
697 maven_set_reg(c, 0x35, 0x1D);
698 else
699 maven_set_reg(c, 0x35, 0x1C);
700 LRP(0x3C);
701 LR(0x37);
702 LR(0x38);
703
704 maven_get_reg(c, 0xB0);
705 LR(0xB0); /* output mode */
706 LR(0x90);
707 LR(0xBE);
708 LR(0xC2);
709
710 LRP(0x9A);
711 LRP(0xA2);
712 LRP(0x9E);
713 LRP(0xA6);
714 LRP(0xAA);
715 LRP(0xAC);
716 maven_set_reg(c, 0x3E, 0x00);
717 maven_set_reg(c, 0x95, 0x20);
718}
719
720static int maven_find_exact_clocks(unsigned int ht, unsigned int vt,
721 struct mavenregs* m) {
722 unsigned int x;
723 unsigned int err = ~0;
724
725 /* 1:1 */
726 m->regs[0x80] = 0x0F;
727 m->regs[0x81] = 0x07;
728 m->regs[0x82] = 0x81;
729
730 for (x = 0; x < 8; x++) {
731 unsigned int c;
732 unsigned int uninitialized_var(a), uninitialized_var(b),
733 uninitialized_var(h2);
734 unsigned int h = ht + 2 + x;
735
736 if (!matroxfb_mavenclock((m->mode == MATROXFB_OUTPUT_MODE_PAL) ? &maven_PAL : &maven_NTSC, h, vt, &a, &b, &c, &h2)) {
737 unsigned int diff = h - h2;
738
739 if (diff < err) {
740 err = diff;
741 m->regs[0x80] = a - 1;
742 m->regs[0x81] = b - 1;
743 m->regs[0x82] = c | 0x80;
744 m->hcorr = h2 - 2;
745 m->htotal = h - 2;
746 }
747 }
748 }
749 return err != ~0U;
750}
751
752static inline int maven_compute_timming(struct maven_data* md,
753 struct my_timming* mt,
754 struct mavenregs* m) {
755 unsigned int tmpi;
756 unsigned int a, bv, c;
757 struct matrox_fb_info *minfo = md->primary_head;
758
759 m->mode = minfo->outputs[1].mode;
760 if (m->mode != MATROXFB_OUTPUT_MODE_MONITOR) {
761 unsigned int lmargin;
762 unsigned int umargin;
763 unsigned int vslen;
764 unsigned int hcrt;
765 unsigned int slen;
766
767 maven_init_TVdata(md, m);
768
769 if (maven_find_exact_clocks(mt->HTotal, mt->VTotal, m) == 0)
770 return -EINVAL;
771
772 lmargin = mt->HTotal - mt->HSyncEnd;
773 slen = mt->HSyncEnd - mt->HSyncStart;
774 hcrt = mt->HTotal - slen - mt->delay;
775 umargin = mt->VTotal - mt->VSyncEnd;
776 vslen = mt->VSyncEnd - mt->VSyncStart;
777
778 if (m->hcorr < mt->HTotal)
779 hcrt += m->hcorr;
780 if (hcrt > mt->HTotal)
781 hcrt -= mt->HTotal;
782 if (hcrt + 2 > mt->HTotal)
783 hcrt = 0; /* or issue warning? */
784
785 /* last (first? middle?) line in picture can have different length */
786 /* hlen - 2 */
787 m->regs[0x96] = m->hcorr;
788 m->regs[0x97] = m->hcorr >> 8;
789 /* ... */
790 m->regs[0x98] = 0x00; m->regs[0x99] = 0x00;
791 /* hblanking end */
792 m->regs[0x9A] = lmargin; /* 100% */
793 m->regs[0x9B] = lmargin >> 8; /* 100% */
794 /* who knows */
795 m->regs[0x9C] = 0x04;
796 m->regs[0x9D] = 0x00;
797 /* htotal - 2 */
798 m->regs[0xA0] = m->htotal;
799 m->regs[0xA1] = m->htotal >> 8;
800 /* vblanking end */
801 m->regs[0xA2] = mt->VTotal - mt->VSyncStart - 1; /* stop vblanking */
802 m->regs[0xA3] = (mt->VTotal - mt->VSyncStart - 1) >> 8;
803 /* something end... [A6]+1..[A8] */
804 if (md->version == MGATVO_B) {
805 m->regs[0xA4] = 0x04;
806 m->regs[0xA5] = 0x00;
807 } else {
808 m->regs[0xA4] = 0x01;
809 m->regs[0xA5] = 0x00;
810 }
811 /* something start... 0..[A4]-1 */
812 m->regs[0xA6] = 0x00;
813 m->regs[0xA7] = 0x00;
814 /* vertical line count - 1 */
815 m->regs[0xA8] = mt->VTotal - 1;
816 m->regs[0xA9] = (mt->VTotal - 1) >> 8;
817 /* horizontal vidrst pos */
818 m->regs[0xAA] = hcrt; /* 0 <= hcrt <= htotal - 2 */
819 m->regs[0xAB] = hcrt >> 8;
820 /* vertical vidrst pos */
821 m->regs[0xAC] = mt->VTotal - 2;
822 m->regs[0xAD] = (mt->VTotal - 2) >> 8;
823 /* moves picture up/down and so on... */
824 m->regs[0xAE] = 0x01; /* Fix this... 0..VTotal */
825 m->regs[0xAF] = 0x00;
826 {
827 int hdec;
828 int hlen;
829 unsigned int ibmin = 4 + lmargin + mt->HDisplay;
830 unsigned int ib;
831 int i;
832
833 /* Verify! */
834 /* Where 94208 came from? */
835 if (mt->HTotal)
836 hdec = 94208 / (mt->HTotal);
837 else
838 hdec = 0x81;
839 if (hdec > 0x81)
840 hdec = 0x81;
841 if (hdec < 0x41)
842 hdec = 0x41;
843 hdec--;
844 hlen = 98304 - 128 - ((lmargin + mt->HDisplay - 8) * hdec);
845 if (hlen < 0)
846 hlen = 0;
847 hlen = hlen >> 8;
848 if (hlen > 0xFF)
849 hlen = 0xFF;
850 /* Now we have to compute input buffer length.
851 If you want any picture, it must be between
852 4 + lmargin + xres
853 and
854 94208 / hdec
855 If you want perfect picture even on the top
856 of screen, it must be also
857 0x3C0000 * i / hdec + Q - R / hdec
858 where
859 R Qmin Qmax
860 0x07000 0x5AE 0x5BF
861 0x08000 0x5CF 0x5FF
862 0x0C000 0x653 0x67F
863 0x10000 0x6F8 0x6FF
864 */
865 i = 1;
866 do {
867 ib = ((0x3C0000 * i - 0x8000)/ hdec + 0x05E7) >> 8;
868 i++;
869 } while (ib < ibmin);
870 if (ib >= m->htotal + 2) {
871 ib = ibmin;
872 }
873
874 m->regs[0x90] = hdec; /* < 0x40 || > 0x80 is bad... 0x80 is questionable */
875 m->regs[0xC2] = hlen;
876 /* 'valid' input line length */
877 m->regs[0x9E] = ib;
878 m->regs[0x9F] = ib >> 8;
879 }
880 {
881 int vdec;
882 int vlen;
883
884#define MATROX_USE64BIT_DIVIDE
885 if (mt->VTotal) {
886#ifdef MATROX_USE64BIT_DIVIDE
887 u64 f1;
888 u32 a;
889 u32 b;
890
891 a = m->vlines * (m->htotal + 2);
892 b = (mt->VTotal - 1) * (m->htotal + 2) + m->hcorr + 2;
893
894 f1 = ((u64)a) << 15; /* *32768 */
895 do_div(f1, b);
896 vdec = f1;
897#else
898 vdec = m->vlines * 32768 / mt->VTotal;
899#endif
900 } else
901 vdec = 0x8000;
902 if (vdec > 0x8000)
903 vdec = 0x8000;
904 vlen = (vslen + umargin + mt->VDisplay) * vdec;
905 vlen = (vlen >> 16) - 146; /* FIXME: 146?! */
906 if (vlen < 0)
907 vlen = 0;
908 if (vlen > 0xFF)
909 vlen = 0xFF;
910 vdec--;
911 m->regs[0x91] = vdec;
912 m->regs[0x92] = vdec >> 8;
913 m->regs[0xBE] = vlen;
914 }
915 m->regs[0xB0] = 0x08; /* output: SVideo/Composite */
916 return 0;
917 }
918
919 DAC1064_calcclock(mt->pixclock, 450000, &a, &bv, &c);
920 m->regs[0x80] = a;
921 m->regs[0x81] = bv;
922 m->regs[0x82] = c | 0x80;
923
924 m->regs[0xB3] = 0x01;
925 m->regs[0x94] = 0xB2;
926
927 /* htotal... */
928 m->regs[0x96] = mt->HTotal;
929 m->regs[0x97] = mt->HTotal >> 8;
930 /* ?? */
931 m->regs[0x98] = 0x00;
932 m->regs[0x99] = 0x00;
933 /* hsync len */
934 tmpi = mt->HSyncEnd - mt->HSyncStart;
935 m->regs[0x9A] = tmpi;
936 m->regs[0x9B] = tmpi >> 8;
937 /* hblank end */
938 tmpi = mt->HTotal - mt->HSyncStart;
939 m->regs[0x9C] = tmpi;
940 m->regs[0x9D] = tmpi >> 8;
941 /* hblank start */
942 tmpi += mt->HDisplay;
943 m->regs[0x9E] = tmpi;
944 m->regs[0x9F] = tmpi >> 8;
945 /* htotal + 1 */
946 tmpi = mt->HTotal + 1;
947 m->regs[0xA0] = tmpi;
948 m->regs[0xA1] = tmpi >> 8;
949 /* vsync?! */
950 tmpi = mt->VSyncEnd - mt->VSyncStart - 1;
951 m->regs[0xA2] = tmpi;
952 m->regs[0xA3] = tmpi >> 8;
953 /* ignored? */
954 tmpi = mt->VTotal - mt->VSyncStart;
955 m->regs[0xA4] = tmpi;
956 m->regs[0xA5] = tmpi >> 8;
957 /* ignored? */
958 tmpi = mt->VTotal - 1;
959 m->regs[0xA6] = tmpi;
960 m->regs[0xA7] = tmpi >> 8;
961 /* vtotal - 1 */
962 m->regs[0xA8] = tmpi;
963 m->regs[0xA9] = tmpi >> 8;
964 /* hor vidrst */
965 tmpi = mt->HTotal - mt->delay;
966 m->regs[0xAA] = tmpi;
967 m->regs[0xAB] = tmpi >> 8;
968 /* vert vidrst */
969 tmpi = mt->VTotal - 2;
970 m->regs[0xAC] = tmpi;
971 m->regs[0xAD] = tmpi >> 8;
972 /* ignored? */
973 m->regs[0xAE] = 0x00;
974 m->regs[0xAF] = 0x00;
975
976 m->regs[0xB0] = 0x03; /* output: monitor */
977 m->regs[0xB1] = 0xA0; /* ??? */
978 m->regs[0x8C] = 0x20; /* must be set... */
979 m->regs[0x8D] = 0x04; /* defaults to 0x10: test signal */
980 m->regs[0xB9] = 0x1A; /* defaults to 0x2C: too bright */
981 m->regs[0xBF] = 0x22; /* makes picture stable */
982
983 return 0;
984}
985
986static int maven_program_timming(struct maven_data* md,
987 const struct mavenregs* m) {
988 struct i2c_client *c = md->client;
989
990 if (m->mode == MATROXFB_OUTPUT_MODE_MONITOR) {
991 LR(0x80);
992 LR(0x81);
993 LR(0x82);
994
995 LR(0xB3);
996 LR(0x94);
997
998 LRP(0x96);
999 LRP(0x98);
1000 LRP(0x9A);
1001 LRP(0x9C);
1002 LRP(0x9E);
1003 LRP(0xA0);
1004 LRP(0xA2);
1005 LRP(0xA4);
1006 LRP(0xA6);
1007 LRP(0xA8);
1008 LRP(0xAA);
1009 LRP(0xAC);
1010 LRP(0xAE);
1011
1012 LR(0xB0); /* output: monitor */
1013 LR(0xB1); /* ??? */
1014 LR(0x8C); /* must be set... */
1015 LR(0x8D); /* defaults to 0x10: test signal */
1016 LR(0xB9); /* defaults to 0x2C: too bright */
1017 LR(0xBF); /* makes picture stable */
1018 } else {
1019 maven_init_TV(c, m);
1020 }
1021 return 0;
1022}
1023
1024static inline int maven_resync(struct maven_data* md) {
1025 struct i2c_client *c = md->client;
1026 maven_set_reg(c, 0x95, 0x20); /* start whole thing */
1027 return 0;
1028}
1029
1030static int maven_get_queryctrl (struct maven_data* md,
1031 struct v4l2_queryctrl *p) {
1032 int i;
1033
1034 i = get_ctrl_id(p->id);
1035 if (i >= 0) {
1036 *p = maven_controls[i].desc;
1037 return 0;
1038 }
1039 if (i == -ENOENT) {
1040 static const struct v4l2_queryctrl disctrl =
1041 { .flags = V4L2_CTRL_FLAG_DISABLED };
1042
1043 i = p->id;
1044 *p = disctrl;
1045 p->id = i;
1046 sprintf(p->name, "Ctrl #%08X", i);
1047 return 0;
1048 }
1049 return -EINVAL;
1050}
1051
1052static int maven_set_control (struct maven_data* md,
1053 struct v4l2_control *p) {
1054 int i;
1055
1056 i = get_ctrl_id(p->id);
1057 if (i < 0) return -EINVAL;
1058
1059 /*
1060 * Check if changed.
1061 */
1062 if (p->value == *get_ctrl_ptr(md, i)) return 0;
1063
1064 /*
1065 * Check limits.
1066 */
1067 if (p->value > maven_controls[i].desc.maximum) return -EINVAL;
1068 if (p->value < maven_controls[i].desc.minimum) return -EINVAL;
1069
1070 /*
1071 * Store new value.
1072 */
1073 *get_ctrl_ptr(md, i) = p->value;
1074
1075 switch (p->id) {
1076 case V4L2_CID_BRIGHTNESS:
1077 case V4L2_CID_CONTRAST:
1078 {
1079 int blacklevel, whitelevel;
1080 maven_compute_bwlevel(md, &blacklevel, &whitelevel);
1081 blacklevel = (blacklevel >> 2) | ((blacklevel & 3) << 8);
1082 whitelevel = (whitelevel >> 2) | ((whitelevel & 3) << 8);
1083 maven_set_reg_pair(md->client, 0x0e, blacklevel);
1084 maven_set_reg_pair(md->client, 0x1e, whitelevel);
1085 }
1086 break;
1087 case V4L2_CID_SATURATION:
1088 {
1089 maven_set_reg(md->client, 0x20, p->value);
1090 maven_set_reg(md->client, 0x22, p->value);
1091 }
1092 break;
1093 case V4L2_CID_HUE:
1094 {
1095 maven_set_reg(md->client, 0x25, p->value);
1096 }
1097 break;
1098 case V4L2_CID_GAMMA:
1099 {
1100 const struct maven_gamma* g;
1101 g = maven_compute_gamma(md);
1102 maven_set_reg(md->client, 0x83, g->reg83);
1103 maven_set_reg(md->client, 0x84, g->reg84);
1104 maven_set_reg(md->client, 0x85, g->reg85);
1105 maven_set_reg(md->client, 0x86, g->reg86);
1106 maven_set_reg(md->client, 0x87, g->reg87);
1107 maven_set_reg(md->client, 0x88, g->reg88);
1108 maven_set_reg(md->client, 0x89, g->reg89);
1109 maven_set_reg(md->client, 0x8a, g->reg8a);
1110 maven_set_reg(md->client, 0x8b, g->reg8b);
1111 }
1112 break;
1113 case MATROXFB_CID_TESTOUT:
1114 {
1115 unsigned char val
1116 = maven_get_reg(md->client, 0x8d);
1117 if (p->value) val |= 0x10;
1118 else val &= ~0x10;
1119 maven_set_reg(md->client, 0x8d, val);
1120 }
1121 break;
1122 case MATROXFB_CID_DEFLICKER:
1123 {
1124 maven_set_reg(md->client, 0x93, maven_compute_deflicker(md));
1125 }
1126 break;
1127 }
1128
1129
1130 return 0;
1131}
1132
1133static int maven_get_control (struct maven_data* md,
1134 struct v4l2_control *p) {
1135 int i;
1136
1137 i = get_ctrl_id(p->id);
1138 if (i < 0) return -EINVAL;
1139 p->value = *get_ctrl_ptr(md, i);
1140 return 0;
1141}
1142
1143/******************************************************/
1144
1145static int maven_out_compute(void* md, struct my_timming* mt) {
1146#define mdinfo ((struct maven_data*)md)
1147#define minfo (mdinfo->primary_head)
1148 return maven_compute_timming(md, mt, &minfo->hw.maven);
1149#undef minfo
1150#undef mdinfo
1151}
1152
1153static int maven_out_program(void* md) {
1154#define mdinfo ((struct maven_data*)md)
1155#define minfo (mdinfo->primary_head)
1156 return maven_program_timming(md, &minfo->hw.maven);
1157#undef minfo
1158#undef mdinfo
1159}
1160
1161static int maven_out_start(void* md) {
1162 return maven_resync(md);
1163}
1164
1165static int maven_out_verify_mode(void* md, u_int32_t arg) {
1166 switch (arg) {
1167 case MATROXFB_OUTPUT_MODE_PAL:
1168 case MATROXFB_OUTPUT_MODE_NTSC:
1169 case MATROXFB_OUTPUT_MODE_MONITOR:
1170 return 0;
1171 }
1172 return -EINVAL;
1173}
1174
1175static int maven_out_get_queryctrl(void* md, struct v4l2_queryctrl* p) {
1176 return maven_get_queryctrl(md, p);
1177}
1178
1179static int maven_out_get_ctrl(void* md, struct v4l2_control* p) {
1180 return maven_get_control(md, p);
1181}
1182
1183static int maven_out_set_ctrl(void* md, struct v4l2_control* p) {
1184 return maven_set_control(md, p);
1185}
1186
1187static struct matrox_altout maven_altout = {
1188 .name = "Secondary output",
1189 .compute = maven_out_compute,
1190 .program = maven_out_program,
1191 .start = maven_out_start,
1192 .verifymode = maven_out_verify_mode,
1193 .getqueryctrl = maven_out_get_queryctrl,
1194 .getctrl = maven_out_get_ctrl,
1195 .setctrl = maven_out_set_ctrl,
1196};
1197
1198static int maven_init_client(struct i2c_client* clnt) {
1199 struct maven_data* md = i2c_get_clientdata(clnt);
1200 struct matrox_fb_info *minfo = container_of(clnt->adapter,
1201 struct i2c_bit_adapter,
1202 adapter)->minfo;
1203
1204 md->primary_head = minfo;
1205 md->client = clnt;
1206 down_write(&minfo->altout.lock);
1207 minfo->outputs[1].output = &maven_altout;
1208 minfo->outputs[1].src = minfo->outputs[1].default_src;
1209 minfo->outputs[1].data = md;
1210 minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR;
1211 up_write(&minfo->altout.lock);
1212 if (maven_get_reg(clnt, 0xB2) < 0x14) {
1213 md->version = MGATVO_B;
1214 /* Tweak some things for this old chip */
1215 } else {
1216 md->version = MGATVO_C;
1217 }
1218 /*
1219 * Set all parameters to its initial values.
1220 */
1221 {
1222 unsigned int i;
1223
1224 for (i = 0; i < MAVCTRLS; ++i) {
1225 *get_ctrl_ptr(md, i) = maven_controls[i].desc.default_value;
1226 }
1227 }
1228
1229 return 0;
1230}
1231
1232static int maven_shutdown_client(struct i2c_client* clnt) {
1233 struct maven_data* md = i2c_get_clientdata(clnt);
1234
1235 if (md->primary_head) {
1236 struct matrox_fb_info *minfo = md->primary_head;
1237
1238 down_write(&minfo->altout.lock);
1239 minfo->outputs[1].src = MATROXFB_SRC_NONE;
1240 minfo->outputs[1].output = NULL;
1241 minfo->outputs[1].data = NULL;
1242 minfo->outputs[1].mode = MATROXFB_OUTPUT_MODE_MONITOR;
1243 up_write(&minfo->altout.lock);
1244 md->primary_head = NULL;
1245 }
1246 return 0;
1247}
1248
1249static int maven_probe(struct i2c_client *client,
1250 const struct i2c_device_id *id)
1251{
1252 struct i2c_adapter *adapter = client->adapter;
1253 int err = -ENODEV;
1254 struct maven_data* data;
1255
1256 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_WORD_DATA |
1257 I2C_FUNC_SMBUS_BYTE_DATA |
1258 I2C_FUNC_NOSTART |
1259 I2C_FUNC_PROTOCOL_MANGLING))
1260 goto ERROR0;
1261 if (!(data = kzalloc(sizeof(*data), GFP_KERNEL))) {
1262 err = -ENOMEM;
1263 goto ERROR0;
1264 }
1265 i2c_set_clientdata(client, data);
1266 err = maven_init_client(client);
1267 if (err)
1268 goto ERROR4;
1269 return 0;
1270ERROR4:;
1271 kfree(data);
1272ERROR0:;
1273 return err;
1274}
1275
1276static int maven_remove(struct i2c_client *client)
1277{
1278 maven_shutdown_client(client);
1279 kfree(i2c_get_clientdata(client));
1280 return 0;
1281}
1282
1283static const struct i2c_device_id maven_id[] = {
1284 { "maven", 0 },
1285 { }
1286};
1287MODULE_DEVICE_TABLE(i2c, maven_id);
1288
1289static struct i2c_driver maven_driver={
1290 .driver = {
1291 .name = "maven",
1292 },
1293 .probe = maven_probe,
1294 .remove = maven_remove,
1295 .id_table = maven_id,
1296};
1297
1298module_i2c_driver(maven_driver);
1299MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
1300MODULE_DESCRIPTION("Matrox G200/G400 Matrox MGA-TVO driver");
1301MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/matrox/matroxfb_maven.h b/drivers/video/fbdev/matrox/matroxfb_maven.h
new file mode 100644
index 000000000000..99eddec9f30c
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_maven.h
@@ -0,0 +1,20 @@
1#ifndef __MATROXFB_MAVEN_H__
2#define __MATROXFB_MAVEN_H__
3
4#include <linux/ioctl.h>
5#include <linux/i2c.h>
6#include <linux/i2c-algo-bit.h>
7#include "matroxfb_base.h"
8
9struct i2c_bit_adapter {
10 struct i2c_adapter adapter;
11 int initialized;
12 struct i2c_algo_bit_data bac;
13 struct matrox_fb_info* minfo;
14 struct {
15 unsigned int data;
16 unsigned int clock;
17 } mask;
18};
19
20#endif /* __MATROXFB_MAVEN_H__ */
diff --git a/drivers/video/fbdev/matrox/matroxfb_misc.c b/drivers/video/fbdev/matrox/matroxfb_misc.c
new file mode 100644
index 000000000000..9948ca2a3046
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_misc.c
@@ -0,0 +1,815 @@
1/*
2 *
3 * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
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 * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
12 *
13 * Contributors: "menion?" <menion@mindless.com>
14 * Betatesting, fixes, ideas
15 *
16 * "Kurt Garloff" <garloff@suse.de>
17 * Betatesting, fixes, ideas, videomodes, videomodes timmings
18 *
19 * "Tom Rini" <trini@kernel.crashing.org>
20 * MTRR stuff, PPC cleanups, betatesting, fixes, ideas
21 *
22 * "Bibek Sahu" <scorpio@dodds.net>
23 * Access device through readb|w|l and write b|w|l
24 * Extensive debugging stuff
25 *
26 * "Daniel Haun" <haund@usa.net>
27 * Testing, hardware cursor fixes
28 *
29 * "Scott Wood" <sawst46+@pitt.edu>
30 * Fixes
31 *
32 * "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
33 * Betatesting
34 *
35 * "Kelly French" <targon@hazmat.com>
36 * "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
37 * Betatesting, bug reporting
38 *
39 * "Pablo Bianucci" <pbian@pccp.com.ar>
40 * Fixes, ideas, betatesting
41 *
42 * "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
43 * Fixes, enhandcements, ideas, betatesting
44 *
45 * "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
46 * PPC betatesting, PPC support, backward compatibility
47 *
48 * "Paul Womar" <Paul@pwomar.demon.co.uk>
49 * "Owen Waller" <O.Waller@ee.qub.ac.uk>
50 * PPC betatesting
51 *
52 * "Thomas Pornin" <pornin@bolet.ens.fr>
53 * Alpha betatesting
54 *
55 * "Pieter van Leuven" <pvl@iae.nl>
56 * "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
57 * G100 testing
58 *
59 * "H. Peter Arvin" <hpa@transmeta.com>
60 * Ideas
61 *
62 * "Cort Dougan" <cort@cs.nmt.edu>
63 * CHRP fixes and PReP cleanup
64 *
65 * "Mark Vojkovich" <mvojkovi@ucsd.edu>
66 * G400 support
67 *
68 * "David C. Hansen" <haveblue@us.ibm.com>
69 * Fixes
70 *
71 * "Ian Romanick" <idr@us.ibm.com>
72 * Find PInS data in BIOS on PowerPC systems.
73 *
74 * (following author is not in any relation with this code, but his code
75 * is included in this driver)
76 *
77 * Based on framebuffer driver for VBE 2.0 compliant graphic boards
78 * (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
79 *
80 * (following author is not in any relation with this code, but his ideas
81 * were used when writing this driver)
82 *
83 * FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
84 *
85 */
86
87
88#include "matroxfb_misc.h"
89#include <linux/interrupt.h>
90#include <linux/matroxfb.h>
91
92void matroxfb_DAC_out(const struct matrox_fb_info *minfo, int reg, int val)
93{
94 DBG_REG(__func__)
95 mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg);
96 mga_outb(M_RAMDAC_BASE+M_X_DATAREG, val);
97}
98
99int matroxfb_DAC_in(const struct matrox_fb_info *minfo, int reg)
100{
101 DBG_REG(__func__)
102 mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg);
103 return mga_inb(M_RAMDAC_BASE+M_X_DATAREG);
104}
105
106void matroxfb_var2my(struct fb_var_screeninfo* var, struct my_timming* mt) {
107 unsigned int pixclock = var->pixclock;
108
109 DBG(__func__)
110
111 if (!pixclock) pixclock = 10000; /* 10ns = 100MHz */
112 mt->pixclock = 1000000000 / pixclock;
113 if (mt->pixclock < 1) mt->pixclock = 1;
114 mt->mnp = -1;
115 mt->dblscan = var->vmode & FB_VMODE_DOUBLE;
116 mt->interlaced = var->vmode & FB_VMODE_INTERLACED;
117 mt->HDisplay = var->xres;
118 mt->HSyncStart = mt->HDisplay + var->right_margin;
119 mt->HSyncEnd = mt->HSyncStart + var->hsync_len;
120 mt->HTotal = mt->HSyncEnd + var->left_margin;
121 mt->VDisplay = var->yres;
122 mt->VSyncStart = mt->VDisplay + var->lower_margin;
123 mt->VSyncEnd = mt->VSyncStart + var->vsync_len;
124 mt->VTotal = mt->VSyncEnd + var->upper_margin;
125 mt->sync = var->sync;
126}
127
128int matroxfb_PLL_calcclock(const struct matrox_pll_features* pll, unsigned int freq, unsigned int fmax,
129 unsigned int* in, unsigned int* feed, unsigned int* post) {
130 unsigned int bestdiff = ~0;
131 unsigned int bestvco = 0;
132 unsigned int fxtal = pll->ref_freq;
133 unsigned int fwant;
134 unsigned int p;
135
136 DBG(__func__)
137
138 fwant = freq;
139
140#ifdef DEBUG
141 printk(KERN_ERR "post_shift_max: %d\n", pll->post_shift_max);
142 printk(KERN_ERR "ref_freq: %d\n", pll->ref_freq);
143 printk(KERN_ERR "freq: %d\n", freq);
144 printk(KERN_ERR "vco_freq_min: %d\n", pll->vco_freq_min);
145 printk(KERN_ERR "in_div_min: %d\n", pll->in_div_min);
146 printk(KERN_ERR "in_div_max: %d\n", pll->in_div_max);
147 printk(KERN_ERR "feed_div_min: %d\n", pll->feed_div_min);
148 printk(KERN_ERR "feed_div_max: %d\n", pll->feed_div_max);
149 printk(KERN_ERR "fmax: %d\n", fmax);
150#endif
151 for (p = 1; p <= pll->post_shift_max; p++) {
152 if (fwant * 2 > fmax)
153 break;
154 fwant *= 2;
155 }
156 if (fwant < pll->vco_freq_min) fwant = pll->vco_freq_min;
157 if (fwant > fmax) fwant = fmax;
158 for (; p-- > 0; fwant >>= 1, bestdiff >>= 1) {
159 unsigned int m;
160
161 if (fwant < pll->vco_freq_min) break;
162 for (m = pll->in_div_min; m <= pll->in_div_max; m++) {
163 unsigned int diff, fvco;
164 unsigned int n;
165
166 n = (fwant * (m + 1) + (fxtal >> 1)) / fxtal - 1;
167 if (n > pll->feed_div_max)
168 break;
169 if (n < pll->feed_div_min)
170 n = pll->feed_div_min;
171 fvco = (fxtal * (n + 1)) / (m + 1);
172 if (fvco < fwant)
173 diff = fwant - fvco;
174 else
175 diff = fvco - fwant;
176 if (diff < bestdiff) {
177 bestdiff = diff;
178 *post = p;
179 *in = m;
180 *feed = n;
181 bestvco = fvco;
182 }
183 }
184 }
185 dprintk(KERN_ERR "clk: %02X %02X %02X %d %d %d\n", *in, *feed, *post, fxtal, bestvco, fwant);
186 return bestvco;
187}
188
189int matroxfb_vgaHWinit(struct matrox_fb_info *minfo, struct my_timming *m)
190{
191 unsigned int hd, hs, he, hbe, ht;
192 unsigned int vd, vs, ve, vt, lc;
193 unsigned int wd;
194 unsigned int divider;
195 int i;
196 struct matrox_hw_state * const hw = &minfo->hw;
197
198 DBG(__func__)
199
200 hw->SEQ[0] = 0x00;
201 hw->SEQ[1] = 0x01; /* or 0x09 */
202 hw->SEQ[2] = 0x0F; /* bitplanes */
203 hw->SEQ[3] = 0x00;
204 hw->SEQ[4] = 0x0E;
205 /* CRTC 0..7, 9, 16..19, 21, 22 are reprogrammed by Matrox Millennium code... Hope that by MGA1064 too */
206 if (m->dblscan) {
207 m->VTotal <<= 1;
208 m->VDisplay <<= 1;
209 m->VSyncStart <<= 1;
210 m->VSyncEnd <<= 1;
211 }
212 if (m->interlaced) {
213 m->VTotal >>= 1;
214 m->VDisplay >>= 1;
215 m->VSyncStart >>= 1;
216 m->VSyncEnd >>= 1;
217 }
218
219 /* GCTL is ignored when not using 0xA0000 aperture */
220 hw->GCTL[0] = 0x00;
221 hw->GCTL[1] = 0x00;
222 hw->GCTL[2] = 0x00;
223 hw->GCTL[3] = 0x00;
224 hw->GCTL[4] = 0x00;
225 hw->GCTL[5] = 0x40;
226 hw->GCTL[6] = 0x05;
227 hw->GCTL[7] = 0x0F;
228 hw->GCTL[8] = 0xFF;
229
230 /* Whole ATTR is ignored in PowerGraphics mode */
231 for (i = 0; i < 16; i++)
232 hw->ATTR[i] = i;
233 hw->ATTR[16] = 0x41;
234 hw->ATTR[17] = 0xFF;
235 hw->ATTR[18] = 0x0F;
236 hw->ATTR[19] = 0x00;
237 hw->ATTR[20] = 0x00;
238
239 hd = m->HDisplay >> 3;
240 hs = m->HSyncStart >> 3;
241 he = m->HSyncEnd >> 3;
242 ht = m->HTotal >> 3;
243 /* standard timmings are in 8pixels, but for interleaved we cannot */
244 /* do it for 4bpp (because of (4bpp >> 1(interleaved))/4 == 0) */
245 /* using 16 or more pixels per unit can save us */
246 divider = minfo->curr.final_bppShift;
247 while (divider & 3) {
248 hd >>= 1;
249 hs >>= 1;
250 he >>= 1;
251 ht >>= 1;
252 divider <<= 1;
253 }
254 divider = divider / 4;
255 /* divider can be from 1 to 8 */
256 while (divider > 8) {
257 hd <<= 1;
258 hs <<= 1;
259 he <<= 1;
260 ht <<= 1;
261 divider >>= 1;
262 }
263 hd = hd - 1;
264 hs = hs - 1;
265 he = he - 1;
266 ht = ht - 1;
267 vd = m->VDisplay - 1;
268 vs = m->VSyncStart - 1;
269 ve = m->VSyncEnd - 1;
270 vt = m->VTotal - 2;
271 lc = vd;
272 /* G200 cannot work with (ht & 7) == 6 */
273 if (((ht & 0x07) == 0x06) || ((ht & 0x0F) == 0x04))
274 ht++;
275 hbe = ht;
276 wd = minfo->fbcon.var.xres_virtual * minfo->curr.final_bppShift / 64;
277
278 hw->CRTCEXT[0] = 0;
279 hw->CRTCEXT[5] = 0;
280 if (m->interlaced) {
281 hw->CRTCEXT[0] = 0x80;
282 hw->CRTCEXT[5] = (hs + he - ht) >> 1;
283 if (!m->dblscan)
284 wd <<= 1;
285 vt &= ~1;
286 }
287 hw->CRTCEXT[0] |= (wd & 0x300) >> 4;
288 hw->CRTCEXT[1] = (((ht - 4) & 0x100) >> 8) |
289 ((hd & 0x100) >> 7) | /* blanking */
290 ((hs & 0x100) >> 6) | /* sync start */
291 (hbe & 0x040); /* end hor. blanking */
292 /* FIXME: Enable vidrst only on G400, and only if TV-out is used */
293 if (minfo->outputs[1].src == MATROXFB_SRC_CRTC1)
294 hw->CRTCEXT[1] |= 0x88; /* enable horizontal and vertical vidrst */
295 hw->CRTCEXT[2] = ((vt & 0xC00) >> 10) |
296 ((vd & 0x400) >> 8) | /* disp end */
297 ((vd & 0xC00) >> 7) | /* vblanking start */
298 ((vs & 0xC00) >> 5) |
299 ((lc & 0x400) >> 3);
300 hw->CRTCEXT[3] = (divider - 1) | 0x80;
301 hw->CRTCEXT[4] = 0;
302
303 hw->CRTC[0] = ht-4;
304 hw->CRTC[1] = hd;
305 hw->CRTC[2] = hd;
306 hw->CRTC[3] = (hbe & 0x1F) | 0x80;
307 hw->CRTC[4] = hs;
308 hw->CRTC[5] = ((hbe & 0x20) << 2) | (he & 0x1F);
309 hw->CRTC[6] = vt & 0xFF;
310 hw->CRTC[7] = ((vt & 0x100) >> 8) |
311 ((vd & 0x100) >> 7) |
312 ((vs & 0x100) >> 6) |
313 ((vd & 0x100) >> 5) |
314 ((lc & 0x100) >> 4) |
315 ((vt & 0x200) >> 4) |
316 ((vd & 0x200) >> 3) |
317 ((vs & 0x200) >> 2);
318 hw->CRTC[8] = 0x00;
319 hw->CRTC[9] = ((vd & 0x200) >> 4) |
320 ((lc & 0x200) >> 3);
321 if (m->dblscan && !m->interlaced)
322 hw->CRTC[9] |= 0x80;
323 for (i = 10; i < 16; i++)
324 hw->CRTC[i] = 0x00;
325 hw->CRTC[16] = vs /* & 0xFF */;
326 hw->CRTC[17] = (ve & 0x0F) | 0x20;
327 hw->CRTC[18] = vd /* & 0xFF */;
328 hw->CRTC[19] = wd /* & 0xFF */;
329 hw->CRTC[20] = 0x00;
330 hw->CRTC[21] = vd /* & 0xFF */;
331 hw->CRTC[22] = (vt + 1) /* & 0xFF */;
332 hw->CRTC[23] = 0xC3;
333 hw->CRTC[24] = lc;
334 return 0;
335};
336
337void matroxfb_vgaHWrestore(struct matrox_fb_info *minfo)
338{
339 int i;
340 struct matrox_hw_state * const hw = &minfo->hw;
341 CRITFLAGS
342
343 DBG(__func__)
344
345 dprintk(KERN_INFO "MiscOutReg: %02X\n", hw->MiscOutReg);
346 dprintk(KERN_INFO "SEQ regs: ");
347 for (i = 0; i < 5; i++)
348 dprintk("%02X:", hw->SEQ[i]);
349 dprintk("\n");
350 dprintk(KERN_INFO "GDC regs: ");
351 for (i = 0; i < 9; i++)
352 dprintk("%02X:", hw->GCTL[i]);
353 dprintk("\n");
354 dprintk(KERN_INFO "CRTC regs: ");
355 for (i = 0; i < 25; i++)
356 dprintk("%02X:", hw->CRTC[i]);
357 dprintk("\n");
358 dprintk(KERN_INFO "ATTR regs: ");
359 for (i = 0; i < 21; i++)
360 dprintk("%02X:", hw->ATTR[i]);
361 dprintk("\n");
362
363 CRITBEGIN
364
365 mga_inb(M_ATTR_RESET);
366 mga_outb(M_ATTR_INDEX, 0);
367 mga_outb(M_MISC_REG, hw->MiscOutReg);
368 for (i = 1; i < 5; i++)
369 mga_setr(M_SEQ_INDEX, i, hw->SEQ[i]);
370 mga_setr(M_CRTC_INDEX, 17, hw->CRTC[17] & 0x7F);
371 for (i = 0; i < 25; i++)
372 mga_setr(M_CRTC_INDEX, i, hw->CRTC[i]);
373 for (i = 0; i < 9; i++)
374 mga_setr(M_GRAPHICS_INDEX, i, hw->GCTL[i]);
375 for (i = 0; i < 21; i++) {
376 mga_inb(M_ATTR_RESET);
377 mga_outb(M_ATTR_INDEX, i);
378 mga_outb(M_ATTR_INDEX, hw->ATTR[i]);
379 }
380 mga_outb(M_PALETTE_MASK, 0xFF);
381 mga_outb(M_DAC_REG, 0x00);
382 for (i = 0; i < 768; i++)
383 mga_outb(M_DAC_VAL, hw->DACpal[i]);
384 mga_inb(M_ATTR_RESET);
385 mga_outb(M_ATTR_INDEX, 0x20);
386
387 CRITEND
388}
389
390static void get_pins(unsigned char __iomem* pins, struct matrox_bios* bd) {
391 unsigned int b0 = readb(pins);
392
393 if (b0 == 0x2E && readb(pins+1) == 0x41) {
394 unsigned int pins_len = readb(pins+2);
395 unsigned int i;
396 unsigned char cksum;
397 unsigned char* dst = bd->pins;
398
399 if (pins_len < 3 || pins_len > 128) {
400 return;
401 }
402 *dst++ = 0x2E;
403 *dst++ = 0x41;
404 *dst++ = pins_len;
405 cksum = 0x2E + 0x41 + pins_len;
406 for (i = 3; i < pins_len; i++) {
407 cksum += *dst++ = readb(pins+i);
408 }
409 if (cksum) {
410 return;
411 }
412 bd->pins_len = pins_len;
413 } else if (b0 == 0x40 && readb(pins+1) == 0x00) {
414 unsigned int i;
415 unsigned char* dst = bd->pins;
416
417 *dst++ = 0x40;
418 *dst++ = 0;
419 for (i = 2; i < 0x40; i++) {
420 *dst++ = readb(pins+i);
421 }
422 bd->pins_len = 0x40;
423 }
424}
425
426static void get_bios_version(unsigned char __iomem * vbios, struct matrox_bios* bd) {
427 unsigned int pcir_offset;
428
429 pcir_offset = readb(vbios + 24) | (readb(vbios + 25) << 8);
430 if (pcir_offset >= 26 && pcir_offset < 0xFFE0 &&
431 readb(vbios + pcir_offset ) == 'P' &&
432 readb(vbios + pcir_offset + 1) == 'C' &&
433 readb(vbios + pcir_offset + 2) == 'I' &&
434 readb(vbios + pcir_offset + 3) == 'R') {
435 unsigned char h;
436
437 h = readb(vbios + pcir_offset + 0x12);
438 bd->version.vMaj = (h >> 4) & 0xF;
439 bd->version.vMin = h & 0xF;
440 bd->version.vRev = readb(vbios + pcir_offset + 0x13);
441 } else {
442 unsigned char h;
443
444 h = readb(vbios + 5);
445 bd->version.vMaj = (h >> 4) & 0xF;
446 bd->version.vMin = h & 0xF;
447 bd->version.vRev = 0;
448 }
449}
450
451static void get_bios_output(unsigned char __iomem* vbios, struct matrox_bios* bd) {
452 unsigned char b;
453
454 b = readb(vbios + 0x7FF1);
455 if (b == 0xFF) {
456 b = 0;
457 }
458 bd->output.state = b;
459}
460
461static void get_bios_tvout(unsigned char __iomem* vbios, struct matrox_bios* bd) {
462 unsigned int i;
463
464 /* Check for 'IBM .*(V....TVO' string - it means TVO BIOS */
465 bd->output.tvout = 0;
466 if (readb(vbios + 0x1D) != 'I' ||
467 readb(vbios + 0x1E) != 'B' ||
468 readb(vbios + 0x1F) != 'M' ||
469 readb(vbios + 0x20) != ' ') {
470 return;
471 }
472 for (i = 0x2D; i < 0x2D + 128; i++) {
473 unsigned char b = readb(vbios + i);
474
475 if (b == '(' && readb(vbios + i + 1) == 'V') {
476 if (readb(vbios + i + 6) == 'T' &&
477 readb(vbios + i + 7) == 'V' &&
478 readb(vbios + i + 8) == 'O') {
479 bd->output.tvout = 1;
480 }
481 return;
482 }
483 if (b == 0)
484 break;
485 }
486}
487
488static void parse_bios(unsigned char __iomem* vbios, struct matrox_bios* bd) {
489 unsigned int pins_offset;
490
491 if (readb(vbios) != 0x55 || readb(vbios + 1) != 0xAA) {
492 return;
493 }
494 bd->bios_valid = 1;
495 get_bios_version(vbios, bd);
496 get_bios_output(vbios, bd);
497 get_bios_tvout(vbios, bd);
498#if defined(__powerpc__)
499 /* On PowerPC cards, the PInS offset isn't stored at the end of the
500 * BIOS image. Instead, you must search the entire BIOS image for
501 * the magic PInS signature.
502 *
503 * This actually applies to all OpenFirmware base cards. Since these
504 * cards could be put in a MIPS or SPARC system, should the condition
505 * be something different?
506 */
507 for ( pins_offset = 0 ; pins_offset <= 0xFF80 ; pins_offset++ ) {
508 unsigned char header[3];
509
510 header[0] = readb(vbios + pins_offset);
511 header[1] = readb(vbios + pins_offset + 1);
512 header[2] = readb(vbios + pins_offset + 2);
513 if ( (header[0] == 0x2E) && (header[1] == 0x41)
514 && ((header[2] == 0x40) || (header[2] == 0x80)) ) {
515 printk(KERN_INFO "PInS data found at offset %u\n",
516 pins_offset);
517 get_pins(vbios + pins_offset, bd);
518 break;
519 }
520 }
521#else
522 pins_offset = readb(vbios + 0x7FFC) | (readb(vbios + 0x7FFD) << 8);
523 if (pins_offset <= 0xFF80) {
524 get_pins(vbios + pins_offset, bd);
525 }
526#endif
527}
528
529static int parse_pins1(struct matrox_fb_info *minfo,
530 const struct matrox_bios *bd)
531{
532 unsigned int maxdac;
533
534 switch (bd->pins[22]) {
535 case 0: maxdac = 175000; break;
536 case 1: maxdac = 220000; break;
537 default: maxdac = 240000; break;
538 }
539 if (get_unaligned_le16(bd->pins + 24)) {
540 maxdac = get_unaligned_le16(bd->pins + 24) * 10;
541 }
542 minfo->limits.pixel.vcomax = maxdac;
543 minfo->values.pll.system = get_unaligned_le16(bd->pins + 28) ?
544 get_unaligned_le16(bd->pins + 28) * 10 : 50000;
545 /* ignore 4MB, 8MB, module clocks */
546 minfo->features.pll.ref_freq = 14318;
547 minfo->values.reg.mctlwtst = 0x00030101;
548 return 0;
549}
550
551static void default_pins1(struct matrox_fb_info *minfo)
552{
553 /* Millennium */
554 minfo->limits.pixel.vcomax = 220000;
555 minfo->values.pll.system = 50000;
556 minfo->features.pll.ref_freq = 14318;
557 minfo->values.reg.mctlwtst = 0x00030101;
558}
559
560static int parse_pins2(struct matrox_fb_info *minfo,
561 const struct matrox_bios *bd)
562{
563 minfo->limits.pixel.vcomax =
564 minfo->limits.system.vcomax = (bd->pins[41] == 0xFF) ? 230000 : ((bd->pins[41] + 100) * 1000);
565 minfo->values.reg.mctlwtst = ((bd->pins[51] & 0x01) ? 0x00000001 : 0) |
566 ((bd->pins[51] & 0x02) ? 0x00000100 : 0) |
567 ((bd->pins[51] & 0x04) ? 0x00010000 : 0) |
568 ((bd->pins[51] & 0x08) ? 0x00020000 : 0);
569 minfo->values.pll.system = (bd->pins[43] == 0xFF) ? 50000 : ((bd->pins[43] + 100) * 1000);
570 minfo->features.pll.ref_freq = 14318;
571 return 0;
572}
573
574static void default_pins2(struct matrox_fb_info *minfo)
575{
576 /* Millennium II, Mystique */
577 minfo->limits.pixel.vcomax =
578 minfo->limits.system.vcomax = 230000;
579 minfo->values.reg.mctlwtst = 0x00030101;
580 minfo->values.pll.system = 50000;
581 minfo->features.pll.ref_freq = 14318;
582}
583
584static int parse_pins3(struct matrox_fb_info *minfo,
585 const struct matrox_bios *bd)
586{
587 minfo->limits.pixel.vcomax =
588 minfo->limits.system.vcomax = (bd->pins[36] == 0xFF) ? 230000 : ((bd->pins[36] + 100) * 1000);
589 minfo->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 48) == 0xFFFFFFFF ?
590 0x01250A21 : get_unaligned_le32(bd->pins + 48);
591 /* memory config */
592 minfo->values.reg.memrdbk = ((bd->pins[57] << 21) & 0x1E000000) |
593 ((bd->pins[57] << 22) & 0x00C00000) |
594 ((bd->pins[56] << 1) & 0x000001E0) |
595 ( bd->pins[56] & 0x0000000F);
596 minfo->values.reg.opt = (bd->pins[54] & 7) << 10;
597 minfo->values.reg.opt2 = bd->pins[58] << 12;
598 minfo->features.pll.ref_freq = (bd->pins[52] & 0x20) ? 14318 : 27000;
599 return 0;
600}
601
602static void default_pins3(struct matrox_fb_info *minfo)
603{
604 /* G100, G200 */
605 minfo->limits.pixel.vcomax =
606 minfo->limits.system.vcomax = 230000;
607 minfo->values.reg.mctlwtst = 0x01250A21;
608 minfo->values.reg.memrdbk = 0x00000000;
609 minfo->values.reg.opt = 0x00000C00;
610 minfo->values.reg.opt2 = 0x00000000;
611 minfo->features.pll.ref_freq = 27000;
612}
613
614static int parse_pins4(struct matrox_fb_info *minfo,
615 const struct matrox_bios *bd)
616{
617 minfo->limits.pixel.vcomax = (bd->pins[ 39] == 0xFF) ? 230000 : bd->pins[ 39] * 4000;
618 minfo->limits.system.vcomax = (bd->pins[ 38] == 0xFF) ? minfo->limits.pixel.vcomax : bd->pins[ 38] * 4000;
619 minfo->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 71);
620 minfo->values.reg.memrdbk = ((bd->pins[87] << 21) & 0x1E000000) |
621 ((bd->pins[87] << 22) & 0x00C00000) |
622 ((bd->pins[86] << 1) & 0x000001E0) |
623 ( bd->pins[86] & 0x0000000F);
624 minfo->values.reg.opt = ((bd->pins[53] << 15) & 0x00400000) |
625 ((bd->pins[53] << 22) & 0x10000000) |
626 ((bd->pins[53] << 7) & 0x00001C00);
627 minfo->values.reg.opt3 = get_unaligned_le32(bd->pins + 67);
628 minfo->values.pll.system = (bd->pins[ 65] == 0xFF) ? 200000 : bd->pins[ 65] * 4000;
629 minfo->features.pll.ref_freq = (bd->pins[ 92] & 0x01) ? 14318 : 27000;
630 return 0;
631}
632
633static void default_pins4(struct matrox_fb_info *minfo)
634{
635 /* G400 */
636 minfo->limits.pixel.vcomax =
637 minfo->limits.system.vcomax = 252000;
638 minfo->values.reg.mctlwtst = 0x04A450A1;
639 minfo->values.reg.memrdbk = 0x000000E7;
640 minfo->values.reg.opt = 0x10000400;
641 minfo->values.reg.opt3 = 0x0190A419;
642 minfo->values.pll.system = 200000;
643 minfo->features.pll.ref_freq = 27000;
644}
645
646static int parse_pins5(struct matrox_fb_info *minfo,
647 const struct matrox_bios *bd)
648{
649 unsigned int mult;
650
651 mult = bd->pins[4]?8000:6000;
652
653 minfo->limits.pixel.vcomax = (bd->pins[ 38] == 0xFF) ? 600000 : bd->pins[ 38] * mult;
654 minfo->limits.system.vcomax = (bd->pins[ 36] == 0xFF) ? minfo->limits.pixel.vcomax : bd->pins[ 36] * mult;
655 minfo->limits.video.vcomax = (bd->pins[ 37] == 0xFF) ? minfo->limits.system.vcomax : bd->pins[ 37] * mult;
656 minfo->limits.pixel.vcomin = (bd->pins[123] == 0xFF) ? 256000 : bd->pins[123] * mult;
657 minfo->limits.system.vcomin = (bd->pins[121] == 0xFF) ? minfo->limits.pixel.vcomin : bd->pins[121] * mult;
658 minfo->limits.video.vcomin = (bd->pins[122] == 0xFF) ? minfo->limits.system.vcomin : bd->pins[122] * mult;
659 minfo->values.pll.system =
660 minfo->values.pll.video = (bd->pins[ 92] == 0xFF) ? 284000 : bd->pins[ 92] * 4000;
661 minfo->values.reg.opt = get_unaligned_le32(bd->pins + 48);
662 minfo->values.reg.opt2 = get_unaligned_le32(bd->pins + 52);
663 minfo->values.reg.opt3 = get_unaligned_le32(bd->pins + 94);
664 minfo->values.reg.mctlwtst = get_unaligned_le32(bd->pins + 98);
665 minfo->values.reg.memmisc = get_unaligned_le32(bd->pins + 102);
666 minfo->values.reg.memrdbk = get_unaligned_le32(bd->pins + 106);
667 minfo->features.pll.ref_freq = (bd->pins[110] & 0x01) ? 14318 : 27000;
668 minfo->values.memory.ddr = (bd->pins[114] & 0x60) == 0x20;
669 minfo->values.memory.dll = (bd->pins[115] & 0x02) != 0;
670 minfo->values.memory.emrswen = (bd->pins[115] & 0x01) != 0;
671 minfo->values.reg.maccess = minfo->values.memory.emrswen ? 0x00004000 : 0x00000000;
672 if (bd->pins[115] & 4) {
673 minfo->values.reg.mctlwtst_core = minfo->values.reg.mctlwtst;
674 } else {
675 u_int32_t wtst_xlat[] = { 0, 1, 5, 6, 7, 5, 2, 3 };
676 minfo->values.reg.mctlwtst_core = (minfo->values.reg.mctlwtst & ~7) |
677 wtst_xlat[minfo->values.reg.mctlwtst & 7];
678 }
679 minfo->max_pixel_clock_panellink = bd->pins[47] * 4000;
680 return 0;
681}
682
683static void default_pins5(struct matrox_fb_info *minfo)
684{
685 /* Mine 16MB G450 with SDRAM DDR */
686 minfo->limits.pixel.vcomax =
687 minfo->limits.system.vcomax =
688 minfo->limits.video.vcomax = 600000;
689 minfo->limits.pixel.vcomin =
690 minfo->limits.system.vcomin =
691 minfo->limits.video.vcomin = 256000;
692 minfo->values.pll.system =
693 minfo->values.pll.video = 284000;
694 minfo->values.reg.opt = 0x404A1160;
695 minfo->values.reg.opt2 = 0x0000AC00;
696 minfo->values.reg.opt3 = 0x0090A409;
697 minfo->values.reg.mctlwtst_core =
698 minfo->values.reg.mctlwtst = 0x0C81462B;
699 minfo->values.reg.memmisc = 0x80000004;
700 minfo->values.reg.memrdbk = 0x01001103;
701 minfo->features.pll.ref_freq = 27000;
702 minfo->values.memory.ddr = 1;
703 minfo->values.memory.dll = 1;
704 minfo->values.memory.emrswen = 1;
705 minfo->values.reg.maccess = 0x00004000;
706}
707
708static int matroxfb_set_limits(struct matrox_fb_info *minfo,
709 const struct matrox_bios *bd)
710{
711 unsigned int pins_version;
712 static const unsigned int pinslen[] = { 64, 64, 64, 128, 128 };
713
714 switch (minfo->chip) {
715 case MGA_2064: default_pins1(minfo); break;
716 case MGA_2164:
717 case MGA_1064:
718 case MGA_1164: default_pins2(minfo); break;
719 case MGA_G100:
720 case MGA_G200: default_pins3(minfo); break;
721 case MGA_G400: default_pins4(minfo); break;
722 case MGA_G450:
723 case MGA_G550: default_pins5(minfo); break;
724 }
725 if (!bd->bios_valid) {
726 printk(KERN_INFO "matroxfb: Your Matrox device does not have BIOS\n");
727 return -1;
728 }
729 if (bd->pins_len < 64) {
730 printk(KERN_INFO "matroxfb: BIOS on your Matrox device does not contain powerup info\n");
731 return -1;
732 }
733 if (bd->pins[0] == 0x2E && bd->pins[1] == 0x41) {
734 pins_version = bd->pins[5];
735 if (pins_version < 2 || pins_version > 5) {
736 printk(KERN_INFO "matroxfb: Unknown version (%u) of powerup info\n", pins_version);
737 return -1;
738 }
739 } else {
740 pins_version = 1;
741 }
742 if (bd->pins_len != pinslen[pins_version - 1]) {
743 printk(KERN_INFO "matroxfb: Invalid powerup info\n");
744 return -1;
745 }
746 switch (pins_version) {
747 case 1:
748 return parse_pins1(minfo, bd);
749 case 2:
750 return parse_pins2(minfo, bd);
751 case 3:
752 return parse_pins3(minfo, bd);
753 case 4:
754 return parse_pins4(minfo, bd);
755 case 5:
756 return parse_pins5(minfo, bd);
757 default:
758 printk(KERN_DEBUG "matroxfb: Powerup info version %u is not yet supported\n", pins_version);
759 return -1;
760 }
761}
762
763void matroxfb_read_pins(struct matrox_fb_info *minfo)
764{
765 u32 opt;
766 u32 biosbase;
767 u32 fbbase;
768 struct pci_dev *pdev = minfo->pcidev;
769
770 memset(&minfo->bios, 0, sizeof(minfo->bios));
771 pci_read_config_dword(pdev, PCI_OPTION_REG, &opt);
772 pci_write_config_dword(pdev, PCI_OPTION_REG, opt | PCI_OPTION_ENABLE_ROM);
773 pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &biosbase);
774 pci_read_config_dword(pdev, minfo->devflags.fbResource, &fbbase);
775 pci_write_config_dword(pdev, PCI_ROM_ADDRESS, (fbbase & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE);
776 parse_bios(vaddr_va(minfo->video.vbase), &minfo->bios);
777 pci_write_config_dword(pdev, PCI_ROM_ADDRESS, biosbase);
778 pci_write_config_dword(pdev, PCI_OPTION_REG, opt);
779#ifdef CONFIG_X86
780 if (!minfo->bios.bios_valid) {
781 unsigned char __iomem* b;
782
783 b = ioremap(0x000C0000, 65536);
784 if (!b) {
785 printk(KERN_INFO "matroxfb: Unable to map legacy BIOS\n");
786 } else {
787 unsigned int ven = readb(b+0x64+0) | (readb(b+0x64+1) << 8);
788 unsigned int dev = readb(b+0x64+2) | (readb(b+0x64+3) << 8);
789
790 if (ven != pdev->vendor || dev != pdev->device) {
791 printk(KERN_INFO "matroxfb: Legacy BIOS is for %04X:%04X, while this device is %04X:%04X\n",
792 ven, dev, pdev->vendor, pdev->device);
793 } else {
794 parse_bios(b, &minfo->bios);
795 }
796 iounmap(b);
797 }
798 }
799#endif
800 matroxfb_set_limits(minfo, &minfo->bios);
801 printk(KERN_INFO "PInS memtype = %u\n",
802 (minfo->values.reg.opt & 0x1C00) >> 10);
803}
804
805EXPORT_SYMBOL(matroxfb_DAC_in);
806EXPORT_SYMBOL(matroxfb_DAC_out);
807EXPORT_SYMBOL(matroxfb_var2my);
808EXPORT_SYMBOL(matroxfb_PLL_calcclock);
809EXPORT_SYMBOL(matroxfb_vgaHWinit); /* DAC1064, Ti3026 */
810EXPORT_SYMBOL(matroxfb_vgaHWrestore); /* DAC1064, Ti3026 */
811EXPORT_SYMBOL(matroxfb_read_pins);
812
813MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");
814MODULE_DESCRIPTION("Miscellaneous support for Matrox video cards");
815MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/matrox/matroxfb_misc.h b/drivers/video/fbdev/matrox/matroxfb_misc.h
new file mode 100644
index 000000000000..351c823f1f74
--- /dev/null
+++ b/drivers/video/fbdev/matrox/matroxfb_misc.h
@@ -0,0 +1,21 @@
1#ifndef __MATROXFB_MISC_H__
2#define __MATROXFB_MISC_H__
3
4#include "matroxfb_base.h"
5
6/* also for modules */
7int matroxfb_PLL_calcclock(const struct matrox_pll_features* pll, unsigned int freq, unsigned int fmax,
8 unsigned int* in, unsigned int* feed, unsigned int* post);
9static inline int PLL_calcclock(const struct matrox_fb_info *minfo,
10 unsigned int freq, unsigned int fmax,
11 unsigned int *in, unsigned int *feed,
12 unsigned int *post)
13{
14 return matroxfb_PLL_calcclock(&minfo->features.pll, freq, fmax, in, feed, post);
15}
16
17int matroxfb_vgaHWinit(struct matrox_fb_info *minfo, struct my_timming* m);
18void matroxfb_vgaHWrestore(struct matrox_fb_info *minfo);
19void matroxfb_read_pins(struct matrox_fb_info *minfo);
20
21#endif /* __MATROXFB_MISC_H__ */