linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] iio: adc: stm32-dfsdm: fix and improve output data managementiio: adc: stm32-dfsdm: fix and improve output data management
@ 2019-06-19 13:03 Olivier Moysan
  2019-06-19 13:03 ` [PATCH 1/5] iio: adc: stm32-dfsdm: fix output resolution Olivier Moysan
                   ` (5 more replies)
  0 siblings, 6 replies; 12+ messages in thread
From: Olivier Moysan @ 2019-06-19 13:03 UTC (permalink / raw)
  To: jic23, knaack.h, lars, pmeerw, mcoquelin.stm32, alexandre.torgue,
	fabrice.gasnier, linux-iio, linux-stm32, linux-arm-kernel,
	linux-kernel, benjamin.gaignard, olivier.moysan

This patch-set provides some fixes and improvements regarding output data format
for STM32 DFSDM.
- Fix output data resolution and saturation management in continuous mode
- Fix data type
- Apply same processing on data in continuous and triggered mode
- Add fast mode support to get better resolution for output data
- Add a comment about 16 bits data transfers

Olivier Moysan (5):
  iio: adc: stm32-dfsdm: fix output resolution
  iio: adc: stm32-dfsdm: fix data type
  iio: adc: stm32-dfsdm: manage data resolution in trigger mode
  iio: adc: stm32-dfsdm: add fast mode support
  iio: adc: stm32-dfsdm: add comment for 16 bits record

 drivers/iio/adc/stm32-dfsdm-adc.c | 233 +++++++++++++++++++++++++++++++-------
 drivers/iio/adc/stm32-dfsdm.h     |  24 +++-
 2 files changed, 208 insertions(+), 49 deletions(-)

-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/5] iio: adc: stm32-dfsdm: fix output resolution
  2019-06-19 13:03 [PATCH 0/5] iio: adc: stm32-dfsdm: fix and improve output data managementiio: adc: stm32-dfsdm: fix and improve output data management Olivier Moysan
@ 2019-06-19 13:03 ` Olivier Moysan
  2019-06-22  9:18   ` Jonathan Cameron
  2019-06-19 13:03 ` [PATCH 2/5] iio: adc: stm32-dfsdm: fix data type Olivier Moysan
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Olivier Moysan @ 2019-06-19 13:03 UTC (permalink / raw)
  To: jic23, knaack.h, lars, pmeerw, mcoquelin.stm32, alexandre.torgue,
	fabrice.gasnier, linux-iio, linux-stm32, linux-arm-kernel,
	linux-kernel, benjamin.gaignard, olivier.moysan

In buffered mode, output samples are shifted left
unconditionally. This works for filter order 3,
but this shift is not adapted for other filter orders.
Compute required shift, left or right, and shift
output data accordingly.
Add also saturation management to avoid wrap-around
when maximum positive sample is reached.

Fixes: eca949800d2d ("IIO: ADC: add stm32 DFSDM support for PDM microphone")

Signed-off-by: Olivier Moysan <olivier.moysan@st.com>
---
 drivers/iio/adc/stm32-dfsdm-adc.c | 158 +++++++++++++++++++++++++++++---------
 drivers/iio/adc/stm32-dfsdm.h     |  24 ++++--
 2 files changed, 142 insertions(+), 40 deletions(-)

diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
index 588907cc3b6b..cb596f104919 100644
--- a/drivers/iio/adc/stm32-dfsdm-adc.c
+++ b/drivers/iio/adc/stm32-dfsdm-adc.c
@@ -39,9 +39,16 @@
 #define DFSDM_MAX_INT_OVERSAMPLING 256
 #define DFSDM_MAX_FL_OVERSAMPLING 1024
 
-/* Max sample resolutions */
-#define DFSDM_MAX_RES BIT(31)
-#define DFSDM_DATA_RES BIT(23)
+/* Limit filter output resolution to 31 bits. (i.e. sample range is +/-2^30) */
+#define DFSDM_DATA_MAX BIT(30)
+/*
+ * Data are output as two's complement data in a 24 bit field.
+ * Data from filters are in the range +/-2^(n-1)
+ * 2^(n-1) maximum positive value cannot be coded in 2's complement n bits
+ * An extra bit is required to avoid wrap-around of the binary code for 2^(n-1)
+ * So, the resolution of samples from filter is actually limited to 23 bits
+ */
+#define DFSDM_DATA_RES 24
 
 /* Filter configuration */
 #define DFSDM_CR1_CFG_MASK (DFSDM_CR1_RCH_MASK | DFSDM_CR1_RCONT_MASK | \
@@ -181,14 +188,15 @@ static int stm32_dfsdm_get_jextsel(struct iio_dev *indio_dev,
 	return -EINVAL;
 }
 
-static int stm32_dfsdm_set_osrs(struct stm32_dfsdm_filter *fl,
-				unsigned int fast, unsigned int oversamp)
+static int stm32_dfsdm_compute_osrs(struct stm32_dfsdm_filter *fl,
+				    unsigned int fast, unsigned int oversamp)
 {
 	unsigned int i, d, fosr, iosr;
-	u64 res;
-	s64 delta;
+	u64 res, max;
+	int bits, shift;
 	unsigned int m = 1;	/* multiplication factor */
 	unsigned int p = fl->ford;	/* filter order (ford) */
+	struct stm32_dfsdm_filter_osr *flo = &fl->flo;
 
 	pr_debug("%s: Requested oversampling: %d\n",  __func__, oversamp);
 	/*
@@ -207,11 +215,9 @@ static int stm32_dfsdm_set_osrs(struct stm32_dfsdm_filter *fl,
 
 	/*
 	 * Look for filter and integrator oversampling ratios which allows
-	 * to reach 24 bits data output resolution.
-	 * Leave as soon as if exact resolution if reached.
-	 * Otherwise the higher resolution below 32 bits is kept.
+	 * to maximize data output resolution.
 	 */
-	fl->res = 0;
+	flo->res = 0;
 	for (fosr = 1; fosr <= DFSDM_MAX_FL_OVERSAMPLING; fosr++) {
 		for (iosr = 1; iosr <= DFSDM_MAX_INT_OVERSAMPLING; iosr++) {
 			if (fast)
@@ -236,32 +242,68 @@ static int stm32_dfsdm_set_osrs(struct stm32_dfsdm_filter *fl,
 			res = fosr;
 			for (i = p - 1; i > 0; i--) {
 				res = res * (u64)fosr;
-				if (res > DFSDM_MAX_RES)
+				if (res > DFSDM_DATA_MAX)
 					break;
 			}
-			if (res > DFSDM_MAX_RES)
+			if (res > DFSDM_DATA_MAX)
 				continue;
+
 			res = res * (u64)m * (u64)iosr;
-			if (res > DFSDM_MAX_RES)
+			if (res > DFSDM_DATA_MAX)
 				continue;
 
-			delta = res - DFSDM_DATA_RES;
-
-			if (res >= fl->res) {
-				fl->res = res;
-				fl->fosr = fosr;
-				fl->iosr = iosr;
-				fl->fast = fast;
-				pr_debug("%s: fosr = %d, iosr = %d\n",
-					 __func__, fl->fosr, fl->iosr);
+			if (res >= flo->res) {
+				flo->res = res;
+				flo->fosr = fosr;
+				flo->iosr = iosr;
+
+				bits = fls(flo->res);
+				/* 8 LBSs in data register contain chan info */
+				max = flo->res << 8;
+
+				/* if resolution is not a power of two */
+				if (flo->res > BIT(bits - 1))
+					bits++;
+				else
+					max--;
+
+				shift = DFSDM_DATA_RES - bits;
+				/*
+				 * Compute right/left shift
+				 * Right shift is performed by hardware
+				 * when transferring samples to data register.
+				 * Left shift is done by software on buffer
+				 */
+				if (shift > 0) {
+					/* Resolution is lower than 24 bits */
+					flo->rshift = 0;
+					flo->lshift = shift;
+				} else {
+					/*
+					 * If resolution is 24 bits or more,
+					 * max positive value may be ambiguous
+					 * (equal to max negative value as sign
+					 * bit is dropped).
+					 * Reduce resolution to 23 bits (rshift)
+					 * to keep the sign on bit 23 and treat
+					 * saturation before rescaling on 24
+					 * bits (lshift).
+					 */
+					flo->rshift = 1 - shift;
+					flo->lshift = 1;
+					max >>= flo->rshift;
+				}
+				flo->max = (s32)max;
+
+				pr_debug("%s: fast %d, fosr %d, iosr %d, res 0x%llx/%d bits, rshift %d, lshift %d\n",
+					 __func__, fast, flo->fosr, flo->iosr,
+					 flo->res, bits, flo->rshift,
+					 flo->lshift);
 			}
-
-			if (!delta)
-				return 0;
 		}
 	}
 
-	if (!fl->res)
+	if (!flo->res)
 		return -EINVAL;
 
 	return 0;
@@ -384,6 +426,36 @@ static int stm32_dfsdm_filter_set_trig(struct stm32_dfsdm_adc *adc,
 	return 0;
 }
 
+static int stm32_dfsdm_channels_configure(struct stm32_dfsdm_adc *adc,
+					  unsigned int fl_id,
+					  struct iio_trigger *trig)
+{
+	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
+	struct regmap *regmap = adc->dfsdm->regmap;
+	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[fl_id];
+	struct stm32_dfsdm_filter_osr *flo = &fl->flo;
+	const struct iio_chan_spec *chan;
+	unsigned int bit;
+	int ret;
+
+	if (!flo->res)
+		return -EINVAL;
+
+	for_each_set_bit(bit, &adc->smask,
+			 sizeof(adc->smask) * BITS_PER_BYTE) {
+		chan = indio_dev->channels + bit;
+
+		ret = regmap_update_bits(regmap,
+					 DFSDM_CHCFGR2(chan->channel),
+					 DFSDM_CHCFGR2_DTRBS_MASK,
+					 DFSDM_CHCFGR2_DTRBS(flo->rshift));
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc,
 					unsigned int fl_id,
 					struct iio_trigger *trig)
@@ -391,6 +463,7 @@ static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc,
 	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
 	struct regmap *regmap = adc->dfsdm->regmap;
 	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[fl_id];
+	struct stm32_dfsdm_filter_osr *flo = &fl->flo;
 	u32 cr1;
 	const struct iio_chan_spec *chan;
 	unsigned int bit, jchg = 0;
@@ -398,13 +471,13 @@ static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc,
 
 	/* Average integrator oversampling */
 	ret = regmap_update_bits(regmap, DFSDM_FCR(fl_id), DFSDM_FCR_IOSR_MASK,
-				 DFSDM_FCR_IOSR(fl->iosr - 1));
+				 DFSDM_FCR_IOSR(flo->iosr - 1));
 	if (ret)
 		return ret;
 
 	/* Filter order and Oversampling */
 	ret = regmap_update_bits(regmap, DFSDM_FCR(fl_id), DFSDM_FCR_FOSR_MASK,
-				 DFSDM_FCR_FOSR(fl->fosr - 1));
+				 DFSDM_FCR_FOSR(flo->fosr - 1));
 	if (ret)
 		return ret;
 
@@ -573,7 +646,7 @@ static int dfsdm_adc_set_samp_freq(struct iio_dev *indio_dev,
 			"Rate not accurate. requested (%u), actual (%u)\n",
 			sample_freq, spi_freq / oversamp);
 
-	ret = stm32_dfsdm_set_osrs(fl, 0, oversamp);
+	ret = stm32_dfsdm_compute_osrs(fl, 0, oversamp);
 	if (ret < 0) {
 		dev_err(&indio_dev->dev, "No filter parameters that match!\n");
 		return ret;
@@ -623,6 +696,10 @@ static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc,
 	struct regmap *regmap = adc->dfsdm->regmap;
 	int ret;
 
+	ret = stm32_dfsdm_channels_configure(adc, adc->fl_id, trig);
+	if (ret < 0)
+		return ret;
+
 	ret = stm32_dfsdm_start_channel(adc);
 	if (ret < 0)
 		return ret;
@@ -729,6 +806,8 @@ static void stm32_dfsdm_dma_buffer_done(void *data)
 {
 	struct iio_dev *indio_dev = data;
 	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
+	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
+	struct stm32_dfsdm_filter_osr *flo = &fl->flo;
 	int available = stm32_dfsdm_adc_dma_residue(adc);
 	size_t old_pos;
 
@@ -751,10 +830,19 @@ static void stm32_dfsdm_dma_buffer_done(void *data)
 	old_pos = adc->bufi;
 
 	while (available >= indio_dev->scan_bytes) {
-		u32 *buffer = (u32 *)&adc->rx_buf[adc->bufi];
+		s32 *buffer = (s32 *)&adc->rx_buf[adc->bufi];
 
 		/* Mask 8 LSB that contains the channel ID */
-		*buffer = (*buffer & 0xFFFFFF00) << 8;
+		*buffer &= 0xFFFFFF00;
+		/* Convert 2^(n-1) sample to 2^(n-1)-1 to avoid wrap-around */
+		if (*buffer > flo->max)
+			*buffer -= 1;
+		/*
+		 * Samples from filter are retrieved with 23 bits resolution
+		 * or less. Shift left to align MSB on 24 bits.
+		 */
+		*buffer <<= flo->lshift;
+
 		available -= indio_dev->scan_bytes;
 		adc->bufi += indio_dev->scan_bytes;
 		if (adc->bufi >= adc->buf_sz) {
@@ -1078,7 +1166,7 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev,
 		ret = iio_device_claim_direct_mode(indio_dev);
 		if (ret)
 			return ret;
-		ret = stm32_dfsdm_set_osrs(fl, 0, val);
+		ret = stm32_dfsdm_compute_osrs(fl, 0, val);
 		if (!ret)
 			adc->oversamp = val;
 		iio_device_release_direct_mode(indio_dev);
@@ -1327,8 +1415,8 @@ static int stm32_dfsdm_adc_init(struct iio_dev *indio_dev)
 	int ret, chan_idx;
 
 	adc->oversamp = DFSDM_DEFAULT_OVERSAMPLING;
-	ret = stm32_dfsdm_set_osrs(&adc->dfsdm->fl_list[adc->fl_id], 0,
-				   adc->oversamp);
+	ret = stm32_dfsdm_compute_osrs(&adc->dfsdm->fl_list[adc->fl_id], 0,
+				       adc->oversamp);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/iio/adc/stm32-dfsdm.h b/drivers/iio/adc/stm32-dfsdm.h
index 8708394b0725..18b06ee6ed7b 100644
--- a/drivers/iio/adc/stm32-dfsdm.h
+++ b/drivers/iio/adc/stm32-dfsdm.h
@@ -243,19 +243,33 @@ enum stm32_dfsdm_sinc_order {
 };
 
 /**
- * struct stm32_dfsdm_filter - structure relative to stm32 FDSDM filter
+ * struct stm32_dfsdm_filter_osr - DFSDM filter settings linked to oversampling
  * @iosr: integrator oversampling
  * @fosr: filter oversampling
- * @ford: filter order
+ * @rshift: output sample right shift (hardware shift)
+ * @lshift: output sample left shift (software shift)
  * @res: output sample resolution
+ * @max: output sample maximum positive value
+ */
+struct stm32_dfsdm_filter_osr {
+	unsigned int iosr;
+	unsigned int fosr;
+	unsigned int rshift;
+	unsigned int lshift;
+	u64 res;
+	s32 max;
+};
+
+/**
+ * struct stm32_dfsdm_filter - structure relative to stm32 FDSDM filter
+ * @ford: filter order
+ * @flo: filter oversampling structure
  * @sync_mode: filter synchronized with filter 0
  * @fast: filter fast mode
  */
 struct stm32_dfsdm_filter {
-	unsigned int iosr;
-	unsigned int fosr;
 	enum stm32_dfsdm_sinc_order ford;
-	u64 res;
+	struct stm32_dfsdm_filter_osr flo;
 	unsigned int sync_mode;
 	unsigned int fast;
 };
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/5] iio: adc: stm32-dfsdm: fix data type
  2019-06-19 13:03 [PATCH 0/5] iio: adc: stm32-dfsdm: fix and improve output data managementiio: adc: stm32-dfsdm: fix and improve output data management Olivier Moysan
  2019-06-19 13:03 ` [PATCH 1/5] iio: adc: stm32-dfsdm: fix output resolution Olivier Moysan
@ 2019-06-19 13:03 ` Olivier Moysan
  2019-06-22  9:21   ` Jonathan Cameron
  2019-06-19 13:03 ` [PATCH 3/5] iio: adc: stm32-dfsdm: manage data resolution in trigger mode Olivier Moysan
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Olivier Moysan @ 2019-06-19 13:03 UTC (permalink / raw)
  To: jic23, knaack.h, lars, pmeerw, mcoquelin.stm32, alexandre.torgue,
	fabrice.gasnier, linux-iio, linux-stm32, linux-arm-kernel,
	linux-kernel, benjamin.gaignard, olivier.moysan

Fix the data type as DFSDM raw output is complements 2,
24bits left aligned in a 32-bit register.
This change does not affect AUDIO path
- Set data as signed for IIO (as for AUDIO)
- Set 8 bit right shift for IIO.
The 8 LSBs bits of data contains channel info and are masked.

Fixes: e2e6771c6462 ("IIO: ADC: add STM32 DFSDM sigma delta ADC support")

Signed-off-by: Olivier Moysan <olivier.moysan@st.com>
---
 drivers/iio/adc/stm32-dfsdm-adc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
index cb596f104919..6b90a40882f2 100644
--- a/drivers/iio/adc/stm32-dfsdm-adc.c
+++ b/drivers/iio/adc/stm32-dfsdm-adc.c
@@ -1365,11 +1365,11 @@ static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev,
 					BIT(IIO_CHAN_INFO_SAMP_FREQ);
 
 	if (adc->dev_data->type == DFSDM_AUDIO) {
-		ch->scan_type.sign = 's';
 		ch->ext_info = dfsdm_adc_audio_ext_info;
 	} else {
-		ch->scan_type.sign = 'u';
+		ch->scan_type.shift = 8;
 	}
+	ch->scan_type.sign = 's';
 	ch->scan_type.realbits = 24;
 	ch->scan_type.storagebits = 32;
 
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/5] iio: adc: stm32-dfsdm: manage data resolution in trigger mode
  2019-06-19 13:03 [PATCH 0/5] iio: adc: stm32-dfsdm: fix and improve output data managementiio: adc: stm32-dfsdm: fix and improve output data management Olivier Moysan
  2019-06-19 13:03 ` [PATCH 1/5] iio: adc: stm32-dfsdm: fix output resolution Olivier Moysan
  2019-06-19 13:03 ` [PATCH 2/5] iio: adc: stm32-dfsdm: fix data type Olivier Moysan
@ 2019-06-19 13:03 ` Olivier Moysan
  2019-06-22  9:23   ` Jonathan Cameron
  2019-06-19 13:03 ` [PATCH 4/5] iio: adc: stm32-dfsdm: add fast mode support Olivier Moysan
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Olivier Moysan @ 2019-06-19 13:03 UTC (permalink / raw)
  To: jic23, knaack.h, lars, pmeerw, mcoquelin.stm32, alexandre.torgue,
	fabrice.gasnier, linux-iio, linux-stm32, linux-arm-kernel,
	linux-kernel, benjamin.gaignard, olivier.moysan

Add output sample resolution management in scan mode.
Add stm32_dfsdm_process_data() function to share sample
processing between continuous and trigger modes.

Signed-off-by: Olivier Moysan <olivier.moysan@st.com>
---
 drivers/iio/adc/stm32-dfsdm-adc.c | 41 ++++++++++++++++++++++++++-------------
 1 file changed, 28 insertions(+), 13 deletions(-)

diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
index 6b90a40882f2..5b19a88412a6 100644
--- a/drivers/iio/adc/stm32-dfsdm-adc.c
+++ b/drivers/iio/adc/stm32-dfsdm-adc.c
@@ -779,6 +779,30 @@ static unsigned int stm32_dfsdm_adc_dma_residue(struct stm32_dfsdm_adc *adc)
 	return 0;
 }
 
+static inline void stm32_dfsdm_process_data(struct stm32_dfsdm_adc *adc,
+					    s32 *buffer)
+{
+	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
+	struct stm32_dfsdm_filter_osr *flo = &fl->flo;
+	unsigned int i = adc->nconv;
+	s32 *ptr = buffer;
+
+	while (i--) {
+		/* Mask 8 LSB that contains the channel ID */
+		*ptr &= 0xFFFFFF00;
+		/* Convert 2^(n-1) sample to 2^(n-1)-1 to avoid wrap-around */
+		if (*ptr > flo->max)
+			*ptr -= 1;
+		/*
+		 * Samples from filter are retrieved with 23 bits resolution
+		 * or less. Shift left to align MSB on 24 bits.
+		 */
+		*ptr <<= flo->lshift;
+
+		ptr++;
+	}
+}
+
 static irqreturn_t stm32_dfsdm_adc_trigger_handler(int irq, void *p)
 {
 	struct iio_poll_func *pf = p;
@@ -787,7 +811,9 @@ static irqreturn_t stm32_dfsdm_adc_trigger_handler(int irq, void *p)
 	int available = stm32_dfsdm_adc_dma_residue(adc);
 
 	while (available >= indio_dev->scan_bytes) {
-		u32 *buffer = (u32 *)&adc->rx_buf[adc->bufi];
+		s32 *buffer = (s32 *)&adc->rx_buf[adc->bufi];
+
+		stm32_dfsdm_process_data(adc, buffer);
 
 		iio_push_to_buffers_with_timestamp(indio_dev, buffer,
 						   pf->timestamp);
@@ -806,8 +832,6 @@ static void stm32_dfsdm_dma_buffer_done(void *data)
 {
 	struct iio_dev *indio_dev = data;
 	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
-	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
-	struct stm32_dfsdm_filter_osr *flo = &fl->flo;
 	int available = stm32_dfsdm_adc_dma_residue(adc);
 	size_t old_pos;
 
@@ -832,16 +856,7 @@ static void stm32_dfsdm_dma_buffer_done(void *data)
 	while (available >= indio_dev->scan_bytes) {
 		s32 *buffer = (s32 *)&adc->rx_buf[adc->bufi];
 
-		/* Mask 8 LSB that contains the channel ID */
-		*buffer &= 0xFFFFFF00;
-		/* Convert 2^(n-1) sample to 2^(n-1)-1 to avoid wrap-around */
-		if (*buffer > flo->max)
-			*buffer -= 1;
-		/*
-		 * Samples from filter are retrieved with 23 bits resolution
-		 * or less. Shift left to align MSB on 24 bits.
-		 */
-		*buffer <<= flo->lshift;
+		stm32_dfsdm_process_data(adc, buffer);
 
 		available -= indio_dev->scan_bytes;
 		adc->bufi += indio_dev->scan_bytes;
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/5] iio: adc: stm32-dfsdm: add fast mode support
  2019-06-19 13:03 [PATCH 0/5] iio: adc: stm32-dfsdm: fix and improve output data managementiio: adc: stm32-dfsdm: fix and improve output data management Olivier Moysan
                   ` (2 preceding siblings ...)
  2019-06-19 13:03 ` [PATCH 3/5] iio: adc: stm32-dfsdm: manage data resolution in trigger mode Olivier Moysan
@ 2019-06-19 13:03 ` Olivier Moysan
  2019-06-22  9:30   ` Jonathan Cameron
  2019-06-19 13:03 ` [PATCH 5/5] iio: adc: stm32-dfsdm: add comment for 16 bits record Olivier Moysan
  2019-06-19 15:04 ` [PATCH 0/5] iio: adc: stm32-dfsdm: fix and improve output data managementiio: adc: stm32-dfsdm: fix and improve output data management Fabrice Gasnier
  5 siblings, 1 reply; 12+ messages in thread
From: Olivier Moysan @ 2019-06-19 13:03 UTC (permalink / raw)
  To: jic23, knaack.h, lars, pmeerw, mcoquelin.stm32, alexandre.torgue,
	fabrice.gasnier, linux-iio, linux-stm32, linux-arm-kernel,
	linux-kernel, benjamin.gaignard, olivier.moysan

The use of fast mode allows to get a larger set of solution
for filter parameters. This can be useful to reach a better
output sample resolution, when fast mode can be used.

Fast mode is selected at startup if it is relevant.
The startup is performed in postenable callback context,
where there are too tight time constraints for filter parameters
computation. For this reason both fast and non fast filter parameters
are pre-computed previously.

Signed-off-by: Olivier Moysan <olivier.moysan@st.com>
---
 drivers/iio/adc/stm32-dfsdm-adc.c | 65 ++++++++++++++++++++++++++++++---------
 drivers/iio/adc/stm32-dfsdm.h     |  4 +--
 2 files changed, 53 insertions(+), 16 deletions(-)

diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
index 5b19a88412a6..d855a605eab6 100644
--- a/drivers/iio/adc/stm32-dfsdm-adc.c
+++ b/drivers/iio/adc/stm32-dfsdm-adc.c
@@ -196,7 +196,7 @@ static int stm32_dfsdm_compute_osrs(struct stm32_dfsdm_filter *fl,
 	int bits, shift;
 	unsigned int m = 1;	/* multiplication factor */
 	unsigned int p = fl->ford;	/* filter order (ford) */
-	struct stm32_dfsdm_filter_osr *flo = &fl->flo;
+	struct stm32_dfsdm_filter_osr *flo = &fl->flo[fast];
 
 	pr_debug("%s: Requested oversampling: %d\n",  __func__, oversamp);
 	/*
@@ -217,7 +217,6 @@ static int stm32_dfsdm_compute_osrs(struct stm32_dfsdm_filter *fl,
 	 * Look for filter and integrator oversampling ratios which allows
 	 * to maximize data output resolution.
 	 */
-	flo->res = 0;
 	for (fosr = 1; fosr <= DFSDM_MAX_FL_OVERSAMPLING; fosr++) {
 		for (iosr = 1; iosr <= DFSDM_MAX_INT_OVERSAMPLING; iosr++) {
 			if (fast)
@@ -309,6 +308,28 @@ static int stm32_dfsdm_compute_osrs(struct stm32_dfsdm_filter *fl,
 	return 0;
 }
 
+static int stm32_dfsdm_compute_all_osrs(struct iio_dev *indio_dev,
+					unsigned int oversamp)
+{
+	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
+	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
+	int ret0, ret1;
+
+	memset(&fl->flo[0], 0, sizeof(fl->flo[0]));
+	memset(&fl->flo[1], 0, sizeof(fl->flo[1]));
+
+	ret0 = stm32_dfsdm_compute_osrs(fl, 0, oversamp);
+	ret1 = stm32_dfsdm_compute_osrs(fl, 1, oversamp);
+	if (ret0 < 0 && ret1 < 0) {
+		dev_err(&indio_dev->dev,
+			"Filter parameters not found: errors %d/%d\n",
+			ret0, ret1);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static int stm32_dfsdm_start_channel(struct stm32_dfsdm_adc *adc)
 {
 	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
@@ -433,11 +454,25 @@ static int stm32_dfsdm_channels_configure(struct stm32_dfsdm_adc *adc,
 	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
 	struct regmap *regmap = adc->dfsdm->regmap;
 	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[fl_id];
-	struct stm32_dfsdm_filter_osr *flo = &fl->flo;
+	struct stm32_dfsdm_filter_osr *flo = &fl->flo[0];
 	const struct iio_chan_spec *chan;
 	unsigned int bit;
 	int ret;
 
+	fl->fast = 0;
+
+	/*
+	 * In continuous mode, use fast mode configuration,
+	 * if it provides a better resolution.
+	 */
+	if (adc->nconv == 1 && !trig &&
+	    (indio_dev->currentmode & INDIO_BUFFER_SOFTWARE)) {
+		if (fl->flo[1].res >= fl->flo[0].res) {
+			fl->fast = 1;
+			flo = &fl->flo[1];
+		}
+	}
+
 	if (!flo->res)
 		return -EINVAL;
 
@@ -463,7 +498,7 @@ static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc,
 	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
 	struct regmap *regmap = adc->dfsdm->regmap;
 	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[fl_id];
-	struct stm32_dfsdm_filter_osr *flo = &fl->flo;
+	struct stm32_dfsdm_filter_osr *flo = &fl->flo[fl->fast];
 	u32 cr1;
 	const struct iio_chan_spec *chan;
 	unsigned int bit, jchg = 0;
@@ -490,6 +525,12 @@ static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc,
 	if (ret)
 		return ret;
 
+	ret = regmap_update_bits(regmap, DFSDM_CR1(fl_id),
+				 DFSDM_CR1_FAST_MASK,
+				 DFSDM_CR1_FAST(fl->fast));
+	if (ret)
+		return ret;
+
 	/*
 	 * DFSDM modes configuration W.R.T audio/iio type modes
 	 * ----------------------------------------------------------------
@@ -636,7 +677,6 @@ static int dfsdm_adc_set_samp_freq(struct iio_dev *indio_dev,
 				   unsigned int spi_freq)
 {
 	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
-	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
 	unsigned int oversamp;
 	int ret;
 
@@ -646,11 +686,10 @@ static int dfsdm_adc_set_samp_freq(struct iio_dev *indio_dev,
 			"Rate not accurate. requested (%u), actual (%u)\n",
 			sample_freq, spi_freq / oversamp);
 
-	ret = stm32_dfsdm_compute_osrs(fl, 0, oversamp);
-	if (ret < 0) {
-		dev_err(&indio_dev->dev, "No filter parameters that match!\n");
+	ret = stm32_dfsdm_compute_all_osrs(indio_dev, oversamp);
+	if (ret < 0)
 		return ret;
-	}
+
 	adc->sample_freq = spi_freq / oversamp;
 	adc->oversamp = oversamp;
 
@@ -783,7 +822,7 @@ static inline void stm32_dfsdm_process_data(struct stm32_dfsdm_adc *adc,
 					    s32 *buffer)
 {
 	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
-	struct stm32_dfsdm_filter_osr *flo = &fl->flo;
+	struct stm32_dfsdm_filter_osr *flo = &fl->flo[fl->fast];
 	unsigned int i = adc->nconv;
 	s32 *ptr = buffer;
 
@@ -1171,7 +1210,6 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev,
 				 int val, int val2, long mask)
 {
 	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
-	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
 	struct stm32_dfsdm_channel *ch = &adc->dfsdm->ch_list[chan->channel];
 	unsigned int spi_freq;
 	int ret = -EINVAL;
@@ -1181,7 +1219,7 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev,
 		ret = iio_device_claim_direct_mode(indio_dev);
 		if (ret)
 			return ret;
-		ret = stm32_dfsdm_compute_osrs(fl, 0, val);
+		ret = stm32_dfsdm_compute_all_osrs(indio_dev, val);
 		if (!ret)
 			adc->oversamp = val;
 		iio_device_release_direct_mode(indio_dev);
@@ -1430,8 +1468,7 @@ static int stm32_dfsdm_adc_init(struct iio_dev *indio_dev)
 	int ret, chan_idx;
 
 	adc->oversamp = DFSDM_DEFAULT_OVERSAMPLING;
-	ret = stm32_dfsdm_compute_osrs(&adc->dfsdm->fl_list[adc->fl_id], 0,
-				       adc->oversamp);
+	ret = stm32_dfsdm_compute_all_osrs(indio_dev, adc->oversamp);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/iio/adc/stm32-dfsdm.h b/drivers/iio/adc/stm32-dfsdm.h
index 18b06ee6ed7b..5dbdae4ed881 100644
--- a/drivers/iio/adc/stm32-dfsdm.h
+++ b/drivers/iio/adc/stm32-dfsdm.h
@@ -263,13 +263,13 @@ struct stm32_dfsdm_filter_osr {
 /**
  * struct stm32_dfsdm_filter - structure relative to stm32 FDSDM filter
  * @ford: filter order
- * @flo: filter oversampling structure
+ * @flo: filter oversampling data table indexed by fast mode flag
  * @sync_mode: filter synchronized with filter 0
  * @fast: filter fast mode
  */
 struct stm32_dfsdm_filter {
 	enum stm32_dfsdm_sinc_order ford;
-	struct stm32_dfsdm_filter_osr flo;
+	struct stm32_dfsdm_filter_osr flo[2];
 	unsigned int sync_mode;
 	unsigned int fast;
 };
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 5/5] iio: adc: stm32-dfsdm: add comment for 16 bits record
  2019-06-19 13:03 [PATCH 0/5] iio: adc: stm32-dfsdm: fix and improve output data managementiio: adc: stm32-dfsdm: fix and improve output data management Olivier Moysan
                   ` (3 preceding siblings ...)
  2019-06-19 13:03 ` [PATCH 4/5] iio: adc: stm32-dfsdm: add fast mode support Olivier Moysan
@ 2019-06-19 13:03 ` Olivier Moysan
  2019-06-22  9:33   ` Jonathan Cameron
  2019-06-19 15:04 ` [PATCH 0/5] iio: adc: stm32-dfsdm: fix and improve output data managementiio: adc: stm32-dfsdm: fix and improve output data management Fabrice Gasnier
  5 siblings, 1 reply; 12+ messages in thread
From: Olivier Moysan @ 2019-06-19 13:03 UTC (permalink / raw)
  To: jic23, knaack.h, lars, pmeerw, mcoquelin.stm32, alexandre.torgue,
	fabrice.gasnier, linux-iio, linux-stm32, linux-arm-kernel,
	linux-kernel, benjamin.gaignard, olivier.moysan

Add a comment on DMA configuration for 16 bits record.

Signed-off-by: Olivier Moysan <olivier.moysan@st.com>
---
 drivers/iio/adc/stm32-dfsdm-adc.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
index d855a605eab6..ee1e0569d0e1 100644
--- a/drivers/iio/adc/stm32-dfsdm-adc.c
+++ b/drivers/iio/adc/stm32-dfsdm-adc.c
@@ -918,6 +918,11 @@ static void stm32_dfsdm_dma_buffer_done(void *data)
 static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev)
 {
 	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
+	/*
+	 * The DFSDM supports half-word transfers. However, for 16 bits record,
+	 * 4 bytes buswidth is kept, to avoid losing samples LSBs when left
+	 * shift is required.
+	 */
 	struct dma_slave_config config = {
 		.src_addr = (dma_addr_t)adc->dfsdm->phys_base,
 		.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH 0/5] iio: adc: stm32-dfsdm: fix and improve output data managementiio: adc: stm32-dfsdm: fix and improve output data management
  2019-06-19 13:03 [PATCH 0/5] iio: adc: stm32-dfsdm: fix and improve output data managementiio: adc: stm32-dfsdm: fix and improve output data management Olivier Moysan
                   ` (4 preceding siblings ...)
  2019-06-19 13:03 ` [PATCH 5/5] iio: adc: stm32-dfsdm: add comment for 16 bits record Olivier Moysan
@ 2019-06-19 15:04 ` Fabrice Gasnier
  5 siblings, 0 replies; 12+ messages in thread
From: Fabrice Gasnier @ 2019-06-19 15:04 UTC (permalink / raw)
  To: Olivier Moysan
  Cc: lars, alexandre.torgue, linux-iio, pmeerw, linux-kernel,
	linux-arm-kernel, mcoquelin.stm32, knaack.h, linux-stm32, jic23,
	benjamin.gaignard

On 6/19/19 3:03 PM, Olivier Moysan wrote:
> This patch-set provides some fixes and improvements regarding output data format
> for STM32 DFSDM.
> - Fix output data resolution and saturation management in continuous mode
> - Fix data type
> - Apply same processing on data in continuous and triggered mode
> - Add fast mode support to get better resolution for output data
> - Add a comment about 16 bits data transfers
> 
> Olivier Moysan (5):
>   iio: adc: stm32-dfsdm: fix output resolution
>   iio: adc: stm32-dfsdm: fix data type
>   iio: adc: stm32-dfsdm: manage data resolution in trigger mode
>   iio: adc: stm32-dfsdm: add fast mode support
>   iio: adc: stm32-dfsdm: add comment for 16 bits record

Hi Olivier,

For the series,
Acked-by: Fabrice Gasnier <fabrice.gasnier@st.com>

Thanks,
Best Regards,
Fabrice
> 
>  drivers/iio/adc/stm32-dfsdm-adc.c | 233 +++++++++++++++++++++++++++++++-------
>  drivers/iio/adc/stm32-dfsdm.h     |  24 +++-
>  2 files changed, 208 insertions(+), 49 deletions(-)
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 1/5] iio: adc: stm32-dfsdm: fix output resolution
  2019-06-19 13:03 ` [PATCH 1/5] iio: adc: stm32-dfsdm: fix output resolution Olivier Moysan
@ 2019-06-22  9:18   ` Jonathan Cameron
  0 siblings, 0 replies; 12+ messages in thread
From: Jonathan Cameron @ 2019-06-22  9:18 UTC (permalink / raw)
  To: Olivier Moysan
  Cc: lars, alexandre.torgue, linux-iio, pmeerw, linux-kernel,
	mcoquelin.stm32, knaack.h, fabrice.gasnier, linux-stm32,
	linux-arm-kernel, benjamin.gaignard

On Wed, 19 Jun 2019 15:03:47 +0200
Olivier Moysan <olivier.moysan@st.com> wrote:

> In buffered mode, output samples are shifted left
> unconditionally. This works for filter order 3,
> but this shift is not adapted for other filter orders.
> Compute required shift, left or right, and shift
> output data accordingly.
> Add also saturation management to avoid wrap-around
> when maximum positive sample is reached.
> 
> Fixes: eca949800d2d ("IIO: ADC: add stm32 DFSDM support for PDM microphone")
> 
> Signed-off-by: Olivier Moysan <olivier.moysan@st.com>
Hi Olivier,

I'm going to take this the 'slow way' for two reasons.
1) We are late in a cycle so I'm not keen on sending things upstream until
   the merge window (unless they are very urgent!)
2) This is large and invasive.  If we want to think about backporting this
   to stable kernels, we may want to see if there is a simpler way of making it
   not broken, perhaps at the cost of functionality.

Anyhow, with that note, applied to the togreg branch of iio.git and pushed
out as testing for the autobuilders to play with it.

thanks,

Jonathan
	
> ---
>  drivers/iio/adc/stm32-dfsdm-adc.c | 158 +++++++++++++++++++++++++++++---------
>  drivers/iio/adc/stm32-dfsdm.h     |  24 ++++--
>  2 files changed, 142 insertions(+), 40 deletions(-)
> 
> diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
> index 588907cc3b6b..cb596f104919 100644
> --- a/drivers/iio/adc/stm32-dfsdm-adc.c
> +++ b/drivers/iio/adc/stm32-dfsdm-adc.c
> @@ -39,9 +39,16 @@
>  #define DFSDM_MAX_INT_OVERSAMPLING 256
>  #define DFSDM_MAX_FL_OVERSAMPLING 1024
>  
> -/* Max sample resolutions */
> -#define DFSDM_MAX_RES BIT(31)
> -#define DFSDM_DATA_RES BIT(23)
> +/* Limit filter output resolution to 31 bits. (i.e. sample range is +/-2^30) */
> +#define DFSDM_DATA_MAX BIT(30)
> +/*
> + * Data are output as two's complement data in a 24 bit field.
> + * Data from filters are in the range +/-2^(n-1)
> + * 2^(n-1) maximum positive value cannot be coded in 2's complement n bits
> + * An extra bit is required to avoid wrap-around of the binary code for 2^(n-1)
> + * So, the resolution of samples from filter is actually limited to 23 bits
> + */
> +#define DFSDM_DATA_RES 24
>  
>  /* Filter configuration */
>  #define DFSDM_CR1_CFG_MASK (DFSDM_CR1_RCH_MASK | DFSDM_CR1_RCONT_MASK | \
> @@ -181,14 +188,15 @@ static int stm32_dfsdm_get_jextsel(struct iio_dev *indio_dev,
>  	return -EINVAL;
>  }
>  
> -static int stm32_dfsdm_set_osrs(struct stm32_dfsdm_filter *fl,
> -				unsigned int fast, unsigned int oversamp)
> +static int stm32_dfsdm_compute_osrs(struct stm32_dfsdm_filter *fl,
> +				    unsigned int fast, unsigned int oversamp)
>  {
>  	unsigned int i, d, fosr, iosr;
> -	u64 res;
> -	s64 delta;
> +	u64 res, max;
> +	int bits, shift;
>  	unsigned int m = 1;	/* multiplication factor */
>  	unsigned int p = fl->ford;	/* filter order (ford) */
> +	struct stm32_dfsdm_filter_osr *flo = &fl->flo;
>  
>  	pr_debug("%s: Requested oversampling: %d\n",  __func__, oversamp);
>  	/*
> @@ -207,11 +215,9 @@ static int stm32_dfsdm_set_osrs(struct stm32_dfsdm_filter *fl,
>  
>  	/*
>  	 * Look for filter and integrator oversampling ratios which allows
> -	 * to reach 24 bits data output resolution.
> -	 * Leave as soon as if exact resolution if reached.
> -	 * Otherwise the higher resolution below 32 bits is kept.
> +	 * to maximize data output resolution.
>  	 */
> -	fl->res = 0;
> +	flo->res = 0;
>  	for (fosr = 1; fosr <= DFSDM_MAX_FL_OVERSAMPLING; fosr++) {
>  		for (iosr = 1; iosr <= DFSDM_MAX_INT_OVERSAMPLING; iosr++) {
>  			if (fast)
> @@ -236,32 +242,68 @@ static int stm32_dfsdm_set_osrs(struct stm32_dfsdm_filter *fl,
>  			res = fosr;
>  			for (i = p - 1; i > 0; i--) {
>  				res = res * (u64)fosr;
> -				if (res > DFSDM_MAX_RES)
> +				if (res > DFSDM_DATA_MAX)
>  					break;
>  			}
> -			if (res > DFSDM_MAX_RES)
> +			if (res > DFSDM_DATA_MAX)
>  				continue;
> +
>  			res = res * (u64)m * (u64)iosr;
> -			if (res > DFSDM_MAX_RES)
> +			if (res > DFSDM_DATA_MAX)
>  				continue;
>  
> -			delta = res - DFSDM_DATA_RES;
> -
> -			if (res >= fl->res) {
> -				fl->res = res;
> -				fl->fosr = fosr;
> -				fl->iosr = iosr;
> -				fl->fast = fast;
> -				pr_debug("%s: fosr = %d, iosr = %d\n",
> -					 __func__, fl->fosr, fl->iosr);
> +			if (res >= flo->res) {
> +				flo->res = res;
> +				flo->fosr = fosr;
> +				flo->iosr = iosr;
> +
> +				bits = fls(flo->res);
> +				/* 8 LBSs in data register contain chan info */
> +				max = flo->res << 8;
> +
> +				/* if resolution is not a power of two */
> +				if (flo->res > BIT(bits - 1))
> +					bits++;
> +				else
> +					max--;
> +
> +				shift = DFSDM_DATA_RES - bits;
> +				/*
> +				 * Compute right/left shift
> +				 * Right shift is performed by hardware
> +				 * when transferring samples to data register.
> +				 * Left shift is done by software on buffer
> +				 */
> +				if (shift > 0) {
> +					/* Resolution is lower than 24 bits */
> +					flo->rshift = 0;
> +					flo->lshift = shift;
> +				} else {
> +					/*
> +					 * If resolution is 24 bits or more,
> +					 * max positive value may be ambiguous
> +					 * (equal to max negative value as sign
> +					 * bit is dropped).
> +					 * Reduce resolution to 23 bits (rshift)
> +					 * to keep the sign on bit 23 and treat
> +					 * saturation before rescaling on 24
> +					 * bits (lshift).
> +					 */
> +					flo->rshift = 1 - shift;
> +					flo->lshift = 1;
> +					max >>= flo->rshift;
> +				}
> +				flo->max = (s32)max;
> +
> +				pr_debug("%s: fast %d, fosr %d, iosr %d, res 0x%llx/%d bits, rshift %d, lshift %d\n",
> +					 __func__, fast, flo->fosr, flo->iosr,
> +					 flo->res, bits, flo->rshift,
> +					 flo->lshift);
>  			}
> -
> -			if (!delta)
> -				return 0;
>  		}
>  	}
>  
> -	if (!fl->res)
> +	if (!flo->res)
>  		return -EINVAL;
>  
>  	return 0;
> @@ -384,6 +426,36 @@ static int stm32_dfsdm_filter_set_trig(struct stm32_dfsdm_adc *adc,
>  	return 0;
>  }
>  
> +static int stm32_dfsdm_channels_configure(struct stm32_dfsdm_adc *adc,
> +					  unsigned int fl_id,
> +					  struct iio_trigger *trig)
> +{
> +	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
> +	struct regmap *regmap = adc->dfsdm->regmap;
> +	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[fl_id];
> +	struct stm32_dfsdm_filter_osr *flo = &fl->flo;
> +	const struct iio_chan_spec *chan;
> +	unsigned int bit;
> +	int ret;
> +
> +	if (!flo->res)
> +		return -EINVAL;
> +
> +	for_each_set_bit(bit, &adc->smask,
> +			 sizeof(adc->smask) * BITS_PER_BYTE) {
> +		chan = indio_dev->channels + bit;
> +
> +		ret = regmap_update_bits(regmap,
> +					 DFSDM_CHCFGR2(chan->channel),
> +					 DFSDM_CHCFGR2_DTRBS_MASK,
> +					 DFSDM_CHCFGR2_DTRBS(flo->rshift));
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
>  static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc,
>  					unsigned int fl_id,
>  					struct iio_trigger *trig)
> @@ -391,6 +463,7 @@ static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc,
>  	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
>  	struct regmap *regmap = adc->dfsdm->regmap;
>  	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[fl_id];
> +	struct stm32_dfsdm_filter_osr *flo = &fl->flo;
>  	u32 cr1;
>  	const struct iio_chan_spec *chan;
>  	unsigned int bit, jchg = 0;
> @@ -398,13 +471,13 @@ static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc,
>  
>  	/* Average integrator oversampling */
>  	ret = regmap_update_bits(regmap, DFSDM_FCR(fl_id), DFSDM_FCR_IOSR_MASK,
> -				 DFSDM_FCR_IOSR(fl->iosr - 1));
> +				 DFSDM_FCR_IOSR(flo->iosr - 1));
>  	if (ret)
>  		return ret;
>  
>  	/* Filter order and Oversampling */
>  	ret = regmap_update_bits(regmap, DFSDM_FCR(fl_id), DFSDM_FCR_FOSR_MASK,
> -				 DFSDM_FCR_FOSR(fl->fosr - 1));
> +				 DFSDM_FCR_FOSR(flo->fosr - 1));
>  	if (ret)
>  		return ret;
>  
> @@ -573,7 +646,7 @@ static int dfsdm_adc_set_samp_freq(struct iio_dev *indio_dev,
>  			"Rate not accurate. requested (%u), actual (%u)\n",
>  			sample_freq, spi_freq / oversamp);
>  
> -	ret = stm32_dfsdm_set_osrs(fl, 0, oversamp);
> +	ret = stm32_dfsdm_compute_osrs(fl, 0, oversamp);
>  	if (ret < 0) {
>  		dev_err(&indio_dev->dev, "No filter parameters that match!\n");
>  		return ret;
> @@ -623,6 +696,10 @@ static int stm32_dfsdm_start_conv(struct stm32_dfsdm_adc *adc,
>  	struct regmap *regmap = adc->dfsdm->regmap;
>  	int ret;
>  
> +	ret = stm32_dfsdm_channels_configure(adc, adc->fl_id, trig);
> +	if (ret < 0)
> +		return ret;
> +
>  	ret = stm32_dfsdm_start_channel(adc);
>  	if (ret < 0)
>  		return ret;
> @@ -729,6 +806,8 @@ static void stm32_dfsdm_dma_buffer_done(void *data)
>  {
>  	struct iio_dev *indio_dev = data;
>  	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
> +	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
> +	struct stm32_dfsdm_filter_osr *flo = &fl->flo;
>  	int available = stm32_dfsdm_adc_dma_residue(adc);
>  	size_t old_pos;
>  
> @@ -751,10 +830,19 @@ static void stm32_dfsdm_dma_buffer_done(void *data)
>  	old_pos = adc->bufi;
>  
>  	while (available >= indio_dev->scan_bytes) {
> -		u32 *buffer = (u32 *)&adc->rx_buf[adc->bufi];
> +		s32 *buffer = (s32 *)&adc->rx_buf[adc->bufi];
>  
>  		/* Mask 8 LSB that contains the channel ID */
> -		*buffer = (*buffer & 0xFFFFFF00) << 8;
> +		*buffer &= 0xFFFFFF00;
> +		/* Convert 2^(n-1) sample to 2^(n-1)-1 to avoid wrap-around */
> +		if (*buffer > flo->max)
> +			*buffer -= 1;
> +		/*
> +		 * Samples from filter are retrieved with 23 bits resolution
> +		 * or less. Shift left to align MSB on 24 bits.
> +		 */
> +		*buffer <<= flo->lshift;
> +
>  		available -= indio_dev->scan_bytes;
>  		adc->bufi += indio_dev->scan_bytes;
>  		if (adc->bufi >= adc->buf_sz) {
> @@ -1078,7 +1166,7 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev,
>  		ret = iio_device_claim_direct_mode(indio_dev);
>  		if (ret)
>  			return ret;
> -		ret = stm32_dfsdm_set_osrs(fl, 0, val);
> +		ret = stm32_dfsdm_compute_osrs(fl, 0, val);
>  		if (!ret)
>  			adc->oversamp = val;
>  		iio_device_release_direct_mode(indio_dev);
> @@ -1327,8 +1415,8 @@ static int stm32_dfsdm_adc_init(struct iio_dev *indio_dev)
>  	int ret, chan_idx;
>  
>  	adc->oversamp = DFSDM_DEFAULT_OVERSAMPLING;
> -	ret = stm32_dfsdm_set_osrs(&adc->dfsdm->fl_list[adc->fl_id], 0,
> -				   adc->oversamp);
> +	ret = stm32_dfsdm_compute_osrs(&adc->dfsdm->fl_list[adc->fl_id], 0,
> +				       adc->oversamp);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/iio/adc/stm32-dfsdm.h b/drivers/iio/adc/stm32-dfsdm.h
> index 8708394b0725..18b06ee6ed7b 100644
> --- a/drivers/iio/adc/stm32-dfsdm.h
> +++ b/drivers/iio/adc/stm32-dfsdm.h
> @@ -243,19 +243,33 @@ enum stm32_dfsdm_sinc_order {
>  };
>  
>  /**
> - * struct stm32_dfsdm_filter - structure relative to stm32 FDSDM filter
> + * struct stm32_dfsdm_filter_osr - DFSDM filter settings linked to oversampling
>   * @iosr: integrator oversampling
>   * @fosr: filter oversampling
> - * @ford: filter order
> + * @rshift: output sample right shift (hardware shift)
> + * @lshift: output sample left shift (software shift)
>   * @res: output sample resolution
> + * @max: output sample maximum positive value
> + */
> +struct stm32_dfsdm_filter_osr {
> +	unsigned int iosr;
> +	unsigned int fosr;
> +	unsigned int rshift;
> +	unsigned int lshift;
> +	u64 res;
> +	s32 max;
> +};
> +
> +/**
> + * struct stm32_dfsdm_filter - structure relative to stm32 FDSDM filter
> + * @ford: filter order
> + * @flo: filter oversampling structure
>   * @sync_mode: filter synchronized with filter 0
>   * @fast: filter fast mode
>   */
>  struct stm32_dfsdm_filter {
> -	unsigned int iosr;
> -	unsigned int fosr;
>  	enum stm32_dfsdm_sinc_order ford;
> -	u64 res;
> +	struct stm32_dfsdm_filter_osr flo;
>  	unsigned int sync_mode;
>  	unsigned int fast;
>  };


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 2/5] iio: adc: stm32-dfsdm: fix data type
  2019-06-19 13:03 ` [PATCH 2/5] iio: adc: stm32-dfsdm: fix data type Olivier Moysan
@ 2019-06-22  9:21   ` Jonathan Cameron
  0 siblings, 0 replies; 12+ messages in thread
From: Jonathan Cameron @ 2019-06-22  9:21 UTC (permalink / raw)
  To: Olivier Moysan
  Cc: lars, alexandre.torgue, linux-iio, pmeerw, linux-kernel,
	mcoquelin.stm32, knaack.h, fabrice.gasnier, linux-stm32,
	linux-arm-kernel, benjamin.gaignard

On Wed, 19 Jun 2019 15:03:48 +0200
Olivier Moysan <olivier.moysan@st.com> wrote:

> Fix the data type as DFSDM raw output is complements 2,
> 24bits left aligned in a 32-bit register.
> This change does not affect AUDIO path
> - Set data as signed for IIO (as for AUDIO)
> - Set 8 bit right shift for IIO.
> The 8 LSBs bits of data contains channel info and are masked.
> 
> Fixes: e2e6771c6462 ("IIO: ADC: add STM32 DFSDM sigma delta ADC support")
> 
> Signed-off-by: Olivier Moysan <olivier.moysan@st.com>
Applied to the togreg branch of iio.git and pushed out as testing
for the autobuilders to play with them.

Thanks,

Jonathan

> ---
>  drivers/iio/adc/stm32-dfsdm-adc.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
> index cb596f104919..6b90a40882f2 100644
> --- a/drivers/iio/adc/stm32-dfsdm-adc.c
> +++ b/drivers/iio/adc/stm32-dfsdm-adc.c
> @@ -1365,11 +1365,11 @@ static int stm32_dfsdm_adc_chan_init_one(struct iio_dev *indio_dev,
>  					BIT(IIO_CHAN_INFO_SAMP_FREQ);
>  
>  	if (adc->dev_data->type == DFSDM_AUDIO) {
> -		ch->scan_type.sign = 's';
>  		ch->ext_info = dfsdm_adc_audio_ext_info;
>  	} else {
> -		ch->scan_type.sign = 'u';
> +		ch->scan_type.shift = 8;
>  	}
> +	ch->scan_type.sign = 's';
>  	ch->scan_type.realbits = 24;
>  	ch->scan_type.storagebits = 32;
>  


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 3/5] iio: adc: stm32-dfsdm: manage data resolution in trigger mode
  2019-06-19 13:03 ` [PATCH 3/5] iio: adc: stm32-dfsdm: manage data resolution in trigger mode Olivier Moysan
@ 2019-06-22  9:23   ` Jonathan Cameron
  0 siblings, 0 replies; 12+ messages in thread
From: Jonathan Cameron @ 2019-06-22  9:23 UTC (permalink / raw)
  To: Olivier Moysan
  Cc: lars, alexandre.torgue, linux-iio, pmeerw, linux-kernel,
	mcoquelin.stm32, knaack.h, fabrice.gasnier, linux-stm32,
	linux-arm-kernel, benjamin.gaignard

On Wed, 19 Jun 2019 15:03:49 +0200
Olivier Moysan <olivier.moysan@st.com> wrote:

> Add output sample resolution management in scan mode.
> Add stm32_dfsdm_process_data() function to share sample
> processing between continuous and trigger modes.
> 
> Signed-off-by: Olivier Moysan <olivier.moysan@st.com>
Makes sense, though I would have preferred a little bit more info
on what the user visible effects fo this change are in
the patch description.  I think I know from reading the code,
but not every one will do that ;)

Applied to the togreg branch of iio.git and pushed out as
testing for the autobuilders to play with it.

Thanks,

Jonathan

> ---
>  drivers/iio/adc/stm32-dfsdm-adc.c | 41 ++++++++++++++++++++++++++-------------
>  1 file changed, 28 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
> index 6b90a40882f2..5b19a88412a6 100644
> --- a/drivers/iio/adc/stm32-dfsdm-adc.c
> +++ b/drivers/iio/adc/stm32-dfsdm-adc.c
> @@ -779,6 +779,30 @@ static unsigned int stm32_dfsdm_adc_dma_residue(struct stm32_dfsdm_adc *adc)
>  	return 0;
>  }
>  
> +static inline void stm32_dfsdm_process_data(struct stm32_dfsdm_adc *adc,
> +					    s32 *buffer)
> +{
> +	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
> +	struct stm32_dfsdm_filter_osr *flo = &fl->flo;
> +	unsigned int i = adc->nconv;
> +	s32 *ptr = buffer;
> +
> +	while (i--) {
> +		/* Mask 8 LSB that contains the channel ID */
> +		*ptr &= 0xFFFFFF00;
> +		/* Convert 2^(n-1) sample to 2^(n-1)-1 to avoid wrap-around */
> +		if (*ptr > flo->max)
> +			*ptr -= 1;
> +		/*
> +		 * Samples from filter are retrieved with 23 bits resolution
> +		 * or less. Shift left to align MSB on 24 bits.
> +		 */
> +		*ptr <<= flo->lshift;
> +
> +		ptr++;
> +	}
> +}
> +
>  static irqreturn_t stm32_dfsdm_adc_trigger_handler(int irq, void *p)
>  {
>  	struct iio_poll_func *pf = p;
> @@ -787,7 +811,9 @@ static irqreturn_t stm32_dfsdm_adc_trigger_handler(int irq, void *p)
>  	int available = stm32_dfsdm_adc_dma_residue(adc);
>  
>  	while (available >= indio_dev->scan_bytes) {
> -		u32 *buffer = (u32 *)&adc->rx_buf[adc->bufi];
> +		s32 *buffer = (s32 *)&adc->rx_buf[adc->bufi];
> +
> +		stm32_dfsdm_process_data(adc, buffer);
>  
>  		iio_push_to_buffers_with_timestamp(indio_dev, buffer,
>  						   pf->timestamp);
> @@ -806,8 +832,6 @@ static void stm32_dfsdm_dma_buffer_done(void *data)
>  {
>  	struct iio_dev *indio_dev = data;
>  	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
> -	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
> -	struct stm32_dfsdm_filter_osr *flo = &fl->flo;
>  	int available = stm32_dfsdm_adc_dma_residue(adc);
>  	size_t old_pos;
>  
> @@ -832,16 +856,7 @@ static void stm32_dfsdm_dma_buffer_done(void *data)
>  	while (available >= indio_dev->scan_bytes) {
>  		s32 *buffer = (s32 *)&adc->rx_buf[adc->bufi];
>  
> -		/* Mask 8 LSB that contains the channel ID */
> -		*buffer &= 0xFFFFFF00;
> -		/* Convert 2^(n-1) sample to 2^(n-1)-1 to avoid wrap-around */
> -		if (*buffer > flo->max)
> -			*buffer -= 1;
> -		/*
> -		 * Samples from filter are retrieved with 23 bits resolution
> -		 * or less. Shift left to align MSB on 24 bits.
> -		 */
> -		*buffer <<= flo->lshift;
> +		stm32_dfsdm_process_data(adc, buffer);
>  
>  		available -= indio_dev->scan_bytes;
>  		adc->bufi += indio_dev->scan_bytes;


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 4/5] iio: adc: stm32-dfsdm: add fast mode support
  2019-06-19 13:03 ` [PATCH 4/5] iio: adc: stm32-dfsdm: add fast mode support Olivier Moysan
@ 2019-06-22  9:30   ` Jonathan Cameron
  0 siblings, 0 replies; 12+ messages in thread
From: Jonathan Cameron @ 2019-06-22  9:30 UTC (permalink / raw)
  To: Olivier Moysan
  Cc: lars, alexandre.torgue, linux-iio, pmeerw, linux-kernel,
	mcoquelin.stm32, knaack.h, fabrice.gasnier, linux-stm32,
	linux-arm-kernel, benjamin.gaignard

On Wed, 19 Jun 2019 15:03:50 +0200
Olivier Moysan <olivier.moysan@st.com> wrote:

> The use of fast mode allows to get a larger set of solution
> for filter parameters. This can be useful to reach a better
> output sample resolution, when fast mode can be used.
> 
> Fast mode is selected at startup if it is relevant.
> The startup is performed in postenable callback context,
> where there are too tight time constraints for filter parameters
> computation. For this reason both fast and non fast filter parameters
> are pre-computed previously.
> 
> Signed-off-by: Olivier Moysan <olivier.moysan@st.com>
I've no problem with precomputing these but I'm curious.
What is the use model where postenable is performance critical?

Patch looks fine to me.

Applied to the togreg branch of iio.git and pushed out as testing
for the autobuilders to play with it.

Thanks,

Jonathan

> ---
>  drivers/iio/adc/stm32-dfsdm-adc.c | 65 ++++++++++++++++++++++++++++++---------
>  drivers/iio/adc/stm32-dfsdm.h     |  4 +--
>  2 files changed, 53 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
> index 5b19a88412a6..d855a605eab6 100644
> --- a/drivers/iio/adc/stm32-dfsdm-adc.c
> +++ b/drivers/iio/adc/stm32-dfsdm-adc.c
> @@ -196,7 +196,7 @@ static int stm32_dfsdm_compute_osrs(struct stm32_dfsdm_filter *fl,
>  	int bits, shift;
>  	unsigned int m = 1;	/* multiplication factor */
>  	unsigned int p = fl->ford;	/* filter order (ford) */
> -	struct stm32_dfsdm_filter_osr *flo = &fl->flo;
> +	struct stm32_dfsdm_filter_osr *flo = &fl->flo[fast];
>  
>  	pr_debug("%s: Requested oversampling: %d\n",  __func__, oversamp);
>  	/*
> @@ -217,7 +217,6 @@ static int stm32_dfsdm_compute_osrs(struct stm32_dfsdm_filter *fl,
>  	 * Look for filter and integrator oversampling ratios which allows
>  	 * to maximize data output resolution.
>  	 */
> -	flo->res = 0;
>  	for (fosr = 1; fosr <= DFSDM_MAX_FL_OVERSAMPLING; fosr++) {
>  		for (iosr = 1; iosr <= DFSDM_MAX_INT_OVERSAMPLING; iosr++) {
>  			if (fast)
> @@ -309,6 +308,28 @@ static int stm32_dfsdm_compute_osrs(struct stm32_dfsdm_filter *fl,
>  	return 0;
>  }
>  
> +static int stm32_dfsdm_compute_all_osrs(struct iio_dev *indio_dev,
> +					unsigned int oversamp)
> +{
> +	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
> +	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
> +	int ret0, ret1;
> +
> +	memset(&fl->flo[0], 0, sizeof(fl->flo[0]));
> +	memset(&fl->flo[1], 0, sizeof(fl->flo[1]));
> +
> +	ret0 = stm32_dfsdm_compute_osrs(fl, 0, oversamp);
> +	ret1 = stm32_dfsdm_compute_osrs(fl, 1, oversamp);
> +	if (ret0 < 0 && ret1 < 0) {
> +		dev_err(&indio_dev->dev,
> +			"Filter parameters not found: errors %d/%d\n",
> +			ret0, ret1);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
>  static int stm32_dfsdm_start_channel(struct stm32_dfsdm_adc *adc)
>  {
>  	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
> @@ -433,11 +454,25 @@ static int stm32_dfsdm_channels_configure(struct stm32_dfsdm_adc *adc,
>  	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
>  	struct regmap *regmap = adc->dfsdm->regmap;
>  	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[fl_id];
> -	struct stm32_dfsdm_filter_osr *flo = &fl->flo;
> +	struct stm32_dfsdm_filter_osr *flo = &fl->flo[0];
>  	const struct iio_chan_spec *chan;
>  	unsigned int bit;
>  	int ret;
>  
> +	fl->fast = 0;
> +
> +	/*
> +	 * In continuous mode, use fast mode configuration,
> +	 * if it provides a better resolution.
> +	 */
> +	if (adc->nconv == 1 && !trig &&
> +	    (indio_dev->currentmode & INDIO_BUFFER_SOFTWARE)) {
> +		if (fl->flo[1].res >= fl->flo[0].res) {
> +			fl->fast = 1;
> +			flo = &fl->flo[1];
> +		}
> +	}
> +
>  	if (!flo->res)
>  		return -EINVAL;
>  
> @@ -463,7 +498,7 @@ static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc,
>  	struct iio_dev *indio_dev = iio_priv_to_dev(adc);
>  	struct regmap *regmap = adc->dfsdm->regmap;
>  	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[fl_id];
> -	struct stm32_dfsdm_filter_osr *flo = &fl->flo;
> +	struct stm32_dfsdm_filter_osr *flo = &fl->flo[fl->fast];
>  	u32 cr1;
>  	const struct iio_chan_spec *chan;
>  	unsigned int bit, jchg = 0;
> @@ -490,6 +525,12 @@ static int stm32_dfsdm_filter_configure(struct stm32_dfsdm_adc *adc,
>  	if (ret)
>  		return ret;
>  
> +	ret = regmap_update_bits(regmap, DFSDM_CR1(fl_id),
> +				 DFSDM_CR1_FAST_MASK,
> +				 DFSDM_CR1_FAST(fl->fast));
> +	if (ret)
> +		return ret;
> +
>  	/*
>  	 * DFSDM modes configuration W.R.T audio/iio type modes
>  	 * ----------------------------------------------------------------
> @@ -636,7 +677,6 @@ static int dfsdm_adc_set_samp_freq(struct iio_dev *indio_dev,
>  				   unsigned int spi_freq)
>  {
>  	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
> -	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
>  	unsigned int oversamp;
>  	int ret;
>  
> @@ -646,11 +686,10 @@ static int dfsdm_adc_set_samp_freq(struct iio_dev *indio_dev,
>  			"Rate not accurate. requested (%u), actual (%u)\n",
>  			sample_freq, spi_freq / oversamp);
>  
> -	ret = stm32_dfsdm_compute_osrs(fl, 0, oversamp);
> -	if (ret < 0) {
> -		dev_err(&indio_dev->dev, "No filter parameters that match!\n");
> +	ret = stm32_dfsdm_compute_all_osrs(indio_dev, oversamp);
> +	if (ret < 0)
>  		return ret;
> -	}
> +
>  	adc->sample_freq = spi_freq / oversamp;
>  	adc->oversamp = oversamp;
>  
> @@ -783,7 +822,7 @@ static inline void stm32_dfsdm_process_data(struct stm32_dfsdm_adc *adc,
>  					    s32 *buffer)
>  {
>  	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
> -	struct stm32_dfsdm_filter_osr *flo = &fl->flo;
> +	struct stm32_dfsdm_filter_osr *flo = &fl->flo[fl->fast];
>  	unsigned int i = adc->nconv;
>  	s32 *ptr = buffer;
>  
> @@ -1171,7 +1210,6 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev,
>  				 int val, int val2, long mask)
>  {
>  	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
> -	struct stm32_dfsdm_filter *fl = &adc->dfsdm->fl_list[adc->fl_id];
>  	struct stm32_dfsdm_channel *ch = &adc->dfsdm->ch_list[chan->channel];
>  	unsigned int spi_freq;
>  	int ret = -EINVAL;
> @@ -1181,7 +1219,7 @@ static int stm32_dfsdm_write_raw(struct iio_dev *indio_dev,
>  		ret = iio_device_claim_direct_mode(indio_dev);
>  		if (ret)
>  			return ret;
> -		ret = stm32_dfsdm_compute_osrs(fl, 0, val);
> +		ret = stm32_dfsdm_compute_all_osrs(indio_dev, val);
>  		if (!ret)
>  			adc->oversamp = val;
>  		iio_device_release_direct_mode(indio_dev);
> @@ -1430,8 +1468,7 @@ static int stm32_dfsdm_adc_init(struct iio_dev *indio_dev)
>  	int ret, chan_idx;
>  
>  	adc->oversamp = DFSDM_DEFAULT_OVERSAMPLING;
> -	ret = stm32_dfsdm_compute_osrs(&adc->dfsdm->fl_list[adc->fl_id], 0,
> -				       adc->oversamp);
> +	ret = stm32_dfsdm_compute_all_osrs(indio_dev, adc->oversamp);
>  	if (ret < 0)
>  		return ret;
>  
> diff --git a/drivers/iio/adc/stm32-dfsdm.h b/drivers/iio/adc/stm32-dfsdm.h
> index 18b06ee6ed7b..5dbdae4ed881 100644
> --- a/drivers/iio/adc/stm32-dfsdm.h
> +++ b/drivers/iio/adc/stm32-dfsdm.h
> @@ -263,13 +263,13 @@ struct stm32_dfsdm_filter_osr {
>  /**
>   * struct stm32_dfsdm_filter - structure relative to stm32 FDSDM filter
>   * @ford: filter order
> - * @flo: filter oversampling structure
> + * @flo: filter oversampling data table indexed by fast mode flag
>   * @sync_mode: filter synchronized with filter 0
>   * @fast: filter fast mode
>   */
>  struct stm32_dfsdm_filter {
>  	enum stm32_dfsdm_sinc_order ford;
> -	struct stm32_dfsdm_filter_osr flo;
> +	struct stm32_dfsdm_filter_osr flo[2];
>  	unsigned int sync_mode;
>  	unsigned int fast;
>  };


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH 5/5] iio: adc: stm32-dfsdm: add comment for 16 bits record
  2019-06-19 13:03 ` [PATCH 5/5] iio: adc: stm32-dfsdm: add comment for 16 bits record Olivier Moysan
@ 2019-06-22  9:33   ` Jonathan Cameron
  0 siblings, 0 replies; 12+ messages in thread
From: Jonathan Cameron @ 2019-06-22  9:33 UTC (permalink / raw)
  To: Olivier Moysan
  Cc: lars, alexandre.torgue, linux-iio, pmeerw, linux-kernel,
	mcoquelin.stm32, knaack.h, fabrice.gasnier, linux-stm32,
	linux-arm-kernel, benjamin.gaignard

On Wed, 19 Jun 2019 15:03:51 +0200
Olivier Moysan <olivier.moysan@st.com> wrote:

> Add a comment on DMA configuration for 16 bits record.
> 
> Signed-off-by: Olivier Moysan <olivier.moysan@st.com>
Applied.

Thanks,

Jonathan

> ---
>  drivers/iio/adc/stm32-dfsdm-adc.c | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
> index d855a605eab6..ee1e0569d0e1 100644
> --- a/drivers/iio/adc/stm32-dfsdm-adc.c
> +++ b/drivers/iio/adc/stm32-dfsdm-adc.c
> @@ -918,6 +918,11 @@ static void stm32_dfsdm_dma_buffer_done(void *data)
>  static int stm32_dfsdm_adc_dma_start(struct iio_dev *indio_dev)
>  {
>  	struct stm32_dfsdm_adc *adc = iio_priv(indio_dev);
> +	/*
> +	 * The DFSDM supports half-word transfers. However, for 16 bits record,
> +	 * 4 bytes buswidth is kept, to avoid losing samples LSBs when left
> +	 * shift is required.
> +	 */
>  	struct dma_slave_config config = {
>  		.src_addr = (dma_addr_t)adc->dfsdm->phys_base,
>  		.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2019-06-22  9:33 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-19 13:03 [PATCH 0/5] iio: adc: stm32-dfsdm: fix and improve output data managementiio: adc: stm32-dfsdm: fix and improve output data management Olivier Moysan
2019-06-19 13:03 ` [PATCH 1/5] iio: adc: stm32-dfsdm: fix output resolution Olivier Moysan
2019-06-22  9:18   ` Jonathan Cameron
2019-06-19 13:03 ` [PATCH 2/5] iio: adc: stm32-dfsdm: fix data type Olivier Moysan
2019-06-22  9:21   ` Jonathan Cameron
2019-06-19 13:03 ` [PATCH 3/5] iio: adc: stm32-dfsdm: manage data resolution in trigger mode Olivier Moysan
2019-06-22  9:23   ` Jonathan Cameron
2019-06-19 13:03 ` [PATCH 4/5] iio: adc: stm32-dfsdm: add fast mode support Olivier Moysan
2019-06-22  9:30   ` Jonathan Cameron
2019-06-19 13:03 ` [PATCH 5/5] iio: adc: stm32-dfsdm: add comment for 16 bits record Olivier Moysan
2019-06-22  9:33   ` Jonathan Cameron
2019-06-19 15:04 ` [PATCH 0/5] iio: adc: stm32-dfsdm: fix and improve output data managementiio: adc: stm32-dfsdm: fix and improve output data management Fabrice Gasnier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).