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 struct class *flashlight_class;
22 static int flashlight_suspend(struct device *dev, pm_message_t state)
24 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
26 if (flashlight_dev->ops)
27 flashlight_dev->ops->suspend(flashlight_dev, state);
31 static int flashlight_resume(struct device *dev)
33 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
35 if (flashlight_dev->ops)
36 flashlight_dev->ops->resume(flashlight_dev);
40 static void flashlight_device_release(struct device *dev)
42 struct flashlight_device *flashlight_dev = to_flashlight_device(dev);
44 kfree(flashlight_dev);
48 * flashlight_device_register - create and register a new object of
49 * flashlight_device class.
50 * @name: the name of the new object(must be the same as the name of the
51 * respective framebuffer device).
52 * @parent: a pointer to the parent device
53 * @devdata: an optional pointer to be stored for private driver use. The
54 * methods may retrieve it by using bl_get_data(flashlight_dev).
55 * @ops: the flashlight operations structure.
57 * Creates and registers new flashlight device. Returns either an
58 * ERR_PTR() or a pointer to the newly allocated device.
60 struct flashlight_device *flashlight_device_register(const char *name,
61 struct device *parent,
63 const struct flashlight_ops
69 struct flashlight_device *flashlight_dev;
72 pr_debug("flashlight_device_register: name=%s\n", name);
73 flashlight_dev = kzalloc(sizeof(*flashlight_dev), GFP_KERNEL);
75 return ERR_PTR(-ENOMEM);
77 mutex_init(&flashlight_dev->ops_lock);
78 flashlight_dev->dev.class = flashlight_class;
79 flashlight_dev->dev.parent = parent;
80 flashlight_dev->dev.release = flashlight_device_release;
81 dev_set_name(&flashlight_dev->dev, name);
82 dev_set_drvdata(&flashlight_dev->dev, devdata);
85 memcpy(&flashlight_dev->props, props,
86 sizeof(struct flashlight_properties));
88 rc = device_register(&flashlight_dev->dev);
90 kfree(flashlight_dev);
93 flashlight_dev->ops = ops;
94 return flashlight_dev;
96 EXPORT_SYMBOL(flashlight_device_register);
99 * flashlight_device_unregister - unregisters a flashlight device object.
100 * @flashlight_dev: the flashlight device object to be unregistered and freed.
102 * Unregisters a previously registered via flashlight_device_register object.
104 void flashlight_device_unregister(struct flashlight_device *flashlight_dev)
109 mutex_lock(&flashlight_dev->ops_lock);
110 flashlight_dev->ops = NULL;
111 mutex_unlock(&flashlight_dev->ops_lock);
112 device_unregister(&flashlight_dev->dev);
114 EXPORT_SYMBOL(flashlight_device_unregister);
116 int flashlight_list_color_temperature(struct flashlight_device *flashlight_dev,
119 if (flashlight_dev->ops && flashlight_dev->ops->list_color_temperature)
120 return flashlight_dev->ops->
121 list_color_temperature(flashlight_dev, selector);
124 EXPORT_SYMBOL(flashlight_list_color_temperature);
126 int flashlight_set_color_temperature(struct flashlight_device *flashlight_dev,
132 if ((flashlight_dev->ops == NULL) ||
133 (flashlight_dev->ops->set_color_temperature == NULL))
135 for (selector = 0;; selector++) {
136 rc = flashlight_list_color_temperature(flashlight_dev,
140 if (rc >= minK && rc <= maxK) {
141 mutex_lock(&flashlight_dev->ops_lock);
142 rc = flashlight_dev->ops->
143 set_color_temperature(flashlight_dev, rc);
144 mutex_unlock(&flashlight_dev->ops_lock);
146 flashlight_dev->props.color_temperature = rc;
153 EXPORT_SYMBOL(flashlight_set_color_temperature);
155 int flashlight_set_torch_brightness(struct flashlight_device *flashlight_dev,
156 int brightness_level)
160 if ((flashlight_dev->ops == NULL) ||
161 (flashlight_dev->ops->set_torch_brightness == NULL))
163 if (brightness_level > flashlight_dev->props.torch_max_brightness)
165 mutex_lock(&flashlight_dev->ops_lock);
166 rc = flashlight_dev->ops->set_torch_brightness(flashlight_dev,
168 mutex_unlock(&flashlight_dev->ops_lock);
171 flashlight_dev->props.torch_brightness = brightness_level;
175 EXPORT_SYMBOL(flashlight_set_torch_brightness);
177 int flashlight_set_strobe_brightness(struct flashlight_device *flashlight_dev,
178 int brightness_level)
182 if ((flashlight_dev->ops == NULL) ||
183 (flashlight_dev->ops->set_strobe_brightness == NULL))
185 if (brightness_level > flashlight_dev->props.strobe_max_brightness)
187 mutex_lock(&flashlight_dev->ops_lock);
188 rc = flashlight_dev->ops->set_strobe_brightness(flashlight_dev,
190 mutex_unlock(&flashlight_dev->ops_lock);
193 flashlight_dev->props.strobe_brightness = brightness_level;
196 EXPORT_SYMBOL(flashlight_set_strobe_brightness);
198 int flashlight_list_strobe_timeout(struct flashlight_device *flashlight_dev,
201 if (flashlight_dev->ops && flashlight_dev->ops->list_strobe_timeout) {
202 return flashlight_dev->ops->list_strobe_timeout(flashlight_dev,
207 EXPORT_SYMBOL(flashlight_list_strobe_timeout);
209 int flashlight_set_strobe_timeout(struct flashlight_device *flashlight_dev,
210 int min_ms, int max_ms)
216 if ((flashlight_dev->ops == NULL) ||
217 (flashlight_dev->ops->set_strobe_timeout == NULL))
219 for (selector = 0;; selector++) {
221 flashlight_list_strobe_timeout(flashlight_dev, selector);
224 if (timeout >= min_ms && timeout <= max_ms) {
225 mutex_lock(&flashlight_dev->ops_lock);
226 rc = flashlight_dev->ops->
227 set_strobe_timeout(flashlight_dev, timeout);
228 mutex_unlock(&flashlight_dev->ops_lock);
230 flashlight_dev->props.strobe_timeout = timeout;
236 EXPORT_SYMBOL(flashlight_set_strobe_timeout);
238 int flashlight_set_mode(struct flashlight_device *flashlight_dev, int mode)
242 if (mode >= FLASHLIGHT_MODE_MAX || mode < 0)
244 if ((flashlight_dev->ops == NULL) ||
245 (flashlight_dev->ops->set_mode == NULL)) {
246 flashlight_dev->props.mode = mode;
249 mutex_lock(&flashlight_dev->ops_lock);
250 rc = flashlight_dev->ops->set_mode(flashlight_dev, mode);
251 mutex_unlock(&flashlight_dev->ops_lock);
254 flashlight_dev->props.mode = mode;
257 EXPORT_SYMBOL(flashlight_set_mode);
259 int flashlight_strobe(struct flashlight_device *flashlight_dev)
261 if (flashlight_dev->props.mode == FLASHLIGHT_MODE_FLASH
262 || flashlight_dev->props.mode == FLASHLIGHT_MODE_MIXED) {
263 if (flashlight_dev->ops == NULL ||
264 flashlight_dev->ops->strobe == NULL)
266 return flashlight_dev->ops->strobe(flashlight_dev);
270 EXPORT_SYMBOL(flashlight_strobe);
272 static int flashlight_match_device_by_name(struct device *dev, const void *data)
274 const char *name = data;
276 return strcmp(dev_name(dev), name) == 0;
279 struct flashlight_device *find_flashlight_by_name(char *name)
284 return (struct flashlight_device *)NULL;
285 dev = class_find_device(flashlight_class, NULL, (void*)name,
286 flashlight_match_device_by_name);
288 return dev ? to_flashlight_device(dev) : NULL;
291 EXPORT_SYMBOL(find_flashlight_by_name);
293 int flashlight_strobe_charge(struct flashlight_device *flashlight_dev,
294 flashlight_charge_event_cb cb, void *data,
298 if (flashlight_dev->ops->strobe_charge)
299 return flashlight_dev->ops->strobe_charge(flashlight_dev,
301 if (flashlight_dev->props.type == FLASHLIGHT_TYPE_LED) {
308 EXPORT_SYMBOL(flashlight_strobe_charge);
310 static void __exit flashlight_class_exit(void)
312 class_destroy(flashlight_class);
315 static int __init flashlight_class_init(void)
317 flashlight_class = class_create(THIS_MODULE, "flashlight");
318 if (IS_ERR(flashlight_class)) {
320 "Unable to create flashlight class; errno = %ld\n",
321 PTR_ERR(flashlight_class));
322 return PTR_ERR(flashlight_class);
325 flashlight_class->suspend = flashlight_suspend;
326 flashlight_class->resume = flashlight_resume;
329 subsys_initcall(flashlight_class_init);
330 module_exit(flashlight_class_exit);
332 MODULE_DESCRIPTION("Flashlight Class Device");
333 MODULE_AUTHOR("Patrick Chang <patrick_chang@richtek.com>");
334 MODULE_VERSION("1.0.0_G");
335 MODULE_LICENSE("GPL");