From patchwork Thu Apr 7 07:32:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sven Schwermer X-Patchwork-Id: 559822 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 260E5C43217 for ; Thu, 7 Apr 2022 07:39:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236899AbiDGHl3 (ORCPT ); Thu, 7 Apr 2022 03:41:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40220 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241987AbiDGHlZ (ORCPT ); Thu, 7 Apr 2022 03:41:25 -0400 Received: from mail.schwermer.no (mail.schwermer.no [49.12.228.226]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3896B63384; Thu, 7 Apr 2022 00:39:16 -0700 (PDT) From: sven@svenschwermer.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=svenschwermer.de; s=mail; t=1649316787; bh=pjAbnCs8cCcjtdBzAC9l+vd148bcJSfRgwQvGacOiYo=; h=From:To:Cc:Subject:In-Reply-To:References; b=cVhZja7pc4Ynpk20QCFXwL/8+1eOnP9W/STrPiSISAPoeL5O1CbMuAF1Odhv+EsyY EEIbywrnMOnPkxk1NGbZzkPPLgr0wIFBbN6QZHEcuVh2BZwWj3LEWAPqAJOyW3xh4l yaGBX/QpWdqmTUjVbLYpL329pCFHoNWVXTs2bQ4huD8ZnAXsAhwPFWJaS1XmXWJChB z2cUS+9kwS3PJ+0k5eLXWwWOlYeeflvSbJL9cIRQ+zsBpsDZp4slmbjtc59ykOo3vL ndTwIna7IwX7LRVm7Ee+e22n8rVmuXv1P3oP4DX8dzzW120fBUvgdbZleq5P22tCM1 zdtyhXNUtSVng== To: linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-pwm@vger.kernel.org Cc: Sven Schwermer , pavel@ucw.cz, robh+dt@kernel.org, thierry.reding@gmail.com, u.kleine-koenig@pengutronix.de, lee.jones@linaro.org, post@lespocky.de, andy.shevchenko@gmail.com, robh@kernel.org Subject: [PATCH v8 1/3 RESEND] dt-bindings: leds: Optional multi-led unit address Date: Thu, 7 Apr 2022 09:32:23 +0200 Message-Id: <20220407073225.71605-2-sven@svenschwermer.de> In-Reply-To: <20220407073225.71605-1-sven@svenschwermer.de> References: <20220407073225.71605-1-sven@svenschwermer.de> Mime-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-leds@vger.kernel.org From: Sven Schwermer The unit address does not make sense in all cases the multi-led node is used, e.g. for the upcoming PWM multi-color LED driver. Signed-off-by: Sven Schwermer Reviewed-by: Rob Herring --- Notes: Changes in v8: * (no changes) Changes in v7: * (no changes) Added in v6 .../devicetree/bindings/leds/leds-class-multicolor.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/leds/leds-class-multicolor.yaml b/Documentation/devicetree/bindings/leds/leds-class-multicolor.yaml index 37445c68cdef..f41d021ed677 100644 --- a/Documentation/devicetree/bindings/leds/leds-class-multicolor.yaml +++ b/Documentation/devicetree/bindings/leds/leds-class-multicolor.yaml @@ -20,7 +20,7 @@ description: | within this documentation directory. patternProperties: - "^multi-led@([0-9a-f])$": + "^multi-led(@[0-9a-f])?$": type: object description: Represents the LEDs that are to be grouped. properties: From patchwork Thu Apr 7 07:32:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sven Schwermer X-Patchwork-Id: 558644 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 43F0DC4167D for ; Thu, 7 Apr 2022 07:39:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241977AbiDGHla (ORCPT ); Thu, 7 Apr 2022 03:41:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39744 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241992AbiDGHl0 (ORCPT ); Thu, 7 Apr 2022 03:41:26 -0400 X-Greylist: delayed 372 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Thu, 07 Apr 2022 00:39:23 PDT Received: from mail.schwermer.no (mail.schwermer.no [49.12.228.226]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B8CE82C12F; Thu, 7 Apr 2022 00:39:16 -0700 (PDT) From: sven@svenschwermer.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=svenschwermer.de; s=mail; t=1649316788; bh=P0tMMt9R/eXzGbDcuMZHOpkIK7L6pAAugPc6ndoWwF8=; h=From:To:Cc:Subject:In-Reply-To:References; b=igi3p+3sZ+2B10Xh4YNQb6U9TuTCp+/PBPqWuFcjkmp+HUFPA8542bXe16stCLA62 ySjJCFim8FdbbH8imakmt6Xb/2IIxO2Qe0FbNE7uRpTenv07/RiRjmXOsPU6kihYLe dcTp1jTf49cw2TEt0NePzlvn2FIGUefsRfkv8vZKK2oYHjwJXKKwARoCkPwkehXZ3Q wjAyRSHcXOds8vxWX+jLieNuyh4mgaLcAbppYVgIyPPJoEk5Z8MhsSK+0sAHDrsxsA 4UeFSrXJJg7jU0noD7HkXq2LUAzr15/OkNVFuzLolEGp5WR6xr9qAXZGpggAF0U4Al fYMV1NtsJJqig== To: linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-pwm@vger.kernel.org Cc: Sven Schwermer , pavel@ucw.cz, robh+dt@kernel.org, thierry.reding@gmail.com, u.kleine-koenig@pengutronix.de, lee.jones@linaro.org, post@lespocky.de, andy.shevchenko@gmail.com, robh@kernel.org Subject: [PATCH v8 2/3 RESEND] dt-bindings: leds: Add multicolor PWM LED bindings Date: Thu, 7 Apr 2022 09:32:24 +0200 Message-Id: <20220407073225.71605-3-sven@svenschwermer.de> In-Reply-To: <20220407073225.71605-1-sven@svenschwermer.de> References: <20220407073225.71605-1-sven@svenschwermer.de> Mime-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-leds@vger.kernel.org From: Sven Schwermer This allows to group multiple PWM-connected monochrome LEDs into multicolor LEDs, e.g. RGB LEDs. Signed-off-by: Sven Schwermer Reviewed-by: Rob Herring --- Notes: Changes in v8: * (no changes) Changes in v7: * Added newlines * Reorder slightly * Rename top-level node in example Changes in v6: * Fix device tree binding schema Changes in v5: * (no changes) Changes in v4: * (no changes) Changes in v3: * Remove multi-led unit name .../bindings/leds/leds-pwm-multicolor.yaml | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/leds-pwm-multicolor.yaml diff --git a/Documentation/devicetree/bindings/leds/leds-pwm-multicolor.yaml b/Documentation/devicetree/bindings/leds/leds-pwm-multicolor.yaml new file mode 100644 index 000000000000..6625a528f727 --- /dev/null +++ b/Documentation/devicetree/bindings/leds/leds-pwm-multicolor.yaml @@ -0,0 +1,79 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/leds/leds-pwm-multicolor.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Multi-color LEDs connected to PWM + +maintainers: + - Sven Schwermer + +description: | + This driver combines several monochrome PWM LEDs into one multi-color + LED using the multicolor LED class. + +properties: + compatible: + const: pwm-leds-multicolor + + multi-led: + type: object + + patternProperties: + "^led-[0-9a-z]+$": + type: object + $ref: common.yaml# + + additionalProperties: false + + properties: + pwms: + maxItems: 1 + + pwm-names: true + + color: true + + required: + - pwms + - color + +required: + - compatible + +allOf: + - $ref: leds-class-multicolor.yaml# + +additionalProperties: false + +examples: + - | + #include + + led-controller { + compatible = "pwm-leds-multicolor"; + + multi-led { + color = ; + function = LED_FUNCTION_INDICATOR; + max-brightness = <65535>; + + led-red { + pwms = <&pwm1 0 1000000>; + color = ; + }; + + led-green { + pwms = <&pwm2 0 1000000>; + color = ; + }; + + led-blue { + pwms = <&pwm3 0 1000000>; + color = ; + }; + }; + }; + +... From patchwork Thu Apr 7 07:32:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sven Schwermer X-Patchwork-Id: 558645 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 C5506C433EF for ; Thu, 7 Apr 2022 07:39:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241975AbiDGHl2 (ORCPT ); Thu, 7 Apr 2022 03:41:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40264 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241989AbiDGHlZ (ORCPT ); Thu, 7 Apr 2022 03:41:25 -0400 X-Greylist: delayed 367 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Thu, 07 Apr 2022 00:39:17 PDT Received: from mail.schwermer.no (mail.schwermer.no [49.12.228.226]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2E76E6326; Thu, 7 Apr 2022 00:39:16 -0700 (PDT) From: sven@svenschwermer.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=svenschwermer.de; s=mail; t=1649316788; bh=YjSfJgahcyOe04pZ9pdE0sp2HmcDXPOk4E4irpcypQo=; h=From:To:Cc:Subject:In-Reply-To:References; b=ltiNNn28VZIHzcG3e0hHpzSyUQcNI0szQihFzwZfoqZsINpTTojHYXOKyhAPL1dWz FiTpa/kFevjGChTDr7HyVNzV+FJfpbxGNJ1ixfRdkDEJl3Hcd+pA0W4hOUvPWwg4VN 13tSXaiBxaKifwvOTA/2rxmb77sr8IX0eL37bp0c2lfNZvRdAFc03WVJJVzBxV1khj jVt8lg4UHiVVl76LPGdrOCmG3jmTlT6+F3bBNJwMKWrx8nbNQRvq0fFG/ZZTGLBMye EAFacPWmYa8GQgxLCJv9hRTd2lfIAvVUCHkWI9HJMPs9FYfQvZzUlMAoL7jBa43wyv atGL26wyZq5SA== To: linux-leds@vger.kernel.org, devicetree@vger.kernel.org, linux-pwm@vger.kernel.org Cc: Sven Schwermer , pavel@ucw.cz, robh+dt@kernel.org, thierry.reding@gmail.com, u.kleine-koenig@pengutronix.de, lee.jones@linaro.org, post@lespocky.de, andy.shevchenko@gmail.com, robh@kernel.org Subject: [PATCH v8 3/3 RESEND] leds: Add PWM multicolor driver Date: Thu, 7 Apr 2022 09:32:25 +0200 Message-Id: <20220407073225.71605-4-sven@svenschwermer.de> In-Reply-To: <20220407073225.71605-1-sven@svenschwermer.de> References: <20220407073225.71605-1-sven@svenschwermer.de> Mime-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-leds@vger.kernel.org From: Sven Schwermer By allowing to group multiple monochrome PWM LEDs into multicolor LEDs, all involved LEDs can be controlled in-sync. This enables using effects using triggers, etc. Signed-off-by: Sven Schwermer Reviewed-by: Andy Shevchenko --- Notes: Changes in v8: * (no changes) Changes in v7: * (no changes) Changes in v6: * (no changes) Changes in v5: * Factor iteration over subleds out into function Changes in v4: * Remove mutex destruction and remove function * Include missing headers * Use post-increment instead of pre-increment * Variable declarations in reverse xmas tree order * Use dev_err_probe where possible * Return immediately where possible * Cosmetic changes * Document LKM name Changes in v3: * Release fwnode handles * Sort header includes * Remove deprecated device tree properties * Remove deprecated LED_OFF * Remove subled channel assignment * s/pwmstate/state/ drivers/leds/Kconfig | 11 ++ drivers/leds/Makefile | 1 + drivers/leds/leds-pwm-multicolor.c | 186 +++++++++++++++++++++++++++++ 3 files changed, 198 insertions(+) create mode 100644 drivers/leds/leds-pwm-multicolor.c diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 6090e647daee..e70a46704076 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -552,6 +552,17 @@ config LEDS_PWM help This option enables support for pwm driven LEDs +config LEDS_PWM_MULTICOLOR + tristate "PWM driven multi-color LED Support" + depends on LEDS_CLASS_MULTICOLOR + depends on PWM + help + This option enables support for PWM driven monochrome LEDs that are + grouped into multicolor LEDs. + + To compile this driver as a module, choose M here: the module + will be called leds-pwm-multicolor. + config LEDS_REGULATOR tristate "REGULATOR driven LED support" depends on LEDS_CLASS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index e58ecb36360f..ba2c2c1edf12 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -73,6 +73,7 @@ obj-$(CONFIG_LEDS_PCA963X) += leds-pca963x.o obj-$(CONFIG_LEDS_PM8058) += leds-pm8058.o obj-$(CONFIG_LEDS_POWERNV) += leds-powernv.o obj-$(CONFIG_LEDS_PWM) += leds-pwm.o +obj-$(CONFIG_LEDS_PWM_MULTICOLOR) += leds-pwm-multicolor.o obj-$(CONFIG_LEDS_REGULATOR) += leds-regulator.o obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o diff --git a/drivers/leds/leds-pwm-multicolor.c b/drivers/leds/leds-pwm-multicolor.c new file mode 100644 index 000000000000..45e38708ecb1 --- /dev/null +++ b/drivers/leds/leds-pwm-multicolor.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * PWM-based multi-color LED control + * + * Copyright 2022 Sven Schwermer + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct pwm_led { + struct pwm_device *pwm; + struct pwm_state state; +}; + +struct pwm_mc_led { + struct led_classdev_mc mc_cdev; + struct mutex lock; + struct pwm_led leds[]; +}; + +static int led_pwm_mc_set(struct led_classdev *cdev, + enum led_brightness brightness) +{ + struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(cdev); + struct pwm_mc_led *priv = container_of(mc_cdev, struct pwm_mc_led, mc_cdev); + unsigned long long duty; + int ret = 0; + int i; + + led_mc_calc_color_components(mc_cdev, brightness); + + mutex_lock(&priv->lock); + + for (i = 0; i < mc_cdev->num_colors; i++) { + duty = priv->leds[i].state.period; + duty *= mc_cdev->subled_info[i].brightness; + do_div(duty, cdev->max_brightness); + + priv->leds[i].state.duty_cycle = duty; + priv->leds[i].state.enabled = duty > 0; + ret = pwm_apply_state(priv->leds[i].pwm, + &priv->leds[i].state); + if (ret) + break; + } + + mutex_unlock(&priv->lock); + + return ret; +} + +static int iterate_subleds(struct device *dev, struct pwm_mc_led *priv, + struct fwnode_handle *mcnode) +{ + struct mc_subled *subled = priv->mc_cdev.subled_info; + struct fwnode_handle *fwnode; + struct pwm_led *pwmled; + u32 color; + int ret; + + /* iterate over the nodes inside the multi-led node */ + fwnode_for_each_child_node(mcnode, fwnode) { + pwmled = &priv->leds[priv->mc_cdev.num_colors]; + pwmled->pwm = devm_fwnode_pwm_get(dev, fwnode, NULL); + if (IS_ERR(pwmled->pwm)) { + ret = PTR_ERR(pwmled->pwm); + dev_err(dev, "unable to request PWM: %d\n", ret); + goto release_fwnode; + } + pwm_init_state(pwmled->pwm, &pwmled->state); + + ret = fwnode_property_read_u32(fwnode, "color", &color); + if (ret) { + dev_err(dev, "cannot read color: %d\n", ret); + goto release_fwnode; + } + + subled[priv->mc_cdev.num_colors].color_index = color; + priv->mc_cdev.num_colors++; + } + + return 0; + +release_fwnode: + fwnode_handle_put(fwnode); + return ret; +} + +static int led_pwm_mc_probe(struct platform_device *pdev) +{ + struct fwnode_handle *mcnode, *fwnode; + struct led_init_data init_data = {}; + struct led_classdev *cdev; + struct mc_subled *subled; + struct pwm_mc_led *priv; + int count = 0; + int ret = 0; + + mcnode = device_get_named_child_node(&pdev->dev, "multi-led"); + if (!mcnode) + return dev_err_probe(&pdev->dev, -ENODEV, + "expected multi-led node\n"); + + /* count the nodes inside the multi-led node */ + fwnode_for_each_child_node(mcnode, fwnode) + count++; + + priv = devm_kzalloc(&pdev->dev, struct_size(priv, leds, count), + GFP_KERNEL); + if (!priv) { + ret = -ENOMEM; + goto release_mcnode; + } + mutex_init(&priv->lock); + + subled = devm_kcalloc(&pdev->dev, count, sizeof(*subled), GFP_KERNEL); + if (!subled) { + ret = -ENOMEM; + goto release_mcnode; + } + priv->mc_cdev.subled_info = subled; + + /* init the multicolor's LED class device */ + cdev = &priv->mc_cdev.led_cdev; + fwnode_property_read_u32(mcnode, "max-brightness", + &cdev->max_brightness); + cdev->flags = LED_CORE_SUSPENDRESUME; + cdev->brightness_set_blocking = led_pwm_mc_set; + + ret = iterate_subleds(&pdev->dev, priv, mcnode); + if (ret) + goto release_mcnode; + + init_data.fwnode = mcnode; + ret = devm_led_classdev_multicolor_register_ext(&pdev->dev, + &priv->mc_cdev, + &init_data); + if (ret) { + dev_err(&pdev->dev, + "failed to register multicolor PWM led for %s: %d\n", + cdev->name, ret); + goto release_mcnode; + } + + ret = led_pwm_mc_set(cdev, cdev->brightness); + if (ret) + return dev_err_probe(&pdev->dev, ret, + "failed to set led PWM value for %s: %d", + cdev->name, ret); + + platform_set_drvdata(pdev, priv); + return 0; + +release_mcnode: + fwnode_handle_put(mcnode); + return ret; +} + +static const struct of_device_id of_pwm_leds_mc_match[] = { + { .compatible = "pwm-leds-multicolor", }, + {} +}; +MODULE_DEVICE_TABLE(of, of_pwm_leds_mc_match); + +static struct platform_driver led_pwm_mc_driver = { + .probe = led_pwm_mc_probe, + .driver = { + .name = "leds_pwm_multicolor", + .of_match_table = of_pwm_leds_mc_match, + }, +}; +module_platform_driver(led_pwm_mc_driver); + +MODULE_AUTHOR("Sven Schwermer "); +MODULE_DESCRIPTION("multi-color PWM LED driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:leds-pwm-multicolor");