root/drivers/leds/leds-as3645a.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. as3645a_write
  2. as3645a_read
  3. as3645a_set_current
  4. as3645a_set_timeout
  5. as3645a_set_control
  6. as3645a_get_fault
  7. __as3645a_current_to_reg
  8. as3645a_current_to_reg
  9. as3645a_set_indicator_brightness
  10. as3645a_set_assist_brightness
  11. as3645a_set_flash_brightness
  12. as3645a_set_flash_timeout
  13. as3645a_set_strobe
  14. as3645a_setup
  15. as3645a_detect
  16. as3645a_parse_node
  17. as3645a_led_class_setup
  18. as3645a_v4l2_setup
  19. as3645a_probe
  20. as3645a_remove

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

/* [<][>][^][v][top][bottom][index][help] */