From: Fenglin Wu <fenglin.wu@oss.qualcomm.com>
To: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>,
linux-arm-msm@vger.kernel.org, Lee Jones <lee@kernel.org>,
Pavel Machek <pavel@kernel.org>,
Bjorn Andersson <andersson@kernel.org>,
Marijn Suijten <marijn.suijten@somainline.org>,
Anjelique Melendez <quic_amelende@quicinc.com>,
Guru Das Srinagesh <linux@gurudas.dev>,
Nathan Chancellor <nathan@kernel.org>,
Nick Desaulniers <nick.desaulniers+lkml@gmail.com>,
Bill Wendling <morbo@google.com>,
Justin Stitt <justinstitt@google.com>
Cc: David Collins <david.collins@oss.qualcomm.com>,
Subbaraman Narayanamurthy
<subbaraman.narayanamurthy@oss.qualcomm.com>,
Kamal Wadhwa <kamal.wadhwa@oss.qualcomm.com>,
kernel@oss.qualcomm.com, Pavel Machek <pavel@ucw.cz>,
linux-leds@vger.kernel.org, linux-kernel@vger.kernel.org,
llvm@lists.linux.dev
Subject: Re: [PATCH v6] leds: rgb: leds-qcom-lpg: Fix LED color balancing in HW pattern mode
Date: Tue, 8 Sep 2026 09:14:55 +0800 [thread overview]
Message-ID: <ec3caf91-ac62-4d2b-8a70-f369a0c64e62@oss.qualcomm.com> (raw)
In-Reply-To: <de251a59-1ace-4b9c-beb2-99fe6f3cb842@oss.qualcomm.com>
On 9/3/2026 7:27 PM, Konrad Dybcio wrote:
> On 7/17/26 6:41 AM, Fenglin Wu wrote:
>> Currently, when the LED is configured as a RGB LED or a multi-color
>> LED device, the same pattern is programmed for all LED channels
>> regardless of the sub-led intensities when triggered by HW pattern.
>> It results that the LED device is always working in a white-balanced
>> mode regardless of the intensity settings.
>>
>> To fix this, scale the pattern data according to the sub-led intensity
>> and program the HW pattern separately for each LPG channel.
>>
>> Fixes: 24e2d05d1b68 ("leds: Add driver for Qualcomm LPG")
>> Fixes: 6ab1f766a80a ("leds: rgb: leds-qcom-lpg: Add support for PPG through single SDAM")
>> Fixes: 5e9ff626861a ("leds: rgb: leds-qcom-lpg: Include support for PPG with dedicated LUT SDAM")
>> Assisted-by: Claude:claude-4-6-sonnet
>> Signed-off-by: Fenglin Wu <fenglin.wu@oss.qualcomm.com>
>> ---
>
> GPT came up with the following fixes/suggestions:
>
> 1] This one makes sense at a glance:
>
> leds: rgb: leds-qcom-lpg: Skip LUT allocation for off colors
>
> Multicolor hardware pattern setup programs a separate LUT range for every
> component. A component with zero calculated brightness is disabled before
> the pattern is applied, so its all-zero range is never used.
>
> Skip allocating it to preserve the shared LUT capacity.
>
> Fixes: 2882fa0dc1cf ("leds: rgb: leds-qcom-lpg: Fix LED color balancing in HW pattern mode")
>
> diff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c
> index 24b1f570f524..e32388a16537 100644
> --- a/drivers/leds/rgb/leds-qcom-lpg.c
> +++ b/drivers/leds/rgb/leds-qcom-lpg.c
> @@ -1219,6 +1219,13 @@ static int lpg_pattern_mc_set(struct led_classdev *cdev,
> chan = led->channels[i];
> scale = mc->subled_info[i].brightness;
>
> + /* An off component neither needs nor uses a LUT range. */
> + if (!scale) {
> + chan->pattern_lo_idx = 0;
> + chan->pattern_hi_idx = 0;
> + continue;
> + }
> +
Thanks. I can add this one even though it is not related with function
correctness; it does help save the LUT with a simple check on the
sub-LED brightness. The sub-LED would just be turned off by gating the
current sink so the setting of pulse generator doesn't matter in such case.
> for (j = 0; j < pattern.len; j++) {
> scaled[j].brightness = DIV_ROUND_CLOSEST(
> (u32)prep_data[j].brightness * scale, LED_FULL);
>
>
> 2] This one.. I'm not convinced..
>
> leds: rgb: leds-qcom-lpg: Reuse LUT patterns for equal colors
>
> Multicolor hardware patterns with equal nonzero component brightnesses
> produce identical LUT data. Reuse their LUT range instead of allocating
> and programming duplicate data.
>
> Free each shared range once when clearing a pattern or unwinding a failed
> allocation.
>
> diff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c
> index e32388a16537..1c4d550c1ed0 100644
> --- a/drivers/leds/rgb/leds-qcom-lpg.c
> +++ b/drivers/leds/rgb/leds-qcom-lpg.c
> @@ -1175,6 +1175,34 @@ static int lpg_pattern_single_set(struct led_classdev *cdev,
> return 0;
> }
>
> +static void lpg_pattern_free(struct lpg_led *led, unsigned int count)
> +{
> + struct lpg_channel *chan;
> + unsigned int i, j;
> +
> + for (i = 0; i < count; i++) {
> + chan = led->channels[i];
> + if (chan->pattern_lo_idx == chan->pattern_hi_idx)
> + continue;
> +
> + for (j = 0; j < i; j++) {
> + if (chan->pattern_lo_idx == led->channels[j]->pattern_lo_idx &&
> + chan->pattern_hi_idx == led->channels[j]->pattern_hi_idx)
> + break;
> + }
> +
> + if (j == i)
> + lpg_lut_free(chan->lpg, chan->pattern_lo_idx,
> + chan->pattern_hi_idx);
> + }
> +
> + for (i = 0; i < count; i++) {
> + chan = led->channels[i];
> + chan->pattern_lo_idx = 0;
> + chan->pattern_hi_idx = 0;
> + }
> +}
> +
> static int lpg_pattern_mc_set(struct led_classdev *cdev,
> struct led_pattern *led_pattern, u32 len,
> int repeat)
> @@ -1226,6 +1254,17 @@ static int lpg_pattern_mc_set(struct led_classdev *cdev,
> continue;
> }
>
> + for (j = 0; j < i; j++) {
> + if (scale == mc->subled_info[j].brightness) {
> + chan->pattern_lo_idx = led->channels[j]->pattern_lo_idx;
> + chan->pattern_hi_idx = led->channels[j]->pattern_hi_idx;
> + break;
> + }
> + }
This is based on a wrong assumption that all sub-LEDs are using the same
pattern, so this is not correct.
> +
> + if (j != i)
> + continue;
> +
> for (j = 0; j < pattern.len; j++) {
> scaled[j].brightness = DIV_ROUND_CLOSEST(
> (u32)prep_data[j].brightness * scale, LED_FULL);
> @@ -1238,14 +1277,7 @@ static int lpg_pattern_mc_set(struct led_classdev *cdev,
> ret = lpg_lut_store_sdam(lpg, scaled, pattern.len, &lo_idx, &hi_idx);
>
> if (ret < 0) {
> - /* Free LUT slots already allocated for previous channels */
> - while (i-- > 0) {
> - chan = led->channels[i];
> - lpg_lut_free(lpg, chan->pattern_lo_idx, chan->pattern_hi_idx);
> - chan->pattern_lo_idx = 0;
> - chan->pattern_hi_idx = 0;
> - }
> -
> + lpg_pattern_free(led, i);
> return ret;
> }
>
> @@ -1271,13 +1303,12 @@ static int lpg_pattern_clear(struct lpg_led *led)
>
> mutex_lock(&lpg->lock);
>
> + lpg_pattern_free(led, led->num_channels);
> +
> for (i = 0; i < led->num_channels; i++) {
> chan = led->channels[i];
> - lpg_lut_free(lpg, chan->pattern_lo_idx, chan->pattern_hi_idx);
> lpg_sdam_configure_triggers(chan, 0);
> lpg_clear_pbs_trigger(chan->lpg, chan->lut_mask);
> - chan->pattern_lo_idx = 0;
> - chan->pattern_hi_idx = 0;
> }
>
> mutex_unlock(&lpg->lock);
prev parent reply other threads:[~2026-09-08 1:15 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-17 4:41 [PATCH v6] leds: rgb: leds-qcom-lpg: Fix LED color balancing in HW pattern mode Fenglin Wu
2026-07-17 4:55 ` sashiko-bot
2026-08-25 4:44 ` Fenglin Wu
2026-08-27 13:37 ` Lee Jones
2026-09-03 11:27 ` Konrad Dybcio
2026-09-08 1:14 ` Fenglin Wu [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ec3caf91-ac62-4d2b-8a70-f369a0c64e62@oss.qualcomm.com \
--to=fenglin.wu@oss.qualcomm.com \
--cc=andersson@kernel.org \
--cc=david.collins@oss.qualcomm.com \
--cc=justinstitt@google.com \
--cc=kamal.wadhwa@oss.qualcomm.com \
--cc=kernel@oss.qualcomm.com \
--cc=konrad.dybcio@oss.qualcomm.com \
--cc=lee@kernel.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-leds@vger.kernel.org \
--cc=linux@gurudas.dev \
--cc=llvm@lists.linux.dev \
--cc=marijn.suijten@somainline.org \
--cc=morbo@google.com \
--cc=nathan@kernel.org \
--cc=nick.desaulniers+lkml@gmail.com \
--cc=pavel@kernel.org \
--cc=pavel@ucw.cz \
--cc=quic_amelende@quicinc.com \
--cc=subbaraman.narayanamurthy@oss.qualcomm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox