Re: [PATCH v6 4/7] pwm: pca9685: Support staggered output ON times

From: Thierry Reding
Date: Wed Mar 31 2021 - 12:22:03 EST


On Wed, Mar 31, 2021 at 02:26:14PM +0200, Clemens Gruber wrote:
> On Mon, Mar 29, 2021 at 08:02:06PM +0200, Uwe Kleine-König wrote:
> > On Mon, Mar 29, 2021 at 07:16:38PM +0200, Clemens Gruber wrote:
> > > On Mon, Mar 29, 2021 at 07:03:57PM +0200, Uwe Kleine-König wrote:
> > > > On Mon, Mar 29, 2021 at 02:57:04PM +0200, Clemens Gruber wrote:
> > > > > The PCA9685 supports staggered LED output ON times to minimize current
> > > > > surges and reduce EMI.
> > > > > When this new option is enabled, the ON times of each channel are
> > > > > delayed by channel number x counter range / 16, which avoids asserting
> > > > > all enabled outputs at the same counter value while still maintaining
> > > > > the configured duty cycle of each output.
> > > > >
> > > > > Signed-off-by: Clemens Gruber <clemens.gruber@xxxxxxxxxxxx>
> > > >
> > > > Is there a reason to not want this staggered output? If it never hurts I
> > > > suggest to always stagger and drop the dt property.
> > >
> > > There might be applications where you want multiple outputs to assert at
> > > the same time / to be synchronized.
> > > With staggered outputs mode always enabled, this would no longer be
> > > possible as they are spread out according to their channel number.
> > >
> > > Not sure how often that usecase is required, but just enforcing the
> > > staggered mode by default sounds risky to me.
> >
> > There is no such guarantee in the PWM framework, so I don't think we
> > need to fear breaking setups. Thierry?
>
> Still, someone might rely on it? But let's wait for Thierry's opinion.

There's currently no way to synchronize two PWM channels in the PWM
framework. And given that each PWM channel is handled separately the
programming for two channels will never happen atomically or even
concurrently, so I don't see how you could run two PWMs completely
synchronized to one another.

That said, it might be possible to implement something like this by
coupling two or more PWMs. However, I think we will only ever be able to
do this on a per-chip basis, because that's the only way we could
guarantee that multiple PWMs can be programmed at the same time, or that
they get enabled with the same write. Of course this all requires that
the chip even supports that. Even if you enable two PWM channels within
the same driver but with two consecutive register writes they will not
be guaranteed to run synchronously. There'd have to be some special chip
support to allow this to work.

However, I'm a bit hesitant about this staggering output mode. From what
I understand what's going to happen for these is basically that overall
each PWM will be running at the requested duty cycle, but the on/off
times will be evenly spread out over the whole period. In other words,
the output *power* of the PWM signal will be the same as if the signal
was a single on/off cycle. That's not technically a PWM signal as the
PWM framework defines it. See the kerneldoc for enum pwm_polarity for
what signals are expected to look like.

So I agree that this is not something that should be enabled by default
because if you've got a consumer that expects exactly one rising edge
and one falling edge per period, they will get confused if you toggle
multiple times during one period.

If that's the case,you probably want to configure this on a per-PWM
basis rather than for the entire chip because otherwise you could end up
in a scenario where one PWM does *not* work with staggered output and
the others do. I guess you could always make that decision up front, but
do you always know what people may end up using these PWMs for? What if
you have a board that breaks out one PWM on some general purpose pin
header and people end up using it via sysfs. They would need have to
recompile the DTB for the device if they wanted to enable or disable
this staggered mode.

Or did I misunderstand and it's only the start time of the rising edge
that's shifted, but the signal will remain high for a full duty cycle
after that and then go down and remain low for period - duty - offset?

That's slightly better than the above in that it likely won't trip up
any consumers. But it might still be worth to make this configurable per
PWM (perhaps by specifying a third specifier cell, in addition to the
period and flags, that defines the offset/phase of the signal).

In both cases, doing this on a per-PWM basis will allow the consumer to
specify that they're okay with staggered mode and you won't actually
force it onto anyone. This effectively makes this opt-in and there will
be no change for existing consumers.

> > One reason we might not want staggering is if we have a consumer who
> > cares about config transitions. (This however is moot it the hardware
> > doesn't provide sane transitions even without staggering.)
> >
> > Did I already ask about races in this driver? I assume there is a
> > free running counter and the ON and OFF registers just define where in
> > the period the transitions happen, right? Given that changing ON and OFF
> > needs two register writes probably all kind of strange things can
> > happen, right? (Example thought: for simplicity's sake I assume ON is
> > always 0. Then if you want to change from OFF = 0xaaa to OFF = 0xccc we
> > might see a period with 0xacc. Depending on how the hardware works we
> > might even see 4 edges in a single period then.)
>
> Yes, there is a free running counter from 0 to 4095.
> And it is probably true, that there can be short intermediate states
> with our two register writes.
>
> There is a separate mode "Update on ACK" (MODE2 register, bit 3 "OCH"),
> which is 0 by default (Outputs change on STOP command) but could be set
> to 1 (Outputs change on ACK):
> "Update on ACK requires all 4 PWM channel registers to be loaded before
> outputs will change on the last ACK."

This sounds like it would allow atomic updates of the PWM settings.
That's probably something that you want to implement to avoid any
glitches.

> The chip datasheet also states:
> "Because the loading of the LEDn_ON and LEDn_OFF registers is via the
> I2C-bus, and asynchronous to the internal oscillator, we want to ensure
> that we do not see any visual artifacts of changing the ON and OFF
> values. This is achieved by updating the changes at the end of the LOW
> cycle."
>
> We could look into this in a future patch series, however I would like
> to keep the register updating as-is for this series (otherwise I would
> have to do all the tests with the oscilloscope again and the transitions
> were like this since the driver was first implemented).

Yeah, it sounds fine to implement this at a later point in time. No need
to conflate it with the current series.

Thierry

Attachment: signature.asc
Description: PGP signature