summaryrefslogtreecommitdiff
path: root/drivers/video/fbdev
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/fbdev')
-rw-r--r--drivers/video/fbdev/Kconfig10
-rw-r--r--drivers/video/fbdev/aty/atyfb_base.c4
-rw-r--r--drivers/video/fbdev/core/bitblit.c46
-rw-r--r--drivers/video/fbdev/core/fb_defio.c266
-rw-r--r--drivers/video/fbdev/core/fbcon.c242
-rw-r--r--drivers/video/fbdev/core/fbcon.h18
-rw-r--r--drivers/video/fbdev/core/fbcon_ccw.c70
-rw-r--r--drivers/video/fbdev/core/fbcon_cw.c70
-rw-r--r--drivers/video/fbdev/core/fbcon_rotate.c88
-rw-r--r--drivers/video/fbdev/core/fbcon_rotate.h71
-rw-r--r--drivers/video/fbdev/core/fbcon_ud.c67
-rw-r--r--drivers/video/fbdev/core/fbmem.c6
-rw-r--r--drivers/video/fbdev/goldfishfb.c14
-rw-r--r--drivers/video/fbdev/macfb.c38
-rw-r--r--drivers/video/fbdev/matrox/g450_pll.c2
-rw-r--r--drivers/video/fbdev/omap/hwa742.c4
-rw-r--r--drivers/video/fbdev/omap2/omapfb/omapfb-main.c2
-rw-r--r--drivers/video/fbdev/tdfxfb.c112
-rw-r--r--drivers/video/fbdev/udlfb.c3
-rw-r--r--drivers/video/fbdev/via/lcd.c3
-rw-r--r--drivers/video/fbdev/wmt_ge_rops.c18
21 files changed, 501 insertions, 653 deletions
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index ac9ac4287c6a..1c73d560f196 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -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.
diff --git a/drivers/video/fbdev/aty/atyfb_base.c b/drivers/video/fbdev/aty/atyfb_base.c
index d5e107730a4d..9fc5af09f86c 100644
--- a/drivers/video/fbdev/aty/atyfb_base.c
+++ b/drivers/video/fbdev/aty/atyfb_base.c
@@ -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;
diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c
index 085ffb44c51a..65681dcc5930 100644
--- a/drivers/video/fbdev/core/bitblit.c
+++ b/drivers/video/fbdev/core/bitblit.c
@@ -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;
diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c
index ca48b89a323d..a12dd25ab697 100644
--- a/drivers/video/fbdev/core/fb_defio.c
+++ b/drivers/video/fbdev/core/fb_defio.c
@@ -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);
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 666261ae59d8..b0e3e765360d 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -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;
- 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)++;
+ font_data_get(data);
+ resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
+ 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;
-
- /* 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);
+ new_data = font_data_import(font, vpitch, crc32);
+ if (IS_ERR(new_data))
+ return PTR_ERR(new_data);
- 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];
diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h
index fca14e9b729b..321cc7f44baa 100644
--- a/drivers/video/fbdev/core/fbcon.h
+++ b/drivers/video/fbdev/core/fbcon.h
@@ -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
diff --git a/drivers/video/fbdev/core/fbcon_ccw.c b/drivers/video/fbdev/core/fbcon_ccw.c
index 2f394b5a17f7..33f02d579e02 100644
--- a/drivers/video/fbdev/core/fbcon_ccw.c
+++ b/drivers/video/fbdev/core/fbcon_ccw.c
@@ -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;
diff --git a/drivers/video/fbdev/core/fbcon_cw.c b/drivers/video/fbdev/core/fbcon_cw.c
index 3c3ad3471ec4..bde820967eb9 100644
--- a/drivers/video/fbdev/core/fbcon_cw.c
+++ b/drivers/video/fbdev/core/fbcon_cw.c
@@ -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;
diff --git a/drivers/video/fbdev/core/fbcon_rotate.c b/drivers/video/fbdev/core/fbcon_rotate.c
index 1562a8f20b4f..6cdbc96eeca6 100644
--- a/drivers/video/fbdev/core/fbcon_rotate.c
+++ b/drivers/video/fbdev/core/fbcon_rotate.c
@@ -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;
-
- if (vc->vc_font.data == par->fontdata &&
- par->p->con_rotate == par->cur_rotate)
- goto finished;
+ unsigned char *buf;
+ int ret;
- 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->p->fontdata == par->rotated.fontdata && par->rotate == par->rotated.buf_rotate)
+ return 0;
- 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;
}
diff --git a/drivers/video/fbdev/core/fbcon_rotate.h b/drivers/video/fbdev/core/fbcon_rotate.h
index 8cb019e8a9c0..725bcae2df61 100644
--- a/drivers/video/fbdev/core/fbcon_rotate.h
+++ b/drivers/video/fbdev/core/fbcon_rotate.h
@@ -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)
diff --git a/drivers/video/fbdev/core/fbcon_ud.c b/drivers/video/fbdev/core/fbcon_ud.c
index 6fc30cad5b19..eaf08999e249 100644
--- a/drivers/video/fbdev/core/fbcon_ud.c
+++ b/drivers/video/fbdev/core/fbcon_ud.c
@@ -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;
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index cf199038f069..30f2b59c47bf 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -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;
diff --git a/drivers/video/fbdev/goldfishfb.c b/drivers/video/fbdev/goldfishfb.c
index ffe33a36b944..c9871281bc1d 100644
--- a/drivers/video/fbdev/goldfishfb.c
+++ b/drivers/video/fbdev/goldfishfb.c
@@ -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);
}
diff --git a/drivers/video/fbdev/macfb.c b/drivers/video/fbdev/macfb.c
index 887fffdccd24..ef3d2304e2f4 100644
--- a/drivers/video/fbdev/macfb.c
+++ b/drivers/video/fbdev/macfb.c
@@ -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;
}
diff --git a/drivers/video/fbdev/matrox/g450_pll.c b/drivers/video/fbdev/matrox/g450_pll.c
index e2c1478aa47f..6a08f78cd1ac 100644
--- a/drivers/video/fbdev/matrox/g450_pll.c
+++ b/drivers/video/fbdev/matrox/g450_pll.c
@@ -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);
diff --git a/drivers/video/fbdev/omap/hwa742.c b/drivers/video/fbdev/omap/hwa742.c
index 64e76e1f5388..68a677f824e9 100644
--- a/drivers/video/fbdev/omap/hwa742.c
+++ b/drivers/video/fbdev/omap/hwa742.c
@@ -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 = {
diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb-main.c b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c
index a8b2930290e1..d70deb6a9150 100644
--- a/drivers/video/fbdev/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c
@@ -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;
}
diff --git a/drivers/video/fbdev/tdfxfb.c b/drivers/video/fbdev/tdfxfb.c
index 51ebe78359ec..4c4e53aaea3a 100644
--- a/drivers/video/fbdev/tdfxfb.c
+++ b/drivers/video/fbdev/tdfxfb.c
@@ -77,6 +77,7 @@
#include <asm/io.h>
#include <video/tdfx.h>
+#include <video/vga.h>
#define DPRINTK(a, b...) pr_debug("fb: %s: " a, __func__ , ## b)
@@ -496,6 +497,9 @@ static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
}
}
+ if (!var->pixclock)
+ return -EINVAL;
+
if (PICOS2KHZ(var->pixclock) > par->max_pixclock) {
DPRINTK("pixclock too high (%ldKHz)\n",
PICOS2KHZ(var->pixclock));
@@ -591,7 +595,7 @@ static int tdfxfb_set_par(struct fb_info *info)
vt = ve + (info->var.upper_margin << 1) - 1;
reg.screensize = info->var.xres | (info->var.yres << 13);
reg.vidcfg |= VIDCFG_HALF_MODE;
- reg.crt[0x09] = 0x80;
+ reg.crt[VGA_CRTC_MAX_SCAN] = 0x80;
} else {
vd = info->var.yres - 1;
vs = vd + info->var.lower_margin;
@@ -609,59 +613,59 @@ static int tdfxfb_set_par(struct fb_info *info)
info->var.xres < 480 ? 0x60 :
info->var.xres < 768 ? 0xe0 : 0x20);
- reg.gra[0x05] = 0x40;
- reg.gra[0x06] = 0x05;
- reg.gra[0x07] = 0x0f;
- reg.gra[0x08] = 0xff;
-
- reg.att[0x00] = 0x00;
- reg.att[0x01] = 0x01;
- reg.att[0x02] = 0x02;
- reg.att[0x03] = 0x03;
- reg.att[0x04] = 0x04;
- reg.att[0x05] = 0x05;
- reg.att[0x06] = 0x06;
- reg.att[0x07] = 0x07;
- reg.att[0x08] = 0x08;
- reg.att[0x09] = 0x09;
- reg.att[0x0a] = 0x0a;
- reg.att[0x0b] = 0x0b;
- reg.att[0x0c] = 0x0c;
- reg.att[0x0d] = 0x0d;
- reg.att[0x0e] = 0x0e;
- reg.att[0x0f] = 0x0f;
- reg.att[0x10] = 0x41;
- reg.att[0x12] = 0x0f;
-
- reg.seq[0x00] = 0x03;
- reg.seq[0x01] = 0x01; /* fixme: clkdiv2? */
- reg.seq[0x02] = 0x0f;
- reg.seq[0x03] = 0x00;
- reg.seq[0x04] = 0x0e;
-
- reg.crt[0x00] = ht - 4;
- reg.crt[0x01] = hd;
- reg.crt[0x02] = hbs;
- reg.crt[0x03] = 0x80 | (hbe & 0x1f);
- reg.crt[0x04] = hs;
- reg.crt[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f);
- reg.crt[0x06] = vt;
- reg.crt[0x07] = ((vs & 0x200) >> 2) |
- ((vd & 0x200) >> 3) |
- ((vt & 0x200) >> 4) | 0x10 |
- ((vbs & 0x100) >> 5) |
- ((vs & 0x100) >> 6) |
- ((vd & 0x100) >> 7) |
- ((vt & 0x100) >> 8);
- reg.crt[0x09] |= 0x40 | ((vbs & 0x200) >> 4);
- reg.crt[0x10] = vs;
- reg.crt[0x11] = (ve & 0x0f) | 0x20;
- reg.crt[0x12] = vd;
- reg.crt[0x13] = wd;
- reg.crt[0x15] = vbs;
- reg.crt[0x16] = vbe + 1;
- reg.crt[0x17] = 0xc3;
- reg.crt[0x18] = 0xff;
+ reg.gra[VGA_GFX_MODE] = 0x40;
+ reg.gra[VGA_GFX_MISC] = 0x05;
+ reg.gra[VGA_GFX_COMPARE_MASK] = 0x0f;
+ reg.gra[VGA_GFX_BIT_MASK] = 0xff;
+
+ reg.att[VGA_ATC_PALETTE0] = 0x00;
+ reg.att[VGA_ATC_PALETTE1] = 0x01;
+ reg.att[VGA_ATC_PALETTE2] = 0x02;
+ reg.att[VGA_ATC_PALETTE3] = 0x03;
+ reg.att[VGA_ATC_PALETTE4] = 0x04;
+ reg.att[VGA_ATC_PALETTE5] = 0x05;
+ reg.att[VGA_ATC_PALETTE6] = 0x06;
+ reg.att[VGA_ATC_PALETTE7] = 0x07;
+ reg.att[VGA_ATC_PALETTE8] = 0x08;
+ reg.att[VGA_ATC_PALETTE9] = 0x09;
+ reg.att[VGA_ATC_PALETTEA] = 0x0a;
+ reg.att[VGA_ATC_PALETTEB] = 0x0b;
+ reg.att[VGA_ATC_PALETTEC] = 0x0c;
+ reg.att[VGA_ATC_PALETTED] = 0x0d;
+ reg.att[VGA_ATC_PALETTEE] = 0x0e;
+ reg.att[VGA_ATC_PALETTEF] = 0x0f;
+ reg.att[VGA_ATC_MODE] = 0x41;
+ reg.att[VGA_ATC_PLANE_ENABLE] = 0x0f;
+
+ reg.seq[VGA_SEQ_RESET] = 0x03;
+ reg.seq[VGA_SEQ_CLOCK_MODE] = 0x01; /* fixme: clkdiv2? */
+ reg.seq[VGA_SEQ_PLANE_WRITE] = 0x0f;
+ reg.seq[VGA_SEQ_CHARACTER_MAP] = 0x00;
+ reg.seq[VGA_SEQ_MEMORY_MODE] = 0x0e;
+
+ reg.crt[VGA_CRTC_H_TOTAL] = ht - 4;
+ reg.crt[VGA_CRTC_H_DISP] = hd;
+ reg.crt[VGA_CRTC_H_BLANK_START] = hbs;
+ reg.crt[VGA_CRTC_H_BLANK_END] = 0x80 | (hbe & 0x1f);
+ reg.crt[VGA_CRTC_H_SYNC_START] = hs;
+ reg.crt[VGA_CRTC_H_SYNC_END] = ((hbe & 0x20) << 2) | (he & 0x1f);
+ reg.crt[VGA_CRTC_V_TOTAL] = vt;
+ reg.crt[VGA_CRTC_OVERFLOW] = ((vs & 0x200) >> 2) |
+ ((vd & 0x200) >> 3) |
+ ((vt & 0x200) >> 4) | 0x10 |
+ ((vbs & 0x100) >> 5) |
+ ((vs & 0x100) >> 6) |
+ ((vd & 0x100) >> 7) |
+ ((vt & 0x100) >> 8);
+ reg.crt[VGA_CRTC_MAX_SCAN] |= 0x40 | ((vbs & 0x200) >> 4);
+ reg.crt[VGA_CRTC_V_SYNC_START] = vs;
+ reg.crt[VGA_CRTC_V_SYNC_END] = (ve & 0x0f) | 0x20;
+ reg.crt[VGA_CRTC_V_DISP_END] = vd;
+ reg.crt[VGA_CRTC_OFFSET] = wd;
+ reg.crt[VGA_CRTC_V_BLANK_START] = vbs;
+ reg.crt[VGA_CRTC_V_BLANK_END] = vbe + 1;
+ reg.crt[VGA_CRTC_MODE] = 0xc3;
+ reg.crt[VGA_CRTC_LINE_COMPARE] = 0xff;
/* Banshee's nonvga stuff */
reg.ext[0x00] = (((ht & 0x100) >> 8) |
diff --git a/drivers/video/fbdev/udlfb.c b/drivers/video/fbdev/udlfb.c
index 3c6a9b5758d9..c341d76bc564 100644
--- a/drivers/video/fbdev/udlfb.c
+++ b/drivers/video/fbdev/udlfb.c
@@ -1018,6 +1018,9 @@ static int dlfb_ops_check_var(struct fb_var_screeninfo *var,
struct fb_videomode mode;
struct dlfb_data *dlfb = info->par;
+ if (!var->pixclock)
+ return -EINVAL;
+
/* set device-specific elements of var unrelated to mode */
dlfb_var_color_format(var);
diff --git a/drivers/video/fbdev/via/lcd.c b/drivers/video/fbdev/via/lcd.c
index 8673fced8749..3fa2304fbda7 100644
--- a/drivers/video/fbdev/via/lcd.c
+++ b/drivers/video/fbdev/via/lcd.c
@@ -954,6 +954,9 @@ bool viafb_lcd_get_mobile_state(bool *mobile)
u16 start_pattern;
biosptr = ioremap(romaddr, 0x10000);
+ if (!biosptr)
+ return false;
+
start_pattern = readw(biosptr);
/* Compare pattern */
diff --git a/drivers/video/fbdev/wmt_ge_rops.c b/drivers/video/fbdev/wmt_ge_rops.c
index 2bd26bfb2b46..0cf78bcadfa6 100644
--- a/drivers/video/fbdev/wmt_ge_rops.c
+++ b/drivers/video/fbdev/wmt_ge_rops.c
@@ -148,25 +148,15 @@ EXPORT_SYMBOL_GPL(wmt_ge_sync);
static int wmt_ge_rops_probe(struct platform_device *pdev)
{
- struct resource *res;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- dev_err(&pdev->dev, "no I/O memory resource defined\n");
- return -ENODEV;
- }
-
/* Only one ROP engine is presently supported. */
if (unlikely(regbase)) {
WARN_ON(1);
return -EBUSY;
}
- regbase = ioremap(res->start, resource_size(res));
- if (regbase == NULL) {
- dev_err(&pdev->dev, "failed to map I/O memory\n");
- return -EBUSY;
- }
+ regbase = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(regbase))
+ return PTR_ERR(regbase);
writel(1, regbase + GE_ENABLE_OFF);
printk(KERN_INFO "Enabled support for WMT GE raster acceleration\n");
@@ -176,7 +166,7 @@ static int wmt_ge_rops_probe(struct platform_device *pdev)
static void wmt_ge_rops_remove(struct platform_device *pdev)
{
- iounmap(regbase);
+ regbase = NULL;
}
static const struct of_device_id wmt_dt_ids[] = {