Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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