1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright 2014 Belkin Inc.
4 * Copyright 2015 Andrew Lunn <andrew@lunn.ch>
8 #include <linux/leds.h>
9 #include <linux/module.h>
11 #include <linux/regmap.h>
12 #include <linux/slab.h>
14 #define TLC591XX_MAX_LEDS 16
15 #define TLC591XX_MAX_BRIGHTNESS 256
17 #define TLC591XX_REG_MODE1 0x00
18 #define MODE1_RESPON_ADDR_MASK 0xF0
19 #define MODE1_NORMAL_MODE (0 << 4)
20 #define MODE1_SPEED_MODE (1 << 4)
22 #define TLC591XX_REG_MODE2 0x01
23 #define MODE2_DIM (0 << 5)
24 #define MODE2_BLINK (1 << 5)
25 #define MODE2_OCH_STOP (0 << 3)
26 #define MODE2_OCH_ACK (1 << 3)
28 #define TLC591XX_REG_PWM(x) (0x02 + (x))
30 #define TLC591XX_REG_GRPPWM 0x12
31 #define TLC591XX_REG_GRPFREQ 0x13
33 /* LED Driver Output State, determine the source that drives LED outputs */
34 #define LEDOUT_OFF 0x0 /* Output LOW */
35 #define LEDOUT_ON 0x1 /* Output HI-Z */
36 #define LEDOUT_DIM 0x2 /* Dimming */
37 #define LEDOUT_BLINK 0x3 /* Blinking */
38 #define LEDOUT_MASK 0x3
40 #define ldev_to_led(c) container_of(c, struct tlc591xx_led, ldev)
45 struct led_classdev ldev
;
46 struct tlc591xx_priv
*priv
;
49 struct tlc591xx_priv
{
50 struct tlc591xx_led leds
[TLC591XX_MAX_LEDS
];
51 struct regmap
*regmap
;
52 unsigned int reg_ledout_offset
;
56 unsigned int max_leds
;
57 unsigned int reg_ledout_offset
;
60 static const struct tlc591xx tlc59116
= {
62 .reg_ledout_offset
= 0x14,
65 static const struct tlc591xx tlc59108
= {
67 .reg_ledout_offset
= 0x0c,
71 tlc591xx_set_mode(struct regmap
*regmap
, u8 mode
)
76 err
= regmap_write(regmap
, TLC591XX_REG_MODE1
, MODE1_NORMAL_MODE
);
80 val
= MODE2_OCH_STOP
| mode
;
82 return regmap_write(regmap
, TLC591XX_REG_MODE2
, val
);
86 tlc591xx_set_ledout(struct tlc591xx_priv
*priv
, struct tlc591xx_led
*led
,
89 unsigned int i
= (led
->led_no
% 4) * 2;
90 unsigned int mask
= LEDOUT_MASK
<< i
;
91 unsigned int addr
= priv
->reg_ledout_offset
+ (led
->led_no
>> 2);
95 return regmap_update_bits(priv
->regmap
, addr
, mask
, val
);
99 tlc591xx_set_pwm(struct tlc591xx_priv
*priv
, struct tlc591xx_led
*led
,
102 u8 pwm
= TLC591XX_REG_PWM(led
->led_no
);
104 return regmap_write(priv
->regmap
, pwm
, brightness
);
108 tlc591xx_brightness_set(struct led_classdev
*led_cdev
,
109 enum led_brightness brightness
)
111 struct tlc591xx_led
*led
= ldev_to_led(led_cdev
);
112 struct tlc591xx_priv
*priv
= led
->priv
;
115 switch ((int)brightness
) {
117 err
= tlc591xx_set_ledout(priv
, led
, LEDOUT_OFF
);
119 case TLC591XX_MAX_BRIGHTNESS
:
120 err
= tlc591xx_set_ledout(priv
, led
, LEDOUT_ON
);
123 err
= tlc591xx_set_ledout(priv
, led
, LEDOUT_DIM
);
125 err
= tlc591xx_set_pwm(priv
, led
, brightness
);
131 static const struct regmap_config tlc591xx_regmap
= {
134 .max_register
= 0x1e,
137 static const struct of_device_id of_tlc591xx_leds_match
[] __maybe_unused
= {
138 { .compatible
= "ti,tlc59116",
140 { .compatible
= "ti,tlc59108",
144 MODULE_DEVICE_TABLE(of
, of_tlc591xx_leds_match
);
147 tlc591xx_probe(struct i2c_client
*client
)
149 struct device_node
*np
;
150 struct device
*dev
= &client
->dev
;
151 const struct tlc591xx
*tlc591xx
;
152 struct tlc591xx_priv
*priv
;
155 np
= dev_of_node(dev
);
159 tlc591xx
= device_get_match_data(dev
);
163 count
= of_get_available_child_count(np
);
164 if (!count
|| count
> tlc591xx
->max_leds
)
167 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
171 priv
->regmap
= devm_regmap_init_i2c(client
, &tlc591xx_regmap
);
172 if (IS_ERR(priv
->regmap
)) {
173 err
= PTR_ERR(priv
->regmap
);
174 dev_err(dev
, "Failed to allocate register map: %d\n", err
);
177 priv
->reg_ledout_offset
= tlc591xx
->reg_ledout_offset
;
179 i2c_set_clientdata(client
, priv
);
181 err
= tlc591xx_set_mode(priv
->regmap
, MODE2_DIM
);
185 for_each_available_child_of_node_scoped(np
, child
) {
186 struct tlc591xx_led
*led
;
187 struct led_init_data init_data
= {};
189 init_data
.fwnode
= of_fwnode_handle(child
);
191 err
= of_property_read_u32(child
, "reg", ®
);
195 if (reg
< 0 || reg
>= tlc591xx
->max_leds
||
196 priv
->leds
[reg
].active
)
199 led
= &priv
->leds
[reg
];
204 led
->ldev
.brightness_set_blocking
= tlc591xx_brightness_set
;
205 led
->ldev
.max_brightness
= TLC591XX_MAX_BRIGHTNESS
;
206 err
= devm_led_classdev_register_ext(dev
, &led
->ldev
,
209 return dev_err_probe(dev
, err
,
210 "couldn't register LED %s\n",
216 static const struct i2c_device_id tlc591xx_id
[] = {
221 MODULE_DEVICE_TABLE(i2c
, tlc591xx_id
);
223 static struct i2c_driver tlc591xx_driver
= {
226 .of_match_table
= of_match_ptr(of_tlc591xx_leds_match
),
228 .probe
= tlc591xx_probe
,
229 .id_table
= tlc591xx_id
,
232 module_i2c_driver(tlc591xx_driver
);
234 MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
235 MODULE_LICENSE("GPL");
236 MODULE_DESCRIPTION("TLC591XX LED driver");