aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/console/fbcon.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/console/fbcon.c')
-rw-r--r--drivers/video/console/fbcon.c136
1 files changed, 109 insertions, 27 deletions
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 0429fd2cece0..73813c60d03a 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -107,7 +107,9 @@ static struct display fb_display[MAX_NR_CONSOLES];
107 107
108static signed char con2fb_map[MAX_NR_CONSOLES]; 108static signed char con2fb_map[MAX_NR_CONSOLES];
109static signed char con2fb_map_boot[MAX_NR_CONSOLES]; 109static signed char con2fb_map_boot[MAX_NR_CONSOLES];
110#ifndef MODULE
110static int logo_height; 111static int logo_height;
112#endif
111static int logo_lines; 113static int logo_lines;
112/* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO 114/* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO
113 enums. */ 115 enums. */
@@ -576,6 +578,13 @@ static int fbcon_takeover(int show_logo)
576 return err; 578 return err;
577} 579}
578 580
581#ifdef MODULE
582static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
583 int cols, int rows, int new_cols, int new_rows)
584{
585 logo_shown = FBCON_LOGO_DONTSHOW;
586}
587#else
579static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, 588static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
580 int cols, int rows, int new_cols, int new_rows) 589 int cols, int rows, int new_cols, int new_rows)
581{ 590{
@@ -584,6 +593,11 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
584 int cnt, erase = vc->vc_video_erase_char, step; 593 int cnt, erase = vc->vc_video_erase_char, step;
585 unsigned short *save = NULL, *r, *q; 594 unsigned short *save = NULL, *r, *q;
586 595
596 if (info->flags & FBINFO_MODULE) {
597 logo_shown = FBCON_LOGO_DONTSHOW;
598 return;
599 }
600
587 /* 601 /*
588 * remove underline attribute from erase character 602 * remove underline attribute from erase character
589 * if black and white framebuffer. 603 * if black and white framebuffer.
@@ -618,8 +632,13 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
618 r -= cols; 632 r -= cols;
619 } 633 }
620 if (!save) { 634 if (!save) {
621 vc->vc_y += logo_lines; 635 int lines;
622 vc->vc_pos += logo_lines * vc->vc_size_row; 636 if (vc->vc_y + logo_lines >= rows)
637 lines = rows - vc->vc_y - 1;
638 else
639 lines = logo_lines;
640 vc->vc_y += lines;
641 vc->vc_pos += lines * vc->vc_size_row;
623 } 642 }
624 } 643 }
625 scr_memsetw((unsigned short *) vc->vc_origin, 644 scr_memsetw((unsigned short *) vc->vc_origin,
@@ -650,6 +669,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
650 vc->vc_top = logo_lines; 669 vc->vc_top = logo_lines;
651 } 670 }
652} 671}
672#endif /* MODULE */
653 673
654#ifdef CONFIG_FB_TILEBLITTING 674#ifdef CONFIG_FB_TILEBLITTING
655static void set_blitting_type(struct vc_data *vc, struct fb_info *info) 675static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
@@ -665,6 +685,17 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
665 fbcon_set_bitops(ops); 685 fbcon_set_bitops(ops);
666 } 686 }
667} 687}
688
689static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount)
690{
691 int err = 0;
692
693 if (info->flags & FBINFO_MISC_TILEBLITTING &&
694 info->tileops->fb_get_tilemax(info) < charcount)
695 err = 1;
696
697 return err;
698}
668#else 699#else
669static void set_blitting_type(struct vc_data *vc, struct fb_info *info) 700static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
670{ 701{
@@ -675,6 +706,12 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
675 fbcon_set_rotation(info); 706 fbcon_set_rotation(info);
676 fbcon_set_bitops(ops); 707 fbcon_set_bitops(ops);
677} 708}
709
710static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount)
711{
712 return 0;
713}
714
678#endif /* CONFIG_MISC_TILEBLITTING */ 715#endif /* CONFIG_MISC_TILEBLITTING */
679 716
680 717
@@ -968,7 +1005,9 @@ static const char *fbcon_startup(void)
968 if (!p->fontdata) { 1005 if (!p->fontdata) {
969 if (!fontname[0] || !(font = find_font(fontname))) 1006 if (!fontname[0] || !(font = find_font(fontname)))
970 font = get_default_font(info->var.xres, 1007 font = get_default_font(info->var.xres,
971 info->var.yres); 1008 info->var.yres,
1009 info->pixmap.blit_x,
1010 info->pixmap.blit_y);
972 vc->vc_font.width = font->width; 1011 vc->vc_font.width = font->width;
973 vc->vc_font.height = font->height; 1012 vc->vc_font.height = font->height;
974 vc->vc_font.data = (void *)(p->fontdata = font->data); 1013 vc->vc_font.data = (void *)(p->fontdata = font->data);
@@ -1088,7 +1127,9 @@ static void fbcon_init(struct vc_data *vc, int init)
1088 1127
1089 if (!fontname[0] || !(font = find_font(fontname))) 1128 if (!fontname[0] || !(font = find_font(fontname)))
1090 font = get_default_font(info->var.xres, 1129 font = get_default_font(info->var.xres,
1091 info->var.yres); 1130 info->var.yres,
1131 info->pixmap.blit_x,
1132 info->pixmap.blit_y);
1092 vc->vc_font.width = font->width; 1133 vc->vc_font.width = font->width;
1093 vc->vc_font.height = font->height; 1134 vc->vc_font.height = font->height;
1094 vc->vc_font.data = (void *)(p->fontdata = font->data); 1135 vc->vc_font.data = (void *)(p->fontdata = font->data);
@@ -1305,7 +1346,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
1305 int y; 1346 int y;
1306 int c = scr_readw((u16 *) vc->vc_pos); 1347 int c = scr_readw((u16 *) vc->vc_pos);
1307 1348
1308 if (fbcon_is_inactive(vc, info)) 1349 if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1)
1309 return; 1350 return;
1310 1351
1311 ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1; 1352 ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
@@ -2475,6 +2516,7 @@ static int fbcon_copy_font(struct vc_data *vc, int con)
2475 2516
2476static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigned flags) 2517static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigned flags)
2477{ 2518{
2519 struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
2478 unsigned charcount = font->charcount; 2520 unsigned charcount = font->charcount;
2479 int w = font->width; 2521 int w = font->width;
2480 int h = font->height; 2522 int h = font->height;
@@ -2488,6 +2530,15 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne
2488 if (charcount != 256 && charcount != 512) 2530 if (charcount != 256 && charcount != 512)
2489 return -EINVAL; 2531 return -EINVAL;
2490 2532
2533 /* Make sure drawing engine can handle the font */
2534 if (!(info->pixmap.blit_x & (1 << (font->width - 1))) ||
2535 !(info->pixmap.blit_y & (1 << (font->height - 1))))
2536 return -EINVAL;
2537
2538 /* Make sure driver can handle the font length */
2539 if (fbcon_invalid_charcount(info, charcount))
2540 return -EINVAL;
2541
2491 size = h * pitch * charcount; 2542 size = h * pitch * charcount;
2492 2543
2493 new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, GFP_USER); 2544 new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, GFP_USER);
@@ -2532,7 +2583,8 @@ static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, cha
2532 const struct font_desc *f; 2583 const struct font_desc *f;
2533 2584
2534 if (!name) 2585 if (!name)
2535 f = get_default_font(info->var.xres, info->var.yres); 2586 f = get_default_font(info->var.xres, info->var.yres,
2587 info->pixmap.blit_x, info->pixmap.blit_y);
2536 else if (!(f = find_font(name))) 2588 else if (!(f = find_font(name)))
2537 return -ENOENT; 2589 return -ENOENT;
2538 2590
@@ -2829,7 +2881,7 @@ static void fbcon_set_all_vcs(struct fb_info *info)
2829 struct fbcon_ops *ops = info->fbcon_par; 2881 struct fbcon_ops *ops = info->fbcon_par;
2830 struct vc_data *vc; 2882 struct vc_data *vc;
2831 struct display *p; 2883 struct display *p;
2832 int i, rows, cols; 2884 int i, rows, cols, fg = -1;
2833 2885
2834 if (!ops || ops->currcon < 0) 2886 if (!ops || ops->currcon < 0)
2835 return; 2887 return;
@@ -2840,34 +2892,23 @@ static void fbcon_set_all_vcs(struct fb_info *info)
2840 registered_fb[con2fb_map[i]] != info) 2892 registered_fb[con2fb_map[i]] != info)
2841 continue; 2893 continue;
2842 2894
2895 if (CON_IS_VISIBLE(vc)) {
2896 fg = i;
2897 continue;
2898 }
2899
2843 p = &fb_display[vc->vc_num]; 2900 p = &fb_display[vc->vc_num];
2844 set_blitting_type(vc, info); 2901 set_blitting_type(vc, info);
2845 var_to_display(p, &info->var, info); 2902 var_to_display(p, &info->var, info);
2846 cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); 2903 cols = FBCON_SWAP(p->rotate, info->var.xres, info->var.yres);
2847 rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); 2904 rows = FBCON_SWAP(p->rotate, info->var.yres, info->var.xres);
2848 cols /= vc->vc_font.width; 2905 cols /= vc->vc_font.width;
2849 rows /= vc->vc_font.height; 2906 rows /= vc->vc_font.height;
2850 vc_resize(vc, cols, rows); 2907 vc_resize(vc, cols, rows);
2851
2852 if (CON_IS_VISIBLE(vc)) {
2853 updatescrollmode(p, info, vc);
2854 scrollback_max = 0;
2855 scrollback_current = 0;
2856
2857 if (!fbcon_is_inactive(vc, info)) {
2858 ops->var.xoffset = ops->var.yoffset =
2859 p->yscroll = 0;
2860 ops->update_start(info);
2861 }
2862
2863 fbcon_set_palette(vc, color_table);
2864 update_screen(vc);
2865 if (softback_buf)
2866 fbcon_update_softback(vc);
2867 }
2868 } 2908 }
2869 2909
2870 ops->p = &fb_display[ops->currcon]; 2910 if (fg != -1)
2911 fbcon_modechanged(info);
2871} 2912}
2872 2913
2873static int fbcon_mode_deleted(struct fb_info *info, 2914static int fbcon_mode_deleted(struct fb_info *info,
@@ -3002,6 +3043,42 @@ static void fbcon_new_modelist(struct fb_info *info)
3002 } 3043 }
3003} 3044}
3004 3045
3046static void fbcon_get_requirement(struct fb_info *info,
3047 struct fb_blit_caps *caps)
3048{
3049 struct vc_data *vc;
3050 struct display *p;
3051
3052 if (caps->flags) {
3053 int i, charcnt;
3054
3055 for (i = first_fb_vc; i <= last_fb_vc; i++) {
3056 vc = vc_cons[i].d;
3057 if (vc && vc->vc_mode == KD_TEXT &&
3058 info->node == con2fb_map[i]) {
3059 p = &fb_display[i];
3060 caps->x |= 1 << (vc->vc_font.width - 1);
3061 caps->y |= 1 << (vc->vc_font.height - 1);
3062 charcnt = (p->userfont) ?
3063 FNTCHARCNT(p->fontdata) : 256;
3064 if (caps->len < charcnt)
3065 caps->len = charcnt;
3066 }
3067 }
3068 } else {
3069 vc = vc_cons[fg_console].d;
3070
3071 if (vc && vc->vc_mode == KD_TEXT &&
3072 info->node == con2fb_map[fg_console]) {
3073 p = &fb_display[fg_console];
3074 caps->x = 1 << (vc->vc_font.width - 1);
3075 caps->y = 1 << (vc->vc_font.height - 1);
3076 caps->len = (p->userfont) ?
3077 FNTCHARCNT(p->fontdata) : 256;
3078 }
3079 }
3080}
3081
3005static int fbcon_event_notify(struct notifier_block *self, 3082static int fbcon_event_notify(struct notifier_block *self,
3006 unsigned long action, void *data) 3083 unsigned long action, void *data)
3007{ 3084{
@@ -3009,6 +3086,7 @@ static int fbcon_event_notify(struct notifier_block *self,
3009 struct fb_info *info = event->info; 3086 struct fb_info *info = event->info;
3010 struct fb_videomode *mode; 3087 struct fb_videomode *mode;
3011 struct fb_con2fbmap *con2fb; 3088 struct fb_con2fbmap *con2fb;
3089 struct fb_blit_caps *caps;
3012 int ret = 0; 3090 int ret = 0;
3013 3091
3014 /* 3092 /*
@@ -3057,6 +3135,10 @@ static int fbcon_event_notify(struct notifier_block *self,
3057 case FB_EVENT_NEW_MODELIST: 3135 case FB_EVENT_NEW_MODELIST:
3058 fbcon_new_modelist(info); 3136 fbcon_new_modelist(info);
3059 break; 3137 break;
3138 case FB_EVENT_GET_REQ:
3139 caps = event->data;
3140 fbcon_get_requirement(info, caps);
3141 break;
3060 } 3142 }
3061 3143
3062done: 3144done: