From 4e914c4dc48b6ba8d9cc92a3d788bf80aceea102 Mon Sep 17 00:00:00 2001 From: Deepa Madiregama Date: Fri, 23 May 2014 15:23:51 +0530 Subject: ASoC: Tegra: Add support for effects capture Add capture node to get the effects data from AVP Bug 1399923 Change-Id: I854de0966a40fe7867001a25058626da63b87b92 Signed-off-by: Deepa Madiregama Reviewed-on: http://git-master/r/414091 Reviewed-by: Emad Mir Tested-by: Emad Mir --- sound/soc/tegra/tegra30_avp.c | 154 ++++++++++++++++++++++++++--- sound/soc/tegra/tegra_offload.c | 212 +++++++++++++++++++++++++++------------- sound/soc/tegra/tegra_offload.h | 3 +- sound/soc/tegra/tegra_rt5639.c | 16 ++- 4 files changed, 301 insertions(+), 84 deletions(-) (limited to 'sound') diff --git a/sound/soc/tegra/tegra30_avp.c b/sound/soc/tegra/tegra30_avp.c index d28e25ab057c..aeefdd53fdee 100644 --- a/sound/soc/tegra/tegra30_avp.c +++ b/sound/soc/tegra/tegra30_avp.c @@ -713,11 +713,114 @@ static void tegra30_avp_free_shared_mem(struct tegra_offload_mem *mem) tegra30_avp_mem_free(mem); } +/* Loopback APIs */ +static int tegra30_avp_loopback_set_params(int id, + struct tegra_offload_pcm_params *params) +{ + struct tegra30_avp_audio *audio_avp = avp_audio_ctx; + struct tegra30_avp_stream *avp_stream = &audio_avp->avp_stream[id]; + struct stream_data *stream = avp_stream->stream; + int ret = 0; + + dev_vdbg(audio_avp->dev, "%s:entry\n", __func__); + + /* TODO : check validity of parameters */ + if (!stream) { + dev_err(audio_avp->dev, "AVP platform not initialized."); + return -ENODEV; + } + + + stream->stream_notification_interval = params->period_size; + stream->stream_notification_enable = 1; + stream->stream_params.rate = params->rate; + stream->stream_params.channels = params->channels; + stream->stream_params.bits_per_sample = params->bits_per_sample; + + + avp_stream->period_size = params->period_size; + avp_stream->notify_cb = params->period_elapsed_cb; + avp_stream->notify_args = params->period_elapsed_args; + + stream->source_buffer_system = + (uintptr_t)(params->source_buf.virt_addr); + stream->source_buffer_avp = params->source_buf.phys_addr; + stream->source_buffer_size = params->buffer_size; + return ret; +} + +static int tegra30_avp_loopback_set_state(int id, int state) +{ + struct tegra30_avp_audio *audio_avp = avp_audio_ctx; + struct tegra30_avp_stream *avp_stream = &audio_avp->avp_stream[id]; + struct stream_data *stream = avp_stream->stream; + + dev_vdbg(audio_avp->dev, "%s : id %d state %d", __func__, id, state); + + if (!stream) { + dev_err(audio_avp->dev, "AVP platform not initialized."); + return -ENODEV; + } + + switch (state) { + case SNDRV_PCM_TRIGGER_START: + stream->stream_state_target = KSSTATE_RUN; + return 0; + case SNDRV_PCM_TRIGGER_STOP: + stream->stream_state_target = KSSTATE_STOP; + stream->source_buffer_write_position = 0; + stream->source_buffer_write_count = 0; + avp_stream->last_notification_offset = 0; + avp_stream->notification_received = 0; + avp_stream->source_buffer_offset = 0; + return 0; + default: + dev_err(audio_avp->dev, "Unsupported state."); + return -EINVAL; + } +} + +static size_t tegra30_avp_loopback_get_position(int id) +{ + struct tegra30_avp_audio *audio_avp = avp_audio_ctx; + struct tegra30_avp_stream *avp_stream = &audio_avp->avp_stream[id]; + struct stream_data *stream = avp_stream->stream; + size_t pos = 0; + + pos = (size_t)stream->source_buffer_read_position; + + dev_vdbg(audio_avp->dev, "%s id %d pos %d", __func__, id, (u32)pos); + + return pos; +} + +static void tegra30_avp_loopback_data_ready(int id, int bytes) +{ + struct tegra30_avp_audio *audio_avp = avp_audio_ctx; + struct tegra30_avp_stream *avp_stream = &audio_avp->avp_stream[id]; + struct stream_data *stream = avp_stream->stream; + + dev_vdbg(audio_avp->dev, "%s :id %d size %d", __func__, id, bytes); + + stream->source_buffer_write_position += bytes; + stream->source_buffer_write_position %= stream->source_buffer_size; + + avp_stream->source_buffer_offset += bytes; + while (avp_stream->source_buffer_offset >= + stream->stream_notification_interval) { + stream->source_buffer_write_count++; + avp_stream->source_buffer_offset -= + stream->stream_notification_interval; + } + return; +} + /* PCM APIs */ -static int tegra30_avp_pcm_open(int *id) +static int tegra30_avp_pcm_open(int *id, char *stream) { struct tegra30_avp_audio *audio_avp = avp_audio_ctx; struct audio_engine_data *audio_engine = audio_avp->audio_engine; + struct tegra30_avp_stream *avp_stream; int ret = 0; dev_vdbg(audio_avp->dev, "%s", __func__); @@ -741,20 +844,36 @@ static int tegra30_avp_pcm_open(int *id) audio_engine = audio_avp->audio_engine; } - if (!audio_engine->stream[pcm_stream_id].stream_allocated) - *id = pcm_stream_id; - else if (!audio_engine->stream[pcm2_stream_id].stream_allocated) - *id = pcm2_stream_id; - else { - dev_err(audio_avp->dev, "All AVP PCM streams are busy"); - return -EBUSY; + if (strcmp(stream, "pcm") == 0) { + avp_stream = &audio_avp->avp_stream[1]; + if (!audio_engine->stream[pcm_stream_id].stream_allocated) { + *id = pcm_stream_id; + audio_engine->stream[*id].stream_allocated = 1; + atomic_inc(&audio_avp->stream_active_count); + } else if ( + !audio_engine->stream[pcm2_stream_id].stream_allocated) { + *id = pcm2_stream_id; + audio_engine->stream[*id].stream_allocated = 1; + atomic_inc(&audio_avp->stream_active_count); + } else { + dev_err(audio_avp->dev, "All AVP PCM streams are busy"); + return -EBUSY; + } + } else if (strcmp(stream, "loopback") == 0) { + avp_stream = &audio_avp->avp_stream[0]; + if + (!audio_engine->stream[loopback_stream_id].stream_allocated) { + dev_vdbg(audio_avp->dev, + "Assigning loopback id:%d\n", loopback_stream_id); + audio_engine->stream[*id].stream_allocated = 1; + *id = loopback_stream_id; + } else { + dev_err(audio_avp->dev, "AVP loopback streams is busy"); + return -EBUSY; + } } - audio_engine->stream[*id].stream_allocated = 1; - - atomic_inc(&audio_avp->stream_active_count); tegra30_avp_audio_set_state(KSSTATE_RUN); - return 0; } @@ -1248,6 +1367,9 @@ static void tegra30_avp_stream_close(int id) stream->stream_allocated = 0; tegra30_avp_stream_set_state(id, KSSTATE_STOP); + if (id == loopback_stream_id) + return; + if (atomic_dec_and_test(&audio_avp->stream_active_count)) { tegra30_avp_audio_free_dma(); tegra30_avp_audio_set_state(KSSTATE_STOP); @@ -1268,6 +1390,14 @@ static struct tegra_offload_ops avp_audio_platform = { .get_stream_position = tegra30_avp_pcm_get_position, .data_ready = tegra30_avp_pcm_data_ready, }, + .loopback_ops = { + .stream_open = tegra30_avp_pcm_open, + .stream_close = tegra30_avp_stream_close, + .set_stream_params = tegra30_avp_loopback_set_params, + .set_stream_state = tegra30_avp_loopback_set_state, + .get_stream_position = tegra30_avp_loopback_get_position, + .data_ready = tegra30_avp_loopback_data_ready, + }, .compr_ops = { .stream_open = tegra30_avp_compr_open, .stream_close = tegra30_avp_stream_close, diff --git a/sound/soc/tegra/tegra_offload.c b/sound/soc/tegra/tegra_offload.c index bdfe94e30add..660bb4739554 100644 --- a/sound/soc/tegra/tegra_offload.c +++ b/sound/soc/tegra/tegra_offload.c @@ -38,6 +38,7 @@ enum { PCM_OFFLOAD_DAI, COMPR_OFFLOAD_DAI, + PCM_CAPTURE_OFFLOAD_DAI, MAX_OFFLOAD_DAI }; @@ -61,7 +62,7 @@ static DEFINE_MUTEX(tegra_offload_lock); static int codec, spk; -static const struct snd_pcm_hardware tegra_offload_pcm_hardware = { +static const struct snd_pcm_hardware tegra_offload_pcm_hardware_playback = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE | @@ -78,6 +79,23 @@ static const struct snd_pcm_hardware tegra_offload_pcm_hardware = { .fifo_size = 4, }; +static const struct snd_pcm_hardware tegra_offload_pcm_hardware_capture = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_RESUME | + SNDRV_PCM_INFO_INTERLEAVED, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .channels_min = 2, + .channels_max = 2, + .period_bytes_min = 128, + .period_bytes_max = PAGE_SIZE * 2, + .periods_min = 1, + .periods_max = 8, + .buffer_bytes_max = PAGE_SIZE * 8, + .fifo_size = 4, +}; + int tegra_register_offload_ops(struct tegra_offload_ops *ops) { mutex_lock(&tegra_offload_lock); @@ -320,7 +338,7 @@ static int tegra_offload_compr_set_params(struct snd_compr_stream *stream, } static int tegra_offload_compr_get_params(struct snd_compr_stream *stream, - struct snd_codec *codec) + struct snd_codec *codec) { struct device *dev = stream->device->dev; struct tegra_offload_compr_data *data = stream->runtime->private_data; @@ -343,7 +361,7 @@ static int tegra_offload_compr_trigger(struct snd_compr_stream *stream, int cmd) } static int tegra_offload_compr_pointer(struct snd_compr_stream *stream, - struct snd_compr_tstamp *tstamp) + struct snd_compr_tstamp *tstamp) { struct device *dev = stream->device->dev; struct tegra_offload_compr_data *data = stream->runtime->private_data; @@ -354,7 +372,7 @@ static int tegra_offload_compr_pointer(struct snd_compr_stream *stream, } static int tegra_offload_compr_copy(struct snd_compr_stream *stream, - char __user *buf, size_t count) + char __user *buf, size_t count) { struct device *dev = stream->device->dev; struct tegra_offload_compr_data *data = stream->runtime->private_data; @@ -365,7 +383,7 @@ static int tegra_offload_compr_copy(struct snd_compr_stream *stream, } static int tegra_offload_compr_get_caps(struct snd_compr_stream *stream, - struct snd_compr_caps *caps) + struct snd_compr_caps *caps) { struct device *dev = stream->device->dev; struct tegra_offload_compr_data *data = stream->runtime->private_data; @@ -383,7 +401,7 @@ static int tegra_offload_compr_get_caps(struct snd_compr_stream *stream, } static int tegra_offload_compr_codec_caps(struct snd_compr_stream *stream, - struct snd_compr_codec_caps *codec_caps) + struct snd_compr_codec_caps *codec_caps) { struct device *dev = stream->device->dev; struct tegra_offload_compr_data *data = stream->runtime->private_data; @@ -403,7 +421,6 @@ static int tegra_offload_compr_codec_caps(struct snd_compr_stream *stream, } static struct snd_compr_ops tegra_compr_ops = { - .open = tegra_offload_compr_open, .free = tegra_offload_compr_free, .set_params = tegra_offload_compr_set_params, @@ -440,28 +457,45 @@ static int tegra_offload_pcm_open(struct snd_pcm_substream *substream) data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) { - dev_err(dev, "Failed to allocate tegra_offload_pcm_data."); + dev_vdbg(dev, + "Failed to allocate tegra_offload_pcm_data\n"); return -ENOMEM; } - - /* Set HW params now that initialization is complete */ - snd_soc_set_runtime_hwparams(substream, &tegra_offload_pcm_hardware); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + /* Set HW params now that initialization is complete */ + snd_soc_set_runtime_hwparams(substream, + &tegra_offload_pcm_hardware_playback); + else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) + snd_soc_set_runtime_hwparams(substream, + &tegra_offload_pcm_hardware_capture); /* Ensure period size is multiple of 4 */ ret = snd_pcm_hw_constraint_step(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 0x4); + SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 0x4); if (ret) { dev_err(dev, "failed to set constraint %d\n", ret); return ret; } - data->ops = &offload_ops.pcm_ops; - - ret = data->ops->stream_open(&data->stream_id); - if (ret < 0) { - dev_err(dev, "Failed to open offload stream. err %d", ret); - return ret; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + data->ops = &offload_ops.pcm_ops; + + ret = data->ops->stream_open(&data->stream_id, "pcm"); + if (ret < 0) { + dev_err(dev, + "Failed to open offload stream err %d", ret); + return ret; + } + } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + data->ops = &offload_ops.loopback_ops; + + ret = data->ops->stream_open(&data->stream_id, "loopback"); + if (ret < 0) { + dev_err(dev, + "Failed to open offload stream err %d", ret); + return ret; + } } - offload_ops.device_ops.set_hw_rate(48000); + offload_ops.device_ops.set_hw_rate(48000); substream->runtime->private_data = data; return 0; } @@ -480,57 +514,69 @@ static int tegra_offload_pcm_close(struct snd_pcm_substream *substream) } static int tegra_offload_pcm_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) + struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct device *dev = rtd->platform->dev; - struct tegra_offload_pcm_data *data = substream->runtime->private_data; - struct snd_dma_buffer *buf = &substream->dma_buffer; - struct tegra_pcm_dma_params *dmap; + struct tegra_offload_pcm_data *data = + substream->runtime->private_data; struct tegra_offload_pcm_params offl_params; + struct snd_dma_buffer *buf = &substream->dma_buffer; int ret = 0; dev_vdbg(dev, "%s", __func__); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + struct tegra_pcm_dma_params *dmap; + + dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); + if (!dmap) { + struct snd_soc_dpcm *dpcm; + + if + (list_empty(&rtd->dpcm[substream->stream].be_clients)) { + dev_err(dev, "No backend DAIs enabled for %s\n", + rtd->dai_link->name); + return -EINVAL; + } - dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); - if (!dmap) { - struct snd_soc_dpcm *dpcm; - - if (list_empty(&rtd->dpcm[substream->stream].be_clients)) { - dev_err(dev, "No backend DAIs enabled for %s\n", - rtd->dai_link->name); - return -EINVAL; - } - - list_for_each_entry(dpcm, - &rtd->dpcm[substream->stream].be_clients, list_be) { - struct snd_soc_pcm_runtime *be = dpcm->be; - struct snd_pcm_substream *be_substream = - snd_soc_dpcm_get_substream(be, + list_for_each_entry(dpcm, + &rtd->dpcm[substream->stream].be_clients, + list_be) { + struct snd_soc_pcm_runtime *be = dpcm->be; + struct snd_pcm_substream *be_substream = + snd_soc_dpcm_get_substream(be, substream->stream); - struct snd_soc_dai_link *dai_link = be->dai_link; + struct snd_soc_dai_link *dai_link = + be->dai_link; - dmap = snd_soc_dai_get_dma_data(be->cpu_dai, - be_substream); - - if (spk && strstr(dai_link->name, "speaker")) { - dmap = snd_soc_dai_get_dma_data(be->cpu_dai, - be_substream); - break; - } - if (codec && strstr(dai_link->name, "codec")) { dmap = snd_soc_dai_get_dma_data(be->cpu_dai, - be_substream); - break; + be_substream); + + if (spk && strstr(dai_link->name, "speaker")) { + dmap = snd_soc_dai_get_dma_data( + be->cpu_dai, + be_substream); + break; + } + if (codec && strstr(dai_link->name, "codec")) { + dmap = snd_soc_dai_get_dma_data( + be->cpu_dai, + be_substream); + break; + } + /* TODO : Multiple BE to + * single FE not yet supported */ } - /* TODO : Multiple BE to single FE not yet supported */ } + if (!dmap) { + dev_err(dev, "Failed to get DMA params."); + return -ENODEV; + } + offl_params.dma_params.addr = dmap->addr; + offl_params.dma_params.width = DMA_SLAVE_BUSWIDTH_4_BYTES; + offl_params.dma_params.req_sel = dmap->req_sel; + offl_params.dma_params.max_burst = 4; } - if (!dmap) { - dev_err(dev, "Failed to get DMA params."); - return -ENODEV; - } - offl_params.bits_per_sample = snd_pcm_format_width(params_format(params)); offl_params.rate = params_rate(params); @@ -539,19 +585,17 @@ static int tegra_offload_pcm_hw_params(struct snd_pcm_substream *substream, offl_params.period_size = params_period_size(params) * ((offl_params.bits_per_sample >> 3) * offl_params.channels); - offl_params.dma_params.addr = dmap->addr; - offl_params.dma_params.width = DMA_SLAVE_BUSWIDTH_4_BYTES; - offl_params.dma_params.req_sel = dmap->req_sel; - offl_params.dma_params.max_burst = 4; offl_params.source_buf.virt_addr = buf->area; offl_params.source_buf.phys_addr = buf->addr; offl_params.source_buf.bytes = buf->bytes; - offl_params.period_elapsed_cb = tegra_offload_pcm_period_elapsed; + offl_params.period_elapsed_cb = + tegra_offload_pcm_period_elapsed; offl_params.period_elapsed_args = (void *)substream; - ret = data->ops->set_stream_params(data->stream_id, &offl_params); + ret = data->ops->set_stream_params(data->stream_id, + &offl_params); if (ret < 0) { dev_err(dev, "Failed to set avp params. ret %d", ret); return ret; @@ -582,10 +626,9 @@ static int tegra_offload_pcm_trigger(struct snd_pcm_substream *substream, data->ops->set_stream_state(data->stream_id, cmd); if ((cmd == SNDRV_PCM_TRIGGER_STOP) || - (cmd == SNDRV_PCM_TRIGGER_SUSPEND) || - (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH)) + (cmd == SNDRV_PCM_TRIGGER_SUSPEND) || + (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH)) data->appl_ptr = 0; - return 0; } @@ -607,6 +650,7 @@ static int tegra_offload_pcm_ack(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct tegra_offload_pcm_data *data = runtime->private_data; + int data_size = runtime->control->appl_ptr - data->appl_ptr; if (data_size < 0) @@ -768,17 +812,40 @@ static int tegra_offload_dma_allocate(struct snd_soc_pcm_runtime *rtd, static int tegra_offload_pcm_new(struct snd_soc_pcm_runtime *rtd) { struct device *dev = rtd->platform->dev; + struct snd_pcm *pcm = rtd->pcm; + int ret = 0; - dev_vdbg(dev, "%s", __func__); - return tegra_offload_dma_allocate(rtd , SNDRV_PCM_STREAM_PLAYBACK, - tegra_offload_pcm_hardware.buffer_bytes_max); + dev_vdbg(dev, "%s", __func__); + dev_err(pcm->card->dev, "Allocating for stream playback\n"); + ret = tegra_offload_dma_allocate(rtd , SNDRV_PCM_STREAM_PLAYBACK, + tegra_offload_pcm_hardware_playback.buffer_bytes_max); + if (ret < 0) { + dev_err(pcm->card->dev, "failing in pcm_new:1 goto err"); + goto err; + } + dev_err(pcm->card->dev, "Allocating for stream capture\n"); + ret = tegra_offload_dma_allocate(rtd , SNDRV_PCM_STREAM_CAPTURE, + tegra_offload_pcm_hardware_capture.buffer_bytes_max); + if (ret < 0) { + dev_err(pcm->card->dev, "failing in pcm_new:1 goto err"); + goto err; + } +err: + return ret; } static void tegra_offload_pcm_free(struct snd_pcm *pcm) { - tegra_offload_dma_free(pcm, SNDRV_PCM_STREAM_PLAYBACK); pr_debug("%s", __func__); + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { + dev_err(pcm->card->dev, "PCM free for stream playback\n"); + tegra_offload_dma_free(pcm, SNDRV_PCM_STREAM_PLAYBACK); + } + if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { + dev_err(pcm->card->dev, "PCM free for stream capture\n"); + tegra_offload_dma_free(pcm, SNDRV_PCM_STREAM_CAPTURE); + } } static int tegra_offload_pcm_probe(struct snd_soc_platform *platform) @@ -827,6 +894,13 @@ static struct snd_soc_dai_driver tegra_offload_dai[] = { .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, .formats = SNDRV_PCM_FMTBIT_S16_LE, }, + .capture = { + .stream_name = "offload-pcm-capture", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE, + }, }, [COMPR_OFFLOAD_DAI] = { .name = "tegra-offload-compr", diff --git a/sound/soc/tegra/tegra_offload.h b/sound/soc/tegra/tegra_offload.h index 6a1d0cf1cb56..b67c19a5d714 100644 --- a/sound/soc/tegra/tegra_offload.h +++ b/sound/soc/tegra/tegra_offload.h @@ -56,7 +56,7 @@ struct tegra_offload_compr_params { }; struct tegra_offload_pcm_ops { - int (*stream_open)(int *id); + int (*stream_open)(int *id, char *stream); void (*stream_close)(int id); int (*set_stream_params)(int id, struct tegra_offload_pcm_params *params); @@ -88,6 +88,7 @@ struct tegra_offload_device_ops { struct tegra_offload_ops { struct tegra_offload_device_ops device_ops; struct tegra_offload_pcm_ops pcm_ops; + struct tegra_offload_pcm_ops loopback_ops; struct tegra_offload_compr_ops compr_ops; }; diff --git a/sound/soc/tegra/tegra_rt5639.c b/sound/soc/tegra/tegra_rt5639.c index 467375e15770..b26096550c2d 100644 --- a/sound/soc/tegra/tegra_rt5639.c +++ b/sound/soc/tegra/tegra_rt5639.c @@ -59,8 +59,9 @@ #define DAI_LINK_BT_VOICE_CALL 4 #define DAI_LINK_PCM_OFFLOAD_FE 5 #define DAI_LINK_COMPR_OFFLOAD_FE 6 -#define DAI_LINK_I2S_OFFLOAD_BE 7 -#define NUM_DAI_LINKS 8 +#define DAI_LINK_PCM_OFFLOAD_CAPTURE_FE 7 +#define DAI_LINK_I2S_OFFLOAD_BE 8 +#define NUM_DAI_LINKS 9 extern int g_is_call_mode; @@ -1062,6 +1063,17 @@ static struct snd_soc_dai_link tegra_rt5639_dai[NUM_DAI_LINKS] = { .dynamic = 1, }, + [DAI_LINK_PCM_OFFLOAD_CAPTURE_FE] = { + .name = "offload-pcm-capture", + .stream_name = "offload-pcm-capture", + + .platform_name = "tegra-offload", + .cpu_dai_name = "tegra-offload-pcm", + + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + + }, [DAI_LINK_I2S_OFFLOAD_BE] = { .name = "offload-audio-codec", .stream_name = "offload-audio-pcm", -- cgit v1.2.3