From cbc65d9c95088d1437a5a84c7d6628b8d27a86f1 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Tue, 28 Nov 2023 12:14:03 +0000 Subject: [PATCH] ASoC: dwc: Fix full-duplex mode Configuration of the DMA register was carelessly zeroing bits that may used by a stream in the other direction. Preserve them instead. See: https://github.com/raspberrypi/linux/issues/5741 Signed-off-by: Phil Elwell --- sound/soc/dwc/dwc-i2s.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) --- a/sound/soc/dwc/dwc-i2s.c +++ b/sound/soc/dwc/dwc-i2s.c @@ -189,10 +189,17 @@ static void dw_i2s_config(struct dw_i2s_ { struct i2s_clk_config_data *config = &dev->config; u32 ch_reg; - u32 dmacr = 0; + u32 dmacr; i2s_disable_channels(dev, stream); + dmacr = i2s_read_reg(dev->i2s_base, DMACR); + + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + dmacr &= ~(DMACR_DMAEN_TXCH0 * 0xf); + else + dmacr &= ~(DMACR_DMAEN_RXCH0 * 0xf); + for (ch_reg = 0; ch_reg < (config->chan_nr / 2); ch_reg++) { if (stream == SNDRV_PCM_STREAM_PLAYBACK) { i2s_write_reg(dev->i2s_base, TCR(ch_reg), @@ -210,10 +217,6 @@ static void dw_i2s_config(struct dw_i2s_ dmacr |= (DMACR_DMAEN_RXCH0 << ch_reg); } } - if (stream == SNDRV_PCM_STREAM_PLAYBACK) - dmacr |= DMACR_DMAEN_TX; - else if (stream == SNDRV_PCM_STREAM_CAPTURE) - dmacr |= DMACR_DMAEN_RX; i2s_write_reg(dev->i2s_base, DMACR, dmacr); } @@ -319,10 +322,13 @@ static int dw_i2s_startup(struct snd_pcm dw_i2s_config(dev, substream->stream); dmacr = i2s_read_reg(dev->i2s_base, DMACR); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dma_data = &dev->play_dma_data; - else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + dmacr |= DMACR_DMAEN_TX; + } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { dma_data = &dev->capture_dma_data; + dmacr |= DMACR_DMAEN_RX; + } snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)dma_data); i2s_write_reg(dev->i2s_base, DMACR, dmacr);