Commit 9c44e5f6 authored by Antonino A. Daplas's avatar Antonino A. Daplas Committed by Linus Torvalds

[PATCH] fbcon: Console Rotation - Add support to rotate the logo

Add support for rotating and positioning of the logo.  Rotation and position
depends on 'int rotate' parameter added to fb_prepare_logo() and
fb_show_logo().
Signed-off-by: default avatarAntonino Daplas <adaplas@pol.net>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent e4fc2761
...@@ -499,6 +499,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, ...@@ -499,6 +499,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
int cols, int rows, int new_cols, int new_rows) int cols, int rows, int new_cols, int new_rows)
{ {
/* Need to make room for the logo */ /* Need to make room for the logo */
struct fbcon_ops *ops = info->fbcon_par;
int cnt, erase = vc->vc_video_erase_char, step; int cnt, erase = vc->vc_video_erase_char, step;
unsigned short *save = NULL, *r, *q; unsigned short *save = NULL, *r, *q;
...@@ -508,7 +509,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, ...@@ -508,7 +509,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
*/ */
if (fb_get_color_depth(&info->var, &info->fix) == 1) if (fb_get_color_depth(&info->var, &info->fix) == 1)
erase &= ~0x400; erase &= ~0x400;
logo_height = fb_prepare_logo(info); logo_height = fb_prepare_logo(info, ops->rotate);
logo_lines = (logo_height + vc->vc_font.height - 1) / logo_lines = (logo_height + vc->vc_font.height - 1) /
vc->vc_font.height; vc->vc_font.height;
q = (unsigned short *) (vc->vc_origin + q = (unsigned short *) (vc->vc_origin +
...@@ -2073,7 +2074,7 @@ static int fbcon_switch(struct vc_data *vc) ...@@ -2073,7 +2074,7 @@ static int fbcon_switch(struct vc_data *vc)
logo_shown = fg_console; logo_shown = fg_console;
/* This is protected above by initmem_freed */ /* This is protected above by initmem_freed */
fb_show_logo(info); fb_show_logo(info, ops->rotate);
update_region(vc, update_region(vc,
vc->vc_origin + vc->vc_size_row * vc->vc_top, vc->vc_origin + vc->vc_size_row * vc->vc_top,
vc->vc_size_row * (vc->vc_bottom - vc->vc_size_row * (vc->vc_bottom -
......
...@@ -323,9 +323,103 @@ static struct logo_data { ...@@ -323,9 +323,103 @@ static struct logo_data {
const struct linux_logo *logo; const struct linux_logo *logo;
} fb_logo; } fb_logo;
int fb_prepare_logo(struct fb_info *info) static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height)
{
u32 size = width * height, i;
out += size - 1;
for (i = size; i--; )
*out-- = *in++;
}
static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height)
{
int i, j, w = width - 1;
for (i = 0; i < height; i++)
for (j = 0; j < width; j++)
out[height * j + w - i] = *in++;
}
static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height)
{
int i, j, w = width - 1;
for (i = 0; i < height; i++)
for (j = 0; j < width; j++)
out[height * (w - j) + i] = *in++;
}
static void fb_rotate_logo(struct fb_info *info, u8 *dst,
struct fb_image *image, int rotate)
{
u32 tmp;
if (rotate == FB_ROTATE_UD) {
image->dx = info->var.xres - image->width;
image->dy = info->var.yres - image->height;
fb_rotate_logo_ud(image->data, dst, image->width,
image->height);
} else if (rotate == FB_ROTATE_CW) {
tmp = image->width;
image->width = image->height;
image->height = tmp;
image->dx = info->var.xres - image->height;
fb_rotate_logo_cw(image->data, dst, image->width,
image->height);
} else if (rotate == FB_ROTATE_CCW) {
tmp = image->width;
image->width = image->height;
image->height = tmp;
image->dy = info->var.yres - image->width;
fb_rotate_logo_ccw(image->data, dst, image->width,
image->height);
}
image->data = dst;
}
static void fb_do_show_logo(struct fb_info *info, struct fb_image *image,
int rotate)
{
int x;
if (rotate == FB_ROTATE_UR) {
for (x = 0; x < num_online_cpus() &&
x * (fb_logo.logo->width + 8) <=
info->var.xres - fb_logo.logo->width; x++) {
info->fbops->fb_imageblit(info, image);
image->dx += fb_logo.logo->width + 8;
}
} else if (rotate == FB_ROTATE_UD) {
for (x = 0; x < num_online_cpus() &&
x * (fb_logo.logo->width + 8) <=
info->var.xres - fb_logo.logo->width; x++) {
info->fbops->fb_imageblit(info, image);
image->dx -= fb_logo.logo->width + 8;
}
} else if (rotate == FB_ROTATE_CW) {
for (x = 0; x < num_online_cpus() &&
x * (fb_logo.logo->width + 8) <=
info->var.yres - fb_logo.logo->width; x++) {
info->fbops->fb_imageblit(info, image);
image->dy += fb_logo.logo->width + 8;
}
} else if (rotate == FB_ROTATE_CCW) {
for (x = 0; x < num_online_cpus() &&
x * (fb_logo.logo->width + 8) <=
info->var.yres - fb_logo.logo->width; x++) {
info->fbops->fb_imageblit(info, image);
image->dy -= fb_logo.logo->width + 8;
}
}
}
int fb_prepare_logo(struct fb_info *info, int rotate)
{ {
int depth = fb_get_color_depth(&info->var, &info->fix); int depth = fb_get_color_depth(&info->var, &info->fix);
int yres;
memset(&fb_logo, 0, sizeof(struct logo_data)); memset(&fb_logo, 0, sizeof(struct logo_data));
...@@ -358,10 +452,16 @@ int fb_prepare_logo(struct fb_info *info) ...@@ -358,10 +452,16 @@ int fb_prepare_logo(struct fb_info *info)
/* Return if no suitable logo was found */ /* Return if no suitable logo was found */
fb_logo.logo = fb_find_logo(depth); fb_logo.logo = fb_find_logo(depth);
if (!fb_logo.logo || fb_logo.logo->height > info->var.yres) { if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD)
yres = info->var.yres;
else
yres = info->var.xres;
if (fb_logo.logo && fb_logo.logo->height > yres) {
fb_logo.logo = NULL; fb_logo.logo = NULL;
return 0; return 0;
} }
/* What depth we asked for might be different from what we get */ /* What depth we asked for might be different from what we get */
if (fb_logo.logo->type == LINUX_LOGO_CLUT224) if (fb_logo.logo->type == LINUX_LOGO_CLUT224)
fb_logo.depth = 8; fb_logo.depth = 8;
...@@ -372,12 +472,11 @@ int fb_prepare_logo(struct fb_info *info) ...@@ -372,12 +472,11 @@ int fb_prepare_logo(struct fb_info *info)
return fb_logo.logo->height; return fb_logo.logo->height;
} }
int fb_show_logo(struct fb_info *info) int fb_show_logo(struct fb_info *info, int rotate)
{ {
u32 *palette = NULL, *saved_pseudo_palette = NULL; u32 *palette = NULL, *saved_pseudo_palette = NULL;
unsigned char *logo_new = NULL; unsigned char *logo_new = NULL, *logo_rotate = NULL;
struct fb_image image; struct fb_image image;
int x;
/* Return if the frame buffer is not mapped or suspended */ /* Return if the frame buffer is not mapped or suspended */
if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING) if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING)
...@@ -417,25 +516,30 @@ int fb_show_logo(struct fb_info *info) ...@@ -417,25 +516,30 @@ int fb_show_logo(struct fb_info *info)
fb_set_logo(info, fb_logo.logo, logo_new, fb_logo.depth); fb_set_logo(info, fb_logo.logo, logo_new, fb_logo.depth);
} }
image.dx = 0;
image.dy = 0;
image.width = fb_logo.logo->width; image.width = fb_logo.logo->width;
image.height = fb_logo.logo->height; image.height = fb_logo.logo->height;
image.dy = 0;
for (x = 0; x < num_online_cpus() * (fb_logo.logo->width + 8) && if (rotate) {
x <= info->var.xres-fb_logo.logo->width; x += (fb_logo.logo->width + 8)) { logo_rotate = kmalloc(fb_logo.logo->width *
image.dx = x; fb_logo.logo->height, GFP_KERNEL);
info->fbops->fb_imageblit(info, &image); if (logo_rotate)
fb_rotate_logo(info, logo_rotate, &image, rotate);
} }
fb_do_show_logo(info, &image, rotate);
kfree(palette); kfree(palette);
if (saved_pseudo_palette != NULL) if (saved_pseudo_palette != NULL)
info->pseudo_palette = saved_pseudo_palette; info->pseudo_palette = saved_pseudo_palette;
kfree(logo_new); kfree(logo_new);
kfree(logo_rotate);
return fb_logo.logo->height; return fb_logo.logo->height;
} }
#else #else
int fb_prepare_logo(struct fb_info *info) { return 0; } int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; }
int fb_show_logo(struct fb_info *info) { return 0; } int fb_show_logo(struct fb_info *info, int rotate) { return 0; }
#endif /* CONFIG_LOGO */ #endif /* CONFIG_LOGO */
static int fbmem_read_proc(char *buf, char **start, off_t offset, static int fbmem_read_proc(char *buf, char **start, off_t offset,
......
...@@ -825,8 +825,8 @@ extern void cfb_imageblit(struct fb_info *info, const struct fb_image *image); ...@@ -825,8 +825,8 @@ extern void cfb_imageblit(struct fb_info *info, const struct fb_image *image);
/* drivers/video/fbmem.c */ /* drivers/video/fbmem.c */
extern int register_framebuffer(struct fb_info *fb_info); extern int register_framebuffer(struct fb_info *fb_info);
extern int unregister_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 int fb_prepare_logo(struct fb_info *fb_info, int rotate);
extern int fb_show_logo(struct fb_info *fb_info); extern int fb_show_logo(struct fb_info *fb_info, int rotate);
extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size); extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size);
extern void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, extern void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx,
u32 height, u32 shift_high, u32 shift_low, u32 mod); u32 height, u32 shift_high, u32 shift_low, u32 mod);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment