18b7cfbecSG.Shark Jeong /* 28b7cfbecSG.Shark Jeong * Simple driver for Texas Instruments LM3642 LED Flash driver chip 38b7cfbecSG.Shark Jeong * Copyright (C) 2012 Texas Instruments 48b7cfbecSG.Shark Jeong * 58b7cfbecSG.Shark Jeong * This program is free software; you can redistribute it and/or modify 68b7cfbecSG.Shark Jeong * it under the terms of the GNU General Public License version 2 as 78b7cfbecSG.Shark Jeong * published by the Free Software Foundation. 88b7cfbecSG.Shark Jeong * 98b7cfbecSG.Shark Jeong */ 108b7cfbecSG.Shark Jeong #include <linux/module.h> 118b7cfbecSG.Shark Jeong #include <linux/delay.h> 128b7cfbecSG.Shark Jeong #include <linux/i2c.h> 138b7cfbecSG.Shark Jeong #include <linux/leds.h> 148b7cfbecSG.Shark Jeong #include <linux/slab.h> 158b7cfbecSG.Shark Jeong #include <linux/platform_device.h> 168b7cfbecSG.Shark Jeong #include <linux/fs.h> 178b7cfbecSG.Shark Jeong #include <linux/regmap.h> 188b7cfbecSG.Shark Jeong #include <linux/workqueue.h> 198b7cfbecSG.Shark Jeong #include <linux/platform_data/leds-lm3642.h> 208b7cfbecSG.Shark Jeong 218b7cfbecSG.Shark Jeong #define REG_FILT_TIME (0x0) 228b7cfbecSG.Shark Jeong #define REG_IVFM_MODE (0x1) 238b7cfbecSG.Shark Jeong #define REG_TORCH_TIME (0x6) 248b7cfbecSG.Shark Jeong #define REG_FLASH (0x8) 258b7cfbecSG.Shark Jeong #define REG_I_CTRL (0x9) 268b7cfbecSG.Shark Jeong #define REG_ENABLE (0xA) 278b7cfbecSG.Shark Jeong #define REG_FLAG (0xB) 288b7cfbecSG.Shark Jeong #define REG_MAX (0xB) 298b7cfbecSG.Shark Jeong 308b7cfbecSG.Shark Jeong #define UVLO_EN_SHIFT (7) 318b7cfbecSG.Shark Jeong #define IVM_D_TH_SHIFT (2) 328b7cfbecSG.Shark Jeong #define TORCH_RAMP_UP_TIME_SHIFT (3) 338b7cfbecSG.Shark Jeong #define TORCH_RAMP_DN_TIME_SHIFT (0) 348b7cfbecSG.Shark Jeong #define INDUCTOR_I_LIMIT_SHIFT (6) 358b7cfbecSG.Shark Jeong #define FLASH_RAMP_TIME_SHIFT (3) 368b7cfbecSG.Shark Jeong #define FLASH_TOUT_TIME_SHIFT (0) 378b7cfbecSG.Shark Jeong #define TORCH_I_SHIFT (4) 388b7cfbecSG.Shark Jeong #define FLASH_I_SHIFT (0) 398b7cfbecSG.Shark Jeong #define IVFM_SHIFT (7) 408b7cfbecSG.Shark Jeong #define TX_PIN_EN_SHIFT (6) 418b7cfbecSG.Shark Jeong #define STROBE_PIN_EN_SHIFT (5) 428b7cfbecSG.Shark Jeong #define TORCH_PIN_EN_SHIFT (4) 438b7cfbecSG.Shark Jeong #define MODE_BITS_SHIFT (0) 448b7cfbecSG.Shark Jeong 458b7cfbecSG.Shark Jeong #define UVLO_EN_MASK (0x1) 468b7cfbecSG.Shark Jeong #define IVM_D_TH_MASK (0x7) 478b7cfbecSG.Shark Jeong #define TORCH_RAMP_UP_TIME_MASK (0x7) 488b7cfbecSG.Shark Jeong #define TORCH_RAMP_DN_TIME_MASK (0x7) 498b7cfbecSG.Shark Jeong #define INDUCTOR_I_LIMIT_MASK (0x1) 508b7cfbecSG.Shark Jeong #define FLASH_RAMP_TIME_MASK (0x7) 518b7cfbecSG.Shark Jeong #define FLASH_TOUT_TIME_MASK (0x7) 528b7cfbecSG.Shark Jeong #define TORCH_I_MASK (0x7) 538b7cfbecSG.Shark Jeong #define FLASH_I_MASK (0xF) 548b7cfbecSG.Shark Jeong #define IVFM_MASK (0x1) 558b7cfbecSG.Shark Jeong #define TX_PIN_EN_MASK (0x1) 568b7cfbecSG.Shark Jeong #define STROBE_PIN_EN_MASK (0x1) 578b7cfbecSG.Shark Jeong #define TORCH_PIN_EN_MASK (0x1) 588b7cfbecSG.Shark Jeong #define MODE_BITS_MASK (0x73) 598b7cfbecSG.Shark Jeong #define EX_PIN_CONTROL_MASK (0x71) 608b7cfbecSG.Shark Jeong #define EX_PIN_ENABLE_MASK (0x70) 618b7cfbecSG.Shark Jeong 628b7cfbecSG.Shark Jeong enum lm3642_mode { 638b7cfbecSG.Shark Jeong MODES_STASNDBY = 0, 648b7cfbecSG.Shark Jeong MODES_INDIC, 658b7cfbecSG.Shark Jeong MODES_TORCH, 668b7cfbecSG.Shark Jeong MODES_FLASH 678b7cfbecSG.Shark Jeong }; 688b7cfbecSG.Shark Jeong 698b7cfbecSG.Shark Jeong struct lm3642_chip_data { 708b7cfbecSG.Shark Jeong struct device *dev; 718b7cfbecSG.Shark Jeong 728b7cfbecSG.Shark Jeong struct led_classdev cdev_flash; 738b7cfbecSG.Shark Jeong struct led_classdev cdev_torch; 748b7cfbecSG.Shark Jeong struct led_classdev cdev_indicator; 758b7cfbecSG.Shark Jeong 768b7cfbecSG.Shark Jeong struct work_struct work_flash; 778b7cfbecSG.Shark Jeong struct work_struct work_torch; 788b7cfbecSG.Shark Jeong struct work_struct work_indicator; 798b7cfbecSG.Shark Jeong 808b7cfbecSG.Shark Jeong u8 br_flash; 818b7cfbecSG.Shark Jeong u8 br_torch; 828b7cfbecSG.Shark Jeong u8 br_indicator; 838b7cfbecSG.Shark Jeong 848b7cfbecSG.Shark Jeong enum lm3642_torch_pin_enable torch_pin; 858b7cfbecSG.Shark Jeong enum lm3642_strobe_pin_enable strobe_pin; 868b7cfbecSG.Shark Jeong enum lm3642_tx_pin_enable tx_pin; 878b7cfbecSG.Shark Jeong 888b7cfbecSG.Shark Jeong struct lm3642_platform_data *pdata; 898b7cfbecSG.Shark Jeong struct regmap *regmap; 908b7cfbecSG.Shark Jeong struct mutex lock; 918b7cfbecSG.Shark Jeong 928b7cfbecSG.Shark Jeong unsigned int last_flag; 938b7cfbecSG.Shark Jeong }; 948b7cfbecSG.Shark Jeong 958b7cfbecSG.Shark Jeong /* chip initialize */ 968b7cfbecSG.Shark Jeong static int __devinit lm3642_chip_init(struct lm3642_chip_data *chip) 978b7cfbecSG.Shark Jeong { 988b7cfbecSG.Shark Jeong int ret; 998b7cfbecSG.Shark Jeong struct lm3642_platform_data *pdata = chip->pdata; 1008b7cfbecSG.Shark Jeong 1018b7cfbecSG.Shark Jeong /* set enable register */ 102e76a322aSAxel Lin ret = regmap_update_bits(chip->regmap, REG_ENABLE, EX_PIN_ENABLE_MASK, 103e76a322aSAxel Lin pdata->tx_pin); 1048b7cfbecSG.Shark Jeong if (ret < 0) 105e76a322aSAxel Lin dev_err(chip->dev, "Failed to update REG_ENABLE Register\n"); 1068b7cfbecSG.Shark Jeong return ret; 1078b7cfbecSG.Shark Jeong } 1088b7cfbecSG.Shark Jeong 1098b7cfbecSG.Shark Jeong /* chip control */ 1108b7cfbecSG.Shark Jeong static int lm3642_control(struct lm3642_chip_data *chip, 1118b7cfbecSG.Shark Jeong u8 brightness, enum lm3642_mode opmode) 1128b7cfbecSG.Shark Jeong { 1138b7cfbecSG.Shark Jeong int ret; 1148b7cfbecSG.Shark Jeong 1158b7cfbecSG.Shark Jeong ret = regmap_read(chip->regmap, REG_FLAG, &chip->last_flag); 1168b7cfbecSG.Shark Jeong if (ret < 0) { 1178b7cfbecSG.Shark Jeong dev_err(chip->dev, "Failed to read REG_FLAG Register\n"); 1188b7cfbecSG.Shark Jeong goto out; 1198b7cfbecSG.Shark Jeong } 1208b7cfbecSG.Shark Jeong 1218b7cfbecSG.Shark Jeong if (chip->last_flag) 1228b7cfbecSG.Shark Jeong dev_info(chip->dev, "Last FLAG is 0x%x\n", chip->last_flag); 1238b7cfbecSG.Shark Jeong 1248b7cfbecSG.Shark Jeong /* brightness 0 means off-state */ 1258b7cfbecSG.Shark Jeong if (!brightness) 1268b7cfbecSG.Shark Jeong opmode = MODES_STASNDBY; 1278b7cfbecSG.Shark Jeong 1288b7cfbecSG.Shark Jeong switch (opmode) { 1298b7cfbecSG.Shark Jeong case MODES_TORCH: 1308b7cfbecSG.Shark Jeong ret = regmap_update_bits(chip->regmap, REG_I_CTRL, 1318b7cfbecSG.Shark Jeong TORCH_I_MASK << TORCH_I_SHIFT, 1328b7cfbecSG.Shark Jeong (brightness - 1) << TORCH_I_SHIFT); 1338b7cfbecSG.Shark Jeong 1348b7cfbecSG.Shark Jeong if (chip->torch_pin) 1358b7cfbecSG.Shark Jeong opmode |= (TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT); 1368b7cfbecSG.Shark Jeong break; 1378b7cfbecSG.Shark Jeong 1388b7cfbecSG.Shark Jeong case MODES_FLASH: 1398b7cfbecSG.Shark Jeong ret = regmap_update_bits(chip->regmap, REG_I_CTRL, 1408b7cfbecSG.Shark Jeong FLASH_I_MASK << FLASH_I_SHIFT, 1418b7cfbecSG.Shark Jeong (brightness - 1) << FLASH_I_SHIFT); 1428b7cfbecSG.Shark Jeong 1438b7cfbecSG.Shark Jeong if (chip->strobe_pin) 1448b7cfbecSG.Shark Jeong opmode |= (STROBE_PIN_EN_MASK << STROBE_PIN_EN_SHIFT); 1458b7cfbecSG.Shark Jeong break; 1468b7cfbecSG.Shark Jeong 1478b7cfbecSG.Shark Jeong case MODES_INDIC: 1488b7cfbecSG.Shark Jeong ret = regmap_update_bits(chip->regmap, REG_I_CTRL, 1498b7cfbecSG.Shark Jeong TORCH_I_MASK << TORCH_I_SHIFT, 1508b7cfbecSG.Shark Jeong (brightness - 1) << TORCH_I_SHIFT); 1518b7cfbecSG.Shark Jeong break; 1528b7cfbecSG.Shark Jeong 1538b7cfbecSG.Shark Jeong case MODES_STASNDBY: 1548b7cfbecSG.Shark Jeong 1558b7cfbecSG.Shark Jeong break; 1568b7cfbecSG.Shark Jeong 1578b7cfbecSG.Shark Jeong default: 1588b7cfbecSG.Shark Jeong return ret; 1598b7cfbecSG.Shark Jeong } 1608b7cfbecSG.Shark Jeong if (ret < 0) { 1618b7cfbecSG.Shark Jeong dev_err(chip->dev, "Failed to write REG_I_CTRL Register\n"); 1628b7cfbecSG.Shark Jeong goto out; 1638b7cfbecSG.Shark Jeong } 1648b7cfbecSG.Shark Jeong 1658b7cfbecSG.Shark Jeong if (chip->tx_pin) 1668b7cfbecSG.Shark Jeong opmode |= (TX_PIN_EN_MASK << TX_PIN_EN_SHIFT); 1678b7cfbecSG.Shark Jeong 1688b7cfbecSG.Shark Jeong ret = regmap_update_bits(chip->regmap, REG_ENABLE, 1698b7cfbecSG.Shark Jeong MODE_BITS_MASK << MODE_BITS_SHIFT, 1708b7cfbecSG.Shark Jeong opmode << MODE_BITS_SHIFT); 1718b7cfbecSG.Shark Jeong out: 1728b7cfbecSG.Shark Jeong return ret; 1738b7cfbecSG.Shark Jeong } 1748b7cfbecSG.Shark Jeong 1758b7cfbecSG.Shark Jeong /* torch */ 1768b7cfbecSG.Shark Jeong 1778b7cfbecSG.Shark Jeong /* torch pin config for lm3642*/ 1788b7cfbecSG.Shark Jeong static ssize_t lm3642_torch_pin_store(struct device *dev, 1798b7cfbecSG.Shark Jeong struct device_attribute *devAttr, 1808b7cfbecSG.Shark Jeong const char *buf, size_t size) 1818b7cfbecSG.Shark Jeong { 1828b7cfbecSG.Shark Jeong ssize_t ret; 1838b7cfbecSG.Shark Jeong struct led_classdev *led_cdev = dev_get_drvdata(dev); 1848b7cfbecSG.Shark Jeong struct lm3642_chip_data *chip = 1858b7cfbecSG.Shark Jeong container_of(led_cdev, struct lm3642_chip_data, cdev_indicator); 1868b7cfbecSG.Shark Jeong unsigned int state; 1878b7cfbecSG.Shark Jeong 1888b7cfbecSG.Shark Jeong ret = kstrtouint(buf, 10, &state); 1898b7cfbecSG.Shark Jeong if (ret) 1908b7cfbecSG.Shark Jeong goto out_strtoint; 1918b7cfbecSG.Shark Jeong if (state != 0) 1928b7cfbecSG.Shark Jeong state = 0x01 << TORCH_PIN_EN_SHIFT; 1938b7cfbecSG.Shark Jeong 1948b7cfbecSG.Shark Jeong chip->torch_pin = state; 1958b7cfbecSG.Shark Jeong ret = regmap_update_bits(chip->regmap, REG_ENABLE, 1968b7cfbecSG.Shark Jeong TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT, 1978b7cfbecSG.Shark Jeong state); 1988b7cfbecSG.Shark Jeong if (ret < 0) 1998b7cfbecSG.Shark Jeong goto out; 2008b7cfbecSG.Shark Jeong 2018b7cfbecSG.Shark Jeong return size; 2028b7cfbecSG.Shark Jeong out: 2038b7cfbecSG.Shark Jeong dev_err(chip->dev, "%s:i2c access fail to register\n", __func__); 204eccb6638SAxel Lin return ret; 2058b7cfbecSG.Shark Jeong out_strtoint: 2068b7cfbecSG.Shark Jeong dev_err(chip->dev, "%s: fail to change str to int\n", __func__); 207eccb6638SAxel Lin return ret; 2088b7cfbecSG.Shark Jeong } 2098b7cfbecSG.Shark Jeong 2108b7cfbecSG.Shark Jeong static DEVICE_ATTR(torch_pin, 0666, NULL, lm3642_torch_pin_store); 2118b7cfbecSG.Shark Jeong 2128b7cfbecSG.Shark Jeong static void lm3642_deferred_torch_brightness_set(struct work_struct *work) 2138b7cfbecSG.Shark Jeong { 2148b7cfbecSG.Shark Jeong struct lm3642_chip_data *chip = 2158b7cfbecSG.Shark Jeong container_of(work, struct lm3642_chip_data, work_torch); 2168b7cfbecSG.Shark Jeong 2178b7cfbecSG.Shark Jeong mutex_lock(&chip->lock); 2188b7cfbecSG.Shark Jeong lm3642_control(chip, chip->br_torch, MODES_TORCH); 2198b7cfbecSG.Shark Jeong mutex_unlock(&chip->lock); 2208b7cfbecSG.Shark Jeong } 2218b7cfbecSG.Shark Jeong 2228b7cfbecSG.Shark Jeong static void lm3642_torch_brightness_set(struct led_classdev *cdev, 2238b7cfbecSG.Shark Jeong enum led_brightness brightness) 2248b7cfbecSG.Shark Jeong { 2258b7cfbecSG.Shark Jeong struct lm3642_chip_data *chip = 2268b7cfbecSG.Shark Jeong container_of(cdev, struct lm3642_chip_data, cdev_torch); 2278b7cfbecSG.Shark Jeong 2288b7cfbecSG.Shark Jeong chip->br_torch = brightness; 2298b7cfbecSG.Shark Jeong schedule_work(&chip->work_torch); 2308b7cfbecSG.Shark Jeong } 2318b7cfbecSG.Shark Jeong 2328b7cfbecSG.Shark Jeong /* flash */ 2338b7cfbecSG.Shark Jeong 2348b7cfbecSG.Shark Jeong /* strobe pin config for lm3642*/ 2358b7cfbecSG.Shark Jeong static ssize_t lm3642_strobe_pin_store(struct device *dev, 2368b7cfbecSG.Shark Jeong struct device_attribute *devAttr, 2378b7cfbecSG.Shark Jeong const char *buf, size_t size) 2388b7cfbecSG.Shark Jeong { 2398b7cfbecSG.Shark Jeong ssize_t ret; 2408b7cfbecSG.Shark Jeong struct led_classdev *led_cdev = dev_get_drvdata(dev); 2418b7cfbecSG.Shark Jeong struct lm3642_chip_data *chip = 2428b7cfbecSG.Shark Jeong container_of(led_cdev, struct lm3642_chip_data, cdev_indicator); 2438b7cfbecSG.Shark Jeong unsigned int state; 2448b7cfbecSG.Shark Jeong 2458b7cfbecSG.Shark Jeong ret = kstrtouint(buf, 10, &state); 2468b7cfbecSG.Shark Jeong if (ret) 2478b7cfbecSG.Shark Jeong goto out_strtoint; 2488b7cfbecSG.Shark Jeong if (state != 0) 2498b7cfbecSG.Shark Jeong state = 0x01 << STROBE_PIN_EN_SHIFT; 2508b7cfbecSG.Shark Jeong 2518b7cfbecSG.Shark Jeong chip->strobe_pin = state; 2528b7cfbecSG.Shark Jeong ret = regmap_update_bits(chip->regmap, REG_ENABLE, 2538b7cfbecSG.Shark Jeong STROBE_PIN_EN_MASK << STROBE_PIN_EN_SHIFT, 2548b7cfbecSG.Shark Jeong state); 2558b7cfbecSG.Shark Jeong if (ret < 0) 2568b7cfbecSG.Shark Jeong goto out; 2578b7cfbecSG.Shark Jeong 2588b7cfbecSG.Shark Jeong return size; 2598b7cfbecSG.Shark Jeong out: 2608b7cfbecSG.Shark Jeong dev_err(chip->dev, "%s:i2c access fail to register\n", __func__); 261eccb6638SAxel Lin return ret; 2628b7cfbecSG.Shark Jeong out_strtoint: 2638b7cfbecSG.Shark Jeong dev_err(chip->dev, "%s: fail to change str to int\n", __func__); 264eccb6638SAxel Lin return ret; 2658b7cfbecSG.Shark Jeong } 2668b7cfbecSG.Shark Jeong 2678b7cfbecSG.Shark Jeong static DEVICE_ATTR(strobe_pin, 0666, NULL, lm3642_strobe_pin_store); 2688b7cfbecSG.Shark Jeong 2698b7cfbecSG.Shark Jeong static void lm3642_deferred_strobe_brightness_set(struct work_struct *work) 2708b7cfbecSG.Shark Jeong { 2718b7cfbecSG.Shark Jeong struct lm3642_chip_data *chip = 2728b7cfbecSG.Shark Jeong container_of(work, struct lm3642_chip_data, work_flash); 2738b7cfbecSG.Shark Jeong 2748b7cfbecSG.Shark Jeong mutex_lock(&chip->lock); 2758b7cfbecSG.Shark Jeong lm3642_control(chip, chip->br_flash, MODES_FLASH); 2768b7cfbecSG.Shark Jeong mutex_unlock(&chip->lock); 2778b7cfbecSG.Shark Jeong } 2788b7cfbecSG.Shark Jeong 2798b7cfbecSG.Shark Jeong static void lm3642_strobe_brightness_set(struct led_classdev *cdev, 2808b7cfbecSG.Shark Jeong enum led_brightness brightness) 2818b7cfbecSG.Shark Jeong { 2828b7cfbecSG.Shark Jeong struct lm3642_chip_data *chip = 2838b7cfbecSG.Shark Jeong container_of(cdev, struct lm3642_chip_data, cdev_flash); 2848b7cfbecSG.Shark Jeong 2858b7cfbecSG.Shark Jeong chip->br_flash = brightness; 2868b7cfbecSG.Shark Jeong schedule_work(&chip->work_flash); 2878b7cfbecSG.Shark Jeong } 2888b7cfbecSG.Shark Jeong 2898b7cfbecSG.Shark Jeong /* indicator */ 2908b7cfbecSG.Shark Jeong static void lm3642_deferred_indicator_brightness_set(struct work_struct *work) 2918b7cfbecSG.Shark Jeong { 2928b7cfbecSG.Shark Jeong struct lm3642_chip_data *chip = 2938b7cfbecSG.Shark Jeong container_of(work, struct lm3642_chip_data, work_indicator); 2948b7cfbecSG.Shark Jeong 2958b7cfbecSG.Shark Jeong mutex_lock(&chip->lock); 2968b7cfbecSG.Shark Jeong lm3642_control(chip, chip->br_indicator, MODES_INDIC); 2978b7cfbecSG.Shark Jeong mutex_unlock(&chip->lock); 2988b7cfbecSG.Shark Jeong } 2998b7cfbecSG.Shark Jeong 3008b7cfbecSG.Shark Jeong static void lm3642_indicator_brightness_set(struct led_classdev *cdev, 3018b7cfbecSG.Shark Jeong enum led_brightness brightness) 3028b7cfbecSG.Shark Jeong { 3038b7cfbecSG.Shark Jeong struct lm3642_chip_data *chip = 3048b7cfbecSG.Shark Jeong container_of(cdev, struct lm3642_chip_data, cdev_indicator); 3058b7cfbecSG.Shark Jeong 3068b7cfbecSG.Shark Jeong chip->br_indicator = brightness; 3078b7cfbecSG.Shark Jeong schedule_work(&chip->work_indicator); 3088b7cfbecSG.Shark Jeong } 3098b7cfbecSG.Shark Jeong 3108b7cfbecSG.Shark Jeong static const struct regmap_config lm3642_regmap = { 3118b7cfbecSG.Shark Jeong .reg_bits = 8, 3128b7cfbecSG.Shark Jeong .val_bits = 8, 3138b7cfbecSG.Shark Jeong .max_register = REG_MAX, 3148b7cfbecSG.Shark Jeong }; 3158b7cfbecSG.Shark Jeong 3168b7cfbecSG.Shark Jeong static int __devinit lm3642_probe(struct i2c_client *client, 3178b7cfbecSG.Shark Jeong const struct i2c_device_id *id) 3188b7cfbecSG.Shark Jeong { 3198b7cfbecSG.Shark Jeong struct lm3642_platform_data *pdata = client->dev.platform_data; 3208b7cfbecSG.Shark Jeong struct lm3642_chip_data *chip; 3218b7cfbecSG.Shark Jeong 3228b7cfbecSG.Shark Jeong int err; 3238b7cfbecSG.Shark Jeong 3248b7cfbecSG.Shark Jeong if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 3258b7cfbecSG.Shark Jeong dev_err(&client->dev, "i2c functionality check fail.\n"); 3268b7cfbecSG.Shark Jeong return -EOPNOTSUPP; 3278b7cfbecSG.Shark Jeong } 3288b7cfbecSG.Shark Jeong 3298b7cfbecSG.Shark Jeong if (pdata == NULL) { 3308b7cfbecSG.Shark Jeong dev_err(&client->dev, "needs Platform Data.\n"); 3318b7cfbecSG.Shark Jeong return -ENODATA; 3328b7cfbecSG.Shark Jeong } 3338b7cfbecSG.Shark Jeong 3348b7cfbecSG.Shark Jeong chip = devm_kzalloc(&client->dev, 3358b7cfbecSG.Shark Jeong sizeof(struct lm3642_chip_data), GFP_KERNEL); 3368b7cfbecSG.Shark Jeong if (!chip) 3378b7cfbecSG.Shark Jeong return -ENOMEM; 3388b7cfbecSG.Shark Jeong 3398b7cfbecSG.Shark Jeong chip->dev = &client->dev; 3408b7cfbecSG.Shark Jeong chip->pdata = pdata; 3418b7cfbecSG.Shark Jeong 3428b7cfbecSG.Shark Jeong chip->tx_pin = pdata->tx_pin; 3438b7cfbecSG.Shark Jeong chip->torch_pin = pdata->torch_pin; 3448b7cfbecSG.Shark Jeong chip->strobe_pin = pdata->strobe_pin; 3458b7cfbecSG.Shark Jeong 3468b7cfbecSG.Shark Jeong chip->regmap = devm_regmap_init_i2c(client, &lm3642_regmap); 3478b7cfbecSG.Shark Jeong if (IS_ERR(chip->regmap)) { 3488b7cfbecSG.Shark Jeong err = PTR_ERR(chip->regmap); 3498b7cfbecSG.Shark Jeong dev_err(&client->dev, "Failed to allocate register map: %d\n", 3508b7cfbecSG.Shark Jeong err); 3518b7cfbecSG.Shark Jeong return err; 3528b7cfbecSG.Shark Jeong } 3538b7cfbecSG.Shark Jeong 3548b7cfbecSG.Shark Jeong mutex_init(&chip->lock); 3558b7cfbecSG.Shark Jeong i2c_set_clientdata(client, chip); 3568b7cfbecSG.Shark Jeong 3578b7cfbecSG.Shark Jeong err = lm3642_chip_init(chip); 3588b7cfbecSG.Shark Jeong if (err < 0) 3598b7cfbecSG.Shark Jeong goto err_out; 3608b7cfbecSG.Shark Jeong 3618b7cfbecSG.Shark Jeong /* flash */ 3628b7cfbecSG.Shark Jeong INIT_WORK(&chip->work_flash, lm3642_deferred_strobe_brightness_set); 3638b7cfbecSG.Shark Jeong chip->cdev_flash.name = "flash"; 3648b7cfbecSG.Shark Jeong chip->cdev_flash.max_brightness = 16; 3658b7cfbecSG.Shark Jeong chip->cdev_flash.brightness_set = lm3642_strobe_brightness_set; 3668b7cfbecSG.Shark Jeong err = led_classdev_register((struct device *) 3678b7cfbecSG.Shark Jeong &client->dev, &chip->cdev_flash); 3688b7cfbecSG.Shark Jeong if (err < 0) { 3698b7cfbecSG.Shark Jeong dev_err(chip->dev, "failed to register flash\n"); 3708b7cfbecSG.Shark Jeong goto err_out; 3718b7cfbecSG.Shark Jeong } 3728b7cfbecSG.Shark Jeong err = device_create_file(chip->cdev_flash.dev, &dev_attr_strobe_pin); 3738b7cfbecSG.Shark Jeong if (err < 0) { 3748b7cfbecSG.Shark Jeong dev_err(chip->dev, "failed to create strobe-pin file\n"); 3758b7cfbecSG.Shark Jeong goto err_create_flash_pin_file; 3768b7cfbecSG.Shark Jeong } 3778b7cfbecSG.Shark Jeong 3788b7cfbecSG.Shark Jeong /* torch */ 3798b7cfbecSG.Shark Jeong INIT_WORK(&chip->work_torch, lm3642_deferred_torch_brightness_set); 3808b7cfbecSG.Shark Jeong chip->cdev_torch.name = "torch"; 3818b7cfbecSG.Shark Jeong chip->cdev_torch.max_brightness = 8; 3828b7cfbecSG.Shark Jeong chip->cdev_torch.brightness_set = lm3642_torch_brightness_set; 3838b7cfbecSG.Shark Jeong err = led_classdev_register((struct device *) 3848b7cfbecSG.Shark Jeong &client->dev, &chip->cdev_torch); 3858b7cfbecSG.Shark Jeong if (err < 0) { 3868b7cfbecSG.Shark Jeong dev_err(chip->dev, "failed to register torch\n"); 3878b7cfbecSG.Shark Jeong goto err_create_torch_file; 3888b7cfbecSG.Shark Jeong } 3898b7cfbecSG.Shark Jeong err = device_create_file(chip->cdev_torch.dev, &dev_attr_torch_pin); 3908b7cfbecSG.Shark Jeong if (err < 0) { 3918b7cfbecSG.Shark Jeong dev_err(chip->dev, "failed to create torch-pin file\n"); 3928b7cfbecSG.Shark Jeong goto err_create_torch_pin_file; 3938b7cfbecSG.Shark Jeong } 3948b7cfbecSG.Shark Jeong 3958b7cfbecSG.Shark Jeong /* indicator */ 3968b7cfbecSG.Shark Jeong INIT_WORK(&chip->work_indicator, 3978b7cfbecSG.Shark Jeong lm3642_deferred_indicator_brightness_set); 3988b7cfbecSG.Shark Jeong chip->cdev_indicator.name = "indicator"; 3998b7cfbecSG.Shark Jeong chip->cdev_indicator.max_brightness = 8; 4008b7cfbecSG.Shark Jeong chip->cdev_indicator.brightness_set = lm3642_indicator_brightness_set; 4018b7cfbecSG.Shark Jeong err = led_classdev_register((struct device *) 4028b7cfbecSG.Shark Jeong &client->dev, &chip->cdev_indicator); 4038b7cfbecSG.Shark Jeong if (err < 0) { 4048b7cfbecSG.Shark Jeong dev_err(chip->dev, "failed to register indicator\n"); 4058b7cfbecSG.Shark Jeong goto err_create_indicator_file; 4068b7cfbecSG.Shark Jeong } 4078b7cfbecSG.Shark Jeong 4088b7cfbecSG.Shark Jeong dev_info(&client->dev, "LM3642 is initialized\n"); 4098b7cfbecSG.Shark Jeong return 0; 4108b7cfbecSG.Shark Jeong 4118b7cfbecSG.Shark Jeong err_create_indicator_file: 4128b7cfbecSG.Shark Jeong device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin); 4138b7cfbecSG.Shark Jeong err_create_torch_pin_file: 4148b7cfbecSG.Shark Jeong led_classdev_unregister(&chip->cdev_torch); 4158b7cfbecSG.Shark Jeong err_create_torch_file: 4168b7cfbecSG.Shark Jeong device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin); 4178b7cfbecSG.Shark Jeong err_create_flash_pin_file: 4188b7cfbecSG.Shark Jeong led_classdev_unregister(&chip->cdev_flash); 4198b7cfbecSG.Shark Jeong err_out: 4208b7cfbecSG.Shark Jeong return err; 4218b7cfbecSG.Shark Jeong } 4228b7cfbecSG.Shark Jeong 4238b7cfbecSG.Shark Jeong static int __devexit lm3642_remove(struct i2c_client *client) 4248b7cfbecSG.Shark Jeong { 4258b7cfbecSG.Shark Jeong struct lm3642_chip_data *chip = i2c_get_clientdata(client); 4268b7cfbecSG.Shark Jeong 4278b7cfbecSG.Shark Jeong led_classdev_unregister(&chip->cdev_indicator); 4288b7cfbecSG.Shark Jeong flush_work(&chip->work_indicator); 4298b7cfbecSG.Shark Jeong device_remove_file(chip->cdev_torch.dev, &dev_attr_torch_pin); 4308b7cfbecSG.Shark Jeong led_classdev_unregister(&chip->cdev_torch); 4318b7cfbecSG.Shark Jeong flush_work(&chip->work_torch); 4328b7cfbecSG.Shark Jeong device_remove_file(chip->cdev_flash.dev, &dev_attr_strobe_pin); 4338b7cfbecSG.Shark Jeong led_classdev_unregister(&chip->cdev_flash); 4348b7cfbecSG.Shark Jeong flush_work(&chip->work_flash); 4358b7cfbecSG.Shark Jeong regmap_write(chip->regmap, REG_ENABLE, 0); 4368b7cfbecSG.Shark Jeong return 0; 4378b7cfbecSG.Shark Jeong } 4388b7cfbecSG.Shark Jeong 4398b7cfbecSG.Shark Jeong static const struct i2c_device_id lm3642_id[] = { 4408b7cfbecSG.Shark Jeong {LM3642_NAME, 0}, 4418b7cfbecSG.Shark Jeong {} 4428b7cfbecSG.Shark Jeong }; 4438b7cfbecSG.Shark Jeong 4448b7cfbecSG.Shark Jeong MODULE_DEVICE_TABLE(i2c, lm3642_id); 4458b7cfbecSG.Shark Jeong 4468b7cfbecSG.Shark Jeong static struct i2c_driver lm3642_i2c_driver = { 4478b7cfbecSG.Shark Jeong .driver = { 4488b7cfbecSG.Shark Jeong .name = LM3642_NAME, 4498b7cfbecSG.Shark Jeong .owner = THIS_MODULE, 4508b7cfbecSG.Shark Jeong .pm = NULL, 4518b7cfbecSG.Shark Jeong }, 4528b7cfbecSG.Shark Jeong .probe = lm3642_probe, 4538b7cfbecSG.Shark Jeong .remove = __devexit_p(lm3642_remove), 4548b7cfbecSG.Shark Jeong .id_table = lm3642_id, 4558b7cfbecSG.Shark Jeong }; 4568b7cfbecSG.Shark Jeong 4578b7cfbecSG.Shark Jeong module_i2c_driver(lm3642_i2c_driver); 4588b7cfbecSG.Shark Jeong 4598b7cfbecSG.Shark Jeong MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3642"); 4608b7cfbecSG.Shark Jeong MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>"); 4618b7cfbecSG.Shark Jeong MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>"); 4628b7cfbecSG.Shark Jeong MODULE_LICENSE("GPL v2"); 463