2 * Copyright 2014 Belkin Inc.
3 * Copyright 2015 Andrew Lunn <andrew@lunn.ch>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
10 #include <linux/i2c.h>
11 #include <linux/leds.h>
12 #include <linux/module.h>
14 #include <linux/of_device.h>
15 #include <linux/regmap.h>
16 #include <linux/slab.h>
18 #define TLC591XX_MAX_LEDS 16
20 #define TLC591XX_REG_MODE1 0x00
21 #define MODE1_RESPON_ADDR_MASK 0xF0
22 #define MODE1_NORMAL_MODE (0 << 4)
23 #define MODE1_SPEED_MODE (1 << 4)
25 #define TLC591XX_REG_MODE2 0x01
26 #define MODE2_DIM (0 << 5)
27 #define MODE2_BLINK (1 << 5)
28 #define MODE2_OCH_STOP (0 << 3)
29 #define MODE2_OCH_ACK (1 << 3)
31 #define TLC591XX_REG_PWM(x) (0x02 + (x))
33 #define TLC591XX_REG_GRPPWM 0x12
34 #define TLC591XX_REG_GRPFREQ 0x13
36 /* LED Driver Output State, determine the source that drives LED outputs */
37 #define LEDOUT_OFF 0x0 /* Output LOW */
38 #define LEDOUT_ON 0x1 /* Output HI-Z */
39 #define LEDOUT_DIM 0x2 /* Dimming */
40 #define LEDOUT_BLINK 0x3 /* Blinking */
41 #define LEDOUT_MASK 0x3
43 #define ldev_to_led(c) container_of(c, struct tlc591xx_led, ldev)
48 struct led_classdev ldev
;
49 struct tlc591xx_priv
*priv
;
52 struct tlc591xx_priv
{
53 struct tlc591xx_led leds
[TLC591XX_MAX_LEDS
];
54 struct regmap
*regmap
;
55 unsigned int reg_ledout_offset
;
59 unsigned int max_leds
;
60 unsigned int reg_ledout_offset
;
63 static const struct tlc591xx tlc59116
= {
65 .reg_ledout_offset
= 0x14,
68 static const struct tlc591xx tlc59108
= {
70 .reg_ledout_offset
= 0x0c,
74 tlc591xx_set_mode(struct regmap
*regmap
, u8 mode
)
79 err
= regmap_write(regmap
, TLC591XX_REG_MODE1
, MODE1_NORMAL_MODE
);
83 val
= MODE2_OCH_STOP
| mode
;
85 return regmap_write(regmap
, TLC591XX_REG_MODE2
, val
);
89 tlc591xx_set_ledout(struct tlc591xx_priv
*priv
, struct tlc591xx_led
*led
,
92 unsigned int i
= (led
->led_no
% 4) * 2;
93 unsigned int mask
= LEDOUT_MASK
<< i
;
94 unsigned int addr
= priv
->reg_ledout_offset
+ (led
->led_no
>> 2);
98 return regmap_update_bits(priv
->regmap
, addr
, mask
, val
);
102 tlc591xx_set_pwm(struct tlc591xx_priv
*priv
, struct tlc591xx_led
*led
,
105 u8 pwm
= TLC591XX_REG_PWM(led
->led_no
);
107 return regmap_write(priv
->regmap
, pwm
, brightness
);
111 tlc591xx_brightness_set(struct led_classdev
*led_cdev
,
112 enum led_brightness brightness
)
114 struct tlc591xx_led
*led
= ldev_to_led(led_cdev
);
115 struct tlc591xx_priv
*priv
= led
->priv
;
118 switch (brightness
) {
120 err
= tlc591xx_set_ledout(priv
, led
, LEDOUT_OFF
);
123 err
= tlc591xx_set_ledout(priv
, led
, LEDOUT_ON
);
126 err
= tlc591xx_set_ledout(priv
, led
, LEDOUT_DIM
);
128 err
= tlc591xx_set_pwm(priv
, led
, brightness
);
135 tlc591xx_destroy_devices(struct tlc591xx_priv
*priv
, unsigned int j
)
140 if (priv
->leds
[i
].active
)
141 led_classdev_unregister(&priv
->leds
[i
].ldev
);
146 tlc591xx_configure(struct device
*dev
,
147 struct tlc591xx_priv
*priv
,
148 const struct tlc591xx
*tlc591xx
)
153 tlc591xx_set_mode(priv
->regmap
, MODE2_DIM
);
154 for (i
= 0; i
< TLC591XX_MAX_LEDS
; i
++) {
155 struct tlc591xx_led
*led
= &priv
->leds
[i
];
162 led
->ldev
.brightness_set_blocking
= tlc591xx_brightness_set
;
163 led
->ldev
.max_brightness
= LED_FULL
;
164 err
= led_classdev_register(dev
, &led
->ldev
);
166 dev_err(dev
, "couldn't register LED %s\n",
175 tlc591xx_destroy_devices(priv
, i
);
179 static const struct regmap_config tlc591xx_regmap
= {
182 .max_register
= 0x1e,
185 static const struct of_device_id of_tlc591xx_leds_match
[] = {
186 { .compatible
= "ti,tlc59116",
188 { .compatible
= "ti,tlc59108",
192 MODULE_DEVICE_TABLE(of
, of_tlc591xx_leds_match
);
195 tlc591xx_probe(struct i2c_client
*client
,
196 const struct i2c_device_id
*id
)
198 struct device_node
*np
= client
->dev
.of_node
, *child
;
199 struct device
*dev
= &client
->dev
;
200 const struct of_device_id
*match
;
201 const struct tlc591xx
*tlc591xx
;
202 struct tlc591xx_priv
*priv
;
205 match
= of_match_device(of_tlc591xx_leds_match
, dev
);
209 tlc591xx
= match
->data
;
213 count
= of_get_child_count(np
);
214 if (!count
|| count
> tlc591xx
->max_leds
)
217 priv
= devm_kzalloc(dev
, sizeof(*priv
), GFP_KERNEL
);
221 priv
->regmap
= devm_regmap_init_i2c(client
, &tlc591xx_regmap
);
222 if (IS_ERR(priv
->regmap
)) {
223 err
= PTR_ERR(priv
->regmap
);
224 dev_err(dev
, "Failed to allocate register map: %d\n", err
);
227 priv
->reg_ledout_offset
= tlc591xx
->reg_ledout_offset
;
229 i2c_set_clientdata(client
, priv
);
231 for_each_child_of_node(np
, child
) {
232 err
= of_property_read_u32(child
, "reg", ®
);
235 if (reg
< 0 || reg
>= tlc591xx
->max_leds
)
237 if (priv
->leds
[reg
].active
)
239 priv
->leds
[reg
].active
= true;
240 priv
->leds
[reg
].ldev
.name
=
241 of_get_property(child
, "label", NULL
) ? : child
->name
;
242 priv
->leds
[reg
].ldev
.default_trigger
=
243 of_get_property(child
, "linux,default-trigger", NULL
);
245 return tlc591xx_configure(dev
, priv
, tlc591xx
);
249 tlc591xx_remove(struct i2c_client
*client
)
251 struct tlc591xx_priv
*priv
= i2c_get_clientdata(client
);
253 tlc591xx_destroy_devices(priv
, TLC591XX_MAX_LEDS
);
258 static const struct i2c_device_id tlc591xx_id
[] = {
263 MODULE_DEVICE_TABLE(i2c
, tlc591xx_id
);
265 static struct i2c_driver tlc591xx_driver
= {
268 .of_match_table
= of_match_ptr(of_tlc591xx_leds_match
),
270 .probe
= tlc591xx_probe
,
271 .remove
= tlc591xx_remove
,
272 .id_table
= tlc591xx_id
,
275 module_i2c_driver(tlc591xx_driver
);
277 MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
278 MODULE_LICENSE("GPL");
279 MODULE_DESCRIPTION("TLC591XX LED driver");