From: Kuninori Morimoto Date: Mon, 6 Jan 2025 05:49:49 +0000 (+0000) Subject: ASoC: audio-graph-card2: Use extra format on each DAI X-Git-Tag: v6.14-rc1~111^2~7^2~6^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=365865b7d7467aea9767ea18670198921bcada7c;p=thirdparty%2Fkernel%2Flinux.git ASoC: audio-graph-card2: Use extra format on each DAI Current ASoC is using dai_link->dai_fmt to set DAI format for both CPU/Codec. But because it is using same settings, and SND_SOC_DAIFMT_CLOCK_PROVIDER is flipped for CPU, we can't set both CPU/Codec as clock consumer, for example. To solve this issue, this patch uses extra format for each DAI which can keep compatibility with legacy system, 1. SND_SOC_DAIFMT_FORMAT_MASK 2. SND_SOC_DAIFMT_CLOCK 3. SND_SOC_DAIFMT_INV 4. SND_SOC_DAIFMT_CLOCK_PROVIDER Legacy dai_fmt includes 1, 2, 3, 4 New idea dai_fmt includes 1, 2, 3 ext_fmt includes 4 Signed-off-by: Kuninori Morimoto Tested-by: Stephen Gordon Link: https://patch.msgid.link/87pll0o5j6.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index 4e330aae04894..c36b1a2ac949e 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -667,8 +667,7 @@ static int graph_parse_node(struct simple_util_priv *priv, return graph_parse_node_single(priv, gtype, port, li, is_cpu); } -static void graph_parse_daifmt(struct device_node *node, - unsigned int *daifmt, unsigned int *bit_frame) +static void graph_parse_daifmt(struct device_node *node, unsigned int *daifmt) { unsigned int fmt; @@ -693,16 +692,6 @@ static void graph_parse_daifmt(struct device_node *node, * }; */ - /* - * clock_provider: - * - * It can be judged it is provider - * if (A) or (B) or (C) has bitclock-master / frame-master flag. - * - * use "or" - */ - *bit_frame |= snd_soc_daifmt_parse_clock_provider_as_bitmap(node, NULL); - #define update_daifmt(name) \ if (!(*daifmt & SND_SOC_DAIFMT_##name##_MASK) && \ (fmt & SND_SOC_DAIFMT_##name##_MASK)) \ @@ -720,6 +709,17 @@ static void graph_parse_daifmt(struct device_node *node, update_daifmt(INV); } +static unsigned int graph_parse_bitframe(struct device_node *ep) +{ + struct device_node *port __free(device_node) = ep_to_port(ep); + struct device_node *ports __free(device_node) = port_to_ports(port); + + return snd_soc_daifmt_clock_provider_from_bitmap( + snd_soc_daifmt_parse_clock_provider_as_bitmap(ep, NULL) | + snd_soc_daifmt_parse_clock_provider_as_bitmap(port, NULL) | + snd_soc_daifmt_parse_clock_provider_as_bitmap(ports, NULL)); +} + static void graph_link_init(struct simple_util_priv *priv, struct device_node *lnk, struct device_node *port_cpu, @@ -730,15 +730,19 @@ static void graph_link_init(struct simple_util_priv *priv, 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; - unsigned int daifmt = 0, daiclk = 0; + struct device_node *multi_cpu_port = NULL, *multi_codec_port = NULL; + struct snd_soc_dai_link_component *dlc; + unsigned int daifmt = 0; bool playback_only = 0, capture_only = 0; enum snd_soc_trigger_order trigger_start = SND_SOC_TRIGGER_ORDER_DEFAULT; enum snd_soc_trigger_order trigger_stop = SND_SOC_TRIGGER_ORDER_DEFAULT; - unsigned int bit_frame = 0; + int multi_cpu_port_idx = 1, multi_codec_port_idx = 1; + int i; of_node_get(port_cpu); if (graph_lnk_is_multi(port_cpu)) { - ep_cpu = graph_get_next_multi_ep(&port_cpu, 1); + multi_cpu_port = port_cpu; + ep_cpu = graph_get_next_multi_ep(&multi_cpu_port, multi_cpu_port_idx++); of_node_put(port_cpu); port_cpu = ep_to_port(ep_cpu); } else { @@ -748,7 +752,8 @@ static void graph_link_init(struct simple_util_priv *priv, of_node_get(port_codec); if (graph_lnk_is_multi(port_codec)) { - ep_codec = graph_get_next_multi_ep(&port_codec, 1); + multi_codec_port = port_codec; + ep_codec = graph_get_next_multi_ep(&multi_codec_port, multi_codec_port_idx++); of_node_put(port_codec); port_codec = ep_to_port(ep_codec); } else { @@ -756,13 +761,13 @@ static void graph_link_init(struct simple_util_priv *priv, } struct device_node *ports_codec __free(device_node) = port_to_ports(port_codec); - 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_parse_daifmt(ep_cpu, &daifmt); + graph_parse_daifmt(ep_codec, &daifmt); + graph_parse_daifmt(port_cpu, &daifmt); + graph_parse_daifmt(port_codec, &daifmt); + graph_parse_daifmt(ports_cpu, &daifmt); + graph_parse_daifmt(ports_codec, &daifmt); + graph_parse_daifmt(lnk, &daifmt); graph_util_parse_link_direction(lnk, &playback_only, &capture_only); graph_util_parse_link_direction(ports_cpu, &playback_only, &capture_only); @@ -788,14 +793,21 @@ static void graph_link_init(struct simple_util_priv *priv, graph_util_parse_trigger_order(priv, ep_cpu, &trigger_start, &trigger_stop); graph_util_parse_trigger_order(priv, ep_codec, &trigger_start, &trigger_stop); - /* - * convert bit_frame - * We need to flip clock_provider if it was CPU node, - * because it is Codec base. - */ - daiclk = snd_soc_daifmt_clock_provider_from_bitmap(bit_frame); - if (is_cpu_node) - daiclk = snd_soc_daifmt_clock_provider_flipped(daiclk); + for_each_link_cpus(dai_link, i, dlc) { + dlc->ext_fmt = graph_parse_bitframe(ep_cpu); + + if (multi_cpu_port) + ep_cpu = graph_get_next_multi_ep(&multi_cpu_port, multi_cpu_port_idx++); + } + + for_each_link_codecs(dai_link, i, dlc) { + dlc->ext_fmt = graph_parse_bitframe(ep_codec); + + if (multi_codec_port) + ep_codec = graph_get_next_multi_ep(&multi_codec_port, multi_codec_port_idx++); + } + + /*** Don't use port_cpu / port_codec after here ***/ dai_link->playback_only = playback_only; dai_link->capture_only = capture_only; @@ -803,7 +815,7 @@ static void graph_link_init(struct simple_util_priv *priv, dai_link->trigger_start = trigger_start; dai_link->trigger_stop = trigger_stop; - dai_link->dai_fmt = daifmt | daiclk; + dai_link->dai_fmt = daifmt; dai_link->init = simple_util_dai_init; dai_link->ops = &graph_ops; if (priv->ops)