diff options
Diffstat (limited to 'drivers/video/fbdev')
| -rw-r--r-- | drivers/video/fbdev/Kconfig | 10 | ||||
| -rw-r--r-- | drivers/video/fbdev/aty/atyfb_base.c | 4 | ||||
| -rw-r--r-- | drivers/video/fbdev/core/bitblit.c | 46 | ||||
| -rw-r--r-- | drivers/video/fbdev/core/fb_defio.c | 266 | ||||
| -rw-r--r-- | drivers/video/fbdev/core/fbcon.c | 242 | ||||
| -rw-r--r-- | drivers/video/fbdev/core/fbcon.h | 18 | ||||
| -rw-r--r-- | drivers/video/fbdev/core/fbcon_ccw.c | 70 | ||||
| -rw-r--r-- | drivers/video/fbdev/core/fbcon_cw.c | 70 | ||||
| -rw-r--r-- | drivers/video/fbdev/core/fbcon_rotate.c | 88 | ||||
| -rw-r--r-- | drivers/video/fbdev/core/fbcon_rotate.h | 71 | ||||
| -rw-r--r-- | drivers/video/fbdev/core/fbcon_ud.c | 67 | ||||
| -rw-r--r-- | drivers/video/fbdev/core/fbmem.c | 6 | ||||
| -rw-r--r-- | drivers/video/fbdev/goldfishfb.c | 14 | ||||
| -rw-r--r-- | drivers/video/fbdev/macfb.c | 38 | ||||
| -rw-r--r-- | drivers/video/fbdev/matrox/g450_pll.c | 2 | ||||
| -rw-r--r-- | drivers/video/fbdev/omap/hwa742.c | 4 | ||||
| -rw-r--r-- | drivers/video/fbdev/omap2/omapfb/omapfb-main.c | 2 | ||||
| -rw-r--r-- | drivers/video/fbdev/tdfxfb.c | 112 | ||||
| -rw-r--r-- | drivers/video/fbdev/udlfb.c | 3 | ||||
| -rw-r--r-- | drivers/video/fbdev/via/lcd.c | 3 | ||||
| -rw-r--r-- | drivers/video/fbdev/wmt_ge_rops.c | 18 |
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[] = { |
