6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abel Vesa abel.vesa@linaro.org
commit 2528eec7da0ec58fcae6d12cfa79a622c933d86b upstream.
When determining the actual best period by looping through all possible PWM configs, the resolution currently used is based on bit shift value which is off-by-one above the possible maximum PWM value allowed.
So subtract one from the resolution before determining the best period so that the maximum duty cycle requested by the PWM user won't result in a value above the maximum allowed by the selected resolution.
Cc: stable@vger.kernel.org # 6.4 Fixes: b00d2ed37617 ("leds: rgb: leds-qcom-lpg: Add support for high resolution PWM") Signed-off-by: Abel Vesa abel.vesa@linaro.org Reviewed-by: Sebastian Reichel sre@kernel.org Link: https://lore.kernel.org/r/20250305-leds-qcom-lpg-fix-max-pwm-on-hi-res-v4-3-... Signed-off-by: Lee Jones lee@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- drivers/leds/rgb/leds-qcom-lpg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/leds/rgb/leds-qcom-lpg.c +++ b/drivers/leds/rgb/leds-qcom-lpg.c @@ -461,7 +461,7 @@ static int lpg_calc_freq(struct lpg_chan max_res = LPG_RESOLUTION_9BIT; }
- min_period = div64_u64((u64)NSEC_PER_SEC * (1 << pwm_resolution_arr[0]), + min_period = div64_u64((u64)NSEC_PER_SEC * ((1 << pwm_resolution_arr[0]) - 1), clk_rate_arr[clk_len - 1]); if (period <= min_period) return -EINVAL; @@ -482,7 +482,7 @@ static int lpg_calc_freq(struct lpg_chan */
for (i = 0; i < pwm_resolution_count; i++) { - resolution = 1 << pwm_resolution_arr[i]; + resolution = (1 << pwm_resolution_arr[i]) - 1; for (clk_sel = 1; clk_sel < clk_len; clk_sel++) { u64 numerator = period * clk_rate_arr[clk_sel];
@@ -1291,7 +1291,7 @@ static int lpg_pwm_get_state(struct pwm_ if (ret) return ret;
- state->period = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * (1 << resolution) * + state->period = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * ((1 << resolution) - 1) * pre_div * (1 << m), refclk); state->duty_cycle = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC * pwm_value * pre_div * (1 << m), refclk); } else {