3434
3535#define IS31FL32XX_PWM_FREQUENCY_22KHZ 0x01
3636
37+ /* Registers for IS31FL3293 */
38+ #define IS31FL3293_SHUTDOWN_REG 0x01
39+ #define IS31FL3293_SHUTDOWN_SSD_DISABLE BIT(0)
40+ #define IS31FL3293_SHUTDOWN_EN1 BIT(4)
41+ #define IS31FL3293_SHUTDOWN_EN2 BIT(5)
42+ #define IS31FL3293_SHUTDOWN_EN3 BIT(6)
43+ #define IS31FL3293_GCC_REG 0x03
44+ #define IS31FL3293_GCC_LEVEL_MAX 0x3f
45+ #define IS31FL3293_CL_REG 0x10
46+ #define IS31FL3293_COLOR_UPDATE_REG 0x27
47+ #define IS31FL3293_COLOR_UPDATE_MAGIC 0xc5
48+ #define IS31FL3293_RESET_REG 0x3c
49+ #define IS31FL3293_RESET_MAGIC 0xc5
50+ #define IS31FL3293_MAX_MICROAMP 20000
51+
3752struct is31fl32xx_priv ;
3853struct is31fl32xx_led_data {
3954 struct led_classdev cdev ;
4055 u8 channel ; /* 1-based, max priv->cdef->channels */
56+ u32 max_microamp ;
4157 struct is31fl32xx_priv * priv ;
4258};
4359
@@ -53,13 +69,15 @@ struct is31fl32xx_priv {
5369 * @channels : Number of LED channels
5470 * @shutdown_reg : address of Shutdown register (optional)
5571 * @pwm_update_reg : address of PWM Update register
72+ * @pwm_update_value : value to write to PWM Update register
5673 * @global_control_reg : address of Global Control register (optional)
5774 * @reset_reg : address of Reset register (optional)
5875 * @output_frequency_setting_reg: address of output frequency register (optional)
5976 * @pwm_register_base : address of first PWM register
6077 * @pwm_registers_reversed: : true if PWM registers count down instead of up
6178 * @led_control_register_base : address of first LED control register (optional)
6279 * @enable_bits_per_led_control_register: number of LEDs enable bits in each
80+ * @brightness_steps : number of brightness steps supported by the chip
6381 * @reset_func : pointer to reset function
6482 * @sw_shutdown_func : pointer to software shutdown function
6583 *
@@ -77,13 +95,15 @@ struct is31fl32xx_chipdef {
7795 u8 channels ;
7896 u8 shutdown_reg ;
7997 u8 pwm_update_reg ;
98+ u8 pwm_update_value ;
8099 u8 global_control_reg ;
81100 u8 reset_reg ;
82101 u8 output_frequency_setting_reg ;
83102 u8 pwm_register_base ;
84103 bool pwm_registers_reversed ;
85104 u8 led_control_register_base ;
86105 u8 enable_bits_per_led_control_register ;
106+ u16 brightness_steps ;
87107 int (* reset_func )(struct is31fl32xx_priv * priv );
88108 int (* sw_shutdown_func )(struct is31fl32xx_priv * priv , bool enable );
89109};
@@ -152,6 +172,62 @@ static int is31fl3216_software_shutdown(struct is31fl32xx_priv *priv,
152172 return is31fl32xx_write (priv , IS31FL3216_CONFIG_REG , value );
153173}
154174
175+ /*
176+ * Custom Reset function for IS31FL3293. We need to set the global current limit
177+ * and write to the color update register once.
178+ */
179+ static int is31fl3293_reset (struct is31fl32xx_priv * priv )
180+ {
181+ int i , ret ;
182+
183+ ret = is31fl32xx_write (priv , IS31FL3293_RESET_REG ,
184+ IS31FL3293_RESET_MAGIC );
185+ if (ret )
186+ return ret ;
187+
188+ /* Set the global current limit to maximum */
189+ ret = is31fl32xx_write (priv , IS31FL3293_GCC_REG ,
190+ IS31FL3293_GCC_LEVEL_MAX );
191+ if (ret )
192+ return ret ;
193+
194+ for (i = 0 ; i < priv -> num_leds ; i ++ ) {
195+ struct is31fl32xx_led_data * led_data = & priv -> leds [i ];
196+ int current_level_reg = IS31FL3293_CL_REG + led_data -> channel - 1 ;
197+ int microamp = max (led_data -> max_microamp , IS31FL3293_MAX_MICROAMP );
198+ int current_level = (microamp * 0xff ) / IS31FL3293_MAX_MICROAMP ;
199+
200+ ret = is31fl32xx_write (priv , current_level_reg , current_level );
201+ if (ret )
202+ return ret ;
203+ }
204+
205+ ret = is31fl32xx_write (priv , IS31FL3293_COLOR_UPDATE_REG ,
206+ IS31FL3293_COLOR_UPDATE_MAGIC );
207+ if (ret )
208+ return ret ;
209+
210+ return 0 ;
211+ }
212+
213+ /*
214+ * Custom Software-Shutdown function for IS31FL3293 because the SHUTDOWN
215+ * register of this device also has bits to enable the channels.
216+ */
217+ static int is31fl3293_software_shutdown (struct is31fl32xx_priv * priv ,
218+ bool enable )
219+ {
220+ u8 value = 0 ;
221+
222+ if (!enable )
223+ value = IS31FL3293_SHUTDOWN_SSD_DISABLE |
224+ IS31FL3293_SHUTDOWN_EN1 |
225+ IS31FL3293_SHUTDOWN_EN2 |
226+ IS31FL3293_SHUTDOWN_EN3 ;
227+
228+ return is31fl32xx_write (priv , IS31FL3293_SHUTDOWN_REG , value );
229+ }
230+
155231/*
156232 * NOTE: A mutex is not needed in this function because:
157233 * - All referenced data is read-only after probe()
@@ -190,13 +266,36 @@ static int is31fl32xx_brightness_set(struct led_classdev *led_cdev,
190266 else
191267 pwm_register_offset = led_data -> channel - 1 ;
192268
193- ret = is31fl32xx_write (led_data -> priv ,
194- cdef -> pwm_register_base + pwm_register_offset ,
195- brightness );
196- if (ret )
197- return ret ;
269+ switch (cdef -> brightness_steps ) {
270+ case 256 :
271+ ret = is31fl32xx_write (led_data -> priv ,
272+ cdef -> pwm_register_base + pwm_register_offset ,
273+ brightness );
274+ if (ret )
275+ return ret ;
276+
277+ break ;
278+ case 4096 :
279+ /* IS31FL329x devices use two registers to store 12 bits of brightness */
280+ pwm_register_offset *= 2 ;
198281
199- return is31fl32xx_write (led_data -> priv , cdef -> pwm_update_reg , 0 );
282+ ret = is31fl32xx_write (led_data -> priv ,
283+ cdef -> pwm_register_base + pwm_register_offset ,
284+ brightness & 0xff );
285+ if (ret )
286+ return ret ;
287+
288+ ret = is31fl32xx_write (led_data -> priv ,
289+ cdef -> pwm_register_base + pwm_register_offset + 1 ,
290+ (brightness >> 8 ) & 0xf );
291+ if (ret )
292+ return ret ;
293+
294+ break ;
295+ }
296+
297+ return is31fl32xx_write (led_data -> priv , cdef -> pwm_update_reg ,
298+ cdef -> pwm_update_value );
200299}
201300
202301static int is31fl32xx_reset_regs (struct is31fl32xx_priv * priv )
@@ -295,6 +394,8 @@ static int is31fl32xx_parse_child_dt(const struct device *dev,
295394 }
296395 led_data -> channel = reg ;
297396
397+ of_property_read_u32 (child , "led-max-microamp" , & led_data -> max_microamp );
398+
298399 cdev -> brightness_set_blocking = is31fl32xx_brightness_set ;
299400
300401 return 0 ;
@@ -339,6 +440,7 @@ static int is31fl32xx_parse_dt(struct device *dev,
339440 const struct is31fl32xx_led_data * other_led_data ;
340441
341442 led_data -> priv = priv ;
443+ led_data -> cdev .max_brightness = priv -> cdef -> brightness_steps - 1 ;
342444
343445 ret = is31fl32xx_parse_child_dt (dev , child , led_data );
344446 if (ret )
@@ -391,6 +493,7 @@ static const struct is31fl32xx_chipdef is31fl3236a_cdef = {
391493 .pwm_register_base = 0x01 ,
392494 .led_control_register_base = 0x26 ,
393495 .enable_bits_per_led_control_register = 1 ,
496+ .brightness_steps = 256 ,
394497};
395498
396499static const struct is31fl32xx_chipdef is31fl3235_cdef = {
@@ -403,6 +506,7 @@ static const struct is31fl32xx_chipdef is31fl3235_cdef = {
403506 .pwm_register_base = 0x05 ,
404507 .led_control_register_base = 0x2a ,
405508 .enable_bits_per_led_control_register = 1 ,
509+ .brightness_steps = 256 ,
406510};
407511
408512static const struct is31fl32xx_chipdef is31fl3218_cdef = {
@@ -415,6 +519,7 @@ static const struct is31fl32xx_chipdef is31fl3218_cdef = {
415519 .pwm_register_base = 0x01 ,
416520 .led_control_register_base = 0x13 ,
417521 .enable_bits_per_led_control_register = 6 ,
522+ .brightness_steps = 256 ,
418523};
419524
420525static const struct is31fl32xx_chipdef is31fl3216_cdef = {
@@ -430,9 +535,25 @@ static const struct is31fl32xx_chipdef is31fl3216_cdef = {
430535 .enable_bits_per_led_control_register = 8 ,
431536 .reset_func = is31fl3216_reset ,
432537 .sw_shutdown_func = is31fl3216_software_shutdown ,
538+ .brightness_steps = 256 ,
539+ };
540+
541+ static const struct is31fl32xx_chipdef is31fl3293_cdef = {
542+ .channels = 3 ,
543+ .shutdown_reg = IS31FL32XX_REG_NONE ,
544+ .pwm_update_reg = 0x28 ,
545+ .pwm_update_value = 0xc5 ,
546+ .global_control_reg = IS31FL32XX_REG_NONE ,
547+ .reset_reg = IS31FL32XX_REG_NONE ,
548+ .pwm_register_base = 0x19 ,
549+ .led_control_register_base = IS31FL32XX_REG_NONE ,
550+ .brightness_steps = 4096 ,
551+ .reset_func = is31fl3293_reset ,
552+ .sw_shutdown_func = is31fl3293_software_shutdown ,
433553};
434554
435555static const struct of_device_id of_is31fl32xx_match [] = {
556+ { .compatible = "issi,is31fl3293" , .data = & is31fl3293_cdef , },
436557 { .compatible = "issi,is31fl3236" , .data = & is31fl3236_cdef , },
437558 { .compatible = "issi,is31fl3236a" , .data = & is31fl3236a_cdef , },
438559 { .compatible = "issi,is31fl3235" , .data = & is31fl3235_cdef , },
@@ -468,11 +589,11 @@ static int is31fl32xx_probe(struct i2c_client *client)
468589 priv -> cdef = cdef ;
469590 i2c_set_clientdata (client , priv );
470591
471- ret = is31fl32xx_init_regs ( priv );
592+ ret = is31fl32xx_parse_dt ( dev , priv );
472593 if (ret )
473594 return ret ;
474595
475- ret = is31fl32xx_parse_dt ( dev , priv );
596+ ret = is31fl32xx_init_regs ( priv );
476597 if (ret )
477598 return ret ;
478599
@@ -495,6 +616,7 @@ static void is31fl32xx_remove(struct i2c_client *client)
495616 * even though it is not used for DeviceTree based instantiation.
496617 */
497618static const struct i2c_device_id is31fl32xx_id [] = {
619+ { "is31fl3293" },
498620 { "is31fl3236" },
499621 { "is31fl3236a" },
500622 { "is31fl3235" },
0 commit comments