From patchwork Fri Jul 28 15:37:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Jacques Hiblot X-Patchwork-Id: 707794 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7F204C001E0 for ; Fri, 28 Jul 2023 15:37:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236509AbjG1Phs (ORCPT ); Fri, 28 Jul 2023 11:37:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59144 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234149AbjG1Phr (ORCPT ); Fri, 28 Jul 2023 11:37:47 -0400 Received: from 9.mo563.mail-out.ovh.net (9.mo563.mail-out.ovh.net [46.105.73.201]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7E3431BE8 for ; Fri, 28 Jul 2023 08:37:45 -0700 (PDT) Received: from director1.derp.mail-out.ovh.net (director1.derp.mail-out.ovh.net [51.68.80.175]) by mo563.mail-out.ovh.net (Postfix) with ESMTPS id 58EA4229C0; Fri, 28 Jul 2023 15:37:43 +0000 (UTC) Received: from director1.derp.mail-out.ovh.net (director1.derp.mail-out.ovh.net. [127.0.0.1]) by director1.derp.mail-out.ovh.net (inspect_sender_mail_agent) with SMTP for ; Fri, 28 Jul 2023 15:37:43 +0000 (UTC) Received: from pro2.mail.ovh.net (unknown [10.109.138.11]) by director1.derp.mail-out.ovh.net (Postfix) with ESMTPS id ED9EB2011DD; Fri, 28 Jul 2023 15:37:42 +0000 (UTC) Received: from traphandler.com (88.161.25.233) by DAG1EX1.emp2.local (172.16.2.1) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 28 Jul 2023 17:37:42 +0200 From: Jean-Jacques Hiblot To: , , , , CC: , , , Jean-Jacques Hiblot , Andy Shevchenko Subject: [RESEND] [PATCH v11 1/4] leds: provide devm_of_led_get_optional() Date: Fri, 28 Jul 2023 17:37:28 +0200 Message-ID: <20230728153731.3742339-2-jjhiblot@traphandler.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230728153731.3742339-1-jjhiblot@traphandler.com> References: <20230728153731.3742339-1-jjhiblot@traphandler.com> MIME-Version: 1.0 X-Originating-IP: [88.161.25.233] X-ClientProxiedBy: CAS4.emp2.local (172.16.1.4) To DAG1EX1.emp2.local (172.16.2.1) X-Ovh-Tracer-Id: 16196914588195699079 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedviedrieeigdekkecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfqggfjpdevjffgvefmvefgnecuuegrihhlohhuthemucehtddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhvfevufffkffojghfggfgtghisehtkeertdertddtnecuhfhrohhmpeflvggrnhdqlfgrtghquhgvshcujfhisghlohhtuceojhhjhhhisghlohhtsehtrhgrphhhrghnughlvghrrdgtohhmqeenucggtffrrghtthgvrhhnpeduteevleevvefggfdvueffffejhfehheeuiedtgedtjeeghfehueduudegfeefueenucfkpheptddrtddrtddrtddpkeekrdduiedurddvhedrvdeffeenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhhouggvpehsmhhtphhouhhtpdhhvghlohepughirhgvtghtohhruddruggvrhhprdhmrghilhdqohhuthdrohhvhhdrnhgvthdpihhnvghtpedtrddtrddtrddtpdhmrghilhhfrhhomhepjhhjhhhisghlohhtsehtrhgrphhhrghnughlvghrrdgtohhmpdhnsggprhgtphhtthhopedupdhrtghpthhtoheplhhinhhugidqlhgvughssehvghgvrhdrkhgvrhhnvghlrdhorhhgpdfovfetjfhoshhtpehmohehieef Precedence: bulk List-ID: X-Mailing-List: linux-leds@vger.kernel.org Add an optional variant of devm_of_led_get(). It behaves the same as devm_of_led_get() except where the LED doesn't exist. In this case, instead of returning -ENOENT, the function returns NULL. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Andy Shevchenko --- drivers/leds/led-class.c | 25 +++++++++++++++++++++++++ include/linux/leds.h | 2 ++ 2 files changed, 27 insertions(+) diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 4758da2b59cf..78068b06d009 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -402,6 +402,31 @@ void led_remove_lookup(struct led_lookup_data *led_lookup) } EXPORT_SYMBOL_GPL(led_remove_lookup); +/** + * devm_of_led_get_optional - Resource-managed request of an optional LED device + * @dev: LED consumer + * @index: index of the LED to obtain in the consumer + * + * The device node of the device is parsed to find the requested LED device. + * The LED device returned from this function is automatically released + * on driver detach. + * + * @return a pointer to a LED device, ERR_PTR(errno) on failure and NULL if the + * led was not found. + */ +struct led_classdev *__must_check devm_of_led_get_optional(struct device *dev, + int index) +{ + struct led_classdev *led; + + led = devm_of_led_get(dev, index); + if (IS_ERR(led) && PTR_ERR(led) == -ENOENT) + return NULL; + + return led; +} +EXPORT_SYMBOL_GPL(devm_of_led_get_optional); + static int led_classdev_next_name(const char *init_name, char *name, size_t len) { diff --git a/include/linux/leds.h b/include/linux/leds.h index 7d428100b42b..8740b4e47f88 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -313,6 +313,8 @@ extern struct led_classdev *of_led_get(struct device_node *np, int index); extern void led_put(struct led_classdev *led_cdev); struct led_classdev *__must_check devm_of_led_get(struct device *dev, int index); +struct led_classdev *__must_check devm_of_led_get_optional(struct device *dev, + int index); /** * led_blink_set - set blinking with software fallback From patchwork Fri Jul 28 15:37:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Jacques Hiblot X-Patchwork-Id: 707793 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 70797C001DF for ; Fri, 28 Jul 2023 15:46:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236685AbjG1PqV (ORCPT ); Fri, 28 Jul 2023 11:46:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35378 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237448AbjG1PqU (ORCPT ); Fri, 28 Jul 2023 11:46:20 -0400 Received: from 6.mo563.mail-out.ovh.net (6.mo563.mail-out.ovh.net [46.105.55.200]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 777FB449F for ; Fri, 28 Jul 2023 08:45:59 -0700 (PDT) Received: from director1.derp.mail-out.ovh.net (director1.derp.mail-out.ovh.net [51.68.80.175]) by mo563.mail-out.ovh.net (Postfix) with ESMTPS id 8E3FF22927; Fri, 28 Jul 2023 15:37:43 +0000 (UTC) Received: from director1.derp.mail-out.ovh.net (director1.derp.mail-out.ovh.net. [127.0.0.1]) by director1.derp.mail-out.ovh.net (inspect_sender_mail_agent) with SMTP for ; Fri, 28 Jul 2023 15:37:43 +0000 (UTC) Received: from pro2.mail.ovh.net (unknown [10.109.138.11]) by director1.derp.mail-out.ovh.net (Postfix) with ESMTPS id 30653201386; Fri, 28 Jul 2023 15:37:43 +0000 (UTC) Received: from traphandler.com (88.161.25.233) by DAG1EX1.emp2.local (172.16.2.1) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 28 Jul 2023 17:37:42 +0200 From: Jean-Jacques Hiblot To: , , , , CC: , , , Jean-Jacques Hiblot Subject: [RESEND] [PATCH v11 2/4] leds: class: store the color index in struct led_classdev Date: Fri, 28 Jul 2023 17:37:29 +0200 Message-ID: <20230728153731.3742339-3-jjhiblot@traphandler.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230728153731.3742339-1-jjhiblot@traphandler.com> References: <20230728153731.3742339-1-jjhiblot@traphandler.com> MIME-Version: 1.0 X-Originating-IP: [88.161.25.233] X-ClientProxiedBy: CAS4.emp2.local (172.16.1.4) To DAG1EX1.emp2.local (172.16.2.1) X-Ovh-Tracer-Id: 16196914586505263579 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: 0 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedviedrieeigdekkecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfqggfjpdevjffgvefmvefgnecuuegrihhlohhuthemucehtddtnecunecujfgurhephffvvefufffkofgjfhgggfgtihesthekredtredttdenucfhrhhomheplfgvrghnqdflrggtqhhuvghsucfjihgslhhothcuoehjjhhhihgslhhothesthhrrghphhgrnhgulhgvrhdrtghomheqnecuggftrfgrthhtvghrnhepudetveelveevgffgvdeuffffjefhheehueeitdegtdejgefhheeuuddugeeffeeunecukfhppedtrddtrddtrddtpdekkedrudeiuddrvdehrddvfeefnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmohguvgepshhmthhpohhuthdphhgvlhhopeguihhrvggtthhorhdurdguvghrphdrmhgrihhlqdhouhhtrdhovhhhrdhnvghtpdhinhgvtheptddrtddrtddrtddpmhgrihhlfhhrohhmpehjjhhhihgslhhothesthhrrghphhgrnhgulhgvrhdrtghomhdpnhgspghrtghpthhtohepuddprhgtphhtthhopehlihhnuhigqdhlvggushesvhhgvghrrdhkvghrnhgvlhdrohhrghdpoffvtefjohhsthepmhhoheeife Precedence: bulk List-ID: X-Mailing-List: linux-leds@vger.kernel.org Store the color of the LED so that it is not lost after the LED's name has been composed. This color information can then be exposed to the user space or used by the LED consumer. Signed-off-by: Jean-Jacques Hiblot --- Documentation/ABI/testing/sysfs-class-led | 9 +++++++++ drivers/leds/led-class.c | 21 +++++++++++++++++++++ include/linux/leds.h | 1 + 3 files changed, 31 insertions(+) diff --git a/Documentation/ABI/testing/sysfs-class-led b/Documentation/ABI/testing/sysfs-class-led index 2e24ac3bd7ef..b2ff0012c0f2 100644 --- a/Documentation/ABI/testing/sysfs-class-led +++ b/Documentation/ABI/testing/sysfs-class-led @@ -59,6 +59,15 @@ Description: brightness. Reading this file when no hw brightness change event has happened will return an ENODATA error. +What: /sys/class/leds//color +Date: June 2023 +KernelVersion: 6.5 +Description: + Color of the LED. + + This is a read-only file. Reading this file returns the color + of the LED as a string (e.g: "red", "green", "multicolor"). + What: /sys/class/leds//trigger Date: March 2006 KernelVersion: 2.6.17 diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 78068b06d009..4bcbd46ec75a 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -76,6 +76,19 @@ static ssize_t max_brightness_show(struct device *dev, } static DEVICE_ATTR_RO(max_brightness); +static ssize_t color_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + const char *color_text = "invalid"; + struct led_classdev *led_cdev = dev_get_drvdata(dev); + + if (led_cdev->color < LED_COLOR_ID_MAX) + color_text = led_colors[led_cdev->color]; + + return sysfs_emit(buf, "%s\n", color_text); +} +static DEVICE_ATTR_RO(color); + #ifdef CONFIG_LEDS_TRIGGERS static BIN_ATTR(trigger, 0644, led_trigger_read, led_trigger_write, 0); static struct bin_attribute *led_trigger_bin_attrs[] = { @@ -90,6 +103,7 @@ static const struct attribute_group led_trigger_group = { static struct attribute *led_class_attrs[] = { &dev_attr_brightness.attr, &dev_attr_max_brightness.attr, + &dev_attr_color.attr, NULL, }; @@ -486,6 +500,10 @@ int led_classdev_register_ext(struct device *parent, fwnode_property_read_u32(init_data->fwnode, "max-brightness", &led_cdev->max_brightness); + + if (fwnode_property_present(init_data->fwnode, "color")) + fwnode_property_read_u32(init_data->fwnode, "color", + &led_cdev->color); } } else { proposed_name = led_cdev->name; @@ -495,6 +513,9 @@ int led_classdev_register_ext(struct device *parent, if (ret < 0) return ret; + if (led_cdev->color >= LED_COLOR_ID_MAX) + dev_warn(parent, "LED %s color identifier out of range\n", final_name); + mutex_init(&led_cdev->led_access); mutex_lock(&led_cdev->led_access); led_cdev->dev = device_create_with_groups(leds_class, parent, 0, diff --git a/include/linux/leds.h b/include/linux/leds.h index 8740b4e47f88..aa16dc2a8230 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h @@ -100,6 +100,7 @@ struct led_classdev { const char *name; unsigned int brightness; unsigned int max_brightness; + unsigned int color; int flags; /* Lower 16 bits reflect status */ From patchwork Fri Jul 28 15:37:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Jacques Hiblot X-Patchwork-Id: 708173 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 04293C41513 for ; Fri, 28 Jul 2023 15:37:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234149AbjG1Pht (ORCPT ); Fri, 28 Jul 2023 11:37:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59148 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235287AbjG1Phr (ORCPT ); Fri, 28 Jul 2023 11:37:47 -0400 Received: from 9.mo562.mail-out.ovh.net (9.mo562.mail-out.ovh.net [46.105.72.114]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D39452129 for ; Fri, 28 Jul 2023 08:37:45 -0700 (PDT) Received: from director1.derp.mail-out.ovh.net (director1.derp.mail-out.ovh.net [51.68.80.175]) by mo562.mail-out.ovh.net (Postfix) with ESMTPS id C3DC122DB7; Fri, 28 Jul 2023 15:37:43 +0000 (UTC) Received: from director1.derp.mail-out.ovh.net (director1.derp.mail-out.ovh.net. [127.0.0.1]) by director1.derp.mail-out.ovh.net (inspect_sender_mail_agent) with SMTP for ; Fri, 28 Jul 2023 15:37:43 +0000 (UTC) Received: from pro2.mail.ovh.net (unknown [10.109.138.11]) by director1.derp.mail-out.ovh.net (Postfix) with ESMTPS id 74047201385; Fri, 28 Jul 2023 15:37:43 +0000 (UTC) Received: from traphandler.com (88.161.25.233) by DAG1EX1.emp2.local (172.16.2.1) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 28 Jul 2023 17:37:42 +0200 From: Jean-Jacques Hiblot To: , , , , CC: , , , Jean-Jacques Hiblot , Rob Herring Subject: [RESEND] [PATCH v11 3/4] dt-bindings: leds: Add binding for a multicolor group of LEDs Date: Fri, 28 Jul 2023 17:37:30 +0200 Message-ID: <20230728153731.3742339-4-jjhiblot@traphandler.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230728153731.3742339-1-jjhiblot@traphandler.com> References: <20230728153731.3742339-1-jjhiblot@traphandler.com> MIME-Version: 1.0 X-Originating-IP: [88.161.25.233] X-ClientProxiedBy: CAS4.emp2.local (172.16.1.4) To DAG1EX1.emp2.local (172.16.2.1) X-Ovh-Tracer-Id: 16196914587960949201 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedviedrieeigdekkecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfqggfjpdevjffgvefmvefgnecuuegrihhlohhuthemucehtddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfjughrpefhvfevufffkffojghfggfgtghisehtkeertdertddtnecuhfhrohhmpeflvggrnhdqlfgrtghquhgvshcujfhisghlohhtuceojhhjhhhisghlohhtsehtrhgrphhhrghnughlvghrrdgtohhmqeenucggtffrrghtthgvrhhnpedttdffveeljeetleeijefhffevtdffleejheejiefgjeeludefvdevjedutdejhfenucffohhmrghinhepuggvvhhitggvthhrvggvrdhorhhgnecukfhppedtrddtrddtrddtpdekkedrudeiuddrvdehrddvfeefnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmohguvgepshhmthhpohhuthdphhgvlhhopeguihhrvggtthhorhdurdguvghrphdrmhgrihhlqdhouhhtrdhovhhhrdhnvghtpdhinhgvtheptddrtddrtddrtddpmhgrihhlfhhrohhmpehjjhhhihgslhhothesthhrrghphhgrnhgulhgvrhdrtghomhdpnhgspghrtghpthhtohepuddprhgtphhtthhopehlihhnuhigqdhlvggushesvhhgvghrrdhkvghrnhgvlhdrohhrghdpoffvtefjohhsthepmhhoheeivd Precedence: bulk List-ID: X-Mailing-List: linux-leds@vger.kernel.org This allows to group multiple monochromatic LEDs into a multicolor LED, e.g. RGB LEDs. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Rob Herring --- .../bindings/leds/leds-group-multicolor.yaml | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/leds-group-multicolor.yaml diff --git a/Documentation/devicetree/bindings/leds/leds-group-multicolor.yaml b/Documentation/devicetree/bindings/leds/leds-group-multicolor.yaml new file mode 100644 index 000000000000..8ed059a5a724 --- /dev/null +++ b/Documentation/devicetree/bindings/leds/leds-group-multicolor.yaml @@ -0,0 +1,64 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/leds-group-multicolor.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Multi-color LED built with monochromatic LEDs + +maintainers: + - Jean-Jacques Hiblot + +description: | + This driver combines several monochromatic LEDs into one multi-color + LED using the multicolor LED class. + +properties: + compatible: + const: leds-group-multicolor + + leds: + description: + An aray of monochromatic leds + $ref: /schemas/types.yaml#/definitions/phandle-array + +required: + - leds + +allOf: + - $ref: leds-class-multicolor.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + + monochromatic-leds { + compatible = "gpio-leds"; + + led0: led-0 { + gpios = <&mcu_pio 0 GPIO_ACTIVE_LOW>; + color = ; + }; + + led1: led-1 { + gpios = <&mcu_pio 1 GPIO_ACTIVE_HIGH>; + color = ; + }; + + led2: led-2 { + gpios = <&mcu_pio 2 GPIO_ACTIVE_HIGH>; + color = ; + }; + }; + + multi-led { + compatible = "leds-group-multicolor"; + color = ; + function = LED_FUNCTION_INDICATOR; + leds = <&led0>, <&led1>, <&led2>; + }; + +... From patchwork Fri Jul 28 15:37:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Jacques Hiblot X-Patchwork-Id: 708172 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D9A5DC001DE for ; Fri, 28 Jul 2023 15:46:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236368AbjG1Pq3 (ORCPT ); Fri, 28 Jul 2023 11:46:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35548 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237469AbjG1Pq2 (ORCPT ); Fri, 28 Jul 2023 11:46:28 -0400 X-Greylist: delayed 513 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Fri, 28 Jul 2023 08:46:19 PDT Received: from 1.mo562.mail-out.ovh.net (1.mo562.mail-out.ovh.net [178.33.109.175]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4DE394217 for ; Fri, 28 Jul 2023 08:46:19 -0700 (PDT) Received: from director1.derp.mail-out.ovh.net (director1.derp.mail-out.ovh.net [51.68.80.175]) by mo562.mail-out.ovh.net (Postfix) with ESMTPS id 40AFA22D20; Fri, 28 Jul 2023 15:37:44 +0000 (UTC) Received: from director1.derp.mail-out.ovh.net (director1.derp.mail-out.ovh.net. [127.0.0.1]) by director1.derp.mail-out.ovh.net (inspect_sender_mail_agent) with SMTP for ; Fri, 28 Jul 2023 15:37:44 +0000 (UTC) Received: from pro2.mail.ovh.net (unknown [10.109.156.149]) by director1.derp.mail-out.ovh.net (Postfix) with ESMTPS id DC0592011DD; Fri, 28 Jul 2023 15:37:43 +0000 (UTC) Received: from traphandler.com (88.161.25.233) by DAG1EX1.emp2.local (172.16.2.1) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Fri, 28 Jul 2023 17:37:43 +0200 From: Jean-Jacques Hiblot To: , , , , CC: , , , Jean-Jacques Hiblot Subject: [RESEND] [PATCH v11 4/4] leds: Add a multicolor LED driver to group monochromatic LEDs Date: Fri, 28 Jul 2023 17:37:31 +0200 Message-ID: <20230728153731.3742339-5-jjhiblot@traphandler.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230728153731.3742339-1-jjhiblot@traphandler.com> References: <20230728153731.3742339-1-jjhiblot@traphandler.com> MIME-Version: 1.0 X-Originating-IP: [88.161.25.233] X-ClientProxiedBy: CAS4.emp2.local (172.16.1.4) To DAG1EX1.emp2.local (172.16.2.1) X-Ovh-Tracer-Id: 16197196062999263707 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: 0 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedviedrieeigdekkecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfqggfjpdevjffgvefmvefgnecuuegrihhlohhuthemucehtddtnecunecujfgurhephffvvefufffkofgjfhgggfgtihesthekredtredttdenucfhrhhomheplfgvrghnqdflrggtqhhuvghsucfjihgslhhothcuoehjjhhhihgslhhothesthhrrghphhgrnhgulhgvrhdrtghomheqnecuggftrfgrthhtvghrnhepudetveelveevgffgvdeuffffjefhheehueeitdegtdejgefhheeuuddugeeffeeunecukfhppedtrddtrddtrddtpdekkedrudeiuddrvdehrddvfeefnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmohguvgepshhmthhpohhuthdphhgvlhhopeguihhrvggtthhorhdurdguvghrphdrmhgrihhlqdhouhhtrdhovhhhrdhnvghtpdhinhgvtheptddrtddrtddrtddpmhgrihhlfhhrohhmpehjjhhhihgslhhothesthhrrghphhgrnhgulhgvrhdrtghomhdpnhgspghrtghpthhtohepuddprhgtphhtthhopehlihhnuhigqdhlvggushesvhhgvghrrdhkvghrnhgvlhdrohhrghdpoffvtefjohhsthepmhhoheeivd Precedence: bulk List-ID: X-Mailing-List: linux-leds@vger.kernel.org Grouping multiple monochrome LEDs into a multicolor LED device has a few benefits over handling the group in user-space: - The state of the LEDs relative to each other is consistent. In other words, if 2 threads competes to set the LED to green and red, the end-result cannot be black or yellow. - The multicolor LED as a whole can be driven through the sysfs LED interface. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Lee Jones --- drivers/leds/rgb/Kconfig | 12 ++ drivers/leds/rgb/Makefile | 1 + drivers/leds/rgb/leds-group-multicolor.c | 169 +++++++++++++++++++++++ 3 files changed, 182 insertions(+) create mode 100644 drivers/leds/rgb/leds-group-multicolor.c diff --git a/drivers/leds/rgb/Kconfig b/drivers/leds/rgb/Kconfig index 360c8679c6e2..183bccc06cf3 100644 --- a/drivers/leds/rgb/Kconfig +++ b/drivers/leds/rgb/Kconfig @@ -2,6 +2,18 @@ if LEDS_CLASS_MULTICOLOR +config LEDS_GROUP_MULTICOLOR + tristate "LEDs group multi-color support" + depends on OF || COMPILE_TEST + help + This option enables support for monochrome LEDs that are grouped + into multicolor LEDs which is useful in the case where LEDs of + different colors are physically grouped in a single multi-color LED + and driven by a controller that doesn't have multi-color support. + + To compile this driver as a module, choose M here: the module + will be called leds-group-multicolor. + config LEDS_PWM_MULTICOLOR tristate "PWM driven multi-color LED Support" depends on PWM diff --git a/drivers/leds/rgb/Makefile b/drivers/leds/rgb/Makefile index 8c01daf63f61..c11cc56384e7 100644 --- a/drivers/leds/rgb/Makefile +++ b/drivers/leds/rgb/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_LEDS_GROUP_MULTICOLOR) += leds-group-multicolor.o obj-$(CONFIG_LEDS_PWM_MULTICOLOR) += leds-pwm-multicolor.o obj-$(CONFIG_LEDS_QCOM_LPG) += leds-qcom-lpg.o obj-$(CONFIG_LEDS_MT6370_RGB) += leds-mt6370-rgb.o diff --git a/drivers/leds/rgb/leds-group-multicolor.c b/drivers/leds/rgb/leds-group-multicolor.c new file mode 100644 index 000000000000..39f58be32af5 --- /dev/null +++ b/drivers/leds/rgb/leds-group-multicolor.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Multi-color LED built with monochromatic LED devices + * + * This driver groups several monochromatic LED devices in a single multicolor LED device. + * + * Compared to handling this grouping in user-space, the benefits are: + * - The state of the monochromatic LED relative to each other is always consistent. + * - The sysfs interface of the LEDs can be used for the group as a whole. + * + * Copyright 2023 Jean-Jacques Hiblot + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct leds_multicolor { + struct led_classdev_mc mc_cdev; + struct led_classdev **monochromatics; +}; + +static int leds_gmc_set(struct led_classdev *cdev, enum led_brightness brightness) +{ + struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(cdev); + struct leds_multicolor *priv = container_of(mc_cdev, struct leds_multicolor, mc_cdev); + const unsigned int group_max_brightness = mc_cdev->led_cdev.max_brightness; + int i; + + for (i = 0; i < mc_cdev->num_colors; i++) { + struct led_classdev *mono = priv->monochromatics[i]; + const unsigned int mono_max_brightness = mono->max_brightness; + unsigned int intensity = mc_cdev->subled_info[i].intensity; + int mono_brightness; + + /* + * Scale the brightness according to relative intensity of the + * color AND the max brightness of the monochromatic LED. + */ + mono_brightness = DIV_ROUND_CLOSEST(brightness * intensity * mono_max_brightness, + group_max_brightness * group_max_brightness); + + led_set_brightness(mono, mono_brightness); + } + + return 0; +} + +static void restore_sysfs_write_access(void *data) +{ + struct led_classdev *led_cdev = data; + + /* Restore the write acccess to the LED */ + mutex_lock(&led_cdev->led_access); + led_sysfs_enable(led_cdev); + mutex_unlock(&led_cdev->led_access); +} + +static int leds_gmc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct led_init_data init_data = {}; + struct led_classdev *cdev; + struct mc_subled *subled; + struct leds_multicolor *priv; + unsigned int max_brightness = 0; + int i, ret, count = 0; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + for (;;) { + struct led_classdev *led_cdev; + + led_cdev = devm_of_led_get_optional(dev, count); + if (IS_ERR(led_cdev)) + return dev_err_probe(dev, PTR_ERR(led_cdev), "Unable to get LED #%d", + count); + if (!led_cdev) + break; + + priv->monochromatics = devm_krealloc_array(dev, priv->monochromatics, + count + 1, sizeof(*priv->monochromatics), + GFP_KERNEL); + if (!priv->monochromatics) + return -ENOMEM; + + priv->monochromatics[count] = led_cdev; + + max_brightness = max(max_brightness, led_cdev->max_brightness); + + count++; + } + + subled = devm_kcalloc(dev, count, sizeof(*subled), GFP_KERNEL); + if (!subled) + return -ENOMEM; + priv->mc_cdev.subled_info = subled; + + for (i = 0; i < count; i++) { + struct led_classdev *led_cdev = priv->monochromatics[i]; + + subled[i].color_index = led_cdev->color; + + /* Configure the LED intensity to its maximum */ + subled[i].intensity = max_brightness; + } + + /* Initialise the multicolor's LED class device */ + cdev = &priv->mc_cdev.led_cdev; + cdev->flags = LED_CORE_SUSPENDRESUME; + cdev->brightness_set_blocking = leds_gmc_set; + cdev->max_brightness = max_brightness; + cdev->color = LED_COLOR_ID_MULTI; + priv->mc_cdev.num_colors = count; + + init_data.fwnode = dev_fwnode(dev); + ret = devm_led_classdev_multicolor_register_ext(dev, &priv->mc_cdev, &init_data); + if (ret) + return dev_err_probe(dev, ret, "failed to register multicolor LED for %s.\n", + cdev->name); + + ret = leds_gmc_set(cdev, cdev->brightness); + if (ret) + return dev_err_probe(dev, ret, "failed to set LED value for %s.", cdev->name); + + for (i = 0; i < count; i++) { + struct led_classdev *led_cdev = priv->monochromatics[i]; + + /* + * Make the individual LED sysfs interface read-only to prevent the user + * to change the brightness of the individual LEDs of the group. + */ + mutex_lock(&led_cdev->led_access); + led_sysfs_disable(led_cdev); + mutex_unlock(&led_cdev->led_access); + + /* Restore the write access to the LED sysfs when the group is destroyed */ + devm_add_action_or_reset(dev, restore_sysfs_write_access, led_cdev); + } + + return 0; +} + +static const struct of_device_id of_leds_group_multicolor_match[] = { + { .compatible = "leds-group-multicolor" }, + {} +}; +MODULE_DEVICE_TABLE(of, of_leds_group_multicolor_match); + +static struct platform_driver leds_group_multicolor_driver = { + .probe = leds_gmc_probe, + .driver = { + .name = "leds_group_multicolor", + .of_match_table = of_leds_group_multicolor_match, + } +}; +module_platform_driver(leds_group_multicolor_driver); + +MODULE_AUTHOR("Jean-Jacques Hiblot "); +MODULE_DESCRIPTION("LEDs group multicolor driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:leds-group-multicolor");