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
  ...
This commit is contained in:
Linus Torvalds committed 2026-04-15 08:37:45 -07:00
commit afac4c66d1
45 files changed
+1325 -787

No files matched your search

+23
View File
@@ -10073,6 +10073,29 @@ S: Maintained
W: https://floatingpoint.billm.au/
F: arch/x86/math-emu/
FRAMEBUFFER CONSOLE
M: Helge Deller <deller@gmx.de>
M: Thomas Zimmermann <tzimmermann@suse.de>
L: dri-devel@lists.freedesktop.org
L: linux-fbdev@vger.kernel.org
S: Maintained
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
F: Documentation/fb/fbcon.rst
F: drivers/video/fbdev/core/bitblit.c
F: drivers/video/fbdev/core/fb_logo.c
F: drivers/video/fbdev/core/fbcon.c
F: drivers/video/fbdev/core/fbcon.h
F: drivers/video/fbdev/core/fbcon_ccw.c
F: drivers/video/fbdev/core/fbcon_cw.c
F: drivers/video/fbdev/core/fbcon_rotate.c
F: drivers/video/fbdev/core/fbcon_rotate.h
F: drivers/video/fbdev/core/fbcon_ud.c
F: drivers/video/fbdev/core/softcursor.c
F: drivers/video/fbdev/core/tileblit.c
F: include/linux/fbcon.h
F: include/linux/font.h
F: lib/fonts/
FRAMEBUFFER CORE
M: Simona Vetter <simona@ffwll.ch>
S: Odd Fixes
+34
View File
@@ -230,6 +230,40 @@ enum {
blank_vesa_wait,
};
/*
* struct vc_font
*/
/**
* vc_font_pitch - Calculates the number of bytes between two adjacent scanlines
* @font: The VC font
*
* Returns:
* The number of bytes between two adjacent scanlines in the font data
*/
unsigned int vc_font_pitch(const struct vc_font *font)
{
return font_glyph_pitch(font->width);
}
EXPORT_SYMBOL_GPL(vc_font_pitch);
/**
* vc_font_size - Calculates the size of the font data in bytes
* @font: The VC font
*
* vc_font_size() calculates the number of bytes of font data in the
* font specified by @font. The function calculates the size from the
* font parameters.
*
* Returns:
* The size of the font data in bytes.
*/
unsigned int vc_font_size(const struct vc_font *font)
{
return font_glyph_size(font->width, font->height) * font->charcount;
}
EXPORT_SYMBOL_GPL(vc_font_size);
/*
* /sys/class/tty/tty0/
*
+19 -42
View File
@@ -33,9 +33,9 @@
#define NEWPORT_LEN 0x10000
#define FONT_DATA ((unsigned char *)font_vga_8x16.data)
#define FONT_DATA font_vga_8x16.data
static unsigned char *font_data[MAX_NR_CONSOLES];
static font_data_t *font_data[MAX_NR_CONSOLES];
static struct newport_regs *npregs;
static unsigned long newport_addr;
@@ -370,9 +370,9 @@ static void newport_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
static void newport_putc(struct vc_data *vc, u16 charattr, unsigned int ypos,
unsigned int xpos)
{
unsigned char *p;
const unsigned char *p;
p = &font_data[vc->vc_num][(charattr & 0xff) << 4];
p = &font_data_buf(font_data[vc->vc_num])[(charattr & 0xff) << 4];
charattr = (charattr >> 8) & 0xff;
xpos <<= 3;
ypos <<= 4;
@@ -400,7 +400,7 @@ static void newport_putcs(struct vc_data *vc, const u16 *s,
unsigned int count, unsigned int ypos,
unsigned int xpos)
{
unsigned char *p;
const unsigned char *p;
unsigned int i;
u16 charattr;
@@ -424,7 +424,7 @@ static void newport_putcs(struct vc_data *vc, const u16 *s,
NPORT_DMODE0_L32);
for (i = 0; i < count; i++, xpos += 8) {
p = &font_data[vc->vc_num][(scr_readw(s++) & 0xff) << 4];
p = &font_data_buf(font_data[vc->vc_num])[(scr_readw(s++) & 0xff) << 4];
newport_wait(npregs);
@@ -501,52 +501,32 @@ static int newport_set_font(int unit, const struct console_font *op,
{
int w = op->width;
int h = op->height;
int size = h * op->charcount;
int i;
unsigned char *new_data, *data = op->data, *p;
font_data_t *new_data;
/* ladis: when I grow up, there will be a day... and more sizes will
* be supported ;-) */
if ((w != 8) || (h != 16) || (vpitch != 32)
|| (op->charcount != 256 && op->charcount != 512))
if (w != 8 || h != 16 || (op->charcount != 256 && op->charcount != 512))
return -EINVAL;
if (!(new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size,
GFP_USER))) return -ENOMEM;
new_data += FONT_EXTRA_WORDS * sizeof(int);
FNTSIZE(new_data) = size;
FNTCHARCNT(new_data) = op->charcount;
REFCOUNT(new_data) = 0; /* usage counter */
FNTSUM(new_data) = 0;
p = new_data;
for (i = 0; i < op->charcount; i++) {
memcpy(p, data, h);
data += 32;
p += h;
}
new_data = font_data_import(op, vpitch, NULL);
if (IS_ERR(new_data))
return PTR_ERR(new_data);
/* check if font is already used by other console */
for (i = 0; i < MAX_NR_CONSOLES; i++) {
if (font_data[i] != FONT_DATA
&& FNTSIZE(font_data[i]) == size
&& !memcmp(font_data[i], new_data, size)) {
kfree(new_data - FONT_EXTRA_WORDS * sizeof(int));
if (font_data_is_equal(font_data[i], new_data)) {
font_data_put(new_data);
/* current font is the same as the new one */
if (i == unit)
return 0;
new_data = font_data[i];
font_data_get(new_data);
break;
}
}
/* old font is user font */
if (font_data[unit] != FONT_DATA) {
if (--REFCOUNT(font_data[unit]) == 0)
kfree(font_data[unit] -
FONT_EXTRA_WORDS * sizeof(int));
}
REFCOUNT(new_data)++;
font_data_put(font_data[unit]);
font_data[unit] = new_data;
return 0;
@@ -554,12 +534,9 @@ static int newport_set_font(int unit, const struct console_font *op,
static int newport_set_def_font(int unit, struct console_font *op)
{
if (font_data[unit] != FONT_DATA) {
if (--REFCOUNT(font_data[unit]) == 0)
kfree(font_data[unit] -
FONT_EXTRA_WORDS * sizeof(int));
font_data[unit] = FONT_DATA;
}
font_data_put(font_data[unit]);
font_data[unit] = FONT_DATA;
font_data_get(font_data[unit]);
return 0;
}
+6 -4
View File
@@ -668,10 +668,12 @@ config FB_NVIDIA
select BITREVERSE
select VGASTATE
help
This driver supports graphics boards with the nVidia chips, TNT
and newer. For very old chipsets, such as the RIVA128, then use
the rivafb.
Say Y if you have such a graphics board.
This driver supports graphics boards with the nVidia chips, from TNT
through early GeForce generations (NV4–NV2x: Twintor, Twintor2, Celsius,
Kelvin).
Later architectures (Rankine and newer) are not reliably supported.
For very old chipsets, such as the RIVA128, use rivafb.
If unsure, say N.
To compile this driver as a module, choose M here: the
module will be called nvidiafb.
-4
View File
@@ -2324,8 +2324,6 @@ static void aty_calc_mem_refresh(struct atyfb_par *par, int xclk)
* Initialisation
*/
static struct fb_info *fb_list = NULL;
#if defined(__i386__) && defined(CONFIG_FB_ATY_GENERIC_LCD)
static int atyfb_get_timings_from_lcd(struct atyfb_par *par,
struct fb_var_screeninfo *var)
@@ -2758,8 +2756,6 @@ static int aty_init(struct fb_info *info)
#endif
}
fb_list = info;
PRINTKI("fb%d: %s frame buffer device on %s\n",
info->node, info->fix.id, par->bus_type == ISA ? "ISA" : "PCI");
return 0;
+8 -38
View File
@@ -22,8 +22,7 @@
/*
* Accelerated handlers.
*/
static void update_attr(u8 *dst, u8 *src, int attribute,
struct vc_data *vc)
static void update_attr(u8 *dst, const u8 *src, int attribute, struct vc_data *vc)
{
int i, offset = (vc->vc_font.height < 10) ? 1 : 2;
int width = DIV_ROUND_UP(vc->vc_font.width, 8);
@@ -81,7 +80,7 @@ static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info,
u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
unsigned int charcnt = vc->vc_font.charcount;
u32 idx = vc->vc_font.width >> 3;
u8 *src;
const u8 *src;
while (cnt--) {
u16 ch = scr_readw(s++) & charmask;
@@ -120,7 +119,7 @@ static inline void bit_putcs_unaligned(struct vc_data *vc,
u32 shift_low = 0, mod = vc->vc_font.width % 8;
u32 shift_high = 8;
u32 idx = vc->vc_font.width >> 3;
u8 *src;
const u8 *src;
while (cnt--) {
u16 ch = scr_readw(s++) & charmask;
@@ -267,7 +266,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
int y = real_y(par->p, vc->state.y);
int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1;
char *src;
const u8 *src;
cursor.set = 0;
@@ -278,7 +277,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
attribute = get_attribute(info, c);
src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
if (par->cursor_state.image.data != src ||
if (par->cursor_state.image.data != (const char *)src ||
par->cursor_reset) {
par->cursor_state.image.data = src;
cursor.set |= FB_CUR_SETIMAGE;
@@ -330,46 +329,17 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
vc->vc_cursor_type != par->p->cursor_shape ||
par->cursor_state.mask == NULL ||
par->cursor_reset) {
char *mask = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC);
int cur_height, size, i = 0;
u8 msk = 0xff;
unsigned char *mask = kmalloc_array(vc->vc_font.height, w, GFP_ATOMIC);
if (!mask)
return;
fbcon_fill_cursor_mask(par, vc, mask);
kfree(par->cursor_state.mask);
par->cursor_state.mask = mask;
par->cursor_state.mask = (const char *)mask;
par->p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE;
switch (CUR_SIZE(par->p->cursor_shape)) {
case CUR_NONE:
cur_height = 0;
break;
case CUR_UNDERLINE:
cur_height = (vc->vc_font.height < 10) ? 1 : 2;
break;
case CUR_LOWER_THIRD:
cur_height = vc->vc_font.height/3;
break;
case CUR_LOWER_HALF:
cur_height = vc->vc_font.height >> 1;
break;
case CUR_TWO_THIRDS:
cur_height = (vc->vc_font.height << 1)/3;
break;
case CUR_BLOCK:
default:
cur_height = vc->vc_font.height;
break;
}
size = (vc->vc_font.height - cur_height) * w;
while (size--)
mask[i++] = ~msk;
size = cur_height * w;
while (size--)
mask[i++] = msk;
}
par->cursor_state.enable = enable && !use_sw;
+192 -74
View File
@@ -14,6 +14,7 @@
#include <linux/export.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
@@ -24,6 +25,104 @@
#include <linux/rmap.h>
#include <linux/pagemap.h>
struct address_space;
/*
* struct fb_deferred_io_state
*/
struct fb_deferred_io_state {
struct kref ref;
int open_count; /* number of opened files; protected by fb_info lock */
struct address_space *mapping; /* page cache object for fb device */
struct mutex lock; /* mutex that protects the pageref list */
/* fields protected by lock */
struct fb_info *info;
struct list_head pagereflist; /* list of pagerefs for touched pages */
unsigned long npagerefs;
struct fb_deferred_io_pageref *pagerefs;
};
static struct fb_deferred_io_state *fb_deferred_io_state_alloc(unsigned long len)
{
struct fb_deferred_io_state *fbdefio_state;
struct fb_deferred_io_pageref *pagerefs;
unsigned long npagerefs;
fbdefio_state = kzalloc_obj(*fbdefio_state);
if (!fbdefio_state)
return NULL;
npagerefs = DIV_ROUND_UP(len, PAGE_SIZE);
/* alloc a page ref for each page of the display memory */
pagerefs = kvzalloc_objs(*pagerefs, npagerefs);
if (!pagerefs)
goto err_kfree;
fbdefio_state->npagerefs = npagerefs;
fbdefio_state->pagerefs = pagerefs;
kref_init(&fbdefio_state->ref);
mutex_init(&fbdefio_state->lock);
INIT_LIST_HEAD(&fbdefio_state->pagereflist);
return fbdefio_state;
err_kfree:
kfree(fbdefio_state);
return NULL;
}
static void fb_deferred_io_state_release(struct fb_deferred_io_state *fbdefio_state)
{
WARN_ON(!list_empty(&fbdefio_state->pagereflist));
mutex_destroy(&fbdefio_state->lock);
kvfree(fbdefio_state->pagerefs);
kfree(fbdefio_state);
}
static void fb_deferred_io_state_get(struct fb_deferred_io_state *fbdefio_state)
{
kref_get(&fbdefio_state->ref);
}
static void __fb_deferred_io_state_release(struct kref *ref)
{
struct fb_deferred_io_state *fbdefio_state =
container_of(ref, struct fb_deferred_io_state, ref);
fb_deferred_io_state_release(fbdefio_state);
}
static void fb_deferred_io_state_put(struct fb_deferred_io_state *fbdefio_state)
{
kref_put(&fbdefio_state->ref, __fb_deferred_io_state_release);
}
/*
* struct vm_operations_struct
*/
static void fb_deferred_io_vm_open(struct vm_area_struct *vma)
{
struct fb_deferred_io_state *fbdefio_state = vma->vm_private_data;
WARN_ON_ONCE(!try_module_get(THIS_MODULE));
fb_deferred_io_state_get(fbdefio_state);
}
static void fb_deferred_io_vm_close(struct vm_area_struct *vma)
{
struct fb_deferred_io_state *fbdefio_state = vma->vm_private_data;
fb_deferred_io_state_put(fbdefio_state);
module_put(THIS_MODULE);
}
static struct page *fb_deferred_io_get_page(struct fb_info *info, unsigned long offs)
{
struct fb_deferred_io *fbdefio = info->fbdefio;
@@ -44,18 +143,19 @@ static struct page *fb_deferred_io_get_page(struct fb_info *info, unsigned long
return page;
}
static struct fb_deferred_io_pageref *fb_deferred_io_pageref_lookup(struct fb_info *info,
unsigned long offset,
struct page *page)
static struct fb_deferred_io_pageref *
fb_deferred_io_pageref_lookup(struct fb_deferred_io_state *fbdefio_state, unsigned long offset,
struct page *page)
{
struct fb_info *info = fbdefio_state->info;
unsigned long pgoff = offset >> PAGE_SHIFT;
struct fb_deferred_io_pageref *pageref;
if (fb_WARN_ON_ONCE(info, pgoff >= info->npagerefs))
if (fb_WARN_ON_ONCE(info, pgoff >= fbdefio_state->npagerefs))
return NULL; /* incorrect allocation size */
/* 1:1 mapping between pageref and page offset */
pageref = &info->pagerefs[pgoff];
pageref = &fbdefio_state->pagerefs[pgoff];
if (pageref->page)
goto out;
@@ -75,10 +175,11 @@ static struct fb_deferred_io_pageref *fb_deferred_io_pageref_get(struct fb_info
struct page *page)
{
struct fb_deferred_io *fbdefio = info->fbdefio;
struct list_head *pos = &fbdefio->pagereflist;
struct fb_deferred_io_state *fbdefio_state = info->fbdefio_state;
struct list_head *pos = &fbdefio_state->pagereflist;
struct fb_deferred_io_pageref *pageref, *cur;
pageref = fb_deferred_io_pageref_lookup(info, offset, page);
pageref = fb_deferred_io_pageref_lookup(fbdefio_state, offset, page);
if (!pageref)
return NULL;
@@ -99,7 +200,7 @@ static struct fb_deferred_io_pageref *fb_deferred_io_pageref_get(struct fb_info
* pages. If possible, drivers should try to work with
* unsorted page lists instead.
*/
list_for_each_entry(cur, &fbdefio->pagereflist, list) {
list_for_each_entry(cur, &fbdefio_state->pagereflist, list) {
if (cur->offset > pageref->offset)
break;
}
@@ -121,25 +222,46 @@ static void fb_deferred_io_pageref_put(struct fb_deferred_io_pageref *pageref,
/* this is to find and return the vmalloc-ed fb pages */
static vm_fault_t fb_deferred_io_fault(struct vm_fault *vmf)
{
struct fb_info *info;
unsigned long offset;
struct page *page;
struct fb_info *info = vmf->vma->vm_private_data;
vm_fault_t ret;
struct fb_deferred_io_state *fbdefio_state = vmf->vma->vm_private_data;
mutex_lock(&fbdefio_state->lock);
info = fbdefio_state->info;
if (!info) {
ret = VM_FAULT_SIGBUS; /* our device is gone */
goto err_mutex_unlock;
}
offset = vmf->pgoff << PAGE_SHIFT;
if (offset >= info->fix.smem_len)
return VM_FAULT_SIGBUS;
if (offset >= info->fix.smem_len) {
ret = VM_FAULT_SIGBUS;
goto err_mutex_unlock;
}
page = fb_deferred_io_get_page(info, offset);
if (!page)
return VM_FAULT_SIGBUS;
if (!page) {
ret = VM_FAULT_SIGBUS;
goto err_mutex_unlock;
}
if (!vmf->vma->vm_file)
fb_err(info, "no mapping available\n");
BUG_ON(!info->fbdefio->mapping);
fb_WARN_ON_ONCE(info, !fbdefio_state->mapping);
mutex_unlock(&fbdefio_state->lock);
vmf->page = page;
return 0;
err_mutex_unlock:
mutex_unlock(&fbdefio_state->lock);
return ret;
}
int fb_deferred_io_fsync(struct file *file, loff_t start, loff_t end, int datasync)
@@ -166,15 +288,24 @@ EXPORT_SYMBOL_GPL(fb_deferred_io_fsync);
* Adds a page to the dirty list. Call this from struct
* vm_operations_struct.page_mkwrite.
*/
static vm_fault_t fb_deferred_io_track_page(struct fb_info *info, unsigned long offset,
struct page *page)
static vm_fault_t fb_deferred_io_track_page(struct fb_deferred_io_state *fbdefio_state,
unsigned long offset, struct page *page)
{
struct fb_deferred_io *fbdefio = info->fbdefio;
struct fb_info *info;
struct fb_deferred_io *fbdefio;
struct fb_deferred_io_pageref *pageref;
vm_fault_t ret;
/* protect against the workqueue changing the page list */
mutex_lock(&fbdefio->lock);
mutex_lock(&fbdefio_state->lock);
info = fbdefio_state->info;
if (!info) {
ret = VM_FAULT_SIGBUS; /* our device is gone */
goto err_mutex_unlock;
}
fbdefio = info->fbdefio;
pageref = fb_deferred_io_pageref_get(info, offset, page);
if (WARN_ON_ONCE(!pageref)) {
@@ -192,50 +323,38 @@ static vm_fault_t fb_deferred_io_track_page(struct fb_info *info, unsigned long
*/
lock_page(pageref->page);
mutex_unlock(&fbdefio->lock);
mutex_unlock(&fbdefio_state->lock);
/* come back after delay to process the deferred IO */
schedule_delayed_work(&info->deferred_work, fbdefio->delay);
return VM_FAULT_LOCKED;
err_mutex_unlock:
mutex_unlock(&fbdefio->lock);
mutex_unlock(&fbdefio_state->lock);
return ret;
}
/*
* fb_deferred_io_page_mkwrite - Mark a page as written for deferred I/O
* @fb_info: The fbdev info structure
* @vmf: The VM fault
*
* This is a callback we get when userspace first tries to
* write to the page. We schedule a workqueue. That workqueue
* will eventually mkclean the touched pages and execute the
* deferred framebuffer IO. Then if userspace touches a page
* again, we repeat the same scheme.
*
* Returns:
* VM_FAULT_LOCKED on success, or a VM_FAULT error otherwise.
*/
static vm_fault_t fb_deferred_io_page_mkwrite(struct fb_info *info, struct vm_fault *vmf)
static vm_fault_t fb_deferred_io_page_mkwrite(struct fb_deferred_io_state *fbdefio_state,
struct vm_fault *vmf)
{
unsigned long offset = vmf->pgoff << PAGE_SHIFT;
struct page *page = vmf->page;
file_update_time(vmf->vma->vm_file);
return fb_deferred_io_track_page(info, offset, page);
return fb_deferred_io_track_page(fbdefio_state, offset, page);
}
/* vm_ops->page_mkwrite handler */
static vm_fault_t fb_deferred_io_mkwrite(struct vm_fault *vmf)
{
struct fb_info *info = vmf->vma->vm_private_data;
struct fb_deferred_io_state *fbdefio_state = vmf->vma->vm_private_data;
return fb_deferred_io_page_mkwrite(info, vmf);
return fb_deferred_io_page_mkwrite(fbdefio_state, vmf);
}
static const struct vm_operations_struct fb_deferred_io_vm_ops = {
.open = fb_deferred_io_vm_open,
.close = fb_deferred_io_vm_close,
.fault = fb_deferred_io_fault,
.page_mkwrite = fb_deferred_io_mkwrite,
};
@@ -248,11 +367,17 @@ int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
if (!try_module_get(THIS_MODULE))
return -EINVAL;
vma->vm_ops = &fb_deferred_io_vm_ops;
vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP);
if (!(info->flags & FBINFO_VIRTFB))
vm_flags_set(vma, VM_IO);
vma->vm_private_data = info;
vma->vm_private_data = info->fbdefio_state;
fb_deferred_io_state_get(info->fbdefio_state); /* released in vma->vm_ops->close() */
return 0;
}
EXPORT_SYMBOL_GPL(fb_deferred_io_mmap);
@@ -263,63 +388,52 @@ static void fb_deferred_io_work(struct work_struct *work)
struct fb_info *info = container_of(work, struct fb_info, deferred_work.work);
struct fb_deferred_io_pageref *pageref, *next;
struct fb_deferred_io *fbdefio = info->fbdefio;
struct fb_deferred_io_state *fbdefio_state = info->fbdefio_state;
/* here we wrprotect the page's mappings, then do all deferred IO. */
mutex_lock(&fbdefio->lock);
mutex_lock(&fbdefio_state->lock);
#ifdef CONFIG_MMU
list_for_each_entry(pageref, &fbdefio->pagereflist, list) {
list_for_each_entry(pageref, &fbdefio_state->pagereflist, list) {
struct page *page = pageref->page;
pgoff_t pgoff = pageref->offset >> PAGE_SHIFT;
mapping_wrprotect_range(fbdefio->mapping, pgoff,
mapping_wrprotect_range(fbdefio_state->mapping, pgoff,
page_to_pfn(page), 1);
}
#endif
/* driver's callback with pagereflist */
fbdefio->deferred_io(info, &fbdefio->pagereflist);
fbdefio->deferred_io(info, &fbdefio_state->pagereflist);
/* clear the list */
list_for_each_entry_safe(pageref, next, &fbdefio->pagereflist, list)
list_for_each_entry_safe(pageref, next, &fbdefio_state->pagereflist, list)
fb_deferred_io_pageref_put(pageref, info);
mutex_unlock(&fbdefio->lock);
mutex_unlock(&fbdefio_state->lock);
}
int fb_deferred_io_init(struct fb_info *info)
{
struct fb_deferred_io *fbdefio = info->fbdefio;
struct fb_deferred_io_pageref *pagerefs;
unsigned long npagerefs;
int ret;
struct fb_deferred_io_state *fbdefio_state;
BUG_ON(!fbdefio);
if (WARN_ON(!info->fix.smem_len))
return -EINVAL;
mutex_init(&fbdefio->lock);
fbdefio_state = fb_deferred_io_state_alloc(info->fix.smem_len);
if (!fbdefio_state)
return -ENOMEM;
fbdefio_state->info = info;
INIT_DELAYED_WORK(&info->deferred_work, fb_deferred_io_work);
INIT_LIST_HEAD(&fbdefio->pagereflist);
if (fbdefio->delay == 0) /* set a default of 1 s */
fbdefio->delay = HZ;
npagerefs = DIV_ROUND_UP(info->fix.smem_len, PAGE_SIZE);
/* alloc a page ref for each page of the display memory */
pagerefs = kvzalloc_objs(*pagerefs, npagerefs);
if (!pagerefs) {
ret = -ENOMEM;
goto err;
}
info->npagerefs = npagerefs;
info->pagerefs = pagerefs;
info->fbdefio_state = fbdefio_state;
return 0;
err:
mutex_destroy(&fbdefio->lock);
return ret;
}
EXPORT_SYMBOL_GPL(fb_deferred_io_init);
@@ -327,11 +441,11 @@ void fb_deferred_io_open(struct fb_info *info,
struct inode *inode,
struct file *file)
{
struct fb_deferred_io *fbdefio = info->fbdefio;
struct fb_deferred_io_state *fbdefio_state = info->fbdefio_state;
fbdefio->mapping = file->f_mapping;
fbdefio_state->mapping = file->f_mapping;
file->f_mapping->a_ops = &fb_deferred_io_aops;
fbdefio->open_count++;
fbdefio_state->open_count++;
}
EXPORT_SYMBOL_GPL(fb_deferred_io_open);
@@ -342,21 +456,25 @@ static void fb_deferred_io_lastclose(struct fb_info *info)
void fb_deferred_io_release(struct fb_info *info)
{
struct fb_deferred_io *fbdefio = info->fbdefio;
struct fb_deferred_io_state *fbdefio_state = info->fbdefio_state;
if (!--fbdefio->open_count)
if (!--fbdefio_state->open_count)
fb_deferred_io_lastclose(info);
}
EXPORT_SYMBOL_GPL(fb_deferred_io_release);
void fb_deferred_io_cleanup(struct fb_info *info)
{
struct fb_deferred_io *fbdefio = info->fbdefio;
struct fb_deferred_io_state *fbdefio_state = info->fbdefio_state;
fb_deferred_io_lastclose(info);
kvfree(info->pagerefs);
mutex_destroy(&fbdefio->lock);
fbdefio->mapping = NULL;
info->fbdefio_state = NULL;
mutex_lock(&fbdefio_state->lock);
fbdefio_state->info = NULL;
mutex_unlock(&fbdefio_state->lock);
fb_deferred_io_state_put(fbdefio_state);
}
EXPORT_SYMBOL_GPL(fb_deferred_io_cleanup);
+99 -143
View File
@@ -446,6 +446,46 @@ static void fbcon_del_cursor_work(struct fb_info *info)
cancel_delayed_work_sync(&par->cursor_work);
}
void fbcon_fill_cursor_mask(struct fbcon_par *par, struct vc_data *vc, unsigned char *mask)
{
static const unsigned int pattern = 0xffffffff;
unsigned int pitch = vc_font_pitch(&vc->vc_font);
unsigned int cur_height, size;
switch (CUR_SIZE(vc->vc_cursor_type)) {
case CUR_NONE:
cur_height = 0;
break;
case CUR_UNDERLINE:
if (vc->vc_font.height < 10)
cur_height = 1;
else
cur_height = 2;
break;
case CUR_LOWER_THIRD:
cur_height = vc->vc_font.height / 3;
break;
case CUR_LOWER_HALF:
cur_height = vc->vc_font.height / 2;
break;
case CUR_TWO_THIRDS:
cur_height = (vc->vc_font.height * 2) / 3;
break;
case CUR_BLOCK:
default:
cur_height = vc->vc_font.height;
break;
}
size = (vc->vc_font.height - cur_height) * pitch;
while (size--)
*mask++ = (unsigned char)~pattern;
size = cur_height * pitch;
while (size--)
*mask++ = (unsigned char)pattern;
}
#ifndef MODULE
static int __init fb_console_setup(char *this_opt)
{
@@ -747,7 +787,9 @@ static void fbcon_release(struct fb_info *info)
kfree(par->cursor_state.mask);
kfree(par->cursor_data);
kfree(par->cursor_src);
kfree(par->fontbuffer);
#ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION
kfree(par->rotated.buf);
#endif
kfree(info->fbcon_par);
info->fbcon_par = NULL;
}
@@ -1000,7 +1042,9 @@ static const char *fbcon_startup(void)
par = info->fbcon_par;
par->currcon = -1;
par->graphics = 1;
par->cur_rotate = -1;
#ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION
par->rotated.buf_rotate = -1;
#endif
p->con_rotate = initial_rotation;
if (p->con_rotate == -1)
@@ -1019,8 +1063,11 @@ static const char *fbcon_startup(void)
info->pixmap.blit_y);
vc->vc_font.width = font->width;
vc->vc_font.height = font->height;
vc->vc_font.data = (void *)(p->fontdata = font->data);
vc->vc_font.data = font_data_buf(font->data);
vc->vc_font.charcount = font->charcount;
p->fontdata = font->data;
font_data_get(p->fontdata);
}
cols = FBCON_SWAP(par->rotate, info->var.xres, info->var.yres);
@@ -1078,15 +1125,13 @@ static void fbcon_init(struct vc_data *vc, bool init)
if (t->fontdata) {
struct vc_data *fvc = vc_cons[fg_console].d;
vc->vc_font.data = (void *)(p->fontdata =
fvc->vc_font.data);
vc->vc_font.data = fvc->vc_font.data;
vc->vc_font.width = fvc->vc_font.width;
vc->vc_font.height = fvc->vc_font.height;
vc->vc_font.charcount = fvc->vc_font.charcount;
p->userfont = t->userfont;
if (p->userfont)
REFCOUNT(p->fontdata)++;
p->fontdata = t->fontdata;
font_data_get(p->fontdata);
} else {
const struct font_desc *font = NULL;
@@ -1097,8 +1142,11 @@ static void fbcon_init(struct vc_data *vc, bool init)
info->pixmap.blit_y);
vc->vc_font.width = font->width;
vc->vc_font.height = font->height;
vc->vc_font.data = (void *)(p->fontdata = font->data);
vc->vc_font.data = font_data_buf(font->data);
vc->vc_font.charcount = font->charcount;
p->fontdata = font->data;
font_data_get(p->fontdata);
}
}
@@ -1189,10 +1237,10 @@ static void fbcon_init(struct vc_data *vc, bool init)
static void fbcon_free_font(struct fbcon_display *p)
{
if (p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0))
kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int));
p->fontdata = NULL;
p->userfont = 0;
if (p->fontdata) {
font_data_put(p->fontdata);
p->fontdata = NULL;
}
}
static void set_vc_hi_font(struct vc_data *vc, bool set);
@@ -1409,14 +1457,13 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
svc = *default_mode;
t = &fb_display[svc->vc_num];
if (!vc->vc_font.data) {
vc->vc_font.data = (void *)(p->fontdata = t->fontdata);
if (!p->fontdata) {
vc->vc_font.data = font_data_buf(t->fontdata);
vc->vc_font.width = (*default_mode)->vc_font.width;
vc->vc_font.height = (*default_mode)->vc_font.height;
vc->vc_font.charcount = (*default_mode)->vc_font.charcount;
p->userfont = t->userfont;
if (p->userfont)
REFCOUNT(p->fontdata)++;
p->fontdata = t->fontdata;
font_data_get(p->fontdata);
}
var->activate = FB_ACTIVATE_NOW;
@@ -2036,9 +2083,6 @@ static void updatescrollmode(struct fbcon_display *p,
updatescrollmode_accel(p, info, vc);
}
#define PITCH(w) (((w) + 7) >> 3)
#define CALC_FONTSZ(h, p, c) ((h) * (p) * (c)) /* size = height * pitch * charcount */
static int fbcon_resize(struct vc_data *vc, unsigned int width,
unsigned int height, bool from_user)
{
@@ -2048,9 +2092,8 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
struct fb_var_screeninfo var = info->var;
int x_diff, y_diff, virt_w, virt_h, virt_fw, virt_fh;
if (p->userfont && FNTSIZE(vc->vc_font.data)) {
int size;
int pitch = PITCH(vc->vc_font.width);
if (font_data_size(p->fontdata)) {
unsigned int size = vc_font_size(&vc->vc_font);
/*
* If user font, ensure that a possible change to user font
@@ -2059,10 +2102,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
* charcount can change and cannot be used to determine the
* font data allocated size.
*/
if (pitch <= 0)
return -EINVAL;
size = CALC_FONTSZ(vc->vc_font.height, pitch, vc->vc_font.charcount);
if (size > FNTSIZE(vc->vc_font.data))
if (!size || size > font_data_size(p->fontdata))
return -EINVAL;
}
@@ -2286,67 +2326,15 @@ static bool fbcon_blank(struct vc_data *vc, enum vesa_blank_mode blank,
static int fbcon_get_font(struct vc_data *vc, struct console_font *font, unsigned int vpitch)
{
u8 *fontdata = vc->vc_font.data;
u8 *data = font->data;
int i, j;
const struct fbcon_display *p = &fb_display[vc->vc_num];
font->width = vc->vc_font.width;
font->height = vc->vc_font.height;
if (font->height > vpitch)
return -ENOSPC;
font->charcount = vc->vc_hi_font_mask ? 512 : 256;
if (!font->data)
return 0;
if (font->width <= 8) {
j = vc->vc_font.height;
if (font->charcount * j > FNTSIZE(fontdata))
return -EINVAL;
for (i = 0; i < font->charcount; i++) {
memcpy(data, fontdata, j);
memset(data + j, 0, vpitch - j);
data += vpitch;
fontdata += j;
}
} else if (font->width <= 16) {
j = vc->vc_font.height * 2;
if (font->charcount * j > FNTSIZE(fontdata))
return -EINVAL;
for (i = 0; i < font->charcount; i++) {
memcpy(data, fontdata, j);
memset(data + j, 0, 2*vpitch - j);
data += 2*vpitch;
fontdata += j;
}
} else if (font->width <= 24) {
if (font->charcount * (vc->vc_font.height * sizeof(u32)) > FNTSIZE(fontdata))
return -EINVAL;
for (i = 0; i < font->charcount; i++) {
for (j = 0; j < vc->vc_font.height; j++) {
*data++ = fontdata[0];
*data++ = fontdata[1];
*data++ = fontdata[2];
fontdata += sizeof(u32);
}
memset(data, 0, 3 * (vpitch - j));
data += 3 * (vpitch - j);
}
} else {
j = vc->vc_font.height * 4;
if (font->charcount * j > FNTSIZE(fontdata))
return -EINVAL;
for (i = 0; i < font->charcount; i++) {
memcpy(data, fontdata, j);
memset(data + j, 0, 4 * vpitch - j);
data += 4 * vpitch;
fontdata += j;
}
}
return 0;
return font_data_export(p->fontdata, font, vpitch);
}
/* set/clear vc_hi_font_mask and update vc attrs accordingly */
@@ -2411,20 +2399,20 @@ static void set_vc_hi_font(struct vc_data *vc, bool set)
}
static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
const u8 * data, int userfont)
font_data_t *data)
{
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
struct fbcon_par *par = info->fbcon_par;
struct fbcon_display *p = &fb_display[vc->vc_num];
int resize, ret, old_userfont, old_width, old_height, old_charcount;
u8 *old_data = vc->vc_font.data;
int resize, ret, old_width, old_height, old_charcount;
font_data_t *old_fontdata = p->fontdata;
const u8 *old_data = vc->vc_font.data;
font_data_get(data);
resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
vc->vc_font.data = (void *)(p->fontdata = data);
old_userfont = p->userfont;
if ((p->userfont = userfont))
REFCOUNT(data)++;
p->fontdata = data;
vc->vc_font.data = font_data_buf(p->fontdata);
old_width = vc->vc_font.width;
old_height = vc->vc_font.height;
old_charcount = vc->vc_font.charcount;
@@ -2453,24 +2441,20 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
update_screen(vc);
}
if (old_userfont && (--REFCOUNT(old_data) == 0))
kfree(old_data - FONT_EXTRA_WORDS * sizeof(int));
if (old_fontdata)
font_data_put(old_fontdata);
return 0;
err_out:
p->fontdata = old_data;
p->fontdata = old_fontdata;
vc->vc_font.data = old_data;
if (userfont) {
p->userfont = old_userfont;
if (--REFCOUNT(data) == 0)
kfree(data - FONT_EXTRA_WORDS * sizeof(int));
}
vc->vc_font.width = old_width;
vc->vc_font.height = old_height;
vc->vc_font.charcount = old_charcount;
font_data_put(data);
return ret;
}
@@ -2486,10 +2470,8 @@ static int fbcon_set_font(struct vc_data *vc, const struct console_font *font,
unsigned charcount = font->charcount;
int w = font->width;
int h = font->height;
int size, alloc_size;
int i, csum;
u8 *new_data, *data = font->data;
int pitch = PITCH(font->width);
int i, ret;
font_data_t *new_data;
/* Is there a reason why fbconsole couldn't handle any charcount >256?
* If not this check should be changed to charcount < 256 */
@@ -2513,50 +2495,24 @@ static int fbcon_set_font(struct vc_data *vc, const struct console_font *font,
if (fbcon_invalid_charcount(info, charcount))
return -EINVAL;
/* Check for integer overflow in font size calculation */
if (check_mul_overflow(h, pitch, &size) ||
check_mul_overflow(size, charcount, &size))
return -EINVAL;
new_data = font_data_import(font, vpitch, crc32);
if (IS_ERR(new_data))
return PTR_ERR(new_data);
/* Check for overflow in allocation size calculation */
if (check_add_overflow(FONT_EXTRA_WORDS * sizeof(int), size, &alloc_size))
return -EINVAL;
new_data = kmalloc(alloc_size, GFP_USER);
if (!new_data)
return -ENOMEM;
memset(new_data, 0, FONT_EXTRA_WORDS * sizeof(int));
new_data += FONT_EXTRA_WORDS * sizeof(int);
FNTSIZE(new_data) = size;
REFCOUNT(new_data) = 0; /* usage counter */
for (i=0; i< charcount; i++) {
memcpy(new_data + i*h*pitch, data + i*vpitch*pitch, h*pitch);
}
/* Since linux has a nice crc32 function use it for counting font
* checksums. */
csum = crc32(0, new_data, size);
FNTSUM(new_data) = csum;
/* Check if the same font is on some other console already */
for (i = first_fb_vc; i <= last_fb_vc; i++) {
struct vc_data *tmp = vc_cons[i].d;
if (fb_display[i].userfont &&
fb_display[i].fontdata &&
FNTSUM(fb_display[i].fontdata) == csum &&
FNTSIZE(fb_display[i].fontdata) == size &&
tmp->vc_font.width == w &&
!memcmp(fb_display[i].fontdata, new_data, size)) {
kfree(new_data - FONT_EXTRA_WORDS * sizeof(int));
new_data = (u8 *)fb_display[i].fontdata;
if (fb_display[i].fontdata &&
font_data_is_equal(fb_display[i].fontdata, new_data)) {
font_data_get(fb_display[i].fontdata);
font_data_put(new_data);
new_data = fb_display[i].fontdata;
break;
}
}
return fbcon_do_set_font(vc, font->width, font->height, charcount, new_data, 1);
ret = fbcon_do_set_font(vc, font->width, font->height, charcount, new_data);
font_data_put(new_data);
return ret;
}
static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font,
@@ -2573,7 +2529,7 @@ static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font,
font->width = f->width;
font->height = f->height;
return fbcon_do_set_font(vc, f->width, f->height, f->charcount, f->data, 0);
return fbcon_do_set_font(vc, f->width, f->height, f->charcount, f->data);
}
static u16 palette_red[16];
+12 -6
View File
@@ -11,6 +11,7 @@
#ifndef _VIDEO_FBCON_H
#define _VIDEO_FBCON_H
#include <linux/font.h>
#include <linux/types.h>
#include <linux/vt_buffer.h>
#include <linux/vt_kern.h>
@@ -25,8 +26,7 @@
struct fbcon_display {
/* Filled in by the low-level console driver */
const u_char *fontdata;
int userfont; /* != 0 if fontdata kmalloc()ed */
font_data_t *fontdata;
#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
u_short scrollmode; /* Scroll Method, use fb_scrollmode() */
#endif
@@ -80,13 +80,17 @@ struct fbcon_par {
int graphics;
bool initialized;
int rotate;
int cur_rotate;
char *cursor_data;
u8 *fontbuffer;
u8 *fontdata;
#ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION
struct {
font_data_t *fontdata; /* source font */
u8 *buf; /* rotated glyphs */
size_t bufsize;
int buf_rotate; /* rotation of buf */
} rotated;
#endif
u8 *cursor_src;
u32 cursor_size;
u32 fd_size;
const struct fbcon_bitops *bitops;
};
@@ -192,6 +196,8 @@ extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);
extern void fbcon_set_bitops_ur(struct fbcon_par *par);
extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor);
void fbcon_fill_cursor_mask(struct fbcon_par *par, struct vc_data *vc, unsigned char *mask);
#define FBCON_ATTRIBUTE_UNDERLINE 1
#define FBCON_ATTRIBUTE_REVERSE 2
#define FBCON_ATTRIBUTE_BOLD 4
+20 -50
View File
@@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/fb.h>
#include <linux/font.h>
#include <linux/vt_kern.h>
#include <linux/console.h>
#include <asm/types.h>
@@ -26,7 +27,7 @@ static void ccw_update_attr(u8 *dst, u8 *src, int attribute,
struct vc_data *vc)
{
int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2;
int width = (vc->vc_font.height + 7) >> 3;
int width = font_glyph_pitch(vc->vc_font.height);
int mod = vc->vc_font.height % 8;
u8 c, msk = ~(0xff << offset), msk1 = 0;
@@ -101,11 +102,11 @@ static inline void ccw_putcs_aligned(struct vc_data *vc, struct fb_info *info,
{
struct fbcon_par *par = info->fbcon_par;
u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
u32 idx = (vc->vc_font.height + 7) >> 3;
u32 idx = font_glyph_pitch(vc->vc_font.height);
u8 *src;
while (cnt--) {
src = par->fontbuffer + (scr_readw(s--) & charmask) * cellsize;
src = par->rotated.buf + (scr_readw(s--) & charmask) * cellsize;
if (attr) {
ccw_update_attr(buf, src, attr, vc);
@@ -131,7 +132,7 @@ static void ccw_putcs(struct vc_data *vc, struct fb_info *info,
{
struct fb_image image;
struct fbcon_par *par = info->fbcon_par;
u32 width = (vc->vc_font.height + 7)/8;
u32 width = font_glyph_pitch(vc->vc_font.height);
u32 cellsize = width * vc->vc_font.width;
u32 maxcnt = info->pixmap.size/cellsize;
u32 scan_align = info->pixmap.scan_align - 1;
@@ -141,7 +142,7 @@ static void ccw_putcs(struct vc_data *vc, struct fb_info *info,
u8 *dst, *buf = NULL;
u32 vyres = GETVYRES(par->p, info);
if (!par->fontbuffer)
if (!par->rotated.buf)
return;
image.fg_color = fg;
@@ -223,21 +224,22 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
struct fb_cursor cursor;
struct fbcon_par *par = info->fbcon_par;
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
int w = (vc->vc_font.height + 7) >> 3, c;
int w = font_glyph_pitch(vc->vc_font.height);
int c;
int y = real_y(par->p, vc->state.y);
int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1, dx, dy;
char *src;
u32 vyres = GETVYRES(par->p, info);
if (!par->fontbuffer)
if (!par->rotated.buf)
return;
cursor.set = 0;
c = scr_readw((u16 *) vc->vc_pos);
attribute = get_attribute(info, c);
src = par->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
src = par->rotated.buf + ((c & charmask) * (w * vc->vc_font.width));
if (par->cursor_state.image.data != src ||
par->cursor_reset) {
@@ -294,58 +296,26 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
vc->vc_cursor_type != par->p->cursor_shape ||
par->cursor_state.mask == NULL ||
par->cursor_reset) {
char *tmp, *mask = kmalloc_array(w, vc->vc_font.width,
GFP_ATOMIC);
int cur_height, size, i = 0;
int width = (vc->vc_font.width + 7)/8;
unsigned char *tmp, *mask;
if (!mask)
tmp = kmalloc_array(vc->vc_font.height, vc_font_pitch(&vc->vc_font), GFP_ATOMIC);
if (!tmp)
return;
fbcon_fill_cursor_mask(par, vc, tmp);
tmp = kmalloc_array(width, vc->vc_font.height, GFP_ATOMIC);
if (!tmp) {
kfree(mask);
mask = kmalloc_array(vc->vc_font.width, w, GFP_ATOMIC);
if (!mask) {
kfree(tmp);
return;
}
font_glyph_rotate_270(tmp, vc->vc_font.width, vc->vc_font.height, mask);
kfree(tmp);
kfree(par->cursor_state.mask);
par->cursor_state.mask = mask;
par->cursor_state.mask = (const char *)mask;
par->p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE;
switch (CUR_SIZE(par->p->cursor_shape)) {
case CUR_NONE:
cur_height = 0;
break;
case CUR_UNDERLINE:
cur_height = (vc->vc_font.height < 10) ? 1 : 2;
break;
case CUR_LOWER_THIRD:
cur_height = vc->vc_font.height/3;
break;
case CUR_LOWER_HALF:
cur_height = vc->vc_font.height >> 1;
break;
case CUR_TWO_THIRDS:
cur_height = (vc->vc_font.height << 1)/3;
break;
case CUR_BLOCK:
default:
cur_height = vc->vc_font.height;
break;
}
size = (vc->vc_font.height - cur_height) * width;
while (size--)
tmp[i++] = 0;
size = cur_height * width;
while (size--)
tmp[i++] = 0xff;
memset(mask, 0, w * vc->vc_font.width);
rotate_ccw(tmp, mask, vc->vc_font.width, vc->vc_font.height);
kfree(tmp);
}
par->cursor_state.enable = enable && !use_sw;
+20 -50
View File
@@ -12,6 +12,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/fb.h>
#include <linux/font.h>
#include <linux/vt_kern.h>
#include <linux/console.h>
#include <asm/types.h>
@@ -26,7 +27,7 @@ static void cw_update_attr(u8 *dst, u8 *src, int attribute,
struct vc_data *vc)
{
int i, j, offset = (vc->vc_font.height < 10) ? 1 : 2;
int width = (vc->vc_font.height + 7) >> 3;
int width = font_glyph_pitch(vc->vc_font.height);
u8 c, msk = ~(0xff >> offset);
for (i = 0; i < vc->vc_font.width; i++) {
@@ -86,11 +87,11 @@ static inline void cw_putcs_aligned(struct vc_data *vc, struct fb_info *info,
{
struct fbcon_par *par = info->fbcon_par;
u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
u32 idx = (vc->vc_font.height + 7) >> 3;
u32 idx = font_glyph_pitch(vc->vc_font.height);
u8 *src;
while (cnt--) {
src = par->fontbuffer + (scr_readw(s++) & charmask) * cellsize;
src = par->rotated.buf + (scr_readw(s++) & charmask) * cellsize;
if (attr) {
cw_update_attr(buf, src, attr, vc);
@@ -116,7 +117,7 @@ static void cw_putcs(struct vc_data *vc, struct fb_info *info,
{
struct fb_image image;
struct fbcon_par *par = info->fbcon_par;
u32 width = (vc->vc_font.height + 7)/8;
u32 width = font_glyph_pitch(vc->vc_font.height);
u32 cellsize = width * vc->vc_font.width;
u32 maxcnt = info->pixmap.size/cellsize;
u32 scan_align = info->pixmap.scan_align - 1;
@@ -126,7 +127,7 @@ static void cw_putcs(struct vc_data *vc, struct fb_info *info,
u8 *dst, *buf = NULL;
u32 vxres = GETVXRES(par->p, info);
if (!par->fontbuffer)
if (!par->rotated.buf)
return;
image.fg_color = fg;
@@ -206,21 +207,22 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
struct fb_cursor cursor;
struct fbcon_par *par = info->fbcon_par;
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
int w = (vc->vc_font.height + 7) >> 3, c;
int w = font_glyph_pitch(vc->vc_font.height);
int c;
int y = real_y(par->p, vc->state.y);
int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1, dx, dy;
char *src;
u32 vxres = GETVXRES(par->p, info);
if (!par->fontbuffer)
if (!par->rotated.buf)
return;
cursor.set = 0;
c = scr_readw((u16 *) vc->vc_pos);
attribute = get_attribute(info, c);
src = par->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
src = par->rotated.buf + ((c & charmask) * (w * vc->vc_font.width));
if (par->cursor_state.image.data != src ||
par->cursor_reset) {
@@ -277,58 +279,26 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
vc->vc_cursor_type != par->p->cursor_shape ||
par->cursor_state.mask == NULL ||
par->cursor_reset) {
char *tmp, *mask = kmalloc_array(w, vc->vc_font.width,
GFP_ATOMIC);
int cur_height, size, i = 0;
int width = (vc->vc_font.width + 7)/8;
unsigned char *tmp, *mask;
if (!mask)
tmp = kmalloc_array(vc->vc_font.height, vc_font_pitch(&vc->vc_font), GFP_ATOMIC);
if (!tmp)
return;
fbcon_fill_cursor_mask(par, vc, tmp);
tmp = kmalloc_array(width, vc->vc_font.height, GFP_ATOMIC);
if (!tmp) {
kfree(mask);
mask = kmalloc_array(vc->vc_font.width, w, GFP_ATOMIC);
if (!mask) {
kfree(tmp);
return;
}
font_glyph_rotate_90(tmp, vc->vc_font.width, vc->vc_font.height, mask);
kfree(tmp);
kfree(par->cursor_state.mask);
par->cursor_state.mask = mask;
par->cursor_state.mask = (const char *)mask;
par->p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE;
switch (CUR_SIZE(par->p->cursor_shape)) {
case CUR_NONE:
cur_height = 0;
break;
case CUR_UNDERLINE:
cur_height = (vc->vc_font.height < 10) ? 1 : 2;
break;
case CUR_LOWER_THIRD:
cur_height = vc->vc_font.height/3;
break;
case CUR_LOWER_HALF:
cur_height = vc->vc_font.height >> 1;
break;
case CUR_TWO_THIRDS:
cur_height = (vc->vc_font.height << 1)/3;
break;
case CUR_BLOCK:
default:
cur_height = vc->vc_font.height;
break;
}
size = (vc->vc_font.height - cur_height) * width;
while (size--)
tmp[i++] = 0;
size = cur_height * width;
while (size--)
tmp[i++] = 0xff;
memset(mask, 0, w * vc->vc_font.width);
rotate_cw(tmp, mask, vc->vc_font.width, vc->vc_font.height);
kfree(tmp);
}
par->cursor_state.enable = enable && !use_sw;
+23 -65
View File
@@ -8,87 +8,45 @@
* more details.
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/fb.h>
#include <linux/vt_kern.h>
#include <linux/console.h>
#include <asm/types.h>
#include <linux/font.h>
#include "fbcon.h"
#include "fbcon_rotate.h"
int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc)
{
struct fbcon_par *par = info->fbcon_par;
int len, err = 0;
int s_cellsize, d_cellsize, i;
const u8 *src;
u8 *dst;
unsigned char *buf;
int ret;
if (vc->vc_font.data == par->fontdata &&
par->p->con_rotate == par->cur_rotate)
goto finished;
if (par->p->fontdata == par->rotated.fontdata && par->rotate == par->rotated.buf_rotate)
return 0;
src = par->fontdata = vc->vc_font.data;
par->cur_rotate = par->p->con_rotate;
len = vc->vc_font.charcount;
s_cellsize = ((vc->vc_font.width + 7)/8) *
vc->vc_font.height;
d_cellsize = s_cellsize;
if (par->rotate == FB_ROTATE_CW ||
par->rotate == FB_ROTATE_CCW)
d_cellsize = ((vc->vc_font.height + 7)/8) *
vc->vc_font.width;
par->rotated.fontdata = par->p->fontdata;
par->rotated.buf_rotate = par->rotate;
if (info->fbops->fb_sync)
info->fbops->fb_sync(info);
if (par->fd_size < d_cellsize * len) {
dst = kmalloc_array(len, d_cellsize, GFP_KERNEL);
if (dst == NULL) {
err = -ENOMEM;
goto finished;
}
par->fd_size = d_cellsize * len;
kfree(par->fontbuffer);
par->fontbuffer = dst;
buf = font_data_rotate(par->rotated.fontdata, vc->vc_font.width,
vc->vc_font.height, vc->vc_font.charcount,
par->rotated.buf_rotate, par->rotated.buf,
&par->rotated.bufsize);
if (IS_ERR(buf)) {
ret = PTR_ERR(buf);
goto err_kfree;
}
dst = par->fontbuffer;
memset(dst, 0, par->fd_size);
par->rotated.buf = buf;
switch (par->rotate) {
case FB_ROTATE_UD:
for (i = len; i--; ) {
rotate_ud(src, dst, vc->vc_font.width,
vc->vc_font.height);
return 0;
src += s_cellsize;
dst += d_cellsize;
}
break;
case FB_ROTATE_CW:
for (i = len; i--; ) {
rotate_cw(src, dst, vc->vc_font.width,
vc->vc_font.height);
src += s_cellsize;
dst += d_cellsize;
}
break;
case FB_ROTATE_CCW:
for (i = len; i--; ) {
rotate_ccw(src, dst, vc->vc_font.width,
vc->vc_font.height);
src += s_cellsize;
dst += d_cellsize;
}
break;
}
err_kfree:
kfree(par->rotated.buf);
par->rotated.buf = NULL; /* clear here to avoid output */
par->rotated.bufsize = 0;
finished:
return err;
return ret;
}
-71
View File
@@ -19,77 +19,6 @@
(fb_scrollmode(s) == SCROLL_REDRAW || fb_scrollmode(s) == SCROLL_MOVE || !(i)->fix.xpanstep) ? \
(i)->var.xres : (i)->var.xres_virtual; })
static inline int pattern_test_bit(u32 x, u32 y, u32 pitch, const char *pat)
{
u32 tmp = (y * pitch) + x, index = tmp / 8, bit = tmp % 8;
pat +=index;
return (*pat) & (0x80 >> bit);
}
static inline void pattern_set_bit(u32 x, u32 y, u32 pitch, char *pat)
{
u32 tmp = (y * pitch) + x, index = tmp / 8, bit = tmp % 8;
pat += index;
(*pat) |= 0x80 >> bit;
}
static inline void rotate_ud(const char *in, char *out, u32 width, u32 height)
{
int i, j;
int shift = (8 - (width % 8)) & 7;
width = (width + 7) & ~7;
for (i = 0; i < height; i++) {
for (j = 0; j < width - shift; j++) {
if (pattern_test_bit(j, i, width, in))
pattern_set_bit(width - (1 + j + shift),
height - (1 + i),
width, out);
}
}
}
static inline void rotate_cw(const char *in, char *out, u32 width, u32 height)
{
int i, j, h = height, w = width;
int shift = (8 - (height % 8)) & 7;
width = (width + 7) & ~7;
height = (height + 7) & ~7;
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
if (pattern_test_bit(j, i, width, in))
pattern_set_bit(height - 1 - i - shift, j,
height, out);
}
}
}
static inline void rotate_ccw(const char *in, char *out, u32 width, u32 height)
{
int i, j, h = height, w = width;
int shift = (8 - (width % 8)) & 7;
width = (width + 7) & ~7;
height = (height + 7) & ~7;
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
if (pattern_test_bit(j, i, width, in))
pattern_set_bit(i, width - 1 - j - shift,
height, out);
}
}
}
int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc);
#if defined(CONFIG_FRAMEBUFFER_CONSOLE_ROTATION)
+22 -45
View File
@@ -26,7 +26,7 @@ static void ud_update_attr(u8 *dst, u8 *src, int attribute,
struct vc_data *vc)
{
int i, offset = (vc->vc_font.height < 10) ? 1 : 2;
int width = (vc->vc_font.width + 7) >> 3;
int width = font_glyph_pitch(vc->vc_font.width);
unsigned int cellsize = vc->vc_font.height * width;
u8 c;
@@ -92,7 +92,7 @@ static inline void ud_putcs_aligned(struct vc_data *vc, struct fb_info *info,
u8 *src;
while (cnt--) {
src = par->fontbuffer + (scr_readw(s--) & charmask) * cellsize;
src = par->rotated.buf + (scr_readw(s--) & charmask) * cellsize;
if (attr) {
ud_update_attr(buf, src, attr, vc);
@@ -127,7 +127,7 @@ static inline void ud_putcs_unaligned(struct vc_data *vc,
u8 *src;
while (cnt--) {
src = par->fontbuffer + (scr_readw(s--) & charmask) * cellsize;
src = par->rotated.buf + (scr_readw(s--) & charmask) * cellsize;
if (attr) {
ud_update_attr(buf, src, attr, vc);
@@ -153,7 +153,7 @@ static void ud_putcs(struct vc_data *vc, struct fb_info *info,
{
struct fb_image image;
struct fbcon_par *par = info->fbcon_par;
u32 width = (vc->vc_font.width + 7)/8;
u32 width = font_glyph_pitch(vc->vc_font.width);
u32 cellsize = width * vc->vc_font.height;
u32 maxcnt = info->pixmap.size/cellsize;
u32 scan_align = info->pixmap.scan_align - 1;
@@ -164,7 +164,7 @@ static void ud_putcs(struct vc_data *vc, struct fb_info *info,
u32 vyres = GETVYRES(par->p, info);
u32 vxres = GETVXRES(par->p, info);
if (!par->fontbuffer)
if (!par->rotated.buf)
return;
image.fg_color = fg;
@@ -253,7 +253,8 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
struct fb_cursor cursor;
struct fbcon_par *par = info->fbcon_par;
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
int w = (vc->vc_font.width + 7) >> 3, c;
int w = font_glyph_pitch(vc->vc_font.width);
int c;
int y = real_y(par->p, vc->state.y);
int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1, dx, dy;
@@ -261,14 +262,14 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
u32 vyres = GETVYRES(par->p, info);
u32 vxres = GETVXRES(par->p, info);
if (!par->fontbuffer)
if (!par->rotated.buf)
return;
cursor.set = 0;
c = scr_readw((u16 *) vc->vc_pos);
attribute = get_attribute(info, c);
src = par->fontbuffer + ((c & charmask) * (w * vc->vc_font.height));
src = par->rotated.buf + ((c & charmask) * (w * vc->vc_font.height));
if (par->cursor_state.image.data != src ||
par->cursor_reset) {
@@ -325,50 +326,26 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, bool enable,
vc->vc_cursor_type != par->p->cursor_shape ||
par->cursor_state.mask == NULL ||
par->cursor_reset) {
char *mask = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC);
int cur_height, size, i = 0;
u8 msk = 0xff;
unsigned char *tmp, *mask;
if (!mask)
tmp = kmalloc_array(vc->vc_font.height, w, GFP_ATOMIC);
if (!tmp)
return;
fbcon_fill_cursor_mask(par, vc, tmp);
mask = kmalloc_array(vc->vc_font.height, w, GFP_ATOMIC);
if (!mask) {
kfree(tmp);
return;
}
font_glyph_rotate_180(tmp, vc->vc_font.width, vc->vc_font.height, mask);
kfree(tmp);
kfree(par->cursor_state.mask);
par->cursor_state.mask = mask;
par->cursor_state.mask = (const char *)mask;
par->p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE;
switch (CUR_SIZE(par->p->cursor_shape)) {
case CUR_NONE:
cur_height = 0;
break;
case CUR_UNDERLINE:
cur_height = (vc->vc_font.height < 10) ? 1 : 2;
break;
case CUR_LOWER_THIRD:
cur_height = vc->vc_font.height/3;
break;
case CUR_LOWER_HALF:
cur_height = vc->vc_font.height >> 1;
break;
case CUR_TWO_THIRDS:
cur_height = (vc->vc_font.height << 1)/3;
break;
case CUR_BLOCK:
default:
cur_height = vc->vc_font.height;
break;
}
size = cur_height * w;
while (size--)
mask[i++] = msk;
size = (vc->vc_font.height - cur_height) * w;
while (size--)
mask[i++] = ~msk;
}
par->cursor_state.enable = enable && !use_sw;
+3 -3
View File
@@ -91,14 +91,14 @@ EXPORT_SYMBOL(fb_get_color_depth);
/*
* Data padding functions.
*/
void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height)
void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, const u8 *src, u32 s_pitch, u32 height)
{
__fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, height);
}
EXPORT_SYMBOL(fb_pad_aligned_buffer);
void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, u32 height,
u32 shift_high, u32 shift_low, u32 mod)
void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, const u8 *src, u32 idx, u32 height,
u32 shift_high, u32 shift_low, u32 mod)
{
u8 mask = (u8) (0xff << shift_high), tmp;
int i, j;
+3 -11
View File
@@ -174,7 +174,6 @@ static const struct fb_ops goldfish_fb_ops = {
static int goldfish_fb_probe(struct platform_device *pdev)
{
int ret;
struct resource *r;
struct goldfish_fb *fb;
size_t framesize;
u32 width, height;
@@ -189,14 +188,9 @@ static int goldfish_fb_probe(struct platform_device *pdev)
init_waitqueue_head(&fb->wait);
platform_set_drvdata(pdev, fb);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (r == NULL) {
ret = -ENODEV;
goto err_no_io_base;
}
fb->reg_base = ioremap(r->start, PAGE_SIZE);
if (fb->reg_base == NULL) {
ret = -ENOMEM;
fb->reg_base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(fb->reg_base)) {
ret = PTR_ERR(fb->reg_base);
goto err_no_io_base;
}
@@ -273,7 +267,6 @@ err_fb_set_var_failed:
fb->fb.fix.smem_start);
err_alloc_screen_base_failed:
err_no_irq:
iounmap(fb->reg_base);
err_no_io_base:
kfree(fb);
err_fb_alloc_failed:
@@ -291,7 +284,6 @@ static void goldfish_fb_remove(struct platform_device *pdev)
dma_free_coherent(&pdev->dev, framesize, (void *)fb->fb.screen_base,
fb->fb.fix.smem_start);
iounmap(fb->reg_base);
kfree(fb);
}
+19 -19
View File
@@ -668,19 +668,19 @@ static int __init macfb_init(void)
switch(ndev->dr_hw) {
case NUBUS_DRHW_APPLE_MDC:
strcpy(macfb_fix.id, "Mac Disp. Card");
strscpy(macfb_fix.id, "Mac Disp. Card");
macfb_setpalette = mdc_setpalette;
break;
case NUBUS_DRHW_APPLE_TFB:
strcpy(macfb_fix.id, "Toby");
strscpy(macfb_fix.id, "Toby");
macfb_setpalette = toby_setpalette;
break;
case NUBUS_DRHW_APPLE_JET:
strcpy(macfb_fix.id, "Jet");
strscpy(macfb_fix.id, "Jet");
macfb_setpalette = jet_setpalette;
break;
default:
strcpy(macfb_fix.id, "Generic NuBus");
strscpy(macfb_fix.id, "Generic NuBus");
break;
}
}
@@ -707,7 +707,7 @@ static int __init macfb_init(void)
case MAC_MODEL_Q700:
case MAC_MODEL_Q900:
case MAC_MODEL_Q950:
strcpy(macfb_fix.id, "DAFB");
strscpy(macfb_fix.id, "DAFB");
macfb_setpalette = dafb_setpalette;
dafb_cmap_regs = ioremap(DAFB_BASE, 0x1000);
break;
@@ -716,7 +716,7 @@ static int __init macfb_init(void)
* LC II uses the V8 framebuffer
*/
case MAC_MODEL_LCII:
strcpy(macfb_fix.id, "V8");
strscpy(macfb_fix.id, "V8");
macfb_setpalette = v8_brazil_setpalette;
v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
break;
@@ -729,7 +729,7 @@ static int __init macfb_init(void)
case MAC_MODEL_IIVI:
case MAC_MODEL_IIVX:
case MAC_MODEL_P600:
strcpy(macfb_fix.id, "Brazil");
strscpy(macfb_fix.id, "Brazil");
macfb_setpalette = v8_brazil_setpalette;
v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
break;
@@ -745,7 +745,7 @@ static int __init macfb_init(void)
case MAC_MODEL_P520:
case MAC_MODEL_P550:
case MAC_MODEL_P460:
strcpy(macfb_fix.id, "Sonora");
strscpy(macfb_fix.id, "Sonora");
macfb_setpalette = v8_brazil_setpalette;
v8_brazil_cmap_regs = ioremap(DAC_BASE, 0x1000);
break;
@@ -757,7 +757,7 @@ static int __init macfb_init(void)
*/
case MAC_MODEL_IICI:
case MAC_MODEL_IISI:
strcpy(macfb_fix.id, "RBV");
strscpy(macfb_fix.id, "RBV");
macfb_setpalette = rbv_setpalette;
rbv_cmap_regs = ioremap(DAC_BASE, 0x1000);
break;
@@ -767,7 +767,7 @@ static int __init macfb_init(void)
*/
case MAC_MODEL_Q840:
case MAC_MODEL_C660:
strcpy(macfb_fix.id, "Civic");
strscpy(macfb_fix.id, "Civic");
macfb_setpalette = civic_setpalette;
civic_cmap_regs = ioremap(CIVIC_BASE, 0x1000);
break;
@@ -778,7 +778,7 @@ static int __init macfb_init(void)
* We think this may be like the LC II
*/
case MAC_MODEL_LC:
strcpy(macfb_fix.id, "LC");
strscpy(macfb_fix.id, "LC");
if (vidtest) {
macfb_setpalette = v8_brazil_setpalette;
v8_brazil_cmap_regs =
@@ -790,7 +790,7 @@ static int __init macfb_init(void)
* We think this may be like the LC II
*/
case MAC_MODEL_CCL:
strcpy(macfb_fix.id, "Color Classic");
strscpy(macfb_fix.id, "Color Classic");
if (vidtest) {
macfb_setpalette = v8_brazil_setpalette;
v8_brazil_cmap_regs =
@@ -802,7 +802,7 @@ static int __init macfb_init(void)
* And we *do* mean "weirdos"
*/
case MAC_MODEL_TV:
strcpy(macfb_fix.id, "Mac TV");
strscpy(macfb_fix.id, "Mac TV");
break;
/*
@@ -810,7 +810,7 @@ static int __init macfb_init(void)
*/
case MAC_MODEL_SE30:
case MAC_MODEL_CLII:
strcpy(macfb_fix.id, "Monochrome");
strscpy(macfb_fix.id, "Monochrome");
break;
/*
@@ -828,7 +828,7 @@ static int __init macfb_init(void)
case MAC_MODEL_PB140:
case MAC_MODEL_PB145:
case MAC_MODEL_PB170:
strcpy(macfb_fix.id, "DDC");
strscpy(macfb_fix.id, "DDC");
break;
/*
@@ -840,7 +840,7 @@ static int __init macfb_init(void)
case MAC_MODEL_PB180:
case MAC_MODEL_PB210:
case MAC_MODEL_PB230:
strcpy(macfb_fix.id, "GSC");
strscpy(macfb_fix.id, "GSC");
break;
/*
@@ -848,7 +848,7 @@ static int __init macfb_init(void)
*/
case MAC_MODEL_PB165C:
case MAC_MODEL_PB180C:
strcpy(macfb_fix.id, "TIM");
strscpy(macfb_fix.id, "TIM");
break;
/*
@@ -860,13 +860,13 @@ static int __init macfb_init(void)
case MAC_MODEL_PB270C:
case MAC_MODEL_PB280:
case MAC_MODEL_PB280C:
strcpy(macfb_fix.id, "CSC");
strscpy(macfb_fix.id, "CSC");
macfb_setpalette = csc_setpalette;
csc_cmap_regs = ioremap(CSC_BASE, 0x1000);
break;
default:
strcpy(macfb_fix.id, "Unknown");
strscpy(macfb_fix.id, "Unknown");
break;
}
+1 -1
View File
@@ -409,7 +409,7 @@ static int __g450_setclk(struct matrox_fb_info *minfo, unsigned int fout,
case M_VIDEO_PLL:
{
u_int8_t tmp;
unsigned int mnp;
unsigned int mnp __maybe_unused;
unsigned long flags;
matroxfb_DAC_lock_irqsave(flags);
+4
View File
@@ -950,6 +950,8 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode,
omapfb_conf = dev_get_platdata(fbdev->dev);
hwa742.sys_ck = clk_get(NULL, "hwa_sys_ck");
if (IS_ERR(hwa742.sys_ck))
return PTR_ERR(hwa742.sys_ck);
spin_lock_init(&hwa742.req_lock);
@@ -1028,6 +1030,7 @@ err3:
err2:
hwa742.int_ctrl->cleanup();
err1:
clk_put(hwa742.sys_ck);
return r;
}
@@ -1037,6 +1040,7 @@ static void hwa742_cleanup(void)
hwa742.extif->cleanup();
hwa742.int_ctrl->cleanup();
clk_disable_unprepare(hwa742.sys_ck);
clk_put(hwa742.sys_ck);
}
struct lcd_ctrl hwa742_ctrl = {
@@ -1121,7 +1121,7 @@ static int omapfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
return 0;
error:
omapfb_put_mem_region(ofbi->region);
omapfb_put_mem_region(rg);
return r;
}
Loaded 20 of 45 files, more files were not shown because too many files have changed in this diff. Show more