]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/video/console/fbcon.c
Merge branch 'drm-patches' of master.kernel.org:/pub/scm/linux/kernel/git/airlied...
[linux-2.6-omap-h63xx.git] / drivers / video / console / fbcon.c
index 19dfdfbd434149543fbbf9889042ed969ae3731a..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;
 
@@ -3011,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)
 {
@@ -3018,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;
 
        /*
@@ -3066,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: