patch-2.1.130 linux/drivers/video/matroxfb.c
Next file: linux/drivers/video/offb.c
Previous file: linux/drivers/video/fbmem.c
Back to the patch index
Back to the overall index
- Lines: 3356
- Date:
Wed Nov 25 14:53:51 1998
- Orig file:
v2.1.129/linux/drivers/video/matroxfb.c
- Orig date:
Thu Nov 19 09:56:28 1998
diff -u --recursive --new-file v2.1.129/linux/drivers/video/matroxfb.c linux/drivers/video/matroxfb.c
@@ -1,10 +1,10 @@
/*
*
- * Hardware accelerated Matrox Millenium I, II, Mystique and G200
+ * Hardware accelerated Matrox Millennium I, II, Mystique and G200
*
* (c) 1998 Petr Vandrovec <vandrove@vc.cvut.cz>
*
- * Version: 1.3 1998/10/28
+ * Version: 1.5 1998/11/19
*
* MTRR stuff: 1998 Tom Rini <tmrini@ntplx.net>
*
@@ -17,6 +17,10 @@
* "Tom Rini" <tmrini@ntplx.net>
* MTRR stuff, betatesting, fixes, ideas
*
+ * "Bibek Sahu" <scorpio@dodds.net>
+ * Access device through readb|w|l and write b|w|l
+ * Extensive debugging stuff
+ *
* "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
* Betatesting
*
@@ -29,11 +33,16 @@
* "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
* Fixes, enhandcements, ideas, betatesting
*
- * "Paul Womar" <Paul@pwomar.demon.co.uk>
* "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
+ * PPC betatesting, PPC support, backward compatibility
+ *
+ * "Paul Womar" <Paul@pwomar.demon.co.uk>
* "Owen Waller" <O.Waller@ee.qub.ac.uk>
* PPC betatesting
*
+ * "H. Peter Arvin" <hpa@transmeta.com>
+ * Ideas
+ *
* (following author is not in any relation with this code, but his code
* is included in this driver)
*
@@ -46,6 +55,21 @@
* FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
*
*/
+
+/* general, but fairly heavy, debugging */
+#undef MATROXFB_DEBUG
+
+/* heavy debugging: */
+/* -- logs putc[s], so everytime a char is displayed, it's logged */
+#undef MATROXFB_DEBUG_HEAVY
+
+/* This one _could_ cause infinite loops */
+/* It _does_ cause lots and lots of messages during idle loops */
+#undef MATROXFB_DEBUG_LOOP
+
+/* Debug register calls, too? */
+#undef MATROXFB_DEBUG_REG
+
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -60,9 +84,11 @@
#include <linux/selection.h>
#include <linux/ioport.h>
#include <linux/init.h>
+#include <linux/timer.h>
#include <linux/pci.h>
#include <asm/io.h>
+#include <asm/spinlock.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif
@@ -74,12 +100,79 @@
#include <video/fbcon-cfb24.h>
#include <video/fbcon-cfb32.h>
+#if defined(CONFIG_FB_COMPAT_XPMAC)
+#include <asm/vc_ioctl.h>
+#endif
+#if defined(CONFIG_PPC)
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <video/macmodes.h>
+#endif
+
+#ifdef MATROXFB_DEBUG
+
+#define DEBUG
+#define DBG(x) printk("matroxfb: %s\n", (x));
+
+#ifdef MATROXFB_DEBUG_HEAVY
+#define DBG_HEAVY(x) DBG(x)
+#else /* MATROXFB_DEBUG_HEAVY */
+#define DBG_HEAVY(x) /* DBG_HEAVY */
+#endif /* MATROXFB_DEBUG_HEAVY */
+
+#ifdef MATROXFB_DEBUG_LOOP
+#define DBG_LOOP(x) DBG(x)
+#else /* MATROXFB_DEBUG_LOOP */
+#define DBG_LOOP(x) /* DBG_LOOP */
+#endif /* MATROXFB_DEBUG_LOOP */
+
+#ifdef MATROXFB_DEBUG_REG
+#define DBG_REG(x) DBG(x)
+#else /* MATROXFB_DEBUG_REG */
+#define DBG_REG(x) /* DBG_REG */
+#endif /* MATROXFB_DEBUG_REG */
+
+#else /* MATROXFB_DEBUG */
+
+#define DBG(x) /* DBG */
+#define DBG_HEAVY(x) /* DBG_HEAVY */
+#define DBG_REG(x) /* DBG_REG */
+#define DBG_LOOP(x) /* DBG_LOOP */
+
+#endif /* MATROXFB_DEBUG */
+
#ifndef __i386__
#ifndef ioremap_nocache
#define ioremap_nocache(X,Y) ioremap(X,Y)
#endif
#endif
+#if defined(__alpha__) || defined(__m68k__)
+#define READx_WORKS
+#define MEMCPYTOIO_WORKS
+#else
+#define READx_FAILS
+/* recheck __ppc__, maybe that __ppc__ needs MEMCPYTOIO_WRITEL */
+/* I benchmarked PII/350MHz with G200... MEMCPY, MEMCPYTOIO and WRITEL are on same speed ( <2% diff) */
+/* so that means that G200 speed (or AGP speed?) is our limit... I do not have benchmark to test, how */
+/* much of PCI bandwidth is used during transfers... */
+#if defined(__i386__) || defined(__ppc__)
+#define MEMCPYTOIO_MEMCPY
+#else
+#define MEMCPYTOIO_WRITEL
+#endif
+#endif
+
+#ifdef __sparc__
+#error "Sorry, I have no idea how to do this on sparc... There is mapioaddr... With bus_type parameter..."
+#endif
+
+#ifdef __m68k__
+#define MAP_BUSTOVIRT
+#else
+#define MAP_IOREMAP
+#endif
+
#ifdef DEBUG
#define dprintk(X...) printk(X)
#else
@@ -103,7 +196,7 @@
#endif
#ifndef PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP
-#define PCI_SS_ID_MATROX_UNSPECIFIED 0xFF00
+#define PCI_SS_ID_MATROX_GENERIC 0xFF00
#define PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP 0xFF01
#define PCI_SS_ID_MATROX_MYSTIQUE_G200_AGP 0xFF02
#define PCI_SS_ID_MATROX_MILLENIUM_G200_AGP 0xFF03
@@ -126,6 +219,119 @@
#define NEED_DAC1064 1
#endif
+typedef struct {
+ u_int8_t* vaddr;
+} vaddr_t;
+
+#ifdef READx_WORKS
+static inline unsigned int mga_readb(vaddr_t va, unsigned int offs) {
+ return readb(va.vaddr + offs);
+}
+
+static inline u_int32_t mga_readl(vaddr_t va, unsigned int offs) {
+ return readl(va.vaddr + offs);
+}
+
+static inline void mga_writeb(vaddr_t va, unsigned int offs, u_int8_t value) {
+ writeb(value, va.vaddr + offs);
+}
+
+static inline void mga_writew(vaddr_t va, unsigned int offs, u_int16_t value) {
+ writew(value, va.vaddr + offs);
+}
+
+static inline void mga_writel(vaddr_t va, unsigned int offs, u_int32_t value) {
+ writel(value, va.vaddr + offs);
+}
+#else
+static inline unsigned int mga_readb(vaddr_t va, unsigned int offs) {
+ return *(volatile u_int8_t*)(va.vaddr + offs);
+}
+
+static inline u_int32_t mga_readl(vaddr_t va, unsigned int offs) {
+ return *(volatile u_int32_t*)(va.vaddr + offs);
+}
+
+static inline void mga_writeb(vaddr_t va, unsigned int offs, u_int8_t value) {
+ *(volatile u_int8_t*)(va.vaddr + offs) = value;
+}
+
+static inline void mga_writew(vaddr_t va, unsigned int offs, u_int16_t value) {
+ *(volatile u_int16_t*)(va.vaddr + offs) = value;
+}
+
+static inline void mga_writel(vaddr_t va, unsigned int offs, u_int32_t value) {
+ *(volatile u_int32_t*)(va.vaddr + offs) = value;
+}
+#endif
+
+static inline void mga_memcpy_toio(vaddr_t va, unsigned int offs, const void* src, int len) {
+#ifdef MEMCPYTOIO_WORKS
+ memcpy_toio(va.vaddr + offs, src, len);
+#elif defined(MEMCPYTOIO_WRITEL)
+#define srcd ((const u_int32_t*)src)
+ if (offs & 3) {
+ while (len >= 4) {
+ mga_writel(va, offs, get_unaligned(srcd++));
+ offs += 4;
+ len -= 4;
+ }
+ } else {
+ while (len >= 4) {
+ mga_writel(va, offs, *srcd++);
+ offs += 4;
+ len -= 4;
+ }
+ }
+#undef srcd
+ if (len) {
+ u_int32_t tmp;
+
+ memcpy(&tmp, src, len);
+ mga_writel(va, offs, tmp);
+ }
+#elif defined(MEMCPYTOIO_MEMCPY)
+ memcpy(va.vaddr + offs, src, len);
+#else
+#error "Sorry, do not know how to write block of data to device"
+#endif
+}
+
+static inline void vaddr_add(vaddr_t* va, unsigned long offs) {
+ va->vaddr += offs;
+}
+
+static inline void* vaddr_va(vaddr_t va) {
+ return va.vaddr;
+}
+
+#define MGA_IOREMAP_NORMAL 0
+#define MGA_IOREMAP_NOCACHE 1
+
+#define MGA_IOREMAP_FB MGA_IOREMAP_NOCACHE
+#define MGA_IOREMAP_MMIO MGA_IOREMAP_NOCACHE
+static inline int mga_ioremap(unsigned long phys, unsigned long size, int flags, vaddr_t* virt) {
+#ifdef MAP_IOREMAP
+ if (flags & MGA_IOREMAP_NOCACHE)
+ virt->vaddr = ioremap_nocache(phys, size);
+ else
+ virt->vaddr = ioremap(phys, size);
+#else
+#ifdef MAP_BUSTOVIRT
+ virt->vaddr = bus_to_virt(phys);
+#else
+#error "Your architecture does not have neither ioremap nor bus_to_virt... Giving up"
+#endif
+#endif
+ return (virt->vaddr == 0); /* 0, !0... 0, error_code in future */
+}
+
+static inline void mga_iounmap(vaddr_t va) {
+#ifdef MAP_IOREMAP
+ iounmap(va.vaddr);
+#endif
+}
+
struct matroxfb_par
{
struct fb_var_screeninfo var;
@@ -133,7 +339,9 @@
unsigned int final_bppShift;
int visual; /* unfortunately, fix */
int video_type;
- int cmap_len;
+ unsigned int cmap_len;
+ void (*putc)(u_int32_t, u_int32_t, struct display*, int, int, int);
+ void (*putcs)(u_int32_t, u_int32_t, struct display*, const unsigned short*, int, int, int);
};
struct my_timming {
@@ -167,6 +375,7 @@
struct matrox_DAC1064_features {
u_int8_t xvrefctrl;
+ unsigned int cursorimage;
};
struct matrox_accel_features {
@@ -194,6 +403,7 @@
unsigned char ramdac_rev;
#endif
u_int32_t m_dwg_rect;
+ u_int32_t m_opmode;
};
#ifdef CONFIG_FB_MATROX_MULTIHEAD
@@ -206,7 +416,7 @@
#define CPMINFO const struct matrox_fb_info* minfo,
#define PMINFO minfo,
-static struct matrox_fb_info* mxinfo(struct display* p) {
+static inline struct matrox_fb_info* mxinfo(struct display* p) {
return (struct matrox_fb_info*)p->fb_info;
}
@@ -228,7 +438,7 @@
#define PMINFO
#if 0
-static struct matrox_fb_info* mxinfo(struct display* p) {
+static inline struct matrox_fb_info* mxinfo(struct display* p) {
return &global_mxinfo;
}
#endif
@@ -266,24 +476,33 @@
struct pci_dev* pcidev;
- unsigned long video_base; /* physical */
- char* video_vbase; /* CPU view */
- unsigned int video_len;
-
- unsigned long mmio_base; /* physical */
- unsigned char* mmio; /* CPU view */
- unsigned int mmio_len;
+ struct {
+ unsigned long base; /* physical */
+ vaddr_t vbase; /* CPU view */
+ unsigned int len;
+ unsigned int len_usable;
+ } video;
+
+ struct {
+ unsigned long base; /* physical */
+ vaddr_t vbase; /* CPU view */
+ unsigned int len;
+ } mmio;
unsigned int max_pixel_clock;
struct matrox_switch* hw_switch;
int currcon;
+ struct display* currcon_display;
struct {
struct matrox_pll_features pll;
struct matrox_DAC1064_features DAC1064;
struct matrox_accel_features accel;
- } features;
+ } features;
+ struct {
+ spinlock_t DAC;
+ } lock;
int interleave;
int millenium;
@@ -291,7 +510,13 @@
struct {
int cfb4;
const int* vxres;
+ int cross4MB;
} capable;
+ struct {
+ unsigned int size;
+ unsigned int mgabase;
+ vaddr_t vbase;
+ } fastfont;
#ifdef CONFIG_MTRR
struct {
int vram;
@@ -306,20 +531,22 @@
int nopciretry;
int inverse;
int hwcursor;
+ int blink;
int accelerator;
int video64bits;
} devflags;
struct display_switch dispsw;
-#ifdef CONFIG_FB_MATROX_MILLENIUM
struct {
- unsigned int x;
- unsigned int y;
- unsigned int w;
- unsigned int h;
- volatile unsigned int mode;
+ int x;
+ int y;
+ unsigned int w;
+ unsigned int u;
+ unsigned int d;
+ unsigned int type;
+ int state;
+ struct timer_list timer;
} cursor;
-#endif
#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32)
union {
#ifdef FBCON_HAS_CFB16
@@ -334,8 +561,20 @@
} cmap;
#endif
struct { unsigned red, green, blue, transp; } palette[256];
+#if defined(CONFIG_FB_COMPAT_XPMAC)
+ char matrox_name[32];
+#endif
};
+#if defined(CONFIG_PPC)
+unsigned char nvram_read_byte(int);
+static int default_vmode = VMODE_NVRAM;
+static int default_cmode = CMODE_NVRAM;
+#endif
+#if defined(CONFIG_FB_OF)
+void matrox_of_init(struct device_node *dp);
+#endif
+
#ifdef MATROX_2MB_WITH_4MB_ADDON
#define mga_ydstorg(x) ACCESS_FBINFO2(x, _mga_ydstorg)
#define curr_ydstorg(x) ACCESS_FBINFO2(x, _curr_ydstorg)
@@ -491,9 +730,10 @@
#define TVP3026_XLATCHCTRL_4_1 0x06
#define TVP3026_XLATCHCTRL_8_1 0x06
#define TVP3026_XLATCHCTRL_16_1 0x06
-#define TVP3026A_XLATCHCTRL_4_3 0x07
+#define TVP3026A_XLATCHCTRL_4_3 0x06 /* ??? do not understand... but it works... !!! */
+#define TVP3026A_XLATCHCTRL_8_3 0x07
#define TVP3026B_XLATCHCTRL_4_3 0x08
-#define TVP3026B_XLATCHCTRL_8_3 0x06 /* ??? do not understand... but it works... ??? */
+#define TVP3026B_XLATCHCTRL_8_3 0x06 /* ??? do not understand... but it works... !!! */
#define TVP3026_XTRUECOLORCTRL 0x18
#define TVP3026_XTRUECOLORCTRL_VRAM_SHIFT_ACCEL 0x00
#define TVP3026_XTRUECOLORCTRL_VRAM_SHIFT_TVP 0x20
@@ -750,16 +990,14 @@
#endif
#endif
-#define mga_inb(addr) (*(volatile u_int8_t*)(ACCESS_FBINFO(mmio)+(addr)))
-/* #define mga_inw(addr) *(volatile u_int16_t*)(ACCESS_FBINFO(mmio)+(addr)) */
-#define mga_inl(addr) (*(volatile u_int32_t*)(ACCESS_FBINFO(mmio)+(addr)))
-#define mga_outb(addr,val) *(volatile u_int8_t*)(ACCESS_FBINFO(mmio)+(addr))=(val)
-/* #define mga_outw(addr,val) *(volatile u_int16_t*)(ACCESS_FBINFO(mmio)+(addr))=(val) */
-#define mga_outl(addr,val) *(volatile u_int32_t*)(ACCESS_FBINFO(mmio)+(addr))=(val)
+#define mga_inb(addr) mga_readb(ACCESS_FBINFO(mmio.vbase), (addr))
+#define mga_inl(addr) mga_readl(ACCESS_FBINFO(mmio.vbase), (addr))
+#define mga_outb(addr,val) mga_writeb(ACCESS_FBINFO(mmio.vbase), (addr), (val))
+#define mga_outw(addr,val) mga_writew(ACCESS_FBINFO(mmio.vbase), (addr), (val))
+#define mga_outl(addr,val) mga_writel(ACCESS_FBINFO(mmio.vbase), (addr), (val))
#define mga_readr(port,idx) (mga_outb((port),(idx)), mga_inb((port)+1))
#ifdef __LITTLE_ENDIAN
-#define __mga_outw(addr,val) *(volatile u_int16_t*)(ACCESS_FBINFO(mmio)+(addr))=(val)
-#define mga_setr(addr,port,val) __mga_outw(addr, ((val)<<8) | (port))
+#define mga_setr(addr,port,val) mga_outw(addr, ((val)<<8) | (port))
#else
#define mga_setr(addr,port,val) do { mga_outb(addr, port); mga_outb((addr)+1, val); } while (0)
#endif
@@ -770,9 +1008,7 @@
#define mga_fifo(n) do {} while ((mga_inl(M_FIFOSTATUS) & 0xFF) < (n))
#endif
-static void WaitTillIdle(const struct matrox_fb_info* minfo) {
- do {} while (mga_inl(M_STATUS) & 0x10000);
-}
+#define WaitTillIdle() do {} while (mga_inl(M_STATUS) & 0x10000)
/* code speedup */
#ifdef CONFIG_FB_MATROX_MILLENIUM
@@ -790,10 +1026,13 @@
u_int32_t mpitch;
u_int32_t mopmode;
+ DBG("matrox_cfbX_init")
+
#ifdef MATROX_2MB_WITH_4MB_ADDON
curr_ydstorg(MINFO) = mga_ydstorg(MINFO);
#endif
mpitch = ACCESS_FBINFO(curr.var.xres_virtual);
+
switch (ACCESS_FBINFO(curr.var.bits_per_pixel)) {
case 4: maccess = 0x00000000; /* accelerate as 8bpp video */
mpitch = (mpitch >> 1) | 0x8000; /* disable linearization */
@@ -838,12 +1077,15 @@
mga_outl(M_MACCESS, maccess);
ACCESS_FBINFO(accel.m_dwg_rect) = M_DWG_TRAP | M_DWG_SOLID | M_DWG_ARZERO | M_DWG_SGNZERO | M_DWG_SHIFTZERO;
if (isMilleniumII(MINFO)) ACCESS_FBINFO(accel.m_dwg_rect) |= M_DWG_TRANSC;
+ ACCESS_FBINFO(accel.m_opmode) = mopmode;
}
static void matrox_cfbX_bmove(struct display* p, int sy, int sx, int dy, int dx, int height, int width) {
int pixx = p->var.xres_virtual, start, end;
MINFO_FROM_DISP(p);
+ DBG("matrox_cfbX_bmove")
+
sx *= fontwidth(p);
dx *= fontwidth(p);
width *= fontwidth(p);
@@ -852,17 +1094,17 @@
dy *= fontheight(p);
if ((dy < sy) || ((dy == sy) && (dx <= sx))) {
mga_fifo(2);
- mga_outl(M_AR5, pixx);
mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_SGNZERO |
M_DWG_BFCOL | M_DWG_REPLACE);
+ mga_outl(M_AR5, pixx);
width--;
start = sy*pixx+sx+curr_ydstorg(MINFO);
end = start+width;
} else {
mga_fifo(3);
+ mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
mga_outl(M_SGN, 5);
mga_outl(M_AR5, -pixx);
- mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SHIFTZERO | M_DWG_BFCOL | M_DWG_REPLACE);
width--;
end = (sy+height-1)*pixx+sx+curr_ydstorg(MINFO);
start = end+width;
@@ -873,7 +1115,7 @@
mga_outl(M_AR3, start);
mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
mga_outl(M_YDSTLEN | M_EXEC, ((dy)<<16) | height);
- WaitTillIdle(MINFO);
+ WaitTillIdle();
}
#ifdef FBCON_HAS_CFB4
@@ -882,6 +1124,9 @@
MINFO_FROM_DISP(p);
/* both (sx or dx or width) and fontwidth() are odd, so their multiply is
also odd, that means that we cannot use acceleration */
+
+ DBG("matrox_cfb4_bmove")
+
if ((sx | dx | width) & fontwidth(p) & 1) {
fbcon_cfb4_bmove(p, sy, sx, dy, dx, height, width);
return;
@@ -920,21 +1165,27 @@
mga_outl(M_FXBNDRY, ((dx+width)<<16) | dx);
mga_outl(M_YDST, dy*pixx >> 5);
mga_outl(M_LEN | M_EXEC, height);
- WaitTillIdle(MINFO);
+ WaitTillIdle();
}
#endif
static void matroxfb_accel_clear(CPMINFO u_int32_t color, int sy, int sx, int height,
int width) {
+
+ DBG("matroxfb_accel_clear")
+
mga_fifo(4);
mga_outl(M_DWGCTL, ACCESS_FBINFO(accel.m_dwg_rect) | M_DWG_REPLACE);
mga_outl(M_FCOL, color);
mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
mga_outl(M_YDSTLEN | M_EXEC, (sy << 16) | height);
- WaitTillIdle(MINFO);
+ WaitTillIdle();
}
static void matrox_cfbX_clear(u_int32_t color, struct display* p, int sy, int sx, int height, int width) {
+
+ DBG("matrox_cfbX_clear")
+
matroxfb_accel_clear(PMXINFO(p) color, sy * fontheight(p), sx * fontwidth(p),
height * fontheight(p), width * fontwidth(p));
}
@@ -945,6 +1196,8 @@
int whattodo;
MINFO_FROM_DISP(p);
+ DBG("matrox_cfb4_clear")
+
whattodo = 0;
bgx = attr_bgcol_ec(p, conp);
bgx |= bgx << 4;
@@ -972,25 +1225,26 @@
mga_outl(M_FXBNDRY, ((sx + width) << 16) | sx);
mga_outl(M_YDST, sy * p->var.xres_virtual >> 6);
mga_outl(M_LEN | M_EXEC, height);
- WaitTillIdle(MINFO);
+ WaitTillIdle();
}
if (whattodo) {
u_int32_t step = p->var.xres_virtual >> 1;
+ vaddr_t vbase = ACCESS_FBINFO(video.vbase);
if (whattodo & 1) {
- u_int8_t* uaddr = p->screen_base + sy * step + sx - 1;
+ unsigned int uaddr = sy * step + sx - 1;
u_int32_t loop;
u_int8_t bgx2 = bgx & 0xF0;
for (loop = height; loop > 0; loop --) {
- *uaddr = (*uaddr & 0x0F) | bgx2;
+ mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0x0F) | bgx2);
uaddr += step;
}
}
if (whattodo & 2) {
- u_int8_t* uaddr = p->screen_base + sy * step + sx + width;
+ unsigned int uaddr = sy * step + sx + width;
u_int32_t loop;
u_int8_t bgx2 = bgx & 0x0F;
for (loop = height; loop > 0; loop --) {
- *uaddr = (*uaddr & 0xF0) | bgx2;
+ mga_writeb(vbase, uaddr, (mga_readb(vbase, uaddr) & 0xF0) | bgx2);
uaddr += step;
}
}
@@ -1002,6 +1256,8 @@
static void matrox_cfb8_clear(struct vc_data* conp, struct display* p, int sy, int sx, int height, int width) {
u_int32_t bgx;
+ DBG("matrox_cfb8_clear")
+
bgx = attr_bgcol_ec(p, conp);
bgx |= bgx << 8;
bgx |= bgx << 16;
@@ -1013,6 +1269,8 @@
static void matrox_cfb16_clear(struct vc_data* conp, struct display* p, int sy, int sx, int height, int width) {
u_int32_t bgx;
+ DBG("matrox_cfb16_clear")
+
bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
matrox_cfbX_clear((bgx << 16) | bgx, p, sy, sx, height, width);
}
@@ -1022,23 +1280,49 @@
static void matrox_cfb32_clear(struct vc_data* conp, struct display* p, int sy, int sx, int height, int width) {
u_int32_t bgx;
+ DBG("matrox_cfb32_clear")
+
bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
matrox_cfbX_clear(bgx, p, sy, sx, height, width);
}
#endif
+static void matrox_cfbX_fastputc(u_int32_t fgx, u_int32_t bgx, struct display* p, int c, int yy, int xx) {
+ unsigned int charcell;
+ unsigned int ar3;
+ MINFO_FROM_DISP(p);
+
+ charcell = fontwidth(p) * fontheight(p);
+ yy *= fontheight(p);
+ xx *= fontwidth(p);
+ mga_fifo(7);
+ mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
+
+ mga_outl(M_FCOL, fgx);
+ mga_outl(M_BCOL, bgx);
+ mga_outl(M_FXBNDRY, ((xx + fontwidth(p) - 1) << 16) | xx);
+ ar3 = ACCESS_FBINFO(fastfont.mgabase) + (c & p->charmask) * charcell;
+ mga_outl(M_AR3, ar3);
+ mga_outl(M_AR0, (ar3 + charcell - 1) & 0x0003FFFF);
+ mga_outl(M_YDSTLEN | M_EXEC, (yy << 16) | fontheight(p));
+ WaitTillIdle();
+}
+
static void matrox_cfbX_putc(u_int32_t fgx, u_int32_t bgx, struct display* p, int c, int yy, int xx) {
u_int32_t ar0;
u_int32_t step;
MINFO_FROM_DISP(p);
+ DBG_HEAVY("matrox_cfbX_putc");
+
yy *= fontheight(p);
xx *= fontwidth(p);
+#ifdef __BIG_ENDIAN
+ WaitTillIdle();
+ mga_outl(M_OPMODE, M_OPMODE_8BPP);
+#else
mga_fifo(7);
- mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
-
- mga_outl(M_FCOL, fgx);
- mga_outl(M_BCOL, bgx);
+#endif
ar0 = fontwidth(p) - 1;
mga_outl(M_FXBNDRY, ((xx+ar0)<<16) | xx);
if (fontwidth(p) <= 8)
@@ -1047,68 +1331,65 @@
step = 2;
else
step = 4;
- /* TODO: set OPMODE_DMA_LE for BE */
if (fontwidth(p) == step << 3) {
size_t charcell = fontheight(p)*step;
/* TODO: Align charcell to 4B for BE */
+ mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
+ mga_outl(M_FCOL, fgx);
+ mga_outl(M_BCOL, bgx);
mga_outl(M_AR3, 0);
mga_outl(M_AR0, fontheight(p)*fontwidth(p)-1);
mga_outl(M_YDSTLEN | M_EXEC, (yy<<16) | fontheight(p));
- memcpy(ACCESS_FBINFO(mmio), p->fontdata+(c&p->charmask)*charcell, charcell);
+ mga_memcpy_toio(ACCESS_FBINFO(mmio.vbase), 0, p->fontdata+(c&p->charmask)*charcell, charcell);
} else {
u8* chardata = p->fontdata+(c&p->charmask)*fontheight(p)*step;
- u_int32_t ydstlen_tmp = (yy << 16) | 1;
int i;
+
+ mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_REPLACE);
+ mga_outl(M_FCOL, fgx);
+ mga_outl(M_BCOL, bgx);
+ mga_outl(M_AR5, 0);
+ mga_outl(M_AR3, 0);
+ mga_outl(M_AR0, ar0);
+ mga_outl(M_YDSTLEN | M_EXEC, (yy << 16) | fontheight(p));
+
switch (step) {
case 1:
for (i = fontheight(p); i > 0; i--) {
- mga_fifo(3);
- mga_outl(M_AR0, ar0);
- mga_outl(M_AR3, 0);
- mga_outl(M_YDSTLEN | M_EXEC, ydstlen_tmp);
#ifdef __LITTLE_ENDIAN
- *(u_int32_t*)ACCESS_FBINFO(mmio) = *chardata++;
+ mga_outl(0, *chardata++);
#else
- *(u_int32_t*)ACCESS_FBINFO(mmio) = (*chardata++) << 24;
+ mga_outl(0, (*chardata++) << 24);
#endif
- ydstlen_tmp += 0x10000;
}
break;
case 2:
for (i = fontheight(p); i > 0; i--) {
- mga_fifo(3);
- mga_outl(M_AR0, ar0);
- mga_outl(M_AR3, 0);
- mga_outl(M_YDSTLEN | M_EXEC, ydstlen_tmp);
#ifdef __LITTLE_ENDIAN
- *(u_int32_t*)ACCESS_FBINFO(mmio) = *(u_int16_t*)chardata;
+ mga_outl(0, *(u_int16_t*)chardata);
#else
- *(u_int32_t*)ACCESS_FBINFO(mmio) = (*(u_int16_t*)chardata) << 16;
+ mga_outl(0, (*(u_int16_t*)chardata) << 16);
#endif
- ydstlen_tmp += 0x10000;
chardata += 2;
}
break;
case 4:
- for (i = fontheight(p); i > 0; i--) {
- mga_fifo(3);
- mga_outl(M_AR0, ar0);
- mga_outl(M_AR3, 0);
- mga_outl(M_YDSTLEN | M_EXEC, ydstlen_tmp);
- *(u_int32_t*)ACCESS_FBINFO(mmio) = *(u_int32_t*)chardata;
- ydstlen_tmp += 0x10000;
- chardata += 4;
- }
+ mga_memcpy_toio(ACCESS_FBINFO(mmio.vbase), 0, chardata, fontheight(p) * 4);
break;
}
}
- /* TODO: restore OPMODE for BE */
- WaitTillIdle(MINFO);
+ WaitTillIdle();
+#ifdef __BIG_ENDIAN
+ mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
+#endif
}
#ifdef FBCON_HAS_CFB8
static void matrox_cfb8_putc(struct vc_data* conp, struct display* p, int c, int yy, int xx) {
u_int32_t fgx, bgx;
+ MINFO_FROM_DISP(p);
+
+ DBG_HEAVY("matroxfb_cfb8_putc");
fgx = attr_fgcol(p, c);
bgx = attr_bgcol(p, c);
@@ -1116,32 +1397,62 @@
fgx |= (fgx << 16);
bgx |= (bgx << 8);
bgx |= (bgx << 16);
- matrox_cfbX_putc(fgx, bgx, p, c, yy, xx);
+ ACCESS_FBINFO(curr.putc)(fgx, bgx, p, c, yy, xx);
}
#endif
#ifdef FBCON_HAS_CFB16
static void matrox_cfb16_putc(struct vc_data* conp, struct display* p, int c, int yy, int xx) {
u_int32_t fgx, bgx;
+ MINFO_FROM_DISP(p);
+
+ DBG_HEAVY("matroxfb_cfb16_putc");
fgx = ((u_int16_t*)p->dispsw_data)[attr_fgcol(p, c)];
bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol(p, c)];
fgx |= (fgx << 16);
bgx |= (bgx << 16);
- matrox_cfbX_putc(fgx, bgx, p, c, yy, xx);
+ ACCESS_FBINFO(curr.putc)(fgx, bgx, p, c, yy, xx);
}
#endif
#if defined(FBCON_HAS_CFB32) || defined(FBCON_HAS_CFB24)
static void matrox_cfb32_putc(struct vc_data* conp, struct display* p, int c, int yy, int xx) {
u_int32_t fgx, bgx;
+ MINFO_FROM_DISP(p);
+
+ DBG_HEAVY("matroxfb_cfb32_putc");
fgx = ((u_int32_t*)p->dispsw_data)[attr_fgcol(p, c)];
bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol(p, c)];
- matrox_cfbX_putc(fgx, bgx, p, c, yy, xx);
+ ACCESS_FBINFO(curr.putc)(fgx, bgx, p, c, yy, xx);
}
#endif
+static void matrox_cfbX_fastputcs(u_int32_t fgx, u_int32_t bgx, struct display* p, const unsigned short* s, int count, int yy, int xx) {
+ unsigned int charcell;
+ MINFO_FROM_DISP(p);
+
+ yy *= fontheight(p);
+ xx *= fontwidth(p);
+ charcell = fontwidth(p) * fontheight(p);
+ mga_fifo(3);
+ mga_outl(M_DWGCTL, M_DWG_BITBLT | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
+ mga_outl(M_FCOL, fgx);
+ mga_outl(M_BCOL, bgx);
+ while (count--) {
+ u_int32_t ar3 = ACCESS_FBINFO(fastfont.mgabase) + (*s++ & p->charmask)*charcell;
+
+ mga_fifo(4);
+ mga_outl(M_FXBNDRY, ((xx + fontwidth(p) - 1) << 16) | xx);
+ mga_outl(M_AR3, ar3);
+ mga_outl(M_AR0, (ar3 + charcell - 1) & 0x0003FFFF);
+ mga_outl(M_YDSTLEN | M_EXEC, (yy << 16) | fontheight(p));
+ xx += fontwidth(p);
+ }
+ WaitTillIdle();
+}
+
static void matrox_cfbX_putcs(u_int32_t fgx, u_int32_t bgx, struct display* p, const unsigned short* s, int count, int yy, int xx) {
u_int32_t step;
u_int32_t ydstlen;
@@ -1149,9 +1460,12 @@
u_int32_t ar0;
u_int32_t charcell;
u_int32_t fxbndry;
+ vaddr_t mmio;
int easy;
MINFO_FROM_DISP(p);
+ DBG_HEAVY("matroxfb_cfbX_putcs");
+
yy *= fontheight(p);
xx *= fontwidth(p);
if (fontwidth(p) <= 8)
@@ -1162,86 +1476,83 @@
step = 4;
charcell = fontheight(p)*step;
xlen = (charcell + 3) & ~3;
+ ydstlen = (yy<<16) | fontheight(p);
if (fontwidth(p) == step << 3) {
- ydstlen = (yy<<16) | fontheight(p);
ar0 = fontheight(p)*fontwidth(p) - 1;
easy = 1;
} else {
- ydstlen = (yy<<16) | 1;
ar0 = fontwidth(p) - 1;
easy = 0;
}
+#ifdef __BIG_ENDIAN
+ WaitTillIdle();
+ mga_outl(M_OPMODE, M_OPMODE_8BPP);
+#else
mga_fifo(3);
- mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
+#endif
+ if (easy)
+ mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_LINEAR | M_DWG_REPLACE);
+ else
+ mga_outl(M_DWGCTL, M_DWG_ILOAD | M_DWG_SGNZERO | M_DWG_SHIFTZERO | M_DWG_BMONOWF | M_DWG_REPLACE);
mga_outl(M_FCOL, fgx);
mga_outl(M_BCOL, bgx);
- /* TODO: set OPMODE_DMA_LE for BE */
fxbndry = ((xx + fontwidth(p) - 1) << 16) | xx;
+ mmio = ACCESS_FBINFO(mmio.vbase);
while (count--) {
u_int8_t* chardata = p->fontdata + (*s++ & p->charmask)*charcell;
- mga_fifo(4);
- mga_outl(M_FXBNDRY, fxbndry);
+ mga_fifo(5);
+ mga_writel(mmio, M_FXBNDRY, fxbndry);
+ mga_writel(mmio, M_AR0, ar0);
+ mga_writel(mmio, M_AR3, 0);
if (easy) {
- mga_outl(M_AR0, ar0);
- mga_outl(M_AR3, 0);
- mga_outl(M_YDSTLEN | M_EXEC, ydstlen);
- memcpy(ACCESS_FBINFO(mmio), chardata, xlen);
+ mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen);
+ mga_memcpy_toio(mmio, 0, chardata, xlen);
} else {
- u_int32_t ydstlen_tmp = ydstlen;
- int i;
+ mga_writel(mmio, M_AR5, 0);
+ mga_writel(mmio, M_YDSTLEN | M_EXEC, ydstlen);
switch (step) {
- case 1:
- for (i = fontheight(p); i > 0; i--) {
- mga_fifo(3);
- mga_outl(M_AR0, ar0);
- mga_outl(M_AR3, 0);
- mga_outl(M_YDSTLEN | M_EXEC, ydstlen_tmp);
+ case 1: {
+ u_int8_t* charend = chardata + charcell;
+ for (; chardata != charend; chardata++) {
#ifdef __LITTLE_ENDIAN
- *(u_int32_t*)ACCESS_FBINFO(mmio) = *chardata++;
+ mga_writel(mmio, 0, *chardata);
#else
- *(u_int32_t*)ACCESS_FBINFO(mmio) = (*chardata++) << 24;
+ mga_writel(mmio, 0, (*chardata) << 24);
#endif
- ydstlen_tmp += 0x10000;
+ }
}
break;
- case 2:
- for (i = fontheight(p); i > 0; i--) {
- mga_fifo(3);
- mga_outl(M_AR0, ar0);
- mga_outl(M_AR3, 0);
- mga_outl(M_YDSTLEN | M_EXEC, ydstlen_tmp);
+ case 2: {
+ u_int8_t* charend = chardata + charcell;
+ for (; chardata != charend; chardata += 2) {
#ifdef __LITTLE_ENDIAN
- *(u_int32_t*)ACCESS_FBINFO(mmio) = *(u_int16_t*)chardata;
+ mga_writel(mmio, 0, *(u_int16_t*)chardata);
#else
- *(u_int32_t*)ACCESS_FBINFO(mmio) = (*(u_int16_t*)chardata) << 32;
+ mga_writel(mmio, 0, (*(u_int16_t*)chardata) << 16);
#endif
- ydstlen_tmp += 0x10000;
- chardata += 2;
+ }
}
break;
- case 4:
- for (i = fontheight(p); i > 0; i--) {
- mga_fifo(3);
- mga_outl(M_AR0, ar0);
- mga_outl(M_AR3, 0);
- mga_outl(M_YDSTLEN | M_EXEC, ydstlen_tmp);
- *(u_int32_t*)ACCESS_FBINFO(mmio) = *(u_int32_t*)chardata;
- ydstlen_tmp += 0x10000;
- chardata += 4;
- }
+ default:
+ mga_memcpy_toio(mmio, 0, chardata, charcell);
break;
}
}
fxbndry += fontwidth(p) + (fontwidth(p) << 16);
}
- /* TODO: restore OPMODE for BE */
- WaitTillIdle(MINFO);
+ WaitTillIdle();
+#ifdef __BIG_ENDIAN
+ mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
+#endif
}
#ifdef FBCON_HAS_CFB8
static void matrox_cfb8_putcs(struct vc_data* conp, struct display* p, const unsigned short* s, int count, int yy, int xx) {
u_int32_t fgx, bgx;
+ MINFO_FROM_DISP(p);
+
+ DBG_HEAVY("matroxfb_cfb8_putcs");
fgx = attr_fgcol(p, *s);
bgx = attr_bgcol(p, *s);
@@ -1249,29 +1560,35 @@
fgx |= (fgx << 16);
bgx |= (bgx << 8);
bgx |= (bgx << 16);
- matrox_cfbX_putcs(fgx, bgx, p, s, count, yy, xx);
+ ACCESS_FBINFO(curr.putcs)(fgx, bgx, p, s, count, yy, xx);
}
#endif
#ifdef FBCON_HAS_CFB16
static void matrox_cfb16_putcs(struct vc_data* conp, struct display* p, const unsigned short* s, int count, int yy, int xx) {
u_int32_t fgx, bgx;
+ MINFO_FROM_DISP(p);
+
+ DBG_HEAVY("matroxfb_cfb16_putcs");
fgx = ((u_int16_t*)p->dispsw_data)[attr_fgcol(p, *s)];
bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol(p, *s)];
fgx |= (fgx << 16);
bgx |= (bgx << 16);
- matrox_cfbX_putcs(fgx, bgx, p, s, count, yy, xx);
+ ACCESS_FBINFO(curr.putcs)(fgx, bgx, p, s, count, yy, xx);
}
#endif
#if defined(FBCON_HAS_CFB32) || defined(FBCON_HAS_CFB24)
static void matrox_cfb32_putcs(struct vc_data* conp, struct display* p, const unsigned short* s, int count, int yy, int xx) {
u_int32_t fgx, bgx;
+ MINFO_FROM_DISP(p);
+
+ DBG_HEAVY("matroxfb_cfb32_putcs");
fgx = ((u_int32_t*)p->dispsw_data)[attr_fgcol(p, *s)];
bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol(p, *s)];
- matrox_cfbX_putcs(fgx, bgx, p, s, count, yy, xx);
+ ACCESS_FBINFO(curr.putcs)(fgx, bgx, p, s, count, yy, xx);
}
#endif
@@ -1279,6 +1596,8 @@
static void matrox_cfb4_revc(struct display* p, int xx, int yy) {
MINFO_FROM_DISP(p);
+ DBG_LOOP("matroxfb_cfb4_revc");
+
if (fontwidth(p) & 1) {
fbcon_cfb4_revc(p, xx, yy);
return;
@@ -1294,7 +1613,7 @@
mga_outl(M_FXBNDRY, xx);
mga_outl(M_YDST, yy * p->var.xres_virtual >> 6);
mga_outl(M_LEN | M_EXEC, fontheight(p));
- WaitTillIdle(MINFO);
+ WaitTillIdle();
}
#endif
@@ -1302,6 +1621,8 @@
static void matrox_cfb8_revc(struct display* p, int xx, int yy) {
MINFO_FROM_DISP(p);
+ DBG_LOOP("matrox_cfb8_revc")
+
yy *= fontheight(p);
xx *= fontwidth(p);
@@ -1310,13 +1631,15 @@
mga_outl(M_FCOL, 0x0F0F0F0F);
mga_outl(M_FXBNDRY, ((xx + fontwidth(p)) << 16) | xx);
mga_outl(M_YDSTLEN | M_EXEC, (yy << 16) | fontheight(p));
- WaitTillIdle(MINFO);
+ WaitTillIdle();
}
#endif
static void matrox_cfbX_revc(struct display* p, int xx, int yy) {
MINFO_FROM_DISP(p);
+ DBG_LOOP("matrox_cfbX_revc")
+
yy *= fontheight(p);
xx *= fontwidth(p);
@@ -1325,7 +1648,7 @@
mga_outl(M_FCOL, 0xFFFFFFFF);
mga_outl(M_FXBNDRY, ((xx + fontwidth(p)) << 16) | xx);
mga_outl(M_YDSTLEN | M_EXEC, (yy << 16) | fontheight(p));
- WaitTillIdle(MINFO);
+ WaitTillIdle();
}
static void matrox_cfbX_clear_margins(struct vc_data* conp, struct display* p, int bottom_only) {
@@ -1333,16 +1656,19 @@
unsigned int bottom_start, right_start;
unsigned int cell_h, cell_w;
+ DBG("matrox_cfbX_clear_margins")
+
cell_w = fontwidth(p);
if (!cell_w) return; /* PARANOID */
right_width = p->var.xres % cell_w;
right_start = p->var.xres - right_width;
if (!bottom_only && right_width) {
+ /* clear whole right margin, not only visible portion */
matroxfb_accel_clear( PMXINFO(p)
/* color */ 0x00000000,
- /* y */ p->var.yoffset,
+ /* y */ 0,
/* x */ p->var.xoffset + right_start,
- /* height */ p->var.yres,
+ /* height */ p->var.yres_virtual,
/* width */ right_width);
}
cell_h = fontheight(p);
@@ -1361,72 +1687,427 @@
#ifdef CONFIG_FB_MATROX_MILLENIUM
static void outTi3026(CPMINFO int reg, int val) {
+
+ DBG_REG("outTi3026")
+
mga_outb(M_RAMDAC_BASE+TVP3026_INDEX, reg);
mga_outb(M_RAMDAC_BASE+TVP3026_X_DATAREG, val);
}
static int inTi3026(CPMINFO int reg) {
+
+ DBG_REG("inTi3026")
+
mga_outb(M_RAMDAC_BASE+TVP3026_INDEX, reg);
return mga_inb(M_RAMDAC_BASE+TVP3026_X_DATAREG);
}
#define POS3026_XCURCTRL 20
+static void matroxfb_ti3026_flashcursor(unsigned long ptr) {
+#define minfo ((struct matrox_fb_info*)ptr)
+ spin_lock(&ACCESS_FBINFO(lock.DAC));
+ outTi3026(PMINFO TVP3026_XCURCTRL, inTi3026(PMINFO TVP3026_XCURCTRL) ^ TVP3026_XCURCTRL_DIS ^ TVP3026_XCURCTRL_XGA);
+ ACCESS_FBINFO(cursor.timer.expires) = jiffies + HZ/2;
+ add_timer(&ACCESS_FBINFO(cursor.timer));
+ spin_unlock(&ACCESS_FBINFO(lock.DAC));
+#undef minfo
+}
+
+static void matroxfb_ti3026_createcursor(WPMINFO struct display* p) {
+ unsigned long flags;
+ u_int32_t xline;
+ unsigned int i;
+ unsigned int w, h;
+ unsigned int cd, cu;
+
+ if (ACCESS_FBINFO(currcon_display) != p)
+ return;
+
+ DBG("matroxfb_ti3026_createcursor");
+
+ w = fontwidth(p);
+ h = fontheight(p);
+
+ if (ACCESS_FBINFO(curr.var.vmode) & FB_VMODE_DOUBLE)
+ h *= 2;
+ cd = h;
+ if (cd >= 10)
+ cd -= 1;
+ switch (ACCESS_FBINFO(cursor.type) = (p->conp->vc_cursor_type & CUR_HWMASK)) {
+ case CUR_NONE:
+ cu = cd;
+ break;
+ case CUR_UNDERLINE:
+ cu = cd - 2;
+ break;
+ case CUR_LOWER_THIRD:
+ cu = (h * 2) / 3;
+ break;
+ case CUR_LOWER_HALF:
+ cu = h / 2;
+ break;
+ case CUR_TWO_THIRDS:
+ cu = h / 3;
+ break;
+ case CUR_BLOCK:
+ default:
+ cu = 0;
+ cd = h;
+ break;
+ }
+ ACCESS_FBINFO(cursor.w) = w;
+ ACCESS_FBINFO(cursor.u) = cu;
+ ACCESS_FBINFO(cursor.d) = cd;
+ xline = (~0) << (32 - ACCESS_FBINFO(cursor.w));
+ spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC), flags);
+ mga_outb(M_RAMDAC_BASE+TVP3026_INDEX, 0);
+ for (i = 0; i < cu; i++) {
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ }
+ for (; i < cd; i++) {
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, xline >> 24);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, xline >> 16);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, xline >> 8);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, xline);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ }
+ for (; i < 64; i++) {
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ }
+ for (i = 0; i < 512; i++)
+ mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0xFF);
+ spin_unlock_irqrestore(&ACCESS_FBINFO(lock.DAC), flags);
+}
+
static void matroxfb_ti3026_cursor(struct display* p, int mode, int x, int y) {
+ unsigned long flags;
MINFO_FROM_DISP(p);
+ DBG("matroxfb_ti3026_cursor")
+
if (mode == CM_ERASE) {
- outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(currenthw->DACreg[POS3026_XCURCTRL]) & ~3);
+ if (ACCESS_FBINFO(cursor.state) != CM_ERASE) {
+ spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC), flags);
+ ACCESS_FBINFO(cursor.state) = CM_ERASE;
+ del_timer(&ACCESS_FBINFO(cursor.timer));
+ outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(currenthw->DACreg[POS3026_XCURCTRL]));
+ spin_unlock_irqrestore(&ACCESS_FBINFO(lock.DAC), flags);
+ }
return;
}
+ if ((p->conp->vc_cursor_type & CUR_HWMASK) != ACCESS_FBINFO(cursor.type))
+ matroxfb_ti3026_createcursor(PMINFO p);
x *= fontwidth(p);
y *= fontheight(p);
y -= p->var.yoffset;
+ if (ACCESS_FBINFO(curr.var.vmode) & FB_VMODE_DOUBLE)
+ y *= 2;
+ spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC), flags);
if ((x != ACCESS_FBINFO(cursor.x)) || (y != ACCESS_FBINFO(cursor.y))) {
ACCESS_FBINFO(cursor.x) = x;
ACCESS_FBINFO(cursor.y) = y;
x += 64;
y += 64;
- outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(currenthw->DACreg[POS3026_XCURCTRL]) & ~3);
+ outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(currenthw->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);
mga_outb(M_RAMDAC_BASE+TVP3026_CURPOSYH, y >> 8);
}
- outTi3026(PMINFO TVP3026_XCURCTRL, ACCESS_FBINFO(currenthw->DACreg[POS3026_XCURCTRL]) | 2);
+ 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);
+ spin_unlock_irqrestore(&ACCESS_FBINFO(lock.DAC), flags);
}
#undef POS3026_XCURCTRL
-static void matroxfb_ti3026_createcursor(WPMINFO int w, int h) {
+static int matroxfb_ti3026_setfont(struct display* p, int width, int height) {
+
+ DBG("matrox_ti3026_setfont");
+
+ if (p && p->conp)
+ matroxfb_ti3026_createcursor(PMXINFO(p) p);
+ return 0;
+}
+#endif
+
+#ifdef NEED_DAC1064
+static void outDAC1064(CPMINFO int reg, int val) {
+
+ DBG_REG("outDAC1064");
+
+ mga_outb(M_RAMDAC_BASE+M1064_INDEX, reg);
+ mga_outb(M_RAMDAC_BASE+M1064_X_DATAREG, val);
+}
+
+static int inDAC1064(CPMINFO int reg) {
+
+ DBG_REG("inDAC1064");
+
+ mga_outb(M_RAMDAC_BASE+M1064_INDEX, reg);
+ return mga_inb(M_RAMDAC_BASE+M1064_X_DATAREG);
+}
+
+static void matroxfb_DAC1064_flashcursor(unsigned long ptr) {
+#define minfo ((struct matrox_fb_info*)ptr)
+ spin_lock(&ACCESS_FBINFO(lock.DAC));
+ outDAC1064(PMINFO M1064_XCURCTRL, inDAC1064(PMINFO M1064_XCURCTRL) ^ M1064_XCURCTRL_DIS ^ M1064_XCURCTRL_XGA);
+ ACCESS_FBINFO(cursor.timer.expires) = jiffies + HZ/2;
+ add_timer(&ACCESS_FBINFO(cursor.timer));
+ spin_unlock(&ACCESS_FBINFO(lock.DAC));
+#undef minfo
+}
+
+static void matroxfb_DAC1064_createcursor(WPMINFO struct display* p) {
+ vaddr_t cursorbase;
u_int32_t xline;
- int i;
+ unsigned int i;
+ unsigned int w, h;
+ unsigned int cu, cd;
+ if (ACCESS_FBINFO(currcon_display) != p)
+ return;
+
+ w = fontwidth(p);
+ h = fontheight(p);
+
+ if (ACCESS_FBINFO(curr.var.vmode) & FB_VMODE_DOUBLE)
+ h *= 2;
+ cd = h;
+ if (cd >= 10)
+ cd -= 1;
+ switch (ACCESS_FBINFO(cursor.type) = (p->conp->vc_cursor_type & CUR_HWMASK)) {
+ case CUR_NONE:
+ cu = cd;
+ break;
+ case CUR_UNDERLINE:
+ cu = cd - 2;
+ break;
+ case CUR_LOWER_THIRD:
+ cu = (h * 2) / 3;
+ break;
+ case CUR_LOWER_HALF:
+ cu = h / 2;
+ break;
+ case CUR_TWO_THIRDS:
+ cu = h / 3;
+ break;
+ case CUR_BLOCK:
+ default:
+ cu = 0;
+ cd = h;
+ break;
+ }
ACCESS_FBINFO(cursor.w) = w;
- ACCESS_FBINFO(cursor.h) = h;
+ ACCESS_FBINFO(cursor.u) = cu;
+ ACCESS_FBINFO(cursor.d) = cd;
xline = (~0) << (32 - ACCESS_FBINFO(cursor.w));
- mga_outb(M_RAMDAC_BASE+TVP3026_INDEX, 0);
- for (i = 0; i < ACCESS_FBINFO(cursor.h); i++) {
- mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, xline >> 24);
- mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, xline >> 16);
- mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, xline >> 8);
- mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, xline);
- mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
- mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
- mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
- mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
+ cursorbase = ACCESS_FBINFO(video.vbase);
+ h = ACCESS_FBINFO(features.DAC1064.cursorimage);
+#ifdef __BIG_ENDIAN
+ WaitTillIdle();
+ mga_outl(M_OPMODE, M_OPMODE_32BPP);
+#endif
+ for (i = 0; i < cu; i++) {
+ mga_writel(cursorbase, h, 0);
+ mga_writel(cursorbase, h+4, 0);
+ mga_writel(cursorbase, h+8, ~0);
+ mga_writel(cursorbase, h+12, ~0);
+ h += 16;
+ }
+ for (; i < cd; i++) {
+ mga_writel(cursorbase, h, 0);
+ mga_writel(cursorbase, h+4, xline);
+ mga_writel(cursorbase, h+8, ~0);
+ mga_writel(cursorbase, h+12, ~0);
+ h += 16;
+ }
+ for (; i < 64; i++) {
+ mga_writel(cursorbase, h, 0);
+ mga_writel(cursorbase, h+4, 0);
+ mga_writel(cursorbase, h+8, ~0);
+ mga_writel(cursorbase, h+12, ~0);
+ h += 16;
+ }
+#ifdef __BIG_ENDIAN
+ mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
+#endif
+}
+
+static void matroxfb_DAC1064_cursor(struct display* p, int mode, int x, int y) {
+ unsigned long flags;
+ MINFO_FROM_DISP(p);
+
+ if (mode == CM_ERASE) {
+ if (ACCESS_FBINFO(cursor.state) != CM_ERASE) {
+ spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC), flags);
+ ACCESS_FBINFO(cursor.state) = CM_ERASE;
+ del_timer(&ACCESS_FBINFO(cursor.timer));
+ outDAC1064(PMINFO M1064_XCURCTRL, M1064_XCURCTRL_DIS);
+ spin_unlock_irqrestore(&ACCESS_FBINFO(lock.DAC), flags);
+ }
+ return;
+ }
+ if ((p->conp->vc_cursor_type & CUR_HWMASK) != ACCESS_FBINFO(cursor.type))
+ matroxfb_DAC1064_createcursor(PMINFO p);
+ x *= fontwidth(p);
+ y *= fontheight(p);
+ y -= p->var.yoffset;
+ if (ACCESS_FBINFO(curr.var.vmode) & FB_VMODE_DOUBLE)
+ y *= 2;
+ spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC), flags);
+ if ((x != ACCESS_FBINFO(cursor.x)) || (y != ACCESS_FBINFO(cursor.y))) {
+ ACCESS_FBINFO(cursor.x) = x;
+ ACCESS_FBINFO(cursor.y) = y;
+ x += 64;
+ y += 64;
+ outDAC1064(PMINFO M1064_XCURCTRL, M1064_XCURCTRL_DIS);
+ mga_outb(M_RAMDAC_BASE+M1064_CURPOSXL, x);
+ mga_outb(M_RAMDAC_BASE+M1064_CURPOSXH, x >> 8);
+ mga_outb(M_RAMDAC_BASE+M1064_CURPOSYL, y);
+ mga_outb(M_RAMDAC_BASE+M1064_CURPOSYH, y >> 8);
+ }
+ ACCESS_FBINFO(cursor.state) = CM_DRAW;
+ if (ACCESS_FBINFO(devflags.blink))
+ mod_timer(&ACCESS_FBINFO(cursor.timer), jiffies + HZ/2);
+ outDAC1064(PMINFO M1064_XCURCTRL, M1064_XCURCTRL_XGA);
+ spin_unlock_irqrestore(&ACCESS_FBINFO(lock.DAC), flags);
+}
+
+static int matroxfb_DAC1064_setfont(struct display* p, int width, int height) {
+ if (p && p->conp)
+ matroxfb_DAC1064_createcursor(PMXINFO(p) p);
+ return 0;
+}
+#endif
+
+#ifndef FNTCHARCNT
+#define FNTCHARCNT(fd) (((int *)(fd))[-3])
+#endif
+
+static int matroxfb_fastfont_tryset(WPMINFO struct display* p) {
+ unsigned int fsize;
+ unsigned int width;
+
+ if (!p || !p->fontdata)
+ return 0;
+ width = fontwidth(p);
+ if (width > 32)
+ return 0;
+ fsize = (p->userfont?FNTCHARCNT(p->fontdata):256) * fontheight(p);
+ if (((fsize * width + 31) / 32) * 4 > ACCESS_FBINFO(fastfont.size))
+ return 0;
+ mga_outl(M_OPMODE, M_OPMODE_8BPP);
+ if (width <= 8) {
+ if (width == 8)
+ mga_memcpy_toio(ACCESS_FBINFO(fastfont.vbase), 0, p->fontdata, fsize);
+ else {
+ vaddr_t dst;
+ unsigned int i;
+ u_int8_t* font;
+ u_int32_t mask, valid, reg;
+
+ dst = ACCESS_FBINFO(fastfont.vbase);
+ font = (u_int8_t*)p->fontdata;
+ mask = ~0 << (8 - width);
+ valid = 0;
+ reg = 0;
+ i = 0;
+ while (fsize--) {
+ reg |= (*font++ & mask) << (8 - valid);
+ valid += width;
+ if (valid >= 8) {
+ mga_writeb(dst, i++, reg >> 8);
+ reg = reg << 8;
+ valid -= 8;
+ }
+ }
+ if (valid)
+ mga_writeb(dst, i, reg >> 8);
+ }
+ } else if (width <= 16) {
+ if (width == 16)
+ mga_memcpy_toio(ACCESS_FBINFO(fastfont.vbase), 0, p->fontdata, fsize*2);
+ else {
+ vaddr_t dst;
+ u_int16_t* font;
+ u_int32_t mask, valid, reg;
+ unsigned int i;
+
+ dst = ACCESS_FBINFO(fastfont.vbase);
+ font = (u_int16_t*)p->fontdata;
+ mask = ~0 << (16 - width);
+ valid = 0;
+ reg = 0;
+ i = 0;
+ while (fsize--) {
+ reg |= (ntohs(*font++) & mask) << (16 - valid);
+ valid += width;
+ if (valid >= 16) {
+ mga_writew(dst, i, htons(reg >> 16));
+ i += 2;
+ reg = reg << 16;
+ valid -= 16;
+ }
+ }
+ if (valid)
+ mga_writew(dst, i, htons(reg >> 16));
+ }
+ } else {
+ if (width == 32)
+ mga_memcpy_toio(ACCESS_FBINFO(fastfont.vbase), 0, p->fontdata, fsize*4);
+ else {
+ vaddr_t dst;
+ u_int32_t* font;
+ u_int32_t mask, valid, reg;
+ unsigned int i;
+
+ dst = ACCESS_FBINFO(fastfont.vbase);
+ font = (u_int32_t*)p->fontdata;
+ mask = ~0 << (32 - width);
+ valid = 0;
+ reg = 0;
+ i = 0;
+ while (fsize--) {
+ reg |= (ntohl(*font) & mask) >> valid;
+ valid += width;
+ if (valid >= 32) {
+ mga_writel(dst, i, htonl(reg));
+ i += 4;
+ valid -= 32;
+ if (valid)
+ reg = (ntohl(*font) & mask) << (width - valid);
+ else
+ reg = 0;
+ }
+ font++;
+ }
+ if (valid)
+ mga_writel(dst, i, htonl(reg));
+ }
}
- i *= 8;
- for (; i < 512; i++)
- mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
- for (i = 0; i < 512; i++)
- mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0xFF);
-}
-
-static int matroxfb_ti3026_setfont(struct display* p, int width, int height) {
- matroxfb_ti3026_createcursor(PMXINFO(p) width, height);
- return 0;
+ mga_outl(M_OPMODE, ACCESS_FBINFO(accel.m_opmode));
+ return 1;
}
-#endif
#define matrox_cfb16_revc matrox_cfbX_revc
#define matrox_cfb24_revc matrox_cfbX_revc
@@ -1483,13 +2164,18 @@
#endif
static struct pci_dev* pci_find(struct pci_dev* p) {
+
+ DBG("pci_find")
+
if (p) return p->next;
return pci_devices;
}
-static void initMatrox(WPMINFO int con, struct display* p) {
+static void initMatrox(WPMINFO struct display* p) {
struct display_switch *swtmp;
+ DBG("initMatrox")
+
p->dispsw_data = NULL;
if ((p->var.accel_flags & FB_ACCELF_TEXT) != FB_ACCELF_TEXT) {
switch (p->var.bits_per_pixel) {
@@ -1526,50 +2212,58 @@
return;
}
dprintk(KERN_INFO "matroxfb: acceleration disabled\n");
- } else {
- switch (p->var.bits_per_pixel) {
+ p->dispsw = swtmp;
+ return;
+ }
+ switch (p->var.bits_per_pixel) {
#ifdef FBCON_HAS_CFB4
- case 4:
- swtmp = &matroxfb_cfb4;
- break;
+ case 4:
+ swtmp = &matroxfb_cfb4;
+ break;
#endif
#ifdef FBCON_HAS_CFB8
- case 8:
- swtmp = &matroxfb_cfb8;
- break;
+ case 8:
+ swtmp = &matroxfb_cfb8;
+ break;
#endif
#ifdef FBCON_HAS_CFB16
- case 16:
- p->dispsw_data = &ACCESS_FBINFO(cmap.cfb16);
- swtmp = &matroxfb_cfb16;
- break;
+ case 16:
+ p->dispsw_data = &ACCESS_FBINFO(cmap.cfb16);
+ swtmp = &matroxfb_cfb16;
+ break;
#endif
#ifdef FBCON_HAS_CFB24
- case 24:
- p->dispsw_data = &ACCESS_FBINFO(cmap.cfb24);
- swtmp = &matroxfb_cfb24;
- break;
+ case 24:
+ p->dispsw_data = &ACCESS_FBINFO(cmap.cfb24);
+ swtmp = &matroxfb_cfb24;
+ break;
#endif
#ifdef FBCON_HAS_CFB32
- case 32:
- p->dispsw_data = &ACCESS_FBINFO(cmap.cfb32);
- swtmp = &matroxfb_cfb32;
- break;
+ case 32:
+ p->dispsw_data = &ACCESS_FBINFO(cmap.cfb32);
+ swtmp = &matroxfb_cfb32;
+ break;
#endif
- default:
- p->dispsw = &fbcon_dummy;
- return;
- }
- dprintk(KERN_INFO "matroxfb: now accelerated\n");
+ default:
+ p->dispsw = &fbcon_dummy;
+ return;
}
+ dprintk(KERN_INFO "matroxfb: now accelerated\n");
memcpy(&ACCESS_FBINFO(dispsw), swtmp, sizeof(ACCESS_FBINFO(dispsw)));
p->dispsw = &ACCESS_FBINFO(dispsw);
+ if (ACCESS_FBINFO(devflags.hwcursor)) {
+ if (isMillenium(MINFO)) {
#ifdef CONFIG_FB_MATROX_MILLENIUM
- if (isMillenium(MINFO) && ACCESS_FBINFO(devflags.hwcursor)) {
- ACCESS_FBINFO(dispsw.cursor) = matroxfb_ti3026_cursor;
- ACCESS_FBINFO(dispsw.set_font) = matroxfb_ti3026_setfont;
- }
+ ACCESS_FBINFO(dispsw.cursor) = matroxfb_ti3026_cursor;
+ ACCESS_FBINFO(dispsw.set_font) = matroxfb_ti3026_setfont;
#endif
+ } else {
+#ifdef NEED_DAC1064
+ ACCESS_FBINFO(dispsw.cursor) = matroxfb_DAC1064_cursor;
+ ACCESS_FBINFO(dispsw.set_font) = matroxfb_DAC1064_setfont;
+#endif
+ }
+ }
}
/* --------------------------------------------------------------------- */
@@ -1603,17 +2297,19 @@
/* --------------------------------------------------------------------- */
-static void matrox_pan_var(struct fb_var_screeninfo *var, struct matrox_fb_info* minfo) {
+static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) {
struct matroxfb_par* p = &ACCESS_FBINFO(curr);
unsigned int pos;
unsigned short p0, p1, p2;
+ DBG("matrox_pan_var")
+
p->var.xoffset = var->xoffset;
p->var.yoffset = var->yoffset;
if (var->vmode & FB_VMODE_YWRAP)
p->var.vmode |= FB_VMODE_YWRAP;
else
- p->var.vmode &= FB_VMODE_YWRAP;
+ p->var.vmode &= ~FB_VMODE_YWRAP;
pos = (p->var.yoffset * p->var.xres_virtual + p->var.xoffset) * p->final_bppShift / 32;
if (mga_ydstorg(MINFO)) {
@@ -1637,6 +2333,8 @@
static int matroxfb_open(struct fb_info *info, int user)
{
+ DBG_LOOP("matroxfb_open")
+
/*
* Nothing, only a usage count for the moment
*/
@@ -1646,6 +2344,8 @@
static int matroxfb_release(struct fb_info *info, int user)
{
+ DBG_LOOP("matroxfb_release")
+
MOD_DEC_USE_COUNT;
return(0);
}
@@ -1653,6 +2353,9 @@
static int matroxfb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info* info) {
#define minfo ((struct matrox_fb_info*)info)
+
+ DBG("matroxfb_pan_display")
+
if (var->vmode & FB_VMODE_YWRAP) {
if (var->yoffset < 0 || var->yoffset >= fb_display[con].var.yres_virtual || var->xoffset)
return -EINVAL;
@@ -1662,7 +2365,7 @@
return -EINVAL;
}
if (con == ACCESS_FBINFO(currcon))
- matrox_pan_var(var, MINFO);
+ matrox_pan_var(PMINFO var);
fb_display[con].var.xoffset = var->xoffset;
fb_display[con].var.yoffset = var->yoffset;
if (var->vmode & FB_VMODE_YWRAP)
@@ -1675,13 +2378,19 @@
static int matroxfb_updatevar(int con, struct fb_info *info)
{
- matrox_pan_var(&fb_display[con].var, (struct matrox_fb_info*)info);
+#define minfo ((struct matrox_fb_info*)info)
+ DBG("matroxfb_updatevar");
+
+ matrox_pan_var(PMINFO &fb_display[con].var);
return 0;
+#undef minfo
}
static int matroxfb_get_final_bppShift(CPMINFO int bpp) {
int bppshft2;
+ DBG("matroxfb_get_final_bppShift")
+
bppshft2 = bpp;
if (isInterleave(MINFO))
bppshft2 >>= 1;
@@ -1694,6 +2403,8 @@
int over;
int rounding;
+ DBG("matroxfb_test_and_set_rounding")
+
switch (bpp) {
case 4: rounding = 128;
break;
@@ -1719,6 +2430,8 @@
const int* width;
int xres_new;
+ DBG("matroxfb_pitch_adjust")
+
width = ACCESS_FBINFO(capable.vxres);
if (ACCESS_FBINFO(devflags.precise_width)) {
@@ -1739,18 +2452,6 @@
return xres_new;
}
-#ifdef NEED_DAC1064
-static void outDAC1064(CPMINFO int reg, int val) {
- mga_outb(M_RAMDAC_BASE+M1064_INDEX, reg);
- mga_outb(M_RAMDAC_BASE+M1064_X_DATAREG, val);
-}
-
-static int inDAC1064(CPMINFO int reg) {
- mga_outb(M_RAMDAC_BASE+M1064_INDEX, reg);
- return mga_inb(M_RAMDAC_BASE+M1064_X_DATAREG);
-}
-#endif
-
#ifdef CONFIG_FB_MATROX_MILLENIUM
static const unsigned char DACseq[] =
{ TVP3026_XLATCHCTRL, TVP3026_XTRUECOLORCTRL,
@@ -1793,8 +2494,10 @@
unsigned int bestvco = 0;
unsigned int fxtal = ACCESS_FBINFO(features.pll.ref_freq);
unsigned int fwant;
- int p;
+ unsigned int p;
+ DBG("PLL_calcclock")
+
fwant = freq;
#ifdef DEBUG
@@ -1808,20 +2511,20 @@
printk(KERN_ERR "feed_div_max: %d\n", ACCESS_FBINFO(features.pll.feed_div_max));
printk(KERN_ERR "fmax: %d\n", fmax);
#endif
- for (p = 0; p < ACCESS_FBINFO(features.pll.post_shift_max); p++) {
+ for (p = 1; p <= ACCESS_FBINFO(features.pll.post_shift_max); p++) {
if (fwant * 2 > fmax)
break;
fwant *= 2;
}
if (fwant < ACCESS_FBINFO(features.pll.vco_freq_min)) fwant = ACCESS_FBINFO(features.pll.vco_freq_min);
if (fwant > fmax) fwant = fmax;
- for (; p >= 0; fwant >>= 1, bestdiff >>= 1, --p) {
- int m;
+ for (; p-- > 0; fwant >>= 1, bestdiff >>= 1) {
+ unsigned int m;
if (fwant < ACCESS_FBINFO(features.pll.vco_freq_min)) break;
for (m = ACCESS_FBINFO(features.pll.in_div_min); m <= ACCESS_FBINFO(features.pll.in_div_max); m++) {
unsigned int diff, fvco;
- int n;
+ unsigned int n;
n = (fwant * (m + 1) + (fxtal >> 1)) / fxtal - 1;
if (n > ACCESS_FBINFO(features.pll.feed_div_max))
@@ -1851,6 +2554,8 @@
unsigned int fvco;
unsigned int p;
+ DBG("DAC1064_calcclock")
+
fvco = PLL_calcclock(PMINFO freq, fmax, in, feed, &p);
p = (1 << p) - 1;
if (fvco <= 100000)
@@ -1870,6 +2575,8 @@
unsigned int fvco;
unsigned int lin, lfeed, lpost;
+ DBG("Ti3026_calcclock")
+
fvco = PLL_calcclock(PMINFO freq, fmax, &lin, &lfeed, &lpost);
fvco >>= (*post = lpost);
*in = 64 - lin;
@@ -1882,6 +2589,8 @@
unsigned int pixfeed, pixin, pixpost;
unsigned int loopfeed, loopin, looppost, loopdiv, z;
+ DBG("Ti3026_setpclk")
+
f_pll = Ti3026_calcclock(PMINFO clk, ACCESS_FBINFO(max_pixel_clock), &pixin, &pixfeed, &pixpost);
hw->DACclk[0] = pixin | 0xC0;
@@ -1916,6 +2625,13 @@
hw->DACclk[4] &= ~0xC0;
hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_4_3;
}
+ } else {
+ if (isInterleave(MINFO))
+ ; /* default... */
+ else {
+ hw->DACclk[4] ^= 0xC0; /* change from 0x80 to 0x40 */
+ hw->DACreg[POS3026_XLATCHCTRL] = TVP3026A_XLATCHCTRL_4_3;
+ }
}
hw->DACclk[5] = looppost | 0xF8;
if (ACCESS_FBINFO(devflags.mga_24bpp_fix))
@@ -1932,6 +2648,9 @@
static void var2my(struct fb_var_screeninfo* var, struct my_timming* mt) {
unsigned int pixclock = var->pixclock;
+
+ DBG("var2my")
+
if (!pixclock) pixclock = 10000; /* 10ns = 100MHz */
mt->pixclock = 1000000000 / pixclock;
if (mt->pixclock < 1) mt->pixclock = 1;
@@ -1949,12 +2668,14 @@
}
static int vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
- unsigned int hd, hs, he, ht;
+ unsigned int hd, hs, he, hbe, ht;
unsigned int vd, vs, ve, vt;
unsigned int wd;
unsigned int divider;
int i;
+ DBG("vgaHWinit")
+
hw->SEQ[0] = 0x00;
hw->SEQ[1] = 0x01; /* or 0x09 */
hw->SEQ[2] = 0x0F; /* bitplanes */
@@ -2028,6 +2749,7 @@
vt = m->VTotal - 2;
if (((ht & 0x0F) == 0x0E) || ((ht & 0x0F) == 0x04))
ht++;
+ hbe = ht;
wd = ACCESS_FBINFO(curr.var.xres_virtual) * ACCESS_FBINFO(curr.final_bppShift) / 64;
hw->CRTCEXT[0] = 0;
@@ -2043,7 +2765,7 @@
hw->CRTCEXT[1] = (((ht - 4) & 0x100) >> 8) |
((hd & 0x100) >> 7) | /* blanking */
((hs & 0x100) >> 6) | /* sync start */
- (ht & 0x040); /* end hor. blanking */
+ (hbe & 0x040); /* end hor. blanking */
hw->CRTCEXT[2] = ((vt & 0xC00) >> 10) |
((vd & 0x400) >> 8) | /* disp end */
((vd & 0xC00) >> 7) | /* vblanking start */
@@ -2054,9 +2776,9 @@
hw->CRTC[0] = ht-4;
hw->CRTC[1] = hd;
hw->CRTC[2] = hd;
- hw->CRTC[3] = (ht & 0x1F) | 0x80;
+ hw->CRTC[3] = (hbe & 0x1F) | 0x80;
hw->CRTC[4] = hs;
- hw->CRTC[5] = ((ht & 0x20) << 2) | (he & 0x1F);
+ hw->CRTC[5] = ((hbe & 0x20) << 2) | (he & 0x1F);
hw->CRTC[6] = vt & 0xFF;
hw->CRTC[7] = ((vt & 0x100) >> 8) |
((vd & 0x100) >> 7) |
@@ -2097,12 +2819,14 @@
M1064_XCRCBITSEL,
M1064_XCOLKEYMASKL, M1064_XCOLKEYMASKH, M1064_XCOLKEYL, M1064_XCOLKEYH };
+#define POS1064_XCURADDL 0
+#define POS1064_XCURADDH 1
#define POS1064_XVREFCTRL 12
#define POS1064_XMULCTRL 13
#define POS1064_XGENCTRL 15
static const unsigned char MGA1064_DAC[] = {
- 0xFF, 0x1F/*Memsizedependent*/, M1064_XCURCTRL_DIS,
+ 0x00, 0x00, M1064_XCURCTRL_DIS,
0x00, 0x00, 0x00, /* black */
0xFF, 0xFF, 0xFF, /* white */
0xFF, 0x00, 0x00, /* red */
@@ -2117,15 +2841,19 @@
static void DAC1064_setpclk(CPMINFO struct matrox_hw_state* hw, 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;
}
-static void DAC1064_setmclk(CPMINFO struct matrox_hw_state* hw, int oscinfo, unsigned long fmem) {
+__initfunc(static void DAC1064_setmclk(CPMINFO struct matrox_hw_state* hw, int oscinfo, unsigned long fmem)) {
u_int32_t mx;
+ DBG("DAC1064_setmclk")
+
mx = hw->MXoptionReg | 0x00000004;
pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx);
mx &= ~0x000000BB;
@@ -2176,6 +2904,9 @@
}
static int DAC1064_init_1(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+
+ DBG("DAC1064_init_1")
+
memcpy(hw->DACreg, MGA1064_DAC, sizeof(MGA1064_DAC_regs));
switch (ACCESS_FBINFO(curr.var.bits_per_pixel)) {
/* case 4: not supported by MGA1064 DAC */
@@ -2200,10 +2931,15 @@
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;
+ hw->DACreg[POS1064_XCURADDL] = ACCESS_FBINFO(features.DAC1064.cursorimage) >> 10;
+ hw->DACreg[POS1064_XCURADDH] = ACCESS_FBINFO(features.DAC1064.cursorimage) >> 18;
return 0;
}
static int DAC1064_init_2(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+
+ DBG("DAC1064_init_2")
+
DAC1064_setpclk(PMINFO hw, m->pixclock);
if (ACCESS_FBINFO(curr.var.bits_per_pixel) > 16) { /* 256 entries */
int i;
@@ -2243,22 +2979,40 @@
}
static void DAC1064_restore_1(CPMINFO const struct matrox_hw_state* hw, const struct matrox_hw_state* oldhw) {
+
+ DBG("DAC1064_restore_1")
+
outDAC1064(PMINFO DAC1064_XSYSPLLM, hw->DACclk[3]);
outDAC1064(PMINFO DAC1064_XSYSPLLN, hw->DACclk[4]);
outDAC1064(PMINFO DAC1064_XSYSPLLP, hw->DACclk[5]);
if (!oldhw || memcmp(hw->DACreg, oldhw->DACreg, sizeof(MGA1064_DAC_regs))) {
- int i;
+ unsigned int i;
for (i = 0; i < sizeof(MGA1064_DAC_regs); i++)
outDAC1064(PMINFO MGA1064_DAC_regs[i], hw->DACreg[i]);
}
}
-static void DAC1064_restore_2(CPMINFO const struct matrox_hw_state* hw, const struct matrox_hw_state* oldhw) {
- int i;
+static void DAC1064_restore_2(WPMINFO const struct matrox_hw_state* hw, const struct matrox_hw_state* oldhw, struct display* p) {
+ unsigned int i;
+
+ DBG("DAC1064_restore_2")
+
for (i = 0; i < 3; i++)
outDAC1064(PMINFO M1064_XPIXPLLCM + i, hw->DACclk[i]);
while (!(inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40));
+ if (p && p->conp) {
+ matroxfb_DAC1064_createcursor(PMINFO p);
+ i = matroxfb_fastfont_tryset(PMINFO p);
+ } else
+ i = 0;
+ if (i) {
+ ACCESS_FBINFO(curr.putc) = matrox_cfbX_fastputc;
+ ACCESS_FBINFO(curr.putcs) = matrox_cfbX_fastputcs;
+ } else {
+ ACCESS_FBINFO(curr.putc) = matrox_cfbX_putc;
+ ACCESS_FBINFO(curr.putcs) = matrox_cfbX_putcs;
+ }
#ifdef DEBUG
dprintk(KERN_DEBUG "DAC1064regs ");
for (i = 0; i < sizeof(MGA1064_DAC_regs); i++) {
@@ -2275,6 +3029,9 @@
#ifdef CONFIG_FB_MATROX_MYSTIQUE
static int MGA1064_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+
+ DBG("MGA1064_init")
+
if (DAC1064_init_1(PMINFO hw, m)) return 1;
if (vgaHWinit(PMINFO hw, m)) return 1;
@@ -2293,6 +3050,9 @@
#ifdef CONFIG_FB_MATROX_G100
static int MGAG100_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+
+ DBG("MGAG100_init")
+
if (DAC1064_init_1(PMINFO hw, m)) return 1;
hw->MXoptionReg &= ~0x2000;
if (vgaHWinit(PMINFO hw, m)) return 1;
@@ -2314,6 +3074,8 @@
static int Ti3026_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
u_int8_t muxctrl = isInterleave(MINFO) ? TVP3026_XMUXCTRL_MEMORY_64BIT : TVP3026_XMUXCTRL_MEMORY_32BIT;
+ DBG("Ti3026_init")
+
memcpy(hw->DACreg, MGADACbpp32, sizeof(hw->DACreg));
switch (ACCESS_FBINFO(curr.var.bits_per_pixel)) {
case 4: hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_16_1; /* or _8_1, they are same */
@@ -2359,15 +3121,17 @@
hw->DACreg[POS3026_XGENCTRL] |= TVP3026_XGENCTRL_SYNC_ON_GREEN;
/* set DELAY */
- if (ACCESS_FBINFO(video_len) < 0x400000)
+ if (ACCESS_FBINFO(video.len) < 0x400000)
hw->CRTCEXT[3] |= 0x08;
- else if (ACCESS_FBINFO(video_len) > 0x400000)
+ else if (ACCESS_FBINFO(video.len) > 0x400000)
hw->CRTCEXT[3] |= 0x10;
/* set HWCURSOR */
if (m->interlaced) {
hw->DACreg[POS3026_XCURCTRL] |= TVP3026_XCURCTRL_INTERLACED;
}
+ if (m->HTotal >= 1536)
+ hw->DACreg[POS3026_XCURCTRL] |= TVP3026_XCURCTRL_BLANK4096;
/* set interleaving */
hw->MXoptionReg &= ~0x00001000;
@@ -2380,6 +3144,9 @@
#endif /* CONFIG_FB_MATROX_MILLENIUM */
static int matroxfb_get_cmap_len(struct fb_var_screeninfo *var) {
+
+ DBG("matroxfb_get_cmap_len")
+
switch (var->bits_per_pixel) {
#ifdef FBCON_HAS_CFB4
case 4:
@@ -2412,6 +3179,8 @@
unsigned int vramlen;
unsigned int memlen;
+ DBG("matroxfb_decode_var")
+
if ((var->xres > var->xres_virtual) || (var->yres > var->yres_virtual) ||
(var->xoffset > var->xres_virtual) || (var->yoffset > var->yres_virtual))
return -EINVAL;
@@ -2434,8 +3203,7 @@
#endif
default: return -EINVAL;
}
- vramlen = ACCESS_FBINFO(video_len);
- if (vramlen > 0x800000) vramlen = 0x800000;
+ vramlen = ACCESS_FBINFO(video.len_usable);
var->xres_virtual = matroxfb_pitch_adjust(PMINFO var->xres_virtual, var->bits_per_pixel);
memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8;
if (memlen > vramlen)
@@ -2443,7 +3211,7 @@
/* There is hardware bug that no line can cross 4MB boundary */
/* give up for CFB24, it is impossible to easy workaround it */
/* for other try to do something */
- if ((memlen > 0x400000) && (var->bits_per_pixel != 24)) {
+ if (!ACCESS_FBINFO(capable.cross4MB) && (memlen > 0x400000) && (var->bits_per_pixel != 24)) {
int new_xres = var->xres_virtual;
if (new_xres <= 512)
@@ -2458,7 +3226,7 @@
/* if now out of memory, try shrink virtual height */
/* but if new virtual height is smaller than visible height, return -EINVAL */
if (var->yres_virtual * memlen > vramlen) {
- int new_yres;
+ unsigned int new_yres;
new_yres = vramlen / memlen;
if (new_yres < var->yres)
@@ -2554,6 +3322,8 @@
unsigned int rfhcnt, mclk_ctl;
int tmout;
+ DBG("ti3026_setMCLK")
+
f_pll = Ti3026_calcclock(PMINFO fout, ACCESS_FBINFO(max_pixel_clock), &mclk_n, &mclk_m, &mclk_p);
/* save pclk */
@@ -2645,6 +3415,9 @@
}
__initfunc(static void ti3026_ramdac_init(WPMINFO struct matrox_hw_state* hw)) {
+
+ DBG("ti3026_ramdac_init")
+
ACCESS_FBINFO(features.pll.vco_freq_min) = 110000;
ACCESS_FBINFO(features.pll.ref_freq) = 114545;
ACCESS_FBINFO(features.pll.feed_div_min) = 2;
@@ -2652,14 +3425,37 @@
ACCESS_FBINFO(features.pll.in_div_min) = 2;
ACCESS_FBINFO(features.pll.in_div_max) = 63;
ACCESS_FBINFO(features.pll.post_shift_max) = 3;
- ACCESS_FBINFO(max_pixel_clock) = 220000;
ti3026_setMCLK(PMINFO hw, 60000);
}
#endif
+__initfunc(static void matroxfb_fastfont_init(struct matrox_fb_info* minfo)) {
+ unsigned int size;
+
+ size = ACCESS_FBINFO(fastfont.size);
+ ACCESS_FBINFO(fastfont.size) = 0;
+ if (size) {
+ unsigned int end = ACCESS_FBINFO(video.len_usable);
+
+ if (size < end) {
+ unsigned int start;
+
+ start = (end - size) & PAGE_MASK;
+ if (start >= 0x00100000) {
+ ACCESS_FBINFO(video.len_usable) = start;
+ ACCESS_FBINFO(fastfont.mgabase) = start * 8;
+ ACCESS_FBINFO(fastfont.vbase) = ACCESS_FBINFO(video.vbase);
+ vaddr_add(&ACCESS_FBINFO(fastfont.vbase), start);
+ ACCESS_FBINFO(fastfont.size) = end - start;
+ }
+ }
+ }
+}
+
#ifdef CONFIG_FB_MATROX_MYSTIQUE
__initfunc(static void MGA1064_ramdac_init(WPMINFO struct matrox_hw_state* hw)) {
- unsigned char rev;
+
+ DBG("MGA1064_ramdac_init");
/* ACCESS_FBINFO(features.DAC1064.vco_freq_min) = 120000; */
ACCESS_FBINFO(features.pll.vco_freq_min) = 50000;
@@ -2670,12 +3466,6 @@
ACCESS_FBINFO(features.pll.in_div_max) = 31;
ACCESS_FBINFO(features.pll.post_shift_max) = 3;
ACCESS_FBINFO(features.DAC1064.xvrefctrl) = DAC1064_XVREFCTRL_EXTERNAL;
- /* I hope */
- pci_read_config_byte(ACCESS_FBINFO(pcidev), PCI_REVISION_ID, &rev);
- if (rev < 3)
- ACCESS_FBINFO(max_pixel_clock) = 170000;
- else
- ACCESS_FBINFO(max_pixel_clock) = 220000;
/* 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);
}
@@ -2684,9 +3474,12 @@
static const int vxres_mystique[] = { 512, 640, 768, 800, 832, 960,
1024, 1152, 1280, 1600, 1664, 1920,
2048, 0};
+ DBG("MGA1064_preinit")
+
/* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */
ACCESS_FBINFO(capable.vxres) = vxres_mystique;
ACCESS_FBINFO(features.accel.has_cacheflush) = 1;
+ ACCESS_FBINFO(cursor.timer.function) = matroxfb_DAC1064_flashcursor;
hw->MXoptionReg &= 0xC0000100;
hw->MXoptionReg |= 0x00094E20;
@@ -2707,6 +3500,13 @@
}
__initfunc(static void MGA1064_reset(WPMINFO struct matrox_hw_state* hw)) {
+
+ DBG("MGA1064_reset");
+
+ ACCESS_FBINFO(features.DAC1064.cursorimage) = ACCESS_FBINFO(video.len_usable) - 1024;
+ if (ACCESS_FBINFO(devflags.hwcursor))
+ ACCESS_FBINFO(video.len_usable) -= 1024;
+ matroxfb_fastfont_init(MINFO);
MGA1064_ramdac_init(PMINFO hw);
}
#endif
@@ -2718,22 +3518,13 @@
static int def50 = 0; /* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */
#endif
-#if 0
-__initfunc(static int G100_ReadFeatureConn(const struct matrox_fb_info* minfo)) {
- int ret;
-
- mga_outb(M_3DA_WR, 0x01);
- ret = (mga_inb(M_3C2_RD) >> 5) & 0x03;
- mga_outb(M_3DA_WR, 0x02);
- return ret | ((mga_inb(M_3C2_RD) >> 3) & 0x0C);
-}
-#endif
-
__initfunc(static void MGAG100_progPixClock(CPMINFO int flags, int m, int n, int p)) {
int reg;
int selClk;
int clk;
+ DBG("MGAG100_progPixClock")
+
outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) | M1064_XPIXCLKCTRL_DIS);
switch (flags & 3) {
case 0: reg = M1064_XPIXPLLAM; break;
@@ -2771,6 +3562,8 @@
__initfunc(static void MGAG100_setPixClock(CPMINFO int flags, int freq)) {
unsigned int m, n, p;
+ DBG("MGAG100_setPixClock")
+
DAC1064_calcclock(PMINFO freq, ACCESS_FBINFO(max_pixel_clock), &m, &n, &p);
MGAG100_progPixClock(PMINFO flags, m, n, p);
}
@@ -2784,9 +3577,12 @@
u_int32_t q;
#endif
+ DBG("MGAG100_preinit")
+
/* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */
ACCESS_FBINFO(capable.vxres) = vxres_g100;
ACCESS_FBINFO(features.accel.has_cacheflush) = 1;
+ ACCESS_FBINFO(cursor.timer.function) = matroxfb_DAC1064_flashcursor;
hw->MXoptionReg &= 0xC0000100;
hw->MXoptionReg |= 0x00078C20;
@@ -2813,24 +3609,20 @@
mga_outb(0x1C05, 0xC0);
pci_write_config_byte(ACCESS_FBINFO(pcidev), 0x50, def50 & 0x0F);
{
- volatile u_int8_t* ptr;
mga_outb(M_GRAPHICS_INDEX, 6);
mga_outb(M_GRAPHICS_DATA, (mga_inb(M_GRAPHICS_DATA) & 3) | 4);
mga_setr(M_EXTVGA_INDEX, 0x03, 0x81);
mga_setr(M_EXTVGA_INDEX, 0x04, 0x00);
- ptr = ACCESS_FBINFO(video_vbase);
- ptr[0x000] = 0xAA;
- ptr[0x800] = 0x55;
- if (ptr[0x000] != 0xAA) {
+ mga_writeb(ACCESS_FBINFO(video.vbase), 0x000, 0xAA);
+ mga_writeb(ACCESS_FBINFO(video.vbase), 0x800, 0x55);
+ if (mga_readb(ACCESS_FBINFO(video.vbase), 0x000) != 0xAA) {
hw->MXoptionReg &= ~0x1000;
}
}
#endif
hw->MXoptionReg = (hw->MXoptionReg & ~0x1F8000) | 0x78000;
-#if 0
if (!(x7AF4 & 0x10))
hw->MXoptionReg |= 0x4000;
-#endif
pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
return 0;
}
@@ -2838,6 +3630,8 @@
__initfunc(static void MGAG100_reset(WPMINFO struct matrox_hw_state* hw)) {
u_int8_t b;
+ DBG("MGAG100_reset")
+
ACCESS_FBINFO(features.pll.vco_freq_min) = 50000;
ACCESS_FBINFO(features.pll.ref_freq) = 27000;
ACCESS_FBINFO(features.pll.feed_div_min) = 7;
@@ -2846,7 +3640,10 @@
ACCESS_FBINFO(features.pll.in_div_max) = 31;
ACCESS_FBINFO(features.pll.post_shift_max) = 3;
ACCESS_FBINFO(features.DAC1064.xvrefctrl) = DAC1064_XVREFCTRL_G100_DEFAULT;
- ACCESS_FBINFO(max_pixel_clock) = 220000;
+ ACCESS_FBINFO(features.DAC1064.cursorimage) = ACCESS_FBINFO(video.len_usable) - 1024;
+ if (ACCESS_FBINFO(devflags.hwcursor))
+ ACCESS_FBINFO(video.len_usable) -= 1024;
+ matroxfb_fastfont_init(MINFO);
{
#ifdef G100_BROKEN_IBM_82351
@@ -2882,6 +3679,8 @@
static void vgaHWrestore(CPMINFO struct matrox_hw_state* hw, struct matrox_hw_state* oldhw) {
int i;
+ DBG("vgaHWrestore")
+
dprintk(KERN_INFO "MiscOutReg: %02X\n", hw->MiscOutReg);
dprintk(KERN_INFO "SEQ regs: ");
for (i = 0; i < 5; i++)
@@ -2930,6 +3729,9 @@
#ifdef CONFIG_FB_MATROX_MULTIHEAD
struct matrox_fb_info* minfo = (struct matrox_fb_info*)fb_info;
#endif
+
+ DBG("matrox_setcolreg")
+
/*
* Set a single color register. The values supplied are
* already rounded down to the hardware's capabilities
@@ -2945,6 +3747,11 @@
ACCESS_FBINFO(palette[regno].blue) = blue;
ACCESS_FBINFO(palette[regno].transp) = transp;
+ if (ACCESS_FBINFO(curr.var.grayscale)) {
+ /* gray = 0.30*R + 0.59*G + 0.11*B */
+ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+ }
+
red = CNVT_TOHW(red, ACCESS_FBINFO(curr.var.red.length));
green = CNVT_TOHW(green, ACCESS_FBINFO(curr.var.green.length));
blue = CNVT_TOHW(blue, ACCESS_FBINFO(curr.var.blue.length));
@@ -2998,6 +3805,8 @@
{
struct display* dsp;
+ DBG("do_install_cmap")
+
if (con != ACCESS_FBINFO(currcon))
return;
if (con >= 0)
@@ -3015,14 +3824,16 @@
static void MGA1064_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_state* oldhw, struct display* p) {
int i;
+ DBG("MGA1064_restore")
+
pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
mga_outb(M_IEN, 0x00);
mga_outb(M_CACHEFLUSH, 0x00);
DAC1064_restore_1(PMINFO hw, oldhw);
+ vgaHWrestore(PMINFO hw, oldhw);
for (i = 0; i < 6; i++)
mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
- vgaHWrestore(PMINFO hw, oldhw);
- DAC1064_restore_2(PMINFO hw, oldhw);
+ DAC1064_restore_2(PMINFO hw, oldhw, p);
}
#endif
@@ -3030,12 +3841,14 @@
static void MGAG100_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_state* oldhw, struct display* p) {
int i;
+ DBG("MGAG100_restore")
+
pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
DAC1064_restore_1(PMINFO hw, oldhw);
+ vgaHWrestore(PMINFO hw, oldhw);
for (i = 0; i < 6; i++)
mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
- vgaHWrestore(PMINFO hw, oldhw);
- DAC1064_restore_2(PMINFO hw, oldhw);
+ DAC1064_restore_2(PMINFO hw, oldhw, p);
}
#endif
@@ -3043,17 +3856,18 @@
static void Ti3026_restore(WPMINFO struct matrox_hw_state* hw, struct matrox_hw_state* oldhw, struct display* p) {
int i;
+ DBG("Ti3026_restore")
+
dprintk(KERN_INFO "EXTVGA regs: ");
for (i = 0; i < 6; i++)
dprintk("%02X:", hw->CRTCEXT[i]);
dprintk("\n");
- for (i = 0; i < 6; i++)
- mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
-
pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
vgaHWrestore(PMINFO hw, oldhw);
+ for (i = 0; i < 6; i++)
+ mga_setr(M_EXTVGA_INDEX, i, hw->CRTCEXT[i]);
for (i = 0; i < 21; i++) {
outTi3026(PMINFO DACseq[i], hw->DACreg[i]);
@@ -3071,7 +3885,7 @@
outTi3026(PMINFO TVP3026_XPLLADDR, 0x00);
for (i = 0; i < 3; i++)
outTi3026(PMINFO TVP3026_XPIXPLLDATA, hw->DACclk[i]);
- /* wait for PLL only if PLL clock requested (always for PowerMode) */
+ /* wait for PLL only if PLL clock requested (always for PowerMode, never for VGA) */
if (hw->MiscOutReg & 0x08) {
int tmout;
outTi3026(PMINFO TVP3026_XPLLADDR, 0x3F);
@@ -3104,7 +3918,18 @@
dprintk(KERN_INFO "LoopPLL: %d\n", 500000-tmout);
}
}
- matroxfb_ti3026_createcursor(PMINFO fontwidth(p), fontheight(p));
+ if (p && p->conp) {
+ matroxfb_ti3026_createcursor(PMINFO p);
+ i = matroxfb_fastfont_tryset(PMINFO p);
+ } else
+ i = 0;
+ if (i) {
+ ACCESS_FBINFO(curr.putc) = matrox_cfbX_fastputc;
+ ACCESS_FBINFO(curr.putcs) = matrox_cfbX_fastputcs;
+ } else {
+ ACCESS_FBINFO(curr.putc) = matrox_cfbX_putc;
+ ACCESS_FBINFO(curr.putcs) = matrox_cfbX_putcs;
+ }
dprintk(KERN_DEBUG "3026DACregs ");
for (i = 0; i < 21; i++) {
@@ -3121,20 +3946,23 @@
static int matroxfb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info)
{
+
+ DBG("matroxfb_get_fix")
+
#define minfo ((struct matrox_fb_info*)info)
memset(fix, 0, sizeof(struct fb_fix_screeninfo));
strcpy(fix->id,"MATROX");
- fix->smem_start = (void*)ACCESS_FBINFO(video_base);
- fix->smem_len = ACCESS_FBINFO(video_len);
+ fix->smem_start = (void*)ACCESS_FBINFO(video.base);
+ fix->smem_len = ACCESS_FBINFO(video.len);
fix->type = ACCESS_FBINFO(curr.video_type);
fix->visual = ACCESS_FBINFO(curr.visual);
fix->xpanstep = 8; /* 8 for 8bpp, 4 for 16bpp, 2 for 32bpp */
fix->ypanstep = 1;
fix->ywrapstep = 0;
fix->line_length = (ACCESS_FBINFO(curr.var.xres_virtual) * ACCESS_FBINFO(curr.var.bits_per_pixel)) >> 3;
- fix->mmio_start = (void*)ACCESS_FBINFO(mmio_base);
- fix->mmio_len = ACCESS_FBINFO(mmio_len);
+ fix->mmio_start = (void*)ACCESS_FBINFO(mmio.base);
+ fix->mmio_len = ACCESS_FBINFO(mmio.len);
fix->accel = ACCESS_FBINFO(devflags.accelerator);
return 0;
#undef minfo
@@ -3143,6 +3971,9 @@
static int matroxfb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
+
+ DBG("matroxfb_get_var")
+
if(con < 0)
*var=ACCESS_FBINFO2(info, curr.var);
else
@@ -3160,6 +3991,8 @@
struct display* display;
int chgvar;
+ DBG("matroxfb_set_var")
+
if ((err = matroxfb_decode_var(PMINFO var, &visual, &cmap_len)) != 0)
return err;
switch (var->activate & FB_ACTIVATE_MASK) {
@@ -3184,7 +4017,7 @@
}
display->var = *var;
/* cmap */
- display->screen_base = ACCESS_FBINFO(video_vbase);
+ display->screen_base = vaddr_va(ACCESS_FBINFO(video.vbase));
display->visual = visual;
display->type = FB_TYPE_PACKED_PIXELS;
display->type_aux = 0;
@@ -3195,7 +4028,7 @@
display->inverse = ACCESS_FBINFO(devflags.inverse);
/* conp, fb_info, vrows, cursor_x, cursor_y, fgcol, bgcol */
/* next_plane, fontdata, _font*, userfont */
- initMatrox(PMINFO con, display); /* dispsw */
+ initMatrox(PMINFO display); /* dispsw */
/* dispsw, scrollmode, yscroll */
/* fgshift, bgshift, charmask */
if (chgvar && info && info->changevar)
@@ -3234,6 +4067,9 @@
memcpy(hw->DACclk, ohw->DACclk, sizeof(hw->DACclk));
/* others are initialized by init() */
+ del_timer(&ACCESS_FBINFO(cursor.timer));
+ ACCESS_FBINFO(cursor.state) = CM_ERASE;
+
ACCESS_FBINFO(hw_switch->init(PMINFO hw, &mt));
pos = (var->yoffset * var->xres_virtual + var->xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32;
if (mga_ydstorg(MINFO)) {
@@ -3251,6 +4087,27 @@
ACCESS_FBINFO(newhw) = ohw;
matrox_cfbX_init(MINFO);
do_install_cmap(PMINFO con);
+#if defined(CONFIG_FB_COMPAT_XPMAC)
+ if (console_fb_info == &ACCESS_FBINFO(fbcon)) {
+ int vmode, cmode;
+
+ display_info.width = var->xres;
+ display_info.height = var->yres;
+ display_info.depth = var->bits_per_pixel;
+ display_info.pitch = (var->xres_virtual)*(var->bits_per_pixel)/8;
+ if (mac_var_to_vmode(var, &vmode, &cmode)
+ display_info.mode = 0;
+ else
+ display_info.mode = vmode;
+ strcpy(display_info.name, ACCESS_FBINFO(matrox_name));
+ display_info.fb_address = ACCESS_FBINFO(video.base);
+ /* we should not expose this addresses outside of driver. Every access to DAC must be
+ exclusive locked by spinlock_irq(ACCESS_FBINFO(lock.DAC)) or by turning hardware cursor (flashing) OFF */
+ display_info.cmap_adr_address = ACCESS_FBINFO(mmio.base) + M_DAC_REG;
+ display_info.cmap_data_address = ACCESS_FBINFO(mmio.base) + M_DAC_VAL;
+ display_info.disp_reg_address = ACCESS_FBINFO(mmio.base);
+ }
+#endif /* CONFIG_FB_COMPAT_XPMAC */
}
}
return 0;
@@ -3261,6 +4118,9 @@
unsigned *blue, unsigned *transp,
struct fb_info *info)
{
+
+ DBG("matrox_getcolreg")
+
#define minfo ((struct matrox_fb_info*)info)
/*
* Read a single color register and split it into colors/transparent.
@@ -3283,6 +4143,8 @@
{
struct display* dsp = (con < 0) ? info->disp : fb_display+con;
+ DBG("matroxfb_get_cmap")
+
if (con == ACCESS_FBINFO2(info, currcon)) /* current console? */
return fb_get_cmap(cmap, kspc, matrox_getcolreg, info);
else if (dsp->cmap.len) /* non default colormap? */
@@ -3296,9 +4158,11 @@
static int matroxfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
- int cmap_len;
+ unsigned int cmap_len;
struct display* dsp = (con < 0) ? info->disp : (fb_display + con);
+ DBG("matroxfb_set_cmap")
+
cmap_len = matroxfb_get_cmap_len(&dsp->var);
if (dsp->cmap.len != cmap_len) {
int err;
@@ -3318,6 +4182,9 @@
unsigned int cmd, unsigned long arg, int con,
struct fb_info *info)
{
+
+ DBG("matroxfb_ioctl")
+
return -EINVAL;
}
@@ -3336,8 +4203,12 @@
static int matroxfb_switch(int con, struct fb_info *info)
{
+#define minfo ((struct matrox_fb_info*)info)
struct fb_cmap* cmap;
- if (ACCESS_FBINFO2(info, currcon) >= 0) {
+
+ DBG("matroxfb_switch");
+
+ if (ACCESS_FBINFO(currcon) >= 0) {
/* Do we have to save the colormap? */
cmap = &fb_display[ACCESS_FBINFO2(info, currcon)].cmap;
dprintk(KERN_DEBUG "switch1: con = %d, cmap.len = %d\n", ACCESS_FBINFO2(info, currcon), cmap->len);
@@ -3352,7 +4223,8 @@
#endif
}
}
- ACCESS_FBINFO2(info, currcon) = con;
+ ACCESS_FBINFO(currcon) = con;
+ ACCESS_FBINFO(currcon_display) = fb_display+con;
fb_display[con].var.activate = FB_ACTIVATE_NOW;
#ifdef DEBUG
cmap = &fb_display[con].cmap;
@@ -3371,6 +4243,7 @@
}
#endif
return 0;
+#undef minfo
}
/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
@@ -3381,6 +4254,8 @@
int seq;
int crtc;
+ DBG("matroxfb_blank")
+
switch (blank) {
case 1: seq = 0x20; crtc = 0x00; break; /* works ??? */
case 2: seq = 0x20; crtc = 0x10; break;
@@ -3438,7 +4313,7 @@
};
#define RSCreate(X,Y) ((X) | ((Y) << 4))
-static struct { int vesa; int info; } *RSptr, vesamap[] __initdata = {
+static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __initdata = {
/* default must be first */
#ifdef FBCON_HAS_CFB8
{ 0x101, RSCreate(RS640x480, RS8bpp ) },
@@ -3503,6 +4378,7 @@
static unsigned int mem = 0; /* "matrox:mem:xxxxxM" */
static int option_precise_width = 1; /* cannot be changed, option_precise_width==0 must imply noaccel */
static int inv24 = 0; /* "matrox:inv24" */
+static int cross4MB = -1; /* "matrox:cross4MB" */
static int disabled = 0; /* "matrox:disabled" */
static int noaccel = 0; /* "matrox:noaccel" */
static int nopan = 0; /* "matrox:nopan" */
@@ -3510,7 +4386,10 @@
static int novga = 0; /* "matrox:novga" */
static int nobios = 0; /* "matrox:nobios" */
static int inverse = 0; /* "matrox:inverse" */
-static int hwcursor = 0; /* "matrox:hwcursor" */
+static int hwcursor = 1; /* "matrox:nohwcursor" */
+static int blink = 1; /* "matrox:noblink" */
+static int grayscale = 0; /* "matrox:grayscale" */
+static unsigned int fastfont = 0; /* "matrox:fastfont:xxxxx" */
static int dev = -1; /* "matrox:dev:xxxxx" */
static unsigned int vesa = 0x101; /* "matrox:vesa:xxxxx" */
static unsigned int depth = 0; /* "matrox:depth:xxxxx" */
@@ -3524,15 +4403,17 @@
static unsigned int hslen = 0; /* "matrox:hslen:xxxxx" */
static unsigned int pixclock = 0; /* "matrox:pixclock:xxxxx" */
static int sync = -1; /* "matrox:sync:xxxxx" */
-static int fv = 0; /* "matrox:fv:xxxxx" */
-static int fh = 0; /* "matrox:fh:xxxxxk" */
-static int maxclk = 0; /* "matrox:maxclk:xxxxM" */
+static unsigned int fv = 0; /* "matrox:fv:xxxxx" */
+static unsigned int fh = 0; /* "matrox:fh:xxxxxk" */
+static unsigned int maxclk = 0; /* "matrox:maxclk:xxxxM" */
static char fontname[64]; /* "matrox:font:xxxxx" */
#ifndef MODULE
__initfunc(void matroxfb_setup(char *options, int *ints)) {
char *this_opt;
+ DBG("matroxfb_setup")
+
fontname[0] = '\0';
if (!options || !*options)
@@ -3542,26 +4423,8 @@
if (!*this_opt) continue;
dprintk("matroxfb_setup: option %s\n", this_opt);
-
- if (! strcmp(this_opt, "inverse"))
- inverse = 1;
- else if (!strcmp(this_opt, "disabled"))
- disabled = 1;
- else if (!strcmp(this_opt, "noaccel"))
- noaccel = 1;
- else if (!strcmp(this_opt, "nopan"))
- nopan = 1;
- else if (!strcmp(this_opt, "nopciretry"))
- no_pci_retry = 1;
- else if (!strcmp(this_opt, "novga"))
- novga = 1;
- else if (!strcmp(this_opt, "nobios"))
- nobios = 1;
- else if (!strcmp(this_opt, "inv24"))
- inv24 = 1;
- else if (!strcmp(this_opt, "hwcursor"))
- hwcursor = 1;
- else if (!strncmp(this_opt, "dev:", 4))
+
+ if (!strncmp(this_opt, "dev:", 4))
dev = simple_strtoul(this_opt+4, NULL, 0);
else if (!strncmp(this_opt, "depth:", 6)) {
switch (simple_strtoul(this_opt+6, NULL, 0)) {
@@ -3606,17 +4469,55 @@
fv = simple_strtoul(this_opt+3, NULL, 0);
else if (!strncmp(this_opt, "mem:", 4))
mem = simple_strtoul(this_opt+4, NULL, 0);
+ else if (!strncmp(this_opt, "fastfont:", 9))
+ fastfont = simple_strtoul(this_opt+9, NULL, 0);
+ else if (!strcmp(this_opt, "nofastfont")) /* fastfont:N and nofastfont (nofastfont = fastfont:0) */
+ fastfont = 0;
+ else if (!strcmp(this_opt, "disabled")) /* nodisabled does not exist */
+ disabled = 1;
+ else if (!strcmp(this_opt, "enabled")) /* noenabled does not exist */
+ disabled = 0;
else {
- printk(KERN_ERR "matroxfb: unknown parameter %s\n", this_opt);
+ int value = 1;
+
+ if (!strncmp(this_opt, "no", 2)) {
+ value = 0;
+ this_opt += 2;
+ }
+ if (! strcmp(this_opt, "inverse"))
+ inverse = value;
+ else if (!strcmp(this_opt, "accel"))
+ noaccel = !value;
+ else if (!strcmp(this_opt, "pan"))
+ nopan = !value;
+ else if (!strcmp(this_opt, "pciretry"))
+ no_pci_retry = !value;
+ else if (!strcmp(this_opt, "vga"))
+ novga = !value;
+ else if (!strcmp(this_opt, "bios"))
+ nobios = !value;
+ else if (!strcmp(this_opt, "inv24"))
+ inv24 = value;
+ else if (!strcmp(this_opt, "cross4MB"))
+ cross4MB = value;
+ else if (!strcmp(this_opt, "hwcursor"))
+ hwcursor = value;
+ else if (!strcmp(this_opt, "blink"))
+ blink = value;
+ else if (!strcmp(this_opt, "grayscale"))
+ grayscale = value;
+ else {
+ printk(KERN_ERR "matroxfb: unknown parameter %s%s\n", value?"":"no", this_opt);
+ }
}
}
}
#endif
-__initfunc(static int matroxfb_getmemory(WPMINFO int maxSize, unsigned int* realOffset, int *realSize)) {
- volatile unsigned char* vm;
- int offs;
- int offs2;
+__initfunc(static int matroxfb_getmemory(WPMINFO unsigned int maxSize, unsigned int* realOffset, unsigned int *realSize)) {
+ vaddr_t vm;
+ unsigned int offs;
+ unsigned int offs2;
unsigned char store;
unsigned char bytes[16];
unsigned char* tmp;
@@ -3625,7 +4526,9 @@
unsigned int clen;
unsigned int mlen;
- vm = ACCESS_FBINFO(video_vbase);
+ DBG("matroxfb_getmemory")
+
+ vm = ACCESS_FBINFO(video.vbase);
maxSize &= ~0x1FFFFF; /* must be X*2MB (really it must be 2 or X*4MB) */
/* at least 2MB */
if (maxSize < 0x0200000) return 0;
@@ -3634,23 +4537,23 @@
mga_outb(M_EXTVGA_INDEX, 0x03);
mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) | 0x80);
- store = vm[0x1234];
+ store = mga_readb(vm, 0x1234);
tmp = bytes;
for (offs = 0x100000; offs < maxSize; offs += 0x200000)
- *tmp++ = vm[offs];
+ *tmp++ = mga_readb(vm, offs);
for (offs = 0x100000; offs < maxSize; offs += 0x200000)
- vm[offs] = 0x02;
+ mga_writeb(vm, offs, 0x02);
if (ACCESS_FBINFO(features.accel.has_cacheflush))
mga_outb(M_CACHEFLUSH, 0x00);
else
- vm[0x1234] = 0x99;
+ mga_writeb(vm, 0x1234, 0x99);
cbase = mbase = 0;
clen = mlen = 0;
for (offs = 0x100000; offs < maxSize; offs += 0x200000) {
- if (vm[offs] != 0x02)
+ if (mga_readb(vm, offs) != 0x02)
continue;
- vm[offs] -= 0x02;
- if (vm[offs])
+ mga_writeb(vm, offs, mga_readb(vm, offs) - 0x02);
+ if (mga_readb(vm, offs))
continue;
if (offs - 0x100000 == cbase + clen) {
clen += 0x200000;
@@ -3669,8 +4572,8 @@
}
tmp = bytes;
for (offs2 = 0x100000; offs2 < maxSize; offs2 += 0x200000)
- vm[offs2] = *tmp++;
- vm[0x1234] = store;
+ mga_writeb(vm, offs2, *tmp++);
+ mga_writeb(vm, 0x1234, store);
mga_outb(M_EXTVGA_INDEX, 0x03);
mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) & ~0x80);
@@ -3691,10 +4594,15 @@
static const int vxres_mill1[] = { 640, 768, 800, 960,
1024, 1152, 1280, 1600, 1920,
2048, 0};
+
+ DBG("Ti3026_preinit")
+
ACCESS_FBINFO(millenium) = 1;
ACCESS_FBINFO(milleniumII) = (ACCESS_FBINFO(pcidev)->device != PCI_DEVICE_ID_MATROX_MIL);
ACCESS_FBINFO(capable.cfb4) = 1;
ACCESS_FBINFO(capable.vxres) = isMilleniumII(MINFO)?vxres_mill2:vxres_mill1;
+ ACCESS_FBINFO(cursor.timer.function) = matroxfb_ti3026_flashcursor;
+
/* preserve VGA I/O, BIOS and PPC */
hw->MXoptionReg &= 0xC0000100;
hw->MXoptionReg |= 0x002C0000;
@@ -3705,10 +4613,7 @@
if (ACCESS_FBINFO(devflags.nopciretry))
hw->MXoptionReg |= 0x20000000;
pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
- return 0;
-}
-__initfunc(static void Ti3026_reset(WPMINFO struct matrox_hw_state* hw)) {
ACCESS_FBINFO(accel.ramdac_rev) = inTi3026(PMINFO TVP3026_XSILICONREV);
outTi3026(PMINFO TVP3026_XCLKCTRL, TVP3026_XCLKCTRL_SRC_CLK0VGA | TVP3026_XCLKCTRL_CLKSTOPPED);
@@ -3723,15 +4628,22 @@
outTi3026(PMINFO TVP3026_XMEMPLLCTRL, TVP3026_XMEMPLLCTRL_STROBEMKC4 | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL);
- ti3026_ramdac_init(PMINFO hw);
-
- dprintk(KERN_INFO "matroxfb: PCI OPTION = %08X\n", hw->MXoptionReg);
-
mga_outl(M_RESET, 1);
udelay(250);
mga_outl(M_RESET, 0);
udelay(250);
- /* wait for retrace, draw black square and so on... */
+ mga_outl(M_MACCESS, 0x00008000);
+ udelay(10);
+ return 0;
+}
+
+__initfunc(static void Ti3026_reset(WPMINFO struct matrox_hw_state* hw)) {
+
+ DBG("Ti3026_reset")
+
+ matroxfb_fastfont_init(MINFO);
+
+ ti3026_ramdac_init(PMINFO hw);
}
#endif
@@ -3775,9 +4687,11 @@
#define DEVF_SWAPS 0x02
#define DEVF_MILLENIUM 0x04
#define DEVF_MILLENIUM2 0x08
+#define DEVF_CROSS4MB 0x10
static struct board {
unsigned short vendor, device, rev, svid, sid;
- unsigned flags;
+ unsigned int flags;
+ unsigned int maxclk;
struct video_board* base;
const char* name;
} dev_list[] __initdata = {
@@ -3785,118 +4699,142 @@
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL, 0xFF,
0, 0,
DEVF_MILLENIUM,
+ 220000,
&vbMillenium,
- "Millenium (PCI)"},
+ "Millennium (PCI)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2, 0xFF,
0, 0,
DEVF_MILLENIUM | DEVF_MILLENIUM2 | DEVF_SWAPS,
+ 220000,
&vbMillenium2,
- "Millenium II (PCI)"},
+ "Millennium II (PCI)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MIL_2_AGP, 0xFF,
0, 0,
DEVF_MILLENIUM | DEVF_MILLENIUM2 | DEVF_SWAPS,
+ 250000,
&vbMillenium2A,
- "Millenium II (AGP)"},
+ "Millennium II (AGP)"},
#endif
#ifdef CONFIG_FB_MATROX_MYSTIQUE
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS, 0x02,
0, 0,
DEVF_VIDEO64BIT,
+ 180000,
&vbMystique,
"Mystique (PCI)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS, 0xFF,
0, 0,
DEVF_VIDEO64BIT | DEVF_SWAPS,
+ 220000,
&vbMystique,
"Mystique 220 (PCI)"},
#endif
#ifdef CONFIG_FB_MATROX_G100
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100, 0xFF,
PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_MGA_G100_PCI,
- DEVF_VIDEO64BIT | DEVF_SWAPS,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
&vbG100,
"MGA-G100 (PCI)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100, 0xFF,
0, 0,
- DEVF_VIDEO64BIT | DEVF_SWAPS,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
&vbG100,
"unknown G100 (PCI)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF,
- PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_UNSPECIFIED,
- DEVF_VIDEO64BIT | DEVF_SWAPS,
+ PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_GENERIC,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
&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_VIDEO64BIT | DEVF_SWAPS,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
&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_VIDEO64BIT | DEVF_SWAPS,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
&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_VIDEO64BIT | DEVF_SWAPS,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
&vbG100,
"Productiva G100 (AGP)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_AGP, 0xFF,
0, 0,
- DEVF_VIDEO64BIT | DEVF_SWAPS,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
&vbG100,
"unknown G100 (AGP)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
- PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_UNSPECIFIED,
- DEVF_VIDEO64BIT | DEVF_SWAPS,
+ PCI_SS_VENDOR_ID_MATROX, PCI_SS_ID_MATROX_GENERIC,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
&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_VIDEO64BIT | DEVF_SWAPS,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
&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_VIDEO64BIT | DEVF_SWAPS,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 250000,
&vbG200,
- "Millenium G200 (AGP)"},
+ "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_VIDEO64BIT | DEVF_SWAPS,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
&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_VIDEO64BIT | DEVF_SWAPS,
+ DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+ 220000,
&vbG200,
"MGA-G200 (AGP)"},
{PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G200_AGP, 0xFF,
0, 0,
DEVF_VIDEO64BIT | DEVF_SWAPS,
+ 220000,
&vbG200,
"unknown G200 (AGP)"},
#endif
{0, 0, 0xFF,
0, 0,
0,
+ 0,
NULL,
NULL}};
__initfunc(static int initMatrox2(WPMINFO struct display* d, struct board* b)) {
unsigned long ctrlptr_phys = 0;
unsigned long video_base_phys = 0;
- int memsize;
+ unsigned int memsize;
struct matrox_hw_state* hw = ACCESS_FBINFO(currenthw);
+ DBG("initMatrox2")
+
/* set default values... */
vesafb_defined.accel_flags = FB_ACCELF_TEXT;
ACCESS_FBINFO(hw_switch) = b->base->lowlevel;
ACCESS_FBINFO(devflags.accelerator) = b->base->accelID;
+ ACCESS_FBINFO(max_pixel_clock) = b->maxclk;
printk(KERN_INFO "matroxfb: Matrox %s detected\n", b->name);
ACCESS_FBINFO(devflags.video64bits) = b->flags & DEVF_VIDEO64BIT;
+ if (ACCESS_FBINFO(capable.cross4MB) < 0)
+ ACCESS_FBINFO(capable.cross4MB) = b->flags & DEVF_CROSS4MB;
if (b->flags & DEVF_SWAPS) {
ctrlptr_phys = ACCESS_FBINFO(pcidev)->base_address[1] & ~0x3FFF;
video_base_phys = ACCESS_FBINFO(pcidev)->base_address[0] & ~0x7FFFFF; /* aligned at 8MB (or 16 for Mill 2) */
@@ -3912,13 +4850,12 @@
printk(KERN_ERR "matroxfb: video RAM is not available in PCI address space, matroxfb disabled\n");
return -EINVAL;
}
- ACCESS_FBINFO(mmio) = ioremap_nocache(ctrlptr_phys, 16384); /* do we really need ioremap_nocache? */
- if (!ACCESS_FBINFO(mmio)) {
+ if (mga_ioremap(ctrlptr_phys, 16384, MGA_IOREMAP_MMIO, &ACCESS_FBINFO(mmio.vbase))) {
printk(KERN_ERR "matroxfb: cannot ioremap(%lX, 16384), matroxfb disabled\n", ctrlptr_phys);
return -ENOMEM;
}
- ACCESS_FBINFO(mmio_base) = ctrlptr_phys;
- ACCESS_FBINFO(mmio_len) = 16384;
+ ACCESS_FBINFO(mmio.base) = ctrlptr_phys;
+ ACCESS_FBINFO(mmio.len) = 16384;
memsize = b->base->maxvram;
/* convert mem (autodetect k, M) */
if (mem < 1024) mem *= 1024;
@@ -3926,12 +4863,11 @@
if (mem && (mem < memsize))
memsize = mem;
- ACCESS_FBINFO(video_vbase) = ioremap(video_base_phys, memsize);
- ACCESS_FBINFO(video_base) = video_base_phys;
- if (!ACCESS_FBINFO(video_vbase)) {
+ ACCESS_FBINFO(video.base) = video_base_phys;
+ if (mga_ioremap(video_base_phys, memsize, MGA_IOREMAP_FB, &ACCESS_FBINFO(video.vbase))) {
printk(KERN_ERR "matroxfb: cannot ioremap(%lX, %d), matroxfb disabled\n",
video_base_phys, memsize);
- iounmap(ACCESS_FBINFO(mmio));
+ mga_iounmap(ACCESS_FBINFO(mmio.vbase));
return -ENOMEM;
}
{
@@ -3971,28 +4907,28 @@
}
if (ACCESS_FBINFO(hw_switch)->preinit(PMINFO hw)) {
- iounmap(ACCESS_FBINFO(video_vbase));
- iounmap(ACCESS_FBINFO(mmio));
+ mga_iounmap(ACCESS_FBINFO(video.vbase));
+ mga_iounmap(ACCESS_FBINFO(mmio.vbase));
return -ENXIO;
}
{
unsigned int offs;
- if (!matroxfb_getmemory(PMINFO memsize, &offs, &ACCESS_FBINFO(video_len)) || !ACCESS_FBINFO(video_len)) {
+ if (!matroxfb_getmemory(PMINFO memsize, &offs, &ACCESS_FBINFO(video.len)) || !ACCESS_FBINFO(video.len)) {
printk(KERN_ERR "matroxfb: cannot determine memory size\n");
- iounmap(ACCESS_FBINFO(video_vbase));
- iounmap(ACCESS_FBINFO(mmio));
+ mga_iounmap(ACCESS_FBINFO(video.vbase));
+ mga_iounmap(ACCESS_FBINFO(mmio.vbase));
return -ENOMEM;
}
#ifdef MATROX_2MB_WITH_4MB_ADDON
#ifdef FBCON_HAS_CFB24
{
- unsigned int end = offs + ACCESS_FBINFO(video_len);
+ unsigned int end = offs + ACCESS_FBINFO(video.len);
if (offs)
offs = ((offs - 1) / (4096 * 3) + 1) * 4096 * 3;
- ACCESS_FBINFO(video_len) = end - offs;
+ ACCESS_FBINFO(video.len) = end - offs;
}
#endif
mga_ydstorg(MINFO) = offs;
@@ -4001,17 +4937,20 @@
}
ACCESS_FBINFO(curr.video_type) = FB_TYPE_PACKED_PIXELS;
ACCESS_FBINFO(currcon) = -1;
- iounmap(ACCESS_FBINFO(video_vbase));
- ACCESS_FBINFO(video_vbase) = ioremap(video_base_phys, ACCESS_FBINFO(video_len));
- ACCESS_FBINFO(video_base) = video_base_phys;
- if (!ACCESS_FBINFO(video_vbase)) {
+ ACCESS_FBINFO(currcon_display) = NULL;
+ 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));
- iounmap(ACCESS_FBINFO(mmio));
+ video_base_phys, ACCESS_FBINFO(video.len));
+ mga_iounmap(ACCESS_FBINFO(mmio.vbase));
return -ENOMEM;
}
+ ACCESS_FBINFO(video.len_usable) = ACCESS_FBINFO(video.len);
+ if (ACCESS_FBINFO(video.len_usable) > 0x08000000)
+ ACCESS_FBINFO(video.len_usable) = 0x08000000;
#ifdef CONFIG_MTRR
- ACCESS_FBINFO(mtrr.vram) = mtrr_add(video_base_phys, ACCESS_FBINFO(video_len), MTRR_TYPE_WRCOMB, 1);
+ ACCESS_FBINFO(mtrr.vram) = mtrr_add(video_base_phys, ACCESS_FBINFO(video.len), MTRR_TYPE_WRCOMB, 1);
ACCESS_FBINFO(mtrr.vram_valid) = 1;
printk(KERN_INFO "matroxfb: MTRR's turned on\n");
#endif /* CONFIG_MTRR */
@@ -4073,7 +5012,7 @@
if (yres > 2048)
yres = 2048;
{
- int tmp;
+ unsigned int tmp;
if (fv) {
tmp = fv * (upper + yres + lower + vslen);
@@ -4099,26 +5038,9 @@
pixclock = 1000000; /* 1MHz */
vesafb_defined.xres = xres;
vesafb_defined.yres = yres;
- {
- int pixel_size = vesafb_defined.bits_per_pixel;
- int avamem = ACCESS_FBINFO(video_len);
-
- /* displaying is possible only in first 8MB */
- if (avamem > 0x8000000)
- avamem = 0x8000000;
-
- vesafb_defined.xres_virtual = matroxfb_pitch_adjust(PMINFO xres, pixel_size);
- if (nopan) {
- vesafb_defined.yres_virtual = yres;
- } else {
- vesafb_defined.yres_virtual = (avamem * 8 / (pixel_size * vesafb_defined.xres_virtual)) & ~0x1F;
- if (vesafb_defined.yres_virtual < vesafb_defined.yres)
- vesafb_defined.yres_virtual = yres;
- }
- }
vesafb_defined.xoffset = 0;
vesafb_defined.yoffset = 0;
- vesafb_defined.grayscale = 0;
+ vesafb_defined.grayscale = grayscale;
vesafb_defined.pixclock = pixclock;
vesafb_defined.left_margin = left;
vesafb_defined.right_margin = right;
@@ -4144,7 +5066,44 @@
ACCESS_FBINFO(fbcon.blank) = &matroxfb_blank;
ACCESS_FBINFO(fbcon.flags) = FBINFO_FLAG_DEFAULT;
ACCESS_FBINFO(hw_switch->reset(PMINFO hw));
+ ACCESS_FBINFO(video.len_usable) &= PAGE_MASK;
+#if defined(CONFIG_FB_COMPAT_XPMAC)
+ strcpy(ACCESS_FBINFO(matrox_name), "MTRX,"); /* OpenFirmware naming convension */
+ strcat(ACCESS_FBINFO(matrox_name), b->name);
+ if (!console_fb_info)
+ console_fb_info = &ACCESS_FBINFO(fbcon);
+#endif
+#if defined(CONFIG_PPC)
+ if ((xres <= 640) && (yres <= 480)) {
+ struct fb_var_screeninfo var;
+
+ if (default_vmode == VMODE_NVRAM)
+ default_vmode = nvram_read_byte(NV_VMODE);
+ if ((default_vmode <= 0) || (default_vmode > VMODE_MAX))
+ default_vmode = VMODE_640_480_60;
+ if (default_cmode == CMODE_NVRAM)
+ default_cmode = nvram_read_byte(NV_CMODE);
+ if ((default_cmode < CMODE_8) || (default_cmode > CMODE_32))
+ default_cmode = CMODE_8;
+ if (!mac_vmode_to_var(default_vmode, default_cmode, &var)) {
+ var.accel_flags = vesafb_defined.accel_flags;
+ vesafb_defined = var;
+ }
+ }
+#endif
+ {
+ int pixel_size = vesafb_defined.bits_per_pixel;
+ int avamem = ACCESS_FBINFO(video.len_usable);
+ vesafb_defined.xres_virtual = matroxfb_pitch_adjust(PMINFO xres, pixel_size);
+ if (nopan) {
+ vesafb_defined.yres_virtual = vesafb_defined.yres;
+ } else {
+ vesafb_defined.yres_virtual = (avamem * 8 / (pixel_size * vesafb_defined.xres_virtual)) & ~0x1F;
+ if (vesafb_defined.yres_virtual < vesafb_defined.yres)
+ vesafb_defined.yres_virtual = vesafb_defined.yres;
+ }
+ }
if (matroxfb_set_var(&vesafb_defined, -2, &ACCESS_FBINFO(fbcon))) {
printk(KERN_ERR "matroxfb: cannot set required parameters\n");
return -EINVAL;
@@ -4154,7 +5113,7 @@
vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel,
vesafb_defined.xres_virtual, vesafb_defined.yres_virtual);
printk(KERN_INFO "matroxfb: framebuffer at 0x%lX, mapped to 0x%p, size %d\n",
- ACCESS_FBINFO(video_base), ACCESS_FBINFO(video_vbase), ACCESS_FBINFO(video_len));
+ ACCESS_FBINFO(video.base), vaddr_va(ACCESS_FBINFO(video.vbase)), ACCESS_FBINFO(video.len));
/* We do not have to set currcon to 0... register_framebuffer do it for us on first console
* and we do not want currcon == 0 for subsequent framebuffers */
@@ -4178,6 +5137,8 @@
__initfunc(static int matrox_init(void)) {
struct pci_dev* pdev = NULL;
+ DBG("matrox_init")
+
if (disabled)
return -ENXIO;
while ((pdev = pci_find(pdev)) != NULL) {
@@ -4223,6 +5184,15 @@
ACCESS_FBINFO(devflags.mga_24bpp_fix) = inv24;
ACCESS_FBINFO(devflags.precise_width) = option_precise_width;
ACCESS_FBINFO(devflags.hwcursor) = hwcursor;
+ ACCESS_FBINFO(devflags.blink) = blink;
+ ACCESS_FBINFO(capable.cross4MB) = cross4MB;
+
+ ACCESS_FBINFO(fastfont.size) = fastfont;
+
+ ACCESS_FBINFO(cursor.state) = CM_ERASE;
+ ACCESS_FBINFO(cursor.timer.prev) = ACCESS_FBINFO(cursor.timer.next) = NULL;
+ ACCESS_FBINFO(cursor.timer.data) = (unsigned long)MINFO;
+ spin_lock_init(&ACCESS_FBINFO(lock.DAC));
err = initMatrox2(PMINFO d, b);
if (!err) {
@@ -4255,13 +5225,25 @@
#ifndef MODULE
__initfunc(void matroxfb_init(void))
{
+ DBG("matroxfb_init")
+#if defined(CONFIG_FB_OF)
+/* Nothing to do, must be called from offb */
+#else
+ matrox_init();
+#endif
+}
+
+#if defined(CONFIG_FB_OF)
+__initfunc(void matrox_of_init(struct device_node *dp)) {
+ DBG("matrox_of_init");
matrox_init();
}
+#endif /* CONFIG_FB_OF */
#else
MODULE_AUTHOR("(c) 1998 Petr Vandrovec <vandrove@vc.cvut.cz>");
-MODULE_DESCRIPTION("Accelerated FBDev driver for Matrox Millenium/Mystique");
+MODULE_DESCRIPTION("Accelerated FBDev driver for Matrox Millennium/Mystique/G100/G200");
MODULE_PARM(mem, "i");
MODULE_PARM_DESC(mem, "Size of available memory in MB, KB or B (2,4,8,12,16MB, default=autodetect)");
MODULE_PARM(disabled, "i");
@@ -4318,9 +5300,26 @@
MODULE_PARM(fv, "i");
MODULE_PARM_DESC(fv, "Startup vertical frequency, 0-INF Hz\n"
"You should specify \"fv:max_monitor_vsync,fh:max_monitor_hsync,maxclk:max_monitor_dotclock\"\n");
-
+MODULE_PARM(hwcursor, "i");
+MODULE_PARM_DESC(hwcursor, "Enables hardware cursor (0 or 1) (default=0)");
+MODULE_PARM(blink, "i");
+MODULE_PARM_DESC(blink, "Enables hardware cursor blinking (0 or 1) (default=1)");
+MODULE_PARM(fastfont, "i");
+MODULE_PARM_DESC(fastfont, "Specifies, how much memory should be used for font data (0, 1024-65536 are reasonable) (default=0)");
+MODULE_PARM(grayscale, "i");
+MODULE_PARM_DESC(grayscale, "Sets display into grayscale. Works perfectly with paletized videomode (4, 8bpp), some limitations apply to 16, 24 and 32bpp videomodes (default=nograyscale)");
+MODULE_PARM(cross4MB, "i");
+MODULE_PARM_DESC(cross4MB, "Specifies that 4MB boundary can be in middle of line. It cannot at least on Millennium (I/II).");
__initfunc(int init_module(void)) {
+
+ DBG("init_module")
+
+#ifdef DEBUG
+ if( disabled )
+ return 0;
+#endif /* DEBUG */
+
if (depth == 0)
depth = 0; /* default */
else if (depth == 4)
@@ -4345,18 +5344,27 @@
}
void cleanup_module(void) {
+
+ DBG("cleanup_module")
+
+#ifdef DEBUG
+ if( disabled )
+ return;
+#endif /* DEBUG */
+
while (fb_list) {
struct matrox_fb_info* minfo;
minfo = fb_list;
fb_list = fb_list->next_fb;
unregister_framebuffer(&ACCESS_FBINFO(fbcon));
+ del_timer(&ACCESS_FBINFO(cursor.timer));
#ifdef CONFIG_MTRR
if (ACCESS_FBINFO(mtrr.vram_valid))
- mtrr_del(ACCESS_FBINFO(mtrr.vram), ACCESS_FBINFO(video_base), ACCESS_FBINFO(video_len));
+ mtrr_del(ACCESS_FBINFO(mtrr.vram), ACCESS_FBINFO(video.base), ACCESS_FBINFO(video.len));
#endif
- iounmap(ACCESS_FBINFO(mmio));
- iounmap(ACCESS_FBINFO(video_vbase));
+ mga_iounmap(ACCESS_FBINFO(mmio.vbase));
+ mga_iounmap(ACCESS_FBINFO(video.vbase));
#ifdef CONFIG_FB_MATROX_MULTIHEAD
kfree_s(ACCESS_FBINFO(fbcon.disp), sizeof(struct display));
kfree_s(minfo, sizeof(struct matrox_fb_info));
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov