Skip to content

Commit a42e988

Browse files
fidomaxbroonie
authored andcommitted
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>
1 parent 0247488 commit a42e988

2 files changed

Lines changed: 43 additions & 2 deletions

File tree

sound/soc/dwc/dwc-i2s.c

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,19 +150,51 @@ static irqreturn_t i2s_irq_handler(int irq, void *dev_id)
150150
return IRQ_NONE;
151151
}
152152

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+
153181
static void i2s_start(struct dw_i2s_dev *dev,
154182
struct snd_pcm_substream *substream)
155183
{
156184
struct i2s_clk_config_data *config = &dev->config;
157185

158186
i2s_write_reg(dev->i2s_base, IER, 1);
159-
i2s_enable_irqs(dev, substream->stream, config->chan_nr);
160187

161188
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
162189
i2s_write_reg(dev->i2s_base, ITER, 1);
163190
else
164191
i2s_write_reg(dev->i2s_base, IRER, 1);
165192

193+
if (dev->use_pio)
194+
i2s_enable_irqs(dev, substream->stream, config->chan_nr);
195+
else
196+
i2s_enable_dma(dev, substream->stream);
197+
166198
i2s_write_reg(dev->i2s_base, CER, 1);
167199
}
168200

@@ -176,7 +208,10 @@ static void i2s_stop(struct dw_i2s_dev *dev,
176208
else
177209
i2s_write_reg(dev->i2s_base, IRER, 0);
178210

179-
i2s_disable_irqs(dev, substream->stream, 8);
211+
if (dev->use_pio)
212+
i2s_disable_irqs(dev, substream->stream, 8);
213+
else
214+
i2s_disable_dma(dev, substream->stream);
180215

181216
if (!dev->active) {
182217
i2s_write_reg(dev->i2s_base, CER, 0);

sound/soc/dwc/local.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@
5353
#define I2S_COMP_VERSION 0x01F8
5454
#define I2S_COMP_TYPE 0x01FC
5555

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+
5662
/*
5763
* Component parameter register fields - define the I2S block's
5864
* configuration.

0 commit comments

Comments
 (0)