Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introducing virtual FE #8

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion include/sound/soc-dpcm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
104 changes: 103 additions & 1 deletion sound/soc/soc-pcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++) {

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

best to keep this line as is.

switch (list->widgets[i]->id) {
case snd_soc_dapm_dai_in:
if (stream != SNDRV_PCM_STREAM_PLAYBACK)
Expand Down Expand Up @@ -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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: all these frees don't reflect what is done for the _new method, could we rely on a helper to avoid tracking all these actions? It looks like either copy-paste or something extracted from somewhere else.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is actually not a copy-paste at all. I traced all the steps from the point of adding the link to the time when the sound card is registered and freed all the data that is allocated. Here're the steps I traced:

  1. Bind DAI link: The PCM runtime and the dpcm runtime is created during this step.
    There are some other runtime child structures allocated during this step too ie codec dais and component list.
  2. Probe DAI link :The pcm device and the substream is created here.
  3. dpcm runtime update: the FE link is connected to the BE

So, in the vfe_free() method, I undid all of this.

But I wonder if I can avoid all of this manually in the free method. Let me dig into these steps a bit more.


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;
Expand Down