6262#define PCA955X_GPIO_HIGH LED_OFF
6363#define PCA955X_GPIO_LOW LED_FULL
6464
65+ #define PCA955X_BLINK_DEFAULT_MS 1000
66+
6567enum pca955x_type {
6668 pca9550 ,
6769 pca9551 ,
@@ -74,33 +76,39 @@ struct pca955x_chipdef {
7476 int bits ;
7577 u8 slv_addr ; /* 7-bit slave address mask */
7678 int slv_addr_shift ; /* Number of bits to ignore */
79+ int blink_div ; /* PSC divider */
7780};
7881
7982static const struct pca955x_chipdef pca955x_chipdefs [] = {
8083 [pca9550 ] = {
8184 .bits = 2 ,
8285 .slv_addr = /* 110000x */ 0x60 ,
8386 .slv_addr_shift = 1 ,
87+ .blink_div = 44 ,
8488 },
8589 [pca9551 ] = {
8690 .bits = 8 ,
8791 .slv_addr = /* 1100xxx */ 0x60 ,
8892 .slv_addr_shift = 3 ,
93+ .blink_div = 38 ,
8994 },
9095 [pca9552 ] = {
9196 .bits = 16 ,
9297 .slv_addr = /* 1100xxx */ 0x60 ,
9398 .slv_addr_shift = 3 ,
99+ .blink_div = 44 ,
94100 },
95101 [ibm_pca9552 ] = {
96102 .bits = 16 ,
97103 .slv_addr = /* 0110xxx */ 0x30 ,
98104 .slv_addr_shift = 3 ,
105+ .blink_div = 44 ,
99106 },
100107 [pca9553 ] = {
101108 .bits = 4 ,
102109 .slv_addr = /* 110001x */ 0x62 ,
103110 .slv_addr_shift = 1 ,
111+ .blink_div = 44 ,
104112 },
105113};
106114
@@ -109,7 +117,9 @@ struct pca955x {
109117 struct pca955x_led * leds ;
110118 const struct pca955x_chipdef * chipdef ;
111119 struct i2c_client * client ;
120+ unsigned long active_blink ;
112121 unsigned long active_pins ;
122+ unsigned long blink_period ;
113123#ifdef CONFIG_LEDS_PCA955X_GPIO
114124 struct gpio_chip gpio ;
115125#endif
@@ -154,7 +164,8 @@ static inline int pca955x_ledstate(u8 ls, int led_num)
154164
155165/*
156166 * Write to frequency prescaler register, used to program the
157- * period of the PWM output. period = (PSCx + 1) / 38
167+ * period of the PWM output. period = (PSCx + 1) / coeff
168+ * Where for pca9551 chips coeff = 38 and for all other chips coeff = 44
158169 */
159170static int pca955x_write_psc (struct pca955x * pca955x , int n , u8 val )
160171{
@@ -235,6 +246,21 @@ static int pca955x_read_pwm(struct pca955x *pca955x, int n, u8 *val)
235246 return 0 ;
236247}
237248
249+ static int pca955x_read_psc (struct pca955x * pca955x , int n , u8 * val )
250+ {
251+ int ret ;
252+ u8 cmd ;
253+
254+ cmd = pca955x_num_input_regs (pca955x -> chipdef -> bits ) + (2 * n );
255+ ret = i2c_smbus_read_byte_data (pca955x -> client , cmd );
256+ if (ret < 0 ) {
257+ dev_err (& pca955x -> client -> dev , "%s: reg 0x%x, err %d\n" , __func__ , n , ret );
258+ return ret ;
259+ }
260+ * val = (u8 )ret ;
261+ return 0 ;
262+ }
263+
238264static enum led_brightness pca955x_led_get (struct led_classdev * led_cdev )
239265{
240266 struct pca955x_led * pca955x_led = led_to_pca955x (led_cdev );
@@ -248,14 +274,12 @@ static enum led_brightness pca955x_led_get(struct led_classdev *led_cdev)
248274
249275 switch (pca955x_ledstate (ls , pca955x_led -> led_num % 4 )) {
250276 case PCA955X_LS_LED_ON :
277+ case PCA955X_LS_BLINK0 :
251278 ret = LED_FULL ;
252279 break ;
253280 case PCA955X_LS_LED_OFF :
254281 ret = LED_OFF ;
255282 break ;
256- case PCA955X_LS_BLINK0 :
257- ret = LED_HALF ;
258- break ;
259283 case PCA955X_LS_BLINK1 :
260284 ret = pca955x_read_pwm (pca955x , 1 , & pwm );
261285 if (ret )
@@ -283,29 +307,36 @@ static int pca955x_led_set(struct led_classdev *led_cdev,
283307 if (ret )
284308 goto out ;
285309
286- switch (value ) {
287- case LED_FULL :
288- ls = pca955x_ledsel (ls , bit , PCA955X_LS_LED_ON );
289- break ;
290- case LED_OFF :
291- ls = pca955x_ledsel (ls , bit , PCA955X_LS_LED_OFF );
292- break ;
293- case LED_HALF :
294- ls = pca955x_ledsel (ls , bit , PCA955X_LS_BLINK0 );
295- break ;
296- default :
297- /*
298- * Use PWM1 for all other values. This has the unwanted
299- * side effect of making all LEDs on the chip share the
300- * same brightness level if set to a value other than
301- * OFF, HALF, or FULL. But, this is probably better than
302- * just turning off for all other values.
303- */
304- ret = pca955x_write_pwm (pca955x , 1 , 255 - value );
305- if (ret )
310+ if (test_bit (pca955x_led -> led_num , & pca955x -> active_blink )) {
311+ if (value == LED_OFF ) {
312+ clear_bit (pca955x_led -> led_num , & pca955x -> active_blink );
313+ ls = pca955x_ledsel (ls , bit , PCA955X_LS_LED_OFF );
314+ } else {
315+ /* No variable brightness for blinking LEDs */
306316 goto out ;
307- ls = pca955x_ledsel (ls , bit , PCA955X_LS_BLINK1 );
308- break ;
317+ }
318+ } else {
319+ switch (value ) {
320+ case LED_FULL :
321+ ls = pca955x_ledsel (ls , bit , PCA955X_LS_LED_ON );
322+ break ;
323+ case LED_OFF :
324+ ls = pca955x_ledsel (ls , bit , PCA955X_LS_LED_OFF );
325+ break ;
326+ default :
327+ /*
328+ * Use PWM1 for all other values. This has the unwanted
329+ * side effect of making all LEDs on the chip share the
330+ * same brightness level if set to a value other than
331+ * OFF or FULL. But, this is probably better than just
332+ * turning off for all other values.
333+ */
334+ ret = pca955x_write_pwm (pca955x , 1 , 255 - value );
335+ if (ret )
336+ goto out ;
337+ ls = pca955x_ledsel (ls , bit , PCA955X_LS_BLINK1 );
338+ break ;
339+ }
309340 }
310341
311342 ret = pca955x_write_ls (pca955x , reg , ls );
@@ -316,6 +347,104 @@ static int pca955x_led_set(struct led_classdev *led_cdev,
316347 return ret ;
317348}
318349
350+ static u8 pca955x_period_to_psc (struct pca955x * pca955x , unsigned long period )
351+ {
352+ /* psc register value = (blink period * coeff) - 1 */
353+ period *= pca955x -> chipdef -> blink_div ;
354+ period /= MSEC_PER_SEC ;
355+ period -= 1 ;
356+
357+ return period ;
358+ }
359+
360+ static unsigned long pca955x_psc_to_period (struct pca955x * pca955x , u8 psc )
361+ {
362+ unsigned long period = psc ;
363+
364+ /* blink period = (psc register value + 1) / coeff */
365+ period += 1 ;
366+ period *= MSEC_PER_SEC ;
367+ period /= pca955x -> chipdef -> blink_div ;
368+
369+ return period ;
370+ }
371+
372+ static int pca955x_led_blink (struct led_classdev * led_cdev ,
373+ unsigned long * delay_on , unsigned long * delay_off )
374+ {
375+ struct pca955x_led * pca955x_led = led_to_pca955x (led_cdev );
376+ struct pca955x * pca955x = pca955x_led -> pca955x ;
377+ unsigned long period = * delay_on + * delay_off ;
378+ int ret = 0 ;
379+
380+ mutex_lock (& pca955x -> lock );
381+
382+ if (period ) {
383+ if (* delay_on != * delay_off ) {
384+ ret = - EINVAL ;
385+ goto out ;
386+ }
387+
388+ if (period < pca955x_psc_to_period (pca955x , 0 ) ||
389+ period > pca955x_psc_to_period (pca955x , 0xff )) {
390+ ret = - EINVAL ;
391+ goto out ;
392+ }
393+ } else {
394+ period = pca955x -> active_blink ? pca955x -> blink_period :
395+ PCA955X_BLINK_DEFAULT_MS ;
396+ }
397+
398+ if (!pca955x -> active_blink ||
399+ pca955x -> active_blink == BIT (pca955x_led -> led_num ) ||
400+ pca955x -> blink_period == period ) {
401+ u8 psc = pca955x_period_to_psc (pca955x , period );
402+
403+ if (!test_and_set_bit (pca955x_led -> led_num ,
404+ & pca955x -> active_blink )) {
405+ u8 ls ;
406+ int reg = pca955x_led -> led_num / 4 ;
407+ int bit = pca955x_led -> led_num % 4 ;
408+
409+ ret = pca955x_read_ls (pca955x , reg , & ls );
410+ if (ret )
411+ goto out ;
412+
413+ ls = pca955x_ledsel (ls , bit , PCA955X_LS_BLINK0 );
414+ ret = pca955x_write_ls (pca955x , reg , ls );
415+ if (ret )
416+ goto out ;
417+
418+ /*
419+ * Force 50% duty cycle to maintain the specified
420+ * blink rate.
421+ */
422+ ret = pca955x_write_pwm (pca955x , 0 , 128 );
423+ if (ret )
424+ goto out ;
425+ }
426+
427+ if (pca955x -> blink_period != period ) {
428+ pca955x -> blink_period = period ;
429+ ret = pca955x_write_psc (pca955x , 0 , psc );
430+ if (ret )
431+ goto out ;
432+ }
433+
434+ period = pca955x_psc_to_period (pca955x , psc );
435+ period /= 2 ;
436+ * delay_on = period ;
437+ * delay_off = period ;
438+ } else {
439+ ret = - EBUSY ;
440+ }
441+
442+ out :
443+ mutex_unlock (& pca955x -> lock );
444+
445+ return ret ;
446+ }
447+
319448#ifdef CONFIG_LEDS_PCA955X_GPIO
320449/*
321450 * Read the INPUT register, which contains the state of LEDs.
@@ -450,8 +579,9 @@ static int pca955x_probe(struct i2c_client *client)
450579 u8 ls1 [4 ];
451580 u8 ls2 [4 ];
452581 struct pca955x_platform_data * pdata ;
582+ u8 psc0 ;
583+ bool keep_psc0 = false;
453584 bool set_default_label = false;
454- bool keep_pwm = false;
455585 char default_label [8 ];
456586
457587 chip = i2c_get_match_data (client );
@@ -502,6 +632,7 @@ static int pca955x_probe(struct i2c_client *client)
502632 mutex_init (& pca955x -> lock );
503633 pca955x -> client = client ;
504634 pca955x -> chipdef = chip ;
635+ pca955x -> blink_period = PCA955X_BLINK_DEFAULT_MS ;
505636
506637 init_data .devname_mandatory = false;
507638 init_data .devicename = "pca955x" ;
@@ -533,11 +664,16 @@ static int pca955x_probe(struct i2c_client *client)
533664 led = & pca955x_led -> led_cdev ;
534665 led -> brightness_set_blocking = pca955x_led_set ;
535666 led -> brightness_get = pca955x_led_get ;
667+ led -> blink_set = pca955x_led_blink ;
536668
537669 if (pdata -> leds [i ].default_state == LEDS_DEFSTATE_OFF )
538670 ls2 [reg ] = pca955x_ledsel (ls2 [reg ], bit , PCA955X_LS_LED_OFF );
539671 else if (pdata -> leds [i ].default_state == LEDS_DEFSTATE_ON )
540672 ls2 [reg ] = pca955x_ledsel (ls2 [reg ], bit , PCA955X_LS_LED_ON );
673+ else if (pca955x_ledstate (ls2 [reg ], bit ) == PCA955X_LS_BLINK0 ) {
674+ keep_psc0 = true;
675+ set_bit (i , & pca955x -> active_blink );
676+ }
541677
542678 init_data .fwnode = pdata -> leds [i ].fwnode ;
543679
@@ -565,19 +701,6 @@ static int pca955x_probe(struct i2c_client *client)
565701 return err ;
566702
567703 set_bit (i , & pca955x -> active_pins );
568-
569- /*
570- * For default-state == "keep", let the core update the
571- * brightness from the hardware, then check the
572- * brightness to see if it's using PWM1. If so, PWM1
573- * should not be written below.
574- */
575- if (pdata -> leds [i ].default_state == LEDS_DEFSTATE_KEEP ) {
576- if (led -> brightness != LED_FULL &&
577- led -> brightness != LED_OFF &&
578- led -> brightness != LED_HALF )
579- keep_pwm = true;
580- }
581704 }
582705 }
583706
@@ -589,22 +712,19 @@ static int pca955x_probe(struct i2c_client *client)
589712 }
590713 }
591714
592- /* PWM0 is used for half brightness or 50% duty cycle */
593- err = pca955x_write_pwm (pca955x , 0 , 255 - LED_HALF );
594- if (err )
595- return err ;
596-
597- if (!keep_pwm ) {
598- /* PWM1 is used for variable brightness, default to OFF */
599- err = pca955x_write_pwm (pca955x , 1 , 0 );
600- if (err )
601- return err ;
715+ if (keep_psc0 ) {
716+ err = pca955x_read_psc (pca955x , 0 , & psc0 );
717+ } else {
718+ psc0 = pca955x_period_to_psc (pca955x , pca955x -> blink_period );
719+ err = pca955x_write_psc (pca955x , 0 , psc0 );
602720 }
603721
604- /* Set to fast frequency so we do not see flashing */
605- err = pca955x_write_psc (pca955x , 0 , 0 );
606722 if (err )
607723 return err ;
724+
725+ pca955x -> blink_period = pca955x_psc_to_period (pca955x , psc0 );
726+
727+ /* Set PWM1 to fast frequency so we do not see flashing */
608728 err = pca955x_write_psc (pca955x , 1 , 0 );
609729 if (err )
610730 return err ;
0 commit comments