Commit ea541686 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.o-hand.com/linux-rpurdie-leds

* 'for-linus' of git://git.o-hand.com/linux-rpurdie-leds:
  leds/acpi: Fix merge fallout from acpi_driver_data change
  leds: Simplify logic in leds-ams-delta
  leds: Fix trigger registration race
  leds: Fix leds-class.c comment
  leds: Add driver for HP harddisk protection LEDs
  leds: leds-pca955x - Mark pca955x_led_set() static
  leds: Remove uneeded leds-cm-x270 driver
  leds: Remove uneeded strlen calls
  leds: Add leds-wrap default-trigger
  leds: Make default trigger fields const
  leds: Add backlight LED trigger
  leds: da903x: Add support for LEDs found on DA9030/DA9034
parents 0d876c6a 601a1b92
...@@ -113,11 +113,12 @@ config LEDS_GPIO ...@@ -113,11 +113,12 @@ config LEDS_GPIO
outputs. To be useful the particular board must have LEDs outputs. To be useful the particular board must have LEDs
and they must be connected to the GPIO lines. and they must be connected to the GPIO lines.
config LEDS_CM_X270 config LEDS_HP_DISK
tristate "LED Support for the CM-X270 LEDs" tristate "LED Support for disk protection LED on HP notebooks"
depends on LEDS_CLASS && MACH_ARMCORE depends on LEDS_CLASS && ACPI
help 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 config LEDS_CLEVO_MAIL
tristate "Mail LED on Clevo notebook (EXPERIMENTAL)" tristate "Mail LED on Clevo notebook (EXPERIMENTAL)"
...@@ -157,6 +158,13 @@ config LEDS_PCA955X ...@@ -157,6 +158,13 @@ config LEDS_PCA955X
LED driver chips accessed via the I2C bus. Supported LED driver chips accessed via the I2C bus. Supported
devices include PCA9550, PCA9551, PCA9552, and PCA9553. 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" comment "LED Triggers"
config LEDS_TRIGGERS config LEDS_TRIGGERS
...@@ -193,6 +201,15 @@ config LEDS_TRIGGER_HEARTBEAT ...@@ -193,6 +201,15 @@ config LEDS_TRIGGER_HEARTBEAT
load average. load average.
If unsure, say Y. 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 config LEDS_TRIGGER_DEFAULT_ON
tristate "LED Default ON Trigger" tristate "LED Default ON Trigger"
depends on LEDS_TRIGGERS depends on LEDS_TRIGGERS
......
...@@ -17,14 +17,16 @@ obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o ...@@ -17,14 +17,16 @@ obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o
obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o
obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o
obj-$(CONFIG_LEDS_GPIO) += leds-gpio.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_CLEVO_MAIL) += leds-clevo-mail.o
obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
obj-$(CONFIG_LEDS_FSG) += leds-fsg.o obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.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 # LED Triggers
obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o
obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.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 obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
...@@ -34,14 +34,11 @@ static ssize_t led_brightness_show(struct device *dev, ...@@ -34,14 +34,11 @@ static ssize_t led_brightness_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct led_classdev *led_cdev = dev_get_drvdata(dev); struct led_classdev *led_cdev = dev_get_drvdata(dev);
ssize_t ret = 0;
/* no lock needed for this */ /* no lock needed for this */
led_update_brightness(led_cdev); 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, static ssize_t led_brightness_store(struct device *dev,
...@@ -113,6 +110,9 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) ...@@ -113,6 +110,9 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
if (rc) if (rc)
goto err_out; goto err_out;
#ifdef CONFIG_LEDS_TRIGGERS
init_rwsem(&led_cdev->trigger_lock);
#endif
/* add to the list of leds */ /* add to the list of leds */
down_write(&leds_list_lock); down_write(&leds_list_lock);
list_add_tail(&led_cdev->node, &leds_list); list_add_tail(&led_cdev->node, &leds_list);
...@@ -121,8 +121,6 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) ...@@ -121,8 +121,6 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
led_update_brightness(led_cdev); led_update_brightness(led_cdev);
#ifdef CONFIG_LEDS_TRIGGERS #ifdef CONFIG_LEDS_TRIGGERS
init_rwsem(&led_cdev->trigger_lock);
rc = device_create_file(led_cdev->dev, &dev_attr_trigger); rc = device_create_file(led_cdev->dev, &dev_attr_trigger);
if (rc) if (rc)
goto err_out_led_list; goto err_out_led_list;
...@@ -147,7 +145,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) ...@@ -147,7 +145,7 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
EXPORT_SYMBOL_GPL(led_classdev_register); 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 * @led_cdev: the led device to unregister
* *
* Unregisters a previously registered via led_classdev_register object. * Unregisters a previously registered via led_classdev_register object.
......
...@@ -107,19 +107,19 @@ static int ams_delta_led_resume(struct platform_device *dev) ...@@ -107,19 +107,19 @@ static int ams_delta_led_resume(struct platform_device *dev)
static int ams_delta_led_probe(struct platform_device *pdev) static int ams_delta_led_probe(struct platform_device *pdev)
{ {
int i; int i, ret;
int 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, ret = led_classdev_register(&pdev->dev,
&ams_delta_leds[i].cdev); &ams_delta_leds[i].cdev);
if (ret < 0)
goto fail;
} }
if (ret < 0 && i > 1) { return 0;
for (i = i - 2; i >= 0; i--) fail:
while (--i >= 0)
led_classdev_unregister(&ams_delta_leds[i].cdev); led_classdev_unregister(&ams_delta_leds[i].cdev);
}
return ret; return ret;
} }
...@@ -127,7 +127,7 @@ static int ams_delta_led_remove(struct platform_device *pdev) ...@@ -127,7 +127,7 @@ static int ams_delta_led_remove(struct platform_device *pdev)
{ {
int i; 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); led_classdev_unregister(&ams_delta_leds[i].cdev);
return 0; return 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");
/*
* 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");
/*
* 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 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);
...@@ -226,7 +226,7 @@ static void pca955x_led_work(struct work_struct *work) ...@@ -226,7 +226,7 @@ static void pca955x_led_work(struct work_struct *work)
pca955x_write_ls(pca955x->client, chip_ls, ls); 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; struct pca955x_led *pca955x;
......
...@@ -55,6 +55,7 @@ static void wrap_extra_led_set(struct led_classdev *led_cdev, ...@@ -55,6 +55,7 @@ static void wrap_extra_led_set(struct led_classdev *led_cdev,
static struct led_classdev wrap_power_led = { static struct led_classdev wrap_power_led = {
.name = "wrap::power", .name = "wrap::power",
.brightness_set = wrap_power_led_set, .brightness_set = wrap_power_led_set,
.default_trigger = "default-on",
}; };
static struct led_classdev wrap_error_led = { static struct led_classdev wrap_error_led = {
......
/*
* 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");
...@@ -70,9 +70,7 @@ static ssize_t led_delay_on_show(struct device *dev, ...@@ -70,9 +70,7 @@ static ssize_t led_delay_on_show(struct device *dev,
struct led_classdev *led_cdev = dev_get_drvdata(dev); struct led_classdev *led_cdev = dev_get_drvdata(dev);
struct timer_trig_data *timer_data = led_cdev->trigger_data; struct timer_trig_data *timer_data = led_cdev->trigger_data;
sprintf(buf, "%lu\n", timer_data->delay_on); return sprintf(buf, "%lu\n", timer_data->delay_on);
return strlen(buf) + 1;
} }
static ssize_t led_delay_on_store(struct device *dev, static ssize_t led_delay_on_store(struct device *dev,
...@@ -116,9 +114,7 @@ static ssize_t led_delay_off_show(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 led_classdev *led_cdev = dev_get_drvdata(dev);
struct timer_trig_data *timer_data = led_cdev->trigger_data; struct timer_trig_data *timer_data = led_cdev->trigger_data;
sprintf(buf, "%lu\n", timer_data->delay_off); return sprintf(buf, "%lu\n", timer_data->delay_off);
return strlen(buf) + 1;
} }
static ssize_t led_delay_off_store(struct device *dev, static ssize_t led_delay_off_store(struct device *dev,
......
...@@ -123,7 +123,7 @@ extern void ledtrig_ide_activity(void); ...@@ -123,7 +123,7 @@ extern void ledtrig_ide_activity(void);
*/ */
struct led_info { struct led_info {
const char *name; const char *name;
char *default_trigger; const char *default_trigger;
int flags; int flags;
}; };
...@@ -135,7 +135,7 @@ struct led_platform_data { ...@@ -135,7 +135,7 @@ struct led_platform_data {
/* For the leds-gpio driver */ /* For the leds-gpio driver */
struct gpio_led { struct gpio_led {
const char *name; const char *name;
char *default_trigger; const char *default_trigger;
unsigned gpio; unsigned gpio;
u8 active_low; u8 active_low;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment