
From: "Antonino A. Daplas" <adaplas@hotpop.com>

Ugly workaround.  When switching from KD_GRAPHICS to KD_TEXT, the event is
captured at fbcon_blank() allowing fbcon to reinitialize the hardware. 
However, some hardware requires the reinitialization to be done
immediately, others require it to be done later.  Others may need it to be
done immediately and later, this is the worst case.  

Signed-off-by: Antonino Daplas <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/video/console/fbcon.c |   27 +++++++++++++++++++++++++--
 25-akpm/drivers/video/riva/fbdev.c    |    3 ++-
 25-akpm/include/linux/fb.h            |    1 +
 3 files changed, 28 insertions(+), 3 deletions(-)

diff -puN drivers/video/console/fbcon.c~fbcon-mode-switch-hack drivers/video/console/fbcon.c
--- 25/drivers/video/console/fbcon.c~fbcon-mode-switch-hack	Fri Jul  2 16:21:44 2004
+++ 25-akpm/drivers/video/console/fbcon.c	Fri Jul  2 16:21:44 2004
@@ -1821,8 +1821,31 @@ static int fbcon_blank(struct vc_data *v
 	struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
 	struct display *p = &fb_display[vc->vc_num];
 
-	if (mode_switch)
-		info->flags |= FBINFO_MISC_MODESWITCH;
+	if (mode_switch) {
+		struct fb_var_screeninfo var = info->var;
+
+/*
+ * HACK ALERT: Some hardware will require reinitializion at this stage,
+ *             others will require it to be done as late as possible.
+ *             For now, we differentiate this with the
+ *             FBINFO_MISC_MODESWITCHLATE bitflag.  Worst case will be
+ *             hardware that requires it here and another one later.
+ *             A definitive solution may require fixing X or the VT
+ *             system.
+ */
+		if (info->flags & FBINFO_MISC_MODESWITCHLATE)
+			info->flags |= FBINFO_MISC_MODESWITCH;
+
+		if (blank) {
+			fbcon_cursor(vc, CM_ERASE);
+			return 0;
+		}
+
+		if (!(info->flags & FBINFO_MISC_MODESWITCHLATE)) {
+			var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE;
+			fb_set_var(info, &var);
+		}
+	}
 
 	fbcon_cursor(vc, blank ? CM_ERASE : CM_DRAW);
 
diff -puN drivers/video/riva/fbdev.c~fbcon-mode-switch-hack drivers/video/riva/fbdev.c
--- 25/drivers/video/riva/fbdev.c~fbcon-mode-switch-hack	Fri Jul  2 16:21:44 2004
+++ 25-akpm/drivers/video/riva/fbdev.c	Fri Jul  2 16:21:44 2004
@@ -1681,7 +1681,8 @@ static int __devinit riva_set_fbinfo(str
 		    | FBINFO_HWACCEL_YPAN
 		    | FBINFO_HWACCEL_COPYAREA
 		    | FBINFO_HWACCEL_FILLRECT
-		    | FBINFO_HWACCEL_IMAGEBLIT;
+		    | FBINFO_HWACCEL_IMAGEBLIT
+	            | FBINFO_MISC_MODESWITCHLATE;
 	info->var = rivafb_default_var;
 	info->fix.visual = (info->var.bits_per_pixel == 8) ?
 				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
diff -puN include/linux/fb.h~fbcon-mode-switch-hack include/linux/fb.h
--- 25/include/linux/fb.h~fbcon-mode-switch-hack	Fri Jul  2 16:21:44 2004
+++ 25-akpm/include/linux/fb.h	Fri Jul  2 16:21:44 2004
@@ -533,6 +533,7 @@ struct fb_ops {
 #define FBINFO_MISC_MODECHANGEUSER     0x10000 /* mode change request
 						  from userspace */
 #define FBINFO_MISC_MODESWITCH         0x20000 /* mode switch */
+#define FBINFO_MISC_MODESWITCHLATE     0x40000 /* init hardware later */
 
 struct fb_info {
 	int node;
_
