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