[alsa-devel] [PATCH v6 0/3] ASoC: simple-card: Add multi-CODEC support
This patch set adds multi-CODEC support to the simple card.
v6: (Mark Brown) - don't stop unreferencing the codec nodes on null node - split the patch about simple-card.c - add example 3 in the DT binding v5: accept only "sound-dai" as the dai link property (Arnd Bergmann) v4: (Mark Brown) - document the new core function - calculation of the number of codecs moved to the core function - split the patch about simple-card.c - less code changes - remove the cast of pointers - less changes in the DT binding example 2 v3: rebase on broonie git 2014/11/03 v2: accept list of CODECs in 'sound-dais' (Benoit Cousson)
Happy New Year!
Jean-Francois Moine (3): ASoC: simple-card: prepare multi-CODECs ASoC: simple-card: Add multi-CODECs in DT ASoC: simple-card: Remove useless check
.../devicetree/bindings/sound/simple-card.txt | 19 ++++- sound/soc/generic/simple-card.c | 81 +++++++++++----------- 2 files changed, 60 insertions(+), 40 deletions(-)
The function asoc_simple_card_sub_parse_of() is used to parse either the CPU or CODEC DAI. To prepare support of many CODECs in a DAI link, the parsing of the phandle and DAI name must be moved to the upper function asoc_simple_card_dai_link_of().
Signed-off-by: Jean-Francois Moine moinejf@free.fr --- sound/soc/generic/simple-card.c | 57 ++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 29 deletions(-)
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index fb9240f..170de17 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -172,34 +172,12 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd) static int asoc_simple_card_sub_parse_of(struct device_node *np, struct asoc_simple_dai *dai, - struct device_node **p_node, - const char **name, - int *args_count) + struct device_node *dai_np) { - struct of_phandle_args args; struct clk *clk; u32 val; int ret;
- /* - * Get node via "sound-dai = <&phandle port>" - * it will be used as xxx_of_node on soc_bind_dai_link() - */ - ret = of_parse_phandle_with_args(np, "sound-dai", - "#sound-dai-cells", 0, &args); - if (ret) - return ret; - - *p_node = args.np; - - if (args_count) - *args_count = args.args_count; - - /* Get dai->name */ - ret = snd_soc_of_get_dai_name(np, name); - if (ret < 0) - return ret; - /* Parse TDM slot */ ret = snd_soc_of_parse_tdm_slot(np, &dai->slots, &dai->slot_width); if (ret) @@ -222,7 +200,7 @@ asoc_simple_card_sub_parse_of(struct device_node *np, } else if (!of_property_read_u32(np, "system-clock-frequency", &val)) { dai->sysclk = val; } else { - clk = of_clk_get(args.np, 0); + clk = of_clk_get(dai_np, 0); if (!IS_ERR(clk)) dai->sysclk = clk_get_rate(clk); } @@ -286,6 +264,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx); struct device_node *cpu = NULL; struct device_node *codec = NULL; + struct of_phandle_args args; char *name; char prop[128]; char *prefix = ""; @@ -312,16 +291,36 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, if (ret < 0) goto dai_link_of_err;
+ /* Get the CPU node and name */ + ret = of_parse_phandle_with_args(cpu, "sound-dai", + "#sound-dai-cells", 0, &args); + if (ret) + goto dai_link_of_err; + dai_link->cpu_of_node = args.np; + cpu_args = args.args_count; + + ret = snd_soc_of_get_dai_name(cpu, &dai_link->cpu_dai_name); + if (ret < 0) + goto dai_link_of_err; + ret = asoc_simple_card_sub_parse_of(cpu, &dai_props->cpu_dai, - &dai_link->cpu_of_node, - &dai_link->cpu_dai_name, - &cpu_args); + dai_link->cpu_of_node); if (ret < 0) goto dai_link_of_err;
+ /* Get the node and name of the CODEC */ + ret = of_parse_phandle_with_args(codec, "sound-dai", + "#sound-dai-cells", 0, &args); + if (ret < 0) + goto dai_link_of_err; + dai_link->codec_of_node = args.np; + + ret = snd_soc_of_get_dai_name(codec, &dai_link->codec_dai_name); + if (ret < 0) + goto dai_link_of_err; + ret = asoc_simple_card_sub_parse_of(codec, &dai_props->codec_dai, - &dai_link->codec_of_node, - &dai_link->codec_dai_name, NULL); + dai_link->codec_of_node); if (ret < 0) goto dai_link_of_err;
This patch allows to declare many CODECs per DAI link in the device tree.
Signed-off-by: Jean-Francois Moine moinejf@free.fr --- .../devicetree/bindings/sound/simple-card.txt | 19 ++++++++++- sound/soc/generic/simple-card.c | 39 +++++++++++++--------- 2 files changed, 42 insertions(+), 16 deletions(-)
diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt index c3cba60..6e3a011 100644 --- a/Documentation/devicetree/bindings/sound/simple-card.txt +++ b/Documentation/devicetree/bindings/sound/simple-card.txt @@ -65,7 +65,8 @@ properties should also be placed in the codec node if needed.
Required CPU/CODEC subnodes properties:
-- sound-dai : phandle and port of CPU/CODEC +- sound-dai : phandle and port of CPU + or list of phandle and port of CODECs
Optional CPU/CODEC subnodes properties:
@@ -153,3 +154,19 @@ sound { }; }; }; + +Example 3 - many CODECs + +sound { + compatible = "simple-audio-card"; + simple-audio-card,name = "Cubox Simple Audio"; + + simple-audio-card,dai-link { /* S/PDIF - HDMI & S/PDIF */ + cpu { + sound-dai = <&audio1 1>; + }; + codec { + sound-dai = <&tda998x 1>, <&spdif_codec>; + }; + }; +}; diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 170de17..a765869 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -264,11 +264,12 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx); struct device_node *cpu = NULL; struct device_node *codec = NULL; + struct snd_soc_dai_link_component *component; struct of_phandle_args args; char *name; char prop[128]; char *prefix = ""; - int ret, cpu_args; + int ret, cpu_args, i;
/* For single DAI link & old style of DT node */ if (is_top_level_node) @@ -308,19 +309,13 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, if (ret < 0) goto dai_link_of_err;
- /* Get the node and name of the CODEC */ - ret = of_parse_phandle_with_args(codec, "sound-dai", - "#sound-dai-cells", 0, &args); + /* Get the node and name of the CODECs */ + ret = snd_soc_of_get_dai_link_codecs(dev, codec, dai_link); if (ret < 0) goto dai_link_of_err; - dai_link->codec_of_node = args.np; - - ret = snd_soc_of_get_dai_name(codec, &dai_link->codec_dai_name); - if (ret < 0) - goto dai_link_of_err;
ret = asoc_simple_card_sub_parse_of(codec, &dai_props->codec_dai, - dai_link->codec_of_node); + dai_link->codecs[0].of_node); if (ret < 0) goto dai_link_of_err;
@@ -335,10 +330,10 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, /* DAI link name is created from CPU/CODEC dai name */ name = devm_kzalloc(dev, strlen(dai_link->cpu_dai_name) + - strlen(dai_link->codec_dai_name) + 2, + strlen(dai_link->codecs[0].dai_name) + 2, GFP_KERNEL); sprintf(name, "%s-%s", dai_link->cpu_dai_name, - dai_link->codec_dai_name); + dai_link->codecs[0].dai_name); dai_link->name = dai_link->stream_name = name; dai_link->ops = &asoc_simple_card_ops; dai_link->init = asoc_simple_card_dai_init; @@ -349,7 +344,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, dai_props->cpu_dai.fmt, dai_props->cpu_dai.sysclk); dev_dbg(dev, "\tcodec : %s / %04x / %d\n", - dai_link->codec_dai_name, + dai_link->codecs[0].dai_name, dai_props->codec_dai.fmt, dai_props->codec_dai.sysclk);
@@ -365,7 +360,17 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, if (!cpu_args) dai_link->cpu_dai_name = NULL;
+ of_node_put(cpu); + of_node_put(codec); + return 0; + dai_link_of_err: + for (i = 0, component = dai_link->codecs; + i < dai_link->num_codecs; + i++, component++) { + of_node_put(component->of_node); + component->of_node = NULL; + } of_node_put(cpu); of_node_put(codec);
@@ -455,13 +460,17 @@ static int asoc_simple_card_unref(struct platform_device *pdev) { struct snd_soc_card *card = platform_get_drvdata(pdev); struct snd_soc_dai_link *dai_link; - int num_links; + struct snd_soc_dai_link_component *component; + int num_links, i;
for (num_links = 0, dai_link = card->dai_link; num_links < card->num_links; num_links++, dai_link++) { of_node_put(dai_link->cpu_of_node); - of_node_put(dai_link->codec_of_node); + for (i = 0, component = dai_link->codecs; + i < dai_link->num_codecs; + i++, component++) + of_node_put(component->of_node); } return 0; }
The CPU and CODEC names are checked when getting the DAI names. There is no need to check them once more.
Signed-off-by: Jean-Francois Moine moinejf@free.fr --- sound/soc/generic/simple-card.c | 5 ----- 1 file changed, 5 deletions(-)
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index a765869..c28d082 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -319,11 +319,6 @@ static int asoc_simple_card_dai_link_of(struct device_node *node, if (ret < 0) goto dai_link_of_err;
- if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) { - ret = -EINVAL; - goto dai_link_of_err; - } - /* Simple Card assumes platform == cpu */ dai_link->platform_of_node = dai_link->cpu_of_node;
participants (1)
-
Jean-Francois Moine