diff options
Diffstat (limited to 'drivers/leds/trigger/ledtrig-backlight.c')
| -rw-r--r-- | drivers/leds/trigger/ledtrig-backlight.c | 132 |
1 files changed, 53 insertions, 79 deletions
diff --git a/drivers/leds/trigger/ledtrig-backlight.c b/drivers/leds/trigger/ledtrig-backlight.c index 3c9c88a07eb8..c1f0f5becaee 100644 --- a/drivers/leds/trigger/ledtrig-backlight.c +++ b/drivers/leds/trigger/ledtrig-backlight.c @@ -1,20 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Backlight emulation LED trigger * * Copyright 2008 (C) Rodolfo Giometti <giometti@linux.it> * Copyright 2008 (C) Eurotech S.p.A. <info@eurotech.it> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/init.h> -#include <linux/fb.h> #include <linux/leds.h> #include "../leds.h" @@ -25,45 +20,47 @@ struct bl_trig_notifier { struct led_classdev *led; int brightness; int old_status; - struct notifier_block notifier; unsigned invert; + + struct list_head entry; }; -static int fb_notifier_callback(struct notifier_block *p, - unsigned long event, void *data) +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 bl_trig_notifier *n = container_of(p, - struct bl_trig_notifier, notifier); struct led_classdev *led = n->led; - struct fb_event *fb_event = data; - int *blank = fb_event->data; - int new_status = *blank ? BLANK : UNBLANK; - switch (event) { - case FB_EVENT_BLANK: - if (new_status == n->old_status) - break; + if (new_status == n->old_status) + return; - if ((n->old_status == UNBLANK) ^ n->invert) { - n->brightness = led->brightness; - __led_set_brightness(led, LED_OFF); - } else { - __led_set_brightness(led, n->brightness); - } + if ((n->old_status == UNBLANK) ^ n->invert) { + n->brightness = led->brightness; + led_set_brightness_nosleep(led, LED_OFF); + } else { + led_set_brightness_nosleep(led, n->brightness); + } - n->old_status = new_status; + n->old_status = new_status; +} - break; - } +void ledtrig_backlight_blank(bool blank) +{ + struct bl_trig_notifier *n; + int new_status = blank ? BLANK : UNBLANK; - return 0; + guard(mutex)(&ledtrig_backlight_list_mutex); + + list_for_each_entry(n, &ledtrig_backlight_list, entry) + ledtrig_backlight_notify_blank(n, new_status); } +EXPORT_SYMBOL(ledtrig_backlight_blank); static ssize_t bl_trig_invert_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct led_classdev *led = dev_get_drvdata(dev); - struct bl_trig_notifier *n = led->trigger_data; + struct bl_trig_notifier *n = led_trigger_get_drvdata(dev); return sprintf(buf, "%u\n", n->invert); } @@ -71,8 +68,8 @@ static ssize_t bl_trig_invert_show(struct device *dev, static ssize_t bl_trig_invert_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t num) { - struct led_classdev *led = dev_get_drvdata(dev); - struct bl_trig_notifier *n = led->trigger_data; + struct led_classdev *led = led_trigger_get_led(dev); + struct bl_trig_notifier *n = led_trigger_get_drvdata(dev); unsigned long invert; int ret; @@ -87,79 +84,56 @@ static ssize_t bl_trig_invert_store(struct device *dev, /* After inverting, we need to update the LED. */ if ((n->old_status == BLANK) ^ n->invert) - __led_set_brightness(led, LED_OFF); + led_set_brightness_nosleep(led, LED_OFF); else - __led_set_brightness(led, n->brightness); + led_set_brightness_nosleep(led, n->brightness); return num; } static DEVICE_ATTR(inverted, 0644, bl_trig_invert_show, bl_trig_invert_store); -static void bl_trig_activate(struct led_classdev *led) -{ - int ret; +static struct attribute *bl_trig_attrs[] = { + &dev_attr_inverted.attr, + NULL, +}; +ATTRIBUTE_GROUPS(bl_trig); +static int bl_trig_activate(struct led_classdev *led) +{ struct bl_trig_notifier *n; n = kzalloc(sizeof(struct bl_trig_notifier), GFP_KERNEL); - led->trigger_data = n; - if (!n) { - dev_err(led->dev, "unable to allocate backlight trigger\n"); - return; - } - - ret = device_create_file(led->dev, &dev_attr_inverted); - if (ret) - goto err_invert; + if (!n) + return -ENOMEM; + led_set_trigger_data(led, n); 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"); - led->activated = true; + guard(mutex)(&ledtrig_backlight_list_mutex); + list_add(&n->entry, &ledtrig_backlight_list); - return; - -err_invert: - led->trigger_data = NULL; - kfree(n); + return 0; } static void bl_trig_deactivate(struct led_classdev *led) { - struct bl_trig_notifier *n = - (struct bl_trig_notifier *) led->trigger_data; - - if (led->activated) { - device_remove_file(led->dev, &dev_attr_inverted); - fb_unregister_client(&n->notifier); - kfree(n); - led->activated = false; - } + struct bl_trig_notifier *n = led_get_trigger_data(led); + + guard(mutex)(&ledtrig_backlight_list_mutex); + list_del(&n->entry); + + kfree(n); } static struct led_trigger bl_led_trigger = { .name = "backlight", .activate = bl_trig_activate, - .deactivate = bl_trig_deactivate + .deactivate = bl_trig_deactivate, + .groups = bl_trig_groups, }; - -static int __init bl_trig_init(void) -{ - return led_trigger_register(&bl_led_trigger); -} - -static void __exit bl_trig_exit(void) -{ - led_trigger_unregister(&bl_led_trigger); -} - -module_init(bl_trig_init); -module_exit(bl_trig_exit); +module_led_trigger(bl_led_trigger); MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); MODULE_DESCRIPTION("Backlight emulation LED trigger"); |
