On Thu, Apr 06, 2023 at 04:30:23PM +0200, Thierry Reding wrote: > On Thu, Apr 06, 2023 at 03:53:58PM +0200, Uwe Kleine-König wrote: > > Hello Thierry, > > > > On Thu, Apr 06, 2023 at 03:38:48PM +0200, Thierry Reding wrote: > > > On Thu, Mar 09, 2023 at 02:04:10AM +0100, Lorenz Brun wrote: > > > > + * appear to have the capability to invert the output. > > > > + * This means that inverted mode can not be fully supported as the > > > > + * waveform will always start with the low period and end with the high > > > > + * period. Thus reject non-normal polarity if the shape of the waveform > > > > + * matters, i.e. usage_power is not set. > > > > + */ > > > > + if (state->polarity != PWM_POLARITY_NORMAL && !state->usage_power) > > > > return -EINVAL; > > > > > > > > if (!state->enabled) { > > > > @@ -213,7 +221,11 @@ static int pwm_mediatek_apply(struct pwm_chip *chip, struct pwm_device *pwm, > > > > return 0; > > > > } > > > > > > > > - err = pwm_mediatek_config(pwm->chip, pwm, state->duty_cycle, state->period); > > > > + duty_cycle = state->duty_cycle; > > > > + if (state->polarity == PWM_POLARITY_INVERSED) > > > > + duty_cycle = state->period - state->duty_cycle; > > > > > > That's not really what state->usage_power was meant to address. > > > > I don't understand your concern here. I don't like .usage_power, but > > AFAICT this is a legitimite use. With .usage_power = true, the lowlevel > > driver is free to shift the phase_offset and even modify the period size > > and the goal is just that the average power-output matches. > > > > Lorenz's patch does exactly this: It even keeps the period and only > > shifts the phase (by period - duty_cycle). If you consider this not > > legitmate, I think we have to improve the docs about .usage_power. > > I realize that I'm being nitpicky here. Setting usage_power = true and > duty = period - duty is a lazy way of achieving what you can easily do > by adjusting the input duty cycle. > > If you all really want this, then it should go into the core, because > it's something that can be implemented on basically every single PWM > controller. You'd need something like: diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index e01147f66e15..6bb851c2e55e 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -556,6 +556,7 @@ static void pwm_apply_state_debug(struct pwm_device *pwm, int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state) { struct pwm_chip *chip; + bool retry_inverted = true; int err; /* @@ -580,10 +581,19 @@ int pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state) state->usage_power == pwm->state.usage_power) return 0; +retry: err = chip->ops->apply(chip, pwm, state); trace_pwm_apply(pwm, state, err); - if (err) + if (err) { + if (err == -EINVAL && state->usage_power && retry_inverted) { + state->duty_cycle = state->period - state->duty_cycle; + state->polarity = 1 - state->polarity; + retry_inverted = false; + goto retry; + } + return err; + } pwm->state = *state; (Just to show the idea. It doesn't work like that, because *state is const.) I don't like that .apply() is called twice and without having thought much about it, I'd prefer explicit support in the lowlevel drivers over this approach. Best regards Uwe -- Pengutronix e.K. | Uwe Kleine-König | Industrial Linux Solutions | https://www.pengutronix.de/ |