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
......@@ -419,6 +419,10 @@ CONFIG_FB_MATROX_G100
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
DDC (I2C) bus present on all Matroxes, an I2C bus which
......@@ -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
......
This diff is collapsed.
#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__ */
This diff is collapsed.
......@@ -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);
progdac[0] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
progdac[3] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
outTi3026(PMINFO TVP3026_XPLLADDR, 0x15);
oldhw->DACclk[1] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
oldhw->DACclk[4] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
progdac[1] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
progdac[4] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
outTi3026(PMINFO TVP3026_XPLLADDR, 0x2A);
oldhw->DACclk[2] = inTi3026(PMINFO TVP3026_XPIXPLLDATA);
oldhw->DACclk[5] = inTi3026(PMINFO TVP3026_XLOOPPLLDATA);
}
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")
......
This diff is collapsed.
......@@ -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);
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 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);
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) {
......
This diff is collapsed.
......@@ -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