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 "flashlight.h"
16 #include <linux/ctype.h>
17 #include <linux/err.h>
18 #include <linux/slab.h>
20 static const char const *flashlight_type_string[] = {
21 [FLASHLIGHT_TYPE_XENON] = "Xenon",
22 [FLASHLIGHT_TYPE_LED] = "LED",
23 [FLASHLIFHT_TYPE_BULB] = "Bulb",
26 static const char const *flashlight_mode_string[] = {
27 [FLASHLIGHT_MODE_OFF] = "Off",
28 [FLASHLIGHT_MODE_TORCH] = "Torch",
29 [FLASHLIGHT_MODE_FLASH] = "Flash",
30 [FLASHLIGHT_MODE_MIXED] = "Mixed",
33 static ssize_t flashlight_show_name(struct device *dev,
34 struct device_attribute *attr, char *buf)
36 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);
48 return sprintf(buf, "%s\n",
49 flashlight_type_string[flashlight_dev->props.type]);
52 static ssize_t flashlight_show_mode(struct device *dev,
53 struct device_attribute *attr, char *buf)
55 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
57 return sprintf(buf, "%s\n",
58 flashlight_mode_string[flashlight_dev->props.mode]);
61 static ssize_t flashlight_show_torch_max_brightness(struct device *dev,
62 struct device_attribute
65 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
67 return sprintf(buf, "%d\n", flashlight_dev->props.torch_max_brightness);
70 static ssize_t flashlight_show_strobe_max_brightness(struct device *dev,
71 struct device_attribute
74 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
76 return sprintf(buf, "%d\n",
77 flashlight_dev->props.strobe_max_brightness);
80 static ssize_t flashlight_show_color_temperature(struct device *dev,
81 struct device_attribute *attr,
84 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
86 return sprintf(buf, "%d\n", flashlight_dev->props.color_temperature);
89 static ssize_t flashlight_show_strobe_delay(struct device *dev,
90 struct device_attribute *attr,
93 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
95 return sprintf(buf, "%d\n", flashlight_dev->props.strobe_delay);
98 static ssize_t flashlight_store_strobe_timeout(struct device *dev,
99 struct device_attribute *attr,
100 const char *buf, size_t count)
103 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
106 rc = kstrtol(buf, 0, &timeout);
109 rc = flashlight_dev->ops->set_strobe_timeout(flashlight_dev, timeout);
115 static ssize_t flashlight_show_strobe_timeout(struct device *dev,
116 struct device_attribute *attr,
119 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
121 return sprintf(buf, "%d\n", flashlight_dev->props.strobe_timeout);
124 static ssize_t flashlight_store_torch_brightness(struct device *dev,
125 struct device_attribute *attr,
126 const char *buf, size_t count)
129 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
132 rc = kstrtol(buf, 0, &brightness);
138 mutex_lock(&flashlight_dev->ops_lock);
139 if (flashlight_dev->ops && flashlight_dev->ops->set_torch_brightness) {
140 if (brightness > flashlight_dev->props.torch_max_brightness)
143 pr_debug("flashlight: set torch brightness to %ld\n",
145 flashlight_dev->props.torch_brightness = brightness;
146 flashlight_dev->ops->
147 set_torch_brightness(flashlight_dev, brightness);
151 mutex_unlock(&flashlight_dev->ops_lock);
156 static ssize_t flashlight_show_torch_brightness(struct device *dev,
157 struct device_attribute *attr,
160 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
162 return sprintf(buf, "%d\n", flashlight_dev->props.torch_brightness);
165 static ssize_t flashlight_store_strobe_brightness(struct device *dev,
166 struct device_attribute *attr,
167 const char *buf, size_t count)
170 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
173 rc = kstrtol(buf, 0, &brightness);
179 mutex_lock(&flashlight_dev->ops_lock);
180 if (flashlight_dev->ops && flashlight_dev->ops->set_strobe_brightness) {
181 if (brightness > flashlight_dev->props.strobe_max_brightness)
184 pr_debug("flashlight: set strobe brightness to %ld\n",
186 flashlight_dev->props.strobe_brightness = brightness;
187 flashlight_dev->ops->
188 set_strobe_brightness(flashlight_dev, brightness);
192 mutex_unlock(&flashlight_dev->ops_lock);
196 static ssize_t flashlight_show_strobe_brightness(struct device *dev,
197 struct device_attribute *attr,
200 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
202 return sprintf(buf, "%d\n", flashlight_dev->props.strobe_brightness);
205 static struct class *flashlight_class;
207 static int flashlight_suspend(struct device *dev, pm_message_t state)
209 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
211 if (flashlight_dev->ops)
212 flashlight_dev->ops->suspend(flashlight_dev, state);
216 static int flashlight_resume(struct device *dev)
218 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
220 if (flashlight_dev->ops)
221 flashlight_dev->ops->resume(flashlight_dev);
225 static void flashlight_device_release(struct device *dev)
227 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
229 kfree(flashlight_dev);
232 static struct device_attribute flashlight_device_attributes[] = {
233 __ATTR(name, 0444, flashlight_show_name, NULL),
234 __ATTR(type, 0444, flashlight_show_type, NULL),
235 __ATTR(mode, 0444, flashlight_show_mode, NULL),
236 __ATTR(torch_max_brightness, 0444,
237 flashlight_show_torch_max_brightness, NULL),
238 __ATTR(strobe_max_brightness, 0444,
239 flashlight_show_strobe_max_brightness, NULL),
240 __ATTR(color_temperature, 0444,
241 flashlight_show_color_temperature, NULL),
242 __ATTR(strobe_delay, 0444,
243 flashlight_show_strobe_delay, NULL),
244 __ATTR(strobe_timeout, 0644,
245 flashlight_show_strobe_timeout,
246 flashlight_store_strobe_timeout),
247 __ATTR(torch_brightness, 0644,
248 flashlight_show_torch_brightness,
249 flashlight_store_torch_brightness),
250 __ATTR(strobe_brightness, 0644,
251 flashlight_show_strobe_brightness,
252 flashlight_store_strobe_brightness),
257 * flashlight_device_register - create and register a new object of
258 * flashlight_device class.
259 * @name: the name of the new object(must be the same as the name of the
260 * respective framebuffer device).
261 * @parent: a pointer to the parent device
262 * @devdata: an optional pointer to be stored for private driver use. The
263 * methods may retrieve it by using bl_get_data(flashlight_dev).
264 * @ops: the flashlight operations structure.
266 * Creates and registers new flashlight device. Returns either an
267 * ERR_PTR() or a pointer to the newly allocated device.
269 struct flashlight_device *flashlight_device_register(const char *name,
270 struct device *parent,
272 const struct flashlight_ops
275 flashlight_properties
278 struct flashlight_device *flashlight_dev;
281 pr_debug("flashlight_device_register: name=%s\n", name);
282 flashlight_dev = kzalloc(sizeof(*flashlight_dev), GFP_KERNEL);
284 return ERR_PTR(-ENOMEM);
286 mutex_init(&flashlight_dev->ops_lock);
287 flashlight_dev->dev.class = flashlight_class;
288 flashlight_dev->dev.parent = parent;
289 flashlight_dev->dev.release = flashlight_device_release;
290 dev_set_name(&flashlight_dev->dev, name);
291 dev_set_drvdata(&flashlight_dev->dev, devdata);
292 /* Copy properties */
294 memcpy(&flashlight_dev->props, props,
295 sizeof(struct flashlight_properties));
297 rc = device_register(&flashlight_dev->dev);
299 kfree(flashlight_dev);
302 flashlight_dev->ops = ops;
303 return flashlight_dev;
305 EXPORT_SYMBOL(flashlight_device_register);
308 * flashlight_device_unregister - unregisters a flashlight device object.
309 * @flashlight_dev: the flashlight device object to be unregistered and freed.
311 * Unregisters a previously registered via flashlight_device_register object.
313 void flashlight_device_unregister(struct flashlight_device *flashlight_dev)
318 mutex_lock(&flashlight_dev->ops_lock);
319 flashlight_dev->ops = NULL;
320 mutex_unlock(&flashlight_dev->ops_lock);
321 device_unregister(&flashlight_dev->dev);
323 EXPORT_SYMBOL(flashlight_device_unregister);
325 int flashlight_list_color_temperature(struct flashlight_device *flashlight_dev,
328 if (flashlight_dev->ops && flashlight_dev->ops->list_color_temperature)
329 return flashlight_dev->ops->
330 list_color_temperature(flashlight_dev, selector);
333 EXPORT_SYMBOL(flashlight_list_color_temperature);
335 int flashlight_set_color_temperature(struct flashlight_device *flashlight_dev,
341 if ((flashlight_dev->ops == NULL) ||
342 (flashlight_dev->ops->set_color_temperature == NULL))
344 for (selector = 0;; selector++) {
345 rc = flashlight_list_color_temperature(flashlight_dev,
349 if (rc >= minK && rc <= maxK) {
350 mutex_lock(&flashlight_dev->ops_lock);
351 rc = flashlight_dev->ops->
352 set_color_temperature(flashlight_dev, rc);
353 mutex_unlock(&flashlight_dev->ops_lock);
355 flashlight_dev->props.color_temperature = rc;
362 EXPORT_SYMBOL(flashlight_set_color_temperature);
364 int flashlight_set_torch_brightness(struct flashlight_device *flashlight_dev,
365 int brightness_level)
369 if ((flashlight_dev->ops == NULL) ||
370 (flashlight_dev->ops->set_torch_brightness == NULL))
372 if (brightness_level > flashlight_dev->props.torch_max_brightness)
374 mutex_lock(&flashlight_dev->ops_lock);
375 rc = flashlight_dev->ops->set_torch_brightness(flashlight_dev,
377 mutex_unlock(&flashlight_dev->ops_lock);
380 flashlight_dev->props.torch_brightness = brightness_level;
384 EXPORT_SYMBOL(flashlight_set_torch_brightness);
386 int flashlight_set_strobe_brightness(struct flashlight_device *flashlight_dev,
387 int brightness_level)
391 if ((flashlight_dev->ops == NULL) ||
392 (flashlight_dev->ops->set_strobe_brightness == NULL))
394 if (brightness_level > flashlight_dev->props.strobe_max_brightness)
396 mutex_lock(&flashlight_dev->ops_lock);
397 rc = flashlight_dev->ops->set_strobe_brightness(flashlight_dev,
399 mutex_unlock(&flashlight_dev->ops_lock);
402 flashlight_dev->props.strobe_brightness = brightness_level;
405 EXPORT_SYMBOL(flashlight_set_strobe_brightness);
407 int flashlight_list_strobe_timeout(struct flashlight_device *flashlight_dev,
410 if (flashlight_dev->ops && flashlight_dev->ops->list_strobe_timeout) {
411 return flashlight_dev->ops->list_strobe_timeout(flashlight_dev,
416 EXPORT_SYMBOL(flashlight_list_strobe_timeout);
418 int flashlight_set_strobe_timeout(struct flashlight_device *flashlight_dev,
419 int min_ms, int max_ms)
425 if ((flashlight_dev->ops == NULL) ||
426 (flashlight_dev->ops->set_strobe_timeout == NULL))
428 for (selector = 0;; selector++) {
430 flashlight_list_strobe_timeout(flashlight_dev, selector);
433 if (timeout >= min_ms && timeout <= max_ms) {
434 mutex_lock(&flashlight_dev->ops_lock);
435 rc = flashlight_dev->ops->
436 set_strobe_timeout(flashlight_dev, timeout);
437 mutex_unlock(&flashlight_dev->ops_lock);
439 flashlight_dev->props.strobe_timeout = timeout;
445 EXPORT_SYMBOL(flashlight_set_strobe_timeout);
447 int flashlight_set_mode(struct flashlight_device *flashlight_dev, int mode)
451 if (mode >= FLASHLIGHT_MODE_MAX || mode < 0)
453 if ((flashlight_dev->ops == NULL) ||
454 (flashlight_dev->ops->set_mode == NULL)) {
455 flashlight_dev->props.mode = mode;
458 mutex_lock(&flashlight_dev->ops_lock);
459 rc = flashlight_dev->ops->set_mode(flashlight_dev, mode);
460 mutex_unlock(&flashlight_dev->ops_lock);
463 flashlight_dev->props.mode = mode;
466 EXPORT_SYMBOL(flashlight_set_mode);
468 int flashlight_strobe(struct flashlight_device *flashlight_dev)
470 if (flashlight_dev->props.mode == FLASHLIGHT_MODE_FLASH
471 || flashlight_dev->props.mode == FLASHLIGHT_MODE_MIXED) {
472 if (flashlight_dev->ops == NULL ||
473 flashlight_dev->ops->strobe == NULL)
475 return flashlight_dev->ops->strobe(flashlight_dev);
479 EXPORT_SYMBOL(flashlight_strobe);
481 static int flashlight_match_device_by_name(struct device *dev, const void *data)
483 const char *name = data;
485 return strcmp(dev_name(dev), name) == 0;
488 struct flashlight_device *find_flashlight_by_name(char *name)
493 return (struct flashlight_device *)NULL;
494 dev = class_find_device(flashlight_class, NULL, (void*)name,
495 flashlight_match_device_by_name);
497 return dev ? to_flashlight_device(dev) : NULL;
500 EXPORT_SYMBOL(find_flashlight_by_name);
502 int flashlight_strobe_charge(struct flashlight_device *flashlight_dev,
503 flashlight_charge_event_cb cb, void *data,
507 if (flashlight_dev->ops->strobe_charge)
508 return flashlight_dev->ops->strobe_charge(flashlight_dev,
510 if (flashlight_dev->props.type == FLASHLIGHT_TYPE_LED) {
517 EXPORT_SYMBOL(flashlight_strobe_charge);
519 static void __exit flashlight_class_exit(void)
521 class_destroy(flashlight_class);
524 static int __init flashlight_class_init(void)
526 flashlight_class = class_create(THIS_MODULE, "flashlight");
527 if (IS_ERR(flashlight_class)) {
529 "Unable to create flashlight class; errno = %ld\n",
530 PTR_ERR(flashlight_class));
531 return PTR_ERR(flashlight_class);
533 flashlight_class->dev_attrs = flashlight_device_attributes;
534 flashlight_class->suspend = flashlight_suspend;
535 flashlight_class->resume = flashlight_resume;
538 subsys_initcall(flashlight_class_init);
539 module_exit(flashlight_class_exit);
541 MODULE_DESCRIPTION("Flashlight Class Device");
542 MODULE_AUTHOR("Patrick Chang <patrick_chang@richtek.com>");
543 MODULE_VERSION("1.0.0_G");
544 MODULE_LICENSE("GPL");