diff options
author | Jani Nikula <jani.nikula@intel.com> | 2021-08-16 09:11:17 +0300 |
---|---|---|
committer | Jani Nikula <jani.nikula@intel.com> | 2021-08-16 09:11:17 +0300 |
commit | b2eb7d716426fe056596761cd371005d64e9caec (patch) | |
tree | 436d0566cf4bc900522c9dbf1e203234ef65b2f7 /drivers/video/fbdev | |
parent | 2817efaeb608421d8f6fe7939826c35a852644e9 (diff) | |
parent | 2819cf0e7dbe45a2bccf2f6c60fe6a27b299cc3e (diff) | |
download | linux-b2eb7d716426fe056596761cd371005d64e9caec.tar.bz2 |
Merge drm/drm-next into drm-intel-next
Catch up with drm core changes.
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Diffstat (limited to 'drivers/video/fbdev')
-rw-r--r-- | drivers/video/fbdev/arcfb.c | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/asiliantfb.c | 3 | ||||
-rw-r--r-- | drivers/video/fbdev/core/fbmem.c | 18 | ||||
-rw-r--r-- | drivers/video/fbdev/ep93xx-fb.c | 4 | ||||
-rw-r--r-- | drivers/video/fbdev/kyro/fbdev.c | 8 | ||||
-rw-r--r-- | drivers/video/fbdev/neofb.c | 2 | ||||
-rw-r--r-- | drivers/video/fbdev/omap2/omapfb/dss/apply.c | 4 | ||||
-rw-r--r-- | drivers/video/fbdev/riva/fbdev.c | 3 | ||||
-rw-r--r-- | drivers/video/fbdev/ssd1307fb.c | 151 | ||||
-rw-r--r-- | drivers/video/fbdev/xilinxfb.c | 2 |
10 files changed, 133 insertions, 64 deletions
diff --git a/drivers/video/fbdev/arcfb.c b/drivers/video/fbdev/arcfb.c index 1447324ed0b6..45e64016db32 100644 --- a/drivers/video/fbdev/arcfb.c +++ b/drivers/video/fbdev/arcfb.c @@ -446,7 +446,7 @@ static ssize_t arcfb_write(struct fb_info *info, const char __user *buf, /* modded from epson 1355 */ unsigned long p; - int err=-EINVAL; + int err; unsigned int fbmemlength,x,y,w,h, bitppos, startpos, endpos, bitcount; struct arcfb_par *par; unsigned int xres; diff --git a/drivers/video/fbdev/asiliantfb.c b/drivers/video/fbdev/asiliantfb.c index 3e006da47752..84c56f525889 100644 --- a/drivers/video/fbdev/asiliantfb.c +++ b/drivers/video/fbdev/asiliantfb.c @@ -227,6 +227,9 @@ static int asiliantfb_check_var(struct fb_var_screeninfo *var, { unsigned long Ftarget, ratio, remainder; + if (!var->pixclock) + return -EINVAL; + ratio = 1000000 / var->pixclock; remainder = 1000000 % var->pixclock; Ftarget = 1000000 * ratio + (1000000 * remainder) / var->pixclock; diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 98f193078c05..71fb710f1ce3 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -67,7 +67,7 @@ static struct fb_info *get_fb_info(unsigned int idx) mutex_lock(®istration_lock); fb_info = registered_fb[idx]; if (fb_info) - atomic_inc(&fb_info->count); + refcount_inc(&fb_info->count); mutex_unlock(®istration_lock); return fb_info; @@ -75,7 +75,7 @@ static struct fb_info *get_fb_info(unsigned int idx) static void put_fb_info(struct fb_info *fb_info) { - if (!atomic_dec_and_test(&fb_info->count)) + if (!refcount_dec_and_test(&fb_info->count)) return; if (fb_info->fbops->fb_destroy) fb_info->fbops->fb_destroy(fb_info); @@ -970,13 +970,11 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) fb_var_to_videomode(&mode2, &info->var); /* make sure we don't delete the videomode of current var */ ret = fb_mode_is_equal(&mode1, &mode2); - - if (!ret) - fbcon_mode_deleted(info, &mode1); - - if (!ret) - fb_delete_videomode(&mode1, &info->modelist); - + if (!ret) { + ret = fbcon_mode_deleted(info, &mode1); + if (!ret) + fb_delete_videomode(&mode1, &info->modelist); + } return ret ? -EINVAL : 0; } @@ -1594,7 +1592,7 @@ static int do_register_framebuffer(struct fb_info *fb_info) if (!registered_fb[i]) break; fb_info->node = i; - atomic_set(&fb_info->count, 1); + refcount_set(&fb_info->count, 1); mutex_init(&fb_info->lock); mutex_init(&fb_info->mm_lock); diff --git a/drivers/video/fbdev/ep93xx-fb.c b/drivers/video/fbdev/ep93xx-fb.c index ba33b4dce0df..2398b3d48fed 100644 --- a/drivers/video/fbdev/ep93xx-fb.c +++ b/drivers/video/fbdev/ep93xx-fb.c @@ -548,7 +548,7 @@ static int ep93xxfb_probe(struct platform_device *pdev) } ep93xxfb_set_par(info); - clk_enable(fbi->clk); + clk_prepare_enable(fbi->clk); err = register_framebuffer(info); if (err) @@ -577,7 +577,7 @@ static int ep93xxfb_remove(struct platform_device *pdev) struct ep93xx_fbi *fbi = info->par; unregister_framebuffer(info); - clk_disable(fbi->clk); + clk_disable_unprepare(fbi->clk); ep93xxfb_dealloc_videomem(info); fb_dealloc_cmap(&info->cmap); diff --git a/drivers/video/fbdev/kyro/fbdev.c b/drivers/video/fbdev/kyro/fbdev.c index 8fbde92ae8b9..25801e8e3f74 100644 --- a/drivers/video/fbdev/kyro/fbdev.c +++ b/drivers/video/fbdev/kyro/fbdev.c @@ -372,6 +372,11 @@ static int kyro_dev_overlay_viewport_set(u32 x, u32 y, u32 ulWidth, u32 ulHeight /* probably haven't called CreateOverlay yet */ return -EINVAL; + if (ulWidth == 0 || ulWidth == 0xffffffff || + ulHeight == 0 || ulHeight == 0xffffffff || + (x < 2 && ulWidth + 2 == 0)) + return -EINVAL; + /* Stop Ramdac Output */ DisableRamdacOutput(deviceInfo.pSTGReg); @@ -394,6 +399,9 @@ static int kyrofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { struct kyrofb_info *par = info->par; + if (!var->pixclock) + return -EINVAL; + if (var->bits_per_pixel != 16 && var->bits_per_pixel != 32) { printk(KERN_WARNING "kyrofb: depth not supported: %u\n", var->bits_per_pixel); return -EINVAL; diff --git a/drivers/video/fbdev/neofb.c b/drivers/video/fbdev/neofb.c index c0f4f402da3f..966df2a07360 100644 --- a/drivers/video/fbdev/neofb.c +++ b/drivers/video/fbdev/neofb.c @@ -585,7 +585,7 @@ neofb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) DBG("neofb_check_var"); - if (PICOS2KHZ(var->pixclock) > par->maxClock) + if (var->pixclock && PICOS2KHZ(var->pixclock) > par->maxClock) return -EINVAL; /* Is the mode larger than the LCD panel? */ diff --git a/drivers/video/fbdev/omap2/omapfb/dss/apply.c b/drivers/video/fbdev/omap2/omapfb/dss/apply.c index c71021091828..acca991c7540 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/apply.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/apply.c @@ -108,7 +108,7 @@ static struct { } dss_data; /* protects dss_data */ -static spinlock_t data_lock; +static DEFINE_SPINLOCK(data_lock); /* lock for blocking functions */ static DEFINE_MUTEX(apply_lock); static DECLARE_COMPLETION(extra_updated_completion); @@ -131,8 +131,6 @@ static void apply_init_priv(void) struct mgr_priv_data *mp; int i; - spin_lock_init(&data_lock); - for (i = 0; i < num_ovls; ++i) { struct ovl_priv_data *op; diff --git a/drivers/video/fbdev/riva/fbdev.c b/drivers/video/fbdev/riva/fbdev.c index 55554b0433cb..84d5e23ad7d3 100644 --- a/drivers/video/fbdev/riva/fbdev.c +++ b/drivers/video/fbdev/riva/fbdev.c @@ -1084,6 +1084,9 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) int mode_valid = 0; NVTRACE_ENTER(); + if (!var->pixclock) + return -EINVAL; + switch (var->bits_per_pixel) { case 1 ... 8: var->red.offset = var->green.offset = var->blue.offset = 0; diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c index eda448b7a0c9..1e2f71c2f8a8 100644 --- a/drivers/video/fbdev/ssd1307fb.c +++ b/drivers/video/fbdev/ssd1307fb.c @@ -82,6 +82,11 @@ struct ssd1307fb_par { struct regulator *vbat_reg; u32 vcomh; u32 width; + /* Cached address ranges */ + u8 col_start; + u8 col_end; + u8 page_start; + u8 page_end; }; struct ssd1307fb_array { @@ -152,17 +157,72 @@ static inline int ssd1307fb_write_cmd(struct i2c_client *client, u8 cmd) return ret; } -static void ssd1307fb_update_display(struct ssd1307fb_par *par) +static int ssd1307fb_set_col_range(struct ssd1307fb_par *par, u8 col_start, + u8 cols) +{ + u8 col_end = col_start + cols - 1; + int ret; + + if (col_start == par->col_start && col_end == par->col_end) + return 0; + + ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE); + if (ret < 0) + return ret; + + ret = ssd1307fb_write_cmd(par->client, col_start); + if (ret < 0) + return ret; + + ret = ssd1307fb_write_cmd(par->client, col_end); + if (ret < 0) + return ret; + + par->col_start = col_start; + par->col_end = col_end; + return 0; +} + +static int ssd1307fb_set_page_range(struct ssd1307fb_par *par, u8 page_start, + u8 pages) +{ + u8 page_end = page_start + pages - 1; + int ret; + + if (page_start == par->page_start && page_end == par->page_end) + return 0; + + ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE); + if (ret < 0) + return ret; + + ret = ssd1307fb_write_cmd(par->client, page_start); + if (ret < 0) + return ret; + + ret = ssd1307fb_write_cmd(par->client, page_end); + if (ret < 0) + return ret; + + par->page_start = page_start; + par->page_end = page_end; + return 0; +} + +static int ssd1307fb_update_rect(struct ssd1307fb_par *par, unsigned int x, + unsigned int y, unsigned int width, + unsigned int height) { struct ssd1307fb_array *array; u8 *vmem = par->info->screen_buffer; unsigned int line_length = par->info->fix.line_length; - unsigned int pages = DIV_ROUND_UP(par->height, 8); - int i, j, k; + unsigned int pages = DIV_ROUND_UP(y % 8 + height, 8); + u32 array_idx = 0; + int ret, i, j, k; - array = ssd1307fb_alloc_array(par->width * pages, SSD1307FB_DATA); + array = ssd1307fb_alloc_array(width * pages, SSD1307FB_DATA); if (!array) - return; + return -ENOMEM; /* * The screen is divided in pages, each having a height of 8 @@ -193,27 +253,44 @@ static void ssd1307fb_update_display(struct ssd1307fb_par *par) * (5) A4 B4 C4 D4 E4 F4 G4 H4 */ - for (i = 0; i < pages; i++) { - for (j = 0; j < par->width; j++) { - int m = 8; - u32 array_idx = i * par->width + j; - array->data[array_idx] = 0; - /* Last page may be partial */ - if (i + 1 == pages && par->height % 8) - m = par->height % 8; + ret = ssd1307fb_set_col_range(par, par->col_offset + x, width); + if (ret < 0) + goto out_free; + + ret = ssd1307fb_set_page_range(par, par->page_offset + y / 8, pages); + if (ret < 0) + goto out_free; + + for (i = y / 8; i < y / 8 + pages; i++) { + int m = 8; + + /* Last page may be partial */ + if (8 * (i + 1) > par->height) + m = par->height % 8; + for (j = x; j < x + width; j++) { + u8 data = 0; + for (k = 0; k < m; k++) { u8 byte = vmem[(8 * i + k) * line_length + j / 8]; u8 bit = (byte >> (j % 8)) & 1; - array->data[array_idx] |= bit << k; + data |= bit << k; } + array->data[array_idx++] = data; } } - ssd1307fb_write_array(par->client, array, par->width * pages); + ret = ssd1307fb_write_array(par->client, array, width * pages); + +out_free: kfree(array); + return ret; } +static int ssd1307fb_update_display(struct ssd1307fb_par *par) +{ + return ssd1307fb_update_rect(par, 0, 0, par->width, par->height); +} static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf, size_t count, loff_t *ppos) @@ -222,6 +299,7 @@ static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf, unsigned long total_size; unsigned long p = *ppos; void *dst; + int ret; total_size = info->fix.smem_len; @@ -239,7 +317,9 @@ static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf, if (copy_from_user(dst, buf, count)) return -EFAULT; - ssd1307fb_update_display(par); + ret = ssd1307fb_update_display(par); + if (ret < 0) + return ret; *ppos += count; @@ -260,21 +340,24 @@ static void ssd1307fb_fillrect(struct fb_info *info, const struct fb_fillrect *r { struct ssd1307fb_par *par = info->par; sys_fillrect(info, rect); - ssd1307fb_update_display(par); + ssd1307fb_update_rect(par, rect->dx, rect->dy, rect->width, + rect->height); } static void ssd1307fb_copyarea(struct fb_info *info, const struct fb_copyarea *area) { struct ssd1307fb_par *par = info->par; sys_copyarea(info, area); - ssd1307fb_update_display(par); + ssd1307fb_update_rect(par, area->dx, area->dy, area->width, + area->height); } static void ssd1307fb_imageblit(struct fb_info *info, const struct fb_image *image) { struct ssd1307fb_par *par = info->par; sys_imageblit(info, image); - ssd1307fb_update_display(par); + ssd1307fb_update_rect(par, image->dx, image->dy, image->width, + image->height); } static const struct fb_ops ssd1307fb_ops = { @@ -454,37 +537,11 @@ static int ssd1307fb_init(struct ssd1307fb_par *par) if (ret < 0) return ret; - /* Set column range */ - ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_COL_RANGE); - if (ret < 0) - return ret; - - ret = ssd1307fb_write_cmd(par->client, par->col_offset); - if (ret < 0) - return ret; - - ret = ssd1307fb_write_cmd(par->client, par->col_offset + par->width - 1); - if (ret < 0) - return ret; - - /* Set page range */ - ret = ssd1307fb_write_cmd(par->client, SSD1307FB_SET_PAGE_RANGE); - if (ret < 0) - return ret; - - ret = ssd1307fb_write_cmd(par->client, par->page_offset); - if (ret < 0) - return ret; - - ret = ssd1307fb_write_cmd(par->client, - par->page_offset + - DIV_ROUND_UP(par->height, 8) - 1); + /* Clear the screen */ + ret = ssd1307fb_update_display(par); if (ret < 0) return ret; - /* Clear the screen */ - ssd1307fb_update_display(par); - /* Turn on the display */ ret = ssd1307fb_write_cmd(par->client, SSD1307FB_DISPLAY_ON); if (ret < 0) diff --git a/drivers/video/fbdev/xilinxfb.c b/drivers/video/fbdev/xilinxfb.c index ffbf900648d9..438e2c78142f 100644 --- a/drivers/video/fbdev/xilinxfb.c +++ b/drivers/video/fbdev/xilinxfb.c @@ -241,6 +241,8 @@ xilinx_fb_blank(int blank_mode, struct fb_info *fbi) case FB_BLANK_POWERDOWN: /* turn off panel */ xilinx_fb_out32(drvdata, REG_CTRL, 0); + break; + default: break; } |