@@ -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: