0001
0002
0003
0004
0005
0006 #include <linux/module.h>
0007 #include <linux/slab.h>
0008 #include <linux/i2c.h>
0009 #include <linux/leds.h>
0010 #include <linux/backlight.h>
0011 #include <linux/err.h>
0012 #include <linux/delay.h>
0013 #include <linux/uaccess.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/regmap.h>
0016 #include <linux/platform_data/lm3639_bl.h>
0017
0018 #define REG_DEV_ID 0x00
0019 #define REG_CHECKSUM 0x01
0020 #define REG_BL_CONF_1 0x02
0021 #define REG_BL_CONF_2 0x03
0022 #define REG_BL_CONF_3 0x04
0023 #define REG_BL_CONF_4 0x05
0024 #define REG_FL_CONF_1 0x06
0025 #define REG_FL_CONF_2 0x07
0026 #define REG_FL_CONF_3 0x08
0027 #define REG_IO_CTRL 0x09
0028 #define REG_ENABLE 0x0A
0029 #define REG_FLAG 0x0B
0030 #define REG_MAX REG_FLAG
0031
0032 struct lm3639_chip_data {
0033 struct device *dev;
0034 struct lm3639_platform_data *pdata;
0035
0036 struct backlight_device *bled;
0037 struct led_classdev cdev_flash;
0038 struct led_classdev cdev_torch;
0039 struct regmap *regmap;
0040
0041 unsigned int bled_mode;
0042 unsigned int bled_map;
0043 unsigned int last_flag;
0044 };
0045
0046
0047 static int lm3639_chip_init(struct lm3639_chip_data *pchip)
0048 {
0049 int ret;
0050 unsigned int reg_val;
0051 struct lm3639_platform_data *pdata = pchip->pdata;
0052
0053
0054 ret =
0055 regmap_update_bits(pchip->regmap, REG_BL_CONF_1, 0x08,
0056 pdata->pin_pwm);
0057 if (ret < 0)
0058 goto out;
0059
0060 reg_val = (pdata->pin_pwm & 0x40) | pdata->pin_strobe | pdata->pin_tx;
0061 ret = regmap_update_bits(pchip->regmap, REG_IO_CTRL, 0x7C, reg_val);
0062 if (ret < 0)
0063 goto out;
0064
0065
0066 ret = regmap_write(pchip->regmap, REG_BL_CONF_4, pdata->init_brt_led);
0067 if (ret < 0)
0068 goto out;
0069
0070 ret = regmap_write(pchip->regmap, REG_BL_CONF_3, pdata->init_brt_led);
0071 if (ret < 0)
0072 goto out;
0073
0074
0075 if (!pdata->init_brt_led) {
0076 reg_val = pdata->fled_pins;
0077 reg_val |= pdata->bled_pins;
0078 } else {
0079 reg_val = pdata->fled_pins;
0080 reg_val |= pdata->bled_pins | 0x01;
0081 }
0082
0083 ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x79, reg_val);
0084 if (ret < 0)
0085 goto out;
0086
0087 return ret;
0088 out:
0089 dev_err(pchip->dev, "i2c failed to access register\n");
0090 return ret;
0091 }
0092
0093
0094 static int lm3639_bled_update_status(struct backlight_device *bl)
0095 {
0096 int ret;
0097 unsigned int reg_val;
0098 struct lm3639_chip_data *pchip = bl_get_data(bl);
0099 struct lm3639_platform_data *pdata = pchip->pdata;
0100
0101 ret = regmap_read(pchip->regmap, REG_FLAG, ®_val);
0102 if (ret < 0)
0103 goto out;
0104
0105 if (reg_val != 0)
0106 dev_info(pchip->dev, "last flag is 0x%x\n", reg_val);
0107
0108
0109 if (pdata->pin_pwm) {
0110 if (pdata->pwm_set_intensity)
0111 pdata->pwm_set_intensity(bl->props.brightness,
0112 pdata->max_brt_led);
0113 else
0114 dev_err(pchip->dev,
0115 "No pwm control func. in plat-data\n");
0116 return bl->props.brightness;
0117 }
0118
0119
0120 ret = regmap_write(pchip->regmap, REG_BL_CONF_4, bl->props.brightness);
0121 if (ret < 0)
0122 goto out;
0123 ret = regmap_write(pchip->regmap, REG_BL_CONF_3, bl->props.brightness);
0124 if (ret < 0)
0125 goto out;
0126
0127 if (!bl->props.brightness)
0128 ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x01, 0x00);
0129 else
0130 ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x01, 0x01);
0131 if (ret < 0)
0132 goto out;
0133
0134 return bl->props.brightness;
0135 out:
0136 dev_err(pchip->dev, "i2c failed to access registers\n");
0137 return bl->props.brightness;
0138 }
0139
0140 static int lm3639_bled_get_brightness(struct backlight_device *bl)
0141 {
0142 int ret;
0143 unsigned int reg_val;
0144 struct lm3639_chip_data *pchip = bl_get_data(bl);
0145 struct lm3639_platform_data *pdata = pchip->pdata;
0146
0147 if (pdata->pin_pwm) {
0148 if (pdata->pwm_get_intensity)
0149 bl->props.brightness = pdata->pwm_get_intensity();
0150 else
0151 dev_err(pchip->dev,
0152 "No pwm control func. in plat-data\n");
0153 return bl->props.brightness;
0154 }
0155
0156 ret = regmap_read(pchip->regmap, REG_BL_CONF_1, ®_val);
0157 if (ret < 0)
0158 goto out;
0159 if (reg_val & 0x10)
0160 ret = regmap_read(pchip->regmap, REG_BL_CONF_4, ®_val);
0161 else
0162 ret = regmap_read(pchip->regmap, REG_BL_CONF_3, ®_val);
0163 if (ret < 0)
0164 goto out;
0165 bl->props.brightness = reg_val;
0166
0167 return bl->props.brightness;
0168 out:
0169 dev_err(pchip->dev, "i2c failed to access register\n");
0170 return bl->props.brightness;
0171 }
0172
0173 static const struct backlight_ops lm3639_bled_ops = {
0174 .options = BL_CORE_SUSPENDRESUME,
0175 .update_status = lm3639_bled_update_status,
0176 .get_brightness = lm3639_bled_get_brightness,
0177 };
0178
0179
0180 static ssize_t lm3639_bled_mode_store(struct device *dev,
0181 struct device_attribute *devAttr,
0182 const char *buf, size_t size)
0183 {
0184 ssize_t ret;
0185 struct lm3639_chip_data *pchip = dev_get_drvdata(dev);
0186 unsigned int state;
0187
0188 ret = kstrtouint(buf, 10, &state);
0189 if (ret)
0190 goto out_input;
0191
0192 if (!state)
0193 ret =
0194 regmap_update_bits(pchip->regmap, REG_BL_CONF_1, 0x10,
0195 0x00);
0196 else
0197 ret =
0198 regmap_update_bits(pchip->regmap, REG_BL_CONF_1, 0x10,
0199 0x10);
0200
0201 if (ret < 0)
0202 goto out;
0203
0204 return size;
0205
0206 out:
0207 dev_err(pchip->dev, "%s:i2c access fail to register\n", __func__);
0208 return ret;
0209
0210 out_input:
0211 dev_err(pchip->dev, "%s:input conversion fail\n", __func__);
0212 return ret;
0213
0214 }
0215
0216 static DEVICE_ATTR(bled_mode, S_IWUSR, NULL, lm3639_bled_mode_store);
0217
0218
0219 static void lm3639_torch_brightness_set(struct led_classdev *cdev,
0220 enum led_brightness brightness)
0221 {
0222 int ret;
0223 unsigned int reg_val;
0224 struct lm3639_chip_data *pchip;
0225
0226 pchip = container_of(cdev, struct lm3639_chip_data, cdev_torch);
0227
0228 ret = regmap_read(pchip->regmap, REG_FLAG, ®_val);
0229 if (ret < 0)
0230 goto out;
0231 if (reg_val != 0)
0232 dev_info(pchip->dev, "last flag is 0x%x\n", reg_val);
0233
0234
0235 if (!brightness) {
0236 ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x06, 0x00);
0237 if (ret < 0)
0238 goto out;
0239 return;
0240 }
0241
0242 ret = regmap_update_bits(pchip->regmap,
0243 REG_FL_CONF_1, 0x70, (brightness - 1) << 4);
0244 if (ret < 0)
0245 goto out;
0246 ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x06, 0x02);
0247 if (ret < 0)
0248 goto out;
0249
0250 return;
0251 out:
0252 dev_err(pchip->dev, "i2c failed to access register\n");
0253 }
0254
0255
0256 static void lm3639_flash_brightness_set(struct led_classdev *cdev,
0257 enum led_brightness brightness)
0258 {
0259 int ret;
0260 unsigned int reg_val;
0261 struct lm3639_chip_data *pchip;
0262
0263 pchip = container_of(cdev, struct lm3639_chip_data, cdev_flash);
0264
0265 ret = regmap_read(pchip->regmap, REG_FLAG, ®_val);
0266 if (ret < 0)
0267 goto out;
0268 if (reg_val != 0)
0269 dev_info(pchip->dev, "last flag is 0x%x\n", reg_val);
0270
0271
0272 ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x06, 0x00);
0273 if (ret < 0)
0274 goto out;
0275
0276
0277 if (!brightness)
0278 return;
0279
0280 ret = regmap_update_bits(pchip->regmap,
0281 REG_FL_CONF_1, 0x0F, brightness - 1);
0282 if (ret < 0)
0283 goto out;
0284 ret = regmap_update_bits(pchip->regmap, REG_ENABLE, 0x06, 0x06);
0285 if (ret < 0)
0286 goto out;
0287
0288 return;
0289 out:
0290 dev_err(pchip->dev, "i2c failed to access register\n");
0291 }
0292
0293 static const struct regmap_config lm3639_regmap = {
0294 .reg_bits = 8,
0295 .val_bits = 8,
0296 .max_register = REG_MAX,
0297 };
0298
0299 static int lm3639_probe(struct i2c_client *client,
0300 const struct i2c_device_id *id)
0301 {
0302 int ret;
0303 struct lm3639_chip_data *pchip;
0304 struct lm3639_platform_data *pdata = dev_get_platdata(&client->dev);
0305 struct backlight_properties props;
0306
0307 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
0308 dev_err(&client->dev, "i2c functionality check fail.\n");
0309 return -EOPNOTSUPP;
0310 }
0311
0312 if (pdata == NULL) {
0313 dev_err(&client->dev, "Needs Platform Data.\n");
0314 return -ENODATA;
0315 }
0316
0317 pchip = devm_kzalloc(&client->dev,
0318 sizeof(struct lm3639_chip_data), GFP_KERNEL);
0319 if (!pchip)
0320 return -ENOMEM;
0321
0322 pchip->pdata = pdata;
0323 pchip->dev = &client->dev;
0324
0325 pchip->regmap = devm_regmap_init_i2c(client, &lm3639_regmap);
0326 if (IS_ERR(pchip->regmap)) {
0327 ret = PTR_ERR(pchip->regmap);
0328 dev_err(&client->dev, "fail : allocate register map: %d\n",
0329 ret);
0330 return ret;
0331 }
0332 i2c_set_clientdata(client, pchip);
0333
0334
0335 ret = lm3639_chip_init(pchip);
0336 if (ret < 0) {
0337 dev_err(&client->dev, "fail : chip init\n");
0338 goto err_out;
0339 }
0340
0341
0342 props.type = BACKLIGHT_RAW;
0343 props.brightness = pdata->init_brt_led;
0344 props.max_brightness = pdata->max_brt_led;
0345 pchip->bled =
0346 devm_backlight_device_register(pchip->dev, "lm3639_bled",
0347 pchip->dev, pchip, &lm3639_bled_ops,
0348 &props);
0349 if (IS_ERR(pchip->bled)) {
0350 dev_err(&client->dev, "fail : backlight register\n");
0351 ret = PTR_ERR(pchip->bled);
0352 goto err_out;
0353 }
0354
0355 ret = device_create_file(&(pchip->bled->dev), &dev_attr_bled_mode);
0356 if (ret < 0) {
0357 dev_err(&client->dev, "failed : add sysfs entries\n");
0358 goto err_out;
0359 }
0360
0361
0362 pchip->cdev_flash.name = "lm3639_flash";
0363 pchip->cdev_flash.max_brightness = 16;
0364 pchip->cdev_flash.brightness_set = lm3639_flash_brightness_set;
0365 ret = led_classdev_register((struct device *)
0366 &client->dev, &pchip->cdev_flash);
0367 if (ret < 0) {
0368 dev_err(&client->dev, "fail : flash register\n");
0369 goto err_flash;
0370 }
0371
0372
0373 pchip->cdev_torch.name = "lm3639_torch";
0374 pchip->cdev_torch.max_brightness = 8;
0375 pchip->cdev_torch.brightness_set = lm3639_torch_brightness_set;
0376 ret = led_classdev_register((struct device *)
0377 &client->dev, &pchip->cdev_torch);
0378 if (ret < 0) {
0379 dev_err(&client->dev, "fail : torch register\n");
0380 goto err_torch;
0381 }
0382
0383 return 0;
0384
0385 err_torch:
0386 led_classdev_unregister(&pchip->cdev_flash);
0387 err_flash:
0388 device_remove_file(&(pchip->bled->dev), &dev_attr_bled_mode);
0389 err_out:
0390 return ret;
0391 }
0392
0393 static int lm3639_remove(struct i2c_client *client)
0394 {
0395 struct lm3639_chip_data *pchip = i2c_get_clientdata(client);
0396
0397 regmap_write(pchip->regmap, REG_ENABLE, 0x00);
0398
0399 led_classdev_unregister(&pchip->cdev_torch);
0400 led_classdev_unregister(&pchip->cdev_flash);
0401 if (pchip->bled)
0402 device_remove_file(&(pchip->bled->dev), &dev_attr_bled_mode);
0403 return 0;
0404 }
0405
0406 static const struct i2c_device_id lm3639_id[] = {
0407 {LM3639_NAME, 0},
0408 {}
0409 };
0410
0411 MODULE_DEVICE_TABLE(i2c, lm3639_id);
0412 static struct i2c_driver lm3639_i2c_driver = {
0413 .driver = {
0414 .name = LM3639_NAME,
0415 },
0416 .probe = lm3639_probe,
0417 .remove = lm3639_remove,
0418 .id_table = lm3639_id,
0419 };
0420
0421 module_i2c_driver(lm3639_i2c_driver);
0422
0423 MODULE_DESCRIPTION("Texas Instruments Backlight+Flash LED driver for LM3639");
0424 MODULE_AUTHOR("Daniel Jeong <gshark.jeong@gmail.com>");
0425 MODULE_AUTHOR("Ldd Mlp <ldd-mlp@list.ti.com>");
0426 MODULE_LICENSE("GPL v2");