Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1b5721b2 authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Mark Brown
Browse files

ASoC: simple-card: add asoc_simple_card_parse_daifmt()



Current daifmt setting method in simple-card driver is
placed to many places, and using un-readable/confusable method.
This patch adds new asoc_simple_card_parse_daifmt()
and tidyup code.

Signed-off-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 84d4cbe9
Loading
Loading
Loading
Loading
+65 −69
Original line number Diff line number Diff line
@@ -226,6 +226,53 @@ asoc_simple_card_sub_parse_of(struct device_node *np,
	return 0;
}

static int asoc_simple_card_parse_daifmt(struct device_node *node,
					 struct simple_card_data *priv,
					 struct device_node *cpu,
					 struct device_node *codec,
					 char *prefix, int idx)
{
	struct device *dev = simple_priv_to_dev(priv);
	struct device_node *bitclkmaster = NULL;
	struct device_node *framemaster = NULL;
	struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx);
	struct asoc_simple_dai *cpu_dai = &dai_props->cpu_dai;
	struct asoc_simple_dai *codec_dai = &dai_props->codec_dai;
	unsigned int daifmt;

	daifmt = snd_soc_of_parse_daifmt(node, prefix,
					 &bitclkmaster, &framemaster);
	daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;

	if (strlen(prefix) && !bitclkmaster && !framemaster) {
		/*
		 * No dai-link level and master setting was not found from
		 * sound node level, revert back to legacy DT parsing and
		 * take the settings from codec node.
		 */
		dev_dbg(dev, "Revert to legacy daifmt parsing\n");

		cpu_dai->fmt = codec_dai->fmt =
			snd_soc_of_parse_daifmt(codec, NULL, NULL, NULL) |
			(daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK);
	} else {
		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;

		cpu_dai->fmt	= daifmt;
		codec_dai->fmt	= daifmt;
	}

	of_node_put(bitclkmaster);
	of_node_put(framemaster);

	return 0;
}

static int asoc_simple_card_dai_link_of(struct device_node *node,
					struct simple_card_data *priv,
					int idx,
@@ -234,10 +281,8 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
	struct device *dev = simple_priv_to_dev(priv);
	struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx);
	struct simple_dai_props *dai_props = simple_priv_to_props(priv, idx);
	struct device_node *np = NULL;
	struct device_node *bitclkmaster = NULL;
	struct device_node *framemaster = NULL;
	unsigned int daifmt;
	struct device_node *cpu = NULL;
	struct device_node *codec = NULL;
	char *name;
	char prop[128];
	char *prefix = "";
@@ -247,85 +292,36 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
	if (is_top_level_node)
		prefix = "simple-audio-card,";

	daifmt = snd_soc_of_parse_daifmt(node, prefix,
					 &bitclkmaster, &framemaster);
	daifmt &= ~SND_SOC_DAIFMT_MASTER_MASK;

	snprintf(prop, sizeof(prop), "%scpu", prefix);
	np = of_get_child_by_name(node, prop);
	if (!np) {
	cpu = of_get_child_by_name(node, prop);

	snprintf(prop, sizeof(prop), "%scodec", prefix);
	codec = of_get_child_by_name(node, prop);

	if (!cpu || !codec) {
		ret = -EINVAL;
		dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop);
		goto dai_link_of_err;
	}

	ret = asoc_simple_card_sub_parse_of(np, &dai_props->cpu_dai,
	ret = asoc_simple_card_parse_daifmt(node, priv,
					    cpu, codec, prefix, idx);
	if (ret < 0)
		goto dai_link_of_err;

	ret = asoc_simple_card_sub_parse_of(cpu, &dai_props->cpu_dai,
					    &dai_link->cpu_of_node,
					    &dai_link->cpu_dai_name,
					    &cpu_args);
	if (ret < 0)
		goto dai_link_of_err;

	dai_props->cpu_dai.fmt = daifmt;
	switch (((np == bitclkmaster) << 4) | (np == framemaster)) {
	case 0x11:
		dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBS_CFS;
		break;
	case 0x10:
		dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBS_CFM;
		break;
	case 0x01:
		dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBM_CFS;
		break;
	default:
		dai_props->cpu_dai.fmt |= SND_SOC_DAIFMT_CBM_CFM;
		break;
	}

	of_node_put(np);
	snprintf(prop, sizeof(prop), "%scodec", prefix);
	np = of_get_child_by_name(node, prop);
	if (!np) {
		ret = -EINVAL;
		dev_err(dev, "%s: Can't find %s DT node\n", __func__, prop);
		goto dai_link_of_err;
	}

	ret = asoc_simple_card_sub_parse_of(np, &dai_props->codec_dai,
	ret = asoc_simple_card_sub_parse_of(codec, &dai_props->codec_dai,
					    &dai_link->codec_of_node,
					    &dai_link->codec_dai_name, NULL);
	if (ret < 0)
		goto dai_link_of_err;

	if (strlen(prefix) && !bitclkmaster && !framemaster) {
		/*
		 * No DAI link level and master setting was found
		 * from sound node level, revert back to legacy DT
		 * parsing and take the settings from codec node.
		 */
		dev_dbg(dev, "%s: Revert to legacy daifmt parsing\n",
			__func__);
		dai_props->cpu_dai.fmt = dai_props->codec_dai.fmt =
			snd_soc_of_parse_daifmt(np, NULL, NULL, NULL) |
			(daifmt & ~SND_SOC_DAIFMT_CLOCK_MASK);
	} else {
		dai_props->codec_dai.fmt = daifmt;
		switch (((np == bitclkmaster) << 4) | (np == framemaster)) {
		case 0x11:
			dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBM_CFM;
			break;
		case 0x10:
			dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBM_CFS;
			break;
		case 0x01:
			dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBS_CFM;
			break;
		default:
			dai_props->codec_dai.fmt |= SND_SOC_DAIFMT_CBS_CFS;
			break;
		}
	}

	if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) {
		ret = -EINVAL;
		goto dai_link_of_err;
@@ -368,9 +364,9 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
		dai_link->cpu_dai_name = NULL;

dai_link_of_err:
	of_node_put(np);
	of_node_put(bitclkmaster);
	of_node_put(framemaster);
	of_node_put(cpu);
	of_node_put(codec);

	return ret;
}