[PATCH] backlight: pwm_bl: apply the initial backlight state with sane defaults

Michael Grzeschik posted 1 patch 2 months ago
drivers/video/backlight/pwm_bl.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
[PATCH] backlight: pwm_bl: apply the initial backlight state with sane defaults
Posted by Michael Grzeschik 2 months ago
Currently when calling pwm_apply_might_sleep in the probe routine
the pwm will be configured with an not fully defined state.

The duty_cycle is not yet set in that moment. There is a final
backlight_update_status call that will have a properly setup state.
However this change in the backlight can create a short flicker if the
backlight was already preinitialised.

We fix the flicker by moving the pwm_apply after the default duty_cycle
can be calculated.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
---
 drivers/video/backlight/pwm_bl.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 237d3d3f3bb1a..5924e0b9f01e7 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -518,13 +518,6 @@ static int pwm_backlight_probe(struct platform_device *pdev)
 	if (!state.period && (data->pwm_period_ns > 0))
 		state.period = data->pwm_period_ns;
 
-	ret = pwm_apply_might_sleep(pb->pwm, &state);
-	if (ret) {
-		dev_err_probe(&pdev->dev, ret,
-			      "failed to apply initial PWM state");
-		goto err_alloc;
-	}
-
 	memset(&props, 0, sizeof(struct backlight_properties));
 
 	if (data->levels) {
@@ -582,6 +575,15 @@ static int pwm_backlight_probe(struct platform_device *pdev)
 	pb->lth_brightness = data->lth_brightness * (div_u64(state.period,
 				pb->scale));
 
+	state.duty_cycle = compute_duty_cycle(pb, data->dft_brightness, &state);
+
+	ret = pwm_apply_might_sleep(pb->pwm, &state);
+	if (ret) {
+		dev_err_probe(&pdev->dev, ret,
+			      "failed to apply initial PWM state");
+		goto err_alloc;
+	}
+
 	props.type = BACKLIGHT_RAW;
 	props.max_brightness = data->max_brightness;
 	bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,

---
base-commit: 739a6c93cc755c0daf3a7e57e018a8c61047cd90
change-id: 20250731-blpwm-598ecad93c4d

Best regards,
-- 
Michael Grzeschik <m.grzeschik@pengutronix.de>
Re: [PATCH] backlight: pwm_bl: apply the initial backlight state with sane defaults
Posted by Uwe Kleine-König 2 months ago
Hallo Michael,

On Thu, Jul 31, 2025 at 10:47:18AM +0200, Michael Grzeschik wrote:
> diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
> index 237d3d3f3bb1a..5924e0b9f01e7 100644
> --- a/drivers/video/backlight/pwm_bl.c
> +++ b/drivers/video/backlight/pwm_bl.c
> @@ -518,13 +518,6 @@ static int pwm_backlight_probe(struct platform_device *pdev)
>  	if (!state.period && (data->pwm_period_ns > 0))
>  		state.period = data->pwm_period_ns;
>  
> -	ret = pwm_apply_might_sleep(pb->pwm, &state);
> -	if (ret) {
> -		dev_err_probe(&pdev->dev, ret,
> -			      "failed to apply initial PWM state");
> -		goto err_alloc;
> -	}
> -
>  	memset(&props, 0, sizeof(struct backlight_properties));
>  
>  	if (data->levels) {
> @@ -582,6 +575,15 @@ static int pwm_backlight_probe(struct platform_device *pdev)
>  	pb->lth_brightness = data->lth_brightness * (div_u64(state.period,
>  				pb->scale));
>  
> +	state.duty_cycle = compute_duty_cycle(pb, data->dft_brightness, &state);
> +
> +	ret = pwm_apply_might_sleep(pb->pwm, &state);
> +	if (ret) {
> +		dev_err_probe(&pdev->dev, ret,
> +			      "failed to apply initial PWM state");
> +		goto err_alloc;
> +	}
> +

I wonder why the PWM is updated at all in .probe(). Wouldn't it be the
natural thing to keep the PWM configured as it was (in its reset default
state or how the bootloader set it up)?

Orthogonal to your change, while looking at the driver I wondered about:

        bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,
                                       &pwm_backlight_ops, &props);
        if (IS_ERR(bl)) {
                ret = dev_err_probe(&pdev->dev, PTR_ERR(bl),
                                    "failed to register backlight\n");
                goto err_alloc;
        }

        if (data->dft_brightness > data->max_brightness) {
                dev_warn(&pdev->dev,
                         "invalid default brightness level: %u, using %u\n",
                         data->dft_brightness, data->max_brightness);
                data->dft_brightness = data->max_brightness;
        }

        bl->props.brightness = data->dft_brightness;
        bl->props.power = pwm_backlight_initial_power_state(pb);
        backlight_update_status(bl);

Shoudn't setting data->dft_brightness, bl->props.brightness and
bl->props.power better happen before backlight_device_register()? Also
calling backlight_update_status() after backlight_device_register()
seems wrong to me, I'd claim the backend driver shouldn't call that.

Best regards
Uwe
Re: [PATCH] backlight: pwm_bl: apply the initial backlight state with sane defaults
Posted by Uwe Kleine-König 3 weeks, 5 days ago
Hello Michael,

On Fri, Aug 01, 2025 at 08:32:20AM +0200, Uwe Kleine-König wrote:
> Hallo Michael,
> 
> On Thu, Jul 31, 2025 at 10:47:18AM +0200, Michael Grzeschik wrote:
> > diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
> > index 237d3d3f3bb1a..5924e0b9f01e7 100644
> > --- a/drivers/video/backlight/pwm_bl.c
> > +++ b/drivers/video/backlight/pwm_bl.c
> > @@ -518,13 +518,6 @@ static int pwm_backlight_probe(struct platform_device *pdev)
> >  	if (!state.period && (data->pwm_period_ns > 0))
> >  		state.period = data->pwm_period_ns;
> >  
> > -	ret = pwm_apply_might_sleep(pb->pwm, &state);
> > -	if (ret) {
> > -		dev_err_probe(&pdev->dev, ret,
> > -			      "failed to apply initial PWM state");
> > -		goto err_alloc;
> > -	}
> > -
> >  	memset(&props, 0, sizeof(struct backlight_properties));
> >  
> >  	if (data->levels) {
> > @@ -582,6 +575,15 @@ static int pwm_backlight_probe(struct platform_device *pdev)
> >  	pb->lth_brightness = data->lth_brightness * (div_u64(state.period,
> >  				pb->scale));
> >  
> > +	state.duty_cycle = compute_duty_cycle(pb, data->dft_brightness, &state);
> > +
> > +	ret = pwm_apply_might_sleep(pb->pwm, &state);
> > +	if (ret) {
> > +		dev_err_probe(&pdev->dev, ret,
> > +			      "failed to apply initial PWM state");
> > +		goto err_alloc;
> > +	}
> > +
> 
> I wonder why the PWM is updated at all in .probe(). Wouldn't it be the
> natural thing to keep the PWM configured as it was (in its reset default
> state or how the bootloader set it up)?
> 
> Orthogonal to your change, while looking at the driver I wondered about:
> 
>         bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,
>                                        &pwm_backlight_ops, &props);
>         if (IS_ERR(bl)) {
>                 ret = dev_err_probe(&pdev->dev, PTR_ERR(bl),
>                                     "failed to register backlight\n");
>                 goto err_alloc;
>         }
> 
>         if (data->dft_brightness > data->max_brightness) {
>                 dev_warn(&pdev->dev,
>                          "invalid default brightness level: %u, using %u\n",
>                          data->dft_brightness, data->max_brightness);
>                 data->dft_brightness = data->max_brightness;
>         }
> 
>         bl->props.brightness = data->dft_brightness;
>         bl->props.power = pwm_backlight_initial_power_state(pb);
>         backlight_update_status(bl);
> 
> Shoudn't setting data->dft_brightness, bl->props.brightness and
> bl->props.power better happen before backlight_device_register()? Also
> calling backlight_update_status() after backlight_device_register()
> seems wrong to me, I'd claim the backend driver shouldn't call that.

Do you intend to work on this orthogonal feedback? If not, I'll put it
on my todo list.

Best regards
Uwe
Re: [PATCH] backlight: pwm_bl: apply the initial backlight state with sane defaults
Posted by Michael Grzeschik 3 weeks, 4 days ago
Hi Uwe

On Tue, Sep 09, 2025 at 03:49:22PM +0200, Uwe Kleine-König wrote:
>On Fri, Aug 01, 2025 at 08:32:20AM +0200, Uwe Kleine-König wrote:
>> On Thu, Jul 31, 2025 at 10:47:18AM +0200, Michael Grzeschik wrote:
>> > diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
>> > index 237d3d3f3bb1a..5924e0b9f01e7 100644
>> > --- a/drivers/video/backlight/pwm_bl.c
>> > +++ b/drivers/video/backlight/pwm_bl.c
>> > @@ -518,13 +518,6 @@ static int pwm_backlight_probe(struct platform_device *pdev)
>> >  	if (!state.period && (data->pwm_period_ns > 0))
>> >  		state.period = data->pwm_period_ns;
>> >
>> > -	ret = pwm_apply_might_sleep(pb->pwm, &state);
>> > -	if (ret) {
>> > -		dev_err_probe(&pdev->dev, ret,
>> > -			      "failed to apply initial PWM state");
>> > -		goto err_alloc;
>> > -	}
>> > -
>> >  	memset(&props, 0, sizeof(struct backlight_properties));
>> >
>> >  	if (data->levels) {
>> > @@ -582,6 +575,15 @@ static int pwm_backlight_probe(struct platform_device *pdev)
>> >  	pb->lth_brightness = data->lth_brightness * (div_u64(state.period,
>> >  				pb->scale));
>> >
>> > +	state.duty_cycle = compute_duty_cycle(pb, data->dft_brightness, &state);
>> > +
>> > +	ret = pwm_apply_might_sleep(pb->pwm, &state);
>> > +	if (ret) {
>> > +		dev_err_probe(&pdev->dev, ret,
>> > +			      "failed to apply initial PWM state");
>> > +		goto err_alloc;
>> > +	}
>> > +
>>
>> I wonder why the PWM is updated at all in .probe(). Wouldn't it be the
>> natural thing to keep the PWM configured as it was (in its reset default
>> state or how the bootloader set it up)?
>>
>> Orthogonal to your change, while looking at the driver I wondered about:
>>
>>         bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,
>>                                        &pwm_backlight_ops, &props);
>>         if (IS_ERR(bl)) {
>>                 ret = dev_err_probe(&pdev->dev, PTR_ERR(bl),
>>                                     "failed to register backlight\n");
>>                 goto err_alloc;
>>         }
>>
>>         if (data->dft_brightness > data->max_brightness) {
>>                 dev_warn(&pdev->dev,
>>                          "invalid default brightness level: %u, using %u\n",
>>                          data->dft_brightness, data->max_brightness);
>>                 data->dft_brightness = data->max_brightness;
>>         }
>>
>>         bl->props.brightness = data->dft_brightness;
>>         bl->props.power = pwm_backlight_initial_power_state(pb);
>>         backlight_update_status(bl);
>>
>> Shoudn't setting data->dft_brightness, bl->props.brightness and
>> bl->props.power better happen before backlight_device_register()? Also
>> calling backlight_update_status() after backlight_device_register()
>> seems wrong to me, I'd claim the backend driver shouldn't call that.
>
>Do you intend to work on this orthogonal feedback? If not, I'll put it
>on my todo list.

Oh, yes, the orthogonal feedback. Thanks for the reminder of this
actually intended patch not being ready. I will work on this first. If you
like, please take the opurtunity to fix the issue you found.

Regards,
Michael

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |