diff options
Diffstat (limited to 'drivers/leds')
-rw-r--r-- | drivers/leds/Kconfig | 10 | ||||
-rw-r--r-- | drivers/leds/Makefile | 1 | ||||
-rw-r--r-- | drivers/leds/leds-88pm860x.c | 60 | ||||
-rw-r--r-- | drivers/leds/leds-bd2802.c | 47 | ||||
-rw-r--r-- | drivers/leds/leds-gpio.c | 214 | ||||
-rw-r--r-- | drivers/leds/leds-lm3530.c | 378 | ||||
-rw-r--r-- | drivers/leds/leds-lp5521.c | 14 | ||||
-rw-r--r-- | drivers/leds/leds-lp5523.c | 20 | ||||
-rw-r--r-- | drivers/leds/leds-mc13783.c | 7 | ||||
-rw-r--r-- | drivers/leds/leds-net5501.c | 2 | ||||
-rw-r--r-- | drivers/leds/leds-pwm.c | 1 |
11 files changed, 555 insertions, 199 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 6f190f4cdbc0..9bec8699b8a3 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
@@ -34,6 +34,16 @@ config LEDS_ATMEL_PWM | |||
34 | This option enables support for LEDs driven using outputs | 34 | This option enables support for LEDs driven using outputs |
35 | of the dedicated PWM controller found on newer Atmel SOCs. | 35 | of the dedicated PWM controller found on newer Atmel SOCs. |
36 | 36 | ||
37 | config LEDS_LM3530 | ||
38 | tristate "LCD Backlight driver for LM3530" | ||
39 | depends on LEDS_CLASS | ||
40 | depends on I2C | ||
41 | help | ||
42 | This option enables support for the LCD backlight using | ||
43 | LM3530 ambient light sensor chip. This ALS chip can be | ||
44 | controlled manually or using PWM input or using ambient | ||
45 | light automatically. | ||
46 | |||
37 | config LEDS_LOCOMO | 47 | config LEDS_LOCOMO |
38 | tristate "LED Support for Locomo device" | 48 | tristate "LED Support for Locomo device" |
39 | depends on LEDS_CLASS | 49 | depends on LEDS_CLASS |
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index aae6989ff6b6..39c80fca84d2 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile | |||
@@ -9,6 +9,7 @@ obj-$(CONFIG_LEDS_88PM860X) += leds-88pm860x.o | |||
9 | obj-$(CONFIG_LEDS_ATMEL_PWM) += leds-atmel-pwm.o | 9 | obj-$(CONFIG_LEDS_ATMEL_PWM) += leds-atmel-pwm.o |
10 | obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o | 10 | obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o |
11 | obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o | 11 | obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o |
12 | obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o | ||
12 | obj-$(CONFIG_LEDS_MIKROTIK_RB532) += leds-rb532.o | 13 | obj-$(CONFIG_LEDS_MIKROTIK_RB532) += leds-rb532.o |
13 | obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o | 14 | obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o |
14 | obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o | 15 | obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o |
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c index e672b44ee172..416def84d045 100644 --- a/drivers/leds/leds-88pm860x.c +++ b/drivers/leds/leds-88pm860x.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/leds.h> | 17 | #include <linux/leds.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/workqueue.h> | 19 | #include <linux/workqueue.h> |
20 | #include <linux/mfd/core.h> | ||
20 | #include <linux/mfd/88pm860x.h> | 21 | #include <linux/mfd/88pm860x.h> |
21 | 22 | ||
22 | #define LED_PWM_SHIFT (3) | 23 | #define LED_PWM_SHIFT (3) |
@@ -118,7 +119,8 @@ static void pm860x_led_work(struct work_struct *work) | |||
118 | 119 | ||
119 | struct pm860x_led *led; | 120 | struct pm860x_led *led; |
120 | struct pm860x_chip *chip; | 121 | struct pm860x_chip *chip; |
121 | int mask; | 122 | unsigned char buf[3]; |
123 | int mask, ret; | ||
122 | 124 | ||
123 | led = container_of(work, struct pm860x_led, work); | 125 | led = container_of(work, struct pm860x_led, work); |
124 | chip = led->chip; | 126 | chip = led->chip; |
@@ -128,16 +130,27 @@ static void pm860x_led_work(struct work_struct *work) | |||
128 | pm860x_set_bits(led->i2c, __led_off(led->port), | 130 | pm860x_set_bits(led->i2c, __led_off(led->port), |
129 | LED_CURRENT_MASK, led->iset); | 131 | LED_CURRENT_MASK, led->iset); |
130 | } | 132 | } |
133 | pm860x_set_bits(led->i2c, __blink_off(led->port), | ||
134 | LED_BLINK_MASK, LED_ON_CONTINUOUS); | ||
131 | mask = __blink_ctl_mask(led->port); | 135 | mask = __blink_ctl_mask(led->port); |
132 | pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask); | 136 | pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask); |
133 | } else if (led->brightness == 0) { | ||
134 | pm860x_set_bits(led->i2c, __led_off(led->port), | ||
135 | LED_CURRENT_MASK, 0); | ||
136 | mask = __blink_ctl_mask(led->port); | ||
137 | pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0); | ||
138 | } | 137 | } |
139 | pm860x_set_bits(led->i2c, __led_off(led->port), LED_PWM_MASK, | 138 | pm860x_set_bits(led->i2c, __led_off(led->port), LED_PWM_MASK, |
140 | led->brightness); | 139 | led->brightness); |
140 | |||
141 | if (led->brightness == 0) { | ||
142 | pm860x_bulk_read(led->i2c, __led_off(led->port), 3, buf); | ||
143 | ret = buf[0] & LED_PWM_MASK; | ||
144 | ret |= buf[1] & LED_PWM_MASK; | ||
145 | ret |= buf[2] & LED_PWM_MASK; | ||
146 | if (ret == 0) { | ||
147 | /* unset current since no led is lighting */ | ||
148 | pm860x_set_bits(led->i2c, __led_off(led->port), | ||
149 | LED_CURRENT_MASK, 0); | ||
150 | mask = __blink_ctl_mask(led->port); | ||
151 | pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0); | ||
152 | } | ||
153 | } | ||
141 | led->current_brightness = led->brightness; | 154 | led->current_brightness = led->brightness; |
142 | dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n", | 155 | dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n", |
143 | __led_off(led->port), led->brightness); | 156 | __led_off(led->port), led->brightness); |
@@ -153,31 +166,12 @@ static void pm860x_led_set(struct led_classdev *cdev, | |||
153 | schedule_work(&data->work); | 166 | schedule_work(&data->work); |
154 | } | 167 | } |
155 | 168 | ||
156 | static int __check_device(struct pm860x_led_pdata *pdata, char *name) | ||
157 | { | ||
158 | struct pm860x_led_pdata *p = pdata; | ||
159 | int ret = -EINVAL; | ||
160 | |||
161 | while (p && p->id) { | ||
162 | if ((p->id != PM8606_ID_LED) || (p->flags < 0)) | ||
163 | break; | ||
164 | |||
165 | if (!strncmp(name, pm860x_led_name[p->flags], | ||
166 | MFD_NAME_SIZE)) { | ||
167 | ret = (int)p->flags; | ||
168 | break; | ||
169 | } | ||
170 | p++; | ||
171 | } | ||
172 | return ret; | ||
173 | } | ||
174 | |||
175 | static int pm860x_led_probe(struct platform_device *pdev) | 169 | static int pm860x_led_probe(struct platform_device *pdev) |
176 | { | 170 | { |
177 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | 171 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); |
178 | struct pm860x_platform_data *pm860x_pdata; | ||
179 | struct pm860x_led_pdata *pdata; | 172 | struct pm860x_led_pdata *pdata; |
180 | struct pm860x_led *data; | 173 | struct pm860x_led *data; |
174 | struct mfd_cell *cell; | ||
181 | struct resource *res; | 175 | struct resource *res; |
182 | int ret; | 176 | int ret; |
183 | 177 | ||
@@ -187,10 +181,11 @@ static int pm860x_led_probe(struct platform_device *pdev) | |||
187 | return -EINVAL; | 181 | return -EINVAL; |
188 | } | 182 | } |
189 | 183 | ||
190 | if (pdev->dev.parent->platform_data) { | 184 | cell = pdev->dev.platform_data; |
191 | pm860x_pdata = pdev->dev.parent->platform_data; | 185 | if (cell == NULL) |
192 | pdata = pm860x_pdata->led; | 186 | return -ENODEV; |
193 | } else { | 187 | pdata = cell->mfd_data; |
188 | if (pdata == NULL) { | ||
194 | dev_err(&pdev->dev, "No platform data!\n"); | 189 | dev_err(&pdev->dev, "No platform data!\n"); |
195 | return -EINVAL; | 190 | return -EINVAL; |
196 | } | 191 | } |
@@ -198,12 +193,12 @@ static int pm860x_led_probe(struct platform_device *pdev) | |||
198 | data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL); | 193 | data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL); |
199 | if (data == NULL) | 194 | if (data == NULL) |
200 | return -ENOMEM; | 195 | return -ENOMEM; |
201 | strncpy(data->name, res->name, MFD_NAME_SIZE); | 196 | strncpy(data->name, res->name, MFD_NAME_SIZE - 1); |
202 | dev_set_drvdata(&pdev->dev, data); | 197 | dev_set_drvdata(&pdev->dev, data); |
203 | data->chip = chip; | 198 | data->chip = chip; |
204 | data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion; | 199 | data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion; |
205 | data->iset = pdata->iset; | 200 | data->iset = pdata->iset; |
206 | data->port = __check_device(pdata, data->name); | 201 | data->port = pdata->flags; |
207 | if (data->port < 0) { | 202 | if (data->port < 0) { |
208 | dev_err(&pdev->dev, "check device failed\n"); | 203 | dev_err(&pdev->dev, "check device failed\n"); |
209 | kfree(data); | 204 | kfree(data); |
@@ -221,6 +216,7 @@ static int pm860x_led_probe(struct platform_device *pdev) | |||
221 | dev_err(&pdev->dev, "Failed to register LED: %d\n", ret); | 216 | dev_err(&pdev->dev, "Failed to register LED: %d\n", ret); |
222 | goto out; | 217 | goto out; |
223 | } | 218 | } |
219 | pm860x_led_set(&data->cdev, 0); | ||
224 | return 0; | 220 | return 0; |
225 | out: | 221 | out: |
226 | kfree(data); | 222 | kfree(data); |
diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c index 19dc4b61a105..3ebe3824662d 100644 --- a/drivers/leds/leds-bd2802.c +++ b/drivers/leds/leds-bd2802.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <linux/leds.h> | 19 | #include <linux/leds.h> |
20 | #include <linux/leds-bd2802.h> | 20 | #include <linux/leds-bd2802.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | 22 | #include <linux/pm.h> | |
23 | 23 | ||
24 | #define LED_CTL(rgb2en, rgb1en) ((rgb2en) << 4 | ((rgb1en) << 0)) | 24 | #define LED_CTL(rgb2en, rgb1en) ((rgb2en) << 4 | ((rgb1en) << 0)) |
25 | 25 | ||
@@ -319,20 +319,6 @@ static void bd2802_turn_off(struct bd2802_led *led, enum led_ids id, | |||
319 | bd2802_update_state(led, id, color, BD2802_OFF); | 319 | bd2802_update_state(led, id, color, BD2802_OFF); |
320 | } | 320 | } |
321 | 321 | ||
322 | static void bd2802_restore_state(struct bd2802_led *led) | ||
323 | { | ||
324 | int i; | ||
325 | |||
326 | for (i = 0; i < LED_NUM; i++) { | ||
327 | if (led->led[i].r) | ||
328 | bd2802_turn_on(led, i, RED, led->led[i].r); | ||
329 | if (led->led[i].g) | ||
330 | bd2802_turn_on(led, i, GREEN, led->led[i].g); | ||
331 | if (led->led[i].b) | ||
332 | bd2802_turn_on(led, i, BLUE, led->led[i].b); | ||
333 | } | ||
334 | } | ||
335 | |||
336 | #define BD2802_SET_REGISTER(reg_addr, reg_name) \ | 322 | #define BD2802_SET_REGISTER(reg_addr, reg_name) \ |
337 | static ssize_t bd2802_store_reg##reg_addr(struct device *dev, \ | 323 | static ssize_t bd2802_store_reg##reg_addr(struct device *dev, \ |
338 | struct device_attribute *attr, const char *buf, size_t count) \ | 324 | struct device_attribute *attr, const char *buf, size_t count) \ |
@@ -761,8 +747,25 @@ static int __exit bd2802_remove(struct i2c_client *client) | |||
761 | return 0; | 747 | return 0; |
762 | } | 748 | } |
763 | 749 | ||
764 | static int bd2802_suspend(struct i2c_client *client, pm_message_t mesg) | 750 | #ifdef CONFIG_PM |
751 | |||
752 | static void bd2802_restore_state(struct bd2802_led *led) | ||
765 | { | 753 | { |
754 | int i; | ||
755 | |||
756 | for (i = 0; i < LED_NUM; i++) { | ||
757 | if (led->led[i].r) | ||
758 | bd2802_turn_on(led, i, RED, led->led[i].r); | ||
759 | if (led->led[i].g) | ||
760 | bd2802_turn_on(led, i, GREEN, led->led[i].g); | ||
761 | if (led->led[i].b) | ||
762 | bd2802_turn_on(led, i, BLUE, led->led[i].b); | ||
763 | } | ||
764 | } | ||
765 | |||
766 | static int bd2802_suspend(struct device *dev) | ||
767 | { | ||
768 | struct i2c_client *client = to_i2c_client(dev); | ||
766 | struct bd2802_led *led = i2c_get_clientdata(client); | 769 | struct bd2802_led *led = i2c_get_clientdata(client); |
767 | 770 | ||
768 | gpio_set_value(led->pdata->reset_gpio, 0); | 771 | gpio_set_value(led->pdata->reset_gpio, 0); |
@@ -770,8 +773,9 @@ static int bd2802_suspend(struct i2c_client *client, pm_message_t mesg) | |||
770 | return 0; | 773 | return 0; |
771 | } | 774 | } |
772 | 775 | ||
773 | static int bd2802_resume(struct i2c_client *client) | 776 | static int bd2802_resume(struct device *dev) |
774 | { | 777 | { |
778 | struct i2c_client *client = to_i2c_client(dev); | ||
775 | struct bd2802_led *led = i2c_get_clientdata(client); | 779 | struct bd2802_led *led = i2c_get_clientdata(client); |
776 | 780 | ||
777 | if (!bd2802_is_all_off(led) || led->adf_on) { | 781 | if (!bd2802_is_all_off(led) || led->adf_on) { |
@@ -782,6 +786,12 @@ static int bd2802_resume(struct i2c_client *client) | |||
782 | return 0; | 786 | return 0; |
783 | } | 787 | } |
784 | 788 | ||
789 | static SIMPLE_DEV_PM_OPS(bd2802_pm, bd2802_suspend, bd2802_resume); | ||
790 | #define BD2802_PM (&bd2802_pm) | ||
791 | #else /* CONFIG_PM */ | ||
792 | #define BD2802_PM NULL | ||
793 | #endif | ||
794 | |||
785 | static const struct i2c_device_id bd2802_id[] = { | 795 | static const struct i2c_device_id bd2802_id[] = { |
786 | { "BD2802", 0 }, | 796 | { "BD2802", 0 }, |
787 | { } | 797 | { } |
@@ -791,11 +801,10 @@ MODULE_DEVICE_TABLE(i2c, bd2802_id); | |||
791 | static struct i2c_driver bd2802_i2c_driver = { | 801 | static struct i2c_driver bd2802_i2c_driver = { |
792 | .driver = { | 802 | .driver = { |
793 | .name = "BD2802", | 803 | .name = "BD2802", |
804 | .pm = BD2802_PM, | ||
794 | }, | 805 | }, |
795 | .probe = bd2802_probe, | 806 | .probe = bd2802_probe, |
796 | .remove = __exit_p(bd2802_remove), | 807 | .remove = __exit_p(bd2802_remove), |
797 | .suspend = bd2802_suspend, | ||
798 | .resume = bd2802_resume, | ||
799 | .id_table = bd2802_id, | 808 | .id_table = bd2802_id, |
800 | }; | 809 | }; |
801 | 810 | ||
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 4d9fa38d9ff6..b0480c8fbcbf 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c | |||
@@ -14,6 +14,8 @@ | |||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
16 | #include <linux/leds.h> | 16 | #include <linux/leds.h> |
17 | #include <linux/of_platform.h> | ||
18 | #include <linux/of_gpio.h> | ||
17 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
18 | #include <linux/workqueue.h> | 20 | #include <linux/workqueue.h> |
19 | 21 | ||
@@ -151,96 +153,34 @@ static void delete_gpio_led(struct gpio_led_data *led) | |||
151 | gpio_free(led->gpio); | 153 | gpio_free(led->gpio); |
152 | } | 154 | } |
153 | 155 | ||
154 | #ifdef CONFIG_LEDS_GPIO_PLATFORM | 156 | struct gpio_leds_priv { |
155 | static int __devinit gpio_led_probe(struct platform_device *pdev) | 157 | int num_leds; |
156 | { | 158 | struct gpio_led_data leds[]; |
157 | struct gpio_led_platform_data *pdata = pdev->dev.platform_data; | 159 | }; |
158 | struct gpio_led_data *leds_data; | ||
159 | int i, ret = 0; | ||
160 | |||
161 | if (!pdata) | ||
162 | return -EBUSY; | ||
163 | |||
164 | leds_data = kzalloc(sizeof(struct gpio_led_data) * pdata->num_leds, | ||
165 | GFP_KERNEL); | ||
166 | if (!leds_data) | ||
167 | return -ENOMEM; | ||
168 | |||
169 | for (i = 0; i < pdata->num_leds; i++) { | ||
170 | ret = create_gpio_led(&pdata->leds[i], &leds_data[i], | ||
171 | &pdev->dev, pdata->gpio_blink_set); | ||
172 | if (ret < 0) | ||
173 | goto err; | ||
174 | } | ||
175 | |||
176 | platform_set_drvdata(pdev, leds_data); | ||
177 | |||
178 | return 0; | ||
179 | |||
180 | err: | ||
181 | for (i = i - 1; i >= 0; i--) | ||
182 | delete_gpio_led(&leds_data[i]); | ||
183 | |||
184 | kfree(leds_data); | ||
185 | |||
186 | return ret; | ||
187 | } | ||
188 | 160 | ||
189 | static int __devexit gpio_led_remove(struct platform_device *pdev) | 161 | static inline int sizeof_gpio_leds_priv(int num_leds) |
190 | { | 162 | { |
191 | int i; | 163 | return sizeof(struct gpio_leds_priv) + |
192 | struct gpio_led_platform_data *pdata = pdev->dev.platform_data; | 164 | (sizeof(struct gpio_led_data) * num_leds); |
193 | struct gpio_led_data *leds_data; | ||
194 | |||
195 | leds_data = platform_get_drvdata(pdev); | ||
196 | |||
197 | for (i = 0; i < pdata->num_leds; i++) | ||
198 | delete_gpio_led(&leds_data[i]); | ||
199 | |||
200 | kfree(leds_data); | ||
201 | |||
202 | return 0; | ||
203 | } | 165 | } |
204 | 166 | ||
205 | static struct platform_driver gpio_led_driver = { | ||
206 | .probe = gpio_led_probe, | ||
207 | .remove = __devexit_p(gpio_led_remove), | ||
208 | .driver = { | ||
209 | .name = "leds-gpio", | ||
210 | .owner = THIS_MODULE, | ||
211 | }, | ||
212 | }; | ||
213 | |||
214 | MODULE_ALIAS("platform:leds-gpio"); | ||
215 | #endif /* CONFIG_LEDS_GPIO_PLATFORM */ | ||
216 | |||
217 | /* Code to create from OpenFirmware platform devices */ | 167 | /* Code to create from OpenFirmware platform devices */ |
218 | #ifdef CONFIG_LEDS_GPIO_OF | 168 | #ifdef CONFIG_LEDS_GPIO_OF |
219 | #include <linux/of_platform.h> | 169 | static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_device *pdev) |
220 | #include <linux/of_gpio.h> | ||
221 | |||
222 | struct gpio_led_of_platform_data { | ||
223 | int num_leds; | ||
224 | struct gpio_led_data led_data[]; | ||
225 | }; | ||
226 | |||
227 | static int __devinit of_gpio_leds_probe(struct platform_device *ofdev, | ||
228 | const struct of_device_id *match) | ||
229 | { | 170 | { |
230 | struct device_node *np = ofdev->dev.of_node, *child; | 171 | struct device_node *np = pdev->dev.of_node, *child; |
231 | struct gpio_led_of_platform_data *pdata; | 172 | struct gpio_leds_priv *priv; |
232 | int count = 0, ret; | 173 | int count = 0, ret; |
233 | 174 | ||
234 | /* count LEDs defined by this device, so we know how much to allocate */ | 175 | /* count LEDs in this device, so we know how much to allocate */ |
235 | for_each_child_of_node(np, child) | 176 | for_each_child_of_node(np, child) |
236 | count++; | 177 | count++; |
237 | if (!count) | 178 | if (!count) |
238 | return 0; /* or ENODEV? */ | 179 | return NULL; |
239 | 180 | ||
240 | pdata = kzalloc(sizeof(*pdata) + sizeof(struct gpio_led_data) * count, | 181 | priv = kzalloc(sizeof_gpio_leds_priv(count), GFP_KERNEL); |
241 | GFP_KERNEL); | 182 | if (!priv) |
242 | if (!pdata) | 183 | return NULL; |
243 | return -ENOMEM; | ||
244 | 184 | ||
245 | for_each_child_of_node(np, child) { | 185 | for_each_child_of_node(np, child) { |
246 | struct gpio_led led = {}; | 186 | struct gpio_led led = {}; |
@@ -256,92 +196,112 @@ static int __devinit of_gpio_leds_probe(struct platform_device *ofdev, | |||
256 | if (state) { | 196 | if (state) { |
257 | if (!strcmp(state, "keep")) | 197 | if (!strcmp(state, "keep")) |
258 | led.default_state = LEDS_GPIO_DEFSTATE_KEEP; | 198 | led.default_state = LEDS_GPIO_DEFSTATE_KEEP; |
259 | else if(!strcmp(state, "on")) | 199 | else if (!strcmp(state, "on")) |
260 | led.default_state = LEDS_GPIO_DEFSTATE_ON; | 200 | led.default_state = LEDS_GPIO_DEFSTATE_ON; |
261 | else | 201 | else |
262 | led.default_state = LEDS_GPIO_DEFSTATE_OFF; | 202 | led.default_state = LEDS_GPIO_DEFSTATE_OFF; |
263 | } | 203 | } |
264 | 204 | ||
265 | ret = create_gpio_led(&led, &pdata->led_data[pdata->num_leds++], | 205 | ret = create_gpio_led(&led, &priv->leds[priv->num_leds++], |
266 | &ofdev->dev, NULL); | 206 | &pdev->dev, NULL); |
267 | if (ret < 0) { | 207 | if (ret < 0) { |
268 | of_node_put(child); | 208 | of_node_put(child); |
269 | goto err; | 209 | goto err; |
270 | } | 210 | } |
271 | } | 211 | } |
272 | 212 | ||
273 | dev_set_drvdata(&ofdev->dev, pdata); | 213 | return priv; |
274 | |||
275 | return 0; | ||
276 | 214 | ||
277 | err: | 215 | err: |
278 | for (count = pdata->num_leds - 2; count >= 0; count--) | 216 | for (count = priv->num_leds - 2; count >= 0; count--) |
279 | delete_gpio_led(&pdata->led_data[count]); | 217 | delete_gpio_led(&priv->leds[count]); |
218 | kfree(priv); | ||
219 | return NULL; | ||
220 | } | ||
280 | 221 | ||
281 | kfree(pdata); | 222 | static const struct of_device_id of_gpio_leds_match[] = { |
223 | { .compatible = "gpio-leds", }, | ||
224 | {}, | ||
225 | }; | ||
226 | #else | ||
227 | static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_device *pdev) | ||
228 | { | ||
229 | return NULL; | ||
230 | } | ||
231 | #define of_gpio_leds_match NULL | ||
232 | #endif | ||
282 | 233 | ||
283 | return ret; | 234 | |
235 | static int __devinit gpio_led_probe(struct platform_device *pdev) | ||
236 | { | ||
237 | struct gpio_led_platform_data *pdata = pdev->dev.platform_data; | ||
238 | struct gpio_leds_priv *priv; | ||
239 | int i, ret = 0; | ||
240 | |||
241 | if (pdata && pdata->num_leds) { | ||
242 | priv = kzalloc(sizeof_gpio_leds_priv(pdata->num_leds), | ||
243 | GFP_KERNEL); | ||
244 | if (!priv) | ||
245 | return -ENOMEM; | ||
246 | |||
247 | priv->num_leds = pdata->num_leds; | ||
248 | for (i = 0; i < priv->num_leds; i++) { | ||
249 | ret = create_gpio_led(&pdata->leds[i], | ||
250 | &priv->leds[i], | ||
251 | &pdev->dev, pdata->gpio_blink_set); | ||
252 | if (ret < 0) { | ||
253 | /* On failure: unwind the led creations */ | ||
254 | for (i = i - 1; i >= 0; i--) | ||
255 | delete_gpio_led(&priv->leds[i]); | ||
256 | kfree(priv); | ||
257 | return ret; | ||
258 | } | ||
259 | } | ||
260 | } else { | ||
261 | priv = gpio_leds_create_of(pdev); | ||
262 | if (!priv) | ||
263 | return -ENODEV; | ||
264 | } | ||
265 | |||
266 | platform_set_drvdata(pdev, priv); | ||
267 | |||
268 | return 0; | ||
284 | } | 269 | } |
285 | 270 | ||
286 | static int __devexit of_gpio_leds_remove(struct platform_device *ofdev) | 271 | static int __devexit gpio_led_remove(struct platform_device *pdev) |
287 | { | 272 | { |
288 | struct gpio_led_of_platform_data *pdata = dev_get_drvdata(&ofdev->dev); | 273 | struct gpio_leds_priv *priv = dev_get_drvdata(&pdev->dev); |
289 | int i; | 274 | int i; |
290 | 275 | ||
291 | for (i = 0; i < pdata->num_leds; i++) | 276 | for (i = 0; i < priv->num_leds; i++) |
292 | delete_gpio_led(&pdata->led_data[i]); | 277 | delete_gpio_led(&priv->leds[i]); |
293 | |||
294 | kfree(pdata); | ||
295 | 278 | ||
296 | dev_set_drvdata(&ofdev->dev, NULL); | 279 | dev_set_drvdata(&pdev->dev, NULL); |
280 | kfree(priv); | ||
297 | 281 | ||
298 | return 0; | 282 | return 0; |
299 | } | 283 | } |
300 | 284 | ||
301 | static const struct of_device_id of_gpio_leds_match[] = { | 285 | static struct platform_driver gpio_led_driver = { |
302 | { .compatible = "gpio-leds", }, | 286 | .probe = gpio_led_probe, |
303 | {}, | 287 | .remove = __devexit_p(gpio_led_remove), |
304 | }; | 288 | .driver = { |
305 | 289 | .name = "leds-gpio", | |
306 | static struct of_platform_driver of_gpio_leds_driver = { | 290 | .owner = THIS_MODULE, |
307 | .driver = { | ||
308 | .name = "of_gpio_leds", | ||
309 | .owner = THIS_MODULE, | ||
310 | .of_match_table = of_gpio_leds_match, | 291 | .of_match_table = of_gpio_leds_match, |
311 | }, | 292 | }, |
312 | .probe = of_gpio_leds_probe, | ||
313 | .remove = __devexit_p(of_gpio_leds_remove), | ||
314 | }; | 293 | }; |
315 | #endif | 294 | |
295 | MODULE_ALIAS("platform:leds-gpio"); | ||
316 | 296 | ||
317 | static int __init gpio_led_init(void) | 297 | static int __init gpio_led_init(void) |
318 | { | 298 | { |
319 | int ret = 0; | 299 | return platform_driver_register(&gpio_led_driver); |
320 | |||
321 | #ifdef CONFIG_LEDS_GPIO_PLATFORM | ||
322 | ret = platform_driver_register(&gpio_led_driver); | ||
323 | if (ret) | ||
324 | return ret; | ||
325 | #endif | ||
326 | #ifdef CONFIG_LEDS_GPIO_OF | ||
327 | ret = of_register_platform_driver(&of_gpio_leds_driver); | ||
328 | #endif | ||
329 | #ifdef CONFIG_LEDS_GPIO_PLATFORM | ||
330 | if (ret) | ||
331 | platform_driver_unregister(&gpio_led_driver); | ||
332 | #endif | ||
333 | |||
334 | return ret; | ||
335 | } | 300 | } |
336 | 301 | ||
337 | static void __exit gpio_led_exit(void) | 302 | static void __exit gpio_led_exit(void) |
338 | { | 303 | { |
339 | #ifdef CONFIG_LEDS_GPIO_PLATFORM | ||
340 | platform_driver_unregister(&gpio_led_driver); | 304 | platform_driver_unregister(&gpio_led_driver); |
341 | #endif | ||
342 | #ifdef CONFIG_LEDS_GPIO_OF | ||
343 | of_unregister_platform_driver(&of_gpio_leds_driver); | ||
344 | #endif | ||
345 | } | 305 | } |
346 | 306 | ||
347 | module_init(gpio_led_init); | 307 | module_init(gpio_led_init); |
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c new file mode 100644 index 000000000000..e7089a1f6cb6 --- /dev/null +++ b/drivers/leds/leds-lm3530.c | |||
@@ -0,0 +1,378 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 ST-Ericsson SA. | ||
3 | * Copyright (C) 2009 Motorola, Inc. | ||
4 | * | ||
5 | * License Terms: GNU General Public License v2 | ||
6 | * | ||
7 | * Simple driver for National Semiconductor LM3530 Backlight driver chip | ||
8 | * | ||
9 | * Author: Shreshtha Kumar SAHU <shreshthakumar.sahu@stericsson.com> | ||
10 | * based on leds-lm3530.c by Dan Murphy <D.Murphy@motorola.com> | ||
11 | */ | ||
12 | |||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/leds.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/input.h> | ||
18 | #include <linux/led-lm3530.h> | ||
19 | #include <linux/types.h> | ||
20 | |||
21 | #define LM3530_LED_DEV "lcd-backlight" | ||
22 | #define LM3530_NAME "lm3530-led" | ||
23 | |||
24 | #define LM3530_GEN_CONFIG 0x10 | ||
25 | #define LM3530_ALS_CONFIG 0x20 | ||
26 | #define LM3530_BRT_RAMP_RATE 0x30 | ||
27 | #define LM3530_ALS_ZONE_REG 0x40 | ||
28 | #define LM3530_ALS_IMP_SELECT 0x41 | ||
29 | #define LM3530_BRT_CTRL_REG 0xA0 | ||
30 | #define LM3530_ALS_ZB0_REG 0x60 | ||
31 | #define LM3530_ALS_ZB1_REG 0x61 | ||
32 | #define LM3530_ALS_ZB2_REG 0x62 | ||
33 | #define LM3530_ALS_ZB3_REG 0x63 | ||
34 | #define LM3530_ALS_Z0T_REG 0x70 | ||
35 | #define LM3530_ALS_Z1T_REG 0x71 | ||
36 | #define LM3530_ALS_Z2T_REG 0x72 | ||
37 | #define LM3530_ALS_Z3T_REG 0x73 | ||
38 | #define LM3530_ALS_Z4T_REG 0x74 | ||
39 | #define LM3530_REG_MAX 15 | ||
40 | |||
41 | /* General Control Register */ | ||
42 | #define LM3530_EN_I2C_SHIFT (0) | ||
43 | #define LM3530_RAMP_LAW_SHIFT (1) | ||
44 | #define LM3530_MAX_CURR_SHIFT (2) | ||
45 | #define LM3530_EN_PWM_SHIFT (5) | ||
46 | #define LM3530_PWM_POL_SHIFT (6) | ||
47 | #define LM3530_EN_PWM_SIMPLE_SHIFT (7) | ||
48 | |||
49 | #define LM3530_ENABLE_I2C (1 << LM3530_EN_I2C_SHIFT) | ||
50 | #define LM3530_ENABLE_PWM (1 << LM3530_EN_PWM_SHIFT) | ||
51 | #define LM3530_POL_LOW (1 << LM3530_PWM_POL_SHIFT) | ||
52 | #define LM3530_ENABLE_PWM_SIMPLE (1 << LM3530_EN_PWM_SIMPLE_SHIFT) | ||
53 | |||
54 | /* ALS Config Register Options */ | ||
55 | #define LM3530_ALS_AVG_TIME_SHIFT (0) | ||
56 | #define LM3530_EN_ALS_SHIFT (3) | ||
57 | #define LM3530_ALS_SEL_SHIFT (5) | ||
58 | |||
59 | #define LM3530_ENABLE_ALS (3 << LM3530_EN_ALS_SHIFT) | ||
60 | |||
61 | /* Brightness Ramp Rate Register */ | ||
62 | #define LM3530_BRT_RAMP_FALL_SHIFT (0) | ||
63 | #define LM3530_BRT_RAMP_RISE_SHIFT (3) | ||
64 | |||
65 | /* ALS Resistor Select */ | ||
66 | #define LM3530_ALS1_IMP_SHIFT (0) | ||
67 | #define LM3530_ALS2_IMP_SHIFT (4) | ||
68 | |||
69 | /* Zone Boundary Register defaults */ | ||
70 | #define LM3530_DEF_ZB_0 (0x33) | ||
71 | #define LM3530_DEF_ZB_1 (0x66) | ||
72 | #define LM3530_DEF_ZB_2 (0x99) | ||
73 | #define LM3530_DEF_ZB_3 (0xCC) | ||
74 | |||
75 | /* Zone Target Register defaults */ | ||
76 | #define LM3530_DEF_ZT_0 (0x19) | ||
77 | #define LM3530_DEF_ZT_1 (0x33) | ||
78 | #define LM3530_DEF_ZT_2 (0x4C) | ||
79 | #define LM3530_DEF_ZT_3 (0x66) | ||
80 | #define LM3530_DEF_ZT_4 (0x7F) | ||
81 | |||
82 | struct lm3530_mode_map { | ||
83 | const char *mode; | ||
84 | enum lm3530_mode mode_val; | ||
85 | }; | ||
86 | |||
87 | static struct lm3530_mode_map mode_map[] = { | ||
88 | { "man", LM3530_BL_MODE_MANUAL }, | ||
89 | { "als", LM3530_BL_MODE_ALS }, | ||
90 | { "pwm", LM3530_BL_MODE_PWM }, | ||
91 | }; | ||
92 | |||
93 | /** | ||
94 | * struct lm3530_data | ||
95 | * @led_dev: led class device | ||
96 | * @client: i2c client | ||
97 | * @pdata: LM3530 platform data | ||
98 | * @mode: mode of operation - manual, ALS, PWM | ||
99 | */ | ||
100 | struct lm3530_data { | ||
101 | struct led_classdev led_dev; | ||
102 | struct i2c_client *client; | ||
103 | struct lm3530_platform_data *pdata; | ||
104 | enum lm3530_mode mode; | ||
105 | }; | ||
106 | |||
107 | static const u8 lm3530_reg[LM3530_REG_MAX] = { | ||
108 | LM3530_GEN_CONFIG, | ||
109 | LM3530_ALS_CONFIG, | ||
110 | LM3530_BRT_RAMP_RATE, | ||
111 | LM3530_ALS_ZONE_REG, | ||
112 | LM3530_ALS_IMP_SELECT, | ||
113 | LM3530_BRT_CTRL_REG, | ||
114 | LM3530_ALS_ZB0_REG, | ||
115 | LM3530_ALS_ZB1_REG, | ||
116 | LM3530_ALS_ZB2_REG, | ||
117 | LM3530_ALS_ZB3_REG, | ||
118 | LM3530_ALS_Z0T_REG, | ||
119 | LM3530_ALS_Z1T_REG, | ||
120 | LM3530_ALS_Z2T_REG, | ||
121 | LM3530_ALS_Z3T_REG, | ||
122 | LM3530_ALS_Z4T_REG, | ||
123 | }; | ||
124 | |||
125 | static int lm3530_get_mode_from_str(const char *str) | ||
126 | { | ||
127 | int i; | ||
128 | |||
129 | for (i = 0; i < ARRAY_SIZE(mode_map); i++) | ||
130 | if (sysfs_streq(str, mode_map[i].mode)) | ||
131 | return mode_map[i].mode_val; | ||
132 | |||
133 | return -1; | ||
134 | } | ||
135 | |||
136 | static int lm3530_init_registers(struct lm3530_data *drvdata) | ||
137 | { | ||
138 | int ret = 0; | ||
139 | int i; | ||
140 | u8 gen_config; | ||
141 | u8 als_config = 0; | ||
142 | u8 brt_ramp; | ||
143 | u8 als_imp_sel = 0; | ||
144 | u8 brightness; | ||
145 | u8 reg_val[LM3530_REG_MAX]; | ||
146 | struct lm3530_platform_data *pltfm = drvdata->pdata; | ||
147 | struct i2c_client *client = drvdata->client; | ||
148 | |||
149 | gen_config = (pltfm->brt_ramp_law << LM3530_RAMP_LAW_SHIFT) | | ||
150 | ((pltfm->max_current & 7) << LM3530_MAX_CURR_SHIFT); | ||
151 | |||
152 | if (drvdata->mode == LM3530_BL_MODE_MANUAL || | ||
153 | drvdata->mode == LM3530_BL_MODE_ALS) | ||
154 | gen_config |= (LM3530_ENABLE_I2C); | ||
155 | |||
156 | if (drvdata->mode == LM3530_BL_MODE_ALS) { | ||
157 | als_config = | ||
158 | (pltfm->als_avrg_time << LM3530_ALS_AVG_TIME_SHIFT) | | ||
159 | (LM3530_ENABLE_ALS) | | ||
160 | (pltfm->als_input_mode << LM3530_ALS_SEL_SHIFT); | ||
161 | |||
162 | als_imp_sel = | ||
163 | (pltfm->als1_resistor_sel << LM3530_ALS1_IMP_SHIFT) | | ||
164 | (pltfm->als2_resistor_sel << LM3530_ALS2_IMP_SHIFT); | ||
165 | } | ||
166 | |||
167 | if (drvdata->mode == LM3530_BL_MODE_PWM) | ||
168 | gen_config |= (LM3530_ENABLE_PWM) | | ||
169 | (pltfm->pwm_pol_hi << LM3530_PWM_POL_SHIFT) | | ||
170 | (LM3530_ENABLE_PWM_SIMPLE); | ||
171 | |||
172 | brt_ramp = (pltfm->brt_ramp_fall << LM3530_BRT_RAMP_FALL_SHIFT) | | ||
173 | (pltfm->brt_ramp_rise << LM3530_BRT_RAMP_RISE_SHIFT); | ||
174 | |||
175 | brightness = pltfm->brt_val; | ||
176 | |||
177 | reg_val[0] = gen_config; /* LM3530_GEN_CONFIG */ | ||
178 | reg_val[1] = als_config; /* LM3530_ALS_CONFIG */ | ||
179 | reg_val[2] = brt_ramp; /* LM3530_BRT_RAMP_RATE */ | ||
180 | reg_val[3] = 0x00; /* LM3530_ALS_ZONE_REG */ | ||
181 | reg_val[4] = als_imp_sel; /* LM3530_ALS_IMP_SELECT */ | ||
182 | reg_val[5] = brightness; /* LM3530_BRT_CTRL_REG */ | ||
183 | reg_val[6] = LM3530_DEF_ZB_0; /* LM3530_ALS_ZB0_REG */ | ||
184 | reg_val[7] = LM3530_DEF_ZB_1; /* LM3530_ALS_ZB1_REG */ | ||
185 | reg_val[8] = LM3530_DEF_ZB_2; /* LM3530_ALS_ZB2_REG */ | ||
186 | reg_val[9] = LM3530_DEF_ZB_3; /* LM3530_ALS_ZB3_REG */ | ||
187 | reg_val[10] = LM3530_DEF_ZT_0; /* LM3530_ALS_Z0T_REG */ | ||
188 | reg_val[11] = LM3530_DEF_ZT_1; /* LM3530_ALS_Z1T_REG */ | ||
189 | reg_val[12] = LM3530_DEF_ZT_2; /* LM3530_ALS_Z2T_REG */ | ||
190 | reg_val[13] = LM3530_DEF_ZT_3; /* LM3530_ALS_Z3T_REG */ | ||
191 | reg_val[14] = LM3530_DEF_ZT_4; /* LM3530_ALS_Z4T_REG */ | ||
192 | |||
193 | for (i = 0; i < LM3530_REG_MAX; i++) { | ||
194 | ret = i2c_smbus_write_byte_data(client, | ||
195 | lm3530_reg[i], reg_val[i]); | ||
196 | if (ret) | ||
197 | break; | ||
198 | } | ||
199 | |||
200 | return ret; | ||
201 | } | ||
202 | |||
203 | static void lm3530_brightness_set(struct led_classdev *led_cdev, | ||
204 | enum led_brightness brt_val) | ||
205 | { | ||
206 | int err; | ||
207 | struct lm3530_data *drvdata = | ||
208 | container_of(led_cdev, struct lm3530_data, led_dev); | ||
209 | |||
210 | switch (drvdata->mode) { | ||
211 | case LM3530_BL_MODE_MANUAL: | ||
212 | |||
213 | /* set the brightness in brightness control register*/ | ||
214 | err = i2c_smbus_write_byte_data(drvdata->client, | ||
215 | LM3530_BRT_CTRL_REG, brt_val / 2); | ||
216 | if (err) | ||
217 | dev_err(&drvdata->client->dev, | ||
218 | "Unable to set brightness: %d\n", err); | ||
219 | break; | ||
220 | case LM3530_BL_MODE_ALS: | ||
221 | break; | ||
222 | case LM3530_BL_MODE_PWM: | ||
223 | break; | ||
224 | default: | ||
225 | break; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | |||
230 | static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute | ||
231 | *attr, const char *buf, size_t size) | ||
232 | { | ||
233 | int err; | ||
234 | struct i2c_client *client = container_of( | ||
235 | dev->parent, struct i2c_client, dev); | ||
236 | struct lm3530_data *drvdata = i2c_get_clientdata(client); | ||
237 | int mode; | ||
238 | |||
239 | mode = lm3530_get_mode_from_str(buf); | ||
240 | if (mode < 0) { | ||
241 | dev_err(dev, "Invalid mode\n"); | ||
242 | return -EINVAL; | ||
243 | } | ||
244 | |||
245 | if (mode == LM3530_BL_MODE_MANUAL) | ||
246 | drvdata->mode = LM3530_BL_MODE_MANUAL; | ||
247 | else if (mode == LM3530_BL_MODE_ALS) | ||
248 | drvdata->mode = LM3530_BL_MODE_ALS; | ||
249 | else if (mode == LM3530_BL_MODE_PWM) { | ||
250 | dev_err(dev, "PWM mode not supported\n"); | ||
251 | return -EINVAL; | ||
252 | } | ||
253 | |||
254 | err = lm3530_init_registers(drvdata); | ||
255 | if (err) { | ||
256 | dev_err(dev, "Setting %s Mode failed :%d\n", buf, err); | ||
257 | return err; | ||
258 | } | ||
259 | |||
260 | return sizeof(drvdata->mode); | ||
261 | } | ||
262 | |||
263 | static DEVICE_ATTR(mode, 0644, NULL, lm3530_mode_set); | ||
264 | |||
265 | static int __devinit lm3530_probe(struct i2c_client *client, | ||
266 | const struct i2c_device_id *id) | ||
267 | { | ||
268 | struct lm3530_platform_data *pdata = client->dev.platform_data; | ||
269 | struct lm3530_data *drvdata; | ||
270 | int err = 0; | ||
271 | |||
272 | if (pdata == NULL) { | ||
273 | dev_err(&client->dev, "platform data required\n"); | ||
274 | err = -ENODEV; | ||
275 | goto err_out; | ||
276 | } | ||
277 | |||
278 | /* BL mode */ | ||
279 | if (pdata->mode > LM3530_BL_MODE_PWM) { | ||
280 | dev_err(&client->dev, "Illegal Mode request\n"); | ||
281 | err = -EINVAL; | ||
282 | goto err_out; | ||
283 | } | ||
284 | |||
285 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
286 | dev_err(&client->dev, "I2C_FUNC_I2C not supported\n"); | ||
287 | err = -EIO; | ||
288 | goto err_out; | ||
289 | } | ||
290 | |||
291 | drvdata = kzalloc(sizeof(struct lm3530_data), GFP_KERNEL); | ||
292 | if (drvdata == NULL) { | ||
293 | err = -ENOMEM; | ||
294 | goto err_out; | ||
295 | } | ||
296 | |||
297 | drvdata->mode = pdata->mode; | ||
298 | drvdata->client = client; | ||
299 | drvdata->pdata = pdata; | ||
300 | drvdata->led_dev.name = LM3530_LED_DEV; | ||
301 | drvdata->led_dev.brightness_set = lm3530_brightness_set; | ||
302 | |||
303 | i2c_set_clientdata(client, drvdata); | ||
304 | |||
305 | err = lm3530_init_registers(drvdata); | ||
306 | if (err < 0) { | ||
307 | dev_err(&client->dev, "Register Init failed: %d\n", err); | ||
308 | err = -ENODEV; | ||
309 | goto err_reg_init; | ||
310 | } | ||
311 | |||
312 | err = led_classdev_register((struct device *) | ||
313 | &client->dev, &drvdata->led_dev); | ||
314 | if (err < 0) { | ||
315 | dev_err(&client->dev, "Register led class failed: %d\n", err); | ||
316 | err = -ENODEV; | ||
317 | goto err_class_register; | ||
318 | } | ||
319 | |||
320 | err = device_create_file(drvdata->led_dev.dev, &dev_attr_mode); | ||
321 | if (err < 0) { | ||
322 | dev_err(&client->dev, "File device creation failed: %d\n", err); | ||
323 | err = -ENODEV; | ||
324 | goto err_create_file; | ||
325 | } | ||
326 | |||
327 | return 0; | ||
328 | |||
329 | err_create_file: | ||
330 | led_classdev_unregister(&drvdata->led_dev); | ||
331 | err_class_register: | ||
332 | err_reg_init: | ||
333 | kfree(drvdata); | ||
334 | err_out: | ||
335 | return err; | ||
336 | } | ||
337 | |||
338 | static int __devexit lm3530_remove(struct i2c_client *client) | ||
339 | { | ||
340 | struct lm3530_data *drvdata = i2c_get_clientdata(client); | ||
341 | |||
342 | device_remove_file(drvdata->led_dev.dev, &dev_attr_mode); | ||
343 | led_classdev_unregister(&drvdata->led_dev); | ||
344 | kfree(drvdata); | ||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | static const struct i2c_device_id lm3530_id[] = { | ||
349 | {LM3530_NAME, 0}, | ||
350 | {} | ||
351 | }; | ||
352 | |||
353 | static struct i2c_driver lm3530_i2c_driver = { | ||
354 | .probe = lm3530_probe, | ||
355 | .remove = lm3530_remove, | ||
356 | .id_table = lm3530_id, | ||
357 | .driver = { | ||
358 | .name = LM3530_NAME, | ||
359 | .owner = THIS_MODULE, | ||
360 | }, | ||
361 | }; | ||
362 | |||
363 | static int __init lm3530_init(void) | ||
364 | { | ||
365 | return i2c_add_driver(&lm3530_i2c_driver); | ||
366 | } | ||
367 | |||
368 | static void __exit lm3530_exit(void) | ||
369 | { | ||
370 | i2c_del_driver(&lm3530_i2c_driver); | ||
371 | } | ||
372 | |||
373 | module_init(lm3530_init); | ||
374 | module_exit(lm3530_exit); | ||
375 | |||
376 | MODULE_DESCRIPTION("Back Light driver for LM3530"); | ||
377 | MODULE_LICENSE("GPL v2"); | ||
378 | MODULE_AUTHOR("Shreshtha Kumar SAHU <shreshthakumar.sahu@stericsson.com>"); | ||
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index 80a3ae3c00b9..c0cff64a1ae6 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, | |||
534 | } | 534 | } |
535 | 535 | ||
536 | /* led class device attributes */ | 536 | /* led class device attributes */ |
537 | static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current); | 537 | static DEVICE_ATTR(led_current, S_IRUGO | S_IWUSR, show_current, store_current); |
538 | static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL); | 538 | static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL); |
539 | 539 | ||
540 | static struct attribute *lp5521_led_attributes[] = { | 540 | static struct attribute *lp5521_led_attributes[] = { |
@@ -548,15 +548,15 @@ static struct attribute_group lp5521_led_attribute_group = { | |||
548 | }; | 548 | }; |
549 | 549 | ||
550 | /* device attributes */ | 550 | /* device attributes */ |
551 | static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUGO, | 551 | static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUSR, |
552 | show_engine1_mode, store_engine1_mode); | 552 | show_engine1_mode, store_engine1_mode); |
553 | static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUGO, | 553 | static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUSR, |
554 | show_engine2_mode, store_engine2_mode); | 554 | show_engine2_mode, store_engine2_mode); |
555 | static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUGO, | 555 | static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUSR, |
556 | show_engine3_mode, store_engine3_mode); | 556 | show_engine3_mode, store_engine3_mode); |
557 | static DEVICE_ATTR(engine1_load, S_IWUGO, NULL, store_engine1_load); | 557 | static DEVICE_ATTR(engine1_load, S_IWUSR, NULL, store_engine1_load); |
558 | static DEVICE_ATTR(engine2_load, S_IWUGO, NULL, store_engine2_load); | 558 | static DEVICE_ATTR(engine2_load, S_IWUSR, NULL, store_engine2_load); |
559 | static DEVICE_ATTR(engine3_load, S_IWUGO, NULL, store_engine3_load); | 559 | static DEVICE_ATTR(engine3_load, S_IWUSR, NULL, store_engine3_load); |
560 | static DEVICE_ATTR(selftest, S_IRUGO, lp5521_selftest, NULL); | 560 | static DEVICE_ATTR(selftest, S_IRUGO, lp5521_selftest, NULL); |
561 | 561 | ||
562 | static struct attribute *lp5521_attributes[] = { | 562 | static struct attribute *lp5521_attributes[] = { |
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c index d0c4068ecddd..e19fed25f137 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, | |||
713 | } | 713 | } |
714 | 714 | ||
715 | /* led class device attributes */ | 715 | /* led class device attributes */ |
716 | static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current); | 716 | static DEVICE_ATTR(led_current, S_IRUGO | S_IWUSR, show_current, store_current); |
717 | static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL); | 717 | static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL); |
718 | 718 | ||
719 | static struct attribute *lp5523_led_attributes[] = { | 719 | static struct attribute *lp5523_led_attributes[] = { |
@@ -727,21 +727,21 @@ static struct attribute_group lp5523_led_attribute_group = { | |||
727 | }; | 727 | }; |
728 | 728 | ||
729 | /* device attributes */ | 729 | /* device attributes */ |
730 | static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUGO, | 730 | static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUSR, |
731 | show_engine1_mode, store_engine1_mode); | 731 | show_engine1_mode, store_engine1_mode); |
732 | static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUGO, | 732 | static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUSR, |
733 | show_engine2_mode, store_engine2_mode); | 733 | show_engine2_mode, store_engine2_mode); |
734 | static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUGO, | 734 | static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUSR, |
735 | show_engine3_mode, store_engine3_mode); | 735 | show_engine3_mode, store_engine3_mode); |
736 | static DEVICE_ATTR(engine1_leds, S_IRUGO | S_IWUGO, | 736 | static DEVICE_ATTR(engine1_leds, S_IRUGO | S_IWUSR, |
737 | show_engine1_leds, store_engine1_leds); | 737 | show_engine1_leds, store_engine1_leds); |
738 | static DEVICE_ATTR(engine2_leds, S_IRUGO | S_IWUGO, | 738 | static DEVICE_ATTR(engine2_leds, S_IRUGO | S_IWUSR, |
739 | show_engine2_leds, store_engine2_leds); | 739 | show_engine2_leds, store_engine2_leds); |
740 | static DEVICE_ATTR(engine3_leds, S_IRUGO | S_IWUGO, | 740 | static DEVICE_ATTR(engine3_leds, S_IRUGO | S_IWUSR, |
741 | show_engine3_leds, store_engine3_leds); | 741 | show_engine3_leds, store_engine3_leds); |
742 | static DEVICE_ATTR(engine1_load, S_IWUGO, NULL, store_engine1_load); | 742 | static DEVICE_ATTR(engine1_load, S_IWUSR, NULL, store_engine1_load); |
743 | static DEVICE_ATTR(engine2_load, S_IWUGO, NULL, store_engine2_load); | 743 | static DEVICE_ATTR(engine2_load, S_IWUSR, NULL, store_engine2_load); |
744 | static DEVICE_ATTR(engine3_load, S_IWUGO, NULL, store_engine3_load); | 744 | static DEVICE_ATTR(engine3_load, S_IWUSR, NULL, store_engine3_load); |
745 | static DEVICE_ATTR(selftest, S_IRUGO, lp5523_selftest, NULL); | 745 | static DEVICE_ATTR(selftest, S_IRUGO, lp5523_selftest, NULL); |
746 | 746 | ||
747 | static struct attribute *lp5523_attributes[] = { | 747 | static struct attribute *lp5523_attributes[] = { |
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c index f05bb08d0f09..06a5bb484707 100644 --- a/drivers/leds/leds-mc13783.c +++ b/drivers/leds/leds-mc13783.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/leds.h> | 22 | #include <linux/leds.h> |
23 | #include <linux/workqueue.h> | 23 | #include <linux/workqueue.h> |
24 | #include <linux/mfd/mc13783.h> | 24 | #include <linux/mfd/mc13783.h> |
25 | #include <linux/mfd/core.h> | ||
25 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
26 | 27 | ||
27 | struct mc13783_led { | 28 | struct mc13783_led { |
@@ -183,7 +184,7 @@ static int __devinit mc13783_led_setup(struct mc13783_led *led, int max_current) | |||
183 | 184 | ||
184 | static int __devinit mc13783_leds_prepare(struct platform_device *pdev) | 185 | static int __devinit mc13783_leds_prepare(struct platform_device *pdev) |
185 | { | 186 | { |
186 | struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); | 187 | struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev); |
187 | struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent); | 188 | struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent); |
188 | int ret = 0; | 189 | int ret = 0; |
189 | int reg = 0; | 190 | int reg = 0; |
@@ -264,7 +265,7 @@ out: | |||
264 | 265 | ||
265 | static int __devinit mc13783_led_probe(struct platform_device *pdev) | 266 | static int __devinit mc13783_led_probe(struct platform_device *pdev) |
266 | { | 267 | { |
267 | struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); | 268 | struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev); |
268 | struct mc13783_led_platform_data *led_cur; | 269 | struct mc13783_led_platform_data *led_cur; |
269 | struct mc13783_led *led, *led_dat; | 270 | struct mc13783_led *led, *led_dat; |
270 | int ret, i; | 271 | int ret, i; |
@@ -351,7 +352,7 @@ err_free: | |||
351 | 352 | ||
352 | static int __devexit mc13783_led_remove(struct platform_device *pdev) | 353 | static int __devexit mc13783_led_remove(struct platform_device *pdev) |
353 | { | 354 | { |
354 | struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); | 355 | struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev); |
355 | struct mc13783_led *led = platform_get_drvdata(pdev); | 356 | struct mc13783_led *led = platform_get_drvdata(pdev); |
356 | struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent); | 357 | struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent); |
357 | int i; | 358 | int i; |
diff --git a/drivers/leds/leds-net5501.c b/drivers/leds/leds-net5501.c index 1739557a9038..7e764b8365e6 100644 --- a/drivers/leds/leds-net5501.c +++ b/drivers/leds/leds-net5501.c | |||
@@ -19,7 +19,7 @@ | |||
19 | 19 | ||
20 | #include <asm/geode.h> | 20 | #include <asm/geode.h> |
21 | 21 | ||
22 | static struct gpio_led net5501_leds[] = { | 22 | static const struct gpio_led net5501_leds[] = { |
23 | { | 23 | { |
24 | .name = "error", | 24 | .name = "error", |
25 | .gpio = 6, | 25 | .gpio = 6, |
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index da3fa8dcdf5b..666daf77872e 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c | |||
@@ -69,6 +69,7 @@ static int led_pwm_probe(struct platform_device *pdev) | |||
69 | led_dat->pwm = pwm_request(cur_led->pwm_id, | 69 | led_dat->pwm = pwm_request(cur_led->pwm_id, |
70 | cur_led->name); | 70 | cur_led->name); |
71 | if (IS_ERR(led_dat->pwm)) { | 71 | if (IS_ERR(led_dat->pwm)) { |
72 | ret = PTR_ERR(led_dat->pwm); | ||
72 | dev_err(&pdev->dev, "unable to request PWM %d\n", | 73 | dev_err(&pdev->dev, "unable to request PWM %d\n", |
73 | cur_led->pwm_id); | 74 | cur_led->pwm_id); |
74 | goto err; | 75 | goto err; |