lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<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

Powered by Openwall GNU/*/Linux Powered by OpenVZ