2121#include <zephyr/dt-bindings/led/led.h>
2222
2323LOG_MODULE_REGISTER (is31fl319x , CONFIG_LED_LOG_LEVEL );
24+
25+ /* define features that are specific subset of supported devices */
2426#define REG_NOT_DEFINED 0xff
2527
28+ #define FEATURE_ID_IS_ADDR 0x01 /* The id is the bus address */
29+ #define FEATURE_SET_CURRENT 0x02 /* the device supports setting current limits */
30+
2631struct is31f1319x_model {
32+ const uint8_t features ;
2733 const uint8_t prod_id_reg ;
2834 const uint8_t shutdown_reg ;
2935 const uint8_t conf_reg ;
@@ -38,7 +44,17 @@ struct is31f1319x_model {
3844 const uint8_t led_channels [];
3945};
4046
47+ struct is31fl319x_config {
48+ struct i2c_dt_spec bus ;
49+ uint8_t channel_count ;
50+ uint8_t num_leds ;
51+ const struct led_info * led_infos ;
52+ const uint8_t * current_limits ;
53+ const struct is31f1319x_model * model ;
54+ };
4155
56+ #ifdef CONFIG_DT_HAS_ISSI_IS31FL3194_ENABLED
57+ /* IS31FL3194 model registers and values */
4258#define IS31FL3194_PROD_ID_REG 0x00
4359#define IS31FL3194_CONF_REG 0x01
4460#define IS31FL3194_CURRENT_REG 0x03
@@ -54,6 +70,8 @@ struct is31f1319x_model {
5470#define IS31FL3194_CHANNEL_COUNT 3
5571
5672static const struct is31f1319x_model is31f13194_model = {
73+ .features = FEATURE_SET_CURRENT ,
74+
5775 /* register indexes */
5876 .prod_id_reg = IS31FL3194_PROD_ID_REG ,
5977 .shutdown_reg = REG_NOT_DEFINED ,
@@ -69,15 +87,46 @@ static const struct is31f1319x_model is31f13194_model = {
6987
7088 /* channel output registers */
7189 .led_channels = {IS31FL3194_OUT1_REG , IS31FL3194_OUT2_REG , IS31FL3194_OUT3_REG }};
90+ #endif
7291
73- struct is31fl319x_config {
74- struct i2c_dt_spec bus ;
75- uint8_t channel_count ;
76- uint8_t num_leds ;
77- const struct led_info * led_infos ;
78- const uint8_t * current_limits ;
79- const struct is31f1319x_model * regs ;
92+ #ifdef CONFIG_DT_HAS_ISSI_IS31FL3197_ENABLED
93+ /* IS31FL3197 model registers and values */
94+ #define IS31FL3197_PROD_ID_REG 0x00
95+ #define IS31FL3197_SHUTDOWN_REG 0x01
96+ #define IS31FL3197_OPER_CONFIG_REG 0x02
97+ #define IS31FL3197_OUT1_REG 0x10
98+ #define IS31FL3197_OUT2_REG 0x11
99+ #define IS31FL3197_OUT3_REG 0x12
100+ #define IS31FL3197_OUT4_REG 0x13
101+ #define IS31FL3197_UPDATE_REG 0x2b
102+
103+ #define IS31FL3197_SHUTDOWN_REG_VAL 0xf1 /* enable all channels */
104+ #define IS31FL3197_OPER_CONFIG_REG_VAL 0xff /* set all to current level */
105+ #define IS31FL3197_UPDATE_VAL 0xc5
106+
107+ #define IS31FL3197_CHANNEL_COUNT 4
108+
109+ static const struct is31f1319x_model is31f13197_model = {
110+ .features = FEATURE_ID_IS_ADDR ,
111+
112+ /* register indexes */
113+ .prod_id_reg = IS31FL3197_PROD_ID_REG ,
114+ .shutdown_reg = IS31FL3197_SHUTDOWN_REG ,
115+ .conf_reg = IS31FL3197_OPER_CONFIG_REG ,
116+ .current_reg = REG_NOT_DEFINED ,
117+ .update_reg = IS31FL3197_UPDATE_REG ,
118+
119+ /* values for those registers */
120+ .prod_id_val = 0xff ,
121+ .shutdown_reg_val = IS31FL3197_SHUTDOWN_REG_VAL ,
122+ .conf_enable = IS31FL3197_OPER_CONFIG_REG_VAL ,
123+ .update_val = IS31FL3197_UPDATE_VAL ,
124+
125+ /* channel output registers */
126+ .led_channels = {IS31FL3197_OUT1_REG , IS31FL3197_OUT2_REG , IS31FL3197_OUT3_REG ,
127+ IS31FL3197_OUT4_REG }
80128};
129+ #endif
81130
82131static const struct led_info * is31fl319x_led_to_info (const struct is31fl319x_config * config ,
83132 uint32_t led )
@@ -123,16 +172,15 @@ static int is31fl319x_write_channels(const struct device *dev, uint32_t start_ch
123172 uint32_t num_channels , const uint8_t * buf )
124173{
125174 const struct is31fl319x_config * config = dev -> config ;
126- const struct is31f1319x_model * regs = config -> regs ;
127- int ret ;
128- int i ;
175+ const struct is31f1319x_model * model = config -> model ;
176+ int ret = 0 ;
129177
130178 if ((start_channel + num_channels ) > config -> channel_count ) {
131179 return - ENOTSUP ;
132180 }
133181
134- for (i = 0 ; i < num_channels ; i ++ ) {
135- ret = i2c_reg_write_byte_dt (& config -> bus , regs -> led_channels [i + start_channel ],
182+ for (int i = 0 ; i < num_channels ; i ++ ) {
183+ ret = i2c_reg_write_byte_dt (& config -> bus , model -> led_channels [i + start_channel ],
136184 buf [i ]);
137185 if (ret != 0 ) {
138186 break ;
@@ -141,8 +189,8 @@ static int is31fl319x_write_channels(const struct device *dev, uint32_t start_ch
141189
142190 if (ret == 0 ) {
143191 ret = i2c_reg_write_byte_dt (& config -> bus ,
144- regs -> update_reg ,
145- regs -> update_val );
192+ model -> update_reg ,
193+ model -> update_val );
146194 }
147195
148196 if (ret != 0 ) {
@@ -176,7 +224,7 @@ static int is31fl319x_set_brightness(const struct device *dev, uint32_t led, uin
176224{
177225 const struct is31fl319x_config * config = dev -> config ;
178226 const struct led_info * info = is31fl319x_led_to_info (config , led );
179- const struct is31f1319x_model * regs = config -> regs ;
227+ const struct is31f1319x_model * model = config -> model ;
180228 uint8_t channel_start ;
181229
182230 int ret = 0 ;
@@ -194,11 +242,11 @@ static int is31fl319x_set_brightness(const struct device *dev, uint32_t led, uin
194242
195243 channel_start = is31fl319x_map_led_to_start_channel (config , led );
196244
197- ret = i2c_reg_write_byte_dt (& config -> bus , regs -> led_channels [channel_start ], value );
245+ ret = i2c_reg_write_byte_dt (& config -> bus , model -> led_channels [channel_start ], value );
198246 if (ret == 0 ) {
199247 ret = i2c_reg_write_byte_dt (& config -> bus ,
200- regs -> update_reg ,
201- regs -> update_val );
248+ model -> update_reg ,
249+ model -> update_val );
202250 }
203251
204252 if (ret != 0 ) {
@@ -213,10 +261,9 @@ static int is31fl319x_check_config(const struct device *dev)
213261 const struct is31fl319x_config * config = dev -> config ;
214262 const struct led_info * info ;
215263 uint8_t rgb_count = 0 ;
216- uint8_t i ;
217264
218265 /* verify that number of leds defined is not > number of channels */
219- for (i = 0 ; i < config -> num_leds ; i ++ ) {
266+ for (uint8_t i = 0 ; i < config -> num_leds ; i ++ ) {
220267 info = & config -> led_infos [i ];
221268 rgb_count += info -> num_colors ;
222269 }
@@ -232,11 +279,10 @@ static int is31fl319x_init(const struct device *dev)
232279{
233280 const struct is31fl319x_config * config = dev -> config ;
234281 const struct led_info * info = NULL ;
235- const struct is31f1319x_model * regs = config -> regs ;
236- int i , j , ret ;
282+ const struct is31f1319x_model * model = config -> model ;
283+ int ret ;
237284 uint8_t prod_id , band , channel ;
238285 uint8_t current_reg = 0 ;
239- int i , j ;
240286
241287 ret = is31fl319x_check_config (dev );
242288 if (ret != 0 ) {
@@ -248,40 +294,59 @@ static int is31fl319x_init(const struct device *dev)
248294 return - ENODEV ;
249295 }
250296
251- ret = i2c_reg_read_byte_dt (& config -> bus , regs -> prod_id_reg , & prod_id );
297+ ret = i2c_reg_read_byte_dt (& config -> bus , model -> prod_id_reg , & prod_id );
252298 if (ret != 0 ) {
253299 LOG_ERR ("%s: failed to read product ID" , dev -> name );
254300 return ret ;
255301 }
256302
257- if (prod_id != regs -> prod_id_val ) {
258- LOG_ERR ("%s: invalid product ID 0x%02x (expected 0x%02x)" , dev -> name , prod_id ,
259- regs -> prod_id_val );
260- return - ENODEV ;
303+
304+ if (model -> features & FEATURE_ID_IS_ADDR ) {
305+ /* The product ID (8 bit) should be the I2C address(7 bit) */
306+ if (prod_id != (config -> bus .addr << 1 )) {
307+ LOG_ERR ("%s: invalid product ID 0x%02x (expected 0x%02x)" , dev -> name ,
308+ prod_id , config -> bus .addr << 1 );
309+ return - ENODEV ;
310+ }
311+ } else {
312+ if (prod_id != model -> prod_id_val ) {
313+ LOG_ERR ("%s: invalid product ID 0x%02x (expected 0x%02x)" , dev -> name ,
314+ prod_id , model -> prod_id_val );
315+ return - ENODEV ;
316+ }
261317 }
262318
263319 /* calc current limit register value */
264- if (regs -> current_reg != REG_NOT_DEFINED ) {
320+ if (model -> features & FEATURE_SET_CURRENT ) {
265321 channel = 0 ;
266- for (i = 0 ; i < config -> num_leds ; i ++ ) {
322+ for (int i = 0 ; i < config -> num_leds ; i ++ ) {
267323 info = & config -> led_infos [i ];
268324 band = (config -> current_limits [i ] / 10 ) - 1 ;
269325
270- for (j = 0 ; j < info -> num_colors ; j ++ ) {
326+ for (int j = 0 ; j < info -> num_colors ; j ++ ) {
271327 current_reg |= band << (2 * channel );
272328 channel ++ ;
273329 }
274330 }
275331
276- ret = i2c_reg_write_byte_dt (& config -> bus , regs -> current_reg , current_reg );
332+ ret = i2c_reg_write_byte_dt (& config -> bus , model -> current_reg , current_reg );
277333 if (ret != 0 ) {
278334 LOG_ERR ("%s: failed to set current limit" , dev -> name );
279335 return ret ;
280336 }
281337 }
338+ if (model -> shutdown_reg != REG_NOT_DEFINED ) {
339+ ret = i2c_reg_write_byte_dt (& config -> bus , model -> shutdown_reg ,
340+ model -> shutdown_reg_val );
341+ if (ret != 0 ) {
342+ LOG_ERR ("%s: failed to set current limit" , dev -> name );
343+ return ret ;
344+ }
345+ }
346+
282347 /* enable device */
283- return i2c_reg_write_byte_dt (& config -> bus , regs -> conf_reg ,
284- regs -> conf_enable );
348+ return i2c_reg_write_byte_dt (& config -> bus , model -> conf_reg ,
349+ model -> conf_enable );
285350}
286351
287352static DEVICE_API (led , is31fl319x_led_api ) = {
@@ -305,7 +370,7 @@ static DEVICE_API(led, is31fl319x_led_api) = {
305370#define LED_CURRENT (led_node_id ) \
306371 DT_PROP(led_node_id, current_limit),
307372
308- #define IS31FL319X_DEVICE (n , id , nchannels , pregs ) \
373+ #define IS31FL319X_DEVICE (n , id , nchannels , pmodel ) \
309374 \
310375 DT_INST_FOREACH_CHILD(n, COLOR_MAPPING) \
311376 \
@@ -323,12 +388,21 @@ static DEVICE_API(led, is31fl319x_led_api) = {
323388 .num_leds = ARRAY_SIZE(is31fl319##id##_leds_##n), \
324389 .led_infos = is31fl319##id##_leds_##n, \
325390 .current_limits = is31fl319##id##_currents_##n, \
326- .regs = pregs, \
391+ .model = pmodel, \
327392 }; \
328393 DEVICE_DT_INST_DEFINE(n, &is31fl319x_init, NULL, NULL, \
329394 &is31fl319##id##_config_##n, POST_KERNEL, \
330395 CONFIG_LED_INIT_PRIORITY, &is31fl319x_led_api);
331396
397+ #ifdef CONFIG_DT_HAS_ISSI_IS31FL3194_ENABLED
332398#define DT_DRV_COMPAT issi_is31fl3194
333399DT_INST_FOREACH_STATUS_OKAY_VARGS (IS31FL319X_DEVICE , 4 , IS31FL3194_CHANNEL_COUNT ,
334400 & is31f13194_model )
401+ #endif
402+
403+ #ifdef CONFIG_DT_HAS_ISSI_IS31FL3197_ENABLED
404+ #undef DT_DRV_COMPAT
405+ #define DT_DRV_COMPAT issi_is31fl3197
406+ DT_INST_FOREACH_STATUS_OKAY_VARGS (IS31FL319X_DEVICE , 7 , IS31FL3197_CHANNEL_COUNT ,
407+ & is31f13197_model )
408+ #endif
0 commit comments