From f2138aed231c88d5c4fa8d06aa15ad19685087c2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 1 Apr 2021 13:15:23 +0900 Subject: [PATCH] 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;