diff options
author | Antonino A. Daplas <adaplas@gmail.com> | 2005-11-09 00:39:10 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-09 10:56:34 -0500 |
commit | 9c44e5f6c211a9b7313ded897f3135ef7d9ad3e2 (patch) | |
tree | b4d94144527964a822367e4018693dc4e8a83383 | |
parent | e4fc27618b75234b721c4a13d0e0d9d07e75e641 (diff) |
[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: Antonino Daplas <adaplas@pol.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/video/console/fbcon.c | 5 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 130 | ||||
-rw-r--r-- | include/linux/fb.h | 4 |
3 files changed, 122 insertions, 17 deletions
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index b5d678c73252..26935e231a1d 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -499,6 +499,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, | |||
499 | int cols, int rows, int new_cols, int new_rows) | 499 | int cols, int rows, int new_cols, int new_rows) |
500 | { | 500 | { |
501 | /* Need to make room for the logo */ | 501 | /* Need to make room for the logo */ |
502 | struct fbcon_ops *ops = info->fbcon_par; | ||
502 | int cnt, erase = vc->vc_video_erase_char, step; | 503 | int cnt, erase = vc->vc_video_erase_char, step; |
503 | unsigned short *save = NULL, *r, *q; | 504 | unsigned short *save = NULL, *r, *q; |
504 | 505 | ||
@@ -508,7 +509,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, | |||
508 | */ | 509 | */ |
509 | if (fb_get_color_depth(&info->var, &info->fix) == 1) | 510 | if (fb_get_color_depth(&info->var, &info->fix) == 1) |
510 | erase &= ~0x400; | 511 | erase &= ~0x400; |
511 | logo_height = fb_prepare_logo(info); | 512 | logo_height = fb_prepare_logo(info, ops->rotate); |
512 | logo_lines = (logo_height + vc->vc_font.height - 1) / | 513 | logo_lines = (logo_height + vc->vc_font.height - 1) / |
513 | vc->vc_font.height; | 514 | vc->vc_font.height; |
514 | q = (unsigned short *) (vc->vc_origin + | 515 | q = (unsigned short *) (vc->vc_origin + |
@@ -2073,7 +2074,7 @@ static int fbcon_switch(struct vc_data *vc) | |||
2073 | 2074 | ||
2074 | logo_shown = fg_console; | 2075 | logo_shown = fg_console; |
2075 | /* This is protected above by initmem_freed */ | 2076 | /* This is protected above by initmem_freed */ |
2076 | fb_show_logo(info); | 2077 | fb_show_logo(info, ops->rotate); |
2077 | update_region(vc, | 2078 | update_region(vc, |
2078 | vc->vc_origin + vc->vc_size_row * vc->vc_top, | 2079 | vc->vc_origin + vc->vc_size_row * vc->vc_top, |
2079 | vc->vc_size_row * (vc->vc_bottom - | 2080 | vc->vc_size_row * (vc->vc_bottom - |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index e2667ddab3f1..7a2a8fa50b3b 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -323,9 +323,103 @@ static struct logo_data { | |||
323 | const struct linux_logo *logo; | 323 | const struct linux_logo *logo; |
324 | } fb_logo; | 324 | } fb_logo; |
325 | 325 | ||
326 | int fb_prepare_logo(struct fb_info *info) | 326 | static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height) |
327 | { | ||
328 | u32 size = width * height, i; | ||
329 | |||
330 | out += size - 1; | ||
331 | |||
332 | for (i = size; i--; ) | ||
333 | *out-- = *in++; | ||
334 | } | ||
335 | |||
336 | static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height) | ||
337 | { | ||
338 | int i, j, w = width - 1; | ||
339 | |||
340 | for (i = 0; i < height; i++) | ||
341 | for (j = 0; j < width; j++) | ||
342 | out[height * j + w - i] = *in++; | ||
343 | } | ||
344 | |||
345 | static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height) | ||
346 | { | ||
347 | int i, j, w = width - 1; | ||
348 | |||
349 | for (i = 0; i < height; i++) | ||
350 | for (j = 0; j < width; j++) | ||
351 | out[height * (w - j) + i] = *in++; | ||
352 | } | ||
353 | |||
354 | static void fb_rotate_logo(struct fb_info *info, u8 *dst, | ||
355 | struct fb_image *image, int rotate) | ||
356 | { | ||
357 | u32 tmp; | ||
358 | |||
359 | if (rotate == FB_ROTATE_UD) { | ||
360 | image->dx = info->var.xres - image->width; | ||
361 | image->dy = info->var.yres - image->height; | ||
362 | fb_rotate_logo_ud(image->data, dst, image->width, | ||
363 | image->height); | ||
364 | } else if (rotate == FB_ROTATE_CW) { | ||
365 | tmp = image->width; | ||
366 | image->width = image->height; | ||
367 | image->height = tmp; | ||
368 | image->dx = info->var.xres - image->height; | ||
369 | fb_rotate_logo_cw(image->data, dst, image->width, | ||
370 | image->height); | ||
371 | } else if (rotate == FB_ROTATE_CCW) { | ||
372 | tmp = image->width; | ||
373 | image->width = image->height; | ||
374 | image->height = tmp; | ||
375 | image->dy = info->var.yres - image->width; | ||
376 | fb_rotate_logo_ccw(image->data, dst, image->width, | ||
377 | image->height); | ||
378 | } | ||
379 | |||
380 | image->data = dst; | ||
381 | } | ||
382 | |||
383 | static void fb_do_show_logo(struct fb_info *info, struct fb_image *image, | ||
384 | int rotate) | ||
385 | { | ||
386 | int x; | ||
387 | |||
388 | if (rotate == FB_ROTATE_UR) { | ||
389 | for (x = 0; x < num_online_cpus() && | ||
390 | x * (fb_logo.logo->width + 8) <= | ||
391 | info->var.xres - fb_logo.logo->width; x++) { | ||
392 | info->fbops->fb_imageblit(info, image); | ||
393 | image->dx += fb_logo.logo->width + 8; | ||
394 | } | ||
395 | } else if (rotate == FB_ROTATE_UD) { | ||
396 | for (x = 0; x < num_online_cpus() && | ||
397 | x * (fb_logo.logo->width + 8) <= | ||
398 | info->var.xres - fb_logo.logo->width; x++) { | ||
399 | info->fbops->fb_imageblit(info, image); | ||
400 | image->dx -= fb_logo.logo->width + 8; | ||
401 | } | ||
402 | } else if (rotate == FB_ROTATE_CW) { | ||
403 | for (x = 0; x < num_online_cpus() && | ||
404 | x * (fb_logo.logo->width + 8) <= | ||
405 | info->var.yres - fb_logo.logo->width; x++) { | ||
406 | info->fbops->fb_imageblit(info, image); | ||
407 | image->dy += fb_logo.logo->width + 8; | ||
408 | } | ||
409 | } else if (rotate == FB_ROTATE_CCW) { | ||
410 | for (x = 0; x < num_online_cpus() && | ||
411 | x * (fb_logo.logo->width + 8) <= | ||
412 | info->var.yres - fb_logo.logo->width; x++) { | ||
413 | info->fbops->fb_imageblit(info, image); | ||
414 | image->dy -= fb_logo.logo->width + 8; | ||
415 | } | ||
416 | } | ||
417 | } | ||
418 | |||
419 | int fb_prepare_logo(struct fb_info *info, int rotate) | ||
327 | { | 420 | { |
328 | int depth = fb_get_color_depth(&info->var, &info->fix); | 421 | int depth = fb_get_color_depth(&info->var, &info->fix); |
422 | int yres; | ||
329 | 423 | ||
330 | memset(&fb_logo, 0, sizeof(struct logo_data)); | 424 | memset(&fb_logo, 0, sizeof(struct logo_data)); |
331 | 425 | ||
@@ -358,10 +452,16 @@ int fb_prepare_logo(struct fb_info *info) | |||
358 | /* Return if no suitable logo was found */ | 452 | /* Return if no suitable logo was found */ |
359 | fb_logo.logo = fb_find_logo(depth); | 453 | fb_logo.logo = fb_find_logo(depth); |
360 | 454 | ||
361 | if (!fb_logo.logo || fb_logo.logo->height > info->var.yres) { | 455 | if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD) |
456 | yres = info->var.yres; | ||
457 | else | ||
458 | yres = info->var.xres; | ||
459 | |||
460 | if (fb_logo.logo && fb_logo.logo->height > yres) { | ||
362 | fb_logo.logo = NULL; | 461 | fb_logo.logo = NULL; |
363 | return 0; | 462 | return 0; |
364 | } | 463 | } |
464 | |||
365 | /* What depth we asked for might be different from what we get */ | 465 | /* What depth we asked for might be different from what we get */ |
366 | if (fb_logo.logo->type == LINUX_LOGO_CLUT224) | 466 | if (fb_logo.logo->type == LINUX_LOGO_CLUT224) |
367 | fb_logo.depth = 8; | 467 | fb_logo.depth = 8; |
@@ -372,12 +472,11 @@ int fb_prepare_logo(struct fb_info *info) | |||
372 | return fb_logo.logo->height; | 472 | return fb_logo.logo->height; |
373 | } | 473 | } |
374 | 474 | ||
375 | int fb_show_logo(struct fb_info *info) | 475 | int fb_show_logo(struct fb_info *info, int rotate) |
376 | { | 476 | { |
377 | u32 *palette = NULL, *saved_pseudo_palette = NULL; | 477 | u32 *palette = NULL, *saved_pseudo_palette = NULL; |
378 | unsigned char *logo_new = NULL; | 478 | unsigned char *logo_new = NULL, *logo_rotate = NULL; |
379 | struct fb_image image; | 479 | struct fb_image image; |
380 | int x; | ||
381 | 480 | ||
382 | /* Return if the frame buffer is not mapped or suspended */ | 481 | /* Return if the frame buffer is not mapped or suspended */ |
383 | if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING) | 482 | if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING) |
@@ -417,25 +516,30 @@ int fb_show_logo(struct fb_info *info) | |||
417 | fb_set_logo(info, fb_logo.logo, logo_new, fb_logo.depth); | 516 | fb_set_logo(info, fb_logo.logo, logo_new, fb_logo.depth); |
418 | } | 517 | } |
419 | 518 | ||
519 | image.dx = 0; | ||
520 | image.dy = 0; | ||
420 | image.width = fb_logo.logo->width; | 521 | image.width = fb_logo.logo->width; |
421 | image.height = fb_logo.logo->height; | 522 | image.height = fb_logo.logo->height; |
422 | image.dy = 0; | ||
423 | 523 | ||
424 | for (x = 0; x < num_online_cpus() * (fb_logo.logo->width + 8) && | 524 | if (rotate) { |
425 | x <= info->var.xres-fb_logo.logo->width; x += (fb_logo.logo->width + 8)) { | 525 | logo_rotate = kmalloc(fb_logo.logo->width * |
426 | image.dx = x; | 526 | fb_logo.logo->height, GFP_KERNEL); |
427 | info->fbops->fb_imageblit(info, &image); | 527 | if (logo_rotate) |
528 | fb_rotate_logo(info, logo_rotate, &image, rotate); | ||
428 | } | 529 | } |
429 | 530 | ||
531 | fb_do_show_logo(info, &image, rotate); | ||
532 | |||
430 | kfree(palette); | 533 | kfree(palette); |
431 | if (saved_pseudo_palette != NULL) | 534 | if (saved_pseudo_palette != NULL) |
432 | info->pseudo_palette = saved_pseudo_palette; | 535 | info->pseudo_palette = saved_pseudo_palette; |
433 | kfree(logo_new); | 536 | kfree(logo_new); |
537 | kfree(logo_rotate); | ||
434 | return fb_logo.logo->height; | 538 | return fb_logo.logo->height; |
435 | } | 539 | } |
436 | #else | 540 | #else |
437 | int fb_prepare_logo(struct fb_info *info) { return 0; } | 541 | int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; } |
438 | int fb_show_logo(struct fb_info *info) { return 0; } | 542 | int fb_show_logo(struct fb_info *info, int rotate) { return 0; } |
439 | #endif /* CONFIG_LOGO */ | 543 | #endif /* CONFIG_LOGO */ |
440 | 544 | ||
441 | static int fbmem_read_proc(char *buf, char **start, off_t offset, | 545 | static int fbmem_read_proc(char *buf, char **start, off_t offset, |
diff --git a/include/linux/fb.h b/include/linux/fb.h index 51791dc5d4dc..357dd3a0a01e 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h | |||
@@ -825,8 +825,8 @@ extern void cfb_imageblit(struct fb_info *info, const struct fb_image *image); | |||
825 | /* drivers/video/fbmem.c */ | 825 | /* drivers/video/fbmem.c */ |
826 | extern int register_framebuffer(struct fb_info *fb_info); | 826 | extern int register_framebuffer(struct fb_info *fb_info); |
827 | extern int unregister_framebuffer(struct fb_info *fb_info); | 827 | extern int unregister_framebuffer(struct fb_info *fb_info); |
828 | extern int fb_prepare_logo(struct fb_info *fb_info); | 828 | extern int fb_prepare_logo(struct fb_info *fb_info, int rotate); |
829 | extern int fb_show_logo(struct fb_info *fb_info); | 829 | extern int fb_show_logo(struct fb_info *fb_info, int rotate); |
830 | extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size); | 830 | extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size); |
831 | extern void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, | 831 | extern void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, |
832 | u32 height, u32 shift_high, u32 shift_low, u32 mod); | 832 | u32 height, u32 shift_high, u32 shift_low, u32 mod); |