Commit 213d2214 authored by Petr Vandrovec's avatar Petr Vandrovec

[PATCH] (1/3) matroxfb for 2.5.3

(1) Updates documentation.
(2) Remove 'current' and 'previous' hardware fields. X just do not play fair,
    and one cannot assume anything about current hardware state.
(3) Changes algorithm for computing PLL parameters to one used by Matrox. On
    recent chips (G550) there are no limits for PLL, you just have to try
    couple of possible combinations to find which one works on this
    particualr hardware.
(4) Add code which can intialize G450/G550 when BIOS did not initalize it
    (non-ia32 hardware, secondary devices on ia32 hardware).

				Petr Vandrovec
parent 1ea864f1
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
/*
*
* 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");
#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__ */
......@@ -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, &reg50);
pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, &reg50);
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, &reg50);
} else if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG200) {
pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, &reg50);
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, &reg50);
pci_read_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION2_REG, &reg50);
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
......
......@@ -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
......
......@@ -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")
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
......
......@@ -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");
......
......@@ -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) {
......
......@@ -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");
......
......@@ -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__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment