1 /* drivers/leds/rtfled.c
2 * Richtek Flash LED Universal Architecture
4 * Copyright (C) 2013 Richtek Technology Corp.
5 * Author: Patrick Chang <patrick_chang@richtek.com>
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.
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>
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)
30 #define RT_FLED_DEVICE "rt-flash-led"
31 #define ALIAS_NAME RT_FLED_DEVICE
35 rt_fled_info_t *rt_fled_get_info_by_name(char *name)
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);
43 EXPORT_SYMBOL(rt_fled_get_info_by_name);
46 static int rtfled_set_torch_brightness(struct flashlight_device *flashlight_dev,
49 rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
50 return info->hal->fled_set_torch_current_sel(info, brightness_sel);
53 static int rtfled_set_strobe_brightness(struct flashlight_device
57 rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
58 return info->hal->fled_set_strobe_current_sel(info, brightness_sel);
61 static int rtfled_set_strobe_timeout(struct flashlight_device *flashlight_dev,
64 rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
67 return info->hal->fled_set_strobe_timeout(info, timeout,
71 static int rtfled_list_strobe_timeout(struct flashlight_device *flashlight_dev,
74 rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
75 return info->hal->fled_strobe_timeout_list(info, selector);
78 static int rtfled_set_mode(struct flashlight_device *flashlight_dev, int mode)
80 rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
81 return info->hal->fled_set_mode(info, mode);
84 static int rtfled_strobe(struct flashlight_device *flashlight_dev)
86 rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
87 return info->hal->fled_strobe(info);
90 static int rtfled_set_color_temperature(struct flashlight_device
94 /* Doesn't support color temperature */
98 static int rtfled_list_color_temperature(struct flashlight_device
102 /* Doesn't support color temperature */
105 static int rtfled_suspend(struct flashlight_device *flashlight_dev,
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);
113 static int rtfled_resume(struct flashlight_device *flashlight_dev)
115 rt_fled_info_t *info = flashlight_get_data(flashlight_dev);
116 if (info->hal->fled_resume)
117 return info->hal->fled_resume(info);
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,
135 static void rfled_shutdown(struct platform_device *pdev)
137 struct rt_fled_info *info = platform_get_drvdata(pdev);
138 if (info->hal->fled_shutdown)
139 info->hal->fled_shutdown(info);
142 static int rtled_impl_set_torch_current(struct rt_fled_info *info,
143 int min_uA, int max_uA, int *selector)
147 for (sel = 0; ; sel++) {
148 rc = info->hal->fled_troch_current_list(info, sel);
151 if (rc >= min_uA && rc <= max_uA) {
153 return info->hal->fled_set_torch_current_sel(info, sel);
159 static int rtled_impl_set_strobe_current(struct rt_fled_info *info,
160 int min_uA, int max_uA, int *selector)
164 for (sel = 0; ; sel++) {
165 rc = info->hal->fled_strobe_current_list(info, sel);
168 if (rc >= min_uA && rc <= max_uA) {
170 return info->hal->fled_set_strobe_current_sel(info, sel);
176 static int rtled_impl_set_timeout_level(struct rt_fled_info *info,
177 int min_uA, int max_uA, int *selector)
181 for (sel = 0; ; sel++) {
182 rc = info->hal->fled_timeout_level_list(info, sel);
185 if (rc >= min_uA && rc <= max_uA) {
187 return info->hal->fled_set_timeout_level_sel(info, sel);
193 static int rtled_impl_set_lv_protection(struct rt_fled_info *info,
194 int min_mV, int max_mV, int *selector)
198 for (sel = 0; ; sel++) {
199 rc = info->hal->fled_lv_protection_list(info, sel);
202 if (rc >= min_mV && rc <= max_mV) {
204 return info->hal->fled_set_lv_protection_sel(info, sel);
210 static int rtled_impl_set_strobe_timeout(struct rt_fled_info *info,
211 int min_ms, int max_ms, int *selector)
215 for (sel = 0; ; sel++) {
216 rc = info->hal->fled_strobe_timeout_list(info, sel);
219 if (rc >= min_ms && rc <= max_ms) {
221 return info->hal->fled_set_strobe_timeout_sel(info, sel);
227 static int rtled_impl_get_torch_current(struct rt_fled_info *info)
229 int sel = info->hal->fled_get_torch_current_sel(info);
232 return info->hal->fled_troch_current_list(info, sel);
235 static int rtled_impl_get_strobe_current(struct rt_fled_info *info)
237 int sel = info->hal->fled_get_strobe_current_sel(info);
240 return info->hal->fled_strobe_current_list(info, sel);
243 static int rtled_impl_get_timeout_level(struct rt_fled_info *info)
245 int sel = info->hal->fled_get_timeout_level_sel(info);
248 return info->hal->fled_timeout_level_list(info, sel);
251 static int rtled_impl_get_lv_protection(struct rt_fled_info *info)
253 int sel = info->hal->fled_get_lv_protection_sel(info);
256 return info->hal->fled_lv_protection_list(info, sel);
259 static int rtled_impl_get_strobe_timeout(struct rt_fled_info *info)
261 int sel = info->hal->fled_get_strobe_timeout_sel(info);
264 return info->hal->fled_strobe_timeout_list(info, sel);
267 #define HAL_NOT_IMPLEMENTED(x) (hal->x == NULL)
268 #define CHECK_HAL_IMPLEMENTED(x) if (hal->x == NULL) return -EINVAL
270 static int rtfled_check_hal_implement(struct rt_fled_hal *hal)
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);
314 static int rtfled_probe(struct platform_device *pdev)
316 rt_fled_info_t *info = dev_get_drvdata(pdev->dev.parent);
318 BUG_ON(info == NULL);
319 BUG_ON(info->hal == NULL);
321 RTFLED_INFO("Richtek FlashLED Driver is probing\n");
322 rc = rtfled_check_hal_implement(info->hal);
324 RTFLED_ERR("HAL implemented incompletely\n");
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,
332 if (info->hal->fled_init) {
333 rc = info->hal->fled_init(info);
335 RTFLED_ERR("Initialization failed\n");
339 RTFLED_INFO("Richtek FlashLED Driver initialized successfully\n");
342 flashlight_device_unregister(info->flashlight_dev);
347 static int rtfled_remove(struct platform_device *pdev)
349 rt_fled_info_t *info = platform_get_drvdata(pdev);
350 platform_set_drvdata(pdev, NULL);
351 flashlight_device_unregister(info->flashlight_dev);
355 static struct platform_driver rt_flash_led_driver = {
357 .name = RT_FLED_DEVICE,
358 .owner = THIS_MODULE,
360 .shutdown = rfled_shutdown,
361 .probe = rtfled_probe,
362 .remove = rtfled_remove,
365 static int __init rtfled_init(void)
367 return platform_driver_register(&rt_flash_led_driver);
369 subsys_initcall(rtfled_init);
371 static void __exit rtfled_exit(void)
373 platform_driver_unregister(&rt_flash_led_driver);
375 module_exit(rtfled_exit);
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");