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 / rtfled.c
1 /* drivers/leds/rtfled.c
2  * Richtek Flash LED Universal Architecture
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/kernel.h>
14 #include <linux/module.h>
15 #include <linux/platform_device.h>
16 #include "rtfled.h"
17 #include <linux/init.h>
18 #include <linux/version.h>
19
20 #define RTFLED_INFO(format, args...) \
21         pr_info("%s:%s() line-%d: " format, \
22           ALIAS_NAME, __func__, __LINE__, ## args)
23 #define RTFLED_WARN(format, args...) \
24         pr_warn("%s:%s() line-%d: " format, \
25           ALIAS_NAME, __func__, __LINE__, ## args)
26 #define RTFLED_ERR(format, args...) \
27         pr_err("%s:%s() line-%d: " format, \
28           ALIAS_NAME, __func__, __LINE__, ## args)
29
30 #define RT_FLED_DEVICE  "rt-flash-led"
31 #define ALIAS_NAME RT_FLED_DEVICE
32
33 rt_fled_info_t *rt_fled_get_info_by_name(char *name)
34 {
35         struct flashlight_device *flashlight_dev;
36
37         flashlight_dev = find_flashlight_by_name(name ? name : RT_FLED_DEVICE);
38         if (flashlight_dev == NULL)
39                 return (rt_fled_info_t *) NULL;
40         return flashlight_get_data(flashlight_dev);
41 }
42 EXPORT_SYMBOL(rt_fled_get_info_by_name);
43
44 static int rtfled_set_torch_brightness(struct flashlight_device *flashlight_dev,
45                                        int brightness_sel)
46 {
47         rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
48
49         return info->hal->fled_set_torch_current_sel(info, brightness_sel);
50 }
51
52 static int rtfled_set_strobe_brightness(struct flashlight_device
53                                         *flashlight_dev, int brightness_sel)
54 {
55         rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
56
57         return info->hal->fled_set_strobe_current_sel(info, brightness_sel);
58 }
59
60 static int rtfled_set_strobe_timeout(struct flashlight_device *flashlight_dev,
61                                      int timeout)
62 {
63         rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
64
65         int sel;
66
67         return info->hal->fled_set_strobe_timeout(info, timeout, timeout, &sel);
68 }
69
70 static int rtfled_list_strobe_timeout(struct flashlight_device *flashlight_dev,
71                                       int selector)
72 {
73         rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
74
75         return info->hal->fled_strobe_timeout_list(info, selector);
76 }
77
78 static int rtfled_set_mode(struct flashlight_device *flashlight_dev, int mode)
79 {
80         rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
81
82         return info->hal->fled_set_mode(info, mode);
83 }
84
85 static int rtfled_strobe(struct flashlight_device *flashlight_dev)
86 {
87         rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
88
89         return info->hal->fled_strobe(info);
90 }
91
92 static int rtfled_set_color_temperature(struct flashlight_device
93                                         *flashlight_dev, int color_temp)
94 {
95         /* Doesn't support color temperature */
96         return -EINVAL;
97 }
98
99 static int rtfled_list_color_temperature(struct flashlight_device
100                                          *flashlight_dev, int selector)
101 {
102         /* Doesn't support color temperature */
103         return -EINVAL;
104 }
105
106 static int rtfled_suspend(struct flashlight_device *flashlight_dev,
107                           pm_message_t state)
108 {
109         rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
110
111         if (info->hal->fled_suspend)
112                 return info->hal->fled_suspend(info, state);
113         return 0;
114 }
115
116 static int rtfled_resume(struct flashlight_device *flashlight_dev)
117 {
118         rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
119
120         if (info->hal->fled_resume)
121                 return info->hal->fled_resume(info);
122         return 0;
123 }
124
125 static struct flashlight_ops rtfled_impl_ops = {
126         .set_torch_brightness = rtfled_set_torch_brightness,
127         .set_strobe_brightness = rtfled_set_strobe_brightness,
128         .set_strobe_timeout = rtfled_set_strobe_timeout,
129         .list_strobe_timeout = rtfled_list_strobe_timeout,
130         .set_mode = rtfled_set_mode,
131         .strobe = rtfled_strobe,
132         .set_color_temperature = rtfled_set_color_temperature,
133         .list_color_temperature = rtfled_list_color_temperature,
134         .suspend = rtfled_suspend,
135         .resume = rtfled_resume,
136 };
137
138 static void rfled_shutdown(struct platform_device *pdev)
139 {
140         struct rt_fled_info *info = platform_get_drvdata(pdev);
141
142         if (info->hal->fled_shutdown)
143                 info->hal->fled_shutdown(info);
144 }
145
146 static int rtled_impl_set_torch_current(struct rt_fled_info *info,
147                                         int min_uA, int max_uA, int *selector)
148 {
149         int sel = 0;
150         int rc;
151
152         for (sel = 0;; sel++) {
153                 rc = info->hal->fled_torch_current_list(info, sel);
154                 if (rc < 0)
155                         return rc;
156                 if (rc >= min_uA && rc <= max_uA) {
157                         *selector = sel;
158                         return info->hal->fled_set_torch_current_sel(info, sel);
159                 }
160         }
161         return -EINVAL;
162 }
163
164 static int rtled_impl_set_strobe_current(struct rt_fled_info *info,
165                                          int min_uA, int max_uA, int *selector)
166 {
167         int sel = 0;
168         int rc;
169
170         for (sel = 0;; sel++) {
171                 rc = info->hal->fled_strobe_current_list(info, sel);
172                 if (rc < 0)
173                         return rc;
174                 if (rc >= min_uA && rc <= max_uA) {
175                         *selector = sel;
176                         return info->hal->fled_set_strobe_current_sel(info,
177                                                                       sel);
178                 }
179         }
180         return -EINVAL;
181 }
182
183 static int rtled_impl_set_timeout_level(struct rt_fled_info *info,
184                                         int min_uA, int max_uA, int *selector)
185 {
186         int sel = 0;
187         int rc;
188
189         for (sel = 0;; sel++) {
190                 rc = info->hal->fled_timeout_level_list(info, sel);
191                 if (rc < 0)
192                         return rc;
193                 if (rc >= min_uA && rc <= max_uA) {
194                         *selector = sel;
195                         return info->hal->fled_set_timeout_level_sel(info, sel);
196                 }
197         }
198         return -EINVAL;
199 }
200
201 static int rtled_impl_set_lv_protection(struct rt_fled_info *info,
202                                         int min_mV, int max_mV, int *selector)
203 {
204         int sel = 0;
205         int rc;
206
207         for (sel = 0;; sel++) {
208                 rc = info->hal->fled_lv_protection_list(info, sel);
209                 if (rc < 0)
210                         return rc;
211                 if (rc >= min_mV && rc <= max_mV) {
212                         *selector = sel;
213                         return info->hal->fled_set_lv_protection_sel(info, sel);
214                 }
215         }
216         return -EINVAL;
217 }
218
219 static int rtled_impl_set_strobe_timeout(struct rt_fled_info *info,
220                                          int min_ms, int max_ms, int *selector)
221 {
222         int sel = 0;
223         int rc;
224
225         for (sel = 0;; sel++) {
226                 rc = info->hal->fled_strobe_timeout_list(info, sel);
227                 if (rc < 0)
228                         return rc;
229                 if (rc >= min_ms && rc <= max_ms) {
230                         *selector = sel;
231                         return info->hal->fled_set_strobe_timeout_sel(info,
232                                                                       sel);
233                 }
234         }
235         return -EINVAL;
236 }
237
238 static int rtled_impl_get_torch_current(struct rt_fled_info *info)
239 {
240         int sel = info->hal->fled_get_torch_current_sel(info);
241
242         if (sel < 0)
243                 return sel;
244         return info->hal->fled_torch_current_list(info, sel);
245 }
246
247 static int rtled_impl_get_strobe_current(struct rt_fled_info *info)
248 {
249         int sel = info->hal->fled_get_strobe_current_sel(info);
250
251         if (sel < 0)
252                 return sel;
253         return info->hal->fled_strobe_current_list(info, sel);
254 }
255
256 static int rtled_impl_get_timeout_level(struct rt_fled_info *info)
257 {
258         int sel = info->hal->fled_get_timeout_level_sel(info);
259
260         if (sel < 0)
261                 return sel;
262         return info->hal->fled_timeout_level_list(info, sel);
263 }
264
265 static int rtled_impl_get_lv_protection(struct rt_fled_info *info)
266 {
267         int sel = info->hal->fled_get_lv_protection_sel(info);
268
269         if (sel < 0)
270                 return sel;
271         return info->hal->fled_lv_protection_list(info, sel);
272 }
273
274 static int rtled_impl_get_strobe_timeout(struct rt_fled_info *info)
275 {
276         int sel = info->hal->fled_get_strobe_timeout_sel(info);
277
278         if (sel < 0)
279                 return sel;
280         return info->hal->fled_strobe_timeout_list(info, sel);
281 }
282
283 #define HAL_NOT_IMPLEMENTED(x) (hal->x == NULL)
284 #define CHECK_HAL_IMPLEMENTED(x)        \
285         do {                            \
286                 if (hal->x == NULL)     \
287                         return -EINVAL; \
288         } while (0)
289
290 static int rtfled_check_hal_implement(struct rt_fled_hal *hal)
291 {
292         if (HAL_NOT_IMPLEMENTED(fled_set_torch_current))
293                 hal->fled_set_torch_current = rtled_impl_set_torch_current;
294         if (HAL_NOT_IMPLEMENTED(fled_set_strobe_current))
295                 hal->fled_set_strobe_current = rtled_impl_set_strobe_current;
296         if (HAL_NOT_IMPLEMENTED(fled_set_timeout_level))
297                 hal->fled_set_timeout_level = rtled_impl_set_timeout_level;
298         if (HAL_NOT_IMPLEMENTED(fled_set_lv_protection))
299                 hal->fled_set_lv_protection = rtled_impl_set_lv_protection;
300         if (HAL_NOT_IMPLEMENTED(fled_set_strobe_timeout))
301                 hal->fled_set_strobe_timeout = rtled_impl_set_strobe_timeout;
302         if (HAL_NOT_IMPLEMENTED(fled_get_torch_current))
303                 hal->fled_get_torch_current = rtled_impl_get_torch_current;
304         if (HAL_NOT_IMPLEMENTED(fled_get_strobe_current))
305                 hal->fled_get_strobe_current = rtled_impl_get_strobe_current;
306         if (HAL_NOT_IMPLEMENTED(fled_get_timeout_level))
307                 hal->fled_get_timeout_level = rtled_impl_get_timeout_level;
308         if (HAL_NOT_IMPLEMENTED(fled_get_lv_protection))
309                 hal->fled_get_lv_protection = rtled_impl_get_lv_protection;
310         if (HAL_NOT_IMPLEMENTED(fled_get_strobe_timeout))
311                 hal->fled_get_strobe_timeout = rtled_impl_get_strobe_timeout;
312         CHECK_HAL_IMPLEMENTED(fled_set_mode);
313         CHECK_HAL_IMPLEMENTED(fled_get_mode);
314         CHECK_HAL_IMPLEMENTED(fled_strobe);
315         CHECK_HAL_IMPLEMENTED(fled_torch_current_list);
316         CHECK_HAL_IMPLEMENTED(fled_strobe_current_list);
317         CHECK_HAL_IMPLEMENTED(fled_timeout_level_list);
318         CHECK_HAL_IMPLEMENTED(fled_lv_protection_list);
319         CHECK_HAL_IMPLEMENTED(fled_strobe_timeout_list);
320         CHECK_HAL_IMPLEMENTED(fled_set_torch_current_sel);
321         CHECK_HAL_IMPLEMENTED(fled_set_strobe_current_sel);
322         CHECK_HAL_IMPLEMENTED(fled_set_timeout_level_sel);
323         CHECK_HAL_IMPLEMENTED(fled_set_lv_protection_sel);
324         CHECK_HAL_IMPLEMENTED(fled_set_strobe_timeout_sel);
325         CHECK_HAL_IMPLEMENTED(fled_get_torch_current_sel);
326         CHECK_HAL_IMPLEMENTED(fled_get_strobe_current_sel);
327         CHECK_HAL_IMPLEMENTED(fled_get_timeout_level_sel);
328         CHECK_HAL_IMPLEMENTED(fled_get_lv_protection_sel);
329         CHECK_HAL_IMPLEMENTED(fled_get_strobe_timeout_sel);
330         return 0;
331 }
332
333 static int rtfled_probe(struct platform_device *pdev)
334 {
335         rt_fled_info_t *info = dev_get_drvdata(pdev->dev.parent);
336         int rc;
337
338         BUG_ON(info == NULL);
339         BUG_ON(info->hal == NULL);
340
341         RTFLED_INFO("Richtek FlashLED Driver is probing\n");
342         rc = rtfled_check_hal_implement(info->hal);
343         if (rc < 0) {
344                 RTFLED_ERR("HAL implemented uncompletedly\n");
345                 goto err_check_hal;
346         }
347         platform_set_drvdata(pdev, info);
348         info->flashlight_dev =
349             flashlight_device_register(info->name ? info->name : RT_FLED_DEVICE,
350                                        &pdev->dev, info, &rtfled_impl_ops,
351                                        info->init_props);
352         if (info->hal->fled_init) {
353                 rc = info->hal->fled_init(info);
354                 if (rc < 0) {
355                         RTFLED_ERR("Initialization failed\n");
356                         goto err_init;
357                 }
358         }
359         RTFLED_INFO("Richtek FlashLED Driver initialized successfully\n");
360         return 0;
361 err_init:
362         flashlight_device_unregister(info->flashlight_dev);
363 err_check_hal:
364         return rc;
365 }
366
367 static int rtfled_remove(struct platform_device *pdev)
368 {
369         rt_fled_info_t *info = platform_get_drvdata(pdev);
370
371         platform_set_drvdata(pdev, NULL);
372         flashlight_device_unregister(info->flashlight_dev);
373         return 0;
374 }
375
376 static struct platform_driver rt_flash_led_driver = {
377         .driver = {
378                    .name = RT_FLED_DEVICE,
379                    .owner = THIS_MODULE,
380                    },
381         .shutdown = rfled_shutdown,
382         .probe = rtfled_probe,
383         .remove = rtfled_remove,
384 };
385
386 static int rtfled_init(void)
387 {
388         return platform_driver_register(&rt_flash_led_driver);
389 }
390 subsys_initcall(rtfled_init);
391
392 static void rtfled_exit(void)
393 {
394         platform_driver_unregister(&rt_flash_led_driver);
395 }
396 module_exit(rtfled_exit);
397
398 MODULE_LICENSE("GPL");
399 MODULE_AUTHOR("Patrick Chang <patrick_chang@richtek.com");
400 MODULE_VERSION("1.0.0_G");
401 MODULE_DESCRIPTION("Richtek Flash LED Driver");