From f2138aed231c88d5c4fa8d06aa15ad19685087c2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 1 Apr 2021 13:15:23 +0900 Subject: [PATCH 1/2] ASoC: simple-card-utils: enable flexible CPU/Codec/Platform Current simple-card / audio-graph are assuming fixed single-CPU/Codec/Platform. This patch prepares multi-CPU/Codec/Platform support. Note is that it is not yet full-multi-support. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87v996od2c.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 8 +++ sound/soc/generic/audio-graph-card.c | 22 ++++++++ sound/soc/generic/simple-card-utils.c | 72 +++++++++++++++++++-------- sound/soc/generic/simple-card.c | 30 +++++++++++ 4 files changed, 110 insertions(+), 22 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 86e46cbf9e14..475f8cb14492 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -38,6 +38,12 @@ struct asoc_simple_jack { struct snd_soc_jack_gpio gpio; }; +struct prop_nums { + int cpus; + int codecs; + int platforms; +}; + struct asoc_simple_priv { struct snd_soc_card snd_card; struct simple_dai_props { @@ -48,6 +54,7 @@ struct asoc_simple_priv { struct snd_soc_dai_link_component *platforms; struct asoc_simple_data adata; struct snd_soc_codec_conf *codec_conf; + struct prop_nums num; unsigned int mclk_fs; } *dai_props; struct asoc_simple_jack hp_jack; @@ -71,6 +78,7 @@ struct link_info { int link; /* number of link */ int conf; /* number of codec_conf */ int cpu; /* turn for CPU / Codec */ + struct prop_nums num[SNDRV_MINOR_DEVICES]; }; int asoc_simple_parse_daifmt(struct device *dev, diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 76036ea377a9..5fe53c5efcbf 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -628,6 +628,15 @@ static int graph_count_noml(struct asoc_simple_priv *priv, { struct device *dev = simple_priv_to_dev(priv); + if (li->link >= SNDRV_MINOR_DEVICES) { + dev_err(dev, "too many links\n"); + return -EINVAL; + } + + li->num[li->link].cpus = 1; + li->num[li->link].codecs = 1; + li->num[li->link].platforms = 1; + li->link += 1; /* 1xCPU-Codec */ li->dais += 2; /* 1xCPU + 1xCodec */ @@ -643,10 +652,23 @@ static int graph_count_dpcm(struct asoc_simple_priv *priv, { struct device *dev = simple_priv_to_dev(priv); + if (li->link >= SNDRV_MINOR_DEVICES) { + dev_err(dev, "too many links\n"); + return -EINVAL; + } + if (li->cpu) { + li->num[li->link].cpus = 1; + li->num[li->link].codecs = 1; + li->num[li->link].platforms = 1; + li->link++; /* 1xCPU-dummy */ li->dais++; /* 1xCPU */ } else { + li->num[li->link].cpus = 1; + li->num[li->link].codecs = 1; + li->num[li->link].platforms = 1; + li->link++; /* 1xdummy-Codec */ li->conf++; /* 1xdummy-Codec */ li->dais++; /* 1xCodec */ diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 3010ff63c71d..1606b9bc6b71 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -604,13 +604,27 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, struct asoc_simple_dai *dais; struct snd_soc_dai_link_component *dlcs; struct snd_soc_codec_conf *cconf = NULL; - int i; + int i, dai_num = 0, dlc_num = 0; dai_props = devm_kcalloc(dev, li->link, sizeof(*dai_props), GFP_KERNEL); dai_link = devm_kcalloc(dev, li->link, sizeof(*dai_link), GFP_KERNEL); - dais = devm_kcalloc(dev, li->dais, sizeof(*dais), GFP_KERNEL); - dlcs = devm_kcalloc(dev, li->link * 3, sizeof(*dai_props), GFP_KERNEL); - if (!dai_props || !dai_link || !dais || !dlcs) + if (!dai_props || !dai_link) + return -ENOMEM; + + /* + * dais (= CPU+Codec) + * dlcs (= CPU+Codec+Platform) + */ + for (i = 0; i < li->link; i++) { + int cc = li->num[i].cpus + li->num[i].codecs; + + dai_num += cc; + dlc_num += cc + li->num[i].platforms; + } + + dais = devm_kcalloc(dev, dai_num, sizeof(*dais), GFP_KERNEL); + dlcs = devm_kcalloc(dev, dlc_num, sizeof(*dai_props), GFP_KERNEL); + if (!dais || !dlcs) return -ENOMEM; if (li->conf) { @@ -619,24 +633,6 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, return -ENOMEM; } - /* - * "platform" might be removed - * see - * simple-card-utils.c :: asoc_simple_canonicalize_platform() - */ - for (i = 0; i < li->link; i++) { - dai_props[i].cpus = dlcs + (3 * i) + 0; - dai_props[i].codecs = dlcs + (3 * i) + 1; - dai_props[i].platforms = dlcs + (3 * i) + 2; - - dai_link[i].cpus = dai_props[i].cpus; - dai_link[i].num_cpus = 1; - dai_link[i].codecs = dai_props[i].codecs; - dai_link[i].num_codecs = 1; - dai_link[i].platforms = dai_props[i].platforms; - dai_link[i].num_platforms = 1; - } - priv->dai_props = dai_props; priv->dai_link = dai_link; priv->dais = dais; @@ -648,6 +644,38 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, card->codec_conf = cconf; card->num_configs = li->conf; + for (i = 0; i < li->link; i++) { + if (li->num[i].cpus) { + /* Normal CPU */ + dai_props[i].cpus = + dai_link[i].cpus = dlcs; + dai_props[i].num.cpus = + dai_link[i].num_cpus = li->num[i].cpus; + + dlcs += li->num[i].cpus; + } + + if (li->num[i].codecs) { + /* Normal Codec */ + dai_props[i].codecs = + dai_link[i].codecs = dlcs; + dai_props[i].num.codecs = + dai_link[i].num_codecs = li->num[i].codecs; + + dlcs += li->num[i].codecs; + } + + if (li->num[i].platforms) { + /* Have Platform */ + dai_props[i].platforms = + dai_link[i].platforms = dlcs; + dai_props[i].num.platforms = + dai_link[i].num_platforms = li->num[i].platforms; + + dlcs += li->num[i].platforms; + } + } + return 0; } EXPORT_SYMBOL_GPL(asoc_simple_init_priv); diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 9a05f44fc3a9..1fad570338b3 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -499,6 +499,17 @@ static int simple_count_noml(struct asoc_simple_priv *priv, struct device_node *codec, struct link_info *li, bool is_top) { + if (li->link >= SNDRV_MINOR_DEVICES) { + struct device *dev = simple_priv_to_dev(priv); + + dev_err(dev, "too many links\n"); + return -EINVAL; + } + + li->num[li->link].cpus = 1; + li->num[li->link].codecs = 1; + li->num[li->link].platforms = 1; + li->link += 1; li->dais += 2; @@ -510,10 +521,25 @@ static int simple_count_dpcm(struct asoc_simple_priv *priv, struct device_node *codec, struct link_info *li, bool is_top) { + if (li->link >= SNDRV_MINOR_DEVICES) { + struct device *dev = simple_priv_to_dev(priv); + + dev_err(dev, "too many links\n"); + return -EINVAL; + } + if (li->cpu) { + li->num[li->link].cpus = 1; + li->num[li->link].codecs = 1; + li->num[li->link].platforms = 1; + li->link++; /* CPU-dummy */ li->dais++; } else { + li->num[li->link].cpus = 1; + li->num[li->link].codecs = 1; + li->num[li->link].platforms = 1; + li->link++; /* dummy-Codec */ li->dais++; li->conf++; @@ -575,6 +601,10 @@ static void simple_get_dais_count(struct asoc_simple_priv *priv, * => 1 ccnf = 1xdummy-Codec */ if (!top) { + li->num[0].cpus = 1; + li->num[0].codecs = 1; + li->num[0].platforms = 1; + li->link = 1; li->dais = 2; li->conf = 0; From 205eb17eddb473c3159743c7d3aaf68db37b7231 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 1 Apr 2021 13:15:33 +0900 Subject: [PATCH 2/2] ASoC: simple-card-utils: share dummy DAI and reduce memory Current simple-card / audio-graph creates 1xCPU + 1xCodec + 1xPlatform for all dai_link, but some of them is not needed. For example Platform is not needed for DPCM BE case. Moreover, we can share snd-soc-dummy DAI for CPU-dummy / dummy-Codec in DPCM. This patch adds dummy DAI and share it when DPCM case, I beliave it can contribute to reduce memory. By this patch, CPU-dummy / dummy-CPU are set at asoc_simple_init_priv(), thus, its settings are no longer needed at DPCM detecting timing on simple-card / audio-graph. Moreover, we can remove triky Platform settings code for DPCM BE, because un-needed Platform is not created. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87tuoqod22.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 1 + sound/soc/generic/audio-graph-card.c | 12 +---------- sound/soc/generic/simple-card-utils.c | 30 ++++++++++++++++++++------- sound/soc/generic/simple-card.c | 12 +---------- 4 files changed, 26 insertions(+), 29 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 475f8cb14492..6635283a8160 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -62,6 +62,7 @@ struct asoc_simple_priv { struct snd_soc_dai_link *dai_link; struct asoc_simple_dai *dais; struct snd_soc_dai_link_component *dlcs; + struct snd_soc_dai_link_component dummy; struct snd_soc_codec_conf *codec_conf; struct gpio_desc *pa_gpio; const struct snd_soc_ops *ops; diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 5fe53c5efcbf..7be2c2cb253e 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -240,9 +240,6 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, int is_single_links = 0; /* Codec is dummy */ - codecs->of_node = NULL; - codecs->dai_name = "snd-soc-dummy-dai"; - codecs->name = "snd-soc-dummy"; /* FE settings */ dai_link->dynamic = 1; @@ -281,13 +278,11 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, /* card->num_links includes Codec */ asoc_simple_canonicalize_cpu(dai_link, is_single_links); + asoc_simple_canonicalize_platform(dai_link); } else { struct snd_soc_codec_conf *cconf; /* CPU is dummy */ - cpus->of_node = NULL; - cpus->dai_name = "snd-soc-dummy-dai"; - cpus->name = "snd-soc-dummy"; /* BE settings */ dai_link->no_pcm = 1; @@ -328,8 +323,6 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, graph_parse_convert(dev, ep, &dai_props->adata); graph_parse_mclk_fs(top, ep, dai_props); - asoc_simple_canonicalize_platform(dai_link); - ret = asoc_simple_parse_tdm(ep, dai); if (ret) goto out_put_node; @@ -659,15 +652,12 @@ static int graph_count_dpcm(struct asoc_simple_priv *priv, if (li->cpu) { li->num[li->link].cpus = 1; - li->num[li->link].codecs = 1; li->num[li->link].platforms = 1; li->link++; /* 1xCPU-dummy */ li->dais++; /* 1xCPU */ } else { - li->num[li->link].cpus = 1; li->num[li->link].codecs = 1; - li->num[li->link].platforms = 1; li->link++; /* 1xdummy-Codec */ li->conf++; /* 1xdummy-Codec */ diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 1606b9bc6b71..64b1ff5bafda 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -404,13 +404,6 @@ void asoc_simple_canonicalize_platform(struct snd_soc_dai_link *dai_link) /* Assumes platform == cpu */ if (!dai_link->platforms->of_node) dai_link->platforms->of_node = dai_link->cpus->of_node; - - /* - * DPCM BE can be no platform. - * Alloced memory will be waste, but not leak. - */ - if (!dai_link->platforms->of_node) - dai_link->num_platforms = 0; } EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_platform); @@ -633,6 +626,11 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, return -ENOMEM; } + /* dummy CPU/Codec */ + priv->dummy.of_node = NULL; + priv->dummy.dai_name = "snd-soc-dummy-dai"; + priv->dummy.name = "snd-soc-dummy"; + priv->dai_props = dai_props; priv->dai_link = dai_link; priv->dais = dais; @@ -653,6 +651,12 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, dai_link[i].num_cpus = li->num[i].cpus; dlcs += li->num[i].cpus; + } else { + /* DPCM Be's CPU = dummy */ + dai_props[i].cpus = + dai_link[i].cpus = &priv->dummy; + dai_props[i].num.cpus = + dai_link[i].num_cpus = 1; } if (li->num[i].codecs) { @@ -663,6 +667,12 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, dai_link[i].num_codecs = li->num[i].codecs; dlcs += li->num[i].codecs; + } else { + /* DPCM Fe's Codec = dummy */ + dai_props[i].codecs = + dai_link[i].codecs = &priv->dummy; + dai_props[i].num.codecs = + dai_link[i].num_codecs = 1; } if (li->num[i].platforms) { @@ -673,6 +683,12 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, dai_link[i].num_platforms = li->num[i].platforms; dlcs += li->num[i].platforms; + } else { + /* Doesn't have Platform */ + dai_props[i].platforms = + dai_link[i].platforms = NULL; + dai_props[i].num.platforms = + dai_link[i].num_platforms = 0; } } diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 1fad570338b3..9132c0ea05af 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -141,9 +141,6 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, int is_single_links = 0; /* Codec is dummy */ - codecs->of_node = NULL; - codecs->dai_name = "snd-soc-dummy-dai"; - codecs->name = "snd-soc-dummy"; /* FE settings */ dai_link->dynamic = 1; @@ -167,13 +164,11 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, goto out_put_node; asoc_simple_canonicalize_cpu(dai_link, is_single_links); + asoc_simple_canonicalize_platform(dai_link); } else { struct snd_soc_codec_conf *cconf; /* CPU is dummy */ - cpus->of_node = NULL; - cpus->dai_name = "snd-soc-dummy-dai"; - cpus->name = "snd-soc-dummy"; /* BE settings */ dai_link->no_pcm = 1; @@ -211,8 +206,6 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, simple_parse_convert(dev, np, &dai_props->adata); simple_parse_mclk_fs(top, np, codec, dai_props, prefix); - asoc_simple_canonicalize_platform(dai_link); - ret = asoc_simple_parse_tdm(np, dai); if (ret) goto out_put_node; @@ -530,15 +523,12 @@ static int simple_count_dpcm(struct asoc_simple_priv *priv, if (li->cpu) { li->num[li->link].cpus = 1; - li->num[li->link].codecs = 1; li->num[li->link].platforms = 1; li->link++; /* CPU-dummy */ li->dais++; } else { - li->num[li->link].cpus = 1; li->num[li->link].codecs = 1; - li->num[li->link].platforms = 1; li->link++; /* dummy-Codec */ li->dais++;