summary refs log tree commit diff
diff options
context:
space:
mode:
authorKnut Petersen <Knut_Petersen@t-online.de>2006-01-09 15:04:20 +0100
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-09 10:00:36 -0800
commit44637a12f80b80157d9c1bc5b7d6ef09c9e05713 (patch)
tree17384805725f7b429685ba4cad0d9488d93f9f25
parent8b78e83bfbc12f7e9bdefd400abdfde9e6c9ac51 (diff)
downloadlinux-44637a12f80b80157d9c1bc5b7d6ef09c9e05713.tar.gz
[PATCH] Update cyblafb driver
This is a major update to the cyblafb framebuffer driver. Most
of the stuff has been tested in the mm tree.

Main advantages:
============
  - vxres > xres support
  - ywrap and xpan support
  - much faster for almost all modes (e.g. 1280x1024-16bpp
     draws more than 41 full screens of text instead of about 25
     full screens of text per second on authors Epia 5000)
  - module init/exit code fixed
  - bugs triggered by console rotation fixed
  - lots of minor improvements
  - startup modes suitable for high performance scrolling
     in all directions

This diff  also contains a lot of white space fixes.

No side effects are possible, only one single graphics core is affected.

Signed-off-by: Knut Petersen <Knut_Petersen@t-online.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--Documentation/fb/cyblafb/bugs1
-rw-r--r--Documentation/fb/cyblafb/fb.modes57
-rw-r--r--Documentation/fb/cyblafb/performance1
-rw-r--r--Documentation/fb/cyblafb/todo5
-rw-r--r--Documentation/fb/cyblafb/usage33
-rw-r--r--Documentation/fb/cyblafb/whatsnew29
-rw-r--r--drivers/video/Kconfig2
-rw-r--r--drivers/video/cyblafb.c1523
-rw-r--r--include/video/cyblafb.h4
9 files changed, 960 insertions, 695 deletions
diff --git a/Documentation/fb/cyblafb/bugs b/Documentation/fb/cyblafb/bugs
index f90cc66ea919..9443a6d72cdd 100644
--- a/Documentation/fb/cyblafb/bugs
+++ b/Documentation/fb/cyblafb/bugs
@@ -11,4 +11,3 @@ Untested features
 
 All LCD stuff is untested. If it worked in tridentfb, it should work in
 cyblafb. Please test and report the results to Knut_Petersen@t-online.de.
-
diff --git a/Documentation/fb/cyblafb/fb.modes b/Documentation/fb/cyblafb/fb.modes
index cf4351fc32ff..fe0e5223ba86 100644
--- a/Documentation/fb/cyblafb/fb.modes
+++ b/Documentation/fb/cyblafb/fb.modes
@@ -14,142 +14,141 @@
 #
 
 mode "640x480-50"
-    geometry 640 480 640 3756 8
+    geometry 640 480 2048 4096 8
     timings 47619 4294967256 24 17 0 216 3
 endmode
 
 mode "640x480-60"
-    geometry 640 480 640 3756 8
+    geometry 640 480 2048 4096 8
     timings 39682 4294967256 24 17 0 216 3
 endmode
 
 mode "640x480-70"
-    geometry 640 480 640 3756 8
+    geometry 640 480 2048 4096 8
     timings 34013 4294967256 24 17 0 216 3
 endmode
 
 mode "640x480-72"
-    geometry 640 480 640 3756 8
+    geometry 640 480 2048 4096 8
     timings 33068 4294967256 24 17 0 216 3
 endmode
 
 mode "640x480-75"
-    geometry 640 480 640 3756 8
+    geometry 640 480 2048 4096 8
     timings 31746 4294967256 24 17 0 216 3
 endmode
 
 mode "640x480-80"
-    geometry 640 480 640 3756 8
+    geometry 640 480 2048 4096 8
     timings 29761 4294967256 24 17 0 216 3
 endmode
 
 mode "640x480-85"
-    geometry 640 480 640 3756 8
+    geometry 640 480 2048 4096 8
     timings 28011 4294967256 24 17 0 216 3
 endmode
 
 mode "800x600-50"
-    geometry 800 600 800 3221 8
+    geometry 800 600 2048 4096 8
     timings 30303 96 24 14 0 136 11
 endmode
 
 mode "800x600-60"
-    geometry 800 600 800 3221 8
+    geometry 800 600 2048 4096 8
     timings 25252 96 24 14 0 136 11
 endmode
 
 mode "800x600-70"
-    geometry 800 600 800 3221 8
+    geometry 800 600 2048 4096 8
     timings 21645 96 24 14 0 136 11
 endmode
 
 mode "800x600-72"
-    geometry 800 600 800 3221 8
+    geometry 800 600 2048 4096 8
     timings 21043 96 24 14 0 136 11
 endmode
 
 mode "800x600-75"
-    geometry 800 600 800 3221 8
+    geometry 800 600 2048 4096 8
     timings 20202 96 24 14 0 136 11
 endmode
 
 mode "800x600-80"
-    geometry 800 600 800 3221 8
+    geometry 800 600 2048 4096 8
     timings 18939 96 24 14 0 136 11
 endmode
 
 mode "800x600-85"
-    geometry 800 600 800 3221 8
+    geometry 800 600 2048 4096 8
     timings 17825 96 24 14 0 136 11
 endmode
 
 mode "1024x768-50"
-    geometry 1024 768 1024 2815 8
+    geometry 1024 768 2048 4096 8
     timings 19054 144 24 29 0 120 3
 endmode
 
 mode "1024x768-60"
-    geometry 1024 768 1024 2815 8
+    geometry 1024 768 2048 4096 8
     timings 15880 144 24 29 0 120 3
 endmode
 
 mode "1024x768-70"
-    geometry 1024 768 1024 2815 8
+    geometry 1024 768 2048 4096 8
     timings 13610 144 24 29 0 120 3
 endmode
 
 mode "1024x768-72"
-    geometry 1024 768 1024 2815 8
+    geometry 1024 768 2048 4096 8
     timings 13232 144 24 29 0 120 3
 endmode
 
 mode "1024x768-75"
-    geometry 1024 768 1024 2815 8
+    geometry 1024 768 2048 4096 8
     timings 12703 144 24 29 0 120 3
 endmode
 
 mode "1024x768-80"
-    geometry 1024 768 1024 2815 8
+    geometry 1024 768 2048 4096 8
     timings 11910 144 24 29 0 120 3
 endmode
 
 mode "1024x768-85"
-    geometry 1024 768 1024 2815 8
+    geometry 1024 768 2048 4096 8
     timings 11209 144 24 29 0 120 3
 endmode
 
 mode "1280x1024-50"
-    geometry 1280 1024 1280 2662 8
+    geometry 1280 1024 2048 4096 8
     timings 11114 232 16 39 0 160 3
 endmode
 
 mode "1280x1024-60"
-    geometry 1280 1024 1280 2662 8
+    geometry 1280 1024 2048 4096 8
     timings 9262 232 16 39 0 160 3
 endmode
 
 mode "1280x1024-70"
-    geometry 1280 1024 1280 2662 8
+    geometry 1280 1024 2048 4096 8
     timings 7939 232 16 39 0 160 3
 endmode
 
 mode "1280x1024-72"
-    geometry 1280 1024 1280 2662 8
+    geometry 1280 1024 2048 4096 8
     timings 7719 232 16 39 0 160 3
 endmode
 
 mode "1280x1024-75"
-    geometry 1280 1024 1280 2662 8
+    geometry 1280 1024 2048 4096 8
     timings 7410 232 16 39 0 160 3
 endmode
 
 mode "1280x1024-80"
-    geometry 1280 1024 1280 2662 8
+    geometry 1280 1024 2048 4096 8
     timings 6946 232 16 39 0 160 3
 endmode
 
 mode "1280x1024-85"
-    geometry 1280 1024 1280 2662 8
+    geometry 1280 1024 2048 4096 8
     timings 6538 232 16 39 0 160 3
 endmode
-
diff --git a/Documentation/fb/cyblafb/performance b/Documentation/fb/cyblafb/performance
index eb4e47a9cea6..8d15d5dfc6b3 100644
--- a/Documentation/fb/cyblafb/performance
+++ b/Documentation/fb/cyblafb/performance
@@ -77,4 +77,3 @@ patch that speeds up kernel bitblitting a lot ( > 20%).
 |	    |		      | 		|		  |
 |	    |		      | 		|		  |
 +-----------+-----------------+-----------------+-----------------+
-
diff --git a/Documentation/fb/cyblafb/todo b/Documentation/fb/cyblafb/todo
index 80fb2f89b6c1..c5f6d0eae545 100644
--- a/Documentation/fb/cyblafb/todo
+++ b/Documentation/fb/cyblafb/todo
@@ -22,11 +22,10 @@ accelerated color blitting	Who needs it? The console driver does use color
 				everything else is done using color expanding
 				blitting of 1bpp character bitmaps.
 
-xpanning			Who needs it?
-
 ioctls				Who needs it?
 
-TV-out				Will be done later
+TV-out				Will be done later. Use "vga= " at boot time
+				to set a suitable video mode.
 
 ???				Feel free to contact me if you have any
 				feature requests
diff --git a/Documentation/fb/cyblafb/usage b/Documentation/fb/cyblafb/usage
index e627c8f54211..a39bb3d402a2 100644
--- a/Documentation/fb/cyblafb/usage
+++ b/Documentation/fb/cyblafb/usage
@@ -40,6 +40,16 @@ Selecting Modes
 	None of the modes possible to select as startup modes are affected by
 	the problems described at the end of the next subsection.
 
+	For all startup modes cyblafb chooses a virtual x resolution of 2048,
+	the only exception is mode 1280x1024 in combination with 32 bpp. This
+	allows ywrap scrolling for all those modes if rotation is 0 or 2, and
+	also fast scrolling if rotation is 1 or 3. The default virtual y reso-
+	lution is 4096 for bpp == 8, 2048 for bpp==16 and 1024 for bpp == 32,
+	again with the only exception of 1280x1024 at 32 bpp.
+
+	Please do set your video memory size to 8 Mb in the Bios setup. Other
+	values will work, but performace is decreased for a lot of modes.
+
 	Mode changes using fbset
 	========================
 
@@ -54,20 +64,26 @@ Selecting Modes
 		- if a flat panel is found, cyblafb does not allow you
 		  to program a resolution higher than the physical
 		  resolution of the flat panel monitor
-		- cyblafb does not allow xres to differ from xres_virtual
 		- cyblafb does not allow vclk to exceed 230 MHz. As 32 bpp
 		  and (currently) 24 bit modes use a doubled vclk internally,
 		  the dotclock limit as seen by fbset is 115 MHz for those
 		  modes and 230 MHz for 8 and 16 bpp modes.
+		- cyblafb will allow you to select very high resolutions as
+		  long as the hardware can be programmed to these modes. The
+		  documented limit 1600x1200 is not enforced, but don't expect
+		  perfect signal quality.
 
-	Any request that violates the rules given above will be ignored and
-	fbset will return an error.
+	Any request that violates the rules given above will be either changed
+	to something the hardware supports or an error value will be returned.
 
 	If you program a virtual y resolution higher than the hardware limit,
 	cyblafb will silently decrease that value to the highest possible
-	value.
+	value. The same is true for a virtual x resolution that is not
+	supported by the hardware. Cyblafb tries to adapt vyres first because
+	vxres decides if ywrap scrolling is possible or not.
 
-	Attempts to disable acceleration are ignored.
+	Attempts to disable acceleration are ignored, I believe that this is
+	safe.
 
 	Some video modes that should work do not work as expected. If you use
 	the standard fb.modes, fbset 640x480-60 will program that mode, but
@@ -129,10 +145,6 @@ mode		640x480 or 800x600 or 1024x768 or 1280x1024
 verbosity	0 is the default, increase to at least 2 for every
 		bug report!
 
-vesafb		allows cyblafb to be loaded after vesafb has been
-		loaded. See sections "Module unloading ...".
-
-
 Development hints
 =================
 
@@ -195,7 +207,7 @@ a graphics mode.
 After booting, load cyblafb without any mode and bpp parameter and assign
 cyblafb to individual ttys using con2fb, e.g.:
 
-	modprobe cyblafb vesafb=1
+	modprobe cyblafb
 	con2fb /dev/fb1 /dev/tty1
 
 Unloading cyblafb works without problems after you assign vesafb to all
@@ -203,4 +215,3 @@ ttys again, e.g.:
 
 	con2fb /dev/fb0 /dev/tty1
 	rmmod cyblafb
-
diff --git a/Documentation/fb/cyblafb/whatsnew b/Documentation/fb/cyblafb/whatsnew
new file mode 100644
index 000000000000..76c07a26e044
--- /dev/null
+++ b/Documentation/fb/cyblafb/whatsnew
@@ -0,0 +1,29 @@
+0.62
+====
+
+      - the vesafb parameter has been removed as I decided to allow the
+      	feature without any special parameter.
+
+      - Cyblafb does not use the vga style of panning any longer, now the
+      	"right view" register in the graphics engine IO space is used. Without
+	that change it was impossible to use all available memory, and without
+	access to all available memory it is impossible to ywrap.
+
+      - The imageblit function now uses hardware acceleration for all font
+        widths. Hardware blitting across pixel column 2048 is broken in the
+	cyberblade/i1 graphics core, but we work around that hardware bug.
+
+      - modes with vxres != xres are supported now.
+
+      - ywrap scrolling is supported now and the default. This is a big
+        performance gain.
+
+      - default video modes use vyres > yres and vxres > xres to allow
+        almost optimal scrolling speed for normal and rotated screens
+
+      - some features mainly usefull for debugging the upper layers of the
+        framebuffer system have been added, have a look at the code
+
+      - fixed: Oops after unloading cyblafb when reading /proc/io*
+
+      - we work around some bugs of the higher framebuffer layers.
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index cc8e3bf5001b..3f04427c9026 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1151,7 +1151,7 @@ config FB_VOODOO1
 
 config FB_CYBLA
 	tristate "Cyberblade/i1 support"
-	depends on FB && PCI
+	depends on FB && PCI && X86_32 && !64BIT
 	select FB_CFB_IMAGEBLIT
 	select VIDEO_SELECT
 	---help---
diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c
index 03fbe83d71a8..e9f5dee67e3c 100644
--- a/drivers/video/cyblafb.c
+++ b/drivers/video/cyblafb.c
@@ -7,11 +7,12 @@
  *	tridentfb.c by Jani Monoses
  *	see files above for further credits
  *
- * TODO:
- *
  */
 
 #define CYBLAFB_DEBUG 0
+#define CYBLAFB_KD_GRAPHICS_QUIRK 1
+
+#define CYBLAFB_PIXMAPSIZE 8192
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -22,7 +23,7 @@
 #include <asm/types.h>
 #include <video/cyblafb.h>
 
-#define VERSION "0.54"
+#define VERSION "0.62"
 
 struct cyblafb_par {
 	u32 pseudo_pal[16];
@@ -32,7 +33,9 @@ struct cyblafb_par {
 static struct fb_fix_screeninfo cyblafb_fix __devinitdata = {
 	.id = "CyBla",
 	.type = FB_TYPE_PACKED_PIXELS,
+	.xpanstep = 1,
 	.ypanstep = 1,
+	.ywrapstep = 1,
 	.visual = FB_VISUAL_PSEUDOCOLOR,
 	.accel = FB_ACCEL_NONE,
 };
@@ -43,8 +46,9 @@ static int ref __devinitdata = 75;
 static int fp __devinitdata;
 static int crt __devinitdata;
 static int memsize __devinitdata;
-static int vesafb __devinitdata;
 
+static int basestride;
+static int vesafb;
 static int nativex;
 static int center;
 static int stretch;
@@ -52,26 +56,50 @@ static int pciwb = 1;
 static int pcirb = 1;
 static int pciwr = 1;
 static int pcirr = 1;
+static int disabled;
 static int verbosity;
 static int displaytype;
 
-static void __iomem * io_virt; // iospace virtual memory address
-
-module_param(mode,charp,0);
-module_param(bpp,int,0);
-module_param(ref,int,0);
-module_param(fp,int,0);
-module_param(crt,int,0);
-module_param(nativex,int,0);
-module_param(center,int,0);
-module_param(stretch,int,0);
-module_param(pciwb,int,0);
-module_param(pcirb,int,0);
-module_param(pciwr,int,0);
-module_param(pcirr,int,0);
-module_param(memsize,int,0);
-module_param(verbosity,int,0);
-module_param(vesafb,int,0);
+static void __iomem *io_virt;	// iospace virtual memory address
+
+module_param(mode, charp, 0);
+module_param(bpp, int, 0);
+module_param(ref, int, 0);
+module_param(fp, int, 0);
+module_param(crt, int, 0);
+module_param(nativex, int, 0);
+module_param(center, int, 0);
+module_param(stretch, int, 0);
+module_param(pciwb, int, 0);
+module_param(pcirb, int, 0);
+module_param(pciwr, int, 0);
+module_param(pcirr, int, 0);
+module_param(memsize, int, 0);
+module_param(verbosity, int, 0);
+
+//=========================================
+//
+// Well, we have to fix the upper layers.
+// Until this has been done, we work around
+// the bugs.
+//
+//=========================================
+
+#if (CYBLAFB_KD_GRAPHICS_QUIRK && CYBLAFB_DEBUG)
+	if (disabled) { \
+		printk("********\n");\
+		dump_stack();\
+		return val;\
+	}
+
+#elif CYBLAFB_KD_GRAPHICS_QUIRK
+#define KD_GRAPHICS_RETURN(val)\
+	if (disabled) {\
+		return val;\
+	}
+#else
+#define KD_GRAPHICS_RETURN(val)
+#endif
 
 //=========================================
 //
@@ -79,10 +107,10 @@ module_param(vesafb,int,0);
 //
 //=========================================
 
-#define out8(r,v) writeb(v,io_virt+r)
-#define out32(r,v) writel(v,io_virt+r)
-#define in8(r) readb(io_virt+r)
-#define in32(r) readl(io_virt+r)
+#define out8(r, v) writeb(v, io_virt + r)
+#define out32(r, v) writel(v, io_virt + r)
+#define in8(r) readb(io_virt + r)
+#define in32(r) readl(io_virt + r)
 
 //======================================
 //
@@ -90,47 +118,47 @@ module_param(vesafb,int,0);
 //
 //======================================
 
-static inline unsigned char read3X4(int reg)
+static inline u8 read3X4(u32 reg)
 {
-	out8(0x3D4,reg);
+	out8(0x3D4, reg);
 	return in8(0x3D5);
 }
 
-static inline unsigned char read3C4(int reg)
+static inline u8 read3C4(u32 reg)
 {
-	out8(0x3C4,reg);
+	out8(0x3C4, reg);
 	return in8(0x3C5);
 }
 
-static inline unsigned char read3CE(int reg)
+static inline u8 read3CE(u32 reg)
 {
-	out8(0x3CE,reg);
+	out8(0x3CE, reg);
 	return in8(0x3CF);
 }
 
-static inline void write3X4(int reg,unsigned char val)
+static inline void write3X4(u32 reg, u8 val)
 {
-	out8(0x3D4,reg);
-	out8(0x3D5,val);
+	out8(0x3D4, reg);
+	out8(0x3D5, val);
 }
 
-static inline void write3C4(int reg,unsigned char val)
+static inline void write3C4(u32 reg, u8 val)
 {
-	out8(0x3C4,reg);
-	out8(0x3C5,val);
+	out8(0x3C4, reg);
+	out8(0x3C5, val);
 }
 
-static inline void write3CE(int reg,unsigned char val)
+static inline void write3CE(u32 reg, u8 val)
 {
-	out8(0x3CE,reg);
-	out8(0x3CF,val);
+	out8(0x3CE, reg);
+	out8(0x3CF, val);
 }
 
-static inline void write3C0(int reg,unsigned char val)
+static inline void write3C0(u32 reg, u8 val)
 {
-	in8(0x3DA);	// read to reset index
-	out8(0x3C0,reg);
-	out8(0x3C0,val);
+	in8(0x3DA);		// read to reset index
+	out8(0x3C0, reg);
+	out8(0x3C0, val);
 }
 
 //=================================================
@@ -139,58 +167,62 @@ static inline void write3C0(int reg,unsigned char val)
 //
 //=================================================
 
-static inline void enable_mmio(void)
+static void enable_mmio(void)
 {
-	int tmp;
+	u8 tmp;
 
-	outb(0x0B,0x3C4);
+	outb(0x0B, 0x3C4);
 	inb(0x3C5);		// Set NEW mode
-	outb(SR0E,0x3C4);	// write enable a lot of extended ports
-	outb(0x80,0x3C5);
+	outb(SR0E, 0x3C4);	// write enable a lot of extended ports
+	outb(0x80, 0x3C5);
 
-	outb(SR11,0x3C4);	// write enable those extended ports that
-	outb(0x87,0x3C5);	// are not affected by SR0E_New
+	outb(SR11, 0x3C4);	// write enable those extended ports that
+	outb(0x87, 0x3C5);	// are not affected by SR0E_New
 
-	outb(CR1E,0x3d4);	// clear write protect bit for port 0x3c2
-	tmp=inb(0x3d5) & 0xBF;
-	outb(CR1E,0x3d4);
-	outb(tmp,0x3d5);
+	outb(CR1E, 0x3d4);	// clear write protect bit for port 0x3c2
+	tmp = inb(0x3d5) & 0xBF;
+	outb(CR1E, 0x3d4);
+	outb(tmp, 0x3d5);
 
-	outb(CR39,0x3D4);
-	outb(inb(0x3D5)|0x01,0x3D5); // Enable mmio, everything else untouched
+	outb(CR39, 0x3D4);
+	outb(inb(0x3D5) | 0x01, 0x3D5); // Enable mmio
 }
 
 //=================================================
 //
 // Set pixel clock VCLK1
-//   - multipliers set elswhere
-//   - freq in units of 0.01 MHz
+// - multipliers set elswhere
+// - freq in units of 0.01 MHz
+//
+// Hardware bug: SR18 >= 250 is broken for the
+//		 cyberblade/i1
 //
 //=================================================
 
 static void set_vclk(struct cyblafb_par *par, int freq)
 {
-	u32 m,n,k;
-	int f,fi,d,di;
-	u8 lo=0,hi=0;
+	u32 m, n, k;
+	int f, fi, d, di;
+	u8 lo = 0, hi = 0;
 
 	d = 2000;
 	k = freq >= 10000 ? 0 : freq >= 5000 ? 1 : freq >= 2500 ? 2 : 3;
-	for(m = 0;m<64;m++)
-	for(n = 0;n<250;n++) { // max 249 is a hardware limit for cybla/i1 !
-		fi = (int)(((5864727*(n+8))/((m+2)*(1<<k)))>>12);
-		if ((di = abs(fi - freq)) < d) {
-			d = di;
-			f = fi;
-			lo = (u8) n;
-			hi = (u8) ((k<<6) | m);
+	for (m = 0; m < 64; m++)
+		for (n = 0; n < 250; n++) {
+			fi = (int)(((5864727 * (n + 8)) /
+				    ((m + 2) * (1 << k))) >> 12);
+			if ((di = abs(fi - freq)) < d) {
+				d = di;
+				f = fi;
+				lo = (u8) n;
+				hi = (u8) ((k << 6) | m);
+			}
 		}
-	}
-	write3C4(SR19,hi);
-	write3C4(SR18,lo);
-	if(verbosity > 1)
+	write3C4(SR19, hi);
+	write3C4(SR18, lo);
+	if (verbosity > 0)
 		output("pixclock = %d.%02d MHz, k/m/n %x %x %x\n",
-		freq/100,freq%100,(hi&0xc0)>>6,hi&0x3f,lo);
+		       freq / 100, freq % 100, (hi & 0xc0) >> 6, hi & 0x3f, lo);
 }
 
 //================================================
@@ -199,83 +231,83 @@ static void set_vclk(struct cyblafb_par *par, int freq)
 //
 //================================================
 
-static void cyblafb_setup_GE(int pitch,int bpp)
+static void cyblafb_setup_GE(int pitch, int bpp)
 {
-	int base = (pitch>>3)<<20;
+	KD_GRAPHICS_RETURN();
 
 	switch (bpp) {
-		case  8: base |= (0<<29); break;
-		case 15: base |= (5<<29); break;
-		case 16: base |= (1<<29); break;
-		case 24:
-		case 32: base |= (2<<29); break;
+	case 8:
+		basestride = ((pitch >> 3) << 20) | (0 << 29);
+		break;
+	case 15:
+		basestride = ((pitch >> 3) << 20) | (5 << 29);
+		break;
+	case 16:
+		basestride = ((pitch >> 3) << 20) | (1 << 29);
+		break;
+	case 24:
+	case 32:
+		basestride = ((pitch >> 3) << 20) | (2 << 29);
+		break;
 	}
 
-	write3X4(CR36,0x90);	// reset GE
-	write3X4(CR36,0x80);	// enable GE
-
-	out32(GE24,1<<7);	// reset all GE pointers
-	out32(GE24,0);
-
-	write3X4(CR2D,0x00);	// GE Timinigs, no delays
-
-	out32(GEB8,base); // Destination Stride / Buffer Base 0, p 133
-	out32(GEBC,base); // Destination Stride / Buffer Base 1, p 133
-	out32(GEC0,base); // Destination Stride / Buffer Base 2, p 133
-	out32(GEC4,base); // Destination Stride / Buffer Base 3, p 133
-	out32(GEC8,base); // Source Stride / Buffer Base 0, p 133
-	out32(GECC,base); // Source Stride / Buffer Base 1, p 133
-	out32(GED0,base); // Source Stride / Buffer Base 2, p 133
-	out32(GED4,base); // Source Stride / Buffer Base 3, p 133
-	out32(GE6C,0);	  // Pattern and Style, p 129, ok
+	write3X4(CR36, 0x90);	// reset GE
+	write3X4(CR36, 0x80);	// enable GE
+	out32(GE24, 1 << 7);	// reset all GE pointers by toggling
+	out32(GE24, 0); 	//   d7 of GE24
+	write3X4(CR2D, 0x00);	// GE Timinigs, no delays
+	out32(GE6C, 0); 	// Pattern and Style, p 129, ok
 }
 
 //=====================================================================
 //
-// Although this is a .fb_sync function that could be enabled in
-// cyblafb_ops, we do not include it there. We sync immediately before
-// new GE operations to improve performance.
+// Cyberblade specific syncing
+//
+//   A timeout might be caused by disabled mmio.
+//   Cause:
+//     - bit CR39 & 1 == 0 upon return, X trident driver bug
+//     - kdm bug (KD_GRAPHICS not set on first switch)
+//     - kernel design flaw (it believes in the correctness
+//	 of kdm/X
+//   First we try to sync ignoring that problem, as most of the
+//   time that will succeed immediately and the enable_mmio()
+//   would only degrade performance.
 //
 //=====================================================================
 
 static int cyblafb_sync(struct fb_info *info)
 {
-	int status, i=100000;
-	while( ((status=in32(GE20)) & 0xFA800000) && i != 0)
+	u32 status, i = 100000;
+
+	KD_GRAPHICS_RETURN(0);
+
+	while (((status = in32(GE20)) & 0xFe800000) && i != 0)
 		i--;
 
 	if (i == 0) {
-		// The timeout might be caused by disabled mmio.
-		// Cause:
-		//   - bit CR39 & 1 == 0 upon return, X trident driver bug
-		//   - kdm bug (KD_GRAPHICS not set on first switch)
-		//   - kernel design flaw (it believes in the correctness
-		//     of kdm/X
-		// So we make sure that mmio is enabled first ...
 		enable_mmio();
-//		show_trace(NULL,&status);
-		i=1000000;
-		while( ((status=in32(GE20)) & 0xFA800000) && i != 0)
+		i = 1000000;
+		while (((status = in32(GE20)) & 0xFA800000) && i != 0)
 			i--;
 		if (i == 0) {
-			output("GE Timeout, status: %x\n",status);
-			if(status & 0x80000000)
+			output("GE Timeout, status: %x\n", status);
+			if (status & 0x80000000)
 				output("Bresenham Engine : Busy\n");
-			if(status & 0x40000000)
+			if (status & 0x40000000)
 				output("Setup Engine     : Busy\n");
-			if(status & 0x20000000)
+			if (status & 0x20000000)
 				output("SP / DPE         : Busy\n");
-			if(status & 0x10000000)
+			if (status & 0x10000000)
 				output("Memory Interface : Busy\n");
-			if(status & 0x08000000)
+			if (status & 0x08000000)
 				output("Com Lst Proc     : Busy\n");
-			if(status & 0x04000000)
+			if (status & 0x04000000)
 				output("Block Write      : Busy\n");
-			if(status & 0x02000000)
+			if (status & 0x02000000)
 				output("Command Buffer   : Full\n");
-			if(status & 0x01000000)
+			if (status & 0x01000000)
 				output("RESERVED         : Busy\n");
-			if(status & 0x00800000)
+			if (status & 0x00800000)
 				output("PCI Write Buffer : Busy\n");
 			cyblafb_setup_GE(info->var.xres,
 					 info->var.bits_per_pixel);
@@ -291,142 +323,193 @@ static int cyblafb_sync(struct fb_info *info)
 //
 //==============================
 
-static void cyblafb_fillrect(struct fb_info * info,
-			     const struct fb_fillrect *fr)
+static void cyblafb_fillrect(struct fb_info *info, const struct fb_fillrect *fr)
 {
-	int bpp = info->var.bits_per_pixel;
-	int col;
+	u32 bpp = info->var.bits_per_pixel, col, desty, height;
+
+	KD_GRAPHICS_RETURN();
 
 	switch (bpp) {
-		default:
-		case 8: col = fr->color;
-			col |= col <<8;
-			col |= col <<16;
-			break;
-		case 16: col = ((u32 *)(info->pseudo_palette))[fr->color];
-			 col |= col <<16;
-			 break;
-		case 32: col = ((u32 *)(info->pseudo_palette))[fr->color];
-			 break;
+	default:
+	case 8:
+		col = fr->color;
+		col |= col << 8;
+		col |= col << 16;
+		break;
+	case 16:
+		col = ((u32 *) (info->pseudo_palette))[fr->color];
+		col |= col << 16;
+		break;
+	case 32:
+		col = ((u32 *) (info->pseudo_palette))[fr->color];
+		break;
 	}
 
-	cyblafb_sync(info);
-
-	out32(GE60,col);
-	out32(GE48,fr->rop ? 0x66:ROP_S);
-	out32(GE44,0x20000000|1<<19|1<<4|2<<2);
-	out32(GE08,point(fr->dx,fr->dy));
-	out32(GE0C,point(fr->dx+fr->width-1,fr->dy+fr->height-1));
-
+	desty = fr->dy;
+	height = fr->height;
+	while (height) {
+		out32(GEB8, basestride | ((desty * info->var.xres_virtual *
+					   bpp) >> 6));
+		out32(GE60, col);
+		out32(GE48, fr->rop ? 0x66 : ROP_S);
+		out32(GE44, 0x20000000 | 1 << 19 | 1 << 4 | 2 << 2);
+		out32(GE08, point(fr->dx, 0));
+		out32(GE0C, point(fr->dx + fr->width - 1,
+				  height > 4096 ? 4095 : height - 1));
+		if (likely(height <= 4096))
+			return;
+		desty += 4096;
+		height -= 4096;
+	}
 }
 
-//==============================
+//================================================
 //
 // Cyberblade specific copyarea
 //
-//==============================
+// This function silently assumes that it never
+// will be called with width or height exceeding
+// 4096.
+//
+//================================================
 
-static void cyblafb_copyarea(struct fb_info *info,
-			     const struct fb_copyarea *ca)
+static void cyblafb_copyarea(struct fb_info *info, const struct fb_copyarea *ca)
 {
-	__u32 s1,s2,d1,d2;
-	int direction;
+	u32 s1, s2, d1, d2, direction;
+
+	KD_GRAPHICS_RETURN();
+
+	s1 = point(ca->sx, 0);
+	s2 = point(ca->sx + ca->width - 1, ca->height - 1);
+	d1 = point(ca->dx, 0);
+	d2 = point(ca->dx + ca->width - 1, ca->height - 1);
 
-	s1 = point(ca->sx,ca->sy);
-	s2 = point(ca->sx+ca->width-1,ca->sy+ca->height-1);
-	d1 = point(ca->dx,ca->dy);
-	d2 = point(ca->dx+ca->width-1,ca->dy+ca->height-1);
 	if ((ca->sy > ca->dy) || ((ca->sy == ca->dy) && (ca->sx > ca->dx)))
 		direction = 0;
 	else
 		direction = 2;
 
-	cyblafb_sync(info);
-
-	out32(GE44,0xa0000000|1<<19|1<<2|direction);
-	out32(GE00,direction?s2:s1);
-	out32(GE04,direction?s1:s2);
-	out32(GE08,direction?d2:d1);
-	out32(GE0C,direction?d1:d2);
-
+	out32(GEB8, basestride | ((ca->dy * info->var.xres_virtual *
+				   info->var.bits_per_pixel) >> 6));
+	out32(GEC8, basestride | ((ca->sy * info->var.xres_virtual *
+				   info->var.bits_per_pixel) >> 6));
+	out32(GE44, 0xa0000000 | 1 << 19 | 1 << 2 | direction);
+	out32(GE00, direction ? s2 : s1);
+	out32(GE04, direction ? s1 : s2);
+	out32(GE08, direction ? d2 : d1);
+	out32(GE0C, direction ? d1 : d2);
 }
 
 //=======================================================================
 //
 // Cyberblade specific imageblit
 //
-// Accelerated for the most usual case, blitting 1-bit deep character
-// character images. Everything else is passed to the generic imageblit.
+// Accelerated for the most usual case, blitting 1 - bit deep
+// character images. Everything else is passed to the generic imageblit
+// unless it is so insane that it is better to printk an alert.
+//
+// Hardware bug: _Never_ blit across pixel column 2048, that will lock
+// the system. We split those blit requests into three blitting
+// operations.
 //
 //=======================================================================
 
 static void cyblafb_imageblit(struct fb_info *info,
 			      const struct fb_image *image)
 {
-
 	u32 fgcol, bgcol;
+	u32 *pd = (u32 *) image->data;
+	u32 bpp = info->var.bits_per_pixel;
 
-	int i;
-	int bpp = info->var.bits_per_pixel;
-	int index = 0;
-	int index_end=image->height * image->width / 8;
-	int width_dds=image->width / 32;
-	int width_dbs=image->width % 32;
-
-	if (image->depth != 1 || bpp < 8 || bpp > 32 || bpp % 8 != 0 ||
-	    image->width % 8 != 0 || image->width == 0 || image->height == 0) {
-		cfb_imageblit(info,image);
+	KD_GRAPHICS_RETURN();
+
+	// Used only for drawing the penguine (image->depth > 1)
+	if (image->depth != 1) {
+		cfb_imageblit(info, image);
+		return;
+	}
+	// That should never happen, but it would be fatal
+	if (image->width == 0 || image->height == 0) {
+		output("imageblit: width/height 0 detected\n");
 		return;
 	}
 
 	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
 	    info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
-		fgcol = ((u32*)(info->pseudo_palette))[image->fg_color];
-		bgcol = ((u32*)(info->pseudo_palette))[image->bg_color];
+		fgcol = ((u32 *) (info->pseudo_palette))[image->fg_color];
+		bgcol = ((u32 *) (info->pseudo_palette))[image->bg_color];
 	} else {
 		fgcol = image->fg_color;
 		bgcol = image->bg_color;
 	}
 
 	switch (bpp) {
-		case 8:
-			fgcol |= fgcol <<8; fgcol |= fgcol <<16;
-			bgcol |= bgcol <<8; bgcol |= bgcol <<16;
-			break;
-		case 16:
-			fgcol |= fgcol <<16;
-			bgcol |= bgcol <<16;
-			break;
-		default:
-			 break;
+	case 8:
+		fgcol |= fgcol << 8;
+		bgcol |= bgcol << 8;
+	case 16:
+		fgcol |= fgcol << 16;
+		bgcol |= bgcol << 16;
+	default:
+		break;
 	}
 
-	cyblafb_sync(info);
-
-	out32(GE60,fgcol);
-	out32(GE64,bgcol);
-	out32(GE44,0xa0000000 | 1<<20 | 1<<19);
-	out32(GE08,point(image->dx,image->dy));
-	out32(GE0C,point(image->dx+image->width-1,image->dy+image->height-1));
+	out32(GEB8, basestride | ((image->dy * info->var.xres_virtual *
+				   bpp) >> 6));
+	out32(GE60, fgcol);
+	out32(GE64, bgcol);
+
+	if (!(image->dx < 2048 && (image->dx + image->width - 1) >= 2048)) {
+		u32 dds = ((image->width + 31) >> 5) * image->height;
+		out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
+		out32(GE08, point(image->dx, 0));
+		out32(GE0C, point(image->dx + image->width - 1,
+				  image->height - 1));
+		while (dds--)
+			out32(GE9C, *pd++);
+	} else {
+		int i, j;
+		u32 ddstotal = (image->width + 31) >> 5;
+		u32 ddsleft = (2048 - image->dx + 31) >> 5;
+		u32 skipleft = ddstotal - ddsleft;
+
+		out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
+		out32(GE08, point(image->dx, 0));
+		out32(GE0C, point(2048 - 1, image->height - 1));
+		for (i = 0; i < image->height; i++) {
+			for (j = 0; j < ddsleft; j++)
+				out32(GE9C, *pd++);
+			pd += skipleft;
+		}
 
-	while(index < index_end) {
-		const char *p = image->data + index;
-		for(i=0;i<width_dds;i++) {
-			out32(GE9C,*(u32*)p);
-			p+=4;
-			index+=4;
+		if (image->dx % 32) {
+			out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
+			out32(GE08, point(2048, 0));
+			if (image->width > ddsleft << 5)
+				out32(GE0C, point(image->dx + (ddsleft << 5) -
+						  1, image->height - 1));
+			else
+				out32(GE0C, point(image->dx + image->width - 1,
+						  image->height - 1));
+			pd = ((u32 *) image->data) + ddstotal - skipleft - 1;
+			for (i = 0; i < image->height; i++) {
+				out32(GE9C, swab32(swab32(*pd) << ((32 -
+					    (image->dx & 31)) & 31)));
+				pd += ddstotal;
+			}
 		}
-		switch(width_dbs) {
-		case 0: break;
-		case 8:	out32(GE9C,*(u8*)p);
-			index+=1;
-			break;
-		case 16: out32(GE9C,*(u16*)p);
-			index+=2;
-			break;
-		case 24: out32(GE9C,*(u16*)p | *(u8*)(p+2)<<16);
-			index+=3;
-			break;
+
+		if (skipleft) {
+			out32(GE44, 0xa0000000 | 1 << 20 | 1 << 19);
+			out32(GE08, point(image->dx + (ddsleft << 5), 0));
+			out32(GE0C, point(image->dx + image->width - 1,
+					  image->height - 1));
+			pd = (u32 *) image->data;
+			for (i = 0; i < image->height; i++) {
+				pd += ddsleft;
+				for (j = 0; j < skipleft; j++)
+					out32(GE9C, *pd++);
+			}
 		}
 	}
 }
@@ -443,7 +526,6 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var,
 			     struct fb_info *info)
 {
 	int bpp = var->bits_per_pixel;
-	int s,t,maxvyres;
 
 	//
 	// we try to support 8, 16, 24 and 32 bpp modes,
@@ -453,9 +535,9 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var,
 	// (This is what tridentfb does ... will be changed in the future)
 	//
 	//
-	if ( bpp % 8 != 0 || bpp < 8 || bpp >32)
+	if (bpp % 8 != 0 || bpp < 8 || bpp > 32)
 		bpp = 8;
-	if (bpp == 24 )
+	if (bpp == 24)
 		bpp = var->bits_per_pixel = 32;
 
 	//
@@ -472,65 +554,93 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var,
 		return -EINVAL;
 
 	//
-	// xres != xres_virtual is broken, fail if such an
-	// unusual mode is requested
+	// we do not allow vclk to exceed 230 MHz. If the requested
+	// vclk is too high, we default to 200 MHz
 	//
-	if (var->xres != var->xres_virtual)
-		return -EINVAL;
+	if ((bpp == 32 ? 200000000 : 100000000) / var->pixclock > 23000)
+		var->pixclock = (bpp == 32 ? 200000000 : 100000000) / 20000;
 
 	//
-	// we do not allow vclk to exceed 230 MHz
+	// enforce (h|v)sync_len limits
 	//
-	if ((bpp==32 ? 200000000 : 100000000) / var->pixclock > 23000)
-		return -EINVAL;
+	var->hsync_len &= ~7;
+	if(var->hsync_len > 248)
+		var->hsync_len = 248;
+
+	var->vsync_len &= 15;
 
 	//
-	// calc max yres_virtual that would fit in memory
-	// and max yres_virtual that could be used for scrolling
-	// and use minimum of the results as maxvyres
-	//
-	// adjust vyres_virtual to maxvyres if necessary
-	// fail if requested yres is bigger than maxvyres
+	// Enforce horizontal and vertical hardware limits.
+	// 1600x1200 is mentioned as a maximum, but higher resolutions could
+	// work with slow refresh, small margins and short sync.
 	//
-	s = (0x1fffff / (var->xres * bpp/8)) + var->yres;
-	t = info->fix.smem_len / (var->xres * bpp/8);
-	maxvyres = t < s ? t : s;
-	if (maxvyres < var->yres_virtual)
-		var->yres_virtual=maxvyres;
-	if (maxvyres < var->yres)
+	var->xres &= ~7;
+
+	if (((var->xres + var->left_margin + var->right_margin +
+			var->hsync_len) > (bpp == 32 ? 2040 : 4088)) ||
+			((var->yres + var->upper_margin + var->lower_margin +
+			var->vsync_len) > 2047))
 		return -EINVAL;
 
-	switch (bpp) {
-		case 8:
-			var->red.offset = 0;
-			var->green.offset = 0;
-			var->blue.offset = 0;
-			var->red.length = 6;
-			var->green.length = 6;
-			var->blue.length = 6;
-			break;
-		case 16:
-			var->red.offset = 11;
-			var->green.offset = 5;
-			var->blue.offset = 0;
-			var->red.length = 5;
-			var->green.length = 6;
-			var->blue.length = 5;
-			break;
-		case 32:
-			var->red.offset = 16;
-			var->green.offset = 8;
-			var->blue.offset = 0;
-			var->red.length = 8;
-			var->green.length = 8;
-			var->blue.length = 8;
-			break;
-		default:
+	if ((var->xres > 1600) || (var->yres > 1200))
+		output("Mode %dx%d exceeds documented limits.\n",
+					   var->xres, var->yres);
+	//
+	// try to be smart about (x|y)res_virtual problems.
+	//
+	if (var->xres > var->xres_virtual)
+		var->xres_virtual = var->xres;
+	if (var->yres > var->yres_virtual)
+		var->yres_virtual = var->yres;
+
+	if (bpp == 8 || bpp == 16) {
+		if (var->xres_virtual > 4088)
+			var->xres_virtual = 4088;
+	} else {
+		if (var->xres_virtual > 2040)
+			var->xres_virtual = 2040;
+	}
+	var->xres_virtual &= ~7;
+	while (var->xres_virtual * var->yres_virtual * bpp / 8 >
+	       info->fix.smem_len) {
+		if (var->yres_virtual > var->yres)
+			var->yres_virtual--;
+		else if (var->xres_virtual > var->xres)
+			var->xres_virtual -= 8;
+		else
 			return -EINVAL;
 	}
 
-	return 0;
+	switch (bpp) {
+	case 8:
+		var->red.offset = 0;
+		var->green.offset = 0;
+		var->blue.offset = 0;
+		var->red.length = 6;
+		var->green.length = 6;
+		var->blue.length = 6;
+		break;
+	case 16:
+		var->red.offset = 11;
+		var->green.offset = 5;
+		var->blue.offset = 0;
+		var->red.length = 5;
+		var->green.length = 6;
+		var->blue.length = 5;
+		break;
+	case 32:
+		var->red.offset = 16;
+		var->green.offset = 8;
+		var->blue.offset = 0;
+		var->red.length = 8;
+		var->green.length = 8;
+		var->blue.length = 8;
+		break;
+	default:
+		return -EINVAL;
+	}
 
+	return 0;
 }
 
 //=====================================================================
@@ -543,23 +653,25 @@ static int cyblafb_check_var(struct fb_var_screeninfo *var,
 // it, so it is also safe to be used here. BTW: datasheet CR0E on page
 // 90 really is CR1E, the real CRE is documented on page 72.
 //
+// BUT:
+//
+// As of internal version 0.60 we do not use vga panning any longer.
+// Vga panning did not allow us the use of all available video memory
+// and thus prevented ywrap scrolling. We do use the "right view"
+// register now.
+//
+//
 //=====================================================================
 
 static int cyblafb_pan_display(struct fb_var_screeninfo *var,
 			       struct fb_info *info)
 {
-	unsigned int offset;
+	KD_GRAPHICS_RETURN(0);
 
-	offset=(var->xoffset+(var->yoffset*var->xres))*var->bits_per_pixel/32;
 	info->var.xoffset = var->xoffset;
 	info->var.yoffset = var->yoffset;
-
-	write3X4(CR0D,offset & 0xFF);
-	write3X4(CR0C,(offset & 0xFF00) >> 8);
-	write3X4(CR1E,(read3X4(CR1E) & 0xDF) | ((offset & 0x10000) >> 11));
-	write3X4(CR27,(read3X4(CR27) & 0xF8) | ((offset & 0xE0000) >> 17));
-	write3X4(CR2B,(read3X4(CR2B) & 0xDF) | ((offset & 0x100000) >> 15));
-
+	out32(GE10, 0x80000000 | ((var->xoffset + (var->yoffset *
+		    var->xres_virtual)) * var->bits_per_pixel / 32));
 	return 0;
 }
 
@@ -578,56 +690,96 @@ static void regdump(struct cyblafb_par *par)
 		return;
 
 	printk("\n");
-	for(i=0; i<=0xff; i++) {
-		outb(i,0x3d4);
-		printk("CR%02x=%02x ",i,inb(0x3d5));
-		if (i%16==15)
+	for (i = 0; i <= 0xff; i++) {
+		outb(i, 0x3d4);
+		printk("CR%02x=%02x ", i, inb(0x3d5));
+		if (i % 16 == 15)
 			printk("\n");
 	}
 
-	outb(0x30,0x3ce);
-	outb(inb(0x3cf) | 0x40,0x3cf);
-	for(i=0; i<=0x1f; i++) {
-		if (i==0 || (i>2 && i<8) || i==0x10 || i==0x11 || i==0x16) {
-			outb(i,0x3d4);
-			printk("CR%02x=%02x ",i,inb(0x3d5));
+	outb(0x30, 0x3ce);
+	outb(inb(0x3cf) | 0x40, 0x3cf);
+	for (i = 0; i <= 0x1f; i++) {
+		if (i == 0 || (i > 2 && i < 8) || i == 0x10 || i == 0x11
+		    || i == 0x16) {
+			outb(i, 0x3d4);
+			printk("CR%02x=%02x ", i, inb(0x3d5));
 		} else
 			printk("------- ");
-		if (i%16==15)
+		if (i % 16 == 15)
 			printk("\n");
 	}
-	outb(0x30,0x3ce);
-	outb(inb(0x3cf) & 0xbf,0x3cf);
+	outb(0x30, 0x3ce);
+	outb(inb(0x3cf) & 0xbf, 0x3cf);
 
 	printk("\n");
-	for(i=0; i<=0x7f; i++) {
-		outb(i,0x3ce);
-		printk("GR%02x=%02x ",i,inb(0x3cf));
-		if (i%16==15)
+	for (i = 0; i <= 0x7f; i++) {
+		outb(i, 0x3ce);
+		printk("GR%02x=%02x ", i, inb(0x3cf));
+		if (i % 16 == 15)
 			printk("\n");
 	}
 
 	printk("\n");
-	for(i=0; i<=0xff; i++) {
-		outb(i,0x3c4);
-		printk("SR%02x=%02x ",i,inb(0x3c5));
-		if (i%16==15)
+	for (i = 0; i <= 0xff; i++) {
+		outb(i, 0x3c4);
+		printk("SR%02x=%02x ", i, inb(0x3c5));
+		if (i % 16 == 15)
 			printk("\n");
 	}
 
 	printk("\n");
-	for(i=0; i <= 0x1F; i++) {
-		inb(0x3da); // next access is index!
-		outb(i,0x3c0);
-		printk("AR%02x=%02x ",i,inb(0x3c1));
-		if (i%16==15)
+	for (i = 0; i <= 0x1F; i++) {
+		inb(0x3da);	// next access is index!
+		outb(i, 0x3c0);
+		printk("AR%02x=%02x ", i, inb(0x3c1));
+		if (i % 16 == 15)
 			printk("\n");
 	}
 	printk("\n");
 
-	inb(0x3DA);			// reset internal flag to 3c0 index
-	outb(0x20,0x3C0);		// enable attr
+	inb(0x3DA);		// reset internal flag to 3c0 index
+	outb(0x20, 0x3C0);	// enable attr
+
+	return;
+}
+
+//=======================================================================
+//
+// Save State
+//
+// This function is called while a switch to KD_TEXT is in progress,
+// before any of the other functions are called.
+//
+//=======================================================================
 
+static void cyblafb_save_state(struct fb_info *info)
+{
+	struct cyblafb_par *par = info->par;
+	if (verbosity > 0)
+		output("Switching to KD_TEXT\n");
+	disabled = 0;
+	regdump(par);
+	enable_mmio();
+	return;
+}
+
+//=======================================================================
+//
+// Restore State
+//
+// This function is called while a switch to KD_GRAPHICS is in progress,
+// We have to turn on vga style panning registers again because the
+// trident driver of X does not know about GE10.
+//
+//=======================================================================
+
+static void cyblafb_restore_state(struct fb_info *info)
+{
+	if (verbosity > 0)
+		output("Switching to KD_GRAPHICS\n");
+	out32(GE10, 0);
+	disabled = 1;
 	return;
 }
 
@@ -640,32 +792,34 @@ static void regdump(struct cyblafb_par *par)
 static int cyblafb_set_par(struct fb_info *info)
 {
 	struct cyblafb_par *par = info->par;
-	u32
-	htotal,hdispend,hsyncstart,hsyncend,hblankstart,hblankend,preendfetch,
-		vtotal,vdispend,vsyncstart,vsyncend,vblankstart,vblankend;
+	u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart,
+	    hblankend, preendfetch, vtotal, vdispend, vsyncstart,
+	    vsyncend, vblankstart, vblankend;
 	struct fb_var_screeninfo *var = &info->var;
 	int bpp = var->bits_per_pixel;
 	int i;
 
+	KD_GRAPHICS_RETURN(0);
+
 	if (verbosity > 0)
 		output("Switching to new mode: "
 		       "fbset -g %d %d %d %d %d -t %d %d %d %d %d %d %d\n",
-			var->xres,var->yres,var->xres_virtual,
-			var->yres_virtual,var->bits_per_pixel,var->pixclock,
-			var->left_margin,var->right_margin,var->upper_margin,
-			var->lower_margin,var->hsync_len,var->vsync_len);
+		       var->xres, var->yres, var->xres_virtual,
+		       var->yres_virtual, var->bits_per_pixel, var->pixclock,
+		       var->left_margin, var->right_margin, var->upper_margin,
+		       var->lower_margin, var->hsync_len, var->vsync_len);
 
 	htotal = (var->xres + var->left_margin + var->right_margin +
-						 var->hsync_len) / 8 - 5;
-	hdispend = var->xres/8 - 1;
-	hsyncstart = (var->xres + var->right_margin)/8;
-	hsyncend = var->hsync_len/8;
+		  var->hsync_len) / 8 - 5;
+	hdispend = var->xres / 8 - 1;
+	hsyncstart = (var->xres + var->right_margin) / 8;
+	hsyncend = var->hsync_len / 8;
 	hblankstart = hdispend + 1;
 	hblankend = htotal + 3; // should be htotal + 5, bios does it this way
-	preendfetch = ((var->xres >> 3) + 1) * ((bpp+1) >> 3);
+	preendfetch = ((var->xres >> 3) + 1) * ((bpp + 1) >> 3);
 
 	vtotal = var->yres + var->upper_margin + var->lower_margin +
-						 var->vsync_len - 2;
+							var->vsync_len - 2;
 	vdispend = var->yres - 1;
 	vsyncstart = var->yres + var->lower_margin;
 	vblankstart = var->yres;
@@ -674,101 +828,99 @@ static int cyblafb_set_par(struct fb_info *info)
 
 	enable_mmio();		// necessary! ... check X ...
 
-	write3X4(CR11,read3X4(CR11) & 0x7F); // unlock cr00 .. cr07
+	write3X4(CR11, read3X4(CR11) & 0x7F);	// unlock cr00 .. cr07
 
-	write3CE(GR30,8);
+	write3CE(GR30, 8);
 
 	if ((displaytype == DISPLAY_FP) && var->xres < nativex) {
 
 		// stretch or center ?
 
-		out8(0x3C2,0xEB);
+		out8(0x3C2, 0xEB);
 
-		write3CE(GR30,read3CE(GR30) | 0x81); // shadow mode on
+		write3CE(GR30, read3CE(GR30) | 0x81);	// shadow mode on
 
 		if (center) {
-			write3CE(GR52,(read3CE(GR52) & 0x7C) | 0x80);
-			write3CE(GR53,(read3CE(GR53) & 0x7C) | 0x80);
-		}
-		else if (stretch) {
-			write3CE(GR5D,0);
-			write3CE(GR52,(read3CE(GR52) & 0x7C) | 1);
-			write3CE(GR53,(read3CE(GR53) & 0x7C) | 1);
+			write3CE(GR52, (read3CE(GR52) & 0x7C) | 0x80);
+			write3CE(GR53, (read3CE(GR53) & 0x7C) | 0x80);
+		} else if (stretch) {
+			write3CE(GR5D, 0);
+			write3CE(GR52, (read3CE(GR52) & 0x7C) | 1);
+			write3CE(GR53, (read3CE(GR53) & 0x7C) | 1);
 		}
 
 	} else {
-		out8(0x3C2,0x2B);
-		write3CE(GR30,8);
+		out8(0x3C2, 0x2B);
+		write3CE(GR30, 8);
 	}
 
 	//
 	// Setup CRxx regs
 	//
 
-	write3X4(CR00,htotal & 0xFF);
-	write3X4(CR01,hdispend & 0xFF);
-	write3X4(CR02,hblankstart & 0xFF);
-	write3X4(CR03,hblankend & 0x1F);
-	write3X4(CR04,hsyncstart & 0xFF);
-	write3X4(CR05,(hsyncend & 0x1F) | ((hblankend & 0x20)<<2));
-	write3X4(CR06,vtotal & 0xFF);
-	write3X4(CR07,(vtotal & 0x100) >> 8 |
-		      (vdispend & 0x100) >> 7 |
-		      (vsyncstart & 0x100) >> 6 |
-		      (vblankstart & 0x100) >> 5 |
-		      0x10 |
-		      (vtotal & 0x200) >> 4 |
-		      (vdispend & 0x200) >> 3 |
-		      (vsyncstart & 0x200) >> 2);
-	write3X4(CR08,0);
-	write3X4(CR09,(vblankstart & 0x200) >> 4 | 0x40 |  // FIX !!!
-		      ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0));
-	write3X4(CR0A,0);  // Init to some reasonable default
-	write3X4(CR0B,0);  // Init to some reasonable default
-	write3X4(CR0C,0);  // Offset 0
-	write3X4(CR0D,0);  // Offset 0
-	write3X4(CR0E,0);  // Init to some reasonable default
-	write3X4(CR0F,0);  // Init to some reasonable default
-	write3X4(CR10,vsyncstart & 0xFF);
-	write3X4(CR11,(vsyncend & 0x0F));
-	write3X4(CR12,vdispend & 0xFF);
-	write3X4(CR13,((info->var.xres * bpp)/(4*16)) & 0xFF);
-	write3X4(CR14,0x40);  // double word mode
-	write3X4(CR15,vblankstart & 0xFF);
-	write3X4(CR16,vblankend & 0xFF);
-	write3X4(CR17,0xC3);
-	write3X4(CR18,0xFF);
+	write3X4(CR00, htotal & 0xFF);
+	write3X4(CR01, hdispend & 0xFF);
+	write3X4(CR02, hblankstart & 0xFF);
+	write3X4(CR03, hblankend & 0x1F);
+	write3X4(CR04, hsyncstart & 0xFF);
+	write3X4(CR05, (hsyncend & 0x1F) | ((hblankend & 0x20) << 2));
+	write3X4(CR06, vtotal & 0xFF);
+	write3X4(CR07, (vtotal & 0x100) >> 8 |
+		       (vdispend & 0x100) >> 7 |
+		       (vsyncstart & 0x100) >> 6 |
+		       (vblankstart & 0x100) >> 5 |
+		       0x10 |
+		       (vtotal & 0x200) >> 4 |
+		       (vdispend & 0x200) >> 3 | (vsyncstart & 0x200) >> 2);
+	write3X4(CR08, 0);
+	write3X4(CR09, (vblankstart & 0x200) >> 4 | 0x40 |	// FIX !!!
+		       ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0));
+	write3X4(CR0A, 0);	// Init to some reasonable default
+	write3X4(CR0B, 0);	// Init to some reasonable default
+	write3X4(CR0C, 0);	// Offset 0
+	write3X4(CR0D, 0);	// Offset 0
+	write3X4(CR0E, 0);	// Init to some reasonable default
+	write3X4(CR0F, 0);	// Init to some reasonable default
+	write3X4(CR10, vsyncstart & 0xFF);
+	write3X4(CR11, (vsyncend & 0x0F));
+	write3X4(CR12, vdispend & 0xFF);
+	write3X4(CR13, ((info->var.xres_virtual * bpp) / (4 * 16)) & 0xFF);
+	write3X4(CR14, 0x40);	// double word mode
+	write3X4(CR15, vblankstart & 0xFF);
+	write3X4(CR16, vblankend & 0xFF);
+	write3X4(CR17, 0xE3);
+	write3X4(CR18, 0xFF);
 	//	 CR19: needed for interlaced modes ... ignore it for now
-	write3X4(CR1A,0x07); // Arbitration Control Counter 1
-	write3X4(CR1B,0x07); // Arbitration Control Counter 2
-	write3X4(CR1C,0x07); // Arbitration Control Counter 3
-	write3X4(CR1D,0x00); // Don't know, doesn't hurt ;-)
-	write3X4(CR1E,(info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80);
+	write3X4(CR1A, 0x07);	// Arbitration Control Counter 1
+	write3X4(CR1B, 0x07);	// Arbitration Control Counter 2
+	write3X4(CR1C, 0x07);	// Arbitration Control Counter 3
+	write3X4(CR1D, 0x00);	// Don't know, doesn't hurt ; -)
+	write3X4(CR1E, (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80);
 	//	 CR1F: do not set, contains BIOS info about memsize
-	write3X4(CR20,0x20); // enabe wr buf, disable 16bit planar mode
-	write3X4(CR21,0x20); // enable linear memory access
+	write3X4(CR20, 0x20);	// enabe wr buf, disable 16bit planar mode
+	write3X4(CR21, 0x20);	// enable linear memory access
 	//	 CR22: RO cpu latch readback
 	//	 CR23: ???
 	//	 CR24: RO AR flag state
 	//	 CR25: RAMDAC rw timing, pclk buffer tristate control ????
 	//	 CR26: ???
-	write3X4(CR27,(vdispend & 0x400) >> 6 |
-		      (vsyncstart & 0x400) >> 5 |
-		      (vblankstart & 0x400) >> 4 |
-		      (vtotal & 0x400) >> 3 |
-		      0x8);
+	write3X4(CR27, (vdispend & 0x400) >> 6 |
+		       (vsyncstart & 0x400) >> 5 |
+		       (vblankstart & 0x400) >> 4 |
+		       (vtotal & 0x400) >> 3 |
+		       0x8);
 	//	 CR28: ???
-	write3X4(CR29,(read3X4(CR29) & 0xCF) |
-		      ((((info->var.xres * bpp) / (4*16)) & 0x300) >>4));
-	write3X4(CR2A,read3X4(CR2A) | 0x40);
-	write3X4(CR2B,(htotal & 0x100) >> 8 |
-		      (hdispend & 0x100) >> 7 |
-		      // (0x00 & 0x100) >> 6 |	 hinterlace para bit 8 ???
-		      (hsyncstart & 0x100) >> 5 |
-		      (hblankstart & 0x100) >> 4);
+	write3X4(CR29, (read3X4(CR29) & 0xCF) | ((((info->var.xres_virtual *
+			bpp) / (4 * 16)) & 0x300) >> 4));
+	write3X4(CR2A, read3X4(CR2A) | 0x40);
+	write3X4(CR2B, (htotal & 0x100) >> 8 |
+		       (hdispend & 0x100) >> 7 |
+		       // (0x00 & 0x100) >> 6 |   hinterlace para bit 8 ???
+		       (hsyncstart & 0x100) >> 5 |
+		       (hblankstart & 0x100) >> 4);
 	//	 CR2C: ???
 	//	 CR2D: initialized in cyblafb_setup_GE()
-	write3X4(CR2F,0x92); // conservative, better signal quality
+	write3X4(CR2F, 0x92);	// conservative, better signal quality
 	//	 CR30: reserved
 	//	 CR31: reserved
 	//	 CR32: reserved
@@ -777,96 +929,116 @@ static int cyblafb_set_par(struct fb_info *info)
 	//	 CR35: disabled in CR36
 	//	 CR36: initialized in cyblafb_setup_GE
 	//	 CR37: i2c, ignore for now
-	write3X4(CR38,(bpp == 8) ? 0x00 :	//
-		      (bpp == 16) ? 0x05 :	// highcolor
-		      (bpp == 24) ? 0x29 :	// packed 24bit truecolor
-		      (bpp == 32) ? 0x09 : 0);	// truecolor, 16 bit pixelbus
-	write3X4(CR39,0x01 |			// MMIO enable
-		      (pcirb ? 0x02 : 0) | // pci read burst enable
-		      (pciwb ? 0x04 : 0)); // pci write burst enable
-	write3X4(CR55,0x1F | // pci clocks * 2 for STOP# during 1st data phase
-		      (pcirr ? 0x40 : 0) | // pci read retry enable
-		      (pciwr ? 0x80 : 0)); // pci write retry enable
-	write3X4(CR56,preendfetch >> 8 < 2 ? (preendfetch >> 8 & 0x01)|2 : 0);
-	write3X4(CR57,preendfetch >> 8 < 2 ? preendfetch & 0xff : 0);
-	write3X4(CR58,0x82);	// Bios does this .... don't know more
+	write3X4(CR38, (bpp == 8) ? 0x00 :	//
+		       (bpp == 16) ? 0x05 :	// highcolor
+		       (bpp == 24) ? 0x29 :	// packed 24bit truecolor
+		       (bpp == 32) ? 0x09 : 0); // truecolor, 16 bit pixelbus
+	write3X4(CR39, 0x01 |	// MMIO enable
+		       (pcirb ? 0x02 : 0) |	// pci read burst enable
+		       (pciwb ? 0x04 : 0));	// pci write burst enable
+	write3X4(CR55, 0x1F | // pci clocks * 2 for STOP# during 1st data phase
+		       (pcirr ? 0x40 : 0) |	// pci read retry enable
+		       (pciwr ? 0x80 : 0));	// pci write retry enable
+	write3X4(CR56, preendfetch >> 8 < 2 ? (preendfetch >> 8 & 0x01) | 2
+					    : 0);
+	write3X4(CR57, preendfetch >> 8 < 2 ? preendfetch & 0xff : 0);
+	write3X4(CR58, 0x82);	// Bios does this .... don't know more
 	//
 	// Setup SRxx regs
 	//
-	write3C4(SR00,3);
-	write3C4(SR01,1);	//set char clock 8 dots wide
-	write3C4(SR02,0x0F);	//enable 4 maps needed in chain4 mode
-	write3C4(SR03,0);	//no character map select
-	write3C4(SR04,0x0E);	//memory mode: ext mem, even, chain4
+	write3C4(SR00, 3);
+	write3C4(SR01, 1);	//set char clock 8 dots wide
+	write3C4(SR02, 0x0F);	//enable 4 maps needed in chain4 mode
+	write3C4(SR03, 0);	//no character map select
+	write3C4(SR04, 0x0E);	//memory mode: ext mem, even, chain4
 
-	out8(0x3C4,0x0b);
+	out8(0x3C4, 0x0b);
 	in8(0x3C5);		// Set NEW mode
-	write3C4(SR0D,0x00);	// test ... check
+	write3C4(SR0D, 0x00);	// test ... check
 
-	set_vclk(par,(bpp==32 ? 200000000 : 100000000)/
-		 info->var.pixclock); //SR18,SR19
+	set_vclk(par, (bpp == 32 ? 200000000 : 100000000)
+					/ info->var.pixclock);	//SR18, SR19
 
 	//
 	// Setup GRxx regs
 	//
-	write3CE(GR00,0x00);	// test ... check
-	write3CE(GR01,0x00);	// test ... check
-	write3CE(GR02,0x00);	// test ... check
-	write3CE(GR03,0x00);	// test ... check
-	write3CE(GR04,0x00);	// test ... check
-	write3CE(GR05,0x40);	// no CGA compat,allow 256 col
-	write3CE(GR06,0x05);	// graphics mode
-	write3CE(GR07,0x0F);	// planes?
-	write3CE(GR08,0xFF);	// test ... check
-	write3CE(GR0F,(bpp==32)?0x1A:0x12); // div vclk by 2 if 32bpp, chain4
-	write3CE(GR20,0xC0);	// test ... check
-	write3CE(GR2F,0xA0);	// PCLK = VCLK, no skew,
+	write3CE(GR00, 0x00);	// test ... check
+	write3CE(GR01, 0x00);	// test ... check
+	write3CE(GR02, 0x00);	// test ... check
+	write3CE(GR03, 0x00);	// test ... check
+	write3CE(GR04, 0x00);	// test ... check
+	write3CE(GR05, 0x40);	// no CGA compat, allow 256 col
+	write3CE(GR06, 0x05);	// graphics mode
+	write3CE(GR07, 0x0F);	// planes?
+	write3CE(GR08, 0xFF);	// test ... check
+	write3CE(GR0F, (bpp == 32) ? 0x1A : 0x12); // vclk / 2 if 32bpp, chain4
+	write3CE(GR20, 0xC0);	// test ... check
+	write3CE(GR2F, 0xA0);	// PCLK = VCLK, no skew,
 
 	//
 	// Setup ARxx regs
 	//
-	for(i = 0;i < 0x10;i++) // set AR00 .. AR0f
-		write3C0(i,i);
-	write3C0(AR10,0x41);	// graphics mode and support 256 color modes
-	write3C0(AR12,0x0F);	// planes
-	write3C0(AR13,0);	// horizontal pel panning
+	for (i = 0; i < 0x10; i++)	// set AR00 .. AR0f
+		write3C0(i, i);
+	write3C0(AR10, 0x41);	// graphics mode and support 256 color modes
+	write3C0(AR12, 0x0F);	// planes
+	write3C0(AR13, 0);	// horizontal pel panning
 	in8(0x3DA);		// reset internal flag to 3c0 index
-	out8(0x3C0,0x20);	// enable attr
+	out8(0x3C0, 0x20);	// enable attr
 
 	//
 	// Setup hidden RAMDAC command register
 	//
-	in8(0x3C8);  // these reads are
-	in8(0x3C6);  // necessary to
-	in8(0x3C6);  // unmask the RAMDAC
-	in8(0x3C6);  // command reg, otherwise
-	in8(0x3C6);  // we would write the pixelmask reg!
-	out8(0x3C6,(bpp ==  8) ? 0x00 : 	// 256 colors
-		   (bpp == 15) ? 0x10 : 	//
-		   (bpp == 16) ? 0x30 : 	// hicolor
-		   (bpp == 24) ? 0xD0 : 	// truecolor
-		   (bpp == 32) ? 0xD0 : 0);	// truecolor
+	in8(0x3C8);		// these reads are
+	in8(0x3C6);		// necessary to
+	in8(0x3C6);		// unmask the RAMDAC
+	in8(0x3C6);		// command reg, otherwise
+	in8(0x3C6);		// we would write the pixelmask reg!
+	out8(0x3C6, (bpp == 8) ? 0x00 : // 256 colors
+	     (bpp == 15) ? 0x10 :	//
+	     (bpp == 16) ? 0x30 :	// hicolor
+	     (bpp == 24) ? 0xD0 :	// truecolor
+	     (bpp == 32) ? 0xD0 : 0);	// truecolor
 	in8(0x3C8);
 
 	//
 	// GR31 is not mentioned in the datasheet
 	//
 	if (displaytype == DISPLAY_FP)
-		write3CE(GR31,(read3CE(GR31) & 0x8F) |
+		write3CE(GR31, (read3CE(GR31) & 0x8F) |
 			 ((info->var.yres > 1024) ? 0x50 :
-			 (info->var.yres >   768) ? 0x30 :
-			 (info->var.yres >   600) ? 0x20 :
-			 (info->var.yres >   480) ? 0x10 : 0));
+			  (info->var.yres > 768) ? 0x30 :
+			  (info->var.yres > 600) ? 0x20 :
+			  (info->var.yres > 480) ? 0x10 : 0));
 
 	info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR
 				      : FB_VISUAL_TRUECOLOR;
-	info->fix.line_length = info->var.xres * (bpp >> 3);
-	info->cmap.len = (bpp == 8) ? 256: 16;
+	info->fix.line_length = info->var.xres_virtual * (bpp >> 3);
+	info->cmap.len = (bpp == 8) ? 256 : 16;
 
 	//
 	// init acceleration engine
 	//
-	cyblafb_setup_GE(info->var.xres,info->var.bits_per_pixel);
+	cyblafb_setup_GE(info->var.xres_virtual, info->var.bits_per_pixel);
+
+	//
+	// Set/clear flags to allow proper scroll mode selection.
+	//
+	if (var->xres == var->xres_virtual)
+		info->flags &= ~FBINFO_HWACCEL_XPAN;
+	else
+		info->flags |= FBINFO_HWACCEL_XPAN;
+
+	if (var->yres == var->yres_virtual)
+		info->flags &= ~FBINFO_HWACCEL_YPAN;
+	else
+		info->flags |= FBINFO_HWACCEL_YPAN;
+
+	if (info->fix.smem_len !=
+	    var->xres_virtual * var->yres_virtual * bpp / 8)
+		info->flags &= ~FBINFO_HWACCEL_YWRAP;
+	else
+		info->flags |= FBINFO_HWACCEL_YWRAP;
 
 	regdump(par);
 
@@ -885,27 +1057,27 @@ static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green,
 {
 	int bpp = info->var.bits_per_pixel;
 
+	KD_GRAPHICS_RETURN(0);
+
 	if (regno >= info->cmap.len)
 		return 1;
 
 	if (bpp == 8) {
-		out8(0x3C6,0xFF);
-		out8(0x3C8,regno);
-		out8(0x3C9,red>>10);
-		out8(0x3C9,green>>10);
-		out8(0x3C9,blue>>10);
-
-	} else if (bpp == 16)				// RGB 565
-		((u32*)info->pseudo_palette)[regno] =
-			(red & 0xF800) |
-			((green & 0xFC00) >> 5) |
-			((blue & 0xF800) >> 11);
-	else if (bpp == 32)				// ARGB 8888
-		((u32*)info->pseudo_palette)[regno] =
-			((transp & 0xFF00) <<16) |
-			((red & 0xFF00) << 8) |
-			((green & 0xFF00)) |
-			((blue & 0xFF00)>>8);
+		out8(0x3C6, 0xFF);
+		out8(0x3C8, regno);
+		out8(0x3C9, red >> 10);
+		out8(0x3C9, green >> 10);
+		out8(0x3C9, blue >> 10);
+
+	} else if (bpp == 16)	// RGB 565
+		((u32 *) info->pseudo_palette)[regno] =
+		    (red & 0xF800) |
+		    ((green & 0xFC00) >> 5) | ((blue & 0xF800) >> 11);
+	else if (bpp == 32)	// ARGB 8888
+		((u32 *) info->pseudo_palette)[regno] =
+		    ((transp & 0xFF00) << 16) |
+		    ((red & 0xFF00) << 8) |
+		    ((green & 0xFF00)) | ((blue & 0xFF00) >> 8);
 
 	return 0;
 }
@@ -918,40 +1090,41 @@ static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green,
 
 static int cyblafb_blank(int blank_mode, struct fb_info *info)
 {
-	unsigned char PMCont,DPMSCont;
+	unsigned char PMCont, DPMSCont;
+
+	KD_GRAPHICS_RETURN(0);
 
 	if (displaytype == DISPLAY_FP)
 		return 0;
 
-	out8(0x83C8,0x04); 		// DPMS Control
+	out8(0x83C8, 0x04);	// DPMS Control
 	PMCont = in8(0x83C6) & 0xFC;
 
 	DPMSCont = read3CE(GR23) & 0xFC;
 
-	switch (blank_mode)
-	{
-	case FB_BLANK_UNBLANK:       // Screen: On, HSync: On, VSync: On
-	case FB_BLANK_NORMAL:	     // Screen: Off, HSync: On, VSync: On
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:	// Screen: On, HSync: On, VSync: On
+	case FB_BLANK_NORMAL:	// Screen: Off, HSync: On, VSync: On
 		PMCont |= 0x03;
 		DPMSCont |= 0x00;
 		break;
-	case FB_BLANK_HSYNC_SUSPEND: // Screen: Off, HSync: Off, VSync: On
+	case FB_BLANK_HSYNC_SUSPEND:	// Screen: Off, HSync: Off, VSync: On
 		PMCont |= 0x02;
 		DPMSCont |= 0x01;
 		break;
-	case FB_BLANK_VSYNC_SUSPEND: // Screen: Off, HSync: On, VSync: Off
+	case FB_BLANK_VSYNC_SUSPEND:	// Screen: Off, HSync: On, VSync: Off
 		PMCont |= 0x02;
 		DPMSCont |= 0x02;
 		break;
-	case FB_BLANK_POWERDOWN:     // Screen: Off, HSync: Off, VSync: Off
+	case FB_BLANK_POWERDOWN:	// Screen: Off, HSync: Off, VSync: Off
 		PMCont |= 0x00;
 		DPMSCont |= 0x03;
 		break;
 	}
 
-	write3CE(GR23,DPMSCont);
-	out8(0x83C8,4);
-	out8(0x83C6,PMCont);
+	write3CE(GR23, DPMSCont);
+	out8(0x83C8, 4);
+	out8(0x83C6, PMCont);
 	//
 	// let fbcon do a softblank for us
 	//
@@ -959,15 +1132,18 @@ static int cyblafb_blank(int blank_mode, struct fb_info *info)
 }
 
 static struct fb_ops cyblafb_ops __devinitdata = {
-	.owner	= THIS_MODULE,
+	.owner = THIS_MODULE,
 	.fb_setcolreg = cyblafb_setcolreg,
 	.fb_pan_display = cyblafb_pan_display,
 	.fb_blank = cyblafb_blank,
 	.fb_check_var = cyblafb_check_var,
 	.fb_set_par = cyblafb_set_par,
 	.fb_fillrect = cyblafb_fillrect,
-	.fb_copyarea= cyblafb_copyarea,
+	.fb_copyarea = cyblafb_copyarea,
 	.fb_imageblit = cyblafb_imageblit,
+	.fb_sync = cyblafb_sync,
+	.fb_restore_state = cyblafb_restore_state,
+	.fb_save_state = cyblafb_save_state,
 };
 
 //==========================================================================
@@ -986,74 +1162,89 @@ static struct fb_ops cyblafb_ops __devinitdata = {
 
 static int __devinit getstartupmode(struct fb_info *info)
 {
-	u32	htotal,hdispend,hsyncstart,hsyncend,hblankstart,hblankend,
-		vtotal,vdispend,vsyncstart,vsyncend,vblankstart,vblankend,
-		cr00,cr01,cr02,cr03,cr04,cr05,cr2b,
-		cr06,cr07,cr09,cr10,cr11,cr12,cr15,cr16,cr27,
-		cr38,
-		sr0d,sr18,sr19,
-		gr0f,
-		fi,pxclkdiv,vclkdiv,tmp,i;
+	u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart, hblankend,
+	    vtotal, vdispend, vsyncstart, vsyncend, vblankstart, vblankend,
+	    cr00, cr01, cr02, cr03, cr04, cr05, cr2b,
+	    cr06, cr07, cr09, cr10, cr11, cr12, cr15, cr16, cr27,
+	    cr38, sr0d, sr18, sr19, gr0f, fi, pxclkdiv, vclkdiv, tmp, i;
 
 	struct modus {
-		int xres; int yres; int vyres; int bpp; int pxclk;
-		int left_margin; int right_margin; int upper_margin;
-		int lower_margin; int hsync_len; int vsync_len;
-	}  modedb[5] = {
-		{   0,	  0, 8000, 0, 0,   0,  0,  0, 0,   0,  0},
-		{ 640,	480, 3756, 0, 0, -40, 24, 17, 0, 216,  3},
-		{ 800,	600, 3221, 0, 0,  96, 24, 14, 0, 136, 11},
-		{1024,	768, 2815, 0, 0, 144, 24, 29, 0, 120,  3},
-		{1280, 1024, 2662, 0, 0, 232, 16, 39, 0, 160,  3}
+		int xres; int vxres; int yres; int vyres;
+		int bpp; int pxclk;
+		int left_margin; int right_margin;
+		int upper_margin; int lower_margin;
+		int hsync_len; int vsync_len;
+	} modedb[5] = {
+		{
+		0, 2048, 0, 4096, 0, 0, 0, 0, 0, 0, 0, 0}, {
+		640, 2048, 480, 4096, 0, 0, -40, 24, 17, 0, 216, 3}, {
+		800, 2048, 600, 4096, 0, 0, 96, 24, 14, 0, 136, 11}, {
+		1024, 2048, 768, 4096, 0, 0, 144, 24, 29, 0, 120, 3}, {
+		1280, 2048, 1024, 4096, 0, 0, 232, 16, 39, 0, 160, 3}
 	};
 
-	outb(0x00,0x3d4); cr00=inb(0x3d5); outb(0x01,0x3d4); cr01=inb(0x3d5);
-	outb(0x02,0x3d4); cr02=inb(0x3d5); outb(0x03,0x3d4); cr03=inb(0x3d5);
-	outb(0x04,0x3d4); cr04=inb(0x3d5); outb(0x05,0x3d4); cr05=inb(0x3d5);
-	outb(0x06,0x3d4); cr06=inb(0x3d5); outb(0x07,0x3d4); cr07=inb(0x3d5);
-	outb(0x09,0x3d4); cr09=inb(0x3d5); outb(0x10,0x3d4); cr10=inb(0x3d5);
-	outb(0x11,0x3d4); cr11=inb(0x3d5); outb(0x12,0x3d4); cr12=inb(0x3d5);
-	outb(0x15,0x3d4); cr15=inb(0x3d5); outb(0x16,0x3d4); cr16=inb(0x3d5);
-	outb(0x27,0x3d4); cr27=inb(0x3d5); outb(0x2b,0x3d4); cr2b=inb(0x3d5);
-	outb(0x38,0x3d4); cr38=inb(0x3d5); outb(0x0b,0x3c4); inb(0x3c5);
-	outb(0x0d,0x3c4); sr0d=inb(0x3c5); outb(0x18,0x3c4); sr18=inb(0x3c5);
-	outb(0x19,0x3c4); sr19=inb(0x3c5); outb(0x0f,0x3ce); gr0f=inb(0x3cf);
-
-	htotal	    = cr00 | (cr2b & 0x01) << 8;
-	hdispend    = cr01 | (cr2b & 0x02) << 7;
+	outb(0x00, 0x3d4); cr00 = inb(0x3d5);
+	outb(0x01, 0x3d4); cr01 = inb(0x3d5);
+	outb(0x02, 0x3d4); cr02 = inb(0x3d5);
+	outb(0x03, 0x3d4); cr03 = inb(0x3d5);
+	outb(0x04, 0x3d4); cr04 = inb(0x3d5);
+	outb(0x05, 0x3d4); cr05 = inb(0x3d5);
+	outb(0x06, 0x3d4); cr06 = inb(0x3d5);
+	outb(0x07, 0x3d4); cr07 = inb(0x3d5);
+	outb(0x09, 0x3d4); cr09 = inb(0x3d5);
+	outb(0x10, 0x3d4); cr10 = inb(0x3d5);
+	outb(0x11, 0x3d4); cr11 = inb(0x3d5);
+	outb(0x12, 0x3d4); cr12 = inb(0x3d5);
+	outb(0x15, 0x3d4); cr15 = inb(0x3d5);
+	outb(0x16, 0x3d4); cr16 = inb(0x3d5);
+	outb(0x27, 0x3d4); cr27 = inb(0x3d5);
+	outb(0x2b, 0x3d4); cr2b = inb(0x3d5);
+	outb(0x38, 0x3d4); cr38 = inb(0x3d5);
+
+	outb(0x0b, 0x3c4);
+	inb(0x3c5);
+
+	outb(0x0d, 0x3c4); sr0d = inb(0x3c5);
+	outb(0x18, 0x3c4); sr18 = inb(0x3c5);
+	outb(0x19, 0x3c4); sr19 = inb(0x3c5);
+	outb(0x0f, 0x3ce); gr0f = inb(0x3cf);
+
+	htotal = cr00 | (cr2b & 0x01) << 8;
+	hdispend = cr01 | (cr2b & 0x02) << 7;
 	hblankstart = cr02 | (cr2b & 0x10) << 4;
-	hblankend   = (cr03 & 0x1f) | (cr05 & 0x80) >> 2;
-	hsyncstart  = cr04 | (cr2b & 0x08) << 5;
-	hsyncend    = cr05 & 0x1f;
+	hblankend = (cr03 & 0x1f) | (cr05 & 0x80) >> 2;
+	hsyncstart = cr04 | (cr2b & 0x08) << 5;
+	hsyncend = cr05 & 0x1f;
 
 	modedb[0].xres = hblankstart * 8;
 	modedb[0].hsync_len = hsyncend * 8;
 	modedb[0].right_margin = hsyncstart * 8 - modedb[0].xres;
 	modedb[0].left_margin = (htotal + 5) * 8 - modedb[0].xres -
-		modedb[0].right_margin - modedb[0].hsync_len;
-
-	vtotal	    = cr06 | (cr07 & 0x01) << 8 | (cr07 & 0x20) << 4
-			   | (cr27 & 0x80) << 3;
-	vdispend    = cr12 | (cr07 & 0x02) << 7 | (cr07 & 0x40) << 3
-			   | (cr27 & 0x10) << 6;
-	vsyncstart  = cr10 | (cr07 & 0x04) << 6 | (cr07 & 0x80) << 2
-			   | (cr27 & 0x20) << 5;
-	vsyncend    = cr11 & 0x0f;
+	    modedb[0].right_margin - modedb[0].hsync_len;
+
+	vtotal = cr06 | (cr07 & 0x01) << 8 | (cr07 & 0x20) << 4
+	    | (cr27 & 0x80) << 3;
+	vdispend = cr12 | (cr07 & 0x02) << 7 | (cr07 & 0x40) << 3
+	    | (cr27 & 0x10) << 6;
+	vsyncstart = cr10 | (cr07 & 0x04) << 6 | (cr07 & 0x80) << 2
+	    | (cr27 & 0x20) << 5;
+	vsyncend = cr11 & 0x0f;
 	vblankstart = cr15 | (cr07 & 0x08) << 5 | (cr09 & 0x20) << 4
-			   | (cr27 & 0x40) << 4;
-	vblankend   = cr16;
+	    | (cr27 & 0x40) << 4;
+	vblankend = cr16;
 
-	modedb[0].yres	       = vdispend + 1;
-	modedb[0].vsync_len    = vsyncend;
+	modedb[0].yres = vdispend + 1;
+	modedb[0].vsync_len = vsyncend;
 	modedb[0].lower_margin = vsyncstart - modedb[0].yres;
 	modedb[0].upper_margin = vtotal - modedb[0].yres -
-		modedb[0].lower_margin - modedb[0].vsync_len + 2;
+	    modedb[0].lower_margin - modedb[0].vsync_len + 2;
 
 	tmp = cr38 & 0x3c;
 	modedb[0].bpp = tmp == 0 ? 8 : tmp == 4 ? 16 : tmp == 28 ? 24 :
-			tmp == 8 ? 32 : 8;
+	    tmp == 8 ? 32 : 8;
 
-	fi = ((5864727*(sr18+8))/(((sr19&0x3f)+2)*(1<<((sr19&0xc0)>>6))))>>12;
+	fi = ((5864727 * (sr18 + 8)) /
+	      (((sr19 & 0x3f) + 2) * (1 << ((sr19 & 0xc0) >> 6)))) >> 12;
 	pxclkdiv = ((gr0f & 0x08) >> 3 | (gr0f & 0x40) >> 5) + 1;
 	tmp = sr0d & 0x06;
 	vclkdiv = tmp == 0 ? 2 : tmp == 2 ? 4 : tmp == 4 ? 8 : 3; // * 2 !
@@ -1062,10 +1253,10 @@ static int __devinit getstartupmode(struct fb_info *info)
 	if (verbosity > 0)
 		output("detected startup mode: "
 		       "fbset -g %d %d %d ??? %d -t %d %d %d %d %d %d %d\n",
-		       modedb[0].xres,modedb[0].yres,modedb[0].xres,
-		       modedb[0].bpp,modedb[0].pxclk,modedb[0].left_margin,
-		       modedb[0].right_margin,modedb[0].upper_margin,
-		       modedb[0].lower_margin,modedb[0].hsync_len,
+		       modedb[0].xres, modedb[0].yres, modedb[0].xres,
+		       modedb[0].bpp, modedb[0].pxclk, modedb[0].left_margin,
+		       modedb[0].right_margin, modedb[0].upper_margin,
+		       modedb[0].lower_margin, modedb[0].hsync_len,
 		       modedb[0].vsync_len);
 
 	//
@@ -1073,36 +1264,39 @@ static int __devinit getstartupmode(struct fb_info *info)
 	// do not want to do it in another way!
 	//
 
-	tryagain:
+      tryagain:
 
 	i = (mode == NULL) ? 0 :
-	    !strncmp(mode,"640x480",7) ? 1 :
-	    !strncmp(mode,"800x600",7) ? 2 :
-	    !strncmp(mode,"1024x768",8) ? 3 :
-	    !strncmp(mode,"1280x1024",9) ? 4 : 0;
+	    !strncmp(mode, "640x480", 7) ? 1 :
+	    !strncmp(mode, "800x600", 7) ? 2 :
+	    !strncmp(mode, "1024x768", 8) ? 3 :
+	    !strncmp(mode, "1280x1024", 9) ? 4 : 0;
 
 	ref = (ref < 50) ? 50 : (ref > 85) ? 85 : ref;
 
-	if(i==0) {
+	if (i == 0) {
 		info->var.pixclock = modedb[i].pxclk;
 		info->var.bits_per_pixel = modedb[i].bpp;
 	} else {
 		info->var.pixclock = (100000000 /
-			((modedb[i].left_margin + modedb[i].xres +
-			  modedb[i].right_margin + modedb[i].hsync_len
-			 ) * (
-			  modedb[i].upper_margin + modedb[i].yres +
-			  modedb[i].lower_margin + modedb[i].vsync_len
-			 ) *
-			  ref / 10000
-			));
+				      ((modedb[i].left_margin +
+					modedb[i].xres +
+					modedb[i].right_margin +
+					modedb[i].hsync_len) *
+				       (modedb[i].upper_margin +
+					modedb[i].yres +
+					modedb[i].lower_margin +
+					modedb[i].vsync_len) * ref / 10000));
 		info->var.bits_per_pixel = bpp;
 	}
 
 	info->var.left_margin = modedb[i].left_margin;
 	info->var.right_margin = modedb[i].right_margin;
 	info->var.xres = modedb[i].xres;
-	info->var.xres_virtual = modedb[i].xres;
+	if (!(modedb[i].yres == 1280 && modedb[i].bpp == 32))
+		info->var.xres_virtual = modedb[i].vxres;
+	else
+		info->var.xres_virtual = modedb[i].xres;
 	info->var.xoffset = 0;
 	info->var.hsync_len = modedb[i].hsync_len;
 	info->var.upper_margin = modedb[i].upper_margin;
@@ -1114,33 +1308,32 @@ static int __devinit getstartupmode(struct fb_info *info)
 	info->var.sync = 0;
 	info->var.vmode = FB_VMODE_NONINTERLACED;
 
-	if(cyblafb_check_var(&info->var,info)) {
-		// 640x480-8@75 should really never fail. One case would
+	if (cyblafb_check_var(&info->var, info)) {
+		// 640x480 - 8@75 should really never fail. One case would
 		// be fp == 1 and nativex < 640 ... give up then
-		if(i==1 && bpp == 8 && ref == 75){
+		if (i == 1 && bpp == 8 && ref == 75) {
 			output("Can't find a valid mode :-(\n");
 			return -EINVAL;
 		}
 		// Our detected mode is unlikely to fail. If it does,
-		// try 640x480-8@75 ...
-		if(i==0) {
-			mode="640x480";
-			bpp=8;
-			ref=75;
+		// try 640x480 - 8@75 ...
+		if (i == 0) {
+			mode = "640x480";
+			bpp = 8;
+			ref = 75;
 			output("Detected mode failed check_var! "
-			       "Trying 640x480-8@75\n");
+			       "Trying 640x480 - 8@75\n");
 			goto tryagain;
 		}
 		// A specified video mode failed for some reason.
 		// Try the startup mode first
 		output("Specified mode '%s' failed check! "
-			"Falling back to startup mode.\n",mode);
-		mode=NULL;
+		       "Falling back to startup mode.\n", mode);
+		mode = NULL;
 		goto tryagain;
 	}
 
 	return 0;
-
 }
 
 //========================================================
@@ -1160,21 +1353,28 @@ static unsigned int __devinit get_memsize(void)
 	else {
 		tmp = read3X4(CR1F) & 0x0F;
 		switch (tmp) {
-			case 0x03: k = 1 * Mb; break;
-			case 0x07: k = 2 * Mb; break;
-			case 0x0F: k = 4 * Mb; break;
-			case 0x04: k = 8 * Mb; break;
-			default:
-				k = 1 * Mb;
-				output("Unknown memory size code %x in CR1F."
-				       " We default to 1 Mb for now, please"
-				       " do provide a memsize parameter!\n",
-				       tmp);
+		case 0x03:
+			k = 1 * 1024 * 1024;
+			break;
+		case 0x07:
+			k = 2 * 1024 * 1024;
+			break;
+		case 0x0F:
+			k = 4 * 1024 * 1024;
+			break;
+		case 0x04:
+			k = 8 * 1024 * 1024;
+			break;
+		default:
+			k = 1 * 1024 * 1024;
+			output("Unknown memory size code %x in CR1F."
+			       " We default to 1 Mb for now, please"
+			       " do provide a memsize parameter!\n", tmp);
 		}
 	}
 
 	if (verbosity > 0)
-		output("framebuffer size = %d Kb\n",k/Kb);
+		output("framebuffer size = %d Kb\n", k / Kb);
 	return k;
 }
 
@@ -1192,7 +1392,7 @@ static unsigned int __devinit get_displaytype(void)
 		return DISPLAY_FP;
 	if (crt)
 		return DISPLAY_CRT;
-	return (read3CE(GR33) & 0x10)?DISPLAY_FP:DISPLAY_CRT;
+	return (read3CE(GR33) & 0x10) ? DISPLAY_FP : DISPLAY_CRT;
 }
 
 //=====================================
@@ -1203,7 +1403,7 @@ static unsigned int __devinit get_displaytype(void)
 
 static int __devinit get_nativex(void)
 {
-	int x,y,tmp;
+	int x, y, tmp;
 
 	if (nativex)
 		return nativex;
@@ -1211,29 +1411,45 @@ static int __devinit get_nativex(void)
 	tmp = (read3CE(GR52) >> 4) & 3;
 
 	switch (tmp) {
-		case 0:  x = 1280; y = 1024; break;
-		case 2:  x = 1024; y = 768;  break;
-		case 3:  x = 800;  y = 600;  break;
-		case 4:  x = 1400; y = 1050; break;
-		case 1:
-		default: x = 640;  y = 480;  break;
+	case 0: x = 1280; y = 1024;
+		break;
+	case 2: x = 1024; y = 768;
+		break;
+	case 3: x = 800;  y = 600;
+		break;
+	case 4: x = 1400; y = 1050;
+		break;
+	case 1:
+	default:
+		x = 640; y = 480;
+		break;
 	}
 
 	if (verbosity > 0)
-		output("%dx%d flat panel found\n",x,y);
+		output("%dx%d flat panel found\n", x, y);
 	return x;
 }
 
-static int __devinit cybla_pci_probe(struct pci_dev * dev,
-				     const struct pci_device_id * id)
+static int __devinit cybla_pci_probe(struct pci_dev *dev,
+				     const struct pci_device_id *id)
 {
 	struct fb_info *info;
 	struct cyblafb_par *par;
 
-	info = framebuffer_alloc(sizeof(struct cyblafb_par),&dev->dev);
-
+	info = framebuffer_alloc(sizeof(struct cyblafb_par), &dev->dev);
 	if (!info)
-		goto errout_alloc;
+		goto errout_alloc_info;
+
+	info->pixmap.addr = kzalloc(CYBLAFB_PIXMAPSIZE, GFP_KERNEL);
+	if (!info->pixmap.addr) {
+		output("allocation of pixmap buffer failed!\n");
+		goto errout_alloc_pixmap;
+	}
+	info->pixmap.size = CYBLAFB_PIXMAPSIZE - 4;
+	info->pixmap.buf_align = 4;
+	info->pixmap.access_align = 32;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+	info->pixmap.scan_align = 4;
 
 	par = info->par;
 	par->ops = cyblafb_ops;
@@ -1246,26 +1462,31 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev,
 		output("could not enable device!\n");
 		goto errout_enable;
 	}
-
 	// might already be requested by vga console or vesafb,
 	// so we do care about success
-	request_region(0x3c0,32,"cyblafb");
+	if (!request_region(0x3c0, 0x20, "cyblafb")) {
+		output("region 0x3c0/0x20 already reserved\n");
+		vesafb |= 1;
 
+	}
 	//
 	// Graphics Engine Registers
 	//
-	request_region(GEBase,0x100,"cyblafb");
+	if (!request_region(GEBase, 0x100, "cyblafb")) {
+		output("region %#x/0x100 already reserved\n", GEBase);
+		vesafb |= 2;
+	}
 
 	regdump(par);
 
 	enable_mmio();
 
 	// setup MMIO region
-	info->fix.mmio_start = pci_resource_start(dev,1);
+	info->fix.mmio_start = pci_resource_start(dev, 1);
 	info->fix.mmio_len = 0x20000;
 
 	if (!request_mem_region(info->fix.mmio_start,
-				info->fix.mmio_len,"cyblafb")) {
+				info->fix.mmio_len, "cyblafb")) {
 		output("request_mem_region failed for mmio region!\n");
 		goto errout_mmio_reqmem;
 	}
@@ -1276,18 +1497,17 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev,
 		output("ioremap failed for mmio region\n");
 		goto errout_mmio_remap;
 	}
-
 	// setup framebuffer memory ... might already be requested
 	// by vesafb. Not to fail in case of an unsuccessful request
-	// is useful for the development cycle
-	info->fix.smem_start = pci_resource_start(dev,0);
+	// is useful if both are loaded.
+	info->fix.smem_start = pci_resource_start(dev, 0);
 	info->fix.smem_len = get_memsize();
 
 	if (!request_mem_region(info->fix.smem_start,
-				info->fix.smem_len,"cyblafb")) {
-		output("request_mem_region failed for smem region!\n");
-		if (!vesafb)
-			goto errout_smem_req;
+				info->fix.smem_len, "cyblafb")) {
+		output("region %#lx/%#x already reserved\n",
+		       info->fix.smem_start, info->fix.smem_len);
+		vesafb |= 4;
 	}
 
 	info->screen_base = ioremap_nocache(info->fix.smem_start,
@@ -1300,31 +1520,30 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev,
 
 	displaytype = get_displaytype();
 
-	if(displaytype == DISPLAY_FP)
+	if (displaytype == DISPLAY_FP)
 		nativex = get_nativex();
 
-	//
-	// FBINFO_HWACCEL_YWRAP    .... does not work (could be made to work?)
-	// FBINFO_PARTIAL_PAN_OK   .... is not ok
-	// FBINFO_READS_FAST	   .... is necessary for optimal scrolling
-	//
-	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN
-		      | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT
-		      | FBINFO_HWACCEL_IMAGEBLIT | FBINFO_READS_FAST;
+	info->flags = FBINFO_DEFAULT
+		    | FBINFO_HWACCEL_COPYAREA
+		    | FBINFO_HWACCEL_FILLRECT
+		    | FBINFO_HWACCEL_IMAGEBLIT
+		    | FBINFO_READS_FAST
+//		    | FBINFO_PARTIAL_PAN_OK
+		    | FBINFO_MISC_ALWAYS_SETPAR;
 
 	info->pseudo_palette = par->pseudo_pal;
 
-	if(getstartupmode(info))
+	if (getstartupmode(info))
 		goto errout_findmode;
 
-	fb_alloc_cmap(&info->cmap,256,0);
+	fb_alloc_cmap(&info->cmap, 256, 0);
 
 	if (register_framebuffer(info)) {
 		output("Could not register CyBla framebuffer\n");
 		goto errout_register;
 	}
 
-	pci_set_drvdata(dev,info);
+	pci_set_drvdata(dev, info);
 
 	//
 	// normal exit and error paths
@@ -1332,23 +1551,24 @@ static int __devinit cybla_pci_probe(struct pci_dev * dev,
 
 	return 0;
 
- errout_register:
- errout_findmode:
+      errout_register:
+      errout_findmode:
 	iounmap(info->screen_base);
- errout_smem_remap:
-	release_mem_region(info->fix.smem_start,
-			   info->fix.smem_len);
- errout_smem_req:
+      errout_smem_remap:
+	if (!(vesafb & 4))
+		release_mem_region(info->fix.smem_start, info->fix.smem_len);
 	iounmap(io_virt);
- errout_mmio_remap:
-	release_mem_region(info->fix.mmio_start,
-			   info->fix.mmio_len);
- errout_mmio_reqmem:
-//	release_region(0x3c0,32);
- errout_enable:
+      errout_mmio_remap:
+	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
+      errout_mmio_reqmem:
+	if (!(vesafb & 1))
+		release_region(0x3c0, 32);
+      errout_enable:
+	kfree(info->pixmap.addr);
+      errout_alloc_pixmap:
 	framebuffer_release(info);
- errout_alloc:
-	output("CyblaFB version %s aborting init.\n",VERSION);
+      errout_alloc_info:
+	output("CyblaFB version %s aborting init.\n", VERSION);
 	return -ENODEV;
 }
 
@@ -1359,35 +1579,41 @@ static void __devexit cybla_pci_remove(struct pci_dev *dev)
 	unregister_framebuffer(info);
 	iounmap(io_virt);
 	iounmap(info->screen_base);
-	release_mem_region(info->fix.smem_start,info->fix.smem_len);
-	release_mem_region(info->fix.mmio_start,info->fix.mmio_len);
+	if (!(vesafb & 4))
+		release_mem_region(info->fix.smem_start, info->fix.smem_len);
+	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
 	fb_dealloc_cmap(&info->cmap);
+	if (!(vesafb & 2))
+		release_region(GEBase, 0x100);
+	if (!(vesafb & 1))
+		release_region(0x3c0, 32);
+	kfree(info->pixmap.addr);
 	framebuffer_release(info);
-	output("CyblaFB version %s normal exit.\n",VERSION);
+	output("CyblaFB version %s normal exit.\n", VERSION);
 }
 
 //
 // List of boards that we are trying to support
 //
 static struct pci_device_id cybla_devices[] = {
-	{PCI_VENDOR_ID_TRIDENT,CYBERBLADEi1,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
+	{PCI_VENDOR_ID_TRIDENT, CYBERBLADEi1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
 	{0,}
 };
 
-MODULE_DEVICE_TABLE(pci,cybla_devices);
+MODULE_DEVICE_TABLE(pci, cybla_devices);
 
 static struct pci_driver cyblafb_pci_driver = {
-	.name		= "cyblafb",
-	.id_table	= cybla_devices,
-	.probe		= cybla_pci_probe,
-	.remove 	= __devexit_p(cybla_pci_remove)
+	.name = "cyblafb",
+	.id_table = cybla_devices,
+	.probe = cybla_pci_probe,
+	.remove = __devexit_p(cybla_pci_remove)
 };
 
 //=============================================================
 //
 // kernel command line example:
 //
-//	video=cyblafb:1280x1024,bpp=16,ref=50 ...
+//	video=cyblafb:1280x1024, bpp=16, ref=50 ...
 //
 // modprobe command line example:
 //
@@ -1401,45 +1627,44 @@ static int __devinit cyblafb_init(void)
 	char *options = NULL;
 	char *opt;
 
-	if (fb_get_options("cyblafb",&options))
+	if (fb_get_options("cyblafb", &options))
 		return -ENODEV;
 
 	if (options && *options)
-		while((opt = strsep(&options,",")) != NULL ) {
-			if (!*opt) continue;
-			else if (!strncmp(opt,"bpp=",4))
-				bpp = simple_strtoul(opt+4,NULL,0);
-			else if (!strncmp(opt,"ref=",4))
-				ref = simple_strtoul(opt+4,NULL,0);
-			else if (!strncmp(opt,"fp",2))
+		while ((opt = strsep(&options, ",")) != NULL) {
+			if (!*opt)
+				continue;
+			else if (!strncmp(opt, "bpp=", 4))
+				bpp = simple_strtoul(opt + 4, NULL, 0);
+			else if (!strncmp(opt, "ref=", 4))
+				ref = simple_strtoul(opt + 4, NULL, 0);
+			else if (!strncmp(opt, "fp", 2))
 				displaytype = DISPLAY_FP;
-			else if (!strncmp(opt,"crt",3))
+			else if (!strncmp(opt, "crt", 3))
 				displaytype = DISPLAY_CRT;
-			else if (!strncmp(opt,"nativex=",8))
-				nativex = simple_strtoul(opt+8,NULL,0);
-			else if (!strncmp(opt,"center",6))
+			else if (!strncmp(opt, "nativex=", 8))
+				nativex = simple_strtoul(opt + 8, NULL, 0);
+			else if (!strncmp(opt, "center", 6))
 				center = 1;
-			else if (!strncmp(opt,"stretch",7))
+			else if (!strncmp(opt, "stretch", 7))
 				stretch = 1;
-			else if (!strncmp(opt,"pciwb=",6))
-				pciwb = simple_strtoul(opt+6,NULL,0);
-			else if (!strncmp(opt,"pcirb=",6))
-				pcirb = simple_strtoul(opt+6,NULL,0);
-			else if (!strncmp(opt,"pciwr=",6))
-				pciwr = simple_strtoul(opt+6,NULL,0);
-			else if (!strncmp(opt,"pcirr=",6))
-				pcirr = simple_strtoul(opt+6,NULL,0);
-			else if (!strncmp(opt,"memsize=",8))
-				memsize = simple_strtoul(opt+8,NULL,0);
-			else if (!strncmp(opt,"verbosity=",10))
-				verbosity = simple_strtoul(opt+10,NULL,0);
-			else if (!strncmp(opt,"vesafb",6))
-				vesafb = 1;
+			else if (!strncmp(opt, "pciwb=", 6))
+				pciwb = simple_strtoul(opt + 6, NULL, 0);
+			else if (!strncmp(opt, "pcirb=", 6))
+				pcirb = simple_strtoul(opt + 6, NULL, 0);
+			else if (!strncmp(opt, "pciwr=", 6))
+				pciwr = simple_strtoul(opt + 6, NULL, 0);
+			else if (!strncmp(opt, "pcirr=", 6))
+				pcirr = simple_strtoul(opt + 6, NULL, 0);
+			else if (!strncmp(opt, "memsize=", 8))
+				memsize = simple_strtoul(opt + 8, NULL, 0);
+			else if (!strncmp(opt, "verbosity=", 10))
+				verbosity = simple_strtoul(opt + 10, NULL, 0);
 			else
 				mode = opt;
 		}
 #endif
-	output("CyblaFB version %s initializing\n",VERSION);
+	output("CyblaFB version %s initializing\n", VERSION);
 	return pci_module_init(&cyblafb_pci_driver);
 }
 
diff --git a/include/video/cyblafb.h b/include/video/cyblafb.h
index a9948232b131..717440575380 100644
--- a/include/video/cyblafb.h
+++ b/include/video/cyblafb.h
@@ -153,6 +153,10 @@
 #define GE04	(GEBase+0x04)	// source 2, p 111
 #define GE08	(GEBase+0x08)	// destination 1, p 111
 #define GE0C	(GEBase+0x0C)	// destination 2, p 112
+#define GE10	(GEBase+0x10)	// right view base & enable, p 112
+#define GE13	(GEBase+0x13)	// left view base & enable, p 112
+#define GE18	(GEBase+0x18)	// block write start address, p 112
+#define GE1C	(GEBase+0x1C)	// block write end address, p 112
 #define GE20	(GEBase+0x20)	// engine status, p 113
 #define GE24	(GEBase+0x24)	// reset all GE pointers
 #define GE44	(GEBase+0x44)	// command register, p 126