diff options
Diffstat (limited to 'drivers/leds')
-rw-r--r-- | drivers/leds/Kconfig | 49 | ||||
-rw-r--r-- | drivers/leds/Makefile | 7 | ||||
-rw-r--r-- | drivers/leds/led-class.c | 16 | ||||
-rw-r--r-- | drivers/leds/leds-ams-delta.c | 20 | ||||
-rw-r--r-- | drivers/leds/leds-cm-x270.c | 124 | ||||
-rw-r--r-- | drivers/leds/leds-corgi.c | 124 | ||||
-rw-r--r-- | drivers/leds/leds-da903x.c | 175 | ||||
-rw-r--r-- | drivers/leds/leds-hp-disk.c | 156 | ||||
-rw-r--r-- | drivers/leds/leds-hp6xx.c | 2 | ||||
-rw-r--r-- | drivers/leds/leds-pca955x.c | 2 | ||||
-rw-r--r-- | drivers/leds/leds-spitz.c | 131 | ||||
-rw-r--r-- | drivers/leds/leds-sunfire.c | 273 | ||||
-rw-r--r-- | drivers/leds/leds-wrap.c | 5 | ||||
-rw-r--r-- | drivers/leds/ledtrig-backlight.c | 110 | ||||
-rw-r--r-- | drivers/leds/ledtrig-timer.c | 8 |
15 files changed, 772 insertions, 430 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 9556262dda5a..e7fb7d2fcbfc 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -24,13 +24,6 @@ config LEDS_ATMEL_PWM This option enables support for LEDs driven using outputs of the dedicated PWM controller found on newer Atmel SOCs. -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 @@ -38,13 +31,6 @@ config LEDS_LOCOMO 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_S3C24XX tristate "LED Support for Samsung S3C24XX GPIO LEDs" depends on LEDS_CLASS && ARCH_S3C2410 @@ -96,6 +82,14 @@ config LEDS_COBALT_RAQ help This option enables support for the Cobalt Raq series LEDs. +config LEDS_SUNFIRE + tristate "LED support for SunFire servers." + depends on LEDS_CLASS && SPARC64 + select LEDS_TRIGGERS + help + This option enables support for the Left, Middle, and Right + LEDs on the I/O and CPU boards of SunFire UltraSPARC servers. + config LEDS_HP6XX tristate "LED Support for the HP Jornada 6xx" depends on LEDS_CLASS && SH_HP6XX @@ -119,11 +113,12 @@ config LEDS_GPIO outputs. To be useful the particular board must have LEDs and they must be connected to the GPIO lines. -config LEDS_CM_X270 - tristate "LED Support for the CM-X270 LEDs" - depends on LEDS_CLASS && MACH_ARMCORE +config LEDS_HP_DISK + tristate "LED Support for disk protection LED on HP notebooks" + depends on LEDS_CLASS && ACPI help - This option enables support for the CM-X270 LEDs. + This option enable support for disk protection LED, found on + newer HP notebooks. config LEDS_CLEVO_MAIL tristate "Mail LED on Clevo notebook (EXPERIMENTAL)" @@ -163,6 +158,13 @@ config LEDS_PCA955X LED driver chips accessed via the I2C bus. Supported devices include PCA9550, PCA9551, PCA9552, and PCA9553. +config LEDS_DA903X + tristate "LED Support for DA9030/DA9034 PMIC" + depends on LEDS_CLASS && PMIC_DA903X + help + This option enables support for on-chip LED drivers found + on Dialog Semiconductor DA9030/DA9034 PMICs. + comment "LED Triggers" config LEDS_TRIGGERS @@ -185,7 +187,7 @@ config LEDS_TRIGGER_TIMER config LEDS_TRIGGER_IDE_DISK bool "LED IDE Disk Trigger" - depends on LEDS_TRIGGERS && BLK_DEV_IDEDISK + depends on LEDS_TRIGGERS && IDE_GD_ATA help This allows LEDs to be controlled by IDE disk activity. If unsure, say Y. @@ -199,6 +201,15 @@ config LEDS_TRIGGER_HEARTBEAT load average. If unsure, say Y. +config LEDS_TRIGGER_BACKLIGHT + tristate "LED backlight Trigger" + depends on LEDS_TRIGGERS + help + This allows LEDs to be controlled as a backlight device: they + turn off and on when the display is blanked and unblanked. + + If unsure, say N. + config LEDS_TRIGGER_DEFAULT_ON tristate "LED Default ON Trigger" depends on LEDS_TRIGGERS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index ff7982b44565..e1967a29850e 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -6,9 +6,7 @@ obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o # LED Platform Drivers obj-$(CONFIG_LEDS_ATMEL_PWM) += leds-atmel-pwm.o -obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o -obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o @@ -16,16 +14,19 @@ obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o obj-$(CONFIG_LEDS_H1940) += leds-h1940.o obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o +obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o 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 obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o +obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o +obj-$(CONFIG_LEDS_HP_DISK) += leds-hp-disk.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_BACKLIGHT) += ledtrig-backlight.o obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 559a40861c39..6c4a326176d7 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -34,14 +34,11 @@ 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; - return ret; + return sprintf(buf, "%u\n", led_cdev->brightness); } static ssize_t led_brightness_store(struct device *dev, @@ -103,8 +100,8 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) { int rc; - led_cdev->dev = device_create_drvdata(leds_class, parent, 0, led_cdev, - "%s", led_cdev->name); + led_cdev->dev = device_create(leds_class, parent, 0, led_cdev, + "%s", led_cdev->name); if (IS_ERR(led_cdev->dev)) return PTR_ERR(led_cdev->dev); @@ -113,6 +110,9 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) if (rc) goto err_out; +#ifdef CONFIG_LEDS_TRIGGERS + init_rwsem(&led_cdev->trigger_lock); +#endif /* add to the list of leds */ down_write(&leds_list_lock); list_add_tail(&led_cdev->node, &leds_list); @@ -121,8 +121,6 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) led_update_brightness(led_cdev); #ifdef CONFIG_LEDS_TRIGGERS - init_rwsem(&led_cdev->trigger_lock); - rc = device_create_file(led_cdev->dev, &dev_attr_trigger); if (rc) goto err_out_led_list; @@ -147,7 +145,7 @@ err_out: EXPORT_SYMBOL_GPL(led_classdev_register); /** - * __led_classdev_unregister - unregisters a object of led_properties class. + * 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. diff --git a/drivers/leds/leds-ams-delta.c b/drivers/leds/leds-ams-delta.c index 32c98b2efa3f..1bd590bb3a6e 100644 --- a/drivers/leds/leds-ams-delta.c +++ b/drivers/leds/leds-ams-delta.c @@ -107,27 +107,27 @@ static int ams_delta_led_resume(struct platform_device *dev) static int ams_delta_led_probe(struct platform_device *pdev) { - int i; - int ret; + int i, ret; - for (i = ret = 0; ret >= 0 && i < ARRAY_SIZE(ams_delta_leds); i++) { + for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++) { ret = led_classdev_register(&pdev->dev, &ams_delta_leds[i].cdev); + if (ret < 0) + goto fail; } - if (ret < 0 && i > 1) { - for (i = i - 2; i >= 0; i--) - led_classdev_unregister(&ams_delta_leds[i].cdev); - } - - return ret; + return 0; +fail: + while (--i >= 0) + 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--) + for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i--) led_classdev_unregister(&ams_delta_leds[i].cdev); return 0; diff --git a/drivers/leds/leds-cm-x270.c b/drivers/leds/leds-cm-x270.c deleted file mode 100644 index 836a43d776e6..000000000000 --- a/drivers/leds/leds-cm-x270.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * drivers/leds/leds-cm-x270.c - * - * Copyright 2007 CompuLab Ltd. - * Author: Mike Rapoport <mike@compulab.co.il> - * - * Based on leds-corgi.c - * 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 <mach/hardware.h> -#include <mach/pxa-regs.h> - -#define GPIO_RED_LED (93) -#define GPIO_GREEN_LED (94) - -static void cmx270_red_set(struct led_classdev *led_cdev, - enum led_brightness value) -{ - if (value) - GPCR(GPIO_RED_LED) = GPIO_bit(GPIO_RED_LED); - else - GPSR(GPIO_RED_LED) = GPIO_bit(GPIO_RED_LED); -} - -static void cmx270_green_set(struct led_classdev *led_cdev, - enum led_brightness value) -{ - if (value) - GPCR(GPIO_GREEN_LED) = GPIO_bit(GPIO_GREEN_LED); - else - GPSR(GPIO_GREEN_LED) = GPIO_bit(GPIO_GREEN_LED); -} - -static struct led_classdev cmx270_red_led = { - .name = "cm-x270:red", - .default_trigger = "nand-disk", - .brightness_set = cmx270_red_set, -}; - -static struct led_classdev cmx270_green_led = { - .name = "cm-x270:green", - .default_trigger = "heartbeat", - .brightness_set = cmx270_green_set, -}; - -#ifdef CONFIG_PM -static int cmx270led_suspend(struct platform_device *dev, pm_message_t state) -{ - led_classdev_suspend(&cmx270_red_led); - led_classdev_suspend(&cmx270_green_led); - return 0; -} - -static int cmx270led_resume(struct platform_device *dev) -{ - led_classdev_resume(&cmx270_red_led); - led_classdev_resume(&cmx270_green_led); - return 0; -} -#endif - -static int cmx270led_probe(struct platform_device *pdev) -{ - int ret; - - ret = led_classdev_register(&pdev->dev, &cmx270_red_led); - if (ret < 0) - return ret; - - ret = led_classdev_register(&pdev->dev, &cmx270_green_led); - if (ret < 0) - led_classdev_unregister(&cmx270_red_led); - - return ret; -} - -static int cmx270led_remove(struct platform_device *pdev) -{ - led_classdev_unregister(&cmx270_red_led); - led_classdev_unregister(&cmx270_green_led); - return 0; -} - -static struct platform_driver cmx270led_driver = { - .probe = cmx270led_probe, - .remove = cmx270led_remove, -#ifdef CONFIG_PM - .suspend = cmx270led_suspend, - .resume = cmx270led_resume, -#endif - .driver = { - .name = "cm-x270-led", - .owner = THIS_MODULE, - }, -}; - -static int __init cmx270led_init(void) -{ - return platform_driver_register(&cmx270led_driver); -} - -static void __exit cmx270led_exit(void) -{ - platform_driver_unregister(&cmx270led_driver); -} - -module_init(cmx270led_init); -module_exit(cmx270led_exit); - -MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); -MODULE_DESCRIPTION("CM-x270 LED driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:cm-x270-led"); diff --git a/drivers/leds/leds-corgi.c b/drivers/leds/leds-corgi.c deleted file mode 100644 index bc2dcd89f635..000000000000 --- a/drivers/leds/leds-corgi.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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 <mach/corgi.h> -#include <mach/hardware.h> -#include <mach/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:charge", - .default_trigger = "sharpsl-charge", - .brightness_set = corgiled_amber_set, -}; - -static struct led_classdev corgi_green_led = { - .name = "corgi:green:mail", - .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", - .owner = THIS_MODULE, - }, -}; - -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"); -MODULE_ALIAS("platform:corgi-led"); diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c new file mode 100644 index 000000000000..f1fddb18d70d --- /dev/null +++ b/drivers/leds/leds-da903x.c @@ -0,0 +1,175 @@ +/* + * LEDs driver for Dialog Semiconductor DA9030/DA9034 + * + * Copyright (C) 2008 Compulab, Ltd. + * Mike Rapoport <mike@compulab.co.il> + * + * Copyright (C) 2006-2008 Marvell International Ltd. + * Eric Miao <eric.miao@marvell.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/platform_device.h> +#include <linux/leds.h> +#include <linux/mfd/da903x.h> + +#define DA9030_LED1_CONTROL 0x20 +#define DA9030_LED2_CONTROL 0x21 +#define DA9030_LED3_CONTROL 0x22 +#define DA9030_LED4_CONTROL 0x23 +#define DA9030_LEDPC_CONTROL 0x24 +#define DA9030_MISC_CONTROL_A 0x26 /* Vibrator Control */ + +#define DA9034_LED1_CONTROL 0x35 +#define DA9034_LED2_CONTROL 0x36 +#define DA9034_VIBRA 0x40 + +struct da903x_led { + struct led_classdev cdev; + struct work_struct work; + struct device *master; + enum led_brightness new_brightness; + int id; + int flags; +}; + +#define DA9030_LED_OFFSET(id) ((id) - DA9030_ID_LED_1) +#define DA9034_LED_OFFSET(id) ((id) - DA9034_ID_LED_1) + +static void da903x_led_work(struct work_struct *work) +{ + struct da903x_led *led = container_of(work, struct da903x_led, work); + uint8_t val; + int offset; + + switch (led->id) { + case DA9030_ID_LED_1: + case DA9030_ID_LED_2: + case DA9030_ID_LED_3: + case DA9030_ID_LED_4: + case DA9030_ID_LED_PC: + offset = DA9030_LED_OFFSET(led->id); + val = led->flags & ~0x87; + val |= (led->new_brightness) ? 0x80 : 0; /* EN bit */ + val |= (led->new_brightness >> 5) & 0x7; /* PWM<2:0> */ + da903x_write(led->master, DA9030_LED1_CONTROL + offset, val); + break; + case DA9030_ID_VIBRA: + val = led->flags & ~0x80; + val |= (led->new_brightness) ? 0x80 : 0; /* EN bit */ + da903x_write(led->master, DA9030_MISC_CONTROL_A, val); + break; + case DA9034_ID_LED_1: + case DA9034_ID_LED_2: + offset = DA9034_LED_OFFSET(led->id); + val = (led->new_brightness * 0x5f / LED_FULL) & 0x7f; + val |= (led->flags & DA9034_LED_RAMP) ? 0x80 : 0; + da903x_write(led->master, DA9034_LED1_CONTROL + offset, val); + break; + case DA9034_ID_VIBRA: + val = led->new_brightness & 0xfe; + da903x_write(led->master, DA9034_VIBRA, val); + break; + } +} + +static void da903x_led_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + struct da903x_led *led; + + led = container_of(led_cdev, struct da903x_led, cdev); + led->new_brightness = value; + schedule_work(&led->work); +} + +static int __devinit da903x_led_probe(struct platform_device *pdev) +{ + struct led_info *pdata = pdev->dev.platform_data; + struct da903x_led *led; + int id, ret; + + if (pdata == NULL) + return 0; + + id = pdev->id; + + if (!((id >= DA9030_ID_LED_1 && id <= DA9030_ID_VIBRA) || + (id >= DA9034_ID_LED_1 && id <= DA9034_ID_VIBRA))) { + dev_err(&pdev->dev, "invalid LED ID (%d) specified\n", id); + return -EINVAL; + } + + led = kzalloc(sizeof(struct da903x_led), GFP_KERNEL); + if (led == NULL) { + dev_err(&pdev->dev, "failed to alloc memory for LED%d\n", id); + return -ENOMEM; + } + + led->cdev.name = pdata->name; + led->cdev.default_trigger = pdata->default_trigger; + led->cdev.brightness_set = da903x_led_set; + led->cdev.brightness = LED_OFF; + + led->id = id; + led->flags = pdata->flags; + led->master = pdev->dev.parent; + led->new_brightness = LED_OFF; + + INIT_WORK(&led->work, da903x_led_work); + + ret = led_classdev_register(led->master, &led->cdev); + if (ret) { + dev_err(&pdev->dev, "failed to register LED %d\n", id); + goto err; + } + + platform_set_drvdata(pdev, led); + return 0; + +err: + kfree(led); + return ret; +} + +static int __devexit da903x_led_remove(struct platform_device *pdev) +{ + struct da903x_led *led = platform_get_drvdata(pdev); + + led_classdev_unregister(&led->cdev); + kfree(led); + return 0; +} + +static struct platform_driver da903x_led_driver = { + .driver = { + .name = "da903x-led", + .owner = THIS_MODULE, + }, + .probe = da903x_led_probe, + .remove = __devexit_p(da903x_led_remove), +}; + +static int __init da903x_led_init(void) +{ + return platform_driver_register(&da903x_led_driver); +} +module_init(da903x_led_init); + +static void __exit da903x_led_exit(void) +{ + platform_driver_unregister(&da903x_led_driver); +} +module_exit(da903x_led_exit); + +MODULE_DESCRIPTION("LEDs driver for Dialog Semiconductor DA9030/DA9034"); +MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>" + "Mike Rapoport <mike@compulab.co.il>"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:da903x-led"); diff --git a/drivers/leds/leds-hp-disk.c b/drivers/leds/leds-hp-disk.c new file mode 100644 index 000000000000..74645ab15660 --- /dev/null +++ b/drivers/leds/leds-hp-disk.c @@ -0,0 +1,156 @@ +/* + * leds-hp-disk.c - driver for HP "hard disk protection" LED + * + * Copyright (C) 2008 Pavel Machek + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/dmi.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/input.h> +#include <linux/kthread.h> +#include <linux/version.h> +#include <linux/leds.h> +#include <acpi/acpi_drivers.h> + +#define DRIVER_NAME "leds-hp-disk" +#define ACPI_MDPS_CLASS "led" + +/* For automatic insertion of the module */ +static struct acpi_device_id hpled_device_ids[] = { + {"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */ + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, hpled_device_ids); + +struct acpi_hpled { + struct acpi_device *device; /* The ACPI device */ +}; + +static struct acpi_hpled adev; + +static acpi_status hpled_acpi_write(acpi_handle handle, int reg) +{ + unsigned long long ret; /* Not used when writing */ + union acpi_object in_obj[1]; + struct acpi_object_list args = { 1, in_obj }; + + in_obj[0].type = ACPI_TYPE_INTEGER; + in_obj[0].integer.value = reg; + + return acpi_evaluate_integer(handle, "ALED", &args, &ret); +} + +static void hpled_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + hpled_acpi_write(adev.device->handle, !!value); +} + +static struct led_classdev hpled_led = { + .name = "hp:red:hddprotection", + .default_trigger = "heartbeat", + .brightness_set = hpled_set, +}; + +#ifdef CONFIG_PM +static int hpled_suspend(struct acpi_device *dev, pm_message_t state) +{ + led_classdev_suspend(&hpled_led); + return 0; +} + +static int hpled_resume(struct acpi_device *dev) +{ + led_classdev_resume(&hpled_led); + return 0; +} +#else +#define hpled_suspend NULL +#define hpled_resume NULL +#endif + +static int hpled_add(struct acpi_device *device) +{ + int ret; + + if (!device) + return -EINVAL; + + adev.device = device; + strcpy(acpi_device_name(device), DRIVER_NAME); + strcpy(acpi_device_class(device), ACPI_MDPS_CLASS); + device->driver_data = &adev; + + ret = led_classdev_register(NULL, &hpled_led); + return ret; +} + +static int hpled_remove(struct acpi_device *device, int type) +{ + if (!device) + return -EINVAL; + + led_classdev_unregister(&hpled_led); + return 0; +} + + + +static struct acpi_driver leds_hp_driver = { + .name = DRIVER_NAME, + .class = ACPI_MDPS_CLASS, + .ids = hpled_device_ids, + .ops = { + .add = hpled_add, + .remove = hpled_remove, + .suspend = hpled_suspend, + .resume = hpled_resume, + } +}; + +static int __init hpled_init_module(void) +{ + int ret; + + if (acpi_disabled) + return -ENODEV; + + ret = acpi_bus_register_driver(&leds_hp_driver); + if (ret < 0) + return ret; + + printk(KERN_INFO DRIVER_NAME " driver loaded.\n"); + + return 0; +} + +static void __exit hpled_exit_module(void) +{ + acpi_bus_unregister_driver(&leds_hp_driver); +} + +MODULE_DESCRIPTION("Driver for HP disk protection LED"); +MODULE_AUTHOR("Pavel Machek <pavel@suse.cz>"); +MODULE_LICENSE("GPL"); + +module_init(hpled_init_module); +module_exit(hpled_exit_module); diff --git a/drivers/leds/leds-hp6xx.c b/drivers/leds/leds-hp6xx.c index 844d5979c904..e8fb1baf8a50 100644 --- a/drivers/leds/leds-hp6xx.c +++ b/drivers/leds/leds-hp6xx.c @@ -15,7 +15,7 @@ #include <linux/platform_device.h> #include <linux/leds.h> #include <asm/hd64461.h> -#include <asm/hp6xx.h> +#include <mach/hp6xx.h> static void hp6xxled_green_set(struct led_classdev *led_cdev, enum led_brightness value) diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c index f508729123b5..4e2d1a42b48f 100644 --- a/drivers/leds/leds-pca955x.c +++ b/drivers/leds/leds-pca955x.c @@ -226,7 +226,7 @@ static void pca955x_led_work(struct work_struct *work) pca955x_write_ls(pca955x->client, chip_ls, ls); } -void pca955x_led_set(struct led_classdev *led_cdev, enum led_brightness value) +static void pca955x_led_set(struct led_classdev *led_cdev, enum led_brightness value) { struct pca955x_led *pca955x; diff --git a/drivers/leds/leds-spitz.c b/drivers/leds/leds-spitz.c deleted file mode 100644 index 178831c64bfb..000000000000 --- a/drivers/leds/leds-spitz.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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 <mach/hardware.h> -#include <mach/pxa-regs.h> -#include <mach/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:charge", - .default_trigger = "sharpsl-charge", - .brightness_set = spitzled_amber_set, -}; - -static struct led_classdev spitz_green_led = { - .name = "spitz:green:hddactivity", - .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.name = "spitz:green:mail"; - 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", - .owner = THIS_MODULE, - }, -}; - -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"); -MODULE_ALIAS("platform:spitz-led"); diff --git a/drivers/leds/leds-sunfire.c b/drivers/leds/leds-sunfire.c new file mode 100644 index 000000000000..6b008f0c3f62 --- /dev/null +++ b/drivers/leds/leds-sunfire.c @@ -0,0 +1,273 @@ +/* leds-sunfire.c: SUNW,Ultra-Enterprise LED driver. + * + * Copyright (C) 2008 David S. Miller <davem@davemloft.net> + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/leds.h> +#include <linux/io.h> +#include <linux/platform_device.h> + +#include <asm/fhc.h> +#include <asm/upa.h> + +#define DRIVER_NAME "leds-sunfire" +#define PFX DRIVER_NAME ": " + +MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); +MODULE_DESCRIPTION("Sun Fire LED driver"); +MODULE_LICENSE("GPL"); + +struct sunfire_led { + struct led_classdev led_cdev; + void __iomem *reg; +}; +#define to_sunfire_led(d) container_of(d, struct sunfire_led, led_cdev) + +static void __clockboard_set(struct led_classdev *led_cdev, + enum led_brightness led_val, u8 bit) +{ + struct sunfire_led *p = to_sunfire_led(led_cdev); + u8 reg = upa_readb(p->reg); + + switch (bit) { + case CLOCK_CTRL_LLED: + if (led_val) + reg &= ~bit; + else + reg |= bit; + break; + + default: + if (led_val) + reg |= bit; + else + reg &= ~bit; + break; + } + upa_writeb(reg, p->reg); +} + +static void clockboard_left_set(struct led_classdev *led_cdev, + enum led_brightness led_val) +{ + __clockboard_set(led_cdev, led_val, CLOCK_CTRL_LLED); +} + +static void clockboard_middle_set(struct led_classdev *led_cdev, + enum led_brightness led_val) +{ + __clockboard_set(led_cdev, led_val, CLOCK_CTRL_MLED); +} + +static void clockboard_right_set(struct led_classdev *led_cdev, + enum led_brightness led_val) +{ + __clockboard_set(led_cdev, led_val, CLOCK_CTRL_RLED); +} + +static void __fhc_set(struct led_classdev *led_cdev, + enum led_brightness led_val, u32 bit) +{ + struct sunfire_led *p = to_sunfire_led(led_cdev); + u32 reg = upa_readl(p->reg); + + switch (bit) { + case FHC_CONTROL_LLED: + if (led_val) + reg &= ~bit; + else + reg |= bit; + break; + + default: + if (led_val) + reg |= bit; + else + reg &= ~bit; + break; + } + upa_writel(reg, p->reg); +} + +static void fhc_left_set(struct led_classdev *led_cdev, + enum led_brightness led_val) +{ + __fhc_set(led_cdev, led_val, FHC_CONTROL_LLED); +} + +static void fhc_middle_set(struct led_classdev *led_cdev, + enum led_brightness led_val) +{ + __fhc_set(led_cdev, led_val, FHC_CONTROL_MLED); +} + +static void fhc_right_set(struct led_classdev *led_cdev, + enum led_brightness led_val) +{ + __fhc_set(led_cdev, led_val, FHC_CONTROL_RLED); +} + +typedef void (*set_handler)(struct led_classdev *, enum led_brightness); +struct led_type { + const char *name; + set_handler handler; + const char *default_trigger; +}; + +#define NUM_LEDS_PER_BOARD 3 +struct sunfire_drvdata { + struct sunfire_led leds[NUM_LEDS_PER_BOARD]; +}; + +static int __devinit sunfire_led_generic_probe(struct platform_device *pdev, + struct led_type *types) +{ + struct sunfire_drvdata *p; + int i, err = -EINVAL; + + if (pdev->num_resources != 1) { + printk(KERN_ERR PFX "Wrong number of resources %d, should be 1\n", + pdev->num_resources); + goto out; + } + + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) { + printk(KERN_ERR PFX "Could not allocate struct sunfire_drvdata\n"); + goto out; + } + + for (i = 0; i < NUM_LEDS_PER_BOARD; i++) { + struct led_classdev *lp = &p->leds[i].led_cdev; + + p->leds[i].reg = (void __iomem *) pdev->resource[0].start; + lp->name = types[i].name; + lp->brightness = LED_FULL; + lp->brightness_set = types[i].handler; + lp->default_trigger = types[i].default_trigger; + + err = led_classdev_register(&pdev->dev, lp); + if (err) { + printk(KERN_ERR PFX "Could not register %s LED\n", + lp->name); + goto out_unregister_led_cdevs; + } + } + + dev_set_drvdata(&pdev->dev, p); + + err = 0; +out: + return err; + +out_unregister_led_cdevs: + for (i--; i >= 0; i--) + led_classdev_unregister(&p->leds[i].led_cdev); + goto out; +} + +static int __devexit sunfire_led_generic_remove(struct platform_device *pdev) +{ + struct sunfire_drvdata *p = dev_get_drvdata(&pdev->dev); + int i; + + for (i = 0; i < NUM_LEDS_PER_BOARD; i++) + led_classdev_unregister(&p->leds[i].led_cdev); + + kfree(p); + + return 0; +} + +static struct led_type clockboard_led_types[NUM_LEDS_PER_BOARD] = { + { + .name = "clockboard-left", + .handler = clockboard_left_set, + }, + { + .name = "clockboard-middle", + .handler = clockboard_middle_set, + }, + { + .name = "clockboard-right", + .handler = clockboard_right_set, + .default_trigger= "heartbeat", + }, +}; + +static int __devinit sunfire_clockboard_led_probe(struct platform_device *pdev) +{ + return sunfire_led_generic_probe(pdev, clockboard_led_types); +} + +static struct led_type fhc_led_types[NUM_LEDS_PER_BOARD] = { + { + .name = "fhc-left", + .handler = fhc_left_set, + }, + { + .name = "fhc-middle", + .handler = fhc_middle_set, + }, + { + .name = "fhc-right", + .handler = fhc_right_set, + .default_trigger= "heartbeat", + }, +}; + +static int __devinit sunfire_fhc_led_probe(struct platform_device *pdev) +{ + return sunfire_led_generic_probe(pdev, fhc_led_types); +} + +MODULE_ALIAS("platform:sunfire-clockboard-leds"); +MODULE_ALIAS("platform:sunfire-fhc-leds"); + +static struct platform_driver sunfire_clockboard_led_driver = { + .probe = sunfire_clockboard_led_probe, + .remove = __devexit_p(sunfire_led_generic_remove), + .driver = { + .name = "sunfire-clockboard-leds", + .owner = THIS_MODULE, + }, +}; + +static struct platform_driver sunfire_fhc_led_driver = { + .probe = sunfire_fhc_led_probe, + .remove = __devexit_p(sunfire_led_generic_remove), + .driver = { + .name = "sunfire-fhc-leds", + .owner = THIS_MODULE, + }, +}; + +static int __init sunfire_leds_init(void) +{ + int err = platform_driver_register(&sunfire_clockboard_led_driver); + + if (err) { + printk(KERN_ERR PFX "Could not register clock board LED driver\n"); + return err; + } + + err = platform_driver_register(&sunfire_fhc_led_driver); + if (err) { + printk(KERN_ERR PFX "Could not register FHC LED driver\n"); + platform_driver_unregister(&sunfire_clockboard_led_driver); + } + + return err; +} + +static void __exit sunfire_leds_exit(void) +{ + platform_driver_unregister(&sunfire_clockboard_led_driver); + platform_driver_unregister(&sunfire_fhc_led_driver); +} + +module_init(sunfire_leds_init); +module_exit(sunfire_leds_exit); diff --git a/drivers/leds/leds-wrap.c b/drivers/leds/leds-wrap.c index 7ac61a7b56ad..2f3aa87f2a1f 100644 --- a/drivers/leds/leds-wrap.c +++ b/drivers/leds/leds-wrap.c @@ -53,8 +53,9 @@ static void wrap_extra_led_set(struct led_classdev *led_cdev, } static struct led_classdev wrap_power_led = { - .name = "wrap::power", - .brightness_set = wrap_power_led_set, + .name = "wrap::power", + .brightness_set = wrap_power_led_set, + .default_trigger = "default-on", }; static struct led_classdev wrap_error_led = { diff --git a/drivers/leds/ledtrig-backlight.c b/drivers/leds/ledtrig-backlight.c new file mode 100644 index 000000000000..d3dfcfb417b8 --- /dev/null +++ b/drivers/leds/ledtrig-backlight.c @@ -0,0 +1,110 @@ +/* + * 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/init.h> +#include <linux/fb.h> +#include <linux/leds.h> +#include "leds.h" + +#define BLANK 1 +#define UNBLANK 0 + +struct bl_trig_notifier { + struct led_classdev *led; + int brightness; + int old_status; + struct notifier_block notifier; +}; + +static int fb_notifier_callback(struct notifier_block *p, + unsigned long event, void *data) +{ + 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; + + switch (event) { + case FB_EVENT_BLANK : + if (*blank && n->old_status == UNBLANK) { + n->brightness = led->brightness; + led_set_brightness(led, LED_OFF); + n->old_status = BLANK; + } else if (!*blank && n->old_status == BLANK) { + led_set_brightness(led, n->brightness); + n->old_status = UNBLANK; + } + break; + } + + return 0; +} + +static void bl_trig_activate(struct led_classdev *led) +{ + int ret; + + 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; + } + + 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"); +} + +static void bl_trig_deactivate(struct led_classdev *led) +{ + struct bl_trig_notifier *n = + (struct bl_trig_notifier *) led->trigger_data; + + if (n) { + fb_unregister_client(&n->notifier); + kfree(n); + } +} + +static struct led_trigger bl_led_trigger = { + .name = "backlight", + .activate = bl_trig_activate, + .deactivate = bl_trig_deactivate +}; + +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_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); +MODULE_DESCRIPTION("Backlight emulation LED trigger"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c index 5c99f4f0c692..db681962d7bb 100644 --- a/drivers/leds/ledtrig-timer.c +++ b/drivers/leds/ledtrig-timer.c @@ -70,9 +70,7 @@ static ssize_t led_delay_on_show(struct device *dev, struct led_classdev *led_cdev = dev_get_drvdata(dev); struct timer_trig_data *timer_data = led_cdev->trigger_data; - sprintf(buf, "%lu\n", timer_data->delay_on); - - return strlen(buf) + 1; + return sprintf(buf, "%lu\n", timer_data->delay_on); } static ssize_t led_delay_on_store(struct device *dev, @@ -116,9 +114,7 @@ static ssize_t led_delay_off_show(struct device *dev, struct led_classdev *led_cdev = dev_get_drvdata(dev); struct timer_trig_data *timer_data = led_cdev->trigger_data; - sprintf(buf, "%lu\n", timer_data->delay_off); - - return strlen(buf) + 1; + return sprintf(buf, "%lu\n", timer_data->delay_off); } static ssize_t led_delay_off_store(struct device *dev, |