modified prepare,trigger and pointer callbacks for bt i2s instance.
Signed-off-by: Vijendar Mukunda Vijendar.Mukunda@amd.com Reviewed-by: Alex Deucher alexander.deucher@amd.com --- sound/soc/amd/acp-pcm-dma.c | 231 +++++++++++++++++++++++++++++++++----------- 1 file changed, 172 insertions(+), 59 deletions(-)
diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c index b1c1ff2..0e2dc05 100644 --- a/sound/soc/amd/acp-pcm-dma.c +++ b/sound/soc/amd/acp-pcm-dma.c @@ -947,23 +947,43 @@ static int acp_dma_hw_free(struct snd_pcm_substream *substream) return snd_pcm_lib_free_pages(substream); }
-static u64 acp_get_byte_count(void __iomem *acp_mmio, int stream) +static u64 acp_get_byte_count(void __iomem *acp_mmio, u16 instance, int stream) { union acp_dma_count playback_dma_count; union acp_dma_count capture_dma_count; u64 bytescount = 0;
if (stream == SNDRV_PCM_STREAM_PLAYBACK) { - playback_dma_count.bcount.high = acp_reg_read(acp_mmio, - mmACP_I2S_TRANSMIT_BYTE_CNT_HIGH); - playback_dma_count.bcount.low = acp_reg_read(acp_mmio, - mmACP_I2S_TRANSMIT_BYTE_CNT_LOW); + switch (instance) { + case I2S_BT_INSTANCE: + playback_dma_count.bcount.high = acp_reg_read(acp_mmio, + mmACP_I2S_BT_TRANSMIT_BYTE_CNT_HIGH); + playback_dma_count.bcount.low = acp_reg_read(acp_mmio, + mmACP_I2S_BT_TRANSMIT_BYTE_CNT_LOW); + break; + case I2S_SP_INSTANCE: + default: + playback_dma_count.bcount.high = acp_reg_read(acp_mmio, + mmACP_I2S_TRANSMIT_BYTE_CNT_HIGH); + playback_dma_count.bcount.low = acp_reg_read(acp_mmio, + mmACP_I2S_TRANSMIT_BYTE_CNT_LOW); + } bytescount = playback_dma_count.bytescount; } else { - capture_dma_count.bcount.high = acp_reg_read(acp_mmio, - mmACP_I2S_RECEIVED_BYTE_CNT_HIGH); - capture_dma_count.bcount.low = acp_reg_read(acp_mmio, - mmACP_I2S_RECEIVED_BYTE_CNT_LOW); + switch (instance) { + case I2S_BT_INSTANCE: + capture_dma_count.bcount.high = acp_reg_read(acp_mmio, + mmACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH); + capture_dma_count.bcount.low = acp_reg_read(acp_mmio, + mmACP_I2S_BT_RECEIVE_BYTE_CNT_LOW); + break; + case I2S_SP_INSTANCE: + default: + capture_dma_count.bcount.high = acp_reg_read(acp_mmio, + mmACP_I2S_RECEIVED_BYTE_CNT_HIGH); + capture_dma_count.bcount.low = acp_reg_read(acp_mmio, + mmACP_I2S_RECEIVED_BYTE_CNT_LOW); + } bytescount = capture_dma_count.bytescount; } return bytescount; @@ -982,14 +1002,32 @@ static snd_pcm_uframes_t acp_dma_pointer(struct snd_pcm_substream *substream) return -EINVAL;
buffersize = frames_to_bytes(runtime, runtime->buffer_size); - bytescount = acp_get_byte_count(rtd->acp_mmio, substream->stream); - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (bytescount > rtd->i2ssp_renderbytescount) - bytescount = bytescount - rtd->i2ssp_renderbytescount; + bytescount = acp_get_byte_count(rtd->acp_mmio, + rtd->i2s_play_instance, substream->stream); + switch (rtd->i2s_play_instance) { + case I2S_BT_INSTANCE: + if (bytescount > rtd->i2sbt_renderbytescount) + bytescount = bytescount - rtd->i2sbt_renderbytescount; + break; + case I2S_SP_INSTANCE: + default: + if (bytescount > rtd->i2ssp_renderbytescount) + bytescount = bytescount - rtd->i2ssp_renderbytescount; + } } else { - if (bytescount > rtd->i2ssp_capturebytescount) - bytescount = bytescount - rtd->i2ssp_capturebytescount; + bytescount = acp_get_byte_count(rtd->acp_mmio, + rtd->i2s_capture_instance, substream->stream); + switch (rtd->i2s_capture_instance) { + case I2S_BT_INSTANCE: + if (bytescount > rtd->i2sbt_capturebytescount) + bytescount = bytescount - rtd->i2sbt_capturebytescount; + break; + case I2S_SP_INSTANCE: + default: + if (bytescount > rtd->i2ssp_capturebytescount) + bytescount = bytescount - rtd->i2ssp_capturebytescount; + } } pos = do_div(bytescount, buffersize); return bytes_to_frames(runtime, pos); @@ -1003,25 +1041,54 @@ static int acp_dma_mmap(struct snd_pcm_substream *substream,
static int acp_dma_prepare(struct snd_pcm_substream *substream) { + u16 start_dscr_idx; struct snd_pcm_runtime *runtime = substream->runtime; struct audio_substream_data *rtd = runtime->private_data;
if (!rtd) return -EINVAL; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - config_acp_dma_channel(rtd->acp_mmio, SYSRAM_TO_ACP_CH_NUM, - PLAYBACK_START_DMA_DESCR_CH12, - NUM_DSCRS_PER_CHANNEL, 0); - config_acp_dma_channel(rtd->acp_mmio, ACP_TO_I2S_DMA_CH_NUM, - PLAYBACK_START_DMA_DESCR_CH13, - NUM_DSCRS_PER_CHANNEL, 0); + switch (rtd->i2s_play_instance) { + case I2S_BT_INSTANCE: + start_dscr_idx = PLAYBACK_START_DMA_DESCR_CH8; + config_acp_dma_channel(rtd->acp_mmio, SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM, + start_dscr_idx, + NUM_DSCRS_PER_CHANNEL, 0); + config_acp_dma_channel(rtd->acp_mmio, ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM, + start_dscr_idx + 2, + NUM_DSCRS_PER_CHANNEL, 0); + break; + case I2S_SP_INSTANCE: + default: + start_dscr_idx = PLAYBACK_START_DMA_DESCR_CH12; + config_acp_dma_channel(rtd->acp_mmio, SYSRAM_TO_ACP_CH_NUM, + start_dscr_idx, + NUM_DSCRS_PER_CHANNEL, 0); + config_acp_dma_channel(rtd->acp_mmio, ACP_TO_I2S_DMA_CH_NUM, + start_dscr_idx + 2, + NUM_DSCRS_PER_CHANNEL, 0); + } } else { - config_acp_dma_channel(rtd->acp_mmio, ACP_TO_SYSRAM_CH_NUM, - CAPTURE_START_DMA_DESCR_CH14, - NUM_DSCRS_PER_CHANNEL, 0); - config_acp_dma_channel(rtd->acp_mmio, I2S_TO_ACP_DMA_CH_NUM, - CAPTURE_START_DMA_DESCR_CH15, - NUM_DSCRS_PER_CHANNEL, 0); + switch (rtd->i2s_capture_instance) { + case I2S_BT_INSTANCE: + start_dscr_idx = CAPTURE_START_DMA_DESCR_CH10; + config_acp_dma_channel(rtd->acp_mmio, ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM, + start_dscr_idx, + NUM_DSCRS_PER_CHANNEL, 0); + config_acp_dma_channel(rtd->acp_mmio, I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM, + start_dscr_idx + 2, + NUM_DSCRS_PER_CHANNEL, 0); + break; + case I2S_SP_INSTANCE: + default: + start_dscr_idx = CAPTURE_START_DMA_DESCR_CH14; + config_acp_dma_channel(rtd->acp_mmio, ACP_TO_SYSRAM_CH_NUM, + start_dscr_idx, + NUM_DSCRS_PER_CHANNEL, 0); + config_acp_dma_channel(rtd->acp_mmio, I2S_TO_ACP_DMA_CH_NUM, + start_dscr_idx + 2, + NUM_DSCRS_PER_CHANNEL, 0); + } } return 0; } @@ -1043,50 +1110,96 @@ static int acp_dma_trigger(struct snd_pcm_substream *substream, int cmd) case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: case SNDRV_PCM_TRIGGER_RESUME: - bytescount = acp_get_byte_count(rtd->acp_mmio, - substream->stream); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - if (rtd->i2ssp_renderbytescount == 0) - rtd->i2ssp_renderbytescount = bytescount; - acp_dma_start(rtd->acp_mmio, - SYSRAM_TO_ACP_CH_NUM, false); - while (acp_reg_read(rtd->acp_mmio, mmACP_DMA_CH_STS) & - BIT(SYSRAM_TO_ACP_CH_NUM)) { - if (!loops--) { - dev_err(component->dev, - "acp dma start timeout\n"); - return -ETIMEDOUT; + bytescount = acp_get_byte_count(rtd->acp_mmio, + rtd->i2s_play_instance, + substream->stream); + switch (rtd->i2s_play_instance) { + case I2S_BT_INSTANCE: + if (rtd->i2sbt_renderbytescount == 0) + rtd->i2sbt_renderbytescount = bytescount; + acp_dma_start(rtd->acp_mmio, + SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM, false); + while (acp_reg_read(rtd->acp_mmio, mmACP_DMA_CH_STS) & + BIT(SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM)) { + if (!loops--) { + dev_err(component->dev, + "acp dma start timeout\n"); + return -ETIMEDOUT; + } + cpu_relax(); } - cpu_relax(); - } - - acp_dma_start(rtd->acp_mmio, + acp_dma_start(rtd->acp_mmio, + ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM, true); + break; + case I2S_SP_INSTANCE: + default: + if (rtd->i2ssp_renderbytescount == 0) + rtd->i2ssp_renderbytescount = bytescount; + acp_dma_start(rtd->acp_mmio, + SYSRAM_TO_ACP_CH_NUM, false); + while (acp_reg_read(rtd->acp_mmio, mmACP_DMA_CH_STS) & + BIT(SYSRAM_TO_ACP_CH_NUM)) { + if (!loops--) { + dev_err(component->dev, + "acp dma start timeout\n"); + return -ETIMEDOUT; + } + cpu_relax(); + } + acp_dma_start(rtd->acp_mmio, ACP_TO_I2S_DMA_CH_NUM, true); - + } } else { - if (rtd->i2ssp_capturebytescount == 0) - rtd->i2ssp_capturebytescount = bytescount; - acp_dma_start(rtd->acp_mmio, - I2S_TO_ACP_DMA_CH_NUM, true); + bytescount = acp_get_byte_count(rtd->acp_mmio, + rtd->i2s_capture_instance, + substream->stream); + switch (rtd->i2s_capture_instance) { + case I2S_BT_INSTANCE: + if (rtd->i2sbt_capturebytescount == 0) + rtd->i2sbt_capturebytescount = 0; + acp_dma_start(rtd->acp_mmio, + I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM, true); + break; + case I2S_SP_INSTANCE: + default: + if (rtd->i2ssp_capturebytescount == 0) + rtd->i2ssp_capturebytescount = bytescount; + acp_dma_start(rtd->acp_mmio, + I2S_TO_ACP_DMA_CH_NUM, true); + } } ret = 0; break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_SUSPEND: - /* Need to stop only circular DMA channels : - * ACP_TO_I2S_DMA_CH_NUM / I2S_TO_ACP_DMA_CH_NUM. Non-circular - * channels will stopped automatically after its transfer - * completes : SYSRAM_TO_ACP_CH_NUM / ACP_TO_SYSRAM_CH_NUM - */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { - ret = acp_dma_stop(rtd->acp_mmio, - ACP_TO_I2S_DMA_CH_NUM); - rtd->i2ssp_renderbytescount = 0; + switch (rtd->i2s_play_instance) { + case I2S_BT_INSTANCE: + ret = acp_dma_stop(rtd->acp_mmio, + ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM); + rtd->i2sbt_renderbytescount = 0; + break; + case I2S_SP_INSTANCE: + default: + ret = acp_dma_stop(rtd->acp_mmio, + ACP_TO_I2S_DMA_CH_NUM); + rtd->i2ssp_renderbytescount = 0; + } } else { - ret = acp_dma_stop(rtd->acp_mmio, - I2S_TO_ACP_DMA_CH_NUM); - rtd->i2ssp_capturebytescount = 0; + switch (rtd->i2s_capture_instance) { + case I2S_BT_INSTANCE: + ret = acp_dma_stop(rtd->acp_mmio, + I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM); + rtd->i2sbt_capturebytescount = 0; + break; + case I2S_SP_INSTANCE: + default: + ret = acp_dma_stop(rtd->acp_mmio, + I2S_TO_ACP_DMA_CH_NUM); + rtd->i2ssp_capturebytescount = 0; + } } break; default: