• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *	LED Flash class driver for the AAT1290
3  *	1.5A Step-Up Current Regulator for Flash LEDs
4  *
5  *	Copyright (C) 2015, Samsung Electronics Co., Ltd.
6  *	Author: Jacek Anaszewski <j.anaszewski@samsung.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * version 2 as published by the Free Software Foundation.
11  */
12 
13 #include <linux/delay.h>
14 #include <linux/gpio/consumer.h>
15 #include <linux/led-class-flash.h>
16 #include <linux/leds.h>
17 #include <linux/module.h>
18 #include <linux/mutex.h>
19 #include <linux/of.h>
20 #include <linux/pinctrl/consumer.h>
21 #include <linux/platform_device.h>
22 #include <linux/slab.h>
23 #include <linux/workqueue.h>
24 #include <media/v4l2-flash-led-class.h>
25 
26 #define AAT1290_MOVIE_MODE_CURRENT_ADDR	17
27 #define AAT1290_MAX_MM_CURR_PERCENT_0	16
28 #define AAT1290_MAX_MM_CURR_PERCENT_100	1
29 
30 #define AAT1290_FLASH_SAFETY_TIMER_ADDR	18
31 
32 #define AAT1290_MOVIE_MODE_CONFIG_ADDR	19
33 #define AAT1290_MOVIE_MODE_OFF		1
34 #define AAT1290_MOVIE_MODE_ON		3
35 
36 #define AAT1290_MM_CURRENT_RATIO_ADDR	20
37 #define AAT1290_MM_TO_FL_1_92		1
38 
39 #define AAT1290_MM_TO_FL_RATIO		1000 / 1920
40 #define AAT1290_MAX_MM_CURRENT(fl_max)	(fl_max * AAT1290_MM_TO_FL_RATIO)
41 
42 #define AAT1290_LATCH_TIME_MIN_US	500
43 #define AAT1290_LATCH_TIME_MAX_US	1000
44 #define AAT1290_EN_SET_TICK_TIME_US	1
45 #define AAT1290_FLEN_OFF_DELAY_TIME_US	10
46 #define AAT1290_FLASH_TM_NUM_LEVELS	16
47 #define AAT1290_MM_CURRENT_SCALE_SIZE	15
48 
49 
50 struct aat1290_led_config_data {
51 	/* maximum LED current in movie mode */
52 	u32 max_mm_current;
53 	/* maximum LED current in flash mode */
54 	u32 max_flash_current;
55 	/* maximum flash timeout */
56 	u32 max_flash_tm;
57 	/* external strobe capability */
58 	bool has_external_strobe;
59 	/* max LED brightness level */
60 	enum led_brightness max_brightness;
61 };
62 
63 struct aat1290_led {
64 	/* platform device data */
65 	struct platform_device *pdev;
66 	/* secures access to the device */
67 	struct mutex lock;
68 
69 	/* corresponding LED Flash class device */
70 	struct led_classdev_flash fled_cdev;
71 	/* V4L2 Flash device */
72 	struct v4l2_flash *v4l2_flash;
73 
74 	/* FLEN pin */
75 	struct gpio_desc *gpio_fl_en;
76 	/* EN|SET pin  */
77 	struct gpio_desc *gpio_en_set;
78 	/* movie mode current scale */
79 	int *mm_current_scale;
80 	/* device mode */
81 	bool movie_mode;
82 
83 	/* brightness cache */
84 	unsigned int torch_brightness;
85 	/* assures led-triggers compatibility */
86 	struct work_struct work_brightness_set;
87 };
88 
fled_cdev_to_led(struct led_classdev_flash * fled_cdev)89 static struct aat1290_led *fled_cdev_to_led(
90 				struct led_classdev_flash *fled_cdev)
91 {
92 	return container_of(fled_cdev, struct aat1290_led, fled_cdev);
93 }
94 
aat1290_as2cwire_write(struct aat1290_led * led,int addr,int value)95 static void aat1290_as2cwire_write(struct aat1290_led *led, int addr, int value)
96 {
97 	int i;
98 
99 	gpiod_direction_output(led->gpio_fl_en, 0);
100 	gpiod_direction_output(led->gpio_en_set, 0);
101 
102 	udelay(AAT1290_FLEN_OFF_DELAY_TIME_US);
103 
104 	/* write address */
105 	for (i = 0; i < addr; ++i) {
106 		udelay(AAT1290_EN_SET_TICK_TIME_US);
107 		gpiod_direction_output(led->gpio_en_set, 0);
108 		udelay(AAT1290_EN_SET_TICK_TIME_US);
109 		gpiod_direction_output(led->gpio_en_set, 1);
110 	}
111 
112 	usleep_range(AAT1290_LATCH_TIME_MIN_US, AAT1290_LATCH_TIME_MAX_US);
113 
114 	/* write data */
115 	for (i = 0; i < value; ++i) {
116 		udelay(AAT1290_EN_SET_TICK_TIME_US);
117 		gpiod_direction_output(led->gpio_en_set, 0);
118 		udelay(AAT1290_EN_SET_TICK_TIME_US);
119 		gpiod_direction_output(led->gpio_en_set, 1);
120 	}
121 
122 	usleep_range(AAT1290_LATCH_TIME_MIN_US, AAT1290_LATCH_TIME_MAX_US);
123 }
124 
aat1290_set_flash_safety_timer(struct aat1290_led * led,unsigned int micro_sec)125 static void aat1290_set_flash_safety_timer(struct aat1290_led *led,
126 					unsigned int micro_sec)
127 {
128 	struct led_classdev_flash *fled_cdev = &led->fled_cdev;
129 	struct led_flash_setting *flash_tm = &fled_cdev->timeout;
130 	int flash_tm_reg = AAT1290_FLASH_TM_NUM_LEVELS -
131 				(micro_sec / flash_tm->step) + 1;
132 
133 	aat1290_as2cwire_write(led, AAT1290_FLASH_SAFETY_TIMER_ADDR,
134 							flash_tm_reg);
135 }
136 
aat1290_brightness_set(struct aat1290_led * led,enum led_brightness brightness)137 static void aat1290_brightness_set(struct aat1290_led *led,
138 					enum led_brightness brightness)
139 {
140 	mutex_lock(&led->lock);
141 
142 	if (brightness == 0) {
143 		gpiod_direction_output(led->gpio_fl_en, 0);
144 		gpiod_direction_output(led->gpio_en_set, 0);
145 		led->movie_mode = false;
146 	} else {
147 		if (!led->movie_mode) {
148 			aat1290_as2cwire_write(led,
149 				AAT1290_MM_CURRENT_RATIO_ADDR,
150 				AAT1290_MM_TO_FL_1_92);
151 			led->movie_mode = true;
152 		}
153 
154 		aat1290_as2cwire_write(led, AAT1290_MOVIE_MODE_CURRENT_ADDR,
155 				AAT1290_MAX_MM_CURR_PERCENT_0 - brightness);
156 		aat1290_as2cwire_write(led, AAT1290_MOVIE_MODE_CONFIG_ADDR,
157 				AAT1290_MOVIE_MODE_ON);
158 	}
159 
160 	mutex_unlock(&led->lock);
161 }
162 
163 /* LED subsystem callbacks */
164 
aat1290_brightness_set_work(struct work_struct * work)165 static void aat1290_brightness_set_work(struct work_struct *work)
166 {
167 	struct aat1290_led *led =
168 		container_of(work, struct aat1290_led, work_brightness_set);
169 
170 	aat1290_brightness_set(led, led->torch_brightness);
171 }
172 
aat1290_led_brightness_set(struct led_classdev * led_cdev,enum led_brightness brightness)173 static void aat1290_led_brightness_set(struct led_classdev *led_cdev,
174 					enum led_brightness brightness)
175 {
176 	struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
177 	struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
178 
179 	led->torch_brightness = brightness;
180 	schedule_work(&led->work_brightness_set);
181 }
182 
aat1290_led_brightness_set_sync(struct led_classdev * led_cdev,enum led_brightness brightness)183 static int aat1290_led_brightness_set_sync(struct led_classdev *led_cdev,
184 					enum led_brightness brightness)
185 {
186 	struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
187 	struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
188 
189 	aat1290_brightness_set(led, brightness);
190 
191 	return 0;
192 }
193 
aat1290_led_flash_strobe_set(struct led_classdev_flash * fled_cdev,bool state)194 static int aat1290_led_flash_strobe_set(struct led_classdev_flash *fled_cdev,
195 					 bool state)
196 
197 {
198 	struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
199 	struct led_classdev *led_cdev = &fled_cdev->led_cdev;
200 	struct led_flash_setting *timeout = &fled_cdev->timeout;
201 
202 	mutex_lock(&led->lock);
203 
204 	if (state) {
205 		aat1290_set_flash_safety_timer(led, timeout->val);
206 		gpiod_direction_output(led->gpio_fl_en, 1);
207 	} else {
208 		gpiod_direction_output(led->gpio_fl_en, 0);
209 		gpiod_direction_output(led->gpio_en_set, 0);
210 	}
211 
212 	/*
213 	 * To reenter movie mode after a flash event the part must be cycled
214 	 * off and back on to reset the movie mode and reprogrammed via the
215 	 * AS2Cwire. Therefore the brightness and movie_mode properties needs
216 	 * to be updated here to reflect the actual state.
217 	 */
218 	led_cdev->brightness = 0;
219 	led->movie_mode = false;
220 
221 	mutex_unlock(&led->lock);
222 
223 	return 0;
224 }
225 
aat1290_led_flash_timeout_set(struct led_classdev_flash * fled_cdev,u32 timeout)226 static int aat1290_led_flash_timeout_set(struct led_classdev_flash *fled_cdev,
227 						u32 timeout)
228 {
229 	/*
230 	 * Don't do anything - flash timeout is cached in the led-class-flash
231 	 * core and will be applied in the strobe_set op, as writing the
232 	 * safety timer register spuriously turns the torch mode on.
233 	 */
234 
235 	return 0;
236 }
237 
aat1290_led_parse_dt(struct aat1290_led * led,struct aat1290_led_config_data * cfg,struct device_node ** sub_node)238 static int aat1290_led_parse_dt(struct aat1290_led *led,
239 			struct aat1290_led_config_data *cfg,
240 			struct device_node **sub_node)
241 {
242 	struct led_classdev *led_cdev = &led->fled_cdev.led_cdev;
243 	struct device *dev = &led->pdev->dev;
244 	struct device_node *child_node;
245 #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
246 	struct pinctrl *pinctrl;
247 #endif
248 	int ret = 0;
249 
250 	led->gpio_fl_en = devm_gpiod_get(dev, "flen", GPIOD_ASIS);
251 	if (IS_ERR(led->gpio_fl_en)) {
252 		ret = PTR_ERR(led->gpio_fl_en);
253 		dev_err(dev, "Unable to claim gpio \"flen\".\n");
254 		return ret;
255 	}
256 
257 	led->gpio_en_set = devm_gpiod_get(dev, "enset", GPIOD_ASIS);
258 	if (IS_ERR(led->gpio_en_set)) {
259 		ret = PTR_ERR(led->gpio_en_set);
260 		dev_err(dev, "Unable to claim gpio \"enset\".\n");
261 		return ret;
262 	}
263 
264 #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
265 	pinctrl = devm_pinctrl_get_select_default(&led->pdev->dev);
266 	if (IS_ERR(pinctrl)) {
267 		cfg->has_external_strobe = false;
268 		dev_info(dev,
269 			 "No support for external strobe detected.\n");
270 	} else {
271 		cfg->has_external_strobe = true;
272 	}
273 #endif
274 
275 	child_node = of_get_next_available_child(dev->of_node, NULL);
276 	if (!child_node) {
277 		dev_err(dev, "No DT child node found for connected LED.\n");
278 		return -EINVAL;
279 	}
280 
281 	led_cdev->name = of_get_property(child_node, "label", NULL) ? :
282 						child_node->name;
283 
284 	ret = of_property_read_u32(child_node, "led-max-microamp",
285 				&cfg->max_mm_current);
286 	/*
287 	 * led-max-microamp will default to 1/20 of flash-max-microamp
288 	 * in case it is missing.
289 	 */
290 	if (ret < 0)
291 		dev_warn(dev,
292 			"led-max-microamp DT property missing\n");
293 
294 	ret = of_property_read_u32(child_node, "flash-max-microamp",
295 				&cfg->max_flash_current);
296 	if (ret < 0) {
297 		dev_err(dev,
298 			"flash-max-microamp DT property missing\n");
299 		return ret;
300 	}
301 
302 	ret = of_property_read_u32(child_node, "flash-max-timeout-us",
303 				&cfg->max_flash_tm);
304 	if (ret < 0) {
305 		dev_err(dev,
306 			"flash-max-timeout-us DT property missing\n");
307 		return ret;
308 	}
309 
310 	of_node_put(child_node);
311 
312 	*sub_node = child_node;
313 
314 	return ret;
315 }
316 
aat1290_led_validate_mm_current(struct aat1290_led * led,struct aat1290_led_config_data * cfg)317 static void aat1290_led_validate_mm_current(struct aat1290_led *led,
318 					struct aat1290_led_config_data *cfg)
319 {
320 	int i, b = 0, e = AAT1290_MM_CURRENT_SCALE_SIZE;
321 
322 	while (e - b > 1) {
323 		i = b + (e - b) / 2;
324 		if (cfg->max_mm_current < led->mm_current_scale[i])
325 			e = i;
326 		else
327 			b = i;
328 	}
329 
330 	cfg->max_mm_current = led->mm_current_scale[b];
331 	cfg->max_brightness = b + 1;
332 }
333 
init_mm_current_scale(struct aat1290_led * led,struct aat1290_led_config_data * cfg)334 static int init_mm_current_scale(struct aat1290_led *led,
335 			struct aat1290_led_config_data *cfg)
336 {
337 	int max_mm_current_percent[] = { 20, 22, 25, 28, 32, 36, 40, 45, 50, 56,
338 						63, 71, 79, 89, 100 };
339 	int i, max_mm_current =
340 			AAT1290_MAX_MM_CURRENT(cfg->max_flash_current);
341 
342 	led->mm_current_scale = devm_kzalloc(&led->pdev->dev,
343 					sizeof(max_mm_current_percent),
344 					GFP_KERNEL);
345 	if (!led->mm_current_scale)
346 		return -ENOMEM;
347 
348 	for (i = 0; i < AAT1290_MM_CURRENT_SCALE_SIZE; ++i)
349 		led->mm_current_scale[i] = max_mm_current *
350 					  max_mm_current_percent[i] / 100;
351 
352 	return 0;
353 }
354 
aat1290_led_get_configuration(struct aat1290_led * led,struct aat1290_led_config_data * cfg,struct device_node ** sub_node)355 static int aat1290_led_get_configuration(struct aat1290_led *led,
356 					struct aat1290_led_config_data *cfg,
357 					struct device_node **sub_node)
358 {
359 	int ret;
360 
361 	ret = aat1290_led_parse_dt(led, cfg, sub_node);
362 	if (ret < 0)
363 		return ret;
364 	/*
365 	 * Init non-linear movie mode current scale basing
366 	 * on the max flash current from led configuration.
367 	 */
368 	ret = init_mm_current_scale(led, cfg);
369 	if (ret < 0)
370 		return ret;
371 
372 	aat1290_led_validate_mm_current(led, cfg);
373 
374 #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
375 #else
376 	devm_kfree(&led->pdev->dev, led->mm_current_scale);
377 #endif
378 
379 	return 0;
380 }
381 
aat1290_init_flash_timeout(struct aat1290_led * led,struct aat1290_led_config_data * cfg)382 static void aat1290_init_flash_timeout(struct aat1290_led *led,
383 				struct aat1290_led_config_data *cfg)
384 {
385 	struct led_classdev_flash *fled_cdev = &led->fled_cdev;
386 	struct led_flash_setting *setting;
387 
388 	/* Init flash timeout setting */
389 	setting = &fled_cdev->timeout;
390 	setting->min = cfg->max_flash_tm / AAT1290_FLASH_TM_NUM_LEVELS;
391 	setting->max = cfg->max_flash_tm;
392 	setting->step = setting->min;
393 	setting->val = setting->max;
394 }
395 
396 #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
aat1290_intensity_to_brightness(struct v4l2_flash * v4l2_flash,s32 intensity)397 static enum led_brightness aat1290_intensity_to_brightness(
398 					struct v4l2_flash *v4l2_flash,
399 					s32 intensity)
400 {
401 	struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
402 	struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
403 	int i;
404 
405 	for (i = AAT1290_MM_CURRENT_SCALE_SIZE - 1; i >= 0; --i)
406 		if (intensity >= led->mm_current_scale[i])
407 			return i + 1;
408 
409 	return 1;
410 }
411 
aat1290_brightness_to_intensity(struct v4l2_flash * v4l2_flash,enum led_brightness brightness)412 static s32 aat1290_brightness_to_intensity(struct v4l2_flash *v4l2_flash,
413 					enum led_brightness brightness)
414 {
415 	struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
416 	struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
417 
418 	return led->mm_current_scale[brightness - 1];
419 }
420 
aat1290_led_external_strobe_set(struct v4l2_flash * v4l2_flash,bool enable)421 static int aat1290_led_external_strobe_set(struct v4l2_flash *v4l2_flash,
422 						bool enable)
423 {
424 	struct aat1290_led *led = fled_cdev_to_led(v4l2_flash->fled_cdev);
425 	struct led_classdev_flash *fled_cdev = v4l2_flash->fled_cdev;
426 	struct led_classdev *led_cdev = &fled_cdev->led_cdev;
427 	struct pinctrl *pinctrl;
428 
429 	gpiod_direction_output(led->gpio_fl_en, 0);
430 	gpiod_direction_output(led->gpio_en_set, 0);
431 
432 	led->movie_mode = false;
433 	led_cdev->brightness = 0;
434 
435 	pinctrl = devm_pinctrl_get_select(&led->pdev->dev,
436 						enable ? "isp" : "host");
437 	if (IS_ERR(pinctrl)) {
438 		dev_warn(&led->pdev->dev, "Unable to switch strobe source.\n");
439 		return PTR_ERR(pinctrl);
440 	}
441 
442 	return 0;
443 }
444 
aat1290_init_v4l2_flash_config(struct aat1290_led * led,struct aat1290_led_config_data * led_cfg,struct v4l2_flash_config * v4l2_sd_cfg)445 static void aat1290_init_v4l2_flash_config(struct aat1290_led *led,
446 					struct aat1290_led_config_data *led_cfg,
447 					struct v4l2_flash_config *v4l2_sd_cfg)
448 {
449 	struct led_classdev *led_cdev = &led->fled_cdev.led_cdev;
450 	struct led_flash_setting *s;
451 
452 	strlcpy(v4l2_sd_cfg->dev_name, led_cdev->name,
453 		sizeof(v4l2_sd_cfg->dev_name));
454 
455 	s = &v4l2_sd_cfg->torch_intensity;
456 	s->min = led->mm_current_scale[0];
457 	s->max = led_cfg->max_mm_current;
458 	s->step = 1;
459 	s->val = s->max;
460 
461 	v4l2_sd_cfg->has_external_strobe = led_cfg->has_external_strobe;
462 }
463 
464 static const struct v4l2_flash_ops v4l2_flash_ops = {
465 	.external_strobe_set = aat1290_led_external_strobe_set,
466 	.intensity_to_led_brightness = aat1290_intensity_to_brightness,
467 	.led_brightness_to_intensity = aat1290_brightness_to_intensity,
468 };
469 #else
aat1290_init_v4l2_flash_config(struct aat1290_led * led,struct aat1290_led_config_data * led_cfg,struct v4l2_flash_config * v4l2_sd_cfg)470 static inline void aat1290_init_v4l2_flash_config(struct aat1290_led *led,
471 				struct aat1290_led_config_data *led_cfg,
472 				struct v4l2_flash_config *v4l2_sd_cfg)
473 {
474 }
475 static const struct v4l2_flash_ops v4l2_flash_ops;
476 #endif
477 
478 static const struct led_flash_ops flash_ops = {
479 	.strobe_set = aat1290_led_flash_strobe_set,
480 	.timeout_set = aat1290_led_flash_timeout_set,
481 };
482 
aat1290_led_probe(struct platform_device * pdev)483 static int aat1290_led_probe(struct platform_device *pdev)
484 {
485 	struct device *dev = &pdev->dev;
486 	struct device_node *sub_node = NULL;
487 	struct aat1290_led *led;
488 	struct led_classdev *led_cdev;
489 	struct led_classdev_flash *fled_cdev;
490 	struct aat1290_led_config_data led_cfg = {};
491 	struct v4l2_flash_config v4l2_sd_cfg = {};
492 	int ret;
493 
494 	led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
495 	if (!led)
496 		return -ENOMEM;
497 
498 	led->pdev = pdev;
499 	platform_set_drvdata(pdev, led);
500 
501 	fled_cdev = &led->fled_cdev;
502 	fled_cdev->ops = &flash_ops;
503 	led_cdev = &fled_cdev->led_cdev;
504 
505 	ret = aat1290_led_get_configuration(led, &led_cfg, &sub_node);
506 	if (ret < 0)
507 		return ret;
508 
509 	mutex_init(&led->lock);
510 
511 	/* Initialize LED Flash class device */
512 	led_cdev->brightness_set = aat1290_led_brightness_set;
513 	led_cdev->brightness_set_sync = aat1290_led_brightness_set_sync;
514 	led_cdev->max_brightness = led_cfg.max_brightness;
515 	led_cdev->flags |= LED_DEV_CAP_FLASH;
516 	INIT_WORK(&led->work_brightness_set, aat1290_brightness_set_work);
517 
518 	aat1290_init_flash_timeout(led, &led_cfg);
519 
520 	/* Register LED Flash class device */
521 	ret = led_classdev_flash_register(&pdev->dev, fled_cdev);
522 	if (ret < 0)
523 		goto err_flash_register;
524 
525 	aat1290_init_v4l2_flash_config(led, &led_cfg, &v4l2_sd_cfg);
526 
527 	/* Create V4L2 Flash subdev. */
528 	led->v4l2_flash = v4l2_flash_init(dev, sub_node, fled_cdev, NULL,
529 					  &v4l2_flash_ops, &v4l2_sd_cfg);
530 	if (IS_ERR(led->v4l2_flash)) {
531 		ret = PTR_ERR(led->v4l2_flash);
532 		goto error_v4l2_flash_init;
533 	}
534 
535 	return 0;
536 
537 error_v4l2_flash_init:
538 	led_classdev_flash_unregister(fled_cdev);
539 err_flash_register:
540 	mutex_destroy(&led->lock);
541 
542 	return ret;
543 }
544 
aat1290_led_remove(struct platform_device * pdev)545 static int aat1290_led_remove(struct platform_device *pdev)
546 {
547 	struct aat1290_led *led = platform_get_drvdata(pdev);
548 
549 	v4l2_flash_release(led->v4l2_flash);
550 	led_classdev_flash_unregister(&led->fled_cdev);
551 	cancel_work_sync(&led->work_brightness_set);
552 
553 	mutex_destroy(&led->lock);
554 
555 	return 0;
556 }
557 
558 static const struct of_device_id aat1290_led_dt_match[] = {
559 	{ .compatible = "skyworks,aat1290" },
560 	{},
561 };
562 MODULE_DEVICE_TABLE(of, aat1290_led_dt_match);
563 
564 static struct platform_driver aat1290_led_driver = {
565 	.probe		= aat1290_led_probe,
566 	.remove		= aat1290_led_remove,
567 	.driver		= {
568 		.name	= "aat1290",
569 		.of_match_table = aat1290_led_dt_match,
570 	},
571 };
572 
573 module_platform_driver(aat1290_led_driver);
574 
575 MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
576 MODULE_DESCRIPTION("Skyworks Current Regulator for Flash LEDs");
577 MODULE_LICENSE("GPL v2");
578