[PATCH 4/9] ASoC: soc-core: add snd_soc_daifmt_parse_format/clock_provider()
Kuninori Morimoto
kuninori.morimoto.gx at renesas.com
Tue Jun 8 02:12:24 CEST 2021
From: Kuninori Morimoto <kuninori.morimoto.gx at renesas.com>
snd_soc_of_parse_daifmt() parses daifmt, but bitclock/frame provider
parsing part is one of headache, 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 A) style as original style,
and user need to update to B) style for clock_provider part if needed.
In such case, user need to re-parse it, like below.
daifmt = snd_soc_of_parse_daifmt(..., &bitclkmaster, &framemaster);
daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;
if (codec == bitclkmaster)
daifmt |= (codec == framemaster) ?
SND_SOC_DAIFMT_CBM_CFM : SND_SOC_DAIFMT_CBM_CFS;
else
daifmt |= (codec == framemaster) ?
SND_SOC_DAIFMT_CBS_CFM : SND_SOC_DAIFMT_CBS_CFS;
This patch adds new functions which separetes
snd_soc_of_parse_daifmt() helper function into
parsing format part (= snd_soc_daifmt_parse_format()), and
parsing clock_provider part (= snd_soc_daifmt_parse_clock_provider()).
User can use snd_soc_daifmt_clock_provider_pickup/fliped() helper
function with it.
style A)
bit_frame = snd_soc_daifmt_parse_clock_provider();
daifmt = snd_soc_daifmt_parse_format(...) | /* format part */
snd_soc_daifmt_clock_provider_pickup(bit_frame); /* clock part */
style B)
snd_soc_daifmt_parse_clock_provider(..., &bit, &frame);
daifmt = snd_soc_daifmt_parse_format(...) | /* format part */
snd_soc_daifmt_clock_provider_pickup( /* clock part */
((codec == bit) << 4) + (codec == frame));
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx at renesas.com>
---
include/sound/soc.h | 6 +++
sound/soc/soc-core.c | 114 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 120 insertions(+)
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 0f25d4be92ae..f402b259a255 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -1235,6 +1235,12 @@ 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_pickup(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(struct device_node *np,
+ const char *prefix,
+ struct device_node **bitclkmaster,
+ struct device_node **framemaster);
unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
const char *prefix,
struct device_node **bitclkmaster,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index fd5a3b60aeb3..a9cb39c3d8c5 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3045,6 +3045,120 @@ unsigned int snd_soc_daifmt_clock_provider_pickup(unsigned int bit_frame)
}
EXPORT_SYMBOL_GPL(snd_soc_daifmt_clock_provider_pickup);
+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(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 (bit << 4) + frame;
+}
+EXPORT_SYMBOL_GPL(snd_soc_daifmt_parse_clock_provider);
+
unsigned int snd_soc_of_parse_daifmt(struct device_node *np,
const char *prefix,
struct device_node **bitclkmaster,
--
2.25.1
More information about the Alsa-devel
mailing list