summaryrefslogtreecommitdiff
path: root/sound/soc
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/stm/stm32_i2s.c87
1 files changed, 46 insertions, 41 deletions
diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c
index 22152a1ca733..8052629a89df 100644
--- a/sound/soc/stm/stm32_i2s.c
+++ b/sound/soc/stm/stm32_i2s.c
@@ -489,7 +489,6 @@ static int stm32_i2s_configure(struct snd_soc_dai *cpu_dai,
struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
int format = params_width(params);
u32 cfgr, cfgr_mask, cfg1, cfg1_mask;
- bool playback_flg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
unsigned int fthlv;
int ret;
@@ -515,19 +514,13 @@ static int stm32_i2s_configure(struct snd_soc_dai *cpu_dai,
}
if (STM32_I2S_IS_SLAVE(i2s)) {
- if (playback_flg)
- cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_TX_SLAVE);
- else
- cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_RX_SLAVE);
+ cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_FD_SLAVE);
/* As data length is either 16 or 32 bits, fixch always set */
cfgr |= I2S_CGFR_FIXCH;
cfgr_mask |= I2S_CGFR_FIXCH;
} else {
- if (playback_flg)
- cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_TX_MASTER);
- else
- cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_RX_MASTER);
+ cfgr |= I2S_CGFR_I2SCFG_SET(I2S_I2SMOD_FD_MASTER);
}
cfgr_mask |= I2S_CGFR_I2SCFG_MASK;
@@ -536,9 +529,7 @@ static int stm32_i2s_configure(struct snd_soc_dai *cpu_dai,
if (ret < 0)
return ret;
- cfg1 = I2S_CFG1_RXDMAEN;
- if (playback_flg)
- cfg1 = I2S_CFG1_TXDMAEN;
+ cfg1 = I2S_CFG1_RXDMAEN | I2S_CFG1_TXDMAEN;
cfg1_mask = cfg1;
fthlv = STM32_I2S_FIFO_SIZE * I2S_FIFO_TH_ONE_QUARTER / 4;
@@ -553,32 +544,15 @@ static int stm32_i2s_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
- int ret, ier;
i2s->substream = substream;
spin_lock(&i2s->lock_fd);
- if (i2s->refcount) {
- dev_err(cpu_dai->dev, "%s stream already started\n",
- (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- "Capture" : "Playback"));
- spin_unlock(&i2s->lock_fd);
- return -EBUSY;
- }
- i2s->refcount = 1;
+ i2s->refcount++;
spin_unlock(&i2s->lock_fd);
- ret = regmap_update_bits(i2s->regmap, STM32_I2S_IFCR_REG,
- I2S_IFCR_MASK, I2S_IFCR_MASK);
- if (ret < 0)
- return ret;
-
- /* Enable ITs */
- ier = I2S_IER_OVRIE | I2S_IER_UDRIE;
- if (STM32_I2S_IS_SLAVE(i2s))
- ier |= I2S_IER_TIFREIE;
-
- return regmap_update_bits(i2s->regmap, STM32_I2S_IER_REG, ier, ier);
+ return regmap_update_bits(i2s->regmap, STM32_I2S_IFCR_REG,
+ I2S_IFCR_MASK, I2S_IFCR_MASK);
}
static int stm32_i2s_hw_params(struct snd_pcm_substream *substream,
@@ -605,7 +579,7 @@ static int stm32_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
{
struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
bool playback_flg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
- u32 cfg1_mask;
+ u32 cfg1_mask, ier;
int ret;
switch (cmd) {
@@ -628,10 +602,48 @@ static int stm32_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
dev_err(cpu_dai->dev, "Error %d starting I2S\n", ret);
return ret;
}
+
+ regmap_update_bits(i2s->regmap, STM32_I2S_IFCR_REG,
+ I2S_IFCR_MASK, I2S_IFCR_MASK);
+
+ if (playback_flg) {
+ ier = I2S_IER_UDRIE;
+ } else {
+ ier = I2S_IER_OVRIE;
+
+ spin_lock(&i2s->lock_fd);
+ if (i2s->refcount == 1)
+ /* dummy write to trigger capture */
+ regmap_write(i2s->regmap,
+ STM32_I2S_TXDR_REG, 0);
+ spin_unlock(&i2s->lock_fd);
+ }
+
+ if (STM32_I2S_IS_SLAVE(i2s))
+ ier |= I2S_IER_TIFREIE;
+
+ regmap_update_bits(i2s->regmap, STM32_I2S_IER_REG, ier, ier);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ if (playback_flg)
+ regmap_update_bits(i2s->regmap, STM32_I2S_IER_REG,
+ I2S_IER_UDRIE,
+ (unsigned int)~I2S_IER_UDRIE);
+ else
+ regmap_update_bits(i2s->regmap, STM32_I2S_IER_REG,
+ I2S_IER_OVRIE,
+ (unsigned int)~I2S_IER_OVRIE);
+
+ spin_lock(&i2s->lock_fd);
+ i2s->refcount--;
+ if (i2s->refcount) {
+ spin_unlock(&i2s->lock_fd);
+ break;
+ }
+ spin_unlock(&i2s->lock_fd);
+
dev_dbg(cpu_dai->dev, "stop I2S\n");
ret = regmap_update_bits(i2s->regmap, STM32_I2S_CR1_REG,
@@ -641,10 +653,7 @@ static int stm32_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
return ret;
}
- cfg1_mask = I2S_CFG1_RXDMAEN;
- if (playback_flg)
- cfg1_mask = I2S_CFG1_TXDMAEN;
-
+ cfg1_mask = I2S_CFG1_RXDMAEN | I2S_CFG1_TXDMAEN;
regmap_update_bits(i2s->regmap, STM32_I2S_CFG1_REG,
cfg1_mask, 0);
break;
@@ -662,10 +671,6 @@ static void stm32_i2s_shutdown(struct snd_pcm_substream *substream,
i2s->substream = NULL;
- spin_lock(&i2s->lock_fd);
- i2s->refcount = 0;
- spin_unlock(&i2s->lock_fd);
-
regmap_update_bits(i2s->regmap, STM32_I2S_CGFR_REG,
I2S_CGFR_MCKOE, (unsigned int)~I2S_CGFR_MCKOE);
}