From 1319de907e12d28894d8db0b3215a0443ff4bd5d Mon Sep 17 00:00:00 2001
From: Egbert Eich <eich@suse.de>
Date: Thu, 22 Oct 2009 13:32:11 +0200
Subject: [PATCH] Cleanup and make boot splash work with KMS
References: bnc#544645
Patch-mainline: not yet

 - Fix API: remove unneeded function argument
 - Remove unneeded function splash_putc().
 - Remove need for 2 framebuffer basis: when swiching from silent to
   verbose rely on update_region() to redraw the verbose picture.
   This removes the need to double the framebuffer size when using
   splash.
 - Use worker to switch to verbose mode.
 - Add support for 24 and 32bpp (24bpp still disabled due to lack of testing).

Acked-by: Michal Marek <mmarek@suse.cz>
---
 drivers/char/vt.c                     |   10 
 drivers/video/bootsplash/bootsplash.c |  407 +++++++++++++++++++++---------
 drivers/video/bootsplash/bootsplash.h |   23 -
 drivers/video/bootsplash/decode-jpg.c |   50 +++
 drivers/video/bootsplash/render.c     |  451 +++++++++++++++++++++-------------
 drivers/video/console/bitblit.c       |   12 
 drivers/video/console/fbcon.c         |    4 
 drivers/video/vesafb.c                |    8 
 include/linux/fb.h                    |    3 
 9 files changed, 652 insertions(+), 316 deletions(-)

--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -4104,7 +4104,7 @@ void vcs_scr_writew(struct vc_data *vc,
 #ifdef CONFIG_BOOTSPLASH
 void con_remap_def_color(struct vc_data *vc, int new_color)
 {
-       unsigned short *sbuf = vc->vc_screenbuf;
+       unsigned short *sbuf = screenpos(vc, 0, 1);
        unsigned c, len = vc->vc_screenbuf_size >> 1;
        int old_color;
 
@@ -4112,11 +4112,13 @@ void con_remap_def_color(struct vc_data
 	       old_color = vc->vc_def_color << 8;
 	       new_color <<= 8;
 	       while(len--) {
-		       c = *sbuf;
+		       c = scr_readw(sbuf);
 		       if (((c ^ old_color) & 0xf000) == 0)
-			       *sbuf ^= (old_color ^ new_color) & 0xf000;
+			     scr_writew(c ^ ((old_color ^ new_color) & 0xf000), sbuf);
+		       *sbuf ^= (old_color ^ new_color) & 0xf000;
 		       if (((c ^ old_color) & 0x0f00) == 0)
-			       *sbuf ^= (old_color ^ new_color) & 0x0f00;
+			     scr_writew(c ^ ((old_color ^ new_color) & 0x0f00), sbuf);
+		       *sbuf ^= (old_color ^ new_color) & 0x0f00;
 		       sbuf++;
 	       }
 	       new_color >>= 8;
--- a/drivers/video/bootsplash/bootsplash.c
+++ b/drivers/video/bootsplash/bootsplash.c
@@ -19,6 +19,8 @@
 #include <linux/vmalloc.h>
 #include <linux/unistd.h>
 #include <linux/syscalls.h>
+#include <linux/console.h>
+#include <linux/workqueue.h>
 
 #include <asm/irq.h>
 #include <asm/system.h>
@@ -27,7 +29,12 @@
 #include "bootsplash.h"
 #include "decode-jpg.h"
 
-extern struct fb_ops vesafb_ops;
+#ifndef DEBUG
+# define SPLASH_DEBUG(fmt, args...)
+#else
+# define SPLASH_DEBUG(fmt, args...) \
+        printk(KERN_WARNING "%s: " fmt "\n",__FUNCTION__, ##args)
+#endif
 extern signed char con2fb_map[MAX_NR_CONSOLES];
 
 #define SPLASH_VERSION "3.1.6-2004/03/31"
@@ -113,18 +120,20 @@ static int boxextract(unsigned char *buf
     return 12;
 }
 
-static void boxit(unsigned char *pic, int bytes, unsigned char *buf, int num, int percent, int overpaint)
+static void boxit(unsigned char *pic, int bytes, unsigned char *buf, int num, int percent, int overpaint, int octpp)
 {
-    int x, y, i, p, doblend, r, g, b, a, add;
+    int x, y, p, doblend, r, g, b, a, add;
+    unsigned int i = 0;
     unsigned short data1[4];
     unsigned char cols1[16];
     unsigned short data2[4];
     unsigned char cols2[16];
     unsigned char *bufend;
-    unsigned short *picp;
+    union pt picp;
     unsigned int stipple[32], sti, stin, stinn, stixs, stixe, stiys, stiye;
     int xs, xe, ys, ye, xo, yo;
 
+    SPLASH_DEBUG();
     if (num == 0)
 	return;
     bufend = buf + num * 12;
@@ -236,11 +245,21 @@ static void boxit(unsigned char *pic, in
 	    }
 	    add = (xs & 1);
 	    add ^= (add ^ y) & 1 ? 1 : 3;		/* 2x2 ordered dithering */
-	    picp = (unsigned short *)(pic + xs * 2 + y * bytes);
+	    picp.ub = (pic + xs * octpp + y * bytes);
 	    for (x = xs; x <= xe; x++) {
 		if (!(sti & 0x80000000)) {
 		    sti <<= 1;
-		    picp++;
+		    switch (octpp) {
+		    case 2:
+		      picp.us++;
+		      break;
+		    case 3:
+		      picp.ub += 3;
+		      break;
+		    case 4:
+		      picp.ul++;
+		      break;
+		    }
 		    add ^= 3;
 		    continue;
 		}
@@ -255,18 +274,37 @@ static void boxit(unsigned char *pic, in
 		r = cols2[0];
 		g = cols2[1];
 		b = cols2[2];
-		if (a != 255) {
-		    i = *picp;
-		    r = ((i >> 8 & 0xf8) * (255 - a) + r * a) / 255;
-		    g = ((i >> 3 & 0xfc) * (255 - a) + g * a) / 255;
-		    b = ((i << 3 & 0xf8) * (255 - a) + b * a) / 255;
-		}
-  #define CLAMP(x) ((x) >= 256 ? 255 : (x))
-		i = ((CLAMP(r + add*2+1) & 0xf8) <<  8) |
-		    ((CLAMP(g + add    ) & 0xfc) <<  3) |
-		    ((CLAMP(b + add*2+1)       ) >>  3);
-		*picp++ = i;
-		add ^= 3;
+#define CLAMP(x) ((x) >= 256 ? 255 : (x))
+		  switch (octpp) {
+		  case 2:
+		    i = *picp.us;
+		    if (a != 255) {
+		      r = ((i >> 8 & 0xf8) * (255 - a) + r * a) / 255;
+		      g = ((i >> 3 & 0xfc) * (255 - a) + g * a) / 255;
+		      b = ((i << 3 & 0xf8) * (255 - a) + b * a) / 255;
+		    }
+		    i = ((CLAMP(r + add*2+1) & 0xf8) <<  8) |
+		      ((CLAMP(g + add    ) & 0xfc) <<  3) |
+		      ((CLAMP(b + add*2+1)       ) >>  3);
+		    *(picp.us++) = i;
+		    break;
+		  case 3:
+		    *(picp.ub++) = CLAMP(a == 255 ? r : (((i       & 0xff) * (255 - a) + r * a) / 255));
+		    *(picp.ub++) = CLAMP(a == 255 ? r : (((i >>  8 & 0xff) * (255 - a) + r * a) / 255));
+		    *(picp.ub++) = CLAMP(a == 255 ? r : (((i >> 16 & 0xff) * (255 - a) + r * a) / 255));
+		    break;
+		  case 4:
+		    i = *picp.ul;
+		    if (a != 255) {
+		      r = ((i >> 16 & 0xff) * (255 - a) + r * a) / 255;
+		      g = ((i >>  8 & 0xff) * (255 - a) + r * a) / 255;
+		      b = ((i       & 0xff) * (255 - a) + r * a) / 255;
+		    }
+		    i = ((CLAMP(r) << 16) | (CLAMP(g) << 8) | (CLAMP(b)));
+		    *(picp.ul++) = i;
+		    break;
+		  }
+		  add ^= 3;
 	    }
 	}
     }
@@ -293,16 +331,14 @@ static int splash_check_jpeg(unsigned ch
 
 static void splash_free(struct vc_data *vc, struct fb_info *info)
 {
-    if (!vc->vc_splash_data)
-	return;
-    if (info->silent_screen_base)
-	    info->screen_base = info->silent_screen_base;
-    info->silent_screen_base = 0;
-    if (vc->vc_splash_data->splash_silentjpeg)
-	    vfree(vc->vc_splash_data->splash_sboxes);
-    vfree(vc->vc_splash_data);
-    vc->vc_splash_data = 0;
-    info->splash_data = 0;
+	SPLASH_DEBUG();
+	if (!vc->vc_splash_data)
+		return;
+	if (vc->vc_splash_data->splash_silentjpeg)
+		vfree(vc->vc_splash_data->splash_sboxes);
+	vfree(vc->vc_splash_data);
+	vc->vc_splash_data = 0;
+	info->splash_data = 0;
 }
 
 static int splash_mkpenguin(struct splash_data *data, int pxo, int pyo, int pwi, int phe, int pr, int pg, int pb)
@@ -590,37 +626,69 @@ static int splash_getraw(unsigned char *
     return -1;
 }
 
-int splash_verbose(void)
+int splash_do_verbose(void)
 {
-    struct vc_data *vc;
-    struct fb_info *info;
+	struct vc_data *vc;
+	struct fb_info *info;
+	int ret = 0;
 
-    if (!splash_usesilent)
-        return 0;
+	SPLASH_DEBUG();
+	if (!oops_in_progress)
+		acquire_console_sem();
 
-    vc = vc_cons[0].d;
+	if (!splash_usesilent)
+		goto done;
 
-    if (!vc || !vc->vc_splash_data || !vc->vc_splash_data->splash_state)
-	return 0;
-    if (fg_console != vc->vc_num)
-	return 0;
-    if (!vc->vc_splash_data->splash_silentjpeg || !vc->vc_splash_data->splash_dosilent)
-	return 0;
-    vc->vc_splash_data->splash_dosilent = 0;
-    info = registered_fb[(int)con2fb_map[0]];
-    if (!info->silent_screen_base)
+	vc = vc_cons[0].d;
+
+	if (!vc || !vc->vc_splash_data || !vc->vc_splash_data->splash_state)
+		goto done;
+	if (fg_console != vc->vc_num)
+		goto done;
+	if (!vc->vc_splash_data->splash_silentjpeg)
+		goto done;
+
+	if(!vc->vc_splash_data->splash_dosilent)
+		goto done;
+	vc->vc_splash_data->splash_dosilent = 0;
+
+	info = registered_fb[(int)con2fb_map[0]];
+
+	if (!info->splash_data)
+		goto done;
+
+	update_region(vc,
+		      vc->vc_origin + vc->vc_size_row * vc->vc_top,
+		      vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
+	splash_clear_margins(vc, info, 0);
+	ret = 0;
+
+ done:
+	if (!oops_in_progress)
+		release_console_sem();
+
+	return ret;
+}
+
+static void splash_verbose_callback(struct work_struct *ignored)
+{
+	splash_do_verbose();
+}
+
+static DECLARE_WORK(splash_work, splash_verbose_callback);
+
+int splash_verbose(void)
+{
+	if (!oops_in_progress)
+		schedule_work(&splash_work);
+	else
+		return splash_do_verbose();
 	return 0;
-    splashcopy(info->silent_screen_base, info->screen_base, info->var.yres, info->var.xres, info->fix.line_length, info->fix.line_length);
-    info->screen_base = info->silent_screen_base;
-    info->silent_screen_base = 0;
-    return 1;
 }
 
 static void splash_off(struct fb_info *info)
 {
-	if (info->silent_screen_base)
-		info->screen_base = info->silent_screen_base;
-	info->silent_screen_base = 0;
+	SPLASH_DEBUG();
 	info->splash_data = 0;
 	if (info->splash_pic)
 		vfree(info->splash_pic);
@@ -631,8 +699,9 @@ static void splash_off(struct fb_info *i
 int splash_prepare(struct vc_data *vc, struct fb_info *info)
 {
 	int err;
-        int width, height, depth, size, sbytes;
+        int width, height, depth, octpp, size, sbytes;
 
+	SPLASH_DEBUG("vc_num: %i", vc->vc_num);
 	if (!vc->vc_splash_data || !vc->vc_splash_data->splash_state) {
 		if (decdata)
 			vfree(decdata);
@@ -644,15 +713,19 @@ int splash_prepare(struct vc_data *vc, s
         width = info->var.xres;
         height = info->var.yres;
         depth = info->var.bits_per_pixel;
-	if (depth != 16) {	/* Other targets might need fixing */
+	octpp = (depth + 1) >> 3;
+
+	if (depth == 24 || depth < 15) {	/* Other targets might need fixing */
 		splash_off(info);
 		return -2;
 	}
 
-	sbytes = ((width + 15) & ~15) * (depth >> 3);
+	sbytes = ((width + 15) & ~15) * octpp;
 	size = sbytes * ((height + 15) & ~15);
-	if (size != info->splash_pic_size)
-		splash_off(info);
+	if (size != info->splash_pic_size) {
+		vfree(info->splash_pic);
+		info->splash_pic = NULL;
+	}
 	if (!info->splash_pic)
 		info->splash_pic = vmalloc(size);
 
@@ -668,38 +741,52 @@ int splash_prepare(struct vc_data *vc, s
 	if (vc->vc_splash_data->splash_silentjpeg && vc->vc_splash_data->splash_dosilent) {
 		/* fill area after framebuffer with other jpeg */
 		if ((err = jpeg_decode(vc->vc_splash_data->splash_silentjpeg, info->splash_pic,
-			 ((width + 15) & ~15), ((height + 15) & ~15), depth, decdata))) {
-			printk(KERN_INFO "bootsplash: error while decompressing silent picture: %s (%d)\n", jpg_errors[err - 1], err);
-			if (info->silent_screen_base)
-				info->screen_base = info->silent_screen_base;
+				       ((width + 15) & ~15), ((height + 15) & ~15), depth, decdata))) {
+			printk(KERN_INFO "bootsplash: error while decompressing silent picture: %s (%d)\n",
+			       jpg_errors[err - 1], err);
 			vc->vc_splash_data->splash_dosilent = 0;
 		} else {
 			if (vc->vc_splash_data->splash_sboxcount)
-				boxit(info->splash_pic, sbytes, vc->vc_splash_data->splash_sboxes,
-					vc->vc_splash_data->splash_sboxcount, vc->vc_splash_data->splash_percent, 0);
-
-			if (!info->silent_screen_base)
-				info->silent_screen_base = info->screen_base;
-			splashcopy(info->silent_screen_base, info->splash_pic, info->var.yres, info->var.xres, info->fix.line_length, sbytes);
-			info->screen_base = info->silent_screen_base + info->fix.line_length * info->var.yres;
+				boxit(info->splash_pic,
+				      sbytes,
+				      vc->vc_splash_data->splash_sboxes,
+				      vc->vc_splash_data->splash_sboxcount,
+				      vc->vc_splash_data->splash_percent,
+				      0,
+				      octpp);
+			splashcopy(info->screen_base,
+				   info->splash_pic,
+				   info->var.yres,
+				   info->var.xres,
+				   info->fix.line_length, sbytes,
+				   octpp );
 		}
-	} else if (info->silent_screen_base)
-		info->screen_base = info->silent_screen_base;
+	} else
+		vc->vc_splash_data->splash_dosilent = 0;
 
 	if ((err = jpeg_decode(vc->vc_splash_data->splash_jpeg, info->splash_pic,
 		 ((width + 15) & ~15), ((height + 15) & ~15), depth, decdata))) {
-		printk(KERN_INFO "bootsplash: error while decompressing picture: %s (%d) .\n", jpg_errors[err - 1], err);
+		printk(KERN_INFO "bootsplash: error while decompressing picture: %s (%d) .\n",
+		       jpg_errors[err - 1], err);
 		splash_off(info);
 		return -4;
 	}
 	info->splash_pic_size = size;
-	info->splash_bytes = sbytes;
+	info->splash_pic_stride = sbytes;
 	if (vc->vc_splash_data->splash_boxcount)
-		boxit(info->splash_pic, sbytes, vc->vc_splash_data->splash_boxes, vc->vc_splash_data->splash_boxcount, vc->vc_splash_data->splash_percent, 0);
+		boxit(info->splash_pic,
+		      sbytes,
+		      vc->vc_splash_data->splash_boxes,
+		      vc->vc_splash_data->splash_boxcount,
+		      vc->vc_splash_data->splash_percent,
+		      0,
+		      octpp);
 	if (vc->vc_splash_data->splash_state)
 		info->splash_data = vc->vc_splash_data;
-	else
+	else {
 		splash_off(info);
+		return -5;
+	}
 	return 0;
 }
 
@@ -720,6 +807,7 @@ static struct proc_dir_entry *proc_splas
 
 static int splash_recolor(struct vc_data *vc)
 {
+	SPLASH_DEBUG();
 	if (!vc->vc_splash_data)
 	    return -1;
 	if (!vc->vc_splash_data->splash_state)
@@ -736,20 +824,27 @@ static int splash_recolor(struct vc_data
 static int splash_status(struct vc_data *vc)
 {
 	struct fb_info *info;
-	printk(KERN_INFO "bootsplash: status on console %d changed to %s\n", vc->vc_num, vc->vc_splash_data && vc->vc_splash_data->splash_state ? "on" : "off");
+	SPLASH_DEBUG("vc_num: %i",vc->vc_num);
+	printk(KERN_INFO "bootsplash: status on console %d changed to %s\n",
+	       vc->vc_num,
+	       vc->vc_splash_data && vc->vc_splash_data->splash_state ? "on" : "off");
 
 	info = registered_fb[(int) con2fb_map[vc->vc_num]];
+
 	if (fg_console == vc->vc_num)
 		splash_prepare(vc, info);
 	if (vc->vc_splash_data && vc->vc_splash_data->splash_state) {
-		con_remap_def_color(vc, vc->vc_splash_data->splash_color << 4 | vc->vc_splash_data->splash_fg_color);
-		/* vc_resize also calls con_switch which resets yscroll */
-		vc_resize(vc, vc->vc_splash_data->splash_text_wi / vc->vc_font.width, vc->vc_splash_data->splash_text_he / vc->vc_font.height);
-		if (fg_console == vc->vc_num) {
-			update_region(vc,
-				      vc->vc_origin + vc->vc_size_row * vc->vc_top,
-				      vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
-			splash_clear_margins(vc->vc_splash_data, vc, info, 0);
+	        if (info->splash_data) {
+			con_remap_def_color(vc, info->splash_data->splash_color << 4 | info->splash_data->splash_fg_color);
+			/* vc_resize also calls con_switch which resets yscroll */
+			vc_resize(vc, info->splash_data->splash_text_wi / vc->vc_font.width,
+				  info->splash_data->splash_text_he / vc->vc_font.height);
+			if (fg_console == vc->vc_num) {
+				update_region(vc,
+					      vc->vc_origin + vc->vc_size_row * vc->vc_top,
+					      vc->vc_size_row * (vc->vc_bottom - vc->vc_top) / 2);
+				splash_clear_margins(vc, info, 0);
+			}
 		}
 	} else {
 		/* Switch bootsplash off */
@@ -787,6 +882,8 @@ void splash_set_percent(struct vc_data *
 	struct fbcon_ops *ops;
 	int oldpe;
 
+	SPLASH_DEBUG();
+
 	if (pe < 0)
 		pe = 0;
 	if (pe > 65535)
@@ -805,15 +902,38 @@ void splash_set_percent(struct vc_data *
 	ops = info->fbcon_par;
 	if (ops->blank_state)
 		return;
-	if (!vc->vc_splash_data->splash_overpaintok || pe == 65536 || pe < oldpe) {
-		if (splash_hasinter(vc->vc_splash_data->splash_boxes, vc->vc_splash_data->splash_boxcount))
-			splash_status(vc);
-		else
-			splash_prepare(vc, info);
+	if (!vc->vc_splash_data->splash_overpaintok
+	    || pe == 65536
+	    || pe < oldpe) {
+	    if (splash_hasinter(vc->vc_splash_data->splash_boxes,
+				vc->vc_splash_data->splash_boxcount)) {
+		splash_status(vc);
+	    }
+	    else
+		splash_prepare(vc, info);
 	} else {
-		if (vc->vc_splash_data->splash_silentjpeg && vc->vc_splash_data->splash_dosilent && info->silent_screen_base)
-			boxit(info->silent_screen_base, info->fix.line_length, vc->vc_splash_data->splash_sboxes, vc->vc_splash_data->splash_sboxcount, vc->vc_splash_data->splash_percent, 1);
-		boxit(info->screen_base, info->fix.line_length, vc->vc_splash_data->splash_boxes, vc->vc_splash_data->splash_boxcount, vc->vc_splash_data->splash_percent, 1);
+	        int octpp = (info->var.bits_per_pixel + 1) >> 3;
+	        if (info->splash_data) {
+		  if ( info->splash_data->splash_silentjpeg
+		       && info->splash_data->splash_dosilent)
+		      boxit(info->screen_base,
+			    info->fix.line_length,
+			    info->splash_data->splash_sboxes,
+			    info->splash_data->splash_sboxcount,
+			    info->splash_data->splash_percent,
+			    1,
+			    octpp);
+#if 0
+		  if (!info->splash_dosilent)
+		      boxit(info->screen_base,
+			    info->fix.line_length,
+			    info->splash_data->splash_boxes,
+			    info->splash_data->splash_boxcount,
+			    info->splash_data->splash_percent,
+			    1,
+			    octpp);
+#endif
+	    }
 	}
 }
 
@@ -823,6 +943,8 @@ static int splash_write_proc(struct file
         int new, unit;
 	struct vc_data *vc;
 
+	SPLASH_DEBUG();
+
 	if (!buffer || !splash_default)
 		return count;
 
@@ -842,8 +964,10 @@ static int splash_write_proc(struct file
 			return count;
 		}
 	}
+	SPLASH_DEBUG(" unit: %i",unit);
 	vc = vc_cons[unit].d;
 	if (!strncmp(buffer, "redraw", 6)) {
+	        SPLASH_DEBUG( " redraw");
 		splash_status(vc);
 		release_console_sem();
 		return count;
@@ -851,6 +975,7 @@ static int splash_write_proc(struct file
 	if (!strncmp(buffer, "show", 4) || !strncmp(buffer, "hide", 4)) {
 		int pe;
 
+		SPLASH_DEBUG( " show/hide");
 		if (buffer[4] == ' ' && buffer[5] == 'p')
 			pe = 0;
 		else if (buffer[4] == '\n')
@@ -867,51 +992,77 @@ static int splash_write_proc(struct file
 		release_console_sem();
 		return count;
 	}
+
 	if (!strncmp(buffer,"silent\n",7) || !strncmp(buffer,"verbose\n",8)) {
+	        SPLASH_DEBUG( " silent/verbose");
 		if (vc->vc_splash_data && vc->vc_splash_data->splash_silentjpeg) {
-		    if (vc->vc_splash_data->splash_dosilent != (buffer[0] == 's')) {
-			vc->vc_splash_data->splash_dosilent = buffer[0] == 's';
-			splash_status(vc);
-		    }
+			if (vc->vc_splash_data->splash_dosilent != (buffer[0] == 's')) {
+				vc->vc_splash_data->splash_dosilent = buffer[0] == 's';
+				splash_status(vc);
+			}
 		}
 		release_console_sem();
 		return count;
 	}
 	if (!strncmp(buffer,"freesilent\n",11)) {
+	        SPLASH_DEBUG( " freesilent");
 		if (vc->vc_splash_data && vc->vc_splash_data->splash_silentjpeg) {
-		    printk(KERN_INFO "bootsplash: freeing silent jpeg\n");
-		    vc->vc_splash_data->splash_silentjpeg = 0;
-		    vfree(vc->vc_splash_data->splash_sboxes);
-		    vc->vc_splash_data->splash_sboxes = 0;
-		    vc->vc_splash_data->splash_sboxcount = 0;
-		    if (vc->vc_splash_data->splash_dosilent)
-			splash_status(vc);
-		    vc->vc_splash_data->splash_dosilent = 0;
+			printk(KERN_INFO "bootsplash: freeing silent jpeg\n");
+			vc->vc_splash_data->splash_silentjpeg = 0;
+			vfree(vc->vc_splash_data->splash_sboxes);
+			vc->vc_splash_data->splash_sboxes = 0;
+			vc->vc_splash_data->splash_sboxcount = 0;
+			if (vc->vc_splash_data->splash_dosilent) {
+				splash_status(vc);
+			}
+			vc->vc_splash_data->splash_dosilent = 0;
 		}
 		release_console_sem();
 		return count;
 	}
-
 	if (!strncmp(buffer, "BOOTSPL", 7)) {
-	    int up = -1;
-	    unit = splash_getraw((unsigned char *)buffer, (unsigned char *)buffer + count, &up);
-	    if (unit >= 0) {
-		vc = vc_cons[unit].d;
-		if (up == -1)
-		    splash_status(vc);
-		else {
-		    struct fb_info *info = registered_fb[(int) con2fb_map[vc->vc_num]];
-		    struct fbcon_ops *ops = info->fbcon_par;
-		    if (ops->blank_state)
-			up = 0;
-		    if ((up & 2) != 0 && vc->vc_splash_data->splash_silentjpeg && vc->vc_splash_data->splash_dosilent && info->silent_screen_base)
-			boxit(info->silent_screen_base, info->fix.line_length, vc->vc_splash_data->splash_sboxes, vc->vc_splash_data->splash_sboxcount, vc->vc_splash_data->splash_percent, 1);
-		    if ((up & 1) != 0)
-			    boxit(info->screen_base, info->fix.line_length, vc->vc_splash_data->splash_boxes, vc->vc_splash_data->splash_boxcount, vc->vc_splash_data->splash_percent, 1);
+		int up = -1;
+
+		SPLASH_DEBUG( " BOOTSPL");
+		unit = splash_getraw((unsigned char *)buffer,
+				     (unsigned char *)buffer + count,
+				     &up);
+		SPLASH_DEBUG( " unit: %i up: %i",unit,up);
+		if (unit >= 0) {
+			struct fb_info *info;
+
+			vc = vc_cons[unit].d;
+			info = registered_fb[(int) con2fb_map[vc->vc_num]];
+			if (up == -1) {
+				splash_status(vc);
+			} else {
+				struct fbcon_ops *ops = info->fbcon_par;
+				int octpp = (info->var.bits_per_pixel + 1) >> 3;
+				if (ops->blank_state || !vc->vc_splash_data || !info->splash_data)
+					up = 0;
+				if ((up & 2) != 0
+				    && info->splash_data->splash_silentjpeg
+				    && info->splash_data->splash_dosilent) {
+					boxit(info->screen_base,
+					      info->fix.line_length,
+					      info->splash_data->splash_sboxes,
+					      info->splash_data->splash_sboxcount,
+					      info->splash_data->splash_percent,
+					      1,
+					      octpp);
+				} else 	if ((up & 1) != 0) {
+					boxit(info->screen_base,
+					      info->fix.line_length,
+					      info->splash_data->splash_boxes,
+					      info->splash_data->splash_boxcount,
+					      info->splash_data->splash_percent,
+					      1,
+					      octpp);
+				}
+			}
 		}
-	    }
-	    release_console_sem();
-	    return count;
+		release_console_sem();
+		return count;
 	}
 	if (!vc->vc_splash_data) {
 		release_console_sem();
@@ -919,6 +1070,7 @@ static int splash_write_proc(struct file
 	}
 	if (buffer[0] == 't') {
 	        vc->vc_splash_data->splash_state ^= 1;
+		SPLASH_DEBUG(" t");
 		splash_status(vc);
 		release_console_sem();
 		return count;
@@ -959,6 +1111,8 @@ static int splash_proc_unregister(void)
 # endif
 #endif	/* CONFIG_PROC_FS */
 
+#define INIT_CONSOLE 0
+
 void splash_init(void)
 {
 	struct fb_info *info;
@@ -971,9 +1125,12 @@ void splash_init(void)
 
 	if (splash_registered)
 		return;
-	vc = vc_cons[0].d;
-	info = registered_fb[0];
-	if (!vc || !info || info->var.bits_per_pixel != 16)
+	vc = vc_cons[INIT_CONSOLE].d;
+	info = registered_fb[(int)con2fb_map[INIT_CONSOLE]];
+	if (!vc
+	    || !info
+	    || info->var.bits_per_pixel == 24 /* not tested */
+	    || info->var.bits_per_pixel < 15) /* not supported */
 		return;
 #ifdef CONFIG_PROC_FS
 	splash_proc_register();
@@ -1004,7 +1161,9 @@ void splash_init(void)
 	mem = vmalloc(len);
 	if (mem) {
 		acquire_console_sem();
-		if ((int)sys_read(fd, mem, len) == len && splash_getraw((unsigned char *)mem, (unsigned char *)mem + len, (int *)0) == 0 && vc->vc_splash_data)
+		if ((int)sys_read(fd, mem, len) == len
+		    && splash_getraw((unsigned char *)mem, (unsigned char *)mem + len, (int *)0) == INIT_CONSOLE
+		    && vc->vc_splash_data)
 			vc->vc_splash_data->splash_state = splash_default & 1;
 		release_console_sem();
 		vfree(mem);
--- a/drivers/video/bootsplash/bootsplash.h
+++ b/drivers/video/bootsplash/bootsplash.h
@@ -12,27 +12,30 @@
 #define __BOOTSPLASH_H
 
 struct fb_info;
+union pt {
+  u32 *ul;
+  u16 *us;
+  u8  *ub;
+};
 
 /* splash.c */
 extern int splash_prepare(struct vc_data *, struct fb_info *);
 extern void splash_init(void);
 
 /* splash_render.c */
-extern void splash_putcs(struct splash_data *sd, struct vc_data *vc, struct fb_info *info,
+extern void splash_putcs(struct vc_data *vc, struct fb_info *info,
 			const unsigned short *s, int count, int ypos, int xpos);
-extern void splash_putc(struct splash_data *sd, struct vc_data *vc, struct fb_info *info,
-			int c, int ypos, int xpos);
-extern void splashcopy(u8 *dst, u8 *src, int height, int width, int dstbytes, int srcbytes);
-extern void splash_clear(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, int sy,
+extern void splashcopy(u8 *dst, u8 *src, int height, int width, int dstbytes, int srcbytes, int depth);
+extern void splash_clear(struct vc_data *vc, struct fb_info *info, int sy,
 			int sx, int height, int width);
-extern void splash_bmove(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, int sy,
+extern void splash_bmove(struct vc_data *vc, struct fb_info *info, int sy,
 			int sx, int dy, int dx, int height, int width);
-extern void splash_clear_margins(struct splash_data *sd, struct vc_data *vc, struct fb_info *info,
+extern void splash_clear_margins(struct vc_data *vc, struct fb_info *info,
 			int bottom_only);
-extern int splash_cursor(struct splash_data *sd, struct fb_info *info, struct fb_cursor *cursor);
-extern void splash_bmove_redraw(struct splash_data *sd, struct vc_data *vc, struct fb_info *info,
+extern int splash_cursor(struct fb_info *info, struct fb_cursor *cursor);
+extern void splash_bmove_redraw(struct vc_data *vc, struct fb_info *info,
 			int y, int sx, int dx, int width);
-extern void splash_blank(struct splash_data *sd, struct vc_data *vc, struct fb_info *info,
+extern void splash_blank(struct vc_data *vc, struct fb_info *info,
 			int blank);
 
 /* vt.c */
--- a/drivers/video/bootsplash/decode-jpg.c
+++ b/drivers/video/bootsplash/decode-jpg.c
@@ -86,6 +86,7 @@ static void initcol __P((PREC[][64]));
 
 static void col221111 __P((int *, unsigned char *, int));
 static void col221111_16 __P((int *, unsigned char *, int));
+static void col221111_32 __P((int *, unsigned char *, int));
 
 /*********************************/
 
@@ -369,6 +370,9 @@ struct jpeg_decdata *decdata;
 			idct(decdata->dcts + 320, decdata->out + 320, decdata->dquant[2], IFIX(0.5), max[5]);
 
 			switch (depth) {
+			case 32:
+				col221111_32(decdata->out, pic + (my * 16 * mcusx + mx) * 16 * 4, mcusx * 16 * 4);
+				break;
 			case 24:
 				col221111(decdata->out, pic + (my * 16 * mcusx + mx) * 16 * 3, mcusx * 16 * 3);
 				break;
@@ -882,6 +886,15 @@ PREC q[][64];
 #endif
 #endif
 
+#define PIC_32(yin, xin, p, xout)		\
+(						\
+  y = outy[(yin) * 8 + xin],			\
+  STORECLAMP(p[(xout) * 4 + 0], y + cr),	\
+  STORECLAMP(p[(xout) * 4 + 1], y - cg),	\
+  STORECLAMP(p[(xout) * 4 + 2], y + cb),	\
+  p[(xout) * 4 + 3] = 0				\
+)
+
 #define PIC221111(xin)						\
 (								\
   CBCRCG(0, xin),						\
@@ -900,6 +913,15 @@ PREC q[][64];
   PIC_16(xin / 4 * 8 + 1, (xin & 3) * 2 + 1, pic1, xin * 2 + 1, 2)      \
 )
 
+#define PIC221111_32(xin)					\
+(								\
+  CBCRCG(0, xin),						\
+  PIC_32(xin / 4 * 8 + 0, (xin & 3) * 2 + 0, pic0, xin * 2 + 0),\
+  PIC_32(xin / 4 * 8 + 0, (xin & 3) * 2 + 1, pic0, xin * 2 + 1),\
+  PIC_32(xin / 4 * 8 + 1, (xin & 3) * 2 + 0, pic1, xin * 2 + 0),\
+  PIC_32(xin / 4 * 8 + 1, (xin & 3) * 2 + 1, pic1, xin * 2 + 1)	\
+)
+
 static void col221111(out, pic, width)
 int *out;
 unsigned char *pic;
@@ -949,6 +971,34 @@ int width;
 			}
 			outc += 8;
 			outy += 16;
+			pic0 += 2 * width;
+			pic1 += 2 * width;
+		}
+		outy += 64 * 2 - 16 * 4;
+	}
+}
+
+static void col221111_32(out, pic, width)
+int *out;
+unsigned char *pic;
+int width;
+{
+	int i, j, k;
+	unsigned char *pic0, *pic1;
+	int *outy, *outc;
+	int cr, cg, cb, y;
+
+	pic0 = pic;
+	pic1 = pic + width;
+	outy = out;
+	outc = out + 64 * 4;
+	for (i = 2; i > 0; i--) {
+		for (j = 4; j > 0; j--) {
+			for (k = 0; k < 8; k++) {
+				PIC221111_32(k);
+			}
+			outc += 8;
+			outy += 16;
 			pic0 += 2 * width;
 			pic1 += 2 * width;
 		}
--- a/drivers/video/bootsplash/render.c
+++ b/drivers/video/bootsplash/render.c
@@ -13,82 +13,131 @@
 #include "../console/fbcon.h"
 #include "bootsplash.h"
 
-void splash_putcs(struct splash_data *sd, struct vc_data *vc, struct fb_info *info,
-			const unsigned short *s, int count, int ypos, int xpos)
-{
-	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
-	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
-	int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
-	u8 *src;
-        u8 *dst, *splashsrc;
-	unsigned int d, x, y;
-	u32 dd, fgx, bgx;
-	u16 c = scr_readw(s);
+#ifndef DEBUG
+# define SPLASH_DEBUG(fmt, args...)
+#else
+# define SPLASH_DEBUG(fmt, args...) \
+        printk(KERN_WARNING "%s: " fmt "\n",__FUNCTION__, ##args)
+#endif
 
-	int fg_color, bg_color, transparent;
-        if (console_blanked)
-	    return;
-        fg_color = attr_fgcol(fgshift, c);
-        bg_color = attr_bgcol(bgshift, c);
-	transparent = sd->splash_color == bg_color;
-	xpos = xpos * vc->vc_font.width + sd->splash_text_xo;
-	ypos = ypos * vc->vc_font.height + sd->splash_text_yo;
-        splashsrc = (u8 *)(info->splash_pic + ypos * info->splash_bytes + xpos * 2);
-        dst = (u8 *)(info->screen_base + ypos * info->fix.line_length + xpos * 2);
-
-	fgx = ((u32 *)info->pseudo_palette)[fg_color];
-	if (transparent && sd->splash_color == 15) {
-	    if (fgx == 0xffea)
-		fgx = 0xfe4a;
-	    else if (fgx == 0x57ea)
-		fgx = 0x0540;
-	    else if (fgx == 0xffff)
-		fgx = 0x52aa;
-	}
-	bgx = ((u32 *)info->pseudo_palette)[bg_color];
-	d = 0;
-
-	while (count--) {
-	    c = scr_readw(s++);
-	    src = vc->vc_font.data + (c & charmask) * vc->vc_font.height * ((vc->vc_font.width + 7) >> 3);
-
-	    for (y = 0; y < vc->vc_font.height; y++) {
-		for (x = 0; x < vc->vc_font.width; x += 2) {
-		    if ((x & 7) == 0)
-			d = *src++;
-		    if (d & 0x80)
-			dd = fgx;
-		    else
-			dd = transparent ? *(u16 *)splashsrc : bgx;
-		    splashsrc += 2;
-		    if (d & 0x40)
-			dd |= fgx << 16;
-		    else
-			dd |= (transparent ? *(u16 *)splashsrc : bgx) << 16;
-		    splashsrc += 2;
-		    d <<= 2;
-		    fb_writel(dd, dst);
-		    dst += 4;
-		}
-		dst += info->fix.line_length - vc->vc_font.width * 2;
-		splashsrc += info->splash_bytes - vc->vc_font.width * 2;
-	    }
-	    dst -= info->fix.line_length * vc->vc_font.height - vc->vc_font.width * 2;
-	    splashsrc -= info->splash_bytes * vc->vc_font.height - vc->vc_font.width * 2;
-	}
-}
-
-static void splash_renderc(struct splash_data *sd, struct fb_info *info, int fg_color, int bg_color, u8 *src, int ypos, int xpos, int height, int width)
+void splash_putcs(struct vc_data *vc, struct fb_info *info,
+		   const unsigned short *s, int count, int ypos, int xpos)
+{
+	struct splash_data *sd;
+       unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+       int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
+       int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
+       union pt src;
+       union pt dst, splashsrc;
+       unsigned int d, x, y;
+       u32 dd, fgx, bgx;
+       u16 c = scr_readw(s);
+       int fg_color, bg_color, transparent;
+       int n;
+       int octpp = (info->var.bits_per_pixel + 1) >> 3;
+
+       if (!oops_in_progress && (console_blanked || info->splash_data->splash_dosilent))
+	       return;
+       sd = info->splash_data;
+
+       fg_color = attr_fgcol(fgshift, c);
+       bg_color = attr_bgcol(bgshift, c);
+       transparent = sd->splash_color == bg_color;
+       xpos = xpos * vc->vc_font.width + sd->splash_text_xo;
+       ypos = ypos * vc->vc_font.height + sd->splash_text_yo;
+       splashsrc.ub = (u8 *)(info->splash_pic + ypos * info->splash_pic_stride + xpos * octpp);
+       dst.ub = (u8 *)(info->screen_base + ypos * info->fix.line_length + xpos * octpp);
+       fgx = ((u32 *)info->pseudo_palette)[fg_color];
+       if (transparent && sd->splash_color == 15) {
+           if (fgx == 0xffea)
+               fgx = 0xfe4a;
+           else if (fgx == 0x57ea)
+               fgx = 0x0540;
+           else if (fgx == 0xffff)
+               fgx = 0x52aa;
+       }
+       bgx = ((u32 *)info->pseudo_palette)[bg_color];
+       d = 0;
+       while (count--) {
+	       c = scr_readw(s++);
+	       src.ub = vc->vc_font.data + (c & charmask) * vc->vc_font.height * ((vc->vc_font.width + 7) >> 3);
+	       for (y = 0; y < vc->vc_font.height; y++) {
+		       for (x = 0; x < vc->vc_font.width; ) {
+			       if ((x & 7) == 0)
+				       d = *src.ub++;
+			       switch (octpp) {
+			       case 2:
+				       if (d & 0x80)
+					       dd = fgx;
+				       else
+					       dd = transparent ? *splashsrc.us : bgx;
+						       splashsrc.us += 1;
+						       if (d & 0x40)
+							       dd |= fgx << 16;
+						       else
+							       dd |= (transparent ? *splashsrc.us : bgx) << 16;
+						       splashsrc.us += 1;
+						       d <<= 2;
+						       x += 2;
+						       fb_writel(dd, dst.ul);
+						       dst.ul += 1;
+						       break;
+			       case 3:
+				       for (n = 0; n <= 16; n += 8) {
+					       if (d & 0x80)
+						       dd = (fgx >> n) && 0xff;
+					       else
+						       dd = (transparent ? *splashsrc.ul : ((bgx >> n) & 0xff) );
+					       splashsrc.ub += 1;
+					       fb_writeb(dd, dst.ub);
+					       dst.ub += 1;
+				       }
+				       d <<= 1;
+				       x += 1;
+				       break;
+			       case 4:
+				       if (d & 0x80)
+					       dd = fgx;
+				       else
+					       dd = (transparent ? *splashsrc.ul : bgx);
+				       splashsrc.ul += 1;
+				       d <<= 1;
+				       x += 1;
+				       fb_writel(dd, dst.ul);
+				       dst.ul += 1;
+				       break;
+			       }
+		       }
+		       dst.ub += info->fix.line_length - vc->vc_font.width * octpp;
+		       splashsrc.ub += info->splash_pic_stride - vc->vc_font.width * octpp;
+	       }
+	       dst.ub -= info->fix.line_length * vc->vc_font.height - vc->vc_font.width * octpp;
+	       splashsrc.ub -= info->splash_pic_stride * vc->vc_font.height - vc->vc_font.width * octpp;
+       }
+}
+
+static void splash_renderc(struct fb_info *info,
+			   int fg_color, int bg_color,
+			   u8 *src,
+			   int ypos, int xpos,
+			   int height, int width)
 {
-	int transparent = sd->splash_color == bg_color;
+	struct splash_data *sd;
+	int transparent;
 	u32 dd, fgx, bgx;
-	u8 *dst, *splashsrc;
+	union pt dst, splashsrc;
 	unsigned int d, x, y;
+	int n;
+	int octpp = (info->var.bits_per_pixel + 1) >> 3;
 
-        if (console_blanked)
-	    return;
-	splashsrc = (u8 *)(info->splash_pic + ypos * info->splash_bytes + xpos * 2);
-	dst = (u8 *)(info->screen_base + ypos * info->fix.line_length + xpos * 2);
+        if (!oops_in_progress && (console_blanked || info->splash_data->splash_dosilent))
+		return;
+
+	sd = info->splash_data;
+
+	transparent = sd->splash_color == bg_color;
+	splashsrc.ub = (u8*)(info->splash_pic + ypos * info->splash_pic_stride + xpos * octpp);
+	dst.ub = (u8*)(info->screen_base + ypos * info->fix.line_length + xpos * octpp);
 	fgx = ((u32 *)info->pseudo_palette)[fg_color];
 	if (transparent && sd->splash_color == 15) {
 	    if (fgx == 0xffea)
@@ -101,93 +150,136 @@ static void splash_renderc(struct splash
 	bgx = ((u32 *)info->pseudo_palette)[bg_color];
 	d = 0;
 	for (y = 0; y < height; y++) {
-	    for (x = 0; x < width; x += 2) {
-		if ((x & 7) == 0)
-		    d = *src++;
-		if (d & 0x80)
-		    dd = fgx;
-		else
-		    dd = transparent ? *(u16 *)splashsrc : bgx;
-		splashsrc += 2;
-		if (d & 0x40)
-		    dd |= fgx << 16;
-		else
-		    dd |= (transparent ? *(u16 *)splashsrc : bgx) << 16;
-		splashsrc += 2;
-		d <<= 2;
-		fb_writel(dd, dst);
-		dst += 4;
-	    }
-	    dst += info->fix.line_length - width * 2;
-	    splashsrc += info->splash_bytes - width * 2;
+		for (x = 0; x < width; ) {
+			if ((x & 7) == 0)
+				d = *src++;
+			switch (octpp) {
+			case 2:
+				if (d & 0x80)
+					dd = fgx;
+				else
+					dd = transparent ? *splashsrc.us : bgx;
+						splashsrc.us += 1;
+						if (d & 0x40)
+							dd |= fgx << 16;
+						else
+							dd |= (transparent ? *splashsrc.us : bgx) << 16;
+						splashsrc.us += 1;
+						d <<= 2;
+						x += 2;
+						fb_writel(dd, dst.ul);
+						dst.ul += 1;
+						break;
+			case 3:
+				for (n = 0; n <= 16; n += 8) {
+					if (d & 0x80)
+						dd = (fgx >> n) & 0xff;
+					else
+						dd = transparent ? *splashsrc.ub : bgx;
+					splashsrc.ub += 1;
+					fb_writeb(dd, dst.ub);
+					dst.ub += 1;
+				}
+				d <<= 1;
+				x += 1;
+				break;
+			case 4:
+				if (d & 0x80)
+					dd = fgx;
+				else
+					dd = transparent ? *splashsrc.ul : bgx;
+						splashsrc.ul += 1;
+						d <<= 1;
+						x += 1;
+						fb_writel(dd, dst.ul);
+						dst.ul += 1;
+						break;
+			}
+		}
+		dst.ub += info->fix.line_length - width * octpp;
+		splashsrc.ub += info->splash_pic_stride - width * octpp;
 	}
 }
 
-void splash_putc(struct splash_data *sd, struct vc_data *vc, struct fb_info *info,
-                      int c, int ypos, int xpos)
-{
-	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
-	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
-	int fgshift = (vc->vc_hi_font_mask) ? 9 : 8;
-	u8 *src = vc->vc_font.data + (c & charmask) * vc->vc_font.height * ((vc->vc_font.width + 7) >> 3);
-	xpos = xpos * vc->vc_font.width + sd->splash_text_xo;
-	ypos = ypos * vc->vc_font.height + sd->splash_text_yo;
-	splash_renderc(sd, info, attr_fgcol(fgshift, c), attr_bgcol(bgshift, c), src, ypos, xpos, vc->vc_font.height, vc->vc_font.width);
-}
-
-void splashcopy(u8 *dst, u8 *src, int height, int width, int dstbytes, int srcbytes)
+void splashcopy(u8 *dst, u8 *src, int height, int width, int dstbytes, int srcbytes, int octpp)
 {
 	int i;
 
+	width *= octpp;
 	while (height-- > 0) {
-	    u32 *p = (u32 *)dst;
-	    u32 *q = (u32 *)src;
-	    for (i=0; i < width/4; i++) {
-		fb_writel(*q++,p++);
-		fb_writel(*q++,p++);
-	    }
-	    if (width & 2)
-		fb_writel(*q++,p++);
-	    if (width & 1)
-		fb_writew(*(u16*)q,(u16*)p);
-	    dst += dstbytes;
-	    src += srcbytes;
+		union pt p, q;
+		p.ul = (u32 *)dst;
+		q.ul = (u32 *)src;
+		for (i=0; i < width/8; i++) {
+			fb_writel(*q.ul++,p.ul++);
+			fb_writel(*q.ul++,p.ul++);
+		}
+		if (width & 4)
+			fb_writel(*q.ul++,p.ul++);
+		if (width & 2)
+			fb_writew(*q.us++,p.us++);
+		if (width & 1)
+			fb_writeb(*q.ub,p.ub);
+		dst += dstbytes;
+		src += srcbytes;
 	}
 }
 
-static void splashset(u8 *dst, int height, int width, int dstbytes, u32 bgx) {
+static void splashset(u8 *dst, int height, int width, int dstbytes, u32 bgx, int octpp) {
 	int i;
 
-	bgx |= bgx << 16;
+	width *= octpp;
+	if (octpp == 2)
+		bgx |= bgx << 16;
 	while (height-- > 0) {
-	    u32 *p = (u32 *)dst;
-	    for (i=0; i < width/4; i++) {
-		fb_writel(bgx,p++);
-		fb_writel(bgx,p++);
-	    }
-	    if (width & 2)
-		fb_writel(bgx,p++);
-	    if (width & 1)
-		fb_writew(bgx,(u16*)p);
-	    dst += dstbytes;
+		union pt p;
+		p.ul = (u32 *)dst;
+		if (octpp != 3) {
+			for (i=0; i < width/8; i++) {
+				fb_writel(bgx,p.ul++);
+				fb_writel(bgx,p.ul++);
+			}
+			if (width & 4)
+				fb_writel(bgx,p.ul++);
+			if (width & 2)
+				fb_writew(bgx,p.us++);
+			if (width & 1)
+				fb_writeb(bgx,p.ub);
+			dst += dstbytes;
+		} else { /* slow! */
+			for (i=0; i < width; i++)
+				fb_writeb((bgx >> ((i & 0x3) * 8)) && 0xff,p.ub++);
+		}
 	}
 }
 
 static void splashfill(struct fb_info *info, int sy, int sx, int height, int width) {
-	splashcopy((u8 *)(info->screen_base + sy * info->fix.line_length + sx * 2), (u8 *)(info->splash_pic + sy * info->splash_bytes + sx * 2), height, width, info->fix.line_length, info->splash_bytes);
+        int octpp = (info->var.bits_per_pixel + 1) >> 3;
+
+        splashcopy((u8 *)(info->screen_base + sy * info->fix.line_length + sx * octpp),
+		   (u8 *)(info->splash_pic + sy * info->splash_pic_stride + sx * octpp),
+		   height, width, info->fix.line_length, info->splash_pic_stride,
+		   octpp);
 }
 
-void splash_clear(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, int sy,
+void splash_clear(struct vc_data *vc, struct fb_info *info, int sy,
 			int sx, int height, int width)
 {
+	struct splash_data *sd;
 	int bgshift = (vc->vc_hi_font_mask) ? 13 : 12;
 	int bg_color = attr_bgcol_ec(bgshift, vc, info);
-	int transparent = sd->splash_color == bg_color;
+	int transparent;
+	int octpp = (info->var.bits_per_pixel + 1) >> 3;
 	u32 bgx;
 	u8 *dst;
 
-        if (console_blanked)
-	    return;
+        if (!oops_in_progress && (console_blanked || info->splash_data->splash_dosilent))
+		return;
+
+	sd = info->splash_data;
+
+	transparent = sd->splash_color == bg_color;
+
 	sy = sy * vc->vc_font.height + sd->splash_text_yo;
 	sx = sx * vc->vc_font.width + sd->splash_text_xo;
 	height *= vc->vc_font.height;
@@ -196,18 +288,26 @@ void splash_clear(struct splash_data *sd
 		splashfill(info, sy, sx, height, width);
 		return;
 	}
-        dst = (u8 *)(info->screen_base + sy * info->fix.line_length + sx * 2);
+        dst = (u8 *)(info->screen_base + sy * info->fix.line_length + sx * octpp);
 	bgx = ((u32 *)info->pseudo_palette)[bg_color];
-	splashset(dst, height, width, info->fix.line_length, bgx);
+	splashset(dst,
+		  height, width,
+		  info->fix.line_length,
+		  bgx,
+		  (info->var.bits_per_pixel + 1) >> 3);
 }
 
-void splash_bmove(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, int sy,
+void splash_bmove(struct vc_data *vc, struct fb_info *info, int sy,
 		int sx, int dy, int dx, int height, int width)
 {
+	struct splash_data *sd;
 	struct fb_copyarea area;
 
-        if (console_blanked)
-	    return;
+	if (!oops_in_progress && (console_blanked || info->splash_data->splash_dosilent))
+		return;
+
+	sd = info->splash_data;
+
 	area.sx = sx * vc->vc_font.width;
 	area.sy = sy * vc->vc_font.height;
 	area.dx = dx * vc->vc_font.width;
@@ -222,34 +322,57 @@ void splash_bmove(struct splash_data *sd
 	info->fbops->fb_copyarea(info, &area);
 }
 
-void splash_clear_margins(struct splash_data *sd, struct vc_data *vc, struct fb_info *info,
+void splash_clear_margins(struct vc_data *vc, struct fb_info *info,
 				int bottom_only)
 {
+	struct splash_data *sd;
 	unsigned int tw = vc->vc_cols*vc->vc_font.width;
 	unsigned int th = vc->vc_rows*vc->vc_font.height;
+	SPLASH_DEBUG();
+
+	if (!oops_in_progress && (console_blanked || info->splash_data->splash_dosilent))
+		return;
+
+	sd = info->splash_data;
 
-        if (console_blanked)
-	    return;
 	if (!bottom_only) {
 		/* top margin */
-		splashfill(info, 0, 0, sd->splash_text_yo, info->var.xres);
+		splashfill(info,
+			   0,
+			   0,
+			   sd->splash_text_yo,
+			   info->var.xres);
 		/* left margin */
-		splashfill(info, sd->splash_text_yo, 0, th, sd->splash_text_xo);
+		splashfill(info,
+			   sd->splash_text_yo,
+			   0,
+			   th,
+			   sd->splash_text_xo);
 		/* right margin */
-		splashfill(info, sd->splash_text_yo, sd->splash_text_xo + tw, th, info->var.xres - sd->splash_text_xo - tw);
-
+		splashfill(info,
+			   sd->splash_text_yo,
+			   sd->splash_text_xo + tw,
+			   th,
+			   info->var.xres - sd->splash_text_xo - tw);
 	}
-	splashfill(info, sd->splash_text_yo + th, 0, info->var.yres - sd->splash_text_yo - th, info->var.xres);
+	splashfill(info,
+		   sd->splash_text_yo + th,
+		   0,
+		   info->var.yres - sd->splash_text_yo - th,
+		   info->var.xres);
 }
 
-int splash_cursor(struct splash_data *sd, struct fb_info *info, struct fb_cursor *cursor)
+int splash_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
+	struct splash_data *sd;
 	int i;
 	unsigned int dsize, s_pitch;
 
 	if (info->state != FBINFO_STATE_RUNNING)
 		return 0;
 
+	sd = info->splash_data;
+
 	s_pitch = (cursor->image.width + 7) >> 3;
         dsize = s_pitch * cursor->image.height;
         if (cursor->enable) {
@@ -267,13 +390,15 @@ int splash_cursor(struct splash_data *sd
         } else if (info->fb_cursordata != cursor->image.data)
                 memcpy(info->fb_cursordata, cursor->image.data, dsize);
 	cursor->image.data = info->fb_cursordata;
-	splash_renderc(sd, info, cursor->image.fg_color, cursor->image.bg_color, (u8 *)info->fb_cursordata, cursor->image.dy + sd->splash_text_yo, cursor->image.dx + sd->splash_text_xo, cursor->image.height, cursor->image.width);
+	splash_renderc(info, cursor->image.fg_color, cursor->image.bg_color, (u8 *)info->fb_cursordata, cursor->image.dy + sd->splash_text_yo, cursor->image.dx + sd->splash_text_xo, cursor->image.height, cursor->image.width);
 	return 0;
 }
 
-void splash_bmove_redraw(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width)
+void splash_bmove_redraw(struct vc_data *vc, struct fb_info *info, int y, int sx, int dx, int width)
 {
-	unsigned short *d = (unsigned short *) (vc->vc_origin + vc->vc_size_row * y + dx * 2);
+	struct splash_data *sd;
+        int octpp = (info->var.bits_per_pixel + 1) >> 3;
+	unsigned short *d = (unsigned short *) (vc->vc_origin + vc->vc_size_row * y + dx * octpp);
 	unsigned short *s = d + (dx - sx);
 	unsigned short *start = d;
 	unsigned short *ls = d;
@@ -282,21 +407,24 @@ void splash_bmove_redraw(struct splash_d
 	int x = dx;
 	unsigned short attr = 1;
 
-        if (console_blanked)
+	if (console_blanked || info->splash_data->splash_dosilent)
 	    return;
+
+	sd = info->splash_data;
+
 	do {
 		c = scr_readw(d);
 		if (attr != (c & 0xff00)) {
 			attr = c & 0xff00;
 			if (d > start) {
-				splash_putcs(sd, vc, info, start, d - start, y, x);
+				splash_putcs(vc, info, start, d - start, y, x);
 				x += d - start;
 				start = d;
 			}
 		}
 		if (s >= ls && s < le && c == scr_readw(s)) {
 			if (d > start) {
-				splash_putcs(sd, vc, info, start, d - start, y, x);
+				splash_putcs(vc, info, start, d - start, y, x);
 				x += d - start + 1;
 				start = d + 1;
 			} else {
@@ -308,21 +436,22 @@ void splash_bmove_redraw(struct splash_d
 		d++;
 	} while (d < le);
 	if (d > start)
-		splash_putcs(sd, vc, info, start, d - start, y, x);
+		splash_putcs(vc, info, start, d - start, y, x);
 }
 
-void splash_blank(struct splash_data *sd, struct vc_data *vc, struct fb_info *info, int blank)
+void splash_blank(struct vc_data *vc, struct fb_info *info, int blank)
 {
+        SPLASH_DEBUG();
 	if (blank) {
-		if (info->silent_screen_base)
-		    splashset((u8 *)info->silent_screen_base, info->var.yres, info->var.xres, info->fix.line_length, 0);
-		splashset((u8 *)info->screen_base, info->var.yres, info->var.xres, info->fix.line_length, 0);
+		splashset((u8 *)info->screen_base,
+			  info->var.yres, info->var.xres,
+			  info->fix.line_length,
+			  0,
+			  (info->var.bits_per_pixel + 1) >> 3);
 	} else {
-		if (info->silent_screen_base)
-			splash_prepare(vc, info);
-		splash_clear_margins(vc->vc_splash_data, vc, info, 0);
+	        // splash_prepare(vc, info); /* do we really need this? */
+		splash_clear_margins(vc, info, 0);
 		/* no longer needed, done in fbcon_blank */
 		/* update_screen(vc->vc_num); */
 	}
 }
-
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -52,7 +52,7 @@ static void bit_bmove(struct vc_data *vc
 
 #ifdef CONFIG_BOOTSPLASH
 	if (info->splash_data) {
-		splash_bmove(info->splash_data, vc, info,
+		splash_bmove(vc, info,
 			sy, sx, dy, dx, height, width);
 		return;
 	}
@@ -75,8 +75,8 @@ static void bit_clear(struct vc_data *vc
 
 #ifdef CONFIG_BOOTSPLASH
 	if (info->splash_data) {
-		splash_clear(info->splash_data, vc, info,
-						sy, sx, height, width);
+		splash_clear(vc, info,
+			     sy, sx, height, width);
 		return;
 	}
 #endif
@@ -179,7 +179,7 @@ static void bit_putcs(struct vc_data *vc
 
 #ifdef CONFIG_BOOTSPLASH
 	if (info->splash_data) {
-		splash_putcs(info->splash_data, vc, info, s, count, yy, xx);
+		splash_putcs(vc, info, s, count, yy, xx);
 		return;
 	}
 #endif
@@ -239,7 +239,7 @@ static void bit_clear_margins(struct vc_
 
 #ifdef CONFIG_BOOTSPLASH
 	if (info->splash_data) {
-		splash_clear_margins(info->splash_data, vc, info, bottom_only);
+		splash_clear_margins(vc, info, bottom_only);
 		return;
 	}
 #endif
@@ -412,7 +412,7 @@ static void bit_cursor(struct vc_data *v
 
 #ifdef CONFIG_BOOTSPLASH
 	if (info->splash_data) {
-		splash_cursor(info->splash_data, info, &cursor);
+		splash_cursor(info, &cursor);
 		ops->cursor_reset = 0;
 		return;
 	}
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -2072,7 +2072,7 @@ static void fbcon_bmove_rec(struct vc_da
 #ifdef CONFIG_BOOTSPLASH
 	if (info->splash_data && sy == dy && height == 1) {
 		/* must use slower redraw bmove to keep background pic intact */
-		splash_bmove_redraw(info->splash_data, vc, info, sy, sx, dx, width);
+	    splash_bmove_redraw(vc, info, sy, sx, dx, width);
 		return;
 	}
 #endif
@@ -2323,7 +2323,7 @@ static void fbcon_generic_blank(struct v
 
 #ifdef CONFIG_BOOTSPLASH
 	if (info->splash_data) {
-		splash_blank(info->splash_data, vc, info, blank);
+		splash_blank(vc, info, blank);
 		return;
 	}
 #endif
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -182,10 +182,7 @@ static void vesafb_destroy(struct fb_inf
 	framebuffer_release(info);
 }
 
-#ifndef CONFIG_BOOTSPLASH
-static
-#endif
-struct fb_ops vesafb_ops = {
+static struct fb_ops vesafb_ops = {
 	.owner		= THIS_MODULE,
 	.fb_destroy     = vesafb_destroy,
 	.fb_setcolreg	= vesafb_setcolreg,
@@ -270,9 +267,6 @@ static int __devinit vesafb_probe(struct
 	 *                 option to simply use size_total as that
 	 *                 wastes plenty of kernel address space. */
 	size_remap  = size_vmode * 2;
-#ifdef CONFIG_BOOTSPLASH
-	size_remap *= 2;	/* some more for the images */
-#endif
 	if (vram_remap)
 		size_remap = vram_remap * 1024 * 1024;
 	if (size_remap < size_vmode)
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -863,8 +863,7 @@ struct fb_info {
 	struct splash_data *splash_data;
 	unsigned char *splash_pic;
 	int splash_pic_size;
-	int splash_bytes;
-	char *silent_screen_base;	/* real screen base */
+	int splash_pic_stride;
 	char fb_cursordata[64];
 #endif
 	/* we need the PCI or similiar aperture base/size not
