Remove support for fb events from the lcd subsystem. Provide the helper lcd_notify_blank_all() instead. In fbdev, call lcd_notify_blank_all() to inform the lcd subsystem of changes to a display's blank state. Signed-off-by: Thomas Zimmermann <tzimmermann@xxxxxxx> --- drivers/video/backlight/lcd.c | 90 ++++++-------------------------- drivers/video/fbdev/core/fbmem.c | 43 +++++++++++++-- include/linux/lcd.h | 7 +-- 3 files changed, 60 insertions(+), 80 deletions(-) diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index b2ee25060d66..67daa3757211 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -15,7 +15,6 @@ #include <linux/notifier.h> #include <linux/ctype.h> #include <linux/err.h> -#include <linux/fb.h> #include <linux/slab.h> static struct list_head lcd_dev_list; @@ -34,6 +33,17 @@ static void lcd_notify_blank(struct lcd_device *ld, struct device *display_dev, ld->ops->set_power(ld, power); } +void lcd_notify_blank_all(struct device *display_dev, int power) +{ + struct lcd_device *ld; + + guard(mutex)(&lcd_dev_list_mutex); + + list_for_each_entry(ld, &lcd_dev_list, entry) + lcd_notify_blank(ld, display_dev, power); +} +EXPORT_SYMBOL(lcd_notify_blank_all); + static void lcd_notify_mode_change(struct lcd_device *ld, struct device *display_dev, unsigned int width, unsigned int height) { @@ -47,75 +57,16 @@ static void lcd_notify_mode_change(struct lcd_device *ld, struct device *display ld->ops->set_mode(ld, width, height); } -#if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \ - defined(CONFIG_LCD_CLASS_DEVICE_MODULE)) -static int to_lcd_power(int fb_blank) -{ - switch (fb_blank) { - case FB_BLANK_UNBLANK: - return LCD_POWER_ON; - /* deprecated; TODO: should become 'off' */ - case FB_BLANK_NORMAL: - return LCD_POWER_REDUCED; - case FB_BLANK_VSYNC_SUSPEND: - return LCD_POWER_REDUCED_VSYNC_SUSPEND; - /* 'off' */ - case FB_BLANK_HSYNC_SUSPEND: - case FB_BLANK_POWERDOWN: - default: - return LCD_POWER_OFF; - } -} - -/* This callback gets called when something important happens inside a - * framebuffer driver. We're looking if that important event is blanking, - * and if it is, we're switching lcd power as well ... - */ -static int fb_notifier_callback(struct notifier_block *self, - unsigned long event, void *data) -{ - struct lcd_device *ld = container_of(self, struct lcd_device, fb_notif); - struct fb_event *evdata = data; - struct fb_info *info = evdata->info; - struct lcd_device *fb_lcd = fb_lcd_device(info); - - if (fb_lcd && fb_lcd != ld) - return 0; - - if (event == FB_EVENT_BLANK) { - int power = to_lcd_power(*(int *)evdata->data); - - lcd_notify_blank(ld, info->device, power); - } else { - const struct fb_videomode *videomode = evdata->data; - - lcd_notify_mode_change(ld, info->device, videomode->xres, videomode->yres); - } - - return 0; -} - -static int lcd_register_fb(struct lcd_device *ld) +void lcd_notify_mode_change_all(struct device *display_dev, + unsigned int width, unsigned int height) { - memset(&ld->fb_notif, 0, sizeof(ld->fb_notif)); - ld->fb_notif.notifier_call = fb_notifier_callback; - return fb_register_client(&ld->fb_notif); -} + struct lcd_device *ld; -static void lcd_unregister_fb(struct lcd_device *ld) -{ - fb_unregister_client(&ld->fb_notif); -} -#else -static int lcd_register_fb(struct lcd_device *ld) -{ - return 0; -} + guard(mutex)(&lcd_dev_list_mutex); -static inline void lcd_unregister_fb(struct lcd_device *ld) -{ + list_for_each_entry(ld, &lcd_dev_list, entry) + lcd_notify_mode_change(ld, display_dev, width, height); } -#endif /* CONFIG_FB */ static ssize_t lcd_power_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -266,12 +217,6 @@ struct lcd_device *lcd_device_register(const char *name, struct device *parent, return ERR_PTR(rc); } - rc = lcd_register_fb(new_ld); - if (rc) { - device_unregister(&new_ld->dev); - return ERR_PTR(rc); - } - mutex_lock(&lcd_dev_list_mutex); list_add(&new_ld->entry, &lcd_dev_list); mutex_unlock(&lcd_dev_list_mutex); @@ -298,7 +243,6 @@ void lcd_device_unregister(struct lcd_device *ld) mutex_lock(&ld->ops_lock); ld->ops = NULL; mutex_unlock(&ld->ops_lock); - lcd_unregister_fb(ld); device_unregister(&ld->dev); } diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 993fbee602e0..fb7ca143a996 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -15,6 +15,7 @@ #include <linux/export.h> #include <linux/fb.h> #include <linux/fbcon.h> +#include <linux/lcd.h> #include <video/nomodeset.h> @@ -220,6 +221,14 @@ static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var, return err; } +static void fb_lcd_notify_mode_change(struct fb_info *info, + struct fb_videomode *mode) +{ +#if IS_REACHABLE(CONFIG_LCD_CLASS_DEVICE) + lcd_notify_mode_change_all(info->device, mode->xres, mode->yres); +#endif +} + int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) { @@ -227,7 +236,6 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) u32 activate; struct fb_var_screeninfo old_var; struct fb_videomode mode; - struct fb_event event; u32 unused; if (var->activate & FB_ACTIVATE_INV_MODE) { @@ -331,14 +339,40 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) if (ret) return ret; - event.info = info; - event.data = &mode; - fb_notifier_call_chain(FB_EVENT_MODE_CHANGE, &event); + fb_lcd_notify_mode_change(info, &mode); return 0; } EXPORT_SYMBOL(fb_set_var); +static void fb_lcd_notify_blank(struct fb_info *info) +{ +#if IS_REACHABLE(CONFIG_LCD_CLASS_DEVICE) + int power; + + switch (info->blank) { + case FB_BLANK_UNBLANK: + power = LCD_POWER_ON; + break; + /* deprecated; TODO: should become 'off' */ + case FB_BLANK_NORMAL: + power = LCD_POWER_REDUCED; + break; + case FB_BLANK_VSYNC_SUSPEND: + power = LCD_POWER_REDUCED_VSYNC_SUSPEND; + break; + /* 'off' */ + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_POWERDOWN: + default: + power = LCD_POWER_OFF; + break; + } + + lcd_notify_blank_all(info->device, power); +#endif +} + int fb_blank(struct fb_info *info, int blank) { int old_blank = info->blank; @@ -364,6 +398,7 @@ int fb_blank(struct fb_info *info, int blank) goto err; fb_bl_notify_blank(info, old_blank); + fb_lcd_notify_blank(info); fb_notifier_call_chain(FB_EVENT_BLANK, &event); diff --git a/include/linux/lcd.h b/include/linux/lcd.h index 195b95edb13f..cabcc193a818 100644 --- a/include/linux/lcd.h +++ b/include/linux/lcd.h @@ -11,7 +11,6 @@ #include <linux/device.h> #include <linux/mutex.h> -#include <linux/notifier.h> #define LCD_POWER_ON (0) #define LCD_POWER_REDUCED (1) // deprecated; don't use in new code @@ -79,8 +78,6 @@ struct lcd_device { const struct lcd_ops *ops; /* Serialise access to set_power method */ struct mutex update_lock; - /* The framebuffer notifier block */ - struct notifier_block fb_notif; /** * @entry: List entry of all registered lcd devices @@ -130,6 +127,10 @@ extern void lcd_device_unregister(struct lcd_device *ld); extern void devm_lcd_device_unregister(struct device *dev, struct lcd_device *ld); +void lcd_notify_blank_all(struct device *display_dev, int power); +void lcd_notify_mode_change_all(struct device *display_dev, + unsigned int width, unsigned int height); + #define to_lcd_device(obj) container_of(obj, struct lcd_device, dev) static inline void * lcd_get_data(struct lcd_device *ld_dev) -- 2.48.1