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