]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/video/console/fbcon.c
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mfashe...
[linux-2.6-omap-h63xx.git] / drivers / video / console / fbcon.c
index c8b4ae6d7efe70cb25d6fdfcde893a1fad176011..73813c60d03a9c010597c35a3960216005fe9ea2 100644 (file)
@@ -685,6 +685,17 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
                fbcon_set_bitops(ops);
        }
 }
+
+static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount)
+{
+       int err = 0;
+
+       if (info->flags & FBINFO_MISC_TILEBLITTING &&
+           info->tileops->fb_get_tilemax(info) < charcount)
+               err = 1;
+
+       return err;
+}
 #else
 static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
 {
@@ -695,6 +706,12 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
        fbcon_set_rotation(info);
        fbcon_set_bitops(ops);
 }
+
+static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount)
+{
+       return 0;
+}
+
 #endif /* CONFIG_MISC_TILEBLITTING */
 
 
@@ -988,7 +1005,9 @@ static const char *fbcon_startup(void)
        if (!p->fontdata) {
                if (!fontname[0] || !(font = find_font(fontname)))
                        font = get_default_font(info->var.xres,
-                                               info->var.yres);
+                                               info->var.yres,
+                                               info->pixmap.blit_x,
+                                               info->pixmap.blit_y);
                vc->vc_font.width = font->width;
                vc->vc_font.height = font->height;
                vc->vc_font.data = (void *)(p->fontdata = font->data);
@@ -1108,7 +1127,9 @@ static void fbcon_init(struct vc_data *vc, int init)
 
                        if (!fontname[0] || !(font = find_font(fontname)))
                                font = get_default_font(info->var.xres,
-                                                       info->var.yres);
+                                                       info->var.yres,
+                                                       info->pixmap.blit_x,
+                                                       info->pixmap.blit_y);
                        vc->vc_font.width = font->width;
                        vc->vc_font.height = font->height;
                        vc->vc_font.data = (void *)(p->fontdata = font->data);
@@ -2495,6 +2516,7 @@ static int fbcon_copy_font(struct vc_data *vc, int con)
 
 static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigned flags)
 {
+       struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
        unsigned charcount = font->charcount;
        int w = font->width;
        int h = font->height;
@@ -2508,6 +2530,15 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne
        if (charcount != 256 && charcount != 512)
                return -EINVAL;
 
+       /* Make sure drawing engine can handle the font */
+       if (!(info->pixmap.blit_x & (1 << (font->width - 1))) ||
+           !(info->pixmap.blit_y & (1 << (font->height - 1))))
+               return -EINVAL;
+
+       /* Make sure driver can handle the font length */
+       if (fbcon_invalid_charcount(info, charcount))
+               return -EINVAL;
+
        size = h * pitch * charcount;
 
        new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, GFP_USER);
@@ -2552,7 +2583,8 @@ static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, cha
        const struct font_desc *f;
 
        if (!name)
-               f = get_default_font(info->var.xres, info->var.yres);
+               f = get_default_font(info->var.xres, info->var.yres,
+                                    info->pixmap.blit_x, info->pixmap.blit_y);
        else if (!(f = find_font(name)))
                return -ENOENT;
 
@@ -2849,7 +2881,7 @@ static void fbcon_set_all_vcs(struct fb_info *info)
        struct fbcon_ops *ops = info->fbcon_par;
        struct vc_data *vc;
        struct display *p;
-       int i, rows, cols;
+       int i, rows, cols, fg = -1;
 
        if (!ops || ops->currcon < 0)
                return;
@@ -2860,34 +2892,23 @@ static void fbcon_set_all_vcs(struct fb_info *info)
                    registered_fb[con2fb_map[i]] != info)
                        continue;
 
+               if (CON_IS_VISIBLE(vc)) {
+                       fg = i;
+                       continue;
+               }
+
                p = &fb_display[vc->vc_num];
                set_blitting_type(vc, info);
                var_to_display(p, &info->var, info);
-               cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
-               rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
+               cols = FBCON_SWAP(p->rotate, info->var.xres, info->var.yres);
+               rows = FBCON_SWAP(p->rotate, info->var.yres, info->var.xres);
                cols /= vc->vc_font.width;
                rows /= vc->vc_font.height;
                vc_resize(vc, cols, rows);
-
-               if (CON_IS_VISIBLE(vc)) {
-                       updatescrollmode(p, info, vc);
-                       scrollback_max = 0;
-                       scrollback_current = 0;
-
-                       if (!fbcon_is_inactive(vc, info)) {
-                           ops->var.xoffset = ops->var.yoffset =
-                               p->yscroll = 0;
-                           ops->update_start(info);
-                       }
-
-                       fbcon_set_palette(vc, color_table);
-                       update_screen(vc);
-                       if (softback_buf)
-                               fbcon_update_softback(vc);
-               }
        }
 
-       ops->p = &fb_display[ops->currcon];
+       if (fg != -1)
+               fbcon_modechanged(info);
 }
 
 static int fbcon_mode_deleted(struct fb_info *info,
@@ -3022,6 +3043,42 @@ static void fbcon_new_modelist(struct fb_info *info)
        }
 }
 
+static void fbcon_get_requirement(struct fb_info *info,
+                                 struct fb_blit_caps *caps)
+{
+       struct vc_data *vc;
+       struct display *p;
+
+       if (caps->flags) {
+               int i, charcnt;
+
+               for (i = first_fb_vc; i <= last_fb_vc; i++) {
+                       vc = vc_cons[i].d;
+                       if (vc && vc->vc_mode == KD_TEXT &&
+                           info->node == con2fb_map[i]) {
+                               p = &fb_display[i];
+                               caps->x |= 1 << (vc->vc_font.width - 1);
+                               caps->y |= 1 << (vc->vc_font.height - 1);
+                               charcnt = (p->userfont) ?
+                                       FNTCHARCNT(p->fontdata) : 256;
+                               if (caps->len < charcnt)
+                                       caps->len = charcnt;
+                       }
+               }
+       } else {
+               vc = vc_cons[fg_console].d;
+
+               if (vc && vc->vc_mode == KD_TEXT &&
+                   info->node == con2fb_map[fg_console]) {
+                       p = &fb_display[fg_console];
+                       caps->x = 1 << (vc->vc_font.width - 1);
+                       caps->y = 1 << (vc->vc_font.height - 1);
+                       caps->len = (p->userfont) ?
+                               FNTCHARCNT(p->fontdata) : 256;
+               }
+       }
+}
+
 static int fbcon_event_notify(struct notifier_block *self, 
                              unsigned long action, void *data)
 {
@@ -3029,6 +3086,7 @@ static int fbcon_event_notify(struct notifier_block *self,
        struct fb_info *info = event->info;
        struct fb_videomode *mode;
        struct fb_con2fbmap *con2fb;
+       struct fb_blit_caps *caps;
        int ret = 0;
 
        /*
@@ -3077,6 +3135,10 @@ static int fbcon_event_notify(struct notifier_block *self,
        case FB_EVENT_NEW_MODELIST:
                fbcon_new_modelist(info);
                break;
+       case FB_EVENT_GET_REQ:
+               caps = event->data;
+               fbcon_get_requirement(info, caps);
+               break;
        }
 
 done: