Re: [PATCH v3 07/10] iio: frequency: ad9910: support drctl control

From: Andy Shevchenko

Date: Tue Nov 03 2026 - 12:11:31 EST


On Tue, Nov 03, 2026 at 11:53:03AM -0300, Rodrigo Alencar via B4 Relay wrote:
>
> The DRCTL pin controls the slope direction of the AD9910 digital ramp
> generator (DRG). When dwell is enabled at a ramp limit, the DRG holds
> that limit until the next DRCTL transition, so the sweep pattern is
> defined by the waveform applied to that pin, which can be generated by
> a PWM.
>
> Get the optional "drctl" PWM and expose the integration_time attribute
> in the DRG ramp up and ramp down channels, which sets the time interval
> assigned to each ramp direction while the sweep parameter is accumulating.
>
> The DRCTL waveform is described with the PWM waveform API, using the duty
> offset when DRCTL needs to start low. The PWM is disabled when the
> resulting period is zero. The waveform is rounded by the PWM provider
> before being applied, so that integration_time reports the intervals
> achieved by it. Writing to integration_time fails with -EOPNOTSUPP when
> no DRCTL PWM is available. As the waveform API has no stubs, the driver
> now depends on PWM.

...

> + if (!ndh && ndl) {
> + /* DRCTL low on the first half, so that it ramps down first */
> + wf.period_length_ns = st->ramp_down_time_ns;
> + wf.duty_offset_ns = st->ramp_down_time_ns / 2;
> + wf.duty_length_ns = wf.period_length_ns - wf.duty_offset_ns;
> + } else if (ndh && !ndl) {
> + wf.period_length_ns = st->ramp_up_time_ns;
> + wf.duty_length_ns = st->ramp_up_time_ns / 2;
> + } else if (!ndh && !ndl) {
> + wf.period_length_ns = st->ramp_up_time_ns + st->ramp_down_time_ns;
> + wf.duty_length_ns = st->ramp_up_time_ns;
> + } else {
> + wf.period_length_ns = st->ramp_up_time_ns + st->ramp_down_time_ns;
> + }
> +
> + /* a zero period disables the PWM, nothing to round */
> + if (wf.period_length_ns) {
> + ret = pwm_round_waveform_might_sleep(st->drctl_pwm, &wf);
> + if (ret < 0)
> + return ret;
> + }
> +
> + ret = pwm_set_waveform_might_sleep(st->drctl_pwm, &wf, false);
> + if (ret)
> + return ret;
> +
> + if (!ndh && ndl) {
> + st->ramp_down_time_ns = wf.period_length_ns;
> + } else if (ndh && !ndl) {
> + st->ramp_up_time_ns = wf.period_length_ns;
> + } else if (!ndh && !ndl) {
> + st->ramp_up_time_ns = wf.duty_length_ns;
> + st->ramp_down_time_ns = wf.period_length_ns - wf.duty_length_ns;
> + }

This and above if-else-if chain can be simplified

if (!ndh && !ndl) {
st->ramp_up_time_ns = wf.duty_length_ns;
st->ramp_down_time_ns = wf.period_length_ns - wf.duty_length_ns;
} else if (!ndh) {
st->ramp_down_time_ns = wf.period_length_ns;
} else if (!ndl) {
st->ramp_up_time_ns = wf.period_length_ns;
} else { // for the above case
... //
}

Or with inverted logic.

--
With Best Regards,
Andy Shevchenko