ARM64: DTS: Add rk3399-firefly uart4 device, node as /dev/ttyS1
[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 struct class *flashlight_class;
21
22 static int flashlight_suspend(struct device *dev, pm_message_t state)
23 {
24         struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
25
26         if (flashlight_dev->ops)
27                 flashlight_dev->ops->suspend(flashlight_dev, state);
28         return 0;
29 }
30
31 static int flashlight_resume(struct device *dev)
32 {
33         struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
34
35         if (flashlight_dev->ops)
36                 flashlight_dev->ops->resume(flashlight_dev);
37         return 0;
38 }
39
40 static void flashlight_device_release(struct device *dev)
41 {
42         struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
43
44         kfree(flashlight_dev);
45 }
46
47 /**
48  * flashlight_device_register - create and register a new object of
49  *   flashlight_device class.
50  * @name: the name of the new object(must be the same as the name of the
51  *   respective framebuffer device).
52  * @parent: a pointer to the parent device
53  * @devdata: an optional pointer to be stored for private driver use. The
54  *   methods may retrieve it by using bl_get_data(flashlight_dev).
55  * @ops: the flashlight operations structure.
56  *
57  * Creates and registers new flashlight device. Returns either an
58  * ERR_PTR() or a pointer to the newly allocated device.
59  */
60 struct flashlight_device *flashlight_device_register(const char *name,
61                                                      struct device *parent,
62                                                      void *devdata,
63                                                      const struct flashlight_ops
64                                                      *ops,
65                                                      const struct
66                                                      flashlight_properties
67                                                      *props)
68 {
69         struct flashlight_device *flashlight_dev;
70         int rc;
71
72         pr_debug("flashlight_device_register: name=%s\n", name);
73         flashlight_dev = kzalloc(sizeof(*flashlight_dev), GFP_KERNEL);
74         if (!flashlight_dev)
75                 return ERR_PTR(-ENOMEM);
76
77         mutex_init(&flashlight_dev->ops_lock);
78         flashlight_dev->dev.class = flashlight_class;
79         flashlight_dev->dev.parent = parent;
80         flashlight_dev->dev.release = flashlight_device_release;
81         dev_set_name(&flashlight_dev->dev, name);
82         dev_set_drvdata(&flashlight_dev->dev, devdata);
83         /* Copy properties */
84         if (props) {
85                 memcpy(&flashlight_dev->props, props,
86                        sizeof(struct flashlight_properties));
87         }
88         rc = device_register(&flashlight_dev->dev);
89         if (rc) {
90                 kfree(flashlight_dev);
91                 return ERR_PTR(rc);
92         }
93         flashlight_dev->ops = ops;
94         return flashlight_dev;
95 }
96 EXPORT_SYMBOL(flashlight_device_register);
97
98 /**
99  * flashlight_device_unregister - unregisters a flashlight device object.
100  * @flashlight_dev: the flashlight device object to be unregistered and freed.
101  *
102  * Unregisters a previously registered via flashlight_device_register object.
103  */
104 void flashlight_device_unregister(struct flashlight_device *flashlight_dev)
105 {
106         if (!flashlight_dev)
107                 return;
108
109         mutex_lock(&flashlight_dev->ops_lock);
110         flashlight_dev->ops = NULL;
111         mutex_unlock(&flashlight_dev->ops_lock);
112         device_unregister(&flashlight_dev->dev);
113 }
114 EXPORT_SYMBOL(flashlight_device_unregister);
115
116 int flashlight_list_color_temperature(struct flashlight_device *flashlight_dev,
117                                       int selector)
118 {
119         if (flashlight_dev->ops && flashlight_dev->ops->list_color_temperature)
120                 return flashlight_dev->ops->
121                     list_color_temperature(flashlight_dev, selector);
122         return -EINVAL;
123 }
124 EXPORT_SYMBOL(flashlight_list_color_temperature);
125
126 int flashlight_set_color_temperature(struct flashlight_device *flashlight_dev,
127                                      int minK, int maxK)
128 {
129         int selector = 0;
130         int rc;
131
132         if ((flashlight_dev->ops == NULL) ||
133             (flashlight_dev->ops->set_color_temperature == NULL))
134                 return -EINVAL;
135         for (selector = 0;; selector++) {
136                 rc = flashlight_list_color_temperature(flashlight_dev,
137                                                        selector);
138                 if (rc < 0)
139                         return rc;
140                 if (rc >= minK && rc <= maxK) {
141                         mutex_lock(&flashlight_dev->ops_lock);
142                         rc = flashlight_dev->ops->
143                             set_color_temperature(flashlight_dev, rc);
144                         mutex_unlock(&flashlight_dev->ops_lock);
145                         if (rc == 0)
146                                 flashlight_dev->props.color_temperature = rc;
147                         return rc;
148                 }
149
150         }
151         return -EINVAL;
152 }
153 EXPORT_SYMBOL(flashlight_set_color_temperature);
154
155 int flashlight_set_torch_brightness(struct flashlight_device *flashlight_dev,
156                                     int brightness_level)
157 {
158         int rc;
159
160         if ((flashlight_dev->ops == NULL) ||
161             (flashlight_dev->ops->set_torch_brightness == NULL))
162                 return -EINVAL;
163         if (brightness_level > flashlight_dev->props.torch_max_brightness)
164                 return -EINVAL;
165         mutex_lock(&flashlight_dev->ops_lock);
166         rc = flashlight_dev->ops->set_torch_brightness(flashlight_dev,
167                                                        brightness_level);
168         mutex_unlock(&flashlight_dev->ops_lock);
169         if (rc < 0)
170                 return rc;
171         flashlight_dev->props.torch_brightness = brightness_level;
172         return rc;
173
174 }
175 EXPORT_SYMBOL(flashlight_set_torch_brightness);
176
177 int flashlight_set_strobe_brightness(struct flashlight_device *flashlight_dev,
178                                      int brightness_level)
179 {
180         int rc;
181
182         if ((flashlight_dev->ops == NULL) ||
183             (flashlight_dev->ops->set_strobe_brightness == NULL))
184                 return -EINVAL;
185         if (brightness_level > flashlight_dev->props.strobe_max_brightness)
186                 return -EINVAL;
187         mutex_lock(&flashlight_dev->ops_lock);
188         rc = flashlight_dev->ops->set_strobe_brightness(flashlight_dev,
189                                                         brightness_level);
190         mutex_unlock(&flashlight_dev->ops_lock);
191         if (rc < 0)
192                 return rc;
193         flashlight_dev->props.strobe_brightness = brightness_level;
194         return rc;
195 }
196 EXPORT_SYMBOL(flashlight_set_strobe_brightness);
197
198 int flashlight_list_strobe_timeout(struct flashlight_device *flashlight_dev,
199                                    int selector)
200 {
201         if (flashlight_dev->ops && flashlight_dev->ops->list_strobe_timeout) {
202                 return flashlight_dev->ops->list_strobe_timeout(flashlight_dev,
203                                                                 selector);
204         }
205         return -EINVAL;
206 }
207 EXPORT_SYMBOL(flashlight_list_strobe_timeout);
208
209 int flashlight_set_strobe_timeout(struct flashlight_device *flashlight_dev,
210                                   int min_ms, int max_ms)
211 {
212         int selector = 0;
213         int rc = -EINVAL;
214         int timeout;
215
216         if ((flashlight_dev->ops == NULL) ||
217             (flashlight_dev->ops->set_strobe_timeout == NULL))
218                 return -EINVAL;
219         for (selector = 0;; selector++) {
220                 timeout =
221                     flashlight_list_strobe_timeout(flashlight_dev, selector);
222                 if (timeout < 0)
223                         return timeout;
224                 if (timeout >= min_ms && timeout <= max_ms) {
225                         mutex_lock(&flashlight_dev->ops_lock);
226                         rc = flashlight_dev->ops->
227                             set_strobe_timeout(flashlight_dev, timeout);
228                         mutex_unlock(&flashlight_dev->ops_lock);
229                         if (rc == 0)
230                                 flashlight_dev->props.strobe_timeout = timeout;
231                         return rc;
232                 }
233         }
234         return -EINVAL;
235 }
236 EXPORT_SYMBOL(flashlight_set_strobe_timeout);
237
238 int flashlight_set_mode(struct flashlight_device *flashlight_dev, int mode)
239 {
240         int rc;
241
242         if (mode >= FLASHLIGHT_MODE_MAX || mode < 0)
243                 return -EINVAL;
244         if ((flashlight_dev->ops == NULL) ||
245             (flashlight_dev->ops->set_mode == NULL)) {
246                 flashlight_dev->props.mode = mode;
247                 return 0;
248         }
249         mutex_lock(&flashlight_dev->ops_lock);
250         rc = flashlight_dev->ops->set_mode(flashlight_dev, mode);
251         mutex_unlock(&flashlight_dev->ops_lock);
252         if (rc < 0)
253                 return rc;
254         flashlight_dev->props.mode = mode;
255         return rc;
256 }
257 EXPORT_SYMBOL(flashlight_set_mode);
258
259 int flashlight_strobe(struct flashlight_device *flashlight_dev)
260 {
261         if (flashlight_dev->props.mode == FLASHLIGHT_MODE_FLASH
262             || flashlight_dev->props.mode == FLASHLIGHT_MODE_MIXED) {
263                 if (flashlight_dev->ops == NULL ||
264                     flashlight_dev->ops->strobe == NULL)
265                         return -EINVAL;
266                 return flashlight_dev->ops->strobe(flashlight_dev);
267         }
268         return -EINVAL;
269 }
270 EXPORT_SYMBOL(flashlight_strobe);
271
272 static int flashlight_match_device_by_name(struct device *dev, const void *data)
273 {
274         const char *name = data;
275
276         return strcmp(dev_name(dev), name) == 0;
277 }
278
279 struct flashlight_device *find_flashlight_by_name(char *name)
280 {
281         struct device *dev;
282
283         if (!name)
284                 return (struct flashlight_device *)NULL;
285         dev = class_find_device(flashlight_class, NULL, (void*)name,
286                                 flashlight_match_device_by_name);
287
288         return dev ? to_flashlight_device(dev) : NULL;
289
290 }
291 EXPORT_SYMBOL(find_flashlight_by_name);
292
293 int flashlight_strobe_charge(struct flashlight_device *flashlight_dev,
294                              flashlight_charge_event_cb cb, void *data,
295                              int start)
296 {
297
298         if (flashlight_dev->ops->strobe_charge)
299                 return flashlight_dev->ops->strobe_charge(flashlight_dev,
300                                                           cb, data, start);
301         if (flashlight_dev->props.type == FLASHLIGHT_TYPE_LED) {
302                 if (cb)
303                         cb(data, 0);
304                 return 0;
305         }
306         return -EINVAL;
307 }
308 EXPORT_SYMBOL(flashlight_strobe_charge);
309
310 static void __exit flashlight_class_exit(void)
311 {
312         class_destroy(flashlight_class);
313 }
314
315 static int __init flashlight_class_init(void)
316 {
317         flashlight_class = class_create(THIS_MODULE, "flashlight");
318         if (IS_ERR(flashlight_class)) {
319                 pr_err(
320                        "Unable to create flashlight class; errno = %ld\n",
321                        PTR_ERR(flashlight_class));
322                 return PTR_ERR(flashlight_class);
323         }
324
325         flashlight_class->suspend = flashlight_suspend;
326         flashlight_class->resume = flashlight_resume;
327         return 0;
328 }
329 subsys_initcall(flashlight_class_init);
330 module_exit(flashlight_class_exit);
331
332 MODULE_DESCRIPTION("Flashlight Class Device");
333 MODULE_AUTHOR("Patrick Chang <patrick_chang@richtek.com>");
334 MODULE_VERSION("1.0.0_G");
335 MODULE_LICENSE("GPL");