video: sprdfd: disable ESD feature
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / leds / flashlight.c
1 /* drivers/leds/flashlight.c
2  * Flashlight Class Device Driver
3  *
4  * Copyright (C) 2013 Richtek Technology Corp.
5  * Author: Patrick Chang <patrick_chang@richtek.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  */
12
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/leds/flashlight.h>
16 #include <linux/ctype.h>
17 #include <linux/err.h>
18 #include <linux/slab.h>
19 #include <linux/regulator/consumer.h>
20
21 static const char const *flashlight_type_string[] = {
22         [FLASHLIGHT_TYPE_XENON] = "Xenon",
23         [FLASHLIGHT_TYPE_LED] = "LED",
24         [FLASHLIFHT_TYPE_BULB] = "Bulb",
25 };
26
27 static const char const *flashlight_mode_string[] = {
28         [FLASHLIGHT_MODE_OFF] = "Off",
29         [FLASHLIGHT_MODE_TORCH] = "Torch",
30         [FLASHLIGHT_MODE_FLASH] = "Flash",
31         [FLASHLIGHT_MODE_MIXED] = "Mixed",
32 };
33
34 static ssize_t flashlight_show_name(struct device *dev,
35                 struct device_attribute *attr, char *buf)
36 {
37         struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
38         return sprintf(buf, "%s\n",
39                         flashlight_dev->props.alias_name ?
40                         flashlight_dev->props.alias_name : "anonymous");
41 }
42
43 static ssize_t flashlight_show_type(struct device *dev,
44                 struct device_attribute *attr, char *buf)
45 {
46         struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
47         return sprintf(buf, "%s\n",
48                         flashlight_type_string[flashlight_dev->props.type]);
49 }
50
51 static ssize_t flashlight_show_mode(struct device *dev,
52                 struct device_attribute *attr, char *buf)
53 {
54         struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
55         return sprintf(buf, "%s\n",
56                         flashlight_mode_string[flashlight_dev->props.mode]);
57 }
58
59 static ssize_t flashlight_show_torch_max_brightness(struct device *dev,
60                 struct device_attribute *attr, char *buf)
61 {
62         struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
63
64         return sprintf(buf, "%d\n",
65                         flashlight_dev->props.torch_max_brightness);
66 }
67
68 static ssize_t flashlight_show_strobe_max_brightness(struct device *dev,
69                 struct device_attribute *attr, char *buf)
70 {
71         struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
72
73         return sprintf(buf, "%d\n",
74                         flashlight_dev->props.strobe_max_brightness);
75 }
76
77 static ssize_t flashlight_show_color_temperature(struct device *dev,
78                 struct device_attribute *attr, char *buf)
79 {
80         struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
81
82         return sprintf(buf, "%d\n",
83                         flashlight_dev->props.color_temperature);
84 }
85
86 static ssize_t flashlight_show_strobe_delay(struct device *dev,
87                 struct device_attribute *attr, char *buf)
88 {
89         struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
90
91         return sprintf(buf, "%d\n",
92                         flashlight_dev->props.strobe_delay);
93 }
94
95 static ssize_t flashlight_store_strobe_timeout(struct device *dev,
96                 struct device_attribute *attr, const char *buf, size_t count)
97 {
98         int rc;
99         struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
100         long timeout;
101
102         rc = kstrtol(buf, 0, &timeout);
103         if (rc)
104                 return rc;
105         rc =  flashlight_dev->ops->set_strobe_timeout(flashlight_dev, timeout);
106         if (rc == 0)
107                 rc = count;
108         return rc;
109 }
110
111 static ssize_t flashlight_show_strobe_timeout(struct device *dev,
112                 struct device_attribute *attr, char *buf)
113 {
114         struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
115         return sprintf(buf, "%d\n",
116                         flashlight_dev->props.strobe_timeout);
117 }
118
119
120 static ssize_t flashlight_store_torch_brightness(struct device *dev,
121                 struct device_attribute *attr, const char *buf, size_t count)
122 {
123         int rc;
124         struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
125         long brightness;
126
127         rc = kstrtol(buf, 0, &brightness);
128         if (rc)
129                 return rc;
130
131         rc = -ENXIO;
132
133         mutex_lock(&flashlight_dev->ops_lock);
134         if (flashlight_dev->ops &&
135                         flashlight_dev->ops->set_torch_brightness) {
136                 if (brightness > flashlight_dev->props.torch_max_brightness)
137                         rc = -EINVAL;
138                 else {
139                         pr_debug("flashlight: set torch brightness to %ld\n",
140                                         brightness);
141                         flashlight_dev->props.torch_brightness = brightness;
142                         flashlight_dev->ops->set_torch_brightness(
143                                         flashlight_dev, brightness);
144                         rc = count;
145                 }
146         }
147         mutex_unlock(&flashlight_dev->ops_lock);
148
149         return rc;
150 }
151
152 static ssize_t flashlight_show_torch_brightness(struct device *dev,
153                 struct device_attribute *attr, char *buf)
154 {
155         struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
156
157         return sprintf(buf, "%d\n",
158                         flashlight_dev->props.torch_brightness);
159 }
160
161 static ssize_t flashlight_store_strobe_brightness(struct device *dev,
162                 struct device_attribute *attr, const char *buf, size_t count)
163 {
164         int rc;
165         struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
166         long brightness;
167
168         rc = kstrtol(buf, 0, &brightness);
169         if (rc)
170                 return rc;
171
172         rc = -ENXIO;
173
174         mutex_lock(&flashlight_dev->ops_lock);
175         if (flashlight_dev->ops &&
176                         flashlight_dev->ops->set_strobe_brightness) {
177                 if (brightness > flashlight_dev->props.strobe_max_brightness)
178                         rc = -EINVAL;
179                 else {
180                         pr_debug("flashlight: set strobe brightness to %ld\n",
181                                         brightness);
182                         flashlight_dev->props.strobe_brightness = brightness;
183                         flashlight_dev->ops->set_strobe_brightness(
184                                         flashlight_dev, brightness);
185                         rc = count;
186                 }
187         }
188         mutex_unlock(&flashlight_dev->ops_lock);
189         return rc;
190 }
191
192 static ssize_t flashlight_show_strobe_brightness(struct device *dev,
193                 struct device_attribute *attr, char *buf)
194 {
195         struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
196
197         return sprintf(buf, "%d\n",
198                         flashlight_dev->props.strobe_brightness);
199 }
200
201
202
203 static struct class *flashlight_class;
204
205 static int flashlight_suspend(struct device *dev, pm_message_t state)
206 {
207         struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
208         if (flashlight_dev->ops) {
209                 flashlight_dev->ops->suspend(flashlight_dev, state);
210         }
211         return 0;
212 }
213
214 static int flashlight_resume(struct device *dev)
215 {
216         struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
217         if (flashlight_dev->ops) {
218                 flashlight_dev->ops->resume(flashlight_dev);
219         }
220         return 0;
221 }
222
223 static void flashlight_device_release(struct device *dev)
224 {
225         struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
226         kfree(flashlight_dev);
227 }
228
229 static struct device_attribute flashlight_device_attributes[] = {
230         __ATTR(name, 0444, flashlight_show_name, NULL),
231         __ATTR(type, 0444, flashlight_show_type, NULL),
232         __ATTR(mode, 0444, flashlight_show_mode, NULL),
233         __ATTR(torch_max_brightness, 0444,
234                         flashlight_show_torch_max_brightness, NULL),
235         __ATTR(strobe_max_brightness, 0444,
236                         flashlight_show_strobe_max_brightness, NULL),
237         __ATTR(color_temperature, 0444,
238                         flashlight_show_color_temperature, NULL),
239         __ATTR(strobe_delay, 0444,
240                         flashlight_show_strobe_delay, NULL),
241         __ATTR(strobe_timeout, 0644,
242                         flashlight_show_strobe_timeout,
243                         flashlight_store_strobe_timeout),
244         __ATTR(torch_brightness, 0644,
245                         flashlight_show_torch_brightness,
246                         flashlight_store_torch_brightness),
247         __ATTR(strobe_brightness, 0644,
248                         flashlight_show_strobe_brightness,
249                         flashlight_store_strobe_brightness),
250         __ATTR_NULL,
251 };
252
253 /**
254  * flashlight_device_register - create and register a new object of
255  *   flashlight_device class.
256  * @name: the name of the new object(must be the same as the name of the
257  *   respective framebuffer device).
258  * @parent: a pointer to the parent device
259  * @devdata: an optional pointer to be stored for private driver use. The
260  *   methods may retrieve it by using bl_get_data(flashlight_dev).
261  * @ops: the flashlight operations structure.
262  *
263  * Creates and registers new flashlight device. Returns either an
264  * ERR_PTR() or a pointer to the newly allocated device.
265  */
266 struct flashlight_device *flashlight_device_register(const char *name,
267                 struct device *parent, void *devdata, const struct flashlight_ops *ops,
268                 const struct flashlight_properties *props)
269 {
270         struct flashlight_device *flashlight_dev;
271         int rc;
272         pr_debug("flashlight_device_register: name=%s\n", name);
273         flashlight_dev = kzalloc(sizeof(*flashlight_dev), GFP_KERNEL);
274         if (!flashlight_dev)
275                 return ERR_PTR(-ENOMEM);
276
277         mutex_init(&flashlight_dev->ops_lock);
278         flashlight_dev->dev.class = flashlight_class;
279         flashlight_dev->dev.parent = parent;
280         flashlight_dev->dev.release = flashlight_device_release;
281         dev_set_name(&flashlight_dev->dev, name);
282         dev_set_drvdata(&flashlight_dev->dev, devdata);
283         /* Copy properties */
284         if (props) {
285                 memcpy(&flashlight_dev->props, props,
286                                 sizeof(struct flashlight_properties));
287         }
288         rc = device_register(&flashlight_dev->dev);
289         if (rc) {
290                 kfree(flashlight_dev);
291                 return ERR_PTR(rc);
292         }
293         flashlight_dev->ops = ops;
294         return flashlight_dev;
295 }
296 EXPORT_SYMBOL(flashlight_device_register);
297
298 /**
299  * flashlight_device_unregister - unregisters a flashlight device object.
300  * @flashlight_dev: the flashlight device object to be unregistered and freed.
301  *
302  * Unregisters a previously registered via flashlight_device_register object.
303  */
304 void flashlight_device_unregister(struct flashlight_device *flashlight_dev)
305 {
306         if (!flashlight_dev)
307                 return;
308
309         mutex_lock(&flashlight_dev->ops_lock);
310         flashlight_dev->ops = NULL;
311         mutex_unlock(&flashlight_dev->ops_lock);
312         device_unregister(&flashlight_dev->dev);
313 }
314 EXPORT_SYMBOL(flashlight_device_unregister);
315
316 int flashlight_list_color_temperature(
317                 struct flashlight_device *flashlight_dev,
318                 int selector)
319 {
320         if (flashlight_dev->ops &&
321                         flashlight_dev->ops->list_color_temperature) {
322                 return flashlight_dev->ops->list_color_temperature(
323                                 flashlight_dev,
324                                 selector);
325         }
326         return -EINVAL;
327 }
328 EXPORT_SYMBOL(flashlight_list_color_temperature);
329
330 int flashlight_set_color_temperature(
331                 struct flashlight_device *flashlight_dev,
332                 int minK, int maxK)
333 {
334         int selector = 0;
335         int rc;
336
337         if ((flashlight_dev->ops ==  NULL) ||
338                         (flashlight_dev->ops->set_color_temperature == NULL))
339                 return -EINVAL;
340         for (selector = 0; ; selector++) {
341                 rc = flashlight_list_color_temperature(flashlight_dev, selector);
342                 if (rc < 0)
343                         return rc;
344                 if (rc >= minK && rc <= maxK) {
345                         mutex_lock(&flashlight_dev->ops_lock);
346                         rc = flashlight_dev->ops->set_color_temperature(
347                                         flashlight_dev, rc);
348                         mutex_unlock(&flashlight_dev->ops_lock);
349                         if (rc == 0)
350                                 flashlight_dev->props.color_temperature = rc;
351                         return rc;
352                 }
353
354         }
355         return -EINVAL;
356 }
357 EXPORT_SYMBOL(flashlight_set_color_temperature);
358
359 int flashlight_set_torch_brightness(
360                 struct flashlight_device *flashlight_dev,
361                 int brightness_level)
362 {
363         int rc;
364         if ((flashlight_dev->ops ==  NULL) ||
365                         (flashlight_dev->ops->set_torch_brightness == NULL))
366                 return -EINVAL;
367         if (brightness_level > flashlight_dev->props.torch_max_brightness)
368                 return -EINVAL;
369         mutex_lock(&flashlight_dev->ops_lock);
370         rc = flashlight_dev->ops->set_torch_brightness(flashlight_dev,
371                         brightness_level);
372         mutex_unlock(&flashlight_dev->ops_lock);
373         if (rc < 0)
374                 return rc;
375         flashlight_dev->props.torch_brightness = brightness_level;
376         return rc;
377
378 }
379 EXPORT_SYMBOL(flashlight_set_torch_brightness);
380
381 int flashlight_set_strobe_brightness(
382                 struct flashlight_device *flashlight_dev,
383                 int brightness_level)
384 {
385         int rc;
386         if ((flashlight_dev->ops ==  NULL) ||
387                         (flashlight_dev->ops->set_strobe_brightness == NULL))
388                 return -EINVAL;
389         if (brightness_level > flashlight_dev->props.strobe_max_brightness)
390                 return -EINVAL;
391         mutex_lock(&flashlight_dev->ops_lock);
392         rc = flashlight_dev->ops->set_strobe_brightness(flashlight_dev,
393                         brightness_level);
394         mutex_unlock(&flashlight_dev->ops_lock);
395         if (rc < 0)
396                 return rc;
397         flashlight_dev->props.strobe_brightness = brightness_level;
398         return rc;
399 }
400 EXPORT_SYMBOL(flashlight_set_strobe_brightness);
401
402 int flashlight_list_strobe_timeout(
403                 struct flashlight_device *flashlight_dev,
404                 int selector)
405 {
406         if (flashlight_dev->ops &&
407                         flashlight_dev->ops->list_strobe_timeout) {
408                 return flashlight_dev->ops->list_strobe_timeout(flashlight_dev,
409                                 selector);
410         }
411         return -EINVAL;
412 }
413 EXPORT_SYMBOL(flashlight_list_strobe_timeout);
414
415 int flashlight_set_strobe_timeout(
416                 struct flashlight_device *flashlight_dev,
417                 int min_ms, int max_ms)
418 {
419         int selector = 0;
420         int rc = -EINVAL;
421         int timeout;
422
423         if ((flashlight_dev->ops ==  NULL) ||
424                         (flashlight_dev->ops->set_strobe_timeout == NULL))
425                 return -EINVAL;
426         for (selector = 0; ; selector++) {
427                 timeout = flashlight_list_strobe_timeout(flashlight_dev, selector);
428                 if (timeout < 0)
429                         return timeout;
430                 if (timeout >= min_ms && timeout <= max_ms) {
431                         mutex_lock(&flashlight_dev->ops_lock);
432                         rc = flashlight_dev->ops->set_strobe_timeout(
433                                         flashlight_dev, timeout);
434                         mutex_unlock(&flashlight_dev->ops_lock);
435                         if (rc == 0)
436                                 flashlight_dev->props.strobe_timeout = timeout;
437                         return rc;
438                 }
439         }
440         return -EINVAL;
441 }
442 EXPORT_SYMBOL(flashlight_set_strobe_timeout);
443
444 int flashlight_set_mode(struct flashlight_device *flashlight_dev,
445                 int mode)
446 {
447         int rc;
448         if (mode >= FLASHLIGHT_MODE_MAX || mode < 0)
449                 return -EINVAL;
450         if ((flashlight_dev->ops ==  NULL) ||
451                         (flashlight_dev->ops->set_mode == NULL)) {
452                 flashlight_dev->props.mode = mode;
453                 return 0;
454         }
455         mutex_lock(&flashlight_dev->ops_lock);
456         rc = flashlight_dev->ops->set_mode(flashlight_dev,
457                         mode);
458         mutex_unlock(&flashlight_dev->ops_lock);
459         if (rc < 0)
460                 return rc;
461         flashlight_dev->props.mode = mode;
462         return rc;
463 }
464 EXPORT_SYMBOL(flashlight_set_mode);
465
466 int flashlight_strobe(struct flashlight_device *flashlight_dev)
467 {
468         if (flashlight_dev->props.mode == FLASHLIGHT_MODE_FLASH
469                         || flashlight_dev->props.mode == FLASHLIGHT_MODE_MIXED) {
470                 if (flashlight_dev->ops == NULL ||
471                                 flashlight_dev->ops->strobe == NULL)
472                         return -EINVAL;
473                 return flashlight_dev->ops->strobe(flashlight_dev);
474         }
475         return -EINVAL;
476 }
477 EXPORT_SYMBOL(flashlight_strobe);
478
479 static int flashlight_match_device_by_name(struct device *dev, void *data)
480 {
481         const char *name = data;
482         return strcmp(dev_name(dev), name) == 0;
483 }
484
485 struct flashlight_device *find_flashlight_by_name(char *name)
486 {
487         struct device *dev;
488         if (!name)
489                 return (struct flashlight_device *)NULL;
490         dev = class_find_device(flashlight_class, NULL, name,
491                         flashlight_match_device_by_name);
492
493         return dev ? to_flashlight_device(dev) : NULL;
494
495 }
496 EXPORT_SYMBOL(find_flashlight_by_name);
497
498 int flashlight_strobe_charge(struct flashlight_device *flashlight_dev,
499                 flashlight_charge_event_cb cb, void *data, int start)
500 {
501
502         if (flashlight_dev->ops->strobe_charge)
503                 return flashlight_dev->ops->strobe_charge(flashlight_dev,
504                                 cb, data, start);
505         if (flashlight_dev->props.type == FLASHLIGHT_TYPE_LED) {
506                 if (cb)
507                         cb(data, 0);
508                 return 0;
509         }
510         return -EINVAL;
511 }
512 EXPORT_SYMBOL(flashlight_strobe_charge);
513
514 static void __exit flashlight_class_exit(void)
515 {
516         class_destroy(flashlight_class);
517 }
518
519 static int __init flashlight_class_init(void)
520 {
521         flashlight_class = class_create(THIS_MODULE, "flashlight");
522         if (IS_ERR(flashlight_class)) {
523                 printk(KERN_WARNING "Unable to create flashlight class; errno = %ld\n",
524                                 PTR_ERR(flashlight_class));
525                 return PTR_ERR(flashlight_class);
526         }
527         flashlight_class->dev_attrs = flashlight_device_attributes;
528         flashlight_class->suspend = flashlight_suspend;
529         flashlight_class->resume = flashlight_resume;
530         return 0;
531 }
532
533 subsys_initcall(flashlight_class_init);
534 module_exit(flashlight_class_exit);
535
536 MODULE_DESCRIPTION("Flashlight Class Device");
537 MODULE_AUTHOR("Patrick Chang <patrick_chang@richtek.com>");
538 MODULE_VERSION("1.0.0_G");
539 MODULE_LICENSE("GPL");