1 /* drivers/leds/flashlight.c
2 * Flashlight Class Device Driver
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/module.h>
14 #include <linux/init.h>
15 #include <linux/leds/flashlight.h>
16 #include <linux/ctype.h>
17 #include <linux/err.h>
18 #include <linux/slab.h>
19 #include <linux/regulator/consumer.h>
21 static const char const *flashlight_type_string[] = {
22 [FLASHLIGHT_TYPE_XENON] = "Xenon",
23 [FLASHLIGHT_TYPE_LED] = "LED",
24 [FLASHLIFHT_TYPE_BULB] = "Bulb",
27 static const char const *flashlight_mode_string[] = {
28 [FLASHLIGHT_MODE_OFF] = "Off",
29 [FLASHLIGHT_MODE_TORCH] = "Torch",
30 [FLASHLIGHT_MODE_FLASH] = "Flash",
31 [FLASHLIGHT_MODE_MIXED] = "Mixed",
34 static ssize_t flashlight_show_name(struct device *dev,
35 struct device_attribute *attr, char *buf)
37 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
38 return sprintf(buf, "%s\n",
39 flashlight_dev->props.alias_name ?
40 flashlight_dev->props.alias_name : "anonymous");
43 static ssize_t flashlight_show_type(struct device *dev,
44 struct device_attribute *attr, char *buf)
46 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
47 return sprintf(buf, "%s\n",
48 flashlight_type_string[flashlight_dev->props.type]);
51 static ssize_t flashlight_show_mode(struct device *dev,
52 struct device_attribute *attr, char *buf)
54 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
55 return sprintf(buf, "%s\n",
56 flashlight_mode_string[flashlight_dev->props.mode]);
59 static ssize_t flashlight_show_torch_max_brightness(struct device *dev,
60 struct device_attribute *attr, char *buf)
62 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
64 return sprintf(buf, "%d\n",
65 flashlight_dev->props.torch_max_brightness);
68 static ssize_t flashlight_show_strobe_max_brightness(struct device *dev,
69 struct device_attribute *attr, char *buf)
71 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
73 return sprintf(buf, "%d\n",
74 flashlight_dev->props.strobe_max_brightness);
77 static ssize_t flashlight_show_color_temperature(struct device *dev,
78 struct device_attribute *attr, char *buf)
80 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
82 return sprintf(buf, "%d\n",
83 flashlight_dev->props.color_temperature);
86 static ssize_t flashlight_show_strobe_delay(struct device *dev,
87 struct device_attribute *attr, char *buf)
89 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
91 return sprintf(buf, "%d\n",
92 flashlight_dev->props.strobe_delay);
95 static ssize_t flashlight_store_strobe_timeout(struct device *dev,
96 struct device_attribute *attr, const char *buf, size_t count)
99 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
102 rc = kstrtol(buf, 0, &timeout);
105 rc = flashlight_dev->ops->set_strobe_timeout(flashlight_dev, timeout);
111 static ssize_t flashlight_show_strobe_timeout(struct device *dev,
112 struct device_attribute *attr, char *buf)
114 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
115 return sprintf(buf, "%d\n",
116 flashlight_dev->props.strobe_timeout);
120 static ssize_t flashlight_store_torch_brightness(struct device *dev,
121 struct device_attribute *attr, const char *buf, size_t count)
124 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
127 rc = kstrtol(buf, 0, &brightness);
133 mutex_lock(&flashlight_dev->ops_lock);
134 if (flashlight_dev->ops &&
135 flashlight_dev->ops->set_torch_brightness) {
136 if (brightness > flashlight_dev->props.torch_max_brightness)
139 pr_debug("flashlight: set torch brightness to %ld\n",
141 flashlight_dev->props.torch_brightness = brightness;
142 flashlight_dev->ops->set_torch_brightness(
143 flashlight_dev, brightness);
147 mutex_unlock(&flashlight_dev->ops_lock);
152 static ssize_t flashlight_show_torch_brightness(struct device *dev,
153 struct device_attribute *attr, char *buf)
155 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
157 return sprintf(buf, "%d\n",
158 flashlight_dev->props.torch_brightness);
161 static ssize_t flashlight_store_strobe_brightness(struct device *dev,
162 struct device_attribute *attr, const char *buf, size_t count)
165 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
168 rc = kstrtol(buf, 0, &brightness);
174 mutex_lock(&flashlight_dev->ops_lock);
175 if (flashlight_dev->ops &&
176 flashlight_dev->ops->set_strobe_brightness) {
177 if (brightness > flashlight_dev->props.strobe_max_brightness)
180 pr_debug("flashlight: set strobe brightness to %ld\n",
182 flashlight_dev->props.strobe_brightness = brightness;
183 flashlight_dev->ops->set_strobe_brightness(
184 flashlight_dev, brightness);
188 mutex_unlock(&flashlight_dev->ops_lock);
192 static ssize_t flashlight_show_strobe_brightness(struct device *dev,
193 struct device_attribute *attr, char *buf)
195 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
197 return sprintf(buf, "%d\n",
198 flashlight_dev->props.strobe_brightness);
203 static struct class *flashlight_class;
205 static int flashlight_suspend(struct device *dev, pm_message_t state)
207 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
208 if (flashlight_dev->ops) {
209 flashlight_dev->ops->suspend(flashlight_dev, state);
214 static int flashlight_resume(struct device *dev)
216 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
217 if (flashlight_dev->ops) {
218 flashlight_dev->ops->resume(flashlight_dev);
223 static void flashlight_device_release(struct device *dev)
225 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
226 kfree(flashlight_dev);
229 static struct device_attribute flashlight_device_attributes[] = {
230 __ATTR(name, 0444, flashlight_show_name, NULL),
231 __ATTR(type, 0444, flashlight_show_type, NULL),
232 __ATTR(mode, 0444, flashlight_show_mode, NULL),
233 __ATTR(torch_max_brightness, 0444,
234 flashlight_show_torch_max_brightness, NULL),
235 __ATTR(strobe_max_brightness, 0444,
236 flashlight_show_strobe_max_brightness, NULL),
237 __ATTR(color_temperature, 0444,
238 flashlight_show_color_temperature, NULL),
239 __ATTR(strobe_delay, 0444,
240 flashlight_show_strobe_delay, NULL),
241 __ATTR(strobe_timeout, 0644,
242 flashlight_show_strobe_timeout,
243 flashlight_store_strobe_timeout),
244 __ATTR(torch_brightness, 0644,
245 flashlight_show_torch_brightness,
246 flashlight_store_torch_brightness),
247 __ATTR(strobe_brightness, 0644,
248 flashlight_show_strobe_brightness,
249 flashlight_store_strobe_brightness),
254 * flashlight_device_register - create and register a new object of
255 * flashlight_device class.
256 * @name: the name of the new object(must be the same as the name of the
257 * respective framebuffer device).
258 * @parent: a pointer to the parent device
259 * @devdata: an optional pointer to be stored for private driver use. The
260 * methods may retrieve it by using bl_get_data(flashlight_dev).
261 * @ops: the flashlight operations structure.
263 * Creates and registers new flashlight device. Returns either an
264 * ERR_PTR() or a pointer to the newly allocated device.
266 struct flashlight_device *flashlight_device_register(const char *name,
267 struct device *parent, void *devdata, const struct flashlight_ops *ops,
268 const struct flashlight_properties *props)
270 struct flashlight_device *flashlight_dev;
272 pr_debug("flashlight_device_register: name=%s\n", name);
273 flashlight_dev = kzalloc(sizeof(*flashlight_dev), GFP_KERNEL);
275 return ERR_PTR(-ENOMEM);
277 mutex_init(&flashlight_dev->ops_lock);
278 flashlight_dev->dev.class = flashlight_class;
279 flashlight_dev->dev.parent = parent;
280 flashlight_dev->dev.release = flashlight_device_release;
281 dev_set_name(&flashlight_dev->dev, name);
282 dev_set_drvdata(&flashlight_dev->dev, devdata);
283 /* Copy properties */
285 memcpy(&flashlight_dev->props, props,
286 sizeof(struct flashlight_properties));
288 rc = device_register(&flashlight_dev->dev);
290 kfree(flashlight_dev);
293 flashlight_dev->ops = ops;
294 return flashlight_dev;
296 EXPORT_SYMBOL(flashlight_device_register);
299 * flashlight_device_unregister - unregisters a flashlight device object.
300 * @flashlight_dev: the flashlight device object to be unregistered and freed.
302 * Unregisters a previously registered via flashlight_device_register object.
304 void flashlight_device_unregister(struct flashlight_device *flashlight_dev)
309 mutex_lock(&flashlight_dev->ops_lock);
310 flashlight_dev->ops = NULL;
311 mutex_unlock(&flashlight_dev->ops_lock);
312 device_unregister(&flashlight_dev->dev);
314 EXPORT_SYMBOL(flashlight_device_unregister);
316 int flashlight_list_color_temperature(
317 struct flashlight_device *flashlight_dev,
320 if (flashlight_dev->ops &&
321 flashlight_dev->ops->list_color_temperature) {
322 return flashlight_dev->ops->list_color_temperature(
328 EXPORT_SYMBOL(flashlight_list_color_temperature);
330 int flashlight_set_color_temperature(
331 struct flashlight_device *flashlight_dev,
337 if ((flashlight_dev->ops == NULL) ||
338 (flashlight_dev->ops->set_color_temperature == NULL))
340 for (selector = 0; ; selector++) {
341 rc = flashlight_list_color_temperature(flashlight_dev, selector);
344 if (rc >= minK && rc <= maxK) {
345 mutex_lock(&flashlight_dev->ops_lock);
346 rc = flashlight_dev->ops->set_color_temperature(
348 mutex_unlock(&flashlight_dev->ops_lock);
350 flashlight_dev->props.color_temperature = rc;
357 EXPORT_SYMBOL(flashlight_set_color_temperature);
359 int flashlight_set_torch_brightness(
360 struct flashlight_device *flashlight_dev,
361 int brightness_level)
364 if ((flashlight_dev->ops == NULL) ||
365 (flashlight_dev->ops->set_torch_brightness == NULL))
367 if (brightness_level > flashlight_dev->props.torch_max_brightness)
369 mutex_lock(&flashlight_dev->ops_lock);
370 rc = flashlight_dev->ops->set_torch_brightness(flashlight_dev,
372 mutex_unlock(&flashlight_dev->ops_lock);
375 flashlight_dev->props.torch_brightness = brightness_level;
379 EXPORT_SYMBOL(flashlight_set_torch_brightness);
381 int flashlight_set_strobe_brightness(
382 struct flashlight_device *flashlight_dev,
383 int brightness_level)
386 if ((flashlight_dev->ops == NULL) ||
387 (flashlight_dev->ops->set_strobe_brightness == NULL))
389 if (brightness_level > flashlight_dev->props.strobe_max_brightness)
391 mutex_lock(&flashlight_dev->ops_lock);
392 rc = flashlight_dev->ops->set_strobe_brightness(flashlight_dev,
394 mutex_unlock(&flashlight_dev->ops_lock);
397 flashlight_dev->props.strobe_brightness = brightness_level;
400 EXPORT_SYMBOL(flashlight_set_strobe_brightness);
402 int flashlight_list_strobe_timeout(
403 struct flashlight_device *flashlight_dev,
406 if (flashlight_dev->ops &&
407 flashlight_dev->ops->list_strobe_timeout) {
408 return flashlight_dev->ops->list_strobe_timeout(flashlight_dev,
413 EXPORT_SYMBOL(flashlight_list_strobe_timeout);
415 int flashlight_set_strobe_timeout(
416 struct flashlight_device *flashlight_dev,
417 int min_ms, int max_ms)
423 if ((flashlight_dev->ops == NULL) ||
424 (flashlight_dev->ops->set_strobe_timeout == NULL))
426 for (selector = 0; ; selector++) {
427 timeout = flashlight_list_strobe_timeout(flashlight_dev, selector);
430 if (timeout >= min_ms && timeout <= max_ms) {
431 mutex_lock(&flashlight_dev->ops_lock);
432 rc = flashlight_dev->ops->set_strobe_timeout(
433 flashlight_dev, timeout);
434 mutex_unlock(&flashlight_dev->ops_lock);
436 flashlight_dev->props.strobe_timeout = timeout;
442 EXPORT_SYMBOL(flashlight_set_strobe_timeout);
444 int flashlight_set_mode(struct flashlight_device *flashlight_dev,
448 if (mode >= FLASHLIGHT_MODE_MAX || mode < 0)
450 if ((flashlight_dev->ops == NULL) ||
451 (flashlight_dev->ops->set_mode == NULL)) {
452 flashlight_dev->props.mode = mode;
455 mutex_lock(&flashlight_dev->ops_lock);
456 rc = flashlight_dev->ops->set_mode(flashlight_dev,
458 mutex_unlock(&flashlight_dev->ops_lock);
461 flashlight_dev->props.mode = mode;
464 EXPORT_SYMBOL(flashlight_set_mode);
466 int flashlight_strobe(struct flashlight_device *flashlight_dev)
468 if (flashlight_dev->props.mode == FLASHLIGHT_MODE_FLASH
469 || flashlight_dev->props.mode == FLASHLIGHT_MODE_MIXED) {
470 if (flashlight_dev->ops == NULL ||
471 flashlight_dev->ops->strobe == NULL)
473 return flashlight_dev->ops->strobe(flashlight_dev);
477 EXPORT_SYMBOL(flashlight_strobe);
479 static int flashlight_match_device_by_name(struct device *dev, void *data)
481 const char *name = data;
482 return strcmp(dev_name(dev), name) == 0;
485 struct flashlight_device *find_flashlight_by_name(char *name)
489 return (struct flashlight_device *)NULL;
490 dev = class_find_device(flashlight_class, NULL, name,
491 flashlight_match_device_by_name);
493 return dev ? to_flashlight_device(dev) : NULL;
496 EXPORT_SYMBOL(find_flashlight_by_name);
498 int flashlight_strobe_charge(struct flashlight_device *flashlight_dev,
499 flashlight_charge_event_cb cb, void *data, int start)
502 if (flashlight_dev->ops->strobe_charge)
503 return flashlight_dev->ops->strobe_charge(flashlight_dev,
505 if (flashlight_dev->props.type == FLASHLIGHT_TYPE_LED) {
512 EXPORT_SYMBOL(flashlight_strobe_charge);
514 static void __exit flashlight_class_exit(void)
516 class_destroy(flashlight_class);
519 static int __init flashlight_class_init(void)
521 flashlight_class = class_create(THIS_MODULE, "flashlight");
522 if (IS_ERR(flashlight_class)) {
523 printk(KERN_WARNING "Unable to create flashlight class; errno = %ld\n",
524 PTR_ERR(flashlight_class));
525 return PTR_ERR(flashlight_class);
527 flashlight_class->dev_attrs = flashlight_device_attributes;
528 flashlight_class->suspend = flashlight_suspend;
529 flashlight_class->resume = flashlight_resume;
533 subsys_initcall(flashlight_class_init);
534 module_exit(flashlight_class_exit);
536 MODULE_DESCRIPTION("Flashlight Class Device");
537 MODULE_AUTHOR("Patrick Chang <patrick_chang@richtek.com>");
538 MODULE_VERSION("1.0.0_G");
539 MODULE_LICENSE("GPL");