Skip to content

Commit

Permalink
ASoC: q6asm: make commands specific to streams
Browse files Browse the repository at this point in the history
Each ASM session can have multiple streams attached to it,
current design was to allow only one static stream id 1 per each session.
However for use-case like gapless, we would need 2 streams to open per session.

This patch converts all the q6asm apis to take stream id as argument
to allow multiple streams to open on a single session, This is useful
for gapless playback cases.

Now the dai driver can specify which stream id for each command.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Tested-by: Vinod Koul <vkoul@kernel.org>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Reviewed-by: Vinod Koul <vkoul@kernel.org>
Link: https://lore.kernel.org/r/20200727093806.17089-3-srinivas.kandagatla@linaro.org
Signed-off-by: Mark Brown <broonie@kernel.org>
  • Loading branch information
Srinivas Kandagatla authored and Mark Brown committed Aug 17, 2020
1 parent 99b7db5 commit 789e3b6
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 80 deletions.
79 changes: 52 additions & 27 deletions sound/soc/qcom/qdsp6/q6asm-dai.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ struct q6asm_dai_rtd {
uint16_t bits_per_sample;
uint16_t source; /* Encoding source bit mask */
struct audio_client *audio_client;
uint32_t stream_id;
uint16_t session_id;
enum stream_state state;
};
Expand Down Expand Up @@ -181,7 +182,7 @@ static void event_handler(uint32_t opcode, uint32_t token,
switch (opcode) {
case ASM_CLIENT_EVENT_CMD_RUN_DONE:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
q6asm_write_async(prtd->audio_client,
q6asm_write_async(prtd->audio_client, prtd->stream_id,
prtd->pcm_count, 0, 0, NO_TIMESTAMP);
break;
case ASM_CLIENT_EVENT_CMD_EOS_DONE:
Expand All @@ -191,7 +192,7 @@ static void event_handler(uint32_t opcode, uint32_t token,
prtd->pcm_irq_pos += prtd->pcm_count;
snd_pcm_period_elapsed(substream);
if (prtd->state == Q6ASM_STREAM_RUNNING)
q6asm_write_async(prtd->audio_client,
q6asm_write_async(prtd->audio_client, prtd->stream_id,
prtd->pcm_count, 0, 0, NO_TIMESTAMP);

break;
Expand All @@ -200,7 +201,7 @@ static void event_handler(uint32_t opcode, uint32_t token,
prtd->pcm_irq_pos += prtd->pcm_count;
snd_pcm_period_elapsed(substream);
if (prtd->state == Q6ASM_STREAM_RUNNING)
q6asm_read(prtd->audio_client);
q6asm_read(prtd->audio_client, prtd->stream_id);

break;
default:
Expand Down Expand Up @@ -233,7 +234,7 @@ static int q6asm_dai_prepare(struct snd_soc_component *component,
/* rate and channels are sent to audio driver */
if (prtd->state) {
/* clear the previous setup if any */
q6asm_cmd(prtd->audio_client, CMD_CLOSE);
q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
q6asm_unmap_memory_regions(substream->stream,
prtd->audio_client);
q6routing_stream_close(soc_prtd->dai_link->id,
Expand All @@ -252,11 +253,13 @@ static int q6asm_dai_prepare(struct snd_soc_component *component,
}

if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
ret = q6asm_open_write(prtd->audio_client, FORMAT_LINEAR_PCM,
ret = q6asm_open_write(prtd->audio_client, prtd->stream_id,
FORMAT_LINEAR_PCM,
0, prtd->bits_per_sample);
} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM,
prtd->bits_per_sample);
ret = q6asm_open_read(prtd->audio_client, prtd->stream_id,
FORMAT_LINEAR_PCM,
prtd->bits_per_sample);
}

if (ret < 0) {
Expand All @@ -276,17 +279,19 @@ static int q6asm_dai_prepare(struct snd_soc_component *component,

if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
ret = q6asm_media_format_block_multi_ch_pcm(
prtd->audio_client, runtime->rate,
runtime->channels, NULL,
prtd->audio_client, prtd->stream_id,
runtime->rate, runtime->channels, NULL,
prtd->bits_per_sample);
} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
ret = q6asm_enc_cfg_blk_pcm_format_support(prtd->audio_client,
runtime->rate, runtime->channels,
prtd->bits_per_sample);
prtd->stream_id,
runtime->rate,
runtime->channels,
prtd->bits_per_sample);

/* Queue the buffers */
for (i = 0; i < runtime->periods; i++)
q6asm_read(prtd->audio_client);
q6asm_read(prtd->audio_client, prtd->stream_id);

}
if (ret < 0)
Expand All @@ -308,15 +313,18 @@ static int q6asm_dai_trigger(struct snd_soc_component *component,
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
ret = q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
ret = q6asm_run_nowait(prtd->audio_client, prtd->stream_id,
0, 0, 0);
break;
case SNDRV_PCM_TRIGGER_STOP:
prtd->state = Q6ASM_STREAM_STOPPED;
ret = q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
CMD_EOS);
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
ret = q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
CMD_PAUSE);
break;
default:
ret = -EINVAL;
Expand Down Expand Up @@ -361,6 +369,9 @@ static int q6asm_dai_open(struct snd_soc_component *component,
return ret;
}

/* DSP expects stream id from 1 */
prtd->stream_id = 1;

if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
runtime->hw = q6asm_dai_hardware_playback;
else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
Expand Down Expand Up @@ -427,7 +438,8 @@ static int q6asm_dai_close(struct snd_soc_component *component,

if (prtd->audio_client) {
if (prtd->state)
q6asm_cmd(prtd->audio_client, CMD_CLOSE);
q6asm_cmd(prtd->audio_client, prtd->stream_id,
CMD_CLOSE);

q6asm_unmap_memory_regions(substream->stream,
prtd->audio_client);
Expand Down Expand Up @@ -499,8 +511,8 @@ static void compress_event_handler(uint32_t opcode, uint32_t token,
case ASM_CLIENT_EVENT_CMD_RUN_DONE:
spin_lock_irqsave(&prtd->lock, flags);
if (!prtd->bytes_sent) {
q6asm_write_async(prtd->audio_client, prtd->pcm_count,
0, 0, NO_TIMESTAMP);
q6asm_write_async(prtd->audio_client, prtd->stream_id,
prtd->pcm_count, 0, 0, NO_TIMESTAMP);
prtd->bytes_sent += prtd->pcm_count;
}

Expand All @@ -525,7 +537,7 @@ static void compress_event_handler(uint32_t opcode, uint32_t token,
avail = prtd->bytes_received - prtd->bytes_sent;

if (avail >= prtd->pcm_count) {
q6asm_write_async(prtd->audio_client,
q6asm_write_async(prtd->audio_client, prtd->stream_id,
prtd->pcm_count, 0, 0, NO_TIMESTAMP);
prtd->bytes_sent += prtd->pcm_count;
}
Expand Down Expand Up @@ -560,6 +572,9 @@ static int q6asm_dai_compr_open(struct snd_soc_component *component,
if (!prtd)
return -ENOMEM;

/* DSP expects stream id from 1 */
prtd->stream_id = 1;

prtd->cstream = stream;
prtd->audio_client = q6asm_audio_client_alloc(dev,
(q6asm_cb)compress_event_handler,
Expand Down Expand Up @@ -607,7 +622,8 @@ static int q6asm_dai_compr_free(struct snd_soc_component *component,

if (prtd->audio_client) {
if (prtd->state)
q6asm_cmd(prtd->audio_client, CMD_CLOSE);
q6asm_cmd(prtd->audio_client, prtd->stream_id,
CMD_CLOSE);

snd_dma_free_pages(&prtd->dma_buffer);
q6asm_unmap_memory_regions(stream->direction,
Expand Down Expand Up @@ -662,8 +678,9 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component,
prtd->pcm_size = runtime->fragments * runtime->fragment_size;
prtd->bits_per_sample = 16;
if (dir == SND_COMPRESS_PLAYBACK) {
ret = q6asm_open_write(prtd->audio_client, params->codec.id,
params->codec.profile, prtd->bits_per_sample);
ret = q6asm_open_write(prtd->audio_client, prtd->stream_id,
params->codec.id, params->codec.profile,
prtd->bits_per_sample);

if (ret < 0) {
dev_err(dev, "q6asm_open_write failed\n");
Expand Down Expand Up @@ -697,6 +714,7 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component,
flac_cfg.min_frame_size = flac->min_frame_size;

ret = q6asm_stream_media_format_block_flac(prtd->audio_client,
prtd->stream_id,
&flac_cfg);
if (ret < 0) {
dev_err(dev, "FLAC CMD Format block failed:%d\n", ret);
Expand Down Expand Up @@ -756,10 +774,12 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component,

if (wma_v9)
ret = q6asm_stream_media_format_block_wma_v9(
prtd->audio_client, &wma_cfg);
prtd->audio_client, prtd->stream_id,
&wma_cfg);
else
ret = q6asm_stream_media_format_block_wma_v10(
prtd->audio_client, &wma_cfg);
prtd->audio_client, prtd->stream_id,
&wma_cfg);
if (ret < 0) {
dev_err(dev, "WMA9 CMD failed:%d\n", ret);
return -EIO;
Expand Down Expand Up @@ -792,6 +812,7 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component,
break;
}
ret = q6asm_stream_media_format_block_alac(prtd->audio_client,
prtd->stream_id,
&alac_cfg);
if (ret < 0) {
dev_err(dev, "ALAC CMD Format block failed:%d\n", ret);
Expand All @@ -816,6 +837,7 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component,
ape_cfg.seek_table_present = ape->seek_table_present;

ret = q6asm_stream_media_format_block_ape(prtd->audio_client,
prtd->stream_id,
&ape_cfg);
if (ret < 0) {
dev_err(dev, "APE CMD Format block failed:%d\n", ret);
Expand Down Expand Up @@ -852,15 +874,18 @@ static int q6asm_dai_compr_trigger(struct snd_soc_component *component,
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
ret = q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
ret = q6asm_run_nowait(prtd->audio_client, prtd->stream_id,
0, 0, 0);
break;
case SNDRV_PCM_TRIGGER_STOP:
prtd->state = Q6ASM_STREAM_STOPPED;
ret = q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
CMD_EOS);
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
ret = q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
CMD_PAUSE);
break;
default:
ret = -EINVAL;
Expand Down
Loading

0 comments on commit 789e3b6

Please sign in to comment.