Commit 19441e35 authored by Olivier Moysan's avatar Olivier Moysan Committed by Mark Brown

ASoC: stm32: dfsdm: manage multiple prepare

The DFSDM must be stopped when a new setting is applied.
restart systematically DFSDM on multiple prepare calls,
to apply changes.
Signed-off-by: default avatarOlivier Moysan <olivier.moysan@st.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent a2bcbc1b
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -37,6 +38,8 @@ struct stm32_adfsdm_priv { ...@@ -37,6 +38,8 @@ struct stm32_adfsdm_priv {
/* PCM buffer */ /* PCM buffer */
unsigned char *pcm_buff; unsigned char *pcm_buff;
unsigned int pos; unsigned int pos;
struct mutex lock; /* protect against race condition on iio state */
}; };
static const struct snd_pcm_hardware stm32_adfsdm_pcm_hw = { static const struct snd_pcm_hardware stm32_adfsdm_pcm_hw = {
...@@ -62,10 +65,12 @@ static void stm32_adfsdm_shutdown(struct snd_pcm_substream *substream, ...@@ -62,10 +65,12 @@ static void stm32_adfsdm_shutdown(struct snd_pcm_substream *substream,
{ {
struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai); struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
mutex_lock(&priv->lock);
if (priv->iio_active) { if (priv->iio_active) {
iio_channel_stop_all_cb(priv->iio_cb); iio_channel_stop_all_cb(priv->iio_cb);
priv->iio_active = false; priv->iio_active = false;
} }
mutex_unlock(&priv->lock);
} }
static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream, static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream,
...@@ -74,13 +79,19 @@ static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream, ...@@ -74,13 +79,19 @@ static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream,
struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai); struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
int ret; int ret;
mutex_lock(&priv->lock);
if (priv->iio_active) {
iio_channel_stop_all_cb(priv->iio_cb);
priv->iio_active = false;
}
ret = iio_write_channel_attribute(priv->iio_ch, ret = iio_write_channel_attribute(priv->iio_ch,
substream->runtime->rate, 0, substream->runtime->rate, 0,
IIO_CHAN_INFO_SAMP_FREQ); IIO_CHAN_INFO_SAMP_FREQ);
if (ret < 0) { if (ret < 0) {
dev_err(dai->dev, "%s: Failed to set %d sampling rate\n", dev_err(dai->dev, "%s: Failed to set %d sampling rate\n",
__func__, substream->runtime->rate); __func__, substream->runtime->rate);
return ret; goto out;
} }
if (!priv->iio_active) { if (!priv->iio_active) {
...@@ -92,6 +103,9 @@ static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream, ...@@ -92,6 +103,9 @@ static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream,
__func__, ret); __func__, ret);
} }
out:
mutex_unlock(&priv->lock);
return ret; return ret;
} }
...@@ -299,6 +313,7 @@ static int stm32_adfsdm_probe(struct platform_device *pdev) ...@@ -299,6 +313,7 @@ static int stm32_adfsdm_probe(struct platform_device *pdev)
priv->dev = &pdev->dev; priv->dev = &pdev->dev;
priv->dai_drv = stm32_adfsdm_dai; priv->dai_drv = stm32_adfsdm_dai;
mutex_init(&priv->lock);
dev_set_drvdata(&pdev->dev, priv); dev_set_drvdata(&pdev->dev, priv);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment