Re: [PATCH RFC] backlight: pwm_bl: Read back PWM period from provider

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Abel,

On Thu, Feb 27, 2025 at 03:07:21PM +0200, Abel Vesa wrote:
> On 25-02-26 17:34:50, Uwe Kleine-König wrote:
> > On Wed, Feb 26, 2025 at 05:31:08PM +0200, Abel Vesa wrote:
> > > The current implementation assumes that the PWM provider will be able to
> > > meet the requested period, but that is not always the case. Some PWM
> > > providers have limited HW configuration capabilities and can only
> > > provide a period that is somewhat close to the requested one. This
> > > simply means that the duty cycle requested might either be above the
> > > PWM's maximum value or the 100% duty cycle is never reached.
> > 
> > If you request a state with 100% relative duty cycle you should get 100%
> > unless the hardware cannot do that. Which PWM hardware are you using?
> > Which requests are you actually doing that don't match your expectation?
> 
> The PWM hardware is Qualcomm PMK8550 PMIC. The way the duty cycle is
> controlled is described in the following comment found in lpg_calc_freq
> of the leds-qcom-lpg driver:
> 
> /*
>  * The PWM period is determined by:
>  *
>  *          resolution * pre_div * 2^M
>  * period = --------------------------
>  *                   refclk
>  *
>  * Resolution = 2^9 bits for PWM or
>  *              2^{8, 9, 10, 11, 12, 13, 14, 15} bits for high resolution PWM
>  * pre_div = {1, 3, 5, 6} and
>  * M = [0..7].
>  *
>  * This allows for periods between 27uS and 384s for PWM channels and periods between
>  * 3uS and 24576s for high resolution PWMs.
>  * The PWM framework wants a period of equal or lower length than requested,
>  * reject anything below minimum period.
>  */
> 
> So if we request a period of 5MHz, that will not ever be reached no matter what config
> is used. Instead, the 4.26 MHz is selected as closest possible.

The trace in the other mail thread suggest that you asked for a period
of 5 ms, not 5 MHz. And that results in a period of 4.26 ms.

> Now, the pwm_bl is not aware of this limitation and will request duty cycle values that
> go above 4.26MHz.

It requests .period = 5 ms + .duty_cycle = 5 ms. This is fine, and
according to the trace this results in both values becoming 4.26 ms in
real life. Seems fine to me.

> > > This could be easily fixed if the pwm_apply*() API family would allow
> > > overriding the period within the PWM state that's used for providing the
> > > duty cycle. But that is currently not the case.
> > 
> > I don't understand what you mean here.
> 
> What I was trying to say is that the PWM generic framework currently doesn't
> allow overriding the PWM state's period with one provided by the consumer,
> when calling pwm_apply_might_sleep().

Either I still don't understand what you want, or that is impossible or
useless. If you target .period = 5 ms and the hardware can only do 4.26
ms, why would you want to override period to 5 ms?

> Also, the pwm_get_state_hw() doesn't cache the state either.

*shrug*.

> This results in always having to call pwm_get_state_hw() before calling
> pwm_apply_might_sleep().

I cannot follow this conclusion. At least one of us two didn't
understand some detail yet.

> On top of that, pwm_get_state_hw() doesn't default to the cached value if the
> provider doesn't implement the ->get_state() op.

If it did that, the consumer wouldn't know if the request was
implemented exactly or if there is no way to read back the actual
configuration.

> Please correct me if I'm wrong about these.
> 
> > 
> > > So easiest fix here is to read back the period from the PWM provider via
> > > the provider's ->get_state() op, if implemented, which should provide the
> > > best matched period. Do this on probe after the first ->pwm_apply() op has
> > > been done, which will allow the provider to determine the best match
> > > period based on available configuration knobs. From there on, the
> > > backlight will use the best matched period, since the driver's internal
> > > PWM state is now synced up with the one from provider.
> > > [...]
> > > diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
> > > index 237d3d3f3bb1a6d713c5f6ec3198af772bf1268c..71a3e9cd8844095e85c01b194d7466978f1ca78e 100644
> > > --- a/drivers/video/backlight/pwm_bl.c
> > > +++ b/drivers/video/backlight/pwm_bl.c
> > > @@ -525,6 +525,17 @@ static int pwm_backlight_probe(struct platform_device *pdev)
> > >  		goto err_alloc;
> > >  	}
> > >  
> > > +	/*
> > > +	 * The actual period might differ from the requested one due to HW
> > > +	 * limitations, so sync up the period with one determined by the
> > > +	 * provider driver.
> > > +	 */
> > > +	ret = pwm_get_state_hw(pb->pwm, &pb->pwm->state);
> > 
> > As a consumer you're not supposed to write to &pb->pwm->state. That's a
> > layer violation. Please call pwm_get_state_hw() with a struct pwm_state
> > that you own and save the relevant parts in your driver data.
> 
> Yep, that is indeed wrong. Maybe making the pwm opaque might be a good idea as well.
> 
> [1] Calling pwm_get_state_hw() would be wrong if the provider doesn't implement the ->get_state(),
> as I mentioned above.
> 
> But are you suggesting we replace all calls to pwm_get_state() with
> pwm_get_state_hw() in pwm_bl?

No, I still didn't understand the problem you want to fix here. So I'm
not suggesting anything yet.
 
Best regards
Uwe

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [Linux for Sparc]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux