From patchwork Thu Jun 20 21:03:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Marangi X-Patchwork-Id: 806140 Received: from mail-wr1-f52.google.com (mail-wr1-f52.google.com [209.85.221.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AC0A9155C8B; Thu, 20 Jun 2024 21:41:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.221.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718919714; cv=none; b=I+OHiRI0q5jJvvrzKN5jKVPAqbdnpQ06dscZAy5f4G/8xaAptMzdYV+WbKqUjhfb8on6qAZuqbExWfWOrXaNDM7CGgfnZdqE2RdIDlEPnEQbeKXCYqjaw/0dWGu4UzHtTtAFK8QeC1Cyo7G7FGRMcayRo6lD5mOOhK78RgoKS4k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1718919714; c=relaxed/simple; bh=oQTkijkig+TTMGeA52/UiQnffzMmX+MMJCK7FJjxfjw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kOl9iQajCZO/IFVl1GngshuJNm4u4QLHoSHzPQvetw3R8qA1isG4qjreqQ6WczeiD9K1EPXivq+uXYSwVyX5qq3tRpmqGsuXbm/4u7z+OtQitDgTSjAVXBwdBsxCqiJTeXmSLFnHCC2AIwq25Q2MOHbOJ0fhboAu+W7NBQPGTSE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=PGreFVkK; arc=none smtp.client-ip=209.85.221.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="PGreFVkK" Received: by mail-wr1-f52.google.com with SMTP id ffacd0b85a97d-36532d177a0so694733f8f.2; Thu, 20 Jun 2024 14:41:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1718919711; x=1719524511; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Zkzn+tBnOJfYBqIIubPBDn9JQ0osj8n0lCkRhH87/uc=; b=PGreFVkKPiNvgDzf2wGercGtny1kRO+ITPsJI2HVdJcwvtR+CATt5xaYq6+x/48HMf 3aHthIr0/XsQG8TeK86h7VsSwVJJj6hs6MKsRc8jMeydxPb+NhA08/cRRKWcpn1/8xb4 ZOO7kIkQNmGfjmoOUxQvG1k8S385yoVCuPuJsimjQ4toI2gmqnuuK7MdduNjJnV0deDO 9jPh1wq+Gqs8BqsFMYh4fBICWDFWwxXTb6HQUqWfWj6n/3MciKM3OHOvgh4Jjl8ztWZe PoHXrMZ5jHU9ydL1OHBn32JU3V37wEjW6K4smqzQ84uMIz6kY5cNfLwzXmCZFd5artyi EAMg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1718919711; x=1719524511; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Zkzn+tBnOJfYBqIIubPBDn9JQ0osj8n0lCkRhH87/uc=; b=lD2sEnuIxPi1q0OwBob8CF7e2Qdp0Ge6MGu11SAYnGjkHbZIiyA+UWRc7X21TrJpM4 SZA1+w6pqvPrpFOhSHBFapBGM7A6OOouFn/vBTwbaXRg7IdKKDIv3iwwaEIMrDPNzb4B m1oyVK/XmHAmHEKEu065QHDop3SHaW7bXOE848JjhsAA8oJKrTwRPd43fWuFD0cXG4kQ HmpvLs9f0l07IYV6egsjJ3ZsIeGRUSnFZ5KxHQBbFMkuDFBTrrz4lt9P5yVVhHTKh3f8 6YQWFRszEPl033jMVBP4ku2AFUnwvj7HNSzVDVfPprpM7CvOx/f1+tfhF1NNWPZpUePQ 9FIA== X-Forwarded-Encrypted: i=1; AJvYcCWseYwcJgEHXPa6ST6b2l/oJZWLgJ2CBu2Fqxr2EyG7OQhp1ulgCRtzg8SPnJTArYs4ZdF1L/nKIVfhOwQvZ2Zk3xU+w4oiBu46Wp3Kkwtl1kMZS9YoKwOwd91Kmb5sWC67JTSUkUtQWZHi1+3/W3Cm/COVxeKUxtZQqpgvaeRaZeW6+3Y= X-Gm-Message-State: AOJu0YyUGnuWQC7VOKAVFLyZnMcvc5o8Pq6PUbq4cMMf9Xrzj5Q/0kip zprWdiVu+6/1uJmm+E/ki/m5BiqXxklnVhIOaNdtgsgLpKC6iyO/ X-Google-Smtp-Source: AGHT+IGZo5QC0yd+XO10iyD96v8flgjMViHGOzXne7J8H4hSPiXUTukXgwTXxgm1z44esHTdlU7xJQ== X-Received: by 2002:a5d:464a:0:b0:361:1ef2:a273 with SMTP id ffacd0b85a97d-363171e2bfdmr4819067f8f.13.1718919710958; Thu, 20 Jun 2024 14:41:50 -0700 (PDT) Received: from localhost.localdomain (93-34-90-105.ip49.fastwebnet.it. [93.34.90.105]) by smtp.googlemail.com with ESMTPSA id ffacd0b85a97d-366383f68acsm48866f8f.2.2024.06.20.14.41.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 20 Jun 2024 14:41:50 -0700 (PDT) From: Christian Marangi To: Pavel Machek , Lee Jones , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Jacek Anaszewski , linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Christian Marangi Subject: [PATCH v7 16/20] leds: leds-lp55xx: Generalize sysfs engine_leds Date: Thu, 20 Jun 2024 23:03:32 +0200 Message-ID: <20240620210401.22053-17-ansuelsmth@gmail.com> X-Mailer: git-send-email 2.45.1 In-Reply-To: <20240620210401.22053-1-ansuelsmth@gmail.com> References: <20240620210401.22053-1-ansuelsmth@gmail.com> Precedence: bulk X-Mailing-List: linux-leds@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Generalize sysfs engine_leds since their implementation is the same across some lp55xx based LED driver. While at it simplify the implementation for show_engine_leds. Suggested-by: Lee Jones Signed-off-by: Christian Marangi --- drivers/leds/leds-lp5523.c | 119 +----------------------------- drivers/leds/leds-lp55xx-common.c | 109 +++++++++++++++++++++++++++ drivers/leds/leds-lp55xx-common.h | 32 ++++---- 3 files changed, 131 insertions(+), 129 deletions(-) diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c index 19b119a2b256..9d91c2c5a3eb 100644 --- a/drivers/leds/leds-lp5523.c +++ b/drivers/leds/leds-lp5523.c @@ -225,119 +225,6 @@ static int lp5523_init_program_engine(struct lp55xx_chip *chip) return ret; } -static int lp5523_mux_parse(const char *buf, u16 *mux, size_t len) -{ - u16 tmp_mux = 0; - int i; - - len = min_t(int, len, LP5523_MAX_LEDS); - - for (i = 0; i < len; i++) { - switch (buf[i]) { - case '1': - tmp_mux |= (1 << i); - break; - case '0': - break; - case '\n': - i = len; - break; - default: - return -1; - } - } - *mux = tmp_mux; - - return 0; -} - -static void lp5523_mux_to_array(u16 led_mux, char *array) -{ - int i, pos = 0; - - for (i = 0; i < LP5523_MAX_LEDS; i++) - pos += sprintf(array + pos, "%x", LED_ACTIVE(led_mux, i)); - - array[pos] = '\0'; -} - -static ssize_t show_engine_leds(struct device *dev, - struct device_attribute *attr, - char *buf, int nr) -{ - struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev)); - struct lp55xx_chip *chip = led->chip; - char mux[LP5523_MAX_LEDS + 1]; - - lp5523_mux_to_array(chip->engines[nr - 1].led_mux, mux); - - return sprintf(buf, "%s\n", mux); -} -show_leds(1) -show_leds(2) -show_leds(3) - -static int lp5523_load_mux(struct lp55xx_chip *chip, u16 mux, int nr) -{ - struct lp55xx_engine *engine = &chip->engines[nr - 1]; - int ret; - static const u8 mux_page[] = { - [LP55XX_ENGINE_1] = LP5523_PAGE_MUX1, - [LP55XX_ENGINE_2] = LP5523_PAGE_MUX2, - [LP55XX_ENGINE_3] = LP5523_PAGE_MUX3, - }; - - lp55xx_load_engine(chip); - - ret = lp55xx_write(chip, LP5523_REG_PROG_PAGE_SEL, mux_page[nr]); - if (ret) - return ret; - - ret = lp55xx_write(chip, LP5523_REG_PROG_MEM, (u8)(mux >> 8)); - if (ret) - return ret; - - ret = lp55xx_write(chip, LP5523_REG_PROG_MEM + 1, (u8)(mux)); - if (ret) - return ret; - - engine->led_mux = mux; - return 0; -} - -static ssize_t store_engine_leds(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t len, int nr) -{ - struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev)); - struct lp55xx_chip *chip = led->chip; - struct lp55xx_engine *engine = &chip->engines[nr - 1]; - u16 mux = 0; - ssize_t ret; - - if (lp5523_mux_parse(buf, &mux, len)) - return -EINVAL; - - mutex_lock(&chip->lock); - - chip->engine_idx = nr; - ret = -EINVAL; - - if (engine->mode != LP55XX_ENGINE_LOAD) - goto leave; - - if (lp5523_load_mux(chip, mux, nr)) - goto leave; - - ret = len; -leave: - mutex_unlock(&chip->lock); - return ret; -} -store_leds(1) -store_leds(2) -store_leds(3) - static ssize_t lp5523_selftest(struct device *dev, struct device_attribute *attr, char *buf) @@ -562,9 +449,9 @@ static ssize_t store_master_fader_leds(struct device *dev, LP55XX_DEV_ATTR_ENGINE_MODE(1); LP55XX_DEV_ATTR_ENGINE_MODE(2); LP55XX_DEV_ATTR_ENGINE_MODE(3); -static LP55XX_DEV_ATTR_RW(engine1_leds, show_engine1_leds, store_engine1_leds); -static LP55XX_DEV_ATTR_RW(engine2_leds, show_engine2_leds, store_engine2_leds); -static LP55XX_DEV_ATTR_RW(engine3_leds, show_engine3_leds, store_engine3_leds); +LP55XX_DEV_ATTR_ENGINE_LEDS(1); +LP55XX_DEV_ATTR_ENGINE_LEDS(2); +LP55XX_DEV_ATTR_ENGINE_LEDS(3); LP55XX_DEV_ATTR_ENGINE_LOAD(1); LP55XX_DEV_ATTR_ENGINE_LOAD(2); LP55XX_DEV_ATTR_ENGINE_LOAD(3); diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c index 0974488780c0..f0b673c61396 100644 --- a/drivers/leds/leds-lp55xx-common.c +++ b/drivers/leds/leds-lp55xx-common.c @@ -62,6 +62,8 @@ /* If supported, each ENGINE have an equal amount of pages offset from page 0 */ #define LP55xx_PAGE_OFFSET(n, pages) (((n) - 1) * (pages)) +#define LED_ACTIVE(mux, led) (!!((mux) & (0x0001 << (led)))) + /* External clock rate */ #define LP55XX_CLK_32K 32768 @@ -691,6 +693,113 @@ ssize_t lp55xx_store_engine_load(struct device *dev, } EXPORT_SYMBOL_GPL(lp55xx_store_engine_load); +static int lp55xx_mux_parse(struct lp55xx_chip *chip, const char *buf, + u16 *mux, size_t len) +{ + const struct lp55xx_device_config *cfg = chip->cfg; + u16 tmp_mux = 0; + int i; + + len = min_t(int, len, cfg->max_channel); + + for (i = 0; i < len; i++) { + switch (buf[i]) { + case '1': + tmp_mux |= (1 << i); + break; + case '0': + break; + case '\n': + i = len; + break; + default: + return -1; + } + } + *mux = tmp_mux; + + return 0; +} + +ssize_t lp55xx_show_engine_leds(struct device *dev, + struct device_attribute *attr, + char *buf, int nr) +{ + struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev)); + struct lp55xx_chip *chip = led->chip; + const struct lp55xx_device_config *cfg = chip->cfg; + unsigned int led_active; + int i, pos = 0; + + for (i = 0; i < cfg->max_channel; i++) { + led_active = LED_ACTIVE(chip->engines[nr - 1].led_mux, i); + pos += sysfs_emit_at(buf, pos, "%x", led_active); + } + + pos += sysfs_emit_at(buf, pos, "\n"); + + return pos; +} +EXPORT_SYMBOL_GPL(lp55xx_show_engine_leds); + +static int lp55xx_load_mux(struct lp55xx_chip *chip, u16 mux, int nr) +{ + struct lp55xx_engine *engine = &chip->engines[nr - 1]; + const struct lp55xx_device_config *cfg = chip->cfg; + u8 mux_page; + int ret; + + lp55xx_load_engine(chip); + + /* Derive the MUX page offset by starting at the end of the ENGINE pages */ + mux_page = cfg->pages_per_engine * LP55XX_ENGINE_MAX + (nr - 1); + ret = lp55xx_write(chip, LP55xx_REG_PROG_PAGE_SEL, mux_page); + if (ret) + return ret; + + ret = lp55xx_write(chip, cfg->prog_mem_base.addr, (u8)(mux >> 8)); + if (ret) + return ret; + + ret = lp55xx_write(chip, cfg->prog_mem_base.addr + 1, (u8)(mux)); + if (ret) + return ret; + + engine->led_mux = mux; + return 0; +} + +ssize_t lp55xx_store_engine_leds(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len, int nr) +{ + struct lp55xx_led *led = i2c_get_clientdata(to_i2c_client(dev)); + struct lp55xx_chip *chip = led->chip; + struct lp55xx_engine *engine = &chip->engines[nr - 1]; + u16 mux = 0; + ssize_t ret; + + if (lp55xx_mux_parse(chip, buf, &mux, len)) + return -EINVAL; + + mutex_lock(&chip->lock); + + chip->engine_idx = nr; + ret = -EINVAL; + + if (engine->mode != LP55XX_ENGINE_LOAD) + goto leave; + + if (lp55xx_load_mux(chip, mux, nr)) + goto leave; + + ret = len; +leave: + mutex_unlock(&chip->lock); + return ret; +} +EXPORT_SYMBOL_GPL(lp55xx_store_engine_leds); + static struct attribute *lp55xx_engine_attributes[] = { &dev_attr_select_engine.attr, &dev_attr_run_engine.attr, diff --git a/drivers/leds/leds-lp55xx-common.h b/drivers/leds/leds-lp55xx-common.h index 5b3e9473cadc..5f2394a6de15 100644 --- a/drivers/leds/leds-lp55xx-common.h +++ b/drivers/leds/leds-lp55xx-common.h @@ -51,21 +51,21 @@ static ssize_t store_engine##nr##_mode(struct device *dev, \ static LP55XX_DEV_ATTR_RW(engine##nr##_mode, show_engine##nr##_mode, \ store_engine##nr##_mode) -#define show_leds(nr) \ +#define LP55XX_DEV_ATTR_ENGINE_LEDS(nr) \ static ssize_t show_engine##nr##_leds(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ + struct device_attribute *attr, \ + char *buf) \ { \ - return show_engine_leds(dev, attr, buf, nr); \ -} - -#define store_leds(nr) \ -static ssize_t store_engine##nr##_leds(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t len) \ -{ \ - return store_engine_leds(dev, attr, buf, len, nr); \ -} + return lp55xx_show_engine_leds(dev, attr, buf, nr); \ +} \ +static ssize_t store_engine##nr##_leds(struct device *dev, \ + struct device_attribute *attr, \ + const char *buf, size_t len) \ +{ \ + return lp55xx_store_engine_leds(dev, attr, buf, len, nr); \ +} \ +static LP55XX_DEV_ATTR_RW(engine##nr##_leds, show_engine##nr##_leds, \ + store_engine##nr##_leds) #define LP55XX_DEV_ATTR_ENGINE_LOAD(nr) \ static ssize_t store_engine##nr##_load(struct device *dev, \ @@ -238,5 +238,11 @@ extern ssize_t lp55xx_store_engine_mode(struct device *dev, extern ssize_t lp55xx_store_engine_load(struct device *dev, struct device_attribute *attr, const char *buf, size_t len, int nr); +extern ssize_t lp55xx_show_engine_leds(struct device *dev, + struct device_attribute *attr, + char *buf, int nr); +extern ssize_t lp55xx_store_engine_leds(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t len, int nr); #endif /* _LEDS_LP55XX_COMMON_H */