ASoC: soc-core: add snd_soc_daifmt_parse_format/clock_provider()
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Mon, 14 Jun 2021 00:57:08 +0000 (09:57 +0900)
committerMark Brown <broonie@kernel.org>
Mon, 21 Jun 2021 12:05:17 +0000 (13:05 +0100)
snd_soc_of_parse_daifmt() parses daifmt, but bitclock/frame provider
parsing part is one of headacke, because we are assuming below both cases.

A) node {
bitclock-master;
frame-master;
...
};

B) link {
bitclock-master = <&xxx>;
frame-master = <&xxx>;
...
};

The original was style A), and style B) was added later
by commit b3ca11ff59bc ("ASoC: simple-card: Move dai-link level
properties away from dai subnodes").

snd_soc_of_parse_daifmt() parses it as style A),
and user need to update it to style B) if needed.

To handle it more flexibile, this patch adds new functions
which separates snd_soc_of_parse_daifmt() helper function.

 snd_soc_daifmt_parse_format()  :for DAI format
 snd_soc_daifmt_parse_clock_provider_as_flag()  :for style A)
 snd_soc_daifmt_parse_clock_provider_as_phandl() :for style B)
 snd_soc_daifmt_parse_clock_provider_as_bitmap() :use with _from_bitmap

This means

 snd_soc_of_parse_daifmt() ==
snd_soc_daifmt_parse_format() |
snd_soc_daifmt_parse_clock_provider_as_flag()

This patch also indicate relatesionship comment for
snd_soc_daifmt_clock_provider_from_bitmap().

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Link: https://lore.kernel.org/r/877dixw9ej.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>
include/sound/soc.h
sound/soc/soc-core.c

index 45f3da2..63194a8 100644 (file)
@@ -1235,6 +1235,20 @@ int snd_soc_of_parse_aux_devs(struct snd_soc_card *card, const char *propname);
 
 unsigned int snd_soc_daifmt_clock_provider_fliped(unsigned int dai_fmt);
 unsigned int snd_soc_daifmt_clock_provider_from_bitmap(unsigned int bit_frame);
+
+unsigned int snd_soc_daifmt_parse_format(struct device_node *np, const char *prefix);
+unsigned int snd_soc_daifmt_parse_clock_provider_raw(struct device_node *np,
+                                                    const char *prefix,
+                                                    struct device_node **bitclkmaster,
+                                                    struct device_node **framemaster);
+#define snd_soc_daifmt_parse_clock_provider_as_bitmap(np, prefix)      \
+       snd_soc_daifmt_parse_clock_provider_raw(np, prefix, NULL, NULL)
+#define snd_soc_daifmt_parse_clock_provider_as_phandle                 \
+       snd_soc_daifmt_parse_clock_provider_raw
+#define snd_soc_daifmt_parse_clock_provider_as_flag(np, prefix)                \
+       snd_soc_daifmt_clock_provider_from_bitmap(                      \
+               snd_soc_daifmt_parse_clock_provider_as_bitmap(np, prefix))
+
 unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
                                     const char *prefix,
                                     struct device_node **bitclkmaster,
index 6050f44..c22e8b5 100644 (file)
@@ -3029,6 +3029,11 @@ EXPORT_SYMBOL_GPL(snd_soc_daifmt_clock_provider_fliped);
 
 unsigned int snd_soc_daifmt_clock_provider_from_bitmap(unsigned int bit_frame)
 {
+       /*
+        * bit_frame is return value from
+        *      snd_soc_daifmt_parse_clock_provider_raw()
+        */
+
        /* Codec base */
        switch (bit_frame) {
        case 0x11:
@@ -3045,6 +3050,125 @@ unsigned int snd_soc_daifmt_clock_provider_from_bitmap(unsigned int bit_frame)
 }
 EXPORT_SYMBOL_GPL(snd_soc_daifmt_clock_provider_from_bitmap);
 
+unsigned int snd_soc_daifmt_parse_format(struct device_node *np,
+                                        const char *prefix)
+{
+       int ret, i;
+       char prop[128];
+       unsigned int format = 0;
+       int bit, frame;
+       const char *str;
+       struct {
+               char *name;
+               unsigned int val;
+       } of_fmt_table[] = {
+               { "i2s",        SND_SOC_DAIFMT_I2S },
+               { "right_j",    SND_SOC_DAIFMT_RIGHT_J },
+               { "left_j",     SND_SOC_DAIFMT_LEFT_J },
+               { "dsp_a",      SND_SOC_DAIFMT_DSP_A },
+               { "dsp_b",      SND_SOC_DAIFMT_DSP_B },
+               { "ac97",       SND_SOC_DAIFMT_AC97 },
+               { "pdm",        SND_SOC_DAIFMT_PDM},
+               { "msb",        SND_SOC_DAIFMT_MSB },
+               { "lsb",        SND_SOC_DAIFMT_LSB },
+       };
+
+       if (!prefix)
+               prefix = "";
+
+       /*
+        * check "dai-format = xxx"
+        * or    "[prefix]format = xxx"
+        * SND_SOC_DAIFMT_FORMAT_MASK area
+        */
+       ret = of_property_read_string(np, "dai-format", &str);
+       if (ret < 0) {
+               snprintf(prop, sizeof(prop), "%sformat", prefix);
+               ret = of_property_read_string(np, prop, &str);
+       }
+       if (ret == 0) {
+               for (i = 0; i < ARRAY_SIZE(of_fmt_table); i++) {
+                       if (strcmp(str, of_fmt_table[i].name) == 0) {
+                               format |= of_fmt_table[i].val;
+                               break;
+                       }
+               }
+       }
+
+       /*
+        * check "[prefix]continuous-clock"
+        * SND_SOC_DAIFMT_CLOCK_MASK area
+        */
+       snprintf(prop, sizeof(prop), "%scontinuous-clock", prefix);
+       if (of_property_read_bool(np, prop))
+               format |= SND_SOC_DAIFMT_CONT;
+       else
+               format |= SND_SOC_DAIFMT_GATED;
+
+       /*
+        * check "[prefix]bitclock-inversion"
+        * check "[prefix]frame-inversion"
+        * SND_SOC_DAIFMT_INV_MASK area
+        */
+       snprintf(prop, sizeof(prop), "%sbitclock-inversion", prefix);
+       bit = !!of_get_property(np, prop, NULL);
+
+       snprintf(prop, sizeof(prop), "%sframe-inversion", prefix);
+       frame = !!of_get_property(np, prop, NULL);
+
+       switch ((bit << 4) + frame) {
+       case 0x11:
+               format |= SND_SOC_DAIFMT_IB_IF;
+               break;
+       case 0x10:
+               format |= SND_SOC_DAIFMT_IB_NF;
+               break;
+       case 0x01:
+               format |= SND_SOC_DAIFMT_NB_IF;
+               break;
+       default:
+               /* SND_SOC_DAIFMT_NB_NF is default */
+               break;
+       }
+
+       return format;
+}
+EXPORT_SYMBOL_GPL(snd_soc_daifmt_parse_format);
+
+unsigned int snd_soc_daifmt_parse_clock_provider_raw(struct device_node *np,
+                                                    const char *prefix,
+                                                    struct device_node **bitclkmaster,
+                                                    struct device_node **framemaster)
+{
+       char prop[128];
+       unsigned int bit, frame;
+
+       if (!prefix)
+               prefix = "";
+
+       /*
+        * check "[prefix]bitclock-master"
+        * check "[prefix]frame-master"
+        */
+       snprintf(prop, sizeof(prop), "%sbitclock-master", prefix);
+       bit = !!of_get_property(np, prop, NULL);
+       if (bit && bitclkmaster)
+               *bitclkmaster = of_parse_phandle(np, prop, 0);
+
+       snprintf(prop, sizeof(prop), "%sframe-master", prefix);
+       frame = !!of_get_property(np, prop, NULL);
+       if (frame && framemaster)
+               *framemaster = of_parse_phandle(np, prop, 0);
+
+       /*
+        * return bitmap.
+        * It will be parameter of
+        *      snd_soc_daifmt_clock_provider_from_bitmap()
+        */
+       return (bit << 4) + frame;
+}
+EXPORT_SYMBOL_GPL(snd_soc_daifmt_parse_clock_provider_raw);
+
 unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
                                     const char *prefix,
                                     struct device_node **bitclkmaster,