summaryrefslogtreecommitdiff
path: root/sound/soc/stm/stm32_sai_sub.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/stm/stm32_sai_sub.c')
-rw-r--r--sound/soc/stm/stm32_sai_sub.c33
1 files changed, 21 insertions, 12 deletions
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index 90d439613899..dde8ddf9e777 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -184,7 +184,6 @@ static const struct regmap_config stm32_sai_sub_regmap_config_h7 = {
static irqreturn_t stm32_sai_isr(int irq, void *devid)
{
struct stm32_sai_sub_data *sai = (struct stm32_sai_sub_data *)devid;
- struct snd_pcm_substream *substream = sai->substream;
struct platform_device *pdev = sai->pdev;
unsigned int sr, imr, flags;
snd_pcm_state_t status = SNDRV_PCM_STATE_RUNNING;
@@ -199,6 +198,11 @@ static irqreturn_t stm32_sai_isr(int irq, void *devid)
regmap_update_bits(sai->regmap, STM_SAI_CLRFR_REGX, SAI_XCLRFR_MASK,
SAI_XCLRFR_MASK);
+ if (!sai->substream) {
+ dev_err(&pdev->dev, "Device stopped. Spurious IRQ 0x%x\n", sr);
+ return IRQ_NONE;
+ }
+
if (flags & SAI_XIMR_OVRUDRIE) {
dev_err(&pdev->dev, "IRQ %s\n",
STM_SAI_IS_PLAYBACK(sai) ? "underrun" : "overrun");
@@ -227,9 +231,9 @@ static irqreturn_t stm32_sai_isr(int irq, void *devid)
}
if (status != SNDRV_PCM_STATE_RUNNING) {
- snd_pcm_stream_lock(substream);
- snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
- snd_pcm_stream_unlock(substream);
+ snd_pcm_stream_lock(sai->substream);
+ snd_pcm_stop(sai->substream, SNDRV_PCM_STATE_XRUN);
+ snd_pcm_stream_unlock(sai->substream);
}
return IRQ_HANDLED;
@@ -442,12 +446,16 @@ static int stm32_sai_set_config(struct snd_soc_dai *cpu_dai,
{
struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
int cr1, cr1_mask, ret;
- int fth = STM_SAI_FIFO_TH_HALF;
- /* FIFO config */
+ /*
+ * DMA bursts increment is set to 4 words.
+ * SAI fifo threshold is set to half fifo, to keep enough space
+ * for DMA incoming bursts.
+ */
regmap_update_bits(sai->regmap, STM_SAI_CR2_REGX,
SAI_XCR2_FFLUSH | SAI_XCR2_FTH_MASK,
- SAI_XCR2_FFLUSH | SAI_XCR2_FTH_SET(fth));
+ SAI_XCR2_FFLUSH |
+ SAI_XCR2_FTH_SET(STM_SAI_FIFO_TH_HALF));
/* Mode, data format and channel config */
cr1 = SAI_XCR1_PRTCFG_SET(SAI_FREE_PROTOCOL);
@@ -481,10 +489,6 @@ static int stm32_sai_set_config(struct snd_soc_dai *cpu_dai,
return ret;
}
- /* DMA config */
- sai->dma_params.maxburst = STM_SAI_FIFO_SIZE * fth / sizeof(u32);
- snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)&sai->dma_params);
-
return 0;
}
@@ -727,7 +731,12 @@ static int stm32_sai_dai_probe(struct snd_soc_dai *cpu_dai)
struct stm32_sai_sub_data *sai = dev_get_drvdata(cpu_dai->dev);
sai->dma_params.addr = (dma_addr_t)(sai->phys_addr + STM_SAI_DR_REGX);
- sai->dma_params.maxburst = 1;
+ /*
+ * DMA supports 4, 8 or 16 burst sizes. Burst size 4 is the best choice,
+ * as it allows bytes, half-word and words transfers. (See DMA fifos
+ * constraints).
+ */
+ sai->dma_params.maxburst = 4;
/* Buswidth will be set by framework at runtime */
sai->dma_params.addr_width = DMA_SLAVE_BUSWIDTH_UNDEFINED;