aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/leds
diff options
context:
space:
mode:
authorMike Rapoport <mike@compulab.co.il>2008-10-13 04:06:10 -0400
committerRichard Purdie <rpurdie@rpsys.net>2008-10-20 17:34:11 -0400
commit9e84561c8c8671d9e58d1893cc524a71b20c9183 (patch)
tree0c3f013a3ad2837e40fced5ab7a72a0f4e34fa1b /drivers/leds
parent6da0b38f4433fb0f24615449d7966471b6e5eae0 (diff)
leds: da903x: Add support for LEDs found on DA9030/DA9034
Signed-off-by: Mike Rapoport <mike@compulab.co.il> Signed-off-by: Eric Miao <eric.miao@marvell.com> Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>
Diffstat (limited to 'drivers/leds')
-rw-r--r--drivers/leds/Kconfig7
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-da903x.c175
3 files changed, 183 insertions, 0 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index e3e40427e00e..14bb57b16593 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -157,6 +157,13 @@ config LEDS_PCA955X
157 LED driver chips accessed via the I2C bus. Supported 157 LED driver chips accessed via the I2C bus. Supported
158 devices include PCA9550, PCA9551, PCA9552, and PCA9553. 158 devices include PCA9550, PCA9551, PCA9552, and PCA9553.
159 159
160config LEDS_DA903X
161 tristate "LED Support for DA9030/DA9034 PMIC"
162 depends on LEDS_CLASS && PMIC_DA903X
163 help
164 This option enables support for on-chip LED drivers found
165 on Dialog Semiconductor DA9030/DA9034 PMICs.
166
160comment "LED Triggers" 167comment "LED Triggers"
161 168
162config LEDS_TRIGGERS 169config LEDS_TRIGGERS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index eb186c351a1c..e8714ad3ffff 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
22obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o 22obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
23obj-$(CONFIG_LEDS_FSG) += leds-fsg.o 23obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
24obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o 24obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o
25obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o
25 26
26# LED Triggers 27# LED Triggers
27obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o 28obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c
new file mode 100644
index 000000000000..f1fddb18d70d
--- /dev/null
+++ b/drivers/leds/leds-da903x.c
@@ -0,0 +1,175 @@
1/*
2 * LEDs driver for Dialog Semiconductor DA9030/DA9034
3 *
4 * Copyright (C) 2008 Compulab, Ltd.
5 * Mike Rapoport <mike@compulab.co.il>
6 *
7 * Copyright (C) 2006-2008 Marvell International Ltd.
8 * Eric Miao <eric.miao@marvell.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/module.h>
16#include <linux/kernel.h>
17#include <linux/init.h>
18#include <linux/platform_device.h>
19#include <linux/leds.h>
20#include <linux/mfd/da903x.h>
21
22#define DA9030_LED1_CONTROL 0x20
23#define DA9030_LED2_CONTROL 0x21
24#define DA9030_LED3_CONTROL 0x22
25#define DA9030_LED4_CONTROL 0x23
26#define DA9030_LEDPC_CONTROL 0x24
27#define DA9030_MISC_CONTROL_A 0x26 /* Vibrator Control */
28
29#define DA9034_LED1_CONTROL 0x35
30#define DA9034_LED2_CONTROL 0x36
31#define DA9034_VIBRA 0x40
32
33struct da903x_led {
34 struct led_classdev cdev;
35 struct work_struct work;
36 struct device *master;
37 enum led_brightness new_brightness;
38 int id;
39 int flags;
40};
41
42#define DA9030_LED_OFFSET(id) ((id) - DA9030_ID_LED_1)
43#define DA9034_LED_OFFSET(id) ((id) - DA9034_ID_LED_1)
44
45static void da903x_led_work(struct work_struct *work)
46{
47 struct da903x_led *led = container_of(work, struct da903x_led, work);
48 uint8_t val;
49 int offset;
50
51 switch (led->id) {
52 case DA9030_ID_LED_1:
53 case DA9030_ID_LED_2:
54 case DA9030_ID_LED_3:
55 case DA9030_ID_LED_4:
56 case DA9030_ID_LED_PC:
57 offset = DA9030_LED_OFFSET(led->id);
58 val = led->flags & ~0x87;
59 val |= (led->new_brightness) ? 0x80 : 0; /* EN bit */
60 val |= (led->new_brightness >> 5) & 0x7; /* PWM<2:0> */
61 da903x_write(led->master, DA9030_LED1_CONTROL + offset, val);
62 break;
63 case DA9030_ID_VIBRA:
64 val = led->flags & ~0x80;
65 val |= (led->new_brightness) ? 0x80 : 0; /* EN bit */
66 da903x_write(led->master, DA9030_MISC_CONTROL_A, val);
67 break;
68 case DA9034_ID_LED_1:
69 case DA9034_ID_LED_2:
70 offset = DA9034_LED_OFFSET(led->id);
71 val = (led->new_brightness * 0x5f / LED_FULL) & 0x7f;
72 val |= (led->flags & DA9034_LED_RAMP) ? 0x80 : 0;
73 da903x_write(led->master, DA9034_LED1_CONTROL + offset, val);
74 break;
75 case DA9034_ID_VIBRA:
76 val = led->new_brightness & 0xfe;
77 da903x_write(led->master, DA9034_VIBRA, val);
78 break;
79 }
80}
81
82static void da903x_led_set(struct led_classdev *led_cdev,
83 enum led_brightness value)
84{
85 struct da903x_led *led;
86
87 led = container_of(led_cdev, struct da903x_led, cdev);
88 led->new_brightness = value;
89 schedule_work(&led->work);
90}
91
92static int __devinit da903x_led_probe(struct platform_device *pdev)
93{
94 struct led_info *pdata = pdev->dev.platform_data;
95 struct da903x_led *led;
96 int id, ret;
97
98 if (pdata == NULL)
99 return 0;
100
101 id = pdev->id;
102
103 if (!((id >= DA9030_ID_LED_1 && id <= DA9030_ID_VIBRA) ||
104 (id >= DA9034_ID_LED_1 && id <= DA9034_ID_VIBRA))) {
105 dev_err(&pdev->dev, "invalid LED ID (%d) specified\n", id);
106 return -EINVAL;
107 }
108
109 led = kzalloc(sizeof(struct da903x_led), GFP_KERNEL);
110 if (led == NULL) {
111 dev_err(&pdev->dev, "failed to alloc memory for LED%d\n", id);
112 return -ENOMEM;
113 }
114
115 led->cdev.name = pdata->name;
116 led->cdev.default_trigger = pdata->default_trigger;
117 led->cdev.brightness_set = da903x_led_set;
118 led->cdev.brightness = LED_OFF;
119
120 led->id = id;
121 led->flags = pdata->flags;
122 led->master = pdev->dev.parent;
123 led->new_brightness = LED_OFF;
124
125 INIT_WORK(&led->work, da903x_led_work);
126
127 ret = led_classdev_register(led->master, &led->cdev);
128 if (ret) {
129 dev_err(&pdev->dev, "failed to register LED %d\n", id);
130 goto err;
131 }
132
133 platform_set_drvdata(pdev, led);
134 return 0;
135
136err:
137 kfree(led);
138 return ret;
139}
140
141static int __devexit da903x_led_remove(struct platform_device *pdev)
142{
143 struct da903x_led *led = platform_get_drvdata(pdev);
144
145 led_classdev_unregister(&led->cdev);
146 kfree(led);
147 return 0;
148}
149
150static struct platform_driver da903x_led_driver = {
151 .driver = {
152 .name = "da903x-led",
153 .owner = THIS_MODULE,
154 },
155 .probe = da903x_led_probe,
156 .remove = __devexit_p(da903x_led_remove),
157};
158
159static int __init da903x_led_init(void)
160{
161 return platform_driver_register(&da903x_led_driver);
162}
163module_init(da903x_led_init);
164
165static void __exit da903x_led_exit(void)
166{
167 platform_driver_unregister(&da903x_led_driver);
168}
169module_exit(da903x_led_exit);
170
171MODULE_DESCRIPTION("LEDs driver for Dialog Semiconductor DA9030/DA9034");
172MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"
173 "Mike Rapoport <mike@compulab.co.il>");
174MODULE_LICENSE("GPL");
175MODULE_ALIAS("platform:da903x-led");