[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220906215855.1937331-4-eajames@linux.ibm.com>
Date: Tue, 6 Sep 2022 16:58:54 -0500
From: Eddie James <eajames@...ux.ibm.com>
To: pavel@....cz
Cc: linux-leds@...r.kernel.org, linux-kernel@...r.kernel.org,
andy.shevchenko@...il.com, joel@....id.au,
dan.carpenter@...cle.com, eajames@...ux.ibm.com
Subject: [PATCH v6 3/4] 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 <eajames@...ux.ibm.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@...il.com>
---
drivers/leds/leds-pca955x.c | 42 +++++++++++++++++++++++++++----------
1 file changed, 31 insertions(+), 11 deletions(-)
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
index cb1895b79eab..ed7056193d14 100644
--- a/drivers/leds/leds-pca955x.c
+++ b/drivers/leds/leds-pca955x.c
@@ -483,7 +483,9 @@ static int pca955x_probe(struct i2c_client *client)
struct led_classdev *led;
struct led_init_data init_data;
struct i2c_adapter *adapter;
- int i, err;
+ int i, bit, err, nls, reg;
+ u8 ls1[4];
+ u8 ls2[4];
struct pca955x_platform_data *pdata;
bool set_default_label = false;
bool keep_pwm = false;
@@ -554,6 +556,17 @@ static int pca955x_probe(struct i2c_client *client)
init_data.devname_mandatory = false;
init_data.devicename = "pca955x";
+ nls = pca955x_num_led_regs(chip->bits);
+ /* use auto-increment feature to read all the led selectors at once */
+ err = i2c_smbus_read_i2c_block_data(client,
+ 0x10 | (pca955x_num_input_regs(chip->bits) + 4), nls,
+ ls1);
+ if (err)
+ return err;
+
+ for (i = 0; i < nls; ++i)
+ ls2[i] = ls1[i];
+
for (i = 0; i < chip->bits; i++) {
pca955x_led = &pca955x->leds[i];
pca955x_led->led_num = i;
@@ -565,21 +578,20 @@ static int pca955x_probe(struct i2c_client *client)
case PCA955X_TYPE_GPIO:
break;
case PCA955X_TYPE_LED:
+ bit = i % 4;
+ reg = i / 4;
led = &pca955x_led->led_cdev;
led->brightness_set_blocking = pca955x_led_set;
led->brightness_get = pca955x_led_get;
if (pdata->leds[i].default_state ==
- LEDS_GPIO_DEFSTATE_OFF) {
- err = pca955x_led_set(led, LED_OFF);
- if (err)
- return err;
- } else if (pdata->leds[i].default_state ==
- LEDS_GPIO_DEFSTATE_ON) {
- err = pca955x_led_set(led, LED_FULL);
- if (err)
- return err;
- }
+ LEDS_GPIO_DEFSTATE_OFF)
+ ls2[reg] = pca955x_ledsel(ls2[reg], bit,
+ PCA955X_LS_LED_OFF);
+ else if (pdata->leds[i].default_state ==
+ LEDS_GPIO_DEFSTATE_ON)
+ ls2[reg] = pca955x_ledsel(ls2[reg], bit,
+ PCA955X_LS_LED_ON);
init_data.fwnode = pdata->leds[i].fwnode;
@@ -624,6 +636,14 @@ static int pca955x_probe(struct i2c_client *client)
}
}
+ for (i = 0; i < nls; ++i) {
+ if (ls1[i] != ls2[i]) {
+ err = pca955x_write_ls(pca955x, i, ls2[i]);
+ if (err)
+ return err;
+ }
+ }
+
/* PWM0 is used for half brightness or 50% duty cycle */
err = pca955x_write_pwm(pca955x, 0, 255 - LED_HALF);
if (err)
--
2.31.1
Powered by blists - more mailing lists