diff options
| -rw-r--r-- | Documentation/fb/matroxfb.txt | 12 | ||||
| -rw-r--r-- | drivers/video/Config.help | 13 | ||||
| -rw-r--r-- | drivers/video/Config.in | 4 | ||||
| -rw-r--r-- | drivers/video/matrox/Makefile | 6 | ||||
| -rw-r--r-- | drivers/video/matrox/g450_pll.c | 472 | ||||
| -rw-r--r-- | drivers/video/matrox/g450_pll.h | 8 | ||||
| -rw-r--r-- | drivers/video/matrox/matroxfb_DAC1064.c | 346 | ||||
| -rw-r--r-- | drivers/video/matrox/matroxfb_DAC1064.h | 12 | ||||
| -rw-r--r-- | drivers/video/matrox/matroxfb_Ti3026.c | 67 | ||||
| -rw-r--r-- | drivers/video/matrox/matroxfb_base.c | 127 | ||||
| -rw-r--r-- | drivers/video/matrox/matroxfb_base.h | 94 | ||||
| -rw-r--r-- | drivers/video/matrox/matroxfb_crtc2.c | 26 | ||||
| -rw-r--r-- | drivers/video/matrox/matroxfb_g450.c | 128 | ||||
| -rw-r--r-- | drivers/video/matrox/matroxfb_maven.c | 16 | ||||
| -rw-r--r-- | drivers/video/matrox/matroxfb_misc.c | 361 | ||||
| -rw-r--r-- | drivers/video/matrox/matroxfb_misc.h | 5 |
16 files changed, 1329 insertions, 368 deletions
diff --git a/Documentation/fb/matroxfb.txt b/Documentation/fb/matroxfb.txt index 508aaa1878ef..1d0dd81dccde 100644 --- a/Documentation/fb/matroxfb.txt +++ b/Documentation/fb/matroxfb.txt @@ -10,7 +10,7 @@ Advantages: * It provides a nice large console (128 cols + 48 lines with 1024x768) without using tiny, unreadable fonts. - * You can run XF68_FBDev on top of /dev/fb0 + * You can run XF{68,86}_FBDev or XFree86 fbdev driver on top of /dev/fb0 * Most important: boot logo :-) Disadvantages: @@ -27,9 +27,6 @@ or using `fbset' program. If you want, for example, enable a resolution of 1280x1024x24bpp you should pass to the kernel this command line: "video=matrox:vesa:0x1BB". -Note that the same line, if 'appended' as a lilo parameter in lilo.conf will -read "video=matrox:vesa:443" because lilo pass integer parameters as decimal -numbers to the kernel. You should compile in both vgacon (to boot if you remove you Matrox from box) and matroxfb (for graphics mode). You should not compile-in vesafb @@ -82,13 +79,16 @@ example 1600x1200x32bpp can be specified by `video=matrox:vesa:0x11C,depth:32'. X11 === -XF68_FBDev should work just fine, but it is non-accelerated. On non-intel +XF{68,86}_FBDev should work just fine, but it is non-accelerated. On non-intel architectures there are some glitches for 24bpp videomodes. 8, 16 and 32bpp works fine. Running another (accelerated) X-Server like XF86_SVGA works too. But (at least) XFree servers have big troubles in multihead configurations (even on first -head, not even talking about second). +head, not even talking about second). Running XFree86 4.x accelerated mga +driver is possible, but you must not enable DRI - if you do, resolution and +color depth of your X desktop must match resolution and color depths of your +virtual consoles, otherwise X will corrupt accelerator settings. SVGALib diff --git a/drivers/video/Config.help b/drivers/video/Config.help index 1dcfd5b473ac..a3598e051049 100644 --- a/drivers/video/Config.help +++ b/drivers/video/Config.help @@ -381,8 +381,8 @@ CONFIG_FB_MATROX Say Y here if you have a Matrox Millennium, Matrox Millennium II, Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox Mystique G200, Matrox Millennium G200, Matrox Marvel G200 video, - Matrox G400 or G450 card in your box. At this time, support for the - G100 is untested and support for G450 is highly experimental. + Matrox G400, G450 or G550 card in your box. At this time, support for + the G-series digital output is almost non-existant. This driver is also available as a module ( = code which can be inserted and removed from the running kernel whenever you want). @@ -408,7 +408,7 @@ CONFIG_FB_MATROX_MYSTIQUE different from 8. CONFIG_FB_MATROX_G100 - Say Y here if you have a Matrox G100, G200, G400 or G450 based + Say Y here if you have a Matrox G100, G200, G400, G450 or G550 based video card. If you select "Advanced lowlevel driver options", you should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed pixel and 32 bpp packed pixel. You can also use font widths @@ -418,6 +418,10 @@ CONFIG_FB_MATROX_G100 "I2C support" and "I2C bit-banging support" in the character devices section, and then to "Matrox I2C support" and "G400 second head support" here in the framebuffer section. + + If you have G550, you must also compile support for G450/G550 secondary + head into kernel, otherwise picture will be shown only on output you + are probably not using... CONFIG_FB_MATROX_I2C This drivers creates I2C buses which are needed for accessing the @@ -462,7 +466,8 @@ CONFIG_FB_MATROX_MAVEN CONFIG_FB_MATROX_G450 Say Y or M here if you want to use a secondary head (meaning two - monitors in parallel) on G450. + monitors in parallel) on G450, or if you are using analog output + of G550. If you compile it as module, two modules are created, matroxfb_crtc2.o and matroxfb_g450.o. Both modules are needed if you diff --git a/drivers/video/Config.in b/drivers/video/Config.in index 1d92c99c2505..f5ce38ed128f 100644 --- a/drivers/video/Config.in +++ b/drivers/video/Config.in @@ -121,14 +121,14 @@ if [ "$CONFIG_FB" = "y" ]; then if [ "$CONFIG_FB_MATROX" != "n" ]; then bool ' Millennium I/II support' CONFIG_FB_MATROX_MILLENIUM bool ' Mystique support' CONFIG_FB_MATROX_MYSTIQUE - bool ' G100/G200/G400/G450 support' CONFIG_FB_MATROX_G100 + bool ' G100/G200/G400/G450/G550 support' CONFIG_FB_MATROX_G100 if [ "$CONFIG_I2C" != "n" ]; then dep_tristate ' Matrox I2C support' CONFIG_FB_MATROX_I2C $CONFIG_FB_MATROX $CONFIG_I2C_ALGOBIT if [ "$CONFIG_FB_MATROX_G100" = "y" ]; then dep_tristate ' G400 second head support' CONFIG_FB_MATROX_MAVEN $CONFIG_FB_MATROX_I2C fi fi - dep_tristate ' G450 second head support' CONFIG_FB_MATROX_G450 $CONFIG_FB_MATROX_G100 + dep_tristate ' G450/G550 second head support (mandatory for G550)' CONFIG_FB_MATROX_G450 $CONFIG_FB_MATROX_G100 bool ' Multihead support' CONFIG_FB_MATROX_MULTIHEAD fi tristate ' ATI Mach64 display support (EXPERIMENTAL)' CONFIG_FB_ATY diff --git a/drivers/video/matrox/Makefile b/drivers/video/matrox/Makefile index 2b7945150cbe..b34afde318de 100644 --- a/drivers/video/matrox/Makefile +++ b/drivers/video/matrox/Makefile @@ -7,11 +7,13 @@ O_TARGET := matrox.o # All of the (potential) objects that export symbols. # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. -export-objs := matroxfb_base.o matroxfb_accel.o matroxfb_DAC1064.o matroxfb_Ti3026.o matroxfb_misc.o +export-objs := matroxfb_base.o matroxfb_accel.o matroxfb_DAC1064.o matroxfb_Ti3026.o matroxfb_misc.o g450_pll.o # Each configuration option enables a list of files. -obj-$(CONFIG_FB_MATROX) += matroxfb_base.o matroxfb_accel.o matroxfb_DAC1064.o matroxfb_Ti3026.o matroxfb_misc.o +my-obj-$(CONFIG_FB_MATROX_G100) := g450_pll.o + +obj-$(CONFIG_FB_MATROX) += matroxfb_base.o matroxfb_accel.o matroxfb_DAC1064.o matroxfb_Ti3026.o matroxfb_misc.o $(my-obj-y) obj-$(CONFIG_FB_MATROX_I2C) += i2c-matroxfb.o obj-$(CONFIG_FB_MATROX_MAVEN) += matroxfb_maven.o matroxfb_crtc2.o obj-$(CONFIG_FB_MATROX_G450) += matroxfb_g450.o matroxfb_crtc2.o diff --git a/drivers/video/matrox/g450_pll.c b/drivers/video/matrox/g450_pll.c new file mode 100644 index 000000000000..2b7e81b08931 --- /dev/null +++ b/drivers/video/matrox/g450_pll.c @@ -0,0 +1,472 @@ +/* + * + * Hardware accelerated Matrox PCI cards - G450/G550 PLL control. + * + * (c) 2001 Petr Vandrovec <vandrove@vc.cvut.cz> + * + * Portions Copyright (c) 2001 Matrox Graphics Inc. + * + * Version: 1.62 2001/11/29 + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + */ + +#include "g450_pll.h" +#include "matroxfb_DAC1064.h" + +static inline unsigned int g450_vco2f(unsigned char p, unsigned int fvco) { + return (p & 0x40) ? fvco : fvco >> ((p & 3) + 1); +} + +static inline unsigned int g450_f2vco(unsigned char p, unsigned int fin) { + return (p & 0x40) ? fin : fin << ((p & 3) + 1); +} + +static unsigned int g450_mnp2vco(CPMINFO unsigned int mnp) { + unsigned int m, n; + + m = ((mnp >> 16) & 0x0FF) + 1; + n = ((mnp >> 7) & 0x1FE) + 4; + return (ACCESS_FBINFO(features).pll.ref_freq * n + (m >> 1)) / m; +} + +static inline unsigned int pll_freq_delta(unsigned int f1, unsigned int f2) { + if (f2 < f1) { + f2 = f1 - f2; + } else { + f2 = f2 - f1; + } + return f2; +} + +#define NO_MORE_MNP 0x01FFFFFF +#define G450_MNP_FREQBITS (0xFFFFFF43) /* do not mask high byte so we'll catch NO_MORE_MNP */ + +static unsigned int g450_nextpll(CPMINFO const struct matrox_pll_limits* pi, unsigned int* fvco, unsigned int mnp) { + unsigned int m, n, p; + unsigned int tvco = *fvco; + + m = (mnp >> 16) & 0xFF; + p = mnp & 0xFF; + + if (m == 0 || m == 0xFF) { + if (m == 0) { + if (p & 0x40) { + return NO_MORE_MNP; + } + if (p & 3) { + p--; + } else { + p = 0x40; + } + tvco >>= 1; + if (tvco < pi->vcomin) { + return NO_MORE_MNP; + } + *fvco = tvco; + } + + p &= 0x43; + if (tvco < 550000) { +/* p |= 0x00; */ + } else if (tvco < 700000) { + p |= 0x08; + } else if (tvco < 1000000) { + p |= 0x10; + } else if (tvco < 1150000) { + p |= 0x18; + } else { + p |= 0x20; + } + m = 9; + } else { + m--; + } + n = ((tvco * (m+1) + ACCESS_FBINFO(features).pll.ref_freq) / (ACCESS_FBINFO(features).pll.ref_freq * 2)) - 2; + return (m << 16) | (n << 8) | p; +} + +static unsigned int g450_firstpll(CPMINFO const struct matrox_pll_limits* pi, unsigned int* vco, unsigned int fout) { + unsigned int p; + unsigned int vcomax; + + vcomax = pi->vcomax; + if (fout > (vcomax / 2)) { + if (fout > vcomax) { + *vco = vcomax; + } else { + *vco = fout; + } + p = 0x40; + } else { + unsigned int tvco; + + p = 3; + tvco = g450_f2vco(p, fout); + while (p && (tvco > vcomax)) { + p--; + tvco >>= 1; + } + if (tvco < pi->vcomin) { + tvco = pi->vcomin; + } + *vco = tvco; + } + return g450_nextpll(PMINFO pi, vco, 0xFF0000 | p); +} + +static inline unsigned int g450_setpll(CPMINFO unsigned int mnp, unsigned int pll) { + switch (pll) { + case M_PIXEL_PLL_A: + matroxfb_DAC_out(PMINFO M1064_XPIXPLLAM, mnp >> 16); + matroxfb_DAC_out(PMINFO M1064_XPIXPLLAN, mnp >> 8); + matroxfb_DAC_out(PMINFO M1064_XPIXPLLAP, mnp); + return M1064_XPIXPLLSTAT; + + case M_PIXEL_PLL_B: + matroxfb_DAC_out(PMINFO M1064_XPIXPLLBM, mnp >> 16); + matroxfb_DAC_out(PMINFO M1064_XPIXPLLBN, mnp >> 8); + matroxfb_DAC_out(PMINFO M1064_XPIXPLLBP, mnp); + return M1064_XPIXPLLSTAT; + + case M_PIXEL_PLL_C: + matroxfb_DAC_out(PMINFO M1064_XPIXPLLCM, mnp >> 16); + matroxfb_DAC_out(PMINFO M1064_XPIXPLLCN, mnp >> 8); + matroxfb_DAC_out(PMINFO M1064_XPIXPLLCP, mnp); + return M1064_XPIXPLLSTAT; + + case M_SYSTEM_PLL: + matroxfb_DAC_out(PMINFO DAC1064_XSYSPLLM, mnp >> 16); + matroxfb_DAC_out(PMINFO DAC1064_XSYSPLLN, mnp >> 8); + matroxfb_DAC_out(PMINFO DAC1064_XSYSPLLP, mnp); + return DAC1064_XSYSPLLSTAT; + + case M_VIDEO_PLL: + matroxfb_DAC_out(PMINFO M1064_XVIDPLLM, mnp >> 16); + matroxfb_DAC_out(PMINFO M1064_XVIDPLLN, mnp >> 8); + matroxfb_DAC_out(PMINFO M1064_XVIDPLLP, mnp); + return M1064_XVIDPLLSTAT; + } + return 0; +} + +static inline unsigned int g450_cmppll(CPMINFO unsigned int mnp, unsigned int pll) { + unsigned char m = mnp >> 16; + unsigned char n = mnp >> 8; + unsigned char p = mnp; + + switch (pll) { + case M_PIXEL_PLL_A: + return (matroxfb_DAC_in(PMINFO M1064_XPIXPLLAM) != m || + matroxfb_DAC_in(PMINFO M1064_XPIXPLLAN) != n || + matroxfb_DAC_in(PMINFO M1064_XPIXPLLAP) != p); + + case M_PIXEL_PLL_B: + return (matroxfb_DAC_in(PMINFO M1064_XPIXPLLBM) != m || + matroxfb_DAC_in(PMINFO M1064_XPIXPLLBN) != n || + matroxfb_DAC_in(PMINFO M1064_XPIXPLLBP) != p); + + case M_PIXEL_PLL_C: + return (matroxfb_DAC_in(PMINFO M1064_XPIXPLLCM) != m || + matroxfb_DAC_in(PMINFO M1064_XPIXPLLCN) != n || + matroxfb_DAC_in(PMINFO M1064_XPIXPLLCP) != p); + + case M_SYSTEM_PLL: + return (matroxfb_DAC_in(PMINFO DAC1064_XSYSPLLM) != m || + matroxfb_DAC_in(PMINFO DAC1064_XSYSPLLN) != n || + matroxfb_DAC_in(PMINFO DAC1064_XSYSPLLP) != p); + + case M_VIDEO_PLL: + return (matroxfb_DAC_in(PMINFO M1064_XVIDPLLM) != m || + matroxfb_DAC_in(PMINFO M1064_XVIDPLLN) != n || + matroxfb_DAC_in(PMINFO M1064_XVIDPLLP) != p); + } + return 1; +} + +static inline int g450_isplllocked(CPMINFO unsigned int regidx) { + unsigned int j; + + for (j = 0; j < 1000; j++) { + if (matroxfb_DAC_in(PMINFO regidx) & 0x40) { + unsigned int r = 0; + int i; + + for (i = 0; i < 100; i++) { + r += matroxfb_DAC_in(PMINFO regidx) & 0x40; + } + return r >= (90 * 0x40); + } + /* udelay(1)... but DAC_in is much slower... */ + } + return 0; +} + +static int g450_testpll(CPMINFO unsigned int mnp, unsigned int pll) { + return g450_isplllocked(PMINFO g450_setpll(PMINFO mnp, pll)); +} + +static void updatehwstate_clk(struct matrox_hw_state* hw, unsigned int mnp, unsigned int pll) { + switch (pll) { + case M_SYSTEM_PLL: + hw->DACclk[3] = mnp >> 16; + hw->DACclk[4] = mnp >> 8; + hw->DACclk[5] = mnp; + break; + } +} + +static inline void g450_setpll_cond(WPMINFO unsigned int mnp, unsigned int pll) { + if (g450_cmppll(PMINFO mnp, pll)) { + g450_setpll(PMINFO mnp, pll); + } +} + +static inline unsigned int g450_findworkingpll(WPMINFO unsigned int pll, unsigned int* mnparray, unsigned int mnpcount) { + unsigned int found = 0; + unsigned int idx; + unsigned int mnpfound = mnparray[0]; + + for (idx = 0; idx < mnpcount; idx++) { + unsigned int sarray[3]; + unsigned int *sptr; + { + unsigned int mnp; + + sptr = sarray; + mnp = mnparray[idx]; + if (mnp & 0x38) { + *sptr++ = mnp - 8; + } + if ((mnp & 0x38) != 0x38) { + *sptr++ = mnp + 8; + } + *sptr = mnp; + } + while (sptr >= sarray) { + unsigned int mnp = *sptr--; + + if (g450_testpll(PMINFO mnp - 0x0300, pll) && + g450_testpll(PMINFO mnp + 0x0300, pll) && + g450_testpll(PMINFO mnp - 0x0200, pll) && + g450_testpll(PMINFO mnp + 0x0200, pll) && + g450_testpll(PMINFO mnp - 0x0100, pll) && + g450_testpll(PMINFO mnp + 0x0100, pll)) { + if (g450_testpll(PMINFO mnp, pll)) { + return mnp; + } + } else if (!found && g450_testpll(PMINFO mnp, pll)) { + mnpfound = mnp; + found = 1; + } + } + } + g450_setpll(PMINFO mnpfound, pll); + return mnpfound; +} + +static void g450_addcache(struct matrox_pll_cache* ci, unsigned int mnp_key, unsigned int mnp_value) { + if (++ci->valid > ARRAY_SIZE(ci->data)) { + ci->valid = ARRAY_SIZE(ci->data); + } + memmove(ci->data + 1, ci->data, (ci->valid - 1) * sizeof(*ci->data)); + ci->data[0].mnp_key = mnp_key & G450_MNP_FREQBITS; + ci->data[0].mnp_value = mnp_value; +} + +static int g450_checkcache(WPMINFO struct matrox_pll_cache* ci, unsigned int mnp_key) { + unsigned int i; + + mnp_key &= G450_MNP_FREQBITS; + for (i = 0; i < ci->valid; i++) { + if (ci->data[i].mnp_key == mnp_key) { + unsigned int mnp; + + mnp = ci->data[i].mnp_value; + if (i) { + memmove(ci->data + 1, ci->data, i * sizeof(*ci->data)); + ci->data[0].mnp_key = mnp_key; + ci->data[0].mnp_value = mnp; + } + return mnp; + } + } + return NO_MORE_MNP; +} + +static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll, + unsigned int* mnparray, unsigned int* deltaarray) { + unsigned int mnpcount; + unsigned int pixel_vco; + const struct matrox_pll_limits* pi; + struct matrox_pll_cache* ci; + + pixel_vco = 0; + switch (pll) { + case M_PIXEL_PLL_A: + case M_PIXEL_PLL_B: + case M_PIXEL_PLL_C: + { + u_int8_t tmp; + unsigned long flags; + + matroxfb_DAC_lock_irqsave(flags); + tmp = matroxfb_DAC_in(PMINFO M1064_XPIXCLKCTRL); + if (!(tmp & M1064_XPIXCLKCTRL_PLL_UP)) { + matroxfb_DAC_out(PMINFO M1064_XPIXCLKCTRL, tmp | M1064_XPIXCLKCTRL_PLL_UP); + } + matroxfb_DAC_unlock_irqrestore(flags); + } + { + u_int8_t misc; + + misc = mga_inb(M_MISC_REG_READ) & ~0x0C; + switch (pll) { + case M_PIXEL_PLL_A: + break; + case M_PIXEL_PLL_B: + misc |= 0x04; + break; + default: + misc |= 0x0C; + break; + } + mga_outb(M_MISC_REG, misc); + } + pi = &ACCESS_FBINFO(limits.pixel); + ci = &ACCESS_FBINFO(cache.pixel); + break; + case M_SYSTEM_PLL: + { + u_int32_t opt; + + pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, &opt); + if (!(opt & 0x20)) { + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, opt | 0x20); + } + } + pi = &ACCESS_FBINFO(limits.system); + ci = &ACCESS_FBINFO(cache.system); + break; + case M_VIDEO_PLL: + { + u_int8_t tmp; + unsigned int mnp; + unsigned long flags; + + matroxfb_DAC_lock_irqsave(flags); + tmp = matroxfb_DAC_in(PMINFO M1064_XPWRCTRL); + if (!(tmp & 2)) { + matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, tmp | 2); + } + + mnp = matroxfb_DAC_in(PMINFO M1064_XPIXPLLCM) << 16; + mnp |= matroxfb_DAC_in(PMINFO M1064_XPIXPLLCN) << 8; + pixel_vco = g450_mnp2vco(PMINFO mnp); + matroxfb_DAC_unlock_irqrestore(flags); + } + pi = &ACCESS_FBINFO(limits.video); + ci = &ACCESS_FBINFO(cache.video); + break; + default: + return -EINVAL; + } + + mnpcount = 0; + { + unsigned int mnp; + unsigned int xvco; + + for(mnp = g450_firstpll(PMINFO pi, &xvco, fout); mnp != NO_MORE_MNP; mnp = g450_nextpll(PMINFO pi, &xvco, mnp)) { + unsigned int idx; + unsigned int vco; + unsigned int delta; + + if ((mnp & 0xFF00) < 0x0300 || (mnp & 0xFF00) > 0x7A00) { + continue; + } + vco = g450_mnp2vco(PMINFO mnp); + if (pll == M_VIDEO_PLL) { + unsigned int big, small; + + if (vco < pixel_vco) { + small = vco; + big = pixel_vco; + } else { + small = pixel_vco; + big = vco; + } + while (big > small) { + big >>= 1; + } + if (big == small) { + continue; + } + } + delta = pll_freq_delta(fout, g450_vco2f(mnp, vco)); + for (idx = mnpcount; idx > 0; idx--) { + /* == is important; due to nextpll algorithm we get + sorted equally good frequencies from lower VCO + frequency to higher - with <= lowest wins, while + with < highest one wins */ + if (delta <= deltaarray[idx-1]) { + mnparray[idx] = mnparray[idx-1]; + deltaarray[idx] = deltaarray[idx-1]; + } else { + break; + } + } + mnparray[idx] = mnp; + deltaarray[idx] = delta; + mnpcount++; + } + } + /* VideoPLL and PixelPLL matched: do nothing... In all other cases we should get at least one frequency */ + if (!mnpcount) { + return 1; + } + { + unsigned long flags; + unsigned int mnp; + + matroxfb_DAC_lock_irqsave(flags); + mnp = g450_checkcache(PMINFO ci, mnparray[0]); + if (mnp != NO_MORE_MNP) { + g450_setpll_cond(PMINFO mnp, pll); + } else { + mnp = g450_findworkingpll(PMINFO pll, mnparray, mnpcount); + g450_addcache(ci, mnparray[0], mnp); + } + updatehwstate_clk(&ACCESS_FBINFO(hw), mnp, pll); + matroxfb_DAC_unlock_irqrestore(flags); + } + return 0; +} + +/* It must be greater than number of possible PLL values. + * Currently there is 5(p) * 10(m) = 50 possible values. */ +#define MNP_TABLE_SIZE 64 + +int matroxfb_g450_setclk(WPMINFO unsigned int fout, unsigned int pll) { + unsigned int* arr; + + arr = kmalloc(sizeof(*arr) * MNP_TABLE_SIZE * 2, GFP_KERNEL); + if (arr) { + int r; + + r = __g450_setclk(PMINFO fout, pll, arr, arr + MNP_TABLE_SIZE); + kfree(arr); + return r; + } + return -ENOMEM; +} + +EXPORT_SYMBOL(matroxfb_g450_setclk); + +MODULE_AUTHOR("(c) 2001 Petr Vandrovec <vandrove@vc.cvut.cz>"); +MODULE_DESCRIPTION("Matrox G450/G550 PLL driver"); + +MODULE_LICENSE("GPL"); diff --git a/drivers/video/matrox/g450_pll.h b/drivers/video/matrox/g450_pll.h new file mode 100644 index 000000000000..58a80ef2fd76 --- /dev/null +++ b/drivers/video/matrox/g450_pll.h @@ -0,0 +1,8 @@ +#ifndef __G450_PLL_H__ +#define __G450_PLL_H__ + +#include "matroxfb_base.h" + +int matroxfb_g450_setclk(WPMINFO unsigned int fout, unsigned int pll); + +#endif /* __G450_PLL_H__ */ diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/matrox/matroxfb_DAC1064.c index b0a12c07e1eb..ad5dfb1a1074 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.c +++ b/drivers/video/matrox/matroxfb_DAC1064.c @@ -4,7 +4,9 @@ * * (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz> * - * Version: 1.54 2001/09/09 + * Portions Copyright (c) 2001 Matrox Graphics Inc. + * + * Version: 1.62 2001/11/29 * * See matroxfb_base.c for contributors. * @@ -16,6 +18,7 @@ #include "matroxfb_DAC1064.h" #include "matroxfb_misc.h" #include "matroxfb_accel.h" +#include "g450_pll.h" #include <linux/matroxfb.h> #ifdef NEED_DAC1064 @@ -217,19 +220,20 @@ static const unsigned char MGA1064_DAC[] = { 0x00, 0x00, 0x00, 0xFF, 0xFF}; -static void DAC1064_setpclk(CPMINFO struct matrox_hw_state* hw, unsigned long fout) { +static void DAC1064_setpclk(WPMINFO unsigned long fout) { unsigned int m, n, p; DBG("DAC1064_setpclk") DAC1064_calcclock(PMINFO fout, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p); - hw->DACclk[0] = m; - hw->DACclk[1] = n; - hw->DACclk[2] = p; + ACCESS_FBINFO(hw).DACclk[0] = m; + ACCESS_FBINFO(hw).DACclk[1] = n; + ACCESS_FBINFO(hw).DACclk[2] = p; } -static void DAC1064_setmclk(CPMINFO struct matrox_hw_state* hw, int oscinfo, unsigned long fmem){ +static void DAC1064_setmclk(WPMINFO int oscinfo, unsigned long fmem) { u_int32_t mx; + struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); DBG("DAC1064_setmclk") @@ -289,7 +293,9 @@ static void DAC1064_setmclk(CPMINFO struct matrox_hw_state* hw, int oscinfo, uns hw->MXoptionReg = mx; } -void DAC1064_global_init(CPMINFO struct matrox_hw_state* hw) { +void DAC1064_global_init(WPMINFO2) { + struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); + hw->DACreg[POS1064_XMISCCTRL] &= M1064_XMISCCTRL_DAC_WIDTHMASK; hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_LUT_EN; hw->DACreg[POS1064_XPIXCLKCTRL] = M1064_XPIXCLKCTRL_PLL_UP | M1064_XPIXCLKCTRL_EN | M1064_XPIXCLKCTRL_SRC_PLL; @@ -314,7 +320,9 @@ void DAC1064_global_init(CPMINFO struct matrox_hw_state* hw) { hw->DACreg[POS1064_XMISCCTRL] |= M1064_XMISCCTRL_DAC_EN; } -void DAC1064_global_restore(CPMINFO const struct matrox_hw_state* hw) { +void DAC1064_global_restore(WPMINFO2) { + struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); + outDAC1064(PMINFO M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]); outDAC1064(PMINFO M1064_XMISCCTRL, hw->DACreg[POS1064_XMISCCTRL]); if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) { @@ -328,7 +336,9 @@ void DAC1064_global_restore(CPMINFO const struct matrox_hw_state* hw) { } } -static int DAC1064_init_1(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display *p) { +static int DAC1064_init_1(WPMINFO struct my_timming* m, struct display *p) { + struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); + DBG("DAC1064_init_1") memcpy(hw->DACreg, MGA1064_DAC, sizeof(MGA1064_DAC_regs)); @@ -359,7 +369,7 @@ static int DAC1064_init_1(CPMINFO struct matrox_hw_state* hw, struct my_timming* } } - DAC1064_global_init(PMINFO hw); + DAC1064_global_init(PMINFO2); hw->DACreg[POS1064_XVREFCTRL] = ACCESS_FBINFO(features.DAC1064.xvrefctrl); hw->DACreg[POS1064_XGENCTRL] &= ~M1064_XGENCTRL_SYNC_ON_GREEN_MASK; hw->DACreg[POS1064_XGENCTRL] |= (m->sync & FB_SYNC_ON_GREEN)?M1064_XGENCTRL_SYNC_ON_GREEN:M1064_XGENCTRL_NO_SYNC_ON_GREEN; @@ -368,7 +378,8 @@ static int DAC1064_init_1(CPMINFO struct matrox_hw_state* hw, struct my_timming* return 0; } -static int DAC1064_init_2(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) { +static int DAC1064_init_2(WPMINFO struct my_timming* m, struct display* p) { + struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); DBG("DAC1064_init_2") @@ -409,21 +420,22 @@ static int DAC1064_init_2(CPMINFO struct matrox_hw_state* hw, struct my_timming* return 0; } -static void DAC1064_restore_1(WPMINFO const struct matrox_hw_state* hw, const struct matrox_hw_state* oldhw) { +static void DAC1064_restore_1(WPMINFO2) { + struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); + CRITFLAGS DBG("DAC1064_restore_1") CRITBEGIN - outDAC1064(PMINFO DAC1064_XSYSPLLM, hw->DACclk[3]); - outDAC1064(PMINFO DAC1064_XSYSPLLN, hw->DACclk[4]); - outDAC1064(PMINFO DAC1064_XSYSPLLP, hw->DACclk[5]); - /* - * We must ALWAYS reprogram hardware due to broken XF4 matrox drivers... - * - * if (!oldhw || memcmp(hw->DACreg, oldhw->DACreg, sizeof(MGA1064_DAC_regs))) - */ + if ((inDAC1064(PMINFO DAC1064_XSYSPLLM) != hw->DACclk[3]) || + (inDAC1064(PMINFO DAC1064_XSYSPLLN) != hw->DACclk[4]) || + (inDAC1064(PMINFO DAC1064_XSYSPLLP) != hw->DACclk[5])) { + outDAC1064(PMINFO DAC1064_XSYSPLLM, hw->DACclk[3]); + outDAC1064(PMINFO DAC1064_XSYSPLLN, hw->DACclk[4]); + outDAC1064(PMINFO DAC1064_XSYSPLLP, hw->DACclk[5]); + } { unsigned int i; @@ -433,12 +445,12 @@ static void DAC1064_restore_1(WPMINFO const struct matrox_hw_state* hw, const st } } - DAC1064_global_restore(PMINFO hw); + DAC1064_global_restore(PMINFO2); CRITEND }; -static void DAC1064_restore_2(WPMINFO const struct matrox_hw_state* hw, const struct matrox_hw_state* oldhw, struct display* p) { +static void DAC1064_restore_2(WPMINFO struct display* p) { #ifdef DEBUG unsigned int i; #endif @@ -449,48 +461,51 @@ static void DAC1064_restore_2(WPMINFO const struct matrox_hw_state* hw, const st #ifdef DEBUG dprintk(KERN_DEBUG "DAC1064regs "); for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) { - dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], hw->DACreg[i]); + dprintk("R%02X=%02X ", MGA1064_DAC_regs[i], ACCESS_FBINFO(hw).DACreg[i]); if ((i & 0x7) == 0x7) dprintk("\n" KERN_DEBUG "continuing... "); } dprintk("\n" KERN_DEBUG "DAC1064clk "); for (i = 0; i < 6; i++) - dprintk("C%02X=%02X ", i, hw->DACclk[i]); + dprintk("C%02X=%02X ", i, ACCESS_FBINFO(hw).DACclk[i]); dprintk("\n"); #endif } -static int m1064_compute(void* outdev, struct my_timming* m, struct matrox_hw_state* hw) { -#define minfo ((struct matrox_fb_info*)outdev) - DAC1064_setpclk(PMINFO hw, m->pixclock); -#undef minfo - return 0; -} - -static int m1064_program(void* outdev, const struct matrox_hw_state* hw) { +static int m1064_compute(void* outdev, struct my_timming* m) { #define minfo ((struct matrox_fb_info*)outdev) - int i; - int tmout; - CRITFLAGS + if (ACCESS_FBINFO(devflags.g450dac)) { + matroxfb_g450_setclk(PMINFO m->pixclock, M_PIXEL_PLL_C); + } else { + int i; + int tmout; + CRITFLAGS - CRITBEGIN + DAC1064_setpclk(PMINFO m->pixclock); - for (i = 0; i < 3; i++) - outDAC1064(PMINFO M1064_XPIXPLLCM + i, hw->DACclk[i]); - for (tmout = 500000; tmout; tmout--) { - if (inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40) - break; - udelay(10); - }; + CRITBEGIN - CRITEND + for (i = 0; i < 3; i++) + outDAC1064(PMINFO M1064_XPIXPLLCM + i, ACCESS_FBINFO(hw).DACclk[i]); + for (tmout = 500000; tmout; tmout--) { + if (inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40) + break; + udelay(10); + }; - if (!tmout) - printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n"); + CRITEND + if (!tmout) + printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n"); + } #undef minfo return 0; } +static int m1064_program(void* outdev) { + /* nothing, hardware is set in m1064_compute */ + return 0; +} + static int m1064_start(void* outdev) { /* nothing */ return 0; @@ -522,12 +537,13 @@ static struct matrox_altout m1064 = { #endif /* NEED_DAC1064 */ #ifdef CONFIG_FB_MATROX_MYSTIQUE -static int MGA1064_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) { +static int MGA1064_init(WPMINFO struct my_timming* m, struct display* p) { + struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); DBG("MGA1064_init") - if (DAC1064_init_1(PMINFO hw, m, p)) return 1; - if (matroxfb_vgaHWinit(PMINFO hw, m, p)) return 1; + if (DAC1064_init_1(PMINFO m, p)) return 1; + if (matroxfb_vgaHWinit(PMINFO m, p)) return 1; hw->MiscOutReg = 0xCB; if (m->sync & FB_SYNC_HOR_HIGH_ACT) @@ -537,19 +553,20 @@ static int MGA1064_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */ hw->CRTCEXT[3] |= 0x40; - if (DAC1064_init_2(PMINFO hw, m, p)) return 1; + if (DAC1064_init_2(PMINFO m, p)) return 1; return 0; } #endif #ifdef CONFIG_FB_MATROX_G100 -static int MGAG100_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) { +static int MGAG100_init(WPMINFO struct my_timming* m, struct display* p) { + struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); DBG("MGAG100_init") - if (DAC1064_init_1(PMINFO hw, m, p)) return 1; + if (DAC1064_init_1(PMINFO m, p)) return 1; hw->MXoptionReg &= ~0x2000; - if (matroxfb_vgaHWinit(PMINFO hw, m, p)) return 1; + if (matroxfb_vgaHWinit(PMINFO m, p)) return 1; hw->MiscOutReg = 0xEF; if (m->sync & FB_SYNC_HOR_HIGH_ACT) @@ -559,13 +576,13 @@ static int MGAG100_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */ hw->CRTCEXT[3] |= 0x40; - if (DAC1064_init_2(PMINFO hw, m, p)) return 1; + if (DAC1064_init_2(PMINFO m, p)) return 1; return 0; } #endif /* G100 */ #ifdef CONFIG_FB_MATROX_MYSTIQUE -static void MGA1064_ramdac_init(WPMINFO struct matrox_hw_state* hw){ +static void MGA1064_ramdac_init(WPMINFO2) { DBG("MGA1064_ramdac_init"); @@ -579,7 +596,7 @@ static void MGA1064_ramdac_init(WPMINFO struct matrox_hw_state* hw){ ACCESS_FBINFO(features.pll.post_shift_max) = 3; ACCESS_FBINFO(features.DAC1064.xvrefctrl) = DAC1064_XVREFCTRL_EXTERNAL; /* maybe cmdline MCLK= ?, doc says gclk=44MHz, mclk=66MHz... it was 55/83 with old values */ - DAC1064_setmclk(PMINFO hw, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PLL, 133333); + DAC1064_setmclk(PMINFO DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PLL, 133333); } #endif @@ -591,7 +608,7 @@ static int x7AF4 = 0x10; /* flags, maybe 0x10 = SDRAM, 0x00 = SGRAM??? */ static int def50 = 0; /* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */ #endif -static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p){ +static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p) { int reg; int selClk; int clk; @@ -635,7 +652,7 @@ static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p){ outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_DIS); } -static void MGAG100_setPixClock(CPMINFO int flags, int freq){ +static void MGAG100_setPixClock(CPMINFO int flags, int freq) { unsigned int m, n, p; DBG("MGAG100_setPixClock") @@ -646,10 +663,12 @@ static void MGAG100_setPixClock(CPMINFO int flags, int freq){ #endif #ifdef CONFIG_FB_MATROX_MYSTIQUE -static int MGA1064_preinit(WPMINFO struct matrox_hw_state* hw){ +static int MGA1064_preinit(WPMINFO2) { static const int vxres_mystique[] = { 512, 640, 768, 800, 832, 960, 1024, 1152, 1280, 1600, 1664, 1920, 2048, 0}; + struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); + DBG("MGA1064_preinit") /* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */ @@ -680,7 +699,7 @@ static int MGA1064_preinit(WPMINFO struct matrox_hw_state* hw){ return 0; } -static void MGA1064_reset(WPMINFO struct matrox_hw_state* hw){ +static void MGA1064_reset(WPMINFO2) { DBG("MGA1064_reset"); @@ -688,15 +707,130 @@ static void MGA1064_reset(WPMINFO struct matrox_hw_state* hw){ if (ACCESS_FBINFO(devflags.hwcursor)) ACCESS_FBINFO(video.len_usable) -= 1024; matroxfb_fastfont_init(MINFO); - MGA1064_ramdac_init(PMINFO hw); + MGA1064_ramdac_init(PMINFO2); } #endif #ifdef CONFIG_FB_MATROX_G100 -static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw){ +static void g450_mclk_init(WPMINFO2) { + /* switch all clocks to PCI source */ + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg | 4); + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION3_REG, ACCESS_FBINFO(values).reg.opt3 & ~0x00300C03); + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); + + if (((ACCESS_FBINFO(values).reg.opt3 & 0x000003) == 0x000003) || + ((ACCESS_FBINFO(values).reg.opt3 & 0x000C00) == 0x000C00) || + ((ACCESS_FBINFO(values).reg.opt3 & 0x300000) == 0x300000)) { + matroxfb_g450_setclk(PMINFO ACCESS_FBINFO(values.pll.video), M_VIDEO_PLL); + } else { + /* slow down video clocks... */ + matroxfb_g450_setclk(PMINFO 0, M_VIDEO_PLL); + } + matroxfb_g450_setclk(PMINFO ACCESS_FBINFO(values.pll.system), M_SYSTEM_PLL); + + /* switch clocks to their real PLL source(s) */ + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg | 4); + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION3_REG, ACCESS_FBINFO(values).reg.opt3); + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); + +} + +static void g450_memory_init(WPMINFO2) { + /* disable memory refresh */ + ACCESS_FBINFO(hw).MXoptionReg &= ~0x001F8000; + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); + + /* set memory interface parameters */ + ACCESS_FBINFO(hw).MXoptionReg &= ~0x00207E00; + ACCESS_FBINFO(hw).MXoptionReg |= 0x00207E00 & ACCESS_FBINFO(values).reg.opt; + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, ACCESS_FBINFO(values).reg.opt2); + + mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst); + + /* first set up memory interface with disabled memory interface clocks */ + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_MEMMISC_REG, ACCESS_FBINFO(values).reg.memmisc & ~0x80000000U); + mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk); + mga_outl(M_MACCESS, ACCESS_FBINFO(values).reg.maccess); + /* start memory clocks */ + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_MEMMISC_REG, ACCESS_FBINFO(values).reg.memmisc | 0x80000000U); + + udelay(200); + + if (ACCESS_FBINFO(values).memory.ddr && (!ACCESS_FBINFO(values).memory.emrswen || !ACCESS_FBINFO(values).memory.dll)) { + mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk & ~0x1000); + } + mga_outl(M_MACCESS, ACCESS_FBINFO(values).reg.maccess | 0x8000); + + udelay(200); + + ACCESS_FBINFO(hw).MXoptionReg |= 0x001F8000 & ACCESS_FBINFO(values).reg.opt; + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); + + /* value is written to memory chips only if old != new */ + mga_outl(M_PLNWT, 0); + mga_outl(M_PLNWT, ~0); + + if (ACCESS_FBINFO(values).reg.mctlwtst != ACCESS_FBINFO(values).reg.mctlwtst_core) { + mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst_core); + } + +} + +static void g450_preinit(WPMINFO2) { + u_int32_t c2ctl; + u_int8_t curctl; + u_int8_t c1ctl; + + /* ACCESS_FBINFO(hw).MXoptionReg = minfo->values.reg.opt; */ + ACCESS_FBINFO(hw).MXoptionReg &= 0xC0000100; + ACCESS_FBINFO(hw).MXoptionReg |= 0x00000020; + if (ACCESS_FBINFO(devflags.novga)) + ACCESS_FBINFO(hw).MXoptionReg &= ~0x00000100; + if (ACCESS_FBINFO(devflags.nobios)) + ACCESS_FBINFO(hw).MXoptionReg &= ~0x40000000; + if (ACCESS_FBINFO(devflags.nopciretry)) + ACCESS_FBINFO(hw).MXoptionReg |= 0x20000000; + ACCESS_FBINFO(hw).MXoptionReg |= ACCESS_FBINFO(values).reg.opt & 0x03400040; + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); + + /* Init system clocks */ + + /* stop crtc2 */ + c2ctl = mga_inl(M_C2CTL); + mga_outl(M_C2CTL, c2ctl & ~1); + /* stop cursor */ + curctl = inDAC1064(PMINFO M1064_XCURCTRL); + outDAC1064(PMINFO M1064_XCURCTRL, 0); + /* stop crtc1 */ + c1ctl = mga_readr(M_SEQ_INDEX, 1); + mga_setr(M_SEQ_INDEX, 1, c1ctl | 0x20); + + g450_mclk_init(PMINFO2); + g450_memory_init(PMINFO2); + + /* set legacy VGA clock sources for DOSEmu or VMware... */ + matroxfb_g450_setclk(PMINFO 25175, M_PIXEL_PLL_A); + matroxfb_g450_setclk(PMINFO 28322, M_PIXEL_PLL_B); + + /* restore crtc1 */ + mga_setr(M_SEQ_INDEX, 1, c1ctl); + + /* restore cursor */ + outDAC1064(PMINFO M1064_XCURCTRL, curctl); + + /* restore crtc2 */ + mga_outl(M_C2CTL, c2ctl); + + return; +} + +static int MGAG100_preinit(WPMINFO2) { static const int vxres_g100[] = { 512, 640, 768, 800, 832, 960, 1024, 1152, 1280, 1600, 1664, 1920, 2048, 0}; + struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); + u_int32_t reg50; #if 0 u_int32_t q; @@ -710,7 +844,9 @@ static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw){ } else { ACCESS_FBINFO(features.pll.vco_freq_min) = 62000; } - ACCESS_FBINFO(features.pll.ref_freq) = 27000; + if (!ACCESS_FBINFO(features.pll.ref_freq)) { + ACCESS_FBINFO(features.pll.ref_freq) = 27000; + } ACCESS_FBINFO(features.pll.feed_div_min) = 7; ACCESS_FBINFO(features.pll.feed_div_max) = 127; ACCESS_FBINFO(features.pll.in_div_min) = 1; @@ -734,6 +870,10 @@ static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw){ } if (ACCESS_FBINFO(devflags.noinit)) return 0; + if (ACCESS_FBINFO(devflags.g450dac)) { + g450_preinit(PMINFO2); + return 0; + } hw->MXoptionReg &= 0xC0000100; hw->MXoptionReg |= 0x00000020; if (ACCESS_FBINFO(devflags.novga)) @@ -743,12 +883,12 @@ static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw){ if (ACCESS_FBINFO(devflags.nopciretry)) hw->MXoptionReg |= 0x20000000; pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); - DAC1064_setmclk(PMINFO hw, DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PCI, 133333); + DAC1064_setmclk(PMINFO DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV3 | DAC1064_OPT_SCLK_PCI, 133333); if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100) { - pci_read_config_dword(ACCESS_FBINFO(pcidev), 0x50, ®50); + pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, ®50); reg50 &= ~0x3000; - pci_write_config_dword(ACCESS_FBINFO(pcidev), 0x50, reg50); + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50); hw->MXoptionReg |= 0x1080; pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); @@ -763,7 +903,7 @@ static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw){ udelay(100); reg50 &= ~0xFF; reg50 |= 0x07; - pci_write_config_dword(ACCESS_FBINFO(pcidev), 0x50, reg50); + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50); /* it should help with G100 */ mga_outb(M_GRAPHICS_INDEX, 6); mga_outb(M_GRAPHICS_DATA, (mga_inb(M_GRAPHICS_DATA) & 3) | 4); @@ -778,29 +918,30 @@ static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw){ } #endif hw->MXoptionReg |= 0x00078020; - } else if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG200) { - pci_read_config_dword(ACCESS_FBINFO(pcidev), 0x50, ®50); + } else if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG200) { + pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, ®50); reg50 &= ~0x3000; - pci_write_config_dword(ACCESS_FBINFO(pcidev), 0x50, reg50); + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50); if (ACCESS_FBINFO(devflags.memtype) == -1) - ACCESS_FBINFO(devflags.memtype) = 3; - hw->MXoptionReg |= (ACCESS_FBINFO(devflags.memtype) & 7) << 10; + hw->MXoptionReg |= ACCESS_FBINFO(values).reg.opt & 0x1C00; + else + hw->MXoptionReg |= (ACCESS_FBINFO(devflags.memtype) & 7) << 10; if (ACCESS_FBINFO(devflags.sgram)) hw->MXoptionReg |= 0x4000; - mga_outl(M_CTLWTST, 0x042450A1); - mga_outl(M_MEMRDBK, 0x00000108); + mga_outl(M_CTLWTST, ACCESS_FBINFO(values).reg.mctlwtst); + mga_outl(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk); udelay(200); mga_outl(M_MACCESS, 0x00000000); mga_outl(M_MACCESS, 0x00008000); udelay(100); - mga_outw(M_MEMRDBK, 0x00000108); + mga_outw(M_MEMRDBK, ACCESS_FBINFO(values).reg.memrdbk); hw->MXoptionReg |= 0x00078020; } else { - pci_read_config_dword(ACCESS_FBINFO(pcidev), 0x50, ®50); + pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, ®50); reg50 &= ~0x00000100; reg50 |= 0x00000000; - pci_write_config_dword(ACCESS_FBINFO(pcidev), 0x50, reg50); + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, reg50); if (ACCESS_FBINFO(devflags.memtype) == -1) ACCESS_FBINFO(devflags.memtype) = 0; @@ -820,8 +961,9 @@ static int MGAG100_preinit(WPMINFO struct matrox_hw_state* hw){ return 0; } -static void MGAG100_reset(WPMINFO struct matrox_hw_state* hw){ +static void MGAG100_reset(WPMINFO2) { u_int8_t b; + struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); DBG("MGAG100_reset") @@ -845,13 +987,20 @@ static void MGAG100_reset(WPMINFO struct matrox_hw_state* hw){ #endif if (!ACCESS_FBINFO(devflags.noinit)) { if (x7AF4 & 8) { - hw->MXoptionReg |= 0x40; + hw->MXoptionReg |= 0x40; /* FIXME... */ pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); } mga_setr(M_EXTVGA_INDEX, 0x06, 0x50); } } - DAC1064_setmclk(PMINFO hw, DAC1064_OPT_RESERVED | DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV1 | DAC1064_OPT_SCLK_PLL, 133333); + if (ACCESS_FBINFO(devflags.g450dac)) { + /* either leave MCLK as is... or they were set in preinit */ + hw->DACclk[3] = inDAC1064(PMINFO DAC1064_XSYSPLLM); + hw->DACclk[4] = inDAC1064(PMINFO DAC1064_XSYSPLLN); + hw->DACclk[5] = inDAC1064(PMINFO DAC1064_XSYSPLLP); + } else { + DAC1064_setmclk(PMINFO DAC1064_OPT_RESERVED | DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV1 | DAC1064_OPT_SCLK_PLL, 133333); + } if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG400) { if (ACCESS_FBINFO(devflags.dfp_type) == -1) { ACCESS_FBINFO(devflags.dfp_type) = inDAC1064(PMINFO 0x1F); @@ -859,20 +1008,25 @@ static void MGAG100_reset(WPMINFO struct matrox_hw_state* hw){ } if (ACCESS_FBINFO(devflags.noinit)) return; - MGAG100_setPixClock(PMINFO 4, 25175); - MGAG100_setPixClock(PMINFO 5, 28322); - if (x7AF4 & 0x10) { - b = inDAC1064(PMINFO M1064_XGENIODATA) & ~1; - outDAC1064(PMINFO M1064_XGENIODATA, b); - b = inDAC1064(PMINFO M1064_XGENIOCTRL) | 1; - outDAC1064(PMINFO M1064_XGENIOCTRL, b); + if (ACCESS_FBINFO(devflags.g450dac)) { + } else { + MGAG100_setPixClock(PMINFO 4, 25175); + MGAG100_setPixClock(PMINFO 5, 28322); + if (x7AF4 & 0x10) { + b = inDAC1064(PMINFO M1064_XGENIODATA) & ~1; + outDAC1064(PMINFO M1064_XGENIODATA, b); + b = inDAC1064(PMINFO M1064_XGENIOCTRL) | 1; + outDAC1064(PMINFO M1064_XGENIOCTRL, b); + } } } #endif #ifdef CONFIG_FB_MATROX_MYSTIQUE -static void MGA1064_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_state* oldhw, struct display* p) { +static void MGA1064_restore(WPMINFO struct display* p) { int i; + struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); + CRITFLAGS DBG("MGA1064_restore") @@ -885,17 +1039,19 @@ static void MGA1064_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw CRITEND - DAC1064_restore_1(PMINFO hw, oldhw); - matroxfb_vgaHWrestore(PMINFO hw, oldhw); + DAC1064_restore_1(PMINFO2); + matroxfb_vgaHWrestore(PMINFO2); for (i = 0; i < 6; i++) mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]); - DAC1064_restore_2(PMINFO hw, oldhw, p); + DAC1064_restore_2(PMINFO p); } #endif #ifdef CONFIG_FB_MATROX_G100 -static void MGAG100_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_state* oldhw, struct display* p) { +static void MGAG100_restore(WPMINFO struct display* p) { int i; + struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); + CRITFLAGS DBG("MGAG100_restore") @@ -905,15 +1061,15 @@ static void MGAG100_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); CRITEND - DAC1064_restore_1(PMINFO hw, oldhw); - matroxfb_vgaHWrestore(PMINFO hw, oldhw); + DAC1064_restore_1(PMINFO2); + matroxfb_vgaHWrestore(PMINFO2); #ifdef CONFIG_FB_MATROX_32MB if (ACCESS_FBINFO(devflags.support32MB)) mga_setr(M_EXTVGA_INDEX, 8, hw->CRTCEXT[8]); #endif for (i = 0; i < 6; i++) mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]); - DAC1064_restore_2(PMINFO hw, oldhw, p); + DAC1064_restore_2(PMINFO p); } #endif diff --git a/drivers/video/matrox/matroxfb_DAC1064.h b/drivers/video/matrox/matroxfb_DAC1064.h index 62cde7919e9d..6136fd33a14b 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.h +++ b/drivers/video/matrox/matroxfb_DAC1064.h @@ -13,8 +13,8 @@ extern struct matrox_switch matrox_mystique; extern struct matrox_switch matrox_G100; #endif #ifdef NEED_DAC1064 -void DAC1064_global_init(CPMINFO struct matrox_hw_state*); -void DAC1064_global_restore(CPMINFO const struct matrox_hw_state*); +void DAC1064_global_init(WPMINFO2); +void DAC1064_global_restore(WPMINFO2); #endif #define M1064_INDEX 0x00 @@ -139,10 +139,10 @@ void DAC1064_global_restore(CPMINFO const struct matrox_hw_state*); #define M1064_XOUTPUTCONN 0x8A #define M1064_XSYNCCTRL 0x8B -#define M1064_XPIXPLL2STAT 0x8C -#define M1064_XPIXPLL2P 0x8D -#define M1064_XPIXPLL2N 0x8E -#define M1064_XPIXPLL2M 0x8F +#define M1064_XVIDPLLSTAT 0x8C +#define M1064_XVIDPLLP 0x8D +#define M1064_XVIDPLLM 0x8E +#define M1064_XVIDPLLN 0x8F #define M1064_XPWRCTRL 0xA0 diff --git a/drivers/video/matrox/matroxfb_Ti3026.c b/drivers/video/matrox/matroxfb_Ti3026.c index 16f1e7653a82..57b37600a3cb 100644 --- a/drivers/video/matrox/matroxfb_Ti3026.c +++ b/drivers/video/matrox/matroxfb_Ti3026.c @@ -4,7 +4,9 @@ * * (c) 1998,1999,2000 Petr Vandrovec <vandrove@vc.cvut.cz> * - * Version: 1.50 2000/08/10 + * Portions Copyright (c) 2001 Matrox Graphics Inc. + * + * Version: 1.62 2000/11/29 * * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org> * @@ -357,7 +359,7 @@ static void matroxfb_ti3026_cursor(struct display* p, int mode, int x, int y) { del_timer_sync(&ACCESS_FBINFO(cursor.timer)); matroxfb_DAC_lock_irqsave(flags); ACCESS_FBINFO(cursor.state) = CM_ERASE; - outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(currenthw->DACreg[POS3026_XCURCTRL])); + outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(hw.DACreg[POS3026_XCURCTRL])); matroxfb_DAC_unlock_irqrestore(flags); } return; @@ -377,7 +379,7 @@ static void matroxfb_ti3026_cursor(struct display* p, int mode, int x, int y) { ACCESS_FBINFO(cursor.y) = y; x += 64; y += 64; - outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(currenthw->DACreg[POS3026_XCURCTRL])); + outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(hw.DACreg[POS3026_XCURCTRL])); mga_outb(M_RAMDAC_BASE+TVP3026_CURPOSXL, x); mga_outb(M_RAMDAC_BASE+TVP3026_CURPOSXH, x >> 8); mga_outb(M_RAMDAC_BASE+TVP3026_CURPOSYL, y); @@ -386,7 +388,7 @@ static void matroxfb_ti3026_cursor(struct display* p, int mode, int x, int y) { ACCESS_FBINFO(cursor.state) = CM_DRAW; if (ACCESS_FBINFO(devflags.blink)) mod_timer(&ACCESS_FBINFO(cursor.timer), jiffies + HZ/2); - outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(currenthw->DACreg[POS3026_XCURCTRL]) | TVP3026_XCURCTRL_XGA); + outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(hw.DACreg[POS3026_XCURCTRL]) | TVP3026_XCURCTRL_XGA); matroxfb_DAC_unlock_irqrestore(flags); } @@ -418,9 +420,10 @@ static int Ti3026_calcclock(CPMINFO unsigned int freq, unsigned int fmax, int* i return fvco; } -static int Ti3026_setpclk(CPMINFO struct matrox_hw_state* hw, int clk, struct display* p) { +static int Ti3026_setpclk(WPMINFO int clk, struct display* p) { unsigned int f_pll; unsigned int pixfeed, pixin, pixpost; + struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); DBG("Ti3026_setpclk") @@ -491,8 +494,9 @@ static int Ti3026_setpclk(CPMINFO struct matrox_hw_state* hw, int clk, struct di return 0; } -static int Ti3026_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) { +static int Ti3026_init(WPMINFO struct my_timming* m, struct display* p) { u_int8_t muxctrl = isInterleave(MINFO) ? TVP3026_XMUXCTRL_MEMORY_64BIT : TVP3026_XMUXCTRL_MEMORY_32BIT; + struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); DBG("Ti3026_init") @@ -538,7 +542,7 @@ static int Ti3026_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, return 1; /* TODO: failed */ } } - if (matroxfb_vgaHWinit(PMINFO hw, m, p)) return 1; + if (matroxfb_vgaHWinit(PMINFO m, p)) return 1; /* set SYNC */ hw->MiscOutReg = 0xCB; @@ -567,11 +571,11 @@ static int Ti3026_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, if ((p->type != FB_TYPE_TEXT) && isInterleave(MINFO)) hw->MXoptionReg |= 0x00001000; /* set DAC */ - Ti3026_setpclk(PMINFO hw, m->pixclock, p); + Ti3026_setpclk(PMINFO m->pixclock, p); return 0; } -static void ti3026_setMCLK(CPMINFO struct matrox_hw_state* hw, int fout){ +static void ti3026_setMCLK(WPMINFO int fout){ unsigned int f_pll; unsigned int pclk_m, pclk_n, pclk_p; unsigned int mclk_m, mclk_n, mclk_p; @@ -643,8 +647,8 @@ static void ti3026_setMCLK(CPMINFO struct matrox_hw_state* hw, int fout){ if (rfhcnt > 15) rfhcnt = 0; } - hw->MXoptionReg = (hw->MXoptionReg & ~0x000F0000) | (rfhcnt << 16); - pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg); + ACCESS_FBINFO(hw).MXoptionReg = (ACCESS_FBINFO(hw).MXoptionReg & ~0x000F0000) | (rfhcnt << 16); + pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, ACCESS_FBINFO(hw).MXoptionReg); /* output MCLK to MCLK pin */ outTi3026(PMINFO TVP3026_XMEMPLLCTRL, (mclk_ctl & 0xE7) | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL); @@ -670,7 +674,7 @@ static void ti3026_setMCLK(CPMINFO struct matrox_hw_state* hw, int fout){ printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n"); } -static void ti3026_ramdac_init(WPMINFO struct matrox_hw_state* hw){ +static void ti3026_ramdac_init(WPMINFO2) { DBG("ti3026_ramdac_init") @@ -683,11 +687,13 @@ static void ti3026_ramdac_init(WPMINFO struct matrox_hw_state* hw){ ACCESS_FBINFO(features.pll.post_shift_max) = 3; if (ACCESS_FBINFO(devflags.noinit)) return; - ti3026_setMCLK(PMINFO hw, 60000); + ti3026_setMCLK(PMINFO 60000); } -static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_state* oldhw, struct display* p) { +static void Ti3026_restore(WPMINFO struct display* p) { int i; + unsigned char progdac[6]; + struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); CRITFLAGS DBG("Ti3026_restore") @@ -705,7 +711,7 @@ static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_ CRITEND - matroxfb_vgaHWrestore(PMINFO hw, oldhw); + matroxfb_vgaHWrestore(PMINFO2); CRITBEGIN @@ -715,19 +721,19 @@ static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_ for (i = 0; i < 21; i++) { outTi3026(PMINFO DACseq[i], hw->DACreg[i]); } - if (oldhw) { - outTi3026(PMINFO TVP3026_XPLLADDR, 0x00); - oldhw->DACclk[0] = inTi3026(PMINFO TVP3026_XPIXPLLDATA); - oldhw->DACclk[3] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA); - outTi3026(PMINFO TVP3026_XPLLADDR, 0x15); - oldhw->DACclk[1] = inTi3026(PMINFO TVP3026_XPIXPLLDATA); - oldhw->DACclk[4] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA); - outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A); - oldhw->DACclk[2] = inTi3026(PMINFO TVP3026_XPIXPLLDATA); - oldhw->DACclk[5] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA); - } + + outTi3026(PMINFO TVP3026_XPLLADDR, 0x00); + progdac[0] = inTi3026(PMINFO TVP3026_XPIXPLLDATA); + progdac[3] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA); + outTi3026(PMINFO TVP3026_XPLLADDR, 0x15); + progdac[1] = inTi3026(PMINFO TVP3026_XPIXPLLDATA); + progdac[4] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA); + outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A); + progdac[2] = inTi3026(PMINFO TVP3026_XPIXPLLDATA); + progdac[5] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA); + CRITEND - if (!oldhw || memcmp(hw->DACclk, oldhw->DACclk, 6)) { + if (memcmp(hw->DACclk, progdac, 6)) { /* agrhh... setting up PLL is very slow on Millennium... */ /* Mystique PLL is locked in few ms, but Millennium PLL lock takes about 0.15 s... */ /* Maybe even we should call schedule() ? */ @@ -796,22 +802,23 @@ static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_ #endif } -static void Ti3026_reset(WPMINFO struct matrox_hw_state* hw){ +static void Ti3026_reset(WPMINFO2) { DBG("Ti3026_reset") matroxfb_fastfont_init(MINFO); - ti3026_ramdac_init(PMINFO hw); + ti3026_ramdac_init(PMINFO2); } -static int Ti3026_preinit(WPMINFO struct matrox_hw_state* hw){ +static int Ti3026_preinit(WPMINFO2) { static const int vxres_mill2[] = { 512, 640, 768, 800, 832, 960, 1024, 1152, 1280, 1600, 1664, 1920, 2048, 0}; static const int vxres_mill1[] = { 640, 768, 800, 960, 1024, 1152, 1280, 1600, 1920, 2048, 0}; + struct matrox_hw_state* hw = &ACCESS_FBINFO(hw); DBG("Ti3026_preinit") diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 0902bee80076..07d881b1c5fa 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -4,7 +4,9 @@ * * (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz> * - * Version: 1.54 2001/09/09 + * Portions Copyright (c) 2001 Matrox Graphics Inc. + * + * Version: 1.62 2001/11/29 * * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org> * @@ -161,11 +163,11 @@ static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) { pos = (var->yoffset * var->xres_virtual + var->xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32; pos += ACCESS_FBINFO(curr.ydstorg.chunks); } - p0 = ACCESS_FBINFO(currenthw)->CRTC[0x0D] = pos & 0xFF; - p1 = ACCESS_FBINFO(currenthw)->CRTC[0x0C] = (pos & 0xFF00) >> 8; - p2 = ACCESS_FBINFO(currenthw)->CRTCEXT[0] = (ACCESS_FBINFO(currenthw)->CRTCEXT[0] & 0xB0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40); + p0 = ACCESS_FBINFO(hw).CRTC[0x0D] = pos & 0xFF; + p1 = ACCESS_FBINFO(hw).CRTC[0x0C] = (pos & 0xFF00) >> 8; + p2 = ACCESS_FBINFO(hw).CRTCEXT[0] = (ACCESS_FBINFO(hw).CRTCEXT[0] & 0xB0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40); #ifdef CONFIG_FB_MATROX_32MB - p3 = ACCESS_FBINFO(currenthw)->CRTCEXT[8] = pos >> 21; + p3 = ACCESS_FBINFO(hw).CRTCEXT[8] = pos >> 21; #endif CRITBEGIN @@ -814,7 +816,6 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con, { struct my_timming mt; struct matrox_hw_state* hw; - struct matrox_hw_state* ohw; matroxfb_var2my(var, &mt); /* CRTC1 delays */ @@ -826,16 +827,12 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con, default: mt.delay = 31 + 8; break; } - hw = ACCESS_FBINFO(newhw); - ohw = ACCESS_FBINFO(currenthw); - - /* copy last setting... */ - memcpy(hw, ohw, sizeof(*hw)); + hw = &ACCESS_FBINFO(hw); del_timer_sync(&ACCESS_FBINFO(cursor.timer)); ACCESS_FBINFO(cursor.state) = CM_ERASE; - ACCESS_FBINFO(hw_switch->init(PMINFO hw, &mt, display)); + ACCESS_FBINFO(hw_switch->init(PMINFO &mt, display)); if (display->type == FB_TYPE_TEXT) { if (fontheight(display)) pos = var->yoffset / fontheight(display) * display->next_line / ACCESS_FBINFO(devflags.textstep) + var->xoffset / (fontwidth(display)?fontwidth(display):8); @@ -852,28 +849,26 @@ static int matroxfb_set_var(struct fb_var_screeninfo *var, int con, hw->CRTCEXT[8] = pos >> 21; if (ACCESS_FBINFO(output.ph) & (MATROXFB_OUTPUT_CONN_PRIMARY | MATROXFB_OUTPUT_CONN_DFP)) { if (ACCESS_FBINFO(primout)) - ACCESS_FBINFO(primout)->compute(MINFO, &mt, hw); + ACCESS_FBINFO(primout)->compute(MINFO, &mt); } if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) { down_read(&ACCESS_FBINFO(altout.lock)); if (ACCESS_FBINFO(altout.output)) - ACCESS_FBINFO(altout.output)->compute(ACCESS_FBINFO(altout.device), &mt, hw); + ACCESS_FBINFO(altout.output)->compute(ACCESS_FBINFO(altout.device), &mt); up_read(&ACCESS_FBINFO(altout.lock)); } - ACCESS_FBINFO(hw_switch->restore(PMINFO hw, ohw, display)); + ACCESS_FBINFO(hw_switch->restore(PMINFO display)); if (ACCESS_FBINFO(output.ph) & (MATROXFB_OUTPUT_CONN_PRIMARY | MATROXFB_OUTPUT_CONN_DFP)) { if (ACCESS_FBINFO(primout)) - ACCESS_FBINFO(primout)->program(MINFO, hw); + ACCESS_FBINFO(primout)->program(MINFO); } if (ACCESS_FBINFO(output.ph) & MATROXFB_OUTPUT_CONN_SECONDARY) { down_read(&ACCESS_FBINFO(altout.lock)); if (ACCESS_FBINFO(altout.output)) - ACCESS_FBINFO(altout.output)->program(ACCESS_FBINFO(altout.device), hw); + ACCESS_FBINFO(altout.output)->program(ACCESS_FBINFO(altout.device)); up_read(&ACCESS_FBINFO(altout.lock)); } ACCESS_FBINFO(cursor.redraw) = 1; - ACCESS_FBINFO(currenthw) = hw; - ACCESS_FBINFO(newhw) = ohw; if (ACCESS_FBINFO(output.ph) & (MATROXFB_OUTPUT_CONN_PRIMARY | MATROXFB_OUTPUT_CONN_DFP)) { if (ACCESS_FBINFO(primout)) ACCESS_FBINFO(primout)->start(MINFO); @@ -1004,7 +999,7 @@ static int matroxfb_get_vblank(CPMINFO struct fb_vblank *vblank) vblank->flags |= FB_VBLANK_HBLANKING; if (sts1 & 8) vblank->flags |= FB_VBLANK_VSYNCING; - if (vblank->count >= ACCESS_FBINFO(currcon_display)->var.yres) + if (vblank->vcount >= ACCESS_FBINFO(currcon_display)->var.yres) vblank->flags |= FB_VBLANK_VBLANKING; vblank->hcount = 0; vblank->count = 0; @@ -1416,7 +1411,7 @@ static struct video_board vbG400 = {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG4 #define DEVF_CROSS4MB 0x0010 #define DEVF_TEXT4B 0x0020 #define DEVF_DDC_8_2 0x0040 -#define DEVF_G550DAC 0x0080 +/* #define DEVF_recycled 0x0080 */ #define DEVF_SUPPORT32MB 0x0100 #define DEVF_ANY_VXRES 0x0200 #define DEVF_TEXT16B 0x0400 @@ -1432,12 +1427,13 @@ static struct video_board vbG400 = {0x2000000, 0x1000000, FB_ACCEL_MATROX_MGAG4 #define DEVF_G400 (DEVF_G2CORE | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2) /* if you'll find how to drive DFP... */ #define DEVF_G450 (DEVF_GCORE | DEVF_ANY_VXRES | DEVF_SUPPORT32MB | DEVF_TEXT16B | DEVF_CRTC2 | DEVF_G450DAC | DEVF_SRCORG) -#define DEVF_G550 (DEVF_G450 | DEVF_G550DAC | DEVF_BOTHDACS) +#define DEVF_G550 (DEVF_G450 | DEVF_BOTHDACS) static struct board { unsigned short vendor, device, rev, svid, sid; unsigned int flags; unsigned int maxclk; + enum mga_chip chip; struct video_board* base; const char* name; } dev_list[] = { @@ -1446,18 +1442,21 @@ static struct board { 0, 0, DEVF_TEXT4B, 230000, + MGA_2064, &vbMillennium, "Millennium (PCI)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2, 0xFF, 0, 0, DEVF_SWAPS, 220000, + MGA_2164, &vbMillennium2, "Millennium II (PCI)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2_AGP, 0xFF, 0, 0, DEVF_SWAPS, 250000, + MGA_2164, &vbMillennium2A, "Millennium II (AGP)"}, #endif @@ -1466,122 +1465,107 @@ static struct board { 0, 0, DEVF_VIDEO64BIT | DEVF_CROSS4MB, 180000, + MGA_1064, &vbMystique, "Mystique (PCI)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS, 0xFF, 0, 0, DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, 220000, + MGA_1164, &vbMystique, "Mystique 220 (PCI)"}, #endif #ifdef CONFIG_FB_MATROX_G100 {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_MM, 0xFF, - PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MGA_G100_PCI, - DEVF_G100, - 230000, - &vbG100, - "MGA-G100 (PCI)"}, - {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_MM, 0xFF, 0, 0, DEVF_G100, 230000, + MGA_G100, &vbG100, - "unknown G100 (PCI)"}, - {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF, - PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_GENERIC, - DEVF_G100, - 230000, - &vbG100, - "MGA-G100 (AGP)"}, - {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF, - PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MGA_G100_AGP, - DEVF_G100, - 230000, - &vbG100, - "MGA-G100 (AGP)"}, - {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF, - PCI_SS_VENDOR_ID_SIEMENS_NIXDORF, PCI_SS_ID_SIEMENS_MGA_G100_AGP, - DEVF_G100, - 230000, - &vbG100, - "MGA-G100 (AGP)"}, - {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF, - PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP, - DEVF_G100, - 230000, - &vbG100, - "Productiva G100 (AGP)"}, + "MGA-G100 (PCI)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF, 0, 0, DEVF_G100, 230000, + MGA_G100, &vbG100, - "unknown G100 (AGP)"}, + "MGA-G100 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_PCI, 0xFF, 0, 0, DEVF_G200, 250000, + MGA_G200, &vbG200, - "unknown G200 (PCI)"}, + "MGA-G200 (PCI)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF, PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_GENERIC, DEVF_G200, 220000, + MGA_G200, &vbG200, "MGA-G200 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF, PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MYSTIQUE_G200_AGP, DEVF_G200, 230000, + MGA_G200, &vbG200, "Mystique G200 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF, PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MILLENIUM_G200_AGP, DEVF_G200, 250000, + MGA_G200, &vbG200, "Millennium G200 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF, PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MARVEL_G200_AGP, DEVF_G200, 230000, + MGA_G200, &vbG200, "Marvel G200 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF, PCI_SS_VENDOR_ID_SIEMENS_NIXDORF, PCI_SS_ID_SIEMENS_MGA_G200_AGP, DEVF_G200, 230000, + MGA_G200, &vbG200, "MGA-G200 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF, 0, 0, DEVF_G200, 230000, + MGA_G200, &vbG200, "G200 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400, 0x80, PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MILLENNIUM_G400_MAX_AGP, DEVF_G400, 360000, + MGA_G400, &vbG400, "Millennium G400 MAX (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400, 0x80, 0, 0, DEVF_G400, 300000, + MGA_G400, &vbG400, "G400 (AGP)"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G400, 0xFF, 0, 0, DEVF_G450, - 500000, /* ??? vco goes up to 900MHz... */ + 360000, + MGA_G450, &vbG400, "G450"}, {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G550, 0xFF, 0, 0, DEVF_G550, - 500000, + 360000, + MGA_G550, &vbG400, "G550"}, #endif @@ -1589,6 +1573,7 @@ static struct board { 0, 0, 0, 0, + 0, NULL, NULL}}; @@ -1606,7 +1591,6 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){ unsigned long ctrlptr_phys = 0; unsigned long video_base_phys = 0; unsigned int memsize; - struct matrox_hw_state* hw = ACCESS_FBINFO(currenthw); int err; DBG("initMatrox2") @@ -1620,6 +1604,7 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){ printk(KERN_INFO "matroxfb: Matrox %s detected\n", b->name); ACCESS_FBINFO(capable.plnwt) = 1; + ACCESS_FBINFO(chip) = b->chip; ACCESS_FBINFO(capable.srcorg) = b->flags & DEVF_SRCORG; ACCESS_FBINFO(devflags.video64bits) = b->flags & DEVF_VIDEO64BIT; if (b->flags & DEVF_TEXT4B) { @@ -1657,7 +1642,6 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){ } ACCESS_FBINFO(devflags.dfp_type) = dfp_type; ACCESS_FBINFO(devflags.g450dac) = b->flags & DEVF_G450DAC; - ACCESS_FBINFO(devflags.g550dac) = b->flags & DEVF_G550DAC; ACCESS_FBINFO(devflags.textstep) = ACCESS_FBINFO(devflags.vgastep) * ACCESS_FBINFO(devflags.textmode); ACCESS_FBINFO(devflags.textvram) = 65536 / ACCESS_FBINFO(devflags.textmode); @@ -1666,9 +1650,11 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){ if (b->flags & DEVF_SWAPS) { ctrlptr_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 1); video_base_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 0); + ACCESS_FBINFO(devflags.fbResource) = PCI_BASE_ADDRESS_0; } else { ctrlptr_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 0); video_base_phys = pci_resource_start(ACCESS_FBINFO(pcidev), 1); + ACCESS_FBINFO(devflags.fbResource) = PCI_BASE_ADDRESS_1; } err = -EINVAL; if (!ctrlptr_phys) { @@ -1725,7 +1711,7 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){ } pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_COMMAND, cmd); pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mga_option); - hw->MXoptionReg = mga_option; + ACCESS_FBINFO(hw).MXoptionReg = mga_option; /* select non-DMA memory for PCI_MGA_DATA, otherwise dump of PCI cfg space can lock PCI bus */ /* maybe preinit() candidate, but it is same... for all devices... at this time... */ @@ -1733,7 +1719,8 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){ } err = -ENXIO; - if (ACCESS_FBINFO(hw_switch)->preinit(PMINFO hw)) { + matroxfb_read_pins(PMINFO2); + if (ACCESS_FBINFO(hw_switch)->preinit(PMINFO2)) { goto failVideoIO; } @@ -1746,13 +1733,7 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){ ACCESS_FBINFO(currcon) = -1; ACCESS_FBINFO(currcon_display) = d; - mga_iounmap(ACCESS_FBINFO(video.vbase)); ACCESS_FBINFO(video.base) = video_base_phys; - if (mga_ioremap(video_base_phys, ACCESS_FBINFO(video.len), MGA_IOREMAP_FB, &ACCESS_FBINFO(video.vbase))) { - printk(KERN_ERR "matroxfb: cannot ioremap(%lX, %d), matroxfb disabled\n", - video_base_phys, ACCESS_FBINFO(video.len)); - goto failCtrlIO; - } ACCESS_FBINFO(video.len_usable) = ACCESS_FBINFO(video.len); if (ACCESS_FBINFO(video.len_usable) > b->base->maxdisplayable) ACCESS_FBINFO(video.len_usable) = b->base->maxdisplayable; @@ -1766,7 +1747,7 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){ if (!ACCESS_FBINFO(devflags.novga)) request_region(0x3C0, 32, "matrox"); - ACCESS_FBINFO(hw_switch->reset(PMINFO hw)); + ACCESS_FBINFO(hw_switch->reset(PMINFO2)); ACCESS_FBINFO(fbcon.monspecs.hfmin) = 0; ACCESS_FBINFO(fbcon.monspecs.hfmax) = fh; @@ -1789,7 +1770,7 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){ strcpy(ACCESS_FBINFO(fbcon.modename), "MATROX VGA"); ACCESS_FBINFO(fbcon.changevar) = NULL; - ACCESS_FBINFO(fbcon.node) = -1; + ACCESS_FBINFO(fbcon.node) = NODEV; ACCESS_FBINFO(fbcon.fbops) = &matroxfb_ops; ACCESS_FBINFO(fbcon.disp) = d; ACCESS_FBINFO(fbcon.switch_con) = &matroxfb_switch; @@ -1848,9 +1829,9 @@ static int initMatrox2(WPMINFO struct display* d, struct board* b){ + vesafb_defined.right_margin + vesafb_defined.hsync_len); if ((tmp < maxclk) || (maxclk == 0)) maxclk = tmp; } - maxclk = (maxclk + 499) / 500; - if (maxclk) { - tmp = (2000000000 + maxclk) / maxclk; + tmp = (maxclk + 499) / 500; + if (tmp) { + tmp = (2000000000 + tmp) / tmp; if (tmp > pixclock) pixclock = tmp; } } @@ -2070,8 +2051,6 @@ static int matroxfb_probe(struct pci_dev* pdev, const struct pci_device_id* dumm memset(MINFO, 0, sizeof(*MINFO)); memset(d, 0, sizeof(*d)); - ACCESS_FBINFO(currenthw) = &ACCESS_FBINFO(hw1); - ACCESS_FBINFO(newhw) = &ACCESS_FBINFO(hw2); ACCESS_FBINFO(pcidev) = pdev; ACCESS_FBINFO(dead) = 0; ACCESS_FBINFO(usecount) = 0; diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h index d4d2df71fd3f..be8074117fec 100644 --- a/drivers/video/matrox/matroxfb_base.h +++ b/drivers/video/matrox/matroxfb_base.h @@ -162,7 +162,7 @@ #define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16) -/* G100, G200 and Mystique have (almost) same DAC */ +/* G-series and Mystique have (almost) same DAC */ #undef NEED_DAC1064 #if defined(CONFIG_FB_MATROX_MYSTIQUE) || defined(CONFIG_FB_MATROX_G100) #define NEED_DAC1064 1 @@ -305,6 +305,21 @@ struct my_timming { unsigned int delay; /* CRTC delay */ }; +enum { M_SYSTEM_PLL, M_PIXEL_PLL_A, M_PIXEL_PLL_B, M_PIXEL_PLL_C, M_VIDEO_PLL }; + +struct matrox_pll_cache { + unsigned int valid; + struct { + unsigned int mnp_key; + unsigned int mnp_value; + } data[4]; +}; + +struct matrox_pll_limits { + unsigned int vcomin; + unsigned int vcomax; +}; + struct matrox_pll_features { unsigned int vco_freq_min; unsigned int ref_freq; @@ -371,6 +386,8 @@ struct matrox_hw_state { /* CRTC2 only */ /* u_int32_t TBD */ + + unsigned int vidclk; }; struct matrox_accel_data { @@ -382,8 +399,8 @@ struct matrox_accel_data { }; struct matrox_altout { - int (*compute)(void* altout_dev, struct my_timming* input, struct matrox_hw_state* state); - int (*program)(void* altout_dev, const struct matrox_hw_state* state); + int (*compute)(void* altout_dev, struct my_timming* input); + int (*program)(void* altout_dev); int (*start)(void* altout_dev); void (*incuse)(void* altout_dev); void (*decuse)(void* altout_dev); @@ -391,6 +408,20 @@ struct matrox_altout { int (*getmode)(void* altout_dev, u_int32_t* mode); }; +enum mga_chip { MGA_2064, MGA_2164, MGA_1064, MGA_1164, MGA_G100, MGA_G200, MGA_G400, MGA_G450, MGA_G550 }; + +struct matrox_bios { + unsigned int bios_valid : 1; + unsigned int pins_len; + unsigned char pins[128]; + struct { + unsigned char vMaj, vMin, vRev; + } version; + struct { + unsigned char state, tvout; + } output; +}; + struct matrox_switch; struct matroxfb_driver; @@ -404,10 +435,7 @@ struct matrox_fb_info { unsigned int usecount; struct matroxfb_par curr; - struct matrox_hw_state hw1; - struct matrox_hw_state hw2; - struct matrox_hw_state* newhw; - struct matrox_hw_state* currenthw; + struct matrox_hw_state hw; struct matrox_accel_data accel; @@ -464,6 +492,8 @@ struct matrox_fb_info { spinlock_t accel; } lock; + enum mga_chip chip; + int interleave; int millenium; int milleniumII; @@ -514,8 +544,8 @@ struct matrox_fb_info { /* 0 except for 6MB Millenium */ int memtype; int g450dac; - int g550dac; int dfp_type; + unsigned int fbResource; } devflags; struct display_switch dispsw; struct { @@ -529,6 +559,38 @@ struct matrox_fb_info { int redraw; struct timer_list timer; } cursor; + struct matrox_bios bios; + struct { + struct matrox_pll_limits pixel; + struct matrox_pll_limits system; + struct matrox_pll_limits video; + } limits; + struct { + struct matrox_pll_cache pixel; + struct matrox_pll_cache system; + struct matrox_pll_cache video; + } cache; + struct { + struct { + unsigned int video; + unsigned int system; + } pll; + struct { + u_int32_t opt; + u_int32_t opt2; + u_int32_t opt3; + u_int32_t mctlwtst; + u_int32_t mctlwtst_core; + u_int32_t memmisc; + u_int32_t memrdbk; + u_int32_t maccess; + } reg; + struct { + unsigned int ddr:1, + emrswen:1, + dll:1; + } memory; + } values; struct { unsigned red, green, blue, transp; } palette[256]; #if defined(CONFIG_FB_COMPAT_XPMAC) char matrox_name[32]; @@ -599,10 +661,10 @@ static inline struct matrox_fb_info* mxinfo(const struct display* p) { #endif struct matrox_switch { - int (*preinit)(WPMINFO struct matrox_hw_state*); - void (*reset)(WPMINFO struct matrox_hw_state*); - int (*init)(CPMINFO struct matrox_hw_state*, struct my_timming*, struct display*); - void (*restore)(WPMINFO struct matrox_hw_state*, struct matrox_hw_state*, struct display*); + int (*preinit)(WPMINFO2); + void (*reset)(WPMINFO2); + int (*init)(WPMINFO struct my_timming*, struct display*); + void (*restore)(WPMINFO struct display*); int (*selhwcursor)(WPMINFO struct display*); }; @@ -617,8 +679,13 @@ int matroxfb_register_driver(struct matroxfb_driver* drv); void matroxfb_unregister_driver(struct matroxfb_driver* drv); #define PCI_OPTION_REG 0x40 +#define PCI_OPTION_ENABLE_ROM 0x40000000 + #define PCI_MGA_INDEX 0x44 #define PCI_MGA_DATA 0x48 +#define PCI_OPTION2_REG 0x50 +#define PCI_OPTION3_REG 0x54 +#define PCI_MEMMISC_REG 0x58 #define M_DWGCTL 0x1C00 #define M_MACCESS 0x1C04 @@ -737,6 +804,8 @@ void matroxfb_unregister_driver(struct matroxfb_driver* drv); #define DAC_XGENIOCTRL 0x2A #define DAC_XGENIODATA 0x2B +#define M_C2CTL 0x3E10 + #ifdef __LITTLE_ENDIAN #define MX_OPTION_BSWAP 0x00000000 @@ -794,6 +863,7 @@ extern void matroxfb_DAC_out(CPMINFO int reg, int val); extern int matroxfb_DAC_in(CPMINFO int reg); extern struct list_head matroxfb_list; extern void matroxfb_var2my(struct fb_var_screeninfo* fvsi, struct my_timming* mt); +extern int matroxfb_switch(int con, struct fb_info *); #ifdef MATROXFB_USE_SPINLOCKS #define CRITBEGIN spin_lock_irqsave(&ACCESS_FBINFO(lock.accel), critflags); diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index ac17dbb5d226..f6f6552d5fa6 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c @@ -4,7 +4,9 @@ * * (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz> * - * Version: 1.52 2001/05/25 + * Portions Copyright (c) 2001 Matrox Graphics Inc. + * + * Version: 1.62 2001/11/29 * */ @@ -402,43 +404,35 @@ static int matroxfb_dh_set_var(struct fb_var_screeninfo* var, int con, info->changevar(con); if (con == m2info->currcon) { struct my_timming mt; - struct matrox_hw_state* hw; - struct matrox_hw_state* ohw; unsigned int pos; matroxfb_var2my(var, &mt); /* CRTC2 delay */ mt.delay = 34; - hw = ACCESS_FBINFO(newhw); - ohw = ACCESS_FBINFO(currenthw); - - /* copy last setting... */ - memcpy(hw, ohw, sizeof(*hw)); - pos = (var->yoffset * var->xres_virtual + var->xoffset) * var->bits_per_pixel >> 3; pos += m2info->video.offbase; - DAC1064_global_init(PMINFO hw); + DAC1064_global_init(PMINFO2); if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_PRIMARY) { if (ACCESS_FBINFO(primout)) - ACCESS_FBINFO(primout)->compute(MINFO, &mt, hw); + ACCESS_FBINFO(primout)->compute(MINFO, &mt); } if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) { down_read(&ACCESS_FBINFO(altout.lock)); if (ACCESS_FBINFO(altout.output)) - ACCESS_FBINFO(altout.output)->compute(ACCESS_FBINFO(altout.device), &mt, hw); + ACCESS_FBINFO(altout.output)->compute(ACCESS_FBINFO(altout.device), &mt); up_read(&ACCESS_FBINFO(altout.lock)); } matroxfb_dh_restore(m2info, &mt, p, mode, pos); - DAC1064_global_restore(PMINFO hw); + DAC1064_global_restore(PMINFO2); if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_PRIMARY) { if (ACCESS_FBINFO(primout)) - ACCESS_FBINFO(primout)->program(MINFO, hw); + ACCESS_FBINFO(primout)->program(MINFO); } if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_SECONDARY) { down_read(&ACCESS_FBINFO(altout.lock)); if (ACCESS_FBINFO(altout.output)) - ACCESS_FBINFO(altout.output)->program(ACCESS_FBINFO(altout.device), hw); + ACCESS_FBINFO(altout.output)->program(ACCESS_FBINFO(altout.device)); up_read(&ACCESS_FBINFO(altout.lock)); } if (ACCESS_FBINFO(output.sh) & MATROXFB_OUTPUT_CONN_PRIMARY) { @@ -693,7 +687,7 @@ static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) { strcpy(m2info->fbcon.modename, "MATROX CRTC2"); m2info->fbcon.changevar = NULL; - m2info->fbcon.node = -1; + m2info->fbcon.node = NODEV; m2info->fbcon.fbops = &matroxfb_dh_ops; m2info->fbcon.disp = d; m2info->fbcon.switch_con = &matroxfb_dh_switch; diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/matrox/matroxfb_g450.c index f3705bf6fca2..d57a8845bbcc 100644 --- a/drivers/video/matrox/matroxfb_g450.c +++ b/drivers/video/matrox/matroxfb_g450.c @@ -4,7 +4,9 @@ * * (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz> * - * Version: 1.51 2001/01/19 + * Portions Copyright (c) 2001 Matrox Graphics Inc. + * + * Version: 1.62 2001/11/29 * * See matroxfb_base.c for contributors. * @@ -13,119 +15,28 @@ #include "matroxfb_g450.h" #include "matroxfb_misc.h" #include "matroxfb_DAC1064.h" +#include "g450_pll.h" #include <linux/matroxfb.h> #include <asm/uaccess.h> -static int matroxfb_g450_get_reg(WPMINFO int reg) { - int val; - unsigned long flags; - - matroxfb_DAC_lock_irqsave(flags); - val = matroxfb_DAC_in(PMINFO reg); - matroxfb_DAC_unlock_irqrestore(flags); - return val; -} - -static int matroxfb_g450_set_reg(WPMINFO int reg, int val) { - unsigned long flags; - - matroxfb_DAC_lock_irqsave(flags); - matroxfb_DAC_out(PMINFO reg, val); - matroxfb_DAC_unlock_irqrestore(flags); - return 0; -} - -static const struct matrox_pll_features maven_pll = { - 110000, - 27000, - 4, 127, - 2, 31, - 3 -}; - -static const struct matrox_pll_features g550_pll = { - 135000, - 27000, - 4, 127, - 0, 9, - 3 -}; - -static void DAC1064_calcclock(unsigned int freq, unsigned int fmax, - unsigned int* in, unsigned int* feed, unsigned int* post, - unsigned int timmings) { - unsigned int fvco; - unsigned int p; - - switch (timmings) { - default: - fvco = matroxfb_PLL_calcclock(&maven_pll, freq, fmax, in, feed, &p); - /* 0 => 100 ... 275 MHz - 1 => 243 ... 367 MHz - 2 => 320 ... 475 MHz - 3 => 453 ... 556 MHz - 4 => 540 ... 594 MHz - 5 => 588 ... 621 MHz - 6 => 626 ... 637 MHz - 7 => 631 ... 642 MHz - - As you can see, never choose frequency > 621 MHz, there is unavailable gap... - Just to be sure, currently driver uses 110 ... 500 MHz range. - */ - if (fvco <= 260000) - ; - else if (fvco <= 350000) - p |= 0x08; - else if (fvco <= 460000) - p |= 0x10; - else if (fvco <= 550000) - p |= 0x18; - else if (fvco <= 590000) - p |= 0x20; - else - p |= 0x28; - break; - case 1: - fvco = matroxfb_PLL_calcclock(&g550_pll, freq, fmax, in, feed, &p); - /* p |= 0x00; */ - break; - } - *post = p; - return; -} - -static inline int matroxfb_g450_compute_timming(struct matroxfb_g450_info* m2info, - struct my_timming* mt, - struct mavenregs* m) { - unsigned int a, b, c; - - DAC1064_calcclock(mt->pixclock, 300000, &a, &b, &c, m2info->timmings); - m->regs[0x80] = a; - m->regs[0x81] = b; - m->regs[0x82] = c; - printk(KERN_DEBUG "PLL: %02X %02X %02X\n", a, b, c); +static int matroxfb_g450_compute(void* md, struct my_timming* mt) { +#define m2info ((struct matroxfb_g450_info*)md) +#define minfo (m2info->primary_dev) + ACCESS_FBINFO(hw).vidclk = mt->pixclock; +#undef minfo +#undef m2info return 0; } -static inline int matroxfb_g450_program_timming(struct matroxfb_g450_info* m2info, const struct mavenregs* m) { - MINFO_FROM(m2info->primary_dev); - - matroxfb_g450_set_reg(PMINFO M1064_XPIXPLL2M, m->regs[0x81]); - matroxfb_g450_set_reg(PMINFO M1064_XPIXPLL2N, m->regs[0x80]); - matroxfb_g450_set_reg(PMINFO M1064_XPIXPLL2P, m->regs[0x82]); +static int matroxfb_g450_program(void* md) { +#define m2info ((struct matroxfb_g450_info*)md) +#define minfo (m2info->primary_dev) + matroxfb_g450_setclk(PMINFO ACCESS_FBINFO(hw).vidclk, M_VIDEO_PLL); +#undef minfo +#undef m2info return 0; } -/******************************************************/ - -static int matroxfb_g450_compute(void* md, struct my_timming* mt, struct matrox_hw_state* mr) { - return matroxfb_g450_compute_timming(md, mt, &mr->maven); -} - -static int matroxfb_g450_program(void* md, const struct matrox_hw_state* mr) { - return matroxfb_g450_program_timming(md, &mr->maven); -} - static int matroxfb_g450_start(void* md) { return 0; } @@ -191,7 +102,7 @@ static void matroxfb_g450_shutdown(struct matroxfb_g450_info* m2info) { static void* matroxfb_g450_probe(struct matrox_fb_info* minfo) { struct matroxfb_g450_info* m2info; - /* hardware is not G450 incapable... */ + /* hardware is not G450... */ if (!ACCESS_FBINFO(devflags.g450dac)) return NULL; m2info = (struct matroxfb_g450_info*)kmalloc(sizeof(*m2info), GFP_KERNEL); @@ -201,11 +112,6 @@ static void* matroxfb_g450_probe(struct matrox_fb_info* minfo) { } memset(m2info, 0, sizeof(*m2info)); m2info->primary_dev = MINFO; - if (ACCESS_FBINFO(devflags.g550dac)) { - m2info->timmings = 1; - } else { - m2info->timmings = 0; - } if (matroxfb_g450_connect(m2info)) { kfree(m2info); printk(KERN_ERR "matroxfb_g450: G450 DAC failed to initialize\n"); diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/matrox/matroxfb_maven.c index cfee9249decc..e6a904dde2b8 100644 --- a/drivers/video/matrox/matroxfb_maven.c +++ b/drivers/video/matrox/matroxfb_maven.c @@ -862,12 +862,20 @@ static int maven_get_output_mode(struct maven_data* md, u_int32_t *arg) { /******************************************************/ -static int maven_out_compute(void* md, struct my_timming* mt, struct matrox_hw_state* mr) { - return maven_compute_timming(md, mt, &mr->maven); +static int maven_out_compute(void* md, struct my_timming* mt) { +#define mdinfo ((struct maven_data*)md) +#define minfo (mdinfo->primary_head) + return maven_compute_timming(md, mt, &ACCESS_FBINFO(hw).maven); +#undef minfo +#undef mdinfo } -static int maven_out_program(void* md, const struct matrox_hw_state* mr) { - return maven_program_timming(md, &mr->maven); +static int maven_out_program(void* md) { +#define mdinfo ((struct maven_data*)md) +#define minfo (mdinfo->primary_head) + return maven_program_timming(md, &ACCESS_FBINFO(hw).maven); +#undef minfo +#undef mdinfo } static int maven_out_start(void* md) { diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/matrox/matroxfb_misc.c index 1c46f42157d7..49a00835203f 100644 --- a/drivers/video/matrox/matroxfb_misc.c +++ b/drivers/video/matrox/matroxfb_misc.c @@ -2,9 +2,11 @@ * * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400 * - * (c) 1998,1999,2000 Petr Vandrovec <vandrove@vc.cvut.cz> + * (c) 1998,1999,2000,2001 Petr Vandrovec <vandrove@vc.cvut.cz> * - * Version: 1.54 2001/09/09 + * Portions Copyright (c) 2001 Matrox Graphics Inc. + * + * Version: 1.62 2001/11/29 * * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org> * @@ -218,7 +220,7 @@ int matroxfb_PLL_calcclock(const struct matrox_pll_features* pll, unsigned int f return bestvco; } -int matroxfb_vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) { +int matroxfb_vgaHWinit(WPMINFO struct my_timming* m, struct display* p) { unsigned int hd, hs, he, hbe, ht; unsigned int vd, vs, ve, vt; unsigned int wd; @@ -226,6 +228,7 @@ int matroxfb_vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, int i; int text = p->type == FB_TYPE_TEXT; int fwidth; + struct matrox_hw_state * const hw = &ACCESS_FBINFO(hw); if (text) { fwidth = fontwidth(p); @@ -416,8 +419,9 @@ int matroxfb_vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, return 0; }; -void matroxfb_vgaHWrestore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_state* oldhw) { +void matroxfb_vgaHWrestore(WPMINFO2) { int i; + struct matrox_hw_state * const hw = &ACCESS_FBINFO(hw); CRITFLAGS DBG("vgaHWrestore") @@ -643,6 +647,354 @@ int matroxfb_fastfont_tryset(WPMINFO struct display* p) { return 1; } +static void get_pins(unsigned char* pins, struct matrox_bios* bd) { + unsigned int b0 = readb(pins); + + if (b0 == 0x2E && readb(pins+1) == 0x41) { + unsigned int pins_len = readb(pins+2); + unsigned int i; + unsigned char cksum; + unsigned char* dst = bd->pins; + + if (pins_len < 3 || pins_len > 128) { + return; + } + *dst++ = 0x2E; + *dst++ = 0x41; + *dst++ = pins_len; + cksum = 0x2E + 0x41 + pins_len; + for (i = 3; i < pins_len; i++) { + cksum += *dst++ = readb(pins+i); + } + if (cksum) { + return; + } + bd->pins_len = pins_len; + } else if (b0 == 0x40 && readb(pins+1) == 0x00) { + unsigned int i; + unsigned char* dst = bd->pins; + + *dst++ = 0x40; + *dst++ = 0; + for (i = 2; i < 0x40; i++) { + *dst++ = readb(pins+i); + } + bd->pins_len = 0x40; + } +} + +static void get_bios_version(unsigned char* vbios, struct matrox_bios* bd) { + unsigned int pcir_offset; + + pcir_offset = readb(vbios + 24) | (readb(vbios + 25) << 8); + if (pcir_offset >= 26 && pcir_offset < 0xFFE0 && + readb(vbios + pcir_offset ) == 'P' && + readb(vbios + pcir_offset + 1) == 'C' && + readb(vbios + pcir_offset + 2) == 'I' && + readb(vbios + pcir_offset + 3) == 'R') { + unsigned char h; + + h = readb(vbios + pcir_offset + 0x12); + bd->version.vMaj = (h >> 4) & 0xF; + bd->version.vMin = h & 0xF; + bd->version.vRev = readb(vbios + pcir_offset + 0x13); + } else { + unsigned char h; + + h = readb(vbios + 5); + bd->version.vMaj = (h >> 4) & 0xF; + bd->version.vMin = h & 0xF; + bd->version.vRev = 0; + } +} + +static void get_bios_output(unsigned char* vbios, struct matrox_bios* bd) { + unsigned char b; + + b = readb(vbios + 0x7FF1); + if (b == 0xFF) { + b = 0; + } + bd->output.state = b; +} + +static void get_bios_tvout(unsigned char* vbios, struct matrox_bios* bd) { + unsigned int i; + + /* Check for 'IBM .*(V....TVO' string - it means TVO BIOS */ + bd->output.tvout = 0; + if (readb(vbios + 0x1D) != 'I' || + readb(vbios + 0x1E) != 'B' || + readb(vbios + 0x1F) != 'M' || + readb(vbios + 0x20) != ' ') { + return; + } + for (i = 0x2D; i < 0x2D + 128; i++) { + unsigned char b = readb(vbios + i); + + if (b == '(' && readb(vbios + i + 1) == 'V') { + if (readb(vbios + i + 6) == 'T' && + readb(vbios + i + 7) == 'V' && + readb(vbios + i + 8) == 'O') { + bd->output.tvout = 1; + } + return; + } + if (b == 0) + break; + } +} + +static void parse_bios(unsigned char* vbios, struct matrox_bios* bd) { + unsigned int pins_offset; + + if (readb(vbios) != 0x55 || readb(vbios + 1) != 0xAA) { + return; + } + bd->bios_valid = 1; + get_bios_version(vbios, bd); + get_bios_output(vbios, bd); + get_bios_tvout(vbios, bd); + pins_offset = readb(vbios + 0x7FFC) | (readb(vbios + 0x7FFD) << 8); + if (pins_offset <= 0xFF80) { + get_pins(vbios + pins_offset, bd); + } +} + +#define get_u16(x) (le16_to_cpu(get_unaligned((__u16*)(x)))) +#define get_u32(x) (le32_to_cpu(get_unaligned((__u32*)(x)))) +static int parse_pins1(WPMINFO const struct matrox_bios* bd) { + unsigned int maxdac; + + switch (bd->pins[22]) { + case 0: maxdac = 175000; break; + case 1: maxdac = 220000; break; + default: maxdac = 240000; break; + } + if (get_u16(bd->pins + 24)) { + maxdac = get_u16(bd->pins + 24) * 10; + } + MINFO->limits.pixel.vcomax = maxdac; + MINFO->values.pll.system = get_u16(bd->pins + 28) ? get_u16(bd->pins + 28) * 10 : 50000; + /* ignore 4MB, 8MB, module clocks */ + MINFO->features.pll.ref_freq = 14318; + MINFO->values.reg.mctlwtst = 0x00030101; + return 0; +} + +static void default_pins1(WPMINFO2) { + /* Millennium */ + MINFO->limits.pixel.vcomax = 220000; + MINFO->values.pll.system = 50000; + MINFO->features.pll.ref_freq = 14318; + MINFO->values.reg.mctlwtst = 0x00030101; +} + +static int parse_pins2(WPMINFO const struct matrox_bios* bd) { + MINFO->limits.pixel.vcomax = + MINFO->limits.system.vcomax = (bd->pins[41] == 0xFF) ? 230000 : ((bd->pins[41] + 100) * 1000); + MINFO->values.reg.mctlwtst = ((bd->pins[51] & 0x01) ? 0x00000001 : 0) | + ((bd->pins[51] & 0x02) ? 0x00000100 : 0) | + ((bd->pins[51] & 0x04) ? 0x00010000 : 0) | + ((bd->pins[51] & 0x08) ? 0x00020000 : 0); + MINFO->values.pll.system = (bd->pins[43] == 0xFF) ? 50000 : ((bd->pins[43] + 100) * 1000); + MINFO->features.pll.ref_freq = 14318; + return 0; +} + +static void default_pins2(WPMINFO2) { + /* Millennium II, Mystique */ + MINFO->limits.pixel.vcomax = + MINFO->limits.system.vcomax = 230000; + MINFO->values.reg.mctlwtst = 0x00030101; + MINFO->values.pll.system = 50000; + MINFO->features.pll.ref_freq = 14318; +} + +static int parse_pins3(WPMINFO const struct matrox_bios* bd) { + MINFO->limits.pixel.vcomax = + MINFO->limits.system.vcomax = (bd->pins[36] == 0xFF) ? 230000 : ((bd->pins[36] + 100) * 1000); + MINFO->values.reg.mctlwtst = get_u32(bd->pins + 48) == 0xFFFFFFFF ? 0x01250A21 : get_u32(bd->pins + 48); + /* memory config */ + MINFO->values.reg.memrdbk = ((bd->pins[57] << 21) & 0x1E000000) | + ((bd->pins[57] << 22) & 0x00C00000) | + ((bd->pins[56] << 1) & 0x000001E0) | + ( bd->pins[56] & 0x0000000F); + MINFO->values.reg.opt = (bd->pins[54] & 7) << 10; + MINFO->values.reg.opt2 = bd->pins[58] << 12; + MINFO->features.pll.ref_freq = (bd->pins[52] & 0x20) ? 14318 : 27000; + return 0; +} + +static void default_pins3(WPMINFO2) { + /* G100, G200 */ + MINFO->limits.pixel.vcomax = + MINFO->limits.system.vcomax = 230000; + MINFO->values.reg.mctlwtst = 0x01250A21; + MINFO->values.reg.memrdbk = 0x00000000; + MINFO->values.reg.opt = 0x00000C00; + MINFO->values.reg.opt2 = 0x00000000; + MINFO->features.pll.ref_freq = 27000; +} + +static int parse_pins4(WPMINFO const struct matrox_bios* bd) { + MINFO->limits.pixel.vcomax = (bd->pins[ 39] == 0xFF) ? 230000 : bd->pins[ 39] * 4000; + MINFO->limits.system.vcomax = (bd->pins[ 38] == 0xFF) ? MINFO->limits.pixel.vcomax : bd->pins[ 38] * 4000; + MINFO->values.reg.mctlwtst = get_u32(bd->pins + 71); + MINFO->values.reg.memrdbk = ((bd->pins[87] << 21) & 0x1E000000) | + ((bd->pins[87] << 22) & 0x00C00000) | + ((bd->pins[86] << 1) & 0x000001E0) | + ( bd->pins[86] & 0x0000000F); + MINFO->values.reg.opt = ((bd->pins[53] << 15) & 0x00400000) | + ((bd->pins[53] << 22) & 0x10000000) | + ((bd->pins[53] << 10) & 0x00001C00); + MINFO->values.reg.opt3 = get_u32(bd->pins + 67); + MINFO->values.pll.system = (bd->pins[ 65] == 0xFF) ? 200000 : bd->pins[ 65] * 4000; + MINFO->features.pll.ref_freq = (bd->pins[ 92] & 0x01) ? 14318 : 27000; + return 0; +} + +static void default_pins4(WPMINFO2) { + /* G400 */ + MINFO->limits.pixel.vcomax = + MINFO->limits.system.vcomax = 252000; + MINFO->values.reg.mctlwtst = 0x04A450A1; + MINFO->values.reg.memrdbk = 0x000000E7; + MINFO->values.reg.opt = 0x10000400; + MINFO->values.reg.opt3 = 0x0190A419; + MINFO->values.pll.system = 200000; + MINFO->features.pll.ref_freq = 27000; +} + +static int parse_pins5(WPMINFO const struct matrox_bios* bd) { + unsigned int mult; + + mult = bd->pins[4]?8000:6000; + + MINFO->limits.pixel.vcomax = (bd->pins[ 38] == 0xFF) ? 600000 : bd->pins[ 38] * mult; + MINFO->limits.system.vcomax = (bd->pins[ 36] == 0xFF) ? MINFO->limits.pixel.vcomax : bd->pins[ 39] * mult; + MINFO->limits.video.vcomax = (bd->pins[ 37] == 0xFF) ? MINFO->limits.system.vcomax : bd->pins[ 37] * mult; + MINFO->limits.pixel.vcomin = (bd->pins[123] == 0xFF) ? 256000 : bd->pins[123] * mult; + MINFO->limits.system.vcomin = (bd->pins[121] == 0xFF) ? MINFO->limits.pixel.vcomin : bd->pins[121] * mult; + MINFO->limits.video.vcomin = (bd->pins[122] == 0xFF) ? MINFO->limits.system.vcomin : bd->pins[122] * mult; + MINFO->values.pll.system = + MINFO->values.pll.video = (bd->pins[ 92] == 0xFF) ? 284000 : bd->pins[ 92] * 4000; + MINFO->values.reg.opt = get_u32(bd->pins+ 48); + MINFO->values.reg.opt2 = get_u32(bd->pins+ 52); + MINFO->values.reg.opt3 = get_u32(bd->pins+ 94); + MINFO->values.reg.mctlwtst = get_u32(bd->pins+ 98); + MINFO->values.reg.memmisc = get_u32(bd->pins+102); + MINFO->values.reg.memrdbk = get_u32(bd->pins+106); + MINFO->features.pll.ref_freq = (bd->pins[110] & 0x01) ? 14318 : 27000; + MINFO->values.memory.ddr = (bd->pins[114] & 0x60) == 0x20; + MINFO->values.memory.dll = (bd->pins[115] & 0x02) != 0; + MINFO->values.memory.emrswen = (bd->pins[115] & 0x01) != 0; + MINFO->values.reg.maccess = MINFO->values.memory.emrswen ? 0x00004000 : 0x00000000; + if (bd->pins[115] & 4) { + MINFO->values.reg.mctlwtst_core = MINFO->values.reg.mctlwtst; + } else { + u_int32_t wtst_xlat[] = { 0, 1, 5, 6, 7, 5, 2, 3 }; + MINFO->values.reg.mctlwtst_core = (MINFO->values.reg.mctlwtst & ~7) | + wtst_xlat[MINFO->values.reg.mctlwtst & 7]; + } + return 0; +} + +static void default_pins5(WPMINFO2) { + /* Mine 16MB G450 with SDRAM DDR */ + MINFO->limits.pixel.vcomax = + MINFO->limits.system.vcomax = + MINFO->limits.video.vcomax = 600000; + MINFO->limits.pixel.vcomin = + MINFO->limits.system.vcomin = + MINFO->limits.video.vcomin = 256000; + MINFO->values.pll.system = + MINFO->values.pll.video = 284000; + MINFO->values.reg.opt = 0x404A1160; + MINFO->values.reg.opt2 = 0x0000AC00; + MINFO->values.reg.opt3 = 0x0090A409; + MINFO->values.reg.mctlwtst_core = + MINFO->values.reg.mctlwtst = 0x0C81462B; + MINFO->values.reg.memmisc = 0x80000004; + MINFO->values.reg.memrdbk = 0x01001103; + MINFO->features.pll.ref_freq = 27000; + MINFO->values.memory.ddr = 1; + MINFO->values.memory.dll = 1; + MINFO->values.memory.emrswen = 1; + MINFO->values.reg.maccess = 0x00004000; +} + +static int matroxfb_set_limits(WPMINFO const struct matrox_bios* bd) { + unsigned int pins_version; + static const unsigned int pinslen[] = { 64, 64, 64, 128, 128 }; + + switch (ACCESS_FBINFO(chip)) { + case MGA_2064: default_pins1(PMINFO2); break; + case MGA_2164: + case MGA_1064: + case MGA_1164: default_pins2(PMINFO2); break; + case MGA_G100: + case MGA_G200: default_pins3(PMINFO2); break; + case MGA_G400: default_pins4(PMINFO2); break; + case MGA_G450: + case MGA_G550: default_pins5(PMINFO2); break; + } + if (!bd->bios_valid) { + printk(KERN_INFO "matroxfb: Your Matrox device does not have BIOS\n"); + return -1; + } + if (bd->pins_len < 64) { + printk(KERN_INFO "matroxfb: BIOS on your Matrox device does not contain powerup info\n"); + return -1; + } + if (bd->pins[0] == 0x2E && bd->pins[1] == 0x41) { + pins_version = bd->pins[5]; + if (pins_version < 2 || pins_version > 5) { + printk(KERN_INFO "matroxfb: Unknown version (%u) of powerup info\n", pins_version); + return -1; + } + } else { + pins_version = 1; + } + if (bd->pins_len != pinslen[pins_version - 1]) { + printk(KERN_INFO "matroxfb: Invalid powerup info\n"); + return -1; + } + switch (pins_version) { + case 1: + return parse_pins1(PMINFO bd); + case 2: + return parse_pins2(PMINFO bd); + case 3: + return parse_pins3(PMINFO bd); + case 4: + return parse_pins4(PMINFO bd); + case 5: + return parse_pins5(PMINFO bd); + default: + printk(KERN_DEBUG "matroxfb: Powerup info version %u is not yet supported\n", pins_version); + return -1; + } +} + +void matroxfb_read_pins(WPMINFO2) { + u32 opt; + u32 biosbase; + u32 fbbase; + struct pci_dev* pdev = ACCESS_FBINFO(pcidev); + + memset(&ACCESS_FBINFO(bios), 0, sizeof(ACCESS_FBINFO(bios))); + pci_read_config_dword(pdev, PCI_OPTION_REG, &opt); + pci_write_config_dword(pdev, PCI_OPTION_REG, opt | PCI_OPTION_ENABLE_ROM); + pci_read_config_dword(pdev, PCI_ROM_ADDRESS, &biosbase); + pci_read_config_dword(pdev, ACCESS_FBINFO(devflags.fbResource), &fbbase); + pci_write_config_dword(pdev, PCI_ROM_ADDRESS, (fbbase & PCI_ROM_ADDRESS_MASK) | PCI_ROM_ADDRESS_ENABLE); + parse_bios(vaddr_va(ACCESS_FBINFO(video).vbase), &ACCESS_FBINFO(bios)); + pci_write_config_dword(pdev, PCI_ROM_ADDRESS, biosbase); + pci_write_config_dword(pdev, PCI_OPTION_REG, opt); + matroxfb_set_limits(PMINFO &ACCESS_FBINFO(bios)); +} + EXPORT_SYMBOL(matroxfb_DAC_in); EXPORT_SYMBOL(matroxfb_DAC_out); EXPORT_SYMBOL(matroxfb_var2my); @@ -657,6 +1009,7 @@ EXPORT_SYMBOL(matroxfb_fastfont_tryset); /* accel */ EXPORT_SYMBOL(matroxfb_fastfont_init); /* DAC1064, Ti3026 */ EXPORT_SYMBOL(matroxfb_vgaHWinit); /* DAC1064, Ti3026 */ EXPORT_SYMBOL(matroxfb_vgaHWrestore); /* DAC1064, Ti3026 */ +EXPORT_SYMBOL(matroxfb_read_pins); MODULE_AUTHOR("(c) 1999-2001 Petr Vandrovec <vandrove@vc.cvut.cz>"); MODULE_DESCRIPTION("Miscellaneous support for Matrox video cards"); diff --git a/drivers/video/matrox/matroxfb_misc.h b/drivers/video/matrox/matroxfb_misc.h index b88ccd8caa1e..58eddccbfa8d 100644 --- a/drivers/video/matrox/matroxfb_misc.h +++ b/drivers/video/matrox/matroxfb_misc.h @@ -12,10 +12,11 @@ static inline int PLL_calcclock(CPMINFO unsigned int freq, unsigned int fmax, } void matroxfb_createcursorshape(WPMINFO struct display* p, int vmode); -int matroxfb_vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p); -void matroxfb_vgaHWrestore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_state* oldhw); +int matroxfb_vgaHWinit(WPMINFO struct my_timming* m, struct display* p); +void matroxfb_vgaHWrestore(WPMINFO2); void matroxfb_fastfont_init(struct matrox_fb_info* minfo); int matrox_text_loadfont(WPMINFO struct display* p); int matroxfb_fastfont_tryset(WPMINFO struct display* p); +void matroxfb_read_pins(WPMINFO2); #endif /* __MATROXFB_MISC_H__ */ |
