@@ -970,6 +970,11 @@ struct snd_soc_dai_link {
enum snd_soc_dpcm_trigger trigger[2]; /* trigger type for DPCM */
+ /* This DAI link is dummy. Machine drivers can define static dummy
+ * links to specify platform/codec with topology.
+ */
+ bool dummy;
+
/* codec/machine specific init - e.g. add machine controls */
int (*init)(struct snd_soc_pcm_runtime *rtd);
@@ -1087,6 +1092,7 @@ struct snd_soc_card {
struct list_head rtd_list;
int num_rtd;
+ int num_rtd_dev; /* monotonic increase and exclude dummy ones */
/* optional codec specific configuration */
struct snd_soc_codec_conf *codec_conf;
@@ -1181,6 +1187,7 @@ struct snd_soc_pcm_runtime {
struct dentry *debugfs_dpcm_state;
#endif
+ bool dummy;
unsigned int num; /* 0-based and monotonic increasing */
struct list_head list; /* rtd list of the soc card */
};
@@ -561,6 +561,7 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime(
rtd->card = card;
rtd->dai_link = dai_link;
+ rtd->dummy = dai_link->dummy;
rtd->codec_dais = devm_kzalloc(card->dev,
sizeof(struct snd_soc_dai *) *
dai_link->num_codecs,
@@ -583,10 +584,28 @@ static void soc_add_pcm_runtime(struct snd_soc_card *card,
struct snd_soc_pcm_runtime *rtd)
{
list_add_tail(&rtd->list, &card->rtd_list);
- rtd->num = card->num_rtd;
+
+ if (!rtd->dummy) {
+ rtd->num = card->num_rtd_dev;
+ card->num_rtd_dev++;
+ }
+
card->num_rtd++;
}
+static void soc_remove_dummy_pcm_runtimes(struct snd_soc_card *card)
+{
+ struct snd_soc_pcm_runtime *rtd, *_rtd;
+
+ list_for_each_entry_safe(rtd, _rtd, &card->rtd_list, list) {
+ if (rtd->dummy) {
+ list_del(&rtd->list);
+ soc_free_pcm_runtime(card, rtd);
+ card->num_rtd--;
+ }
+ }
+}
+
static void soc_remove_pcm_runtimes(struct snd_soc_card *card)
{
struct snd_soc_pcm_runtime *rtd, *_rtd;
@@ -1007,6 +1026,15 @@ static int soc_bind_dai_link(struct snd_soc_card *card,
}
}
+ /* Dummy link can use dummy cpu DAI but set platform to get topology */
+ if (dai_link->dummy && dai_link->platform_name) {
+ if (!soc_find_component(NULL, dai_link->platform_name)) {
+ dev_err(card->dev, "ASoC: Platform %s not registered\n",
+ dai_link->platform_name);
+ goto _err_defer;
+ }
+ }
+
/* Single codec links expect codec and codec_dai in runtime data */
rtd->codec_dai = codec_dais[0];
rtd->codec = rtd->codec_dai->codec;
@@ -1250,6 +1278,10 @@ static int soc_init_dai_link(struct snd_soc_card *card,
void snd_soc_add_dai_link(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_link)
{
+ /* Dummy links should be static, so overlook them */
+ if (dai_link->dummy)
+ return;
+
lockdep_assert_held(&client_mutex);
list_add_tail(&dai_link->list, &card->dai_link_list);
card->num_dai_links++;
@@ -1818,6 +1850,9 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
}
}
+ /* no longer need dummy runtimes */
+ soc_remove_dummy_pcm_runtimes(card);
+
/* probe all DAI links on this card */
for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
order++) {
@@ -2516,6 +2551,7 @@ int snd_soc_register_card(struct snd_soc_card *card)
INIT_LIST_HEAD(&card->rtd_list);
card->num_rtd = 0;
+ card->num_rtd_dev = 0;
card->rtd_aux = devm_kzalloc(card->dev,
sizeof(struct snd_soc_pcm_runtime) *