Skip to content

Commit 14ef073

Browse files
Eddie Jameslag-linaro
authored andcommitted
leds: pca955x: Optimize probe LED selection
Previously, the probe function might do up to 32 reads and writes to the same 4 registers to program the LED selection. Reduce this to a maximum of 5 operations by accumulating the changes to the LED selection and comparing with the previous value to write the selection if different. Signed-off-by: Eddie James <[email protected]> Reviewed-by: Andy Shevchenko <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Lee Jones <[email protected]>
1 parent 1ddab1e commit 14ef073

File tree

1 file changed

+28
-10
lines changed

1 file changed

+28
-10
lines changed

drivers/leds/leds-pca955x.c

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,9 @@ static int pca955x_probe(struct i2c_client *client)
446446
struct led_classdev *led;
447447
struct led_init_data init_data;
448448
struct i2c_adapter *adapter;
449-
int i, err;
449+
int i, bit, err, nls, reg;
450+
u8 ls1[4];
451+
u8 ls2[4];
450452
struct pca955x_platform_data *pdata;
451453
bool set_default_label = false;
452454
bool keep_pwm = false;
@@ -504,6 +506,17 @@ static int pca955x_probe(struct i2c_client *client)
504506
init_data.devname_mandatory = false;
505507
init_data.devicename = "pca955x";
506508

509+
nls = pca955x_num_led_regs(chip->bits);
510+
/* Use auto-increment feature to read all the LED selectors at once. */
511+
err = i2c_smbus_read_i2c_block_data(client,
512+
0x10 | (pca955x_num_input_regs(chip->bits) + 4), nls,
513+
ls1);
514+
if (err < 0)
515+
return err;
516+
517+
for (i = 0; i < nls; i++)
518+
ls2[i] = ls1[i];
519+
507520
for (i = 0; i < chip->bits; i++) {
508521
pca955x_led = &pca955x->leds[i];
509522
pca955x_led->led_num = i;
@@ -515,19 +528,16 @@ static int pca955x_probe(struct i2c_client *client)
515528
case PCA955X_TYPE_GPIO:
516529
break;
517530
case PCA955X_TYPE_LED:
531+
bit = i % 4;
532+
reg = i / 4;
518533
led = &pca955x_led->led_cdev;
519534
led->brightness_set_blocking = pca955x_led_set;
520535
led->brightness_get = pca955x_led_get;
521536

522-
if (pdata->leds[i].default_state == LEDS_DEFSTATE_OFF) {
523-
err = pca955x_led_set(led, LED_OFF);
524-
if (err)
525-
return err;
526-
} else if (pdata->leds[i].default_state == LEDS_DEFSTATE_ON) {
527-
err = pca955x_led_set(led, LED_FULL);
528-
if (err)
529-
return err;
530-
}
537+
if (pdata->leds[i].default_state == LEDS_DEFSTATE_OFF)
538+
ls2[reg] = pca955x_ledsel(ls2[reg], bit, PCA955X_LS_LED_OFF);
539+
else if (pdata->leds[i].default_state == LEDS_DEFSTATE_ON)
540+
ls2[reg] = pca955x_ledsel(ls2[reg], bit, PCA955X_LS_LED_ON);
531541

532542
init_data.fwnode = pdata->leds[i].fwnode;
533543

@@ -571,6 +581,14 @@ static int pca955x_probe(struct i2c_client *client)
571581
}
572582
}
573583

584+
for (i = 0; i < nls; i++) {
585+
if (ls1[i] != ls2[i]) {
586+
err = pca955x_write_ls(pca955x, i, ls2[i]);
587+
if (err)
588+
return err;
589+
}
590+
}
591+
574592
/* PWM0 is used for half brightness or 50% duty cycle */
575593
err = pca955x_write_pwm(pca955x, 0, 255 - LED_HALF);
576594
if (err)

0 commit comments

Comments
 (0)