Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.o-hand.com/linux-rpurdie-leds
Browse files Browse the repository at this point in the history
* 'for-linus' of git://git.o-hand.com/linux-rpurdie-leds:
  leds: Add default-on trigger
  leds: Document the context brightness_set needs
  leds: Add new driver for the LEDs on the Freecom FSG-3
  leds: Add support to leds with readable status
  leds: enable support for blink_set() platform hook in leds-gpio
  leds: Cleanup various whitespace and code style issues
  leds: disable triggers on brightness set
  leds: Add mail LED support for "Clevo D400P"
  • Loading branch information
Linus Torvalds committed Apr 25, 2008
2 parents bf16ae2 + 060856c commit eb855fd
Show file tree
Hide file tree
Showing 21 changed files with 536 additions and 126 deletions.
12 changes: 9 additions & 3 deletions Documentation/leds-class.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ optimises away.

Complex triggers whilst available to all LEDs have LED specific
parameters and work on a per LED basis. The timer trigger is an example.
The timer trigger will periodically change the LED brightness between
LED_OFF and the current brightness setting. The "on" and "off" time can
be specified via /sys/class/leds/<device>/delay_{on,off} in milliseconds.
You can change the brightness value of a LED independently of the timer
trigger. However, if you set the brightness value to LED_OFF it will
also disable the timer trigger.

You can change triggers in a similar manner to the way an IO scheduler
is chosen (via /sys/class/leds/<device>/trigger). Trigger specific
Expand Down Expand Up @@ -63,9 +69,9 @@ value if it is called with *delay_on==0 && *delay_off==0 parameters. In
this case the driver should give back the chosen value through delay_on
and delay_off parameters to the leds subsystem.

Any call to the brightness_set() callback function should cancel the
previously programmed hardware blinking function so setting the brightness
to 0 can also cancel the blinking of the LED.
Setting the brightness to zero with brightness_set() callback function
should completely turn off the LED and cancel the previously programmed
hardware blinking function, if any.


Known Issues
Expand Down
17 changes: 17 additions & 0 deletions drivers/leds/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ config LEDS_NET48XX
This option enables support for the Soekris net4801 and net4826 error
LED.

config LEDS_FSG
tristate "LED Support for the Freecom FSG-3"
depends on LEDS_CLASS && MACH_FSG
help
This option enables support for the LEDs on the Freecom FSG-3.

config LEDS_WRAP
tristate "LED Support for the WRAP series LEDs"
depends on LEDS_CLASS && SCx200_GPIO
Expand Down Expand Up @@ -127,13 +133,17 @@ config LEDS_CLEVO_MAIL

This module can drive the mail LED for the following notebooks:

Clevo D400P
Clevo D410J
Clevo D410V
Clevo D400V/D470V (not tested, but might work)
Clevo M540N
Clevo M5x0N (not tested, but might work)
Positivo Mobile (Clevo M5x0V)

If your model is not listed here you can try the "nodetect"
module paramter.

To compile this driver as a module, choose M here: the
module will be called leds-clevo-mail.

Expand Down Expand Up @@ -173,4 +183,11 @@ config LEDS_TRIGGER_HEARTBEAT
load average.
If unsure, say Y.

config LEDS_TRIGGER_DEFAULT_ON
tristate "LED Default ON Trigger"
depends on LEDS_TRIGGERS
help
This allows LEDs to be initialised in the ON state.
If unsure, say Y.

endif # NEW_LEDS
2 changes: 2 additions & 0 deletions drivers/leds/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o
obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
obj-$(CONFIG_LEDS_FSG) += leds-fsg.o

# LED Triggers
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o
obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o
obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
12 changes: 12 additions & 0 deletions drivers/leds/led-class.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,20 @@

static struct class *leds_class;

static void led_update_brightness(struct led_classdev *led_cdev)
{
if (led_cdev->brightness_get)
led_cdev->brightness = led_cdev->brightness_get(led_cdev);
}

static ssize_t led_brightness_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct led_classdev *led_cdev = dev_get_drvdata(dev);
ssize_t ret = 0;

/* no lock needed for this */
led_update_brightness(led_cdev);
sprintf(buf, "%u\n", led_cdev->brightness);
ret = strlen(buf) + 1;

Expand All @@ -51,6 +58,9 @@ static ssize_t led_brightness_store(struct device *dev,

if (count == size) {
ret = count;

if (state == LED_OFF)
led_trigger_remove(led_cdev);
led_set_brightness(led_cdev, state);
}

Expand Down Expand Up @@ -110,6 +120,8 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
list_add_tail(&led_cdev->node, &leds_list);
up_write(&leds_list_lock);

led_update_brightness(led_cdev);

#ifdef CONFIG_LEDS_TRIGGERS
init_rwsem(&led_cdev->trigger_lock);

Expand Down
4 changes: 2 additions & 2 deletions drivers/leds/led-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include "leds.h"

DECLARE_RWSEM(leds_list_lock);
LIST_HEAD(leds_list);
EXPORT_SYMBOL_GPL(leds_list_lock);

LIST_HEAD(leds_list);
EXPORT_SYMBOL_GPL(leds_list);
EXPORT_SYMBOL_GPL(leds_list_lock);
120 changes: 63 additions & 57 deletions drivers/leds/led-triggers.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
static DECLARE_RWSEM(triggers_list_lock);
static LIST_HEAD(trigger_list);

/* Used by LED Class */

ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
Expand All @@ -45,9 +47,7 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,
trigger_name[len - 1] = '\0';

if (!strcmp(trigger_name, "none")) {
down_write(&led_cdev->trigger_lock);
led_trigger_set(led_cdev, NULL);
up_write(&led_cdev->trigger_lock);
led_trigger_remove(led_cdev);
return count;
}

Expand All @@ -66,7 +66,7 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr,

return -EINVAL;
}

EXPORT_SYMBOL_GPL(led_trigger_store);

ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr,
char *buf)
Expand Down Expand Up @@ -96,24 +96,7 @@ ssize_t led_trigger_show(struct device *dev, struct device_attribute *attr,
len += sprintf(len+buf, "\n");
return len;
}

void led_trigger_event(struct led_trigger *trigger,
enum led_brightness brightness)
{
struct list_head *entry;

if (!trigger)
return;

read_lock(&trigger->leddev_list_lock);
list_for_each(entry, &trigger->led_cdevs) {
struct led_classdev *led_cdev;

led_cdev = list_entry(entry, struct led_classdev, trig_list);
led_set_brightness(led_cdev, brightness);
}
read_unlock(&trigger->leddev_list_lock);
}
EXPORT_SYMBOL_GPL(led_trigger_show);

/* Caller must ensure led_cdev->trigger_lock held */
void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
Expand All @@ -124,7 +107,8 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
if (led_cdev->trigger) {
write_lock_irqsave(&led_cdev->trigger->leddev_list_lock, flags);
list_del(&led_cdev->trig_list);
write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, flags);
write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock,
flags);
if (led_cdev->trigger->deactivate)
led_cdev->trigger->deactivate(led_cdev);
led_set_brightness(led_cdev, LED_OFF);
Expand All @@ -138,6 +122,15 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
}
led_cdev->trigger = trigger;
}
EXPORT_SYMBOL_GPL(led_trigger_set);

void led_trigger_remove(struct led_classdev *led_cdev)
{
down_write(&led_cdev->trigger_lock);
led_trigger_set(led_cdev, NULL);
up_write(&led_cdev->trigger_lock);
}
EXPORT_SYMBOL_GPL(led_trigger_remove);

void led_trigger_set_default(struct led_classdev *led_cdev)
{
Expand All @@ -155,6 +148,9 @@ void led_trigger_set_default(struct led_classdev *led_cdev)
up_write(&led_cdev->trigger_lock);
up_read(&triggers_list_lock);
}
EXPORT_SYMBOL_GPL(led_trigger_set_default);

/* LED Trigger Interface */

int led_trigger_register(struct led_trigger *trigger)
{
Expand All @@ -181,26 +177,7 @@ int led_trigger_register(struct led_trigger *trigger)

return 0;
}

void led_trigger_register_simple(const char *name, struct led_trigger **tp)
{
struct led_trigger *trigger;
int err;

trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);

if (trigger) {
trigger->name = name;
err = led_trigger_register(trigger);
if (err < 0)
printk(KERN_WARNING "LED trigger %s failed to register"
" (%d)\n", name, err);
} else
printk(KERN_WARNING "LED trigger %s failed to register"
" (no memory)\n", name);

*tp = trigger;
}
EXPORT_SYMBOL_GPL(led_trigger_register);

void led_trigger_unregister(struct led_trigger *trigger)
{
Expand All @@ -221,28 +198,57 @@ void led_trigger_unregister(struct led_trigger *trigger)
}
up_read(&leds_list_lock);
}
EXPORT_SYMBOL_GPL(led_trigger_unregister);

/* Simple LED Tigger Interface */

void led_trigger_event(struct led_trigger *trigger,
enum led_brightness brightness)
{
struct list_head *entry;

if (!trigger)
return;

read_lock(&trigger->leddev_list_lock);
list_for_each(entry, &trigger->led_cdevs) {
struct led_classdev *led_cdev;

led_cdev = list_entry(entry, struct led_classdev, trig_list);
led_set_brightness(led_cdev, brightness);
}
read_unlock(&trigger->leddev_list_lock);
}
EXPORT_SYMBOL_GPL(led_trigger_event);

void led_trigger_register_simple(const char *name, struct led_trigger **tp)
{
struct led_trigger *trigger;
int err;

trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);

if (trigger) {
trigger->name = name;
err = led_trigger_register(trigger);
if (err < 0)
printk(KERN_WARNING "LED trigger %s failed to register"
" (%d)\n", name, err);
} else
printk(KERN_WARNING "LED trigger %s failed to register"
" (no memory)\n", name);

*tp = trigger;
}
EXPORT_SYMBOL_GPL(led_trigger_register_simple);

void led_trigger_unregister_simple(struct led_trigger *trigger)
{
if (trigger)
led_trigger_unregister(trigger);
kfree(trigger);
}

/* Used by LED Class */
EXPORT_SYMBOL_GPL(led_trigger_set);
EXPORT_SYMBOL_GPL(led_trigger_set_default);
EXPORT_SYMBOL_GPL(led_trigger_show);
EXPORT_SYMBOL_GPL(led_trigger_store);

/* LED Trigger Interface */
EXPORT_SYMBOL_GPL(led_trigger_register);
EXPORT_SYMBOL_GPL(led_trigger_unregister);

/* Simple LED Tigger Interface */
EXPORT_SYMBOL_GPL(led_trigger_register_simple);
EXPORT_SYMBOL_GPL(led_trigger_unregister_simple);
EXPORT_SYMBOL_GPL(led_trigger_event);

MODULE_AUTHOR("Richard Purdie");
MODULE_LICENSE("GPL");
Expand Down
16 changes: 13 additions & 3 deletions drivers/leds/leds-clevo-mail.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#define CLEVO_MAIL_LED_BLINK_1HZ 0x008A
#define CLEVO_MAIL_LED_BLINK_0_5HZ 0x0083

MODULE_AUTHOR("Márton Németh <nm127@freemail.hu>");
MODULE_AUTHOR("Márton Németh <nm127@freemail.hu>");
MODULE_DESCRIPTION("Clevo mail LED driver");
MODULE_LICENSE("GPL");

Expand Down Expand Up @@ -67,6 +67,16 @@ static struct dmi_system_id __initdata mail_led_whitelist[] = {
DMI_MATCH(DMI_PRODUCT_VERSION, "VT6198")
}
},
{
.callback = clevo_mail_led_dmi_callback,
.ident = "Clevo D400P",
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Clevo"),
DMI_MATCH(DMI_BOARD_NAME, "D400P"),
DMI_MATCH(DMI_BOARD_VERSION, "Rev.A"),
DMI_MATCH(DMI_PRODUCT_VERSION, "0106")
}
},
{
.callback = clevo_mail_led_dmi_callback,
.ident = "Clevo D410V",
Expand All @@ -93,8 +103,8 @@ static void clevo_mail_led_set(struct led_classdev *led_cdev,
}

static int clevo_mail_led_blink(struct led_classdev *led_cdev,
unsigned long* delay_on,
unsigned long* delay_off)
unsigned long *delay_on,
unsigned long *delay_off)
{
int status = -EINVAL;

Expand Down
2 changes: 1 addition & 1 deletion drivers/leds/leds-cobalt-qube.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ static void __iomem *led_port;
static u8 led_value;

static void qube_front_led_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
enum led_brightness brightness)
{
if (brightness)
led_value = LED_FRONT_LEFT | LED_FRONT_RIGHT;
Expand Down
6 changes: 3 additions & 3 deletions drivers/leds/leds-cobalt-raq.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/init.h>
#include <linux/io.h>
Expand All @@ -33,7 +33,7 @@ static u8 led_value;
static DEFINE_SPINLOCK(led_value_lock);

static void raq_web_led_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
enum led_brightness brightness)
{
unsigned long flags;

Expand All @@ -54,7 +54,7 @@ static struct led_classdev raq_web_led = {
};

static void raq_power_off_led_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
enum led_brightness brightness)
{
unsigned long flags;

Expand Down
Loading

0 comments on commit eb855fd

Please sign in to comment.