All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Nuno Sá" <noname.nuno@gmail.com>
To: Jonathan Cameron <jic23@kernel.org>,
	Nuno Sa via B4 Relay <devnull+nuno.sa.analog.com@kernel.org>
Cc: nuno.sa@analog.com, linux-iio@vger.kernel.org,
	devicetree@vger.kernel.org,
	 Dragos Bogdan <dragos.bogdan@analog.com>,
	Lars-Peter Clausen <lars@metafoo.de>,
	Michael Hennerich <Michael.Hennerich@analog.com>,
	Rob Herring <robh@kernel.org>,
	Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
	Conor Dooley <conor+dt@kernel.org>,
	Olivier Moysan <olivier.moysan@foss.st.com>
Subject: Re: [PATCH 09/10] iio: dac: add support for AXI DAC IP core
Date: Thu, 28 Mar 2024 17:43:43 +0100	[thread overview]
Message-ID: <d86dbdd7c1f234ebedc08c3433735f43abff7f7e.camel@gmail.com> (raw)
In-Reply-To: <20240328153542.7ddb897c@jic23-huawei>

On Thu, 2024-03-28 at 15:35 +0000, Jonathan Cameron wrote:
> On Thu, 28 Mar 2024 14:22:33 +0100
> Nuno Sa via B4 Relay <devnull+nuno.sa.analog.com@kernel.org> wrote:
> 
> > From: Nuno Sa <nuno.sa@analog.com>
> > 
> > Support the Analog Devices Generic AXI DAC IP core. The IP core is used
> > for interfacing with digital-to-analog (DAC) converters that require either
> > a high-speed serial interface (JESD204B/C) or a source synchronous parallel
> > interface (LVDS/CMOS). Typically (for such devices) SPI will be used for
> > configuration only, while this IP core handles the streaming of data into
> > memory via DMA.
> > 
> > Signed-off-by: Nuno Sa <nuno.sa@analog.com>
> 
> 
> A few minor things inline, but mostly seems fine to me.
> 
> Jonathan
> 
> 
> ...
> 
> > diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c
> > new file mode 100644
> > index 000000000000..0022ecb4e4bb
> > --- /dev/null
> > +++ b/drivers/iio/dac/adi-axi-dac.c
> 
> 
> > +
> > +enum {
> > +	AXI_DAC_FREQ_TONE_1,
> > +	AXI_DAC_FREQ_TONE_2,
> > +	AXI_DAC_SCALE_TONE_1,
> > +	AXI_DAC_SCALE_TONE_2,
> > +	AXI_DAC_PHASE_TONE_1,
> > +	AXI_DAC_PHASE_TONE_2,
> > +};
> > +
> > +static int __axi_dac_frequency_get(struct axi_dac_state *st, unsigned int chan,
> > +				   unsigned int tone, unsigned int *freq)
> > +{
> > +	u32 reg, raw;
> > +	int ret;
> > +
> > +	if (!st->dac_clk) {
> > +		dev_err(st->dev, "Sampling rate is 0...\n");
> > +		return -EINVAL;
> > +	}
> > +
> > +	if (tone == AXI_DAC_FREQ_TONE_1)
> 
> Given this is matching 2 out of enum with other values, it would be more
> locally readable as a switch statement with an error returning default.
> Then we wouldn't need to look at the caller.
> 
> Or at the caller convert from the enum to 0,1 for all these functions.
> 

Ok, will see what of the alternatives looks better.

> 
> 
> > +		reg = AXI_DAC_REG_CHAN_CNTRL_2(chan);
> > +	else
> > +		reg = AXI_DAC_REG_CHAN_CNTRL_4(chan);
> > +
> > +	ret = regmap_read(st->regmap, reg, &raw);
> > +	if (ret)
> > +		return ret;
> > +
> > +	raw = FIELD_GET(AXI_DAC_FREQUENCY, raw);
> > +	*freq = DIV_ROUND_CLOSEST_ULL(raw * st->dac_clk, BIT(16));
> > +
> > +	return 0;
> > +}
> 
> ...
> 
> > +static int axi_dac_scale_set(struct axi_dac_state *st,
> > +			     const struct iio_chan_spec *chan,
> > +			     const char *buf, size_t len, unsigned int tone)
> > +{
> > +	int integer, frac, scale;
> > +	u32 raw = 0, reg;
> > +	int ret;
> > +
> > +	ret = iio_str_to_fixpoint(buf, 100000, &integer, &frac);
> > +	if (ret)
> > +		return ret;
> > +
> > +	scale = integer * MEGA + frac;
> > +	if (scale <= -2 * (int)MEGA || scale >= 2 * (int)MEGA)
> > +		return -EINVAL;
> > +
> > +	/*  format is 1.1.14 (sign, integer and fractional bits) */
> > +	if (scale < 0) {
> > +		raw = FIELD_PREP(AXI_DAC_SCALE_SIGN, 1);
> > +		scale *= -1;
> > +	}
> > +
> > +	raw |= div_u64((u64)scale * AXI_DAC_SCALE_INT, MEGA);
> > +
> > +	if (tone == AXI_DAC_SCALE_TONE_1)
> > +		reg = AXI_DAC_REG_CHAN_CNTRL_1(chan->channel);
> > +	else
> > +		reg = AXI_DAC_REG_CHAN_CNTRL_3(chan->channel);
> > +
> > +	guard(mutex)(&st->lock);
> > +	ret = regmap_write(st->regmap, reg, raw);
> > +	if (ret)
> > +		return ret;
> > +
> > +	/* synchronize channels */
> > +	ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_1, AXI_DAC_SYNC);
> > +	if (ret)
> > +		return ret;
> > +
> > +	return len;
> > +}
> > +
> > +static int axi_dac_phase_set(struct axi_dac_state *st,
> > +			     const struct iio_chan_spec *chan,
> > +			     const char *buf, size_t len, unsigned int tone)
> > +{
> > +	int integer, frac, phase;
> > +	u32 raw, reg;
> > +	int ret;
> > +
> > +	ret = iio_str_to_fixpoint(buf, 100000, &integer, &frac);
> 
> > +	if (ret)
> > +		return ret;
> > +
> > +	phase = integer * MEGA + frac;
> > +	if (phase < 0 || phase > AXI_DAC_2_PI_MEGA)
> > +		return -EINVAL;
> > +
> > +	raw = DIV_ROUND_CLOSEST_ULL((u64)phase * U16_MAX, AXI_DAC_2_PI_MEGA);
> > +
> > +	if (tone == AXI_DAC_PHASE_TONE_1)
> Preference for a switch so it's clear there are only 2 choices.
> > +		reg = AXI_DAC_REG_CHAN_CNTRL_2(chan->channel);
> > +	else
> > +		reg = AXI_DAC_REG_CHAN_CNTRL_4(chan->channel);
> > +
> > +	guard(mutex)(&st->lock);
> > +	ret = regmap_update_bits(st->regmap, reg, AXI_DAC_PHASE,
> > +				 FIELD_PREP(AXI_DAC_PHASE, raw));
> > +	if (ret)
> > +		return ret;
> > +
> > +	/* synchronize channels */
> > +	ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_1, AXI_DAC_SYNC);
> > +	if (ret)
> > +		return ret;
> > +
> > +	return len;
> > +}
> > +
> > +static int axi_dac_ext_info_set(struct iio_backend *back, uintptr_t private,
> > +				const struct iio_chan_spec *chan,
> > +				const char *buf, size_t len)
> > +{
> > +	struct axi_dac_state *st = iio_backend_get_priv(back);
> > +
> > +	switch (private) {
> > +	case AXI_DAC_FREQ_TONE_1:
> > +	case AXI_DAC_FREQ_TONE_2:
> 
> Same as the get path - convert to which tone here so that the enum becomes
> a tone index for the functions called and the mapping to that single enum
> is kept clear of the lower level code.
> 
> > +		return axi_dac_frequency_set(st, chan, buf, len, private);
> > +	case AXI_DAC_SCALE_TONE_1:
> > +	case AXI_DAC_SCALE_TONE_2:
> > +		return axi_dac_scale_set(st, chan, buf, len, private);
> > +	case AXI_DAC_PHASE_TONE_1:
> > +	case AXI_DAC_PHASE_TONE_2:
> > +		return axi_dac_phase_set(st, chan, buf, len, private);
> > +	default:
> > +		return -EOPNOTSUPP;
> > +	}
> > +}
> > +
> > +static int axi_dac_ext_info_get(struct iio_backend *back, uintptr_t private,
> > +				const struct iio_chan_spec *chan, char *buf)
> > +{
> > +	struct axi_dac_state *st = iio_backend_get_priv(back);
> > +
> > +	switch (private) {
> > +	case AXI_DAC_FREQ_TONE_1:
> > +	case AXI_DAC_FREQ_TONE_2:
> > +		return axi_dac_frequency_get(st, chan, buf, private);
> I'd break out private as an unsigned int here and then - AXI_DAC_FREQ_TONE_1
> so that it is just which tone for all the calls made from here.
> Similar for the following ones.
> 

ack..

> > +	case AXI_DAC_SCALE_TONE_1:
> > +	case AXI_DAC_SCALE_TONE_2:
> > +		return axi_dac_scale_get(st, chan, buf, private);
> > +	case AXI_DAC_PHASE_TONE_1:
> > +	case AXI_DAC_PHASE_TONE_2:
> > +		return axi_dac_phase_get(st, chan, buf, private);
> > +	default:
> > +		return -EOPNOTSUPP;
> > +	}
> > +}
> > +
> > +static const struct iio_chan_spec_ext_info axi_dac_ext_info[] = {
> > +	IIO_BACKEND_EX_INFO("frequency0", IIO_SEPARATE, AXI_DAC_FREQ_TONE_1),
> > +	IIO_BACKEND_EX_INFO("frequency1", IIO_SEPARATE, AXI_DAC_FREQ_TONE_2),
> > +	IIO_BACKEND_EX_INFO("scale0", IIO_SEPARATE, AXI_DAC_SCALE_TONE_1),
> > +	IIO_BACKEND_EX_INFO("scale1", IIO_SEPARATE, AXI_DAC_SCALE_TONE_2),
> > +	IIO_BACKEND_EX_INFO("phase0", IIO_SEPARATE, AXI_DAC_PHASE_TONE_1),
> > +	IIO_BACKEND_EX_INFO("phase1", IIO_SEPARATE, AXI_DAC_PHASE_TONE_2),
> > +	{}
> > +};
> > +
> > +static int axi_dac_extend_chan(struct iio_backend *back,
> > +			       struct iio_chan_spec *chan)
> > +{
> > +	struct axi_dac_state *st = iio_backend_get_priv(back);
> > +
> > +	if (chan->type != IIO_ALTVOLTAGE)
> > +		return -EINVAL;
> > +	if (st->reg_config & AXI_DDS_DISABLE)
> > +		/* nothing to extend */
> > +		return 0;
> > +
> > +	chan->ext_info = axi_dac_ext_info;
> > +
> > +	return 0;
> > +}
> 
> > +static int axi_dac_set_sample_rate(struct iio_backend *back, unsigned int chan,
> > +				   u64 sample_rate)
> > +{
> > +	struct axi_dac_state *st = iio_backend_get_priv(back);
> > +	unsigned int freq;
> > +	int ret, tone;
> > +
> > +	if (!sample_rate)
> > +		return -EINVAL;
> > +	if (st->reg_config & AXI_DDS_DISABLE)
> > +		/* nothing to care if DDS is disabled */
> Rephrase this.  Is the point that the sample rate has no meaning without DDS or
> that it has meaning but nothing to do here?

Has no meaning as it's not used with DDS enabled...

- Nuno Sá
> 

  reply	other threads:[~2024-03-28 16:43 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-28 13:22 [PATCH 00/10] iio: dac: support IIO backends on the output direction Nuno Sa via B4 Relay
2024-03-28 13:22 ` Nuno Sa
2024-03-28 13:22 ` [PATCH 01/10] iio: buffer: add helper for setting direction Nuno Sa via B4 Relay
2024-03-28 13:22   ` Nuno Sa
2024-03-28 14:36   ` Jonathan Cameron
2024-03-28 15:18     ` Nuno Sá
2024-03-28 15:54       ` Jonathan Cameron
2024-03-28 13:22 ` [PATCH 02/10] iio: buffer-dma: Rename iio_dma_buffer_data_available() Nuno Sa via B4 Relay
2024-03-28 13:22   ` Nuno Sa
2024-03-28 13:22 ` [PATCH 03/10] iio: buffer-dma: Enable buffer write support Nuno Sa via B4 Relay
2024-03-28 13:22   ` Nuno Sa
2024-03-28 13:22 ` [PATCH 04/10] iio: buffer-dmaengine: Support specifying buffer direction Nuno Sa via B4 Relay
2024-03-28 13:22   ` Nuno Sa
2024-03-28 13:22 ` [PATCH 05/10] iio: buffer-dmaengine: Enable write support Nuno Sa via B4 Relay
2024-03-28 13:22   ` Nuno Sa
2024-03-28 13:22 ` [PATCH 06/10] dt-bindings: iio: dac: add bindings doc for AXI DAC driver Nuno Sa via B4 Relay
2024-03-28 13:22   ` Nuno Sa
2024-03-29 18:46   ` David Lechner
2024-04-02  7:51     ` Nuno Sá
2024-04-01 13:59   ` Rob Herring
2024-04-04 10:03     ` Nuno Sá
2024-03-28 13:22 ` [PATCH 07/10] dt-bindings: iio: dac: add bindings doc for AD9739A Nuno Sa via B4 Relay
2024-03-28 13:22   ` Nuno Sa
2024-03-29 19:06   ` David Lechner
2024-03-30 18:27     ` Krzysztof Kozlowski
2024-04-02  7:49       ` Nuno Sá
2024-04-02  7:50     ` Nuno Sá
2024-04-01 14:02   ` Rob Herring
2024-03-28 13:22 ` [PATCH 08/10] iio: backend: add new functionality Nuno Sa via B4 Relay
2024-03-28 13:22   ` Nuno Sa
2024-03-28 15:16   ` Jonathan Cameron
2024-03-28 15:42     ` Nuno Sá
2024-03-28 15:59       ` Jonathan Cameron
2024-03-28 16:54         ` Nuno Sá
2024-03-28 13:22 ` [PATCH 09/10] iio: dac: add support for AXI DAC IP core Nuno Sa via B4 Relay
2024-03-28 13:22   ` Nuno Sa
2024-03-28 15:35   ` Jonathan Cameron
2024-03-28 16:43     ` Nuno Sá [this message]
2024-03-28 13:22 ` [PATCH 10/10] iio: dac: support the ad9739a RF DAC Nuno Sa via B4 Relay
2024-03-28 13:22   ` Nuno Sa
2024-03-28 15:51   ` Jonathan Cameron
2024-03-28 16:37     ` Nuno Sá
2024-03-28 16:52       ` Jonathan Cameron

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d86dbdd7c1f234ebedc08c3433735f43abff7f7e.camel@gmail.com \
    --to=noname.nuno@gmail.com \
    --cc=Michael.Hennerich@analog.com \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=devnull+nuno.sa.analog.com@kernel.org \
    --cc=dragos.bogdan@analog.com \
    --cc=jic23@kernel.org \
    --cc=krzysztof.kozlowski+dt@linaro.org \
    --cc=lars@metafoo.de \
    --cc=linux-iio@vger.kernel.org \
    --cc=nuno.sa@analog.com \
    --cc=olivier.moysan@foss.st.com \
    --cc=robh@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.