From 0b9536c957095eb1497828aa51b34ac695f67eae Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Fri, 7 Jan 2011 16:28:16 +0000 Subject: leds: Add ability to blink via simple trigger As blink API is now available, it's possible to add ability to blink via simple trigger. Signed-off-by: Vasily Khoruzhick Signed-off-by: Anton Vorontsov --- drivers/leds/led-triggers.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/leds') diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index c41eb6180c9..4bebae73334 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -231,6 +231,26 @@ void led_trigger_event(struct led_trigger *trigger, } EXPORT_SYMBOL_GPL(led_trigger_event); +void led_trigger_blink(struct led_trigger *trigger, + unsigned long *delay_on, + unsigned long *delay_off) +{ + 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_blink_set(led_cdev, delay_on, delay_off); + } + read_unlock(&trigger->leddev_list_lock); +} +EXPORT_SYMBOL_GPL(led_trigger_blink); + void led_trigger_register_simple(const char *name, struct led_trigger **tp) { struct led_trigger *trigger; -- cgit v1.2.3 From 551ea73838c5eba18d673bd4e7fb0fec77cdcb8a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Tue, 22 Mar 2011 16:30:14 -0700 Subject: leds: convert bd2802 driver to dev_pm_ops There is a move to deprecate bus-specific PM operations and move to using dev_pm_ops instead in order to reduce the amount of boilerplate code in buses and facilitiate updates to the PM core. Do this move for the bs2802 driver. [akpm@linux-foundation.org: fix warnings] Signed-off-by: Mark Brown Cc: Kim Kyuwon Cc: Kim Kyuwon Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/leds-bd2802.c | 47 +++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 19 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c index 19dc4b61a10..3ebe3824662 100644 --- a/drivers/leds/leds-bd2802.c +++ b/drivers/leds/leds-bd2802.c @@ -19,7 +19,7 @@ #include #include #include - +#include #define LED_CTL(rgb2en, rgb1en) ((rgb2en) << 4 | ((rgb1en) << 0)) @@ -319,20 +319,6 @@ static void bd2802_turn_off(struct bd2802_led *led, enum led_ids id, bd2802_update_state(led, id, color, BD2802_OFF); } -static void bd2802_restore_state(struct bd2802_led *led) -{ - int i; - - for (i = 0; i < LED_NUM; i++) { - if (led->led[i].r) - bd2802_turn_on(led, i, RED, led->led[i].r); - if (led->led[i].g) - bd2802_turn_on(led, i, GREEN, led->led[i].g); - if (led->led[i].b) - bd2802_turn_on(led, i, BLUE, led->led[i].b); - } -} - #define BD2802_SET_REGISTER(reg_addr, reg_name) \ static ssize_t bd2802_store_reg##reg_addr(struct device *dev, \ struct device_attribute *attr, const char *buf, size_t count) \ @@ -761,8 +747,25 @@ static int __exit bd2802_remove(struct i2c_client *client) return 0; } -static int bd2802_suspend(struct i2c_client *client, pm_message_t mesg) +#ifdef CONFIG_PM + +static void bd2802_restore_state(struct bd2802_led *led) { + int i; + + for (i = 0; i < LED_NUM; i++) { + if (led->led[i].r) + bd2802_turn_on(led, i, RED, led->led[i].r); + if (led->led[i].g) + bd2802_turn_on(led, i, GREEN, led->led[i].g); + if (led->led[i].b) + bd2802_turn_on(led, i, BLUE, led->led[i].b); + } +} + +static int bd2802_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); struct bd2802_led *led = i2c_get_clientdata(client); gpio_set_value(led->pdata->reset_gpio, 0); @@ -770,8 +773,9 @@ static int bd2802_suspend(struct i2c_client *client, pm_message_t mesg) return 0; } -static int bd2802_resume(struct i2c_client *client) +static int bd2802_resume(struct device *dev) { + struct i2c_client *client = to_i2c_client(dev); struct bd2802_led *led = i2c_get_clientdata(client); if (!bd2802_is_all_off(led) || led->adf_on) { @@ -782,6 +786,12 @@ static int bd2802_resume(struct i2c_client *client) return 0; } +static SIMPLE_DEV_PM_OPS(bd2802_pm, bd2802_suspend, bd2802_resume); +#define BD2802_PM (&bd2802_pm) +#else /* CONFIG_PM */ +#define BD2802_PM NULL +#endif + static const struct i2c_device_id bd2802_id[] = { { "BD2802", 0 }, { } @@ -791,11 +801,10 @@ MODULE_DEVICE_TABLE(i2c, bd2802_id); static struct i2c_driver bd2802_i2c_driver = { .driver = { .name = "BD2802", + .pm = BD2802_PM, }, .probe = bd2802_probe, .remove = __exit_p(bd2802_remove), - .suspend = bd2802_suspend, - .resume = bd2802_resume, .id_table = bd2802_id, }; -- cgit v1.2.3 From b1e6b7068f026e88257c20522555c78122e5a14d Mon Sep 17 00:00:00 2001 From: Shreshtha Kumar Sahu Date: Tue, 22 Mar 2011 16:30:16 -0700 Subject: leds: add driver for LM3530 ALS Simple backlight driver for National Semiconductor LM3530. Presently only manual mode is supported, PWM and ALS support to be added. Signed-off-by: Shreshtha Kumar Sahu Cc: Linus Walleij Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/Kconfig | 10 ++ drivers/leds/Makefile | 1 + drivers/leds/leds-lm3530.c | 378 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 389 insertions(+) create mode 100644 drivers/leds/leds-lm3530.c (limited to 'drivers/leds') diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 6f190f4cdbc..9bec8699b8a 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -34,6 +34,16 @@ 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_LM3530 + tristate "LCD Backlight driver for LM3530" + depends on LEDS_CLASS + depends on I2C + help + This option enables support for the LCD backlight using + LM3530 ambient light sensor chip. This ALS chip can be + controlled manually or using PWM input or using ambient + light automatically. + config LEDS_LOCOMO tristate "LED Support for Locomo device" depends on LEDS_CLASS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index aae6989ff6b..39c80fca84d 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_LEDS_88PM860X) += leds-88pm860x.o obj-$(CONFIG_LEDS_ATMEL_PWM) += leds-atmel-pwm.o obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o +obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o obj-$(CONFIG_LEDS_MIKROTIK_RB532) += leds-rb532.o obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c new file mode 100644 index 00000000000..e7089a1f6cb --- /dev/null +++ b/drivers/leds/leds-lm3530.c @@ -0,0 +1,378 @@ +/* + * Copyright (C) 2011 ST-Ericsson SA. + * Copyright (C) 2009 Motorola, Inc. + * + * License Terms: GNU General Public License v2 + * + * Simple driver for National Semiconductor LM3530 Backlight driver chip + * + * Author: Shreshtha Kumar SAHU + * based on leds-lm3530.c by Dan Murphy + */ + +#include +#include +#include +#include +#include +#include +#include + +#define LM3530_LED_DEV "lcd-backlight" +#define LM3530_NAME "lm3530-led" + +#define LM3530_GEN_CONFIG 0x10 +#define LM3530_ALS_CONFIG 0x20 +#define LM3530_BRT_RAMP_RATE 0x30 +#define LM3530_ALS_ZONE_REG 0x40 +#define LM3530_ALS_IMP_SELECT 0x41 +#define LM3530_BRT_CTRL_REG 0xA0 +#define LM3530_ALS_ZB0_REG 0x60 +#define LM3530_ALS_ZB1_REG 0x61 +#define LM3530_ALS_ZB2_REG 0x62 +#define LM3530_ALS_ZB3_REG 0x63 +#define LM3530_ALS_Z0T_REG 0x70 +#define LM3530_ALS_Z1T_REG 0x71 +#define LM3530_ALS_Z2T_REG 0x72 +#define LM3530_ALS_Z3T_REG 0x73 +#define LM3530_ALS_Z4T_REG 0x74 +#define LM3530_REG_MAX 15 + +/* General Control Register */ +#define LM3530_EN_I2C_SHIFT (0) +#define LM3530_RAMP_LAW_SHIFT (1) +#define LM3530_MAX_CURR_SHIFT (2) +#define LM3530_EN_PWM_SHIFT (5) +#define LM3530_PWM_POL_SHIFT (6) +#define LM3530_EN_PWM_SIMPLE_SHIFT (7) + +#define LM3530_ENABLE_I2C (1 << LM3530_EN_I2C_SHIFT) +#define LM3530_ENABLE_PWM (1 << LM3530_EN_PWM_SHIFT) +#define LM3530_POL_LOW (1 << LM3530_PWM_POL_SHIFT) +#define LM3530_ENABLE_PWM_SIMPLE (1 << LM3530_EN_PWM_SIMPLE_SHIFT) + +/* ALS Config Register Options */ +#define LM3530_ALS_AVG_TIME_SHIFT (0) +#define LM3530_EN_ALS_SHIFT (3) +#define LM3530_ALS_SEL_SHIFT (5) + +#define LM3530_ENABLE_ALS (3 << LM3530_EN_ALS_SHIFT) + +/* Brightness Ramp Rate Register */ +#define LM3530_BRT_RAMP_FALL_SHIFT (0) +#define LM3530_BRT_RAMP_RISE_SHIFT (3) + +/* ALS Resistor Select */ +#define LM3530_ALS1_IMP_SHIFT (0) +#define LM3530_ALS2_IMP_SHIFT (4) + +/* Zone Boundary Register defaults */ +#define LM3530_DEF_ZB_0 (0x33) +#define LM3530_DEF_ZB_1 (0x66) +#define LM3530_DEF_ZB_2 (0x99) +#define LM3530_DEF_ZB_3 (0xCC) + +/* Zone Target Register defaults */ +#define LM3530_DEF_ZT_0 (0x19) +#define LM3530_DEF_ZT_1 (0x33) +#define LM3530_DEF_ZT_2 (0x4C) +#define LM3530_DEF_ZT_3 (0x66) +#define LM3530_DEF_ZT_4 (0x7F) + +struct lm3530_mode_map { + const char *mode; + enum lm3530_mode mode_val; +}; + +static struct lm3530_mode_map mode_map[] = { + { "man", LM3530_BL_MODE_MANUAL }, + { "als", LM3530_BL_MODE_ALS }, + { "pwm", LM3530_BL_MODE_PWM }, +}; + +/** + * struct lm3530_data + * @led_dev: led class device + * @client: i2c client + * @pdata: LM3530 platform data + * @mode: mode of operation - manual, ALS, PWM + */ +struct lm3530_data { + struct led_classdev led_dev; + struct i2c_client *client; + struct lm3530_platform_data *pdata; + enum lm3530_mode mode; +}; + +static const u8 lm3530_reg[LM3530_REG_MAX] = { + LM3530_GEN_CONFIG, + LM3530_ALS_CONFIG, + LM3530_BRT_RAMP_RATE, + LM3530_ALS_ZONE_REG, + LM3530_ALS_IMP_SELECT, + LM3530_BRT_CTRL_REG, + LM3530_ALS_ZB0_REG, + LM3530_ALS_ZB1_REG, + LM3530_ALS_ZB2_REG, + LM3530_ALS_ZB3_REG, + LM3530_ALS_Z0T_REG, + LM3530_ALS_Z1T_REG, + LM3530_ALS_Z2T_REG, + LM3530_ALS_Z3T_REG, + LM3530_ALS_Z4T_REG, +}; + +static int lm3530_get_mode_from_str(const char *str) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mode_map); i++) + if (sysfs_streq(str, mode_map[i].mode)) + return mode_map[i].mode_val; + + return -1; +} + +static int lm3530_init_registers(struct lm3530_data *drvdata) +{ + int ret = 0; + int i; + u8 gen_config; + u8 als_config = 0; + u8 brt_ramp; + u8 als_imp_sel = 0; + u8 brightness; + u8 reg_val[LM3530_REG_MAX]; + struct lm3530_platform_data *pltfm = drvdata->pdata; + struct i2c_client *client = drvdata->client; + + gen_config = (pltfm->brt_ramp_law << LM3530_RAMP_LAW_SHIFT) | + ((pltfm->max_current & 7) << LM3530_MAX_CURR_SHIFT); + + if (drvdata->mode == LM3530_BL_MODE_MANUAL || + drvdata->mode == LM3530_BL_MODE_ALS) + gen_config |= (LM3530_ENABLE_I2C); + + if (drvdata->mode == LM3530_BL_MODE_ALS) { + als_config = + (pltfm->als_avrg_time << LM3530_ALS_AVG_TIME_SHIFT) | + (LM3530_ENABLE_ALS) | + (pltfm->als_input_mode << LM3530_ALS_SEL_SHIFT); + + als_imp_sel = + (pltfm->als1_resistor_sel << LM3530_ALS1_IMP_SHIFT) | + (pltfm->als2_resistor_sel << LM3530_ALS2_IMP_SHIFT); + } + + if (drvdata->mode == LM3530_BL_MODE_PWM) + gen_config |= (LM3530_ENABLE_PWM) | + (pltfm->pwm_pol_hi << LM3530_PWM_POL_SHIFT) | + (LM3530_ENABLE_PWM_SIMPLE); + + brt_ramp = (pltfm->brt_ramp_fall << LM3530_BRT_RAMP_FALL_SHIFT) | + (pltfm->brt_ramp_rise << LM3530_BRT_RAMP_RISE_SHIFT); + + brightness = pltfm->brt_val; + + reg_val[0] = gen_config; /* LM3530_GEN_CONFIG */ + reg_val[1] = als_config; /* LM3530_ALS_CONFIG */ + reg_val[2] = brt_ramp; /* LM3530_BRT_RAMP_RATE */ + reg_val[3] = 0x00; /* LM3530_ALS_ZONE_REG */ + reg_val[4] = als_imp_sel; /* LM3530_ALS_IMP_SELECT */ + reg_val[5] = brightness; /* LM3530_BRT_CTRL_REG */ + reg_val[6] = LM3530_DEF_ZB_0; /* LM3530_ALS_ZB0_REG */ + reg_val[7] = LM3530_DEF_ZB_1; /* LM3530_ALS_ZB1_REG */ + reg_val[8] = LM3530_DEF_ZB_2; /* LM3530_ALS_ZB2_REG */ + reg_val[9] = LM3530_DEF_ZB_3; /* LM3530_ALS_ZB3_REG */ + reg_val[10] = LM3530_DEF_ZT_0; /* LM3530_ALS_Z0T_REG */ + reg_val[11] = LM3530_DEF_ZT_1; /* LM3530_ALS_Z1T_REG */ + reg_val[12] = LM3530_DEF_ZT_2; /* LM3530_ALS_Z2T_REG */ + reg_val[13] = LM3530_DEF_ZT_3; /* LM3530_ALS_Z3T_REG */ + reg_val[14] = LM3530_DEF_ZT_4; /* LM3530_ALS_Z4T_REG */ + + for (i = 0; i < LM3530_REG_MAX; i++) { + ret = i2c_smbus_write_byte_data(client, + lm3530_reg[i], reg_val[i]); + if (ret) + break; + } + + return ret; +} + +static void lm3530_brightness_set(struct led_classdev *led_cdev, + enum led_brightness brt_val) +{ + int err; + struct lm3530_data *drvdata = + container_of(led_cdev, struct lm3530_data, led_dev); + + switch (drvdata->mode) { + case LM3530_BL_MODE_MANUAL: + + /* set the brightness in brightness control register*/ + err = i2c_smbus_write_byte_data(drvdata->client, + LM3530_BRT_CTRL_REG, brt_val / 2); + if (err) + dev_err(&drvdata->client->dev, + "Unable to set brightness: %d\n", err); + break; + case LM3530_BL_MODE_ALS: + break; + case LM3530_BL_MODE_PWM: + break; + default: + break; + } +} + + +static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute + *attr, const char *buf, size_t size) +{ + int err; + struct i2c_client *client = container_of( + dev->parent, struct i2c_client, dev); + struct lm3530_data *drvdata = i2c_get_clientdata(client); + int mode; + + mode = lm3530_get_mode_from_str(buf); + if (mode < 0) { + dev_err(dev, "Invalid mode\n"); + return -EINVAL; + } + + if (mode == LM3530_BL_MODE_MANUAL) + drvdata->mode = LM3530_BL_MODE_MANUAL; + else if (mode == LM3530_BL_MODE_ALS) + drvdata->mode = LM3530_BL_MODE_ALS; + else if (mode == LM3530_BL_MODE_PWM) { + dev_err(dev, "PWM mode not supported\n"); + return -EINVAL; + } + + err = lm3530_init_registers(drvdata); + if (err) { + dev_err(dev, "Setting %s Mode failed :%d\n", buf, err); + return err; + } + + return sizeof(drvdata->mode); +} + +static DEVICE_ATTR(mode, 0644, NULL, lm3530_mode_set); + +static int __devinit lm3530_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct lm3530_platform_data *pdata = client->dev.platform_data; + struct lm3530_data *drvdata; + int err = 0; + + if (pdata == NULL) { + dev_err(&client->dev, "platform data required\n"); + err = -ENODEV; + goto err_out; + } + + /* BL mode */ + if (pdata->mode > LM3530_BL_MODE_PWM) { + dev_err(&client->dev, "Illegal Mode request\n"); + err = -EINVAL; + goto err_out; + } + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { + dev_err(&client->dev, "I2C_FUNC_I2C not supported\n"); + err = -EIO; + goto err_out; + } + + drvdata = kzalloc(sizeof(struct lm3530_data), GFP_KERNEL); + if (drvdata == NULL) { + err = -ENOMEM; + goto err_out; + } + + drvdata->mode = pdata->mode; + drvdata->client = client; + drvdata->pdata = pdata; + drvdata->led_dev.name = LM3530_LED_DEV; + drvdata->led_dev.brightness_set = lm3530_brightness_set; + + i2c_set_clientdata(client, drvdata); + + err = lm3530_init_registers(drvdata); + if (err < 0) { + dev_err(&client->dev, "Register Init failed: %d\n", err); + err = -ENODEV; + goto err_reg_init; + } + + err = led_classdev_register((struct device *) + &client->dev, &drvdata->led_dev); + if (err < 0) { + dev_err(&client->dev, "Register led class failed: %d\n", err); + err = -ENODEV; + goto err_class_register; + } + + err = device_create_file(drvdata->led_dev.dev, &dev_attr_mode); + if (err < 0) { + dev_err(&client->dev, "File device creation failed: %d\n", err); + err = -ENODEV; + goto err_create_file; + } + + return 0; + +err_create_file: + led_classdev_unregister(&drvdata->led_dev); +err_class_register: +err_reg_init: + kfree(drvdata); +err_out: + return err; +} + +static int __devexit lm3530_remove(struct i2c_client *client) +{ + struct lm3530_data *drvdata = i2c_get_clientdata(client); + + device_remove_file(drvdata->led_dev.dev, &dev_attr_mode); + led_classdev_unregister(&drvdata->led_dev); + kfree(drvdata); + return 0; +} + +static const struct i2c_device_id lm3530_id[] = { + {LM3530_NAME, 0}, + {} +}; + +static struct i2c_driver lm3530_i2c_driver = { + .probe = lm3530_probe, + .remove = lm3530_remove, + .id_table = lm3530_id, + .driver = { + .name = LM3530_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init lm3530_init(void) +{ + return i2c_add_driver(&lm3530_i2c_driver); +} + +static void __exit lm3530_exit(void) +{ + i2c_del_driver(&lm3530_i2c_driver); +} + +module_init(lm3530_init); +module_exit(lm3530_exit); + +MODULE_DESCRIPTION("Back Light driver for LM3530"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Shreshtha Kumar SAHU "); -- cgit v1.2.3 From 9517f925f2eb9ffca78b3f0f9389fc675bcb572c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 22 Mar 2011 16:30:17 -0700 Subject: leds: make *struct gpio_led_platform_data.leds const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And fix a typo. Signed-off-by: Uwe Kleine-König Cc: Lars-Peter Clausen Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/leds-net5501.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-net5501.c b/drivers/leds/leds-net5501.c index 1739557a903..7e764b8365e 100644 --- a/drivers/leds/leds-net5501.c +++ b/drivers/leds/leds-net5501.c @@ -19,7 +19,7 @@ #include -static struct gpio_led net5501_leds[] = { +static const struct gpio_led net5501_leds[] = { { .name = "error", .gpio = 6, -- cgit v1.2.3 From 67d1da79b25c05d9a38b820bb5b5d89c91070ab2 Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Tue, 22 Mar 2011 16:30:19 -0700 Subject: drivers/leds/leds-lp5521.c: world-writable sysfs engine* files Don't allow everybody to change LED settings. Signed-off-by: Vasiliy Kulikov Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/leds-lp5521.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index 80a3ae3c00b..c0cff64a1ae 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c @@ -534,7 +534,7 @@ static ssize_t lp5521_selftest(struct device *dev, } /* led class device attributes */ -static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current); +static DEVICE_ATTR(led_current, S_IRUGO | S_IWUSR, show_current, store_current); static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL); static struct attribute *lp5521_led_attributes[] = { @@ -548,15 +548,15 @@ static struct attribute_group lp5521_led_attribute_group = { }; /* device attributes */ -static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUGO, +static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUSR, show_engine1_mode, store_engine1_mode); -static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUGO, +static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUSR, show_engine2_mode, store_engine2_mode); -static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUGO, +static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUSR, show_engine3_mode, store_engine3_mode); -static DEVICE_ATTR(engine1_load, S_IWUGO, NULL, store_engine1_load); -static DEVICE_ATTR(engine2_load, S_IWUGO, NULL, store_engine2_load); -static DEVICE_ATTR(engine3_load, S_IWUGO, NULL, store_engine3_load); +static DEVICE_ATTR(engine1_load, S_IWUSR, NULL, store_engine1_load); +static DEVICE_ATTR(engine2_load, S_IWUSR, NULL, store_engine2_load); +static DEVICE_ATTR(engine3_load, S_IWUSR, NULL, store_engine3_load); static DEVICE_ATTR(selftest, S_IRUGO, lp5521_selftest, NULL); static struct attribute *lp5521_attributes[] = { -- cgit v1.2.3 From ccd7510fd8dea5b4b2af87fb2aef2ebd6b23b76b Mon Sep 17 00:00:00 2001 From: Vasiliy Kulikov Date: Tue, 22 Mar 2011 16:30:20 -0700 Subject: drivers/leds/leds-lp5523.c: world-writable engine* sysfs files Don't allow everybody to change LED settings. Signed-off-by: Vasiliy Kulikov Cc: Richard Purdie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/leds-lp5523.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c index d0c4068ecdd..e19fed25f13 100644 --- a/drivers/leds/leds-lp5523.c +++ b/drivers/leds/leds-lp5523.c @@ -713,7 +713,7 @@ static ssize_t store_current(struct device *dev, } /* led class device attributes */ -static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current); +static DEVICE_ATTR(led_current, S_IRUGO | S_IWUSR, show_current, store_current); static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL); static struct attribute *lp5523_led_attributes[] = { @@ -727,21 +727,21 @@ static struct attribute_group lp5523_led_attribute_group = { }; /* device attributes */ -static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUGO, +static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUSR, show_engine1_mode, store_engine1_mode); -static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUGO, +static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUSR, show_engine2_mode, store_engine2_mode); -static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUGO, +static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUSR, show_engine3_mode, store_engine3_mode); -static DEVICE_ATTR(engine1_leds, S_IRUGO | S_IWUGO, +static DEVICE_ATTR(engine1_leds, S_IRUGO | S_IWUSR, show_engine1_leds, store_engine1_leds); -static DEVICE_ATTR(engine2_leds, S_IRUGO | S_IWUGO, +static DEVICE_ATTR(engine2_leds, S_IRUGO | S_IWUSR, show_engine2_leds, store_engine2_leds); -static DEVICE_ATTR(engine3_leds, S_IRUGO | S_IWUGO, +static DEVICE_ATTR(engine3_leds, S_IRUGO | S_IWUSR, show_engine3_leds, store_engine3_leds); -static DEVICE_ATTR(engine1_load, S_IWUGO, NULL, store_engine1_load); -static DEVICE_ATTR(engine2_load, S_IWUGO, NULL, store_engine2_load); -static DEVICE_ATTR(engine3_load, S_IWUGO, NULL, store_engine3_load); +static DEVICE_ATTR(engine1_load, S_IWUSR, NULL, store_engine1_load); +static DEVICE_ATTR(engine2_load, S_IWUSR, NULL, store_engine2_load); +static DEVICE_ATTR(engine3_load, S_IWUSR, NULL, store_engine3_load); static DEVICE_ATTR(selftest, S_IRUGO, lp5523_selftest, NULL); static struct attribute *lp5523_attributes[] = { -- cgit v1.2.3 From 4ec1b54c4d082d4bad19b55ca709da7e7138d542 Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Thu, 17 Feb 2011 19:07:23 -0800 Subject: mfd: mfd_cell is now implicitly available to mc13xxx drivers The cell's platform_data is now accessed with a helper function; change clients to use that, and remove the now-unused data_size. Note that mfd-core no longer makes a copy of platform_data, but the mc13xxx-core driver creates the pdata structures on the stack. In order to get around that, the various ARM mach types that set the pdata have been changed to hold the variable in static (global) memory. Also note that __initdata references in aforementioned pdata structs have been dropped. Signed-off-by: Andres Salomon Signed-off-by: Samuel Ortiz --- drivers/leds/leds-mc13783.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c index f05bb08d0f0..06a5bb48470 100644 --- a/drivers/leds/leds-mc13783.c +++ b/drivers/leds/leds-mc13783.c @@ -22,6 +22,7 @@ #include #include #include +#include #include struct mc13783_led { @@ -183,7 +184,7 @@ static int __devinit mc13783_led_setup(struct mc13783_led *led, int max_current) static int __devinit mc13783_leds_prepare(struct platform_device *pdev) { - struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev); struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent); int ret = 0; int reg = 0; @@ -264,7 +265,7 @@ out: static int __devinit mc13783_led_probe(struct platform_device *pdev) { - struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev); struct mc13783_led_platform_data *led_cur; struct mc13783_led *led, *led_dat; int ret, i; @@ -351,7 +352,7 @@ err_free: static int __devexit mc13783_led_remove(struct platform_device *pdev) { - struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev); struct mc13783_led *led = platform_get_drvdata(pdev); struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent); int i; -- cgit v1.2.3 From 3154c344696e58b7e15317cd624816dbe3832ad1 Mon Sep 17 00:00:00 2001 From: Haojian Zhuang Date: Mon, 7 Mar 2011 23:43:10 +0800 Subject: mfd: Adopt mfd_data in 88pm860x led Copy 88pm860x platform data into different mfd_data structure for led driver. So move the identification of device node from led driver to mfd driver. Signed-off-by: Haojian Zhuang Signed-off-by: Samuel Ortiz --- drivers/leds/leds-88pm860x.c | 60 +++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 32 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c index e672b44ee17..416def84d04 100644 --- a/drivers/leds/leds-88pm860x.c +++ b/drivers/leds/leds-88pm860x.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #define LED_PWM_SHIFT (3) @@ -118,7 +119,8 @@ static void pm860x_led_work(struct work_struct *work) struct pm860x_led *led; struct pm860x_chip *chip; - int mask; + unsigned char buf[3]; + int mask, ret; led = container_of(work, struct pm860x_led, work); chip = led->chip; @@ -128,16 +130,27 @@ static void pm860x_led_work(struct work_struct *work) pm860x_set_bits(led->i2c, __led_off(led->port), LED_CURRENT_MASK, led->iset); } + pm860x_set_bits(led->i2c, __blink_off(led->port), + LED_BLINK_MASK, LED_ON_CONTINUOUS); mask = __blink_ctl_mask(led->port); pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask); - } else if (led->brightness == 0) { - pm860x_set_bits(led->i2c, __led_off(led->port), - LED_CURRENT_MASK, 0); - mask = __blink_ctl_mask(led->port); - pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0); } pm860x_set_bits(led->i2c, __led_off(led->port), LED_PWM_MASK, led->brightness); + + if (led->brightness == 0) { + pm860x_bulk_read(led->i2c, __led_off(led->port), 3, buf); + ret = buf[0] & LED_PWM_MASK; + ret |= buf[1] & LED_PWM_MASK; + ret |= buf[2] & LED_PWM_MASK; + if (ret == 0) { + /* unset current since no led is lighting */ + pm860x_set_bits(led->i2c, __led_off(led->port), + LED_CURRENT_MASK, 0); + mask = __blink_ctl_mask(led->port); + pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0); + } + } led->current_brightness = led->brightness; dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n", __led_off(led->port), led->brightness); @@ -153,31 +166,12 @@ static void pm860x_led_set(struct led_classdev *cdev, schedule_work(&data->work); } -static int __check_device(struct pm860x_led_pdata *pdata, char *name) -{ - struct pm860x_led_pdata *p = pdata; - int ret = -EINVAL; - - while (p && p->id) { - if ((p->id != PM8606_ID_LED) || (p->flags < 0)) - break; - - if (!strncmp(name, pm860x_led_name[p->flags], - MFD_NAME_SIZE)) { - ret = (int)p->flags; - break; - } - p++; - } - return ret; -} - static int pm860x_led_probe(struct platform_device *pdev) { struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); - struct pm860x_platform_data *pm860x_pdata; struct pm860x_led_pdata *pdata; struct pm860x_led *data; + struct mfd_cell *cell; struct resource *res; int ret; @@ -187,10 +181,11 @@ static int pm860x_led_probe(struct platform_device *pdev) return -EINVAL; } - if (pdev->dev.parent->platform_data) { - pm860x_pdata = pdev->dev.parent->platform_data; - pdata = pm860x_pdata->led; - } else { + cell = pdev->dev.platform_data; + if (cell == NULL) + return -ENODEV; + pdata = cell->mfd_data; + if (pdata == NULL) { dev_err(&pdev->dev, "No platform data!\n"); return -EINVAL; } @@ -198,12 +193,12 @@ static int pm860x_led_probe(struct platform_device *pdev) data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL); if (data == NULL) return -ENOMEM; - strncpy(data->name, res->name, MFD_NAME_SIZE); + strncpy(data->name, res->name, MFD_NAME_SIZE - 1); dev_set_drvdata(&pdev->dev, data); data->chip = chip; data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion; data->iset = pdata->iset; - data->port = __check_device(pdata, data->name); + data->port = pdata->flags; if (data->port < 0) { dev_err(&pdev->dev, "check device failed\n"); kfree(data); @@ -221,6 +216,7 @@ static int pm860x_led_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed to register LED: %d\n", ret); goto out; } + pm860x_led_set(&data->cdev, 0); return 0; out: kfree(data); -- cgit v1.2.3 From 25985edcedea6396277003854657b5f3cb31a628 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 30 Mar 2011 22:57:33 -0300 Subject: Fix common misspellings Fixes generated by 'codespell' and manually reviewed. Signed-off-by: Lucas De Marchi --- drivers/leds/leds-pca9532.c | 2 +- drivers/leds/leds-wm8350.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c index afac338d502..5bf63af09dd 100644 --- a/drivers/leds/leds-pca9532.c +++ b/drivers/leds/leds-pca9532.c @@ -58,7 +58,7 @@ static struct i2c_driver pca9532_driver = { .id_table = pca9532_id, }; -/* We have two pwm/blinkers, but 16 possible leds to drive. Additionaly, +/* We have two pwm/blinkers, but 16 possible leds to drive. Additionally, * the clever Thecus people are using one pwm to drive the beeper. So, * as a compromise we average one pwm to the values requested by all * leds that are not ON/OFF. diff --git a/drivers/leds/leds-wm8350.c b/drivers/leds/leds-wm8350.c index a0452327328..f14edd82cb0 100644 --- a/drivers/leds/leds-wm8350.c +++ b/drivers/leds/leds-wm8350.c @@ -215,13 +215,13 @@ static int wm8350_led_probe(struct platform_device *pdev) isink = regulator_get(&pdev->dev, "led_isink"); if (IS_ERR(isink)) { - printk(KERN_ERR "%s: cant get ISINK\n", __func__); + printk(KERN_ERR "%s: can't get ISINK\n", __func__); return PTR_ERR(isink); } dcdc = regulator_get(&pdev->dev, "led_vcc"); if (IS_ERR(dcdc)) { - printk(KERN_ERR "%s: cant get DCDC\n", __func__); + printk(KERN_ERR "%s: can't get DCDC\n", __func__); ret = PTR_ERR(dcdc); goto err_isink; } -- cgit v1.2.3 From 592ce316395abc6b4e96c1ac198e5f347bb5d578 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Thu, 14 Apr 2011 15:21:59 -0700 Subject: leds/leds-regulator.c: fix handling of already enabled regulators Make the driver aware of the initial status of the regulator. The leds-regulator driver was ignoring the initial status of the regulator; this resulted in rdev->use_count being incremented to 2 after calling regulator_led_set_value() in the .probe method when a regulator was already enabled at insmod time, which made it impossible to ever disable the regulator. Signed-off-by: Antonio Ospite Cc: Richard Purdie Cc: Antonio Ospite Acked-by: Mark Brown Cc: Liam Girdwood Cc: Daniel Ribeiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/leds/leds-regulator.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/leds') diff --git a/drivers/leds/leds-regulator.c b/drivers/leds/leds-regulator.c index 3790816643b..8497f56f8e4 100644 --- a/drivers/leds/leds-regulator.c +++ b/drivers/leds/leds-regulator.c @@ -178,6 +178,10 @@ static int __devinit regulator_led_probe(struct platform_device *pdev) led->cdev.flags |= LED_CORE_SUSPENDRESUME; led->vcc = vcc; + /* to handle correctly an already enabled regulator */ + if (regulator_is_enabled(led->vcc)) + led->enabled = 1; + mutex_init(&led->mutex); INIT_WORK(&led->work, led_work); -- cgit v1.2.3