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 f80a9af3d16e94de51e4f124ec4ff40a43eaa31a..d18a1a5de14495aa639ae5888beb1986421da663 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 dca9c0325b3f0a703a597c4e6226a7185f982f6b..082501feceb96a118df3b0f9e25f04d3708ebc7a 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 1183e7a871f8b270a9ff2106cef15e44720184a4..4b67b32fdbc7af27a4b3c485446b7119495be7a7 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 fc206755f5f6da99cc7e29216ea6451ad45d3138..5ca18bfe11f669e6bfc3fda68eeeae6fbfea6686 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 2cba158888ea4e9fda92b267c98e07c4e8c7f093..821b89a0a6453bc16724802d85b1957fd89b4c75 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 07722a5ea8eff8a63e5827e4a79349f00689ee46..ff84106ecf1c11d726afec9e0e888bf158eb31b1 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 b485e919820134cd334f76689cfaa99c9756289d..a87bafbb119cc1dc6b60732d14ef6260fe8ca7c5 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 f8d022cb61e8d10ec091a3ec1776a7be49b97178..df984f3a7ff64165178e6f528d8bacdee5f3bf23 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 7115b325817f621d54e7ead9432cbbd7674aca39..88a1758616e021e7e3e691e715d47b854ac37a70 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 05dc9624897df9fe01b06ab18bea1ea23b53ecda..7d7c7791fd26a59709e085752bf8e85e3dc58e90 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 abf1442ce71919e0562d0f457e791cd23a1952b1..81caffd51bb49433eb4bd903f5e8b032c2deb63e 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 973866438608870c06af198de3cfe28756ec7831..47e34950b665c3d4de0472ff0558601351701ca9 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) {