2 * Simple driver for Texas Instruments LM3556 LED Flash driver chip (Rev0x03)
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.
9 * Please refer Documentation/leds/leds-lm3556.txt file.
11 #include <linux/module.h>
12 #include <linux/delay.h>
13 #include <linux/i2c.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-lm3556.h>
21 #define REG_FILT_TIME (0x0)
22 #define REG_IVFM_MODE (0x1)
24 #define REG_INDIC_TIME (0x3)
25 #define REG_INDIC_BLINK (0x4)
26 #define REG_INDIC_PERIOD (0x5)
27 #define REG_TORCH_TIME (0x6)
28 #define REG_CONF (0x7)
29 #define REG_FLASH (0x8)
30 #define REG_I_CTRL (0x9)
31 #define REG_ENABLE (0xA)
32 #define REG_FLAG (0xB)
35 #define IVFM_FILTER_TIME_SHIFT (3)
36 #define UVLO_EN_SHIFT (7)
37 #define HYSTERSIS_SHIFT (5)
38 #define IVM_D_TH_SHIFT (2)
39 #define IVFM_ADJ_MODE_SHIFT (0)
40 #define NTC_EVENT_LVL_SHIFT (5)
41 #define NTC_TRIP_TH_SHIFT (2)
42 #define NTC_BIAS_I_LVL_SHIFT (0)
43 #define INDIC_RAMP_UP_TIME_SHIFT (3)
44 #define INDIC_RAMP_DN_TIME_SHIFT (0)
45 #define INDIC_N_BLANK_SHIFT (4)
46 #define INDIC_PULSE_TIME_SHIFT (0)
47 #define INDIC_N_PERIOD_SHIFT (0)
48 #define TORCH_RAMP_UP_TIME_SHIFT (3)
49 #define TORCH_RAMP_DN_TIME_SHIFT (0)
50 #define STROBE_USUAGE_SHIFT (7)
51 #define STROBE_PIN_POLARITY_SHIFT (6)
52 #define TORCH_PIN_POLARITY_SHIFT (5)
53 #define TX_PIN_POLARITY_SHIFT (4)
54 #define TX_EVENT_LVL_SHIFT (3)
55 #define IVFM_EN_SHIFT (2)
56 #define NTC_MODE_SHIFT (1)
57 #define INDIC_MODE_SHIFT (0)
58 #define INDUCTOR_I_LIMIT_SHIFT (6)
59 #define FLASH_RAMP_TIME_SHIFT (3)
60 #define FLASH_TOUT_TIME_SHIFT (0)
61 #define TORCH_I_SHIFT (4)
62 #define FLASH_I_SHIFT (0)
63 #define NTC_EN_SHIFT (7)
64 #define TX_PIN_EN_SHIFT (6)
65 #define STROBE_PIN_EN_SHIFT (5)
66 #define TORCH_PIN_EN_SHIFT (4)
67 #define PRECHG_MODE_EN_SHIFT (3)
68 #define PASS_MODE_ONLY_EN_SHIFT (2)
69 #define MODE_BITS_SHIFT (0)
71 #define IVFM_FILTER_TIME_MASK (0x3)
72 #define UVLO_EN_MASK (0x1)
73 #define HYSTERSIS_MASK (0x3)
74 #define IVM_D_TH_MASK (0x7)
75 #define IVFM_ADJ_MODE_MASK (0x3)
76 #define NTC_EVENT_LVL_MASK (0x1)
77 #define NTC_TRIP_TH_MASK (0x7)
78 #define NTC_BIAS_I_LVL_MASK (0x3)
79 #define INDIC_RAMP_UP_TIME_MASK (0x7)
80 #define INDIC_RAMP_DN_TIME_MASK (0x7)
81 #define INDIC_N_BLANK_MASK (0x7)
82 #define INDIC_PULSE_TIME_MASK (0x7)
83 #define INDIC_N_PERIOD_MASK (0x7)
84 #define TORCH_RAMP_UP_TIME_MASK (0x7)
85 #define TORCH_RAMP_DN_TIME_MASK (0x7)
86 #define STROBE_USUAGE_MASK (0x1)
87 #define STROBE_PIN_POLARITY_MASK (0x1)
88 #define TORCH_PIN_POLARITY_MASK (0x1)
89 #define TX_PIN_POLARITY_MASK (0x1)
90 #define TX_EVENT_LVL_MASK (0x1)
91 #define IVFM_EN_MASK (0x1)
92 #define NTC_MODE_MASK (0x1)
93 #define INDIC_MODE_MASK (0x1)
94 #define INDUCTOR_I_LIMIT_MASK (0x3)
95 #define FLASH_RAMP_TIME_MASK (0x7)
96 #define FLASH_TOUT_TIME_MASK (0x7)
97 #define TORCH_I_MASK (0x7)
98 #define FLASH_I_MASK (0xF)
99 #define NTC_EN_MASK (0x1)
100 #define TX_PIN_EN_MASK (0x1)
101 #define STROBE_PIN_EN_MASK (0x1)
102 #define TORCH_PIN_EN_MASK (0x1)
103 #define PRECHG_MODE_EN_MASK (0x1)
104 #define PASS_MODE_ONLY_EN_MASK (0x1)
105 #define MODE_BITS_MASK (0x13)
106 #define EX_PIN_CONTROL_MASK (0xF1)
107 #define EX_PIN_ENABLE_MASK (0x70)
109 enum lm3556_indic_pulse_time
{
128 enum lm3556_indic_n_blank
{
147 enum lm3556_indic_period
{
165 #define INDIC_PATTERN_SIZE 4
172 struct lm3556_chip_data
{
175 struct led_classdev cdev_flash
;
176 struct led_classdev cdev_torch
;
177 struct led_classdev cdev_indicator
;
179 struct lm3556_platform_data
*pdata
;
180 struct regmap
*regmap
;
183 unsigned int last_flag
;
186 /* indicator pattern */
187 static struct indicator indicator_pattern
[INDIC_PATTERN_SIZE
] = {
188 [0] = {(INDIC_N_BLANK_1
<< INDIC_N_BLANK_SHIFT
)
189 | PULSE_TIME_32_MS
, INDIC_PERIOD_1
},
190 [1] = {(INDIC_N_BLANK_15
<< INDIC_N_BLANK_SHIFT
)
191 | PULSE_TIME_32_MS
, INDIC_PERIOD_2
},
192 [2] = {(INDIC_N_BLANK_10
<< INDIC_N_BLANK_SHIFT
)
193 | PULSE_TIME_32_MS
, INDIC_PERIOD_4
},
194 [3] = {(INDIC_N_BLANK_5
<< INDIC_N_BLANK_SHIFT
)
195 | PULSE_TIME_32_MS
, INDIC_PERIOD_7
},
198 /* chip initialize */
199 static int __devinit
lm3556_chip_init(struct lm3556_chip_data
*chip
)
201 unsigned int reg_val
;
203 struct lm3556_platform_data
*pdata
= chip
->pdata
;
205 /* set config register */
206 ret
= regmap_read(chip
->regmap
, REG_CONF
, ®_val
);
208 dev_err(chip
->dev
, "Failed to read REG_CONF Register\n");
212 reg_val
&= (~EX_PIN_CONTROL_MASK
);
213 reg_val
|= ((pdata
->torch_pin_polarity
& 0x01)
214 << TORCH_PIN_POLARITY_SHIFT
);
215 reg_val
|= ((pdata
->strobe_usuage
& 0x01) << STROBE_USUAGE_SHIFT
);
216 reg_val
|= ((pdata
->strobe_pin_polarity
& 0x01)
217 << STROBE_PIN_POLARITY_SHIFT
);
218 reg_val
|= ((pdata
->tx_pin_polarity
& 0x01) << TX_PIN_POLARITY_SHIFT
);
219 reg_val
|= ((pdata
->indicator_mode
& 0x01) << INDIC_MODE_SHIFT
);
221 ret
= regmap_write(chip
->regmap
, REG_CONF
, reg_val
);
223 dev_err(chip
->dev
, "Failed to write REG_CONF Regisgter\n");
227 /* set enable register */
228 ret
= regmap_read(chip
->regmap
, REG_ENABLE
, ®_val
);
230 dev_err(chip
->dev
, "Failed to read REG_ENABLE Register\n");
234 reg_val
&= (~EX_PIN_ENABLE_MASK
);
235 reg_val
|= ((pdata
->torch_pin_en
& 0x01) << TORCH_PIN_EN_SHIFT
);
236 reg_val
|= ((pdata
->strobe_pin_en
& 0x01) << STROBE_PIN_EN_SHIFT
);
237 reg_val
|= ((pdata
->tx_pin_en
& 0x01) << TX_PIN_EN_SHIFT
);
239 ret
= regmap_write(chip
->regmap
, REG_ENABLE
, reg_val
);
241 dev_err(chip
->dev
, "Failed to write REG_ENABLE Regisgter\n");
250 static int lm3556_control(struct lm3556_chip_data
*chip
,
251 u8 brightness
, enum lm3556_mode opmode
)
254 struct lm3556_platform_data
*pdata
= chip
->pdata
;
256 ret
= regmap_read(chip
->regmap
, REG_FLAG
, &chip
->last_flag
);
258 dev_err(chip
->dev
, "Failed to read REG_FLAG Register\n");
263 dev_info(chip
->dev
, "Last FLAG is 0x%x\n", chip
->last_flag
);
265 /* brightness 0 means off-state */
267 opmode
= MODES_STASNDBY
;
271 ret
= regmap_update_bits(chip
->regmap
, REG_I_CTRL
,
272 TORCH_I_MASK
<< TORCH_I_SHIFT
,
273 (brightness
- 1) << TORCH_I_SHIFT
);
275 if (pdata
->torch_pin_en
)
276 opmode
|= (TORCH_PIN_EN_MASK
<< TORCH_PIN_EN_SHIFT
);
280 ret
= regmap_update_bits(chip
->regmap
, REG_I_CTRL
,
281 FLASH_I_MASK
<< FLASH_I_SHIFT
,
282 (brightness
- 1) << FLASH_I_SHIFT
);
286 ret
= regmap_update_bits(chip
->regmap
, REG_I_CTRL
,
287 TORCH_I_MASK
<< TORCH_I_SHIFT
,
288 (brightness
- 1) << TORCH_I_SHIFT
);
292 if (pdata
->torch_pin_en
)
293 opmode
|= (TORCH_PIN_EN_MASK
<< TORCH_PIN_EN_SHIFT
);
300 dev_err(chip
->dev
, "Failed to write REG_I_CTRL Register\n");
303 ret
= regmap_update_bits(chip
->regmap
, REG_ENABLE
,
304 MODE_BITS_MASK
<< MODE_BITS_SHIFT
,
305 opmode
<< MODE_BITS_SHIFT
);
312 static void lm3556_torch_brightness_set(struct led_classdev
*cdev
,
313 enum led_brightness brightness
)
315 struct lm3556_chip_data
*chip
=
316 container_of(cdev
, struct lm3556_chip_data
, cdev_torch
);
318 mutex_lock(&chip
->lock
);
319 lm3556_control(chip
, brightness
, MODES_TORCH
);
320 mutex_unlock(&chip
->lock
);
324 static void lm3556_strobe_brightness_set(struct led_classdev
*cdev
,
325 enum led_brightness brightness
)
327 struct lm3556_chip_data
*chip
=
328 container_of(cdev
, struct lm3556_chip_data
, cdev_flash
);
330 mutex_lock(&chip
->lock
);
331 lm3556_control(chip
, brightness
, MODES_FLASH
);
332 mutex_unlock(&chip
->lock
);
336 static void lm3556_indicator_brightness_set(struct led_classdev
*cdev
,
337 enum led_brightness brightness
)
339 struct lm3556_chip_data
*chip
=
340 container_of(cdev
, struct lm3556_chip_data
, cdev_indicator
);
342 mutex_lock(&chip
->lock
);
343 lm3556_control(chip
, brightness
, MODES_INDIC
);
344 mutex_unlock(&chip
->lock
);
347 /* indicator pattern */
348 static ssize_t
lm3556_indicator_pattern_store(struct device
*dev
,
349 struct device_attribute
*devAttr
,
350 const char *buf
, size_t size
)
353 struct led_classdev
*led_cdev
= dev_get_drvdata(dev
);
354 struct lm3556_chip_data
*chip
=
355 container_of(led_cdev
, struct lm3556_chip_data
, cdev_indicator
);
358 ret
= kstrtouint(buf
, 10, &state
);
361 if (state
> INDIC_PATTERN_SIZE
- 1)
362 state
= INDIC_PATTERN_SIZE
- 1;
364 ret
= regmap_write(chip
->regmap
, REG_INDIC_BLINK
,
365 indicator_pattern
[state
].blinking
);
367 dev_err(chip
->dev
, "Failed to write REG_ENABLE Regisgter\n");
371 ret
= regmap_write(chip
->regmap
, REG_INDIC_PERIOD
,
372 indicator_pattern
[state
].period_cnt
);
374 dev_err(chip
->dev
, "Failed to write REG_ENABLE Regisgter\n");
380 dev_err(chip
->dev
, "Indicator pattern doesn't saved\n");
384 static DEVICE_ATTR(pattern
, 0666, NULL
, lm3556_indicator_pattern_store
);
386 static const struct regmap_config lm3556_regmap
= {
389 .max_register
= REG_MAX
,
392 /* module initialize */
393 static int __devinit
lm3556_probe(struct i2c_client
*client
,
394 const struct i2c_device_id
*id
)
396 struct lm3556_platform_data
*pdata
= client
->dev
.platform_data
;
397 struct lm3556_chip_data
*chip
;
401 if (!i2c_check_functionality(client
->adapter
, I2C_FUNC_I2C
)) {
402 dev_err(&client
->dev
, "i2c functionality check fail.\n");
407 dev_err(&client
->dev
, "Needs Platform Data.\n");
412 devm_kzalloc(&client
->dev
, sizeof(struct lm3556_chip_data
),
417 chip
->dev
= &client
->dev
;
420 chip
->regmap
= devm_regmap_init_i2c(client
, &lm3556_regmap
);
421 if (IS_ERR(chip
->regmap
)) {
422 err
= PTR_ERR(chip
->regmap
);
423 dev_err(&client
->dev
, "Failed to allocate register map: %d\n",
428 mutex_init(&chip
->lock
);
429 i2c_set_clientdata(client
, chip
);
431 err
= lm3556_chip_init(chip
);
436 chip
->cdev_flash
.name
= "flash";
437 chip
->cdev_flash
.max_brightness
= 16;
438 chip
->cdev_flash
.brightness_set
= lm3556_strobe_brightness_set
;
439 err
= led_classdev_register((struct device
*)
440 &client
->dev
, &chip
->cdev_flash
);
444 chip
->cdev_torch
.name
= "torch";
445 chip
->cdev_torch
.max_brightness
= 8;
446 chip
->cdev_torch
.brightness_set
= lm3556_torch_brightness_set
;
447 err
= led_classdev_register((struct device
*)
448 &client
->dev
, &chip
->cdev_torch
);
450 goto err_create_torch_file
;
452 chip
->cdev_indicator
.name
= "indicator";
453 chip
->cdev_indicator
.max_brightness
= 8;
454 chip
->cdev_indicator
.brightness_set
= lm3556_indicator_brightness_set
;
455 err
= led_classdev_register((struct device
*)
456 &client
->dev
, &chip
->cdev_indicator
);
458 goto err_create_indicator_file
;
460 err
= device_create_file(chip
->cdev_indicator
.dev
, &dev_attr_pattern
);
462 goto err_create_pattern_file
;
464 dev_info(&client
->dev
, "LM3556 is initialized\n");
467 err_create_pattern_file
:
468 led_classdev_unregister(&chip
->cdev_indicator
);
469 err_create_indicator_file
:
470 led_classdev_unregister(&chip
->cdev_torch
);
471 err_create_torch_file
:
472 led_classdev_unregister(&chip
->cdev_flash
);
477 static int __devexit
lm3556_remove(struct i2c_client
*client
)
479 struct lm3556_chip_data
*chip
= i2c_get_clientdata(client
);
481 device_remove_file(chip
->cdev_indicator
.dev
, &dev_attr_pattern
);
482 led_classdev_unregister(&chip
->cdev_indicator
);
483 led_classdev_unregister(&chip
->cdev_torch
);
484 led_classdev_unregister(&chip
->cdev_flash
);
485 regmap_write(chip
->regmap
, REG_ENABLE
, 0);
489 static const struct i2c_device_id lm3556_id
[] = {
494 MODULE_DEVICE_TABLE(i2c
, lm3556_id
);
496 static struct i2c_driver lm3556_i2c_driver
= {
499 .owner
= THIS_MODULE
,
502 .probe
= lm3556_probe
,
503 .remove
= __devexit_p(lm3556_remove
),
504 .id_table
= lm3556_id
,
507 module_i2c_driver(lm3556_i2c_driver
);
509 MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3556");
510 MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
511 MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");
512 MODULE_LICENSE("GPL v2");