fbcon: Increase maximum font width x height to 64 x 128
authorSamuel Thibault <samuel.thibault@ens-lyon.org>
Sat, 16 Mar 2024 00:10:21 +0000 (01:10 +0100)
committerHelge Deller <deller@gmx.de>
Sat, 16 Mar 2024 07:29:48 +0000 (08:29 +0100)
By using bitmaps we actually support whatever size we would want, but
the console currently limits fonts to 64x128 (which gives 60x16 text on
4k screens), so we don't need more for now, and we can easily increase
later.

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Signed-off-by: Helge Deller <deller@gmx.de>
12 files changed:
drivers/firmware/efi/earlycon.c
drivers/video/fbdev/arkfb.c
drivers/video/fbdev/core/fbcon.c
drivers/video/fbdev/core/fbmem.c
drivers/video/fbdev/core/svgalib.c
drivers/video/fbdev/s3fb.c
drivers/video/fbdev/vga16fb.c
drivers/video/fbdev/vt8623fb.c
drivers/video/sticore.c
include/linux/fb.h
include/linux/font.h
lib/fonts/fonts.c

index f80a9af..d18a1a5 100644 (file)
@@ -252,7 +252,7 @@ static int __init efi_earlycon_setup(struct earlycon_device *device,
        if (si->lfb_depth != 32)
                return -ENODEV;
 
-       font = get_default_font(xres, yres, -1, -1);
+       font = get_default_font(xres, yres, NULL, NULL);
        if (!font)
                return -ENODEV;
 
index dca9c03..082501f 100644 (file)
@@ -622,8 +622,13 @@ static int arkfb_set_par(struct fb_info *info)
                info->tileops = NULL;
 
                /* in 4bpp supports 8p wide tiles only, any tiles otherwise */
-               info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0);
-               info->pixmap.blit_y = ~(u32)0;
+               if (bpp == 4) {
+                       bitmap_zero(info->pixmap.blit_x, FB_MAX_BLIT_WIDTH);
+                       set_bit(8 - 1, info->pixmap.blit_x);
+               } else {
+                       bitmap_fill(info->pixmap.blit_x, FB_MAX_BLIT_WIDTH);
+               }
+               bitmap_fill(info->pixmap.blit_y, FB_MAX_BLIT_HEIGHT);
 
                offset_value = (info->var.xres_virtual * bpp) / 64;
                screen_size = info->var.yres_virtual * info->fix.line_length;
@@ -635,8 +640,10 @@ static int arkfb_set_par(struct fb_info *info)
                info->tileops = &arkfb_tile_ops;
 
                /* supports 8x16 tiles only */
-               info->pixmap.blit_x = 1 << (8 - 1);
-               info->pixmap.blit_y = 1 << (16 - 1);
+               bitmap_zero(info->pixmap.blit_x, FB_MAX_BLIT_WIDTH);
+               set_bit(8 - 1, info->pixmap.blit_x);
+               bitmap_zero(info->pixmap.blit_y, FB_MAX_BLIT_HEIGHT);
+               set_bit(16 - 1, info->pixmap.blit_y);
 
                offset_value = info->var.xres_virtual / 16;
                screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64;
index 1183e7a..4b67b32 100644 (file)
@@ -2485,12 +2485,12 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font,
            h > FBCON_SWAP(info->var.rotate, info->var.yres, info->var.xres))
                return -EINVAL;
 
-       if (font->width > 32 || font->height > 32)
+       if (font->width > FB_MAX_BLIT_WIDTH || font->height > FB_MAX_BLIT_HEIGHT)
                return -EINVAL;
 
        /* Make sure drawing engine can handle the font */
-       if (!(info->pixmap.blit_x & BIT(font->width - 1)) ||
-           !(info->pixmap.blit_y & BIT(font->height - 1)))
+       if (!test_bit(font->width - 1, info->pixmap.blit_x) ||
+           !test_bit(font->height - 1, info->pixmap.blit_y))
                return -EINVAL;
 
        /* Make sure driver can handle the font length */
@@ -3084,8 +3084,8 @@ void fbcon_get_requirement(struct fb_info *info,
                        vc = vc_cons[i].d;
                        if (vc && vc->vc_mode == KD_TEXT &&
                            info->node == con2fb_map[i]) {
-                               caps->x |= 1 << (vc->vc_font.width - 1);
-                               caps->y |= 1 << (vc->vc_font.height - 1);
+                               set_bit(vc->vc_font.width - 1, caps->x);
+                               set_bit(vc->vc_font.height - 1, caps->y);
                                charcnt = vc->vc_font.charcount;
                                if (caps->len < charcnt)
                                        caps->len = charcnt;
@@ -3096,8 +3096,10 @@ void fbcon_get_requirement(struct fb_info *info,
 
                if (vc && vc->vc_mode == KD_TEXT &&
                    info->node == con2fb_map[fg_console]) {
-                       caps->x = 1 << (vc->vc_font.width - 1);
-                       caps->y = 1 << (vc->vc_font.height - 1);
+                       bitmap_zero(caps->x, FB_MAX_BLIT_WIDTH);
+                       set_bit(vc->vc_font.width - 1, caps->x);
+                       bitmap_zero(caps->y, FB_MAX_BLIT_HEIGHT);
+                       set_bit(vc->vc_font.height - 1, caps->y);
                        caps->len = vc->vc_font.charcount;
                }
        }
index fc20675..5ca18bf 100644 (file)
@@ -212,8 +212,8 @@ static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var,
        fbcon_get_requirement(info, &caps);
        info->fbops->fb_get_caps(info, &fbcaps, var);
 
-       if (((fbcaps.x ^ caps.x) & caps.x) ||
-           ((fbcaps.y ^ caps.y) & caps.y) ||
+       if (!bitmap_subset(caps.x, fbcaps.x, FB_MAX_BLIT_WIDTH) ||
+           !bitmap_subset(caps.y, fbcaps.y, FB_MAX_BLIT_HEIGHT) ||
            (fbcaps.len < caps.len))
                err = -EINVAL;
 
@@ -420,11 +420,11 @@ static int do_register_framebuffer(struct fb_info *fb_info)
        }
        fb_info->pixmap.offset = 0;
 
-       if (!fb_info->pixmap.blit_x)
-               fb_info->pixmap.blit_x = ~(u32)0;
+       if (bitmap_empty(fb_info->pixmap.blit_x, FB_MAX_BLIT_WIDTH))
+               bitmap_fill(fb_info->pixmap.blit_x, FB_MAX_BLIT_WIDTH);
 
-       if (!fb_info->pixmap.blit_y)
-               fb_info->pixmap.blit_y = ~(u32)0;
+       if (bitmap_empty(fb_info->pixmap.blit_y, FB_MAX_BLIT_HEIGHT))
+               bitmap_fill(fb_info->pixmap.blit_y, FB_MAX_BLIT_HEIGHT);
 
        if (!fb_info->modelist.prev || !fb_info->modelist.next)
                INIT_LIST_HEAD(&fb_info->modelist);
index 2cba158..821b89a 100644 (file)
@@ -354,12 +354,19 @@ void svga_get_caps(struct fb_info *info, struct fb_blit_caps *caps,
 {
        if (var->bits_per_pixel == 0) {
                /* can only support 256 8x16 bitmap */
-               caps->x = 1 << (8 - 1);
-               caps->y = 1 << (16 - 1);
+               bitmap_zero(caps->x, FB_MAX_BLIT_WIDTH);
+               set_bit(8 - 1, caps->x);
+               bitmap_zero(caps->y, FB_MAX_BLIT_HEIGHT);
+               set_bit(16 - 1, caps->y);
                caps->len = 256;
        } else {
-               caps->x = (var->bits_per_pixel == 4) ? 1 << (8 - 1) : ~(u32)0;
-               caps->y = ~(u32)0;
+               if (var->bits_per_pixel == 4) {
+                       bitmap_zero(caps->x, FB_MAX_BLIT_WIDTH);
+                       set_bit(8 - 1, caps->x);
+               } else {
+                       bitmap_fill(caps->x, FB_MAX_BLIT_WIDTH);
+               }
+               bitmap_fill(caps->y, FB_MAX_BLIT_HEIGHT);
                caps->len = ~(u32)0;
        }
 }
index 07722a5..ff84106 100644 (file)
@@ -617,8 +617,13 @@ static int s3fb_set_par(struct fb_info *info)
                info->tileops = NULL;
 
                /* in 4bpp supports 8p wide tiles only, any tiles otherwise */
-               info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0);
-               info->pixmap.blit_y = ~(u32)0;
+               if (bpp == 4) {
+                       bitmap_zero(info->pixmap.blit_x, FB_MAX_BLIT_WIDTH);
+                       set_bit(8 - 1, info->pixmap.blit_x);
+               } else {
+                       bitmap_fill(info->pixmap.blit_x, FB_MAX_BLIT_WIDTH);
+               }
+               bitmap_fill(info->pixmap.blit_y, FB_MAX_BLIT_HEIGHT);
 
                offset_value = (info->var.xres_virtual * bpp) / 64;
                screen_size = info->var.yres_virtual * info->fix.line_length;
@@ -630,8 +635,10 @@ static int s3fb_set_par(struct fb_info *info)
                info->tileops = fasttext ? &s3fb_fast_tile_ops : &s3fb_tile_ops;
 
                /* supports 8x16 tiles only */
-               info->pixmap.blit_x = 1 << (8 - 1);
-               info->pixmap.blit_y = 1 << (16 - 1);
+               bitmap_zero(info->pixmap.blit_x, FB_MAX_BLIT_WIDTH);
+               set_bit(8 - 1, info->pixmap.blit_x);
+               bitmap_zero(info->pixmap.blit_y, FB_MAX_BLIT_HEIGHT);
+               set_bit(16 - 1, info->pixmap.blit_y);
 
                offset_value = info->var.xres_virtual / 16;
                screen_size = (info->var.xres_virtual * info->var.yres_virtual) / 64;
index b485e91..a87bafb 100644 (file)
@@ -1353,7 +1353,11 @@ static int vga16fb_probe(struct platform_device *dev)
        info->var = vga16fb_defined;
        info->fix = vga16fb_fix;
        /* supports rectangles with widths of multiples of 8 */
-       info->pixmap.blit_x = 1 << 7 | 1 << 15 | 1 << 23 | 1 << 31;
+       bitmap_zero(info->pixmap.blit_x, FB_MAX_BLIT_WIDTH);
+       set_bit(8 - 1, info->pixmap.blit_x);
+       set_bit(16 - 1, info->pixmap.blit_x);
+       set_bit(24 - 1, info->pixmap.blit_x);
+       set_bit(32 - 1, info->pixmap.blit_x);
        info->flags = FBINFO_HWACCEL_YPAN;
 
        i = (info->var.bits_per_pixel == 8) ? 256 : 16;
index f8d022c..df984f3 100644 (file)
@@ -390,8 +390,13 @@ static int vt8623fb_set_par(struct fb_info *info)
                info->tileops = NULL;
 
                /* in 4bpp supports 8p wide tiles only, any tiles otherwise */
-               info->pixmap.blit_x = (bpp == 4) ? (1 << (8 - 1)) : (~(u32)0);
-               info->pixmap.blit_y = ~(u32)0;
+               if (bpp == 4) {
+                       bitmap_zero(info->pixmap.blit_x, FB_MAX_BLIT_WIDTH);
+                       set_bit(8 - 1, info->pixmap.blit_x);
+               } else {
+                       bitmap_fill(info->pixmap.blit_x, FB_MAX_BLIT_WIDTH);
+               }
+               bitmap_fill(info->pixmap.blit_y, FB_MAX_BLIT_HEIGHT);
 
                offset_value = (info->var.xres_virtual * bpp) / 64;
                fetch_value  = ((info->var.xres * bpp) / 128) + 4;
@@ -408,8 +413,10 @@ static int vt8623fb_set_par(struct fb_info *info)
                info->tileops = &vt8623fb_tile_ops;
 
                /* supports 8x16 tiles only */
-               info->pixmap.blit_x = 1 << (8 - 1);
-               info->pixmap.blit_y = 1 << (16 - 1);
+               bitmap_zero(info->pixmap.blit_x, FB_MAX_BLIT_WIDTH);
+               set_bit(8 - 1, info->pixmap.blit_x);
+               bitmap_zero(info->pixmap.blit_y, FB_MAX_BLIT_HEIGHT);
+               set_bit(16 - 1, info->pixmap.blit_y);
 
                offset_value = info->var.xres_virtual / 16;
                fetch_value  = (info->var.xres / 8) + 8;
index 7115b32..88a1758 100644 (file)
@@ -529,7 +529,7 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
        if (fbfont_name && strlen(fbfont_name))
                fbfont = find_font(fbfont_name);
        if (!fbfont)
-               fbfont = get_default_font(1024,768, ~(u32)0, ~(u32)0);
+               fbfont = get_default_font(1024, 768, NULL, NULL);
        if (!fbfont)
                return NULL;
 
index 05dc962..7d7c779 100644 (file)
@@ -143,9 +143,13 @@ struct fb_event {
        void *data;
 };
 
+/*     Enough for the VT console needs, see its max_font_width/height */
+#define FB_MAX_BLIT_WIDTH      64
+#define FB_MAX_BLIT_HEIGHT     128
+
 struct fb_blit_caps {
-       u32 x;
-       u32 y;
+       DECLARE_BITMAP(x, FB_MAX_BLIT_WIDTH);
+       DECLARE_BITMAP(y, FB_MAX_BLIT_HEIGHT);
        u32 len;
        u32 flags;
 };
@@ -192,10 +196,12 @@ struct fb_pixmap {
        u32 scan_align;         /* alignment per scanline               */
        u32 access_align;       /* alignment per read/write (bits)      */
        u32 flags;              /* see FB_PIXMAP_*                      */
-       u32 blit_x;             /* supported bit block dimensions (1-32)*/
-       u32 blit_y;             /* Format: blit_x = 1 << (width - 1)    */
-                               /*         blit_y = 1 << (height - 1)   */
-                               /* if 0, will be set to 0xffffffff (all)*/
+                               /* supported bit block dimensions       */
+                               /* Format: test_bit(width - 1, blit_x)  */
+                               /*         test_bit(height - 1, blit_y) */
+                               /* if zero, will be set to full (all)   */
+       DECLARE_BITMAP(blit_x, FB_MAX_BLIT_WIDTH);
+       DECLARE_BITMAP(blit_y, FB_MAX_BLIT_HEIGHT);
        /* access methods */
        void (*writeio)(struct fb_info *info, void __iomem *dst, void *src, unsigned int size);
        void (*readio) (struct fb_info *info, void *dst, void __iomem *src, unsigned int size);
index abf1442..81caffd 100644 (file)
@@ -57,7 +57,8 @@ extern const struct font_desc *find_font(const char *name);
 /* Get the default font for a specific screen size */
 
 extern const struct font_desc *get_default_font(int xres, int yres,
-                                               u32 font_w, u32 font_h);
+                                               unsigned long *font_w,
+                                               unsigned long *font_h);
 
 /* Max. length for the name of a predefined font */
 #define MAX_FONT_NAME  32
index 9738664..47e3495 100644 (file)
@@ -96,18 +96,21 @@ EXPORT_SYMBOL(find_font);
  *     get_default_font - get default font
  *     @xres: screen size of X
  *     @yres: screen size of Y
- *      @font_w: bit array of supported widths (1 - 32)
- *      @font_h: bit array of supported heights (1 - 32)
+ *     @font_w: bit array of supported widths (1 - FB_MAX_BLIT_WIDTH)
+ *     @font_h: bit array of supported heights (1 - FB_MAX_BLIT_HEIGHT)
  *
  *     Get the default font for a specified screen size.
  *     Dimensions are in pixels.
  *
+ *     font_w or font_h being NULL means all values are supported.
+ *
  *     Returns %NULL if no font is found, or a pointer to the
  *     chosen font.
  *
  */
-const struct font_desc *get_default_font(int xres, int yres, u32 font_w,
-                                        u32 font_h)
+const struct font_desc *get_default_font(int xres, int yres,
+                                        unsigned long *font_w,
+                                        unsigned long *font_h)
 {
        int i, c, cc, res;
        const struct font_desc *f, *g;
@@ -135,8 +138,8 @@ const struct font_desc *get_default_font(int xres, int yres, u32 font_w,
                if (res > 20)
                        c += 20 - res;
 
-               if ((font_w & (1U << (f->width - 1))) &&
-                   (font_h & (1U << (f->height - 1))))
+               if ((!font_w || test_bit(f->width - 1, font_w)) &&
+                   (!font_h || test_bit(f->height - 1, font_h)))
                        c += 1000;
 
                if (c > cc) {