[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20250212071525.1148988-1-marshall_zhan@wiwynn.com>
Date: Wed, 12 Feb 2025 15:15:24 +0800
From: MarshallZhan-wiwynn <marshall_zhan@...ynn.com>
To: patrick@...cx.xyz,
Pavel Machek <pavel@....cz>,
Lee Jones <lee@...nel.org>
Cc: MarshallZhan-wiwynn <marshall_zhan@...ynn.com>,
linux-leds@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: [PATCH v1] leds: cat9532: support cat9532 in pca955x
The CAT9532 chips are almost 100% compatible with PCA9552, except that
the CAT9532 used the opposite polarity in register that sets on/off.
Compare the state at INPUT with the state of LSn and dynamically
adjust how you program LSn
Signed-off-by: MarshallZhan-wiwynn <marshall_zhan@...ynn.com>
---
drivers/leds/leds-pca955x.c | 37 ++++++++++++++++++++++++++++++++-----
1 file changed, 32 insertions(+), 5 deletions(-)
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
index 94a9f8a54b35..c5bb81473b6a 100644
--- a/drivers/leds/leds-pca955x.c
+++ b/drivers/leds/leds-pca955x.c
@@ -13,6 +13,7 @@
* PCA9550 2-bit driver 0x60 .. 0x61
* PCA9551 8-bit driver 0x60 .. 0x67
* PCA9552 16-bit driver 0x60 .. 0x67
+ * CAT9532 16-bit driver 0x60 .. 0x67
* PCA9553/01 4-bit driver 0x62
* PCA9553/02 4-bit driver 0x63
*
@@ -235,6 +236,20 @@ static int pca955x_read_pwm(struct i2c_client *client, int n, u8 *val)
return 0;
}
+static int pca955x_read_input_bit(struct pca955x *pca955x, int led_num)
+{
+ u8 cmd = led_num / 8;
+ int ret;
+
+ ret = i2c_smbus_read_byte_data(pca955x->client, cmd);
+ if (ret < 0) {
+ dev_err(&pca955x->client->dev, "%s: reg 0x%x, err %d\n", __func__, led_num, ret);
+ return ret;
+ }
+ return (ret >> (led_num % 8)) & 1;
+
+}
+
static enum led_brightness pca955x_led_get(struct led_classdev *led_cdev)
{
struct pca955x_led *pca955x_led = container_of(led_cdev,
@@ -251,10 +266,11 @@ static enum led_brightness pca955x_led_get(struct led_classdev *led_cdev)
ls = (ls >> ((pca955x_led->led_num % 4) << 1)) & 0x3;
switch (ls) {
case PCA955X_LS_LED_ON:
- ret = LED_FULL;
- break;
case PCA955X_LS_LED_OFF:
- ret = LED_OFF;
+ if (pca955x_read_input_bit(pca955x, pca955x_led->led_num))
+ ret = LED_FULL;
+ else
+ ret = LED_OFF;
break;
case PCA955X_LS_BLINK0:
ret = LED_HALF;
@@ -276,6 +292,8 @@ static int pca955x_led_set(struct led_classdev *led_cdev,
struct pca955x_led *pca955x_led;
struct pca955x *pca955x;
u8 ls;
+ u8 ls_last_state;
+ int inupt_bit;
int chip_ls; /* which LSx to use (0-3 potentially) */
int ls_led; /* which set of bits within LSx to use (0-3) */
int ret;
@@ -292,12 +310,21 @@ static int pca955x_led_set(struct led_classdev *led_cdev,
if (ret)
goto out;
+ ls_last_state = pca955x_ledstate(ls, bit);
switch (value) {
case LED_FULL:
- ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_LED_ON);
+ input_bit = pca955x_read_input_bit(pca955x, pca955x_led->led_num);
+ if (ls_last_state == input_bit)
+ ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_LED_ON);
+ else
+ ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_LED_OFF);
break;
case LED_OFF:
- ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_LED_OFF);
+ input_bit = pca955x_read_input_bit(pca955x, pca955x_led->led_num);
+ if (ls_last_state == input_bit)
+ ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_LED_OFF);
+ else
+ ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_LED_ON);
break;
case LED_HALF:
ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_BLINK0);
--
2.25.1
WIWYNN PROPRIETARY
This email (and any attachments) contains proprietary or confidential information and is for the sole use of its intended recipient. Any unauthorized review, use, copying or distribution of this email or the content of this email is strictly prohibited. If you are not the intended recipient, please notify the sender and delete this email immediately.
Powered by blists - more mailing lists