1/* 2* Simple driver for Texas Instruments LM355x LED Flash driver chip 3* Copyright (C) 2012 Texas Instruments 4* 5* This program is free software; you can redistribute it and/or modify 6* it under the terms of the GNU General Public License version 2 as 7* published by the Free Software Foundation. 8*/ 9 10#include <linux/module.h> 11#include <linux/delay.h> 12#include <linux/i2c.h> 13#include <linux/gpio.h> 14#include <linux/leds.h> 15#include <linux/slab.h> 16#include <linux/platform_device.h> 17#include <linux/fs.h> 18#include <linux/regmap.h> 19#include <linux/workqueue.h> 20#include <linux/platform_data/leds-lm355x.h> 21 22enum lm355x_type { 23 CHIP_LM3554 = 0, 24 CHIP_LM3556, 25}; 26 27enum lm355x_regs { 28 REG_FLAG = 0, 29 REG_TORCH_CFG, 30 REG_TORCH_CTRL, 31 REG_STROBE_CFG, 32 REG_FLASH_CTRL, 33 REG_INDI_CFG, 34 REG_INDI_CTRL, 35 REG_OPMODE, 36 REG_MAX, 37}; 38 39/* operation mode */ 40enum lm355x_mode { 41 MODE_SHDN = 0, 42 MODE_INDIC, 43 MODE_TORCH, 44 MODE_FLASH 45}; 46 47/* register map info. */ 48struct lm355x_reg_data { 49 u8 regno; 50 u8 mask; 51 u8 shift; 52}; 53 54struct lm355x_chip_data { 55 struct device *dev; 56 enum lm355x_type type; 57 58 struct led_classdev cdev_flash; 59 struct led_classdev cdev_torch; 60 struct led_classdev cdev_indicator; 61 62 struct work_struct work_flash; 63 struct work_struct work_torch; 64 struct work_struct work_indicator; 65 66 u8 br_flash; 67 u8 br_torch; 68 u8 br_indicator; 69 70 struct lm355x_platform_data *pdata; 71 struct regmap *regmap; 72 struct mutex lock; 73 74 unsigned int last_flag; 75 struct lm355x_reg_data *regs; 76}; 77 78/* specific indicator function for lm3556 */ 79enum lm3556_indic_pulse_time { 80 PULSE_TIME_0_MS = 0, 81 PULSE_TIME_32_MS, 82 PULSE_TIME_64_MS, 83 PULSE_TIME_92_MS, 84 PULSE_TIME_128_MS, 85 PULSE_TIME_160_MS, 86 PULSE_TIME_196_MS, 87 PULSE_TIME_224_MS, 88 PULSE_TIME_256_MS, 89 PULSE_TIME_288_MS, 90 PULSE_TIME_320_MS, 91 PULSE_TIME_352_MS, 92 PULSE_TIME_384_MS, 93 PULSE_TIME_416_MS, 94 PULSE_TIME_448_MS, 95 PULSE_TIME_480_MS, 96}; 97 98enum lm3556_indic_n_blank { 99 INDIC_N_BLANK_0 = 0, 100 INDIC_N_BLANK_1, 101 INDIC_N_BLANK_2, 102 INDIC_N_BLANK_3, 103 INDIC_N_BLANK_4, 104 INDIC_N_BLANK_5, 105 INDIC_N_BLANK_6, 106 INDIC_N_BLANK_7, 107 INDIC_N_BLANK_8, 108 INDIC_N_BLANK_9, 109 INDIC_N_BLANK_10, 110 INDIC_N_BLANK_11, 111 INDIC_N_BLANK_12, 112 INDIC_N_BLANK_13, 113 INDIC_N_BLANK_14, 114 INDIC_N_BLANK_15, 115}; 116 117enum lm3556_indic_period { 118 INDIC_PERIOD_0 = 0, 119 INDIC_PERIOD_1, 120 INDIC_PERIOD_2, 121 INDIC_PERIOD_3, 122 INDIC_PERIOD_4, 123 INDIC_PERIOD_5, 124 INDIC_PERIOD_6, 125 INDIC_PERIOD_7, 126}; 127 128#define INDIC_PATTERN_SIZE 4 129 130struct indicator { 131 u8 blinking; 132 u8 period_cnt; 133}; 134 135/* indicator pattern data only for lm3556 */ 136static struct indicator indicator_pattern[INDIC_PATTERN_SIZE] = { 137 [0] = {(INDIC_N_BLANK_1 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_1}, 138 [1] = {(INDIC_N_BLANK_15 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_2}, 139 [2] = {(INDIC_N_BLANK_10 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_4}, 140 [3] = {(INDIC_N_BLANK_5 << 4) | PULSE_TIME_32_MS, INDIC_PERIOD_7}, 141}; 142 143static struct lm355x_reg_data lm3554_regs[REG_MAX] = { 144 [REG_FLAG] = {0xD0, 0xBF, 0}, 145 [REG_TORCH_CFG] = {0xE0, 0x80, 7}, 146 [REG_TORCH_CTRL] = {0xA0, 0x38, 3}, 147 [REG_STROBE_CFG] = {0xE0, 0x04, 2}, 148 [REG_FLASH_CTRL] = {0xB0, 0x78, 3}, 149 [REG_INDI_CFG] = {0xE0, 0x08, 3}, 150 [REG_INDI_CTRL] = {0xA0, 0xC0, 6}, 151 [REG_OPMODE] = {0xA0, 0x03, 0}, 152}; 153 154static struct lm355x_reg_data lm3556_regs[REG_MAX] = { 155 [REG_FLAG] = {0x0B, 0xFF, 0}, 156 [REG_TORCH_CFG] = {0x0A, 0x10, 4}, 157 [REG_TORCH_CTRL] = {0x09, 0x70, 4}, 158 [REG_STROBE_CFG] = {0x0A, 0x20, 5}, 159 [REG_FLASH_CTRL] = {0x09, 0x0F, 0}, 160 [REG_INDI_CFG] = {0xFF, 0xFF, 0}, 161 [REG_INDI_CTRL] = {0x09, 0x70, 4}, 162 [REG_OPMODE] = {0x0A, 0x03, 0}, 163}; 164 165static char lm355x_name[][I2C_NAME_SIZE] = { 166 [CHIP_LM3554] = LM3554_NAME, 167 [CHIP_LM3556] = LM3556_NAME, 168}; 169 170/* chip initialize */ 171static int lm355x_chip_init(struct lm355x_chip_data *chip) 172{ 173 int ret; 174 unsigned int reg_val; 175 struct lm355x_platform_data *pdata = chip->pdata; 176 177 /* input and output pins configuration */ 178 switch (chip->type) { 179 case CHIP_LM3554: 180 reg_val = pdata->pin_tx2 | pdata->ntc_pin; 181 ret = regmap_update_bits(chip->regmap, 0xE0, 0x28, reg_val); 182 if (ret < 0) 183 goto out; 184 reg_val = pdata->pass_mode; 185 ret = regmap_update_bits(chip->regmap, 0xA0, 0x04, reg_val); 186 if (ret < 0) 187 goto out; 188 break; 189 190 case CHIP_LM3556: 191 reg_val = pdata->pin_tx2 | pdata->ntc_pin | pdata->pass_mode; 192 ret = regmap_update_bits(chip->regmap, 0x0A, 0xC4, reg_val); 193 if (ret < 0) 194 goto out; 195 break; 196 default: 197 return -ENODATA; 198 } 199 200 return ret; 201out: 202 dev_err(chip->dev, "%s:i2c access fail to register\n", __func__); 203 return ret; 204} 205 206/* chip control */ 207static void lm355x_control(struct lm355x_chip_data *chip, 208 u8 brightness, enum lm355x_mode opmode) 209{ 210 int ret; 211 unsigned int reg_val; 212 struct lm355x_platform_data *pdata = chip->pdata; 213 struct lm355x_reg_data *preg = chip->regs; 214 215 ret = regmap_read(chip->regmap, preg[REG_FLAG].regno, &chip->last_flag); 216 if (ret < 0) 217 goto out; 218 if (chip->last_flag & preg[REG_FLAG].mask) 219 dev_info(chip->dev, "%s Last FLAG is 0x%x\n", 220 lm355x_name[chip->type], 221 chip->last_flag & preg[REG_FLAG].mask); 222 /* brightness 0 means shutdown */ 223 if (!brightness) 224 opmode = MODE_SHDN; 225 226 switch (opmode) { 227 case MODE_TORCH: 228 ret = 229 regmap_update_bits(chip->regmap, preg[REG_TORCH_CTRL].regno, 230 preg[REG_TORCH_CTRL].mask, 231 (brightness - 1) 232 << preg[REG_TORCH_CTRL].shift); 233 if (ret < 0) 234 goto out; 235 236 if (pdata->pin_tx1 != LM355x_PIN_TORCH_DISABLE) { 237 ret = 238 regmap_update_bits(chip->regmap, 239 preg[REG_TORCH_CFG].regno, 240 preg[REG_TORCH_CFG].mask, 241 0x01 << 242 preg[REG_TORCH_CFG].shift); 243 if (ret < 0) 244 goto out; 245 opmode = MODE_SHDN; 246 dev_info(chip->dev, 247 "torch brt is set - ext. torch pin mode\n"); 248 } 249 break; 250 251 case MODE_FLASH: 252 253 ret = 254 regmap_update_bits(chip->regmap, preg[REG_FLASH_CTRL].regno, 255 preg[REG_FLASH_CTRL].mask, 256 (brightness - 1) 257 << preg[REG_FLASH_CTRL].shift); 258 if (ret < 0) 259 goto out; 260 261 if (pdata->pin_strobe != LM355x_PIN_STROBE_DISABLE) { 262 if (chip->type == CHIP_LM3554) 263 reg_val = 0x00; 264 else 265 reg_val = 0x01; 266 ret = 267 regmap_update_bits(chip->regmap, 268 preg[REG_STROBE_CFG].regno, 269 preg[REG_STROBE_CFG].mask, 270 reg_val << 271 preg[REG_STROBE_CFG].shift); 272 if (ret < 0) 273 goto out; 274 opmode = MODE_SHDN; 275 dev_info(chip->dev, 276 "flash brt is set - ext. strobe pin mode\n"); 277 } 278 break; 279 280 case MODE_INDIC: 281 ret = 282 regmap_update_bits(chip->regmap, preg[REG_INDI_CTRL].regno, 283 preg[REG_INDI_CTRL].mask, 284 (brightness - 1) 285 << preg[REG_INDI_CTRL].shift); 286 if (ret < 0) 287 goto out; 288 289 if (pdata->pin_tx2 != LM355x_PIN_TX_DISABLE) { 290 ret = 291 regmap_update_bits(chip->regmap, 292 preg[REG_INDI_CFG].regno, 293 preg[REG_INDI_CFG].mask, 294 0x01 << 295 preg[REG_INDI_CFG].shift); 296 if (ret < 0) 297 goto out; 298 opmode = MODE_SHDN; 299 } 300 break; 301 case MODE_SHDN: 302 break; 303 default: 304 return; 305 } 306 /* operation mode control */ 307 ret = regmap_update_bits(chip->regmap, preg[REG_OPMODE].regno, 308 preg[REG_OPMODE].mask, 309 opmode << preg[REG_OPMODE].shift); 310 if (ret < 0) 311 goto out; 312 return; 313out: 314 dev_err(chip->dev, "%s:i2c access fail to register\n", __func__); 315 return; 316} 317 318/* torch */ 319static void lm355x_deferred_torch_brightness_set(struct work_struct *work) 320{ 321 struct lm355x_chip_data *chip = 322 container_of(work, struct lm355x_chip_data, work_torch); 323 324 mutex_lock(&chip->lock); 325 lm355x_control(chip, chip->br_torch, MODE_TORCH); 326 mutex_unlock(&chip->lock); 327} 328 329static void lm355x_torch_brightness_set(struct led_classdev *cdev, 330 enum led_brightness brightness) 331{ 332 struct lm355x_chip_data *chip = 333 container_of(cdev, struct lm355x_chip_data, cdev_torch); 334 335 chip->br_torch = brightness; 336 schedule_work(&chip->work_torch); 337} 338 339/* flash */ 340static void lm355x_deferred_strobe_brightness_set(struct work_struct *work) 341{ 342 struct lm355x_chip_data *chip = 343 container_of(work, struct lm355x_chip_data, work_flash); 344 345 mutex_lock(&chip->lock); 346 lm355x_control(chip, chip->br_flash, MODE_FLASH); 347 mutex_unlock(&chip->lock); 348} 349 350static void lm355x_strobe_brightness_set(struct led_classdev *cdev, 351 enum led_brightness brightness) 352{ 353 struct lm355x_chip_data *chip = 354 container_of(cdev, struct lm355x_chip_data, cdev_flash); 355 356 chip->br_flash = brightness; 357 schedule_work(&chip->work_flash); 358} 359 360/* indicator */ 361static void lm355x_deferred_indicator_brightness_set(struct work_struct *work) 362{ 363 struct lm355x_chip_data *chip = 364 container_of(work, struct lm355x_chip_data, work_indicator); 365 366 mutex_lock(&chip->lock); 367 lm355x_control(chip, chip->br_indicator, MODE_INDIC); 368 mutex_unlock(&chip->lock); 369} 370 371static void lm355x_indicator_brightness_set(struct led_classdev *cdev, 372 enum led_brightness brightness) 373{ 374 struct lm355x_chip_data *chip = 375 container_of(cdev, struct lm355x_chip_data, cdev_indicator); 376 377 chip->br_indicator = brightness; 378 schedule_work(&chip->work_indicator); 379} 380 381/* indicator pattern only for lm3556*/ 382static ssize_t lm3556_indicator_pattern_store(struct device *dev, 383 struct device_attribute *attr, 384 const char *buf, size_t size) 385{ 386 ssize_t ret; 387 struct led_classdev *led_cdev = dev_get_drvdata(dev); 388 struct lm355x_chip_data *chip = 389 container_of(led_cdev, struct lm355x_chip_data, cdev_indicator); 390 unsigned int state; 391 392 ret = kstrtouint(buf, 10, &state); 393 if (ret) 394 goto out; 395 if (state > INDIC_PATTERN_SIZE - 1) 396 state = INDIC_PATTERN_SIZE - 1; 397 398 ret = regmap_write(chip->regmap, 0x04, 399 indicator_pattern[state].blinking); 400 if (ret < 0) 401 goto out; 402 403 ret = regmap_write(chip->regmap, 0x05, 404 indicator_pattern[state].period_cnt); 405 if (ret < 0) 406 goto out; 407 408 return size; 409out: 410 dev_err(chip->dev, "%s:i2c access fail to register\n", __func__); 411 return ret; 412} 413 414static DEVICE_ATTR(pattern, S_IWUSR, NULL, lm3556_indicator_pattern_store); 415 416static struct attribute *lm355x_indicator_attrs[] = { 417 &dev_attr_pattern.attr, 418 NULL 419}; 420ATTRIBUTE_GROUPS(lm355x_indicator); 421 422static const struct regmap_config lm355x_regmap = { 423 .reg_bits = 8, 424 .val_bits = 8, 425 .max_register = 0xFF, 426}; 427 428/* module initialize */ 429static int lm355x_probe(struct i2c_client *client, 430 const struct i2c_device_id *id) 431{ 432 struct lm355x_platform_data *pdata = dev_get_platdata(&client->dev); 433 struct lm355x_chip_data *chip; 434 435 int err; 436 437 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 438 dev_err(&client->dev, "i2c functionality check fail.\n"); 439 return -EOPNOTSUPP; 440 } 441 442 if (pdata == NULL) { 443 dev_err(&client->dev, "needs Platform Data.\n"); 444 return -ENODATA; 445 } 446 447 chip = devm_kzalloc(&client->dev, 448 sizeof(struct lm355x_chip_data), GFP_KERNEL); 449 if (!chip) 450 return -ENOMEM; 451 452 chip->dev = &client->dev; 453 chip->type = id->driver_data; 454 switch (id->driver_data) { 455 case CHIP_LM3554: 456 chip->regs = lm3554_regs; 457 break; 458 case CHIP_LM3556: 459 chip->regs = lm3556_regs; 460 break; 461 default: 462 return -ENOSYS; 463 } 464 chip->pdata = pdata; 465 466 chip->regmap = devm_regmap_init_i2c(client, &lm355x_regmap); 467 if (IS_ERR(chip->regmap)) { 468 err = PTR_ERR(chip->regmap); 469 dev_err(&client->dev, 470 "Failed to allocate register map: %d\n", err); 471 return err; 472 } 473 474 mutex_init(&chip->lock); 475 i2c_set_clientdata(client, chip); 476 477 err = lm355x_chip_init(chip); 478 if (err < 0) 479 goto err_out; 480 481 /* flash */ 482 INIT_WORK(&chip->work_flash, lm355x_deferred_strobe_brightness_set); 483 chip->cdev_flash.name = "flash"; 484 chip->cdev_flash.max_brightness = 16; 485 chip->cdev_flash.brightness_set = lm355x_strobe_brightness_set; 486 chip->cdev_flash.default_trigger = "flash"; 487 err = led_classdev_register((struct device *) 488 &client->dev, &chip->cdev_flash); 489 if (err < 0) 490 goto err_out; 491 /* torch */ 492 INIT_WORK(&chip->work_torch, lm355x_deferred_torch_brightness_set); 493 chip->cdev_torch.name = "torch"; 494 chip->cdev_torch.max_brightness = 8; 495 chip->cdev_torch.brightness_set = lm355x_torch_brightness_set; 496 chip->cdev_torch.default_trigger = "torch"; 497 err = led_classdev_register((struct device *) 498 &client->dev, &chip->cdev_torch); 499 if (err < 0) 500 goto err_create_torch_file; 501 /* indicator */ 502 INIT_WORK(&chip->work_indicator, 503 lm355x_deferred_indicator_brightness_set); 504 chip->cdev_indicator.name = "indicator"; 505 if (id->driver_data == CHIP_LM3554) 506 chip->cdev_indicator.max_brightness = 4; 507 else 508 chip->cdev_indicator.max_brightness = 8; 509 chip->cdev_indicator.brightness_set = lm355x_indicator_brightness_set; 510 /* indicator pattern control only for LM3556 */ 511 if (id->driver_data == CHIP_LM3556) 512 chip->cdev_indicator.groups = lm355x_indicator_groups; 513 err = led_classdev_register((struct device *) 514 &client->dev, &chip->cdev_indicator); 515 if (err < 0) 516 goto err_create_indicator_file; 517 518 dev_info(&client->dev, "%s is initialized\n", 519 lm355x_name[id->driver_data]); 520 return 0; 521 522err_create_indicator_file: 523 led_classdev_unregister(&chip->cdev_torch); 524err_create_torch_file: 525 led_classdev_unregister(&chip->cdev_flash); 526err_out: 527 return err; 528} 529 530static int lm355x_remove(struct i2c_client *client) 531{ 532 struct lm355x_chip_data *chip = i2c_get_clientdata(client); 533 struct lm355x_reg_data *preg = chip->regs; 534 535 regmap_write(chip->regmap, preg[REG_OPMODE].regno, 0); 536 led_classdev_unregister(&chip->cdev_indicator); 537 flush_work(&chip->work_indicator); 538 led_classdev_unregister(&chip->cdev_torch); 539 flush_work(&chip->work_torch); 540 led_classdev_unregister(&chip->cdev_flash); 541 flush_work(&chip->work_flash); 542 dev_info(&client->dev, "%s is removed\n", lm355x_name[chip->type]); 543 544 return 0; 545} 546 547static const struct i2c_device_id lm355x_id[] = { 548 {LM3554_NAME, CHIP_LM3554}, 549 {LM3556_NAME, CHIP_LM3556}, 550 {} 551}; 552 553MODULE_DEVICE_TABLE(i2c, lm355x_id); 554 555static struct i2c_driver lm355x_i2c_driver = { 556 .driver = { 557 .name = LM355x_NAME, 558 .owner = THIS_MODULE, 559 .pm = NULL, 560 }, 561 .probe = lm355x_probe, 562 .remove = lm355x_remove, 563 .id_table = lm355x_id, 564}; 565 566module_i2c_driver(lm355x_i2c_driver); 567 568MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM355x"); 569MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>"); 570MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>"); 571MODULE_LICENSE("GPL v2"); 572