diff options
Diffstat (limited to 'drivers/video/fbdev/core')
-rw-r--r-- | drivers/video/fbdev/core/Makefile | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/core/fb_io_fops.c | 133 | ||||
-rw-r--r-- | drivers/video/fbdev/core/fb_sys_fops.c | 36 | ||||
-rw-r--r-- | drivers/video/fbdev/core/fbcon.c | 19 | ||||
-rw-r--r-- | drivers/video/fbdev/core/fbmem.c | 117 | ||||
-rw-r--r-- | drivers/video/fbdev/core/modedb.c | 5 |
6 files changed, 175 insertions, 137 deletions
diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile index 08fabce76b74..8f0060160ffb 100644 --- a/drivers/video/fbdev/core/Makefile +++ b/drivers/video/fbdev/core/Makefile @@ -2,7 +2,7 @@ obj-$(CONFIG_FB_NOTIFY) += fb_notify.o obj-$(CONFIG_FB) += fb.o fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \ - modedb.o fbcvt.o fb_cmdline.o + modedb.o fbcvt.o fb_cmdline.o fb_io_fops.o fb-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o ifeq ($(CONFIG_FRAMEBUFFER_CONSOLE),y) diff --git a/drivers/video/fbdev/core/fb_io_fops.c b/drivers/video/fbdev/core/fb_io_fops.c new file mode 100644 index 000000000000..5985e5e1b040 --- /dev/null +++ b/drivers/video/fbdev/core/fb_io_fops.c @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/fb.h> +#include <linux/module.h> +#include <linux/uaccess.h> + +ssize_t fb_io_read(struct fb_info *info, char __user *buf, size_t count, loff_t *ppos) +{ + unsigned long p = *ppos; + u8 *buffer, *dst; + u8 __iomem *src; + int c, cnt = 0, err = 0; + unsigned long total_size, trailing; + + if (!info->screen_base) + return -ENODEV; + + total_size = info->screen_size; + + if (total_size == 0) + total_size = info->fix.smem_len; + + if (p >= total_size) + return 0; + + if (count >= total_size) + count = total_size; + + if (count + p > total_size) + count = total_size - p; + + buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, + GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + src = (u8 __iomem *) (info->screen_base + p); + + if (info->fbops->fb_sync) + info->fbops->fb_sync(info); + + while (count) { + c = (count > PAGE_SIZE) ? PAGE_SIZE : count; + dst = buffer; + fb_memcpy_fromio(dst, src, c); + dst += c; + src += c; + + trailing = copy_to_user(buf, buffer, c); + if (trailing == c) { + err = -EFAULT; + break; + } + c -= trailing; + + *ppos += c; + buf += c; + cnt += c; + count -= c; + } + + kfree(buffer); + + return cnt ? cnt : err; +} +EXPORT_SYMBOL(fb_io_read); + +ssize_t fb_io_write(struct fb_info *info, const char __user *buf, size_t count, loff_t *ppos) +{ + unsigned long p = *ppos; + u8 *buffer, *src; + u8 __iomem *dst; + int c, cnt = 0, err = 0; + unsigned long total_size, trailing; + + if (!info->screen_base) + return -ENODEV; + + total_size = info->screen_size; + + if (total_size == 0) + total_size = info->fix.smem_len; + + if (p > total_size) + return -EFBIG; + + if (count > total_size) { + err = -EFBIG; + count = total_size; + } + + if (count + p > total_size) { + if (!err) + err = -ENOSPC; + + count = total_size - p; + } + + buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, + GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + dst = (u8 __iomem *) (info->screen_base + p); + + if (info->fbops->fb_sync) + info->fbops->fb_sync(info); + + while (count) { + c = (count > PAGE_SIZE) ? PAGE_SIZE : count; + src = buffer; + + trailing = copy_from_user(src, buf, c); + if (trailing == c) { + err = -EFAULT; + break; + } + c -= trailing; + + fb_memcpy_toio(dst, src, c); + dst += c; + src += c; + *ppos += c; + buf += c; + cnt += c; + count -= c; + } + + kfree(buffer); + + return (cnt) ? cnt : err; +} +EXPORT_SYMBOL(fb_io_write); diff --git a/drivers/video/fbdev/core/fb_sys_fops.c b/drivers/video/fbdev/core/fb_sys_fops.c index ff275d7f3eaf..0cb0989abda6 100644 --- a/drivers/video/fbdev/core/fb_sys_fops.c +++ b/drivers/video/fbdev/core/fb_sys_fops.c @@ -19,10 +19,11 @@ ssize_t fb_sys_read(struct fb_info *info, char __user *buf, size_t count, unsigned long p = *ppos; void *src; int err = 0; - unsigned long total_size; + unsigned long total_size, c; + ssize_t ret; - if (info->state != FBINFO_STATE_RUNNING) - return -EPERM; + if (!info->screen_buffer) + return -ENODEV; total_size = info->screen_size; @@ -38,18 +39,19 @@ ssize_t fb_sys_read(struct fb_info *info, char __user *buf, size_t count, if (count + p > total_size) count = total_size - p; - src = (void __force *)(info->screen_base + p); + src = info->screen_buffer + p; if (info->fbops->fb_sync) info->fbops->fb_sync(info); - if (copy_to_user(buf, src, count)) + c = copy_to_user(buf, src, count); + if (c) err = -EFAULT; + ret = count - c; - if (!err) - *ppos += count; + *ppos += ret; - return (err) ? err : count; + return ret ? ret : err; } EXPORT_SYMBOL_GPL(fb_sys_read); @@ -59,10 +61,11 @@ ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, unsigned long p = *ppos; void *dst; int err = 0; - unsigned long total_size; + unsigned long total_size, c; + size_t ret; - if (info->state != FBINFO_STATE_RUNNING) - return -EPERM; + if (!info->screen_buffer) + return -ENODEV; total_size = info->screen_size; @@ -84,18 +87,19 @@ ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, count = total_size - p; } - dst = (void __force *) (info->screen_base + p); + dst = info->screen_buffer + p; if (info->fbops->fb_sync) info->fbops->fb_sync(info); - if (copy_from_user(dst, buf, count)) + c = copy_from_user(dst, buf, count); + if (c) err = -EFAULT; + ret = count - c; - if (!err) - *ppos += count; + *ppos += ret; - return (err) ? err : count; + return ret ? ret : err; } EXPORT_SYMBOL_GPL(fb_sys_write); diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 0a2c47df01f4..c6c9d040bdec 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -75,7 +75,6 @@ #include <linux/interrupt.h> #include <linux/crc32.h> /* For counting font checksums */ #include <linux/uaccess.h> -#include <asm/fb.h> #include <asm/irq.h> #include "fbcon.h" @@ -823,7 +822,7 @@ static int set_con2fb_map(int unit, int newidx, int user) int oldidx = con2fb_map[unit]; struct fb_info *info = fbcon_registered_fb[newidx]; struct fb_info *oldinfo = NULL; - int found, err = 0, show_logo; + int err = 0, show_logo; WARN_CONSOLE_UNLOCKED(); @@ -841,26 +840,26 @@ static int set_con2fb_map(int unit, int newidx, int user) if (oldidx != -1) oldinfo = fbcon_registered_fb[oldidx]; - found = search_fb_in_map(newidx); - - if (!err && !found) { + if (!search_fb_in_map(newidx)) { err = con2fb_acquire_newinfo(vc, info, unit); - if (!err) - con2fb_map[unit] = newidx; + if (err) + return err; + + fbcon_add_cursor_work(info); } + con2fb_map[unit] = newidx; + /* * If old fb is not mapped to any of the consoles, * fbcon should release it. */ - if (!err && oldinfo && !search_fb_in_map(oldidx)) + if (oldinfo && !search_fb_in_map(oldidx)) con2fb_release_oldinfo(vc, oldinfo, info); show_logo = (fg_console == 0 && !user && logo_shown != FBCON_LOGO_DONTSHOW); - if (!found) - fbcon_add_cursor_work(info); con2fb_map_boot[unit] = newidx; con2fb_init_display(vc, info, unit, show_logo); diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 875541ff185b..d5f897b5ba54 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -37,8 +37,6 @@ #include <linux/mem_encrypt.h> #include <linux/pci.h> -#include <asm/fb.h> - #include <video/nomodeset.h> #include <video/vga.h> @@ -761,14 +759,9 @@ static struct fb_info *file_fb_info(struct file *file) static ssize_t fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) { - unsigned long p = *ppos; struct fb_info *info = file_fb_info(file); - u8 *buffer, *dst; - u8 __iomem *src; - int c, cnt = 0, err = 0; - unsigned long total_size; - if (!info || ! info->screen_base) + if (!info) return -ENODEV; if (info->state != FBINFO_STATE_RUNNING) @@ -777,63 +770,15 @@ fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) if (info->fbops->fb_read) return info->fbops->fb_read(info, buf, count, ppos); - total_size = info->screen_size; - - if (total_size == 0) - total_size = info->fix.smem_len; - - if (p >= total_size) - return 0; - - if (count >= total_size) - count = total_size; - - if (count + p > total_size) - count = total_size - p; - - buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, - GFP_KERNEL); - if (!buffer) - return -ENOMEM; - - src = (u8 __iomem *) (info->screen_base + p); - - if (info->fbops->fb_sync) - info->fbops->fb_sync(info); - - while (count) { - c = (count > PAGE_SIZE) ? PAGE_SIZE : count; - dst = buffer; - fb_memcpy_fromfb(dst, src, c); - dst += c; - src += c; - - if (copy_to_user(buf, buffer, c)) { - err = -EFAULT; - break; - } - *ppos += c; - buf += c; - cnt += c; - count -= c; - } - - kfree(buffer); - - return (err) ? err : cnt; + return fb_io_read(info, buf, count, ppos); } static ssize_t fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - unsigned long p = *ppos; struct fb_info *info = file_fb_info(file); - u8 *buffer, *src; - u8 __iomem *dst; - int c, cnt = 0, err = 0; - unsigned long total_size; - if (!info || !info->screen_base) + if (!info) return -ENODEV; if (info->state != FBINFO_STATE_RUNNING) @@ -842,57 +787,7 @@ fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) if (info->fbops->fb_write) return info->fbops->fb_write(info, buf, count, ppos); - total_size = info->screen_size; - - if (total_size == 0) - total_size = info->fix.smem_len; - - if (p > total_size) - return -EFBIG; - - if (count > total_size) { - err = -EFBIG; - count = total_size; - } - - if (count + p > total_size) { - if (!err) - err = -ENOSPC; - - count = total_size - p; - } - - buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, - GFP_KERNEL); - if (!buffer) - return -ENOMEM; - - dst = (u8 __iomem *) (info->screen_base + p); - - if (info->fbops->fb_sync) - info->fbops->fb_sync(info); - - while (count) { - c = (count > PAGE_SIZE) ? PAGE_SIZE : count; - src = buffer; - - if (copy_from_user(src, buf, c)) { - err = -EFAULT; - break; - } - - fb_memcpy_tofb(dst, src, c); - dst += c; - src += c; - *ppos += c; - buf += c; - cnt += c; - count -= c; - } - - kfree(buffer); - - return (cnt) ? cnt : err; + return fb_io_write(info, buf, count, ppos); } int @@ -1116,6 +1011,8 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, case FBIOPUT_VSCREENINFO: if (copy_from_user(&var, argp, sizeof(var))) return -EFAULT; + /* only for kernel-internal use */ + var.activate &= ~FB_ACTIVATE_KD_TEXT; console_lock(); lock_fb_info(info); ret = fbcon_modechange_possible(info, &var); @@ -1749,7 +1646,7 @@ fbmem_init(void) goto err_chrdev; } - fb_class = class_create(THIS_MODULE, "graphics"); + fb_class = class_create("graphics"); if (IS_ERR(fb_class)) { ret = PTR_ERR(fb_class); pr_warn("Unable to create fb class; errno = %d\n", ret); diff --git a/drivers/video/fbdev/core/modedb.c b/drivers/video/fbdev/core/modedb.c index 23cf8eba785d..f7e019dded0f 100644 --- a/drivers/video/fbdev/core/modedb.c +++ b/drivers/video/fbdev/core/modedb.c @@ -257,6 +257,11 @@ static const struct fb_videomode modedb[] = { { NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3, 0, FB_VMODE_DOUBLE }, + /* 1920x1080 @ 60 Hz, 67.3 kHz hsync */ + { NULL, 60, 1920, 1080, 6734, 148, 88, 36, 4, 44, 5, 0, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED }, + /* 1920x1200 @ 60 Hz, 74.5 Khz hsync */ { NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3, FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |