Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

backlight: pwm_bl: Don't rely on a disabled PWM emiting inactive state

Most but not all PWMs drive the PWM pin to its inactive state when
disabled. However if there is no enable_gpio and no regulator the PWM
must drive the inactive state to actually disable the backlight.

So keep the PWM on in this case.

Note that to determine if there is a regulator some effort is required
because it might happen that there isn't actually one but the regulator
core gave us a dummy. (A nice side effect is that this makes the
regulator actually optional even on fully constrained systems.)

This fixes backlight disabling e.g. on i.MX6 when an inverted PWM is
used.

Hint for the future: If this change results in a regression, the bug is
in the lowlevel PWM driver.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Reviewed-by: Daniel Thompson <daniel.thompson@linaro.org>
Signed-off-by: Lee Jones <lee@kernel.org>
Link: https://lore.kernel.org/r/20230120120018.161103-3-u.kleine-koenig@pengutronix.de

authored by

Uwe Kleine-König and committed by
Lee Jones
deaeeda2 00e7e698

+22 -8
+22 -8
drivers/video/backlight/pwm_bl.c
··· 45 45 if (pb->enabled) 46 46 return; 47 47 48 - err = regulator_enable(pb->power_supply); 49 - if (err < 0) 50 - dev_err(pb->dev, "failed to enable power supply\n"); 48 + if (pb->power_supply) { 49 + err = regulator_enable(pb->power_supply); 50 + if (err < 0) 51 + dev_err(pb->dev, "failed to enable power supply\n"); 52 + } 51 53 52 54 if (pb->post_pwm_on_delay) 53 55 msleep(pb->post_pwm_on_delay); ··· 71 69 if (pb->pwm_off_delay) 72 70 msleep(pb->pwm_off_delay); 73 71 74 - regulator_disable(pb->power_supply); 72 + if (pb->power_supply) 73 + regulator_disable(pb->power_supply); 75 74 pb->enabled = false; 76 75 } 77 76 ··· 112 109 pwm_backlight_power_off(pb); 113 110 114 111 pwm_get_state(pb->pwm, &state); 115 - state.enabled = false; 116 112 state.duty_cycle = 0; 113 + /* 114 + * We cannot assume a disabled PWM to drive its output to the 115 + * inactive state. If we have an enable GPIO and/or a regulator 116 + * we assume that this isn't relevant and we can disable the PWM 117 + * to save power. If however there is neither an enable GPIO nor 118 + * a regulator keep the PWM on be sure to get a constant 119 + * inactive output. 120 + */ 121 + state.enabled = !pb->power_supply && !pb->enable_gpio; 117 122 pwm_apply_state(pb->pwm, &state); 118 123 } 119 124 ··· 419 408 if (pb->enable_gpio && gpiod_get_value_cansleep(pb->enable_gpio) == 0) 420 409 active = false; 421 410 422 - if (!regulator_is_enabled(pb->power_supply)) 411 + if (pb->power_supply && !regulator_is_enabled(pb->power_supply)) 423 412 active = false; 424 413 425 414 if (!pwm_is_enabled(pb->pwm)) ··· 500 489 goto err_alloc; 501 490 } 502 491 503 - pb->power_supply = devm_regulator_get(&pdev->dev, "power"); 492 + pb->power_supply = devm_regulator_get_optional(&pdev->dev, "power"); 504 493 if (IS_ERR(pb->power_supply)) { 505 494 ret = PTR_ERR(pb->power_supply); 506 - goto err_alloc; 495 + if (ret == -ENODEV) 496 + pb->power_supply = NULL; 497 + else 498 + goto err_alloc; 507 499 } 508 500 509 501 pb->pwm = devm_pwm_get(&pdev->dev, NULL);