]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/leds/leds-as3645a.c
dt: bindings: as3645a: Use LED number to refer to LEDs
[mirror_ubuntu-jammy-kernel.git] / drivers / leds / leds-as3645a.c
CommitLineData
a56ba8fb
SA
1/*
2 * drivers/leds/leds-as3645a.c - AS3645A and LM3555 flash controllers driver
3 *
4 * Copyright (C) 2008-2011 Nokia Corporation
5 * Copyright (c) 2011, 2017 Intel Corporation.
6 *
7 * Based on drivers/media/i2c/as3645a.c.
8 *
9 * Contact: Sakari Ailus <sakari.ailus@iki.fi>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * version 2 as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
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/* Register definitions */
37
38/* Read-only Design info register: Reset state: xxxx 0001 */
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/* Read-only Version control register: Reset state: 0000 0000
44 * for first engineering samples
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/* Read / Write (Indicator and timer register): Reset state: 0000 1111 */
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/* Read / Write (Current set register): Reset state: 0110 1001 */
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/* Read / Write (Control register): Reset state: 1011 0100 */
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/* Read only (D3 is read / write) (Fault and info): Reset state: 0000 x000 */
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/* Boost register */
83#define AS_BOOST_REG 0x0d
84#define AS_BOOST_CURRENT_DISABLE (0 << 0)
85#define AS_BOOST_CURRENT_ENABLE (1 << 0)
86
87/* Password register is used to unlock boost register writing */
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) /* W:0x60, R:0x61 */
93
94#define AS_FLASH_TIMEOUT_MIN 100000 /* us */
95#define AS_FLASH_TIMEOUT_MAX 850000
96#define AS_FLASH_TIMEOUT_STEP 50000
97
98#define AS_FLASH_INTENSITY_MIN 200000 /* uA */
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 /* uA */
104#define AS_TORCH_INTENSITY_MAX 160000
105#define AS_TORCH_INTENSITY_STEP 20000
106
107#define AS_INDICATOR_INTENSITY_MIN 0 /* uA */
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
115enum as_mode {
116 AS_MODE_EXT_TORCH = 0 << AS_CONTROL_MODE_SETTING_SHIFT,
117 AS_MODE_INDICATOR = 1 << AS_CONTROL_MODE_SETTING_SHIFT,
118 AS_MODE_ASSIST = 2 << AS_CONTROL_MODE_SETTING_SHIFT,
119 AS_MODE_FLASH = 3 << AS_CONTROL_MODE_SETTING_SHIFT,
120};
121
122struct as3645a_config {
123 u32 flash_timeout_us;
124 u32 flash_max_ua;
125 u32 assist_max_ua;
126 u32 indicator_max_ua;
127 u32 voltage_reference;
128 u32 peak;
129};
130
131struct as3645a_names {
132 char flash[32];
133 char indicator[32];
134};
135
136struct as3645a {
137 struct i2c_client *client;
138
139 struct mutex mutex;
140
141 struct led_classdev_flash fled;
142 struct led_classdev iled_cdev;
143
144 struct v4l2_flash *vf;
145 struct v4l2_flash *vfind;
146
147 struct device_node *flash_node;
148 struct device_node *indicator_node;
149
150 struct as3645a_config cfg;
151
152 enum as_mode mode;
153 unsigned int timeout;
154 unsigned int flash_current;
155 unsigned int assist_current;
156 unsigned int indicator_current;
157 enum v4l2_flash_strobe_source strobe_source;
158};
159
160#define fled_to_as3645a(__fled) container_of(__fled, struct as3645a, fled)
161#define iled_cdev_to_as3645a(__iled_cdev) \
162 container_of(__iled_cdev, struct as3645a, iled_cdev)
163
164/* Return negative errno else zero on success */
165static int as3645a_write(struct as3645a *flash, u8 addr, u8 val)
166{
167 struct i2c_client *client = flash->client;
168 int rval;
169
170 rval = i2c_smbus_write_byte_data(client, addr, val);
171
172 dev_dbg(&client->dev, "Write Addr:%02X Val:%02X %s\n", addr, val,
173 rval < 0 ? "fail" : "ok");
174
175 return rval;
176}
177
178/* Return negative errno else a data byte received from the device. */
179static int as3645a_read(struct as3645a *flash, u8 addr)
180{
181 struct i2c_client *client = flash->client;
182 int rval;
183
184 rval = i2c_smbus_read_byte_data(client, addr);
185
186 dev_dbg(&client->dev, "Read Addr:%02X Val:%02X %s\n", addr, rval,
187 rval < 0 ? "fail" : "ok");
188
189 return rval;
190}
191
192/* -----------------------------------------------------------------------------
193 * Hardware configuration and trigger
194 */
195
196/**
197 * as3645a_set_config - Set flash configuration registers
198 * @flash: The flash
199 *
200 * Configure the hardware with flash, assist and indicator currents, as well as
201 * flash timeout.
202 *
203 * Return 0 on success, or a negative error code if an I2C communication error
204 * occurred.
205 */
206static int as3645a_set_current(struct as3645a *flash)
207{
208 u8 val;
209
210 val = (flash->flash_current << AS_CURRENT_FLASH_CURRENT_SHIFT)
211 | (flash->assist_current << AS_CURRENT_ASSIST_LIGHT_SHIFT)
212 | AS_CURRENT_LED_DET_ON;
213
214 return as3645a_write(flash, AS_CURRENT_SET_REG, val);
215}
216
217static int as3645a_set_timeout(struct as3645a *flash)
218{
219 u8 val;
220
221 val = flash->timeout << AS_INDICATOR_AND_TIMER_TIMEOUT_SHIFT;
222
223 val |= (flash->cfg.voltage_reference
224 << AS_INDICATOR_AND_TIMER_VREF_SHIFT)
225 | ((flash->indicator_current ? flash->indicator_current - 1 : 0)
226 << AS_INDICATOR_AND_TIMER_INDICATOR_SHIFT);
227
228 return as3645a_write(flash, AS_INDICATOR_AND_TIMER_REG, val);
229}
230
231/**
232 * as3645a_set_control - Set flash control register
233 * @flash: The flash
234 * @mode: Desired output mode
235 * @on: Desired output state
236 *
237 * Configure the hardware with output mode and state.
238 *
239 * Return 0 on success, or a negative error code if an I2C communication error
240 * occurred.
241 */
242static int
243as3645a_set_control(struct as3645a *flash, enum as_mode mode, bool on)
244{
245 u8 reg;
246
247 /* Configure output parameters and operation mode. */
248 reg = (flash->cfg.peak << AS_CONTROL_COIL_PEAK_SHIFT)
249 | (on ? AS_CONTROL_OUT_ON : 0)
250 | mode;
251
252 if (mode == AS_MODE_FLASH &&
253 flash->strobe_source == V4L2_FLASH_STROBE_SOURCE_EXTERNAL)
254 reg |= AS_CONTROL_STROBE_TYPE_LEVEL
255 | AS_CONTROL_STROBE_ON;
256
257 return as3645a_write(flash, AS_CONTROL_REG, reg);
258}
259
260static int as3645a_get_fault(struct led_classdev_flash *fled, u32 *fault)
261{
262 struct as3645a *flash = fled_to_as3645a(fled);
263 int rval;
264
265 /* NOTE: reading register clears fault status */
266 rval = as3645a_read(flash, AS_FAULT_INFO_REG);
267 if (rval < 0)
268 return rval;
269
270 if (rval & AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT)
271 *fault |= LED_FAULT_OVER_CURRENT;
272
273 if (rval & AS_FAULT_INFO_INDICATOR_LED)
274 *fault |= LED_FAULT_INDICATOR;
275
276 dev_dbg(&flash->client->dev, "%u connected LEDs\n",
277 rval & AS_FAULT_INFO_LED_AMOUNT ? 2 : 1);
278
279 if (rval & AS_FAULT_INFO_TIMEOUT)
280 *fault |= LED_FAULT_TIMEOUT;
281
282 if (rval & AS_FAULT_INFO_OVER_TEMPERATURE)
283 *fault |= LED_FAULT_OVER_TEMPERATURE;
284
285 if (rval & AS_FAULT_INFO_SHORT_CIRCUIT)
286 *fault |= LED_FAULT_OVER_CURRENT;
287
288 if (rval & AS_FAULT_INFO_OVER_VOLTAGE)
289 *fault |= LED_FAULT_INPUT_VOLTAGE;
290
291 return rval;
292}
293
294static unsigned int __as3645a_current_to_reg(unsigned int min, unsigned int max,
295 unsigned int step,
296 unsigned int val)
297{
298 if (val < min)
299 val = min;
300
301 if (val > max)
302 val = max;
303
304 return (val - min) / step;
305}
306
307static unsigned int as3645a_current_to_reg(struct as3645a *flash, bool is_flash,
308 unsigned int ua)
309{
310 if (is_flash)
311 return __as3645a_current_to_reg(AS_TORCH_INTENSITY_MIN,
312 flash->cfg.assist_max_ua,
313 AS_TORCH_INTENSITY_STEP, ua);
314 else
315 return __as3645a_current_to_reg(AS_FLASH_INTENSITY_MIN,
316 flash->cfg.flash_max_ua,
317 AS_FLASH_INTENSITY_STEP, ua);
318}
319
320static int as3645a_set_indicator_brightness(struct led_classdev *iled_cdev,
321 enum led_brightness brightness)
322{
323 struct as3645a *flash = iled_cdev_to_as3645a(iled_cdev);
324 int rval;
325
326 flash->indicator_current = brightness;
327
328 rval = as3645a_set_timeout(flash);
329 if (rval)
330 return rval;
331
332 return as3645a_set_control(flash, AS_MODE_INDICATOR, brightness);
333}
334
335static int as3645a_set_assist_brightness(struct led_classdev *fled_cdev,
336 enum led_brightness brightness)
337{
338 struct led_classdev_flash *fled = lcdev_to_flcdev(fled_cdev);
339 struct as3645a *flash = fled_to_as3645a(fled);
340 int rval;
341
342 if (brightness) {
343 /* Register value 0 is 20 mA. */
344 flash->assist_current = brightness - 1;
345
346 rval = as3645a_set_current(flash);
347 if (rval)
348 return rval;
349 }
350
351 return as3645a_set_control(flash, AS_MODE_ASSIST, brightness);
352}
353
354static int as3645a_set_flash_brightness(struct led_classdev_flash *fled,
355 u32 brightness_ua)
356{
357 struct as3645a *flash = fled_to_as3645a(fled);
358
359 flash->flash_current = as3645a_current_to_reg(flash, true, brightness_ua);
360
361 return as3645a_set_current(flash);
362}
363
364static int as3645a_set_flash_timeout(struct led_classdev_flash *fled,
365 u32 timeout_us)
366{
367 struct as3645a *flash = fled_to_as3645a(fled);
368
369 flash->timeout = AS_TIMER_US_TO_CODE(timeout_us);
370
371 return as3645a_set_timeout(flash);
372}
373
374static int as3645a_set_strobe(struct led_classdev_flash *fled, bool state)
375{
376 struct as3645a *flash = fled_to_as3645a(fled);
377
378 return as3645a_set_control(flash, AS_MODE_FLASH, state);
379}
380
381static const struct led_flash_ops as3645a_led_flash_ops = {
382 .flash_brightness_set = as3645a_set_flash_brightness,
383 .timeout_set = as3645a_set_flash_timeout,
384 .strobe_set = as3645a_set_strobe,
385 .fault_get = as3645a_get_fault,
386};
387
388static int as3645a_setup(struct as3645a *flash)
389{
390 struct device *dev = &flash->client->dev;
391 u32 fault = 0;
392 int rval;
393
394 /* clear errors */
395 rval = as3645a_read(flash, AS_FAULT_INFO_REG);
396 if (rval < 0)
397 return rval;
398
399 dev_dbg(dev, "Fault info: %02x\n", rval);
400
401 rval = as3645a_set_current(flash);
402 if (rval < 0)
403 return rval;
404
405 rval = as3645a_set_timeout(flash);
406 if (rval < 0)
407 return rval;
408
409 rval = as3645a_set_control(flash, AS_MODE_INDICATOR, false);
410 if (rval < 0)
411 return rval;
412
413 /* read status */
414 rval = as3645a_get_fault(&flash->fled, &fault);
415 if (rval < 0)
416 return rval;
417
418 dev_dbg(dev, "AS_INDICATOR_AND_TIMER_REG: %02x\n",
419 as3645a_read(flash, AS_INDICATOR_AND_TIMER_REG));
420 dev_dbg(dev, "AS_CURRENT_SET_REG: %02x\n",
421 as3645a_read(flash, AS_CURRENT_SET_REG));
422 dev_dbg(dev, "AS_CONTROL_REG: %02x\n",
423 as3645a_read(flash, AS_CONTROL_REG));
424
425 return rval & ~AS_FAULT_INFO_LED_AMOUNT ? -EIO : 0;
426}
427
428static int as3645a_detect(struct as3645a *flash)
429{
430 struct device *dev = &flash->client->dev;
431 int rval, man, model, rfu, version;
432 const char *vendor;
433
434 rval = as3645a_read(flash, AS_DESIGN_INFO_REG);
435 if (rval < 0) {
436 dev_err(dev, "can't read design info reg\n");
437 return rval;
438 }
439
440 man = AS_DESIGN_INFO_FACTORY(rval);
441 model = AS_DESIGN_INFO_MODEL(rval);
442
443 rval = as3645a_read(flash, AS_VERSION_CONTROL_REG);
444 if (rval < 0) {
445 dev_err(dev, "can't read version control reg\n");
446 return rval;
447 }
448
449 rfu = AS_VERSION_CONTROL_RFU(rval);
450 version = AS_VERSION_CONTROL_VERSION(rval);
451
452 /* Verify the chip model and version. */
453 if (model != 0x01 || rfu != 0x00) {
454 dev_err(dev, "AS3645A not detected "
455 "(model %d rfu %d)\n", model, rfu);
456 return -ENODEV;
457 }
458
459 switch (man) {
460 case 1:
461 vendor = "AMS, Austria Micro Systems";
462 break;
463 case 2:
464 vendor = "ADI, Analog Devices Inc.";
465 break;
466 case 3:
467 vendor = "NSC, National Semiconductor";
468 break;
469 case 4:
470 vendor = "NXP";
471 break;
472 case 5:
473 vendor = "TI, Texas Instrument";
474 break;
475 default:
476 vendor = "Unknown";
477 }
478
479 dev_info(dev, "Chip vendor: %s (%d) Version: %d\n", vendor,
480 man, version);
481
482 rval = as3645a_write(flash, AS_PASSWORD_REG, AS_PASSWORD_UNLOCK_VALUE);
483 if (rval < 0)
484 return rval;
485
486 return as3645a_write(flash, AS_BOOST_REG, AS_BOOST_CURRENT_DISABLE);
487}
488
489static int as3645a_parse_node(struct as3645a *flash,
490 struct as3645a_names *names,
491 struct device_node *node)
492{
493 struct as3645a_config *cfg = &flash->cfg;
494 const char *name;
495 int rval;
496
497 flash->flash_node = of_get_child_by_name(node, "flash");
498 if (!flash->flash_node) {
499 dev_err(&flash->client->dev, "can't find flash node\n");
500 return -ENODEV;
501 }
502
503 rval = of_property_read_string(flash->flash_node, "label", &name);
504 if (!rval)
505 strlcpy(names->flash, name, sizeof(names->flash));
506 else
507 snprintf(names->flash, sizeof(names->flash),
508 "%s:flash", node->name);
509
510 rval = of_property_read_u32(flash->flash_node, "flash-timeout-us",
511 &cfg->flash_timeout_us);
512 if (rval < 0) {
513 dev_err(&flash->client->dev,
514 "can't read flash-timeout-us property for flash\n");
515 goto out_err;
516 }
517
518 rval = of_property_read_u32(flash->flash_node, "flash-max-microamp",
519 &cfg->flash_max_ua);
520 if (rval < 0) {
521 dev_err(&flash->client->dev,
522 "can't read flash-max-microamp property for flash\n");
523 goto out_err;
524 }
525
526 rval = of_property_read_u32(flash->flash_node, "led-max-microamp",
527 &cfg->assist_max_ua);
528 if (rval < 0) {
529 dev_err(&flash->client->dev,
530 "can't read led-max-microamp property for flash\n");
531 goto out_err;
532 }
533
534 of_property_read_u32(flash->flash_node, "voltage-reference",
535 &cfg->voltage_reference);
536
af2e658f 537 of_property_read_u32(flash->flash_node, "ams,input-max-microamp",
a56ba8fb
SA
538 &cfg->peak);
539 cfg->peak = AS_PEAK_mA_TO_REG(cfg->peak);
540
541 flash->indicator_node = of_get_child_by_name(node, "indicator");
542 if (!flash->indicator_node) {
543 dev_warn(&flash->client->dev,
544 "can't find indicator node\n");
545 goto out_err;
546 }
547
548 rval = of_property_read_string(flash->indicator_node, "label", &name);
549 if (!rval)
550 strlcpy(names->indicator, name, sizeof(names->indicator));
551 else
552 snprintf(names->indicator, sizeof(names->indicator),
553 "%s:indicator", node->name);
554
555 rval = of_property_read_u32(flash->indicator_node, "led-max-microamp",
556 &cfg->indicator_max_ua);
557 if (rval < 0) {
558 dev_err(&flash->client->dev,
559 "can't read led-max-microamp property for indicator\n");
560 goto out_err;
561 }
562
563 return 0;
564
565out_err:
566 of_node_put(flash->flash_node);
567 of_node_put(flash->indicator_node);
568
569 return rval;
570}
571
572static int as3645a_led_class_setup(struct as3645a *flash,
573 struct as3645a_names *names)
574{
575 struct led_classdev *fled_cdev = &flash->fled.led_cdev;
576 struct led_classdev *iled_cdev = &flash->iled_cdev;
577 struct led_flash_setting *cfg;
578 int rval;
579
580 iled_cdev->name = names->indicator;
581 iled_cdev->brightness_set_blocking = as3645a_set_indicator_brightness;
582 iled_cdev->max_brightness =
583 flash->cfg.indicator_max_ua / AS_INDICATOR_INTENSITY_STEP;
584 iled_cdev->flags = LED_CORE_SUSPENDRESUME;
585
586 rval = led_classdev_register(&flash->client->dev, iled_cdev);
587 if (rval < 0)
588 return rval;
589
590 cfg = &flash->fled.brightness;
591 cfg->min = AS_FLASH_INTENSITY_MIN;
592 cfg->max = flash->cfg.flash_max_ua;
593 cfg->step = AS_FLASH_INTENSITY_STEP;
594 cfg->val = flash->cfg.flash_max_ua;
595
596 cfg = &flash->fled.timeout;
597 cfg->min = AS_FLASH_TIMEOUT_MIN;
598 cfg->max = flash->cfg.flash_timeout_us;
599 cfg->step = AS_FLASH_TIMEOUT_STEP;
600 cfg->val = flash->cfg.flash_timeout_us;
601
602 flash->fled.ops = &as3645a_led_flash_ops;
603
604 fled_cdev->name = names->flash;
605 fled_cdev->brightness_set_blocking = as3645a_set_assist_brightness;
606 /* Value 0 is off in LED class. */
607 fled_cdev->max_brightness =
608 as3645a_current_to_reg(flash, false,
609 flash->cfg.assist_max_ua) + 1;
610 fled_cdev->flags = LED_DEV_CAP_FLASH | LED_CORE_SUSPENDRESUME;
611
612 rval = led_classdev_flash_register(&flash->client->dev, &flash->fled);
613 if (rval) {
614 led_classdev_unregister(iled_cdev);
615 dev_err(&flash->client->dev,
616 "led_classdev_flash_register() failed, error %d\n",
617 rval);
618 }
619
620 return rval;
621}
622
623static int as3645a_v4l2_setup(struct as3645a *flash)
624{
625 struct led_classdev_flash *fled = &flash->fled;
626 struct led_classdev *led = &fled->led_cdev;
627 struct v4l2_flash_config cfg = {
628 .intensity = {
629 .min = AS_TORCH_INTENSITY_MIN,
630 .max = flash->cfg.assist_max_ua,
631 .step = AS_TORCH_INTENSITY_STEP,
632 .val = flash->cfg.assist_max_ua,
633 },
634 };
635 struct v4l2_flash_config cfgind = {
636 .intensity = {
637 .min = AS_INDICATOR_INTENSITY_MIN,
638 .max = flash->cfg.indicator_max_ua,
639 .step = AS_INDICATOR_INTENSITY_STEP,
640 .val = flash->cfg.indicator_max_ua,
641 },
642 };
643
644 strlcpy(cfg.dev_name, led->name, sizeof(cfg.dev_name));
645 strlcpy(cfgind.dev_name, flash->iled_cdev.name, sizeof(cfg.dev_name));
646
647 flash->vf = v4l2_flash_init(
648 &flash->client->dev, of_fwnode_handle(flash->flash_node),
649 &flash->fled, NULL, &cfg);
650 if (IS_ERR(flash->vf))
651 return PTR_ERR(flash->vf);
652
653 flash->vfind = v4l2_flash_indicator_init(
654 &flash->client->dev, of_fwnode_handle(flash->indicator_node),
655 &flash->iled_cdev, &cfgind);
656 if (IS_ERR(flash->vfind)) {
657 v4l2_flash_release(flash->vf);
658 return PTR_ERR(flash->vfind);
659 }
660
661 return 0;
662}
663
664static int as3645a_probe(struct i2c_client *client)
665{
666 struct as3645a_names names;
667 struct as3645a *flash;
668 int rval;
669
670 if (client->dev.of_node == NULL)
671 return -ENODEV;
672
673 flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL);
674 if (flash == NULL)
675 return -ENOMEM;
676
677 flash->client = client;
678
679 rval = as3645a_parse_node(flash, &names, client->dev.of_node);
680 if (rval < 0)
681 return rval;
682
683 rval = as3645a_detect(flash);
684 if (rval < 0)
685 goto out_put_nodes;
686
687 mutex_init(&flash->mutex);
688 i2c_set_clientdata(client, flash);
689
690 rval = as3645a_setup(flash);
691 if (rval)
692 goto out_mutex_destroy;
693
694 rval = as3645a_led_class_setup(flash, &names);
695 if (rval)
696 goto out_mutex_destroy;
697
698 rval = as3645a_v4l2_setup(flash);
699 if (rval)
700 goto out_led_classdev_flash_unregister;
701
702 return 0;
703
704out_led_classdev_flash_unregister:
705 led_classdev_flash_unregister(&flash->fled);
706
707out_mutex_destroy:
708 mutex_destroy(&flash->mutex);
709
710out_put_nodes:
711 of_node_put(flash->flash_node);
712 of_node_put(flash->indicator_node);
713
714 return rval;
715}
716
717static int as3645a_remove(struct i2c_client *client)
718{
719 struct as3645a *flash = i2c_get_clientdata(client);
720
721 as3645a_set_control(flash, AS_MODE_EXT_TORCH, false);
722
723 v4l2_flash_release(flash->vf);
724
725 led_classdev_flash_unregister(&flash->fled);
726 led_classdev_unregister(&flash->iled_cdev);
727
728 mutex_destroy(&flash->mutex);
729
730 of_node_put(flash->flash_node);
731 of_node_put(flash->indicator_node);
732
733 return 0;
734}
735
736static const struct i2c_device_id as3645a_id_table[] = {
737 { AS_NAME, 0 },
738 { },
739};
740MODULE_DEVICE_TABLE(i2c, as3645a_id_table);
741
742static const struct of_device_id as3645a_of_table[] = {
743 { .compatible = "ams,as3645a" },
744 { },
745};
746MODULE_DEVICE_TABLE(of, as3645a_of_table);
747
748static struct i2c_driver as3645a_i2c_driver = {
749 .driver = {
750 .of_match_table = as3645a_of_table,
751 .name = AS_NAME,
752 },
753 .probe_new = as3645a_probe,
754 .remove = as3645a_remove,
755 .id_table = as3645a_id_table,
756};
757
758module_i2c_driver(as3645a_i2c_driver);
759
760MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
761MODULE_AUTHOR("Sakari Ailus <sakari.ailus@iki.fi>");
762MODULE_DESCRIPTION("LED flash driver for AS3645A, LM3555 and their clones");
763MODULE_LICENSE("GPL v2");