From 1319de907e12d28894d8db0b3215a0443ff4bd5d Mon Sep 17 00:00:00 2001 From: Egbert Eich 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 --- drivers/tty/vt/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/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -4216,7 +4216,7 @@ void vcs_scr_updated(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; @@ -4224,11 +4224,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 #include #include +#include +#include #include #include @@ -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) + console_lock(); - 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) + console_unlock(); + + 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); console_unlock(); 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 console_unlock(); 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); + } } console_unlock(); 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; } console_unlock(); 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); + } + } } - } - console_unlock(); - return count; + console_unlock(); + return count; } if (!vc->vc_splash_data) { console_unlock(); @@ -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); console_unlock(); 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) { console_lock(); - 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; console_unlock(); 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 @@ -53,7 +53,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; } @@ -76,8 +76,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 @@ -180,7 +180,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 @@ -240,7 +240,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 @@ -413,7 +413,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 @@ -2074,7 +2074,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 @@ -2325,7 +2325,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 @@ -181,10 +181,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, @@ -269,9 +266,6 @@ static int __init vesafb_probe(struct pl * 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 @@ -879,8 +879,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