Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ASoC: dwc: add DMA handshake control

DMA mode uses hardware handshake signals. DMACR register is used to enable
the DMA Controller interface operation. So add DMA enable/disable to
i2s_start()/i2s_stop() functions if using DMA mode.

Signed-off-by: Maxim Kochetkov <fido_max@inbox.ru>
Link: https://lore.kernel.org/r/20230613191910.725049-1-fido_max@inbox.ru
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Maxim Kochetkov and committed by
Mark Brown
a42e988b 02474880

+43 -2
+37 -2
sound/soc/dwc/dwc-i2s.c
··· 150 150 return IRQ_NONE; 151 151 } 152 152 153 + static void i2s_enable_dma(struct dw_i2s_dev *dev, u32 stream) 154 + { 155 + u32 dma_reg = i2s_read_reg(dev->i2s_base, I2S_DMACR); 156 + 157 + /* Enable DMA handshake for stream */ 158 + if (stream == SNDRV_PCM_STREAM_PLAYBACK) 159 + dma_reg |= I2S_DMAEN_TXBLOCK; 160 + else 161 + dma_reg |= I2S_DMAEN_RXBLOCK; 162 + 163 + i2s_write_reg(dev->i2s_base, I2S_DMACR, dma_reg); 164 + } 165 + 166 + static void i2s_disable_dma(struct dw_i2s_dev *dev, u32 stream) 167 + { 168 + u32 dma_reg = i2s_read_reg(dev->i2s_base, I2S_DMACR); 169 + 170 + /* Disable DMA handshake for stream */ 171 + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { 172 + dma_reg &= ~I2S_DMAEN_TXBLOCK; 173 + i2s_write_reg(dev->i2s_base, I2S_RTXDMA, 1); 174 + } else { 175 + dma_reg &= ~I2S_DMAEN_RXBLOCK; 176 + i2s_write_reg(dev->i2s_base, I2S_RRXDMA, 1); 177 + } 178 + i2s_write_reg(dev->i2s_base, I2S_DMACR, dma_reg); 179 + } 180 + 153 181 static void i2s_start(struct dw_i2s_dev *dev, 154 182 struct snd_pcm_substream *substream) 155 183 { 156 184 struct i2s_clk_config_data *config = &dev->config; 157 185 158 186 i2s_write_reg(dev->i2s_base, IER, 1); 159 - i2s_enable_irqs(dev, substream->stream, config->chan_nr); 160 187 161 188 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 162 189 i2s_write_reg(dev->i2s_base, ITER, 1); 163 190 else 164 191 i2s_write_reg(dev->i2s_base, IRER, 1); 192 + 193 + if (dev->use_pio) 194 + i2s_enable_irqs(dev, substream->stream, config->chan_nr); 195 + else 196 + i2s_enable_dma(dev, substream->stream); 165 197 166 198 i2s_write_reg(dev->i2s_base, CER, 1); 167 199 } ··· 208 176 else 209 177 i2s_write_reg(dev->i2s_base, IRER, 0); 210 178 211 - i2s_disable_irqs(dev, substream->stream, 8); 179 + if (dev->use_pio) 180 + i2s_disable_irqs(dev, substream->stream, 8); 181 + else 182 + i2s_disable_dma(dev, substream->stream); 212 183 213 184 if (!dev->active) { 214 185 i2s_write_reg(dev->i2s_base, CER, 0);
+6
sound/soc/dwc/local.h
··· 53 53 #define I2S_COMP_VERSION 0x01F8 54 54 #define I2S_COMP_TYPE 0x01FC 55 55 56 + #define I2S_RRXDMA 0x01C4 57 + #define I2S_RTXDMA 0x01CC 58 + #define I2S_DMACR 0x0200 59 + #define I2S_DMAEN_RXBLOCK (1 << 16) 60 + #define I2S_DMAEN_TXBLOCK (1 << 17) 61 + 56 62 /* 57 63 * Component parameter register fields - define the I2S block's 58 64 * configuration.