aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/fbmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/fbmem.c')
-rw-r--r--drivers/video/fbmem.c212
1 files changed, 143 insertions, 69 deletions
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 717684bde486..215ac579f901 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,
404 } 404 }
405} 405}
406 406
407int fb_prepare_logo(struct fb_info *info, int rotate)
408{
409 int depth = fb_get_color_depth(&info->var, &info->fix);
410 int yres;
411
412 memset(&fb_logo, 0, sizeof(struct logo_data));
413
414 if (info->flags & FBINFO_MISC_TILEBLITTING ||
415 info->flags & FBINFO_MODULE)
416 return 0;
417
418 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
419 depth = info->var.blue.length;
420 if (info->var.red.length < depth)
421 depth = info->var.red.length;
422 if (info->var.green.length < depth)
423 depth = info->var.green.length;
424 }
425
426 if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR && depth > 4) {
427 /* assume console colormap */
428 depth = 4;
429 }
430
431 if (depth >= 8) {
432 switch (info->fix.visual) {
433 case FB_VISUAL_TRUECOLOR:
434 fb_logo.needs_truepalette = 1;
435 break;
436 case FB_VISUAL_DIRECTCOLOR:
437 fb_logo.needs_directpalette = 1;
438 fb_logo.needs_cmapreset = 1;
439 break;
440 case FB_VISUAL_PSEUDOCOLOR:
441 fb_logo.needs_cmapreset = 1;
442 break;
443 }
444 }
445
446 /* Return if no suitable logo was found */
447 fb_logo.logo = fb_find_logo(depth);
448
449 if (!fb_logo.logo) {
450 return 0;
451 }
452
453 if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD)
454 yres = info->var.yres;
455 else
456 yres = info->var.xres;
457
458 if (fb_logo.logo->height > yres) {
459 fb_logo.logo = NULL;
460 return 0;
461 }
462
463 /* What depth we asked for might be different from what we get */
464 if (fb_logo.logo->type == LINUX_LOGO_CLUT224)
465 fb_logo.depth = 8;
466 else if (fb_logo.logo->type == LINUX_LOGO_VGA16)
467 fb_logo.depth = 4;
468 else
469 fb_logo.depth = 1;
470 return fb_logo.logo->height;
471}
472
473static int fb_show_logo_line(struct fb_info *info, int rotate, 407static int fb_show_logo_line(struct fb_info *info, int rotate,
474 const struct linux_logo *logo, int y, 408 const struct linux_logo *logo, int y,
475 unsigned int n) 409 unsigned int n)
@@ -489,7 +423,7 @@ static int fb_show_logo_line(struct fb_info *info, int rotate,
489 if (fb_logo.needs_cmapreset) 423 if (fb_logo.needs_cmapreset)
490 fb_set_logocmap(info, logo); 424 fb_set_logocmap(info, logo);
491 425
492 if (fb_logo.needs_truepalette || 426 if (fb_logo.needs_truepalette ||
493 fb_logo.needs_directpalette) { 427 fb_logo.needs_directpalette) {
494 palette = kmalloc(256 * 4, GFP_KERNEL); 428 palette = kmalloc(256 * 4, GFP_KERNEL);
495 if (palette == NULL) 429 if (palette == NULL)
@@ -538,10 +472,150 @@ static int fb_show_logo_line(struct fb_info *info, int rotate,
538 return logo->height; 472 return logo->height;
539} 473}
540 474
475
476#ifdef CONFIG_FB_LOGO_EXTRA
477
478#define FB_LOGO_EX_NUM_MAX 10
479static struct logo_data_extra {
480 const struct linux_logo *logo;
481 unsigned int n;
482} fb_logo_ex[FB_LOGO_EX_NUM_MAX];
483static unsigned int fb_logo_ex_num;
484
485void fb_append_extra_logo(const struct linux_logo *logo, unsigned int n)
486{
487 if (!n || fb_logo_ex_num == FB_LOGO_EX_NUM_MAX)
488 return;
489
490 fb_logo_ex[fb_logo_ex_num].logo = logo;
491 fb_logo_ex[fb_logo_ex_num].n = n;
492 fb_logo_ex_num++;
493}
494
495static int fb_prepare_extra_logos(struct fb_info *info, unsigned int height,
496 unsigned int yres)
497{
498 unsigned int i;
499
500 /* FIXME: logo_ex supports only truecolor fb. */
501 if (info->fix.visual != FB_VISUAL_TRUECOLOR)
502 fb_logo_ex_num = 0;
503
504 for (i = 0; i < fb_logo_ex_num; i++) {
505 height += fb_logo_ex[i].logo->height;
506 if (height > yres) {
507 height -= fb_logo_ex[i].logo->height;
508 fb_logo_ex_num = i;
509 break;
510 }
511 }
512 return height;
513}
514
515static int fb_show_extra_logos(struct fb_info *info, int y, int rotate)
516{
517 unsigned int i;
518
519 for (i = 0; i < fb_logo_ex_num; i++)
520 y += fb_show_logo_line(info, rotate,
521 fb_logo_ex[i].logo, y, fb_logo_ex[i].n);
522
523 return y;
524}
525
526#else /* !CONFIG_FB_LOGO_EXTRA */
527
528static inline int fb_prepare_extra_logos(struct fb_info *info,
529 unsigned int height,
530 unsigned int yres)
531{
532 return height;
533}
534
535static inline int fb_show_extra_logos(struct fb_info *info, int y, int rotate)
536{
537 return y;
538}
539
540#endif /* CONFIG_FB_LOGO_EXTRA */
541
542
543int fb_prepare_logo(struct fb_info *info, int rotate)
544{
545 int depth = fb_get_color_depth(&info->var, &info->fix);
546 unsigned int yres;
547
548 memset(&fb_logo, 0, sizeof(struct logo_data));
549
550 if (info->flags & FBINFO_MISC_TILEBLITTING ||
551 info->flags & FBINFO_MODULE)
552 return 0;
553
554 if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
555 depth = info->var.blue.length;
556 if (info->var.red.length < depth)
557 depth = info->var.red.length;
558 if (info->var.green.length < depth)
559 depth = info->var.green.length;
560 }
561
562 if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR && depth > 4) {
563 /* assume console colormap */
564 depth = 4;
565 }
566
567 if (depth >= 8) {
568 switch (info->fix.visual) {
569 case FB_VISUAL_TRUECOLOR:
570 fb_logo.needs_truepalette = 1;
571 break;
572 case FB_VISUAL_DIRECTCOLOR:
573 fb_logo.needs_directpalette = 1;
574 fb_logo.needs_cmapreset = 1;
575 break;
576 case FB_VISUAL_PSEUDOCOLOR:
577 fb_logo.needs_cmapreset = 1;
578 break;
579 }
580 }
581
582 /* Return if no suitable logo was found */
583 fb_logo.logo = fb_find_logo(depth);
584
585 if (!fb_logo.logo) {
586 return 0;
587 }
588
589 if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD)
590 yres = info->var.yres;
591 else
592 yres = info->var.xres;
593
594 if (fb_logo.logo->height > yres) {
595 fb_logo.logo = NULL;
596 return 0;
597 }
598
599 /* What depth we asked for might be different from what we get */
600 if (fb_logo.logo->type == LINUX_LOGO_CLUT224)
601 fb_logo.depth = 8;
602 else if (fb_logo.logo->type == LINUX_LOGO_VGA16)
603 fb_logo.depth = 4;
604 else
605 fb_logo.depth = 1;
606
607 return fb_prepare_extra_logos(info, fb_logo.logo->height, yres);
608}
609
541int fb_show_logo(struct fb_info *info, int rotate) 610int fb_show_logo(struct fb_info *info, int rotate)
542{ 611{
543 return fb_show_logo_line(info, rotate, fb_logo.logo, 0, 612 int y;
544 num_online_cpus()); 613
614 y = fb_show_logo_line(info, rotate, fb_logo.logo, 0,
615 num_online_cpus());
616 y = fb_show_extra_logos(info, y, rotate);
617
618 return y;
545} 619}
546#else 620#else
547int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; } 621int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; }