aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-10 07:14:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-10 07:14:07 -0400
commitc7a6ced9d8e8411bdafe83998474d185a79badc3 (patch)
treebf9a230bfc99165b9d8fa9ed9fc453619bd4a9fb
parenta188e7e93a36627fb3f0013f41857ab54f076d04 (diff)
parent2f73c3927318abe3d7fcaecadfbad89e2d12f881 (diff)
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds
Pull LED subsystem update from Bryan Wu. * 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds: (24 commits) leds: add output driver configuration for pca9633 led driver leds: lm3642: Use regmap_update_bits() in lm3642_chip_init() leds: Add new LED driver for lm3642 chips leds-lp5523: Fix riskiness of the page fault leds-lp5523: turn off the LED engines on unloading the driver leds-lm3530: Fix smatch warnings leds-lm3530: Use devm_regulator_get function leds: leds-gpio: adopt pinctrl support leds: Add new LED driver for lm355x chips leds-lp5523: use the i2c device id rather than fixed name leds-lp5523: add new device id for LP55231 leds-lp5523: support new LP55231 device leds: triggers: send uevent when changing triggers leds-lp5523: minor code style fixes leds-lp5523: change the return type of lp5523_set_mode() leds-lp5523: set the brightness to 0 forcely on removing the driver leds-lp5523: add channel name in the platform data leds: leds-gpio: Use of_get_child_count() helper leds: leds-gpio: Use platform_{get,set}_drvdata leds: leds-gpio: use of_match_ptr() ...
-rw-r--r--Documentation/leds/leds-lp5523.txt21
-rw-r--r--drivers/leds/Kconfig26
-rw-r--r--drivers/leds/Makefile3
-rw-r--r--drivers/leds/led-class.c15
-rw-r--r--drivers/leds/led-core.c16
-rw-r--r--drivers/leds/led-triggers.c17
-rw-r--r--drivers/leds/leds-clevo-mail.c10
-rw-r--r--drivers/leds/leds-gpio.c19
-rw-r--r--drivers/leds/leds-lm3530.c16
-rw-r--r--drivers/leds/leds-lm3556.c512
-rw-r--r--drivers/leds/leds-lm355x.c572
-rw-r--r--drivers/leds/leds-lm3642.c462
-rw-r--r--drivers/leds/leds-lp5523.c75
-rw-r--r--drivers/leds/leds-pca9633.c19
-rw-r--r--drivers/leds/leds-wm8350.c29
-rw-r--r--drivers/leds/leds.h2
-rw-r--r--include/linux/leds-lp5523.h1
-rw-r--r--include/linux/leds.h4
-rw-r--r--include/linux/platform_data/leds-lm3556.h50
-rw-r--r--include/linux/platform_data/leds-lm355x.h66
-rw-r--r--include/linux/platform_data/leds-lm3642.h38
-rw-r--r--include/linux/platform_data/leds-pca9633.h35
22 files changed, 1350 insertions, 658 deletions
diff --git a/Documentation/leds/leds-lp5523.txt b/Documentation/leds/leds-lp5523.txt
index fad2feb8b7ce..c2743f59f9ac 100644
--- a/Documentation/leds/leds-lp5523.txt
+++ b/Documentation/leds/leds-lp5523.txt
@@ -10,8 +10,22 @@ Contact: Samu Onkalo (samu.p.onkalo-at-nokia.com)
10Description 10Description
11----------- 11-----------
12LP5523 can drive up to 9 channels. Leds can be controlled directly via 12LP5523 can drive up to 9 channels. Leds can be controlled directly via
13the led class control interface. Channels have generic names: 13the led class control interface.
14lp5523:channelx where x is 0...8 14The name of each channel is configurable in the platform data - name and label.
15There are three options to make the channel name.
16
17a) Define the 'name' in the platform data
18To make specific channel name, then use 'name' platform data.
19/sys/class/leds/R1 (name: 'R1')
20/sys/class/leds/B1 (name: 'B1')
21
22b) Use the 'label' with no 'name' field
23For one device name with channel number, then use 'label'.
24/sys/class/leds/RGB:channelN (label: 'RGB', N: 0 ~ 8)
25
26c) Default
27If both fields are NULL, 'lp5523' is used by default.
28/sys/class/leds/lp5523:channelN (N: 0 ~ 8)
15 29
16The chip provides 3 engines. Each engine can control channels without 30The chip provides 3 engines. Each engine can control channels without
17interaction from the main CPU. Details of the micro engine code can be found 31interaction from the main CPU. Details of the micro engine code can be found
@@ -46,12 +60,13 @@ Note - chan_nr can have values between 0 and 8.
46 60
47static struct lp5523_led_config lp5523_led_config[] = { 61static struct lp5523_led_config lp5523_led_config[] = {
48 { 62 {
63 .name = "D1",
49 .chan_nr = 0, 64 .chan_nr = 0,
50 .led_current = 50, 65 .led_current = 50,
51 .max_current = 130, 66 .max_current = 130,
52 }, 67 },
53... 68...
54 }, { 69 {
55 .chan_nr = 8, 70 .chan_nr = 8,
56 .led_current = 50, 71 .led_current = 50,
57 .max_current = 130, 72 .max_current = 130,
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 16578d3b52bb..f508defc0d96 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -63,6 +63,17 @@ config LEDS_LM3533
63 hardware-accelerated blinking with maximum on and off periods of 9.8 63 hardware-accelerated blinking with maximum on and off periods of 9.8
64 and 77 seconds respectively. 64 and 77 seconds respectively.
65 65
66config LEDS_LM3642
67 tristate "LED support for LM3642 Chip"
68 depends on LEDS_CLASS && I2C
69 select REGMAP_I2C
70 help
71 This option enables support for LEDs connected to LM3642.
72 The LM3642 is a 4MHz fixed-frequency synchronous boost
73 converter plus 1.5A constant current driver for a high-current
74 white LED.
75
76
66config LEDS_LOCOMO 77config LEDS_LOCOMO
67 tristate "LED Support for Locomo device" 78 tristate "LED Support for Locomo device"
68 depends on LEDS_CLASS 79 depends on LEDS_CLASS
@@ -192,11 +203,12 @@ config LEDS_LP5521
192 programming the engines. 203 programming the engines.
193 204
194config LEDS_LP5523 205config LEDS_LP5523
195 tristate "LED Support for N.S. LP5523 LED driver chip" 206 tristate "LED Support for TI/National LP5523/55231 LED driver chip"
196 depends on LEDS_CLASS && I2C 207 depends on LEDS_CLASS && I2C
197 help 208 help
198 If you say yes here you get support for the National Semiconductor 209 If you say yes here you get support for TI/National Semiconductor
199 LP5523 LED driver. It is 9 channel chip with programmable engines. 210 LP5523/55231 LED driver.
211 It is 9 channel chip with programmable engines.
200 Driver provides direct control via LED class and interface for 212 Driver provides direct control via LED class and interface for
201 programming the engines. 213 programming the engines.
202 214
@@ -422,13 +434,13 @@ config LEDS_MAX8997
422 This option enables support for on-chip LED drivers on 434 This option enables support for on-chip LED drivers on
423 MAXIM MAX8997 PMIC. 435 MAXIM MAX8997 PMIC.
424 436
425config LEDS_LM3556 437config LEDS_LM355x
426 tristate "LED support for LM3556 Chip" 438 tristate "LED support for LM355x Chips, LM3554 and LM3556"
427 depends on LEDS_CLASS && I2C 439 depends on LEDS_CLASS && I2C
428 select REGMAP_I2C 440 select REGMAP_I2C
429 help 441 help
430 This option enables support for LEDs connected to LM3556. 442 This option enables support for LEDs connected to LM355x.
431 LM3556 includes Torch, Flash and Indicator functions. 443 LM355x includes Torch, Flash and Indicator functions.
432 444
433config LEDS_OT200 445config LEDS_OT200
434 tristate "LED support for the Bachmann OT200" 446 tristate "LED support for the Bachmann OT200"
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index a9b627c4f8ba..3fb9641b6194 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o
11obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o 11obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
12obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o 12obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o
13obj-$(CONFIG_LEDS_LM3533) += leds-lm3533.o 13obj-$(CONFIG_LEDS_LM3533) += leds-lm3533.o
14obj-$(CONFIG_LEDS_LM3642) += leds-lm3642.o
14obj-$(CONFIG_LEDS_MIKROTIK_RB532) += leds-rb532.o 15obj-$(CONFIG_LEDS_MIKROTIK_RB532) += leds-rb532.o
15obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o 16obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
16obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o 17obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o
@@ -48,7 +49,7 @@ obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o
48obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o 49obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o
49obj-$(CONFIG_LEDS_RENESAS_TPU) += leds-renesas-tpu.o 50obj-$(CONFIG_LEDS_RENESAS_TPU) += leds-renesas-tpu.o
50obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o 51obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o
51obj-$(CONFIG_LEDS_LM3556) += leds-lm3556.o 52obj-$(CONFIG_LEDS_LM355x) += leds-lm355x.o
52obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o 53obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o
53 54
54# LED SPI Drivers 55# LED SPI Drivers
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index c599095bc005..48cce18e9d6d 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -124,6 +124,16 @@ static void led_timer_function(unsigned long data)
124 mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay)); 124 mod_timer(&led_cdev->blink_timer, jiffies + msecs_to_jiffies(delay));
125} 125}
126 126
127static void set_brightness_delayed(struct work_struct *ws)
128{
129 struct led_classdev *led_cdev =
130 container_of(ws, struct led_classdev, set_brightness_work);
131
132 led_stop_software_blink(led_cdev);
133
134 __led_set_brightness(led_cdev, led_cdev->delayed_set_value);
135}
136
127/** 137/**
128 * led_classdev_suspend - suspend an led_classdev. 138 * led_classdev_suspend - suspend an led_classdev.
129 * @led_cdev: the led_classdev to suspend. 139 * @led_cdev: the led_classdev to suspend.
@@ -191,6 +201,8 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
191 201
192 led_update_brightness(led_cdev); 202 led_update_brightness(led_cdev);
193 203
204 INIT_WORK(&led_cdev->set_brightness_work, set_brightness_delayed);
205
194 init_timer(&led_cdev->blink_timer); 206 init_timer(&led_cdev->blink_timer);
195 led_cdev->blink_timer.function = led_timer_function; 207 led_cdev->blink_timer.function = led_timer_function;
196 led_cdev->blink_timer.data = (unsigned long)led_cdev; 208 led_cdev->blink_timer.data = (unsigned long)led_cdev;
@@ -221,7 +233,10 @@ void led_classdev_unregister(struct led_classdev *led_cdev)
221 up_write(&led_cdev->trigger_lock); 233 up_write(&led_cdev->trigger_lock);
222#endif 234#endif
223 235
236 cancel_work_sync(&led_cdev->set_brightness_work);
237
224 /* Stop blinking */ 238 /* Stop blinking */
239 led_stop_software_blink(led_cdev);
225 led_set_brightness(led_cdev, LED_OFF); 240 led_set_brightness(led_cdev, LED_OFF);
226 241
227 device_unregister(led_cdev->dev); 242 device_unregister(led_cdev->dev);
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index 2ab05af3de31..ce8921a753a3 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -103,13 +103,23 @@ void led_blink_set_oneshot(struct led_classdev *led_cdev,
103} 103}
104EXPORT_SYMBOL(led_blink_set_oneshot); 104EXPORT_SYMBOL(led_blink_set_oneshot);
105 105
106void led_set_brightness(struct led_classdev *led_cdev, 106void led_stop_software_blink(struct led_classdev *led_cdev)
107 enum led_brightness brightness)
108{ 107{
109 /* stop and clear soft-blink timer */
110 del_timer_sync(&led_cdev->blink_timer); 108 del_timer_sync(&led_cdev->blink_timer);
111 led_cdev->blink_delay_on = 0; 109 led_cdev->blink_delay_on = 0;
112 led_cdev->blink_delay_off = 0; 110 led_cdev->blink_delay_off = 0;
111}
112EXPORT_SYMBOL_GPL(led_stop_software_blink);
113
114void led_set_brightness(struct led_classdev *led_cdev,
115 enum led_brightness brightness)
116{
117 /* delay brightness setting if need to stop soft-blink timer */
118 if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) {
119 led_cdev->delayed_set_value = brightness;
120 schedule_work(&led_cdev->set_brightness_work);
121 return;
122 }
113 123
114 __led_set_brightness(led_cdev, brightness); 124 __led_set_brightness(led_cdev, brightness);
115} 125}
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
index 363975b3c925..262eb4193710 100644
--- a/drivers/leds/led-triggers.c
+++ b/drivers/leds/led-triggers.c
@@ -102,6 +102,12 @@ EXPORT_SYMBOL_GPL(led_trigger_show);
102void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig) 102void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
103{ 103{
104 unsigned long flags; 104 unsigned long flags;
105 char *event = NULL;
106 char *envp[2];
107 const char *name;
108
109 name = trig ? trig->name : "none";
110 event = kasprintf(GFP_KERNEL, "TRIGGER=%s", name);
105 111
106 /* Remove any existing trigger */ 112 /* Remove any existing trigger */
107 if (led_cdev->trigger) { 113 if (led_cdev->trigger) {
@@ -109,6 +115,8 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
109 list_del(&led_cdev->trig_list); 115 list_del(&led_cdev->trig_list);
110 write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock, 116 write_unlock_irqrestore(&led_cdev->trigger->leddev_list_lock,
111 flags); 117 flags);
118 cancel_work_sync(&led_cdev->set_brightness_work);
119 led_stop_software_blink(led_cdev);
112 if (led_cdev->trigger->deactivate) 120 if (led_cdev->trigger->deactivate)
113 led_cdev->trigger->deactivate(led_cdev); 121 led_cdev->trigger->deactivate(led_cdev);
114 led_cdev->trigger = NULL; 122 led_cdev->trigger = NULL;
@@ -122,6 +130,13 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trig)
122 if (trig->activate) 130 if (trig->activate)
123 trig->activate(led_cdev); 131 trig->activate(led_cdev);
124 } 132 }
133
134 if (event) {
135 envp[0] = event;
136 envp[1] = NULL;
137 kobject_uevent_env(&led_cdev->dev->kobj, KOBJ_CHANGE, envp);
138 kfree(event);
139 }
125} 140}
126EXPORT_SYMBOL_GPL(led_trigger_set); 141EXPORT_SYMBOL_GPL(led_trigger_set);
127 142
@@ -224,7 +239,7 @@ void led_trigger_event(struct led_trigger *trig,
224 struct led_classdev *led_cdev; 239 struct led_classdev *led_cdev;
225 240
226 led_cdev = list_entry(entry, struct led_classdev, trig_list); 241 led_cdev = list_entry(entry, struct led_classdev, trig_list);
227 __led_set_brightness(led_cdev, brightness); 242 led_set_brightness(led_cdev, brightness);
228 } 243 }
229 read_unlock(&trig->leddev_list_lock); 244 read_unlock(&trig->leddev_list_lock);
230} 245}
diff --git a/drivers/leds/leds-clevo-mail.c b/drivers/leds/leds-clevo-mail.c
index 1ed1677c916f..e024b0b1c3b1 100644
--- a/drivers/leds/leds-clevo-mail.c
+++ b/drivers/leds/leds-clevo-mail.c
@@ -31,7 +31,7 @@ static int __init clevo_mail_led_dmi_callback(const struct dmi_system_id *id)
31} 31}
32 32
33/* 33/*
34 * struct mail_led_whitelist - List of known good models 34 * struct clevo_mail_led_dmi_table - List of known good models
35 * 35 *
36 * Contains the known good models this driver is compatible with. 36 * Contains the known good models this driver is compatible with.
37 * When adding a new model try to be as strict as possible. This 37 * When adding a new model try to be as strict as possible. This
@@ -39,7 +39,7 @@ static int __init clevo_mail_led_dmi_callback(const struct dmi_system_id *id)
39 * detected as working, but in reality it is not) as low as 39 * detected as working, but in reality it is not) as low as
40 * possible. 40 * possible.
41 */ 41 */
42static struct dmi_system_id __initdata mail_led_whitelist[] = { 42static struct dmi_system_id __initdata clevo_mail_led_dmi_table[] = {
43 { 43 {
44 .callback = clevo_mail_led_dmi_callback, 44 .callback = clevo_mail_led_dmi_callback,
45 .ident = "Clevo D410J", 45 .ident = "Clevo D410J",
@@ -59,11 +59,10 @@ static struct dmi_system_id __initdata mail_led_whitelist[] = {
59 }, 59 },
60 { 60 {
61 .callback = clevo_mail_led_dmi_callback, 61 .callback = clevo_mail_led_dmi_callback,
62 .ident = "Positivo Mobile", 62 .ident = "Clevo M5x0V",
63 .matches = { 63 .matches = {
64 DMI_MATCH(DMI_BOARD_VENDOR, "CLEVO Co. "), 64 DMI_MATCH(DMI_BOARD_VENDOR, "CLEVO Co. "),
65 DMI_MATCH(DMI_BOARD_NAME, "M5X0V "), 65 DMI_MATCH(DMI_BOARD_NAME, "M5X0V "),
66 DMI_MATCH(DMI_PRODUCT_NAME, "Positivo Mobile"),
67 DMI_MATCH(DMI_PRODUCT_VERSION, "VT6198") 66 DMI_MATCH(DMI_PRODUCT_VERSION, "VT6198")
68 } 67 }
69 }, 68 },
@@ -89,6 +88,7 @@ static struct dmi_system_id __initdata mail_led_whitelist[] = {
89 }, 88 },
90 { } 89 { }
91}; 90};
91MODULE_DEVICE_TABLE(dmi, clevo_mail_led_dmi_table);
92 92
93static void clevo_mail_led_set(struct led_classdev *led_cdev, 93static void clevo_mail_led_set(struct led_classdev *led_cdev,
94 enum led_brightness value) 94 enum led_brightness value)
@@ -180,7 +180,7 @@ static int __init clevo_mail_led_init(void)
180 180
181 /* Check with the help of DMI if we are running on supported hardware */ 181 /* Check with the help of DMI if we are running on supported hardware */
182 if (!nodetect) { 182 if (!nodetect) {
183 count = dmi_check_system(mail_led_whitelist); 183 count = dmi_check_system(clevo_mail_led_dmi_table);
184 } else { 184 } else {
185 count = 1; 185 count = 1;
186 printk(KERN_ERR KBUILD_MODNAME ": Skipping DMI detection. " 186 printk(KERN_ERR KBUILD_MODNAME ": Skipping DMI detection. "
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index c032b2180340..087d1e66f4f7 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -20,6 +20,7 @@
20#include <linux/slab.h> 20#include <linux/slab.h>
21#include <linux/workqueue.h> 21#include <linux/workqueue.h>
22#include <linux/module.h> 22#include <linux/module.h>
23#include <linux/pinctrl/consumer.h>
23 24
24struct gpio_led_data { 25struct gpio_led_data {
25 struct led_classdev cdev; 26 struct led_classdev cdev;
@@ -170,11 +171,10 @@ static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_dev
170{ 171{
171 struct device_node *np = pdev->dev.of_node, *child; 172 struct device_node *np = pdev->dev.of_node, *child;
172 struct gpio_leds_priv *priv; 173 struct gpio_leds_priv *priv;
173 int count = 0, ret; 174 int count, ret;
174 175
175 /* count LEDs in this device, so we know how much to allocate */ 176 /* count LEDs in this device, so we know how much to allocate */
176 for_each_child_of_node(np, child) 177 count = of_get_child_count(np);
177 count++;
178 if (!count) 178 if (!count)
179 return NULL; 179 return NULL;
180 180
@@ -228,7 +228,6 @@ static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_dev
228{ 228{
229 return NULL; 229 return NULL;
230} 230}
231#define of_gpio_leds_match NULL
232#endif /* CONFIG_OF_GPIO */ 231#endif /* CONFIG_OF_GPIO */
233 232
234 233
@@ -236,8 +235,14 @@ static int __devinit gpio_led_probe(struct platform_device *pdev)
236{ 235{
237 struct gpio_led_platform_data *pdata = pdev->dev.platform_data; 236 struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
238 struct gpio_leds_priv *priv; 237 struct gpio_leds_priv *priv;
238 struct pinctrl *pinctrl;
239 int i, ret = 0; 239 int i, ret = 0;
240 240
241 pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
242 if (IS_ERR(pinctrl))
243 dev_warn(&pdev->dev,
244 "pins are not configured from the driver\n");
245
241 if (pdata && pdata->num_leds) { 246 if (pdata && pdata->num_leds) {
242 priv = devm_kzalloc(&pdev->dev, 247 priv = devm_kzalloc(&pdev->dev,
243 sizeof_gpio_leds_priv(pdata->num_leds), 248 sizeof_gpio_leds_priv(pdata->num_leds),
@@ -270,13 +275,13 @@ static int __devinit gpio_led_probe(struct platform_device *pdev)
270 275
271static int __devexit gpio_led_remove(struct platform_device *pdev) 276static int __devexit gpio_led_remove(struct platform_device *pdev)
272{ 277{
273 struct gpio_leds_priv *priv = dev_get_drvdata(&pdev->dev); 278 struct gpio_leds_priv *priv = platform_get_drvdata(pdev);
274 int i; 279 int i;
275 280
276 for (i = 0; i < priv->num_leds; i++) 281 for (i = 0; i < priv->num_leds; i++)
277 delete_gpio_led(&priv->leds[i]); 282 delete_gpio_led(&priv->leds[i]);
278 283
279 dev_set_drvdata(&pdev->dev, NULL); 284 platform_set_drvdata(pdev, NULL);
280 285
281 return 0; 286 return 0;
282} 287}
@@ -287,7 +292,7 @@ static struct platform_driver gpio_led_driver = {
287 .driver = { 292 .driver = {
288 .name = "leds-gpio", 293 .name = "leds-gpio",
289 .owner = THIS_MODULE, 294 .owner = THIS_MODULE,
290 .of_match_table = of_gpio_leds_match, 295 .of_match_table = of_match_ptr(of_gpio_leds_match),
291 }, 296 },
292}; 297};
293 298
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c
index 23637bdb275d..b26306f6724d 100644
--- a/drivers/leds/leds-lm3530.c
+++ b/drivers/leds/leds-lm3530.c
@@ -150,7 +150,7 @@ static int lm3530_get_mode_from_str(const char *str)
150 if (sysfs_streq(str, mode_map[i].mode)) 150 if (sysfs_streq(str, mode_map[i].mode))
151 return mode_map[i].mode_val; 151 return mode_map[i].mode_val;
152 152
153 return -1; 153 return -EINVAL;
154} 154}
155 155
156static void lm3530_als_configure(struct lm3530_platform_data *pdata, 156static void lm3530_als_configure(struct lm3530_platform_data *pdata,
@@ -358,7 +358,7 @@ static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute
358 mode = lm3530_get_mode_from_str(buf); 358 mode = lm3530_get_mode_from_str(buf);
359 if (mode < 0) { 359 if (mode < 0) {
360 dev_err(dev, "Invalid mode\n"); 360 dev_err(dev, "Invalid mode\n");
361 return -EINVAL; 361 return mode;
362 } 362 }
363 363
364 drvdata->mode = mode; 364 drvdata->mode = mode;
@@ -416,7 +416,7 @@ static int __devinit lm3530_probe(struct i2c_client *client,
416 416
417 i2c_set_clientdata(client, drvdata); 417 i2c_set_clientdata(client, drvdata);
418 418
419 drvdata->regulator = regulator_get(&client->dev, "vin"); 419 drvdata->regulator = devm_regulator_get(&client->dev, "vin");
420 if (IS_ERR(drvdata->regulator)) { 420 if (IS_ERR(drvdata->regulator)) {
421 dev_err(&client->dev, "regulator get failed\n"); 421 dev_err(&client->dev, "regulator get failed\n");
422 err = PTR_ERR(drvdata->regulator); 422 err = PTR_ERR(drvdata->regulator);
@@ -429,15 +429,13 @@ static int __devinit lm3530_probe(struct i2c_client *client,
429 if (err < 0) { 429 if (err < 0) {
430 dev_err(&client->dev, 430 dev_err(&client->dev,
431 "Register Init failed: %d\n", err); 431 "Register Init failed: %d\n", err);
432 err = -ENODEV; 432 return err;
433 goto err_reg_init;
434 } 433 }
435 } 434 }
436 err = led_classdev_register(&client->dev, &drvdata->led_dev); 435 err = led_classdev_register(&client->dev, &drvdata->led_dev);
437 if (err < 0) { 436 if (err < 0) {
438 dev_err(&client->dev, "Register led class failed: %d\n", err); 437 dev_err(&client->dev, "Register led class failed: %d\n", err);
439 err = -ENODEV; 438 return err;
440 goto err_class_register;
441 } 439 }
442 440
443 err = device_create_file(drvdata->led_dev.dev, &dev_attr_mode); 441 err = device_create_file(drvdata->led_dev.dev, &dev_attr_mode);
@@ -451,9 +449,6 @@ static int __devinit lm3530_probe(struct i2c_client *client,
451 449
452err_create_file: 450err_create_file:
453 led_classdev_unregister(&drvdata->led_dev); 451 led_classdev_unregister(&drvdata->led_dev);
454err_class_register:
455err_reg_init:
456 regulator_put(drvdata->regulator);
457 return err; 452 return err;
458} 453}
459 454
@@ -465,7 +460,6 @@ static int __devexit lm3530_remove(struct i2c_client *client)
465 460
466 if (drvdata->enable) 461 if (drvdata->enable)
467 regulator_disable(drvdata->regulator); 462 regulator_disable(drvdata->regulator);
468 regulator_put(drvdata->regulator);
469 led_classdev_unregister(&drvdata->led_dev); 463 led_classdev_unregister(&drvdata->led_dev);
470 return 0; 464 return 0;
471} 465}
diff --git a/drivers/leds/leds-lm3556.c b/drivers/leds/leds-lm3556.c
deleted file mode 100644
index 3062abd9a532..000000000000
--- a/drivers/leds/leds-lm3556.c
+++ /dev/null
@@ -1,512 +0,0 @@
1/*
2 * Simple driver for Texas Instruments LM3556 LED Flash driver chip (Rev0x03)
3 * Copyright (C) 2012 Texas Instruments
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Please refer Documentation/leds/leds-lm3556.txt file.
10 */
11#include <linux/module.h>
12#include <linux/delay.h>
13#include <linux/i2c.h>
14#include <linux/leds.h>
15#include <linux/slab.h>
16#include <linux/platform_device.h>
17#include <linux/fs.h>
18#include <linux/regmap.h>
19#include <linux/platform_data/leds-lm3556.h>
20
21#define REG_FILT_TIME (0x0)
22#define REG_IVFM_MODE (0x1)
23#define REG_NTC (0x2)
24#define REG_INDIC_TIME (0x3)
25#define REG_INDIC_BLINK (0x4)
26#define REG_INDIC_PERIOD (0x5)
27#define REG_TORCH_TIME (0x6)
28#define REG_CONF (0x7)
29#define REG_FLASH (0x8)
30#define REG_I_CTRL (0x9)
31#define REG_ENABLE (0xA)
32#define REG_FLAG (0xB)
33#define REG_MAX (0xB)
34
35#define IVFM_FILTER_TIME_SHIFT (3)
36#define UVLO_EN_SHIFT (7)
37#define HYSTERSIS_SHIFT (5)
38#define IVM_D_TH_SHIFT (2)
39#define IVFM_ADJ_MODE_SHIFT (0)
40#define NTC_EVENT_LVL_SHIFT (5)
41#define NTC_TRIP_TH_SHIFT (2)
42#define NTC_BIAS_I_LVL_SHIFT (0)
43#define INDIC_RAMP_UP_TIME_SHIFT (3)
44#define INDIC_RAMP_DN_TIME_SHIFT (0)
45#define INDIC_N_BLANK_SHIFT (4)
46#define INDIC_PULSE_TIME_SHIFT (0)
47#define INDIC_N_PERIOD_SHIFT (0)
48#define TORCH_RAMP_UP_TIME_SHIFT (3)
49#define TORCH_RAMP_DN_TIME_SHIFT (0)
50#define STROBE_USUAGE_SHIFT (7)
51#define STROBE_PIN_POLARITY_SHIFT (6)
52#define TORCH_PIN_POLARITY_SHIFT (5)
53#define TX_PIN_POLARITY_SHIFT (4)
54#define TX_EVENT_LVL_SHIFT (3)
55#define IVFM_EN_SHIFT (2)
56#define NTC_MODE_SHIFT (1)
57#define INDIC_MODE_SHIFT (0)
58#define INDUCTOR_I_LIMIT_SHIFT (6)
59#define FLASH_RAMP_TIME_SHIFT (3)
60#define FLASH_TOUT_TIME_SHIFT (0)
61#define TORCH_I_SHIFT (4)
62#define FLASH_I_SHIFT (0)
63#define NTC_EN_SHIFT (7)
64#define TX_PIN_EN_SHIFT (6)
65#define STROBE_PIN_EN_SHIFT (5)
66#define TORCH_PIN_EN_SHIFT (4)
67#define PRECHG_MODE_EN_SHIFT (3)
68#define PASS_MODE_ONLY_EN_SHIFT (2)
69#define MODE_BITS_SHIFT (0)
70
71#define IVFM_FILTER_TIME_MASK (0x3)
72#define UVLO_EN_MASK (0x1)
73#define HYSTERSIS_MASK (0x3)
74#define IVM_D_TH_MASK (0x7)
75#define IVFM_ADJ_MODE_MASK (0x3)
76#define NTC_EVENT_LVL_MASK (0x1)
77#define NTC_TRIP_TH_MASK (0x7)
78#define NTC_BIAS_I_LVL_MASK (0x3)
79#define INDIC_RAMP_UP_TIME_MASK (0x7)
80#define INDIC_RAMP_DN_TIME_MASK (0x7)
81#define INDIC_N_BLANK_MASK (0x7)
82#define INDIC_PULSE_TIME_MASK (0x7)
83#define INDIC_N_PERIOD_MASK (0x7)
84#define TORCH_RAMP_UP_TIME_MASK (0x7)
85#define TORCH_RAMP_DN_TIME_MASK (0x7)
86#define STROBE_USUAGE_MASK (0x1)
87#define STROBE_PIN_POLARITY_MASK (0x1)
88#define TORCH_PIN_POLARITY_MASK (0x1)
89#define TX_PIN_POLARITY_MASK (0x1)
90#define TX_EVENT_LVL_MASK (0x1)
91#define IVFM_EN_MASK (0x1)
92#define NTC_MODE_MASK (0x1)
93#define INDIC_MODE_MASK (0x1)
94#define INDUCTOR_I_LIMIT_MASK (0x3)
95#define FLASH_RAMP_TIME_MASK (0x7)
96#define FLASH_TOUT_TIME_MASK (0x7)
97#define TORCH_I_MASK (0x7)
98#define FLASH_I_MASK (0xF)
99#define NTC_EN_MASK (0x1)
100#define TX_PIN_EN_MASK (0x1)
101#define STROBE_PIN_EN_MASK (0x1)
102#define TORCH_PIN_EN_MASK (0x1)
103#define PRECHG_MODE_EN_MASK (0x1)
104#define PASS_MODE_ONLY_EN_MASK (0x1)
105#define MODE_BITS_MASK (0x13)
106#define EX_PIN_CONTROL_MASK (0xF1)
107#define EX_PIN_ENABLE_MASK (0x70)
108
109enum lm3556_indic_pulse_time {
110 PULSE_TIME_0_MS = 0,
111 PULSE_TIME_32_MS,
112 PULSE_TIME_64_MS,
113 PULSE_TIME_92_MS,
114 PULSE_TIME_128_MS,
115 PULSE_TIME_160_MS,
116 PULSE_TIME_196_MS,
117 PULSE_TIME_224_MS,
118 PULSE_TIME_256_MS,
119 PULSE_TIME_288_MS,
120 PULSE_TIME_320_MS,
121 PULSE_TIME_352_MS,
122 PULSE_TIME_384_MS,
123 PULSE_TIME_416_MS,
124 PULSE_TIME_448_MS,
125 PULSE_TIME_480_MS,
126};
127
128enum lm3556_indic_n_blank {
129 INDIC_N_BLANK_0 = 0,
130 INDIC_N_BLANK_1,
131 INDIC_N_BLANK_2,
132 INDIC_N_BLANK_3,
133 INDIC_N_BLANK_4,
134 INDIC_N_BLANK_5,
135 INDIC_N_BLANK_6,
136 INDIC_N_BLANK_7,
137 INDIC_N_BLANK_8,
138 INDIC_N_BLANK_9,
139 INDIC_N_BLANK_10,
140 INDIC_N_BLANK_11,
141 INDIC_N_BLANK_12,
142 INDIC_N_BLANK_13,
143 INDIC_N_BLANK_14,
144 INDIC_N_BLANK_15,
145};
146
147enum lm3556_indic_period {
148 INDIC_PERIOD_0 = 0,
149 INDIC_PERIOD_1,
150 INDIC_PERIOD_2,
151 INDIC_PERIOD_3,
152 INDIC_PERIOD_4,
153 INDIC_PERIOD_5,
154 INDIC_PERIOD_6,
155 INDIC_PERIOD_7,
156};
157
158enum lm3556_mode {
159 MODES_STASNDBY = 0,
160 MODES_INDIC,
161 MODES_TORCH,
162 MODES_FLASH
163};
164
165#define INDIC_PATTERN_SIZE 4
166
167struct indicator {
168 u8 blinking;
169 u8 period_cnt;
170};
171
172struct lm3556_chip_data {
173 struct device *dev;
174
175 struct led_classdev cdev_flash;
176 struct led_classdev cdev_torch;
177 struct led_classdev cdev_indicator;
178
179 struct lm3556_platform_data *pdata;
180 struct regmap *regmap;
181 struct mutex lock;
182
183 unsigned int last_flag;
184};
185
186/* indicator pattern */
187static struct indicator indicator_pattern[INDIC_PATTERN_SIZE] = {
188 [0] = {(INDIC_N_BLANK_1 << INDIC_N_BLANK_SHIFT)
189 | PULSE_TIME_32_MS, INDIC_PERIOD_1},
190 [1] = {(INDIC_N_BLANK_15 << INDIC_N_BLANK_SHIFT)
191 | PULSE_TIME_32_MS, INDIC_PERIOD_2},
192 [2] = {(INDIC_N_BLANK_10 << INDIC_N_BLANK_SHIFT)
193 | PULSE_TIME_32_MS, INDIC_PERIOD_4},
194 [3] = {(INDIC_N_BLANK_5 << INDIC_N_BLANK_SHIFT)
195 | PULSE_TIME_32_MS, INDIC_PERIOD_7},
196};
197
198/* chip initialize */
199static int __devinit lm3556_chip_init(struct lm3556_chip_data *chip)
200{
201 unsigned int reg_val;
202 int ret;
203 struct lm3556_platform_data *pdata = chip->pdata;
204
205 /* set config register */
206 ret = regmap_read(chip->regmap, REG_CONF, &reg_val);
207 if (ret < 0) {
208 dev_err(chip->dev, "Failed to read REG_CONF Register\n");
209 goto out;
210 }
211
212 reg_val &= (~EX_PIN_CONTROL_MASK);
213 reg_val |= ((pdata->torch_pin_polarity & 0x01)
214 << TORCH_PIN_POLARITY_SHIFT);
215 reg_val |= ((pdata->strobe_usuage & 0x01) << STROBE_USUAGE_SHIFT);
216 reg_val |= ((pdata->strobe_pin_polarity & 0x01)
217 << STROBE_PIN_POLARITY_SHIFT);
218 reg_val |= ((pdata->tx_pin_polarity & 0x01) << TX_PIN_POLARITY_SHIFT);
219 reg_val |= ((pdata->indicator_mode & 0x01) << INDIC_MODE_SHIFT);
220
221 ret = regmap_write(chip->regmap, REG_CONF, reg_val);
222 if (ret < 0) {
223 dev_err(chip->dev, "Failed to write REG_CONF Regisgter\n");
224 goto out;
225 }
226
227 /* set enable register */
228 ret = regmap_read(chip->regmap, REG_ENABLE, &reg_val);
229 if (ret < 0) {
230 dev_err(chip->dev, "Failed to read REG_ENABLE Register\n");
231 goto out;
232 }
233
234 reg_val &= (~EX_PIN_ENABLE_MASK);
235 reg_val |= ((pdata->torch_pin_en & 0x01) << TORCH_PIN_EN_SHIFT);
236 reg_val |= ((pdata->strobe_pin_en & 0x01) << STROBE_PIN_EN_SHIFT);
237 reg_val |= ((pdata->tx_pin_en & 0x01) << TX_PIN_EN_SHIFT);
238
239 ret = regmap_write(chip->regmap, REG_ENABLE, reg_val);
240 if (ret < 0) {
241 dev_err(chip->dev, "Failed to write REG_ENABLE Regisgter\n");
242 goto out;
243 }
244
245out:
246 return ret;
247}
248
249/* chip control */
250static int lm3556_control(struct lm3556_chip_data *chip,
251 u8 brightness, enum lm3556_mode opmode)
252{
253 int ret;
254 struct lm3556_platform_data *pdata = chip->pdata;
255
256 ret = regmap_read(chip->regmap, REG_FLAG, &chip->last_flag);
257 if (ret < 0) {
258 dev_err(chip->dev, "Failed to read REG_FLAG Register\n");
259 goto out;
260 }
261
262 if (chip->last_flag)
263 dev_info(chip->dev, "Last FLAG is 0x%x\n", chip->last_flag);
264
265 /* brightness 0 means off-state */
266 if (!brightness)
267 opmode = MODES_STASNDBY;
268
269 switch (opmode) {
270 case MODES_TORCH:
271 ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
272 TORCH_I_MASK << TORCH_I_SHIFT,
273 (brightness - 1) << TORCH_I_SHIFT);
274
275 if (pdata->torch_pin_en)
276 opmode |= (TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT);
277 break;
278
279 case MODES_FLASH:
280 ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
281 FLASH_I_MASK << FLASH_I_SHIFT,
282 (brightness - 1) << FLASH_I_SHIFT);
283 break;
284
285 case MODES_INDIC:
286 ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
287 TORCH_I_MASK << TORCH_I_SHIFT,
288 (brightness - 1) << TORCH_I_SHIFT);
289 break;
290
291 case MODES_STASNDBY:
292 if (pdata->torch_pin_en)
293 opmode |= (TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT);
294 break;
295
296 default:
297 return ret;
298 }
299 if (ret < 0) {
300 dev_err(chip->dev, "Failed to write REG_I_CTRL Register\n");
301 goto out;
302 }
303 ret = regmap_update_bits(chip->regmap, REG_ENABLE,
304 MODE_BITS_MASK << MODE_BITS_SHIFT,
305 opmode << MODE_BITS_SHIFT);
306
307out:
308 return ret;
309}
310
311/* torch */
312static void lm3556_torch_brightness_set(struct led_classdev *cdev,
313 enum led_brightness brightness)
314{
315 struct lm3556_chip_data *chip =
316 container_of(cdev, struct lm3556_chip_data, cdev_torch);
317
318 mutex_lock(&chip->lock);
319 lm3556_control(chip, brightness, MODES_TORCH);
320 mutex_unlock(&chip->lock);
321}
322
323/* flash */
324static void lm3556_strobe_brightness_set(struct led_classdev *cdev,
325 enum led_brightness brightness)
326{
327 struct lm3556_chip_data *chip =
328 container_of(cdev, struct lm3556_chip_data, cdev_flash);
329
330 mutex_lock(&chip->lock);
331 lm3556_control(chip, brightness, MODES_FLASH);
332 mutex_unlock(&chip->lock);
333}
334
335/* indicator */
336static void lm3556_indicator_brightness_set(struct led_classdev *cdev,
337 enum led_brightness brightness)
338{
339 struct lm3556_chip_data *chip =
340 container_of(cdev, struct lm3556_chip_data, cdev_indicator);
341
342 mutex_lock(&chip->lock);
343 lm3556_control(chip, brightness, MODES_INDIC);
344 mutex_unlock(&chip->lock);
345}
346
347/* indicator pattern */
348static ssize_t lm3556_indicator_pattern_store(struct device *dev,
349 struct device_attribute *devAttr,
350 const char *buf, size_t size)
351{
352 ssize_t ret;
353 struct led_classdev *led_cdev = dev_get_drvdata(dev);
354 struct lm3556_chip_data *chip =
355 container_of(led_cdev, struct lm3556_chip_data, cdev_indicator);
356 unsigned int state;
357
358 ret = kstrtouint(buf, 10, &state);
359 if (ret)
360 goto out;
361 if (state > INDIC_PATTERN_SIZE - 1)
362 state = INDIC_PATTERN_SIZE - 1;
363
364 ret = regmap_write(chip->regmap, REG_INDIC_BLINK,
365 indicator_pattern[state].blinking);
366 if (ret < 0) {
367 dev_err(chip->dev, "Failed to write REG_ENABLE Regisgter\n");
368 goto out;
369 }
370
371 ret = regmap_write(chip->regmap, REG_INDIC_PERIOD,
372 indicator_pattern[state].period_cnt);
373 if (ret < 0) {
374 dev_err(chip->dev, "Failed to write REG_ENABLE Regisgter\n");
375 goto out;
376 }
377
378 return size;
379out:
380 dev_err(chip->dev, "Indicator pattern doesn't saved\n");
381 return size;
382}
383
384static DEVICE_ATTR(pattern, 0666, NULL, lm3556_indicator_pattern_store);
385
386static const struct regmap_config lm3556_regmap = {
387 .reg_bits = 8,
388 .val_bits = 8,
389 .max_register = REG_MAX,
390};
391
392/* module initialize */
393static int __devinit lm3556_probe(struct i2c_client *client,
394 const struct i2c_device_id *id)
395{
396 struct lm3556_platform_data *pdata = client->dev.platform_data;
397 struct lm3556_chip_data *chip;
398
399 int err;
400
401 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
402 dev_err(&client->dev, "i2c functionality check fail.\n");
403 return -EOPNOTSUPP;
404 }
405
406 if (pdata == NULL) {
407 dev_err(&client->dev, "Needs Platform Data.\n");
408 return -ENODATA;
409 }
410
411 chip =
412 devm_kzalloc(&client->dev, sizeof(struct lm3556_chip_data),
413 GFP_KERNEL);
414 if (!chip)
415 return -ENOMEM;
416
417 chip->dev = &client->dev;
418 chip->pdata = pdata;
419
420 chip->regmap = devm_regmap_init_i2c(client, &lm3556_regmap);
421 if (IS_ERR(chip->regmap)) {
422 err = PTR_ERR(chip->regmap);
423 dev_err(&client->dev, "Failed to allocate register map: %d\n",
424 err);
425 return err;
426 }
427
428 mutex_init(&chip->lock);
429 i2c_set_clientdata(client, chip);
430
431 err = lm3556_chip_init(chip);
432 if (err < 0)
433 goto err_out;
434
435 /* flash */
436 chip->cdev_flash.name = "flash";
437 chip->cdev_flash.max_brightness = 16;
438 chip->cdev_flash.brightness_set = lm3556_strobe_brightness_set;
439 err = led_classdev_register((struct device *)
440 &client->dev, &chip->cdev_flash);
441 if (err < 0)
442 goto err_out;
443 /* torch */
444 chip->cdev_torch.name = "torch";
445 chip->cdev_torch.max_brightness = 8;
446 chip->cdev_torch.brightness_set = lm3556_torch_brightness_set;
447 err = led_classdev_register((struct device *)
448 &client->dev, &chip->cdev_torch);
449 if (err < 0)
450 goto err_create_torch_file;
451 /* indicator */
452 chip->cdev_indicator.name = "indicator";
453 chip->cdev_indicator.max_brightness = 8;
454 chip->cdev_indicator.brightness_set = lm3556_indicator_brightness_set;
455 err = led_classdev_register((struct device *)
456 &client->dev, &chip->cdev_indicator);
457 if (err < 0)
458 goto err_create_indicator_file;
459
460 err = device_create_file(chip->cdev_indicator.dev, &dev_attr_pattern);
461 if (err < 0)
462 goto err_create_pattern_file;
463
464 dev_info(&client->dev, "LM3556 is initialized\n");
465 return 0;
466
467err_create_pattern_file:
468 led_classdev_unregister(&chip->cdev_indicator);
469err_create_indicator_file:
470 led_classdev_unregister(&chip->cdev_torch);
471err_create_torch_file:
472 led_classdev_unregister(&chip->cdev_flash);
473err_out:
474 return err;
475}
476
477static int __devexit lm3556_remove(struct i2c_client *client)
478{
479 struct lm3556_chip_data *chip = i2c_get_clientdata(client);
480
481 device_remove_file(chip->cdev_indicator.dev, &dev_attr_pattern);
482 led_classdev_unregister(&chip->cdev_indicator);
483 led_classdev_unregister(&chip->cdev_torch);
484 led_classdev_unregister(&chip->cdev_flash);
485 regmap_write(chip->regmap, REG_ENABLE, 0);
486 return 0;
487}
488
489static const struct i2c_device_id lm3556_id[] = {
490 {LM3556_NAME, 0},
491 {}
492};
493
494MODULE_DEVICE_TABLE(i2c, lm3556_id);
495
496static struct i2c_driver lm3556_i2c_driver = {
497 .driver = {
498 .name = LM3556_NAME,
499 .owner = THIS_MODULE,
500 .pm = NULL,
501 },
502 .probe = lm3556_probe,
503 .remove = __devexit_p(lm3556_remove),
504 .id_table = lm3556_id,
505};
506
507module_i2c_driver(lm3556_i2c_driver);
508
509MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3556");
510MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
511MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");
512MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-lm355x.c b/drivers/leds/leds-lm355x.c
new file mode 100644
index 000000000000..065ec015d67a
--- /dev/null
+++ b/drivers/leds/leds-lm355x.c
@@ -0,0 +1,572 @@
1/*
2* Simple driver for Texas Instruments LM355x LED Flash driver chip
3* Copyright (C) 2012 Texas Instruments
4*
5* This program is free software; you can redistribute it and/or modify
6* it under the terms of the GNU General Public License version 2 as
7* published by the Free Software Foundation.
8*/
9
10#include <linux/module.h>
11#include <linux/delay.h>
12#include <linux/i2c.h>
13#include <linux/gpio.h>
14#include <linux/leds.h>
15#include <linux/slab.h>
16#include <linux/platform_device.h>
17#include <linux/fs.h>
18#include <linux/regmap.h>
19#include <linux/workqueue.h>
20#include <linux/platform_data/leds-lm355x.h>
21
22enum lm355x_type {
23 CHIP_LM3554 = 0,
24 CHIP_LM3556,
25};
26
27enum lm355x_regs {
28 REG_FLAG = 0,
29 REG_TORCH_CFG,
30 REG_TORCH_CTRL,
31 REG_STROBE_CFG,
32 REG_FLASH_CTRL,
33 REG_INDI_CFG,
34 REG_INDI_CTRL,
35 REG_OPMODE,
36 REG_MAX,
37};
38
39/* operation mode */
40enum lm355x_mode {
41 MODE_SHDN = 0,
42 MODE_INDIC,
43 MODE_TORCH,
44 MODE_FLASH
45};
46
47/* register map info. */
48struct lm355x_reg_data {
49 u8 regno;
50 u8 mask;
51 u8 shift;
52};
53
54struct lm355x_chip_data {
55 struct device *dev;
56 enum lm355x_type type;
57
58 struct led_classdev cdev_flash;
59 struct led_classdev cdev_torch;
60 struct led_classdev cdev_indicator;
61
62 struct work_struct work_flash;
63 struct work_struct work_torch;
64 struct work_struct work_indicator;
65
66 u8 br_flash;
67 u8 br_torch;
68 u8 br_indicator;
69
70 struct lm355x_platform_data *pdata;
71 struct regmap *regmap;
72 struct mutex lock;
73
74 unsigned int last_flag;
75 struct lm355x_reg_data *regs;
76};
77
78/* specific indicator function for lm3556 */
79enum lm3556_indic_pulse_time {
80 PULSE_TIME_0_MS = 0,
81 PULSE_TIME_32_MS,
82 PULSE_TIME_64_MS,
83 PULSE_TIME_92_MS,
84 PULSE_TIME_128_MS,
85 PULSE_TIME_160_MS,
86 PULSE_TIME_196_MS,
87 PULSE_TIME_224_MS,
88 PULSE_TIME_256_MS,
89 PULSE_TIME_288_MS,
90 PULSE_TIME_320_MS,
91 PULSE_TIME_352_MS,
92 PULSE_TIME_384_MS,
93 PULSE_TIME_416_MS,
94 PULSE_TIME_448_MS,
95 PULSE_TIME_480_MS,
96};
97
98enum lm3556_indic_n_blank {
99 INDIC_N_BLANK_0 = 0,
100 INDIC_N_BLANK_1,
101 INDIC_N_BLANK_2,
102 INDIC_N_BLANK_3,
103 INDIC_N_BLANK_4,
104 INDIC_N_BLANK_5,
105 INDIC_N_BLANK_6,
106 INDIC_N_BLANK_7,
107 INDIC_N_BLANK_8,
108 INDIC_N_BLANK_9,
109 INDIC_N_BLANK_10,
110 INDIC_N_BLANK_11,
111 INDIC_N_BLANK_12,
112 INDIC_N_BLANK_13,
113 INDIC_N_BLANK_14,
114 INDIC_N_BLANK_15,
115};
116
117enum lm3556_indic_period {
118 INDIC_PERIOD_0 = 0,
119 INDIC_PERIOD_1,
120 INDIC_PERIOD_2,
121 INDIC_PERIOD_3,
122 INDIC_PERIOD_4,
123 INDIC_PERIOD_5,
124 INDIC_PERIOD_6,
125 INDIC_PERIOD_7,
126};
127
128#define INDIC_PATTERN_SIZE 4
129
130struct indicator {
131 u8 blinking;
132 u8 period_cnt;
133};
134
135/* indicator pattern data only for lm3556 */
136static struct indicator indicator_pattern[INDIC_PATTERN_SIZE] = {
137 [0] = {(INDIC_N_BLANK_1 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_1},
138 [1] = {(INDIC_N_BLANK_15 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_2},
139 [2] = {(INDIC_N_BLANK_10 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_4},
140 [3] = {(INDIC_N_BLANK_5 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_7},
141};
142
143static struct lm355x_reg_data lm3554_regs[REG_MAX] = {
144 [REG_FLAG] = {0xD0, 0xBF, 0},
145 [REG_TORCH_CFG] = {0xE0, 0x80, 7},
146 [REG_TORCH_CTRL] = {0xA0, 0x38, 3},
147 [REG_STROBE_CFG] = {0xE0, 0x04, 2},
148 [REG_FLASH_CTRL] = {0xB0, 0x78, 3},
149 [REG_INDI_CFG] = {0xE0, 0x08, 3},
150 [REG_INDI_CTRL] = {0xA0, 0xC0, 6},
151 [REG_OPMODE] = {0xA0, 0x03, 0},
152};
153
154static struct lm355x_reg_data lm3556_regs[REG_MAX] = {
155 [REG_FLAG] = {0x0B, 0xFF, 0},
156 [REG_TORCH_CFG] = {0x0A, 0x10, 4},
157 [REG_TORCH_CTRL] = {0x09, 0x70, 4},
158 [REG_STROBE_CFG] = {0x0A, 0x20, 5},
159 [REG_FLASH_CTRL] = {0x09, 0x0F, 0},
160 [REG_INDI_CFG] = {0xFF, 0xFF, 0},
161 [REG_INDI_CTRL] = {0x09, 0x70, 4},
162 [REG_OPMODE] = {0x0A, 0x03, 0},
163};
164
165static char lm355x_name[][I2C_NAME_SIZE] = {
166 [CHIP_LM3554] = LM3554_NAME,
167 [CHIP_LM3556] = LM3556_NAME,
168};
169
170/* chip initialize */
171static int __devinit lm355x_chip_init(struct lm355x_chip_data *chip)
172{
173 int ret;
174 unsigned int reg_val;
175 struct lm355x_platform_data *pdata = chip->pdata;
176
177 /* input and output pins configuration */
178 switch (chip->type) {
179 case CHIP_LM3554:
180 reg_val = pdata->pin_tx2 | pdata->ntc_pin;
181 ret = regmap_update_bits(chip->regmap, 0xE0, 0x28, reg_val);
182 if (ret < 0)
183 goto out;
184 reg_val = pdata->pass_mode;
185 ret = regmap_update_bits(chip->regmap, 0xA0, 0x04, reg_val);
186 if (ret < 0)
187 goto out;
188 break;
189
190 case CHIP_LM3556:
191 reg_val = pdata->pin_tx2 | pdata->ntc_pin | pdata->pass_mode;
192 ret = regmap_update_bits(chip->regmap, 0x0A, 0xC4, reg_val);
193 if (ret < 0)
194 goto out;
195 break;
196 default:
197 return -ENODATA;
198 }
199
200 return ret;
201out:
202 dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
203 return ret;
204}
205
206/* chip control */
207static void lm355x_control(struct lm355x_chip_data *chip,
208 u8 brightness, enum lm355x_mode opmode)
209{
210 int ret;
211 unsigned int reg_val;
212 struct lm355x_platform_data *pdata = chip->pdata;
213 struct lm355x_reg_data *preg = chip->regs;
214
215 ret = regmap_read(chip->regmap, preg[REG_FLAG].regno, &chip->last_flag);
216 if (ret < 0)
217 goto out;
218 if (chip->last_flag & preg[REG_FLAG].mask)
219 dev_info(chip->dev, "%s Last FLAG is 0x%x\n",
220 lm355x_name[chip->type],
221 chip->last_flag & preg[REG_FLAG].mask);
222 /* brightness 0 means shutdown */
223 if (!brightness)
224 opmode = MODE_SHDN;
225
226 switch (opmode) {
227 case MODE_TORCH:
228 ret =
229 regmap_update_bits(chip->regmap, preg[REG_TORCH_CTRL].regno,
230 preg[REG_TORCH_CTRL].mask,
231 (brightness - 1)
232 << preg[REG_TORCH_CTRL].shift);
233 if (ret < 0)
234 goto out;
235
236 if (pdata->pin_tx1 != LM355x_PIN_TORCH_DISABLE) {
237 ret =
238 regmap_update_bits(chip->regmap,
239 preg[REG_TORCH_CFG].regno,
240 preg[REG_TORCH_CFG].mask,
241 0x01 <<
242 preg[REG_TORCH_CFG].shift);
243 if (ret < 0)
244 goto out;
245 opmode = MODE_SHDN;
246 dev_info(chip->dev,
247 "torch brt is set - ext. torch pin mode\n");
248 }
249 break;
250
251 case MODE_FLASH:
252
253 ret =
254 regmap_update_bits(chip->regmap, preg[REG_FLASH_CTRL].regno,
255 preg[REG_FLASH_CTRL].mask,
256 (brightness - 1)
257 << preg[REG_FLASH_CTRL].shift);
258 if (ret < 0)
259 goto out;
260
261 if (pdata->pin_strobe != LM355x_PIN_STROBE_DISABLE) {
262 if (chip->type == CHIP_LM3554)
263 reg_val = 0x00;
264 else
265 reg_val = 0x01;
266 ret =
267 regmap_update_bits(chip->regmap,
268 preg[REG_STROBE_CFG].regno,
269 preg[REG_STROBE_CFG].mask,
270 reg_val <<
271 preg[REG_STROBE_CFG].shift);
272 if (ret < 0)
273 goto out;
274 opmode = MODE_SHDN;
275 dev_info(chip->dev,
276 "flash brt is set - ext. strobe pin mode\n");
277 }
278 break;
279
280 case MODE_INDIC:
281 ret =
282 regmap_update_bits(chip->regmap, preg[REG_INDI_CTRL].regno,
283 preg[REG_INDI_CTRL].mask,
284 (brightness - 1)
285 << preg[REG_INDI_CTRL].shift);
286 if (ret < 0)
287 goto out;
288
289 if (pdata->pin_tx2 != LM355x_PIN_TX_DISABLE) {
290 ret =
291 regmap_update_bits(chip->regmap,
292 preg[REG_INDI_CFG].regno,
293 preg[REG_INDI_CFG].mask,
294 0x01 <<
295 preg[REG_INDI_CFG].shift);
296 if (ret < 0)
297 goto out;
298 opmode = MODE_SHDN;
299 }
300 break;
301 case MODE_SHDN:
302 break;
303 default:
304 return;
305 }
306 /* operation mode control */
307 ret = regmap_update_bits(chip->regmap, preg[REG_OPMODE].regno,
308 preg[REG_OPMODE].mask,
309 opmode << preg[REG_OPMODE].shift);
310 if (ret < 0)
311 goto out;
312 return;
313out:
314 dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
315 return;
316}
317
318/* torch */
319static void lm355x_deferred_torch_brightness_set(struct work_struct *work)
320{
321 struct lm355x_chip_data *chip =
322 container_of(work, struct lm355x_chip_data, work_torch);
323
324 mutex_lock(&chip->lock);
325 lm355x_control(chip, chip->br_torch, MODE_TORCH);
326 mutex_unlock(&chip->lock);
327}
328
329static void lm355x_torch_brightness_set(struct led_classdev *cdev,
330 enum led_brightness brightness)
331{
332 struct lm355x_chip_data *chip =
333 container_of(cdev, struct lm355x_chip_data, cdev_torch);
334
335 chip->br_torch = brightness;
336 schedule_work(&chip->work_torch);
337}
338
339/* flash */
340static void lm355x_deferred_strobe_brightness_set(struct work_struct *work)
341{
342 struct lm355x_chip_data *chip =
343 container_of(work, struct lm355x_chip_data, work_flash);
344
345 mutex_lock(&chip->lock);
346 lm355x_control(chip, chip->br_flash, MODE_FLASH);
347 mutex_unlock(&chip->lock);
348}
349
350static void lm355x_strobe_brightness_set(struct led_classdev *cdev,
351 enum led_brightness brightness)
352{
353 struct lm355x_chip_data *chip =
354 container_of(cdev, struct lm355x_chip_data, cdev_flash);
355
356 chip->br_flash = brightness;
357 schedule_work(&chip->work_flash);
358}
359
360/* indicator */
361static void lm355x_deferred_indicator_brightness_set(struct work_struct *work)
362{
363 struct lm355x_chip_data *chip =
364 container_of(work, struct lm355x_chip_data, work_indicator);
365
366 mutex_lock(&chip->lock);
367 lm355x_control(chip, chip->br_indicator, MODE_INDIC);
368 mutex_unlock(&chip->lock);
369}
370
371static void lm355x_indicator_brightness_set(struct led_classdev *cdev,
372 enum led_brightness brightness)
373{
374 struct lm355x_chip_data *chip =
375 container_of(cdev, struct lm355x_chip_data, cdev_indicator);
376
377 chip->br_indicator = brightness;
378 schedule_work(&chip->work_indicator);
379}
380
381/* indicator pattern only for lm3556*/
382static ssize_t lm3556_indicator_pattern_store(struct device *dev,
383 struct device_attribute *devAttr,
384 const char *buf, size_t size)
385{
386 ssize_t ret;
387 struct led_classdev *led_cdev = dev_get_drvdata(dev);
388 struct lm355x_chip_data *chip =
389 container_of(led_cdev, struct lm355x_chip_data, cdev_indicator);
390 unsigned int state;
391
392 ret = kstrtouint(buf, 10, &state);
393 if (ret)
394 goto out;
395 if (state > INDIC_PATTERN_SIZE - 1)
396 state = INDIC_PATTERN_SIZE - 1;
397
398 ret = regmap_write(chip->regmap, 0x04,
399 indicator_pattern[state].blinking);
400 if (ret < 0)
401 goto out;
402
403 ret = regmap_write(chip->regmap, 0x05,
404 indicator_pattern[state].period_cnt);
405 if (ret < 0)
406 goto out;
407
408 return size;
409out:
410 dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
411 return size;
412}
413
414static DEVICE_ATTR(pattern, 0666, NULL, lm3556_indicator_pattern_store);
415
416static const struct regmap_config lm355x_regmap = {
417 .reg_bits = 8,
418 .val_bits = 8,
419 .max_register = 0xFF,
420};
421
422/* module initialize */
423static int __devinit lm355x_probe(struct i2c_client *client,
424 const struct i2c_device_id *id)
425{
426 struct lm355x_platform_data *pdata = client->dev.platform_data;
427 struct lm355x_chip_data *chip;
428
429 int err;
430
431 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
432 dev_err(&client->dev, "i2c functionality check fail.\n");
433 return -EOPNOTSUPP;
434 }
435
436 if (pdata == NULL) {
437 dev_err(&client->dev, "needs Platform Data.\n");
438 return -ENODATA;
439 }
440
441 chip = devm_kzalloc(&client->dev,
442 sizeof(struct lm355x_chip_data), GFP_KERNEL);
443 if (!chip)
444 return -ENOMEM;
445
446 chip->dev = &client->dev;
447 chip->type = id->driver_data;
448 switch (id->driver_data) {
449 case CHIP_LM3554:
450 chip->regs = lm3554_regs;
451 break;
452 case CHIP_LM3556:
453 chip->regs = lm3556_regs;
454 break;
455 default:
456 return -ENOSYS;
457 }
458 chip->pdata = pdata;
459
460 chip->regmap = devm_regmap_init_i2c(client, &lm355x_regmap);
461 if (IS_ERR(chip->regmap)) {
462 err = PTR_ERR(chip->regmap);
463 dev_err(&client->dev,
464 "Failed to allocate register map: %d\n", err);
465 return err;
466 }
467
468 mutex_init(&chip->lock);
469 i2c_set_clientdata(client, chip);
470
471 err = lm355x_chip_init(chip);
472 if (err < 0)
473 goto err_out;
474
475 /* flash */
476 INIT_WORK(&chip->work_flash, lm355x_deferred_strobe_brightness_set);
477 chip->cdev_flash.name = "flash";
478 chip->cdev_flash.max_brightness = 16;
479 chip->cdev_flash.brightness_set = lm355x_strobe_brightness_set;
480 err = led_classdev_register((struct device *)
481 &client->dev, &chip->cdev_flash);
482 if (err < 0)
483 goto err_out;
484 /* torch */
485 INIT_WORK(&chip->work_torch, lm355x_deferred_torch_brightness_set);
486 chip->cdev_torch.name = "torch";
487 chip->cdev_torch.max_brightness = 8;
488 chip->cdev_torch.brightness_set = lm355x_torch_brightness_set;
489 err = led_classdev_register((struct device *)
490 &client->dev, &chip->cdev_torch);
491 if (err < 0)
492 goto err_create_torch_file;
493 /* indicator */
494 INIT_WORK(&chip->work_indicator,
495 lm355x_deferred_indicator_brightness_set);
496 chip->cdev_indicator.name = "indicator";
497 if (id->driver_data == CHIP_LM3554)
498 chip->cdev_indicator.max_brightness = 4;
499 else
500 chip->cdev_indicator.max_brightness = 8;
501 chip->cdev_indicator.brightness_set = lm355x_indicator_brightness_set;
502 err = led_classdev_register((struct device *)
503 &client->dev, &chip->cdev_indicator);
504 if (err < 0)
505 goto err_create_indicator_file;
506 /* indicator pattern control only for LM3554 */
507 if (id->driver_data == CHIP_LM3556) {
508 err =
509 device_create_file(chip->cdev_indicator.dev,
510 &dev_attr_pattern);
511 if (err < 0)
512 goto err_create_pattern_file;
513 }
514
515 dev_info(&client->dev, "%s is initialized\n",
516 lm355x_name[id->driver_data]);
517 return 0;
518
519err_create_pattern_file:
520 led_classdev_unregister(&chip->cdev_indicator);
521err_create_indicator_file:
522 led_classdev_unregister(&chip->cdev_torch);
523err_create_torch_file:
524 led_classdev_unregister(&chip->cdev_flash);
525err_out:
526 return err;
527}
528
529static int __devexit lm355x_remove(struct i2c_client *client)
530{
531 struct lm355x_chip_data *chip = i2c_get_clientdata(client);
532 struct lm355x_reg_data *preg = chip->regs;
533
534 regmap_write(chip->regmap, preg[REG_OPMODE].regno, 0);
535 if (chip->type == CHIP_LM3556)
536 device_remove_file(chip->cdev_indicator.dev, &dev_attr_pattern);
537 led_classdev_unregister(&chip->cdev_indicator);
538 flush_work(&chip->work_indicator);
539 led_classdev_unregister(&chip->cdev_torch);
540 flush_work(&chip->work_torch);
541 led_classdev_unregister(&chip->cdev_flash);
542 flush_work(&chip->work_flash);
543 dev_info(&client->dev, "%s is removed\n", lm355x_name[chip->type]);
544
545 return 0;
546}
547
548static const struct i2c_device_id lm355x_id[] = {
549 {LM3554_NAME, CHIP_LM3554},
550 {LM3556_NAME, CHIP_LM3556},
551 {}
552};
553
554MODULE_DEVICE_TABLE(i2c, lm355x_id);
555
556static struct i2c_driver lm355x_i2c_driver = {
557 .driver = {
558 .name = LM355x_NAME,
559 .owner = THIS_MODULE,
560 .pm = NULL,
561 },
562 .probe = lm355x_probe,
563 .remove = __devexit_p(lm355x_remove),
564 .id_table = lm355x_id,
565};
566
567module_i2c_driver(lm355x_i2c_driver);
568
569MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM355x");
570MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
571MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");
572MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-lm3642.c b/drivers/leds/leds-lm3642.c
new file mode 100644
index 000000000000..3285006e9888
--- /dev/null
+++ b/drivers/leds/leds-lm3642.c
@@ -0,0 +1,462 @@
1/*
2* Simple driver for Texas Instruments LM3642 LED Flash driver chip
3* Copyright (C) 2012 Texas Instruments
4*
5* This program is free software; you can redistribute it and/or modify
6* it under the terms of the GNU General Public License version 2 as
7* published by the Free Software Foundation.
8*
9*/
10#include <linux/module.h>
11#include <linux/delay.h>
12#include <linux/i2c.h>
13#include <linux/leds.h>
14#include <linux/slab.h>
15#include <linux/platform_device.h>
16#include <linux/fs.h>
17#include <linux/regmap.h>
18#include <linux/workqueue.h>
19#include <linux/platform_data/leds-lm3642.h>
20
21#define REG_FILT_TIME (0x0)
22#define REG_IVFM_MODE (0x1)
23#define REG_TORCH_TIME (0x6)
24#define REG_FLASH (0x8)
25#define REG_I_CTRL (0x9)
26#define REG_ENABLE (0xA)
27#define REG_FLAG (0xB)
28#define REG_MAX (0xB)
29
30#define UVLO_EN_SHIFT (7)
31#define IVM_D_TH_SHIFT (2)
32#define TORCH_RAMP_UP_TIME_SHIFT (3)
33#define TORCH_RAMP_DN_TIME_SHIFT (0)
34#define INDUCTOR_I_LIMIT_SHIFT (6)
35#define FLASH_RAMP_TIME_SHIFT (3)
36#define FLASH_TOUT_TIME_SHIFT (0)
37#define TORCH_I_SHIFT (4)
38#define FLASH_I_SHIFT (0)
39#define IVFM_SHIFT (7)
40#define TX_PIN_EN_SHIFT (6)
41#define STROBE_PIN_EN_SHIFT (5)
42#define TORCH_PIN_EN_SHIFT (4)
43#define MODE_BITS_SHIFT (0)
44
45#define UVLO_EN_MASK (0x1)
46#define IVM_D_TH_MASK (0x7)
47#define TORCH_RAMP_UP_TIME_MASK (0x7)
48#define TORCH_RAMP_DN_TIME_MASK (0x7)
49#define INDUCTOR_I_LIMIT_MASK (0x1)
50#define FLASH_RAMP_TIME_MASK (0x7)
51#define FLASH_TOUT_TIME_MASK (0x7)
52#define TORCH_I_MASK (0x7)
53#define FLASH_I_MASK (0xF)
54#define IVFM_MASK (0x1)
55#define TX_PIN_EN_MASK (0x1)
56#define STROBE_PIN_EN_MASK (0x1)
57#define TORCH_PIN_EN_MASK (0x1)
58#define MODE_BITS_MASK (0x73)
59#define EX_PIN_CONTROL_MASK (0x71)
60#define EX_PIN_ENABLE_MASK (0x70)
61
62enum lm3642_mode {
63 MODES_STASNDBY = 0,
64 MODES_INDIC,
65 MODES_TORCH,
66 MODES_FLASH
67};
68
69struct lm3642_chip_data {
70 struct device *dev;
71
72 struct led_classdev cdev_flash;
73 struct led_classdev cdev_torch;
74 struct led_classdev cdev_indicator;
75
76 struct work_struct work_flash;
77 struct work_struct work_torch;
78 struct work_struct work_indicator;
79
80 u8 br_flash;
81 u8 br_torch;
82 u8 br_indicator;
83
84 enum lm3642_torch_pin_enable torch_pin;
85 enum lm3642_strobe_pin_enable strobe_pin;
86 enum lm3642_tx_pin_enable tx_pin;
87
88 struct lm3642_platform_data *pdata;
89 struct regmap *regmap;
90 struct mutex lock;
91
92 unsigned int last_flag;
93};
94
95/* chip initialize */
96static int __devinit lm3642_chip_init(struct lm3642_chip_data *chip)
97{
98 int ret;
99 struct lm3642_platform_data *pdata = chip->pdata;
100
101 /* set enable register */
102 ret = regmap_update_bits(chip->regmap, REG_ENABLE, EX_PIN_ENABLE_MASK,
103 pdata->tx_pin);
104 if (ret < 0)
105 dev_err(chip->dev, "Failed to update REG_ENABLE Register\n");
106 return ret;
107}
108
109/* chip control */
110static int lm3642_control(struct lm3642_chip_data *chip,
111 u8 brightness, enum lm3642_mode opmode)
112{
113 int ret;
114
115 ret = regmap_read(chip->regmap, REG_FLAG, &chip->last_flag);
116 if (ret < 0) {
117 dev_err(chip->dev, "Failed to read REG_FLAG Register\n");
118 goto out;
119 }
120
121 if (chip->last_flag)
122 dev_info(chip->dev, "Last FLAG is 0x%x\n", chip->last_flag);
123
124 /* brightness 0 means off-state */
125 if (!brightness)
126 opmode = MODES_STASNDBY;
127
128 switch (opmode) {
129 case MODES_TORCH:
130 ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
131 TORCH_I_MASK << TORCH_I_SHIFT,
132 (brightness - 1) << TORCH_I_SHIFT);
133
134 if (chip->torch_pin)
135 opmode |= (TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT);
136 break;
137
138 case MODES_FLASH:
139 ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
140 FLASH_I_MASK << FLASH_I_SHIFT,
141 (brightness - 1) << FLASH_I_SHIFT);
142
143 if (chip->strobe_pin)
144 opmode |= (STROBE_PIN_EN_MASK << STROBE_PIN_EN_SHIFT);
145 break;
146
147 case MODES_INDIC:
148 ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
149 TORCH_I_MASK << TORCH_I_SHIFT,
150 (brightness - 1) << TORCH_I_SHIFT);
151 break;
152
153 case MODES_STASNDBY:
154
155 break;
156
157 default:
158 return ret;
159 }
160 if (ret < 0) {
161 dev_err(chip->dev, "Failed to write REG_I_CTRL Register\n");
162 goto out;
163 }
164
165 if (chip->tx_pin)
166 opmode |= (TX_PIN_EN_MASK << TX_PIN_EN_SHIFT);
167
168 ret = regmap_update_bits(chip->regmap, REG_ENABLE,
169 MODE_BITS_MASK << MODE_BITS_SHIFT,
170 opmode << MODE_BITS_SHIFT);
171out:
172 return ret;
173}
174
175/* torch */
176
177/* torch pin config for lm3642*/
178static ssize_t lm3642_torch_pin_store(struct device *dev,
179 struct device_attribute *devAttr,
180 const char *buf, size_t size)
181{
182 ssize_t ret;
183 struct led_classdev *led_cdev = dev_get_drvdata(dev);
184 struct lm3642_chip_data *chip =
185 container_of(led_cdev, struct lm3642_chip_data, cdev_indicator);
186 unsigned int state;
187
188 ret = kstrtouint(buf, 10, &state);
189 if (ret)
190 goto out_strtoint;
191 if (state != 0)
192 state = 0x01 << TORCH_PIN_EN_SHIFT;
193
194 chip->torch_pin = state;
195 ret = regmap_update_bits(chip->regmap, REG_ENABLE,
196 TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT,
197 state);
198 if (ret < 0)
199 goto out;
200
201 return size;
202out:
203 dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
204 return size;
205out_strtoint:
206 dev_err(chip->dev, "%s: fail to change str to int\n", __func__);
207 return size;
208}
209
210static DEVICE_ATTR(torch_pin, 0666, NULL, lm3642_torch_pin_store);
211
212static void lm3642_deferred_torch_brightness_set(struct work_struct *work)
213{
214 struct lm3642_chip_data *chip =
215 container_of(work, struct lm3642_chip_data, work_torch);
216
217 mutex_lock(&chip->lock);
218 lm3642_control(chip, chip->br_torch, MODES_TORCH);
219 mutex_unlock(&chip->lock);
220}
221
222static void lm3642_torch_brightness_set(struct led_classdev *cdev,
223 enum led_brightness brightness)
224{
225 struct lm3642_chip_data *chip =
226 container_of(cdev, struct lm3642_chip_data, cdev_torch);
227
228 chip->br_torch = brightness;
229 schedule_work(&chip->work_torch);
230}
231
232/* flash */
233
234/* strobe pin config for lm3642*/
235static ssize_t lm3642_strobe_pin_store(struct device *dev,
236 struct device_attribute *devAttr,
237 const char *buf, size_t size)
238{
239 ssize_t ret;
240 struct led_classdev *led_cdev = dev_get_drvdata(dev);
241 struct lm3642_chip_data *chip =
242 container_of(led_cdev, struct lm3642_chip_data, cdev_indicator);
243 unsigned int state;
244
245 ret = kstrtouint(buf, 10, &state);
246 if (ret)
247 goto out_strtoint;
248 if (state != 0)
249 state = 0x01 << STROBE_PIN_EN_SHIFT;
250
251 chip->strobe_pin = state;
252 ret = regmap_update_bits(chip->regmap, REG_ENABLE,
253 STROBE_PIN_EN_MASK << STROBE_PIN_EN_SHIFT,
254 state);
255 if (ret < 0)
256 goto out;
257
258 return size;
259out:
260 dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
261 return size;
262out_strtoint:
263 dev_err(chip->dev, "%s: fail to change str to int\n", __func__);
264 return size;
265}
266
267static DEVICE_ATTR(strobe_pin, 0666, NULL, lm3642_strobe_pin_store);
268
269static void lm3642_deferred_strobe_brightness_set(struct work_struct *work)
270{
271 struct lm3642_chip_data *chip =
272 container_of(work, struct lm3642_chip_data, work_flash);
273
274 mutex_lock(&chip->lock);
275 lm3642_control(chip, chip->br_flash, MODES_FLASH);
276 mutex_unlock(&chip->lock);
277}
278
279static void lm3642_strobe_brightness_set(struct led_classdev *cdev,
280 enum led_brightness brightness)
281{
282 struct lm3642_chip_data *chip =
283 container_of(cdev, struct lm3642_chip_data, cdev_flash);
284
285 chip->br_flash = brightness;
286 schedule_work(&chip->work_flash);
287}
288
289/* indicator */
290static void lm3642_deferred_indicator_brightness_set(struct work_struct *work)
291{
292 struct lm3642_chip_data *chip =
293 container_of(work, struct lm3642_chip_data, work_indicator);
294
295 mutex_lock(&chip->lock);
296 lm3642_control(chip, chip->br_indicator, MODES_INDIC);
297 mutex_unlock(&chip->lock);
298}
299
300static void lm3642_indicator_brightness_set(struct led_classdev *cdev,
301 enum led_brightness brightness)
302{
303 struct lm3642_chip_data *chip =
304 container_of(cdev, struct lm3642_chip_data, cdev_indicator);
305
306 chip->br_indicator = brightness;
307 schedule_work(&chip->work_indicator);
308}
309
310static const struct regmap_config lm3642_regmap = {
311 .reg_bits = 8,
312 .val_bits = 8,
313 .max_register = REG_MAX,
314};
315
316static int __devinit lm3642_probe(struct i2c_client *client,
317 const struct i2c_device_id *id)
318{
319 struct lm3642_platform_data *pdata = client->dev.platform_data;
320 struct lm3642_chip_data *chip;
321
322 int err;
323
324 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
325 dev_err(&client->dev, "i2c functionality check fail.\n");
326 return -EOPNOTSUPP;
327 }
328
329 if (pdata == NULL) {
330 dev_err(&client->dev, "needs Platform Data.\n");
331 return -ENODATA;
332 }
333
334 chip = devm_kzalloc(&client->dev,
335 sizeof(struct lm3642_chip_data), GFP_KERNEL);
336 if (!chip)
337 return -ENOMEM;
338
339 chip->dev = &client->dev;
340 chip->pdata = pdata;
341
342 chip->tx_pin = pdata->tx_pin;
343 chip->torch_pin = pdata->torch_pin;
344 chip->strobe_pin = pdata->strobe_pin;
345
346 chip->regmap = devm_regmap_init_i2c(client, &lm3642_regmap);
347 if (IS_ERR(chip->regmap)) {
348 err = PTR_ERR(chip->regmap);
349 dev_err(&client->dev, "Failed to allocate register map: %d\n",
350 err);
351 return err;
352 }
353
354 mutex_init(&chip->lock);
355 i2c_set_clientdata(client, chip);
356
357 err = lm3642_chip_init(chip);
358 if (err < 0)
359 goto err_out;
360
361 /* flash */
362 INIT_WORK(&chip->work_flash, lm3642_deferred_strobe_brightness_set);
363 chip->cdev_flash.name = "flash";
364 chip->cdev_flash.max_brightness = 16;
365 chip->cdev_flash.brightness_set = lm3642_strobe_brightness_set;
366 err = led_classdev_register((struct device *)
367 &client->dev, &chip->cdev_flash);
368 if (err < 0) {
369 dev_err(chip->dev, "failed to register flash\n");
370 goto err_out;
371 }
372 err = device_create_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
373 if (err < 0) {
374 dev_err(chip->dev, "failed to create strobe-pin file\n");
375 goto err_create_flash_pin_file;
376 }
377
378 /* torch */
379 INIT_WORK(&chip->work_torch, lm3642_deferred_torch_brightness_set);
380 chip->cdev_torch.name = "torch";
381 chip->cdev_torch.max_brightness = 8;
382 chip->cdev_torch.brightness_set = lm3642_torch_brightness_set;
383 err = led_classdev_register((struct device *)
384 &client->dev, &chip->cdev_torch);
385 if (err < 0) {
386 dev_err(chip->dev, "failed to register torch\n");
387 goto err_create_torch_file;
388 }
389 err = device_create_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
390 if (err < 0) {
391 dev_err(chip->dev, "failed to create torch-pin file\n");
392 goto err_create_torch_pin_file;
393 }
394
395 /* indicator */
396 INIT_WORK(&chip->work_indicator,
397 lm3642_deferred_indicator_brightness_set);
398 chip->cdev_indicator.name = "indicator";
399 chip->cdev_indicator.max_brightness = 8;
400 chip->cdev_indicator.brightness_set = lm3642_indicator_brightness_set;
401 err = led_classdev_register((struct device *)
402 &client->dev, &chip->cdev_indicator);
403 if (err < 0) {
404 dev_err(chip->dev, "failed to register indicator\n");
405 goto err_create_indicator_file;
406 }
407
408 dev_info(&client->dev, "LM3642 is initialized\n");
409 return 0;
410
411err_create_indicator_file:
412 device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
413err_create_torch_pin_file:
414 led_classdev_unregister(&chip->cdev_torch);
415err_create_torch_file:
416 device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
417err_create_flash_pin_file:
418 led_classdev_unregister(&chip->cdev_flash);
419err_out:
420 return err;
421}
422
423static int __devexit lm3642_remove(struct i2c_client *client)
424{
425 struct lm3642_chip_data *chip = i2c_get_clientdata(client);
426
427 led_classdev_unregister(&chip->cdev_indicator);
428 flush_work(&chip->work_indicator);
429 device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin);
430 led_classdev_unregister(&chip->cdev_torch);
431 flush_work(&chip->work_torch);
432 device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin);
433 led_classdev_unregister(&chip->cdev_flash);
434 flush_work(&chip->work_flash);
435 regmap_write(chip->regmap, REG_ENABLE, 0);
436 return 0;
437}
438
439static const struct i2c_device_id lm3642_id[] = {
440 {LM3642_NAME, 0},
441 {}
442};
443
444MODULE_DEVICE_TABLE(i2c, lm3642_id);
445
446static struct i2c_driver lm3642_i2c_driver = {
447 .driver = {
448 .name = LM3642_NAME,
449 .owner = THIS_MODULE,
450 .pm = NULL,
451 },
452 .probe = lm3642_probe,
453 .remove = __devexit_p(lm3642_remove),
454 .id_table = lm3642_id,
455};
456
457module_i2c_driver(lm3642_i2c_driver);
458
459MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3642");
460MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
461MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");
462MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
index fbc12acada95..97994ffdc014 100644
--- a/drivers/leds/leds-lp5523.c
+++ b/drivers/leds/leds-lp5523.c
@@ -104,6 +104,11 @@
104#define LED_ACTIVE(mux, led) (!!(mux & (0x0001 << led))) 104#define LED_ACTIVE(mux, led) (!!(mux & (0x0001 << led)))
105#define SHIFT_MASK(id) (((id) - 1) * 2) 105#define SHIFT_MASK(id) (((id) - 1) * 2)
106 106
107enum lp5523_chip_id {
108 LP5523,
109 LP55231,
110};
111
107struct lp5523_engine { 112struct lp5523_engine {
108 int id; 113 int id;
109 u8 mode; 114 u8 mode;
@@ -150,7 +155,7 @@ static inline struct lp5523_chip *led_to_lp5523(struct lp5523_led *led)
150 leds[led->id]); 155 leds[led->id]);
151} 156}
152 157
153static int lp5523_set_mode(struct lp5523_engine *engine, u8 mode); 158static void lp5523_set_mode(struct lp5523_engine *engine, u8 mode);
154static int lp5523_set_engine_mode(struct lp5523_engine *engine, u8 mode); 159static int lp5523_set_engine_mode(struct lp5523_engine *engine, u8 mode);
155static int lp5523_load_program(struct lp5523_engine *engine, const u8 *pattern); 160static int lp5523_load_program(struct lp5523_engine *engine, const u8 *pattern);
156 161
@@ -177,7 +182,7 @@ static int lp5523_detect(struct i2c_client *client)
177 int ret; 182 int ret;
178 u8 buf; 183 u8 buf;
179 184
180 ret = lp5523_write(client, LP5523_REG_ENABLE, 0x40); 185 ret = lp5523_write(client, LP5523_REG_ENABLE, LP5523_ENABLE);
181 if (ret) 186 if (ret)
182 return ret; 187 return ret;
183 ret = lp5523_read(client, LP5523_REG_ENABLE, &buf); 188 ret = lp5523_read(client, LP5523_REG_ENABLE, &buf);
@@ -338,7 +343,8 @@ static int lp5523_mux_parse(const char *buf, u16 *mux, size_t len)
338{ 343{
339 int i; 344 int i;
340 u16 tmp_mux = 0; 345 u16 tmp_mux = 0;
341 len = len < LP5523_LEDS ? len : LP5523_LEDS; 346
347 len = min_t(int, len, LP5523_LEDS);
342 for (i = 0; i < len; i++) { 348 for (i = 0; i < len; i++) {
343 switch (buf[i]) { 349 switch (buf[i]) {
344 case '1': 350 case '1':
@@ -546,6 +552,9 @@ static int lp5523_do_store_load(struct lp5523_engine *engine,
546 unsigned cmd; 552 unsigned cmd;
547 u8 pattern[LP5523_PROGRAM_LENGTH] = {0}; 553 u8 pattern[LP5523_PROGRAM_LENGTH] = {0};
548 554
555 if (engine->mode != LP5523_CMD_LOAD)
556 return -EINVAL;
557
549 while ((offset < len - 1) && (i < LP5523_PROGRAM_LENGTH)) { 558 while ((offset < len - 1) && (i < LP5523_PROGRAM_LENGTH)) {
550 /* separate sscanfs because length is working only for %s */ 559 /* separate sscanfs because length is working only for %s */
551 ret = sscanf(buf + offset, "%2s%n ", c, &nrchars); 560 ret = sscanf(buf + offset, "%2s%n ", c, &nrchars);
@@ -563,12 +572,7 @@ static int lp5523_do_store_load(struct lp5523_engine *engine,
563 goto fail; 572 goto fail;
564 573
565 mutex_lock(&chip->lock); 574 mutex_lock(&chip->lock);
566 575 ret = lp5523_load_program(engine, pattern);
567 if (engine->mode == LP5523_CMD_LOAD)
568 ret = lp5523_load_program(engine, pattern);
569 else
570 ret = -EINVAL;
571
572 mutex_unlock(&chip->lock); 576 mutex_unlock(&chip->lock);
573 577
574 if (ret) { 578 if (ret) {
@@ -755,6 +759,7 @@ static struct attribute *lp5523_attributes[] = {
755 &dev_attr_engine2_leds.attr, 759 &dev_attr_engine2_leds.attr,
756 &dev_attr_engine3_load.attr, 760 &dev_attr_engine3_load.attr,
757 &dev_attr_engine3_leds.attr, 761 &dev_attr_engine3_leds.attr,
762 NULL,
758}; 763};
759 764
760static const struct attribute_group lp5523_group = { 765static const struct attribute_group lp5523_group = {
@@ -789,26 +794,28 @@ static void lp5523_unregister_sysfs(struct i2c_client *client)
789/*--------------------------------------------------------------*/ 794/*--------------------------------------------------------------*/
790/* Set chip operating mode */ 795/* Set chip operating mode */
791/*--------------------------------------------------------------*/ 796/*--------------------------------------------------------------*/
792static int lp5523_set_mode(struct lp5523_engine *engine, u8 mode) 797static void lp5523_set_mode(struct lp5523_engine *engine, u8 mode)
793{ 798{
794 int ret = 0;
795
796 /* if in that mode already do nothing, except for run */ 799 /* if in that mode already do nothing, except for run */
797 if (mode == engine->mode && mode != LP5523_CMD_RUN) 800 if (mode == engine->mode && mode != LP5523_CMD_RUN)
798 return 0; 801 return;
799 802
800 if (mode == LP5523_CMD_RUN) { 803 switch (mode) {
801 ret = lp5523_run_program(engine); 804 case LP5523_CMD_RUN:
802 } else if (mode == LP5523_CMD_LOAD) { 805 lp5523_run_program(engine);
806 break;
807 case LP5523_CMD_LOAD:
803 lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED); 808 lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED);
804 lp5523_set_engine_mode(engine, LP5523_CMD_LOAD); 809 lp5523_set_engine_mode(engine, LP5523_CMD_LOAD);
805 } else if (mode == LP5523_CMD_DISABLED) { 810 break;
811 case LP5523_CMD_DISABLED:
806 lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED); 812 lp5523_set_engine_mode(engine, LP5523_CMD_DISABLED);
813 break;
814 default:
815 return;
807 } 816 }
808 817
809 engine->mode = mode; 818 engine->mode = mode;
810
811 return ret;
812} 819}
813 820
814/*--------------------------------------------------------------*/ 821/*--------------------------------------------------------------*/
@@ -827,7 +834,8 @@ static int __init lp5523_init_engine(struct lp5523_engine *engine, int id)
827} 834}
828 835
829static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev, 836static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev,
830 int chan, struct lp5523_platform_data *pdata) 837 int chan, struct lp5523_platform_data *pdata,
838 const char *chip_name)
831{ 839{
832 char name[32]; 840 char name[32];
833 int res; 841 int res;
@@ -846,10 +854,14 @@ static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev,
846 return -EINVAL; 854 return -EINVAL;
847 } 855 }
848 856
849 snprintf(name, sizeof(name), "%s:channel%d", 857 if (pdata->led_config[chan].name) {
850 pdata->label ?: "lp5523", chan); 858 led->cdev.name = pdata->led_config[chan].name;
859 } else {
860 snprintf(name, sizeof(name), "%s:channel%d",
861 pdata->label ? : chip_name, chan);
862 led->cdev.name = name;
863 }
851 864
852 led->cdev.name = name;
853 led->cdev.brightness_set = lp5523_set_brightness; 865 led->cdev.brightness_set = lp5523_set_brightness;
854 res = led_classdev_register(dev, &led->cdev); 866 res = led_classdev_register(dev, &led->cdev);
855 if (res < 0) { 867 if (res < 0) {
@@ -917,7 +929,7 @@ static int __devinit lp5523_probe(struct i2c_client *client,
917 if (ret) 929 if (ret)
918 goto fail1; 930 goto fail1;
919 931
920 dev_info(&client->dev, "LP5523 Programmable led chip found\n"); 932 dev_info(&client->dev, "%s Programmable led chip found\n", id->name);
921 933
922 /* Initialize engines */ 934 /* Initialize engines */
923 for (i = 0; i < ARRAY_SIZE(chip->engines); i++) { 935 for (i = 0; i < ARRAY_SIZE(chip->engines); i++) {
@@ -945,7 +957,8 @@ static int __devinit lp5523_probe(struct i2c_client *client,
945 INIT_WORK(&chip->leds[led].brightness_work, 957 INIT_WORK(&chip->leds[led].brightness_work,
946 lp5523_led_brightness_work); 958 lp5523_led_brightness_work);
947 959
948 ret = lp5523_init_led(&chip->leds[led], &client->dev, i, pdata); 960 ret = lp5523_init_led(&chip->leds[led], &client->dev, i, pdata,
961 id->name);
949 if (ret) { 962 if (ret) {
950 dev_err(&client->dev, "error initializing leds\n"); 963 dev_err(&client->dev, "error initializing leds\n");
951 goto fail2; 964 goto fail2;
@@ -970,7 +983,7 @@ static int __devinit lp5523_probe(struct i2c_client *client,
970fail2: 983fail2:
971 for (i = 0; i < chip->num_leds; i++) { 984 for (i = 0; i < chip->num_leds; i++) {
972 led_classdev_unregister(&chip->leds[i].cdev); 985 led_classdev_unregister(&chip->leds[i].cdev);
973 cancel_work_sync(&chip->leds[i].brightness_work); 986 flush_work(&chip->leds[i].brightness_work);
974 } 987 }
975fail1: 988fail1:
976 if (pdata->enable) 989 if (pdata->enable)
@@ -985,11 +998,14 @@ static int lp5523_remove(struct i2c_client *client)
985 struct lp5523_chip *chip = i2c_get_clientdata(client); 998 struct lp5523_chip *chip = i2c_get_clientdata(client);
986 int i; 999 int i;
987 1000
1001 /* Disable engine mode */
1002 lp5523_write(client, LP5523_REG_OP_MODE, LP5523_CMD_DISABLED);
1003
988 lp5523_unregister_sysfs(client); 1004 lp5523_unregister_sysfs(client);
989 1005
990 for (i = 0; i < chip->num_leds; i++) { 1006 for (i = 0; i < chip->num_leds; i++) {
991 led_classdev_unregister(&chip->leds[i].cdev); 1007 led_classdev_unregister(&chip->leds[i].cdev);
992 cancel_work_sync(&chip->leds[i].brightness_work); 1008 flush_work(&chip->leds[i].brightness_work);
993 } 1009 }
994 1010
995 if (chip->pdata->enable) 1011 if (chip->pdata->enable)
@@ -1000,7 +1016,8 @@ static int lp5523_remove(struct i2c_client *client)
1000} 1016}
1001 1017
1002static const struct i2c_device_id lp5523_id[] = { 1018static const struct i2c_device_id lp5523_id[] = {
1003 { "lp5523", 0 }, 1019 { "lp5523", LP5523 },
1020 { "lp55231", LP55231 },
1004 { } 1021 { }
1005}; 1022};
1006 1023
@@ -1008,7 +1025,7 @@ MODULE_DEVICE_TABLE(i2c, lp5523_id);
1008 1025
1009static struct i2c_driver lp5523_driver = { 1026static struct i2c_driver lp5523_driver = {
1010 .driver = { 1027 .driver = {
1011 .name = "lp5523", 1028 .name = "lp5523x",
1012 }, 1029 },
1013 .probe = lp5523_probe, 1030 .probe = lp5523_probe,
1014 .remove = lp5523_remove, 1031 .remove = lp5523_remove,
diff --git a/drivers/leds/leds-pca9633.c b/drivers/leds/leds-pca9633.c
index edcd706c5631..2f2f9c43535d 100644
--- a/drivers/leds/leds-pca9633.c
+++ b/drivers/leds/leds-pca9633.c
@@ -22,6 +22,7 @@
22#include <linux/i2c.h> 22#include <linux/i2c.h>
23#include <linux/workqueue.h> 23#include <linux/workqueue.h>
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/platform_data/leds-pca9633.h>
25 26
26/* LED select registers determine the source that drives LED outputs */ 27/* LED select registers determine the source that drives LED outputs */
27#define PCA9633_LED_OFF 0x0 /* LED driver off */ 28#define PCA9633_LED_OFF 0x0 /* LED driver off */
@@ -96,13 +97,13 @@ static int __devinit pca9633_probe(struct i2c_client *client,
96 const struct i2c_device_id *id) 97 const struct i2c_device_id *id)
97{ 98{
98 struct pca9633_led *pca9633; 99 struct pca9633_led *pca9633;
99 struct led_platform_data *pdata; 100 struct pca9633_platform_data *pdata;
100 int i, err; 101 int i, err;
101 102
102 pdata = client->dev.platform_data; 103 pdata = client->dev.platform_data;
103 104
104 if (pdata) { 105 if (pdata) {
105 if (pdata->num_leds <= 0 || pdata->num_leds > 4) { 106 if (pdata->leds.num_leds <= 0 || pdata->leds.num_leds > 4) {
106 dev_err(&client->dev, "board info must claim at most 4 LEDs"); 107 dev_err(&client->dev, "board info must claim at most 4 LEDs");
107 return -EINVAL; 108 return -EINVAL;
108 } 109 }
@@ -119,14 +120,14 @@ static int __devinit pca9633_probe(struct i2c_client *client,
119 pca9633[i].led_num = i; 120 pca9633[i].led_num = i;
120 121
121 /* Platform data can specify LED names and default triggers */ 122 /* Platform data can specify LED names and default triggers */
122 if (pdata && i < pdata->num_leds) { 123 if (pdata && i < pdata->leds.num_leds) {
123 if (pdata->leds[i].name) 124 if (pdata->leds.leds[i].name)
124 snprintf(pca9633[i].name, 125 snprintf(pca9633[i].name,
125 sizeof(pca9633[i].name), "pca9633:%s", 126 sizeof(pca9633[i].name), "pca9633:%s",
126 pdata->leds[i].name); 127 pdata->leds.leds[i].name);
127 if (pdata->leds[i].default_trigger) 128 if (pdata->leds.leds[i].default_trigger)
128 pca9633[i].led_cdev.default_trigger = 129 pca9633[i].led_cdev.default_trigger =
129 pdata->leds[i].default_trigger; 130 pdata->leds.leds[i].default_trigger;
130 } else { 131 } else {
131 snprintf(pca9633[i].name, sizeof(pca9633[i].name), 132 snprintf(pca9633[i].name, sizeof(pca9633[i].name),
132 "pca9633:%d", i); 133 "pca9633:%d", i);
@@ -145,6 +146,10 @@ static int __devinit pca9633_probe(struct i2c_client *client,
145 /* Disable LED all-call address and set normal mode */ 146 /* Disable LED all-call address and set normal mode */
146 i2c_smbus_write_byte_data(client, PCA9633_MODE1, 0x00); 147 i2c_smbus_write_byte_data(client, PCA9633_MODE1, 0x00);
147 148
149 /* Configure output: open-drain or totem pole (push-pull) */
150 if (pdata && pdata->outdrv == PCA9633_OPEN_DRAIN)
151 i2c_smbus_write_byte_data(client, PCA9633_MODE2, 0x01);
152
148 /* Turn off LEDs */ 153 /* Turn off LEDs */
149 i2c_smbus_write_byte_data(client, PCA9633_LEDOUT, 0x00); 154 i2c_smbus_write_byte_data(client, PCA9633_LEDOUT, 0x00);
150 155
diff --git a/drivers/leds/leds-wm8350.c b/drivers/leds/leds-wm8350.c
index 4c62113f7a77..88f23f845595 100644
--- a/drivers/leds/leds-wm8350.c
+++ b/drivers/leds/leds-wm8350.c
@@ -201,7 +201,7 @@ static int wm8350_led_probe(struct platform_device *pdev)
201 struct regulator *isink, *dcdc; 201 struct regulator *isink, *dcdc;
202 struct wm8350_led *led; 202 struct wm8350_led *led;
203 struct wm8350_led_platform_data *pdata = pdev->dev.platform_data; 203 struct wm8350_led_platform_data *pdata = pdev->dev.platform_data;
204 int ret, i; 204 int i;
205 205
206 if (pdata == NULL) { 206 if (pdata == NULL) {
207 dev_err(&pdev->dev, "no platform data\n"); 207 dev_err(&pdev->dev, "no platform data\n");
@@ -214,24 +214,21 @@ static int wm8350_led_probe(struct platform_device *pdev)
214 return -EINVAL; 214 return -EINVAL;
215 } 215 }
216 216
217 isink = regulator_get(&pdev->dev, "led_isink"); 217 isink = devm_regulator_get(&pdev->dev, "led_isink");
218 if (IS_ERR(isink)) { 218 if (IS_ERR(isink)) {
219 printk(KERN_ERR "%s: can't get ISINK\n", __func__); 219 printk(KERN_ERR "%s: can't get ISINK\n", __func__);
220 return PTR_ERR(isink); 220 return PTR_ERR(isink);
221 } 221 }
222 222
223 dcdc = regulator_get(&pdev->dev, "led_vcc"); 223 dcdc = devm_regulator_get(&pdev->dev, "led_vcc");
224 if (IS_ERR(dcdc)) { 224 if (IS_ERR(dcdc)) {
225 printk(KERN_ERR "%s: can't get DCDC\n", __func__); 225 printk(KERN_ERR "%s: can't get DCDC\n", __func__);
226 ret = PTR_ERR(dcdc); 226 return PTR_ERR(dcdc);
227 goto err_isink;
228 } 227 }
229 228
230 led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL); 229 led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL);
231 if (led == NULL) { 230 if (led == NULL)
232 ret = -ENOMEM; 231 return -ENOMEM;
233 goto err_dcdc;
234 }
235 232
236 led->cdev.brightness_set = wm8350_led_set; 233 led->cdev.brightness_set = wm8350_led_set;
237 led->cdev.default_trigger = pdata->default_trigger; 234 led->cdev.default_trigger = pdata->default_trigger;
@@ -257,17 +254,7 @@ static int wm8350_led_probe(struct platform_device *pdev)
257 led->value = LED_OFF; 254 led->value = LED_OFF;
258 platform_set_drvdata(pdev, led); 255 platform_set_drvdata(pdev, led);
259 256
260 ret = led_classdev_register(&pdev->dev, &led->cdev); 257 return led_classdev_register(&pdev->dev, &led->cdev);
261 if (ret < 0)
262 goto err_dcdc;
263
264 return 0;
265
266 err_dcdc:
267 regulator_put(dcdc);
268 err_isink:
269 regulator_put(isink);
270 return ret;
271} 258}
272 259
273static int wm8350_led_remove(struct platform_device *pdev) 260static int wm8350_led_remove(struct platform_device *pdev)
@@ -277,8 +264,6 @@ static int wm8350_led_remove(struct platform_device *pdev)
277 led_classdev_unregister(&led->cdev); 264 led_classdev_unregister(&led->cdev);
278 flush_work(&led->work); 265 flush_work(&led->work);
279 wm8350_led_disable(led); 266 wm8350_led_disable(led);
280 regulator_put(led->dcdc);
281 regulator_put(led->isink);
282 return 0; 267 return 0;
283} 268}
284 269
diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
index d02acd496126..4c50365344a9 100644
--- a/drivers/leds/leds.h
+++ b/drivers/leds/leds.h
@@ -32,6 +32,8 @@ static inline int led_get_brightness(struct led_classdev *led_cdev)
32 return led_cdev->brightness; 32 return led_cdev->brightness;
33} 33}
34 34
35void led_stop_software_blink(struct led_classdev *led_cdev);
36
35extern struct rw_semaphore leds_list_lock; 37extern struct rw_semaphore leds_list_lock;
36extern struct list_head leds_list; 38extern struct list_head leds_list;
37 39
diff --git a/include/linux/leds-lp5523.h b/include/linux/leds-lp5523.h
index 2694289babd0..727877fb406d 100644
--- a/include/linux/leds-lp5523.h
+++ b/include/linux/leds-lp5523.h
@@ -26,6 +26,7 @@
26/* See Documentation/leds/leds-lp5523.txt */ 26/* See Documentation/leds/leds-lp5523.txt */
27 27
28struct lp5523_led_config { 28struct lp5523_led_config {
29 const char *name;
29 u8 chan_nr; 30 u8 chan_nr;
30 u8 led_current; /* mA x10, 0 if led is not connected */ 31 u8 led_current; /* mA x10, 0 if led is not connected */
31 u8 max_current; 32 u8 max_current;
diff --git a/include/linux/leds.h b/include/linux/leds.h
index c6f8dad2ceb0..6e53bb31c220 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -16,6 +16,7 @@
16#include <linux/spinlock.h> 16#include <linux/spinlock.h>
17#include <linux/rwsem.h> 17#include <linux/rwsem.h>
18#include <linux/timer.h> 18#include <linux/timer.h>
19#include <linux/workqueue.h>
19 20
20struct device; 21struct device;
21/* 22/*
@@ -69,6 +70,9 @@ struct led_classdev {
69 struct timer_list blink_timer; 70 struct timer_list blink_timer;
70 int blink_brightness; 71 int blink_brightness;
71 72
73 struct work_struct set_brightness_work;
74 int delayed_set_value;
75
72#ifdef CONFIG_LEDS_TRIGGERS 76#ifdef CONFIG_LEDS_TRIGGERS
73 /* Protects the trigger data below */ 77 /* Protects the trigger data below */
74 struct rw_semaphore trigger_lock; 78 struct rw_semaphore trigger_lock;
diff --git a/include/linux/platform_data/leds-lm3556.h b/include/linux/platform_data/leds-lm3556.h
deleted file mode 100644
index 4b4e7d6b0527..000000000000
--- a/include/linux/platform_data/leds-lm3556.h
+++ /dev/null
@@ -1,50 +0,0 @@
1/*
2 * Simple driver for Texas Instruments LM3556 LED Flash driver chip (Rev0x03)
3 * Copyright (C) 2012 Texas Instruments
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 */
10
11#ifndef __LINUX_LM3556_H
12#define __LINUX_LM3556_H
13
14#define LM3556_NAME "leds-lm3556"
15
16enum lm3556_pin_polarity {
17 PIN_LOW_ACTIVE = 0,
18 PIN_HIGH_ACTIVE,
19};
20
21enum lm3556_pin_enable {
22 PIN_DISABLED = 0,
23 PIN_ENABLED,
24};
25
26enum lm3556_strobe_usuage {
27 STROBE_EDGE_DETECT = 0,
28 STROBE_LEVEL_DETECT,
29};
30
31enum lm3556_indic_mode {
32 INDIC_MODE_INTERNAL = 0,
33 INDIC_MODE_EXTERNAL,
34};
35
36struct lm3556_platform_data {
37 enum lm3556_pin_enable torch_pin_en;
38 enum lm3556_pin_polarity torch_pin_polarity;
39
40 enum lm3556_strobe_usuage strobe_usuage;
41 enum lm3556_pin_enable strobe_pin_en;
42 enum lm3556_pin_polarity strobe_pin_polarity;
43
44 enum lm3556_pin_enable tx_pin_en;
45 enum lm3556_pin_polarity tx_pin_polarity;
46
47 enum lm3556_indic_mode indicator_mode;
48};
49
50#endif /* __LINUX_LM3556_H */
diff --git a/include/linux/platform_data/leds-lm355x.h b/include/linux/platform_data/leds-lm355x.h
new file mode 100644
index 000000000000..b88724bb0b46
--- /dev/null
+++ b/include/linux/platform_data/leds-lm355x.h
@@ -0,0 +1,66 @@
1/*
2 * Copyright (C) 2012 Texas Instruments
3 *
4 * License Terms: GNU General Public License v2
5 *
6 * Simple driver for Texas Instruments LM355x LED driver chip
7 *
8 * Author: G.Shark Jeong <gshark.jeong@gmail.com>
9 * Daniel Jeong <daniel.jeong@ti.com>
10 */
11
12#define LM355x_NAME "leds-lm355x"
13#define LM3554_NAME "leds-lm3554"
14#define LM3556_NAME "leds-lm3556"
15
16/* lm3554 : strobe def. on */
17enum lm355x_strobe {
18 LM355x_PIN_STROBE_DISABLE = 0x00,
19 LM355x_PIN_STROBE_ENABLE = 0x01,
20};
21
22enum lm355x_torch {
23 LM355x_PIN_TORCH_DISABLE = 0,
24 LM3554_PIN_TORCH_ENABLE = 0x80,
25 LM3556_PIN_TORCH_ENABLE = 0x10,
26};
27
28enum lm355x_tx2 {
29 LM355x_PIN_TX_DISABLE = 0,
30 LM3554_PIN_TX_ENABLE = 0x20,
31 LM3556_PIN_TX_ENABLE = 0x40,
32};
33
34enum lm355x_ntc {
35 LM355x_PIN_NTC_DISABLE = 0,
36 LM3554_PIN_NTC_ENABLE = 0x08,
37 LM3556_PIN_NTC_ENABLE = 0x80,
38};
39
40enum lm355x_pmode {
41 LM355x_PMODE_DISABLE = 0,
42 LM355x_PMODE_ENABLE = 0x04,
43};
44
45/*
46 * struct lm3554_platform_data
47 * @pin_strobe: strobe input
48 * @pin_torch : input pin
49 * lm3554-tx1/torch/gpio1
50 * lm3556-torch
51 * @pin_tx2 : input pin
52 * lm3554-envm/tx2/gpio2
53 * lm3556-tx pin
54 * @ntc_pin : output pin
55 * lm3554-ledi/ntc
56 * lm3556-temp pin
57 * @pass_mode : pass mode
58 */
59struct lm355x_platform_data {
60 enum lm355x_strobe pin_strobe;
61 enum lm355x_torch pin_tx1;
62 enum lm355x_tx2 pin_tx2;
63 enum lm355x_ntc ntc_pin;
64
65 enum lm355x_pmode pass_mode;
66};
diff --git a/include/linux/platform_data/leds-lm3642.h b/include/linux/platform_data/leds-lm3642.h
new file mode 100644
index 000000000000..72d6ee6ade57
--- /dev/null
+++ b/include/linux/platform_data/leds-lm3642.h
@@ -0,0 +1,38 @@
1/*
2* Copyright (C) 2012 Texas Instruments
3*
4* License Terms: GNU General Public License v2
5*
6* Simple driver for Texas Instruments LM3642 LED driver chip
7*
8* Author: G.Shark Jeong <gshark.jeong@gmail.com>
9* Daniel Jeong <daniel.jeong@ti.com>
10*/
11
12#ifndef __LINUX_LM3642_H
13#define __LINUX_LM3642_H
14
15#define LM3642_NAME "leds-lm3642"
16
17enum lm3642_torch_pin_enable {
18 LM3642_TORCH_PIN_DISABLE = 0x00,
19 LM3642_TORCH_PIN_ENABLE = 0x10,
20};
21
22enum lm3642_strobe_pin_enable {
23 LM3642_STROBE_PIN_DISABLE = 0x00,
24 LM3642_STROBE_PIN_ENABLE = 0x20,
25};
26
27enum lm3642_tx_pin_enable {
28 LM3642_TX_PIN_DISABLE = 0x00,
29 LM3642_TX_PIN_ENABLE = 0x40,
30};
31
32struct lm3642_platform_data {
33 enum lm3642_torch_pin_enable torch_pin;
34 enum lm3642_strobe_pin_enable strobe_pin;
35 enum lm3642_tx_pin_enable tx_pin;
36};
37
38#endif /* __LINUX_LM3642_H */
diff --git a/include/linux/platform_data/leds-pca9633.h b/include/linux/platform_data/leds-pca9633.h
new file mode 100644
index 000000000000..c5bf29b6fa7f
--- /dev/null
+++ b/include/linux/platform_data/leds-pca9633.h
@@ -0,0 +1,35 @@
1/*
2 * PCA9633 LED chip driver.
3 *
4 * Copyright 2012 bct electronic GmbH
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 */
20
21#ifndef __LINUX_PCA9633_H
22#define __LINUX_PCA9633_H
23#include <linux/leds.h>
24
25enum pca9633_outdrv {
26 PCA9633_OPEN_DRAIN,
27 PCA9633_TOTEM_POLE, /* aka push-pull */
28};
29
30struct pca9633_platform_data {
31 struct led_platform_data leds;
32 enum pca9633_outdrv outdrv;
33};
34
35#endif /* __LINUX_PCA9633_H*/