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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'backlight-next-6.16' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight

Pull backlight updates from Lee Jones:
"Framebuffer Subsystem (fbdev):
- The display's blanking status is now tracked in 'struct fb_info'
- 'framebuffer_alloc()' initializes the blank state to FB_BLANK_UNBLANK
- 'register_framebuffer()' sets the state to 'FB_BLANK_POWERDOWN' if
an 'fb_blank' callback exists, ensuring 'FB_EVENT_BLANK' listeners
correctly see the display being turned on during the first modeset
- The 'FB_EVENT_BLANK' event data now includes both the new and the
old blank states
- 'fb_blank()' has been reworked to return early on errors, without
functional changes, in preparation for further state tracking
improvements
- Fbdev now calls dedicated functions in the backlight subsystems to
notify them of blank state changes, instead of relying on fbdev
event notifiers
- For LCDs, fbdev also calls a dedicated function to notify of mode
changes
- Removed the definitions for the unused fbdev event constants
'FB_EVENT_MODE_CHANGE' and 'FB_EVENT_BLANK' from the header file

Backlight Subsystem:
- Implemented fbdev blank state tracking using the (newly enhanced)
blank state information provided directly by 'FB_EVENT_BLANK'
- Removed internal blank state tracking fields ('fb_bl_on') from
'struct backlight_device'
- Moved the handling of blank-state updates into a separate internal
helper function, 'backlight_notify_blank()'
- Removed support for fbdev events and replaced it with a dedicated
function call interface ('backlight_notify_blank()' and
'backlight_notify_blank_all()') for display drivers to update
backlight status

LCD Subsystem:
- Moved the handling of display updates (blank events and mode
changes) from fbdev event notifiers to separate internal helper
functions ('lcd_notify_blank',
'lcd_notify_mode_change')
- Removed support for fbdev events and replaced it with dedicated
function call interfaces ('lcd_notify_blank_all()',
'lcd_notify_mode_change_all()')
- The LCD subsystem now maintains its own internal list of LCD
devices instead of relying on fbdev notifiers

LED Backlight Trigger:
- Moved the handling of blank-state updates into a separate internal
helper, 'ledtrig_backlight_notify_blank()'
- Removed support for fbdev events and replaced it with a dedicated
function call, 'ledtrig_backlight_blank()', for fbdev to notify
trigger of blank state changes
- The LED backlight trigger now maintains its own internal list of
triggers instead of relying on fbdev notifiers

Qualcomm WLED Backlight:
- Added a NULL check after 'devm_kasprintf()' in 'wled_configure()'
to prevent a potential NULL pointer dereference if memory
allocation fails"

* tag 'backlight-next-6.16' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight:
backlight: pm8941: Add NULL check in wled_configure()
fbdev: Remove constants of unused events
leds: backlight trigger: Replace fb events with a dedicated function call
leds: backlight trigger: Move blank-state handling into helper
backlight: lcd: Replace fb events with a dedicated function call
backlight: lcd: Move event handling into helpers
backlight: Replace fb events with a dedicated function call
backlight: Move blank-state handling into helper
backlight: Implement fbdev tracking with blank state from event
fbdev: Send old blank state in FB_EVENT_BLANK
fbdev: Track display blanking state
fbdev: Rework fb_blank()

+222 -213
+24 -26
drivers/leds/trigger/ledtrig-backlight.c
··· 10 10 #include <linux/kernel.h> 11 11 #include <linux/slab.h> 12 12 #include <linux/init.h> 13 - #include <linux/fb.h> 14 13 #include <linux/leds.h> 15 14 #include "../leds.h" 16 15 ··· 20 21 struct led_classdev *led; 21 22 int brightness; 22 23 int old_status; 23 - struct notifier_block notifier; 24 24 unsigned invert; 25 + 26 + struct list_head entry; 25 27 }; 26 28 27 - static int fb_notifier_callback(struct notifier_block *p, 28 - unsigned long event, void *data) 29 + static DEFINE_MUTEX(ledtrig_backlight_list_mutex); 30 + static LIST_HEAD(ledtrig_backlight_list); 31 + 32 + static void ledtrig_backlight_notify_blank(struct bl_trig_notifier *n, int new_status) 29 33 { 30 - struct bl_trig_notifier *n = container_of(p, 31 - struct bl_trig_notifier, notifier); 32 34 struct led_classdev *led = n->led; 33 - struct fb_event *fb_event = data; 34 - int *blank; 35 - int new_status; 36 - 37 - /* If we aren't interested in this event, skip it immediately ... */ 38 - if (event != FB_EVENT_BLANK) 39 - return 0; 40 - 41 - blank = fb_event->data; 42 - new_status = *blank ? BLANK : UNBLANK; 43 35 44 36 if (new_status == n->old_status) 45 - return 0; 37 + return; 46 38 47 39 if ((n->old_status == UNBLANK) ^ n->invert) { 48 40 n->brightness = led->brightness; ··· 43 53 } 44 54 45 55 n->old_status = new_status; 46 - 47 - return 0; 48 56 } 57 + 58 + void ledtrig_backlight_blank(bool blank) 59 + { 60 + struct bl_trig_notifier *n; 61 + int new_status = blank ? BLANK : UNBLANK; 62 + 63 + guard(mutex)(&ledtrig_backlight_list_mutex); 64 + 65 + list_for_each_entry(n, &ledtrig_backlight_list, entry) 66 + ledtrig_backlight_notify_blank(n, new_status); 67 + } 68 + EXPORT_SYMBOL(ledtrig_backlight_blank); 49 69 50 70 static ssize_t bl_trig_invert_show(struct device *dev, 51 71 struct device_attribute *attr, char *buf) ··· 100 100 101 101 static int bl_trig_activate(struct led_classdev *led) 102 102 { 103 - int ret; 104 - 105 103 struct bl_trig_notifier *n; 106 104 107 105 n = kzalloc(sizeof(struct bl_trig_notifier), GFP_KERNEL); ··· 110 112 n->led = led; 111 113 n->brightness = led->brightness; 112 114 n->old_status = UNBLANK; 113 - n->notifier.notifier_call = fb_notifier_callback; 114 115 115 - ret = fb_register_client(&n->notifier); 116 - if (ret) 117 - dev_err(led->dev, "unable to register backlight trigger\n"); 116 + guard(mutex)(&ledtrig_backlight_list_mutex); 117 + list_add(&n->entry, &ledtrig_backlight_list); 118 118 119 119 return 0; 120 120 } ··· 121 125 { 122 126 struct bl_trig_notifier *n = led_get_trigger_data(led); 123 127 124 - fb_unregister_client(&n->notifier); 128 + guard(mutex)(&ledtrig_backlight_list_mutex); 129 + list_del(&n->entry); 130 + 125 131 kfree(n); 126 132 } 127 133
+19 -72
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 - /* 83 - * fb_notifier_callback 84 - * 85 - * This callback gets called when something important happens inside a 86 - * framebuffer driver. The backlight core only cares about FB_BLANK_UNBLANK 87 - * which is reported to the driver using backlight_update_status() 88 - * as a state change. 89 - * 90 - * There may be several fbdev's connected to the backlight device, 91 - * in which case they are kept track of. A state change is only reported 92 - * if there is a change in backlight for the specified fbdev. 93 - */ 94 - static int fb_notifier_callback(struct notifier_block *self, 95 - unsigned long event, void *data) 81 + void backlight_notify_blank(struct backlight_device *bd, struct device *display_dev, 82 + bool fb_on, bool prev_fb_on) 96 83 { 97 - struct backlight_device *bd; 98 - struct fb_event *evdata = data; 99 - struct fb_info *info = evdata->info; 100 - struct backlight_device *fb_bd = fb_bl_device(info); 101 - int node = info->node; 102 - int fb_blank = 0; 103 - 104 - /* If we aren't interested in this event, skip it immediately ... */ 105 - if (event != FB_EVENT_BLANK) 106 - return 0; 107 - 108 - bd = container_of(self, struct backlight_device, fb_notif); 109 - mutex_lock(&bd->ops_lock); 84 + guard(mutex)(&bd->ops_lock); 110 85 111 86 if (!bd->ops) 112 - goto out; 113 - if (bd->ops->controls_device && !bd->ops->controls_device(bd, info->device)) 114 - goto out; 115 - if (fb_bd && fb_bd != bd) 116 - goto out; 87 + return; 88 + if (bd->ops->controls_device && !bd->ops->controls_device(bd, display_dev)) 89 + return; 117 90 118 - fb_blank = *(int *)evdata->data; 119 - if (fb_blank == FB_BLANK_UNBLANK && !bd->fb_bl_on[node]) { 120 - bd->fb_bl_on[node] = true; 91 + if (fb_on && (!prev_fb_on || !bd->use_count)) { 121 92 if (!bd->use_count++) { 122 93 bd->props.state &= ~BL_CORE_FBBLANK; 123 94 backlight_update_status(bd); 124 95 } 125 - } else if (fb_blank != FB_BLANK_UNBLANK && bd->fb_bl_on[node]) { 126 - bd->fb_bl_on[node] = false; 96 + } else if (!fb_on && prev_fb_on && bd->use_count) { 127 97 if (!(--bd->use_count)) { 128 98 bd->props.state |= BL_CORE_FBBLANK; 129 99 backlight_update_status(bd); 130 100 } 131 101 } 132 - out: 133 - mutex_unlock(&bd->ops_lock); 134 - return 0; 135 102 } 103 + EXPORT_SYMBOL(backlight_notify_blank); 136 104 137 - static int backlight_register_fb(struct backlight_device *bd) 105 + void backlight_notify_blank_all(struct device *display_dev, bool fb_on, bool prev_fb_on) 138 106 { 139 - memset(&bd->fb_notif, 0, sizeof(bd->fb_notif)); 140 - bd->fb_notif.notifier_call = fb_notifier_callback; 107 + struct backlight_device *bd; 141 108 142 - return fb_register_client(&bd->fb_notif); 143 - } 109 + guard(mutex)(&backlight_dev_list_mutex); 144 110 145 - static void backlight_unregister_fb(struct backlight_device *bd) 146 - { 147 - fb_unregister_client(&bd->fb_notif); 111 + list_for_each_entry(bd, &backlight_dev_list, entry) 112 + backlight_notify_blank(bd, display_dev, fb_on, prev_fb_on); 148 113 } 149 - #else 150 - static inline int backlight_register_fb(struct backlight_device *bd) 151 - { 152 - return 0; 153 - } 154 - 155 - static inline void backlight_unregister_fb(struct backlight_device *bd) 156 - { 157 - } 158 - #endif /* CONFIG_FB_CORE */ 114 + EXPORT_SYMBOL(backlight_notify_blank_all); 159 115 160 116 static void backlight_generate_event(struct backlight_device *bd, 161 117 enum backlight_update_reason reason) ··· 401 447 return ERR_PTR(rc); 402 448 } 403 449 404 - rc = backlight_register_fb(new_bd); 405 - if (rc) { 406 - device_unregister(&new_bd->dev); 407 - return ERR_PTR(rc); 408 - } 409 - 410 450 new_bd->ops = ops; 411 451 412 452 #ifdef CONFIG_PMAC_BACKLIGHT ··· 487 539 bd->ops = NULL; 488 540 mutex_unlock(&bd->ops_lock); 489 541 490 - backlight_unregister_fb(bd); 491 542 device_unregister(&bd->dev); 492 543 } 493 544 EXPORT_SYMBOL(backlight_device_unregister);
+43 -71
drivers/video/backlight/lcd.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 - #if defined(CONFIG_FB) || (defined(CONFIG_FB_MODULE) && \ 22 - defined(CONFIG_LCD_CLASS_DEVICE_MODULE)) 23 - static int to_lcd_power(int fb_blank) 24 - { 25 - switch (fb_blank) { 26 - case FB_BLANK_UNBLANK: 27 - return LCD_POWER_ON; 28 - /* deprecated; TODO: should become 'off' */ 29 - case FB_BLANK_NORMAL: 30 - return LCD_POWER_REDUCED; 31 - case FB_BLANK_VSYNC_SUSPEND: 32 - return LCD_POWER_REDUCED_VSYNC_SUSPEND; 33 - /* 'off' */ 34 - case FB_BLANK_HSYNC_SUSPEND: 35 - case FB_BLANK_POWERDOWN: 36 - default: 37 - return LCD_POWER_OFF; 38 - } 39 - } 20 + static DEFINE_MUTEX(lcd_dev_list_mutex); 21 + static LIST_HEAD(lcd_dev_list); 40 22 41 - /* This callback gets called when something important happens inside a 42 - * framebuffer driver. We're looking if that important event is blanking, 43 - * and if it is, we're switching lcd power as well ... 44 - */ 45 - static int fb_notifier_callback(struct notifier_block *self, 46 - unsigned long event, void *data) 23 + static void lcd_notify_blank(struct lcd_device *ld, struct device *display_dev, 24 + int power) 47 25 { 48 - struct lcd_device *ld = container_of(self, struct lcd_device, fb_notif); 49 - struct fb_event *evdata = data; 50 - struct fb_info *info = evdata->info; 51 - struct lcd_device *fb_lcd = fb_lcd_device(info); 52 - 53 26 guard(mutex)(&ld->ops_lock); 54 27 55 - if (!ld->ops) 56 - return 0; 57 - if (ld->ops->controls_device && !ld->ops->controls_device(ld, info->device)) 58 - return 0; 59 - if (fb_lcd && fb_lcd != ld) 60 - return 0; 28 + if (!ld->ops || !ld->ops->set_power) 29 + return; 30 + if (ld->ops->controls_device && !ld->ops->controls_device(ld, display_dev)) 31 + return; 61 32 62 - if (event == FB_EVENT_BLANK) { 63 - int power = to_lcd_power(*(int *)evdata->data); 64 - 65 - if (ld->ops->set_power) 66 - ld->ops->set_power(ld, power); 67 - } else { 68 - const struct fb_videomode *videomode = evdata->data; 69 - 70 - if (ld->ops->set_mode) 71 - ld->ops->set_mode(ld, videomode->xres, videomode->yres); 72 - } 73 - 74 - return 0; 33 + ld->ops->set_power(ld, power); 75 34 } 76 35 77 - static int lcd_register_fb(struct lcd_device *ld) 36 + void lcd_notify_blank_all(struct device *display_dev, int power) 78 37 { 79 - memset(&ld->fb_notif, 0, sizeof(ld->fb_notif)); 80 - ld->fb_notif.notifier_call = fb_notifier_callback; 81 - return fb_register_client(&ld->fb_notif); 38 + struct lcd_device *ld; 39 + 40 + guard(mutex)(&lcd_dev_list_mutex); 41 + 42 + list_for_each_entry(ld, &lcd_dev_list, entry) 43 + lcd_notify_blank(ld, display_dev, power); 44 + } 45 + EXPORT_SYMBOL(lcd_notify_blank_all); 46 + 47 + static void lcd_notify_mode_change(struct lcd_device *ld, struct device *display_dev, 48 + unsigned int width, unsigned int height) 49 + { 50 + guard(mutex)(&ld->ops_lock); 51 + 52 + if (!ld->ops || !ld->ops->set_mode) 53 + return; 54 + if (ld->ops->controls_device && !ld->ops->controls_device(ld, display_dev)) 55 + return; 56 + 57 + ld->ops->set_mode(ld, width, height); 82 58 } 83 59 84 - static void lcd_unregister_fb(struct lcd_device *ld) 60 + void lcd_notify_mode_change_all(struct device *display_dev, 61 + unsigned int width, unsigned int height) 85 62 { 86 - fb_unregister_client(&ld->fb_notif); 87 - } 88 - #else 89 - static int lcd_register_fb(struct lcd_device *ld) 90 - { 91 - return 0; 92 - } 63 + struct lcd_device *ld; 93 64 94 - static inline void lcd_unregister_fb(struct lcd_device *ld) 95 - { 65 + guard(mutex)(&lcd_dev_list_mutex); 66 + 67 + list_for_each_entry(ld, &lcd_dev_list, entry) 68 + lcd_notify_mode_change(ld, display_dev, width, height); 96 69 } 97 - #endif /* CONFIG_FB */ 70 + EXPORT_SYMBOL(lcd_notify_mode_change_all); 98 71 99 72 static ssize_t lcd_power_show(struct device *dev, struct device_attribute *attr, 100 73 char *buf) ··· 218 245 return ERR_PTR(rc); 219 246 } 220 247 221 - rc = lcd_register_fb(new_ld); 222 - if (rc) { 223 - device_unregister(&new_ld->dev); 224 - return ERR_PTR(rc); 225 - } 248 + guard(mutex)(&lcd_dev_list_mutex); 249 + list_add(&new_ld->entry, &lcd_dev_list); 226 250 227 251 return new_ld; 228 252 } ··· 236 266 if (!ld) 237 267 return; 238 268 269 + guard(mutex)(&lcd_dev_list_mutex); 270 + list_del(&ld->entry); 271 + 239 272 mutex_lock(&ld->ops_lock); 240 273 ld->ops = NULL; 241 274 mutex_unlock(&ld->ops_lock); 242 - lcd_unregister_fb(ld); 243 275 244 276 device_unregister(&ld->dev); 245 277 }
+4 -2
drivers/video/backlight/qcom-wled.c
··· 1406 1406 wled->ctrl_addr = be32_to_cpu(*prop_addr); 1407 1407 1408 1408 rc = of_property_read_string(dev->of_node, "label", &wled->name); 1409 - if (rc) 1409 + if (rc) { 1410 1410 wled->name = devm_kasprintf(dev, GFP_KERNEL, "%pOFn", dev->of_node); 1411 - 1411 + if (!wled->name) 1412 + return -ENOMEM; 1413 + } 1412 1414 switch (wled->version) { 1413 1415 case 3: 1414 1416 u32_opts = wled3_opts;
+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
+1
drivers/video/fbdev/core/fb_info.c
··· 42 42 43 43 info->device = dev; 44 44 info->fbcon_rotate_hint = -1; 45 + info->blank = FB_BLANK_UNBLANK; 45 46 46 47 #if IS_ENABLED(CONFIG_FB_BACKLIGHT) 47 48 mutex_init(&info->bl_curve_mutex);
+68 -14
drivers/video/fbdev/core/fbmem.c
··· 15 15 #include <linux/export.h> 16 16 #include <linux/fb.h> 17 17 #include <linux/fbcon.h> 18 + #include <linux/lcd.h> 19 + #include <linux/leds.h> 18 20 19 21 #include <video/nomodeset.h> 20 22 ··· 222 220 return err; 223 221 } 224 222 223 + static void fb_lcd_notify_mode_change(struct fb_info *info, 224 + struct fb_videomode *mode) 225 + { 226 + lcd_notify_mode_change_all(info->device, mode->xres, mode->yres); 227 + } 228 + 225 229 int 226 230 fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) 227 231 { ··· 235 227 u32 activate; 236 228 struct fb_var_screeninfo old_var; 237 229 struct fb_videomode mode; 238 - struct fb_event event; 239 230 u32 unused; 240 231 241 232 if (var->activate & FB_ACTIVATE_INV_MODE) { ··· 340 333 return ret; 341 334 } 342 335 343 - event.info = info; 344 - event.data = &mode; 345 - fb_notifier_call_chain(FB_EVENT_MODE_CHANGE, &event); 336 + fb_lcd_notify_mode_change(info, &mode); 346 337 347 338 return 0; 348 339 } 349 340 EXPORT_SYMBOL(fb_set_var); 350 341 351 - int 352 - fb_blank(struct fb_info *info, int blank) 342 + static void fb_lcd_notify_blank(struct fb_info *info) 353 343 { 354 - struct fb_event event; 355 - int ret = -EINVAL; 344 + int power; 345 + 346 + switch (info->blank) { 347 + case FB_BLANK_UNBLANK: 348 + power = LCD_POWER_ON; 349 + break; 350 + /* deprecated; TODO: should become 'off' */ 351 + case FB_BLANK_NORMAL: 352 + power = LCD_POWER_REDUCED; 353 + break; 354 + case FB_BLANK_VSYNC_SUSPEND: 355 + power = LCD_POWER_REDUCED_VSYNC_SUSPEND; 356 + break; 357 + /* 'off' */ 358 + case FB_BLANK_HSYNC_SUSPEND: 359 + case FB_BLANK_POWERDOWN: 360 + default: 361 + power = LCD_POWER_OFF; 362 + break; 363 + } 364 + 365 + lcd_notify_blank_all(info->device, power); 366 + } 367 + 368 + static void fb_ledtrig_backlight_notify_blank(struct fb_info *info) 369 + { 370 + if (info->blank == FB_BLANK_UNBLANK) 371 + ledtrig_backlight_blank(false); 372 + else 373 + ledtrig_backlight_blank(true); 374 + } 375 + 376 + int fb_blank(struct fb_info *info, int blank) 377 + { 378 + int old_blank = info->blank; 379 + int ret; 380 + 381 + if (!info->fbops->fb_blank) 382 + return -EINVAL; 356 383 357 384 if (blank > FB_BLANK_POWERDOWN) 358 385 blank = FB_BLANK_POWERDOWN; 359 386 360 - event.info = info; 361 - event.data = &blank; 387 + info->blank = blank; 362 388 363 - if (info->fbops->fb_blank) 364 - ret = info->fbops->fb_blank(blank, info); 389 + ret = info->fbops->fb_blank(blank, info); 390 + if (ret) 391 + goto err; 365 392 366 - if (!ret) 367 - fb_notifier_call_chain(FB_EVENT_BLANK, &event); 393 + fb_bl_notify_blank(info, old_blank); 394 + fb_lcd_notify_blank(info); 395 + fb_ledtrig_backlight_notify_blank(info); 368 396 397 + return 0; 398 + 399 + err: 400 + info->blank = old_blank; 369 401 return ret; 370 402 } 371 403 EXPORT_SYMBOL(fb_blank); ··· 461 415 refcount_set(&fb_info->count, 1); 462 416 mutex_init(&fb_info->lock); 463 417 mutex_init(&fb_info->mm_lock); 418 + 419 + /* 420 + * With an fb_blank callback present, we assume that the 421 + * display is blank, so that fb_blank() enables it on the 422 + * first modeset. 423 + */ 424 + if (fb_info->fbops->fb_blank) 425 + fb_info->blank = FB_BLANK_POWERDOWN; 464 426 465 427 fb_device_create(fb_info); 466 428
+4 -4
drivers/video/fbdev/core/fbsysfs.c
··· 242 242 return count; 243 243 } 244 244 245 - static ssize_t show_blank(struct device *device, 246 - struct device_attribute *attr, char *buf) 245 + static ssize_t show_blank(struct device *device, struct device_attribute *attr, char *buf) 247 246 { 248 - // struct fb_info *fb_info = dev_get_drvdata(device); 249 - return 0; 247 + struct fb_info *fb_info = dev_get_drvdata(device); 248 + 249 + return sysfs_emit(buf, "%d\n", fb_info->blank); 250 250 } 251 251 252 252 static ssize_t store_console(struct device *device,
+17 -15
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; ··· 288 294 struct device dev; 289 295 290 296 /** 291 - * @fb_bl_on: The state of individual fbdev's. 292 - * 293 - * Multiple fbdev's may share one backlight device. The fb_bl_on 294 - * records the state of the individual fbdev. 295 - */ 296 - bool fb_bl_on[FB_MAX]; 297 - 298 - /** 299 - * @use_count: The number of uses of fb_bl_on. 297 + * @use_count: The number of unblanked displays. 300 298 */ 301 299 int use_count; 302 300 }; ··· 393 407 struct backlight_device *backlight_device_get_by_type(enum backlight_type type); 394 408 int backlight_device_set_brightness(struct backlight_device *bd, 395 409 unsigned long brightness); 410 + 411 + #if IS_REACHABLE(CONFIG_BACKLIGHT_CLASS_DEVICE) 412 + void backlight_notify_blank(struct backlight_device *bd, 413 + struct device *display_dev, 414 + bool fb_on, bool prev_fb_on); 415 + void backlight_notify_blank_all(struct device *display_dev, 416 + bool fb_on, bool prev_fb_on); 417 + #else 418 + static inline void backlight_notify_blank(struct backlight_device *bd, 419 + struct device *display_dev, 420 + bool fb_on, bool prev_fb_on) 421 + { } 422 + static inline void backlight_notify_blank_all(struct device *display_dev, 423 + bool fb_on, bool prev_fb_on) 424 + { } 425 + #endif 396 426 397 427 #define to_backlight_device(obj) container_of(obj, struct backlight_device, dev) 398 428
+6 -6
include/linux/fb.h
··· 129 129 * Register/unregister for framebuffer events 130 130 */ 131 131 132 - /* The resolution of the passed in fb_info about to change */ 133 - #define FB_EVENT_MODE_CHANGE 0x01 134 - 135 132 #ifdef CONFIG_GUMSTIX_AM200EPD 136 133 /* only used by mach-pxa/am200epd.c */ 137 134 #define FB_EVENT_FB_REGISTERED 0x05 138 135 #define FB_EVENT_FB_UNREGISTERED 0x06 139 136 #endif 140 - 141 - /* A display blank is requested */ 142 - #define FB_EVENT_BLANK 0x09 143 137 144 138 struct fb_event { 145 139 struct fb_info *info; ··· 466 472 struct list_head modelist; /* mode list */ 467 473 struct fb_videomode *mode; /* current mode */ 468 474 475 + int blank; /* current blanking; see FB_BLANK_ constants */ 476 + 469 477 #if IS_ENABLED(CONFIG_FB_BACKLIGHT) 470 478 /* assigned backlight device */ 471 479 /* set before framebuffer registration, ··· 752 756 753 757 #if IS_ENABLED(CONFIG_FB_BACKLIGHT) 754 758 struct backlight_device *fb_bl_device(struct fb_info *info); 759 + void fb_bl_notify_blank(struct fb_info *info, int old_blank); 755 760 #else 756 761 static inline struct backlight_device *fb_bl_device(struct fb_info *info) 757 762 { 758 763 return NULL; 759 764 } 765 + 766 + static inline void fb_bl_notify_blank(struct fb_info *info, int old_blank) 767 + { } 760 768 #endif 761 769 762 770 static inline struct lcd_device *fb_lcd_device(struct fb_info *info)
+18 -3
include/linux/lcd.h
··· 11 11 12 12 #include <linux/device.h> 13 13 #include <linux/mutex.h> 14 - #include <linux/notifier.h> 15 14 16 15 #define LCD_POWER_ON (0) 17 16 #define LCD_POWER_REDUCED (1) // deprecated; don't use in new code ··· 78 79 const struct lcd_ops *ops; 79 80 /* Serialise access to set_power method */ 80 81 struct mutex update_lock; 81 - /* The framebuffer notifier block */ 82 - struct notifier_block fb_notif; 82 + 83 + /** 84 + * @entry: List entry of all registered lcd devices 85 + */ 86 + struct list_head entry; 83 87 84 88 struct device dev; 85 89 }; ··· 126 124 extern void lcd_device_unregister(struct lcd_device *ld); 127 125 extern void devm_lcd_device_unregister(struct device *dev, 128 126 struct lcd_device *ld); 127 + 128 + #if IS_REACHABLE(CONFIG_LCD_CLASS_DEVICE) 129 + void lcd_notify_blank_all(struct device *display_dev, int power); 130 + void lcd_notify_mode_change_all(struct device *display_dev, 131 + unsigned int width, unsigned int height); 132 + #else 133 + static inline void lcd_notify_blank_all(struct device *display_dev, int power) 134 + {} 135 + 136 + static inline void lcd_notify_mode_change_all(struct device *display_dev, 137 + unsigned int width, unsigned int height) 138 + {} 139 + #endif 129 140 130 141 #define to_lcd_device(obj) container_of(obj, struct lcd_device, dev) 131 142
+6
include/linux/leds.h
··· 640 640 static inline void ledtrig_torch_ctrl(bool on) {} 641 641 #endif 642 642 643 + #if IS_REACHABLE(CONFIG_LEDS_TRIGGER_BACKLIGHT) 644 + void ledtrig_backlight_blank(bool blank); 645 + #else 646 + static inline void ledtrig_backlight_blank(bool blank) {} 647 + #endif 648 + 643 649 /* 644 650 * Generic LED platform data for describing LED names and default triggers. 645 651 */