From 5017eda4f4943cca60ce9b3bd592042e48557cdd Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Wed, 23 May 2018 18:45:42 -0700 Subject: [PATCH 1/6] ASoC: dapm: enable kcontrols for siggen type widgets This patch proposes to enable kcontrols for siggen type dapm widgets. This will allow triggering the tone generating siggen component and also modifying the run-time attributes such as frequency, amplitude etc. Signed-off-by: Ranjani Sridharan --- sound/soc/soc-dapm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 6d54128e44b46b..04f84b2cc04f83 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -855,6 +855,7 @@ static int dapm_create_or_share_kcontrol(struct snd_soc_dapm_widget *w, kcname_in_long_name = true; } else { switch (w->id) { + case snd_soc_dapm_siggen: case snd_soc_dapm_switch: case snd_soc_dapm_mixer: case snd_soc_dapm_pga: @@ -3076,6 +3077,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card) case snd_soc_dapm_demux: dapm_new_mux(w); break; + case snd_soc_dapm_siggen: case snd_soc_dapm_pga: case snd_soc_dapm_out_drv: dapm_new_pga(w); From 0452dd40688be16383caef802be2594e527a1cce Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Fri, 22 Jun 2018 21:09:39 -0700 Subject: [PATCH 2/6] ASoC: pcm: add methods to create/remove virtual dai link This patch adds the methods for create a virtual FE dal link and add it to the sound card. It also adds the method to free the virtual FE connected to the card. Signed-off-by: Ranjani Sridharan --- include/sound/soc-dpcm.h | 6 ++- sound/soc/soc-pcm.c | 104 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 108 insertions(+), 2 deletions(-) diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index 806059052bfcca..93aafa87d4edc7 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h @@ -158,5 +158,9 @@ static inline void dpcm_path_put(struct snd_soc_dapm_widget_list **list) kfree(*list); } - +/* create/free virtual FE dai links */ +int soc_dpcm_vfe_new(struct snd_soc_card *, int index, const char *link_name, + const char *cpu_dai_name, const char *platform_name, + int stream_dir); +int soc_dpcm_vfe_free(struct snd_soc_card *card, const char *link_name); #endif diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 4ce489165a6d9b..acba166cb63abd 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1582,7 +1582,6 @@ static int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, /* Create any new FE <--> BE connections */ for (i = 0; i < list->num_widgets; i++) { - switch (list->widgets[i]->id) { case snd_soc_dapm_dai_in: if (stream != SNDRV_PCM_STREAM_PLAYBACK) @@ -2789,6 +2788,109 @@ int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute) return 0; } +/* + * create a virtual FE DAI link which has no pcm device registered. + * Virtual FE DAI links are used in hostless pipelines + * to enable the codecs when the pipeline is triggered + */ +int soc_dpcm_vfe_new(struct snd_soc_card *card, int index, + const char *link_name, const char *cpu_dai_name, + const char *platform_name, int stream_dir) +{ + struct snd_soc_dai_link *link; + + link = kzalloc(sizeof(*link), GFP_KERNEL); + if (!link) + return -ENOMEM; + + dev_dbg(card->dev, "ASoC: adding new virtual FE DAI link %s\n", + link_name); + + /* define FE DAI link */ + link->name = link_name; + link->cpu_dai_name = cpu_dai_name; + link->platform_name = platform_name; + link->codec_name = "snd-soc-dummy"; + link->codec_dai_name = "snd-soc-dummy-dai"; + + /* + * Enabling both dynamic and no_pcm flags indicates the link is virtual + * i.e. it is a FE dai link but without a registered pcm device + */ + link->dynamic = 1; + link->no_pcm = 1; + + /* enable playback */ + if (stream_dir == SNDRV_PCM_STREAM_PLAYBACK) + link->dpcm_playback = 1; + + /* enable capture */ + if (stream_dir == SNDRV_PCM_STREAM_CAPTURE) + link->dpcm_capture = 1; + + link->dobj.index = index; + link->dobj.type = SND_SOC_DOBJ_DAI_LINK; + + /* add link to card dai link list */ + snd_soc_add_dai_link(card, link); + + return 0; +} +EXPORT_SYMBOL_GPL(soc_dpcm_vfe_new); + +/* free virtual FE DAI link */ +int soc_dpcm_vfe_free(struct snd_soc_card *card, const char *link_name) +{ + struct snd_soc_rtdcom_list *rtdcom1, *rtdcom2; + struct snd_soc_pcm_runtime *rtd, *temp; + struct snd_pcm_str *pstr; + int stream_dir; + + list_for_each_entry_safe(rtd, temp, &card->rtd_list, list) { + + /* delete requested FE link */ + if (!strcmp(rtd->dai_link->name, link_name)) { + + if (rtd->dai_link->dpcm_playback) + stream_dir = SNDRV_PCM_STREAM_PLAYBACK; + else + stream_dir = SNDRV_PCM_STREAM_CAPTURE; + + /* disconnect FE from BE */ + dpcm_be_disconnect(rtd, stream_dir); + + /* free pcm runtime */ + kfree(rtd->dpcm[stream_dir].runtime); + + pstr = &rtd->pcm->streams[stream_dir]; + + /* free pcm substream amd pcm */ + kfree(pstr->substream); + + /* free pcm */ + kfree(rtd->pcm); + + /* free codec dais and component list */ + kfree(rtd->codec_dais); + + for_each_rtdcom_safe(rtd, rtdcom1, rtdcom2) + kfree(rtdcom1); + + /* remove dai_link from card */ + snd_soc_remove_dai_link(card, rtd->dai_link); + + /* free link */ + kfree(rtd->dai_link); + + /* free runtime */ + kfree(rtd); + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(soc_dpcm_vfe_free); + static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream) { struct snd_soc_pcm_runtime *fe = fe_substream->private_data; From 188a1918f26fed42fd20da7df58ce7ba80d681dd Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Fri, 22 Jun 2018 21:15:04 -0700 Subject: [PATCH 3/6] ASoC: dapm: dont delete starting point if list is singular When walking the graph to discover the path from the virtual FE to the BE, there is only one widget in the path. Do not remove this BE widget from the list, so it can be used to connect with the virtual FE dai link. Signed-off-by: Ranjani Sridharan --- sound/soc/soc-dapm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 04f84b2cc04f83..a0c1527e1b2917 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1247,7 +1247,8 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, custom_stop_condition); /* Drop starting point */ - list_del(widgets.next); + if (!list_is_singular(&widgets)) + list_del(widgets.next); ret = dapm_widget_list_create(list, &widgets); if (ret) From b829c2b0fe9078ec98c332ab246ee7f27593cd66 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Fri, 22 Jun 2018 21:27:16 -0700 Subject: [PATCH 4/6] ASoC: core: set runtime and the cpu_dai/codec_dai active status for virtual dai link Virtual FE dai links should be manually set to running state by default with a pcm runtime. The active count of their cpu_dai and codec_dai's should also be updated. This is required to establish FE-BE connection and enable the BE DAI when the dpcm runtime is updated. Signed-off-by: Ranjani Sridharan --- sound/soc/soc-core.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index a0160a409e4094..2e924717cf0146 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1047,6 +1047,7 @@ static int soc_bind_dai_link(struct snd_soc_card *card, struct snd_soc_dai **codec_dais; struct snd_soc_platform *platform; struct device_node *platform_of_node; + struct snd_pcm_runtime *runtime; const char *platform_name; int i; @@ -1134,6 +1135,31 @@ static int soc_bind_dai_link(struct snd_soc_card *card, } soc_add_pcm_runtime(card, rtd); + + /* if this is a virtual FE link, create runtime and set it as active */ + if (rtd->dai_link->dynamic && rtd->dai_link->no_pcm) { + runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); + if (!runtime) + return -ENOMEM; + + /* set playback active status */ + if (rtd->dai_link->dpcm_playback) { + rtd->dpcm[SNDRV_PCM_STREAM_PLAYBACK].runtime = runtime; + rtd->cpu_dai->playback_active = 1; + rtd->codec_dai->playback_active = 1; + } + + /* set capture active statue */ + if (rtd->dai_link->dpcm_capture) { + rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].runtime = runtime; + rtd->cpu_dai->capture_active = 1; + rtd->codec_dai->capture_active = 1; + } + + /* increment the active count for cpu dai */ + rtd->cpu_dai->active++; + } + return 0; _err_defer: From bd1132f9244045656faa57057d9645dcb5503583 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Sat, 23 Jun 2018 20:48:41 -0700 Subject: [PATCH 5/6] ASoC: pcm: do not register pcm device for virtual FE dai links Virtual FE dai links do not need to register the pcm device. So just create the empty pcm device and substream in the requested direction. Signed-off-by: Ranjani Sridharan --- sound/soc/soc-pcm.c | 56 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index acba166cb63abd..8e86dff4263f70 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -3098,6 +3098,55 @@ static int soc_rtdcom_mmap(struct snd_pcm_substream *substream, return -EINVAL; } +/* + * for virtual FE dai links, there is no need + * to register PCM device. So only allocate memory for + * the dummy pcm device and substreams to be used for + * codec startup + */ +static int setup_virtual_fe(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm *pcm) +{ + struct snd_pcm_substream *substream; + struct snd_pcm_str *pstr; + int stream_dir; + + /* create pcm */ + pcm = kzalloc(sizeof(*pcm), GFP_KERNEL); + if (!pcm) + return -ENOMEM; + + /* set up playback/capture substream */ + if (rtd->dai_link->dpcm_playback) + stream_dir = SNDRV_PCM_STREAM_PLAYBACK; + else + stream_dir = SNDRV_PCM_STREAM_CAPTURE; + + pstr = &pcm->streams[stream_dir]; + + /* allocate memory for substream */ + substream = kzalloc(sizeof(*substream), GFP_KERNEL); + if (!substream) + return -ENOMEM; + + /* define substream */ + substream->pcm = pcm; + substream->pstr = pstr; + substream->number = 0; + substream->stream = stream_dir; + sprintf(substream->name, "subdevice #%i", 0); + substream->buffer_bytes_max = UINT_MAX; + + /* set pcm substream */ + pstr->substream = substream; + + pcm->nonatomic = rtd->dai_link->nonatomic; + rtd->pcm = pcm; + pcm->private_data = rtd; + + return 0; +} + /* create a new pcm */ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) { @@ -3145,6 +3194,13 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) ret = snd_pcm_new_internal(rtd->card->snd_card, new_name, num, playback, capture, &pcm); } else { + + /* set up virtual FE dai link */ + if (rtd->dai_link->dynamic && rtd->dai_link->no_pcm) { + setup_virtual_fe(rtd, pcm); + goto out; + } + if (rtd->dai_link->dynamic) snprintf(new_name, sizeof(new_name), "%s (*)", rtd->dai_link->stream_name); From f00e120347b4d3e0c4bee1ec3c0950ca5814a6bb Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Sat, 23 Jun 2018 21:46:34 -0700 Subject: [PATCH 6/6] ASoC: pcm: make soc_dpcm_runtime_update() accessible from modules the soc_dpcm_runtime_update() method will be called to establish a connection to the BE and enable the codec. So make this method accessible to modules. Signed-off-by: Ranjani Sridharan --- sound/soc/soc-pcm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 8e86dff4263f70..73faa469d8ae36 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2758,6 +2758,8 @@ int soc_dpcm_runtime_update(struct snd_soc_card *card) mutex_unlock(&card->mutex); return 0; } +EXPORT_SYMBOL_GPL(soc_dpcm_runtime_update); + int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute) { struct snd_soc_dpcm *dpcm;