diff options
Diffstat (limited to 'drivers/video/fbmem.c')
-rw-r--r-- | drivers/video/fbmem.c | 212 |
1 files changed, 143 insertions, 69 deletions
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 717684bde48..215ac579f90 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -404,72 +404,6 @@ static void fb_do_show_logo(struct fb_info *info, struct fb_image *image, } } -int fb_prepare_logo(struct fb_info *info, int rotate) -{ - int depth = fb_get_color_depth(&info->var, &info->fix); - int yres; - - memset(&fb_logo, 0, sizeof(struct logo_data)); - - if (info->flags & FBINFO_MISC_TILEBLITTING || - info->flags & FBINFO_MODULE) - return 0; - - if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) { - depth = info->var.blue.length; - if (info->var.red.length < depth) - depth = info->var.red.length; - if (info->var.green.length < depth) - depth = info->var.green.length; - } - - if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR && depth > 4) { - /* assume console colormap */ - depth = 4; - } - - if (depth >= 8) { - switch (info->fix.visual) { - case FB_VISUAL_TRUECOLOR: - fb_logo.needs_truepalette = 1; - break; - case FB_VISUAL_DIRECTCOLOR: - fb_logo.needs_directpalette = 1; - fb_logo.needs_cmapreset = 1; - break; - case FB_VISUAL_PSEUDOCOLOR: - fb_logo.needs_cmapreset = 1; - break; - } - } - - /* Return if no suitable logo was found */ - fb_logo.logo = fb_find_logo(depth); - - if (!fb_logo.logo) { - return 0; - } - - if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD) - yres = info->var.yres; - else - yres = info->var.xres; - - if (fb_logo.logo->height > yres) { - fb_logo.logo = NULL; - return 0; - } - - /* What depth we asked for might be different from what we get */ - if (fb_logo.logo->type == LINUX_LOGO_CLUT224) - fb_logo.depth = 8; - else if (fb_logo.logo->type == LINUX_LOGO_VGA16) - fb_logo.depth = 4; - else - fb_logo.depth = 1; - return fb_logo.logo->height; -} - static int fb_show_logo_line(struct fb_info *info, int rotate, const struct linux_logo *logo, int y, unsigned int n) @@ -489,7 +423,7 @@ static int fb_show_logo_line(struct fb_info *info, int rotate, if (fb_logo.needs_cmapreset) fb_set_logocmap(info, logo); - if (fb_logo.needs_truepalette || + if (fb_logo.needs_truepalette || fb_logo.needs_directpalette) { palette = kmalloc(256 * 4, GFP_KERNEL); if (palette == NULL) @@ -538,10 +472,150 @@ static int fb_show_logo_line(struct fb_info *info, int rotate, return logo->height; } + +#ifdef CONFIG_FB_LOGO_EXTRA + +#define FB_LOGO_EX_NUM_MAX 10 +static struct logo_data_extra { + const struct linux_logo *logo; + unsigned int n; +} fb_logo_ex[FB_LOGO_EX_NUM_MAX]; +static unsigned int fb_logo_ex_num; + +void fb_append_extra_logo(const struct linux_logo *logo, unsigned int n) +{ + if (!n || fb_logo_ex_num == FB_LOGO_EX_NUM_MAX) + return; + + fb_logo_ex[fb_logo_ex_num].logo = logo; + fb_logo_ex[fb_logo_ex_num].n = n; + fb_logo_ex_num++; +} + +static int fb_prepare_extra_logos(struct fb_info *info, unsigned int height, + unsigned int yres) +{ + unsigned int i; + + /* FIXME: logo_ex supports only truecolor fb. */ + if (info->fix.visual != FB_VISUAL_TRUECOLOR) + fb_logo_ex_num = 0; + + for (i = 0; i < fb_logo_ex_num; i++) { + height += fb_logo_ex[i].logo->height; + if (height > yres) { + height -= fb_logo_ex[i].logo->height; + fb_logo_ex_num = i; + break; + } + } + return height; +} + +static int fb_show_extra_logos(struct fb_info *info, int y, int rotate) +{ + unsigned int i; + + for (i = 0; i < fb_logo_ex_num; i++) + y += fb_show_logo_line(info, rotate, + fb_logo_ex[i].logo, y, fb_logo_ex[i].n); + + return y; +} + +#else /* !CONFIG_FB_LOGO_EXTRA */ + +static inline int fb_prepare_extra_logos(struct fb_info *info, + unsigned int height, + unsigned int yres) +{ + return height; +} + +static inline int fb_show_extra_logos(struct fb_info *info, int y, int rotate) +{ + return y; +} + +#endif /* CONFIG_FB_LOGO_EXTRA */ + + +int fb_prepare_logo(struct fb_info *info, int rotate) +{ + int depth = fb_get_color_depth(&info->var, &info->fix); + unsigned int yres; + + memset(&fb_logo, 0, sizeof(struct logo_data)); + + if (info->flags & FBINFO_MISC_TILEBLITTING || + info->flags & FBINFO_MODULE) + return 0; + + if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) { + depth = info->var.blue.length; + if (info->var.red.length < depth) + depth = info->var.red.length; + if (info->var.green.length < depth) + depth = info->var.green.length; + } + + if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR && depth > 4) { + /* assume console colormap */ + depth = 4; + } + + if (depth >= 8) { + switch (info->fix.visual) { + case FB_VISUAL_TRUECOLOR: + fb_logo.needs_truepalette = 1; + break; + case FB_VISUAL_DIRECTCOLOR: + fb_logo.needs_directpalette = 1; + fb_logo.needs_cmapreset = 1; + break; + case FB_VISUAL_PSEUDOCOLOR: + fb_logo.needs_cmapreset = 1; + break; + } + } + + /* Return if no suitable logo was found */ + fb_logo.logo = fb_find_logo(depth); + + if (!fb_logo.logo) { + return 0; + } + + if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD) + yres = info->var.yres; + else + yres = info->var.xres; + + if (fb_logo.logo->height > yres) { + fb_logo.logo = NULL; + return 0; + } + + /* What depth we asked for might be different from what we get */ + if (fb_logo.logo->type == LINUX_LOGO_CLUT224) + fb_logo.depth = 8; + else if (fb_logo.logo->type == LINUX_LOGO_VGA16) + fb_logo.depth = 4; + else + fb_logo.depth = 1; + + return fb_prepare_extra_logos(info, fb_logo.logo->height, yres); +} + int fb_show_logo(struct fb_info *info, int rotate) { - return fb_show_logo_line(info, rotate, fb_logo.logo, 0, - num_online_cpus()); + int y; + + y = fb_show_logo_line(info, rotate, fb_logo.logo, 0, + num_online_cpus()); + y = fb_show_extra_logos(info, y, rotate); + + return y; } #else int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; } |