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 22 enum lm355x_type { 23 CHIP_LM3554 = 0, 24 CHIP_LM3556, 25 }; 26 27 enum 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 */ 40 enum lm355x_mode { 41 MODE_SHDN = 0, 42 MODE_INDIC, 43 MODE_TORCH, 44 MODE_FLASH 45 }; 46 47 /* register map info. */ 48 struct lm355x_reg_data { 49 u8 regno; 50 u8 mask; 51 u8 shift; 52 }; 53 54 struct 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 */ 79 enum 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 98 enum 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 117 enum 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 130 struct indicator { 131 u8 blinking; 132 u8 period_cnt; 133 }; 134 135 /* indicator pattern data only for lm3556 */ 136 static 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 143 static 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 154 static 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 165 static char lm355x_name[][I2C_NAME_SIZE] = { 166 [CHIP_LM3554] = LM3554_NAME, 167 [CHIP_LM3556] = LM3556_NAME, 168 }; 169 170 /* chip initialize */ 171 static 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; 201 out: 202 dev_err(chip->dev, "%s:i2c access fail to register\n", __func__); 203 return ret; 204 } 205 206 /* chip control */ 207 static 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; 313 out: 314 dev_err(chip->dev, "%s:i2c access fail to register\n", __func__); 315 return; 316 } 317 318 /* torch */ 319 static 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 329 static 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 */ 340 static 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 350 static 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 */ 361 static 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 371 static 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*/ 382 static ssize_t lm3556_indicator_pattern_store(struct device *dev, 383 struct device_attribute *devAttr, 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; 409 out: 410 dev_err(chip->dev, "%s:i2c access fail to register\n", __func__); 411 return ret; 412 } 413 414 static DEVICE_ATTR(pattern, S_IWUSR, NULL, lm3556_indicator_pattern_store); 415 416 static const struct regmap_config lm355x_regmap = { 417 .reg_bits = 8, 418 .val_bits = 8, 419 .max_register = 0xFF, 420 }; 421 422 /* module initialize */ 423 static int lm355x_probe(struct i2c_client *client, 424 const struct i2c_device_id *id) 425 { 426 struct lm355x_platform_data *pdata = client->dev.platform_data; 427 struct lm355x_chip_data *chip; 428 429 int err; 430 431 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 432 dev_err(&client->dev, "i2c functionality check fail.\n"); 433 return -EOPNOTSUPP; 434 } 435 436 if (pdata == NULL) { 437 dev_err(&client->dev, "needs Platform Data.\n"); 438 return -ENODATA; 439 } 440 441 chip = devm_kzalloc(&client->dev, 442 sizeof(struct lm355x_chip_data), GFP_KERNEL); 443 if (!chip) 444 return -ENOMEM; 445 446 chip->dev = &client->dev; 447 chip->type = id->driver_data; 448 switch (id->driver_data) { 449 case CHIP_LM3554: 450 chip->regs = lm3554_regs; 451 break; 452 case CHIP_LM3556: 453 chip->regs = lm3556_regs; 454 break; 455 default: 456 return -ENOSYS; 457 } 458 chip->pdata = pdata; 459 460 chip->regmap = devm_regmap_init_i2c(client, &lm355x_regmap); 461 if (IS_ERR(chip->regmap)) { 462 err = PTR_ERR(chip->regmap); 463 dev_err(&client->dev, 464 "Failed to allocate register map: %d\n", err); 465 return err; 466 } 467 468 mutex_init(&chip->lock); 469 i2c_set_clientdata(client, chip); 470 471 err = lm355x_chip_init(chip); 472 if (err < 0) 473 goto err_out; 474 475 /* flash */ 476 INIT_WORK(&chip->work_flash, lm355x_deferred_strobe_brightness_set); 477 chip->cdev_flash.name = "flash"; 478 chip->cdev_flash.max_brightness = 16; 479 chip->cdev_flash.brightness_set = lm355x_strobe_brightness_set; 480 err = led_classdev_register((struct device *) 481 &client->dev, &chip->cdev_flash); 482 if (err < 0) 483 goto err_out; 484 /* torch */ 485 INIT_WORK(&chip->work_torch, lm355x_deferred_torch_brightness_set); 486 chip->cdev_torch.name = "torch"; 487 chip->cdev_torch.max_brightness = 8; 488 chip->cdev_torch.brightness_set = lm355x_torch_brightness_set; 489 err = led_classdev_register((struct device *) 490 &client->dev, &chip->cdev_torch); 491 if (err < 0) 492 goto err_create_torch_file; 493 /* indicator */ 494 INIT_WORK(&chip->work_indicator, 495 lm355x_deferred_indicator_brightness_set); 496 chip->cdev_indicator.name = "indicator"; 497 if (id->driver_data == CHIP_LM3554) 498 chip->cdev_indicator.max_brightness = 4; 499 else 500 chip->cdev_indicator.max_brightness = 8; 501 chip->cdev_indicator.brightness_set = lm355x_indicator_brightness_set; 502 err = led_classdev_register((struct device *) 503 &client->dev, &chip->cdev_indicator); 504 if (err < 0) 505 goto err_create_indicator_file; 506 /* indicator pattern control only for LM3554 */ 507 if (id->driver_data == CHIP_LM3556) { 508 err = 509 device_create_file(chip->cdev_indicator.dev, 510 &dev_attr_pattern); 511 if (err < 0) 512 goto err_create_pattern_file; 513 } 514 515 dev_info(&client->dev, "%s is initialized\n", 516 lm355x_name[id->driver_data]); 517 return 0; 518 519 err_create_pattern_file: 520 led_classdev_unregister(&chip->cdev_indicator); 521 err_create_indicator_file: 522 led_classdev_unregister(&chip->cdev_torch); 523 err_create_torch_file: 524 led_classdev_unregister(&chip->cdev_flash); 525 err_out: 526 return err; 527 } 528 529 static int lm355x_remove(struct i2c_client *client) 530 { 531 struct lm355x_chip_data *chip = i2c_get_clientdata(client); 532 struct lm355x_reg_data *preg = chip->regs; 533 534 regmap_write(chip->regmap, preg[REG_OPMODE].regno, 0); 535 if (chip->type == CHIP_LM3556) 536 device_remove_file(chip->cdev_indicator.dev, &dev_attr_pattern); 537 led_classdev_unregister(&chip->cdev_indicator); 538 flush_work(&chip->work_indicator); 539 led_classdev_unregister(&chip->cdev_torch); 540 flush_work(&chip->work_torch); 541 led_classdev_unregister(&chip->cdev_flash); 542 flush_work(&chip->work_flash); 543 dev_info(&client->dev, "%s is removed\n", lm355x_name[chip->type]); 544 545 return 0; 546 } 547 548 static const struct i2c_device_id lm355x_id[] = { 549 {LM3554_NAME, CHIP_LM3554}, 550 {LM3556_NAME, CHIP_LM3556}, 551 {} 552 }; 553 554 MODULE_DEVICE_TABLE(i2c, lm355x_id); 555 556 static struct i2c_driver lm355x_i2c_driver = { 557 .driver = { 558 .name = LM355x_NAME, 559 .owner = THIS_MODULE, 560 .pm = NULL, 561 }, 562 .probe = lm355x_probe, 563 .remove = lm355x_remove, 564 .id_table = lm355x_id, 565 }; 566 567 module_i2c_driver(lm355x_i2c_driver); 568 569 MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM355x"); 570 MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>"); 571 MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>"); 572 MODULE_LICENSE("GPL v2"); 573