[v3,3/8] ASoC: soc-core: add snd_soc_daifmt_parse_format/clock_provider()

Message ID 877dixw9ej.wl-kuninori.morimoto.gx@renesas.com
State Accepted
Commit 7766861d1f8d3afc35361ab599eee6851fcd4416
Headers show
Series
  • ASoC: tidyup snd_soc_of_parse_daifmt()
Related show

Commit Message

Kuninori Morimoto June 14, 2021, 12:57 a.m.
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

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>
---
 include/sound/soc.h  |  14 +++++
 sound/soc/soc-core.c | 124 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 138 insertions(+)

Patch

diff --git a/include/sound/soc.h b/include/sound/soc.h
index 45f3da277c5d..63194a8773cd 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -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,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 0a8143e3fcdb..4cb9bb009e90 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -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,