leds: Add support for max77693 mfd flash cell
[linux-2.6-block.git] / drivers / leds / leds-max77693.c
CommitLineData
a43f6a86
JA
1/*
2 * LED Flash class driver for the flash cell of max77693 mfd.
3 *
4 * Copyright (C) 2015, Samsung Electronics Co., Ltd.
5 *
6 * Authors: Jacek Anaszewski <j.anaszewski@samsung.com>
7 * Andrzej Hajda <a.hajda@samsung.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 */
13
14#include <linux/led-class-flash.h>
15#include <linux/mfd/max77693.h>
16#include <linux/mfd/max77693-private.h>
17#include <linux/module.h>
18#include <linux/mutex.h>
19#include <linux/platform_device.h>
20#include <linux/regmap.h>
21#include <linux/slab.h>
22#include <linux/workqueue.h>
23
24#define MODE_OFF 0
25#define MODE_FLASH(a) (1 << (a))
26#define MODE_TORCH(a) (1 << (2 + (a)))
27#define MODE_FLASH_EXTERNAL(a) (1 << (4 + (a)))
28
29#define MODE_FLASH_MASK (MODE_FLASH(FLED1) | MODE_FLASH(FLED2) | \
30 MODE_FLASH_EXTERNAL(FLED1) | \
31 MODE_FLASH_EXTERNAL(FLED2))
32#define MODE_TORCH_MASK (MODE_TORCH(FLED1) | MODE_TORCH(FLED2))
33
34#define FLED1_IOUT (1 << 0)
35#define FLED2_IOUT (1 << 1)
36
37enum max77693_fled {
38 FLED1,
39 FLED2,
40};
41
42enum max77693_led_mode {
43 FLASH,
44 TORCH,
45};
46
47struct max77693_led_config_data {
48 const char *label[2];
49 u32 iout_torch_max[2];
50 u32 iout_flash_max[2];
51 u32 flash_timeout_max[2];
52 u32 num_leds;
53 u32 boost_mode;
54 u32 boost_vout;
55 u32 low_vsys;
56};
57
58struct max77693_sub_led {
59 /* corresponding FLED output identifier */
60 int fled_id;
61 /* corresponding LED Flash class device */
62 struct led_classdev_flash fled_cdev;
63 /* assures led-triggers compatibility */
64 struct work_struct work_brightness_set;
65
66 /* brightness cache */
67 unsigned int torch_brightness;
68 /* flash timeout cache */
69 unsigned int flash_timeout;
70 /* flash faults that may have occurred */
71 u32 flash_faults;
72};
73
74struct max77693_led_device {
75 /* parent mfd regmap */
76 struct regmap *regmap;
77 /* platform device data */
78 struct platform_device *pdev;
79 /* secures access to the device */
80 struct mutex lock;
81
82 /* sub led data */
83 struct max77693_sub_led sub_leds[2];
84
85 /* maximum torch current values for FLED outputs */
86 u32 iout_torch_max[2];
87 /* maximum flash current values for FLED outputs */
88 u32 iout_flash_max[2];
89
90 /* current flash timeout cache */
91 unsigned int current_flash_timeout;
92 /* ITORCH register cache */
93 u8 torch_iout_reg;
94 /* mode of fled outputs */
95 unsigned int mode_flags;
96 /* recently strobed fled */
97 int strobing_sub_led_id;
98 /* bitmask of FLED outputs use state (bit 0. - FLED1, bit 1. - FLED2) */
99 u8 fled_mask;
100 /* FLED modes that can be set */
101 u8 allowed_modes;
102
103 /* arrangement of current outputs */
104 bool iout_joint;
105};
106
107static u8 max77693_led_iout_to_reg(u32 ua)
108{
109 if (ua < FLASH_IOUT_MIN)
110 ua = FLASH_IOUT_MIN;
111 return (ua - FLASH_IOUT_MIN) / FLASH_IOUT_STEP;
112}
113
114static u8 max77693_flash_timeout_to_reg(u32 us)
115{
116 return (us - FLASH_TIMEOUT_MIN) / FLASH_TIMEOUT_STEP;
117}
118
119static inline struct max77693_sub_led *flcdev_to_sub_led(
120 struct led_classdev_flash *fled_cdev)
121{
122 return container_of(fled_cdev, struct max77693_sub_led, fled_cdev);
123}
124
125static inline struct max77693_led_device *sub_led_to_led(
126 struct max77693_sub_led *sub_led)
127{
128 return container_of(sub_led, struct max77693_led_device,
129 sub_leds[sub_led->fled_id]);
130}
131
132static inline u8 max77693_led_vsys_to_reg(u32 mv)
133{
134 return ((mv - MAX_FLASH1_VSYS_MIN) / MAX_FLASH1_VSYS_STEP) << 2;
135}
136
137static inline u8 max77693_led_vout_to_reg(u32 mv)
138{
139 return (mv - FLASH_VOUT_MIN) / FLASH_VOUT_STEP + FLASH_VOUT_RMIN;
140}
141
142static inline bool max77693_fled_used(struct max77693_led_device *led,
143 int fled_id)
144{
145 u8 fled_bit = (fled_id == FLED1) ? FLED1_IOUT : FLED2_IOUT;
146
147 return led->fled_mask & fled_bit;
148}
149
150static int max77693_set_mode_reg(struct max77693_led_device *led, u8 mode)
151{
152 struct regmap *rmap = led->regmap;
153 int ret, v = 0, i;
154
155 for (i = FLED1; i <= FLED2; ++i) {
156 if (mode & MODE_TORCH(i))
157 v |= FLASH_EN_ON << TORCH_EN_SHIFT(i);
158
159 if (mode & MODE_FLASH(i)) {
160 v |= FLASH_EN_ON << FLASH_EN_SHIFT(i);
161 } else if (mode & MODE_FLASH_EXTERNAL(i)) {
162 v |= FLASH_EN_FLASH << FLASH_EN_SHIFT(i);
163 /*
164 * Enable hw triggering also for torch mode, as some
165 * camera sensors use torch led to fathom ambient light
166 * conditions before strobing the flash.
167 */
168 v |= FLASH_EN_TORCH << TORCH_EN_SHIFT(i);
169 }
170 }
171
172 /* Reset the register only prior setting flash modes */
173 if (mode & ~(MODE_TORCH(FLED1) | MODE_TORCH(FLED2))) {
174 ret = regmap_write(rmap, MAX77693_LED_REG_FLASH_EN, 0);
175 if (ret < 0)
176 return ret;
177 }
178
179 return regmap_write(rmap, MAX77693_LED_REG_FLASH_EN, v);
180}
181
182static int max77693_add_mode(struct max77693_led_device *led, u8 mode)
183{
184 u8 new_mode_flags;
185 int i, ret;
186
187 if (led->iout_joint)
188 /* Span the mode on FLED2 for joint iouts case */
189 mode |= (mode << 1);
190
191 /*
192 * FLASH_EXTERNAL mode activates FLASHEN and TORCHEN pins in the device.
193 * Corresponding register bit fields interfere with SW triggered modes,
194 * thus clear them to ensure proper device configuration.
195 */
196 for (i = FLED1; i <= FLED2; ++i)
197 if (mode & MODE_FLASH_EXTERNAL(i))
198 led->mode_flags &= (~MODE_TORCH(i) & ~MODE_FLASH(i));
199
200 new_mode_flags = mode | led->mode_flags;
201 new_mode_flags &= led->allowed_modes;
202
203 if (new_mode_flags ^ led->mode_flags)
204 led->mode_flags = new_mode_flags;
205 else
206 return 0;
207
208 ret = max77693_set_mode_reg(led, led->mode_flags);
209 if (ret < 0)
210 return ret;
211
212 /*
213 * Clear flash mode flag after setting the mode to avoid spurious flash
214 * strobing on each subsequent torch mode setting.
215 */
216 if (mode & MODE_FLASH_MASK)
217 led->mode_flags &= ~mode;
218
219 return ret;
220}
221
222static int max77693_clear_mode(struct max77693_led_device *led,
223 u8 mode)
224{
225 if (led->iout_joint)
226 /* Clear mode also on FLED2 for joint iouts case */
227 mode |= (mode << 1);
228
229 led->mode_flags &= ~mode;
230
231 return max77693_set_mode_reg(led, led->mode_flags);
232}
233
234static void max77693_add_allowed_modes(struct max77693_led_device *led,
235 int fled_id, enum max77693_led_mode mode)
236{
237 if (mode == FLASH)
238 led->allowed_modes |= (MODE_FLASH(fled_id) |
239 MODE_FLASH_EXTERNAL(fled_id));
240 else
241 led->allowed_modes |= MODE_TORCH(fled_id);
242}
243
244static void max77693_distribute_currents(struct max77693_led_device *led,
245 int fled_id, enum max77693_led_mode mode,
246 u32 micro_amp, u32 iout_max[2], u32 iout[2])
247{
248 if (!led->iout_joint) {
249 iout[fled_id] = micro_amp;
250 max77693_add_allowed_modes(led, fled_id, mode);
251 return;
252 }
253
254 iout[FLED1] = min(micro_amp, iout_max[FLED1]);
255 iout[FLED2] = micro_amp - iout[FLED1];
256
257 if (mode == FLASH)
258 led->allowed_modes &= ~MODE_FLASH_MASK;
259 else
260 led->allowed_modes &= ~MODE_TORCH_MASK;
261
262 max77693_add_allowed_modes(led, FLED1, mode);
263
264 if (iout[FLED2])
265 max77693_add_allowed_modes(led, FLED2, mode);
266}
267
268static int max77693_set_torch_current(struct max77693_led_device *led,
269 int fled_id, u32 micro_amp)
270{
271 struct regmap *rmap = led->regmap;
272 u8 iout1_reg = 0, iout2_reg = 0;
273 u32 iout[2];
274
275 max77693_distribute_currents(led, fled_id, TORCH, micro_amp,
276 led->iout_torch_max, iout);
277
278 if (fled_id == FLED1 || led->iout_joint) {
279 iout1_reg = max77693_led_iout_to_reg(iout[FLED1]);
280 led->torch_iout_reg &= TORCH_IOUT_MASK(TORCH_IOUT2_SHIFT);
281 }
282 if (fled_id == FLED2 || led->iout_joint) {
283 iout2_reg = max77693_led_iout_to_reg(iout[FLED2]);
284 led->torch_iout_reg &= TORCH_IOUT_MASK(TORCH_IOUT1_SHIFT);
285 }
286
287 led->torch_iout_reg |= ((iout1_reg << TORCH_IOUT1_SHIFT) |
288 (iout2_reg << TORCH_IOUT2_SHIFT));
289
290 return regmap_write(rmap, MAX77693_LED_REG_ITORCH,
291 led->torch_iout_reg);
292}
293
294static int max77693_set_flash_current(struct max77693_led_device *led,
295 int fled_id,
296 u32 micro_amp)
297{
298 struct regmap *rmap = led->regmap;
299 u8 iout1_reg, iout2_reg;
300 u32 iout[2];
301 int ret = -EINVAL;
302
303 max77693_distribute_currents(led, fled_id, FLASH, micro_amp,
304 led->iout_flash_max, iout);
305
306 if (fled_id == FLED1 || led->iout_joint) {
307 iout1_reg = max77693_led_iout_to_reg(iout[FLED1]);
308 ret = regmap_write(rmap, MAX77693_LED_REG_IFLASH1,
309 iout1_reg);
310 if (ret < 0)
311 return ret;
312 }
313 if (fled_id == FLED2 || led->iout_joint) {
314 iout2_reg = max77693_led_iout_to_reg(iout[FLED2]);
315 ret = regmap_write(rmap, MAX77693_LED_REG_IFLASH2,
316 iout2_reg);
317 }
318
319 return ret;
320}
321
322static int max77693_set_timeout(struct max77693_led_device *led, u32 microsec)
323{
324 struct regmap *rmap = led->regmap;
325 u8 v;
326 int ret;
327
328 v = max77693_flash_timeout_to_reg(microsec) | FLASH_TMR_LEVEL;
329
330 ret = regmap_write(rmap, MAX77693_LED_REG_FLASH_TIMER, v);
331 if (ret < 0)
332 return ret;
333
334 led->current_flash_timeout = microsec;
335
336 return 0;
337}
338
339static int max77693_get_strobe_status(struct max77693_led_device *led,
340 bool *state)
341{
342 struct regmap *rmap = led->regmap;
343 unsigned int v;
344 int ret;
345
346 ret = regmap_read(rmap, MAX77693_LED_REG_FLASH_STATUS, &v);
347 if (ret < 0)
348 return ret;
349
350 *state = v & FLASH_STATUS_FLASH_ON;
351
352 return ret;
353}
354
355static int max77693_get_flash_faults(struct max77693_sub_led *sub_led)
356{
357 struct max77693_led_device *led = sub_led_to_led(sub_led);
358 struct regmap *rmap = led->regmap;
359 unsigned int v;
360 u8 fault_open_mask, fault_short_mask;
361 int ret;
362
363 sub_led->flash_faults = 0;
364
365 if (led->iout_joint) {
366 fault_open_mask = FLASH_INT_FLED1_OPEN | FLASH_INT_FLED2_OPEN;
367 fault_short_mask = FLASH_INT_FLED1_SHORT |
368 FLASH_INT_FLED2_SHORT;
369 } else {
370 fault_open_mask = (sub_led->fled_id == FLED1) ?
371 FLASH_INT_FLED1_OPEN :
372 FLASH_INT_FLED2_OPEN;
373 fault_short_mask = (sub_led->fled_id == FLED1) ?
374 FLASH_INT_FLED1_SHORT :
375 FLASH_INT_FLED2_SHORT;
376 }
377
378 ret = regmap_read(rmap, MAX77693_LED_REG_FLASH_INT, &v);
379 if (ret < 0)
380 return ret;
381
382 if (v & fault_open_mask)
383 sub_led->flash_faults |= LED_FAULT_OVER_VOLTAGE;
384 if (v & fault_short_mask)
385 sub_led->flash_faults |= LED_FAULT_SHORT_CIRCUIT;
386 if (v & FLASH_INT_OVER_CURRENT)
387 sub_led->flash_faults |= LED_FAULT_OVER_CURRENT;
388
389 return 0;
390}
391
392static int max77693_setup(struct max77693_led_device *led,
393 struct max77693_led_config_data *led_cfg)
394{
395 struct regmap *rmap = led->regmap;
396 int i, first_led, last_led, ret;
397 u32 max_flash_curr[2];
398 u8 v;
399
400 /*
401 * Initialize only flash current. Torch current doesn't
402 * require initialization as ITORCH register is written with
403 * new value each time brightness_set op is called.
404 */
405 if (led->iout_joint) {
406 first_led = FLED1;
407 last_led = FLED1;
408 max_flash_curr[FLED1] = led_cfg->iout_flash_max[FLED1] +
409 led_cfg->iout_flash_max[FLED2];
410 } else {
411 first_led = max77693_fled_used(led, FLED1) ? FLED1 : FLED2;
412 last_led = max77693_fled_used(led, FLED2) ? FLED2 : FLED1;
413 max_flash_curr[FLED1] = led_cfg->iout_flash_max[FLED1];
414 max_flash_curr[FLED2] = led_cfg->iout_flash_max[FLED2];
415 }
416
417 for (i = first_led; i <= last_led; ++i) {
418 ret = max77693_set_flash_current(led, i,
419 max_flash_curr[i]);
420 if (ret < 0)
421 return ret;
422 }
423
424 v = TORCH_TMR_NO_TIMER | MAX77693_LED_TRIG_TYPE_LEVEL;
425 ret = regmap_write(rmap, MAX77693_LED_REG_ITORCHTIMER, v);
426 if (ret < 0)
427 return ret;
428
429 if (led_cfg->low_vsys > 0)
430 v = max77693_led_vsys_to_reg(led_cfg->low_vsys) |
431 MAX_FLASH1_MAX_FL_EN;
432 else
433 v = 0;
434
435 ret = regmap_write(rmap, MAX77693_LED_REG_MAX_FLASH1, v);
436 if (ret < 0)
437 return ret;
438 ret = regmap_write(rmap, MAX77693_LED_REG_MAX_FLASH2, 0);
439 if (ret < 0)
440 return ret;
441
442 if (led_cfg->boost_mode == MAX77693_LED_BOOST_FIXED)
443 v = FLASH_BOOST_FIXED;
444 else
445 v = led_cfg->boost_mode | led_cfg->boost_mode << 1;
446
447 if (max77693_fled_used(led, FLED1) && max77693_fled_used(led, FLED2))
448 v |= FLASH_BOOST_LEDNUM_2;
449
450 ret = regmap_write(rmap, MAX77693_LED_REG_VOUT_CNTL, v);
451 if (ret < 0)
452 return ret;
453
454 v = max77693_led_vout_to_reg(led_cfg->boost_vout);
455 ret = regmap_write(rmap, MAX77693_LED_REG_VOUT_FLASH1, v);
456 if (ret < 0)
457 return ret;
458
459 return max77693_set_mode_reg(led, MODE_OFF);
460}
461
462static int __max77693_led_brightness_set(struct max77693_led_device *led,
463 int fled_id, enum led_brightness value)
464{
465 int ret;
466
467 mutex_lock(&led->lock);
468
469 if (value == 0) {
470 ret = max77693_clear_mode(led, MODE_TORCH(fled_id));
471 if (ret < 0)
472 dev_dbg(&led->pdev->dev,
473 "Failed to clear torch mode (%d)\n",
474 ret);
475 goto unlock;
476 }
477
478 ret = max77693_set_torch_current(led, fled_id, value * TORCH_IOUT_STEP);
479 if (ret < 0) {
480 dev_dbg(&led->pdev->dev,
481 "Failed to set torch current (%d)\n",
482 ret);
483 goto unlock;
484 }
485
486 ret = max77693_add_mode(led, MODE_TORCH(fled_id));
487 if (ret < 0)
488 dev_dbg(&led->pdev->dev,
489 "Failed to set torch mode (%d)\n",
490 ret);
491unlock:
492 mutex_unlock(&led->lock);
493 return ret;
494}
495
496static void max77693_led_brightness_set_work(
497 struct work_struct *work)
498{
499 struct max77693_sub_led *sub_led =
500 container_of(work, struct max77693_sub_led,
501 work_brightness_set);
502 struct max77693_led_device *led = sub_led_to_led(sub_led);
503
504 __max77693_led_brightness_set(led, sub_led->fled_id,
505 sub_led->torch_brightness);
506}
507
508/* LED subsystem callbacks */
509
510static int max77693_led_brightness_set_sync(
511 struct led_classdev *led_cdev,
512 enum led_brightness value)
513{
514 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
515 struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
516 struct max77693_led_device *led = sub_led_to_led(sub_led);
517
518 return __max77693_led_brightness_set(led, sub_led->fled_id, value);
519}
520
521static void max77693_led_brightness_set(
522 struct led_classdev *led_cdev,
523 enum led_brightness value)
524{
525 struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
526 struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
527
528 sub_led->torch_brightness = value;
529 schedule_work(&sub_led->work_brightness_set);
530}
531
532static int max77693_led_flash_brightness_set(
533 struct led_classdev_flash *fled_cdev,
534 u32 brightness)
535{
536 struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
537 struct max77693_led_device *led = sub_led_to_led(sub_led);
538 int ret;
539
540 mutex_lock(&led->lock);
541 ret = max77693_set_flash_current(led, sub_led->fled_id, brightness);
542 mutex_unlock(&led->lock);
543
544 return ret;
545}
546
547static int max77693_led_flash_strobe_set(
548 struct led_classdev_flash *fled_cdev,
549 bool state)
550{
551 struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
552 struct max77693_led_device *led = sub_led_to_led(sub_led);
553 int fled_id = sub_led->fled_id;
554 int ret;
555
556 mutex_lock(&led->lock);
557
558 if (!state) {
559 ret = max77693_clear_mode(led, MODE_FLASH(fled_id));
560 goto unlock;
561 }
562
563 if (sub_led->flash_timeout != led->current_flash_timeout) {
564 ret = max77693_set_timeout(led, sub_led->flash_timeout);
565 if (ret < 0)
566 goto unlock;
567 }
568
569 led->strobing_sub_led_id = fled_id;
570
571 ret = max77693_add_mode(led, MODE_FLASH(fled_id));
572 if (ret < 0)
573 goto unlock;
574
575 ret = max77693_get_flash_faults(sub_led);
576
577unlock:
578 mutex_unlock(&led->lock);
579 return ret;
580}
581
582static int max77693_led_flash_fault_get(
583 struct led_classdev_flash *fled_cdev,
584 u32 *fault)
585{
586 struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
587
588 *fault = sub_led->flash_faults;
589
590 return 0;
591}
592
593static int max77693_led_flash_strobe_get(
594 struct led_classdev_flash *fled_cdev,
595 bool *state)
596{
597 struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
598 struct max77693_led_device *led = sub_led_to_led(sub_led);
599 int ret;
600
601 if (!state)
602 return -EINVAL;
603
604 mutex_lock(&led->lock);
605
606 ret = max77693_get_strobe_status(led, state);
607
608 *state = !!(*state && (led->strobing_sub_led_id == sub_led->fled_id));
609
610 mutex_unlock(&led->lock);
611
612 return ret;
613}
614
615static int max77693_led_flash_timeout_set(
616 struct led_classdev_flash *fled_cdev,
617 u32 timeout)
618{
619 struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
620 struct max77693_led_device *led = sub_led_to_led(sub_led);
621
622 mutex_lock(&led->lock);
623 sub_led->flash_timeout = timeout;
624 mutex_unlock(&led->lock);
625
626 return 0;
627}
628
629static int max77693_led_parse_dt(struct max77693_led_device *led,
630 struct max77693_led_config_data *cfg)
631{
632 struct device *dev = &led->pdev->dev;
633 struct max77693_sub_led *sub_leds = led->sub_leds;
634 struct device_node *node = dev->of_node, *child_node;
635 struct property *prop;
636 u32 led_sources[2];
637 int i, ret, fled_id;
638
639 of_property_read_u32(node, "maxim,boost-mode", &cfg->boost_mode);
640 of_property_read_u32(node, "maxim,boost-mvout", &cfg->boost_vout);
641 of_property_read_u32(node, "maxim,mvsys-min", &cfg->low_vsys);
642
643 for_each_available_child_of_node(node, child_node) {
644 prop = of_find_property(child_node, "led-sources", NULL);
645 if (prop) {
646 const __be32 *srcs = NULL;
647
648 for (i = 0; i < ARRAY_SIZE(led_sources); ++i) {
649 srcs = of_prop_next_u32(prop, srcs,
650 &led_sources[i]);
651 if (!srcs)
652 break;
653 }
654 } else {
655 dev_err(dev,
656 "led-sources DT property missing\n");
657 of_node_put(child_node);
658 return -EINVAL;
659 }
660
661 if (i == 2) {
662 fled_id = FLED1;
663 led->fled_mask = FLED1_IOUT | FLED2_IOUT;
664 } else if (led_sources[0] == FLED1) {
665 fled_id = FLED1;
666 led->fled_mask |= FLED1_IOUT;
667 } else if (led_sources[0] == FLED2) {
668 fled_id = FLED2;
669 led->fled_mask |= FLED2_IOUT;
670 } else {
671 dev_err(dev,
672 "Wrong led-sources DT property value.\n");
673 of_node_put(child_node);
674 return -EINVAL;
675 }
676
677 sub_leds[fled_id].fled_id = fled_id;
678
679 cfg->label[fled_id] =
680 of_get_property(child_node, "label", NULL) ? :
681 child_node->name;
682
683 ret = of_property_read_u32(child_node, "led-max-microamp",
684 &cfg->iout_torch_max[fled_id]);
685 if (ret < 0) {
686 cfg->iout_torch_max[fled_id] = TORCH_IOUT_MIN;
687 dev_warn(dev, "led-max-microamp DT property missing\n");
688 }
689
690 ret = of_property_read_u32(child_node, "flash-max-microamp",
691 &cfg->iout_flash_max[fled_id]);
692 if (ret < 0) {
693 cfg->iout_flash_max[fled_id] = FLASH_IOUT_MIN;
694 dev_warn(dev,
695 "flash-max-microamp DT property missing\n");
696 }
697
698 ret = of_property_read_u32(child_node, "flash-max-timeout-us",
699 &cfg->flash_timeout_max[fled_id]);
700 if (ret < 0) {
701 cfg->flash_timeout_max[fled_id] = FLASH_TIMEOUT_MIN;
702 dev_warn(dev,
703 "flash-max-timeout-us DT property missing\n");
704 }
705
706 if (++cfg->num_leds == 2 ||
707 (max77693_fled_used(led, FLED1) &&
708 max77693_fled_used(led, FLED2))) {
709 of_node_put(child_node);
710 break;
711 }
712 }
713
714 if (cfg->num_leds == 0) {
715 dev_err(dev, "No DT child node found for connected LED(s).\n");
716 return -EINVAL;
717 }
718
719 return 0;
720}
721
722static void clamp_align(u32 *v, u32 min, u32 max, u32 step)
723{
724 *v = clamp_val(*v, min, max);
725 if (step > 1)
726 *v = (*v - min) / step * step + min;
727}
728
729static void max77693_align_iout_current(struct max77693_led_device *led,
730 u32 *iout, u32 min, u32 max, u32 step)
731{
732 int i;
733
734 if (led->iout_joint) {
735 if (iout[FLED1] > min) {
736 iout[FLED1] /= 2;
737 iout[FLED2] = iout[FLED1];
738 } else {
739 iout[FLED1] = min;
740 iout[FLED2] = 0;
741 return;
742 }
743 }
744
745 for (i = FLED1; i <= FLED2; ++i)
746 if (max77693_fled_used(led, i))
747 clamp_align(&iout[i], min, max, step);
748 else
749 iout[i] = 0;
750}
751
752static void max77693_led_validate_configuration(struct max77693_led_device *led,
753 struct max77693_led_config_data *cfg)
754{
755 u32 flash_iout_max = cfg->boost_mode ? FLASH_IOUT_MAX_2LEDS :
756 FLASH_IOUT_MAX_1LED;
757 int i;
758
759 if (cfg->num_leds == 1 &&
760 max77693_fled_used(led, FLED1) && max77693_fled_used(led, FLED2))
761 led->iout_joint = true;
762
763 cfg->boost_mode = clamp_val(cfg->boost_mode, MAX77693_LED_BOOST_NONE,
764 MAX77693_LED_BOOST_FIXED);
765
766 /* Boost must be enabled if both current outputs are used */
767 if ((cfg->boost_mode == MAX77693_LED_BOOST_NONE) && led->iout_joint)
768 cfg->boost_mode = MAX77693_LED_BOOST_FIXED;
769
770 max77693_align_iout_current(led, cfg->iout_torch_max,
771 TORCH_IOUT_MIN, TORCH_IOUT_MAX, TORCH_IOUT_STEP);
772
773 max77693_align_iout_current(led, cfg->iout_flash_max,
774 FLASH_IOUT_MIN, flash_iout_max, FLASH_IOUT_STEP);
775
776 for (i = 0; i < ARRAY_SIZE(cfg->flash_timeout_max); ++i)
777 clamp_align(&cfg->flash_timeout_max[i], FLASH_TIMEOUT_MIN,
778 FLASH_TIMEOUT_MAX, FLASH_TIMEOUT_STEP);
779
780 clamp_align(&cfg->boost_vout, FLASH_VOUT_MIN, FLASH_VOUT_MAX,
781 FLASH_VOUT_STEP);
782
783 if (cfg->low_vsys)
784 clamp_align(&cfg->low_vsys, MAX_FLASH1_VSYS_MIN,
785 MAX_FLASH1_VSYS_MAX, MAX_FLASH1_VSYS_STEP);
786}
787
788static int max77693_led_get_configuration(struct max77693_led_device *led,
789 struct max77693_led_config_data *cfg)
790{
791 int ret;
792
793 ret = max77693_led_parse_dt(led, cfg);
794 if (ret < 0)
795 return ret;
796
797 max77693_led_validate_configuration(led, cfg);
798
799 memcpy(led->iout_torch_max, cfg->iout_torch_max,
800 sizeof(led->iout_torch_max));
801 memcpy(led->iout_flash_max, cfg->iout_flash_max,
802 sizeof(led->iout_flash_max));
803
804 return 0;
805}
806
807static const struct led_flash_ops flash_ops = {
808 .flash_brightness_set = max77693_led_flash_brightness_set,
809 .strobe_set = max77693_led_flash_strobe_set,
810 .strobe_get = max77693_led_flash_strobe_get,
811 .timeout_set = max77693_led_flash_timeout_set,
812 .fault_get = max77693_led_flash_fault_get,
813};
814
815static void max77693_init_flash_settings(struct max77693_sub_led *sub_led,
816 struct max77693_led_config_data *led_cfg)
817{
818 struct led_classdev_flash *fled_cdev = &sub_led->fled_cdev;
819 struct max77693_led_device *led = sub_led_to_led(sub_led);
820 int fled_id = sub_led->fled_id;
821 struct led_flash_setting *setting;
822
823 /* Init flash intensity setting */
824 setting = &fled_cdev->brightness;
825 setting->min = FLASH_IOUT_MIN;
826 setting->max = led->iout_joint ?
827 led_cfg->iout_flash_max[FLED1] +
828 led_cfg->iout_flash_max[FLED2] :
829 led_cfg->iout_flash_max[fled_id];
830 setting->step = FLASH_IOUT_STEP;
831 setting->val = setting->max;
832
833 /* Init flash timeout setting */
834 setting = &fled_cdev->timeout;
835 setting->min = FLASH_TIMEOUT_MIN;
836 setting->max = led_cfg->flash_timeout_max[fled_id];
837 setting->step = FLASH_TIMEOUT_STEP;
838 setting->val = setting->max;
839}
840
841static void max77693_init_fled_cdev(struct max77693_sub_led *sub_led,
842 struct max77693_led_config_data *led_cfg)
843{
844 struct max77693_led_device *led = sub_led_to_led(sub_led);
845 int fled_id = sub_led->fled_id;
846 struct led_classdev_flash *fled_cdev;
847 struct led_classdev *led_cdev;
848
849 /* Initialize LED Flash class device */
850 fled_cdev = &sub_led->fled_cdev;
851 fled_cdev->ops = &flash_ops;
852 led_cdev = &fled_cdev->led_cdev;
853
854 led_cdev->name = led_cfg->label[fled_id];
855
856 led_cdev->brightness_set = max77693_led_brightness_set;
857 led_cdev->brightness_set_sync = max77693_led_brightness_set_sync;
858 led_cdev->max_brightness = (led->iout_joint ?
859 led_cfg->iout_torch_max[FLED1] +
860 led_cfg->iout_torch_max[FLED2] :
861 led_cfg->iout_torch_max[fled_id]) /
862 TORCH_IOUT_STEP;
863 led_cdev->flags |= LED_DEV_CAP_FLASH;
864 INIT_WORK(&sub_led->work_brightness_set,
865 max77693_led_brightness_set_work);
866
867 max77693_init_flash_settings(sub_led, led_cfg);
868
869 /* Init flash timeout cache */
870 sub_led->flash_timeout = fled_cdev->timeout.val;
871}
872
873static int max77693_led_probe(struct platform_device *pdev)
874{
875 struct device *dev = &pdev->dev;
876 struct max77693_dev *iodev = dev_get_drvdata(dev->parent);
877 struct max77693_led_device *led;
878 struct max77693_sub_led *sub_leds;
879 struct max77693_led_config_data led_cfg = {};
880 int init_fled_cdev[2], i, ret;
881
882 led = devm_kzalloc(dev, sizeof(*led), GFP_KERNEL);
883 if (!led)
884 return -ENOMEM;
885
886 led->pdev = pdev;
887 led->regmap = iodev->regmap;
888 led->allowed_modes = MODE_FLASH_MASK;
889 sub_leds = led->sub_leds;
890
891 platform_set_drvdata(pdev, led);
892 ret = max77693_led_get_configuration(led, &led_cfg);
893 if (ret < 0)
894 return ret;
895
896 ret = max77693_setup(led, &led_cfg);
897 if (ret < 0)
898 return ret;
899
900 mutex_init(&led->lock);
901
902 init_fled_cdev[FLED1] =
903 led->iout_joint || max77693_fled_used(led, FLED1);
904 init_fled_cdev[FLED2] =
905 !led->iout_joint && max77693_fled_used(led, FLED2);
906
907 for (i = FLED1; i <= FLED2; ++i) {
908 if (!init_fled_cdev[i])
909 continue;
910
911 /* Initialize LED Flash class device */
912 max77693_init_fled_cdev(&sub_leds[i], &led_cfg);
913
914 /* Register LED Flash class device */
915 ret = led_classdev_flash_register(dev, &sub_leds[i].fled_cdev);
916 if (ret < 0) {
917 /*
918 * At this moment FLED1 might have been already
919 * registered and it needs to be released.
920 */
921 if (i == FLED2)
922 goto err_register_led2;
923 else
924 goto err_register_led1;
925 }
926 }
927
928 return 0;
929
930err_register_led2:
931 /* It is possible than only FLED2 was to be registered */
932 if (!init_fled_cdev[FLED1])
933 goto err_register_led1;
934 led_classdev_flash_unregister(&sub_leds[FLED1].fled_cdev);
935err_register_led1:
936 mutex_destroy(&led->lock);
937
938 return ret;
939}
940
941static int max77693_led_remove(struct platform_device *pdev)
942{
943 struct max77693_led_device *led = platform_get_drvdata(pdev);
944 struct max77693_sub_led *sub_leds = led->sub_leds;
945
946 if (led->iout_joint || max77693_fled_used(led, FLED1)) {
947 led_classdev_flash_unregister(&sub_leds[FLED1].fled_cdev);
948 cancel_work_sync(&sub_leds[FLED1].work_brightness_set);
949 }
950
951 if (!led->iout_joint && max77693_fled_used(led, FLED2)) {
952 led_classdev_flash_unregister(&sub_leds[FLED2].fled_cdev);
953 cancel_work_sync(&sub_leds[FLED2].work_brightness_set);
954 }
955
956 mutex_destroy(&led->lock);
957
958 return 0;
959}
960
961static const struct of_device_id max77693_led_dt_match[] = {
962 { .compatible = "maxim,max77693-led" },
963 {},
964};
965
966static struct platform_driver max77693_led_driver = {
967 .probe = max77693_led_probe,
968 .remove = max77693_led_remove,
969 .driver = {
970 .name = "max77693-led",
971 .of_match_table = max77693_led_dt_match,
972 },
973};
974
975module_platform_driver(max77693_led_driver);
976
977MODULE_AUTHOR("Jacek Anaszewski <j.anaszewski@samsung.com>");
978MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
979MODULE_DESCRIPTION("Maxim MAX77693 led flash driver");
980MODULE_LICENSE("GPL v2");