1 // SPDX-License-Identifier: GPL-2.0
2 // TI LM3532 LED driver
3 // Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
6 #include <linux/leds.h>
7 #include <linux/slab.h>
8 #include <linux/regmap.h>
9 #include <linux/types.h>
10 #include <linux/regulator/consumer.h>
11 #include <linux/module.h>
12 #include <uapi/linux/uleds.h>
13 #include <linux/gpio/consumer.h>
15 #define LM3532_NAME "lm3532-led"
16 #define LM3532_BL_MODE_MANUAL 0x00
17 #define LM3532_BL_MODE_ALS 0x01
19 #define LM3532_REG_OUTPUT_CFG 0x10
20 #define LM3532_REG_STARTSHUT_RAMP 0x11
21 #define LM3532_REG_RT_RAMP 0x12
22 #define LM3532_REG_PWM_A_CFG 0x13
23 #define LM3532_REG_PWM_B_CFG 0x14
24 #define LM3532_REG_PWM_C_CFG 0x15
25 #define LM3532_REG_ZONE_CFG_A 0x16
26 #define LM3532_REG_CTRL_A_BRT 0x17
27 #define LM3532_REG_ZONE_CFG_B 0x18
28 #define LM3532_REG_CTRL_B_BRT 0x19
29 #define LM3532_REG_ZONE_CFG_C 0x1a
30 #define LM3532_REG_CTRL_C_BRT 0x1b
31 #define LM3532_REG_ENABLE 0x1d
32 #define LM3532_ALS_CONFIG 0x23
33 #define LM3532_REG_ZN_0_HI 0x60
34 #define LM3532_REG_ZN_0_LO 0x61
35 #define LM3532_REG_ZN_1_HI 0x62
36 #define LM3532_REG_ZN_1_LO 0x63
37 #define LM3532_REG_ZN_2_HI 0x64
38 #define LM3532_REG_ZN_2_LO 0x65
39 #define LM3532_REG_ZN_3_HI 0x66
40 #define LM3532_REG_ZN_3_LO 0x67
41 #define LM3532_REG_MAX 0x7e
44 #define LM3532_CTRL_A_ENABLE BIT(0)
45 #define LM3532_CTRL_B_ENABLE BIT(1)
46 #define LM3532_CTRL_C_ENABLE BIT(2)
48 /* PWM Zone Control */
49 #define LM3532_PWM_ZONE_MASK 0x7c
50 #define LM3532_PWM_ZONE_0_EN BIT(2)
51 #define LM3532_PWM_ZONE_1_EN BIT(3)
52 #define LM3532_PWM_ZONE_2_EN BIT(4)
53 #define LM3532_PWM_ZONE_3_EN BIT(5)
54 #define LM3532_PWM_ZONE_4_EN BIT(6)
56 /* Brightness Configuration */
57 #define LM3532_I2C_CTRL BIT(0)
58 #define LM3532_ALS_CTRL 0
59 #define LM3532_LINEAR_MAP BIT(1)
60 #define LM3532_ZONE_MASK (BIT(2) | BIT(3) | BIT(4))
61 #define LM3532_ZONE_0 0
62 #define LM3532_ZONE_1 BIT(2)
63 #define LM3532_ZONE_2 BIT(3)
64 #define LM3532_ZONE_3 (BIT(2) | BIT(3))
65 #define LM3532_ZONE_4 BIT(4)
67 #define LM3532_ENABLE_ALS BIT(3)
68 #define LM3532_ALS_SEL_SHIFT 6
70 /* Zone Boundary Register */
71 #define LM3532_ALS_WINDOW_mV 2000
72 #define LM3532_ALS_ZB_MAX 4
73 #define LM3532_ALS_OFFSET_mV 2
75 #define LM3532_CONTROL_A 0
76 #define LM3532_CONTROL_B 1
77 #define LM3532_CONTROL_C 2
78 #define LM3532_MAX_CONTROL_BANKS 3
79 #define LM3532_MAX_LED_STRINGS 3
81 #define LM3532_OUTPUT_CFG_MASK 0x3
82 #define LM3532_BRT_VAL_ADJUST 8
83 #define LM3532_RAMP_DOWN_SHIFT 3
85 #define LM3532_NUM_RAMP_VALS 8
86 #define LM3532_NUM_AVG_VALS 8
87 #define LM3532_NUM_IMP_VALS 32
90 * struct lm3532_als_data
91 * @config - value of ALS configuration register
92 * @als1_imp_sel - value of ALS1 resistor select register
93 * @als2_imp_sel - value of ALS2 resistor select register
94 * @als_avrg_time - ALS averaging time
95 * @als_input_mode - ALS input mode for brightness control
96 * @als_vmin - Minimum ALS voltage
97 * @als_vmax - Maximum ALS voltage
98 * @zone_lo - values of ALS lo ZB(Zone Boundary) registers
99 * @zone_hi - values of ALS hi ZB(Zone Boundary) registers
101 struct lm3532_als_data
{
109 u8 zones_lo
[LM3532_ALS_ZB_MAX
];
110 u8 zones_hi
[LM3532_ALS_ZB_MAX
];
115 * @led_dev: led class device
116 * @priv - Pointer the device data structure
117 * @control_bank - Control bank the LED is associated to
118 * @mode - Mode of the LED string
119 * @num_leds - Number of LED strings are supported in this array
120 * @led_strings - The LED strings supported in this array
124 struct led_classdev led_dev
;
125 struct lm3532_data
*priv
;
130 u32 led_strings
[LM3532_MAX_CONTROL_BANKS
];
131 char label
[LED_MAX_NAME_SIZE
];
136 * @enable_gpio - Hardware enable gpio
137 * @regulator: regulator
138 * @client: i2c client
139 * @regmap - Devices register map
140 * @dev - Pointer to the devices device struct
141 * @lock - Lock for reading/writing the device
142 * @als_data - Pointer to the als data struct
143 * @runtime_ramp_up - Runtime ramp up setting
144 * @runtime_ramp_down - Runtime ramp down setting
145 * @leds - Array of LED strings
148 struct gpio_desc
*enable_gpio
;
149 struct regulator
*regulator
;
150 struct i2c_client
*client
;
151 struct regmap
*regmap
;
155 struct lm3532_als_data
*als_data
;
158 u32 runtime_ramp_down
;
160 struct lm3532_led leds
[];
163 static const struct reg_default lm3532_reg_defs
[] = {
164 {LM3532_REG_OUTPUT_CFG
, 0xe4},
165 {LM3532_REG_STARTSHUT_RAMP
, 0xc0},
166 {LM3532_REG_RT_RAMP
, 0xc0},
167 {LM3532_REG_PWM_A_CFG
, 0x82},
168 {LM3532_REG_PWM_B_CFG
, 0x82},
169 {LM3532_REG_PWM_C_CFG
, 0x82},
170 {LM3532_REG_ZONE_CFG_A
, 0xf1},
171 {LM3532_REG_CTRL_A_BRT
, 0xf3},
172 {LM3532_REG_ZONE_CFG_B
, 0xf1},
173 {LM3532_REG_CTRL_B_BRT
, 0xf3},
174 {LM3532_REG_ZONE_CFG_C
, 0xf1},
175 {LM3532_REG_CTRL_C_BRT
, 0xf3},
176 {LM3532_REG_ENABLE
, 0xf8},
177 {LM3532_ALS_CONFIG
, 0x44},
178 {LM3532_REG_ZN_0_HI
, 0x35},
179 {LM3532_REG_ZN_0_LO
, 0x33},
180 {LM3532_REG_ZN_1_HI
, 0x6a},
181 {LM3532_REG_ZN_1_LO
, 0x66},
182 {LM3532_REG_ZN_2_HI
, 0xa1},
183 {LM3532_REG_ZN_2_LO
, 0x99},
184 {LM3532_REG_ZN_3_HI
, 0xdc},
185 {LM3532_REG_ZN_3_LO
, 0xcc},
188 static const struct regmap_config lm3532_regmap_config
= {
192 .max_register
= LM3532_REG_MAX
,
193 .reg_defaults
= lm3532_reg_defs
,
194 .num_reg_defaults
= ARRAY_SIZE(lm3532_reg_defs
),
195 .cache_type
= REGCACHE_FLAT
,
198 const static int als_imp_table
[LM3532_NUM_IMP_VALS
] = {37000, 18500, 12330,
199 92500, 7400, 6170, 5290,
200 4630, 4110, 3700, 3360,
201 3080, 2850, 2640, 2440,
202 2310, 2180, 2060, 1950,
203 1850, 1760, 1680, 1610,
204 1540, 1480, 1420, 1370,
205 1320, 1280, 1230, 1190};
206 static int lm3532_get_als_imp_index(int als_imped
)
210 if (als_imped
> als_imp_table
[1])
213 if (als_imped
< als_imp_table
[LM3532_NUM_IMP_VALS
- 1])
214 return LM3532_NUM_IMP_VALS
- 1;
216 for (i
= 1; i
< LM3532_NUM_IMP_VALS
; i
++) {
217 if (als_imped
== als_imp_table
[i
])
220 /* Find an approximate index by looking up the table */
221 if (als_imped
< als_imp_table
[i
- 1] &&
222 als_imped
> als_imp_table
[i
]) {
223 if (als_imped
- als_imp_table
[i
- 1] <
224 als_imp_table
[i
] - als_imped
)
234 static int lm3532_get_index(const int table
[], int size
, int value
)
238 for (i
= 1; i
< size
; i
++) {
239 if (value
== table
[i
])
242 /* Find an approximate index by looking up the table */
243 if (value
> table
[i
- 1] &&
245 if (value
- table
[i
- 1] < table
[i
] - value
)
255 const static int als_avrg_table
[LM3532_NUM_AVG_VALS
] = {17920, 35840, 71680,
256 1433360, 286720, 573440,
258 static int lm3532_get_als_avg_index(int avg_time
)
260 if (avg_time
<= als_avrg_table
[0])
263 if (avg_time
> als_avrg_table
[LM3532_NUM_AVG_VALS
- 1])
264 return LM3532_NUM_AVG_VALS
- 1;
266 return lm3532_get_index(&als_avrg_table
[0], LM3532_NUM_AVG_VALS
,
270 const static int ramp_table
[LM3532_NUM_RAMP_VALS
] = { 8, 1024, 2048, 4096, 8192,
271 16384, 32768, 65536};
272 static int lm3532_get_ramp_index(int ramp_time
)
274 if (ramp_time
<= ramp_table
[0])
277 if (ramp_time
> ramp_table
[LM3532_NUM_RAMP_VALS
- 1])
278 return LM3532_NUM_RAMP_VALS
- 1;
280 return lm3532_get_index(&ramp_table
[0], LM3532_NUM_RAMP_VALS
,
284 static int lm3532_led_enable(struct lm3532_led
*led_data
)
286 int ctrl_en_val
= BIT(led_data
->control_bank
);
289 ret
= regmap_update_bits(led_data
->priv
->regmap
, LM3532_REG_ENABLE
,
290 ctrl_en_val
, ctrl_en_val
);
292 dev_err(led_data
->priv
->dev
, "Failed to set ctrl:%d\n", ret
);
296 return regulator_enable(led_data
->priv
->regulator
);
299 static int lm3532_led_disable(struct lm3532_led
*led_data
)
301 int ctrl_en_val
= BIT(led_data
->control_bank
);
304 ret
= regmap_update_bits(led_data
->priv
->regmap
, LM3532_REG_ENABLE
,
305 ctrl_en_val
, ~ctrl_en_val
);
307 dev_err(led_data
->priv
->dev
, "Failed to set ctrl:%d\n", ret
);
311 return regulator_disable(led_data
->priv
->regulator
);
314 static int lm3532_brightness_set(struct led_classdev
*led_cdev
,
315 enum led_brightness brt_val
)
317 struct lm3532_led
*led
=
318 container_of(led_cdev
, struct lm3532_led
, led_dev
);
322 mutex_lock(&led
->priv
->lock
);
324 if (led
->mode
== LM3532_BL_MODE_ALS
) {
325 if (brt_val
> LED_OFF
)
326 ret
= lm3532_led_enable(led
);
328 ret
= lm3532_led_disable(led
);
333 if (brt_val
== LED_OFF
) {
334 ret
= lm3532_led_disable(led
);
338 ret
= lm3532_led_enable(led
);
342 brightness_reg
= LM3532_REG_CTRL_A_BRT
+ led
->control_bank
* 2;
343 brt_val
= brt_val
/ LM3532_BRT_VAL_ADJUST
;
345 ret
= regmap_write(led
->priv
->regmap
, brightness_reg
, brt_val
);
348 mutex_unlock(&led
->priv
->lock
);
352 static int lm3532_init_registers(struct lm3532_led
*led
)
354 struct lm3532_data
*drvdata
= led
->priv
;
355 unsigned int runtime_ramp_val
;
356 unsigned int output_cfg_val
= 0;
357 unsigned int output_cfg_shift
= 0;
358 unsigned int output_cfg_mask
= 0;
361 for (i
= 0; i
< led
->num_leds
; i
++) {
362 output_cfg_shift
= led
->led_strings
[i
] * 2;
363 output_cfg_val
|= (led
->control_bank
<< output_cfg_shift
);
364 output_cfg_mask
|= LM3532_OUTPUT_CFG_MASK
<< output_cfg_shift
;
367 ret
= regmap_update_bits(drvdata
->regmap
, LM3532_REG_OUTPUT_CFG
,
368 output_cfg_mask
, output_cfg_val
);
372 runtime_ramp_val
= drvdata
->runtime_ramp_up
|
373 (drvdata
->runtime_ramp_down
<< LM3532_RAMP_DOWN_SHIFT
);
375 return regmap_write(drvdata
->regmap
, LM3532_REG_RT_RAMP
,
379 static int lm3532_als_configure(struct lm3532_data
*priv
,
380 struct lm3532_led
*led
)
382 struct lm3532_als_data
*als
= priv
->als_data
;
383 u32 als_vmin
, als_vmax
, als_vstep
;
384 int zone_reg
= LM3532_REG_ZN_0_HI
;
385 int brightnes_config_reg
;
389 als_vmin
= als
->als_vmin
;
390 als_vmax
= als
->als_vmax
;
392 als_vstep
= (als_vmax
- als_vmin
) / ((LM3532_ALS_ZB_MAX
+ 1) * 2);
394 for (i
= 0; i
< LM3532_ALS_ZB_MAX
; i
++) {
395 als
->zones_lo
[i
] = ((als_vmin
+ als_vstep
+ (i
* als_vstep
)) *
397 als
->zones_hi
[i
] = ((als_vmin
+ LM3532_ALS_OFFSET_mV
+
398 als_vstep
+ (i
* als_vstep
)) * LED_FULL
) / 1000;
400 zone_reg
= LM3532_REG_ZN_0_HI
+ i
* 2;
401 ret
= regmap_write(priv
->regmap
, zone_reg
, als
->zones_lo
[i
]);
406 ret
= regmap_write(priv
->regmap
, zone_reg
, als
->zones_hi
[i
]);
411 als
->config
= (als
->als_avrg_time
| (LM3532_ENABLE_ALS
) |
412 (als
->als_input_mode
<< LM3532_ALS_SEL_SHIFT
));
414 ret
= regmap_write(priv
->regmap
, LM3532_ALS_CONFIG
, als
->config
);
418 brightnes_config_reg
= LM3532_REG_ZONE_CFG_A
+ led
->control_bank
* 2;
420 return regmap_update_bits(priv
->regmap
, brightnes_config_reg
,
421 LM3532_I2C_CTRL
, LM3532_ALS_CTRL
);
424 static int lm3532_parse_als(struct lm3532_data
*priv
)
426 struct lm3532_als_data
*als
;
431 als
= devm_kzalloc(priv
->dev
, sizeof(*als
), GFP_KERNEL
);
435 ret
= device_property_read_u32(&priv
->client
->dev
, "ti,als-vmin",
440 ret
= device_property_read_u32(&priv
->client
->dev
, "ti,als-vmax",
443 als
->als_vmax
= LM3532_ALS_WINDOW_mV
;
445 if (als
->als_vmax
> LM3532_ALS_WINDOW_mV
) {
450 ret
= device_property_read_u32(&priv
->client
->dev
, "ti,als1-imp-sel",
453 als
->als1_imp_sel
= 0;
455 als
->als1_imp_sel
= lm3532_get_als_imp_index(als_impedance
);
457 ret
= device_property_read_u32(&priv
->client
->dev
, "ti,als2-imp-sel",
460 als
->als2_imp_sel
= 0;
462 als
->als2_imp_sel
= lm3532_get_als_imp_index(als_impedance
);
464 ret
= device_property_read_u32(&priv
->client
->dev
, "ti,als-avrg-time-us",
467 als
->als_avrg_time
= 0;
469 als
->als_avrg_time
= lm3532_get_als_avg_index(als_avg_time
);
471 ret
= device_property_read_u8(&priv
->client
->dev
, "ti,als-input-mode",
472 &als
->als_input_mode
);
474 als
->als_input_mode
= 0;
476 if (als
->als_input_mode
> LM3532_BL_MODE_ALS
) {
481 priv
->als_data
= als
;
486 static int lm3532_parse_node(struct lm3532_data
*priv
)
488 struct fwnode_handle
*child
= NULL
;
489 struct lm3532_led
*led
;
496 priv
->enable_gpio
= devm_gpiod_get_optional(&priv
->client
->dev
,
497 "enable", GPIOD_OUT_LOW
);
498 if (IS_ERR(priv
->enable_gpio
))
499 priv
->enable_gpio
= NULL
;
501 priv
->regulator
= devm_regulator_get(&priv
->client
->dev
, "vin");
502 if (IS_ERR(priv
->regulator
))
503 priv
->regulator
= NULL
;
505 ret
= device_property_read_u32(&priv
->client
->dev
, "ramp-up-us",
508 dev_info(&priv
->client
->dev
, "ramp-up-ms property missing\n");
510 priv
->runtime_ramp_up
= lm3532_get_ramp_index(ramp_time
);
512 ret
= device_property_read_u32(&priv
->client
->dev
, "ramp-down-us",
515 dev_info(&priv
->client
->dev
, "ramp-down-ms property missing\n");
517 priv
->runtime_ramp_down
= lm3532_get_ramp_index(ramp_time
);
519 device_for_each_child_node(priv
->dev
, child
) {
520 led
= &priv
->leds
[i
];
522 ret
= fwnode_property_read_u32(child
, "reg", &control_bank
);
524 dev_err(&priv
->client
->dev
, "reg property missing\n");
525 fwnode_handle_put(child
);
529 if (control_bank
> LM3532_CONTROL_C
) {
530 dev_err(&priv
->client
->dev
, "Control bank invalid\n");
534 led
->control_bank
= control_bank
;
536 ret
= fwnode_property_read_u32(child
, "ti,led-mode",
539 dev_err(&priv
->client
->dev
, "ti,led-mode property missing\n");
540 fwnode_handle_put(child
);
544 if (led
->mode
== LM3532_BL_MODE_ALS
) {
545 ret
= lm3532_parse_als(priv
);
547 dev_err(&priv
->client
->dev
, "Failed to parse als\n");
549 lm3532_als_configure(priv
, led
);
552 led
->num_leds
= fwnode_property_read_u32_array(child
,
556 if (led
->num_leds
> LM3532_MAX_LED_STRINGS
) {
557 dev_err(&priv
->client
->dev
, "To many LED string defined\n");
561 ret
= fwnode_property_read_u32_array(child
, "led-sources",
565 dev_err(&priv
->client
->dev
, "led-sources property missing\n");
566 fwnode_handle_put(child
);
570 fwnode_property_read_string(child
, "linux,default-trigger",
571 &led
->led_dev
.default_trigger
);
573 ret
= fwnode_property_read_string(child
, "label", &name
);
575 snprintf(led
->label
, sizeof(led
->label
),
576 "%s::", priv
->client
->name
);
578 snprintf(led
->label
, sizeof(led
->label
),
579 "%s:%s", priv
->client
->name
, name
);
582 led
->led_dev
.name
= led
->label
;
583 led
->led_dev
.brightness_set_blocking
= lm3532_brightness_set
;
585 ret
= devm_led_classdev_register(priv
->dev
, &led
->led_dev
);
587 dev_err(&priv
->client
->dev
, "led register err: %d\n",
589 fwnode_handle_put(child
);
593 lm3532_init_registers(led
);
602 static int lm3532_probe(struct i2c_client
*client
,
603 const struct i2c_device_id
*id
)
605 struct lm3532_data
*drvdata
;
609 count
= device_get_child_node_count(&client
->dev
);
611 dev_err(&client
->dev
, "LEDs are not defined in device tree!");
615 drvdata
= devm_kzalloc(&client
->dev
, struct_size(drvdata
, leds
, count
),
620 drvdata
->client
= client
;
621 drvdata
->dev
= &client
->dev
;
623 drvdata
->regmap
= devm_regmap_init_i2c(client
, &lm3532_regmap_config
);
624 if (IS_ERR(drvdata
->regmap
)) {
625 ret
= PTR_ERR(drvdata
->regmap
);
626 dev_err(&client
->dev
, "Failed to allocate register map: %d\n",
631 mutex_init(&drvdata
->lock
);
632 i2c_set_clientdata(client
, drvdata
);
634 ret
= lm3532_parse_node(drvdata
);
636 dev_err(&client
->dev
, "Failed to parse node\n");
640 if (drvdata
->enable_gpio
)
641 gpiod_direction_output(drvdata
->enable_gpio
, 1);
646 static int lm3532_remove(struct i2c_client
*client
)
648 struct lm3532_data
*drvdata
= i2c_get_clientdata(client
);
650 mutex_destroy(&drvdata
->lock
);
652 if (drvdata
->enable_gpio
)
653 gpiod_direction_output(drvdata
->enable_gpio
, 0);
658 static const struct of_device_id of_lm3532_leds_match
[] = {
659 { .compatible
= "ti,lm3532", },
662 MODULE_DEVICE_TABLE(of
, of_lm3532_leds_match
);
664 static const struct i2c_device_id lm3532_id
[] = {
668 MODULE_DEVICE_TABLE(i2c
, lm3532_id
);
670 static struct i2c_driver lm3532_i2c_driver
= {
671 .probe
= lm3532_probe
,
672 .remove
= lm3532_remove
,
673 .id_table
= lm3532_id
,
676 .of_match_table
= of_lm3532_leds_match
,
679 module_i2c_driver(lm3532_i2c_driver
);
681 MODULE_DESCRIPTION("Back Light driver for LM3532");
682 MODULE_LICENSE("GPL v2");
683 MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");