Merge remote-tracking branch 'stable/linux-3.0.y' into develop-3.0
[firefly-linux-kernel-4.4.55.git] / drivers / leds / leds-wm831x-status.c
1 /*
2  * LED driver for WM831x status LEDs
3  *
4  * Copyright(C) 2009 Wolfson Microelectronics PLC.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  */
11
12 #include <linux/kernel.h>
13 #include <linux/init.h>
14 #include <linux/platform_device.h>
15 #include <linux/slab.h>
16 #include <linux/leds.h>
17 #include <linux/err.h>
18 #include <linux/mfd/wm831x/core.h>
19 #include <linux/mfd/wm831x/pdata.h>
20 #include <linux/mfd/wm831x/status.h>
21
22 struct light_state_t {
23         unsigned int color;
24
25         int mode;
26         int onms;
27         int offms;
28
29         int brightness;
30 };
31
32 struct wm831x_status {
33         struct led_classdev cdev;
34         struct wm831x *wm831x;
35         struct work_struct work;
36         struct mutex mutex;
37
38         spinlock_t value_lock;
39         int reg;     /* Control register */
40         int reg_val; /* Control register value */
41
42         int blink;
43         int blink_time;
44         int blink_cyc;
45         int src;
46         enum led_brightness brightness;
47 };
48
49 #define to_wm831x_status(led_cdev) \
50         container_of(led_cdev, struct wm831x_status, cdev)
51
52 static void wm831x_status_work(struct work_struct *work)
53 {
54         struct wm831x_status *led = container_of(work, struct wm831x_status,
55                                                  work);
56         unsigned long flags;
57
58         mutex_lock(&led->mutex);
59
60         led->reg_val &= ~(WM831X_LED_SRC_MASK | WM831X_LED_MODE_MASK |
61                           WM831X_LED_DUTY_CYC_MASK | WM831X_LED_DUR_MASK);
62
63         spin_lock_irqsave(&led->value_lock, flags);
64
65         led->reg_val |= led->src << WM831X_LED_SRC_SHIFT;
66         if (led->blink) {
67                 led->reg_val |= 2 << WM831X_LED_MODE_SHIFT;
68                 led->reg_val |= led->blink_time << WM831X_LED_DUR_SHIFT;
69                 led->reg_val |= led->blink_cyc;
70         } else {
71                 if (led->brightness != LED_OFF)
72                         led->reg_val |= 1 << WM831X_LED_MODE_SHIFT;
73         }
74
75         spin_unlock_irqrestore(&led->value_lock, flags);
76
77         wm831x_reg_write(led->wm831x, led->reg, led->reg_val);
78
79         mutex_unlock(&led->mutex);
80 }
81
82 static void wm831x_status_set(struct led_classdev *led_cdev,
83                            enum led_brightness value)
84 {
85         struct wm831x_status *led = to_wm831x_status(led_cdev);
86         unsigned long flags;
87
88         spin_lock_irqsave(&led->value_lock, flags);
89         led->brightness = value;
90         if (value == LED_OFF)
91                 led->blink = 0;
92         schedule_work(&led->work);
93         spin_unlock_irqrestore(&led->value_lock, flags);
94 }
95
96 static int wm831x_status_blink_set(struct led_classdev *led_cdev,
97                                    unsigned long *delay_on,
98                                    unsigned long *delay_off)
99 {
100         struct wm831x_status *led = to_wm831x_status(led_cdev);
101         unsigned long flags;
102         int ret = 0;
103
104         /* Pick some defaults if we've not been given times */
105         if (*delay_on == 0 && *delay_off == 0) {
106                 *delay_on = 250;
107                 *delay_off = 250;
108         }
109
110         spin_lock_irqsave(&led->value_lock, flags);
111
112         /* We only have a limited selection of settings, see if we can
113          * support the configuration we're being given */
114         switch (*delay_on) {
115         case 1000:
116                 led->blink_time = 0;
117                 break;
118         case 250:
119                 led->blink_time = 1;
120                 break;
121         case 125:
122                 led->blink_time = 2;
123                 break;
124         case 62:
125         case 63:
126                 /* Actually 62.5ms */
127                 led->blink_time = 3;
128                 break;
129         default:
130                 ret = -EINVAL;
131                 break;
132         }
133
134         if (ret == 0) {
135                 switch (*delay_off / *delay_on) {
136                 case 1:
137                         led->blink_cyc = 0;
138                         break;
139                 case 3:
140                         led->blink_cyc = 1;
141                         break;
142                 case 4:
143                         led->blink_cyc = 2;
144                         break;
145                 case 8:
146                         led->blink_cyc = 3;
147                         break;
148                 default:
149                         ret = -EINVAL;
150                         break;
151                 }
152         }
153
154         if (ret == 0)
155                 led->blink = 1;
156         else
157                 led->blink = 0;
158
159         /* Always update; if we fail turn off blinking since we expect
160          * a software fallback. */
161         schedule_work(&led->work);
162
163         spin_unlock_irqrestore(&led->value_lock, flags);
164
165         return ret;
166 }
167
168 static ssize_t wm831x_status_blink_store(struct device *dev,
169                                        struct device_attribute *attr,
170                                        const char *buf, size_t size)
171 {
172         struct led_classdev *led_cdev = dev_get_drvdata(dev);
173         struct wm831x_status *led = to_wm831x_status(led_cdev);
174         struct light_state_t *light_state = NULL;
175         unsigned long flags;
176         int ret = 0;
177     enum led_brightness value;
178         unsigned int delay_on, delay_off, mode, color;
179
180         if (size != sizeof (struct light_state_t)) {
181                 printk("%s: set led blink err\n", __func__);
182                 return -1;
183         }
184
185         light_state = (struct light_state_t *)buf;
186         if (light_state) {
187                 led->src = 3;
188
189                 value = light_state->brightness;
190                 delay_on = light_state->onms;
191                 delay_off = light_state->offms;
192                 mode = light_state->mode;
193                 color = light_state->color;
194
195                 //printk("%s: color = %#x delay_on = %d delya_off = %d brightness = %d mode = %d\n",
196                 //              __func__, color, delay_on, delay_off, value, mode);
197                 if (delay_on == 0 && delay_off == 0) {
198                         delay_on = 250;
199                         delay_off = 250;
200                 }
201
202                 spin_lock_irqsave(&led->value_lock, flags);
203
204                 switch (delay_on) {
205                 case 1000:
206                         led->blink_time = 0;
207                         break;
208                 case 500:
209                 case 250:
210                         led->blink_time = 1;
211                         break;
212                 case 125:
213                         led->blink_time = 2;
214                         break;
215                 case 62:
216                 case 63:
217                         /* Actually 62.5ms */
218                         led->blink_time = 3;
219                         break;
220                 default:
221                         ret = -EINVAL;
222                         break;
223                 }
224
225                 if (ret == 0) {
226                         switch (delay_off / delay_on) {
227                         case 1:
228                                 led->blink_cyc = 0;
229                                 break;
230                         case 3:
231                                 led->blink_cyc = 1;
232                                 break;
233                         case 4:
234                                 led->blink_cyc = 2;
235                                 break;
236                         case 8:
237                                 led->blink_cyc = 3;
238                                 break;
239                         default:
240                                 ret = -EINVAL;
241                                 break;
242                         }
243                 }
244
245                 if (ret == 0)
246                         led->blink = 1;
247                 else
248                         led->blink = 0;
249                 
250                 //set led brightness
251                 led->brightness = mode;
252                 if (led->brightness == LED_OFF)
253                         led->blink = 0;
254
255                 schedule_work(&led->work);
256
257                 spin_unlock_irqrestore(&led->value_lock, flags);
258         }
259
260         return size;
261 }
262 static DEVICE_ATTR(blink, 0777, NULL, wm831x_status_blink_store);
263
264 static const char *led_src_texts[] = {
265         "otp",
266         "power",
267         "charger",
268         "soft",
269 };
270
271 static ssize_t wm831x_status_src_show(struct device *dev,
272                                       struct device_attribute *attr, char *buf)
273 {
274         struct led_classdev *led_cdev = dev_get_drvdata(dev);
275         struct wm831x_status *led = to_wm831x_status(led_cdev);
276         int i;
277         ssize_t ret = 0;
278
279         mutex_lock(&led->mutex);
280
281         for (i = 0; i < ARRAY_SIZE(led_src_texts); i++)
282                 if (i == led->src)
283                         ret += sprintf(&buf[ret], "[%s] ", led_src_texts[i]);
284                 else
285                         ret += sprintf(&buf[ret], "%s ", led_src_texts[i]);
286
287         mutex_unlock(&led->mutex);
288
289         ret += sprintf(&buf[ret], "\n");
290
291         return ret;
292 }
293
294 static ssize_t wm831x_status_src_store(struct device *dev,
295                                        struct device_attribute *attr,
296                                        const char *buf, size_t size)
297 {
298         struct led_classdev *led_cdev = dev_get_drvdata(dev);
299         struct wm831x_status *led = to_wm831x_status(led_cdev);
300         char name[20];
301         int i;
302         size_t len;
303
304         name[sizeof(name) - 1] = '\0';
305         strncpy(name, buf, sizeof(name) - 1);
306         len = strlen(name);
307
308         if (len && name[len - 1] == '\n')
309                 name[len - 1] = '\0';
310
311         for (i = 0; i < ARRAY_SIZE(led_src_texts); i++) {
312                 if (!strcmp(name, led_src_texts[i])) {
313                         mutex_lock(&led->mutex);
314
315                         led->src = i;
316                         schedule_work(&led->work);
317
318                         mutex_unlock(&led->mutex);
319                 }
320         }
321
322         return size;
323 }
324
325 static DEVICE_ATTR(src, 0644, wm831x_status_src_show, wm831x_status_src_store);
326
327 static int wm831x_status_probe(struct platform_device *pdev)
328 {
329         struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
330         struct wm831x_pdata *chip_pdata;
331         struct wm831x_status_pdata pdata;
332         struct wm831x_status *drvdata;
333         struct resource *res;
334         int id = pdev->id % ARRAY_SIZE(chip_pdata->status);
335         int ret;
336
337         res = platform_get_resource(pdev, IORESOURCE_IO, 0);
338         if (res == NULL) {
339                 dev_err(&pdev->dev, "No I/O resource\n");
340                 ret = -EINVAL;
341                 goto err;
342         }
343
344         drvdata = kzalloc(sizeof(struct wm831x_status), GFP_KERNEL);
345         if (!drvdata)
346                 return -ENOMEM;
347         dev_set_drvdata(&pdev->dev, drvdata);
348
349         drvdata->wm831x = wm831x;
350         drvdata->reg = res->start;
351
352         if (wm831x->dev->platform_data)
353                 chip_pdata = wm831x->dev->platform_data;
354         else
355                 chip_pdata = NULL;
356
357         memset(&pdata, 0, sizeof(pdata));
358         if (chip_pdata && chip_pdata->status[id])
359                 memcpy(&pdata, chip_pdata->status[id], sizeof(pdata));
360         else
361                 pdata.name = dev_name(&pdev->dev);
362
363         mutex_init(&drvdata->mutex);
364         INIT_WORK(&drvdata->work, wm831x_status_work);
365         spin_lock_init(&drvdata->value_lock);
366
367         /* We cache the configuration register and read startup values
368          * from it. */
369         drvdata->reg_val = wm831x_reg_read(wm831x, drvdata->reg);
370         if (drvdata->reg == WM831X_STATUS_LED_2)
371                 wm831x_reg_write(wm831x, drvdata->reg, 0xc027);
372
373         if (drvdata->reg_val & WM831X_LED_MODE_MASK)
374                 drvdata->brightness = LED_FULL;
375         else
376                 drvdata->brightness = LED_OFF;
377
378         /* Set a default source if configured, otherwise leave the
379          * current hardware setting.
380          */
381         if (pdata.default_src == WM831X_STATUS_PRESERVE) {
382                 drvdata->src = drvdata->reg_val;
383                 drvdata->src &= WM831X_LED_SRC_MASK;
384                 drvdata->src >>= WM831X_LED_SRC_SHIFT;
385         } else {
386                 drvdata->src = pdata.default_src - 1;
387         }
388
389         drvdata->cdev.name = pdata.name;
390         drvdata->cdev.default_trigger = pdata.default_trigger;
391         drvdata->cdev.brightness_set = wm831x_status_set;
392         drvdata->cdev.blink_set = wm831x_status_blink_set;
393
394         ret = led_classdev_register(wm831x->dev, &drvdata->cdev);
395         if (ret < 0) {
396                 dev_err(&pdev->dev, "Failed to register LED: %d\n", ret);
397                 goto err_led;
398         }
399
400         ret = device_create_file(drvdata->cdev.dev, &dev_attr_blink);
401         if (ret != 0)
402                 dev_err(&pdev->dev,
403                         "LED no blink function: %d\n", ret);
404
405         ret = device_create_file(drvdata->cdev.dev, &dev_attr_src);
406         if (ret != 0)
407                 dev_err(&pdev->dev,
408                         "No source control for LED: %d\n", ret);
409
410         return 0;
411
412 err_led:
413         led_classdev_unregister(&drvdata->cdev);
414         kfree(drvdata);
415 err:
416         return ret;
417 }
418
419 static int wm831x_status_remove(struct platform_device *pdev)
420 {
421         struct wm831x_status *drvdata = platform_get_drvdata(pdev);
422
423         device_remove_file(drvdata->cdev.dev, &dev_attr_src);
424         led_classdev_unregister(&drvdata->cdev);
425         kfree(drvdata);
426
427         return 0;
428 }
429
430 static struct platform_driver wm831x_status_driver = {
431         .driver = {
432                    .name = "wm831x-status",
433                    .owner = THIS_MODULE,
434                    },
435         .probe = wm831x_status_probe,
436         .remove = wm831x_status_remove,
437 };
438
439 static int __devinit wm831x_status_init(void)
440 {
441         return platform_driver_register(&wm831x_status_driver);
442 }
443 module_init(wm831x_status_init);
444
445 static void wm831x_status_exit(void)
446 {
447         platform_driver_unregister(&wm831x_status_driver);
448 }
449 module_exit(wm831x_status_exit);
450
451 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
452 MODULE_DESCRIPTION("WM831x status LED driver");
453 MODULE_LICENSE("GPL");
454 MODULE_ALIAS("platform:wm831x-status");