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