Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

backlight: Replace fb events with a dedicated function call

Remove support for fb events from backlight subsystem. Provide the
helper backlight_notify_blank_all() instead. Also export the existing
helper backlight_notify_blank() to update a single backlight device.

In fbdev, call either helper to inform the backlight subsystem of
changes to a display's blank state. If the framebuffer device has a
specific backlight, only update this one; otherwise update all.

v4:
- protect blacklight declarations with IS_REACHABLE() (kernel test robot)
v3:
- declare empty fb_bl_notify_blank() as static inline (kernel test robot)

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Acked-by: Simona Vetter <simona.vetter@ffwll.ch>
Reviewed-by: "Daniel Thompson (RISCstar)" <danielt@kernel.org>
Link: https://lore.kernel.org/r/20250321095517.313713-7-tzimmermann@suse.de
Signed-off-by: Lee Jones <lee@kernel.org>

authored by

Thomas Zimmermann and committed by
Lee Jones
b01beb2f 4bfb77f3

+46 -79
+12 -73
drivers/video/backlight/backlight.c
··· 15 15 #include <linux/notifier.h> 16 16 #include <linux/ctype.h> 17 17 #include <linux/err.h> 18 - #include <linux/fb.h> 19 18 #include <linux/slab.h> 20 19 21 20 #ifdef CONFIG_PMAC_BACKLIGHT ··· 56 57 * a hot-key to adjust backlight, the driver must notify the backlight 57 58 * core that brightness has changed using backlight_force_update(). 58 59 * 59 - * The backlight driver core receives notifications from fbdev and 60 - * if the event is FB_EVENT_BLANK and if the value of blank, from the 61 - * FBIOBLANK ioctrl, results in a change in the backlight state the 62 - * update_status() operation is called. 60 + * Display drives can control the backlight device's status using 61 + * backlight_notify_blank() and backlight_notify_blank_all(). If this 62 + * results in a change in the backlight state the functions call the 63 + * update_status() operation. 63 64 */ 64 65 65 66 static struct list_head backlight_dev_list; ··· 77 78 [BACKLIGHT_SCALE_NON_LINEAR] = "non-linear", 78 79 }; 79 80 80 - #if defined(CONFIG_FB_CORE) || (defined(CONFIG_FB_CORE_MODULE) && \ 81 - defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)) 82 - static void backlight_notify_blank(struct backlight_device *bd, 83 - struct device *display_dev, 84 - bool fb_on, bool prev_fb_on) 81 + void backlight_notify_blank(struct backlight_device *bd, struct device *display_dev, 82 + bool fb_on, bool prev_fb_on) 85 83 { 86 84 guard(mutex)(&bd->ops_lock); 87 85 ··· 99 103 } 100 104 } 101 105 } 106 + EXPORT_SYMBOL(backlight_notify_blank); 102 107 103 - /* 104 - * fb_notifier_callback 105 - * 106 - * This callback gets called when something important happens inside a 107 - * framebuffer driver. The backlight core only cares about FB_BLANK_UNBLANK 108 - * which is reported to the driver using backlight_update_status() 109 - * as a state change. 110 - * 111 - * There may be several fbdev's connected to the backlight device, 112 - * in which case they are kept track of. A state change is only reported 113 - * if there is a change in backlight for the specified fbdev. 114 - */ 115 - static int fb_notifier_callback(struct notifier_block *self, 116 - unsigned long event, void *data) 108 + void backlight_notify_blank_all(struct device *display_dev, bool fb_on, bool prev_fb_on) 117 109 { 118 110 struct backlight_device *bd; 119 - struct fb_event *evdata = data; 120 - struct fb_info *info = evdata->info; 121 - const int *fb_blank = evdata->data; 122 - struct backlight_device *fb_bd = fb_bl_device(info); 123 - bool fb_on, prev_fb_on; 124 111 125 - /* If we aren't interested in this event, skip it immediately ... */ 126 - if (event != FB_EVENT_BLANK) 127 - return 0; 112 + guard(mutex)(&backlight_dev_list_mutex); 128 113 129 - bd = container_of(self, struct backlight_device, fb_notif); 130 - 131 - if (fb_bd && fb_bd != bd) 132 - return 0; 133 - 134 - fb_on = fb_blank[0] == FB_BLANK_UNBLANK; 135 - prev_fb_on = fb_blank[1] == FB_BLANK_UNBLANK; 136 - 137 - backlight_notify_blank(bd, info->device, fb_on, prev_fb_on); 138 - 139 - return 0; 114 + list_for_each_entry(bd, &backlight_dev_list, entry) 115 + backlight_notify_blank(bd, display_dev, fb_on, prev_fb_on); 140 116 } 141 - 142 - static int backlight_register_fb(struct backlight_device *bd) 143 - { 144 - memset(&bd->fb_notif, 0, sizeof(bd->fb_notif)); 145 - bd->fb_notif.notifier_call = fb_notifier_callback; 146 - 147 - return fb_register_client(&bd->fb_notif); 148 - } 149 - 150 - static void backlight_unregister_fb(struct backlight_device *bd) 151 - { 152 - fb_unregister_client(&bd->fb_notif); 153 - } 154 - #else 155 - static inline int backlight_register_fb(struct backlight_device *bd) 156 - { 157 - return 0; 158 - } 159 - 160 - static inline void backlight_unregister_fb(struct backlight_device *bd) 161 - { 162 - } 163 - #endif /* CONFIG_FB_CORE */ 117 + EXPORT_SYMBOL(backlight_notify_blank_all); 164 118 165 119 static void backlight_generate_event(struct backlight_device *bd, 166 120 enum backlight_update_reason reason) ··· 401 455 return ERR_PTR(rc); 402 456 } 403 457 404 - rc = backlight_register_fb(new_bd); 405 - if (rc) { 406 - device_unregister(&new_bd->dev); 407 - return ERR_PTR(rc); 408 - } 409 - 410 458 new_bd->ops = ops; 411 459 412 460 #ifdef CONFIG_PMAC_BACKLIGHT ··· 487 547 bd->ops = NULL; 488 548 mutex_unlock(&bd->ops_lock); 489 549 490 - backlight_unregister_fb(bd); 491 550 device_unregister(&bd->dev); 492 551 } 493 552 EXPORT_SYMBOL(backlight_device_unregister);
+12
drivers/video/fbdev/core/fb_backlight.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-or-later 2 2 3 + #include <linux/backlight.h> 3 4 #include <linux/export.h> 4 5 #include <linux/fb.h> 5 6 #include <linux/mutex.h> ··· 37 36 return info->bl_dev; 38 37 } 39 38 EXPORT_SYMBOL(fb_bl_device); 39 + 40 + void fb_bl_notify_blank(struct fb_info *info, int old_blank) 41 + { 42 + bool on = info->blank == FB_BLANK_UNBLANK; 43 + bool prev_on = old_blank == FB_BLANK_UNBLANK; 44 + 45 + if (info->bl_dev) 46 + backlight_notify_blank(info->bl_dev, info->device, on, prev_on); 47 + else 48 + backlight_notify_blank_all(info->device, on, prev_on); 49 + } 40 50 #endif
+2
drivers/video/fbdev/core/fbmem.c
··· 363 363 if (ret) 364 364 goto err; 365 365 366 + fb_bl_notify_blank(info, old_blank); 367 + 366 368 fb_notifier_call_chain(FB_EVENT_BLANK, &event); 367 369 368 370 return 0;
+16 -6
include/linux/backlight.h
··· 12 12 #include <linux/device.h> 13 13 #include <linux/fb.h> 14 14 #include <linux/mutex.h> 15 - #include <linux/notifier.h> 16 15 #include <linux/types.h> 17 16 18 17 /** ··· 278 279 const struct backlight_ops *ops; 279 280 280 281 /** 281 - * @fb_notif: The framebuffer notifier block 282 - */ 283 - struct notifier_block fb_notif; 284 - 285 - /** 286 282 * @entry: List entry of all registered backlight devices 287 283 */ 288 284 struct list_head entry; ··· 393 399 struct backlight_device *backlight_device_get_by_type(enum backlight_type type); 394 400 int backlight_device_set_brightness(struct backlight_device *bd, 395 401 unsigned long brightness); 402 + 403 + #if IS_REACHABLE(CONFIG_BACKLIGHT_CLASS_DEVICE) 404 + void backlight_notify_blank(struct backlight_device *bd, 405 + struct device *display_dev, 406 + bool fb_on, bool prev_fb_on); 407 + void backlight_notify_blank_all(struct device *display_dev, 408 + bool fb_on, bool prev_fb_on); 409 + #else 410 + static inline void backlight_notify_blank(struct backlight_device *bd, 411 + struct device *display_dev, 412 + bool fb_on, bool prev_fb_on) 413 + { } 414 + static inline void backlight_notify_blank_all(struct device *display_dev, 415 + bool fb_on, bool prev_fb_on) 416 + { } 417 + #endif 396 418 397 419 #define to_backlight_device(obj) container_of(obj, struct backlight_device, dev) 398 420
+4
include/linux/fb.h
··· 758 758 759 759 #if IS_ENABLED(CONFIG_FB_BACKLIGHT) 760 760 struct backlight_device *fb_bl_device(struct fb_info *info); 761 + void fb_bl_notify_blank(struct fb_info *info, int old_blank); 761 762 #else 762 763 static inline struct backlight_device *fb_bl_device(struct fb_info *info) 763 764 { 764 765 return NULL; 765 766 } 767 + 768 + static inline void fb_bl_notify_blank(struct fb_info *info, int old_blank) 769 + { } 766 770 #endif 767 771 768 772 static inline struct lcd_device *fb_lcd_device(struct fb_info *info)