Creation of Cybook 2416 (actually Gen4) repository

This commit is contained in:
mlt
2009-12-18 17:10:00 +00:00
committed by godzil
commit 76f20f4d40
13791 changed files with 6812321 additions and 0 deletions

131
drivers/leds/Kconfig Normal file
View File

@@ -0,0 +1,131 @@
menu "LED devices"
config NEW_LEDS
bool "LED Support"
help
Say Y to enable Linux LED support. This allows control of supported
LEDs from both userspace and optionally, by kernel events (triggers).
This is not related to standard keyboard LEDs which are controlled
via the input system.
config LEDS_CLASS
tristate "LED Class Support"
depends on NEW_LEDS
help
This option enables the led sysfs class in /sys/class/leds. You'll
need this to do anything useful with LEDs. If unsure, say N.
comment "LED drivers"
config LEDS_CORGI
tristate "LED Support for the Sharp SL-C7x0 series"
depends on LEDS_CLASS && PXA_SHARP_C7xx
help
This option enables support for the LEDs on Sharp Zaurus
SL-C7x0 series (C700, C750, C760, C860).
config LEDS_LOCOMO
tristate "LED Support for Locomo device"
depends on LEDS_CLASS && SHARP_LOCOMO
help
This option enables support for the LEDs on Sharp Locomo.
Zaurus models SL-5500 and SL-5600.
config LEDS_SPITZ
tristate "LED Support for the Sharp SL-Cxx00 series"
depends on LEDS_CLASS && PXA_SHARP_Cxx00
help
This option enables support for the LEDs on Sharp Zaurus
SL-Cxx00 series (C1000, C3000, C3100).
config LEDS_IXP4XX
tristate "LED Support for GPIO connected LEDs on IXP4XX processors"
depends on LEDS_CLASS && ARCH_IXP4XX
help
This option enables support for the LEDs connected to GPIO
outputs of the Intel IXP4XX processors. To be useful the
particular board must have LEDs and they must be connected
to the GPIO lines. If unsure, say Y.
config LEDS_TOSA
tristate "LED Support for the Sharp SL-6000 series"
depends on LEDS_CLASS && PXA_SHARPSL
help
This option enables support for the LEDs on Sharp Zaurus
SL-6000 series.
config LEDS_S3C24XX
tristate "LED Support for Samsung S3C24XX GPIO LEDs"
depends on LEDS_CLASS && ARCH_S3C2410
help
This option enables support for LEDs connected to GPIO lines
on Samsung S3C24XX series CPUs, such as the S3C2410 and S3C2440.
config LEDS_AMS_DELTA
tristate "LED Support for the Amstrad Delta (E3)"
depends on LEDS_CLASS && MACH_AMS_DELTA
help
This option enables support for the LEDs on Amstrad Delta (E3).
config LEDS_NET48XX
tristate "LED Support for Soekris net48xx series Error LED"
depends on LEDS_CLASS && SCx200_GPIO
help
This option enables support for the Soekris net4801 and net4826 error
LED.
config LEDS_WRAP
tristate "LED Support for the WRAP series LEDs"
depends on LEDS_CLASS && SCx200_GPIO
help
This option enables support for the PCEngines WRAP programmable LEDs.
config LEDS_H1940
tristate "LED Support for iPAQ H1940 device"
depends LEDS_CLASS && ARCH_H1940
help
This option enables support for the LEDs on the h1940.
config LEDS_COBALT
tristate "LED Support for Cobalt Server front LED"
depends on LEDS_CLASS && MIPS_COBALT
help
This option enables support for the front LED on Cobalt Server
comment "LED Triggers"
config LEDS_TRIGGERS
bool "LED Trigger support"
depends on NEW_LEDS
help
This option enables trigger support for the leds class.
These triggers allow kernel events to drive the LEDs and can
be configured via sysfs. If unsure, say Y.
config LEDS_TRIGGER_TIMER
tristate "LED Timer Trigger"
depends on LEDS_TRIGGERS
help
This allows LEDs to be controlled by a programmable timer
via sysfs. If unsure, say Y.
config LEDS_TRIGGER_IDE_DISK
bool "LED IDE Disk Trigger"
depends on LEDS_TRIGGERS && BLK_DEV_IDEDISK
help
This allows LEDs to be controlled by IDE disk activity.
If unsure, say Y.
config LEDS_TRIGGER_HEARTBEAT
tristate "LED Heartbeat Trigger"
depends on LEDS_TRIGGERS
help
This allows LEDs to be controlled by a CPU load average.
The flash frequency is a hyperbolic function of the 1-minute
load average.
If unsure, say Y.
endmenu

23
drivers/leds/Makefile Normal file
View File

@@ -0,0 +1,23 @@
# LED Core
obj-$(CONFIG_NEW_LEDS) += led-core.o
obj-$(CONFIG_LEDS_CLASS) += led-class.o
obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o
# LED Platform Drivers
obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o
obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o
obj-$(CONFIG_LEDS_IXP4XX) += leds-ixp4xx-gpio.o
obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o
obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o
obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o
obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o
obj-$(CONFIG_LEDS_H1940) += leds-h1940.o
obj-$(CONFIG_LEDS_COBALT) += leds-cobalt.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

187
drivers/leds/led-class.c Normal file
View File

@@ -0,0 +1,187 @@
/*
* LED Class Core
*
* Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu>
* Copyright (C) 2005-2006 Richard Purdie <rpurdie@openedhand.com>
*
* 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/init.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/device.h>
#include <linux/sysdev.h>
#include <linux/timer.h>
#include <linux/err.h>
#include <linux/ctype.h>
#include <linux/leds.h>
#include "leds.h"
static struct class *leds_class;
static ssize_t led_brightness_show(struct class_device *dev, char *buf)
{
struct led_classdev *led_cdev = class_get_devdata(dev);
ssize_t ret = 0;
/* no lock needed for this */
sprintf(buf, "%u\n", led_cdev->brightness);
ret = strlen(buf) + 1;
return ret;
}
static ssize_t led_brightness_store(struct class_device *dev,
const char *buf, size_t size)
{
struct led_classdev *led_cdev = class_get_devdata(dev);
ssize_t ret = -EINVAL;
char *after;
unsigned long state = simple_strtoul(buf, &after, 10);
size_t count = after - buf;
if (*after && isspace(*after))
count++;
if (count == size) {
ret = count;
led_set_brightness(led_cdev, state);
}
return ret;
}
static CLASS_DEVICE_ATTR(brightness, 0644, led_brightness_show,
led_brightness_store);
#ifdef CONFIG_LEDS_TRIGGERS
static CLASS_DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store);
#endif
/**
* led_classdev_suspend - suspend an led_classdev.
* @led_cdev: the led_classdev to suspend.
*/
void led_classdev_suspend(struct led_classdev *led_cdev)
{
led_cdev->flags |= LED_SUSPENDED;
led_cdev->brightness_set(led_cdev, 0);
}
EXPORT_SYMBOL_GPL(led_classdev_suspend);
/**
* led_classdev_resume - resume an led_classdev.
* @led_cdev: the led_classdev to resume.
*/
void led_classdev_resume(struct led_classdev *led_cdev)
{
led_cdev->brightness_set(led_cdev, led_cdev->brightness);
led_cdev->flags &= ~LED_SUSPENDED;
}
EXPORT_SYMBOL_GPL(led_classdev_resume);
/**
* led_classdev_register - register a new object of led_classdev class.
* @dev: The device to register.
* @led_cdev: the led_classdev structure for this device.
*/
int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
{
int rc;
led_cdev->class_dev = class_device_create(leds_class, NULL, 0,
parent, "%s", led_cdev->name);
if (unlikely(IS_ERR(led_cdev->class_dev)))
return PTR_ERR(led_cdev->class_dev);
class_set_devdata(led_cdev->class_dev, led_cdev);
/* register the attributes */
rc = class_device_create_file(led_cdev->class_dev,
&class_device_attr_brightness);
if (rc)
goto err_out;
/* add to the list of leds */
write_lock(&leds_list_lock);
list_add_tail(&led_cdev->node, &leds_list);
write_unlock(&leds_list_lock);
#ifdef CONFIG_LEDS_TRIGGERS
rwlock_init(&led_cdev->trigger_lock);
rc = class_device_create_file(led_cdev->class_dev,
&class_device_attr_trigger);
if (rc)
goto err_out_led_list;
led_trigger_set_default(led_cdev);
#endif
printk(KERN_INFO "Registered led device: %s\n",
led_cdev->class_dev->class_id);
return 0;
#ifdef CONFIG_LEDS_TRIGGERS
err_out_led_list:
class_device_remove_file(led_cdev->class_dev,
&class_device_attr_brightness);
list_del(&led_cdev->node);
#endif
err_out:
class_device_unregister(led_cdev->class_dev);
return rc;
}
EXPORT_SYMBOL_GPL(led_classdev_register);
/**
* led_classdev_unregister - unregisters a object of led_properties class.
* @led_cdev: the led device to unregister
*
* Unregisters a previously registered via led_classdev_register object.
*/
void led_classdev_unregister(struct led_classdev *led_cdev)
{
class_device_remove_file(led_cdev->class_dev,
&class_device_attr_brightness);
#ifdef CONFIG_LEDS_TRIGGERS
class_device_remove_file(led_cdev->class_dev,
&class_device_attr_trigger);
write_lock(&led_cdev->trigger_lock);
if (led_cdev->trigger)
led_trigger_set(led_cdev, NULL);
write_unlock(&led_cdev->trigger_lock);
#endif
class_device_unregister(led_cdev->class_dev);
write_lock(&leds_list_lock);
list_del(&led_cdev->node);
write_unlock(&leds_list_lock);
}
EXPORT_SYMBOL_GPL(led_classdev_unregister);
static int __init leds_init(void)
{
leds_class = class_create(THIS_MODULE, "leds");
if (IS_ERR(leds_class))
return PTR_ERR(leds_class);
return 0;
}
static void __exit leds_exit(void)
{
class_destroy(leds_class);
}
subsys_initcall(leds_init);
module_exit(leds_exit);
MODULE_AUTHOR("John Lenz, Richard Purdie");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("LED Class Interface");

25
drivers/leds/led-core.c Normal file
View File

@@ -0,0 +1,25 @@
/*
* LED Class Core
*
* Copyright 2005-2006 Openedhand Ltd.
*
* Author: Richard Purdie <rpurdie@openedhand.com>
*
* 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/kernel.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/leds.h>
#include "leds.h"
DEFINE_RWLOCK(leds_list_lock);
LIST_HEAD(leds_list);
EXPORT_SYMBOL_GPL(leds_list);
EXPORT_SYMBOL_GPL(leds_list_lock);

239
drivers/leds/led-triggers.c Normal file
View File

@@ -0,0 +1,239 @@
/*
* LED Triggers Core
*
* Copyright 2005-2006 Openedhand Ltd.
*
* Author: Richard Purdie <rpurdie@openedhand.com>
*
* 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/init.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/device.h>
#include <linux/sysdev.h>
#include <linux/timer.h>
#include <linux/leds.h>
#include "leds.h"
/*
* Nests outside led_cdev->trigger_lock
*/
static DEFINE_RWLOCK(triggers_list_lock);
static LIST_HEAD(trigger_list);
ssize_t led_trigger_store(struct class_device *dev, const char *buf,
size_t count)
{
struct led_classdev *led_cdev = class_get_devdata(dev);
char trigger_name[TRIG_NAME_MAX];
struct led_trigger *trig;
size_t len;
trigger_name[sizeof(trigger_name) - 1] = '\0';
strncpy(trigger_name, buf, sizeof(trigger_name) - 1);
len = strlen(trigger_name);
if (len && trigger_name[len - 1] == '\n')
trigger_name[len - 1] = '\0';
if (!strcmp(trigger_name, "none")) {
write_lock(&led_cdev->trigger_lock);
led_trigger_set(led_cdev, NULL);
write_unlock(&led_cdev->trigger_lock);
return count;
}
read_lock(&triggers_list_lock);
list_for_each_entry(trig, &trigger_list, next_trig) {
if (!strcmp(trigger_name, trig->name)) {
write_lock(&led_cdev->trigger_lock);
led_trigger_set(led_cdev, trig);
write_unlock(&led_cdev->trigger_lock);
read_unlock(&triggers_list_lock);
return count;
}
}
read_unlock(&triggers_list_lock);
return -EINVAL;
}
ssize_t led_trigger_show(struct class_device *dev, char *buf)
{
struct led_classdev *led_cdev = class_get_devdata(dev);
struct led_trigger *trig;
int len = 0;
read_lock(&triggers_list_lock);
read_lock(&led_cdev->trigger_lock);
if (!led_cdev->trigger)
len += sprintf(buf+len, "[none] ");
else
len += sprintf(buf+len, "none ");
list_for_each_entry(trig, &trigger_list, next_trig) {
if (led_cdev->trigger && !strcmp(led_cdev->trigger->name,
trig->name))
len += sprintf(buf+len, "[%s] ", trig->name);
else
len += sprintf(buf+len, "%s ", trig->name);
}
read_unlock(&led_cdev->trigger_lock);
read_unlock(&triggers_list_lock);
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);
}
/* Caller must ensure led_cdev->trigger_lock held */
void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger)
{
unsigned long flags;
/* Remove any existing 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);
if (led_cdev->trigger->deactivate)
led_cdev->trigger->deactivate(led_cdev);
led_set_brightness(led_cdev, LED_OFF);
}
if (trigger) {
write_lock_irqsave(&trigger->leddev_list_lock, flags);
list_add_tail(&led_cdev->trig_list, &trigger->led_cdevs);
write_unlock_irqrestore(&trigger->leddev_list_lock, flags);
if (trigger->activate)
trigger->activate(led_cdev);
}
led_cdev->trigger = trigger;
}
void led_trigger_set_default(struct led_classdev *led_cdev)
{
struct led_trigger *trig;
if (!led_cdev->default_trigger)
return;
read_lock(&triggers_list_lock);
write_lock(&led_cdev->trigger_lock);
list_for_each_entry(trig, &trigger_list, next_trig) {
if (!strcmp(led_cdev->default_trigger, trig->name))
led_trigger_set(led_cdev, trig);
}
write_unlock(&led_cdev->trigger_lock);
read_unlock(&triggers_list_lock);
}
int led_trigger_register(struct led_trigger *trigger)
{
struct led_classdev *led_cdev;
rwlock_init(&trigger->leddev_list_lock);
INIT_LIST_HEAD(&trigger->led_cdevs);
/* Add to the list of led triggers */
write_lock(&triggers_list_lock);
list_add_tail(&trigger->next_trig, &trigger_list);
write_unlock(&triggers_list_lock);
/* Register with any LEDs that have this as a default trigger */
read_lock(&leds_list_lock);
list_for_each_entry(led_cdev, &leds_list, node) {
write_lock(&led_cdev->trigger_lock);
if (!led_cdev->trigger && led_cdev->default_trigger &&
!strcmp(led_cdev->default_trigger, trigger->name))
led_trigger_set(led_cdev, trigger);
write_unlock(&led_cdev->trigger_lock);
}
read_unlock(&leds_list_lock);
return 0;
}
void led_trigger_register_simple(const char *name, struct led_trigger **tp)
{
struct led_trigger *trigger;
trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL);
if (trigger) {
trigger->name = name;
led_trigger_register(trigger);
}
*tp = trigger;
}
void led_trigger_unregister(struct led_trigger *trigger)
{
struct led_classdev *led_cdev;
/* Remove from the list of led triggers */
write_lock(&triggers_list_lock);
list_del(&trigger->next_trig);
write_unlock(&triggers_list_lock);
/* Remove anyone actively using this trigger */
read_lock(&leds_list_lock);
list_for_each_entry(led_cdev, &leds_list, node) {
write_lock(&led_cdev->trigger_lock);
if (led_cdev->trigger == trigger)
led_trigger_set(led_cdev, NULL);
write_unlock(&led_cdev->trigger_lock);
}
read_unlock(&leds_list_lock);
}
void led_trigger_unregister_simple(struct led_trigger *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");
MODULE_DESCRIPTION("LED Triggers Core");

View File

@@ -0,0 +1,161 @@
/*
* LEDs driver for Amstrad Delta (E3)
*
* Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
*
* 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/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <asm/arch/board-ams-delta.h>
/*
* Our context
*/
struct ams_delta_led {
struct led_classdev cdev;
u8 bitmask;
};
static void ams_delta_led_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
struct ams_delta_led *led_dev =
container_of(led_cdev, struct ams_delta_led, cdev);
if (value)
ams_delta_latch1_write(led_dev->bitmask, led_dev->bitmask);
else
ams_delta_latch1_write(led_dev->bitmask, 0);
}
static struct ams_delta_led ams_delta_leds[] = {
{
.cdev = {
.name = "ams-delta:camera",
.brightness_set = ams_delta_led_set,
},
.bitmask = AMS_DELTA_LATCH1_LED_CAMERA,
},
{
.cdev = {
.name = "ams-delta:advert",
.brightness_set = ams_delta_led_set,
},
.bitmask = AMS_DELTA_LATCH1_LED_ADVERT,
},
{
.cdev = {
.name = "ams-delta:email",
.brightness_set = ams_delta_led_set,
},
.bitmask = AMS_DELTA_LATCH1_LED_EMAIL,
},
{
.cdev = {
.name = "ams-delta:handsfree",
.brightness_set = ams_delta_led_set,
},
.bitmask = AMS_DELTA_LATCH1_LED_HANDSFREE,
},
{
.cdev = {
.name = "ams-delta:voicemail",
.brightness_set = ams_delta_led_set,
},
.bitmask = AMS_DELTA_LATCH1_LED_VOICEMAIL,
},
{
.cdev = {
.name = "ams-delta:voice",
.brightness_set = ams_delta_led_set,
},
.bitmask = AMS_DELTA_LATCH1_LED_VOICE,
},
};
#ifdef CONFIG_PM
static int ams_delta_led_suspend(struct platform_device *dev,
pm_message_t state)
{
int i;
for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++)
led_classdev_suspend(&ams_delta_leds[i].cdev);
return 0;
}
static int ams_delta_led_resume(struct platform_device *dev)
{
int i;
for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++)
led_classdev_resume(&ams_delta_leds[i].cdev);
return 0;
}
#else
#define ams_delta_led_suspend NULL
#define ams_delta_led_resume NULL
#endif
static int ams_delta_led_probe(struct platform_device *pdev)
{
int i;
int ret;
for (i = ret = 0; ret >= 0 && i < ARRAY_SIZE(ams_delta_leds); i++) {
ret = led_classdev_register(&pdev->dev,
&ams_delta_leds[i].cdev);
}
if (ret < 0 && i > 1) {
for (i = i - 2; i >= 0; i--)
led_classdev_unregister(&ams_delta_leds[i].cdev);
}
return ret;
}
static int ams_delta_led_remove(struct platform_device *pdev)
{
int i;
for (i = ARRAY_SIZE(ams_delta_leds) - 1; i >= 0; i--)
led_classdev_unregister(&ams_delta_leds[i].cdev);
return 0;
}
static struct platform_driver ams_delta_led_driver = {
.probe = ams_delta_led_probe,
.remove = ams_delta_led_remove,
.suspend = ams_delta_led_suspend,
.resume = ams_delta_led_resume,
.driver = {
.name = "ams-delta-led",
},
};
static int __init ams_delta_led_init(void)
{
return platform_driver_register(&ams_delta_led_driver);
}
static void __exit ams_delta_led_exit(void)
{
return platform_driver_unregister(&ams_delta_led_driver);
}
module_init(ams_delta_led_init);
module_exit(ams_delta_led_exit);
MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>");
MODULE_DESCRIPTION("Amstrad Delta LED driver");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2006 - Florian Fainelli <florian@openwrt.org>
*
* Control the Cobalt Qube/RaQ front LED
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/leds.h>
#include <asm/mach-cobalt/cobalt.h>
static void cobalt_led_set(struct led_classdev *led_cdev, enum led_brightness brightness)
{
if (brightness)
COBALT_LED_PORT = COBALT_LED_BAR_LEFT | COBALT_LED_BAR_RIGHT;
else
COBALT_LED_PORT = 0;
}
static struct led_classdev cobalt_led = {
.name = "cobalt-front-led",
.brightness_set = cobalt_led_set,
.default_trigger = "ide-disk",
};
static int __init cobalt_led_init(void)
{
return led_classdev_register(NULL, &cobalt_led);
}
static void __exit cobalt_led_exit(void)
{
led_classdev_unregister(&cobalt_led);
}
module_init(cobalt_led_init);
module_exit(cobalt_led_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Front LED support for Cobalt Server");
MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");

120
drivers/leds/leds-corgi.c Normal file
View File

@@ -0,0 +1,120 @@
/*
* LED Triggers Core
*
* Copyright 2005-2006 Openedhand Ltd.
*
* Author: Richard Purdie <rpurdie@openedhand.com>
*
* 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/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <asm/mach-types.h>
#include <asm/arch/corgi.h>
#include <asm/arch/hardware.h>
#include <asm/arch/pxa-regs.h>
#include <asm/hardware/scoop.h>
static void corgiled_amber_set(struct led_classdev *led_cdev, enum led_brightness value)
{
if (value)
GPSR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE);
else
GPCR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE);
}
static void corgiled_green_set(struct led_classdev *led_cdev, enum led_brightness value)
{
if (value)
set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN);
else
reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN);
}
static struct led_classdev corgi_amber_led = {
.name = "corgi:amber",
.default_trigger = "sharpsl-charge",
.brightness_set = corgiled_amber_set,
};
static struct led_classdev corgi_green_led = {
.name = "corgi:green",
.default_trigger = "nand-disk",
.brightness_set = corgiled_green_set,
};
#ifdef CONFIG_PM
static int corgiled_suspend(struct platform_device *dev, pm_message_t state)
{
#ifdef CONFIG_LEDS_TRIGGERS
if (corgi_amber_led.trigger && strcmp(corgi_amber_led.trigger->name, "sharpsl-charge"))
#endif
led_classdev_suspend(&corgi_amber_led);
led_classdev_suspend(&corgi_green_led);
return 0;
}
static int corgiled_resume(struct platform_device *dev)
{
led_classdev_resume(&corgi_amber_led);
led_classdev_resume(&corgi_green_led);
return 0;
}
#endif
static int corgiled_probe(struct platform_device *pdev)
{
int ret;
ret = led_classdev_register(&pdev->dev, &corgi_amber_led);
if (ret < 0)
return ret;
ret = led_classdev_register(&pdev->dev, &corgi_green_led);
if (ret < 0)
led_classdev_unregister(&corgi_amber_led);
return ret;
}
static int corgiled_remove(struct platform_device *pdev)
{
led_classdev_unregister(&corgi_amber_led);
led_classdev_unregister(&corgi_green_led);
return 0;
}
static struct platform_driver corgiled_driver = {
.probe = corgiled_probe,
.remove = corgiled_remove,
#ifdef CONFIG_PM
.suspend = corgiled_suspend,
.resume = corgiled_resume,
#endif
.driver = {
.name = "corgi-led",
},
};
static int __init corgiled_init(void)
{
return platform_driver_register(&corgiled_driver);
}
static void __exit corgiled_exit(void)
{
platform_driver_unregister(&corgiled_driver);
}
module_init(corgiled_init);
module_exit(corgiled_exit);
MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
MODULE_DESCRIPTION("Corgi LED driver");
MODULE_LICENSE("GPL");

163
drivers/leds/leds-h1940.c Normal file
View File

@@ -0,0 +1,163 @@
/*
* drivers/leds/h1940-leds.c
* Copyright (c) Arnaud Patard <arnaud.patard@rtp-net.org>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details.
*
* H1940 leds driver
*
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/leds.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#include <asm/arch/h1940-latch.h>
/*
* Green led.
*/
void h1940_greenled_set(struct led_classdev *led_dev, enum led_brightness value)
{
switch (value) {
case LED_HALF:
h1940_latch_control(0,H1940_LATCH_LED_FLASH);
s3c2410_gpio_setpin(S3C2410_GPA7,1);
break;
case LED_FULL:
h1940_latch_control(0,H1940_LATCH_LED_GREEN);
s3c2410_gpio_setpin(S3C2410_GPA7,1);
break;
default:
case LED_OFF:
h1940_latch_control(H1940_LATCH_LED_FLASH,0);
h1940_latch_control(H1940_LATCH_LED_GREEN,0);
s3c2410_gpio_setpin(S3C2410_GPA7,0);
break;
}
}
static struct led_classdev h1940_greenled = {
.name = "h1940:green",
.brightness_set = h1940_greenled_set,
.default_trigger = "h1940-charger",
};
/*
* Red led.
*/
void h1940_redled_set(struct led_classdev *led_dev, enum led_brightness value)
{
switch (value) {
case LED_HALF:
h1940_latch_control(0,H1940_LATCH_LED_FLASH);
s3c2410_gpio_setpin(S3C2410_GPA1,1);
break;
case LED_FULL:
h1940_latch_control(0,H1940_LATCH_LED_RED);
s3c2410_gpio_setpin(S3C2410_GPA1,1);
break;
default:
case LED_OFF:
h1940_latch_control(H1940_LATCH_LED_FLASH,0);
h1940_latch_control(H1940_LATCH_LED_RED,0);
s3c2410_gpio_setpin(S3C2410_GPA1,0);
break;
}
}
static struct led_classdev h1940_redled = {
.name = "h1940:red",
.brightness_set = h1940_redled_set,
.default_trigger = "h1940-charger",
};
/*
* Blue led.
* (it can only be blue flashing led)
*/
void h1940_blueled_set(struct led_classdev *led_dev, enum led_brightness value)
{
if (value) {
/* flashing Blue */
h1940_latch_control(0,H1940_LATCH_LED_FLASH);
s3c2410_gpio_setpin(S3C2410_GPA3,1);
} else {
h1940_latch_control(H1940_LATCH_LED_FLASH,0);
s3c2410_gpio_setpin(S3C2410_GPA3,0);
}
}
static struct led_classdev h1940_blueled = {
.name = "h1940:blue",
.brightness_set = h1940_blueled_set,
.default_trigger = "h1940-bluetooth",
};
static int __init h1940leds_probe(struct platform_device *pdev)
{
int ret;
ret = led_classdev_register(&pdev->dev, &h1940_greenled);
if (ret)
goto err_green;
ret = led_classdev_register(&pdev->dev, &h1940_redled);
if (ret)
goto err_red;
ret = led_classdev_register(&pdev->dev, &h1940_blueled);
if (ret)
goto err_blue;
return 0;
err_blue:
led_classdev_unregister(&h1940_redled);
err_red:
led_classdev_unregister(&h1940_greenled);
err_green:
return ret;
}
static int h1940leds_remove(struct platform_device *pdev)
{
led_classdev_unregister(&h1940_greenled);
led_classdev_unregister(&h1940_redled);
led_classdev_unregister(&h1940_blueled);
return 0;
}
static struct platform_driver h1940leds_driver = {
.driver = {
.name = "h1940-leds",
},
.probe = h1940leds_probe,
.remove = h1940leds_remove,
};
static int __init h1940leds_init(void)
{
return platform_driver_register(&h1940leds_driver);
}
static void __exit h1940leds_exit(void)
{
platform_driver_unregister(&h1940leds_driver);
}
module_init(h1940leds_init);
module_exit(h1940leds_exit);
MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
MODULE_DESCRIPTION("LED driver for the iPAQ H1940");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,214 @@
/*
* IXP4XX GPIO driver LED driver
*
* Author: John Bowler <jbowler@acm.org>
*
* Copyright (c) 2006 John Bowler
*
* Permission is hereby granted, free of charge, to any
* person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the
* Software without restriction, including without
* limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice
* shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
* ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
* SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/leds.h>
#include <asm/arch/hardware.h>
extern spinlock_t gpio_lock;
/* Up to 16 gpio lines are possible. */
#define GPIO_MAX 16
static struct ixp4xxgpioled_device {
struct led_classdev ancestor;
int flags;
} ixp4xxgpioled_devices[GPIO_MAX];
void ixp4xxgpioled_brightness_set(struct led_classdev *pled,
enum led_brightness value)
{
const struct ixp4xxgpioled_device *const ixp4xx_dev =
container_of(pled, struct ixp4xxgpioled_device, ancestor);
const u32 gpio_pin = ixp4xx_dev - ixp4xxgpioled_devices;
if (gpio_pin < GPIO_MAX && ixp4xx_dev->ancestor.name != 0) {
/* Set or clear the 'gpio_pin' bit according to the style
* and the required setting (value > 0 == on)
*/
const int gpio_value =
(value > 0) == (ixp4xx_dev->flags != IXP4XX_GPIO_LOW) ?
IXP4XX_GPIO_HIGH : IXP4XX_GPIO_LOW;
{
unsigned long flags;
spin_lock_irqsave(&gpio_lock, flags);
gpio_line_set(gpio_pin, gpio_value);
spin_unlock_irqrestore(&gpio_lock, flags);
}
}
}
/* LEDs are described in resources, the following iterates over the valid
* LED resources.
*/
#define for_all_leds(i, pdev) \
for (i=0; i<pdev->num_resources; ++i) \
if (pdev->resource[i].start < GPIO_MAX && \
pdev->resource[i].name != 0)
/* The following applies 'operation' to each LED from the given platform,
* the function always returns 0 to allow tail call elimination.
*/
static int apply_to_all_leds(struct platform_device *pdev,
void (*operation)(struct led_classdev *pled))
{
int i;
for_all_leds(i, pdev)
operation(&ixp4xxgpioled_devices[pdev->resource[i].start].ancestor);
return 0;
}
#ifdef CONFIG_PM
static int ixp4xxgpioled_suspend(struct platform_device *pdev,
pm_message_t state)
{
return apply_to_all_leds(pdev, led_classdev_suspend);
}
static int ixp4xxgpioled_resume(struct platform_device *pdev)
{
return apply_to_all_leds(pdev, led_classdev_resume);
}
#endif
static void ixp4xxgpioled_remove_one_led(struct led_classdev *pled)
{
led_classdev_unregister(pled);
pled->name = 0;
}
static int ixp4xxgpioled_remove(struct platform_device *pdev)
{
return apply_to_all_leds(pdev, ixp4xxgpioled_remove_one_led);
}
static int ixp4xxgpioled_probe(struct platform_device *pdev)
{
/* The board level has to tell the driver where the
* LEDs are connected - there is no way to find out
* electrically. It must also say whether the GPIO
* lines are active high or active low.
*
* To do this read the num_resources (the number of
* LEDs) and the struct resource (the data for each
* LED). The name comes from the resource, and it
* isn't copied.
*/
int i;
for_all_leds(i, pdev) {
const u8 gpio_pin = pdev->resource[i].start;
int rc;
if (ixp4xxgpioled_devices[gpio_pin].ancestor.name == 0) {
unsigned long flags;
spin_lock_irqsave(&gpio_lock, flags);
gpio_line_config(gpio_pin, IXP4XX_GPIO_OUT);
/* The config can, apparently, reset the state,
* I suspect the gpio line may be an input and
* the config may cause the line to be latched,
* so the setting depends on how the LED is
* connected to the line (which affects how it
* floats if not driven).
*/
gpio_line_set(gpio_pin, IXP4XX_GPIO_HIGH);
spin_unlock_irqrestore(&gpio_lock, flags);
ixp4xxgpioled_devices[gpio_pin].flags =
pdev->resource[i].flags & IORESOURCE_BITS;
ixp4xxgpioled_devices[gpio_pin].ancestor.name =
pdev->resource[i].name;
/* This is how a board manufacturer makes the LED
* come on on reset - the GPIO line will be high, so
* make the LED light when the line is low...
*/
if (ixp4xxgpioled_devices[gpio_pin].flags != IXP4XX_GPIO_LOW)
ixp4xxgpioled_devices[gpio_pin].ancestor.brightness = 100;
else
ixp4xxgpioled_devices[gpio_pin].ancestor.brightness = 0;
ixp4xxgpioled_devices[gpio_pin].ancestor.flags = 0;
ixp4xxgpioled_devices[gpio_pin].ancestor.brightness_set =
ixp4xxgpioled_brightness_set;
ixp4xxgpioled_devices[gpio_pin].ancestor.default_trigger = 0;
}
rc = led_classdev_register(&pdev->dev,
&ixp4xxgpioled_devices[gpio_pin].ancestor);
if (rc < 0) {
ixp4xxgpioled_devices[gpio_pin].ancestor.name = 0;
ixp4xxgpioled_remove(pdev);
return rc;
}
}
return 0;
}
static struct platform_driver ixp4xxgpioled_driver = {
.probe = ixp4xxgpioled_probe,
.remove = ixp4xxgpioled_remove,
#ifdef CONFIG_PM
.suspend = ixp4xxgpioled_suspend,
.resume = ixp4xxgpioled_resume,
#endif
.driver = {
.name = "IXP4XX-GPIO-LED",
},
};
static int __init ixp4xxgpioled_init(void)
{
return platform_driver_register(&ixp4xxgpioled_driver);
}
static void __exit ixp4xxgpioled_exit(void)
{
platform_driver_unregister(&ixp4xxgpioled_driver);
}
module_init(ixp4xxgpioled_init);
module_exit(ixp4xxgpioled_exit);
MODULE_AUTHOR("John Bowler <jbowler@acm.org>");
MODULE_DESCRIPTION("IXP4XX GPIO LED driver");
MODULE_LICENSE("Dual MIT/GPL");

View File

@@ -0,0 +1,96 @@
/*
* linux/drivers/leds/leds-locomo.c
*
* Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu>
*
* 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/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/leds.h>
#include <asm/hardware.h>
#include <asm/hardware/locomo.h>
static void locomoled_brightness_set(struct led_classdev *led_cdev,
enum led_brightness value, int offset)
{
struct locomo_dev *locomo_dev = LOCOMO_DEV(led_cdev->class_dev->dev);
unsigned long flags;
local_irq_save(flags);
if (value)
locomo_writel(LOCOMO_LPT_TOFH, locomo_dev->mapbase + offset);
else
locomo_writel(LOCOMO_LPT_TOFL, locomo_dev->mapbase + offset);
local_irq_restore(flags);
}
static void locomoled_brightness_set0(struct led_classdev *led_cdev,
enum led_brightness value)
{
locomoled_brightness_set(led_cdev, value, LOCOMO_LPT0);
}
static void locomoled_brightness_set1(struct led_classdev *led_cdev,
enum led_brightness value)
{
locomoled_brightness_set(led_cdev, value, LOCOMO_LPT1);
}
static struct led_classdev locomo_led0 = {
.name = "locomo:amber",
.default_trigger = "sharpsl-charge",
.brightness_set = locomoled_brightness_set0,
};
static struct led_classdev locomo_led1 = {
.name = "locomo:green",
.default_trigger = "nand-disk",
.brightness_set = locomoled_brightness_set1,
};
static int locomoled_probe(struct locomo_dev *ldev)
{
int ret;
ret = led_classdev_register(&ldev->dev, &locomo_led0);
if (ret < 0)
return ret;
ret = led_classdev_register(&ldev->dev, &locomo_led1);
if (ret < 0)
led_classdev_unregister(&locomo_led0);
return ret;
}
static int locomoled_remove(struct locomo_dev *dev)
{
led_classdev_unregister(&locomo_led0);
led_classdev_unregister(&locomo_led1);
return 0;
}
static struct locomo_driver locomoled_driver = {
.drv = {
.name = "locomoled"
},
.devid = LOCOMO_DEVID_LED,
.probe = locomoled_probe,
.remove = locomoled_remove,
};
static int __init locomoled_init(void)
{
return locomo_driver_register(&locomoled_driver);
}
module_init(locomoled_init);
MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>");
MODULE_DESCRIPTION("Locomo LED driver");
MODULE_LICENSE("GPL");

115
drivers/leds/leds-net48xx.c Normal file
View File

@@ -0,0 +1,115 @@
/*
* LEDs driver for Soekris net48xx
*
* Copyright (C) 2006 Chris Boot <bootc@bootc.net>
*
* Based on leds-ams-delta.c
*
* 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/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/err.h>
#include <asm/io.h>
#include <linux/nsc_gpio.h>
#include <linux/scx200_gpio.h>
#define DRVNAME "net48xx-led"
#define NET48XX_ERROR_LED_GPIO 20
static struct platform_device *pdev;
static void net48xx_error_led_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
scx200_gpio_ops.gpio_set(NET48XX_ERROR_LED_GPIO, value ? 1 : 0);
}
static struct led_classdev net48xx_error_led = {
.name = "net48xx:error",
.brightness_set = net48xx_error_led_set,
};
#ifdef CONFIG_PM
static int net48xx_led_suspend(struct platform_device *dev,
pm_message_t state)
{
led_classdev_suspend(&net48xx_error_led);
return 0;
}
static int net48xx_led_resume(struct platform_device *dev)
{
led_classdev_resume(&net48xx_error_led);
return 0;
}
#else
#define net48xx_led_suspend NULL
#define net48xx_led_resume NULL
#endif
static int net48xx_led_probe(struct platform_device *pdev)
{
return led_classdev_register(&pdev->dev, &net48xx_error_led);
}
static int net48xx_led_remove(struct platform_device *pdev)
{
led_classdev_unregister(&net48xx_error_led);
return 0;
}
static struct platform_driver net48xx_led_driver = {
.probe = net48xx_led_probe,
.remove = net48xx_led_remove,
.suspend = net48xx_led_suspend,
.resume = net48xx_led_resume,
.driver = {
.name = DRVNAME,
.owner = THIS_MODULE,
},
};
static int __init net48xx_led_init(void)
{
int ret;
/* small hack, but scx200_gpio doesn't set .dev if the probe fails */
if (!scx200_gpio_ops.dev) {
ret = -ENODEV;
goto out;
}
ret = platform_driver_register(&net48xx_led_driver);
if (ret < 0)
goto out;
pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
if (IS_ERR(pdev)) {
ret = PTR_ERR(pdev);
platform_driver_unregister(&net48xx_led_driver);
goto out;
}
out:
return ret;
}
static void __exit net48xx_led_exit(void)
{
platform_device_unregister(pdev);
platform_driver_unregister(&net48xx_led_driver);
}
module_init(net48xx_led_init);
module_exit(net48xx_led_exit);
MODULE_AUTHOR("Chris Boot <bootc@bootc.net>");
MODULE_DESCRIPTION("Soekris net48xx LED driver");
MODULE_LICENSE("GPL");

162
drivers/leds/leds-s3c24xx.c Normal file
View File

@@ -0,0 +1,162 @@
/* drivers/leds/leds-s3c24xx.c
*
* (c) 2006 Simtec Electronics
* http://armlinux.simtec.co.uk/
* Ben Dooks <ben@simtec.co.uk>
*
* S3C24XX - LEDs GPIO driver
*
* 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/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <asm/hardware.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/leds-gpio.h>
/* our context */
struct s3c24xx_gpio_led {
struct led_classdev cdev;
struct s3c24xx_led_platdata *pdata;
};
static inline struct s3c24xx_gpio_led *pdev_to_gpio(struct platform_device *dev)
{
return platform_get_drvdata(dev);
}
static inline struct s3c24xx_gpio_led *to_gpio(struct led_classdev *led_cdev)
{
return container_of(led_cdev, struct s3c24xx_gpio_led, cdev);
}
static void s3c24xx_led_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
struct s3c24xx_gpio_led *led = to_gpio(led_cdev);
struct s3c24xx_led_platdata *pd = led->pdata;
/* there will be a sort delay between setting the output and
* going from output to input when using tristate. */
s3c2410_gpio_setpin(pd->gpio, (value ? 1 : 0) ^
(pd->flags & S3C24XX_LEDF_ACTLOW));
if (pd->flags & S3C24XX_LEDF_TRISTATE)
s3c2410_gpio_cfgpin(pd->gpio,
value ? S3C2410_GPIO_OUTPUT : S3C2410_GPIO_INPUT);
}
static int s3c24xx_led_remove(struct platform_device *dev)
{
struct s3c24xx_gpio_led *led = pdev_to_gpio(dev);
led_classdev_unregister(&led->cdev);
kfree(led);
return 0;
}
static int s3c24xx_led_probe(struct platform_device *dev)
{
struct s3c24xx_led_platdata *pdata = dev->dev.platform_data;
struct s3c24xx_gpio_led *led;
int ret;
led = kzalloc(sizeof(struct s3c24xx_gpio_led), GFP_KERNEL);
if (led == NULL) {
dev_err(&dev->dev, "No memory for device\n");
return -ENOMEM;
}
platform_set_drvdata(dev, led);
led->cdev.brightness_set = s3c24xx_led_set;
led->cdev.default_trigger = pdata->def_trigger;
led->cdev.name = pdata->name;
led->pdata = pdata;
/* no point in having a pull-up if we are always driving */
if (pdata->flags & S3C24XX_LEDF_TRISTATE) {
s3c2410_gpio_setpin(pdata->gpio, 0);
s3c2410_gpio_cfgpin(pdata->gpio, S3C2410_GPIO_INPUT);
} else {
s3c2410_gpio_pullup(pdata->gpio, 0);
s3c2410_gpio_setpin(pdata->gpio, 0);
s3c2410_gpio_cfgpin(pdata->gpio, S3C2410_GPIO_OUTPUT);
}
/* register our new led device */
ret = led_classdev_register(&dev->dev, &led->cdev);
if (ret < 0) {
dev_err(&dev->dev, "led_classdev_register failed\n");
goto exit_err1;
}
return 0;
exit_err1:
kfree(led);
return ret;
}
#ifdef CONFIG_PM
static int s3c24xx_led_suspend(struct platform_device *dev, pm_message_t state)
{
struct s3c24xx_gpio_led *led = pdev_to_gpio(dev);
led_classdev_suspend(&led->cdev);
return 0;
}
static int s3c24xx_led_resume(struct platform_device *dev)
{
struct s3c24xx_gpio_led *led = pdev_to_gpio(dev);
led_classdev_resume(&led->cdev);
return 0;
}
#else
#define s3c24xx_led_suspend NULL
#define s3c24xx_led_resume NULL
#endif
static struct platform_driver s3c24xx_led_driver = {
.probe = s3c24xx_led_probe,
.remove = s3c24xx_led_remove,
.suspend = s3c24xx_led_suspend,
.resume = s3c24xx_led_resume,
.driver = {
.name = "s3c24xx_led",
.owner = THIS_MODULE,
},
};
static int __init s3c24xx_led_init(void)
{
return platform_driver_register(&s3c24xx_led_driver);
}
static void __exit s3c24xx_led_exit(void)
{
platform_driver_unregister(&s3c24xx_led_driver);
}
module_init(s3c24xx_led_init);
module_exit(s3c24xx_led_exit);
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
MODULE_DESCRIPTION("S3C24XX LED driver");
MODULE_LICENSE("GPL");

124
drivers/leds/leds-spitz.c Normal file
View File

@@ -0,0 +1,124 @@
/*
* LED Triggers Core
*
* Copyright 2005-2006 Openedhand Ltd.
*
* Author: Richard Purdie <rpurdie@openedhand.com>
*
* 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/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <asm/hardware/scoop.h>
#include <asm/mach-types.h>
#include <asm/arch/hardware.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/spitz.h>
static void spitzled_amber_set(struct led_classdev *led_cdev, enum led_brightness value)
{
if (value)
set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE);
else
reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE);
}
static void spitzled_green_set(struct led_classdev *led_cdev, enum led_brightness value)
{
if (value)
set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN);
else
reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN);
}
static struct led_classdev spitz_amber_led = {
.name = "spitz:amber",
.default_trigger = "sharpsl-charge",
.brightness_set = spitzled_amber_set,
};
static struct led_classdev spitz_green_led = {
.name = "spitz:green",
.default_trigger = "ide-disk",
.brightness_set = spitzled_green_set,
};
#ifdef CONFIG_PM
static int spitzled_suspend(struct platform_device *dev, pm_message_t state)
{
#ifdef CONFIG_LEDS_TRIGGERS
if (spitz_amber_led.trigger && strcmp(spitz_amber_led.trigger->name, "sharpsl-charge"))
#endif
led_classdev_suspend(&spitz_amber_led);
led_classdev_suspend(&spitz_green_led);
return 0;
}
static int spitzled_resume(struct platform_device *dev)
{
led_classdev_resume(&spitz_amber_led);
led_classdev_resume(&spitz_green_led);
return 0;
}
#endif
static int spitzled_probe(struct platform_device *pdev)
{
int ret;
if (machine_is_akita())
spitz_green_led.default_trigger = "nand-disk";
ret = led_classdev_register(&pdev->dev, &spitz_amber_led);
if (ret < 0)
return ret;
ret = led_classdev_register(&pdev->dev, &spitz_green_led);
if (ret < 0)
led_classdev_unregister(&spitz_amber_led);
return ret;
}
static int spitzled_remove(struct platform_device *pdev)
{
led_classdev_unregister(&spitz_amber_led);
led_classdev_unregister(&spitz_green_led);
return 0;
}
static struct platform_driver spitzled_driver = {
.probe = spitzled_probe,
.remove = spitzled_remove,
#ifdef CONFIG_PM
.suspend = spitzled_suspend,
.resume = spitzled_resume,
#endif
.driver = {
.name = "spitz-led",
},
};
static int __init spitzled_init(void)
{
return platform_driver_register(&spitzled_driver);
}
static void __exit spitzled_exit(void)
{
platform_driver_unregister(&spitzled_driver);
}
module_init(spitzled_init);
module_exit(spitzled_exit);
MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
MODULE_DESCRIPTION("Spitz LED driver");
MODULE_LICENSE("GPL");

130
drivers/leds/leds-tosa.c Normal file
View File

@@ -0,0 +1,130 @@
/*
* LED Triggers Core
*
* Copyright 2005 Dirk Opfer
*
* Author: Dirk Opfer <Dirk@Opfer-Online.de>
* based on spitz.c
*
* 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/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <asm/hardware/scoop.h>
#include <asm/mach-types.h>
#include <asm/arch/hardware.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/tosa.h>
static void tosaled_amber_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
if (value)
set_scoop_gpio(&tosascoop_jc_device.dev,
TOSA_SCOOP_JC_CHRG_ERR_LED);
else
reset_scoop_gpio(&tosascoop_jc_device.dev,
TOSA_SCOOP_JC_CHRG_ERR_LED);
}
static void tosaled_green_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
if (value)
set_scoop_gpio(&tosascoop_jc_device.dev,
TOSA_SCOOP_JC_NOTE_LED);
else
reset_scoop_gpio(&tosascoop_jc_device.dev,
TOSA_SCOOP_JC_NOTE_LED);
}
static struct led_classdev tosa_amber_led = {
.name = "tosa:amber",
.default_trigger = "sharpsl-charge",
.brightness_set = tosaled_amber_set,
};
static struct led_classdev tosa_green_led = {
.name = "tosa:green",
.default_trigger = "nand-disk",
.brightness_set = tosaled_green_set,
};
#ifdef CONFIG_PM
static int tosaled_suspend(struct platform_device *dev, pm_message_t state)
{
#ifdef CONFIG_LEDS_TRIGGERS
if (tosa_amber_led.trigger && strcmp(tosa_amber_led.trigger->name,
"sharpsl-charge"))
#endif
led_classdev_suspend(&tosa_amber_led);
led_classdev_suspend(&tosa_green_led);
return 0;
}
static int tosaled_resume(struct platform_device *dev)
{
led_classdev_resume(&tosa_amber_led);
led_classdev_resume(&tosa_green_led);
return 0;
}
#else
#define tosaled_suspend NULL
#define tosaled_resume NULL
#endif
static int tosaled_probe(struct platform_device *pdev)
{
int ret;
ret = led_classdev_register(&pdev->dev, &tosa_amber_led);
if (ret < 0)
return ret;
ret = led_classdev_register(&pdev->dev, &tosa_green_led);
if (ret < 0)
led_classdev_unregister(&tosa_amber_led);
return ret;
}
static int tosaled_remove(struct platform_device *pdev)
{
led_classdev_unregister(&tosa_amber_led);
led_classdev_unregister(&tosa_green_led);
return 0;
}
static struct platform_driver tosaled_driver = {
.probe = tosaled_probe,
.remove = tosaled_remove,
.suspend = tosaled_suspend,
.resume = tosaled_resume,
.driver = {
.name = "tosa-led",
},
};
static int __init tosaled_init(void)
{
return platform_driver_register(&tosaled_driver);
}
static void __exit tosaled_exit(void)
{
platform_driver_unregister(&tosaled_driver);
}
module_init(tosaled_init);
module_exit(tosaled_exit);
MODULE_AUTHOR("Dirk Opfer <Dirk@Opfer-Online.de>");
MODULE_DESCRIPTION("Tosa LED driver");
MODULE_LICENSE("GPL");

142
drivers/leds/leds-wrap.c Normal file
View File

@@ -0,0 +1,142 @@
/*
* LEDs driver for PCEngines WRAP
*
* Copyright (C) 2006 Kristian Kielhofner <kris@krisk.org>
*
* Based on leds-net48xx.c
*
* 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/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/err.h>
#include <asm/io.h>
#include <linux/scx200_gpio.h>
#define DRVNAME "wrap-led"
#define WRAP_ERROR_LED_GPIO 3
#define WRAP_EXTRA_LED_GPIO 18
static struct platform_device *pdev;
static void wrap_error_led_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
if (value)
scx200_gpio_set_low(WRAP_ERROR_LED_GPIO);
else
scx200_gpio_set_high(WRAP_ERROR_LED_GPIO);
}
static void wrap_extra_led_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
if (value)
scx200_gpio_set_low(WRAP_EXTRA_LED_GPIO);
else
scx200_gpio_set_high(WRAP_EXTRA_LED_GPIO);
}
static struct led_classdev wrap_error_led = {
.name = "wrap:error",
.brightness_set = wrap_error_led_set,
};
static struct led_classdev wrap_extra_led = {
.name = "wrap:extra",
.brightness_set = wrap_extra_led_set,
};
#ifdef CONFIG_PM
static int wrap_led_suspend(struct platform_device *dev,
pm_message_t state)
{
led_classdev_suspend(&wrap_error_led);
led_classdev_suspend(&wrap_extra_led);
return 0;
}
static int wrap_led_resume(struct platform_device *dev)
{
led_classdev_resume(&wrap_error_led);
led_classdev_resume(&wrap_extra_led);
return 0;
}
#else
#define wrap_led_suspend NULL
#define wrap_led_resume NULL
#endif
static int wrap_led_probe(struct platform_device *pdev)
{
int ret;
ret = led_classdev_register(&pdev->dev, &wrap_error_led);
if (ret == 0) {
ret = led_classdev_register(&pdev->dev, &wrap_extra_led);
if (ret < 0)
led_classdev_unregister(&wrap_error_led);
}
return ret;
}
static int wrap_led_remove(struct platform_device *pdev)
{
led_classdev_unregister(&wrap_error_led);
led_classdev_unregister(&wrap_extra_led);
return 0;
}
static struct platform_driver wrap_led_driver = {
.probe = wrap_led_probe,
.remove = wrap_led_remove,
.suspend = wrap_led_suspend,
.resume = wrap_led_resume,
.driver = {
.name = DRVNAME,
.owner = THIS_MODULE,
},
};
static int __init wrap_led_init(void)
{
int ret;
if (!scx200_gpio_present()) {
ret = -ENODEV;
goto out;
}
ret = platform_driver_register(&wrap_led_driver);
if (ret < 0)
goto out;
pdev = platform_device_register_simple(DRVNAME, -1, NULL, 0);
if (IS_ERR(pdev)) {
ret = PTR_ERR(pdev);
platform_driver_unregister(&wrap_led_driver);
goto out;
}
out:
return ret;
}
static void __exit wrap_led_exit(void)
{
platform_device_unregister(pdev);
platform_driver_unregister(&wrap_led_driver);
}
module_init(wrap_led_init);
module_exit(wrap_led_exit);
MODULE_AUTHOR("Kristian Kielhofner <kris@krisk.org>");
MODULE_DESCRIPTION("PCEngines WRAP LED driver");
MODULE_LICENSE("GPL");

44
drivers/leds/leds.h Normal file
View File

@@ -0,0 +1,44 @@
/*
* LED Core
*
* Copyright 2005 Openedhand Ltd.
*
* Author: Richard Purdie <rpurdie@openedhand.com>
*
* 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.
*
*/
#ifndef __LEDS_H_INCLUDED
#define __LEDS_H_INCLUDED
#include <linux/leds.h>
static inline void led_set_brightness(struct led_classdev *led_cdev,
enum led_brightness value)
{
if (value > LED_FULL)
value = LED_FULL;
led_cdev->brightness = value;
if (!(led_cdev->flags & LED_SUSPENDED))
led_cdev->brightness_set(led_cdev, value);
}
extern rwlock_t leds_list_lock;
extern struct list_head leds_list;
#ifdef CONFIG_LEDS_TRIGGERS
void led_trigger_set_default(struct led_classdev *led_cdev);
void led_trigger_set(struct led_classdev *led_cdev,
struct led_trigger *trigger);
#else
#define led_trigger_set_default(x) do {} while(0)
#define led_trigger_set(x, y) do {} while(0)
#endif
ssize_t led_trigger_store(struct class_device *dev, const char *buf,
size_t count);
ssize_t led_trigger_show(struct class_device *dev, char *buf);
#endif /* __LEDS_H_INCLUDED */

View File

@@ -0,0 +1,118 @@
/*
* LED Heartbeat Trigger
*
* Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp>
*
* Based on Richard Purdie's ledtrig-timer.c and some arch's
* CONFIG_HEARTBEAT code.
*
* 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/init.h>
#include <linux/timer.h>
#include <linux/sched.h>
#include <linux/leds.h>
#include "leds.h"
struct heartbeat_trig_data {
unsigned int phase;
unsigned int period;
struct timer_list timer;
};
static void led_heartbeat_function(unsigned long data)
{
struct led_classdev *led_cdev = (struct led_classdev *) data;
struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
unsigned long brightness = LED_OFF;
unsigned long delay = 0;
/* acts like an actual heart beat -- ie thump-thump-pause... */
switch (heartbeat_data->phase) {
case 0:
/*
* The hyperbolic function below modifies the
* heartbeat period length in dependency of the
* current (1min) load. It goes through the points
* f(0)=1260, f(1)=860, f(5)=510, f(inf)->300.
*/
heartbeat_data->period = 300 +
(6720 << FSHIFT) / (5 * avenrun[0] + (7 << FSHIFT));
heartbeat_data->period =
msecs_to_jiffies(heartbeat_data->period);
delay = msecs_to_jiffies(70);
heartbeat_data->phase++;
brightness = LED_FULL;
break;
case 1:
delay = heartbeat_data->period / 4 - msecs_to_jiffies(70);
heartbeat_data->phase++;
break;
case 2:
delay = msecs_to_jiffies(70);
heartbeat_data->phase++;
brightness = LED_FULL;
break;
default:
delay = heartbeat_data->period - heartbeat_data->period / 4 -
msecs_to_jiffies(70);
heartbeat_data->phase = 0;
break;
}
led_set_brightness(led_cdev, brightness);
mod_timer(&heartbeat_data->timer, jiffies + delay);
}
static void heartbeat_trig_activate(struct led_classdev *led_cdev)
{
struct heartbeat_trig_data *heartbeat_data;
heartbeat_data = kzalloc(sizeof(*heartbeat_data), GFP_KERNEL);
if (!heartbeat_data)
return;
led_cdev->trigger_data = heartbeat_data;
setup_timer(&heartbeat_data->timer,
led_heartbeat_function, (unsigned long) led_cdev);
heartbeat_data->phase = 0;
led_heartbeat_function(heartbeat_data->timer.data);
}
static void heartbeat_trig_deactivate(struct led_classdev *led_cdev)
{
struct heartbeat_trig_data *heartbeat_data = led_cdev->trigger_data;
if (heartbeat_data) {
del_timer_sync(&heartbeat_data->timer);
kfree(heartbeat_data);
}
}
static struct led_trigger heartbeat_led_trigger = {
.name = "heartbeat",
.activate = heartbeat_trig_activate,
.deactivate = heartbeat_trig_deactivate,
};
static int __init heartbeat_trig_init(void)
{
return led_trigger_register(&heartbeat_led_trigger);
}
static void __exit heartbeat_trig_exit(void)
{
led_trigger_unregister(&heartbeat_led_trigger);
}
module_init(heartbeat_trig_init);
module_exit(heartbeat_trig_exit);
MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
MODULE_DESCRIPTION("Heartbeat LED trigger");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,63 @@
/*
* LED IDE-Disk Activity Trigger
*
* Copyright 2006 Openedhand Ltd.
*
* Author: Richard Purdie <rpurdie@openedhand.com>
*
* 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/jiffies.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/leds.h>
static void ledtrig_ide_timerfunc(unsigned long data);
DEFINE_LED_TRIGGER(ledtrig_ide);
static DEFINE_TIMER(ledtrig_ide_timer, ledtrig_ide_timerfunc, 0, 0);
static int ide_activity;
static int ide_lastactivity;
void ledtrig_ide_activity(void)
{
ide_activity++;
if (!timer_pending(&ledtrig_ide_timer))
mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
}
EXPORT_SYMBOL(ledtrig_ide_activity);
static void ledtrig_ide_timerfunc(unsigned long data)
{
if (ide_lastactivity != ide_activity) {
ide_lastactivity = ide_activity;
led_trigger_event(ledtrig_ide, LED_FULL);
mod_timer(&ledtrig_ide_timer, jiffies + msecs_to_jiffies(10));
} else {
led_trigger_event(ledtrig_ide, LED_OFF);
}
}
static int __init ledtrig_ide_init(void)
{
led_trigger_register_simple("ide-disk", &ledtrig_ide);
return 0;
}
static void __exit ledtrig_ide_exit(void)
{
led_trigger_unregister_simple(ledtrig_ide);
}
module_init(ledtrig_ide_init);
module_exit(ledtrig_ide_exit);
MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
MODULE_DESCRIPTION("LED IDE Disk Activity Trigger");
MODULE_LICENSE("GPL");

View File

@@ -0,0 +1,191 @@
/*
* LED Kernel Timer Trigger
*
* Copyright 2005-2006 Openedhand Ltd.
*
* Author: Richard Purdie <rpurdie@openedhand.com>
*
* 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/jiffies.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/device.h>
#include <linux/sysdev.h>
#include <linux/timer.h>
#include <linux/ctype.h>
#include <linux/leds.h>
#include "leds.h"
struct timer_trig_data {
unsigned long delay_on; /* milliseconds on */
unsigned long delay_off; /* milliseconds off */
struct timer_list timer;
};
static void led_timer_function(unsigned long data)
{
struct led_classdev *led_cdev = (struct led_classdev *) data;
struct timer_trig_data *timer_data = led_cdev->trigger_data;
unsigned long brightness = LED_OFF;
unsigned long delay = timer_data->delay_off;
if (!timer_data->delay_on || !timer_data->delay_off) {
led_set_brightness(led_cdev, LED_OFF);
return;
}
if (!led_cdev->brightness) {
brightness = LED_FULL;
delay = timer_data->delay_on;
}
led_set_brightness(led_cdev, brightness);
mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay));
}
static ssize_t led_delay_on_show(struct class_device *dev, char *buf)
{
struct led_classdev *led_cdev = class_get_devdata(dev);
struct timer_trig_data *timer_data = led_cdev->trigger_data;
sprintf(buf, "%lu\n", timer_data->delay_on);
return strlen(buf) + 1;
}
static ssize_t led_delay_on_store(struct class_device *dev, const char *buf,
size_t size)
{
struct led_classdev *led_cdev = class_get_devdata(dev);
struct timer_trig_data *timer_data = led_cdev->trigger_data;
int ret = -EINVAL;
char *after;
unsigned long state = simple_strtoul(buf, &after, 10);
size_t count = after - buf;
if (*after && isspace(*after))
count++;
if (count == size) {
timer_data->delay_on = state;
mod_timer(&timer_data->timer, jiffies + 1);
ret = count;
}
return ret;
}
static ssize_t led_delay_off_show(struct class_device *dev, char *buf)
{
struct led_classdev *led_cdev = class_get_devdata(dev);
struct timer_trig_data *timer_data = led_cdev->trigger_data;
sprintf(buf, "%lu\n", timer_data->delay_off);
return strlen(buf) + 1;
}
static ssize_t led_delay_off_store(struct class_device *dev, const char *buf,
size_t size)
{
struct led_classdev *led_cdev = class_get_devdata(dev);
struct timer_trig_data *timer_data = led_cdev->trigger_data;
int ret = -EINVAL;
char *after;
unsigned long state = simple_strtoul(buf, &after, 10);
size_t count = after - buf;
if (*after && isspace(*after))
count++;
if (count == size) {
timer_data->delay_off = state;
mod_timer(&timer_data->timer, jiffies + 1);
ret = count;
}
return ret;
}
static CLASS_DEVICE_ATTR(delay_on, 0644, led_delay_on_show,
led_delay_on_store);
static CLASS_DEVICE_ATTR(delay_off, 0644, led_delay_off_show,
led_delay_off_store);
static void timer_trig_activate(struct led_classdev *led_cdev)
{
struct timer_trig_data *timer_data;
int rc;
timer_data = kzalloc(sizeof(struct timer_trig_data), GFP_KERNEL);
if (!timer_data)
return;
led_cdev->trigger_data = timer_data;
init_timer(&timer_data->timer);
timer_data->timer.function = led_timer_function;
timer_data->timer.data = (unsigned long) led_cdev;
rc = class_device_create_file(led_cdev->class_dev,
&class_device_attr_delay_on);
if (rc) goto err_out;
rc = class_device_create_file(led_cdev->class_dev,
&class_device_attr_delay_off);
if (rc) goto err_out_delayon;
return;
err_out_delayon:
class_device_remove_file(led_cdev->class_dev,
&class_device_attr_delay_on);
err_out:
led_cdev->trigger_data = NULL;
kfree(timer_data);
}
static void timer_trig_deactivate(struct led_classdev *led_cdev)
{
struct timer_trig_data *timer_data = led_cdev->trigger_data;
if (timer_data) {
class_device_remove_file(led_cdev->class_dev,
&class_device_attr_delay_on);
class_device_remove_file(led_cdev->class_dev,
&class_device_attr_delay_off);
del_timer_sync(&timer_data->timer);
kfree(timer_data);
}
}
static struct led_trigger timer_led_trigger = {
.name = "timer",
.activate = timer_trig_activate,
.deactivate = timer_trig_deactivate,
};
static int __init timer_trig_init(void)
{
return led_trigger_register(&timer_led_trigger);
}
static void __exit timer_trig_exit(void)
{
led_trigger_unregister(&timer_led_trigger);
}
module_init(timer_trig_init);
module_exit(timer_trig_exit);
MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
MODULE_DESCRIPTION("Timer LED trigger");
MODULE_LICENSE("GPL");