From 45919c28134519080a85a5fb66d0f65955ef7572 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 28 May 2024 05:05:14 +0000 Subject: [PATCH 01/11] ASoC: simple-card-utils: remove both playback/capture_only check soc-pcm.c :: soc_get_playback_capture() will indicate error if both playback_only / capture_only were true. Thus, graph_util_parse_link_direction() which setup playback_only / capture_only don't need to check it. And, its return value is not used on existing driver. Let's remove it. Signed-off-by: Kuninori Morimoto Link: https://msgid.link/r/87a5kah6gm.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 2 +- sound/soc/generic/simple-card-utils.c | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 2c2279d082ec..0a6435ac5c5f 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -197,7 +197,7 @@ int graph_util_is_ports0(struct device_node *port); int graph_util_parse_dai(struct device *dev, struct device_node *ep, struct snd_soc_dai_link_component *dlc, int *is_single_link); -int graph_util_parse_link_direction(struct device_node *np, +void graph_util_parse_link_direction(struct device_node *np, bool *is_playback_only, bool *is_capture_only); #ifdef DEBUG diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 852989611362..bc4d518c35cb 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -1140,7 +1140,7 @@ int graph_util_parse_dai(struct device *dev, struct device_node *ep, } EXPORT_SYMBOL_GPL(graph_util_parse_dai); -int graph_util_parse_link_direction(struct device_node *np, +void graph_util_parse_link_direction(struct device_node *np, bool *playback_only, bool *capture_only) { bool is_playback_only = false; @@ -1149,13 +1149,8 @@ int graph_util_parse_link_direction(struct device_node *np, is_playback_only = of_property_read_bool(np, "playback-only"); is_capture_only = of_property_read_bool(np, "capture-only"); - if (is_playback_only && is_capture_only) - return -EINVAL; - *playback_only = is_playback_only; *capture_only = is_capture_only; - - return 0; } EXPORT_SYMBOL_GPL(graph_util_parse_link_direction); From 72999a1b6663f1ff604e79aea54f168f78e2441a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 28 May 2024 05:05:20 +0000 Subject: [PATCH 02/11] ASoC: audio-graph-card2: add ep_to_port() / port_to_ports() Current audio-graph-card2 is using of_get_parent() to get "port" from "ep", or get "ports" from "port". But it is difficlut to understand, and "ports" might not exist. This patch adds ep_to_port() to get "port" from "ep", and port_to_ports() to get "ports" from "port". "ports" will be NULL if not exist. Signed-off-by: Kuninori Morimoto Link: https://msgid.link/r/878qzuh6gf.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card2.c | 46 +++++++++++++++++---------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index 81e84095107e..58123fbc2904 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -236,6 +236,18 @@ enum graph_type { #define port_to_endpoint(port) of_get_child_by_name(port, "endpoint") +#define ep_to_port(ep) of_get_parent(ep) +static struct device_node *port_to_ports(struct device_node *port) +{ + struct device_node *ports = of_get_parent(port); + + if (!of_node_name_eq(ports, "ports")) { + of_node_put(ports); + return NULL; + } + return ports; +} + static enum graph_type __graph_get_type(struct device_node *lnk) { struct device_node *np, *parent_np; @@ -320,7 +332,7 @@ static int graph_lnk_is_multi(struct device_node *lnk) static struct device_node *graph_get_next_multi_ep(struct device_node **port) { - struct device_node *ports = of_get_parent(*port); + struct device_node *ports = port_to_ports(*port); struct device_node *ep = NULL; struct device_node *rep = NULL; @@ -365,8 +377,8 @@ static const struct snd_soc_ops graph_ops = { static void graph_parse_convert(struct device_node *ep, struct simple_dai_props *props) { - struct device_node *port = of_get_parent(ep); - struct device_node *ports = of_get_parent(port); + struct device_node *port = ep_to_port(ep); + struct device_node *ports = port_to_ports(port); struct simple_util_data *adata = &props->adata; if (of_node_name_eq(ports, "ports")) @@ -381,8 +393,8 @@ static void graph_parse_convert(struct device_node *ep, static void graph_parse_mclk_fs(struct device_node *ep, struct simple_dai_props *props) { - struct device_node *port = of_get_parent(ep); - struct device_node *ports = of_get_parent(port); + struct device_node *port = ep_to_port(ep); + struct device_node *ports = port_to_ports(port); if (of_node_name_eq(ports, "ports")) of_property_read_u32(ports, "mclk-fs", &props->mclk_fs); @@ -481,8 +493,8 @@ static int __graph_parse_node(struct simple_util_priv *priv, if (!is_cpu && gtype == GRAPH_DPCM) { struct snd_soc_dai_link_component *codecs = snd_soc_link_to_codec(dai_link, idx); struct snd_soc_codec_conf *cconf = simple_props_to_codec_conf(dai_props, idx); - struct device_node *rport = of_get_parent(ep); - struct device_node *rports = of_get_parent(rport); + struct device_node *rport = ep_to_port(ep); + struct device_node *rports = port_to_ports(rport); if (of_node_name_eq(rports, "ports")) snd_soc_of_parse_node_prefix(rports, cconf, codecs->of_node, "prefix"); @@ -539,11 +551,11 @@ static int graph_parse_node_multi_nm(struct snd_soc_dai_link *dai_link, */ struct device_node *mcpu_ep = port_to_endpoint(mcpu_port); struct device_node *mcpu_ep_n = mcpu_ep; - struct device_node *mcpu_port_top = of_get_next_child(of_get_parent(mcpu_port), NULL); + struct device_node *mcpu_port_top = of_get_next_child(port_to_ports(mcpu_port), NULL); struct device_node *mcpu_ep_top = port_to_endpoint(mcpu_port_top); struct device_node *mcodec_ep_top = of_graph_get_remote_endpoint(mcpu_ep_top); - struct device_node *mcodec_port_top = of_get_parent(mcodec_ep_top); - struct device_node *mcodec_ports = of_get_parent(mcodec_port_top); + struct device_node *mcodec_port_top = ep_to_port(mcodec_ep_top); + struct device_node *mcodec_ports = port_to_ports(mcodec_port_top); int nm_max = max(dai_link->num_cpus, dai_link->num_codecs); int ret = -EINVAL; @@ -566,9 +578,9 @@ static int graph_parse_node_multi_nm(struct snd_soc_dai_link *dai_link, } mcodec_ep_n = of_graph_get_remote_endpoint(mcpu_ep_n); - mcodec_port = of_get_parent(mcodec_ep_n); + mcodec_port = ep_to_port(mcodec_ep_n); - if (mcodec_ports != of_get_parent(mcodec_port)) + if (mcodec_ports != port_to_ports(mcodec_port)) goto mcpu_err; codec_idx = 0; @@ -765,12 +777,12 @@ static void graph_link_init(struct simple_util_priv *priv, if (graph_lnk_is_multi(port)) { of_node_get(port); ep = graph_get_next_multi_ep(&port); - port = of_get_parent(ep); + port = ep_to_port(ep); } else { ep = port_to_endpoint(port); } - ports = of_get_parent(port); + ports = port_to_ports(port); /* * ports { @@ -966,7 +978,7 @@ int audio_graph2_link_c2c(struct simple_util_priv *priv, */ of_node_get(lnk); port0 = lnk; - ports = of_get_parent(port0); + ports = port_to_ports(port0); port1 = of_get_next_child(ports, lnk); /* @@ -1098,7 +1110,7 @@ static int graph_counter(struct device_node *lnk) * ignore first lnk part */ if (graph_lnk_is_multi(lnk)) { - struct device_node *ports = of_get_parent(lnk); + struct device_node *ports = port_to_ports(lnk); struct device_node *port = NULL; int cnt = 0; @@ -1195,7 +1207,7 @@ static int graph_count_c2c(struct simple_util_priv *priv, struct device_node *lnk, struct link_info *li) { - struct device_node *ports = of_get_parent(lnk); + struct device_node *ports = port_to_ports(lnk); struct device_node *port0 = lnk; struct device_node *port1 = of_get_next_child(ports, of_node_get(lnk)); struct device_node *ep0 = port_to_endpoint(port0); From 33ae57277ce08b83c65c18a09bf09499de613c01 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 28 May 2024 05:05:24 +0000 Subject: [PATCH 03/11] ASoC: audio-graph-card2: remove ports node name check Current audio-graph-card2 is checking if the node name was "ports" or not when parsing the property. if (of_node_name_eq(ports, "ports")) of_xxx(ports, ...); Now, it is using new port_to_ports() which will be NULL if the node doesn't have "ports", and each of_xxx functions will do nothing if node was NULL. Now we don't need to check ports node name. Let's remove and cleanup it. Signed-off-by: Kuninori Morimoto Link: https://msgid.link/r/877cfeh6gb.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card2.c | 15 +++++++-------- sound/soc/generic/simple-card-utils.c | 3 +++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index 58123fbc2904..3029e8ebfa22 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -381,8 +381,7 @@ static void graph_parse_convert(struct device_node *ep, struct device_node *ports = port_to_ports(port); struct simple_util_data *adata = &props->adata; - if (of_node_name_eq(ports, "ports")) - simple_util_parse_convert(ports, NULL, adata); + simple_util_parse_convert(ports, NULL, adata); simple_util_parse_convert(port, NULL, adata); simple_util_parse_convert(ep, NULL, adata); @@ -396,8 +395,7 @@ static void graph_parse_mclk_fs(struct device_node *ep, struct device_node *port = ep_to_port(ep); struct device_node *ports = port_to_ports(port); - if (of_node_name_eq(ports, "ports")) - of_property_read_u32(ports, "mclk-fs", &props->mclk_fs); + of_property_read_u32(ports, "mclk-fs", &props->mclk_fs); of_property_read_u32(port, "mclk-fs", &props->mclk_fs); of_property_read_u32(ep, "mclk-fs", &props->mclk_fs); @@ -496,8 +494,7 @@ static int __graph_parse_node(struct simple_util_priv *priv, struct device_node *rport = ep_to_port(ep); struct device_node *rports = port_to_ports(rport); - if (of_node_name_eq(rports, "ports")) - snd_soc_of_parse_node_prefix(rports, cconf, codecs->of_node, "prefix"); + snd_soc_of_parse_node_prefix(rports, cconf, codecs->of_node, "prefix"); snd_soc_of_parse_node_prefix(rport, cconf, codecs->of_node, "prefix"); of_node_put(rport); @@ -717,6 +714,9 @@ static void graph_parse_daifmt(struct device_node *node, { unsigned int fmt; + if (!node) + return; + /* * see also above "daifmt" explanation * and samples. @@ -798,8 +798,7 @@ static void graph_link_init(struct simple_util_priv *priv, */ graph_parse_daifmt(ep, &daifmt, &bit_frame); /* (C) */ graph_parse_daifmt(port, &daifmt, &bit_frame); /* (B) */ - if (of_node_name_eq(ports, "ports")) - graph_parse_daifmt(ports, &daifmt, &bit_frame); /* (A) */ + graph_parse_daifmt(ports, &daifmt, &bit_frame); /* (A) */ /* * convert bit_frame diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index bc4d518c35cb..a655f20428af 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -60,6 +60,9 @@ void simple_util_parse_convert(struct device_node *np, { char prop[128]; + if (!np) + return; + if (!prefix) prefix = ""; From 844de7eebe97a1c277f8a408457712086c957195 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 28 May 2024 05:05:28 +0000 Subject: [PATCH 04/11] ASoC: audio-graph-card2: expand dai_link property part Current dai_link related property are parsed and enabled only on CPU port node (A)(b)(c). OTOH, Audio Graph Card2 supports many connections like Multi-CPU, DPCM, Codec2Codec today. For example in Multi-CPU case, it will be checked via (X) -> (B) -> (b) process, but (X) / (B) part property is not parsed. >From dai_link related settings point of view, (B) (C) part and Codec port also enabled is more viscerally understandable, and useful. card2 { (X) links = <&snd-cpu (A) &snd-multi (B) &snd-dpcm (C) ...> multi { ports { (B) snd-multi: port { ... }; ... }; }; dpcm { ports { (C) snd-dpcm: port { ... }; ... }; }; codec2codec { ... }; }; cpu_device { ports { (A) snd-cpu: port { ... }; (b) mcpu: port { ... }; (c) dcpu: port { ... }; } }; One note here is that if it was Multi-CPU/Codec case, 1st port only enabled to have property it. Signed-off-by: Kuninori Morimoto Link: https://msgid.link/r/875xuyh6g7.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card2.c | 95 +++++++++++++++++---------- sound/soc/generic/simple-card-utils.c | 13 ++-- 2 files changed, 66 insertions(+), 42 deletions(-) diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index 3029e8ebfa22..bd714a6f74e6 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -763,42 +763,55 @@ static void graph_parse_daifmt(struct device_node *node, } static void graph_link_init(struct simple_util_priv *priv, - struct device_node *port, + struct device_node *lnk, + struct device_node *port_cpu, + struct device_node *port_codec, struct link_info *li, int is_cpu_node) { struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); - struct device_node *ep; - struct device_node *ports; + struct device_node *ep_cpu, *ep_codec; + struct device_node *ports_cpu, *ports_codec; unsigned int daifmt = 0, daiclk = 0; bool playback_only = 0, capture_only = 0; unsigned int bit_frame = 0; - if (graph_lnk_is_multi(port)) { - of_node_get(port); - ep = graph_get_next_multi_ep(&port); - port = ep_to_port(ep); + of_node_get(port_cpu); + if (graph_lnk_is_multi(port_cpu)) { + ep_cpu = graph_get_next_multi_ep(&port_cpu); + of_node_put(port_cpu); + port_cpu = ep_to_port(ep_cpu); } else { - ep = port_to_endpoint(port); + ep_cpu = port_to_endpoint(port_cpu); } + ports_cpu = port_to_ports(port_cpu); - ports = port_to_ports(port); + of_node_get(port_codec); + if (graph_lnk_is_multi(port_codec)) { + ep_codec = graph_get_next_multi_ep(&port_codec); + of_node_put(port_cpu); + port_codec = ep_to_port(ep_codec); + } else { + ep_codec = port_to_endpoint(port_codec); + } + ports_codec = port_to_ports(port_codec); - /* - * ports { - * (A) - * port { - * (B) - * endpoint { - * (C) - * }; - * }; - * }; - * }; - */ - graph_parse_daifmt(ep, &daifmt, &bit_frame); /* (C) */ - graph_parse_daifmt(port, &daifmt, &bit_frame); /* (B) */ - graph_parse_daifmt(ports, &daifmt, &bit_frame); /* (A) */ + + graph_parse_daifmt(ep_cpu, &daifmt, &bit_frame); + graph_parse_daifmt(ep_codec, &daifmt, &bit_frame); + graph_parse_daifmt(port_cpu, &daifmt, &bit_frame); + graph_parse_daifmt(port_codec, &daifmt, &bit_frame); + graph_parse_daifmt(ports_cpu, &daifmt, &bit_frame); + graph_parse_daifmt(ports_codec, &daifmt, &bit_frame); + graph_parse_daifmt(lnk, &daifmt, &bit_frame); + + graph_util_parse_link_direction(lnk, &playback_only, &capture_only); + graph_util_parse_link_direction(ports_cpu, &playback_only, &capture_only); + graph_util_parse_link_direction(ports_codec, &playback_only, &capture_only); + graph_util_parse_link_direction(port_cpu, &playback_only, &capture_only); + graph_util_parse_link_direction(port_codec, &playback_only, &capture_only); + graph_util_parse_link_direction(ep_cpu, &playback_only, &capture_only); + graph_util_parse_link_direction(ep_codec, &playback_only, &capture_only); /* * convert bit_frame @@ -809,16 +822,21 @@ static void graph_link_init(struct simple_util_priv *priv, if (is_cpu_node) daiclk = snd_soc_daifmt_clock_provider_flipped(daiclk); - graph_util_parse_link_direction(port, &playback_only, &capture_only); - - dai_link->playback_only = playback_only; - dai_link->capture_only = capture_only; + dai_link->playback_only = playback_only; + dai_link->capture_only = capture_only; dai_link->dai_fmt = daifmt | daiclk; dai_link->init = simple_util_dai_init; dai_link->ops = &graph_ops; if (priv->ops) dai_link->ops = priv->ops; + + of_node_put(ports_cpu); + of_node_put(ports_codec); + of_node_put(port_cpu); + of_node_put(port_codec); + of_node_put(ep_cpu); + of_node_put(ep_codec); } int audio_graph2_link_normal(struct simple_util_priv *priv, @@ -846,7 +864,7 @@ int audio_graph2_link_normal(struct simple_util_priv *priv, if (ret < 0) goto err; - graph_link_init(priv, cpu_port, li, 1); + graph_link_init(priv, lnk, cpu_port, codec_port, li, 1); err: of_node_put(codec_port); of_node_put(cpu_ep); @@ -861,13 +879,16 @@ int audio_graph2_link_dpcm(struct simple_util_priv *priv, { struct device_node *ep = port_to_endpoint(lnk); struct device_node *rep = of_graph_get_remote_endpoint(ep); - struct device_node *rport = of_graph_get_remote_port(ep); + struct device_node *cpu_port = NULL; + struct device_node *codec_port = NULL; struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); int is_cpu = graph_util_is_ports0(lnk); int ret; if (is_cpu) { + cpu_port = of_graph_get_remote_port(ep); /* rport */ + /* * dpcm { * // Front-End @@ -895,10 +916,13 @@ int audio_graph2_link_dpcm(struct simple_util_priv *priv, dai_link->dynamic = 1; dai_link->dpcm_merged_format = 1; - ret = graph_parse_node(priv, GRAPH_DPCM, rport, li, 1); + ret = graph_parse_node(priv, GRAPH_DPCM, cpu_port, li, 1); if (ret) goto err; + } else { + codec_port = of_graph_get_remote_port(ep); /* rport */ + /* * dpcm { * // Front-End @@ -928,7 +952,7 @@ int audio_graph2_link_dpcm(struct simple_util_priv *priv, dai_link->no_pcm = 1; dai_link->be_hw_params_fixup = simple_util_be_hw_params_fixup; - ret = graph_parse_node(priv, GRAPH_DPCM, rport, li, 0); + ret = graph_parse_node(priv, GRAPH_DPCM, codec_port, li, 0); if (ret < 0) goto err; } @@ -938,11 +962,12 @@ int audio_graph2_link_dpcm(struct simple_util_priv *priv, snd_soc_dai_link_set_capabilities(dai_link); - graph_link_init(priv, rport, li, is_cpu); + graph_link_init(priv, lnk, cpu_port, codec_port, li, is_cpu); err: of_node_put(ep); of_node_put(rep); - of_node_put(rport); + of_node_put(cpu_port); + of_node_put(codec_port); return ret; } @@ -1030,7 +1055,7 @@ int audio_graph2_link_c2c(struct simple_util_priv *priv, if (ret < 0) goto err2; - graph_link_init(priv, codec0_port, li, 1); + graph_link_init(priv, lnk, codec0_port, codec1_port, li, 1); err2: of_node_put(ep0); of_node_put(ep1); diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index a655f20428af..dcd0569157ce 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -1146,14 +1146,13 @@ EXPORT_SYMBOL_GPL(graph_util_parse_dai); void graph_util_parse_link_direction(struct device_node *np, bool *playback_only, bool *capture_only) { - bool is_playback_only = false; - bool is_capture_only = false; + bool is_playback_only = of_property_read_bool(np, "playback-only"); + bool is_capture_only = of_property_read_bool(np, "capture-only"); - is_playback_only = of_property_read_bool(np, "playback-only"); - is_capture_only = of_property_read_bool(np, "capture-only"); - - *playback_only = is_playback_only; - *capture_only = is_capture_only; + if (is_playback_only) + *playback_only = is_playback_only; + if (is_capture_only) + *capture_only = is_capture_only; } EXPORT_SYMBOL_GPL(graph_util_parse_link_direction); From f2d7e85962baf410b1bbbb4cf23a1ca59261ef76 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 28 May 2024 05:05:32 +0000 Subject: [PATCH 05/11] ASoC: audio-graph-card2: merge graph_parse_mclk_fs() into graph_link_init() Now graph_link_init() is parsing dai_link related property. Let's handle mclk_fs on it, too. Signed-off-by: Kuninori Morimoto Link: https://msgid.link/r/874jaih6g3.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card2.c | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index bd714a6f74e6..8eea81888758 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -389,20 +389,6 @@ static void graph_parse_convert(struct device_node *ep, of_node_put(ports); } -static void graph_parse_mclk_fs(struct device_node *ep, - struct simple_dai_props *props) -{ - struct device_node *port = ep_to_port(ep); - struct device_node *ports = port_to_ports(port); - - of_property_read_u32(ports, "mclk-fs", &props->mclk_fs); - of_property_read_u32(port, "mclk-fs", &props->mclk_fs); - of_property_read_u32(ep, "mclk-fs", &props->mclk_fs); - - of_node_put(port); - of_node_put(ports); -} - static int __graph_parse_node(struct simple_util_priv *priv, enum graph_type gtype, struct device_node *ep, @@ -424,8 +410,6 @@ static int __graph_parse_node(struct simple_util_priv *priv, dai = simple_props_to_dai_codec(dai_props, idx); } - graph_parse_mclk_fs(ep, dai_props); - ret = graph_util_parse_dai(dev, ep, dlc, &is_single_links); if (ret < 0) return ret; @@ -770,6 +754,7 @@ static void graph_link_init(struct simple_util_priv *priv, int is_cpu_node) { struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); + struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); struct device_node *ep_cpu, *ep_codec; struct device_node *ports_cpu, *ports_codec; unsigned int daifmt = 0, daiclk = 0; @@ -813,6 +798,14 @@ static void graph_link_init(struct simple_util_priv *priv, graph_util_parse_link_direction(ep_cpu, &playback_only, &capture_only); graph_util_parse_link_direction(ep_codec, &playback_only, &capture_only); + of_property_read_u32(lnk, "mclk-fs", &dai_props->mclk_fs); + of_property_read_u32(ports_cpu, "mclk-fs", &dai_props->mclk_fs); + of_property_read_u32(ports_codec, "mclk-fs", &dai_props->mclk_fs); + of_property_read_u32(port_cpu, "mclk-fs", &dai_props->mclk_fs); + of_property_read_u32(port_codec, "mclk-fs", &dai_props->mclk_fs); + of_property_read_u32(ep_cpu, "mclk-fs", &dai_props->mclk_fs); + of_property_read_u32(ep_codec, "mclk-fs", &dai_props->mclk_fs); + /* * convert bit_frame * We need to flip clock_provider if it was CPU node, From df23fcd56bb75ab522350bd8cb52bde9067aea45 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 28 May 2024 05:05:36 +0000 Subject: [PATCH 06/11] ASoC: audio-graph-card: add ep_to_port() / port_to_ports() Current audio-graph-card is using of_get_parent() to get "port" from "ep", or get "ports" from "port". But it is difficlut to understand, and "ports" might not exist. This patch adds ep_to_port() to get "port" from "ep", and port_to_ports() to get "ports" from "port". "ports" will be NULL if not exist. Signed-off-by: Kuninori Morimoto Link: https://msgid.link/r/8734q2h6fz.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 83e3ba773fbd..552b94908cf7 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -19,6 +19,18 @@ #define DPCM_SELECTABLE 1 +#define ep_to_port(ep) of_get_parent(ep) +static struct device_node *port_to_ports(struct device_node *port) +{ + struct device_node *ports = of_get_parent(port); + + if (!of_node_name_eq(ports, "ports")) { + of_node_put(ports); + return NULL; + } + return ports; +} + static int graph_outdrv_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) @@ -68,8 +80,8 @@ static void graph_parse_convert(struct device *dev, struct simple_util_data *adata) { struct device_node *top = dev->of_node; - struct device_node *port = of_get_parent(ep); - struct device_node *ports = of_get_parent(port); + struct device_node *port = ep_to_port(ep); + struct device_node *ports = port_to_ports(port); struct device_node *node = of_graph_get_port_parent(ep); simple_util_parse_convert(top, NULL, adata); @@ -87,8 +99,8 @@ static void graph_parse_mclk_fs(struct device_node *top, struct device_node *ep, struct simple_dai_props *props) { - struct device_node *port = of_get_parent(ep); - struct device_node *ports = of_get_parent(port); + struct device_node *port = ep_to_port(ep); + struct device_node *ports = port_to_ports(port); of_property_read_u32(top, "mclk-fs", &props->mclk_fs); if (of_node_name_eq(ports, "ports")) @@ -231,8 +243,8 @@ static int graph_dai_link_of_dpcm(struct simple_util_priv *priv, "be.%pOFP.%s", codecs->of_node, codecs->dai_name); /* check "prefix" from top node */ - port = of_get_parent(ep); - ports = of_get_parent(port); + port = ep_to_port(ep); + ports = port_to_ports(port); snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node, "prefix"); if (of_node_name_eq(ports, "ports")) @@ -350,7 +362,7 @@ static int __graph_for_each_link(struct simple_util_priv *priv, /* get codec */ codec_ep = of_graph_get_remote_endpoint(cpu_ep); - codec_port = of_get_parent(codec_ep); + codec_port = ep_to_port(codec_ep); /* get convert-xxx property */ memset(&adata, 0, sizeof(adata)); From 84c9601a92b755f869ac811607402e5b2162c225 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 28 May 2024 05:05:40 +0000 Subject: [PATCH 07/11] ASoC: audio-graph-card: remove ports node name check Current audio-graph-card is checking if the node name was "ports" or not when parsing the property. if (of_node_name_eq(ports, "ports")) of_xxx(ports, ...); Now, it is using new port_to_ports() which will be NULL if the node doesn't have "ports", and each of_xxx functions will do nothing if node was NULL. Now we don't need to check ports node name. Let's remove and cleanup it. Signed-off-by: Kuninori Morimoto Link: https://msgid.link/r/871q5mh6fv.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 552b94908cf7..c60f00146859 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -85,8 +85,7 @@ static void graph_parse_convert(struct device *dev, struct device_node *node = of_graph_get_port_parent(ep); simple_util_parse_convert(top, NULL, adata); - if (of_node_name_eq(ports, "ports")) - simple_util_parse_convert(ports, NULL, adata); + simple_util_parse_convert(ports, NULL, adata); simple_util_parse_convert(port, NULL, adata); simple_util_parse_convert(ep, NULL, adata); @@ -103,8 +102,7 @@ static void graph_parse_mclk_fs(struct device_node *top, struct device_node *ports = port_to_ports(port); of_property_read_u32(top, "mclk-fs", &props->mclk_fs); - if (of_node_name_eq(ports, "ports")) - of_property_read_u32(ports, "mclk-fs", &props->mclk_fs); + of_property_read_u32(ports, "mclk-fs", &props->mclk_fs); of_property_read_u32(port, "mclk-fs", &props->mclk_fs); of_property_read_u32(ep, "mclk-fs", &props->mclk_fs); @@ -245,12 +243,9 @@ static int graph_dai_link_of_dpcm(struct simple_util_priv *priv, /* check "prefix" from top node */ port = ep_to_port(ep); ports = port_to_ports(port); - snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node, - "prefix"); - if (of_node_name_eq(ports, "ports")) - snd_soc_of_parse_node_prefix(ports, cconf, codecs->of_node, "prefix"); - snd_soc_of_parse_node_prefix(port, cconf, codecs->of_node, - "prefix"); + snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node, "prefix"); + snd_soc_of_parse_node_prefix(ports, cconf, codecs->of_node, "prefix"); + snd_soc_of_parse_node_prefix(port, cconf, codecs->of_node, "prefix"); of_node_put(ports); of_node_put(port); From f23bac6e6913eed9eb831b4893255ea862d40ea5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 28 May 2024 05:05:44 +0000 Subject: [PATCH 08/11] ASoC: audio-graph-card: enable playback/capture_only property Audio Graph Card2 is supporting playback/capture_only property, let's follow Audio Graph Card, too. Signed-off-by: Kuninori Morimoto Link: https://msgid.link/r/87zfsafrvb.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index c60f00146859..6a19e40d2c4a 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -149,26 +149,44 @@ static int graph_parse_node(struct simple_util_priv *priv, } static int graph_link_init(struct simple_util_priv *priv, - struct device_node *cpu_ep, - struct device_node *codec_ep, + struct device_node *ep_cpu, + struct device_node *ep_codec, struct link_info *li, char *name) { struct device *dev = simple_priv_to_dev(priv); + struct device_node *top = dev->of_node; struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); + struct device_node *port_cpu = ep_to_port(ep_cpu); + struct device_node *port_codec = ep_to_port(ep_codec); + bool playback_only = 0, capture_only = 0; int ret; - ret = simple_util_parse_daifmt(dev, cpu_ep, codec_ep, + ret = simple_util_parse_daifmt(dev, ep_cpu, ep_codec, NULL, &dai_link->dai_fmt); if (ret < 0) - return ret; + goto init_end; + + graph_util_parse_link_direction(top, &playback_only, &capture_only); + graph_util_parse_link_direction(port_cpu, &playback_only, &capture_only); + graph_util_parse_link_direction(port_codec, &playback_only, &capture_only); + graph_util_parse_link_direction(ep_cpu, &playback_only, &capture_only); + graph_util_parse_link_direction(ep_codec, &playback_only, &capture_only); + + dai_link->playback_only = playback_only; + dai_link->capture_only = capture_only; dai_link->init = simple_util_dai_init; dai_link->ops = &graph_ops; if (priv->ops) dai_link->ops = priv->ops; - return simple_util_set_dailink_name(dev, dai_link, name); + ret = simple_util_set_dailink_name(dev, dai_link, name); +init_end: + of_node_put(port_cpu); + of_node_put(port_codec); + + return ret; } static int graph_dai_link_of_dpcm(struct simple_util_priv *priv, From a0174c88386b48bea7c35bc5a927f7057cb45d38 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 28 May 2024 05:05:48 +0000 Subject: [PATCH 09/11] ASoC: audio-graph-card: merge graph_parse_mclk_fs() into graph_link_init() Now graph_link_init() is parsing dai_link related property. Let's handle mclk_fs on it, too. Signed-off-by: Kuninori Morimoto Link: https://msgid.link/r/87y17ufrv8.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 32 +++++++++++----------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 6a19e40d2c4a..7b981aa8690a 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -94,29 +94,12 @@ static void graph_parse_convert(struct device *dev, of_node_put(node); } -static void graph_parse_mclk_fs(struct device_node *top, - struct device_node *ep, - struct simple_dai_props *props) -{ - struct device_node *port = ep_to_port(ep); - struct device_node *ports = port_to_ports(port); - - of_property_read_u32(top, "mclk-fs", &props->mclk_fs); - of_property_read_u32(ports, "mclk-fs", &props->mclk_fs); - of_property_read_u32(port, "mclk-fs", &props->mclk_fs); - of_property_read_u32(ep, "mclk-fs", &props->mclk_fs); - - of_node_put(port); - of_node_put(ports); -} - static int graph_parse_node(struct simple_util_priv *priv, struct device_node *ep, struct link_info *li, int *cpu) { struct device *dev = simple_priv_to_dev(priv); - struct device_node *top = dev->of_node; struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); struct snd_soc_dai_link_component *dlc; @@ -131,8 +114,6 @@ static int graph_parse_node(struct simple_util_priv *priv, dai = simple_props_to_dai_codec(dai_props, 0); } - graph_parse_mclk_fs(top, ep, dai_props); - ret = graph_util_parse_dai(dev, ep, dlc, cpu); if (ret < 0) return ret; @@ -157,8 +138,11 @@ static int graph_link_init(struct simple_util_priv *priv, struct device *dev = simple_priv_to_dev(priv); struct device_node *top = dev->of_node; struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); + struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); struct device_node *port_cpu = ep_to_port(ep_cpu); struct device_node *port_codec = ep_to_port(ep_codec); + struct device_node *ports_cpu = port_to_ports(port_cpu); + struct device_node *ports_codec = port_to_ports(port_codec); bool playback_only = 0, capture_only = 0; int ret; @@ -173,6 +157,14 @@ static int graph_link_init(struct simple_util_priv *priv, graph_util_parse_link_direction(ep_cpu, &playback_only, &capture_only); graph_util_parse_link_direction(ep_codec, &playback_only, &capture_only); + of_property_read_u32(top, "mclk-fs", &dai_props->mclk_fs); + of_property_read_u32(ports_cpu, "mclk-fs", &dai_props->mclk_fs); + of_property_read_u32(ports_codec, "mclk-fs", &dai_props->mclk_fs); + of_property_read_u32(port_cpu, "mclk-fs", &dai_props->mclk_fs); + of_property_read_u32(port_codec, "mclk-fs", &dai_props->mclk_fs); + of_property_read_u32(ep_cpu, "mclk-fs", &dai_props->mclk_fs); + of_property_read_u32(ep_codec, "mclk-fs", &dai_props->mclk_fs); + dai_link->playback_only = playback_only; dai_link->capture_only = capture_only; @@ -183,6 +175,8 @@ static int graph_link_init(struct simple_util_priv *priv, ret = simple_util_set_dailink_name(dev, dai_link, name); init_end: + of_node_put(ports_cpu); + of_node_put(ports_codec); of_node_put(port_cpu); of_node_put(port_codec); From 42d37e8de8f2d121481a65e6a3e10f6387c0ad4c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 28 May 2024 05:05:51 +0000 Subject: [PATCH 10/11] ASoC: simple-audio-card: enable playback/capture_only property Audio Graph Card2 is supporting playback/capture_only property, let's follow Simple Audio Card, too. Signed-off-by: Kuninori Morimoto Link: https://msgid.link/r/87wmnefrv4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 9c79ff6a568f..e436e8fcfa0f 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -187,24 +187,39 @@ static int simple_parse_node(struct simple_util_priv *priv, } static int simple_link_init(struct simple_util_priv *priv, - struct device_node *node, + struct device_node *cpu, struct device_node *codec, struct link_info *li, char *prefix, char *name) { struct device *dev = simple_priv_to_dev(priv); + struct device_node *top = dev->of_node; struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); + struct device_node *node = of_get_parent(cpu); + bool playback_only = 0, capture_only = 0; int ret; ret = simple_util_parse_daifmt(dev, node, codec, prefix, &dai_link->dai_fmt); if (ret < 0) - return 0; + goto init_end; + + graph_util_parse_link_direction(top, &playback_only, &capture_only); + graph_util_parse_link_direction(node, &playback_only, &capture_only); + graph_util_parse_link_direction(cpu, &playback_only, &capture_only); + graph_util_parse_link_direction(codec, &playback_only, &capture_only); + + dai_link->playback_only = playback_only; + dai_link->capture_only = capture_only; dai_link->init = simple_util_dai_init; dai_link->ops = &simple_ops; - return simple_util_set_dailink_name(dev, dai_link, name); + ret = simple_util_set_dailink_name(dev, dai_link, name); +init_end: + of_node_put(node); + + return ret; } static int simple_dai_link_of_dpcm(struct simple_util_priv *priv, @@ -278,7 +293,7 @@ static int simple_dai_link_of_dpcm(struct simple_util_priv *priv, snd_soc_dai_link_set_capabilities(dai_link); - ret = simple_link_init(priv, node, codec, li, prefix, dai_name); + ret = simple_link_init(priv, np, codec, li, prefix, dai_name); out_put_node: li->link++; @@ -336,7 +351,7 @@ static int simple_dai_link_of(struct simple_util_priv *priv, simple_util_canonicalize_cpu(cpus, single_cpu); simple_util_canonicalize_platform(platforms, cpus); - ret = simple_link_init(priv, node, codec, li, prefix, dai_name); + ret = simple_link_init(priv, cpu, codec, li, prefix, dai_name); dai_link_of_err: of_node_put(plat); From c4cfe1136d6edf8970ccdd944b7f86f7aa3edb77 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 28 May 2024 05:05:55 +0000 Subject: [PATCH 11/11] ASoC: simple-audio-card: merge simple_parse_mclk_fs() into simple_link_init() Now graph_link_init() is parsing dai_link related property. Let's handle mclk_fs on it, too. Signed-off-by: Kuninori Morimoto Link: https://msgid.link/r/87v82yfrv0.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index e436e8fcfa0f..2de5e6efe947 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -129,24 +129,6 @@ static void simple_parse_convert(struct device *dev, of_node_put(node); } -static void simple_parse_mclk_fs(struct device_node *top, - struct device_node *np, - struct simple_dai_props *props, - char *prefix) -{ - struct device_node *node = of_get_parent(np); - char prop[128]; - - snprintf(prop, sizeof(prop), "%smclk-fs", PREFIX); - of_property_read_u32(top, prop, &props->mclk_fs); - - snprintf(prop, sizeof(prop), "%smclk-fs", prefix); - of_property_read_u32(node, prop, &props->mclk_fs); - of_property_read_u32(np, prop, &props->mclk_fs); - - of_node_put(node); -} - static int simple_parse_node(struct simple_util_priv *priv, struct device_node *np, struct link_info *li, @@ -154,7 +136,6 @@ static int simple_parse_node(struct simple_util_priv *priv, int *cpu) { struct device *dev = simple_priv_to_dev(priv); - struct device_node *top = dev->of_node; struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); struct snd_soc_dai_link_component *dlc; @@ -169,8 +150,6 @@ static int simple_parse_node(struct simple_util_priv *priv, dai = simple_props_to_dai_codec(dai_props, 0); } - simple_parse_mclk_fs(top, np, dai_props, prefix); - ret = simple_parse_dai(dev, np, dlc, cpu); if (ret) return ret; @@ -195,6 +174,7 @@ static int simple_link_init(struct simple_util_priv *priv, struct device *dev = simple_priv_to_dev(priv); struct device_node *top = dev->of_node; struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); + struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); struct device_node *node = of_get_parent(cpu); bool playback_only = 0, capture_only = 0; int ret; @@ -209,6 +189,15 @@ static int simple_link_init(struct simple_util_priv *priv, graph_util_parse_link_direction(cpu, &playback_only, &capture_only); graph_util_parse_link_direction(codec, &playback_only, &capture_only); + of_property_read_u32(top, "mclk-fs", &dai_props->mclk_fs); + of_property_read_u32(top, PREFIX "mclk-fs", &dai_props->mclk_fs); + of_property_read_u32(node, "mclk-fs", &dai_props->mclk_fs); + of_property_read_u32(node, PREFIX "mclk-fs", &dai_props->mclk_fs); + of_property_read_u32(cpu, "mclk-fs", &dai_props->mclk_fs); + of_property_read_u32(cpu, PREFIX "mclk-fs", &dai_props->mclk_fs); + of_property_read_u32(codec, "mclk-fs", &dai_props->mclk_fs); + of_property_read_u32(codec, PREFIX "mclk-fs", &dai_props->mclk_fs); + dai_link->playback_only = playback_only; dai_link->capture_only = capture_only;