Commit a8a6b118 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'fbdev-v4.21' of git://github.com/bzolnier/linux

Pull fbdev updates from Bartlomiej Zolnierkiewicz:
 "This time the pull request is really small.

  The most notable changes are fixing fbcon to not cause crash on
  unregister_framebuffer() operation when there is more than one
  framebuffer, adding config option to center the bootup logo and making
  FB_BACKLIGHT config option tristate (which in turn uncovered incorrect
  FB_BACKLIGHT usage by DRM's nouveau driver).

  Summary:

   - fix fbcon to not cause crash on unregister_framebuffer() when there
     is more than one framebuffer (Noralf Trønnes)

   - improve support for small rotated displays (Peter Rosin)

   - fix probe failure handling in udlfb driver (Dan Carpenter)

   - add config option to center the bootup logo (Peter Rosin)

   - make FB_BACKLIGHT config option tristate (Rob Clark)

   - remove superfluous HAS_DMA dependency for goldfishfb driver (Geert
     Uytterhoeven)

   - misc fixes (Alexey Khoroshilov, YueHaibing, Colin Ian King, Lubomir
     Rintel)

   - misc cleanups (Yangtao Li, Wen Yang)

  also there is DRM's nouveau driver fix for wrong FB_BACKLIGHT config
  option usage (FB_BACKLIGHT is for internal fbdev subsystem use only)"

* tag 'fbdev-v4.21' of git://github.com/bzolnier/linux:
  drm/nouveau: fix incorrect FB_BACKLIGHT usage in Kconfig
  fbdev: fbcon: Fix unregister crash when more than one framebuffer
  fbdev: Remove depends on HAS_DMA in case of platform dependency
  pxa168fb: trivial typo fix
  fbdev: fsl-diu: remove redundant null check on cmap
  fbdev: omap2: omapfb: convert to DEFINE_SHOW_ATTRIBUTE
  fbdev: uvesafb: fix spelling mistake "memoery" -> "memory"
  fbdev: fbmem: add config option to center the bootup logo
  fbdev: fbmem: make fb_show_logo_line return the end instead of the height
  video: fbdev: pxafb: Fix "WARNING: invalid free of devm_ allocated data"
  fbdev: fbmem: behave better with small rotated displays and many CPUs
  video: clps711x-fb: release disp device node in probe()
  fbdev: make FB_BACKLIGHT a tristate
  udlfb: fix some inconsistent NULL checking
parents 7671c14e 399382f8
...@@ -4,7 +4,8 @@ config DRM_NOUVEAU ...@@ -4,7 +4,8 @@ config DRM_NOUVEAU
select FW_LOADER select FW_LOADER
select DRM_KMS_HELPER select DRM_KMS_HELPER
select DRM_TTM select DRM_TTM
select FB_BACKLIGHT if DRM_NOUVEAU_BACKLIGHT select BACKLIGHT_CLASS_DEVICE if DRM_NOUVEAU_BACKLIGHT
select BACKLIGHT_LCD_SUPPORT if DRM_NOUVEAU_BACKLIGHT
select ACPI_VIDEO if ACPI && X86 && BACKLIGHT_CLASS_DEVICE && INPUT select ACPI_VIDEO if ACPI && X86 && BACKLIGHT_CLASS_DEVICE && INPUT
select X86_PLATFORM_DEVICES if ACPI && X86 select X86_PLATFORM_DEVICES if ACPI && X86
select ACPI_WMI if ACPI && X86 select ACPI_WMI if ACPI && X86
......
...@@ -184,7 +184,7 @@ config FB_MACMODES ...@@ -184,7 +184,7 @@ config FB_MACMODES
depends on FB depends on FB
config FB_BACKLIGHT config FB_BACKLIGHT
bool tristate
depends on FB depends on FB
select BACKLIGHT_LCD_SUPPORT select BACKLIGHT_LCD_SUPPORT
select BACKLIGHT_CLASS_DEVICE select BACKLIGHT_CLASS_DEVICE
...@@ -2037,7 +2037,8 @@ config FB_XILINX ...@@ -2037,7 +2037,8 @@ config FB_XILINX
config FB_GOLDFISH config FB_GOLDFISH
tristate "Goldfish Framebuffer" tristate "Goldfish Framebuffer"
depends on FB && HAS_DMA && (GOLDFISH || COMPILE_TEST) depends on FB
depends on GOLDFISH || COMPILE_TEST
select FB_CFB_FILLRECT select FB_CFB_FILLRECT
select FB_CFB_COPYAREA select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT select FB_CFB_IMAGEBLIT
......
...@@ -287,14 +287,17 @@ static int clps711x_fb_probe(struct platform_device *pdev) ...@@ -287,14 +287,17 @@ static int clps711x_fb_probe(struct platform_device *pdev)
} }
ret = of_get_fb_videomode(disp, &cfb->mode, OF_USE_NATIVE_MODE); ret = of_get_fb_videomode(disp, &cfb->mode, OF_USE_NATIVE_MODE);
if (ret) if (ret) {
of_node_put(disp);
goto out_fb_release; goto out_fb_release;
}
of_property_read_u32(disp, "ac-prescale", &cfb->ac_prescale); of_property_read_u32(disp, "ac-prescale", &cfb->ac_prescale);
cfb->cmap_invert = of_property_read_bool(disp, "cmap-invert"); cfb->cmap_invert = of_property_read_bool(disp, "cmap-invert");
ret = of_property_read_u32(disp, "bits-per-pixel", ret = of_property_read_u32(disp, "bits-per-pixel",
&info->var.bits_per_pixel); &info->var.bits_per_pixel);
of_node_put(disp);
if (ret) if (ret)
goto out_fb_release; goto out_fb_release;
......
...@@ -3064,7 +3064,7 @@ static int fbcon_fb_unbind(int idx) ...@@ -3064,7 +3064,7 @@ static int fbcon_fb_unbind(int idx)
for (i = first_fb_vc; i <= last_fb_vc; i++) { for (i = first_fb_vc; i <= last_fb_vc; i++) {
if (con2fb_map[i] != idx && if (con2fb_map[i] != idx &&
con2fb_map[i] != -1) { con2fb_map[i] != -1) {
new_idx = i; new_idx = con2fb_map[i];
break; break;
} }
} }
......
...@@ -436,7 +436,9 @@ static void fb_do_show_logo(struct fb_info *info, struct fb_image *image, ...@@ -436,7 +436,9 @@ static void fb_do_show_logo(struct fb_info *info, struct fb_image *image,
image->dx += image->width + 8; image->dx += image->width + 8;
} }
} else if (rotate == FB_ROTATE_UD) { } else if (rotate == FB_ROTATE_UD) {
for (x = 0; x < num; x++) { u32 dx = image->dx;
for (x = 0; x < num && image->dx <= dx; x++) {
info->fbops->fb_imageblit(info, image); info->fbops->fb_imageblit(info, image);
image->dx -= image->width + 8; image->dx -= image->width + 8;
} }
...@@ -448,7 +450,9 @@ static void fb_do_show_logo(struct fb_info *info, struct fb_image *image, ...@@ -448,7 +450,9 @@ static void fb_do_show_logo(struct fb_info *info, struct fb_image *image,
image->dy += image->height + 8; image->dy += image->height + 8;
} }
} else if (rotate == FB_ROTATE_CCW) { } else if (rotate == FB_ROTATE_CCW) {
for (x = 0; x < num; x++) { u32 dy = image->dy;
for (x = 0; x < num && image->dy <= dy; x++) {
info->fbops->fb_imageblit(info, image); info->fbops->fb_imageblit(info, image);
image->dy -= image->height + 8; image->dy -= image->height + 8;
} }
...@@ -502,8 +506,25 @@ static int fb_show_logo_line(struct fb_info *info, int rotate, ...@@ -502,8 +506,25 @@ static int fb_show_logo_line(struct fb_info *info, int rotate,
fb_set_logo(info, logo, logo_new, fb_logo.depth); fb_set_logo(info, logo, logo_new, fb_logo.depth);
} }
#ifdef CONFIG_FB_LOGO_CENTER
{
int xres = info->var.xres;
int yres = info->var.yres;
if (rotate == FB_ROTATE_CW || rotate == FB_ROTATE_CCW) {
xres = info->var.yres;
yres = info->var.xres;
}
while (n && (n * (logo->width + 8) - 8 > xres))
--n;
image.dx = (xres - n * (logo->width + 8) - 8) / 2;
image.dy = y ?: (yres - logo->height) / 2;
}
#else
image.dx = 0; image.dx = 0;
image.dy = y; image.dy = y;
#endif
image.width = logo->width; image.width = logo->width;
image.height = logo->height; image.height = logo->height;
...@@ -521,7 +542,7 @@ static int fb_show_logo_line(struct fb_info *info, int rotate, ...@@ -521,7 +542,7 @@ static int fb_show_logo_line(struct fb_info *info, int rotate,
info->pseudo_palette = saved_pseudo_palette; info->pseudo_palette = saved_pseudo_palette;
kfree(logo_new); kfree(logo_new);
kfree(logo_rotate); kfree(logo_rotate);
return logo->height; return image.dy + logo->height;
} }
...@@ -573,7 +594,7 @@ static int fb_show_extra_logos(struct fb_info *info, int y, int rotate) ...@@ -573,7 +594,7 @@ static int fb_show_extra_logos(struct fb_info *info, int y, int rotate)
unsigned int i; unsigned int i;
for (i = 0; i < fb_logo_ex_num; i++) for (i = 0; i < fb_logo_ex_num; i++)
y += fb_show_logo_line(info, rotate, y = fb_show_logo_line(info, rotate,
fb_logo_ex[i].logo, y, fb_logo_ex[i].n); fb_logo_ex[i].logo, y, fb_logo_ex[i].n);
return y; return y;
...@@ -600,6 +621,7 @@ int fb_prepare_logo(struct fb_info *info, int rotate) ...@@ -600,6 +621,7 @@ int fb_prepare_logo(struct fb_info *info, int rotate)
{ {
int depth = fb_get_color_depth(&info->var, &info->fix); int depth = fb_get_color_depth(&info->var, &info->fix);
unsigned int yres; unsigned int yres;
int height;
memset(&fb_logo, 0, sizeof(struct logo_data)); memset(&fb_logo, 0, sizeof(struct logo_data));
...@@ -661,7 +683,12 @@ int fb_prepare_logo(struct fb_info *info, int rotate) ...@@ -661,7 +683,12 @@ int fb_prepare_logo(struct fb_info *info, int rotate)
} }
} }
return fb_prepare_extra_logos(info, fb_logo.logo->height, yres); height = fb_logo.logo->height;
#ifdef CONFIG_FB_LOGO_CENTER
height += (yres - fb_logo.logo->height) / 2;
#endif
return fb_prepare_extra_logos(info, height, yres);
} }
int fb_show_logo(struct fb_info *info, int rotate) int fb_show_logo(struct fb_info *info, int rotate)
......
...@@ -60,7 +60,7 @@ struct fb_info *framebuffer_alloc(size_t size, struct device *dev) ...@@ -60,7 +60,7 @@ struct fb_info *framebuffer_alloc(size_t size, struct device *dev)
info->device = dev; info->device = dev;
info->fbcon_rotate_hint = -1; info->fbcon_rotate_hint = -1;
#ifdef CONFIG_FB_BACKLIGHT #if IS_ENABLED(CONFIG_FB_BACKLIGHT)
mutex_init(&info->bl_curve_mutex); mutex_init(&info->bl_curve_mutex);
#endif #endif
...@@ -429,7 +429,7 @@ static ssize_t show_fbstate(struct device *device, ...@@ -429,7 +429,7 @@ static ssize_t show_fbstate(struct device *device,
return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state); return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->state);
} }
#ifdef CONFIG_FB_BACKLIGHT #if IS_ENABLED(CONFIG_FB_BACKLIGHT)
static ssize_t store_bl_curve(struct device *device, static ssize_t store_bl_curve(struct device *device,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
...@@ -510,7 +510,7 @@ static struct device_attribute device_attrs[] = { ...@@ -510,7 +510,7 @@ static struct device_attribute device_attrs[] = {
__ATTR(stride, S_IRUGO, show_stride, NULL), __ATTR(stride, S_IRUGO, show_stride, NULL),
__ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate), __ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate),
__ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate), __ATTR(state, S_IRUGO|S_IWUSR, show_fbstate, store_fbstate),
#ifdef CONFIG_FB_BACKLIGHT #if IS_ENABLED(CONFIG_FB_BACKLIGHT)
__ATTR(bl_curve, S_IRUGO|S_IWUSR, show_bl_curve, store_bl_curve), __ATTR(bl_curve, S_IRUGO|S_IWUSR, show_bl_curve, store_bl_curve),
#endif #endif
}; };
...@@ -551,7 +551,7 @@ void fb_cleanup_device(struct fb_info *fb_info) ...@@ -551,7 +551,7 @@ void fb_cleanup_device(struct fb_info *fb_info)
} }
} }
#ifdef CONFIG_FB_BACKLIGHT #if IS_ENABLED(CONFIG_FB_BACKLIGHT)
/* This function generates a linear backlight curve /* This function generates a linear backlight curve
* *
* 0: off * 0: off
......
...@@ -1575,7 +1575,6 @@ static void uninstall_fb(struct fb_info *info) ...@@ -1575,7 +1575,6 @@ static void uninstall_fb(struct fb_info *info)
unregister_framebuffer(info); unregister_framebuffer(info);
unmap_video_memory(info); unmap_video_memory(info);
if (&info->cmap)
fb_dealloc_cmap(&info->cmap); fb_dealloc_cmap(&info->cmap);
mfbi->registered = 0; mfbi->registered = 0;
......
...@@ -99,24 +99,14 @@ int dss_set_min_bus_tput(struct device *dev, unsigned long tput) ...@@ -99,24 +99,14 @@ int dss_set_min_bus_tput(struct device *dev, unsigned long tput)
} }
#if defined(CONFIG_FB_OMAP2_DSS_DEBUGFS) #if defined(CONFIG_FB_OMAP2_DSS_DEBUGFS)
static int dss_debug_show(struct seq_file *s, void *unused) static int dss_show(struct seq_file *s, void *unused)
{ {
void (*func)(struct seq_file *) = s->private; void (*func)(struct seq_file *) = s->private;
func(s); func(s);
return 0; return 0;
} }
static int dss_debug_open(struct inode *inode, struct file *file) DEFINE_SHOW_ATTRIBUTE(dss);
{
return single_open(file, dss_debug_show, inode->i_private);
}
static const struct file_operations dss_debug_fops = {
.open = dss_debug_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static struct dentry *dss_debugfs_dir; static struct dentry *dss_debugfs_dir;
...@@ -130,7 +120,7 @@ static int dss_initialize_debugfs(void) ...@@ -130,7 +120,7 @@ static int dss_initialize_debugfs(void)
} }
debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir, debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
&dss_debug_dump_clocks, &dss_debug_fops); &dss_debug_dump_clocks, &dss_fops);
return 0; return 0;
} }
...@@ -145,7 +135,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)) ...@@ -145,7 +135,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
struct dentry *d; struct dentry *d;
d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir, d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir,
write, &dss_debug_fops); write, &dss_fops);
return PTR_ERR_OR_ZERO(d); return PTR_ERR_OR_ZERO(d);
} }
......
...@@ -279,7 +279,7 @@ static void set_clock_divider(struct pxa168fb_info *fbi, ...@@ -279,7 +279,7 @@ static void set_clock_divider(struct pxa168fb_info *fbi,
/* check whether divisor is too small. */ /* check whether divisor is too small. */
if (divider_int < 2) { if (divider_int < 2) {
dev_warn(fbi->dev, "Warning: clock source is too slow." dev_warn(fbi->dev, "Warning: clock source is too slow. "
"Try smaller resolution\n"); "Try smaller resolution\n");
divider_int = 2; divider_int = 2;
} }
......
...@@ -2234,10 +2234,8 @@ static struct pxafb_mach_info *of_pxafb_of_mach_info(struct device *dev) ...@@ -2234,10 +2234,8 @@ static struct pxafb_mach_info *of_pxafb_of_mach_info(struct device *dev)
if (!info) if (!info)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
ret = of_get_pxafb_mode_info(dev, info); ret = of_get_pxafb_mode_info(dev, info);
if (ret) { if (ret)
kfree(info->modes);
return ERR_PTR(ret); return ERR_PTR(ret);
}
/* /*
* On purpose, neither lccrX registers nor video memory size can be * On purpose, neither lccrX registers nor video memory size can be
......
...@@ -1598,7 +1598,7 @@ static int dlfb_usb_probe(struct usb_interface *intf, ...@@ -1598,7 +1598,7 @@ static int dlfb_usb_probe(struct usb_interface *intf,
dlfb = kzalloc(sizeof(*dlfb), GFP_KERNEL); dlfb = kzalloc(sizeof(*dlfb), GFP_KERNEL);
if (!dlfb) { if (!dlfb) {
dev_err(&intf->dev, "%s: failed to allocate dlfb\n", __func__); dev_err(&intf->dev, "%s: failed to allocate dlfb\n", __func__);
goto error; return -ENOMEM;
} }
INIT_LIST_HEAD(&dlfb->deferred_free); INIT_LIST_HEAD(&dlfb->deferred_free);
...@@ -1703,7 +1703,7 @@ static int dlfb_usb_probe(struct usb_interface *intf, ...@@ -1703,7 +1703,7 @@ static int dlfb_usb_probe(struct usb_interface *intf,
error: error:
if (dlfb->info) { if (dlfb->info) {
dlfb_ops_destroy(dlfb->info); dlfb_ops_destroy(dlfb->info);
} else if (dlfb) { } else {
usb_put_dev(dlfb->udev); usb_put_dev(dlfb->udev);
kfree(dlfb); kfree(dlfb);
} }
...@@ -1730,12 +1730,10 @@ static void dlfb_usb_disconnect(struct usb_interface *intf) ...@@ -1730,12 +1730,10 @@ static void dlfb_usb_disconnect(struct usb_interface *intf)
/* this function will wait for all in-flight urbs to complete */ /* this function will wait for all in-flight urbs to complete */
dlfb_free_urb_list(dlfb); dlfb_free_urb_list(dlfb);
if (info) {
/* remove udlfb's sysfs interfaces */ /* remove udlfb's sysfs interfaces */
for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++) for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
device_remove_file(info->dev, &fb_device_attrs[i]); device_remove_file(info->dev, &fb_device_attrs[i]);
device_remove_bin_file(info->dev, &edid_attr); device_remove_bin_file(info->dev, &edid_attr);
}
unregister_framebuffer(info); unregister_framebuffer(info);
} }
......
...@@ -1979,7 +1979,7 @@ MODULE_PARM_DESC(noedid, ...@@ -1979,7 +1979,7 @@ MODULE_PARM_DESC(noedid,
module_param(vram_remap, uint, 0); module_param(vram_remap, uint, 0);
MODULE_PARM_DESC(vram_remap, "Set amount of video memory to be used [MiB]"); MODULE_PARM_DESC(vram_remap, "Set amount of video memory to be used [MiB]");
module_param(vram_total, uint, 0); module_param(vram_total, uint, 0);
MODULE_PARM_DESC(vram_total, "Set total amount of video memoery [MiB]"); MODULE_PARM_DESC(vram_total, "Set total amount of video memory [MiB]");
module_param(maxclk, ushort, 0); module_param(maxclk, ushort, 0);
MODULE_PARM_DESC(maxclk, "Maximum pixelclock [MHz], overrides EDID data"); MODULE_PARM_DESC(maxclk, "Maximum pixelclock [MHz], overrides EDID data");
module_param(maxhf, ushort, 0); module_param(maxhf, ushort, 0);
......
...@@ -10,6 +10,15 @@ menuconfig LOGO ...@@ -10,6 +10,15 @@ menuconfig LOGO
if LOGO if LOGO
config FB_LOGO_CENTER
bool "Center the logo"
depends on FB=y
help
When this option is selected, the bootup logo is centered both
horizontally and vertically. If more than one logo is displayed
due to multiple CPUs, the collected line of logos is centered
as a whole.
config FB_LOGO_EXTRA config FB_LOGO_EXTRA
bool bool
depends on FB=y depends on FB=y
......
...@@ -485,7 +485,7 @@ struct fb_info { ...@@ -485,7 +485,7 @@ struct fb_info {
struct list_head modelist; /* mode list */ struct list_head modelist; /* mode list */
struct fb_videomode *mode; /* current mode */ struct fb_videomode *mode; /* current mode */
#ifdef CONFIG_FB_BACKLIGHT #if IS_ENABLED(CONFIG_FB_BACKLIGHT)
/* assigned backlight device */ /* assigned backlight device */
/* set before framebuffer registration, /* set before framebuffer registration,
remove after unregister */ remove after unregister */
......
...@@ -393,11 +393,9 @@ struct fb_cursor { ...@@ -393,11 +393,9 @@ struct fb_cursor {
struct fb_image image; /* Cursor image */ struct fb_image image; /* Cursor image */
}; };
#ifdef CONFIG_FB_BACKLIGHT
/* Settings for the generic backlight code */ /* Settings for the generic backlight code */
#define FB_BACKLIGHT_LEVELS 128 #define FB_BACKLIGHT_LEVELS 128
#define FB_BACKLIGHT_MAX 0xFF #define FB_BACKLIGHT_MAX 0xFF
#endif
#endif /* _UAPI_LINUX_FB_H */ #endif /* _UAPI_LINUX_FB_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment