1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 28b7cfbecSG.Shark Jeong /* 38b7cfbecSG.Shark Jeong * Simple driver for Texas Instruments LM3642 LED Flash driver chip 48b7cfbecSG.Shark Jeong * Copyright (C) 2012 Texas Instruments 58b7cfbecSG.Shark Jeong */ 68b7cfbecSG.Shark Jeong #include <linux/module.h> 78b7cfbecSG.Shark Jeong #include <linux/delay.h> 88b7cfbecSG.Shark Jeong #include <linux/i2c.h> 98b7cfbecSG.Shark Jeong #include <linux/leds.h> 108b7cfbecSG.Shark Jeong #include <linux/slab.h> 118b7cfbecSG.Shark Jeong #include <linux/platform_device.h> 128b7cfbecSG.Shark Jeong #include <linux/fs.h> 138b7cfbecSG.Shark Jeong #include <linux/regmap.h> 148b7cfbecSG.Shark Jeong #include <linux/platform_data/leds-lm3642.h> 158b7cfbecSG.Shark Jeong 168b7cfbecSG.Shark Jeong #define REG_FILT_TIME (0x0) 178b7cfbecSG.Shark Jeong #define REG_IVFM_MODE (0x1) 188b7cfbecSG.Shark Jeong #define REG_TORCH_TIME (0x6) 198b7cfbecSG.Shark Jeong #define REG_FLASH (0x8) 208b7cfbecSG.Shark Jeong #define REG_I_CTRL (0x9) 218b7cfbecSG.Shark Jeong #define REG_ENABLE (0xA) 228b7cfbecSG.Shark Jeong #define REG_FLAG (0xB) 238b7cfbecSG.Shark Jeong #define REG_MAX (0xB) 248b7cfbecSG.Shark Jeong 258b7cfbecSG.Shark Jeong #define UVLO_EN_SHIFT (7) 268b7cfbecSG.Shark Jeong #define IVM_D_TH_SHIFT (2) 278b7cfbecSG.Shark Jeong #define TORCH_RAMP_UP_TIME_SHIFT (3) 288b7cfbecSG.Shark Jeong #define TORCH_RAMP_DN_TIME_SHIFT (0) 298b7cfbecSG.Shark Jeong #define INDUCTOR_I_LIMIT_SHIFT (6) 308b7cfbecSG.Shark Jeong #define FLASH_RAMP_TIME_SHIFT (3) 318b7cfbecSG.Shark Jeong #define FLASH_TOUT_TIME_SHIFT (0) 328b7cfbecSG.Shark Jeong #define TORCH_I_SHIFT (4) 338b7cfbecSG.Shark Jeong #define FLASH_I_SHIFT (0) 348b7cfbecSG.Shark Jeong #define IVFM_SHIFT (7) 358b7cfbecSG.Shark Jeong #define TX_PIN_EN_SHIFT (6) 368b7cfbecSG.Shark Jeong #define STROBE_PIN_EN_SHIFT (5) 378b7cfbecSG.Shark Jeong #define TORCH_PIN_EN_SHIFT (4) 388b7cfbecSG.Shark Jeong #define MODE_BITS_SHIFT (0) 398b7cfbecSG.Shark Jeong 408b7cfbecSG.Shark Jeong #define UVLO_EN_MASK (0x1) 418b7cfbecSG.Shark Jeong #define IVM_D_TH_MASK (0x7) 428b7cfbecSG.Shark Jeong #define TORCH_RAMP_UP_TIME_MASK (0x7) 438b7cfbecSG.Shark Jeong #define TORCH_RAMP_DN_TIME_MASK (0x7) 448b7cfbecSG.Shark Jeong #define INDUCTOR_I_LIMIT_MASK (0x1) 458b7cfbecSG.Shark Jeong #define FLASH_RAMP_TIME_MASK (0x7) 468b7cfbecSG.Shark Jeong #define FLASH_TOUT_TIME_MASK (0x7) 478b7cfbecSG.Shark Jeong #define TORCH_I_MASK (0x7) 488b7cfbecSG.Shark Jeong #define FLASH_I_MASK (0xF) 498b7cfbecSG.Shark Jeong #define IVFM_MASK (0x1) 508b7cfbecSG.Shark Jeong #define TX_PIN_EN_MASK (0x1) 518b7cfbecSG.Shark Jeong #define STROBE_PIN_EN_MASK (0x1) 528b7cfbecSG.Shark Jeong #define TORCH_PIN_EN_MASK (0x1) 538b7cfbecSG.Shark Jeong #define MODE_BITS_MASK (0x73) 548b7cfbecSG.Shark Jeong #define EX_PIN_CONTROL_MASK (0x71) 558b7cfbecSG.Shark Jeong #define EX_PIN_ENABLE_MASK (0x70) 568b7cfbecSG.Shark Jeong 578b7cfbecSG.Shark Jeong enum lm3642_mode { 588b7cfbecSG.Shark Jeong MODES_STASNDBY = 0, 598b7cfbecSG.Shark Jeong MODES_INDIC, 608b7cfbecSG.Shark Jeong MODES_TORCH, 618b7cfbecSG.Shark Jeong MODES_FLASH 628b7cfbecSG.Shark Jeong }; 638b7cfbecSG.Shark Jeong 648b7cfbecSG.Shark Jeong struct lm3642_chip_data { 658b7cfbecSG.Shark Jeong struct device *dev; 668b7cfbecSG.Shark Jeong 678b7cfbecSG.Shark Jeong struct led_classdev cdev_flash; 688b7cfbecSG.Shark Jeong struct led_classdev cdev_torch; 698b7cfbecSG.Shark Jeong struct led_classdev cdev_indicator; 708b7cfbecSG.Shark Jeong 718b7cfbecSG.Shark Jeong u8 br_flash; 728b7cfbecSG.Shark Jeong u8 br_torch; 738b7cfbecSG.Shark Jeong u8 br_indicator; 748b7cfbecSG.Shark Jeong 758b7cfbecSG.Shark Jeong enum lm3642_torch_pin_enable torch_pin; 768b7cfbecSG.Shark Jeong enum lm3642_strobe_pin_enable strobe_pin; 778b7cfbecSG.Shark Jeong enum lm3642_tx_pin_enable tx_pin; 788b7cfbecSG.Shark Jeong 798b7cfbecSG.Shark Jeong struct lm3642_platform_data *pdata; 808b7cfbecSG.Shark Jeong struct regmap *regmap; 818b7cfbecSG.Shark Jeong struct mutex lock; 828b7cfbecSG.Shark Jeong 838b7cfbecSG.Shark Jeong unsigned int last_flag; 848b7cfbecSG.Shark Jeong }; 858b7cfbecSG.Shark Jeong 868b7cfbecSG.Shark Jeong /* chip initialize */ 8798ea1ea2SBill Pemberton static int lm3642_chip_init(struct lm3642_chip_data *chip) 888b7cfbecSG.Shark Jeong { 898b7cfbecSG.Shark Jeong int ret; 908b7cfbecSG.Shark Jeong struct lm3642_platform_data *pdata = chip->pdata; 918b7cfbecSG.Shark Jeong 928b7cfbecSG.Shark Jeong /* set enable register */ 93e76a322aSAxel Lin ret = regmap_update_bits(chip->regmap, REG_ENABLE, EX_PIN_ENABLE_MASK, 94e76a322aSAxel Lin pdata->tx_pin); 958b7cfbecSG.Shark Jeong if (ret < 0) 96e76a322aSAxel Lin dev_err(chip->dev, "Failed to update REG_ENABLE Register\n"); 978b7cfbecSG.Shark Jeong return ret; 988b7cfbecSG.Shark Jeong } 998b7cfbecSG.Shark Jeong 1008b7cfbecSG.Shark Jeong /* chip control */ 1018b7cfbecSG.Shark Jeong static int lm3642_control(struct lm3642_chip_data *chip, 1028b7cfbecSG.Shark Jeong u8 brightness, enum lm3642_mode opmode) 1038b7cfbecSG.Shark Jeong { 1048b7cfbecSG.Shark Jeong int ret; 1058b7cfbecSG.Shark Jeong 1068b7cfbecSG.Shark Jeong ret = regmap_read(chip->regmap, REG_FLAG, &chip->last_flag); 1078b7cfbecSG.Shark Jeong if (ret < 0) { 1088b7cfbecSG.Shark Jeong dev_err(chip->dev, "Failed to read REG_FLAG Register\n"); 109867b6824SPavel Machek return ret; 1108b7cfbecSG.Shark Jeong } 1118b7cfbecSG.Shark Jeong 1128b7cfbecSG.Shark Jeong if (chip->last_flag) 1138b7cfbecSG.Shark Jeong dev_info(chip->dev, "Last FLAG is 0x%x\n", chip->last_flag); 1148b7cfbecSG.Shark Jeong 1158b7cfbecSG.Shark Jeong /* brightness 0 means off-state */ 1168b7cfbecSG.Shark Jeong if (!brightness) 1178b7cfbecSG.Shark Jeong opmode = MODES_STASNDBY; 1188b7cfbecSG.Shark Jeong 1198b7cfbecSG.Shark Jeong switch (opmode) { 1208b7cfbecSG.Shark Jeong case MODES_TORCH: 1218b7cfbecSG.Shark Jeong ret = regmap_update_bits(chip->regmap, REG_I_CTRL, 1228b7cfbecSG.Shark Jeong TORCH_I_MASK << TORCH_I_SHIFT, 1238b7cfbecSG.Shark Jeong (brightness - 1) << TORCH_I_SHIFT); 1248b7cfbecSG.Shark Jeong 1258b7cfbecSG.Shark Jeong if (chip->torch_pin) 1268b7cfbecSG.Shark Jeong opmode |= (TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT); 1278b7cfbecSG.Shark Jeong break; 1288b7cfbecSG.Shark Jeong 1298b7cfbecSG.Shark Jeong case MODES_FLASH: 1308b7cfbecSG.Shark Jeong ret = regmap_update_bits(chip->regmap, REG_I_CTRL, 1318b7cfbecSG.Shark Jeong FLASH_I_MASK << FLASH_I_SHIFT, 1328b7cfbecSG.Shark Jeong (brightness - 1) << FLASH_I_SHIFT); 1338b7cfbecSG.Shark Jeong 1348b7cfbecSG.Shark Jeong if (chip->strobe_pin) 1358b7cfbecSG.Shark Jeong opmode |= (STROBE_PIN_EN_MASK << STROBE_PIN_EN_SHIFT); 1368b7cfbecSG.Shark Jeong break; 1378b7cfbecSG.Shark Jeong 1388b7cfbecSG.Shark Jeong case MODES_INDIC: 1398b7cfbecSG.Shark Jeong ret = regmap_update_bits(chip->regmap, REG_I_CTRL, 1408b7cfbecSG.Shark Jeong TORCH_I_MASK << TORCH_I_SHIFT, 1418b7cfbecSG.Shark Jeong (brightness - 1) << TORCH_I_SHIFT); 1428b7cfbecSG.Shark Jeong break; 1438b7cfbecSG.Shark Jeong 1448b7cfbecSG.Shark Jeong case MODES_STASNDBY: 1458b7cfbecSG.Shark Jeong 1468b7cfbecSG.Shark Jeong break; 1478b7cfbecSG.Shark Jeong 1488b7cfbecSG.Shark Jeong default: 149867b6824SPavel Machek return -EINVAL; 1508b7cfbecSG.Shark Jeong } 1518b7cfbecSG.Shark Jeong if (ret < 0) { 1528b7cfbecSG.Shark Jeong dev_err(chip->dev, "Failed to write REG_I_CTRL Register\n"); 153867b6824SPavel Machek return ret; 1548b7cfbecSG.Shark Jeong } 1558b7cfbecSG.Shark Jeong 1568b7cfbecSG.Shark Jeong if (chip->tx_pin) 1578b7cfbecSG.Shark Jeong opmode |= (TX_PIN_EN_MASK << TX_PIN_EN_SHIFT); 1588b7cfbecSG.Shark Jeong 1598b7cfbecSG.Shark Jeong ret = regmap_update_bits(chip->regmap, REG_ENABLE, 1608b7cfbecSG.Shark Jeong MODE_BITS_MASK << MODE_BITS_SHIFT, 1618b7cfbecSG.Shark Jeong opmode << MODE_BITS_SHIFT); 1628b7cfbecSG.Shark Jeong return ret; 1638b7cfbecSG.Shark Jeong } 1648b7cfbecSG.Shark Jeong 1658b7cfbecSG.Shark Jeong /* torch */ 1668b7cfbecSG.Shark Jeong 1678b7cfbecSG.Shark Jeong /* torch pin config for lm3642 */ 1685ccfa39dSDwaipayan Ray static ssize_t torch_pin_store(struct device *dev, 16985b4b756SJingoo Han struct device_attribute *attr, 1708b7cfbecSG.Shark Jeong const char *buf, size_t size) 1718b7cfbecSG.Shark Jeong { 1728b7cfbecSG.Shark Jeong ssize_t ret; 1738b7cfbecSG.Shark Jeong struct led_classdev *led_cdev = dev_get_drvdata(dev); 1748b7cfbecSG.Shark Jeong struct lm3642_chip_data *chip = 1758b7cfbecSG.Shark Jeong container_of(led_cdev, struct lm3642_chip_data, cdev_indicator); 1768b7cfbecSG.Shark Jeong unsigned int state; 1778b7cfbecSG.Shark Jeong 1788b7cfbecSG.Shark Jeong ret = kstrtouint(buf, 10, &state); 1798b7cfbecSG.Shark Jeong if (ret) 180867b6824SPavel Machek return ret; 1818b7cfbecSG.Shark Jeong if (state != 0) 1828b7cfbecSG.Shark Jeong state = 0x01 << TORCH_PIN_EN_SHIFT; 1838b7cfbecSG.Shark Jeong 1848b7cfbecSG.Shark Jeong chip->torch_pin = state; 1858b7cfbecSG.Shark Jeong ret = regmap_update_bits(chip->regmap, REG_ENABLE, 1868b7cfbecSG.Shark Jeong TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT, 1878b7cfbecSG.Shark Jeong state); 188867b6824SPavel Machek if (ret < 0) { 1898b7cfbecSG.Shark Jeong dev_err(chip->dev, "%s:i2c access fail to register\n", __func__); 190eccb6638SAxel Lin return ret; 191867b6824SPavel Machek } 192867b6824SPavel Machek 193867b6824SPavel Machek return size; 1948b7cfbecSG.Shark Jeong } 1958b7cfbecSG.Shark Jeong 1965ccfa39dSDwaipayan Ray static DEVICE_ATTR_WO(torch_pin); 1978b7cfbecSG.Shark Jeong 198bb58cc81SAndrew Lunn static int lm3642_torch_brightness_set(struct led_classdev *cdev, 1998b7cfbecSG.Shark Jeong enum led_brightness brightness) 2008b7cfbecSG.Shark Jeong { 2018b7cfbecSG.Shark Jeong struct lm3642_chip_data *chip = 2028b7cfbecSG.Shark Jeong container_of(cdev, struct lm3642_chip_data, cdev_torch); 203bb58cc81SAndrew Lunn int ret; 2048b7cfbecSG.Shark Jeong 205bb58cc81SAndrew Lunn mutex_lock(&chip->lock); 2068b7cfbecSG.Shark Jeong chip->br_torch = brightness; 207bb58cc81SAndrew Lunn ret = lm3642_control(chip, chip->br_torch, MODES_TORCH); 208bb58cc81SAndrew Lunn mutex_unlock(&chip->lock); 209bb58cc81SAndrew Lunn return ret; 2108b7cfbecSG.Shark Jeong } 2118b7cfbecSG.Shark Jeong 2128b7cfbecSG.Shark Jeong /* flash */ 2138b7cfbecSG.Shark Jeong 2148b7cfbecSG.Shark Jeong /* strobe pin config for lm3642*/ 2155ccfa39dSDwaipayan Ray static ssize_t strobe_pin_store(struct device *dev, 21685b4b756SJingoo Han struct device_attribute *attr, 2178b7cfbecSG.Shark Jeong const char *buf, size_t size) 2188b7cfbecSG.Shark Jeong { 2198b7cfbecSG.Shark Jeong ssize_t ret; 2208b7cfbecSG.Shark Jeong struct led_classdev *led_cdev = dev_get_drvdata(dev); 2218b7cfbecSG.Shark Jeong struct lm3642_chip_data *chip = 2228b7cfbecSG.Shark Jeong container_of(led_cdev, struct lm3642_chip_data, cdev_indicator); 2238b7cfbecSG.Shark Jeong unsigned int state; 2248b7cfbecSG.Shark Jeong 2258b7cfbecSG.Shark Jeong ret = kstrtouint(buf, 10, &state); 2268b7cfbecSG.Shark Jeong if (ret) 227867b6824SPavel Machek return ret; 2288b7cfbecSG.Shark Jeong if (state != 0) 2298b7cfbecSG.Shark Jeong state = 0x01 << STROBE_PIN_EN_SHIFT; 2308b7cfbecSG.Shark Jeong 2318b7cfbecSG.Shark Jeong chip->strobe_pin = state; 2328b7cfbecSG.Shark Jeong ret = regmap_update_bits(chip->regmap, REG_ENABLE, 2338b7cfbecSG.Shark Jeong STROBE_PIN_EN_MASK << STROBE_PIN_EN_SHIFT, 2348b7cfbecSG.Shark Jeong state); 235867b6824SPavel Machek if (ret < 0) { 2368b7cfbecSG.Shark Jeong dev_err(chip->dev, "%s:i2c access fail to register\n", __func__); 237eccb6638SAxel Lin return ret; 238867b6824SPavel Machek } 239867b6824SPavel Machek 240867b6824SPavel Machek return size; 2418b7cfbecSG.Shark Jeong } 2428b7cfbecSG.Shark Jeong 2435ccfa39dSDwaipayan Ray static DEVICE_ATTR_WO(strobe_pin); 2448b7cfbecSG.Shark Jeong 245bb58cc81SAndrew Lunn static int lm3642_strobe_brightness_set(struct led_classdev *cdev, 2468b7cfbecSG.Shark Jeong enum led_brightness brightness) 2478b7cfbecSG.Shark Jeong { 2488b7cfbecSG.Shark Jeong struct lm3642_chip_data *chip = 2498b7cfbecSG.Shark Jeong container_of(cdev, struct lm3642_chip_data, cdev_flash); 250bb58cc81SAndrew Lunn int ret; 2518b7cfbecSG.Shark Jeong 252bb58cc81SAndrew Lunn mutex_lock(&chip->lock); 2538b7cfbecSG.Shark Jeong chip->br_flash = brightness; 254bb58cc81SAndrew Lunn ret = lm3642_control(chip, chip->br_flash, MODES_FLASH); 255bb58cc81SAndrew Lunn mutex_unlock(&chip->lock); 256bb58cc81SAndrew Lunn return ret; 2578b7cfbecSG.Shark Jeong } 2588b7cfbecSG.Shark Jeong 2598b7cfbecSG.Shark Jeong /* indicator */ 260bb58cc81SAndrew Lunn static int lm3642_indicator_brightness_set(struct led_classdev *cdev, 2618b7cfbecSG.Shark Jeong enum led_brightness brightness) 2628b7cfbecSG.Shark Jeong { 2638b7cfbecSG.Shark Jeong struct lm3642_chip_data *chip = 2648b7cfbecSG.Shark Jeong container_of(cdev, struct lm3642_chip_data, cdev_indicator); 265bb58cc81SAndrew Lunn int ret; 2668b7cfbecSG.Shark Jeong 267bb58cc81SAndrew Lunn mutex_lock(&chip->lock); 2688b7cfbecSG.Shark Jeong chip->br_indicator = brightness; 269bb58cc81SAndrew Lunn ret = lm3642_control(chip, chip->br_indicator, MODES_INDIC); 270bb58cc81SAndrew Lunn mutex_unlock(&chip->lock); 271bb58cc81SAndrew Lunn return ret; 2728b7cfbecSG.Shark Jeong } 2738b7cfbecSG.Shark Jeong 2748b7cfbecSG.Shark Jeong static const struct regmap_config lm3642_regmap = { 2758b7cfbecSG.Shark Jeong .reg_bits = 8, 2768b7cfbecSG.Shark Jeong .val_bits = 8, 2778b7cfbecSG.Shark Jeong .max_register = REG_MAX, 2788b7cfbecSG.Shark Jeong }; 2798b7cfbecSG.Shark Jeong 280fe29a3b0SJohan Hovold static struct attribute *lm3642_flash_attrs[] = { 281fe29a3b0SJohan Hovold &dev_attr_strobe_pin.attr, 282fe29a3b0SJohan Hovold NULL 283fe29a3b0SJohan Hovold }; 284fe29a3b0SJohan Hovold ATTRIBUTE_GROUPS(lm3642_flash); 285fe29a3b0SJohan Hovold 286fe29a3b0SJohan Hovold static struct attribute *lm3642_torch_attrs[] = { 287fe29a3b0SJohan Hovold &dev_attr_torch_pin.attr, 288fe29a3b0SJohan Hovold NULL 289fe29a3b0SJohan Hovold }; 290fe29a3b0SJohan Hovold ATTRIBUTE_GROUPS(lm3642_torch); 291fe29a3b0SJohan Hovold 29298ea1ea2SBill Pemberton static int lm3642_probe(struct i2c_client *client, 2938b7cfbecSG.Shark Jeong const struct i2c_device_id *id) 2948b7cfbecSG.Shark Jeong { 29587aae1eaSJingoo Han struct lm3642_platform_data *pdata = dev_get_platdata(&client->dev); 2968b7cfbecSG.Shark Jeong struct lm3642_chip_data *chip; 2978b7cfbecSG.Shark Jeong 2988b7cfbecSG.Shark Jeong int err; 2998b7cfbecSG.Shark Jeong 3008b7cfbecSG.Shark Jeong if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 3018b7cfbecSG.Shark Jeong dev_err(&client->dev, "i2c functionality check fail.\n"); 3028b7cfbecSG.Shark Jeong return -EOPNOTSUPP; 3038b7cfbecSG.Shark Jeong } 3048b7cfbecSG.Shark Jeong 3058b7cfbecSG.Shark Jeong if (pdata == NULL) { 3068b7cfbecSG.Shark Jeong dev_err(&client->dev, "needs Platform Data.\n"); 3078b7cfbecSG.Shark Jeong return -ENODATA; 3088b7cfbecSG.Shark Jeong } 3098b7cfbecSG.Shark Jeong 3108b7cfbecSG.Shark Jeong chip = devm_kzalloc(&client->dev, 3118b7cfbecSG.Shark Jeong sizeof(struct lm3642_chip_data), GFP_KERNEL); 3128b7cfbecSG.Shark Jeong if (!chip) 3138b7cfbecSG.Shark Jeong return -ENOMEM; 3148b7cfbecSG.Shark Jeong 3158b7cfbecSG.Shark Jeong chip->dev = &client->dev; 3168b7cfbecSG.Shark Jeong chip->pdata = pdata; 3178b7cfbecSG.Shark Jeong 3188b7cfbecSG.Shark Jeong chip->tx_pin = pdata->tx_pin; 3198b7cfbecSG.Shark Jeong chip->torch_pin = pdata->torch_pin; 3208b7cfbecSG.Shark Jeong chip->strobe_pin = pdata->strobe_pin; 3218b7cfbecSG.Shark Jeong 3228b7cfbecSG.Shark Jeong chip->regmap = devm_regmap_init_i2c(client, &lm3642_regmap); 3238b7cfbecSG.Shark Jeong if (IS_ERR(chip->regmap)) { 3248b7cfbecSG.Shark Jeong err = PTR_ERR(chip->regmap); 3258b7cfbecSG.Shark Jeong dev_err(&client->dev, "Failed to allocate register map: %d\n", 3268b7cfbecSG.Shark Jeong err); 3278b7cfbecSG.Shark Jeong return err; 3288b7cfbecSG.Shark Jeong } 3298b7cfbecSG.Shark Jeong 3308b7cfbecSG.Shark Jeong mutex_init(&chip->lock); 3318b7cfbecSG.Shark Jeong i2c_set_clientdata(client, chip); 3328b7cfbecSG.Shark Jeong 3338b7cfbecSG.Shark Jeong err = lm3642_chip_init(chip); 3348b7cfbecSG.Shark Jeong if (err < 0) 3358b7cfbecSG.Shark Jeong goto err_out; 3368b7cfbecSG.Shark Jeong 3378b7cfbecSG.Shark Jeong /* flash */ 3388b7cfbecSG.Shark Jeong chip->cdev_flash.name = "flash"; 3398b7cfbecSG.Shark Jeong chip->cdev_flash.max_brightness = 16; 340bb58cc81SAndrew Lunn chip->cdev_flash.brightness_set_blocking = lm3642_strobe_brightness_set; 341313bf0b1SKim, Milo chip->cdev_flash.default_trigger = "flash"; 342*fcc96cefSZheng Yongjun chip->cdev_flash.groups = lm3642_flash_groups; 343b5684a73SJohan Hovold err = led_classdev_register(&client->dev, &chip->cdev_flash); 3448b7cfbecSG.Shark Jeong if (err < 0) { 3458b7cfbecSG.Shark Jeong dev_err(chip->dev, "failed to register flash\n"); 3468b7cfbecSG.Shark Jeong goto err_out; 3478b7cfbecSG.Shark Jeong } 3488b7cfbecSG.Shark Jeong 3498b7cfbecSG.Shark Jeong /* torch */ 3508b7cfbecSG.Shark Jeong chip->cdev_torch.name = "torch"; 3518b7cfbecSG.Shark Jeong chip->cdev_torch.max_brightness = 8; 352bb58cc81SAndrew Lunn chip->cdev_torch.brightness_set_blocking = lm3642_torch_brightness_set; 353313bf0b1SKim, Milo chip->cdev_torch.default_trigger = "torch"; 354*fcc96cefSZheng Yongjun chip->cdev_torch.groups = lm3642_torch_groups; 355b5684a73SJohan Hovold err = led_classdev_register(&client->dev, &chip->cdev_torch); 3568b7cfbecSG.Shark Jeong if (err < 0) { 3578b7cfbecSG.Shark Jeong dev_err(chip->dev, "failed to register torch\n"); 3588b7cfbecSG.Shark Jeong goto err_create_torch_file; 3598b7cfbecSG.Shark Jeong } 3608b7cfbecSG.Shark Jeong 3618b7cfbecSG.Shark Jeong /* indicator */ 3628b7cfbecSG.Shark Jeong chip->cdev_indicator.name = "indicator"; 3638b7cfbecSG.Shark Jeong chip->cdev_indicator.max_brightness = 8; 364bb58cc81SAndrew Lunn chip->cdev_indicator.brightness_set_blocking = 365bb58cc81SAndrew Lunn lm3642_indicator_brightness_set; 366b5684a73SJohan Hovold err = led_classdev_register(&client->dev, &chip->cdev_indicator); 3678b7cfbecSG.Shark Jeong if (err < 0) { 3688b7cfbecSG.Shark Jeong dev_err(chip->dev, "failed to register indicator\n"); 3698b7cfbecSG.Shark Jeong goto err_create_indicator_file; 3708b7cfbecSG.Shark Jeong } 3718b7cfbecSG.Shark Jeong 3728b7cfbecSG.Shark Jeong dev_info(&client->dev, "LM3642 is initialized\n"); 3738b7cfbecSG.Shark Jeong return 0; 3748b7cfbecSG.Shark Jeong 3758b7cfbecSG.Shark Jeong err_create_indicator_file: 3768b7cfbecSG.Shark Jeong led_classdev_unregister(&chip->cdev_torch); 3778b7cfbecSG.Shark Jeong err_create_torch_file: 3788b7cfbecSG.Shark Jeong led_classdev_unregister(&chip->cdev_flash); 3798b7cfbecSG.Shark Jeong err_out: 3808b7cfbecSG.Shark Jeong return err; 3818b7cfbecSG.Shark Jeong } 3828b7cfbecSG.Shark Jeong 383678e8a6bSBill Pemberton static int lm3642_remove(struct i2c_client *client) 3848b7cfbecSG.Shark Jeong { 3858b7cfbecSG.Shark Jeong struct lm3642_chip_data *chip = i2c_get_clientdata(client); 3868b7cfbecSG.Shark Jeong 3878b7cfbecSG.Shark Jeong led_classdev_unregister(&chip->cdev_indicator); 3888b7cfbecSG.Shark Jeong led_classdev_unregister(&chip->cdev_torch); 3898b7cfbecSG.Shark Jeong led_classdev_unregister(&chip->cdev_flash); 3908b7cfbecSG.Shark Jeong regmap_write(chip->regmap, REG_ENABLE, 0); 3918b7cfbecSG.Shark Jeong return 0; 3928b7cfbecSG.Shark Jeong } 3938b7cfbecSG.Shark Jeong 3948b7cfbecSG.Shark Jeong static const struct i2c_device_id lm3642_id[] = { 3958b7cfbecSG.Shark Jeong {LM3642_NAME, 0}, 3968b7cfbecSG.Shark Jeong {} 3978b7cfbecSG.Shark Jeong }; 3988b7cfbecSG.Shark Jeong 3998b7cfbecSG.Shark Jeong MODULE_DEVICE_TABLE(i2c, lm3642_id); 4008b7cfbecSG.Shark Jeong 4018b7cfbecSG.Shark Jeong static struct i2c_driver lm3642_i2c_driver = { 4028b7cfbecSG.Shark Jeong .driver = { 4038b7cfbecSG.Shark Jeong .name = LM3642_NAME, 4048b7cfbecSG.Shark Jeong .pm = NULL, 4058b7cfbecSG.Shark Jeong }, 4068b7cfbecSG.Shark Jeong .probe = lm3642_probe, 407df07cf81SBill Pemberton .remove = lm3642_remove, 4088b7cfbecSG.Shark Jeong .id_table = lm3642_id, 4098b7cfbecSG.Shark Jeong }; 4108b7cfbecSG.Shark Jeong 4118b7cfbecSG.Shark Jeong module_i2c_driver(lm3642_i2c_driver); 4128b7cfbecSG.Shark Jeong 4138b7cfbecSG.Shark Jeong MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3642"); 4148b7cfbecSG.Shark Jeong MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>"); 4158b7cfbecSG.Shark Jeong MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>"); 4168b7cfbecSG.Shark Jeong MODULE_LICENSE("GPL v2"); 417