0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/delay.h>
0014 #include <linux/gpio/consumer.h>
0015 #include <linux/i2c.h>
0016 #include <linux/led-class-flash.h>
0017 #include <linux/leds.h>
0018 #include <linux/module.h>
0019 #include <linux/mutex.h>
0020 #include <linux/property.h>
0021 #include <linux/slab.h>
0022
0023 #include <media/v4l2-flash-led-class.h>
0024
0025 #define AS_TIMER_US_TO_CODE(t) (((t) / 1000 - 100) / 50)
0026 #define AS_TIMER_CODE_TO_US(c) ((50 * (c) + 100) * 1000)
0027
0028
0029
0030
0031 #define AS_DESIGN_INFO_REG 0x00
0032 #define AS_DESIGN_INFO_FACTORY(x) (((x) >> 4))
0033 #define AS_DESIGN_INFO_MODEL(x) ((x) & 0x0f)
0034
0035
0036
0037
0038 #define AS_VERSION_CONTROL_REG 0x01
0039 #define AS_VERSION_CONTROL_RFU(x) (((x) >> 4))
0040 #define AS_VERSION_CONTROL_VERSION(x) ((x) & 0x0f)
0041
0042
0043 #define AS_INDICATOR_AND_TIMER_REG 0x02
0044 #define AS_INDICATOR_AND_TIMER_TIMEOUT_SHIFT 0
0045 #define AS_INDICATOR_AND_TIMER_VREF_SHIFT 4
0046 #define AS_INDICATOR_AND_TIMER_INDICATOR_SHIFT 6
0047
0048
0049 #define AS_CURRENT_SET_REG 0x03
0050 #define AS_CURRENT_ASSIST_LIGHT_SHIFT 0
0051 #define AS_CURRENT_LED_DET_ON (1 << 3)
0052 #define AS_CURRENT_FLASH_CURRENT_SHIFT 4
0053
0054
0055 #define AS_CONTROL_REG 0x04
0056 #define AS_CONTROL_MODE_SETTING_SHIFT 0
0057 #define AS_CONTROL_STROBE_ON (1 << 2)
0058 #define AS_CONTROL_OUT_ON (1 << 3)
0059 #define AS_CONTROL_EXT_TORCH_ON (1 << 4)
0060 #define AS_CONTROL_STROBE_TYPE_EDGE (0 << 5)
0061 #define AS_CONTROL_STROBE_TYPE_LEVEL (1 << 5)
0062 #define AS_CONTROL_COIL_PEAK_SHIFT 6
0063
0064
0065 #define AS_FAULT_INFO_REG 0x05
0066 #define AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT (1 << 1)
0067 #define AS_FAULT_INFO_INDICATOR_LED (1 << 2)
0068 #define AS_FAULT_INFO_LED_AMOUNT (1 << 3)
0069 #define AS_FAULT_INFO_TIMEOUT (1 << 4)
0070 #define AS_FAULT_INFO_OVER_TEMPERATURE (1 << 5)
0071 #define AS_FAULT_INFO_SHORT_CIRCUIT (1 << 6)
0072 #define AS_FAULT_INFO_OVER_VOLTAGE (1 << 7)
0073
0074
0075 #define AS_BOOST_REG 0x0d
0076 #define AS_BOOST_CURRENT_DISABLE (0 << 0)
0077 #define AS_BOOST_CURRENT_ENABLE (1 << 0)
0078
0079
0080 #define AS_PASSWORD_REG 0x0f
0081 #define AS_PASSWORD_UNLOCK_VALUE 0x55
0082
0083 #define AS_NAME "as3645a"
0084 #define AS_I2C_ADDR (0x60 >> 1)
0085
0086 #define AS_FLASH_TIMEOUT_MIN 100000
0087 #define AS_FLASH_TIMEOUT_MAX 850000
0088 #define AS_FLASH_TIMEOUT_STEP 50000
0089
0090 #define AS_FLASH_INTENSITY_MIN 200000
0091 #define AS_FLASH_INTENSITY_MAX_1LED 500000
0092 #define AS_FLASH_INTENSITY_MAX_2LEDS 400000
0093 #define AS_FLASH_INTENSITY_STEP 20000
0094
0095 #define AS_TORCH_INTENSITY_MIN 20000
0096 #define AS_TORCH_INTENSITY_MAX 160000
0097 #define AS_TORCH_INTENSITY_STEP 20000
0098
0099 #define AS_INDICATOR_INTENSITY_MIN 0
0100 #define AS_INDICATOR_INTENSITY_MAX 10000
0101 #define AS_INDICATOR_INTENSITY_STEP 2500
0102
0103 #define AS_PEAK_mA_MAX 2000
0104 #define AS_PEAK_mA_TO_REG(a) \
0105 ((min_t(u32, AS_PEAK_mA_MAX, a) - 1250) / 250)
0106
0107
0108 #define AS_LED_FLASH 0
0109 #define AS_LED_INDICATOR 1
0110
0111 enum as_mode {
0112 AS_MODE_EXT_TORCH = 0 << AS_CONTROL_MODE_SETTING_SHIFT,
0113 AS_MODE_INDICATOR = 1 << AS_CONTROL_MODE_SETTING_SHIFT,
0114 AS_MODE_ASSIST = 2 << AS_CONTROL_MODE_SETTING_SHIFT,
0115 AS_MODE_FLASH = 3 << AS_CONTROL_MODE_SETTING_SHIFT,
0116 };
0117
0118 struct as3645a_config {
0119 u32 flash_timeout_us;
0120 u32 flash_max_ua;
0121 u32 assist_max_ua;
0122 u32 indicator_max_ua;
0123 u32 voltage_reference;
0124 u32 peak;
0125 };
0126
0127 struct as3645a {
0128 struct i2c_client *client;
0129
0130 struct mutex mutex;
0131
0132 struct led_classdev_flash fled;
0133 struct led_classdev iled_cdev;
0134
0135 struct v4l2_flash *vf;
0136 struct v4l2_flash *vfind;
0137
0138 struct fwnode_handle *flash_node;
0139 struct fwnode_handle *indicator_node;
0140
0141 struct as3645a_config cfg;
0142
0143 enum as_mode mode;
0144 unsigned int timeout;
0145 unsigned int flash_current;
0146 unsigned int assist_current;
0147 unsigned int indicator_current;
0148 enum v4l2_flash_strobe_source strobe_source;
0149 };
0150
0151 #define fled_to_as3645a(__fled) container_of(__fled, struct as3645a, fled)
0152 #define iled_cdev_to_as3645a(__iled_cdev) \
0153 container_of(__iled_cdev, struct as3645a, iled_cdev)
0154
0155
0156 static int as3645a_write(struct as3645a *flash, u8 addr, u8 val)
0157 {
0158 struct i2c_client *client = flash->client;
0159 int rval;
0160
0161 rval = i2c_smbus_write_byte_data(client, addr, val);
0162
0163 dev_dbg(&client->dev, "Write Addr:%02X Val:%02X %s\n", addr, val,
0164 rval < 0 ? "fail" : "ok");
0165
0166 return rval;
0167 }
0168
0169
0170 static int as3645a_read(struct as3645a *flash, u8 addr)
0171 {
0172 struct i2c_client *client = flash->client;
0173 int rval;
0174
0175 rval = i2c_smbus_read_byte_data(client, addr);
0176
0177 dev_dbg(&client->dev, "Read Addr:%02X Val:%02X %s\n", addr, rval,
0178 rval < 0 ? "fail" : "ok");
0179
0180 return rval;
0181 }
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197 static int as3645a_set_current(struct as3645a *flash)
0198 {
0199 u8 val;
0200
0201 val = (flash->flash_current << AS_CURRENT_FLASH_CURRENT_SHIFT)
0202 | (flash->assist_current << AS_CURRENT_ASSIST_LIGHT_SHIFT)
0203 | AS_CURRENT_LED_DET_ON;
0204
0205 return as3645a_write(flash, AS_CURRENT_SET_REG, val);
0206 }
0207
0208 static int as3645a_set_timeout(struct as3645a *flash)
0209 {
0210 u8 val;
0211
0212 val = flash->timeout << AS_INDICATOR_AND_TIMER_TIMEOUT_SHIFT;
0213
0214 val |= (flash->cfg.voltage_reference
0215 << AS_INDICATOR_AND_TIMER_VREF_SHIFT)
0216 | ((flash->indicator_current ? flash->indicator_current - 1 : 0)
0217 << AS_INDICATOR_AND_TIMER_INDICATOR_SHIFT);
0218
0219 return as3645a_write(flash, AS_INDICATOR_AND_TIMER_REG, val);
0220 }
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233 static int
0234 as3645a_set_control(struct as3645a *flash, enum as_mode mode, bool on)
0235 {
0236 u8 reg;
0237
0238
0239 reg = (flash->cfg.peak << AS_CONTROL_COIL_PEAK_SHIFT)
0240 | (on ? AS_CONTROL_OUT_ON : 0)
0241 | mode;
0242
0243 if (mode == AS_MODE_FLASH &&
0244 flash->strobe_source == V4L2_FLASH_STROBE_SOURCE_EXTERNAL)
0245 reg |= AS_CONTROL_STROBE_TYPE_LEVEL
0246 | AS_CONTROL_STROBE_ON;
0247
0248 return as3645a_write(flash, AS_CONTROL_REG, reg);
0249 }
0250
0251 static int as3645a_get_fault(struct led_classdev_flash *fled, u32 *fault)
0252 {
0253 struct as3645a *flash = fled_to_as3645a(fled);
0254 int rval;
0255
0256
0257 rval = as3645a_read(flash, AS_FAULT_INFO_REG);
0258 if (rval < 0)
0259 return rval;
0260
0261 if (rval & AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT)
0262 *fault |= LED_FAULT_OVER_CURRENT;
0263
0264 if (rval & AS_FAULT_INFO_INDICATOR_LED)
0265 *fault |= LED_FAULT_INDICATOR;
0266
0267 dev_dbg(&flash->client->dev, "%u connected LEDs\n",
0268 rval & AS_FAULT_INFO_LED_AMOUNT ? 2 : 1);
0269
0270 if (rval & AS_FAULT_INFO_TIMEOUT)
0271 *fault |= LED_FAULT_TIMEOUT;
0272
0273 if (rval & AS_FAULT_INFO_OVER_TEMPERATURE)
0274 *fault |= LED_FAULT_OVER_TEMPERATURE;
0275
0276 if (rval & AS_FAULT_INFO_SHORT_CIRCUIT)
0277 *fault |= LED_FAULT_OVER_CURRENT;
0278
0279 if (rval & AS_FAULT_INFO_OVER_VOLTAGE)
0280 *fault |= LED_FAULT_INPUT_VOLTAGE;
0281
0282 return rval;
0283 }
0284
0285 static unsigned int __as3645a_current_to_reg(unsigned int min, unsigned int max,
0286 unsigned int step,
0287 unsigned int val)
0288 {
0289 if (val < min)
0290 val = min;
0291
0292 if (val > max)
0293 val = max;
0294
0295 return (val - min) / step;
0296 }
0297
0298 static unsigned int as3645a_current_to_reg(struct as3645a *flash, bool is_flash,
0299 unsigned int ua)
0300 {
0301 if (is_flash)
0302 return __as3645a_current_to_reg(AS_TORCH_INTENSITY_MIN,
0303 flash->cfg.assist_max_ua,
0304 AS_TORCH_INTENSITY_STEP, ua);
0305 else
0306 return __as3645a_current_to_reg(AS_FLASH_INTENSITY_MIN,
0307 flash->cfg.flash_max_ua,
0308 AS_FLASH_INTENSITY_STEP, ua);
0309 }
0310
0311 static int as3645a_set_indicator_brightness(struct led_classdev *iled_cdev,
0312 enum led_brightness brightness)
0313 {
0314 struct as3645a *flash = iled_cdev_to_as3645a(iled_cdev);
0315 int rval;
0316
0317 flash->indicator_current = brightness;
0318
0319 rval = as3645a_set_timeout(flash);
0320 if (rval)
0321 return rval;
0322
0323 return as3645a_set_control(flash, AS_MODE_INDICATOR, brightness);
0324 }
0325
0326 static int as3645a_set_assist_brightness(struct led_classdev *fled_cdev,
0327 enum led_brightness brightness)
0328 {
0329 struct led_classdev_flash *fled = lcdev_to_flcdev(fled_cdev);
0330 struct as3645a *flash = fled_to_as3645a(fled);
0331 int rval;
0332
0333 if (brightness) {
0334
0335 flash->assist_current = brightness - 1;
0336
0337 rval = as3645a_set_current(flash);
0338 if (rval)
0339 return rval;
0340 }
0341
0342 return as3645a_set_control(flash, AS_MODE_ASSIST, brightness);
0343 }
0344
0345 static int as3645a_set_flash_brightness(struct led_classdev_flash *fled,
0346 u32 brightness_ua)
0347 {
0348 struct as3645a *flash = fled_to_as3645a(fled);
0349
0350 flash->flash_current = as3645a_current_to_reg(flash, true,
0351 brightness_ua);
0352
0353 return as3645a_set_current(flash);
0354 }
0355
0356 static int as3645a_set_flash_timeout(struct led_classdev_flash *fled,
0357 u32 timeout_us)
0358 {
0359 struct as3645a *flash = fled_to_as3645a(fled);
0360
0361 flash->timeout = AS_TIMER_US_TO_CODE(timeout_us);
0362
0363 return as3645a_set_timeout(flash);
0364 }
0365
0366 static int as3645a_set_strobe(struct led_classdev_flash *fled, bool state)
0367 {
0368 struct as3645a *flash = fled_to_as3645a(fled);
0369
0370 return as3645a_set_control(flash, AS_MODE_FLASH, state);
0371 }
0372
0373 static const struct led_flash_ops as3645a_led_flash_ops = {
0374 .flash_brightness_set = as3645a_set_flash_brightness,
0375 .timeout_set = as3645a_set_flash_timeout,
0376 .strobe_set = as3645a_set_strobe,
0377 .fault_get = as3645a_get_fault,
0378 };
0379
0380 static int as3645a_setup(struct as3645a *flash)
0381 {
0382 struct device *dev = &flash->client->dev;
0383 u32 fault = 0;
0384 int rval;
0385
0386
0387 rval = as3645a_read(flash, AS_FAULT_INFO_REG);
0388 if (rval < 0)
0389 return rval;
0390
0391 dev_dbg(dev, "Fault info: %02x\n", rval);
0392
0393 rval = as3645a_set_current(flash);
0394 if (rval < 0)
0395 return rval;
0396
0397 rval = as3645a_set_timeout(flash);
0398 if (rval < 0)
0399 return rval;
0400
0401 rval = as3645a_set_control(flash, AS_MODE_INDICATOR, false);
0402 if (rval < 0)
0403 return rval;
0404
0405
0406 rval = as3645a_get_fault(&flash->fled, &fault);
0407 if (rval < 0)
0408 return rval;
0409
0410 dev_dbg(dev, "AS_INDICATOR_AND_TIMER_REG: %02x\n",
0411 as3645a_read(flash, AS_INDICATOR_AND_TIMER_REG));
0412 dev_dbg(dev, "AS_CURRENT_SET_REG: %02x\n",
0413 as3645a_read(flash, AS_CURRENT_SET_REG));
0414 dev_dbg(dev, "AS_CONTROL_REG: %02x\n",
0415 as3645a_read(flash, AS_CONTROL_REG));
0416
0417 return rval & ~AS_FAULT_INFO_LED_AMOUNT ? -EIO : 0;
0418 }
0419
0420 static int as3645a_detect(struct as3645a *flash)
0421 {
0422 struct device *dev = &flash->client->dev;
0423 int rval, man, model, rfu, version;
0424 const char *vendor;
0425
0426 rval = as3645a_read(flash, AS_DESIGN_INFO_REG);
0427 if (rval < 0) {
0428 dev_err(dev, "can't read design info reg\n");
0429 return rval;
0430 }
0431
0432 man = AS_DESIGN_INFO_FACTORY(rval);
0433 model = AS_DESIGN_INFO_MODEL(rval);
0434
0435 rval = as3645a_read(flash, AS_VERSION_CONTROL_REG);
0436 if (rval < 0) {
0437 dev_err(dev, "can't read version control reg\n");
0438 return rval;
0439 }
0440
0441 rfu = AS_VERSION_CONTROL_RFU(rval);
0442 version = AS_VERSION_CONTROL_VERSION(rval);
0443
0444
0445 if (model != 0x01 || rfu != 0x00) {
0446 dev_err(dev, "AS3645A not detected (model %d rfu %d)\n",
0447 model, rfu);
0448 return -ENODEV;
0449 }
0450
0451 switch (man) {
0452 case 1:
0453 vendor = "AMS, Austria Micro Systems";
0454 break;
0455 case 2:
0456 vendor = "ADI, Analog Devices Inc.";
0457 break;
0458 case 3:
0459 vendor = "NSC, National Semiconductor";
0460 break;
0461 case 4:
0462 vendor = "NXP";
0463 break;
0464 case 5:
0465 vendor = "TI, Texas Instrument";
0466 break;
0467 default:
0468 vendor = "Unknown";
0469 }
0470
0471 dev_info(dev, "Chip vendor: %s (%d) Version: %d\n", vendor,
0472 man, version);
0473
0474 rval = as3645a_write(flash, AS_PASSWORD_REG, AS_PASSWORD_UNLOCK_VALUE);
0475 if (rval < 0)
0476 return rval;
0477
0478 return as3645a_write(flash, AS_BOOST_REG, AS_BOOST_CURRENT_DISABLE);
0479 }
0480
0481 static int as3645a_parse_node(struct as3645a *flash,
0482 struct fwnode_handle *fwnode)
0483 {
0484 struct as3645a_config *cfg = &flash->cfg;
0485 struct fwnode_handle *child;
0486 int rval;
0487
0488 fwnode_for_each_child_node(fwnode, child) {
0489 u32 id = 0;
0490
0491 fwnode_property_read_u32(child, "reg", &id);
0492
0493 switch (id) {
0494 case AS_LED_FLASH:
0495 flash->flash_node = child;
0496 fwnode_handle_get(child);
0497 break;
0498 case AS_LED_INDICATOR:
0499 flash->indicator_node = child;
0500 fwnode_handle_get(child);
0501 break;
0502 default:
0503 dev_warn(&flash->client->dev,
0504 "unknown LED %u encountered, ignoring\n", id);
0505 break;
0506 }
0507 }
0508
0509 if (!flash->flash_node) {
0510 dev_err(&flash->client->dev, "can't find flash node\n");
0511 return -ENODEV;
0512 }
0513
0514 rval = fwnode_property_read_u32(flash->flash_node, "flash-timeout-us",
0515 &cfg->flash_timeout_us);
0516 if (rval < 0) {
0517 dev_err(&flash->client->dev,
0518 "can't read flash-timeout-us property for flash\n");
0519 goto out_err;
0520 }
0521
0522 rval = fwnode_property_read_u32(flash->flash_node, "flash-max-microamp",
0523 &cfg->flash_max_ua);
0524 if (rval < 0) {
0525 dev_err(&flash->client->dev,
0526 "can't read flash-max-microamp property for flash\n");
0527 goto out_err;
0528 }
0529
0530 rval = fwnode_property_read_u32(flash->flash_node, "led-max-microamp",
0531 &cfg->assist_max_ua);
0532 if (rval < 0) {
0533 dev_err(&flash->client->dev,
0534 "can't read led-max-microamp property for flash\n");
0535 goto out_err;
0536 }
0537
0538 fwnode_property_read_u32(flash->flash_node, "voltage-reference",
0539 &cfg->voltage_reference);
0540
0541 fwnode_property_read_u32(flash->flash_node, "ams,input-max-microamp",
0542 &cfg->peak);
0543 cfg->peak = AS_PEAK_mA_TO_REG(cfg->peak);
0544
0545 if (!flash->indicator_node) {
0546 dev_warn(&flash->client->dev,
0547 "can't find indicator node\n");
0548 rval = -ENODEV;
0549 goto out_err;
0550 }
0551
0552
0553 rval = fwnode_property_read_u32(flash->indicator_node,
0554 "led-max-microamp",
0555 &cfg->indicator_max_ua);
0556 if (rval < 0) {
0557 dev_err(&flash->client->dev,
0558 "can't read led-max-microamp property for indicator\n");
0559 goto out_err;
0560 }
0561
0562 return 0;
0563
0564 out_err:
0565 fwnode_handle_put(flash->flash_node);
0566 fwnode_handle_put(flash->indicator_node);
0567
0568 return rval;
0569 }
0570
0571 static int as3645a_led_class_setup(struct as3645a *flash)
0572 {
0573 struct led_classdev *fled_cdev = &flash->fled.led_cdev;
0574 struct led_classdev *iled_cdev = &flash->iled_cdev;
0575 struct led_init_data init_data = {};
0576 struct led_flash_setting *cfg;
0577 int rval;
0578
0579 iled_cdev->brightness_set_blocking = as3645a_set_indicator_brightness;
0580 iled_cdev->max_brightness =
0581 flash->cfg.indicator_max_ua / AS_INDICATOR_INTENSITY_STEP;
0582 iled_cdev->flags = LED_CORE_SUSPENDRESUME;
0583
0584 init_data.fwnode = flash->indicator_node;
0585 init_data.devicename = AS_NAME;
0586 init_data.default_label = "indicator";
0587
0588 rval = led_classdev_register_ext(&flash->client->dev, iled_cdev,
0589 &init_data);
0590 if (rval < 0)
0591 return rval;
0592
0593 cfg = &flash->fled.brightness;
0594 cfg->min = AS_FLASH_INTENSITY_MIN;
0595 cfg->max = flash->cfg.flash_max_ua;
0596 cfg->step = AS_FLASH_INTENSITY_STEP;
0597 cfg->val = flash->cfg.flash_max_ua;
0598
0599 cfg = &flash->fled.timeout;
0600 cfg->min = AS_FLASH_TIMEOUT_MIN;
0601 cfg->max = flash->cfg.flash_timeout_us;
0602 cfg->step = AS_FLASH_TIMEOUT_STEP;
0603 cfg->val = flash->cfg.flash_timeout_us;
0604
0605 flash->fled.ops = &as3645a_led_flash_ops;
0606
0607 fled_cdev->brightness_set_blocking = as3645a_set_assist_brightness;
0608
0609 fled_cdev->max_brightness =
0610 as3645a_current_to_reg(flash, false,
0611 flash->cfg.assist_max_ua) + 1;
0612 fled_cdev->flags = LED_DEV_CAP_FLASH | LED_CORE_SUSPENDRESUME;
0613
0614 init_data.fwnode = flash->flash_node;
0615 init_data.devicename = AS_NAME;
0616 init_data.default_label = "flash";
0617
0618 rval = led_classdev_flash_register_ext(&flash->client->dev,
0619 &flash->fled, &init_data);
0620 if (rval)
0621 goto out_err;
0622
0623 return rval;
0624
0625 out_err:
0626 led_classdev_unregister(iled_cdev);
0627 dev_err(&flash->client->dev,
0628 "led_classdev_flash_register() failed, error %d\n",
0629 rval);
0630 return rval;
0631 }
0632
0633 static int as3645a_v4l2_setup(struct as3645a *flash)
0634 {
0635 struct led_classdev_flash *fled = &flash->fled;
0636 struct led_classdev *led = &fled->led_cdev;
0637 struct v4l2_flash_config cfg = {
0638 .intensity = {
0639 .min = AS_TORCH_INTENSITY_MIN,
0640 .max = flash->cfg.assist_max_ua,
0641 .step = AS_TORCH_INTENSITY_STEP,
0642 .val = flash->cfg.assist_max_ua,
0643 },
0644 };
0645 struct v4l2_flash_config cfgind = {
0646 .intensity = {
0647 .min = AS_INDICATOR_INTENSITY_MIN,
0648 .max = flash->cfg.indicator_max_ua,
0649 .step = AS_INDICATOR_INTENSITY_STEP,
0650 .val = flash->cfg.indicator_max_ua,
0651 },
0652 };
0653
0654 strlcpy(cfg.dev_name, led->dev->kobj.name, sizeof(cfg.dev_name));
0655 strlcpy(cfgind.dev_name, flash->iled_cdev.dev->kobj.name,
0656 sizeof(cfgind.dev_name));
0657
0658 flash->vf = v4l2_flash_init(
0659 &flash->client->dev, flash->flash_node, &flash->fled, NULL,
0660 &cfg);
0661 if (IS_ERR(flash->vf))
0662 return PTR_ERR(flash->vf);
0663
0664 flash->vfind = v4l2_flash_indicator_init(
0665 &flash->client->dev, flash->indicator_node, &flash->iled_cdev,
0666 &cfgind);
0667 if (IS_ERR(flash->vfind)) {
0668 v4l2_flash_release(flash->vf);
0669 return PTR_ERR(flash->vfind);
0670 }
0671
0672 return 0;
0673 }
0674
0675 static int as3645a_probe(struct i2c_client *client)
0676 {
0677 struct as3645a *flash;
0678 int rval;
0679
0680 if (!dev_fwnode(&client->dev))
0681 return -ENODEV;
0682
0683 flash = devm_kzalloc(&client->dev, sizeof(*flash), GFP_KERNEL);
0684 if (flash == NULL)
0685 return -ENOMEM;
0686
0687 flash->client = client;
0688
0689 rval = as3645a_parse_node(flash, dev_fwnode(&client->dev));
0690 if (rval < 0)
0691 return rval;
0692
0693 rval = as3645a_detect(flash);
0694 if (rval < 0)
0695 goto out_put_nodes;
0696
0697 mutex_init(&flash->mutex);
0698 i2c_set_clientdata(client, flash);
0699
0700 rval = as3645a_setup(flash);
0701 if (rval)
0702 goto out_mutex_destroy;
0703
0704 rval = as3645a_led_class_setup(flash);
0705 if (rval)
0706 goto out_mutex_destroy;
0707
0708 rval = as3645a_v4l2_setup(flash);
0709 if (rval)
0710 goto out_led_classdev_flash_unregister;
0711
0712 return 0;
0713
0714 out_led_classdev_flash_unregister:
0715 led_classdev_flash_unregister(&flash->fled);
0716
0717 out_mutex_destroy:
0718 mutex_destroy(&flash->mutex);
0719
0720 out_put_nodes:
0721 fwnode_handle_put(flash->flash_node);
0722 fwnode_handle_put(flash->indicator_node);
0723
0724 return rval;
0725 }
0726
0727 static int as3645a_remove(struct i2c_client *client)
0728 {
0729 struct as3645a *flash = i2c_get_clientdata(client);
0730
0731 as3645a_set_control(flash, AS_MODE_EXT_TORCH, false);
0732
0733 v4l2_flash_release(flash->vf);
0734 v4l2_flash_release(flash->vfind);
0735
0736 led_classdev_flash_unregister(&flash->fled);
0737 led_classdev_unregister(&flash->iled_cdev);
0738
0739 mutex_destroy(&flash->mutex);
0740
0741 fwnode_handle_put(flash->flash_node);
0742 fwnode_handle_put(flash->indicator_node);
0743
0744 return 0;
0745 }
0746
0747 static const struct i2c_device_id as3645a_id_table[] = {
0748 { AS_NAME, 0 },
0749 { },
0750 };
0751 MODULE_DEVICE_TABLE(i2c, as3645a_id_table);
0752
0753 static const struct of_device_id as3645a_of_table[] = {
0754 { .compatible = "ams,as3645a" },
0755 { },
0756 };
0757 MODULE_DEVICE_TABLE(of, as3645a_of_table);
0758
0759 static struct i2c_driver as3645a_i2c_driver = {
0760 .driver = {
0761 .of_match_table = as3645a_of_table,
0762 .name = AS_NAME,
0763 },
0764 .probe_new = as3645a_probe,
0765 .remove = as3645a_remove,
0766 .id_table = as3645a_id_table,
0767 };
0768
0769 module_i2c_driver(as3645a_i2c_driver);
0770
0771 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
0772 MODULE_AUTHOR("Sakari Ailus <sakari.ailus@iki.fi>");
0773 MODULE_DESCRIPTION("LED flash driver for AS3645A, LM3555 and their clones");
0774 MODULE_LICENSE("GPL v2");