Commit dc2139c0 authored by Thomas Zimmermann's avatar Thomas Zimmermann Committed by Lee Jones
Browse files

leds: backlight trigger: Replace fb events with a dedicated function call



Remove support for fb events from the led backlight trigger. Provide
the helper ledtrig_backlight_blank() instead. Call it from fbdev to
inform the trigger of changes to a display's blank state.

Fbdev maintains a list of all installed notifiers. Instead of the fbdev
notifiers, maintain an internal list of led backlight triggers.

v3:
- export ledtrig_backlight_blank()
v2:
- maintain global list of led backlight triggers (Lee)
- avoid IS_REACHABLE() in source file (Lee)
- notify on changes to blank state instead of display state
- use lock guards
- initialize led list and list mutex

Signed-off-by: default avatarThomas Zimmermann <tzimmermann@suse.de>
Acked-by: default avatarSimona Vetter <simona.vetter@ffwll.ch>
Link: https://lore.kernel.org/r/20250321095517.313713-11-tzimmermann@suse.de


Signed-off-by: default avatarLee Jones <lee@kernel.org>
parent 28f8bab7
Loading
Loading
Loading
Loading
+17 −25
Original line number Diff line number Diff line
@@ -10,7 +10,6 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/fb.h>
#include <linux/leds.h>
#include "../leds.h"

@@ -21,10 +20,14 @@ struct bl_trig_notifier {
	struct led_classdev *led;
	int brightness;
	int old_status;
	struct notifier_block notifier;
	unsigned invert;

	struct list_head entry;
};

static DEFINE_MUTEX(ledtrig_backlight_list_mutex);
static LIST_HEAD(ledtrig_backlight_list);

static void ledtrig_backlight_notify_blank(struct bl_trig_notifier *n, int new_status)
{
	struct led_classdev *led = n->led;
@@ -42,26 +45,17 @@ static void ledtrig_backlight_notify_blank(struct bl_trig_notifier *n, int new_s
	n->old_status = new_status;
}

static int fb_notifier_callback(struct notifier_block *p,
				unsigned long event, void *data)
void ledtrig_backlight_blank(bool blank)
{
	struct bl_trig_notifier *n = container_of(p,
					struct bl_trig_notifier, notifier);
	struct fb_event *fb_event = data;
	int *blank;
	int new_status;

	/* If we aren't interested in this event, skip it immediately ... */
	if (event != FB_EVENT_BLANK)
		return 0;
	struct bl_trig_notifier *n;
	int new_status = blank ? BLANK : UNBLANK;

	blank = fb_event->data;
	new_status = *blank ? BLANK : UNBLANK;
	guard(mutex)(&ledtrig_backlight_list_mutex);

	list_for_each_entry(n, &ledtrig_backlight_list, entry)
		ledtrig_backlight_notify_blank(n, new_status);

	return 0;
}
EXPORT_SYMBOL(ledtrig_backlight_blank);

static ssize_t bl_trig_invert_show(struct device *dev,
		struct device_attribute *attr, char *buf)
@@ -106,8 +100,6 @@ ATTRIBUTE_GROUPS(bl_trig);

static int bl_trig_activate(struct led_classdev *led)
{
	int ret;

	struct bl_trig_notifier *n;

	n = kzalloc(sizeof(struct bl_trig_notifier), GFP_KERNEL);
@@ -118,11 +110,9 @@ static int bl_trig_activate(struct led_classdev *led)
	n->led = led;
	n->brightness = led->brightness;
	n->old_status = UNBLANK;
	n->notifier.notifier_call = fb_notifier_callback;

	ret = fb_register_client(&n->notifier);
	if (ret)
		dev_err(led->dev, "unable to register backlight trigger\n");
	guard(mutex)(&ledtrig_backlight_list_mutex);
	list_add(&n->entry, &ledtrig_backlight_list);

	return 0;
}
@@ -131,7 +121,9 @@ static void bl_trig_deactivate(struct led_classdev *led)
{
	struct bl_trig_notifier *n = led_get_trigger_data(led);

	fb_unregister_client(&n->notifier);
	guard(mutex)(&ledtrig_backlight_list_mutex);
	list_del(&n->entry);

	kfree(n);
}

+10 −9
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <linux/fb.h>
#include <linux/fbcon.h>
#include <linux/lcd.h>
#include <linux/leds.h>

#include <video/nomodeset.h>

@@ -369,11 +370,17 @@ static void fb_lcd_notify_blank(struct fb_info *info)
	lcd_notify_blank_all(info->device, power);
}

static void fb_ledtrig_backlight_notify_blank(struct fb_info *info)
{
	if (info->blank == FB_BLANK_UNBLANK)
		ledtrig_backlight_blank(false);
	else
		ledtrig_backlight_blank(true);
}

int fb_blank(struct fb_info *info, int blank)
{
	int old_blank = info->blank;
	struct fb_event event;
	int data[2];
	int ret;

	if (!info->fbops->fb_blank)
@@ -382,11 +389,6 @@ int fb_blank(struct fb_info *info, int blank)
	if (blank > FB_BLANK_POWERDOWN)
		blank = FB_BLANK_POWERDOWN;

	data[0] = blank;
	data[1] = old_blank;
	event.info = info;
	event.data = data;

	info->blank = blank;

	ret = info->fbops->fb_blank(blank, info);
@@ -395,8 +397,7 @@ int fb_blank(struct fb_info *info, int blank)

	fb_bl_notify_blank(info, old_blank);
	fb_lcd_notify_blank(info);

	fb_notifier_call_chain(FB_EVENT_BLANK, &event);
	fb_ledtrig_backlight_notify_blank(info);

	return 0;

+6 −0
Original line number Diff line number Diff line
@@ -640,6 +640,12 @@ static inline void ledtrig_flash_ctrl(bool on) {}
static inline void ledtrig_torch_ctrl(bool on) {}
#endif

#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_BACKLIGHT)
void ledtrig_backlight_blank(bool blank);
#else
static inline void ledtrig_backlight_blank(bool blank) {}
#endif

/*
 * Generic LED platform data for describing LED names and default triggers.
 */