1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include <linux/delay.h>
22#include <linux/gpio/consumer.h>
23#include <linux/i2c.h>
24#include <linux/led-class-flash.h>
25#include <linux/leds.h>
26#include <linux/module.h>
27#include <linux/mutex.h>
28#include <linux/of.h>
29#include <linux/slab.h>
30
31#include <media/v4l2-flash-led-class.h>
32
33#define AS_TIMER_US_TO_CODE(t) (((t) / 1000 - 100) / 50)
34#define AS_TIMER_CODE_TO_US(c) ((50 * (c) + 100) * 1000)
35
36
37
38
39#define AS_DESIGN_INFO_REG 0x00
40#define AS_DESIGN_INFO_FACTORY(x) (((x) >> 4))
41#define AS_DESIGN_INFO_MODEL(x) ((x) & 0x0f)
42
43
44
45
46#define AS_VERSION_CONTROL_REG 0x01
47#define AS_VERSION_CONTROL_RFU(x) (((x) >> 4))
48#define AS_VERSION_CONTROL_VERSION(x) ((x) & 0x0f)
49
50
51#define AS_INDICATOR_AND_TIMER_REG 0x02
52#define AS_INDICATOR_AND_TIMER_TIMEOUT_SHIFT 0
53#define AS_INDICATOR_AND_TIMER_VREF_SHIFT 4
54#define AS_INDICATOR_AND_TIMER_INDICATOR_SHIFT 6
55
56
57#define AS_CURRENT_SET_REG 0x03
58#define AS_CURRENT_ASSIST_LIGHT_SHIFT 0
59#define AS_CURRENT_LED_DET_ON (1 << 3)
60#define AS_CURRENT_FLASH_CURRENT_SHIFT 4
61
62
63#define AS_CONTROL_REG 0x04
64#define AS_CONTROL_MODE_SETTING_SHIFT 0
65#define AS_CONTROL_STROBE_ON (1 << 2)
66#define AS_CONTROL_OUT_ON (1 << 3)
67#define AS_CONTROL_EXT_TORCH_ON (1 << 4)
68#define AS_CONTROL_STROBE_TYPE_EDGE (0 << 5)
69#define AS_CONTROL_STROBE_TYPE_LEVEL (1 << 5)
70#define AS_CONTROL_COIL_PEAK_SHIFT 6
71
72
73#define AS_FAULT_INFO_REG 0x05
74#define AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT (1 << 1)
75#define AS_FAULT_INFO_INDICATOR_LED (1 << 2)
76#define AS_FAULT_INFO_LED_AMOUNT (1 << 3)
77#define AS_FAULT_INFO_TIMEOUT (1 << 4)
78#define AS_FAULT_INFO_OVER_TEMPERATURE (1 << 5)
79#define AS_FAULT_INFO_SHORT_CIRCUIT (1 << 6)
80#define AS_FAULT_INFO_OVER_VOLTAGE (1 << 7)
81
82
83#define AS_BOOST_REG 0x0d
84#define AS_BOOST_CURRENT_DISABLE (0 << 0)
85#define AS_BOOST_CURRENT_ENABLE (1 << 0)
86
87
88#define AS_PASSWORD_REG 0x0f
89#define AS_PASSWORD_UNLOCK_VALUE 0x55
90
91#define AS_NAME "as3645a"
92#define AS_I2C_ADDR (0x60 >> 1)
93
94#define AS_FLASH_TIMEOUT_MIN 100000
95#define AS_FLASH_TIMEOUT_MAX 850000
96#define AS_FLASH_TIMEOUT_STEP 50000
97
98#define AS_FLASH_INTENSITY_MIN 200000
99#define AS_FLASH_INTENSITY_MAX_1LED 500000
100#define AS_FLASH_INTENSITY_MAX_2LEDS 400000
101#define AS_FLASH_INTENSITY_STEP 20000
102
103#define AS_TORCH_INTENSITY_MIN 20000
104#define AS_TORCH_INTENSITY_MAX 160000
105#define AS_TORCH_INTENSITY_STEP 20000
106
107#define AS_INDICATOR_INTENSITY_MIN 0
108#define AS_INDICATOR_INTENSITY_MAX 10000
109#define AS_INDICATOR_INTENSITY_STEP 2500
110
111#define AS_PEAK_mA_MAX 2000
112#define AS_PEAK_mA_TO_REG(a) \
113 ((min_t(u32, AS_PEAK_mA_MAX, a) - 1250) / 250)
114
115
116#define AS_LED_FLASH 0
117#define AS_LED_INDICATOR 1
118
119enum as_mode {
120 AS_MODE_EXT_TORCH = 0 << AS_CONTROL_MODE_SETTING_SHIFT,
121 AS_MODE_INDICATOR = 1 << AS_CONTROL_MODE_SETTING_SHIFT,
122 AS_MODE_ASSIST = 2 << AS_CONTROL_MODE_SETTING_SHIFT,
123 AS_MODE_FLASH = 3 << AS_CONTROL_MODE_SETTING_SHIFT,
124};
125
126struct as3645a_config {
127 u32 flash_timeout_us;
128 u32 flash_max_ua;
129 u32 assist_max_ua;
130 u32 indicator_max_ua;
131 u32 voltage_reference;
132 u32 peak;
133};
134
135struct as3645a_names {
136 char flash[32];
137 char indicator[32];
138};
139
140struct as3645a {
141 struct i2c_client *client;
142
143 struct mutex mutex;
144
145 struct led_classdev_flash fled;
146 struct led_classdev iled_cdev;
147
148 struct v4l2_flash *vf;
149 struct v4l2_flash *vfind;
150
151 struct device_node *flash_node;
152 struct device_node *indicator_node;
153
154 struct as3645a_config cfg;
155
156 enum as_mode mode;
157 unsigned int timeout;
158 unsigned int flash_current;
159 unsigned int assist_current;
160 unsigned int indicator_current;
161 enum v4l2_flash_strobe_source strobe_source;
162};
163
164#define fled_to_as3645a(__fled) container_of(__fled, struct as3645a, fled)
165#define iled_cdev_to_as3645a(__iled_cdev) \
166 container_of(__iled_cdev, struct as3645a, iled_cdev)
167
168
169static int as3645a_write(struct as3645a *flash, u8 addr, u8 val)
170{
171 struct i2c_client *client = flash->client;
172 int rval;
173
174 rval = i2c_smbus_write_byte_data(client, addr, val);
175
176 dev_dbg(&client->dev, "Write Addr:%02X Val:%02X %s\n", addr, val,
177 rval < 0 ? "fail" : "ok");
178
179 return rval;
180}
181
182
183static int as3645a_read(struct as3645a *flash, u8 addr)
184{
185 struct i2c_client *client = flash->client;
186 int rval;
187
188 rval = i2c_smbus_read_byte_data(client, addr);
189
190 dev_dbg(&client->dev, "Read Addr:%02X Val:%02X %s\n", addr, rval,
191 rval < 0 ? "fail" : "ok");
192
193 return rval;
194}
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210static int as3645a_set_current(struct as3645a *flash)
211{
212 u8 val;
213
214 val = (flash->flash_current << AS_CURRENT_FLASH_CURRENT_SHIFT)
215 | (flash->assist_current << AS_CURRENT_ASSIST_LIGHT_SHIFT)
216 | AS_CURRENT_LED_DET_ON;
217
218 return as3645a_write(flash, AS_CURRENT_SET_REG, val);
219}
220
221static int as3645a_set_timeout(struct as3645a *flash)
222{
223 u8 val;
224
225 val = flash->timeout << AS_INDICATOR_AND_TIMER_TIMEOUT_SHIFT;
226
227 val |= (flash->cfg.voltage_reference
228 << AS_INDICATOR_AND_TIMER_VREF_SHIFT)
229 | ((flash->indicator_current ? flash->indicator_current - 1 : 0)
230 << AS_INDICATOR_AND_TIMER_INDICATOR_SHIFT);
231
232 return as3645a_write(flash, AS_INDICATOR_AND_TIMER_REG, val);
233}
234
235
236
237
238
239
240
241
242
243
244
245
246static int
247as3645a_set_control(struct as3645a *flash, enum as_mode mode, bool on)
248{
249 u8 reg;
250
251
252 reg = (flash->cfg.peak << AS_CONTROL_COIL_PEAK_SHIFT)
253 | (on ? AS_CONTROL_OUT_ON : 0)
254 | mode;
255
256 if (mode == AS_MODE_FLASH &&
257 flash->strobe_source == V4L2_FLASH_STROBE_SOURCE_EXTERNAL)
258 reg |= AS_CONTROL_STROBE_TYPE_LEVEL
259 | AS_CONTROL_STROBE_ON;
260
261 return as3645a_write(flash, AS_CONTROL_REG, reg);
262}
263
264static int as3645a_get_fault(struct led_classdev_flash *fled, u32 *fault)
265{
266 struct as3645a *flash = fled_to_as3645a(fled);
267 int rval;
268
269
270 rval = as3645a_read(flash, AS_FAULT_INFO_REG);
271 if (rval < 0)
272 return rval;
273
274 if (rval & AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT)
275 *fault |= LED_FAULT_OVER_CURRENT;
276
277 if (rval & AS_FAULT_INFO_INDICATOR_LED)
278 *fault |= LED_FAULT_INDICATOR;
279
280 dev_dbg(&flash->client->dev, "%u connected LEDs\n",
281 rval & AS_FAULT_INFO_LED_AMOUNT ? 2 : 1);
282
283 if (rval & AS_FAULT_INFO_TIMEOUT)
284 *fault |= LED_FAULT_TIMEOUT;
285
286 if (rval & AS_FAULT_INFO_OVER_TEMPERATURE)
287 *fault |= LED_FAULT_OVER_TEMPERATURE;
288
289 if (rval & AS_FAULT_INFO_SHORT_CIRCUIT)
290 *fault |= LED_FAULT_OVER_CURRENT;
291
292 if (rval & AS_FAULT_INFO_OVER_VOLTAGE)
293 *fault |= LED_FAULT_INPUT_VOLTAGE;
294
295 return rval;
296}
297
298static unsigned int __as3645a_current_to_reg(unsigned int min, unsigned int max,
299 unsigned int step,
300 unsigned int val)
301{
302 if (val < min)
303 val = min;
304
305 if (val > max)
306 val = max;
307
308 return (val - min) / step;
309}
310
311static unsigned int as3645a_current_to_reg(struct as3645a *flash, bool is_flash,
312 unsigned int ua)
313{
314 if (is_flash)
315 return __as3645a_current_to_reg(AS_TORCH_INTENSITY_MIN,
316 flash->cfg.assist_max_ua,
317 AS_TORCH_INTENSITY_STEP, ua);
318 else
319 return __as3645a_current_to_reg(AS_FLASH_INTENSITY_MIN,
320 flash->cfg.flash_max_ua,
321 AS_FLASH_INTENSITY_STEP, ua);
322}
323
324static int as3645a_set_indicator_brightness(struct led_classdev *iled_cdev,
325 enum led_brightness brightness)
326{
327 struct as3645a *flash = iled_cdev_to_as3645a(iled_cdev);
328 int rval;
329
330 flash->indicator_current = brightness;
331
332 rval = as3645a_set_timeout(flash);
333 if (rval)
334 return rval;
335
336 return as3645a_set_control(flash, AS_MODE_INDICATOR, brightness);
337}
338
339static int as3645a_set_assist_brightness(struct led_classdev *fled_cdev,
340 enum led_brightness brightness)
341{
342 struct led_classdev_flash *fled = lcdev_to_flcdev(fled_cdev);
343 struct as3645a *flash = fled_to_as3645a(fled);
344 int rval;
345
346 if (brightness) {
347
348 flash->assist_current = brightness - 1;
349
350 rval = as3645a_set_current(flash);
351 if (rval)
352 return rval;
353 }
354
355 return as3645a_set_control(flash, AS_MODE_ASSIST, brightness);
356}
357
358static int as3645a_set_flash_brightness(struct led_classdev_flash *fled,
359 u32 brightness_ua)
360{
361 struct as3645a *flash = fled_to_as3645a(fled);
362
363 flash->flash_current = as3645a_current_to_reg(flash, true,
364 brightness_ua);
365
366 return as3645a_set_current(flash);
367}
368
369static int as3645a_set_flash_timeout(struct led_classdev_flash *fled,
370 u32 timeout_us)
371{
372 struct as3645a *flash = fled_to_as3645a(fled);
373
374 flash->timeout = AS_TIMER_US_TO_CODE(timeout_us);
375
376 return as3645a_set_timeout(flash);
377}
378
379static int as3645a_set_strobe(struct led_classdev_flash *fled, bool state)
380{
381 struct as3645a *flash = fled_to_as3645a(fled);
382
383 return as3645a_set_control(flash, AS_MODE_FLASH, state);
384}
385
386static const struct led_flash_ops as3645a_led_flash_ops = {
387 .flash_brightness_set = as3645a_set_flash_brightness,
388 .timeout_set = as3645a_set_flash_timeout,
389 .strobe_set = as3645a_set_strobe,
390 .fault_get = as3645a_get_fault,
391};
392
393static int as3645a_setup(struct as3645a *flash)
394{
395 struct device *dev = &flash->client->dev;
396 u32 fault = 0;
397 int rval;
398
399
400 rval = as3645a_read(flash, AS_FAULT_INFO_REG);
401 if (rval < 0)
402 return rval;
403
404 dev_dbg(dev, "Fault info: %02x\n", rval);
405
406 rval = as3645a_set_current(flash);
407 if (rval < 0)
408 return rval;
409
410 rval = as3645a_set_timeout(flash);
411 if (rval < 0)
412 return rval;
413
414 rval = as3645a_set_control(flash, AS_MODE_INDICATOR, false);
415 if (rval < 0)
416 return rval;
417
418
419 rval = as3645a_get_fault(&flash->fled, &fault);
420 if (rval < 0)
421 return rval;
422
423 dev_dbg(dev, "AS_INDICATOR_AND_TIMER_REG: %02x\n",
424 as3645a_read(flash, AS_INDICATOR_AND_TIMER_REG));
425 dev_dbg(dev, "AS_CURRENT_SET_REG: %02x\n",
426 as3645a_read(flash, AS_CURRENT_SET_REG));
427 dev_dbg(dev, "AS_CONTROL_REG: %02x\n",
428 as3645a_read(flash, AS_CONTROL_REG));
429
430 return rval & ~AS_FAULT_INFO_LED_AMOUNT ? -EIO : 0;
431}
432
433static int as3645a_detect(struct as3645a *flash)
434{
435 struct device *dev = &flash->client->dev;
436 int rval, man, model, rfu, version;
437 const char *vendor;
438
439 rval = as3645a_read(flash, AS_DESIGN_INFO_REG);
440 if (rval < 0) {
441 dev_err(dev, "can't read design info reg\n");
442 return rval;
443 }
444
445 man = AS_DESIGN_INFO_FACTORY(rval);
446 model = AS_DESIGN_INFO_MODEL(rval);
447
448 rval = as3645a_read(flash, AS_VERSION_CONTROL_REG);
449 if (rval < 0) {
450 dev_err(dev, "can't read version control reg\n");
451 return rval;
452 }
453
454 rfu = AS_VERSION_CONTROL_RFU(rval);
455 version = AS_VERSION_CONTROL_VERSION(rval);
456
457
458 if (model != 0x01 || rfu != 0x00) {
459 dev_err(dev, "AS3645A not detected (model %d rfu %d)\n",
460 model, rfu);
461 return -ENODEV;
462 }
463
464 switch (man) {
465 case 1:
466 vendor = "AMS, Austria Micro Systems";
467 break;
468 case 2:
469 vendor = "ADI, Analog Devices Inc.";
470 break;
471 case 3:
472 vendor = "NSC, National Semiconductor";
473 break;
474 case 4:
475 vendor = "NXP";
476 break;
477 case 5:
478 vendor = "TI, Texas Instrument";
479 break;
480 default:
481 vendor = "Unknown";
482 }
483
484 dev_info(dev, "Chip vendor: %s (%d) Version: %d\n", vendor,
485 man, version);
486
487 rval = as3645a_write(flash, AS_PASSWORD_REG, AS_PASSWORD_UNLOCK_VALUE);
488 if (rval < 0)
489 return rval;
490
491 return as3645a_write(flash, AS_BOOST_REG, AS_BOOST_CURRENT_DISABLE);
492}
493
494static int as3645a_parse_node(struct as3645a *flash,
495 struct as3645a_names *names,
496 struct device_node *node)
497{
498 struct as3645a_config *cfg = &flash->cfg;
499 struct device_node *child;
500 const char *name;
501 int rval;
502
503 for_each_child_of_node(node, child) {
504 u32 id = 0;
505
506 of_property_read_u32(child, "reg", &id);
507
508 switch (id) {
509 case AS_LED_FLASH:
510 flash->flash_node = of_node_get(child);
511 break;
512 case AS_LED_INDICATOR:
513 flash->indicator_node = of_node_get(child);
514 break;
515 default:
516 dev_warn(&flash->client->dev,
517 "unknown LED %u encountered, ignoring\n", id);
518 break;
519 }
520 }
521
522 if (!flash->flash_node) {
523 dev_err(&flash->client->dev, "can't find flash node\n");
524 return -ENODEV;
525 }
526
527 rval = of_property_read_string(flash->flash_node, "label", &name);
528 if (!rval)
529 strlcpy(names->flash, name, sizeof(names->flash));
530 else
531 snprintf(names->flash, sizeof(names->flash),
532 "%s:flash", node->name);
533
534 rval = of_property_read_u32(flash->flash_node, "flash-timeout-us",
535 &cfg->flash_timeout_us);
536 if (rval < 0) {
537 dev_err(&flash->client->dev,
538 "can't read flash-timeout-us property for flash\n");
539 goto out_err;
540 }
541
542 rval = of_property_read_u32(flash->flash_node, "flash-max-microamp",
543 &cfg->flash_max_ua);
544 if (rval < 0) {
545 dev_err(&flash->client->dev,
546 "can't read flash-max-microamp property for flash\n");
547 goto out_err;
548 }
549
550 rval = of_property_read_u32(flash->flash_node, "led-max-microamp",
551 &cfg->assist_max_ua);
552 if (rval < 0) {
553 dev_err(&flash->client->dev,
554 "can't read led-max-microamp property for flash\n");
555 goto out_err;
556 }
557
558 of_property_read_u32(flash->flash_node, "voltage-reference",
559 &cfg->voltage_reference);
560
561 of_property_read_u32(flash->flash_node, "ams,input-max-microamp",
562 &cfg->peak);
563 cfg->peak = AS_PEAK_mA_TO_REG(cfg->peak);
564
565 if (!flash->indicator_node) {
566 dev_warn(&flash->client->dev,
567 "can't find indicator node\n");
568 goto out_err;
569 }
570
571 rval = of_property_read_string(flash->indicator_node, "label", &name);
572 if (!rval)
573 strlcpy(names->indicator, name, sizeof(names->indicator));
574 else
575 snprintf(names->indicator, sizeof(names->indicator),
576 "%s:indicator", node->name);
577
578 rval = of_property_read_u32(flash->indicator_node, "led-max-microamp",
579 &cfg->indicator_max_ua);
580 if (rval < 0) {
581 dev_err(&flash->client->dev,
582 "can't read led-max-microamp property for indicator\n");
583 goto out_err;
584 }
585
586 return 0;
587
588out_err:
589 of_node_put(flash->flash_node);
590 of_node_put(flash->indicator_node);
591
592 return rval;
593}
594
595static int as3645a_led_class_setup(struct as3645a *flash,
596 struct as3645a_names *names)
597{
598 struct led_classdev *fled_cdev = &flash->fled.led_cdev;
599 struct led_classdev *iled_cdev = &flash->iled_cdev;
600 struct led_flash_setting *cfg;
601 int rval;
602
603 iled_cdev->name = names->indicator;
604 iled_cdev->brightness_set_blocking = as3645a_set_indicator_brightness;
605 iled_cdev->max_brightness =
606 flash->cfg.indicator_max_ua / AS_INDICATOR_INTENSITY_STEP;
607 iled_cdev->flags = LED_CORE_SUSPENDRESUME;
608
609 rval = led_classdev_register(&flash->client->dev, iled_cdev);
610 if (rval < 0)
611 return rval;
612
613 cfg = &flash->fled.brightness;
614 cfg->min = AS_FLASH_INTENSITY_MIN;
615 cfg->max = flash->cfg.flash_max_ua;
616 cfg->step = AS_FLASH_INTENSITY_STEP;
617 cfg->val = flash->cfg.flash_max_ua;
618
619 cfg = &flash->fled.timeout;
620 cfg->min = AS_FLASH_TIMEOUT_MIN;
621 cfg->max = flash->cfg.flash_timeout_us;
622 cfg->step = AS_FLASH_TIMEOUT_STEP;
623 cfg->val = flash->cfg.flash_timeout_us;
624
625 flash->fled.ops = &as3645a_led_flash_ops;
626
627 fled_cdev->name = names->flash;
628 fled_cdev->brightness_set_blocking = as3645a_set_assist_brightness;
629
630 fled_cdev->max_brightness =
631 as3645a_current_to_reg(flash, false,
632 flash->cfg.assist_max_ua) + 1;
633 fled_cdev->flags = LED_DEV_CAP_FLASH | LED_CORE_SUSPENDRESUME;
634
635 rval = led_classdev_flash_register(&flash->client->dev, &flash->fled);
636 if (rval) {
637 led_classdev_unregister(iled_cdev);
638 dev_err(&flash->client->dev,
639 "led_classdev_flash_register() failed, error %d\n",
640 rval);
641 }
642
643 return rval;
644}
645
646static int as3645a_v4l2_setup(struct as3645a *flash)
647{
648 struct led_classdev_flash *fled = &flash->fled;
649 struct led_classdev *led = &fled->led_cdev;
650 struct v4l2_flash_config cfg = {
651 .intensity = {
652 .min = AS_TORCH_INTENSITY_MIN,
653 .max = flash->cfg.assist_max_ua,
654 .step = AS_TORCH_INTENSITY_STEP,
655 .val = flash->cfg.assist_max_ua,
656 },
657 };
658 struct v4l2_flash_config cfgind = {
659 .intensity = {
660 .min = AS_INDICATOR_INTENSITY_MIN,
661 .max = flash->cfg.indicator_max_ua,
662 .step = AS_INDICATOR_INTENSITY_STEP,
663 .val = flash->cfg.indicator_max_ua,
664 },
665 };
666
667 strlcpy(cfg.dev_name, led->name, sizeof(cfg.dev_name));
668 strlcpy(cfgind.dev_name, flash->iled_cdev.name, sizeof(cfg.dev_name));
669
670 flash->vf = v4l2_flash_init(
671 &flash->client->dev, of_fwnode_handle(flash->flash_node),
672 &flash->fled, NULL, &cfg);
673 if (IS_ERR(flash->vf))
674 return PTR_ERR(flash->vf);
675
676 flash->vfind = v4l2_flash_indicator_init(
677 &flash->client->dev, of_fwnode_handle(flash->indicator_node),
678 &flash->iled_cdev, &cfgind);
679 if (IS_ERR(flash->vfind)) {
680 v4l2_flash_release(flash->vf);
681 return PTR_ERR(flash->vfind);
682 }
683
684 return 0;
685}
686
687static int as3645a_probe(struct i2c_client *client)
688{
689 struct as3645a_names names;
690 struct as3645a *flash;
691 int rval;
692
693 if (client->dev.of_node == NULL)
694 return -ENODEV;
695
696 flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL);
697 if (flash == NULL)
698 return -ENOMEM;
699
700 flash->client = client;
701
702 rval = as3645a_parse_node(flash, &names, client->dev.of_node);
703 if (rval < 0)
704 return rval;
705
706 rval = as3645a_detect(flash);
707 if (rval < 0)
708 goto out_put_nodes;
709
710 mutex_init(&flash->mutex);
711 i2c_set_clientdata(client, flash);
712
713 rval = as3645a_setup(flash);
714 if (rval)
715 goto out_mutex_destroy;
716
717 rval = as3645a_led_class_setup(flash, &names);
718 if (rval)
719 goto out_mutex_destroy;
720
721 rval = as3645a_v4l2_setup(flash);
722 if (rval)
723 goto out_led_classdev_flash_unregister;
724
725 return 0;
726
727out_led_classdev_flash_unregister:
728 led_classdev_flash_unregister(&flash->fled);
729
730out_mutex_destroy:
731 mutex_destroy(&flash->mutex);
732
733out_put_nodes:
734 of_node_put(flash->flash_node);
735 of_node_put(flash->indicator_node);
736
737 return rval;
738}
739
740static int as3645a_remove(struct i2c_client *client)
741{
742 struct as3645a *flash = i2c_get_clientdata(client);
743
744 as3645a_set_control(flash, AS_MODE_EXT_TORCH, false);
745
746 v4l2_flash_release(flash->vf);
747 v4l2_flash_release(flash->vfind);
748
749 led_classdev_flash_unregister(&flash->fled);
750 led_classdev_unregister(&flash->iled_cdev);
751
752 mutex_destroy(&flash->mutex);
753
754 of_node_put(flash->flash_node);
755 of_node_put(flash->indicator_node);
756
757 return 0;
758}
759
760static const struct i2c_device_id as3645a_id_table[] = {
761 { AS_NAME, 0 },
762 { },
763};
764MODULE_DEVICE_TABLE(i2c, as3645a_id_table);
765
766static const struct of_device_id as3645a_of_table[] = {
767 { .compatible = "ams,as3645a" },
768 { },
769};
770MODULE_DEVICE_TABLE(of, as3645a_of_table);
771
772static struct i2c_driver as3645a_i2c_driver = {
773 .driver = {
774 .of_match_table = as3645a_of_table,
775 .name = AS_NAME,
776 },
777 .probe_new = as3645a_probe,
778 .remove = as3645a_remove,
779 .id_table = as3645a_id_table,
780};
781
782module_i2c_driver(as3645a_i2c_driver);
783
784MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
785MODULE_AUTHOR("Sakari Ailus <sakari.ailus@iki.fi>");
786MODULE_DESCRIPTION("LED flash driver for AS3645A, LM3555 and their clones");
787MODULE_LICENSE("GPL v2");
788