2 * Simple driver for Texas Instruments LM355x LED Flash driver chip
3 * Copyright (C) 2012 Texas Instruments
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.
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>
18 #include <linux/regmap.h>
19 #include <linux/workqueue.h>
20 #include <linux/platform_data/leds-lm355x.h>
47 /* register map info. */
48 struct lm355x_reg_data
{
54 struct lm355x_chip_data
{
56 enum lm355x_type type
;
58 struct led_classdev cdev_flash
;
59 struct led_classdev cdev_torch
;
60 struct led_classdev cdev_indicator
;
62 struct work_struct work_flash
;
63 struct work_struct work_torch
;
64 struct work_struct work_indicator
;
70 struct lm355x_platform_data
*pdata
;
71 struct regmap
*regmap
;
74 unsigned int last_flag
;
75 struct lm355x_reg_data
*regs
;
78 /* specific indicator function for lm3556 */
79 enum lm3556_indic_pulse_time
{
98 enum lm3556_indic_n_blank
{
117 enum lm3556_indic_period
{
128 #define INDIC_PATTERN_SIZE 4
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
},
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},
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},
165 static char lm355x_name
[][I2C_NAME_SIZE
] = {
166 [CHIP_LM3554
] = LM3554_NAME
,
167 [CHIP_LM3556
] = LM3556_NAME
,
170 /* chip initialize */
171 static int lm355x_chip_init(struct lm355x_chip_data
*chip
)
174 unsigned int reg_val
;
175 struct lm355x_platform_data
*pdata
= chip
->pdata
;
177 /* input and output pins configuration */
178 switch (chip
->type
) {
180 reg_val
= pdata
->pin_tx2
| pdata
->ntc_pin
;
181 ret
= regmap_update_bits(chip
->regmap
, 0xE0, 0x28, reg_val
);
184 reg_val
= pdata
->pass_mode
;
185 ret
= regmap_update_bits(chip
->regmap
, 0xA0, 0x04, reg_val
);
191 reg_val
= pdata
->pin_tx2
| pdata
->ntc_pin
| pdata
->pass_mode
;
192 ret
= regmap_update_bits(chip
->regmap
, 0x0A, 0xC4, reg_val
);
202 dev_err(chip
->dev
, "%s:i2c access fail to register\n", __func__
);
207 static void lm355x_control(struct lm355x_chip_data
*chip
,
208 u8 brightness
, enum lm355x_mode opmode
)
211 unsigned int reg_val
;
212 struct lm355x_platform_data
*pdata
= chip
->pdata
;
213 struct lm355x_reg_data
*preg
= chip
->regs
;
215 ret
= regmap_read(chip
->regmap
, preg
[REG_FLAG
].regno
, &chip
->last_flag
);
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 */
229 regmap_update_bits(chip
->regmap
, preg
[REG_TORCH_CTRL
].regno
,
230 preg
[REG_TORCH_CTRL
].mask
,
232 << preg
[REG_TORCH_CTRL
].shift
);
236 if (pdata
->pin_tx1
!= LM355x_PIN_TORCH_DISABLE
) {
238 regmap_update_bits(chip
->regmap
,
239 preg
[REG_TORCH_CFG
].regno
,
240 preg
[REG_TORCH_CFG
].mask
,
242 preg
[REG_TORCH_CFG
].shift
);
247 "torch brt is set - ext. torch pin mode\n");
254 regmap_update_bits(chip
->regmap
, preg
[REG_FLASH_CTRL
].regno
,
255 preg
[REG_FLASH_CTRL
].mask
,
257 << preg
[REG_FLASH_CTRL
].shift
);
261 if (pdata
->pin_strobe
!= LM355x_PIN_STROBE_DISABLE
) {
262 if (chip
->type
== CHIP_LM3554
)
267 regmap_update_bits(chip
->regmap
,
268 preg
[REG_STROBE_CFG
].regno
,
269 preg
[REG_STROBE_CFG
].mask
,
271 preg
[REG_STROBE_CFG
].shift
);
276 "flash brt is set - ext. strobe pin mode\n");
282 regmap_update_bits(chip
->regmap
, preg
[REG_INDI_CTRL
].regno
,
283 preg
[REG_INDI_CTRL
].mask
,
285 << preg
[REG_INDI_CTRL
].shift
);
289 if (pdata
->pin_tx2
!= LM355x_PIN_TX_DISABLE
) {
291 regmap_update_bits(chip
->regmap
,
292 preg
[REG_INDI_CFG
].regno
,
293 preg
[REG_INDI_CFG
].mask
,
295 preg
[REG_INDI_CFG
].shift
);
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
);
314 dev_err(chip
->dev
, "%s:i2c access fail to register\n", __func__
);
319 static void lm355x_deferred_torch_brightness_set(struct work_struct
*work
)
321 struct lm355x_chip_data
*chip
=
322 container_of(work
, struct lm355x_chip_data
, work_torch
);
324 mutex_lock(&chip
->lock
);
325 lm355x_control(chip
, chip
->br_torch
, MODE_TORCH
);
326 mutex_unlock(&chip
->lock
);
329 static void lm355x_torch_brightness_set(struct led_classdev
*cdev
,
330 enum led_brightness brightness
)
332 struct lm355x_chip_data
*chip
=
333 container_of(cdev
, struct lm355x_chip_data
, cdev_torch
);
335 chip
->br_torch
= brightness
;
336 schedule_work(&chip
->work_torch
);
340 static void lm355x_deferred_strobe_brightness_set(struct work_struct
*work
)
342 struct lm355x_chip_data
*chip
=
343 container_of(work
, struct lm355x_chip_data
, work_flash
);
345 mutex_lock(&chip
->lock
);
346 lm355x_control(chip
, chip
->br_flash
, MODE_FLASH
);
347 mutex_unlock(&chip
->lock
);
350 static void lm355x_strobe_brightness_set(struct led_classdev
*cdev
,
351 enum led_brightness brightness
)
353 struct lm355x_chip_data
*chip
=
354 container_of(cdev
, struct lm355x_chip_data
, cdev_flash
);
356 chip
->br_flash
= brightness
;
357 schedule_work(&chip
->work_flash
);
361 static void lm355x_deferred_indicator_brightness_set(struct work_struct
*work
)
363 struct lm355x_chip_data
*chip
=
364 container_of(work
, struct lm355x_chip_data
, work_indicator
);
366 mutex_lock(&chip
->lock
);
367 lm355x_control(chip
, chip
->br_indicator
, MODE_INDIC
);
368 mutex_unlock(&chip
->lock
);
371 static void lm355x_indicator_brightness_set(struct led_classdev
*cdev
,
372 enum led_brightness brightness
)
374 struct lm355x_chip_data
*chip
=
375 container_of(cdev
, struct lm355x_chip_data
, cdev_indicator
);
377 chip
->br_indicator
= brightness
;
378 schedule_work(&chip
->work_indicator
);
381 /* indicator pattern only for lm3556*/
382 static ssize_t
lm3556_indicator_pattern_store(struct device
*dev
,
383 struct device_attribute
*attr
,
384 const char *buf
, size_t size
)
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
);
392 ret
= kstrtouint(buf
, 10, &state
);
395 if (state
> INDIC_PATTERN_SIZE
- 1)
396 state
= INDIC_PATTERN_SIZE
- 1;
398 ret
= regmap_write(chip
->regmap
, 0x04,
399 indicator_pattern
[state
].blinking
);
403 ret
= regmap_write(chip
->regmap
, 0x05,
404 indicator_pattern
[state
].period_cnt
);
410 dev_err(chip
->dev
, "%s:i2c access fail to register\n", __func__
);
414 static DEVICE_ATTR(pattern
, S_IWUSR
, NULL
, lm3556_indicator_pattern_store
);
416 static struct attribute
*lm355x_indicator_attrs
[] = {
417 &dev_attr_pattern
.attr
,
420 ATTRIBUTE_GROUPS(lm355x_indicator
);
422 static const struct regmap_config lm355x_regmap
= {
425 .max_register
= 0xFF,
428 /* module initialize */
429 static int lm355x_probe(struct i2c_client
*client
,
430 const struct i2c_device_id
*id
)
432 struct lm355x_platform_data
*pdata
= dev_get_platdata(&client
->dev
);
433 struct lm355x_chip_data
*chip
;
437 if (!i2c_check_functionality(client
->adapter
, I2C_FUNC_I2C
)) {
438 dev_err(&client
->dev
, "i2c functionality check fail.\n");
443 dev_err(&client
->dev
, "needs Platform Data.\n");
447 chip
= devm_kzalloc(&client
->dev
,
448 sizeof(struct lm355x_chip_data
), GFP_KERNEL
);
452 chip
->dev
= &client
->dev
;
453 chip
->type
= id
->driver_data
;
454 switch (id
->driver_data
) {
456 chip
->regs
= lm3554_regs
;
459 chip
->regs
= lm3556_regs
;
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
);
474 mutex_init(&chip
->lock
);
475 i2c_set_clientdata(client
, chip
);
477 err
= lm355x_chip_init(chip
);
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
);
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
);
500 goto err_create_torch_file
;
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;
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
);
516 goto err_create_indicator_file
;
518 dev_info(&client
->dev
, "%s is initialized\n",
519 lm355x_name
[id
->driver_data
]);
522 err_create_indicator_file
:
523 led_classdev_unregister(&chip
->cdev_torch
);
524 err_create_torch_file
:
525 led_classdev_unregister(&chip
->cdev_flash
);
530 static int lm355x_remove(struct i2c_client
*client
)
532 struct lm355x_chip_data
*chip
= i2c_get_clientdata(client
);
533 struct lm355x_reg_data
*preg
= chip
->regs
;
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
]);
547 static const struct i2c_device_id lm355x_id
[] = {
548 {LM3554_NAME
, CHIP_LM3554
},
549 {LM3556_NAME
, CHIP_LM3556
},
553 MODULE_DEVICE_TABLE(i2c
, lm355x_id
);
555 static struct i2c_driver lm355x_i2c_driver
= {
558 .owner
= THIS_MODULE
,
561 .probe
= lm355x_probe
,
562 .remove
= lm355x_remove
,
563 .id_table
= lm355x_id
,
566 module_i2c_driver(lm355x_i2c_driver
);
568 MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM355x");
569 MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
570 MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");
571 MODULE_LICENSE("GPL v2");