get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/2222976/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2222976,
    "url": "http://patchwork.ozlabs.org/api/patches/2222976/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/rtc-linux/patch/20260414-s2mu005-pmic-v4-10-7fe7480577e6@disroot.org/",
    "project": {
        "id": 9,
        "url": "http://patchwork.ozlabs.org/api/projects/9/?format=api",
        "name": "Linux RTC development",
        "link_name": "rtc-linux",
        "list_id": "linux-rtc.vger.kernel.org",
        "list_email": "linux-rtc@vger.kernel.org",
        "web_url": "",
        "scm_url": "",
        "webscm_url": "",
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260414-s2mu005-pmic-v4-10-7fe7480577e6@disroot.org>",
    "list_archive_url": null,
    "date": "2026-04-14T06:33:02",
    "name": "[v4,10/13] leds: rgb: add support for Samsung S2M series PMIC RGB LED device",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "7043741ac3a4c6238067ef6fb7229c035f4964c5",
    "submitter": {
        "id": 88698,
        "url": "http://patchwork.ozlabs.org/api/people/88698/?format=api",
        "name": "Kaustabh Chakraborty",
        "email": "kauschluss@disroot.org"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/rtc-linux/patch/20260414-s2mu005-pmic-v4-10-7fe7480577e6@disroot.org/mbox/",
    "series": [
        {
            "id": 499781,
            "url": "http://patchwork.ozlabs.org/api/series/499781/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/rtc-linux/list/?series=499781",
            "date": "2026-04-14T06:32:53",
            "name": "Support for Samsung S2MU005 PMIC and its sub-devices",
            "version": 4,
            "mbox": "http://patchwork.ozlabs.org/series/499781/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2222976/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2222976/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "\n <linux-rtc+bounces-6326-incoming=patchwork.ozlabs.org@vger.kernel.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "linux-rtc@vger.kernel.org"
        ],
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n secure) header.d=disroot.org header.i=@disroot.org header.a=rsa-sha256\n header.s=mail header.b=Dddi+8z5;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=172.234.253.10; helo=sea.lore.kernel.org;\n envelope-from=linux-rtc+bounces-6326-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)",
            "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org\n header.b=\"Dddi+8z5\"",
            "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=178.21.23.139",
            "smtp.subspace.kernel.org;\n dmarc=pass (p=reject dis=none) header.from=disroot.org",
            "smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=disroot.org"
        ],
        "Received": [
            "from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fvvln5SsHz1y2d\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 14 Apr 2026 16:40:05 +1000 (AEST)",
            "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id 6FDD430DEE0A\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 14 Apr 2026 06:34:24 +0000 (UTC)",
            "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id EB02136E466;\n\tTue, 14 Apr 2026 06:34:23 +0000 (UTC)",
            "from layka.disroot.org (layka.disroot.org [178.21.23.139])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 119CD36DA02;\n\tTue, 14 Apr 2026 06:34:21 +0000 (UTC)",
            "from [127.0.0.1] (localhost [127.0.0.1])\n\tby disroot.org (Postfix) with ESMTP id 93FC825D82;\n\tTue, 14 Apr 2026 08:34:20 +0200 (CEST)",
            "from layka.disroot.org ([127.0.0.1])\n by localhost (disroot.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id 7gVT6s3IUv2e; Tue, 14 Apr 2026 08:34:19 +0200 (CEST)"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1776148463; cv=none;\n b=ECrbYDFr/+FkHS69MfMvB9w2Si3tpMHCzfm8JWQWOI4oK0VZd/ddZeM7teimskSKyB4rxYk+AIQZMrWFZQiio9XI5gIAd29jDuLgSZ2DqLctV5PLm+6j1dzqaCMWFL4Kf4qY1CGsAaADYQdSCzq8tIlJZVaDS2+Gm9Y7ZwhC1Yg=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1776148463; c=relaxed/simple;\n\tbh=zbWLA9HhoqFN2pF1fYTL6ftBe5NDhn0wLGl856dgrbY=;\n\th=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References:\n\t In-Reply-To:To:Cc;\n b=aCmrTExj2D87Kw3gNbv+IgeWkZLNYrr/bPsFTMzETkUABLxK3OaqkdIogoHvCPxIRgBy0cMKDvqCsFJZU2jk1d+FNBc/vxr49wyCQCJvsaCVpTiuRsDInzCSgzV8W7cdTkNyY68MGlUOXd/Jzrt+yRXA9DKv3b8YUQ+LIORJHBo=",
        "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=reject dis=none) header.from=disroot.org;\n spf=pass smtp.mailfrom=disroot.org;\n dkim=pass (2048-bit key) header.d=disroot.org header.i=@disroot.org\n header.b=Dddi+8z5; arc=none smtp.client-ip=178.21.23.139",
        "X-Virus-Scanned": "SPAM Filter at disroot.org",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=disroot.org; s=mail;\n\tt=1776148459; bh=zbWLA9HhoqFN2pF1fYTL6ftBe5NDhn0wLGl856dgrbY=;\n\th=From:Date:Subject:References:In-Reply-To:To:Cc;\n\tb=Dddi+8z5QhQToWEkT8ZXaDzeS+D7glQnhMK2TGvxLVoyqdgi9EMgiHX+47l3Hp7SX\n\t idW0yfGCbMaN/V9mSa2ujAJ+8CB37GdRf6CJxSCFW/UXsxVOA7ypqinQZRilVaZef4\n\t Q9848HOn5h2CQzoLj17vAPFfF+D5o2H9AulLC7cMUq/I2yFOFVo5Jv9nGhp67aO2ck\n\t KCW7RkXiiPNyCezNaIpAMKxqQV0FX/kovaBDeOuCtBE8bGDLGBYxGd70KIZnnv+bEf\n\t LEh7hUQ593faPXHdQab8G1QyZPeyeWmJ6U4LScuLqTEwqUXKHPQlSYdzOc/MQF/W2N\n\t 7NNqBwsfa3gVQ==",
        "From": "Kaustabh Chakraborty <kauschluss@disroot.org>",
        "Date": "Tue, 14 Apr 2026 12:03:02 +0530",
        "Subject": "[PATCH v4 10/13] leds: rgb: add support for Samsung S2M series\n PMIC RGB LED device",
        "Precedence": "bulk",
        "X-Mailing-List": "linux-rtc@vger.kernel.org",
        "List-Id": "<linux-rtc.vger.kernel.org>",
        "List-Subscribe": "<mailto:linux-rtc+subscribe@vger.kernel.org>",
        "List-Unsubscribe": "<mailto:linux-rtc+unsubscribe@vger.kernel.org>",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "7bit",
        "Message-Id": "<20260414-s2mu005-pmic-v4-10-7fe7480577e6@disroot.org>",
        "References": "<20260414-s2mu005-pmic-v4-0-7fe7480577e6@disroot.org>",
        "In-Reply-To": "<20260414-s2mu005-pmic-v4-0-7fe7480577e6@disroot.org>",
        "To": "Lee Jones <lee@kernel.org>, Pavel Machek <pavel@kernel.org>,\n  Rob Herring <robh@kernel.org>, Krzysztof Kozlowski <krzk+dt@kernel.org>,\n  Conor Dooley <conor+dt@kernel.org>, MyungJoo Ham <myungjoo.ham@samsung.com>,\n  Chanwoo Choi <cw00.choi@samsung.com>, Sebastian Reichel <sre@kernel.org>,\n  Krzysztof Kozlowski <krzk@kernel.org>,\n =?utf-8?q?Andr=C3=A9_Draszik?= <andre.draszik@linaro.org>,\n  Alexandre Belloni <alexandre.belloni@bootlin.com>,\n  Jonathan Corbet <corbet@lwn.net>, Shuah Khan <skhan@linuxfoundation.org>,\n  Nam Tran <trannamatk@gmail.com>,\n =?utf-8?b?xYF1a2FzeiBMZWJpZWR6acWEc2tp?= <kernel@lvkasz.us>",
        "Cc": "linux-leds@vger.kernel.org, devicetree@vger.kernel.org,\n linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org,\n linux-samsung-soc@vger.kernel.org, linux-rtc@vger.kernel.org,\n linux-doc@vger.kernel.org, Kaustabh Chakraborty <kauschluss@disroot.org>"
    },
    "content": "Add support for the RGB LEDs found in certain Samsung S2M series PMICs.\nThe device has three LED channels, controlled as a single device. These\nLEDs are typically used as status indicators in mobile phones.\n\nThe driver includes initial support for the S2MU005 PMIC RGB LEDs.\n\nSigned-off-by: Kaustabh Chakraborty <kauschluss@disroot.org>\n---\n drivers/leds/rgb/Kconfig        |  11 +\n drivers/leds/rgb/Makefile       |   1 +\n drivers/leds/rgb/leds-s2m-rgb.c | 446 ++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 458 insertions(+)",
    "diff": "diff --git a/drivers/leds/rgb/Kconfig b/drivers/leds/rgb/Kconfig\nindex 28ef4c487367c..30051342f4e4d 100644\n--- a/drivers/leds/rgb/Kconfig\n+++ b/drivers/leds/rgb/Kconfig\n@@ -75,6 +75,17 @@ config LEDS_QCOM_LPG\n \n \t  If compiled as a module, the module will be named leds-qcom-lpg.\n \n+config LEDS_S2M_RGB\n+\ttristate \"Samsung S2M series PMICs RGB LED support\"\n+\tdepends on LEDS_CLASS\n+\tdepends on MFD_SEC_CORE\n+\tselect REGMAP_IRQ\n+\thelp\n+\t  This option enables support for the S2MU005 RGB LEDs. These\n+\t  devices have three LED channels, with 8-bit brightness control\n+\t  for each channel. It's usually found in mobile phones as\n+\t  status indicators.\n+\n config LEDS_MT6370_RGB\n \ttristate \"LED Support for MediaTek MT6370 PMIC\"\n \tdepends on MFD_MT6370\ndiff --git a/drivers/leds/rgb/Makefile b/drivers/leds/rgb/Makefile\nindex be45991f63f50..98050e1aa4255 100644\n--- a/drivers/leds/rgb/Makefile\n+++ b/drivers/leds/rgb/Makefile\n@@ -6,4 +6,5 @@ obj-$(CONFIG_LEDS_LP5812)\t\t+= leds-lp5812.o\n obj-$(CONFIG_LEDS_NCP5623)\t\t+= leds-ncp5623.o\n obj-$(CONFIG_LEDS_PWM_MULTICOLOR)\t+= leds-pwm-multicolor.o\n obj-$(CONFIG_LEDS_QCOM_LPG)\t\t+= leds-qcom-lpg.o\n+obj-$(CONFIG_LEDS_S2M_RGB)\t\t+= leds-s2m-rgb.o\n obj-$(CONFIG_LEDS_MT6370_RGB)\t\t+= leds-mt6370-rgb.o\ndiff --git a/drivers/leds/rgb/leds-s2m-rgb.c b/drivers/leds/rgb/leds-s2m-rgb.c\nnew file mode 100644\nindex 0000000000000..5cefe8b990fb4\n--- /dev/null\n+++ b/drivers/leds/rgb/leds-s2m-rgb.c\n@@ -0,0 +1,446 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/*\n+ * RGB LED Driver for Samsung S2M series PMICs.\n+ *\n+ * Copyright (c) 2015 Samsung Electronics Co., Ltd\n+ * Copyright (c) 2025 Kaustabh Chakraborty <kauschluss@disroot.org>\n+ */\n+\n+#include <linux/container_of.h>\n+#include <linux/led-class-multicolor.h>\n+#include <linux/mfd/samsung/core.h>\n+#include <linux/mfd/samsung/s2mu005.h>\n+#include <linux/minmax.h>\n+#include <linux/module.h>\n+#include <linux/mutex.h>\n+#include <linux/of.h>\n+#include <linux/platform_device.h>\n+#include <linux/regmap.h>\n+\n+struct s2m_rgb {\n+\tstruct device *dev;\n+\tstruct regmap *regmap;\n+\tstruct led_classdev_mc mc;\n+\tenum sec_device_type device_type;\n+\t/*\n+\t * The mutex object prevents race conditions when evaluation and\n+\t * application of LED pattern state.\n+\t */\n+\tstruct mutex lock;\n+\t/*\n+\t * State variables representing the current LED pattern, these only to\n+\t * be accessed when lock is held.\n+\t */\n+\tu8 ramp_up;\n+\tu8 ramp_dn;\n+\tu8 stay_hi;\n+\tu8 stay_lo;\n+};\n+\n+static struct led_classdev_mc *to_s2m_mc(struct led_classdev *cdev)\n+{\n+\treturn container_of(cdev, struct led_classdev_mc, led_cdev);\n+}\n+\n+static struct s2m_rgb *to_s2m_rgb(struct led_classdev_mc *mc)\n+{\n+\treturn container_of(mc, struct s2m_rgb, mc);\n+}\n+\n+static const u32 s2mu005_rgb_lut_ramp[] = {\n+\t0,\t100,\t200,\t300,\t400,\t500,\t600,\t700,\n+\t800,\t1000,\t1200,\t1400,\t1600,\t1800,\t2000,\t2200,\n+};\n+\n+static const u32 s2mu005_rgb_lut_stay_hi[] = {\n+\t100,\t200,\t300,\t400,\t500,\t750,\t1000,\t1250,\n+\t1500,\t1750,\t2000,\t2250,\t2500,\t2750,\t3000,\t3250,\n+};\n+\n+static const u32 s2mu005_rgb_lut_stay_lo[] = {\n+\t0,\t500,\t1000,\t1500,\t2000,\t2500,\t3000,\t3500,\n+\t4000,\t4500,\t5000,\t6000,\t7000,\t8000,\t10000,\t12000,\n+};\n+\n+static int s2mu005_rgb_apply_params(struct s2m_rgb *rgb)\n+{\n+\tstruct regmap *regmap = rgb->regmap;\n+\tunsigned int ramp_val = 0;\n+\tunsigned int stay_val = 0;\n+\tint ret;\n+\tint i;\n+\n+\tramp_val |= FIELD_PREP(S2MU005_RGB_CH_RAMP_UP, rgb->ramp_up);\n+\tramp_val |= FIELD_PREP(S2MU005_RGB_CH_RAMP_DN, rgb->ramp_dn);\n+\n+\tstay_val |= FIELD_PREP(S2MU005_RGB_CH_STAY_HI, rgb->stay_hi);\n+\tstay_val |= FIELD_PREP(S2MU005_RGB_CH_STAY_LO, rgb->stay_lo);\n+\n+\tret = regmap_write(regmap, S2MU005_REG_RGB_EN, S2MU005_RGB_RESET);\n+\tif (ret < 0) {\n+\t\tdev_err(rgb->dev, \"failed to reset RGB LEDs\\n\");\n+\t\treturn ret;\n+\t}\n+\n+\tfor (i = 0; i < rgb->mc.num_colors; i++) {\n+\t\tret = regmap_write(regmap, S2MU005_REG_RGB_CH_CTRL(i),\n+\t\t\t\t   rgb->mc.subled_info[i].brightness);\n+\t\tif (ret < 0) {\n+\t\t\tdev_err(rgb->dev, \"failed to set LED brightness\\n\");\n+\t\t\treturn ret;\n+\t\t}\n+\n+\t\tret = regmap_write(regmap, S2MU005_REG_RGB_CH_RAMP(i), ramp_val);\n+\t\tif (ret < 0) {\n+\t\t\tdev_err(rgb->dev, \"failed to set ramp timings\\n\");\n+\t\t\treturn ret;\n+\t\t}\n+\n+\t\tret = regmap_write(regmap, S2MU005_REG_RGB_CH_STAY(i), stay_val);\n+\t\tif (ret < 0) {\n+\t\t\tdev_err(rgb->dev, \"failed to set stay timings\\n\");\n+\t\t\treturn ret;\n+\t\t}\n+\t}\n+\n+\tret = regmap_update_bits(regmap, S2MU005_REG_RGB_EN, S2MU005_RGB_SLOPE,\n+\t\t\t\t S2MU005_RGB_SLOPE_SMOOTH);\n+\tif (ret < 0) {\n+\t\tdev_err(rgb->dev, \"failed to set ramp slope\\n\");\n+\t\treturn ret;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+static int s2mu005_rgb_reset_params(struct s2m_rgb *rgb)\n+{\n+\tstruct regmap *regmap = rgb->regmap;\n+\tint ret;\n+\n+\tret = regmap_write(regmap, S2MU005_REG_RGB_EN, S2MU005_RGB_RESET);\n+\tif (ret < 0) {\n+\t\tdev_err(rgb->dev, \"failed to reset RGB LEDs\\n\");\n+\t\treturn ret;\n+\t}\n+\n+\trgb->ramp_up = 0;\n+\trgb->ramp_dn = 0;\n+\trgb->stay_hi = 0;\n+\trgb->stay_lo = 0;\n+\n+\treturn 0;\n+}\n+\n+static int s2m_rgb_lut_calc_timing(const u32 *lut, const size_t len,\n+\t\t\t\t   const u32 req_time, u8 *idx)\n+{\n+\tint lo = 0;\n+\tint hi = len - 2;\n+\n+\t/* Bounds checking */\n+\tif (req_time < lut[0] || req_time > lut[len - 1])\n+\t\treturn -EINVAL;\n+\n+\t/*\n+\t * Perform a binary search to pick the best timing from the LUT.\n+\t *\n+\t * The search algorithm picks two consecutive elements of the\n+\t * LUT and tries to search the pair between which the requested\n+\t * time lies.\n+\t */\n+\twhile (lo <= hi) {\n+\t\t*idx = (lo + hi) / 2;\n+\n+\t\tif ((lut[*idx] <= req_time) && (req_time <= lut[*idx + 1]))\n+\t\t\tbreak;\n+\n+\t\tif ((req_time < lut[*idx]) && (req_time < lut[*idx + 1]))\n+\t\t\thi = *idx - 1;\n+\t\telse\n+\t\t\tlo = *idx + 1;\n+\t}\n+\n+\t/*\n+\t * The searched timing is always less than the requested time. At\n+\t * times, the succeeding timing in the LUT is closer thus more\n+\t * accurate. Adjust the resulting value if that's the case.\n+\t */\n+\tif (abs(req_time - lut[*idx]) > abs(lut[*idx + 1] - req_time))\n+\t\t(*idx)++;\n+\n+\treturn 0;\n+}\n+\n+static int s2m_rgb_pattern_set(struct led_classdev *cdev, struct led_pattern *pattern,\n+\t\t\t       u32 len, int repeat)\n+{\n+\tstruct s2m_rgb *rgb = to_s2m_rgb(to_s2m_mc(cdev));\n+\tconst u32 *lut_ramp_up, *lut_ramp_dn, *lut_stay_hi, *lut_stay_lo;\n+\tsize_t lut_ramp_up_len, lut_ramp_dn_len, lut_stay_hi_len, lut_stay_lo_len;\n+\tint brightness_peak = 0;\n+\tu32 time_hi = 0, time_lo = 0;\n+\tbool ramp_up_en, ramp_dn_en;\n+\tint ret;\n+\tint i;\n+\n+\t/*\n+\t * The typical pattern supported by this device can be\n+\t * represented with the following graph:\n+\t *\n+\t *  255 T ''''''-.                         .-'''''''-.\n+\t *      |         '.                     .'           '.\n+\t *      |           \\                   /               \\\n+\t *      |            '.               .'                 '.\n+\t *      |              '-...........-'                     '-\n+\t *    0 +----------------------------------------------------> time (s)\n+\t *\n+\t *       <---- HIGH ----><-- LOW --><-------- HIGH --------->\n+\t *       <-----><-------><---------><-------><-----><------->\n+\t *       stay_hi ramp_dn   stay_lo   ramp_up stay_hi ramp_dn\n+\t *\n+\t * There are two states, named HIGH and LOW. HIGH has a non-zero\n+\t * brightness level, while LOW is of zero brightness. The\n+\t * pattern provided should mention only one zero and non-zero\n+\t * brightness level. The hardware always starts the pattern from\n+\t * the HIGH state, as shown in the graph.\n+\t *\n+\t * The HIGH state can be divided in three somewhat equal timings:\n+\t * ramp_up, stay_hi, and ramp_dn. The LOW state has only one\n+\t * timing: stay_lo.\n+\t */\n+\n+\t/* Only indefinitely looping patterns are supported. */\n+\tif (repeat != -1)\n+\t\treturn -EINVAL;\n+\n+\t/* Pattern should consist of at least two tuples. */\n+\tif (len < 2)\n+\t\treturn -EINVAL;\n+\n+\tfor (i = 0; i < len; i++) {\n+\t\tint brightness = pattern[i].brightness;\n+\t\tu32 delta_t = pattern[i].delta_t;\n+\n+\t\tif (brightness) {\n+\t\t\t/*\n+\t\t\t * The pattern shold define only one non-zero\n+\t\t\t * brightness in the HIGH state. The device\n+\t\t\t * doesn't have any provisions to handle\n+\t\t\t * multiple peak brightness levels.\n+\t\t\t */\n+\t\t\tif (brightness_peak && brightness_peak != brightness)\n+\t\t\t\treturn -EINVAL;\n+\n+\t\t\tbrightness_peak = brightness;\n+\t\t\ttime_hi += delta_t;\n+\t\t\tramp_dn_en = !!delta_t;\n+\t\t} else {\n+\t\t\ttime_lo += delta_t;\n+\t\t\tramp_up_en = !!delta_t;\n+\t\t}\n+\t}\n+\n+\tswitch (rgb->device_type) {\n+\tcase S2MU005:\n+\t\tlut_ramp_up = s2mu005_rgb_lut_ramp;\n+\t\tlut_ramp_up_len = ARRAY_SIZE(s2mu005_rgb_lut_ramp);\n+\t\tlut_ramp_dn = s2mu005_rgb_lut_ramp;\n+\t\tlut_ramp_dn_len = ARRAY_SIZE(s2mu005_rgb_lut_ramp);\n+\t\tlut_stay_hi = s2mu005_rgb_lut_stay_hi;\n+\t\tlut_stay_hi_len = ARRAY_SIZE(s2mu005_rgb_lut_stay_hi);\n+\t\tlut_stay_lo = s2mu005_rgb_lut_stay_lo;\n+\t\tlut_stay_lo_len = ARRAY_SIZE(s2mu005_rgb_lut_stay_lo);\n+\t\tbreak;\n+\tdefault:\n+\t\t/* execution shouldn't reach here */\n+\t\tbreak;\n+\t}\n+\n+\tmutex_lock(&rgb->lock);\n+\n+\t/*\n+\t * The timings ramp_up, stay_hi, and ramp_dn of the HIGH state\n+\t * are roughly equal. Firstly, calculate and set timings for\n+\t * ramp_up and ramp_dn (making sure they're exactly equal).\n+\t */\n+\trgb->ramp_up = 0;\n+\trgb->ramp_dn = 0;\n+\n+\tif (ramp_up_en) {\n+\t\tret = s2m_rgb_lut_calc_timing(lut_ramp_up, lut_ramp_up_len, time_hi / 3,\n+\t\t\t\t\t      &rgb->ramp_up);\n+\t\tif (ret < 0)\n+\t\t\tgoto param_fail;\n+\t}\n+\n+\tif (ramp_dn_en) {\n+\t\tret = s2m_rgb_lut_calc_timing(lut_ramp_dn, lut_ramp_dn_len, time_hi / 3,\n+\t\t\t\t\t      &rgb->ramp_dn);\n+\t\tif (ret < 0)\n+\t\t\tgoto param_fail;\n+\t}\n+\n+\t/*\n+\t * Subtract the allocated ramp timings from time_hi (and also\n+\t * making sure it doesn't underflow!). The remaining time is\n+\t * allocated to stay_hi.\n+\t */\n+\ttime_hi -= min(time_hi, lut_ramp_up[rgb->ramp_up]);\n+\ttime_hi -= min(time_hi, lut_ramp_dn[rgb->ramp_dn]);\n+\n+\tret = s2m_rgb_lut_calc_timing(lut_stay_hi, lut_stay_hi_len, time_hi, &rgb->stay_hi);\n+\tif (ret < 0)\n+\t\tgoto param_fail;\n+\n+\tret = s2m_rgb_lut_calc_timing(lut_stay_lo, lut_stay_lo_len, time_lo, &rgb->stay_lo);\n+\tif (ret < 0)\n+\t\tgoto param_fail;\n+\n+\tled_mc_calc_color_components(&rgb->mc, brightness_peak);\n+\tswitch (rgb->device_type) {\n+\tcase S2MU005:\n+\t\tret = s2mu005_rgb_apply_params(rgb);\n+\t\tbreak;\n+\tdefault:\n+\t\t/* execution shouldn't reach here */\n+\t\tbreak;\n+\t}\n+\tif (ret < 0)\n+\t\tgoto param_fail;\n+\n+\tmutex_unlock(&rgb->lock);\n+\n+\treturn 0;\n+\n+param_fail:\n+\trgb->ramp_up = 0;\n+\trgb->ramp_dn = 0;\n+\trgb->stay_hi = 0;\n+\trgb->stay_lo = 0;\n+\n+\tmutex_unlock(&rgb->lock);\n+\n+\treturn ret;\n+}\n+\n+static int s2m_rgb_pattern_clear(struct led_classdev *cdev)\n+{\n+\tstruct s2m_rgb *rgb = to_s2m_rgb(to_s2m_mc(cdev));\n+\tint ret = 0;\n+\n+\tmutex_lock(&rgb->lock);\n+\n+\tswitch (rgb->device_type) {\n+\tcase S2MU005:\n+\t\tret = s2mu005_rgb_reset_params(rgb);\n+\t\tbreak;\n+\tdefault:\n+\t\t/* execution shouldn't reach here */\n+\t\tbreak;\n+\t}\n+\n+\tmutex_unlock(&rgb->lock);\n+\n+\treturn ret;\n+}\n+\n+static int s2m_rgb_brightness_set(struct led_classdev *cdev, enum led_brightness value)\n+{\n+\tstruct s2m_rgb *rgb = to_s2m_rgb(to_s2m_mc(cdev));\n+\tint ret = 0;\n+\n+\tif (!value)\n+\t\treturn s2m_rgb_pattern_clear(cdev);\n+\n+\tmutex_lock(&rgb->lock);\n+\n+\tled_mc_calc_color_components(&rgb->mc, value);\n+\tswitch (rgb->device_type) {\n+\tcase S2MU005:\n+\t\tret = s2mu005_rgb_apply_params(rgb);\n+\t\tbreak;\n+\tdefault:\n+\t\t/* execution shouldn't reach here */\n+\t\tbreak;\n+\t}\n+\n+\tmutex_unlock(&rgb->lock);\n+\n+\treturn ret;\n+}\n+\n+static struct mc_subled s2mu005_rgb_subled_info[] = {\n+\t{ .channel = 0, .color_index = LED_COLOR_ID_BLUE },\n+\t{ .channel = 1, .color_index = LED_COLOR_ID_GREEN },\n+\t{ .channel = 2, .color_index = LED_COLOR_ID_RED },\n+};\n+\n+static int s2m_rgb_probe(struct platform_device *pdev)\n+{\n+\tstruct device *dev = &pdev->dev;\n+\tstruct sec_pmic_dev *pmic_drvdata = dev_get_drvdata(dev->parent);\n+\tstruct s2m_rgb *rgb;\n+\tstruct led_init_data init_data = {};\n+\tint ret;\n+\n+\trgb = devm_kzalloc(dev, sizeof(*rgb), GFP_KERNEL);\n+\tif (!rgb)\n+\t\treturn -ENOMEM;\n+\n+\tplatform_set_drvdata(pdev, rgb);\n+\trgb->dev = dev;\n+\trgb->regmap = pmic_drvdata->regmap_pmic;\n+\trgb->device_type = platform_get_device_id(pdev)->driver_data;\n+\n+\tswitch (rgb->device_type) {\n+\tcase S2MU005:\n+\t\trgb->mc.subled_info = s2mu005_rgb_subled_info;\n+\t\trgb->mc.num_colors = ARRAY_SIZE(s2mu005_rgb_subled_info);\n+\t\tbreak;\n+\tdefault:\n+\t\treturn dev_err_probe(dev, -ENODEV, \"device type %d is not supported by driver\\n\",\n+\t\t\t\t     pmic_drvdata->device_type);\n+\t}\n+\n+\trgb->mc.led_cdev.max_brightness = 255;\n+\trgb->mc.led_cdev.brightness_set_blocking = s2m_rgb_brightness_set;\n+\trgb->mc.led_cdev.pattern_set = s2m_rgb_pattern_set;\n+\trgb->mc.led_cdev.pattern_clear = s2m_rgb_pattern_clear;\n+\n+\tret = devm_mutex_init(dev, &rgb->lock);\n+\tif (ret)\n+\t\treturn dev_err_probe(dev, ret, \"failed to create mutex lock\\n\");\n+\n+\tinit_data.fwnode = of_fwnode_handle(dev->of_node);\n+\tret = devm_led_classdev_multicolor_register_ext(dev, &rgb->mc, &init_data);\n+\tif (ret < 0)\n+\t\treturn dev_err_probe(dev, ret, \"failed to create LED device\\n\");\n+\n+\treturn 0;\n+}\n+\n+static const struct platform_device_id s2m_rgb_id_table[] = {\n+\t{ \"s2mu005-rgb\", S2MU005 },\n+\t{ /* sentinel */ },\n+};\n+MODULE_DEVICE_TABLE(platform, s2m_rgb_id_table);\n+\n+static const struct of_device_id s2m_rgb_of_match_table[] = {\n+\t{ .compatible = \"samsung,s2mu005-rgb\", .data = (void *)S2MU005 },\n+\t{ /* sentinel */ },\n+};\n+MODULE_DEVICE_TABLE(of, s2m_rgb_of_match_table);\n+\n+static struct platform_driver s2m_rgb_driver = {\n+\t.driver = {\n+\t\t.name = \"s2m-rgb\",\n+\t},\n+\t.probe = s2m_rgb_probe,\n+\t.id_table = s2m_rgb_id_table,\n+};\n+module_platform_driver(s2m_rgb_driver);\n+\n+MODULE_DESCRIPTION(\"RGB LED Driver For Samsung S2M Series PMICs\");\n+MODULE_AUTHOR(\"Kaustabh Chakraborty <kauschluss@disroot.org>\");\n+MODULE_LICENSE(\"GPL\");\n",
    "prefixes": [
        "v4",
        "10/13"
    ]
}