]> www.infradead.org Git - users/hch/misc.git/commitdiff
ASoC: audio-graph-card2: Use extra format on each DAI
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Mon, 6 Jan 2025 05:49:49 +0000 (05:49 +0000)
committerMark Brown <broonie@kernel.org>
Mon, 13 Jan 2025 14:16:56 +0000 (14:16 +0000)
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 <kuninori.morimoto.gx@renesas.com>
Tested-by: Stephen Gordon <gordoste@iinet.net.au>
Link: https://patch.msgid.link/87pll0o5j6.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/generic/audio-graph-card2.c

index 4e330aae0489419018b1c0a330e2e8e02b156c14..c36b1a2ac949ea4ab4ce404e57ffe498721fb38b 100644 (file)
@@ -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)