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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'fbdev-for-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev

Pull fbdev updates from Helge Deller:
"A major refactorization by Thomas Zimmermann from SUSE regarding
handling of console font data, addition of helpers for console font
rotation and split into individual components for glyphs, fonts and
the overall fbcon state.

And there is the round of usual code cleanups and fixes:

Cleanups:
- atyfb: Remove unused fb_list (Geert Uytterhoeven)
- goldfishfb, wmt_ge_rops: use devm_platform_ioremap_resource() (Amin GATTOUT)
- matroxfb: Mark variable with __maybe_unused (Andy Shevchenko)
- omapfb: Add missing error check for clk_get() (Chen Ni)
- tdfxfb: Make the VGA register initialisation a bit more obvious (Daniel Palmer)
- macfb: Replace deprecated strcpy with strscpy (Thorsten Blum)

Fixes:
- tdfxfb, udlfb: avoid divide-by-zero on FBIOPUT_VSCREENINFO (Greg Kroah-Hartman)
- omap2: fix inconsistent lock returns in omapfb_mmap (Hongling Zeng)
- viafb: check ioremap return value in viafb_lcd_get_mobile_state (Wang Jun)"

* tag 'fbdev-for-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev: (40 commits)
fbdev: udlfb: avoid divide-by-zero on FBIOPUT_VSCREENINFO
fbdev: tdfxfb: avoid divide-by-zero on FBIOPUT_VSCREENINFO
fbdev: omap2: fix inconsistent lock returns in omapfb_mmap
MAINTAINERS: Add dedicated entry for fbcon
fbcon: Put font-rotation state into separate struct
fbcon: Fill cursor mask in helper function
lib/fonts: Implement font rotation
lib/fonts: Refactor glyph-rotation helpers
lib/fonts: Refactor glyph-pattern helpers
lib/fonts: Implement glyph rotation
lib/fonts: Clean up Makefile
lib/fonts: Provide helpers for calculating glyph pitch and size
vt: Implement helpers for struct vc_font in source file
fbcon: Avoid OOB font access if console rotation fails
fbdev: atyfb: Remove unused fb_list
fbdev: matroxfb: Mark variable with __maybe_unused to avoid W=1 build break
fbdev: update help text for CONFIG_FB_NVIDIA
fbdev: omapfb: Add missing error check for clk_get()
fbdev: viafb: check ioremap return value in viafb_lcd_get_mobile_state
lib/fonts: Remove internal symbols and macros from public header file
...

+1325 -787
+23
MAINTAINERS
··· 10073 10073 W: https://floatingpoint.billm.au/ 10074 10074 F: arch/x86/math-emu/ 10075 10075 10076 + FRAMEBUFFER CONSOLE 10077 + M: Helge Deller <deller@gmx.de> 10078 + M: Thomas Zimmermann <tzimmermann@suse.de> 10079 + L: dri-devel@lists.freedesktop.org 10080 + L: linux-fbdev@vger.kernel.org 10081 + S: Maintained 10082 + T: git https://gitlab.freedesktop.org/drm/misc/kernel.git 10083 + F: Documentation/fb/fbcon.rst 10084 + F: drivers/video/fbdev/core/bitblit.c 10085 + F: drivers/video/fbdev/core/fb_logo.c 10086 + F: drivers/video/fbdev/core/fbcon.c 10087 + F: drivers/video/fbdev/core/fbcon.h 10088 + F: drivers/video/fbdev/core/fbcon_ccw.c 10089 + F: drivers/video/fbdev/core/fbcon_cw.c 10090 + F: drivers/video/fbdev/core/fbcon_rotate.c 10091 + F: drivers/video/fbdev/core/fbcon_rotate.h 10092 + F: drivers/video/fbdev/core/fbcon_ud.c 10093 + F: drivers/video/fbdev/core/softcursor.c 10094 + F: drivers/video/fbdev/core/tileblit.c 10095 + F: include/linux/fbcon.h 10096 + F: include/linux/font.h 10097 + F: lib/fonts/ 10098 + 10076 10099 FRAMEBUFFER CORE 10077 10100 M: Simona Vetter <simona@ffwll.ch> 10078 10101 S: Odd Fixes
+34
drivers/tty/vt/vt.c
··· 231 231 }; 232 232 233 233 /* 234 + * struct vc_font 235 + */ 236 + 237 + /** 238 + * vc_font_pitch - Calculates the number of bytes between two adjacent scanlines 239 + * @font: The VC font 240 + * 241 + * Returns: 242 + * The number of bytes between two adjacent scanlines in the font data 243 + */ 244 + unsigned int vc_font_pitch(const struct vc_font *font) 245 + { 246 + return font_glyph_pitch(font->width); 247 + } 248 + EXPORT_SYMBOL_GPL(vc_font_pitch); 249 + 250 + /** 251 + * vc_font_size - Calculates the size of the font data in bytes 252 + * @font: The VC font 253 + * 254 + * vc_font_size() calculates the number of bytes of font data in the 255 + * font specified by @font. The function calculates the size from the 256 + * font parameters. 257 + * 258 + * Returns: 259 + * The size of the font data in bytes. 260 + */ 261 + unsigned int vc_font_size(const struct vc_font *font) 262 + { 263 + return font_glyph_size(font->width, font->height) * font->charcount; 264 + } 265 + EXPORT_SYMBOL_GPL(vc_font_size); 266 + 267 + /* 234 268 * /sys/class/tty/tty0/ 235 269 * 236 270 * the attribute 'active' contains the name of the current vc
+19 -42
drivers/video/console/newport_con.c
··· 33 33 34 34 #define NEWPORT_LEN 0x10000 35 35 36 - #define FONT_DATA ((unsigned char *)font_vga_8x16.data) 36 + #define FONT_DATA font_vga_8x16.data 37 37 38 - static unsigned char *font_data[MAX_NR_CONSOLES]; 38 + static font_data_t *font_data[MAX_NR_CONSOLES]; 39 39 40 40 static struct newport_regs *npregs; 41 41 static unsigned long newport_addr; ··· 370 370 static void newport_putc(struct vc_data *vc, u16 charattr, unsigned int ypos, 371 371 unsigned int xpos) 372 372 { 373 - unsigned char *p; 373 + const unsigned char *p; 374 374 375 - p = &font_data[vc->vc_num][(charattr & 0xff) << 4]; 375 + p = &font_data_buf(font_data[vc->vc_num])[(charattr & 0xff) << 4]; 376 376 charattr = (charattr >> 8) & 0xff; 377 377 xpos <<= 3; 378 378 ypos <<= 4; ··· 400 400 unsigned int count, unsigned int ypos, 401 401 unsigned int xpos) 402 402 { 403 - unsigned char *p; 403 + const unsigned char *p; 404 404 unsigned int i; 405 405 u16 charattr; 406 406 ··· 424 424 NPORT_DMODE0_L32); 425 425 426 426 for (i = 0; i < count; i++, xpos += 8) { 427 - p = &font_data[vc->vc_num][(scr_readw(s++) & 0xff) << 4]; 427 + p = &font_data_buf(font_data[vc->vc_num])[(scr_readw(s++) & 0xff) << 4]; 428 428 429 429 newport_wait(npregs); 430 430 ··· 501 501 { 502 502 int w = op->width; 503 503 int h = op->height; 504 - int size = h * op->charcount; 505 504 int i; 506 - unsigned char *new_data, *data = op->data, *p; 505 + font_data_t *new_data; 507 506 508 507 /* ladis: when I grow up, there will be a day... and more sizes will 509 508 * be supported ;-) */ 510 - if ((w != 8) || (h != 16) || (vpitch != 32) 511 - || (op->charcount != 256 && op->charcount != 512)) 509 + if (w != 8 || h != 16 || (op->charcount != 256 && op->charcount != 512)) 512 510 return -EINVAL; 513 511 514 - if (!(new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, 515 - GFP_USER))) return -ENOMEM; 516 - 517 - new_data += FONT_EXTRA_WORDS * sizeof(int); 518 - FNTSIZE(new_data) = size; 519 - FNTCHARCNT(new_data) = op->charcount; 520 - REFCOUNT(new_data) = 0; /* usage counter */ 521 - FNTSUM(new_data) = 0; 522 - 523 - p = new_data; 524 - for (i = 0; i < op->charcount; i++) { 525 - memcpy(p, data, h); 526 - data += 32; 527 - p += h; 528 - } 512 + new_data = font_data_import(op, vpitch, NULL); 513 + if (IS_ERR(new_data)) 514 + return PTR_ERR(new_data); 529 515 530 516 /* check if font is already used by other console */ 531 517 for (i = 0; i < MAX_NR_CONSOLES; i++) { 532 - if (font_data[i] != FONT_DATA 533 - && FNTSIZE(font_data[i]) == size 534 - && !memcmp(font_data[i], new_data, size)) { 535 - kfree(new_data - FONT_EXTRA_WORDS * sizeof(int)); 518 + if (font_data_is_equal(font_data[i], new_data)) { 519 + font_data_put(new_data); 536 520 /* current font is the same as the new one */ 537 521 if (i == unit) 538 522 return 0; 539 523 new_data = font_data[i]; 524 + font_data_get(new_data); 540 525 break; 541 526 } 542 527 } 543 - /* old font is user font */ 544 - if (font_data[unit] != FONT_DATA) { 545 - if (--REFCOUNT(font_data[unit]) == 0) 546 - kfree(font_data[unit] - 547 - FONT_EXTRA_WORDS * sizeof(int)); 548 - } 549 - REFCOUNT(new_data)++; 528 + 529 + font_data_put(font_data[unit]); 550 530 font_data[unit] = new_data; 551 531 552 532 return 0; ··· 534 554 535 555 static int newport_set_def_font(int unit, struct console_font *op) 536 556 { 537 - if (font_data[unit] != FONT_DATA) { 538 - if (--REFCOUNT(font_data[unit]) == 0) 539 - kfree(font_data[unit] - 540 - FONT_EXTRA_WORDS * sizeof(int)); 541 - font_data[unit] = FONT_DATA; 542 - } 557 + font_data_put(font_data[unit]); 558 + font_data[unit] = FONT_DATA; 559 + font_data_get(font_data[unit]); 543 560 544 561 return 0; 545 562 }
+6 -4
drivers/video/fbdev/Kconfig
··· 668 668 select BITREVERSE 669 669 select VGASTATE 670 670 help 671 - This driver supports graphics boards with the nVidia chips, TNT 672 - and newer. For very old chipsets, such as the RIVA128, then use 673 - the rivafb. 674 - Say Y if you have such a graphics board. 671 + This driver supports graphics boards with the nVidia chips, from TNT 672 + through early GeForce generations (NV4–NV2x: Twintor, Twintor2, Celsius, 673 + Kelvin). 674 + Later architectures (Rankine and newer) are not reliably supported. 675 + For very old chipsets, such as the RIVA128, use rivafb. 676 + If unsure, say N. 675 677 676 678 To compile this driver as a module, choose M here: the 677 679 module will be called nvidiafb.
-4
drivers/video/fbdev/aty/atyfb_base.c
··· 2324 2324 * Initialisation 2325 2325 */ 2326 2326 2327 - static struct fb_info *fb_list = NULL; 2328 - 2329 2327 #if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD) 2330 2328 static int atyfb_get_timings_from_lcd(struct atyfb_par *par, 2331 2329 struct fb_var_screeninfo *var) ··· 2755 2757 aty_bl_init(par); 2756 2758 #endif 2757 2759 } 2758 - 2759 - fb_list = info; 2760 2760 2761 2761 PRINTKI("fb%d: %s frame buffer device on %s\n", 2762 2762 info->node, info->fix.id, par->bus_type == ISA ? "ISA" : "PCI");
+8 -38
drivers/video/fbdev/core/bitblit.c
··· 22 22 /* 23 23 * Accelerated handlers. 24 24 */ 25 - static void update_attr(u8 *dst, u8 *src, int attribute, 26 - struct vc_data *vc) 25 + static void update_attr(u8 *dst, const u8 *src, int attribute, struct vc_data *vc) 27 26 { 28 27 int i, offset = (vc->vc_font.height < 10) ? 1 : 2; 29 28 int width = DIV_ROUND_UP(vc->vc_font.width, 8); ··· 80 81 u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; 81 82 unsigned int charcnt = vc->vc_font.charcount; 82 83 u32 idx = vc->vc_font.width >> 3; 83 - u8 *src; 84 + const u8 *src; 84 85 85 86 while (cnt--) { 86 87 u16 ch = scr_readw(s++) & charmask; ··· 119 120 u32 shift_low = 0, mod = vc->vc_font.width % 8; 120 121 u32 shift_high = 8; 121 122 u32 idx = vc->vc_font.width >> 3; 122 - u8 *src; 123 + const u8 *src; 123 124 124 125 while (cnt--) { 125 126 u16 ch = scr_readw(s++) & charmask; ··· 266 267 int y = real_y(par->p, vc->state.y); 267 268 int attribute, use_sw = vc->vc_cursor_type & CUR_SW; 268 269 int err = 1; 269 - char *src; 270 + const u8 *src; 270 271 271 272 cursor.set = 0; 272 273 ··· 277 278 attribute = get_attribute(info, c); 278 279 src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height)); 279 280 280 - if (par->cursor_state.image.data != src || 281 + if (par->cursor_state.image.data != (const char *)src || 281 282 par->cursor_reset) { 282 283 par->cursor_state.image.data = src; 283 284 cursor.set |= FB_CUR_SETIMAGE; ··· 329 330 vc->vc_cursor_type != par->p->cursor_shape || 330 331 par->cursor_state.mask == NULL || 331 332 par->cursor_reset) { 332 - char *mask = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC); 333 - int cur_height, size, i = 0; 334 - u8 msk = 0xff; 333 + unsigned char *mask = kmalloc_array(vc->vc_font.height, w, GFP_ATOMIC); 335 334 336 335 if (!mask) 337 336 return; 337 + fbcon_fill_cursor_mask(par, vc, mask); 338 338 339 339 kfree(par->cursor_state.mask); 340 - par->cursor_state.mask = mask; 340 + par->cursor_state.mask = (const char *)mask; 341 341 342 342 par->p->cursor_shape = vc->vc_cursor_type; 343 343 cursor.set |= FB_CUR_SETSHAPE; 344 - 345 - switch (CUR_SIZE(par->p->cursor_shape)) { 346 - case CUR_NONE: 347 - cur_height = 0; 348 - break; 349 - case CUR_UNDERLINE: 350 - cur_height = (vc->vc_font.height < 10) ? 1 : 2; 351 - break; 352 - case CUR_LOWER_THIRD: 353 - cur_height = vc->vc_font.height/3; 354 - break; 355 - case CUR_LOWER_HALF: 356 - cur_height = vc->vc_font.height >> 1; 357 - break; 358 - case CUR_TWO_THIRDS: 359 - cur_height = (vc->vc_font.height << 1)/3; 360 - break; 361 - case CUR_BLOCK: 362 - default: 363 - cur_height = vc->vc_font.height; 364 - break; 365 - } 366 - size = (vc->vc_font.height - cur_height) * w; 367 - while (size--) 368 - mask[i++] = ~msk; 369 - size = cur_height * w; 370 - while (size--) 371 - mask[i++] = msk; 372 344 } 373 345 374 346 par->cursor_state.enable = enable && !use_sw;
+192 -74
drivers/video/fbdev/core/fb_defio.c
··· 14 14 #include <linux/export.h> 15 15 #include <linux/string.h> 16 16 #include <linux/mm.h> 17 + #include <linux/module.h> 17 18 #include <linux/vmalloc.h> 18 19 #include <linux/delay.h> 19 20 #include <linux/interrupt.h> ··· 24 23 /* to support deferred IO */ 25 24 #include <linux/rmap.h> 26 25 #include <linux/pagemap.h> 26 + 27 + struct address_space; 28 + 29 + /* 30 + * struct fb_deferred_io_state 31 + */ 32 + 33 + struct fb_deferred_io_state { 34 + struct kref ref; 35 + 36 + int open_count; /* number of opened files; protected by fb_info lock */ 37 + struct address_space *mapping; /* page cache object for fb device */ 38 + 39 + struct mutex lock; /* mutex that protects the pageref list */ 40 + /* fields protected by lock */ 41 + struct fb_info *info; 42 + struct list_head pagereflist; /* list of pagerefs for touched pages */ 43 + unsigned long npagerefs; 44 + struct fb_deferred_io_pageref *pagerefs; 45 + }; 46 + 47 + static struct fb_deferred_io_state *fb_deferred_io_state_alloc(unsigned long len) 48 + { 49 + struct fb_deferred_io_state *fbdefio_state; 50 + struct fb_deferred_io_pageref *pagerefs; 51 + unsigned long npagerefs; 52 + 53 + fbdefio_state = kzalloc_obj(*fbdefio_state); 54 + if (!fbdefio_state) 55 + return NULL; 56 + 57 + npagerefs = DIV_ROUND_UP(len, PAGE_SIZE); 58 + 59 + /* alloc a page ref for each page of the display memory */ 60 + pagerefs = kvzalloc_objs(*pagerefs, npagerefs); 61 + if (!pagerefs) 62 + goto err_kfree; 63 + fbdefio_state->npagerefs = npagerefs; 64 + fbdefio_state->pagerefs = pagerefs; 65 + 66 + kref_init(&fbdefio_state->ref); 67 + mutex_init(&fbdefio_state->lock); 68 + 69 + INIT_LIST_HEAD(&fbdefio_state->pagereflist); 70 + 71 + return fbdefio_state; 72 + 73 + err_kfree: 74 + kfree(fbdefio_state); 75 + return NULL; 76 + } 77 + 78 + static void fb_deferred_io_state_release(struct fb_deferred_io_state *fbdefio_state) 79 + { 80 + WARN_ON(!list_empty(&fbdefio_state->pagereflist)); 81 + mutex_destroy(&fbdefio_state->lock); 82 + kvfree(fbdefio_state->pagerefs); 83 + 84 + kfree(fbdefio_state); 85 + } 86 + 87 + static void fb_deferred_io_state_get(struct fb_deferred_io_state *fbdefio_state) 88 + { 89 + kref_get(&fbdefio_state->ref); 90 + } 91 + 92 + static void __fb_deferred_io_state_release(struct kref *ref) 93 + { 94 + struct fb_deferred_io_state *fbdefio_state = 95 + container_of(ref, struct fb_deferred_io_state, ref); 96 + 97 + fb_deferred_io_state_release(fbdefio_state); 98 + } 99 + 100 + static void fb_deferred_io_state_put(struct fb_deferred_io_state *fbdefio_state) 101 + { 102 + kref_put(&fbdefio_state->ref, __fb_deferred_io_state_release); 103 + } 104 + 105 + /* 106 + * struct vm_operations_struct 107 + */ 108 + 109 + static void fb_deferred_io_vm_open(struct vm_area_struct *vma) 110 + { 111 + struct fb_deferred_io_state *fbdefio_state = vma->vm_private_data; 112 + 113 + WARN_ON_ONCE(!try_module_get(THIS_MODULE)); 114 + fb_deferred_io_state_get(fbdefio_state); 115 + } 116 + 117 + static void fb_deferred_io_vm_close(struct vm_area_struct *vma) 118 + { 119 + struct fb_deferred_io_state *fbdefio_state = vma->vm_private_data; 120 + 121 + fb_deferred_io_state_put(fbdefio_state); 122 + module_put(THIS_MODULE); 123 + } 27 124 28 125 static struct page *fb_deferred_io_get_page(struct fb_info *info, unsigned long offs) 29 126 { ··· 143 44 return page; 144 45 } 145 46 146 - static struct fb_deferred_io_pageref *fb_deferred_io_pageref_lookup(struct fb_info *info, 147 - unsigned long offset, 148 - struct page *page) 47 + static struct fb_deferred_io_pageref * 48 + fb_deferred_io_pageref_lookup(struct fb_deferred_io_state *fbdefio_state, unsigned long offset, 49 + struct page *page) 149 50 { 51 + struct fb_info *info = fbdefio_state->info; 150 52 unsigned long pgoff = offset >> PAGE_SHIFT; 151 53 struct fb_deferred_io_pageref *pageref; 152 54 153 - if (fb_WARN_ON_ONCE(info, pgoff >= info->npagerefs)) 55 + if (fb_WARN_ON_ONCE(info, pgoff >= fbdefio_state->npagerefs)) 154 56 return NULL; /* incorrect allocation size */ 155 57 156 58 /* 1:1 mapping between pageref and page offset */ 157 - pageref = &info->pagerefs[pgoff]; 59 + pageref = &fbdefio_state->pagerefs[pgoff]; 158 60 159 61 if (pageref->page) 160 62 goto out; ··· 175 75 struct page *page) 176 76 { 177 77 struct fb_deferred_io *fbdefio = info->fbdefio; 178 - struct list_head *pos = &fbdefio->pagereflist; 78 + struct fb_deferred_io_state *fbdefio_state = info->fbdefio_state; 79 + struct list_head *pos = &fbdefio_state->pagereflist; 179 80 struct fb_deferred_io_pageref *pageref, *cur; 180 81 181 - pageref = fb_deferred_io_pageref_lookup(info, offset, page); 82 + pageref = fb_deferred_io_pageref_lookup(fbdefio_state, offset, page); 182 83 if (!pageref) 183 84 return NULL; 184 85 ··· 200 99 * pages. If possible, drivers should try to work with 201 100 * unsorted page lists instead. 202 101 */ 203 - list_for_each_entry(cur, &fbdefio->pagereflist, list) { 102 + list_for_each_entry(cur, &fbdefio_state->pagereflist, list) { 204 103 if (cur->offset > pageref->offset) 205 104 break; 206 105 } ··· 222 121 /* this is to find and return the vmalloc-ed fb pages */ 223 122 static vm_fault_t fb_deferred_io_fault(struct vm_fault *vmf) 224 123 { 124 + struct fb_info *info; 225 125 unsigned long offset; 226 126 struct page *page; 227 - struct fb_info *info = vmf->vma->vm_private_data; 127 + vm_fault_t ret; 128 + struct fb_deferred_io_state *fbdefio_state = vmf->vma->vm_private_data; 129 + 130 + mutex_lock(&fbdefio_state->lock); 131 + 132 + info = fbdefio_state->info; 133 + if (!info) { 134 + ret = VM_FAULT_SIGBUS; /* our device is gone */ 135 + goto err_mutex_unlock; 136 + } 228 137 229 138 offset = vmf->pgoff << PAGE_SHIFT; 230 - if (offset >= info->fix.smem_len) 231 - return VM_FAULT_SIGBUS; 139 + if (offset >= info->fix.smem_len) { 140 + ret = VM_FAULT_SIGBUS; 141 + goto err_mutex_unlock; 142 + } 232 143 233 144 page = fb_deferred_io_get_page(info, offset); 234 - if (!page) 235 - return VM_FAULT_SIGBUS; 145 + if (!page) { 146 + ret = VM_FAULT_SIGBUS; 147 + goto err_mutex_unlock; 148 + } 236 149 237 150 if (!vmf->vma->vm_file) 238 151 fb_err(info, "no mapping available\n"); 239 152 240 - BUG_ON(!info->fbdefio->mapping); 153 + fb_WARN_ON_ONCE(info, !fbdefio_state->mapping); 154 + 155 + mutex_unlock(&fbdefio_state->lock); 241 156 242 157 vmf->page = page; 158 + 243 159 return 0; 160 + 161 + err_mutex_unlock: 162 + mutex_unlock(&fbdefio_state->lock); 163 + return ret; 244 164 } 245 165 246 166 int fb_deferred_io_fsync(struct file *file, loff_t start, loff_t end, int datasync) ··· 288 166 * Adds a page to the dirty list. Call this from struct 289 167 * vm_operations_struct.page_mkwrite. 290 168 */ 291 - static vm_fault_t fb_deferred_io_track_page(struct fb_info *info, unsigned long offset, 292 - struct page *page) 169 + static vm_fault_t fb_deferred_io_track_page(struct fb_deferred_io_state *fbdefio_state, 170 + unsigned long offset, struct page *page) 293 171 { 294 - struct fb_deferred_io *fbdefio = info->fbdefio; 172 + struct fb_info *info; 173 + struct fb_deferred_io *fbdefio; 295 174 struct fb_deferred_io_pageref *pageref; 296 175 vm_fault_t ret; 297 176 298 177 /* protect against the workqueue changing the page list */ 299 - mutex_lock(&fbdefio->lock); 178 + mutex_lock(&fbdefio_state->lock); 179 + 180 + info = fbdefio_state->info; 181 + if (!info) { 182 + ret = VM_FAULT_SIGBUS; /* our device is gone */ 183 + goto err_mutex_unlock; 184 + } 185 + 186 + fbdefio = info->fbdefio; 300 187 301 188 pageref = fb_deferred_io_pageref_get(info, offset, page); 302 189 if (WARN_ON_ONCE(!pageref)) { ··· 323 192 */ 324 193 lock_page(pageref->page); 325 194 326 - mutex_unlock(&fbdefio->lock); 195 + mutex_unlock(&fbdefio_state->lock); 327 196 328 197 /* come back after delay to process the deferred IO */ 329 198 schedule_delayed_work(&info->deferred_work, fbdefio->delay); 330 199 return VM_FAULT_LOCKED; 331 200 332 201 err_mutex_unlock: 333 - mutex_unlock(&fbdefio->lock); 202 + mutex_unlock(&fbdefio_state->lock); 334 203 return ret; 335 204 } 336 205 337 - /* 338 - * fb_deferred_io_page_mkwrite - Mark a page as written for deferred I/O 339 - * @fb_info: The fbdev info structure 340 - * @vmf: The VM fault 341 - * 342 - * This is a callback we get when userspace first tries to 343 - * write to the page. We schedule a workqueue. That workqueue 344 - * will eventually mkclean the touched pages and execute the 345 - * deferred framebuffer IO. Then if userspace touches a page 346 - * again, we repeat the same scheme. 347 - * 348 - * Returns: 349 - * VM_FAULT_LOCKED on success, or a VM_FAULT error otherwise. 350 - */ 351 - static vm_fault_t fb_deferred_io_page_mkwrite(struct fb_info *info, struct vm_fault *vmf) 206 + static vm_fault_t fb_deferred_io_page_mkwrite(struct fb_deferred_io_state *fbdefio_state, 207 + struct vm_fault *vmf) 352 208 { 353 209 unsigned long offset = vmf->pgoff << PAGE_SHIFT; 354 210 struct page *page = vmf->page; 355 211 356 212 file_update_time(vmf->vma->vm_file); 357 213 358 - return fb_deferred_io_track_page(info, offset, page); 214 + return fb_deferred_io_track_page(fbdefio_state, offset, page); 359 215 } 360 216 361 - /* vm_ops->page_mkwrite handler */ 362 217 static vm_fault_t fb_deferred_io_mkwrite(struct vm_fault *vmf) 363 218 { 364 - struct fb_info *info = vmf->vma->vm_private_data; 219 + struct fb_deferred_io_state *fbdefio_state = vmf->vma->vm_private_data; 365 220 366 - return fb_deferred_io_page_mkwrite(info, vmf); 221 + return fb_deferred_io_page_mkwrite(fbdefio_state, vmf); 367 222 } 368 223 369 224 static const struct vm_operations_struct fb_deferred_io_vm_ops = { 225 + .open = fb_deferred_io_vm_open, 226 + .close = fb_deferred_io_vm_close, 370 227 .fault = fb_deferred_io_fault, 371 228 .page_mkwrite = fb_deferred_io_mkwrite, 372 229 }; ··· 367 248 { 368 249 vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 369 250 251 + if (!try_module_get(THIS_MODULE)) 252 + return -EINVAL; 253 + 370 254 vma->vm_ops = &fb_deferred_io_vm_ops; 371 255 vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP); 372 256 if (!(info->flags & FBINFO_VIRTFB)) 373 257 vm_flags_set(vma, VM_IO); 374 - vma->vm_private_data = info; 258 + vma->vm_private_data = info->fbdefio_state; 259 + 260 + fb_deferred_io_state_get(info->fbdefio_state); /* released in vma->vm_ops->close() */ 261 + 375 262 return 0; 376 263 } 377 264 EXPORT_SYMBOL_GPL(fb_deferred_io_mmap); ··· 388 263 struct fb_info *info = container_of(work, struct fb_info, deferred_work.work); 389 264 struct fb_deferred_io_pageref *pageref, *next; 390 265 struct fb_deferred_io *fbdefio = info->fbdefio; 266 + struct fb_deferred_io_state *fbdefio_state = info->fbdefio_state; 391 267 392 268 /* here we wrprotect the page's mappings, then do all deferred IO. */ 393 - mutex_lock(&fbdefio->lock); 269 + mutex_lock(&fbdefio_state->lock); 394 270 #ifdef CONFIG_MMU 395 - list_for_each_entry(pageref, &fbdefio->pagereflist, list) { 271 + list_for_each_entry(pageref, &fbdefio_state->pagereflist, list) { 396 272 struct page *page = pageref->page; 397 273 pgoff_t pgoff = pageref->offset >> PAGE_SHIFT; 398 274 399 - mapping_wrprotect_range(fbdefio->mapping, pgoff, 275 + mapping_wrprotect_range(fbdefio_state->mapping, pgoff, 400 276 page_to_pfn(page), 1); 401 277 } 402 278 #endif 403 279 404 280 /* driver's callback with pagereflist */ 405 - fbdefio->deferred_io(info, &fbdefio->pagereflist); 281 + fbdefio->deferred_io(info, &fbdefio_state->pagereflist); 406 282 407 283 /* clear the list */ 408 - list_for_each_entry_safe(pageref, next, &fbdefio->pagereflist, list) 284 + list_for_each_entry_safe(pageref, next, &fbdefio_state->pagereflist, list) 409 285 fb_deferred_io_pageref_put(pageref, info); 410 286 411 - mutex_unlock(&fbdefio->lock); 287 + mutex_unlock(&fbdefio_state->lock); 412 288 } 413 289 414 290 int fb_deferred_io_init(struct fb_info *info) 415 291 { 416 292 struct fb_deferred_io *fbdefio = info->fbdefio; 417 - struct fb_deferred_io_pageref *pagerefs; 418 - unsigned long npagerefs; 419 - int ret; 293 + struct fb_deferred_io_state *fbdefio_state; 420 294 421 295 BUG_ON(!fbdefio); 422 296 423 297 if (WARN_ON(!info->fix.smem_len)) 424 298 return -EINVAL; 425 299 426 - mutex_init(&fbdefio->lock); 300 + fbdefio_state = fb_deferred_io_state_alloc(info->fix.smem_len); 301 + if (!fbdefio_state) 302 + return -ENOMEM; 303 + fbdefio_state->info = info; 304 + 427 305 INIT_DELAYED_WORK(&info->deferred_work, fb_deferred_io_work); 428 - INIT_LIST_HEAD(&fbdefio->pagereflist); 429 306 if (fbdefio->delay == 0) /* set a default of 1 s */ 430 307 fbdefio->delay = HZ; 431 308 432 - npagerefs = DIV_ROUND_UP(info->fix.smem_len, PAGE_SIZE); 433 - 434 - /* alloc a page ref for each page of the display memory */ 435 - pagerefs = kvzalloc_objs(*pagerefs, npagerefs); 436 - if (!pagerefs) { 437 - ret = -ENOMEM; 438 - goto err; 439 - } 440 - info->npagerefs = npagerefs; 441 - info->pagerefs = pagerefs; 309 + info->fbdefio_state = fbdefio_state; 442 310 443 311 return 0; 444 - 445 - err: 446 - mutex_destroy(&fbdefio->lock); 447 - return ret; 448 312 } 449 313 EXPORT_SYMBOL_GPL(fb_deferred_io_init); 450 314 ··· 441 327 struct inode *inode, 442 328 struct file *file) 443 329 { 444 - struct fb_deferred_io *fbdefio = info->fbdefio; 330 + struct fb_deferred_io_state *fbdefio_state = info->fbdefio_state; 445 331 446 - fbdefio->mapping = file->f_mapping; 332 + fbdefio_state->mapping = file->f_mapping; 447 333 file->f_mapping->a_ops = &fb_deferred_io_aops; 448 - fbdefio->open_count++; 334 + fbdefio_state->open_count++; 449 335 } 450 336 EXPORT_SYMBOL_GPL(fb_deferred_io_open); 451 337 ··· 456 342 457 343 void fb_deferred_io_release(struct fb_info *info) 458 344 { 459 - struct fb_deferred_io *fbdefio = info->fbdefio; 345 + struct fb_deferred_io_state *fbdefio_state = info->fbdefio_state; 460 346 461 - if (!--fbdefio->open_count) 347 + if (!--fbdefio_state->open_count) 462 348 fb_deferred_io_lastclose(info); 463 349 } 464 350 EXPORT_SYMBOL_GPL(fb_deferred_io_release); 465 351 466 352 void fb_deferred_io_cleanup(struct fb_info *info) 467 353 { 468 - struct fb_deferred_io *fbdefio = info->fbdefio; 354 + struct fb_deferred_io_state *fbdefio_state = info->fbdefio_state; 469 355 470 356 fb_deferred_io_lastclose(info); 471 357 472 - kvfree(info->pagerefs); 473 - mutex_destroy(&fbdefio->lock); 474 - fbdefio->mapping = NULL; 358 + info->fbdefio_state = NULL; 359 + 360 + mutex_lock(&fbdefio_state->lock); 361 + fbdefio_state->info = NULL; 362 + mutex_unlock(&fbdefio_state->lock); 363 + 364 + fb_deferred_io_state_put(fbdefio_state); 475 365 } 476 366 EXPORT_SYMBOL_GPL(fb_deferred_io_cleanup);
+99 -143
drivers/video/fbdev/core/fbcon.c
··· 446 446 cancel_delayed_work_sync(&par->cursor_work); 447 447 } 448 448 449 + void fbcon_fill_cursor_mask(struct fbcon_par *par, struct vc_data *vc, unsigned char *mask) 450 + { 451 + static const unsigned int pattern = 0xffffffff; 452 + unsigned int pitch = vc_font_pitch(&vc->vc_font); 453 + unsigned int cur_height, size; 454 + 455 + switch (CUR_SIZE(vc->vc_cursor_type)) { 456 + case CUR_NONE: 457 + cur_height = 0; 458 + break; 459 + case CUR_UNDERLINE: 460 + if (vc->vc_font.height < 10) 461 + cur_height = 1; 462 + else 463 + cur_height = 2; 464 + break; 465 + case CUR_LOWER_THIRD: 466 + cur_height = vc->vc_font.height / 3; 467 + break; 468 + case CUR_LOWER_HALF: 469 + cur_height = vc->vc_font.height / 2; 470 + break; 471 + case CUR_TWO_THIRDS: 472 + cur_height = (vc->vc_font.height * 2) / 3; 473 + break; 474 + case CUR_BLOCK: 475 + default: 476 + cur_height = vc->vc_font.height; 477 + break; 478 + } 479 + 480 + size = (vc->vc_font.height - cur_height) * pitch; 481 + while (size--) 482 + *mask++ = (unsigned char)~pattern; 483 + 484 + size = cur_height * pitch; 485 + while (size--) 486 + *mask++ = (unsigned char)pattern; 487 + } 488 + 449 489 #ifndef MODULE 450 490 static int __init fb_console_setup(char *this_opt) 451 491 { ··· 787 747 kfree(par->cursor_state.mask); 788 748 kfree(par->cursor_data); 789 749 kfree(par->cursor_src); 790 - kfree(par->fontbuffer); 750 + #ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION 751 + kfree(par->rotated.buf); 752 + #endif 791 753 kfree(info->fbcon_par); 792 754 info->fbcon_par = NULL; 793 755 } ··· 1042 1000 par = info->fbcon_par; 1043 1001 par->currcon = -1; 1044 1002 par->graphics = 1; 1045 - par->cur_rotate = -1; 1003 + #ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION 1004 + par->rotated.buf_rotate = -1; 1005 + #endif 1046 1006 1047 1007 p->con_rotate = initial_rotation; 1048 1008 if (p->con_rotate == -1) ··· 1063 1019 info->pixmap.blit_y); 1064 1020 vc->vc_font.width = font->width; 1065 1021 vc->vc_font.height = font->height; 1066 - vc->vc_font.data = (void *)(p->fontdata = font->data); 1022 + vc->vc_font.data = font_data_buf(font->data); 1067 1023 vc->vc_font.charcount = font->charcount; 1024 + 1025 + p->fontdata = font->data; 1026 + font_data_get(p->fontdata); 1068 1027 } 1069 1028 1070 1029 cols = FBCON_SWAP(par->rotate, info->var.xres, info->var.yres); ··· 1125 1078 if (t->fontdata) { 1126 1079 struct vc_data *fvc = vc_cons[fg_console].d; 1127 1080 1128 - vc->vc_font.data = (void *)(p->fontdata = 1129 - fvc->vc_font.data); 1081 + vc->vc_font.data = fvc->vc_font.data; 1130 1082 vc->vc_font.width = fvc->vc_font.width; 1131 1083 vc->vc_font.height = fvc->vc_font.height; 1132 1084 vc->vc_font.charcount = fvc->vc_font.charcount; 1133 - p->userfont = t->userfont; 1134 1085 1135 - if (p->userfont) 1136 - REFCOUNT(p->fontdata)++; 1086 + p->fontdata = t->fontdata; 1087 + font_data_get(p->fontdata); 1137 1088 } else { 1138 1089 const struct font_desc *font = NULL; 1139 1090 ··· 1142 1097 info->pixmap.blit_y); 1143 1098 vc->vc_font.width = font->width; 1144 1099 vc->vc_font.height = font->height; 1145 - vc->vc_font.data = (void *)(p->fontdata = font->data); 1100 + vc->vc_font.data = font_data_buf(font->data); 1146 1101 vc->vc_font.charcount = font->charcount; 1102 + 1103 + p->fontdata = font->data; 1104 + font_data_get(p->fontdata); 1147 1105 } 1148 1106 } 1149 1107 ··· 1237 1189 1238 1190 static void fbcon_free_font(struct fbcon_display *p) 1239 1191 { 1240 - if (p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0)) 1241 - kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int)); 1242 - p->fontdata = NULL; 1243 - p->userfont = 0; 1192 + if (p->fontdata) { 1193 + font_data_put(p->fontdata); 1194 + p->fontdata = NULL; 1195 + } 1244 1196 } 1245 1197 1246 1198 static void set_vc_hi_font(struct vc_data *vc, bool set); ··· 1457 1409 svc = *default_mode; 1458 1410 t = &fb_display[svc->vc_num]; 1459 1411 1460 - if (!vc->vc_font.data) { 1461 - vc->vc_font.data = (void *)(p->fontdata = t->fontdata); 1412 + if (!p->fontdata) { 1413 + vc->vc_font.data = font_data_buf(t->fontdata); 1462 1414 vc->vc_font.width = (*default_mode)->vc_font.width; 1463 1415 vc->vc_font.height = (*default_mode)->vc_font.height; 1464 1416 vc->vc_font.charcount = (*default_mode)->vc_font.charcount; 1465 - p->userfont = t->userfont; 1466 - if (p->userfont) 1467 - REFCOUNT(p->fontdata)++; 1417 + p->fontdata = t->fontdata; 1418 + font_data_get(p->fontdata); 1468 1419 } 1469 1420 1470 1421 var->activate = FB_ACTIVATE_NOW; ··· 2083 2036 updatescrollmode_accel(p, info, vc); 2084 2037 } 2085 2038 2086 - #define PITCH(w) (((w) + 7) >> 3) 2087 - #define CALC_FONTSZ(h, p, c) ((h) * (p) * (c)) /* size = height * pitch * charcount */ 2088 - 2089 2039 static int fbcon_resize(struct vc_data *vc, unsigned int width, 2090 2040 unsigned int height, bool from_user) 2091 2041 { ··· 2092 2048 struct fb_var_screeninfo var = info->var; 2093 2049 int x_diff, y_diff, virt_w, virt_h, virt_fw, virt_fh; 2094 2050 2095 - if (p->userfont && FNTSIZE(vc->vc_font.data)) { 2096 - int size; 2097 - int pitch = PITCH(vc->vc_font.width); 2051 + if (font_data_size(p->fontdata)) { 2052 + unsigned int size = vc_font_size(&vc->vc_font); 2098 2053 2099 2054 /* 2100 2055 * If user font, ensure that a possible change to user font ··· 2102 2059 * charcount can change and cannot be used to determine the 2103 2060 * font data allocated size. 2104 2061 */ 2105 - if (pitch <= 0) 2106 - return -EINVAL; 2107 - size = CALC_FONTSZ(vc->vc_font.height, pitch, vc->vc_font.charcount); 2108 - if (size > FNTSIZE(vc->vc_font.data)) 2062 + if (!size || size > font_data_size(p->fontdata)) 2109 2063 return -EINVAL; 2110 2064 } 2111 2065 ··· 2326 2286 2327 2287 static int fbcon_get_font(struct vc_data *vc, struct console_font *font, unsigned int vpitch) 2328 2288 { 2329 - u8 *fontdata = vc->vc_font.data; 2330 - u8 *data = font->data; 2331 - int i, j; 2289 + const struct fbcon_display *p = &fb_display[vc->vc_num]; 2332 2290 2333 2291 font->width = vc->vc_font.width; 2334 2292 font->height = vc->vc_font.height; 2335 2293 if (font->height > vpitch) 2336 2294 return -ENOSPC; 2337 2295 font->charcount = vc->vc_hi_font_mask ? 512 : 256; 2338 - if (!font->data) 2339 - return 0; 2340 2296 2341 - if (font->width <= 8) { 2342 - j = vc->vc_font.height; 2343 - if (font->charcount * j > FNTSIZE(fontdata)) 2344 - return -EINVAL; 2345 - 2346 - for (i = 0; i < font->charcount; i++) { 2347 - memcpy(data, fontdata, j); 2348 - memset(data + j, 0, vpitch - j); 2349 - data += vpitch; 2350 - fontdata += j; 2351 - } 2352 - } else if (font->width <= 16) { 2353 - j = vc->vc_font.height * 2; 2354 - if (font->charcount * j > FNTSIZE(fontdata)) 2355 - return -EINVAL; 2356 - 2357 - for (i = 0; i < font->charcount; i++) { 2358 - memcpy(data, fontdata, j); 2359 - memset(data + j, 0, 2*vpitch - j); 2360 - data += 2*vpitch; 2361 - fontdata += j; 2362 - } 2363 - } else if (font->width <= 24) { 2364 - if (font->charcount * (vc->vc_font.height * sizeof(u32)) > FNTSIZE(fontdata)) 2365 - return -EINVAL; 2366 - 2367 - for (i = 0; i < font->charcount; i++) { 2368 - for (j = 0; j < vc->vc_font.height; j++) { 2369 - *data++ = fontdata[0]; 2370 - *data++ = fontdata[1]; 2371 - *data++ = fontdata[2]; 2372 - fontdata += sizeof(u32); 2373 - } 2374 - memset(data, 0, 3 * (vpitch - j)); 2375 - data += 3 * (vpitch - j); 2376 - } 2377 - } else { 2378 - j = vc->vc_font.height * 4; 2379 - if (font->charcount * j > FNTSIZE(fontdata)) 2380 - return -EINVAL; 2381 - 2382 - for (i = 0; i < font->charcount; i++) { 2383 - memcpy(data, fontdata, j); 2384 - memset(data + j, 0, 4 * vpitch - j); 2385 - data += 4 * vpitch; 2386 - fontdata += j; 2387 - } 2388 - } 2389 - return 0; 2297 + return font_data_export(p->fontdata, font, vpitch); 2390 2298 } 2391 2299 2392 2300 /* set/clear vc_hi_font_mask and update vc attrs accordingly */ ··· 2399 2411 } 2400 2412 2401 2413 static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount, 2402 - const u8 * data, int userfont) 2414 + font_data_t *data) 2403 2415 { 2404 2416 struct fb_info *info = fbcon_info_from_console(vc->vc_num); 2405 2417 struct fbcon_par *par = info->fbcon_par; 2406 2418 struct fbcon_display *p = &fb_display[vc->vc_num]; 2407 - int resize, ret, old_userfont, old_width, old_height, old_charcount; 2408 - u8 *old_data = vc->vc_font.data; 2419 + int resize, ret, old_width, old_height, old_charcount; 2420 + font_data_t *old_fontdata = p->fontdata; 2421 + const u8 *old_data = vc->vc_font.data; 2422 + 2423 + font_data_get(data); 2409 2424 2410 2425 resize = (w != vc->vc_font.width) || (h != vc->vc_font.height); 2411 - vc->vc_font.data = (void *)(p->fontdata = data); 2412 - old_userfont = p->userfont; 2413 - if ((p->userfont = userfont)) 2414 - REFCOUNT(data)++; 2415 - 2426 + p->fontdata = data; 2427 + vc->vc_font.data = font_data_buf(p->fontdata); 2416 2428 old_width = vc->vc_font.width; 2417 2429 old_height = vc->vc_font.height; 2418 2430 old_charcount = vc->vc_font.charcount; ··· 2441 2453 update_screen(vc); 2442 2454 } 2443 2455 2444 - if (old_userfont && (--REFCOUNT(old_data) == 0)) 2445 - kfree(old_data - FONT_EXTRA_WORDS * sizeof(int)); 2456 + if (old_fontdata) 2457 + font_data_put(old_fontdata); 2458 + 2446 2459 return 0; 2447 2460 2448 2461 err_out: 2449 - p->fontdata = old_data; 2462 + p->fontdata = old_fontdata; 2450 2463 vc->vc_font.data = old_data; 2451 - 2452 - if (userfont) { 2453 - p->userfont = old_userfont; 2454 - if (--REFCOUNT(data) == 0) 2455 - kfree(data - FONT_EXTRA_WORDS * sizeof(int)); 2456 - } 2457 - 2458 2464 vc->vc_font.width = old_width; 2459 2465 vc->vc_font.height = old_height; 2460 2466 vc->vc_font.charcount = old_charcount; 2467 + 2468 + font_data_put(data); 2461 2469 2462 2470 return ret; 2463 2471 } ··· 2470 2486 unsigned charcount = font->charcount; 2471 2487 int w = font->width; 2472 2488 int h = font->height; 2473 - int size, alloc_size; 2474 - int i, csum; 2475 - u8 *new_data, *data = font->data; 2476 - int pitch = PITCH(font->width); 2489 + int i, ret; 2490 + font_data_t *new_data; 2477 2491 2478 2492 /* Is there a reason why fbconsole couldn't handle any charcount >256? 2479 2493 * If not this check should be changed to charcount < 256 */ ··· 2495 2513 if (fbcon_invalid_charcount(info, charcount)) 2496 2514 return -EINVAL; 2497 2515 2498 - /* Check for integer overflow in font size calculation */ 2499 - if (check_mul_overflow(h, pitch, &size) || 2500 - check_mul_overflow(size, charcount, &size)) 2501 - return -EINVAL; 2516 + new_data = font_data_import(font, vpitch, crc32); 2517 + if (IS_ERR(new_data)) 2518 + return PTR_ERR(new_data); 2502 2519 2503 - /* Check for overflow in allocation size calculation */ 2504 - if (check_add_overflow(FONT_EXTRA_WORDS * sizeof(int), size, &alloc_size)) 2505 - return -EINVAL; 2506 - 2507 - new_data = kmalloc(alloc_size, GFP_USER); 2508 - 2509 - if (!new_data) 2510 - return -ENOMEM; 2511 - 2512 - memset(new_data, 0, FONT_EXTRA_WORDS * sizeof(int)); 2513 - 2514 - new_data += FONT_EXTRA_WORDS * sizeof(int); 2515 - FNTSIZE(new_data) = size; 2516 - REFCOUNT(new_data) = 0; /* usage counter */ 2517 - for (i=0; i< charcount; i++) { 2518 - memcpy(new_data + i*h*pitch, data + i*vpitch*pitch, h*pitch); 2519 - } 2520 - 2521 - /* Since linux has a nice crc32 function use it for counting font 2522 - * checksums. */ 2523 - csum = crc32(0, new_data, size); 2524 - 2525 - FNTSUM(new_data) = csum; 2526 2520 /* Check if the same font is on some other console already */ 2527 2521 for (i = first_fb_vc; i <= last_fb_vc; i++) { 2528 - struct vc_data *tmp = vc_cons[i].d; 2529 - 2530 - if (fb_display[i].userfont && 2531 - fb_display[i].fontdata && 2532 - FNTSUM(fb_display[i].fontdata) == csum && 2533 - FNTSIZE(fb_display[i].fontdata) == size && 2534 - tmp->vc_font.width == w && 2535 - !memcmp(fb_display[i].fontdata, new_data, size)) { 2536 - kfree(new_data - FONT_EXTRA_WORDS * sizeof(int)); 2537 - new_data = (u8 *)fb_display[i].fontdata; 2522 + if (fb_display[i].fontdata && 2523 + font_data_is_equal(fb_display[i].fontdata, new_data)) { 2524 + font_data_get(fb_display[i].fontdata); 2525 + font_data_put(new_data); 2526 + new_data = fb_display[i].fontdata; 2538 2527 break; 2539 2528 } 2540 2529 } 2541 - return fbcon_do_set_font(vc, font->width, font->height, charcount, new_data, 1); 2530 + ret = fbcon_do_set_font(vc, font->width, font->height, charcount, new_data); 2531 + font_data_put(new_data); 2532 + 2533 + return ret; 2542 2534 } 2543 2535 2544 2536 static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, ··· 2529 2573 2530 2574 font->width = f->width; 2531 2575 font->height = f->height; 2532 - return fbcon_do_set_font(vc, f->width, f->height, f->charcount, f->data, 0); 2576 + return fbcon_do_set_font(vc, f->width, f->height, f->charcount, f->data); 2533 2577 } 2534 2578 2535 2579 static u16 palette_red[16];
+12 -6
drivers/video/fbdev/core/fbcon.h
··· 11 11 #ifndef _VIDEO_FBCON_H 12 12 #define _VIDEO_FBCON_H 13 13 14 + #include <linux/font.h> 14 15 #include <linux/types.h> 15 16 #include <linux/vt_buffer.h> 16 17 #include <linux/vt_kern.h> ··· 26 25 27 26 struct fbcon_display { 28 27 /* Filled in by the low-level console driver */ 29 - const u_char *fontdata; 30 - int userfont; /* != 0 if fontdata kmalloc()ed */ 28 + font_data_t *fontdata; 31 29 #ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION 32 30 u_short scrollmode; /* Scroll Method, use fb_scrollmode() */ 33 31 #endif ··· 80 80 int graphics; 81 81 bool initialized; 82 82 int rotate; 83 - int cur_rotate; 84 83 char *cursor_data; 85 - u8 *fontbuffer; 86 - u8 *fontdata; 84 + #ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION 85 + struct { 86 + font_data_t *fontdata; /* source font */ 87 + u8 *buf; /* rotated glyphs */ 88 + size_t bufsize; 89 + int buf_rotate; /* rotation of buf */ 90 + } rotated; 91 + #endif 87 92 u8 *cursor_src; 88 93 u32 cursor_size; 89 - u32 fd_size; 90 94 91 95 const struct fbcon_bitops *bitops; 92 96 }; ··· 195 191 #endif 196 192 extern void fbcon_set_bitops_ur(struct fbcon_par *par); 197 193 extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor); 194 + 195 + void fbcon_fill_cursor_mask(struct fbcon_par *par, struct vc_data *vc, unsigned char *mask); 198 196 199 197 #define FBCON_ATTRIBUTE_UNDERLINE 1 200 198 #define FBCON_ATTRIBUTE_REVERSE 2
+20 -50
drivers/video/fbdev/core/fbcon_ccw.c
··· 12 12 #include <linux/slab.h> 13 13 #include <linux/string.h> 14 14 #include <linux/fb.h> 15 + #include <linux/font.h> 15 16 #include <linux/vt_kern.h> 16 17 #include <linux/console.h> 17 18 #include <asm/types.h> ··· 27 26 struct vc_data *vc) 28 27 { 29 28 int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2; 30 - int width = (vc->vc_font.height + 7) >> 3; 29 + int width = font_glyph_pitch(vc->vc_font.height); 31 30 int mod = vc->vc_font.height % 8; 32 31 u8 c, msk = ~(0xff << offset), msk1 = 0; 33 32 ··· 102 101 { 103 102 struct fbcon_par *par = info->fbcon_par; 104 103 u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; 105 - u32 idx = (vc->vc_font.height + 7) >> 3; 104 + u32 idx = font_glyph_pitch(vc->vc_font.height); 106 105 u8 *src; 107 106 108 107 while (cnt--) { 109 - src = par->fontbuffer + (scr_readw(s--) & charmask) * cellsize; 108 + src = par->rotated.buf + (scr_readw(s--) & charmask) * cellsize; 110 109 111 110 if (attr) { 112 111 ccw_update_attr(buf, src, attr, vc); ··· 132 131 { 133 132 struct fb_image image; 134 133 struct fbcon_par *par = info->fbcon_par; 135 - u32 width = (vc->vc_font.height + 7)/8; 134 + u32 width = font_glyph_pitch(vc->vc_font.height); 136 135 u32 cellsize = width * vc->vc_font.width; 137 136 u32 maxcnt = info->pixmap.size/cellsize; 138 137 u32 scan_align = info->pixmap.scan_align - 1; ··· 142 141 u8 *dst, *buf = NULL; 143 142 u32 vyres = GETVYRES(par->p, info); 144 143 145 - if (!par->fontbuffer) 144 + if (!par->rotated.buf) 146 145 return; 147 146 148 147 image.fg_color = fg; ··· 224 223 struct fb_cursor cursor; 225 224 struct fbcon_par *par = info->fbcon_par; 226 225 unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; 227 - int w = (vc->vc_font.height + 7) >> 3, c; 226 + int w = font_glyph_pitch(vc->vc_font.height); 227 + int c; 228 228 int y = real_y(par->p, vc->state.y); 229 229 int attribute, use_sw = vc->vc_cursor_type & CUR_SW; 230 230 int err = 1, dx, dy; 231 231 char *src; 232 232 u32 vyres = GETVYRES(par->p, info); 233 233 234 - if (!par->fontbuffer) 234 + if (!par->rotated.buf) 235 235 return; 236 236 237 237 cursor.set = 0; 238 238 239 239 c = scr_readw((u16 *) vc->vc_pos); 240 240 attribute = get_attribute(info, c); 241 - src = par->fontbuffer + ((c & charmask) * (w * vc->vc_font.width)); 241 + src = par->rotated.buf + ((c & charmask) * (w * vc->vc_font.width)); 242 242 243 243 if (par->cursor_state.image.data != src || 244 244 par->cursor_reset) { ··· 296 294 vc->vc_cursor_type != par->p->cursor_shape || 297 295 par->cursor_state.mask == NULL || 298 296 par->cursor_reset) { 299 - char *tmp, *mask = kmalloc_array(w, vc->vc_font.width, 300 - GFP_ATOMIC); 301 - int cur_height, size, i = 0; 302 - int width = (vc->vc_font.width + 7)/8; 297 + unsigned char *tmp, *mask; 303 298 304 - if (!mask) 299 + tmp = kmalloc_array(vc->vc_font.height, vc_font_pitch(&vc->vc_font), GFP_ATOMIC); 300 + if (!tmp) 305 301 return; 302 + fbcon_fill_cursor_mask(par, vc, tmp); 306 303 307 - tmp = kmalloc_array(width, vc->vc_font.height, GFP_ATOMIC); 308 - 309 - if (!tmp) { 310 - kfree(mask); 304 + mask = kmalloc_array(vc->vc_font.width, w, GFP_ATOMIC); 305 + if (!mask) { 306 + kfree(tmp); 311 307 return; 312 308 } 309 + font_glyph_rotate_270(tmp, vc->vc_font.width, vc->vc_font.height, mask); 310 + kfree(tmp); 313 311 314 312 kfree(par->cursor_state.mask); 315 - par->cursor_state.mask = mask; 313 + par->cursor_state.mask = (const char *)mask; 316 314 317 315 par->p->cursor_shape = vc->vc_cursor_type; 318 316 cursor.set |= FB_CUR_SETSHAPE; 319 - 320 - switch (CUR_SIZE(par->p->cursor_shape)) { 321 - case CUR_NONE: 322 - cur_height = 0; 323 - break; 324 - case CUR_UNDERLINE: 325 - cur_height = (vc->vc_font.height < 10) ? 1 : 2; 326 - break; 327 - case CUR_LOWER_THIRD: 328 - cur_height = vc->vc_font.height/3; 329 - break; 330 - case CUR_LOWER_HALF: 331 - cur_height = vc->vc_font.height >> 1; 332 - break; 333 - case CUR_TWO_THIRDS: 334 - cur_height = (vc->vc_font.height << 1)/3; 335 - break; 336 - case CUR_BLOCK: 337 - default: 338 - cur_height = vc->vc_font.height; 339 - break; 340 - } 341 - 342 - size = (vc->vc_font.height - cur_height) * width; 343 - while (size--) 344 - tmp[i++] = 0; 345 - size = cur_height * width; 346 - while (size--) 347 - tmp[i++] = 0xff; 348 - memset(mask, 0, w * vc->vc_font.width); 349 - rotate_ccw(tmp, mask, vc->vc_font.width, vc->vc_font.height); 350 - kfree(tmp); 351 317 } 352 318 353 319 par->cursor_state.enable = enable && !use_sw;
+20 -50
drivers/video/fbdev/core/fbcon_cw.c
··· 12 12 #include <linux/slab.h> 13 13 #include <linux/string.h> 14 14 #include <linux/fb.h> 15 + #include <linux/font.h> 15 16 #include <linux/vt_kern.h> 16 17 #include <linux/console.h> 17 18 #include <asm/types.h> ··· 27 26 struct vc_data *vc) 28 27 { 29 28 int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2; 30 - int width = (vc->vc_font.height + 7) >> 3; 29 + int width = font_glyph_pitch(vc->vc_font.height); 31 30 u8 c, msk = ~(0xff >> offset); 32 31 33 32 for (i = 0; i < vc->vc_font.width; i++) { ··· 87 86 { 88 87 struct fbcon_par *par = info->fbcon_par; 89 88 u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; 90 - u32 idx = (vc->vc_font.height + 7) >> 3; 89 + u32 idx = font_glyph_pitch(vc->vc_font.height); 91 90 u8 *src; 92 91 93 92 while (cnt--) { 94 - src = par->fontbuffer + (scr_readw(s++) & charmask) * cellsize; 93 + src = par->rotated.buf + (scr_readw(s++) & charmask) * cellsize; 95 94 96 95 if (attr) { 97 96 cw_update_attr(buf, src, attr, vc); ··· 117 116 { 118 117 struct fb_image image; 119 118 struct fbcon_par *par = info->fbcon_par; 120 - u32 width = (vc->vc_font.height + 7)/8; 119 + u32 width = font_glyph_pitch(vc->vc_font.height); 121 120 u32 cellsize = width * vc->vc_font.width; 122 121 u32 maxcnt = info->pixmap.size/cellsize; 123 122 u32 scan_align = info->pixmap.scan_align - 1; ··· 127 126 u8 *dst, *buf = NULL; 128 127 u32 vxres = GETVXRES(par->p, info); 129 128 130 - if (!par->fontbuffer) 129 + if (!par->rotated.buf) 131 130 return; 132 131 133 132 image.fg_color = fg; ··· 207 206 struct fb_cursor cursor; 208 207 struct fbcon_par *par = info->fbcon_par; 209 208 unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; 210 - int w = (vc->vc_font.height + 7) >> 3, c; 209 + int w = font_glyph_pitch(vc->vc_font.height); 210 + int c; 211 211 int y = real_y(par->p, vc->state.y); 212 212 int attribute, use_sw = vc->vc_cursor_type & CUR_SW; 213 213 int err = 1, dx, dy; 214 214 char *src; 215 215 u32 vxres = GETVXRES(par->p, info); 216 216 217 - if (!par->fontbuffer) 217 + if (!par->rotated.buf) 218 218 return; 219 219 220 220 cursor.set = 0; 221 221 222 222 c = scr_readw((u16 *) vc->vc_pos); 223 223 attribute = get_attribute(info, c); 224 - src = par->fontbuffer + ((c & charmask) * (w * vc->vc_font.width)); 224 + src = par->rotated.buf + ((c & charmask) * (w * vc->vc_font.width)); 225 225 226 226 if (par->cursor_state.image.data != src || 227 227 par->cursor_reset) { ··· 279 277 vc->vc_cursor_type != par->p->cursor_shape || 280 278 par->cursor_state.mask == NULL || 281 279 par->cursor_reset) { 282 - char *tmp, *mask = kmalloc_array(w, vc->vc_font.width, 283 - GFP_ATOMIC); 284 - int cur_height, size, i = 0; 285 - int width = (vc->vc_font.width + 7)/8; 280 + unsigned char *tmp, *mask; 286 281 287 - if (!mask) 282 + tmp = kmalloc_array(vc->vc_font.height, vc_font_pitch(&vc->vc_font), GFP_ATOMIC); 283 + if (!tmp) 288 284 return; 285 + fbcon_fill_cursor_mask(par, vc, tmp); 289 286 290 - tmp = kmalloc_array(width, vc->vc_font.height, GFP_ATOMIC); 291 - 292 - if (!tmp) { 293 - kfree(mask); 287 + mask = kmalloc_array(vc->vc_font.width, w, GFP_ATOMIC); 288 + if (!mask) { 289 + kfree(tmp); 294 290 return; 295 291 } 292 + font_glyph_rotate_90(tmp, vc->vc_font.width, vc->vc_font.height, mask); 293 + kfree(tmp); 296 294 297 295 kfree(par->cursor_state.mask); 298 - par->cursor_state.mask = mask; 296 + par->cursor_state.mask = (const char *)mask; 299 297 300 298 par->p->cursor_shape = vc->vc_cursor_type; 301 299 cursor.set |= FB_CUR_SETSHAPE; 302 - 303 - switch (CUR_SIZE(par->p->cursor_shape)) { 304 - case CUR_NONE: 305 - cur_height = 0; 306 - break; 307 - case CUR_UNDERLINE: 308 - cur_height = (vc->vc_font.height < 10) ? 1 : 2; 309 - break; 310 - case CUR_LOWER_THIRD: 311 - cur_height = vc->vc_font.height/3; 312 - break; 313 - case CUR_LOWER_HALF: 314 - cur_height = vc->vc_font.height >> 1; 315 - break; 316 - case CUR_TWO_THIRDS: 317 - cur_height = (vc->vc_font.height << 1)/3; 318 - break; 319 - case CUR_BLOCK: 320 - default: 321 - cur_height = vc->vc_font.height; 322 - break; 323 - } 324 - 325 - size = (vc->vc_font.height - cur_height) * width; 326 - while (size--) 327 - tmp[i++] = 0; 328 - size = cur_height * width; 329 - while (size--) 330 - tmp[i++] = 0xff; 331 - memset(mask, 0, w * vc->vc_font.width); 332 - rotate_cw(tmp, mask, vc->vc_font.width, vc->vc_font.height); 333 - kfree(tmp); 334 300 } 335 301 336 302 par->cursor_state.enable = enable && !use_sw;
+23 -65
drivers/video/fbdev/core/fbcon_rotate.c
··· 8 8 * more details. 9 9 */ 10 10 11 - #include <linux/module.h> 12 - #include <linux/slab.h> 13 - #include <linux/string.h> 11 + #include <linux/errno.h> 14 12 #include <linux/fb.h> 15 - #include <linux/vt_kern.h> 16 - #include <linux/console.h> 17 - #include <asm/types.h> 13 + #include <linux/font.h> 14 + 18 15 #include "fbcon.h" 19 16 #include "fbcon_rotate.h" 20 17 21 18 int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc) 22 19 { 23 20 struct fbcon_par *par = info->fbcon_par; 24 - int len, err = 0; 25 - int s_cellsize, d_cellsize, i; 26 - const u8 *src; 27 - u8 *dst; 21 + unsigned char *buf; 22 + int ret; 28 23 29 - if (vc->vc_font.data == par->fontdata && 30 - par->p->con_rotate == par->cur_rotate) 31 - goto finished; 24 + if (par->p->fontdata == par->rotated.fontdata && par->rotate == par->rotated.buf_rotate) 25 + return 0; 32 26 33 - src = par->fontdata = vc->vc_font.data; 34 - par->cur_rotate = par->p->con_rotate; 35 - len = vc->vc_font.charcount; 36 - s_cellsize = ((vc->vc_font.width + 7)/8) * 37 - vc->vc_font.height; 38 - d_cellsize = s_cellsize; 39 - 40 - if (par->rotate == FB_ROTATE_CW || 41 - par->rotate == FB_ROTATE_CCW) 42 - d_cellsize = ((vc->vc_font.height + 7)/8) * 43 - vc->vc_font.width; 27 + par->rotated.fontdata = par->p->fontdata; 28 + par->rotated.buf_rotate = par->rotate; 44 29 45 30 if (info->fbops->fb_sync) 46 31 info->fbops->fb_sync(info); 47 32 48 - if (par->fd_size < d_cellsize * len) { 49 - dst = kmalloc_array(len, d_cellsize, GFP_KERNEL); 50 - 51 - if (dst == NULL) { 52 - err = -ENOMEM; 53 - goto finished; 54 - } 55 - 56 - par->fd_size = d_cellsize * len; 57 - kfree(par->fontbuffer); 58 - par->fontbuffer = dst; 33 + buf = font_data_rotate(par->rotated.fontdata, vc->vc_font.width, 34 + vc->vc_font.height, vc->vc_font.charcount, 35 + par->rotated.buf_rotate, par->rotated.buf, 36 + &par->rotated.bufsize); 37 + if (IS_ERR(buf)) { 38 + ret = PTR_ERR(buf); 39 + goto err_kfree; 59 40 } 60 41 61 - dst = par->fontbuffer; 62 - memset(dst, 0, par->fd_size); 42 + par->rotated.buf = buf; 63 43 64 - switch (par->rotate) { 65 - case FB_ROTATE_UD: 66 - for (i = len; i--; ) { 67 - rotate_ud(src, dst, vc->vc_font.width, 68 - vc->vc_font.height); 44 + return 0; 69 45 70 - src += s_cellsize; 71 - dst += d_cellsize; 72 - } 73 - break; 74 - case FB_ROTATE_CW: 75 - for (i = len; i--; ) { 76 - rotate_cw(src, dst, vc->vc_font.width, 77 - vc->vc_font.height); 78 - src += s_cellsize; 79 - dst += d_cellsize; 80 - } 81 - break; 82 - case FB_ROTATE_CCW: 83 - for (i = len; i--; ) { 84 - rotate_ccw(src, dst, vc->vc_font.width, 85 - vc->vc_font.height); 86 - src += s_cellsize; 87 - dst += d_cellsize; 88 - } 89 - break; 90 - } 46 + err_kfree: 47 + kfree(par->rotated.buf); 48 + par->rotated.buf = NULL; /* clear here to avoid output */ 49 + par->rotated.bufsize = 0; 91 50 92 - finished: 93 - return err; 51 + return ret; 94 52 }
-71
drivers/video/fbdev/core/fbcon_rotate.h
··· 19 19 (fb_scrollmode(s) == SCROLL_REDRAW || fb_scrollmode(s) == SCROLL_MOVE || !(i)->fix.xpanstep) ? \ 20 20 (i)->var.xres : (i)->var.xres_virtual; }) 21 21 22 - 23 - static inline int pattern_test_bit(u32 x, u32 y, u32 pitch, const char *pat) 24 - { 25 - u32 tmp = (y * pitch) + x, index = tmp / 8, bit = tmp % 8; 26 - 27 - pat +=index; 28 - return (*pat) & (0x80 >> bit); 29 - } 30 - 31 - static inline void pattern_set_bit(u32 x, u32 y, u32 pitch, char *pat) 32 - { 33 - u32 tmp = (y * pitch) + x, index = tmp / 8, bit = tmp % 8; 34 - 35 - pat += index; 36 - 37 - (*pat) |= 0x80 >> bit; 38 - } 39 - 40 - static inline void rotate_ud(const char *in, char *out, u32 width, u32 height) 41 - { 42 - int i, j; 43 - int shift = (8 - (width % 8)) & 7; 44 - 45 - width = (width + 7) & ~7; 46 - 47 - for (i = 0; i < height; i++) { 48 - for (j = 0; j < width - shift; j++) { 49 - if (pattern_test_bit(j, i, width, in)) 50 - pattern_set_bit(width - (1 + j + shift), 51 - height - (1 + i), 52 - width, out); 53 - } 54 - 55 - } 56 - } 57 - 58 - static inline void rotate_cw(const char *in, char *out, u32 width, u32 height) 59 - { 60 - int i, j, h = height, w = width; 61 - int shift = (8 - (height % 8)) & 7; 62 - 63 - width = (width + 7) & ~7; 64 - height = (height + 7) & ~7; 65 - 66 - for (i = 0; i < h; i++) { 67 - for (j = 0; j < w; j++) { 68 - if (pattern_test_bit(j, i, width, in)) 69 - pattern_set_bit(height - 1 - i - shift, j, 70 - height, out); 71 - 72 - } 73 - } 74 - } 75 - 76 - static inline void rotate_ccw(const char *in, char *out, u32 width, u32 height) 77 - { 78 - int i, j, h = height, w = width; 79 - int shift = (8 - (width % 8)) & 7; 80 - 81 - width = (width + 7) & ~7; 82 - height = (height + 7) & ~7; 83 - 84 - for (i = 0; i < h; i++) { 85 - for (j = 0; j < w; j++) { 86 - if (pattern_test_bit(j, i, width, in)) 87 - pattern_set_bit(i, width - 1 - j - shift, 88 - height, out); 89 - } 90 - } 91 - } 92 - 93 22 int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc); 94 23 95 24 #if defined(CONFIG_FRAMEBUFFER_CONSOLE_ROTATION)
+22 -45
drivers/video/fbdev/core/fbcon_ud.c
··· 26 26 struct vc_data *vc) 27 27 { 28 28 int i, offset = (vc->vc_font.height < 10) ? 1 : 2; 29 - int width = (vc->vc_font.width + 7) >> 3; 29 + int width = font_glyph_pitch(vc->vc_font.width); 30 30 unsigned int cellsize = vc->vc_font.height * width; 31 31 u8 c; 32 32 ··· 92 92 u8 *src; 93 93 94 94 while (cnt--) { 95 - src = par->fontbuffer + (scr_readw(s--) & charmask) * cellsize; 95 + src = par->rotated.buf + (scr_readw(s--) & charmask) * cellsize; 96 96 97 97 if (attr) { 98 98 ud_update_attr(buf, src, attr, vc); ··· 127 127 u8 *src; 128 128 129 129 while (cnt--) { 130 - src = par->fontbuffer + (scr_readw(s--) & charmask) * cellsize; 130 + src = par->rotated.buf + (scr_readw(s--) & charmask) * cellsize; 131 131 132 132 if (attr) { 133 133 ud_update_attr(buf, src, attr, vc); ··· 153 153 { 154 154 struct fb_image image; 155 155 struct fbcon_par *par = info->fbcon_par; 156 - u32 width = (vc->vc_font.width + 7)/8; 156 + u32 width = font_glyph_pitch(vc->vc_font.width); 157 157 u32 cellsize = width * vc->vc_font.height; 158 158 u32 maxcnt = info->pixmap.size/cellsize; 159 159 u32 scan_align = info->pixmap.scan_align - 1; ··· 164 164 u32 vyres = GETVYRES(par->p, info); 165 165 u32 vxres = GETVXRES(par->p, info); 166 166 167 - if (!par->fontbuffer) 167 + if (!par->rotated.buf) 168 168 return; 169 169 170 170 image.fg_color = fg; ··· 253 253 struct fb_cursor cursor; 254 254 struct fbcon_par *par = info->fbcon_par; 255 255 unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; 256 - int w = (vc->vc_font.width + 7) >> 3, c; 256 + int w = font_glyph_pitch(vc->vc_font.width); 257 + int c; 257 258 int y = real_y(par->p, vc->state.y); 258 259 int attribute, use_sw = vc->vc_cursor_type & CUR_SW; 259 260 int err = 1, dx, dy; ··· 262 261 u32 vyres = GETVYRES(par->p, info); 263 262 u32 vxres = GETVXRES(par->p, info); 264 263 265 - if (!par->fontbuffer) 264 + if (!par->rotated.buf) 266 265 return; 267 266 268 267 cursor.set = 0; 269 268 270 269 c = scr_readw((u16 *) vc->vc_pos); 271 270 attribute = get_attribute(info, c); 272 - src = par->fontbuffer + ((c & charmask) * (w * vc->vc_font.height)); 271 + src = par->rotated.buf + ((c & charmask) * (w * vc->vc_font.height)); 273 272 274 273 if (par->cursor_state.image.data != src || 275 274 par->cursor_reset) { ··· 326 325 vc->vc_cursor_type != par->p->cursor_shape || 327 326 par->cursor_state.mask == NULL || 328 327 par->cursor_reset) { 329 - char *mask = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC); 330 - int cur_height, size, i = 0; 331 - u8 msk = 0xff; 328 + unsigned char *tmp, *mask; 332 329 333 - if (!mask) 330 + tmp = kmalloc_array(vc->vc_font.height, w, GFP_ATOMIC); 331 + if (!tmp) 334 332 return; 333 + fbcon_fill_cursor_mask(par, vc, tmp); 334 + 335 + mask = kmalloc_array(vc->vc_font.height, w, GFP_ATOMIC); 336 + if (!mask) { 337 + kfree(tmp); 338 + return; 339 + } 340 + font_glyph_rotate_180(tmp, vc->vc_font.width, vc->vc_font.height, mask); 341 + kfree(tmp); 335 342 336 343 kfree(par->cursor_state.mask); 337 - par->cursor_state.mask = mask; 344 + par->cursor_state.mask = (const char *)mask; 338 345 339 346 par->p->cursor_shape = vc->vc_cursor_type; 340 347 cursor.set |= FB_CUR_SETSHAPE; 341 - 342 - switch (CUR_SIZE(par->p->cursor_shape)) { 343 - case CUR_NONE: 344 - cur_height = 0; 345 - break; 346 - case CUR_UNDERLINE: 347 - cur_height = (vc->vc_font.height < 10) ? 1 : 2; 348 - break; 349 - case CUR_LOWER_THIRD: 350 - cur_height = vc->vc_font.height/3; 351 - break; 352 - case CUR_LOWER_HALF: 353 - cur_height = vc->vc_font.height >> 1; 354 - break; 355 - case CUR_TWO_THIRDS: 356 - cur_height = (vc->vc_font.height << 1)/3; 357 - break; 358 - case CUR_BLOCK: 359 - default: 360 - cur_height = vc->vc_font.height; 361 - break; 362 - } 363 - 364 - size = cur_height * w; 365 - 366 - while (size--) 367 - mask[i++] = msk; 368 - 369 - size = (vc->vc_font.height - cur_height) * w; 370 - 371 - while (size--) 372 - mask[i++] = ~msk; 373 348 } 374 349 375 350 par->cursor_state.enable = enable && !use_sw;
+3 -3
drivers/video/fbdev/core/fbmem.c
··· 91 91 /* 92 92 * Data padding functions. 93 93 */ 94 - void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height) 94 + void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, const u8 *src, u32 s_pitch, u32 height) 95 95 { 96 96 __fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, height); 97 97 } 98 98 EXPORT_SYMBOL(fb_pad_aligned_buffer); 99 99 100 - void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, u32 height, 101 - u32 shift_high, u32 shift_low, u32 mod) 100 + void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, const u8 *src, u32 idx, u32 height, 101 + u32 shift_high, u32 shift_low, u32 mod) 102 102 { 103 103 u8 mask = (u8) (0xff << shift_high), tmp; 104 104 int i, j;
+3 -11
drivers/video/fbdev/goldfishfb.c
··· 174 174 static int goldfish_fb_probe(struct platform_device *pdev) 175 175 { 176 176 int ret; 177 - struct resource *r; 178 177 struct goldfish_fb *fb; 179 178 size_t framesize; 180 179 u32 width, height; ··· 188 189 init_waitqueue_head(&fb->wait); 189 190 platform_set_drvdata(pdev, fb); 190 191 191 - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 192 - if (r == NULL) { 193 - ret = -ENODEV; 194 - goto err_no_io_base; 195 - } 196 - fb->reg_base = ioremap(r->start, PAGE_SIZE); 197 - if (fb->reg_base == NULL) { 198 - ret = -ENOMEM; 192 + fb->reg_base = devm_platform_ioremap_resource(pdev, 0); 193 + if (IS_ERR(fb->reg_base)) { 194 + ret = PTR_ERR(fb->reg_base); 199 195 goto err_no_io_base; 200 196 } 201 197 ··· 267 273 fb->fb.fix.smem_start); 268 274 err_alloc_screen_base_failed: 269 275 err_no_irq: 270 - iounmap(fb->reg_base); 271 276 err_no_io_base: 272 277 kfree(fb); 273 278 err_fb_alloc_failed: ··· 284 291 285 292 dma_free_coherent(&pdev->dev, framesize, (void *)fb->fb.screen_base, 286 293 fb->fb.fix.smem_start); 287 - iounmap(fb->reg_base); 288 294 kfree(fb); 289 295 } 290 296
+19 -19
drivers/video/fbdev/macfb.c
··· 668 668 669 669 switch(ndev->dr_hw) { 670 670 case NUBUS_DRHW_APPLE_MDC: 671 - strcpy(macfb_fix.id, "Mac Disp. Card"); 671 + strscpy(macfb_fix.id, "Mac Disp. Card"); 672 672 macfb_setpalette = mdc_setpalette; 673 673 break; 674 674 case NUBUS_DRHW_APPLE_TFB: 675 - strcpy(macfb_fix.id, "Toby"); 675 + strscpy(macfb_fix.id, "Toby"); 676 676 macfb_setpalette = toby_setpalette; 677 677 break; 678 678 case NUBUS_DRHW_APPLE_JET: 679 - strcpy(macfb_fix.id, "Jet"); 679 + strscpy(macfb_fix.id, "Jet"); 680 680 macfb_setpalette = jet_setpalette; 681 681 break; 682 682 default: 683 - strcpy(macfb_fix.id, "Generic NuBus"); 683 + strscpy(macfb_fix.id, "Generic NuBus"); 684 684 break; 685 685 } 686 686 } ··· 707 707 case MAC_MODEL_Q700: 708 708 case MAC_MODEL_Q900: 709 709 case MAC_MODEL_Q950: 710 - strcpy(macfb_fix.id, "DAFB"); 710 + strscpy(macfb_fix.id, "DAFB"); 711 711 macfb_setpalette = dafb_setpalette; 712 712 dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000); 713 713 break; ··· 716 716 * LC II uses the V8 framebuffer 717 717 */ 718 718 case MAC_MODEL_LCII: 719 - strcpy(macfb_fix.id, "V8"); 719 + strscpy(macfb_fix.id, "V8"); 720 720 macfb_setpalette = v8_brazil_setpalette; 721 721 v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); 722 722 break; ··· 729 729 case MAC_MODEL_IIVI: 730 730 case MAC_MODEL_IIVX: 731 731 case MAC_MODEL_P600: 732 - strcpy(macfb_fix.id, "Brazil"); 732 + strscpy(macfb_fix.id, "Brazil"); 733 733 macfb_setpalette = v8_brazil_setpalette; 734 734 v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); 735 735 break; ··· 745 745 case MAC_MODEL_P520: 746 746 case MAC_MODEL_P550: 747 747 case MAC_MODEL_P460: 748 - strcpy(macfb_fix.id, "Sonora"); 748 + strscpy(macfb_fix.id, "Sonora"); 749 749 macfb_setpalette = v8_brazil_setpalette; 750 750 v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000); 751 751 break; ··· 757 757 */ 758 758 case MAC_MODEL_IICI: 759 759 case MAC_MODEL_IISI: 760 - strcpy(macfb_fix.id, "RBV"); 760 + strscpy(macfb_fix.id, "RBV"); 761 761 macfb_setpalette = rbv_setpalette; 762 762 rbv_cmap_regs = ioremap(DAC_BASE, 0x1000); 763 763 break; ··· 767 767 */ 768 768 case MAC_MODEL_Q840: 769 769 case MAC_MODEL_C660: 770 - strcpy(macfb_fix.id, "Civic"); 770 + strscpy(macfb_fix.id, "Civic"); 771 771 macfb_setpalette = civic_setpalette; 772 772 civic_cmap_regs = ioremap(CIVIC_BASE, 0x1000); 773 773 break; ··· 778 778 * We think this may be like the LC II 779 779 */ 780 780 case MAC_MODEL_LC: 781 - strcpy(macfb_fix.id, "LC"); 781 + strscpy(macfb_fix.id, "LC"); 782 782 if (vidtest) { 783 783 macfb_setpalette = v8_brazil_setpalette; 784 784 v8_brazil_cmap_regs = ··· 790 790 * We think this may be like the LC II 791 791 */ 792 792 case MAC_MODEL_CCL: 793 - strcpy(macfb_fix.id, "Color Classic"); 793 + strscpy(macfb_fix.id, "Color Classic"); 794 794 if (vidtest) { 795 795 macfb_setpalette = v8_brazil_setpalette; 796 796 v8_brazil_cmap_regs = ··· 802 802 * And we *do* mean "weirdos" 803 803 */ 804 804 case MAC_MODEL_TV: 805 - strcpy(macfb_fix.id, "Mac TV"); 805 + strscpy(macfb_fix.id, "Mac TV"); 806 806 break; 807 807 808 808 /* ··· 810 810 */ 811 811 case MAC_MODEL_SE30: 812 812 case MAC_MODEL_CLII: 813 - strcpy(macfb_fix.id, "Monochrome"); 813 + strscpy(macfb_fix.id, "Monochrome"); 814 814 break; 815 815 816 816 /* ··· 828 828 case MAC_MODEL_PB140: 829 829 case MAC_MODEL_PB145: 830 830 case MAC_MODEL_PB170: 831 - strcpy(macfb_fix.id, "DDC"); 831 + strscpy(macfb_fix.id, "DDC"); 832 832 break; 833 833 834 834 /* ··· 840 840 case MAC_MODEL_PB180: 841 841 case MAC_MODEL_PB210: 842 842 case MAC_MODEL_PB230: 843 - strcpy(macfb_fix.id, "GSC"); 843 + strscpy(macfb_fix.id, "GSC"); 844 844 break; 845 845 846 846 /* ··· 848 848 */ 849 849 case MAC_MODEL_PB165C: 850 850 case MAC_MODEL_PB180C: 851 - strcpy(macfb_fix.id, "TIM"); 851 + strscpy(macfb_fix.id, "TIM"); 852 852 break; 853 853 854 854 /* ··· 860 860 case MAC_MODEL_PB270C: 861 861 case MAC_MODEL_PB280: 862 862 case MAC_MODEL_PB280C: 863 - strcpy(macfb_fix.id, "CSC"); 863 + strscpy(macfb_fix.id, "CSC"); 864 864 macfb_setpalette = csc_setpalette; 865 865 csc_cmap_regs = ioremap(CSC_BASE, 0x1000); 866 866 break; 867 867 868 868 default: 869 - strcpy(macfb_fix.id, "Unknown"); 869 + strscpy(macfb_fix.id, "Unknown"); 870 870 break; 871 871 } 872 872
+1 -1
drivers/video/fbdev/matrox/g450_pll.c
··· 409 409 case M_VIDEO_PLL: 410 410 { 411 411 u_int8_t tmp; 412 - unsigned int mnp; 412 + unsigned int mnp __maybe_unused; 413 413 unsigned long flags; 414 414 415 415 matroxfb_DAC_lock_irqsave(flags);
+4
drivers/video/fbdev/omap/hwa742.c
··· 950 950 omapfb_conf = dev_get_platdata(fbdev->dev); 951 951 952 952 hwa742.sys_ck = clk_get(NULL, "hwa_sys_ck"); 953 + if (IS_ERR(hwa742.sys_ck)) 954 + return PTR_ERR(hwa742.sys_ck); 953 955 954 956 spin_lock_init(&hwa742.req_lock); 955 957 ··· 1030 1028 err2: 1031 1029 hwa742.int_ctrl->cleanup(); 1032 1030 err1: 1031 + clk_put(hwa742.sys_ck); 1033 1032 return r; 1034 1033 } 1035 1034 ··· 1040 1037 hwa742.extif->cleanup(); 1041 1038 hwa742.int_ctrl->cleanup(); 1042 1039 clk_disable_unprepare(hwa742.sys_ck); 1040 + clk_put(hwa742.sys_ck); 1043 1041 } 1044 1042 1045 1043 struct lcd_ctrl hwa742_ctrl = {
+1 -1
drivers/video/fbdev/omap2/omapfb/omapfb-main.c
··· 1121 1121 return 0; 1122 1122 1123 1123 error: 1124 - omapfb_put_mem_region(ofbi->region); 1124 + omapfb_put_mem_region(rg); 1125 1125 1126 1126 return r; 1127 1127 }
+55 -51
drivers/video/fbdev/tdfxfb.c
··· 77 77 #include <asm/io.h> 78 78 79 79 #include <video/tdfx.h> 80 + #include <video/vga.h> 80 81 81 82 #define DPRINTK(a, b...) pr_debug("fb: %s: " a, __func__ , ## b) 82 83 ··· 497 496 } 498 497 } 499 498 499 + if (!var->pixclock) 500 + return -EINVAL; 501 + 500 502 if (PICOS2KHZ(var->pixclock) > par->max_pixclock) { 501 503 DPRINTK("pixclock too high (%ldKHz)\n", 502 504 PICOS2KHZ(var->pixclock)); ··· 595 591 vt = ve + (info->var.upper_margin << 1) - 1; 596 592 reg.screensize = info->var.xres | (info->var.yres << 13); 597 593 reg.vidcfg |= VIDCFG_HALF_MODE; 598 - reg.crt[0x09] = 0x80; 594 + reg.crt[VGA_CRTC_MAX_SCAN] = 0x80; 599 595 } else { 600 596 vd = info->var.yres - 1; 601 597 vs = vd + info->var.lower_margin; ··· 613 609 info->var.xres < 480 ? 0x60 : 614 610 info->var.xres < 768 ? 0xe0 : 0x20); 615 611 616 - reg.gra[0x05] = 0x40; 617 - reg.gra[0x06] = 0x05; 618 - reg.gra[0x07] = 0x0f; 619 - reg.gra[0x08] = 0xff; 612 + reg.gra[VGA_GFX_MODE] = 0x40; 613 + reg.gra[VGA_GFX_MISC] = 0x05; 614 + reg.gra[VGA_GFX_COMPARE_MASK] = 0x0f; 615 + reg.gra[VGA_GFX_BIT_MASK] = 0xff; 620 616 621 - reg.att[0x00] = 0x00; 622 - reg.att[0x01] = 0x01; 623 - reg.att[0x02] = 0x02; 624 - reg.att[0x03] = 0x03; 625 - reg.att[0x04] = 0x04; 626 - reg.att[0x05] = 0x05; 627 - reg.att[0x06] = 0x06; 628 - reg.att[0x07] = 0x07; 629 - reg.att[0x08] = 0x08; 630 - reg.att[0x09] = 0x09; 631 - reg.att[0x0a] = 0x0a; 632 - reg.att[0x0b] = 0x0b; 633 - reg.att[0x0c] = 0x0c; 634 - reg.att[0x0d] = 0x0d; 635 - reg.att[0x0e] = 0x0e; 636 - reg.att[0x0f] = 0x0f; 637 - reg.att[0x10] = 0x41; 638 - reg.att[0x12] = 0x0f; 617 + reg.att[VGA_ATC_PALETTE0] = 0x00; 618 + reg.att[VGA_ATC_PALETTE1] = 0x01; 619 + reg.att[VGA_ATC_PALETTE2] = 0x02; 620 + reg.att[VGA_ATC_PALETTE3] = 0x03; 621 + reg.att[VGA_ATC_PALETTE4] = 0x04; 622 + reg.att[VGA_ATC_PALETTE5] = 0x05; 623 + reg.att[VGA_ATC_PALETTE6] = 0x06; 624 + reg.att[VGA_ATC_PALETTE7] = 0x07; 625 + reg.att[VGA_ATC_PALETTE8] = 0x08; 626 + reg.att[VGA_ATC_PALETTE9] = 0x09; 627 + reg.att[VGA_ATC_PALETTEA] = 0x0a; 628 + reg.att[VGA_ATC_PALETTEB] = 0x0b; 629 + reg.att[VGA_ATC_PALETTEC] = 0x0c; 630 + reg.att[VGA_ATC_PALETTED] = 0x0d; 631 + reg.att[VGA_ATC_PALETTEE] = 0x0e; 632 + reg.att[VGA_ATC_PALETTEF] = 0x0f; 633 + reg.att[VGA_ATC_MODE] = 0x41; 634 + reg.att[VGA_ATC_PLANE_ENABLE] = 0x0f; 639 635 640 - reg.seq[0x00] = 0x03; 641 - reg.seq[0x01] = 0x01; /* fixme: clkdiv2? */ 642 - reg.seq[0x02] = 0x0f; 643 - reg.seq[0x03] = 0x00; 644 - reg.seq[0x04] = 0x0e; 636 + reg.seq[VGA_SEQ_RESET] = 0x03; 637 + reg.seq[VGA_SEQ_CLOCK_MODE] = 0x01; /* fixme: clkdiv2? */ 638 + reg.seq[VGA_SEQ_PLANE_WRITE] = 0x0f; 639 + reg.seq[VGA_SEQ_CHARACTER_MAP] = 0x00; 640 + reg.seq[VGA_SEQ_MEMORY_MODE] = 0x0e; 645 641 646 - reg.crt[0x00] = ht - 4; 647 - reg.crt[0x01] = hd; 648 - reg.crt[0x02] = hbs; 649 - reg.crt[0x03] = 0x80 | (hbe & 0x1f); 650 - reg.crt[0x04] = hs; 651 - reg.crt[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f); 652 - reg.crt[0x06] = vt; 653 - reg.crt[0x07] = ((vs & 0x200) >> 2) | 654 - ((vd & 0x200) >> 3) | 655 - ((vt & 0x200) >> 4) | 0x10 | 656 - ((vbs & 0x100) >> 5) | 657 - ((vs & 0x100) >> 6) | 658 - ((vd & 0x100) >> 7) | 659 - ((vt & 0x100) >> 8); 660 - reg.crt[0x09] |= 0x40 | ((vbs & 0x200) >> 4); 661 - reg.crt[0x10] = vs; 662 - reg.crt[0x11] = (ve & 0x0f) | 0x20; 663 - reg.crt[0x12] = vd; 664 - reg.crt[0x13] = wd; 665 - reg.crt[0x15] = vbs; 666 - reg.crt[0x16] = vbe + 1; 667 - reg.crt[0x17] = 0xc3; 668 - reg.crt[0x18] = 0xff; 642 + reg.crt[VGA_CRTC_H_TOTAL] = ht - 4; 643 + reg.crt[VGA_CRTC_H_DISP] = hd; 644 + reg.crt[VGA_CRTC_H_BLANK_START] = hbs; 645 + reg.crt[VGA_CRTC_H_BLANK_END] = 0x80 | (hbe & 0x1f); 646 + reg.crt[VGA_CRTC_H_SYNC_START] = hs; 647 + reg.crt[VGA_CRTC_H_SYNC_END] = ((hbe & 0x20) << 2) | (he & 0x1f); 648 + reg.crt[VGA_CRTC_V_TOTAL] = vt; 649 + reg.crt[VGA_CRTC_OVERFLOW] = ((vs & 0x200) >> 2) | 650 + ((vd & 0x200) >> 3) | 651 + ((vt & 0x200) >> 4) | 0x10 | 652 + ((vbs & 0x100) >> 5) | 653 + ((vs & 0x100) >> 6) | 654 + ((vd & 0x100) >> 7) | 655 + ((vt & 0x100) >> 8); 656 + reg.crt[VGA_CRTC_MAX_SCAN] |= 0x40 | ((vbs & 0x200) >> 4); 657 + reg.crt[VGA_CRTC_V_SYNC_START] = vs; 658 + reg.crt[VGA_CRTC_V_SYNC_END] = (ve & 0x0f) | 0x20; 659 + reg.crt[VGA_CRTC_V_DISP_END] = vd; 660 + reg.crt[VGA_CRTC_OFFSET] = wd; 661 + reg.crt[VGA_CRTC_V_BLANK_START] = vbs; 662 + reg.crt[VGA_CRTC_V_BLANK_END] = vbe + 1; 663 + reg.crt[VGA_CRTC_MODE] = 0xc3; 664 + reg.crt[VGA_CRTC_LINE_COMPARE] = 0xff; 669 665 670 666 /* Banshee's nonvga stuff */ 671 667 reg.ext[0x00] = (((ht & 0x100) >> 8) |
+3
drivers/video/fbdev/udlfb.c
··· 1018 1018 struct fb_videomode mode; 1019 1019 struct dlfb_data *dlfb = info->par; 1020 1020 1021 + if (!var->pixclock) 1022 + return -EINVAL; 1023 + 1021 1024 /* set device-specific elements of var unrelated to mode */ 1022 1025 dlfb_var_color_format(var); 1023 1026
+3
drivers/video/fbdev/via/lcd.c
··· 954 954 u16 start_pattern; 955 955 956 956 biosptr = ioremap(romaddr, 0x10000); 957 + if (!biosptr) 958 + return false; 959 + 957 960 start_pattern = readw(biosptr); 958 961 959 962 /* Compare pattern */
+4 -14
drivers/video/fbdev/wmt_ge_rops.c
··· 148 148 149 149 static int wmt_ge_rops_probe(struct platform_device *pdev) 150 150 { 151 - struct resource *res; 152 - 153 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 154 - if (res == NULL) { 155 - dev_err(&pdev->dev, "no I/O memory resource defined\n"); 156 - return -ENODEV; 157 - } 158 - 159 151 /* Only one ROP engine is presently supported. */ 160 152 if (unlikely(regbase)) { 161 153 WARN_ON(1); 162 154 return -EBUSY; 163 155 } 164 156 165 - regbase = ioremap(res->start, resource_size(res)); 166 - if (regbase == NULL) { 167 - dev_err(&pdev->dev, "failed to map I/O memory\n"); 168 - return -EBUSY; 169 - } 157 + regbase = devm_platform_ioremap_resource(pdev, 0); 158 + if (IS_ERR(regbase)) 159 + return PTR_ERR(regbase); 170 160 171 161 writel(1, regbase + GE_ENABLE_OFF); 172 162 printk(KERN_INFO "Enabled support for WMT GE raster acceleration\n"); ··· 166 176 167 177 static void wmt_ge_rops_remove(struct platform_device *pdev) 168 178 { 169 - iounmap(regbase); 179 + regbase = NULL; 170 180 } 171 181 172 182 static const struct of_device_id wmt_dt_ids[] = {
+30 -3
include/linux/console_struct.h
··· 13 13 #ifndef _LINUX_CONSOLE_STRUCT_H 14 14 #define _LINUX_CONSOLE_STRUCT_H 15 15 16 - #include <linux/wait.h> 17 16 #include <linux/vt.h> 17 + #include <linux/wait.h> 18 18 #include <linux/workqueue.h> 19 19 20 20 struct uni_pagedict; ··· 57 57 bool blink; 58 58 bool reverse; 59 59 }; 60 + 61 + /** 62 + * struct vc_font - Describes a font 63 + * @width: The width of a single glyph in bits 64 + * @height: The height of a single glyph in scanlines 65 + * @charcount: The number of glyphs in the font 66 + * @data: The raw font data 67 + * 68 + * Font data is organized as an array of glyphs. Each glyph is a bitmap with 69 + * set bits indicating the foreground color. Unset bits indicate background 70 + * color. The fields @width and @height store a single glyph's number of 71 + * horizontal bits and vertical scanlines. If width is not a multiple of 8, 72 + * there are trailing bits to fill up the byte. These bits should not be drawn. 73 + * 74 + * The field @data points to the first glyph's first byte. The value @charcount 75 + * gives the number of glyphs in the font. There are no empty scanlines between 76 + * two adjacent glyphs. 77 + */ 78 + struct vc_font { 79 + unsigned int width; 80 + unsigned int height; 81 + unsigned int charcount; 82 + const unsigned char *data; 83 + }; 84 + 85 + unsigned int vc_font_pitch(const struct vc_font *font); 86 + unsigned int vc_font_size(const struct vc_font *font); 60 87 61 88 /* 62 89 * Example: vc_data of a console that was scrolled 3 lines down. ··· 147 120 unsigned short vc_complement_mask; /* [#] Xor mask for mouse pointer */ 148 121 unsigned short vc_s_complement_mask; /* Saved mouse pointer mask */ 149 122 unsigned long vc_pos; /* Cursor address */ 150 - /* fonts */ 123 + /* fonts */ 151 124 unsigned short vc_hi_font_mask; /* [#] Attribute set for upper 256 chars of font or 0 if not supported */ 152 - struct console_font vc_font; /* Current VC font set */ 125 + struct vc_font vc_font; /* Current VC font set */ 153 126 unsigned short vc_video_erase_char; /* Background erase character */ 154 127 /* VT terminal data */ 155 128 unsigned int vc_state; /* Escape sequence parser state */
+8 -11
include/linux/fb.h
··· 217 217 /* delay between mkwrite and deferred handler */ 218 218 unsigned long delay; 219 219 bool sort_pagereflist; /* sort pagelist by offset */ 220 - int open_count; /* number of opened files; protected by fb_info lock */ 221 - struct mutex lock; /* mutex that protects the pageref list */ 222 - struct list_head pagereflist; /* list of pagerefs for touched pages */ 223 - struct address_space *mapping; /* page cache object for fb device */ 224 220 /* callback */ 225 221 struct page *(*get_page)(struct fb_info *info, unsigned long offset); 226 222 void (*deferred_io)(struct fb_info *info, struct list_head *pagelist); 227 223 }; 224 + 225 + struct fb_deferred_io_state; 228 226 #endif 229 227 230 228 /* ··· 482 484 483 485 #ifdef CONFIG_FB_DEFERRED_IO 484 486 struct delayed_work deferred_work; 485 - unsigned long npagerefs; 486 - struct fb_deferred_io_pageref *pagerefs; 487 487 struct fb_deferred_io *fbdefio; 488 + struct fb_deferred_io_state *fbdefio_state; 488 489 #endif 489 490 490 491 const struct fb_ops *fbops; ··· 602 605 extern void unregister_framebuffer(struct fb_info *fb_info); 603 606 extern int devm_register_framebuffer(struct device *dev, struct fb_info *fb_info); 604 607 extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size); 605 - extern void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, 606 - u32 height, u32 shift_high, u32 shift_low, u32 mod); 607 - extern void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height); 608 + void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, const u8 *src, u32 idx, u32 height, 609 + u32 shift_high, u32 shift_low, u32 mod); 610 + void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, const u8 *src, u32 s_pitch, u32 height); 608 611 extern void fb_set_suspend(struct fb_info *info, int state); 609 612 extern int fb_get_color_depth(struct fb_var_screeninfo *var, 610 613 struct fb_fix_screeninfo *fix); ··· 630 633 #endif 631 634 } 632 635 633 - static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, 634 - u8 *src, u32 s_pitch, u32 height) 636 + static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, const u8 *src, u32 s_pitch, 637 + u32 height) 635 638 { 636 639 u32 i, j; 637 640
+124 -42
include/linux/font.h
··· 11 11 #ifndef _VIDEO_FONT_H 12 12 #define _VIDEO_FONT_H 13 13 14 + #include <linux/math.h> 14 15 #include <linux/types.h> 16 + 17 + struct console_font; 18 + 19 + /* 20 + * Glyphs 21 + */ 22 + 23 + /** 24 + * font_glyph_pitch - Calculates the number of bytes per scanline 25 + * @width: The glyph width in bits per scanline 26 + * 27 + * A glyph's pitch is the number of bytes in a single scanline, rounded 28 + * up to the next full byte. The parameter @width receives the number 29 + * of visible bits per scanline. For example, if width is 14 bytes per 30 + * scanline, the pitch is 2 bytes per scanline. If width is 8 bits per 31 + * scanline, the pitch is 1 byte per scanline. 32 + * 33 + * Returns: 34 + * The number of bytes in a single scanline of the glyph 35 + */ 36 + static inline unsigned int font_glyph_pitch(unsigned int width) 37 + { 38 + return DIV_ROUND_UP(width, 8); 39 + } 40 + 41 + /** 42 + * font_glyph_size - Calculates the number of bytes per glyph 43 + * @width: The glyph width in bits per scanline 44 + * @vpitch: The number of scanlines in the glyph 45 + * 46 + * The number of bytes in a glyph depends on the pitch and the number 47 + * of scanlines. font_glyph_size automatically calculates the pitch 48 + * from the given width. The parameter @vpitch gives the number of 49 + * scanlines, which is usually the glyph's height in scanlines. Fonts 50 + * coming from user space can sometimes have a different vertical pitch 51 + * with empty scanlines between two adjacent glyphs. 52 + */ 53 + static inline unsigned int font_glyph_size(unsigned int width, unsigned int vpitch) 54 + { 55 + return font_glyph_pitch(width) * vpitch; 56 + } 57 + 58 + /* 59 + * font_data_t and helpers 60 + */ 61 + 62 + /** 63 + * font_data_t - Raw font data 64 + * 65 + * Values of type font_data_t store a pointer to raw font data. The format 66 + * is monochrome. Each bit sets a pixel of a stored glyph. Font data does 67 + * not store geometry information for the individual glyphs. Users of the 68 + * font have to store glyph size, pitch and character count separately. 69 + * 70 + * Font data in font_data_t is not equivalent to raw u8. Each pointer stores 71 + * an additional hidden header before the font data. The layout is 72 + * 73 + * +------+-----------------------------+ 74 + * | -16 | CRC32 Checksum (optional) | 75 + * | -12 | <Unused> | 76 + * | -8 | Number of data bytes | 77 + * | -4 | Reference count | 78 + * +------+-----------------------------+ 79 + * | 0 | Data buffer | 80 + * | ... | | 81 + * +------+-----------------------------+ 82 + * 83 + * Use helpers to access font_data_t. Use font_data_buf() to get the stored data. 84 + */ 85 + typedef const unsigned char font_data_t; 86 + 87 + /** 88 + * font_data_buf() - Returns the font data as raw bytes 89 + * @fd: The font data 90 + * 91 + * Returns: 92 + * The raw font data. The provided buffer is read-only. 93 + */ 94 + static inline const unsigned char *font_data_buf(font_data_t *fd) 95 + { 96 + return (const unsigned char *)fd; 97 + } 98 + 99 + font_data_t *font_data_import(const struct console_font *font, unsigned int vpitch, 100 + u32 (*calc_csum)(u32, const void *, size_t)); 101 + void font_data_get(font_data_t *fd); 102 + bool font_data_put(font_data_t *fd); 103 + unsigned int font_data_size(font_data_t *fd); 104 + bool font_data_is_equal(font_data_t *lhs, font_data_t *rhs); 105 + int font_data_export(font_data_t *fd, struct console_font *font, unsigned int vpitch); 106 + 107 + /* font_rotate.c */ 108 + void font_glyph_rotate_90(const unsigned char *glyph, unsigned int width, unsigned int height, 109 + unsigned char *out); 110 + void font_glyph_rotate_180(const unsigned char *glyph, unsigned int width, unsigned int height, 111 + unsigned char *out); 112 + void font_glyph_rotate_270(const unsigned char *glyph, unsigned int width, unsigned int height, 113 + unsigned char *out); 114 + unsigned char *font_data_rotate(font_data_t *fd, unsigned int width, unsigned int height, 115 + unsigned int charcount, unsigned int steps, 116 + unsigned char *buf, size_t *bufsize); 117 + 118 + /* 119 + * Font description 120 + */ 15 121 16 122 struct font_desc { 17 123 int idx; 18 124 const char *name; 19 125 unsigned int width, height; 20 126 unsigned int charcount; 21 - const void *data; 127 + font_data_t *data; 22 128 int pref; 23 129 }; 24 - 25 - #define VGA8x8_IDX 0 26 - #define VGA8x16_IDX 1 27 - #define PEARL8x8_IDX 2 28 - #define VGA6x11_IDX 3 29 - #define FONT7x14_IDX 4 30 - #define FONT10x18_IDX 5 31 - #define SUN8x16_IDX 6 32 - #define SUN12x22_IDX 7 33 - #define ACORN8x8_IDX 8 34 - #define MINI4x6_IDX 9 35 - #define FONT6x10_IDX 10 36 - #define TER16x32_IDX 11 37 - #define FONT6x8_IDX 12 38 - #define TER10x18_IDX 13 39 - 40 - extern const struct font_desc font_vga_8x8, 41 - font_vga_8x16, 42 - font_pearl_8x8, 43 - font_vga_6x11, 44 - font_7x14, 45 - font_10x18, 46 - font_sun_8x16, 47 - font_sun_12x22, 48 - font_acorn_8x8, 49 - font_mini_4x6, 50 - font_6x10, 51 - font_ter_16x32, 52 - font_6x8, 53 - font_ter_10x18; 54 130 55 131 /* Find a font with a specific name */ 56 132 ··· 141 65 /* Max. length for the name of a predefined font */ 142 66 #define MAX_FONT_NAME 32 143 67 144 - /* Extra word getters */ 145 - #define REFCOUNT(fd) (((int *)(fd))[-1]) 146 - #define FNTSIZE(fd) (((int *)(fd))[-2]) 147 - #define FNTCHARCNT(fd) (((int *)(fd))[-3]) 148 - #define FNTSUM(fd) (((int *)(fd))[-4]) 68 + /* 69 + * Built-in fonts 70 + */ 149 71 150 - #define FONT_EXTRA_WORDS 4 151 - 152 - struct font_data { 153 - unsigned int extra[FONT_EXTRA_WORDS]; 154 - const unsigned char data[]; 155 - } __packed; 72 + extern const struct font_desc font_10x18; 73 + extern const struct font_desc font_6x10; 74 + extern const struct font_desc font_6x8; 75 + extern const struct font_desc font_7x14; 76 + extern const struct font_desc font_acorn_8x8; 77 + extern const struct font_desc font_mini_4x6; 78 + extern const struct font_desc font_pearl_8x8; 79 + extern const struct font_desc font_sun_12x22; 80 + extern const struct font_desc font_sun_8x16; 81 + extern const struct font_desc font_ter_10x18; 82 + extern const struct font_desc font_ter_16x32; 83 + extern const struct font_desc font_vga_6x11; 84 + extern const struct font_desc font_vga_8x16; 85 + extern const struct font_desc font_vga_8x8; 156 86 157 87 #endif /* _VIDEO_FONT_H */
+18 -18
lib/fonts/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 # Font handling 3 3 4 - font-objs := fonts.o 4 + font-y := fonts.o 5 + font-$(CONFIG_FRAMEBUFFER_CONSOLE_ROTATION) += font_rotate.o 5 6 6 - font-objs-$(CONFIG_FONT_SUN8x16) += font_sun8x16.o 7 - font-objs-$(CONFIG_FONT_SUN12x22) += font_sun12x22.o 8 - font-objs-$(CONFIG_FONT_8x8) += font_8x8.o 9 - font-objs-$(CONFIG_FONT_8x16) += font_8x16.o 10 - font-objs-$(CONFIG_FONT_6x11) += font_6x11.o 11 - font-objs-$(CONFIG_FONT_7x14) += font_7x14.o 12 - font-objs-$(CONFIG_FONT_10x18) += font_10x18.o 13 - font-objs-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o 14 - font-objs-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o 15 - font-objs-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o 16 - font-objs-$(CONFIG_FONT_6x10) += font_6x10.o 17 - font-objs-$(CONFIG_FONT_TER10x18) += font_ter10x18.o 18 - font-objs-$(CONFIG_FONT_TER16x32) += font_ter16x32.o 19 - font-objs-$(CONFIG_FONT_6x8) += font_6x8.o 7 + # Built-in fonts; sorted by Family-Size in ascending order 8 + font-$(CONFIG_FONT_6x8) += font_6x8.o 9 + font-$(CONFIG_FONT_6x10) += font_6x10.o 10 + font-$(CONFIG_FONT_6x11) += font_6x11.o 11 + font-$(CONFIG_FONT_7x14) += font_7x14.o 12 + font-$(CONFIG_FONT_8x8) += font_8x8.o 13 + font-$(CONFIG_FONT_8x16) += font_8x16.o 14 + font-$(CONFIG_FONT_10x18) += font_10x18.o 15 + font-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o 16 + font-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o 17 + font-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o 18 + font-$(CONFIG_FONT_SUN8x16) += font_sun8x16.o 19 + font-$(CONFIG_FONT_SUN12x22) += font_sun12x22.o 20 + font-$(CONFIG_FONT_TER10x18) += font_ter10x18.o 21 + font-$(CONFIG_FONT_TER16x32) += font_ter16x32.o 20 22 21 - font-objs += $(font-objs-y) 22 - 23 - obj-$(CONFIG_FONT_SUPPORT) += font.o 23 + obj-$(CONFIG_FONT_SUPPORT) += font.o
+38
lib/fonts/font.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + 3 + #ifndef _LIB_FONTS_FONT_H 4 + #define _LIB_FONTS_FONT_H 5 + 6 + #include <linux/font.h> 7 + 8 + /* 9 + * Font data 10 + */ 11 + 12 + #define FONT_EXTRA_WORDS 4 13 + 14 + struct font_data { 15 + unsigned int extra[FONT_EXTRA_WORDS]; 16 + unsigned char data[]; 17 + } __packed; 18 + 19 + /* 20 + * Built-in fonts 21 + */ 22 + 23 + #define VGA8x8_IDX 0 24 + #define VGA8x16_IDX 1 25 + #define PEARL8x8_IDX 2 26 + #define VGA6x11_IDX 3 27 + #define FONT7x14_IDX 4 28 + #define FONT10x18_IDX 5 29 + #define SUN8x16_IDX 6 30 + #define SUN12x22_IDX 7 31 + #define ACORN8x8_IDX 8 32 + #define MINI4x6_IDX 9 33 + #define FONT6x10_IDX 10 34 + #define TER16x32_IDX 11 35 + #define FONT6x8_IDX 12 36 + #define TER10x18_IDX 13 37 + 38 + #endif
+1 -1
lib/fonts/font_10x18.c
··· 4 4 * by Jurriaan Kalkman 06-2005 * 5 5 ********************************/ 6 6 7 - #include <linux/font.h> 7 + #include "font.h" 8 8 9 9 #define FONTDATAMAX 9216 10 10
+2 -1
lib/fonts/font_6x10.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 - #include <linux/font.h> 2 + 3 + #include "font.h" 3 4 4 5 #define FONTDATAMAX 2560 5 6
+1 -1
lib/fonts/font_6x11.c
··· 5 5 /* */ 6 6 /**********************************************/ 7 7 8 - #include <linux/font.h> 8 + #include "font.h" 9 9 10 10 #define FONTDATAMAX (11*256) 11 11
+2 -1
lib/fonts/font_6x8.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 - #include <linux/font.h> 2 + 3 + #include "font.h" 3 4 4 5 #define FONTDATAMAX 2048 5 6
+1 -1
lib/fonts/font_7x14.c
··· 4 4 /* by Jurriaan Kalkman 05-2005 */ 5 5 /**************************************/ 6 6 7 - #include <linux/font.h> 7 + #include "font.h" 8 8 9 9 #define FONTDATAMAX 3584 10 10
+2 -1
lib/fonts/font_8x16.c
··· 5 5 /* */ 6 6 /**********************************************/ 7 7 8 - #include <linux/font.h> 9 8 #include <linux/module.h> 9 + 10 + #include "font.h" 10 11 11 12 #define FONTDATAMAX 4096 12 13
+1 -1
lib/fonts/font_8x8.c
··· 5 5 /* */ 6 6 /**********************************************/ 7 7 8 - #include <linux/font.h> 8 + #include "font.h" 9 9 10 10 #define FONTDATAMAX 2048 11 11
+2 -2
lib/fonts/font_acorn_8x8.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* Acorn-like font definition, with PC graphics characters */ 3 3 4 - #include <linux/font.h> 4 + #include "font.h" 5 5 6 6 #define FONTDATAMAX 2048 7 7 ··· 68 68 /* 3A */ 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, /* : */ 69 69 /* 3B */ 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30, /* ; */ 70 70 /* 3C */ 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x00, /* < */ 71 - /* 3D */ 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00, /* = */ 71 + /* 3D */ 0x00, 0x00, 0x7E, 0x00, 0x7E, 0x00, 0x00, 0x00, /* = */ 72 72 /* 3E */ 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x00, /* > */ 73 73 /* 3F */ 0x3C, 0x66, 0x0C, 0x18, 0x18, 0x00, 0x18, 0x00, /* ? */ 74 74 /* 40 */ 0x3C, 0x66, 0x6E, 0x6A, 0x6E, 0x60, 0x3C, 0x00, /* @ */
+5 -5
lib/fonts/font_mini_4x6.c
··· 18 18 s{((0x)?[0-9a-fA-F]+)(.*\[([\*\ ]{4})\])}{ 19 19 20 20 ($num,$pat,$bits) = ($1,$3,$4); 21 - 21 + 22 22 $bits =~ s/([^\s0])|(.)/ defined($1) + 0 /ge; 23 - 23 + 24 24 $num = ord(pack("B8", $bits)); 25 25 $num |= $num >> 4; 26 26 $num = sprintf("0x%.2x", $num); 27 - 27 + 28 28 #print "$num,$pat,$bits\n"; 29 - 29 + 30 30 $num . $pat; 31 31 }ge; 32 32 ··· 39 39 MSBit to LSBit = left to right. 40 40 */ 41 41 42 - #include <linux/font.h> 42 + #include "font.h" 43 43 44 44 #define FONTDATAMAX 1536 45 45
+1 -1
lib/fonts/font_pearl_8x8.c
··· 10 10 /* */ 11 11 /**********************************************/ 12 12 13 - #include <linux/font.h> 13 + #include "font.h" 14 14 15 15 #define FONTDATAMAX 2048 16 16
+275
lib/fonts/font_rotate.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Font rotation 4 + * 5 + * Copyright (C) 2005 Antonino Daplas <adaplas @pol.net> 6 + * 7 + * This file is subject to the terms and conditions of the GNU General Public 8 + * License. See the file COPYING in the main directory of this archive for 9 + * more details. 10 + */ 11 + 12 + #include <linux/errno.h> 13 + #include <linux/export.h> 14 + #include <linux/math.h> 15 + #include <linux/overflow.h> 16 + #include <linux/slab.h> 17 + #include <linux/string.h> 18 + 19 + #include "font.h" 20 + 21 + /* number of bits per line */ 22 + static unsigned int font_glyph_bit_pitch(unsigned int width) 23 + { 24 + return round_up(width, 8); 25 + } 26 + 27 + static unsigned int __font_glyph_pos(unsigned int x, unsigned int y, unsigned int bit_pitch, 28 + unsigned int *bit) 29 + { 30 + unsigned int off = y * bit_pitch + x; 31 + unsigned int bit_shift = off % 8; 32 + 33 + *bit = 0x80 >> bit_shift; /* MSB has position 0, LSB has position 7 */ 34 + 35 + return off / 8; 36 + } 37 + 38 + static bool font_glyph_test_bit(const unsigned char *glyph, unsigned int x, unsigned int y, 39 + unsigned int bit_pitch) 40 + { 41 + unsigned int bit; 42 + unsigned int i = __font_glyph_pos(x, y, bit_pitch, &bit); 43 + 44 + return glyph[i] & bit; 45 + } 46 + 47 + static void font_glyph_set_bit(unsigned char *glyph, unsigned int x, unsigned int y, 48 + unsigned int bit_pitch) 49 + { 50 + unsigned int bit; 51 + unsigned int i = __font_glyph_pos(x, y, bit_pitch, &bit); 52 + 53 + glyph[i] |= bit; 54 + } 55 + 56 + static void __font_glyph_rotate_90(const unsigned char *glyph, 57 + unsigned int width, unsigned int height, 58 + unsigned char *out) 59 + { 60 + unsigned int x, y; 61 + unsigned int shift = (8 - (height % 8)) & 7; 62 + unsigned int bit_pitch = font_glyph_bit_pitch(width); 63 + unsigned int out_bit_pitch = font_glyph_bit_pitch(height); 64 + 65 + for (y = 0; y < height; y++) { 66 + for (x = 0; x < width; x++) { 67 + if (font_glyph_test_bit(glyph, x, y, bit_pitch)) { 68 + font_glyph_set_bit(out, out_bit_pitch - 1 - y - shift, x, 69 + out_bit_pitch); 70 + } 71 + } 72 + } 73 + } 74 + 75 + /** 76 + * font_glyph_rotate_90 - Rotate a glyph pattern by 90° in clockwise direction 77 + * @glyph: The glyph to rotate 78 + * @width: The glyph width in bits per scanline 79 + * @height: The number of scanlines in the glyph 80 + * @out: The rotated glyph bitmap 81 + * 82 + * The parameters @width and @height refer to the input glyph given in @glyph. 83 + * The caller has to provide the output buffer @out of sufficient size to hold 84 + * the rotated glyph. Rotating by 90° flips the width and height for the output 85 + * glyph. Depending on the glyph pitch, the size of the output glyph can be 86 + * different than the size of the input. Callers have to take this into account 87 + * when allocating the output memory. 88 + */ 89 + void font_glyph_rotate_90(const unsigned char *glyph, unsigned int width, unsigned int height, 90 + unsigned char *out) 91 + { 92 + memset(out, 0, font_glyph_size(height, width)); /* flip width/height */ 93 + 94 + __font_glyph_rotate_90(glyph, width, height, out); 95 + } 96 + EXPORT_SYMBOL_GPL(font_glyph_rotate_90); 97 + 98 + static void __font_glyph_rotate_180(const unsigned char *glyph, 99 + unsigned int width, unsigned int height, 100 + unsigned char *out) 101 + { 102 + unsigned int x, y; 103 + unsigned int shift = (8 - (width % 8)) & 7; 104 + unsigned int bit_pitch = font_glyph_bit_pitch(width); 105 + 106 + for (y = 0; y < height; y++) { 107 + for (x = 0; x < width; x++) { 108 + if (font_glyph_test_bit(glyph, x, y, bit_pitch)) { 109 + font_glyph_set_bit(out, width - (1 + x + shift), height - (1 + y), 110 + bit_pitch); 111 + } 112 + } 113 + } 114 + } 115 + 116 + /** 117 + * font_glyph_rotate_180 - Rotate a glyph pattern by 180° 118 + * @glyph: The glyph to rotate 119 + * @width: The glyph width in bits per scanline 120 + * @height: The number of scanlines in the glyph 121 + * @out: The rotated glyph bitmap 122 + * 123 + * The parameters @width and @height refer to the input glyph given in @glyph. 124 + * The caller has to provide the output buffer @out of sufficient size to hold 125 + * the rotated glyph. 126 + */ 127 + void font_glyph_rotate_180(const unsigned char *glyph, unsigned int width, unsigned int height, 128 + unsigned char *out) 129 + { 130 + memset(out, 0, font_glyph_size(width, height)); 131 + 132 + __font_glyph_rotate_180(glyph, width, height, out); 133 + } 134 + EXPORT_SYMBOL_GPL(font_glyph_rotate_180); 135 + 136 + static void __font_glyph_rotate_270(const unsigned char *glyph, 137 + unsigned int width, unsigned int height, 138 + unsigned char *out) 139 + { 140 + unsigned int x, y; 141 + unsigned int shift = (8 - (width % 8)) & 7; 142 + unsigned int bit_pitch = font_glyph_bit_pitch(width); 143 + unsigned int out_bit_pitch = font_glyph_bit_pitch(height); 144 + 145 + for (y = 0; y < height; y++) { 146 + for (x = 0; x < width; x++) { 147 + if (font_glyph_test_bit(glyph, x, y, bit_pitch)) 148 + font_glyph_set_bit(out, y, bit_pitch - 1 - x - shift, 149 + out_bit_pitch); 150 + } 151 + } 152 + } 153 + 154 + /** 155 + * font_glyph_rotate_270 - Rotate a glyph pattern by 270° in clockwise direction 156 + * @glyph: The glyph to rotate 157 + * @width: The glyph width in bits per scanline 158 + * @height: The number of scanlines in the glyph 159 + * @out: The rotated glyph bitmap 160 + * 161 + * The parameters @width and @height refer to the input glyph given in @glyph. 162 + * The caller has to provide the output buffer @out of sufficient size to hold 163 + * the rotated glyph. Rotating by 270° flips the width and height for the output 164 + * glyph. Depending on the glyph pitch, the size of the output glyph can be 165 + * different than the size of the input. Callers have to take this into account 166 + * when allocating the output memory. 167 + */ 168 + void font_glyph_rotate_270(const unsigned char *glyph, unsigned int width, unsigned int height, 169 + unsigned char *out) 170 + { 171 + memset(out, 0, font_glyph_size(height, width)); /* flip width/height */ 172 + 173 + __font_glyph_rotate_270(glyph, width, height, out); 174 + } 175 + EXPORT_SYMBOL_GPL(font_glyph_rotate_270); 176 + 177 + /** 178 + * font_data_rotate - Rotate font data by multiples of 90° 179 + * @fd: The font data to rotate 180 + * @width: The glyph width in bits per scanline 181 + * @height: The number of scanlines in the glyph 182 + * @charcount: The number of glyphs in the font 183 + * @steps: Number of rotation steps of 90° 184 + * @buf: Preallocated output buffer; can be NULL 185 + * @bufsize: The size of @buf in bytes; can be NULL 186 + * 187 + * The parameters @width and @height refer to the visible number of pixels 188 + * and scanlines in a single glyph. The number of glyphs is given in @charcount. 189 + * Rotation happens in steps of 90°. The @steps parameter can have any value, 190 + * but only 0 to 3 produce distinct results. With 4 or higher, a full rotation 191 + * has been performed. You can pass any value for @steps and the helper will 192 + * perform the appropriate rotation. Note that the returned buffer is not 193 + * compatible with font_data_t. It only contains glyph data in the same format 194 + * as returned by font_data_buf(). Callers are responsible to free the returned 195 + * buffer with kfree(). Font rotation typically happens when displays get 196 + * re-oriented. To avoid unnecessary re-allocation of the memory buffer, the 197 + * caller can pass in an earlier result buffer in @buf for reuse. The old and 198 + * new buffer sizes are given and retrieved by the caller in @bufsize. The 199 + * allocation semantics are compatible with krealloc(). 200 + * 201 + * Returns: 202 + * A buffer with rotated glyphs on success, or an error pointer otherwise 203 + */ 204 + unsigned char *font_data_rotate(font_data_t *fd, unsigned int width, unsigned int height, 205 + unsigned int charcount, unsigned int steps, 206 + unsigned char *buf, size_t *bufsize) 207 + { 208 + const unsigned char *src = font_data_buf(fd); 209 + unsigned int s_cellsize = font_glyph_size(width, height); 210 + unsigned int d_cellsize, i; 211 + unsigned char *dst; 212 + size_t size; 213 + 214 + steps %= 4; 215 + 216 + switch (steps) { 217 + case 0: 218 + case 2: 219 + d_cellsize = s_cellsize; 220 + break; 221 + case 1: 222 + case 3: 223 + d_cellsize = font_glyph_size(height, width); /* flip width/height */ 224 + break; 225 + } 226 + 227 + if (check_mul_overflow(charcount, d_cellsize, &size)) 228 + return ERR_PTR(-EINVAL); 229 + 230 + if (!buf || !bufsize || size > *bufsize) { 231 + dst = kmalloc_array(charcount, d_cellsize, GFP_KERNEL); 232 + if (!dst) 233 + return ERR_PTR(-ENOMEM); 234 + 235 + kfree(buf); 236 + buf = dst; 237 + if (bufsize) 238 + *bufsize = size; 239 + } else { 240 + dst = buf; 241 + } 242 + 243 + switch (steps) { 244 + case 0: 245 + memcpy(dst, src, size); 246 + break; 247 + case 1: 248 + memset(dst, 0, size); 249 + for (i = 0; i < charcount; ++i) { 250 + __font_glyph_rotate_90(src, width, height, dst); 251 + src += s_cellsize; 252 + dst += d_cellsize; 253 + } 254 + break; 255 + case 2: 256 + memset(dst, 0, size); 257 + for (i = 0; i < charcount; ++i) { 258 + __font_glyph_rotate_180(src, width, height, dst); 259 + src += s_cellsize; 260 + dst += d_cellsize; 261 + } 262 + break; 263 + case 3: 264 + memset(dst, 0, size); 265 + for (i = 0; i < charcount; ++i) { 266 + __font_glyph_rotate_270(src, width, height, dst); 267 + src += s_cellsize; 268 + dst += d_cellsize; 269 + } 270 + break; 271 + } 272 + 273 + return buf; 274 + } 275 + EXPORT_SYMBOL_GPL(font_data_rotate);
+2 -1
lib/fonts/font_sun12x22.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 - #include <linux/font.h> 2 + 3 + #include "font.h" 3 4 4 5 #define FONTDATAMAX 11264 5 6
+2 -1
lib/fonts/font_sun8x16.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 - #include <linux/font.h> 2 + 3 + #include "font.h" 3 4 4 5 #define FONTDATAMAX 4096 5 6
+3 -1
lib/fonts/font_ter10x18.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 - #include <linux/font.h> 2 + 3 3 #include <linux/module.h> 4 + 5 + #include "font.h" 4 6 5 7 #define FONTDATAMAX 9216 6 8
+3 -1
lib/fonts/font_ter16x32.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 - #include <linux/font.h> 2 + 3 3 #include <linux/module.h> 4 + 5 + #include "font.h" 4 6 5 7 #define FONTDATAMAX 16384 6 8
+230 -2
lib/fonts/fonts.c
··· 12 12 * for more details. 13 13 */ 14 14 15 + #include <linux/container_of.h> 16 + #include <linux/kd.h> 15 17 #include <linux/module.h> 16 - #include <linux/types.h> 18 + #include <linux/overflow.h> 19 + #include <linux/slab.h> 17 20 #include <linux/string.h> 21 + #include <linux/types.h> 22 + 18 23 #if defined(__mc68000__) 19 24 #include <asm/setup.h> 20 25 #endif 21 - #include <linux/font.h> 26 + 27 + #include "font.h" 28 + 29 + #define console_font_pitch(font) font_glyph_pitch((font)->width) 30 + 31 + /* 32 + * Helpers for font_data_t 33 + */ 34 + 35 + /* Extra word getters */ 36 + #define REFCOUNT(fd) (((int *)(fd))[-1]) 37 + #define FNTSIZE(fd) (((int *)(fd))[-2]) 38 + #define FNTSUM(fd) (((int *)(fd))[-4]) 39 + 40 + static struct font_data *to_font_data_struct(font_data_t *fd) 41 + { 42 + return container_of(fd, struct font_data, data[0]); 43 + } 44 + 45 + static bool font_data_is_internal(font_data_t *fd) 46 + { 47 + return !REFCOUNT(fd); /* internal fonts have no reference counting */ 48 + } 49 + 50 + static void font_data_free(font_data_t *fd) 51 + { 52 + kfree(to_font_data_struct(fd)); 53 + } 54 + 55 + /** 56 + * font_data_import - Allocates and initializes font data from user space 57 + * @font: A font from user space 58 + * @vpitch: The size of a single glyph in @font in bytes 59 + * @calc_csum: An optional helper to calculate a chechsum 60 + * 61 + * Font data from user space must be translated to the kernel's format. The 62 + * font's glyph geometry and data is provided in @font. The parameter @vpitch 63 + * gives the number of bytes per glyph, including trailing bytes. 64 + * 65 + * The parameter @calc_csum is optional. Fbcon passes crc32() to calculate the 66 + * font data's checksum. 67 + * 68 + * Returns: 69 + * Newly initialized font data on success, or a pointer-encoded errno value otherwise. 70 + */ 71 + font_data_t *font_data_import(const struct console_font *font, unsigned int vpitch, 72 + u32 (*calc_csum)(u32, const void *, size_t)) 73 + { 74 + unsigned int pitch = console_font_pitch(font); 75 + unsigned int h = font->height; 76 + unsigned int charcount = font->charcount; 77 + const unsigned char *data = font->data; 78 + u32 csum = 0; 79 + struct font_data *font_data; 80 + int size, alloc_size; 81 + unsigned int i; 82 + font_data_t *fd; 83 + 84 + /* Check for integer overflow in font-size calculation */ 85 + if (check_mul_overflow(h, pitch, &size) || 86 + check_mul_overflow(size, charcount, &size)) 87 + return ERR_PTR(-EINVAL); 88 + 89 + /* Check for overflow in allocation size calculation */ 90 + if (check_add_overflow(sizeof(*font_data), size, &alloc_size)) 91 + return ERR_PTR(-EINVAL); 92 + 93 + font_data = kmalloc(alloc_size, GFP_USER); 94 + if (!font_data) 95 + return ERR_PTR(-ENOMEM); 96 + memset(font_data->extra, 0, sizeof(font_data->extra)); 97 + 98 + for (i = 0; i < charcount; ++i) 99 + memcpy(font_data->data + i * h * pitch, data + i * vpitch * pitch, h * pitch); 100 + 101 + if (calc_csum) 102 + csum = calc_csum(0, font_data->data, size); 103 + 104 + fd = font_data->data; 105 + REFCOUNT(fd) = 1; /* start with reference acquired */ 106 + FNTSIZE(fd) = size; 107 + FNTSUM(fd) = csum; 108 + 109 + return fd; 110 + } 111 + EXPORT_SYMBOL_GPL(font_data_import); 112 + 113 + /** 114 + * font_data_get - Acquires a reference on font data 115 + * @fd: Font data 116 + * 117 + * Font data from user space is reference counted. The helper 118 + * font_data_get() increases the reference counter by one. Invoke 119 + * font_data_put() to release the reference. 120 + * 121 + * Internal font data is located in read-only memory. In this case 122 + * the helper returns success without modifying the counter field. 123 + * It is still required to call font_data_put() on internal font data. 124 + */ 125 + void font_data_get(font_data_t *fd) 126 + { 127 + if (font_data_is_internal(fd)) 128 + return; /* never ref static data */ 129 + 130 + if (WARN_ON(!REFCOUNT(fd))) 131 + return; /* should never be 0 */ 132 + ++REFCOUNT(fd); 133 + } 134 + EXPORT_SYMBOL_GPL(font_data_get); 135 + 136 + /** 137 + * font_data_put - Release a reference on font data 138 + * @fd: Font data 139 + * 140 + * Font data from user space is reference counted. The helper 141 + * font_data_put() decreases the reference counter by one. If this was 142 + * the final reference, it frees the allocated memory. 143 + * 144 + * Internal font data is located in read-only memory. In this case 145 + * the helper returns success without modifying the counter field. 146 + * 147 + * Returns: 148 + * True if the font data's memory buffer has been freed, false otherwise. 149 + */ 150 + bool font_data_put(font_data_t *fd) 151 + { 152 + unsigned int count; 153 + 154 + if (font_data_is_internal(fd)) 155 + return false; /* never unref static data */ 156 + 157 + if (WARN_ON(!REFCOUNT(fd))) 158 + return false; /* should never be 0 */ 159 + 160 + count = --REFCOUNT(fd); 161 + if (!count) 162 + font_data_free(fd); 163 + 164 + return !count; 165 + } 166 + EXPORT_SYMBOL_GPL(font_data_put); 167 + 168 + /** 169 + * font_data_size - Return size of the font data in bytes 170 + * @fd: Font data 171 + * 172 + * Returns: 173 + * The number of bytes in the given font data. 174 + */ 175 + unsigned int font_data_size(font_data_t *fd) 176 + { 177 + return FNTSIZE(fd); 178 + } 179 + EXPORT_SYMBOL_GPL(font_data_size); 180 + 181 + /** 182 + * font_data_is_equal - Compares font data for equality 183 + * @lhs: Left-hand side font data 184 + * @rhs: Right-hand-size font data 185 + * 186 + * Font data is equal if is constain the same sequence of values. The 187 + * helper also use the checksum, if both arguments contain it. Font data 188 + * coming from different origins, internal or from user space, is never 189 + * equal. Allowing this would break reference counting. 190 + * 191 + * Returns: 192 + * True if the given font data is equal, false otherwise. 193 + */ 194 + bool font_data_is_equal(font_data_t *lhs, font_data_t *rhs) 195 + { 196 + if (font_data_is_internal(lhs) != font_data_is_internal(rhs)) 197 + return false; 198 + if (font_data_size(lhs) != font_data_size(rhs)) 199 + return false; 200 + if (FNTSUM(lhs) && FNTSUM(rhs) && FNTSUM(lhs) != FNTSUM(rhs)) 201 + return false; 202 + 203 + return !memcmp(lhs, rhs, FNTSIZE(lhs)); 204 + } 205 + EXPORT_SYMBOL_GPL(font_data_is_equal); 206 + 207 + /** 208 + * font_data_export - Stores font data for user space 209 + * @fd: Font data 210 + * @font: A font for user space 211 + * @vpitch: The size of a single glyph in @font in bytes 212 + * 213 + * Store the font data given in @fd to the font in @font. Values and 214 + * pointers in @font are pre-initialized. This helper mostly checks some 215 + * corner cases and translates glyph sizes according to the value given 216 + * @vpitch. 217 + * 218 + * Returns: 219 + * 0 on success, or a negative errno code otherwise. 220 + */ 221 + int font_data_export(font_data_t *fd, struct console_font *font, unsigned int vpitch) 222 + { 223 + const unsigned char *font_data = font_data_buf(fd); 224 + unsigned char *data = font->data; 225 + unsigned int pitch = console_font_pitch(font); 226 + unsigned int glyphsize, i; 227 + 228 + if (!font->width || !font->height || !font->charcount || !font->data) 229 + return 0; 230 + 231 + glyphsize = font->height * pitch; 232 + 233 + if (font->charcount * glyphsize > font_data_size(fd)) 234 + return -EINVAL; 235 + 236 + for (i = 0; i < font->charcount; i++) { 237 + memcpy(data, font_data, glyphsize); 238 + memset(data + glyphsize, 0, pitch * vpitch - glyphsize); 239 + data += pitch * vpitch; 240 + font_data += glyphsize; 241 + } 242 + 243 + return 0; 244 + } 245 + EXPORT_SYMBOL_GPL(font_data_export); 246 + 247 + /* 248 + * Font lookup 249 + */ 22 250 23 251 static const struct font_desc *fonts[] = { 24 252 #ifdef CONFIG_FONT_8x8