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/platform_data/leds-lm355x.h>
46 /* register map info. */
47 struct lm355x_reg_data
{
53 struct lm355x_chip_data
{
55 enum lm355x_type type
;
57 struct led_classdev cdev_flash
;
58 struct led_classdev cdev_torch
;
59 struct led_classdev cdev_indicator
;
61 struct lm355x_platform_data
*pdata
;
62 struct regmap
*regmap
;
65 unsigned int last_flag
;
66 struct lm355x_reg_data
*regs
;
69 /* specific indicator function for lm3556 */
70 enum lm3556_indic_pulse_time
{
89 enum lm3556_indic_n_blank
{
108 enum lm3556_indic_period
{
119 #define INDIC_PATTERN_SIZE 4
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
},
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},
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},
156 static char lm355x_name
[][I2C_NAME_SIZE
] = {
157 [CHIP_LM3554
] = LM3554_NAME
,
158 [CHIP_LM3556
] = LM3556_NAME
,
161 /* chip initialize */
162 static int lm355x_chip_init(struct lm355x_chip_data
*chip
)
165 unsigned int reg_val
;
166 struct lm355x_platform_data
*pdata
= chip
->pdata
;
168 /* input and output pins configuration */
169 switch (chip
->type
) {
171 reg_val
= pdata
->pin_tx2
| pdata
->ntc_pin
;
172 ret
= regmap_update_bits(chip
->regmap
, 0xE0, 0x28, reg_val
);
175 reg_val
= pdata
->pass_mode
;
176 ret
= regmap_update_bits(chip
->regmap
, 0xA0, 0x04, reg_val
);
182 reg_val
= pdata
->pin_tx2
| pdata
->ntc_pin
| pdata
->pass_mode
;
183 ret
= regmap_update_bits(chip
->regmap
, 0x0A, 0xC4, reg_val
);
193 dev_err(chip
->dev
, "%s:i2c access fail to register\n", __func__
);
198 static int lm355x_control(struct lm355x_chip_data
*chip
,
199 u8 brightness
, enum lm355x_mode opmode
)
202 unsigned int reg_val
;
203 struct lm355x_platform_data
*pdata
= chip
->pdata
;
204 struct lm355x_reg_data
*preg
= chip
->regs
;
206 ret
= regmap_read(chip
->regmap
, preg
[REG_FLAG
].regno
, &chip
->last_flag
);
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 */
220 regmap_update_bits(chip
->regmap
, preg
[REG_TORCH_CTRL
].regno
,
221 preg
[REG_TORCH_CTRL
].mask
,
223 << preg
[REG_TORCH_CTRL
].shift
);
227 if (pdata
->pin_tx1
!= LM355x_PIN_TORCH_DISABLE
) {
229 regmap_update_bits(chip
->regmap
,
230 preg
[REG_TORCH_CFG
].regno
,
231 preg
[REG_TORCH_CFG
].mask
,
233 preg
[REG_TORCH_CFG
].shift
);
238 "torch brt is set - ext. torch pin mode\n");
245 regmap_update_bits(chip
->regmap
, preg
[REG_FLASH_CTRL
].regno
,
246 preg
[REG_FLASH_CTRL
].mask
,
248 << preg
[REG_FLASH_CTRL
].shift
);
252 if (pdata
->pin_strobe
!= LM355x_PIN_STROBE_DISABLE
) {
253 if (chip
->type
== CHIP_LM3554
)
258 regmap_update_bits(chip
->regmap
,
259 preg
[REG_STROBE_CFG
].regno
,
260 preg
[REG_STROBE_CFG
].mask
,
262 preg
[REG_STROBE_CFG
].shift
);
267 "flash brt is set - ext. strobe pin mode\n");
273 regmap_update_bits(chip
->regmap
, preg
[REG_INDI_CTRL
].regno
,
274 preg
[REG_INDI_CTRL
].mask
,
276 << preg
[REG_INDI_CTRL
].shift
);
280 if (pdata
->pin_tx2
!= LM355x_PIN_TX_DISABLE
) {
282 regmap_update_bits(chip
->regmap
,
283 preg
[REG_INDI_CFG
].regno
,
284 preg
[REG_INDI_CFG
].mask
,
286 preg
[REG_INDI_CFG
].shift
);
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
);
305 dev_err(chip
->dev
, "%s:i2c access fail to register\n", __func__
);
311 static int lm355x_torch_brightness_set(struct led_classdev
*cdev
,
312 enum led_brightness brightness
)
314 struct lm355x_chip_data
*chip
=
315 container_of(cdev
, struct lm355x_chip_data
, cdev_torch
);
318 mutex_lock(&chip
->lock
);
319 ret
= lm355x_control(chip
, brightness
, MODE_TORCH
);
320 mutex_unlock(&chip
->lock
);
326 static int lm355x_strobe_brightness_set(struct led_classdev
*cdev
,
327 enum led_brightness brightness
)
329 struct lm355x_chip_data
*chip
=
330 container_of(cdev
, struct lm355x_chip_data
, cdev_flash
);
333 mutex_lock(&chip
->lock
);
334 ret
= lm355x_control(chip
, brightness
, MODE_FLASH
);
335 mutex_unlock(&chip
->lock
);
341 static int lm355x_indicator_brightness_set(struct led_classdev
*cdev
,
342 enum led_brightness brightness
)
344 struct lm355x_chip_data
*chip
=
345 container_of(cdev
, struct lm355x_chip_data
, cdev_indicator
);
348 mutex_lock(&chip
->lock
);
349 ret
= lm355x_control(chip
, brightness
, MODE_INDIC
);
350 mutex_unlock(&chip
->lock
);
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
)
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
);
365 ret
= kstrtouint(buf
, 10, &state
);
368 if (state
> INDIC_PATTERN_SIZE
- 1)
369 state
= INDIC_PATTERN_SIZE
- 1;
371 ret
= regmap_write(chip
->regmap
, 0x04,
372 indicator_pattern
[state
].blinking
);
376 ret
= regmap_write(chip
->regmap
, 0x05,
377 indicator_pattern
[state
].period_cnt
);
383 dev_err(chip
->dev
, "%s:i2c access fail to register\n", __func__
);
387 static DEVICE_ATTR(pattern
, S_IWUSR
, NULL
, lm3556_indicator_pattern_store
);
389 static struct attribute
*lm355x_indicator_attrs
[] = {
390 &dev_attr_pattern
.attr
,
393 ATTRIBUTE_GROUPS(lm355x_indicator
);
395 static const struct regmap_config lm355x_regmap
= {
398 .max_register
= 0xFF,
401 /* module initialize */
402 static int lm355x_probe(struct i2c_client
*client
,
403 const struct i2c_device_id
*id
)
405 struct lm355x_platform_data
*pdata
= dev_get_platdata(&client
->dev
);
406 struct lm355x_chip_data
*chip
;
410 if (!i2c_check_functionality(client
->adapter
, I2C_FUNC_I2C
)) {
411 dev_err(&client
->dev
, "i2c functionality check fail.\n");
416 dev_err(&client
->dev
, "needs Platform Data.\n");
420 chip
= devm_kzalloc(&client
->dev
,
421 sizeof(struct lm355x_chip_data
), GFP_KERNEL
);
425 chip
->dev
= &client
->dev
;
426 chip
->type
= id
->driver_data
;
427 switch (id
->driver_data
) {
429 chip
->regs
= lm3554_regs
;
432 chip
->regs
= lm3556_regs
;
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
);
447 mutex_init(&chip
->lock
);
448 i2c_set_clientdata(client
, chip
);
450 err
= lm355x_chip_init(chip
);
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
);
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
);
471 goto err_create_torch_file
;
473 chip
->cdev_indicator
.name
= "indicator";
474 if (id
->driver_data
== CHIP_LM3554
)
475 chip
->cdev_indicator
.max_brightness
= 4;
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
);
486 goto err_create_indicator_file
;
488 dev_info(&client
->dev
, "%s is initialized\n",
489 lm355x_name
[id
->driver_data
]);
492 err_create_indicator_file
:
493 led_classdev_unregister(&chip
->cdev_torch
);
494 err_create_torch_file
:
495 led_classdev_unregister(&chip
->cdev_flash
);
500 static int lm355x_remove(struct i2c_client
*client
)
502 struct lm355x_chip_data
*chip
= i2c_get_clientdata(client
);
503 struct lm355x_reg_data
*preg
= chip
->regs
;
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
]);
514 static const struct i2c_device_id lm355x_id
[] = {
515 {LM3554_NAME
, CHIP_LM3554
},
516 {LM3556_NAME
, CHIP_LM3556
},
520 MODULE_DEVICE_TABLE(i2c
, lm355x_id
);
522 static struct i2c_driver lm355x_i2c_driver
= {
527 .probe
= lm355x_probe
,
528 .remove
= lm355x_remove
,
529 .id_table
= lm355x_id
,
532 module_i2c_driver(lm355x_i2c_driver
);
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");