Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

VT: Add height parameter to con_font_get/set consw operations

The current con_font_get/set API currently hardcodes a 32-pixel-tall
limitation, which only dates from the old VGA hardware which could not
handle taller fonts than that.

This change just adds a vpitch parameter to release this
constraint. Drivers which do not support vpitch != 32 can just return
EINVAL when it is not 32, font loading tools will revert to trying 32
and succeed.

This change makes the fbcon driver consider vpitch appropriately, thus
making it able to load large fonts.

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Link: https://lore.kernel.org/r/20230119151934.932642243@ens-lyon.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Samuel Thibault and committed by
Greg Kroah-Hartman
ffc1e089 e34a79d0

+32 -36
+2 -2
drivers/tty/vt/vt.c
··· 4552 4552 if (vc->vc_mode != KD_TEXT) 4553 4553 rc = -EINVAL; 4554 4554 else if (vc->vc_sw->con_font_get) 4555 - rc = vc->vc_sw->con_font_get(vc, &font); 4555 + rc = vc->vc_sw->con_font_get(vc, &font, 32); 4556 4556 else 4557 4557 rc = -ENOSYS; 4558 4558 console_unlock(); ··· 4613 4613 else if (vc->vc_sw->con_font_set) { 4614 4614 if (vc_is_sel(vc)) 4615 4615 clear_selection(); 4616 - rc = vc->vc_sw->con_font_set(vc, &font, op->flags); 4616 + rc = vc->vc_sw->con_font_set(vc, &font, 32, op->flags); 4617 4617 } else 4618 4618 rc = -ENOSYS; 4619 4619 console_unlock();
+5 -4
drivers/video/console/newport_con.c
··· 497 497 return 1; 498 498 } 499 499 500 - static int newport_set_font(int unit, struct console_font *op) 500 + static int newport_set_font(int unit, struct console_font *op, unsigned int vpitch) 501 501 { 502 502 int w = op->width; 503 503 int h = op->height; ··· 507 507 508 508 /* ladis: when I grow up, there will be a day... and more sizes will 509 509 * be supported ;-) */ 510 - if ((w != 8) || (h != 16) 510 + if ((w != 8) || (h != 16) || (vpitch != 32) 511 511 || (op->charcount != 256 && op->charcount != 512)) 512 512 return -EINVAL; 513 513 ··· 569 569 return newport_set_def_font(vc->vc_num, op); 570 570 } 571 571 572 - static int newport_font_set(struct vc_data *vc, struct console_font *font, unsigned flags) 572 + static int newport_font_set(struct vc_data *vc, struct console_font *font, 573 + unsigned int vpitch, unsigned int flags) 573 574 { 574 - return newport_set_font(vc->vc_num, font); 575 + return newport_set_font(vc->vc_num, font, vpitch); 575 576 } 576 577 577 578 static bool newport_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
+5 -4
drivers/video/console/sticon.c
··· 169 169 return 0; 170 170 } 171 171 172 - static int sticon_set_font(struct vc_data *vc, struct console_font *op) 172 + static int sticon_set_font(struct vc_data *vc, struct console_font *op, 173 + unsigned int vpitch) 173 174 { 174 175 struct sti_struct *sti = sticon_sti; 175 176 int vc_cols, vc_rows, vc_old_cols, vc_old_rows; ··· 182 181 struct sti_cooked_font *cooked_font; 183 182 unsigned char *data = op->data, *p; 184 183 185 - if ((w < 6) || (h < 6) || (w > 32) || (h > 32) 184 + if ((w < 6) || (h < 6) || (w > 32) || (h > 32) || (vpitch != 32) 186 185 || (op->charcount != 256 && op->charcount != 512)) 187 186 return -EINVAL; 188 187 pitch = ALIGN(w, 8) / 8; ··· 268 267 } 269 268 270 269 static int sticon_font_set(struct vc_data *vc, struct console_font *font, 271 - unsigned int flags) 270 + unsigned int vpitch, unsigned int flags) 272 271 { 273 - return sticon_set_font(vc, font); 272 + return sticon_set_font(vc, font, vpitch); 274 273 } 275 274 276 275 static void sticon_init(struct vc_data *c, int init)
+4 -4
drivers/video/console/vgacon.c
··· 1029 1029 } 1030 1030 1031 1031 static int vgacon_font_set(struct vc_data *c, struct console_font *font, 1032 - unsigned int flags) 1032 + unsigned int vpitch, unsigned int flags) 1033 1033 { 1034 1034 unsigned charcount = font->charcount; 1035 1035 int rc; ··· 1037 1037 if (vga_video_type < VIDEO_TYPE_EGAM) 1038 1038 return -EINVAL; 1039 1039 1040 - if (font->width != VGA_FONTWIDTH || 1040 + if (font->width != VGA_FONTWIDTH || vpitch != 32 || 1041 1041 (charcount != 256 && charcount != 512)) 1042 1042 return -EINVAL; 1043 1043 ··· 1050 1050 return rc; 1051 1051 } 1052 1052 1053 - static int vgacon_font_get(struct vc_data *c, struct console_font *font) 1053 + static int vgacon_font_get(struct vc_data *c, struct console_font *font, unsigned int vpitch) 1054 1054 { 1055 - if (vga_video_type < VIDEO_TYPE_EGAM) 1055 + if (vga_video_type < VIDEO_TYPE_EGAM || vpitch != 32) 1056 1056 return -EINVAL; 1057 1057 1058 1058 font->width = VGA_FONTWIDTH;
+13 -20
drivers/video/fbdev/core/fbcon.c
··· 2271 2271 return 0; 2272 2272 } 2273 2273 2274 - static int fbcon_get_font(struct vc_data *vc, struct console_font *font) 2274 + static int fbcon_get_font(struct vc_data *vc, struct console_font *font, unsigned int vpitch) 2275 2275 { 2276 2276 u8 *fontdata = vc->vc_font.data; 2277 2277 u8 *data = font->data; ··· 2290 2290 2291 2291 for (i = 0; i < font->charcount; i++) { 2292 2292 memcpy(data, fontdata, j); 2293 - memset(data + j, 0, 32 - j); 2294 - data += 32; 2293 + memset(data + j, 0, vpitch - j); 2294 + data += vpitch; 2295 2295 fontdata += j; 2296 2296 } 2297 2297 } else if (font->width <= 16) { ··· 2301 2301 2302 2302 for (i = 0; i < font->charcount; i++) { 2303 2303 memcpy(data, fontdata, j); 2304 - memset(data + j, 0, 64 - j); 2305 - data += 64; 2304 + memset(data + j, 0, 2*vpitch - j); 2305 + data += 2*vpitch; 2306 2306 fontdata += j; 2307 2307 } 2308 2308 } else if (font->width <= 24) { ··· 2316 2316 *data++ = fontdata[2]; 2317 2317 fontdata += sizeof(u32); 2318 2318 } 2319 - memset(data, 0, 3 * (32 - j)); 2320 - data += 3 * (32 - j); 2319 + memset(data, 0, 3 * (vpitch - j)); 2320 + data += 3 * (vpitch - j); 2321 2321 } 2322 2322 } else { 2323 2323 j = vc->vc_font.height * 4; ··· 2326 2326 2327 2327 for (i = 0; i < font->charcount; i++) { 2328 2328 memcpy(data, fontdata, j); 2329 - memset(data + j, 0, 128 - j); 2330 - data += 128; 2329 + memset(data + j, 0, 4 * vpitch - j); 2330 + data += 4 * vpitch; 2331 2331 fontdata += j; 2332 2332 } 2333 2333 } ··· 2462 2462 } 2463 2463 2464 2464 /* 2465 - * User asked to set font; we are guaranteed that 2466 - * a) width and height are in range 1..32 2467 - * b) charcount does not exceed 512 2468 - * but lets not assume that, since someone might someday want to use larger 2469 - * fonts. And charcount of 512 is small for unicode support. 2470 - * 2471 - * However, user space gives the font in 32 rows , regardless of 2472 - * actual font height. So a new API is needed if support for larger fonts 2473 - * is ever implemented. 2465 + * User asked to set font; we are guaranteed that charcount does not exceed 512 2466 + * but lets not assume that, since charcount of 512 is small for unicode support. 2474 2467 */ 2475 2468 2476 2469 static int fbcon_set_font(struct vc_data *vc, struct console_font *font, 2477 - unsigned int flags) 2470 + unsigned int vpitch, unsigned int flags) 2478 2471 { 2479 2472 struct fb_info *info = fbcon_info_from_console(vc->vc_num); 2480 2473 unsigned charcount = font->charcount; ··· 2510 2517 FNTSIZE(new_data) = size; 2511 2518 REFCOUNT(new_data) = 0; /* usage counter */ 2512 2519 for (i=0; i< charcount; i++) { 2513 - memcpy(new_data + i*h*pitch, data + i*32*pitch, h*pitch); 2520 + memcpy(new_data + i*h*pitch, data + i*vpitch*pitch, h*pitch); 2514 2521 } 2515 2522 2516 2523 /* Since linux has a nice crc32 function use it for counting font
+3 -2
include/linux/console.h
··· 59 59 int (*con_switch)(struct vc_data *vc); 60 60 int (*con_blank)(struct vc_data *vc, int blank, int mode_switch); 61 61 int (*con_font_set)(struct vc_data *vc, struct console_font *font, 62 - unsigned int flags); 63 - int (*con_font_get)(struct vc_data *vc, struct console_font *font); 62 + unsigned int vpitch, unsigned int flags); 63 + int (*con_font_get)(struct vc_data *vc, struct console_font *font, 64 + unsigned int vpitch); 64 65 int (*con_font_default)(struct vc_data *vc, 65 66 struct console_font *font, char *name); 66 67 int (*con_resize)(struct vc_data *vc, unsigned int width,