Geert,
I was wondering how to implement positioning of the logo with the
current method of displaying it (by reserving screen space of height 
"logo_lines"). This is not so nice to look at when we position the logo
in the center or the bottom.
So how about making the logo "float" above/obscure the text (ie,
overlay)?  It's not difficult to implement since fbcon.c has "redraw"
versions of fbcon_bmove() and fbcon_clear().  All that needs to be done
is do a "scissors" test before an fb_imageblit().  
Here's a trial implementation.  The logo configuration has extra options
for the "overlay method" (CONFIG_LOGO_OVERLAY) and positioning of the
logo (top, bottom, left, right, center).  The logo will always stay on
top while the underlying text is scrolling.
Attached is a diff.  James' latest fbdev.diff and the series of patches
I submitted must be applied first.
Tony
diff -Naur linux-2.5.61-fbdev/drivers/video/console/fbcon.c linux-2.5.61/drivers/video/console/fbcon.c
--- linux-2.5.61-fbdev/drivers/video/console/fbcon.c	2003-02-17 17:57:37.000000000 +0000
+++ linux-2.5.61/drivers/video/console/fbcon.c	2003-02-17 18:39:56.000000000 +0000
@@ -106,9 +106,25 @@
 
 struct display fb_display[MAX_NR_CONSOLES];
 char con2fb_map[MAX_NR_CONSOLES];
+static struct fb_fillrect dim_logo;
 static int logo_height;
 static int logo_lines;
 static int logo_shown = -1;
+
+#ifdef CONFIG_LOGO_OVERLAY
+static int logo_scissors = 1;
+static inline int get_logo_height(void)
+{
+	return 0;
+}
+#else
+static int logo_scissors = 0;
+static inline int get_logo_height(void)
+{
+	return (dim_logo.height);
+}
+#endif /* CONFIG_LOGO_OVERLAY */
+
 /* Software scrollback */
 int fbcon_softback_size = 32768;
 static unsigned long softback_buf, softback_curr;
@@ -394,6 +410,27 @@
 	image.height = vc->vc_font.height;
 	image.depth = 0;
 
+	if (logo_scissors) {
+		int sx1 = dim_logo.dx;
+		int sx2 = dim_logo.dx + dim_logo.width;
+		int sy1 = dim_logo.dy;
+		int sy2 = dim_logo.dy + dim_logo.height;
+
+		image.width = vc->vc_font.width;
+		while (count--) {
+			if (!(image.dx + image.width > sx1 && 
+			      image.dy + image.height > sy1 &&
+			      image.dx < sx2 && image.dy < sy2)) {
+				image.data = p->fontdata + 
+					(scr_readw(s) & charmask) * cellsize;
+				info->fbops->fb_imageblit(info, &image);
+			}
+			image.dx += vc->vc_font.width;
+			s++;
+		}	
+		return;
+	}
+
 	if (!(vc->vc_font.width & 7)) {
 		unsigned int pitch, cnt, i, j, k;
 		unsigned int maxcnt = FB_PIXMAPSIZE/cellsize;
@@ -563,6 +600,19 @@
 	cursor.dest = dest;
 	cursor.rop = ROP_XOR;
 
+	if (logo_scissors) {
+		int sx1 = dim_logo.dx;
+		int sx2 = dim_logo.dx + dim_logo.width;
+		int sy1 = dim_logo.dy;
+		int sy2 = dim_logo.dy + dim_logo.height;
+
+		if (cursor.image.dx < sx2 && 
+		    cursor.image.dy < sy2 &&
+		    cursor.image.dx + cursor.image.width > sx1 &&
+		    cursor.image.dy + cursor.image.height > sy1)
+			return;
+	}
+
 	if (info->fbops->fb_cursor)
 		info->fbops->fb_cursor(info, &cursor);
 }
@@ -945,7 +995,8 @@
 		int cnt;
 		int step;
 
-		logo_height = fb_prepare_logo(info);
+		fb_prepare_logo(&dim_logo, info);
+		logo_height = get_logo_height();
 		logo_lines = (logo_height + vc->vc_font.height - 1) /
 			     vc->vc_font.height;
 		q = (unsigned short *) (vc->vc_origin +
@@ -1115,6 +1166,11 @@
 		redraw_cursor = 1;
 	}
 
+	if (logo_scissors) {
+		fbcon_redraw_clear(vc, p, sy, sx, height, width);
+		return;
+	}
+
 	/* Split blits that cross physical y_wrap boundary */
 
 	y_break = p->vrows - p->yscroll;
@@ -1151,12 +1207,23 @@
 		redraw_cursor = 1;
 	}
 
-	image.fg_color = attr_fgcol(p, c);
-	image.bg_color = attr_bgcol(p, c);
 	image.dx = xpos * vc->vc_font.width;
 	image.dy = real_y(p, ypos) * vc->vc_font.height;
 	image.width = vc->vc_font.width;
 	image.height = vc->vc_font.height;
+	if (logo_scissors) {
+		int sx1 = dim_logo.dx;
+		int sx2 = dim_logo.dx + dim_logo.width;
+		int sy1 = dim_logo.dy;
+		int sy2 = dim_logo.dy + dim_logo.height;
+
+		if (image.dx < sx2 && image.dy < sy2 &&
+		    image.dx + image.width > sx1 &&
+		    image.dy + image.height > sy1)
+			return;
+	}
+	image.fg_color = attr_fgcol(p, c);
+	image.bg_color = attr_bgcol(p, c);
 	image.depth = 1;
 	image.data = p->fontdata + (c & charmask) * vc->vc_font.height * width;
 
@@ -1707,8 +1774,7 @@
 		      redraw_up:
 			fbcon_redraw(vc, p, t, b - t - count,
 				     count * vc->vc_cols);
-			accel_clear(vc, p, real_y(p, b - count), 0,
-					 count, vc->vc_cols);
+			fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
 			scr_memsetw((unsigned short *) (vc->vc_origin +
 							vc->vc_size_row *
 							(b - count)),
@@ -1913,6 +1979,7 @@
 		    && conp2->vc_bottom == conp2->vc_rows)
 			conp2->vc_top = 0;
 		logo_shown = -1;
+		logo_scissors = 0;
 	}
 	if (info)
 		info->var.yoffset = p->yscroll = 0;
@@ -2476,6 +2543,7 @@
 					      logo_lines * vc->vc_cols);
 			}
 			logo_shown = -1;
+			logo_scissors = 0;
 		}
 		fbcon_cursor(vc, CM_ERASE | CM_SOFTBACK);
 		fbcon_redraw_softback(vc, p, lines);
diff -Naur linux-2.5.61-fbdev/drivers/video/fbmem.c linux-2.5.61/drivers/video/fbmem.c
--- linux-2.5.61-fbdev/drivers/video/fbmem.c	2003-02-17 17:57:40.000000000 +0000
+++ linux-2.5.61/drivers/video/fbmem.c	2003-02-17 18:38:50.000000000 +0000
@@ -363,15 +363,15 @@
 static int ofonly __initdata = 0;
 #endif
 
+#ifdef CONFIG_LOGO
+#include <linux/linux_logo.h>
+
 static inline unsigned safe_shift(unsigned d, int n)
 {
 	return n < 0 ? d >> -n : d << n;
 }
 
-#ifdef CONFIG_FB_LOGO
-#include <linux/linux_logo.h>
-
-static void __init fb_set_logocmap(struct fb_info *info,
+static void fb_set_logocmap(struct fb_info *info,
 				   const struct linux_logo *logo)
 {
 	struct fb_cmap palette_cmap;
@@ -435,7 +435,7 @@
 	}
 }
 
-static void __init fb_set_logo_directpalette(struct fb_info *info,
+static void fb_set_logo_directpalette(struct fb_info *info,
 					     const struct linux_logo *logo,
 					     u32 *palette)
 {
@@ -520,15 +520,72 @@
 	int needs_truepalette;
 	int needs_cmapreset;
 	int type;
+	int dx;
+	int dy;
 	const struct linux_logo *logo;
 } fb_logo;
 
-int fb_prepare_logo(struct fb_info *info)
+#ifdef CONFIG_LOGO_CENTER
+static inline int get_logo_xpos(struct fb_info *info)
 {
-	memset(&fb_logo, 0, sizeof(struct logo_data));
+	return ((info->var.xres - fb_logo.logo->width)/2);
+}
+#elif CONFIG_LOGO_RIGHT
+static inline int get_logo_xpos(struct fb_info *info)
+{
+	return (info->var.xres - fb_logo.logo->width);
+}
+#else
+static inline int get_logo_xpos(struct fb_info *info)
+{
+	return (0);
+}
+#endif
 
-	fb_logo.depth = info->var.bits_per_pixel;
+#ifdef CONFIG_LOGO_MIDDLE
+static inline int get_logo_ypos(struct fb_info *info)
+{
+	return ((info->var.yres - fb_logo.logo->height)/2);
+}
+#elif CONFIG_LOGO_BOTTOM
+static inline int get_logo_ypos(struct fb_info *info)
+{
+	return (info->var.yres - fb_logo.logo->height);
+}
+#else
+static inline int get_logo_ypos(struct fb_info *info)
+{
+	return (0);
+}
+#endif
+
+#ifdef CONFIG_LOGO_OVERLAY
+static inline void draw_logo(struct fb_image *image, struct fb_info *info)
+{
+	image->dx = fb_logo.dx;
+	info->fbops->fb_imageblit(info, image);
+}
+#else
+static inline void draw_logo(struct fb_image *image, struct fb_info *info)
+{
+	int xpos = fb_logo.dx;
+	int width = fb_logo.logo->width + 8;
+	int times = num_online_cpus(), x;
 
+	for (x = xpos; x < times * width && 
+	     x <= info->var.xres-width; x += width) {
+		image->dx = x;
+		info->fbops->fb_imageblit(info, image);
+	}
+}
+#endif /* CONFIG_LOGO_OVERLAY */
+
+void fb_prepare_logo(struct fb_fillrect *rect, struct fb_info *info)
+{
+	memset(&fb_logo, 0, sizeof(struct logo_data));
+	memset(rect, 0, sizeof(struct fb_fillrect));
+	fb_logo.depth = info->var.bits_per_pixel;
+	
 	switch (info->fix.visual) {
 	case FB_VISUAL_TRUECOLOR:
 		if (fb_logo.depth >= 8) {
@@ -587,9 +644,14 @@
 	fb_logo.logo = fb_find_logo(fb_logo.type);
 	if (!fb_logo.logo || fb_logo.logo->height > info->var.yres) {
 		fb_logo.logo = NULL;
-		return 0;
+		return;
 	}
-	return fb_logo.logo->height;
+	fb_logo.dx = get_logo_xpos(info);
+	fb_logo.dy = get_logo_ypos(info);
+	rect->dx = fb_logo.dx;
+	rect->dy = fb_logo.dy;
+	rect->width = fb_logo.logo->width;
+	rect->height = fb_logo.logo->height;
 }
 
 int fb_show_logo(struct fb_info *info)
@@ -597,7 +659,6 @@
 	unsigned char *fb = info->screen_base, *logo_new = NULL;
 	u32 *palette = NULL, *saved_pseudo_palette = NULL;
 	struct fb_image image;
-	int x;
 
 	/* Return if the frame buffer is not mapped */
 	if (!fb || !info->fbops->fb_imageblit ||
@@ -642,14 +703,10 @@
 
 	image.width = fb_logo.logo->width;
 	image.height = fb_logo.logo->height;
-	image.dy = 0;
+	image.dy = fb_logo.dy;
+
+	draw_logo(&image, info);
 
-	for (x = 0; x < num_online_cpus() * (fb_logo.logo->width + 8) &&
-	     x <= info->var.xres-fb_logo.logo->width; x += (fb_logo.logo->width + 8)) {
-		image.dx = x;
-		info->fbops->fb_imageblit(info, &image);
-	}
-	
 	if (palette != NULL)
 		kfree(palette);
 	if (saved_pseudo_palette != NULL)
@@ -659,9 +716,10 @@
 	return fb_logo.logo->height;
 }
 #else
-int fb_prepare_logo(struct fb_info *info) { return 0; }
+void fb_prepare_logo(struct fb_fillrect *rect, struct fb_info *info) 
+{ return 0; }
 int fb_show_logo(struct fb_info *info) { return 0; }
-#endif /* CONFIG_FB_LOGO */
+#endif /* CONFIG_LOGO */
 
 static int fbmem_read_proc(char *buf, char **start, off_t offset,
 			   int len, int *eof, void *private)
diff -Naur linux-2.5.61-fbdev/drivers/video/logo/Kconfig linux-2.5.61/drivers/video/logo/Kconfig
--- linux-2.5.61-fbdev/drivers/video/logo/Kconfig	2003-02-17 18:10:15.000000000 +0000
+++ linux-2.5.61/drivers/video/logo/Kconfig	2003-02-17 18:08:22.000000000 +0000
@@ -8,6 +8,47 @@
 	bool "Bootup logo"
 	depends on FB || CONFIG_SGI_NEWPORT_CONSOLE
 
+config LOGO_OVERLAY
+	bool "Logo Overlay"
+	depends on LOGO && FB
+	---help---
+          If you say Y, the logo will appear to "float" over
+          the primary display, obstructing the underlying
+          text.
+
+          If unsure, say N.
+choice 
+	prompt "Horizontal Position"
+	depends on LOGO_OVERLAY
+	default LOGO_LEFT
+	
+config LOGO_LEFT
+	bool "Left"
+
+config LOGO_CENTER
+	bool "Center"	
+
+config LOGO_RIGHT
+	bool "Right"
+
+endchoice
+
+choice 
+	prompt "Vertical Position"
+	depends on LOGO_OVERLAY
+	default LOGO_TOP
+
+config LOGO_TOP
+	bool "Top"
+
+config LOGO_MIDDLE
+	bool "Center"	
+
+config LOGO_BOTTOM
+	bool "Bottom"
+
+endchoice
+
 config LOGO_LINUX_MONO
 	bool "Black and white Linux logo"
 	depends on LOGO
diff -Naur linux-2.5.61-fbdev/include/linux/fb.h linux-2.5.61/include/linux/fb.h
--- linux-2.5.61-fbdev/include/linux/fb.h	2003-02-17 17:57:37.000000000 +0000
+++ linux-2.5.61/include/linux/fb.h	2003-02-17 18:05:01.000000000 +0000
@@ -462,7 +462,7 @@
 /* drivers/video/fbmem.c */
 extern int register_framebuffer(struct fb_info *fb_info);
 extern int unregister_framebuffer(struct fb_info *fb_info);
-extern int fb_prepare_logo(struct fb_info *fb_info);
+extern void fb_prepare_logo(struct fb_fillrect *rect, struct fb_info *fb_info);
 extern int fb_show_logo(struct fb_info *fb_info);
 extern struct fb_info *registered_fb[FB_MAX];
 extern int num_registered_fb; 
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/