Unverified Commit 522f88da authored by Mark Brown's avatar Mark Brown
Browse files

ASoC: simple-card: sync support

Merge series from Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>:

We have simple-card / audio-graph / audio-graph2, basically these supports
same feature but is using different DT style.

Because we are using 3 drivers, some feature was added to one driver,
but other drivers doesn't have it. This patch set try to sync it on these
3 drivers.
parents 9d52d7ea c4cfe113
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -197,7 +197,7 @@ int graph_util_is_ports0(struct device_node *port);
int graph_util_parse_dai(struct device *dev, struct device_node *ep,
			 struct snd_soc_dai_link_component *dlc, int *is_single_link);

int graph_util_parse_link_direction(struct device_node *np,
void graph_util_parse_link_direction(struct device_node *np,
				    bool *is_playback_only, bool *is_capture_only);

#ifdef DEBUG
+57 −38
Original line number Diff line number Diff line
@@ -19,6 +19,18 @@

#define DPCM_SELECTABLE 1

#define ep_to_port(ep)	of_get_parent(ep)
static struct device_node *port_to_ports(struct device_node *port)
{
	struct device_node *ports = of_get_parent(port);

	if (!of_node_name_eq(ports, "ports")) {
		of_node_put(ports);
		return NULL;
	}
	return ports;
}

static int graph_outdrv_event(struct snd_soc_dapm_widget *w,
			      struct snd_kcontrol *kcontrol,
			      int event)
@@ -68,12 +80,11 @@ static void graph_parse_convert(struct device *dev,
				struct simple_util_data *adata)
{
	struct device_node *top = dev->of_node;
	struct device_node *port = of_get_parent(ep);
	struct device_node *ports = of_get_parent(port);
	struct device_node *port = ep_to_port(ep);
	struct device_node *ports = port_to_ports(port);
	struct device_node *node = of_graph_get_port_parent(ep);

	simple_util_parse_convert(top,   NULL,   adata);
	if (of_node_name_eq(ports, "ports"))
	simple_util_parse_convert(ports, NULL,   adata);
	simple_util_parse_convert(port,  NULL,   adata);
	simple_util_parse_convert(ep,    NULL,   adata);
@@ -83,30 +94,12 @@ static void graph_parse_convert(struct device *dev,
	of_node_put(node);
}

static void graph_parse_mclk_fs(struct device_node *top,
				struct device_node *ep,
				struct simple_dai_props *props)
{
	struct device_node *port	= of_get_parent(ep);
	struct device_node *ports	= of_get_parent(port);

	of_property_read_u32(top,	"mclk-fs", &props->mclk_fs);
	if (of_node_name_eq(ports, "ports"))
		of_property_read_u32(ports, "mclk-fs", &props->mclk_fs);
	of_property_read_u32(port,	"mclk-fs", &props->mclk_fs);
	of_property_read_u32(ep,	"mclk-fs", &props->mclk_fs);

	of_node_put(port);
	of_node_put(ports);
}

static int graph_parse_node(struct simple_util_priv *priv,
			    struct device_node *ep,
			    struct link_info *li,
			    int *cpu)
{
	struct device *dev = simple_priv_to_dev(priv);
	struct device_node *top = dev->of_node;
	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 snd_soc_dai_link_component *dlc;
@@ -121,8 +114,6 @@ static int graph_parse_node(struct simple_util_priv *priv,
		dai = simple_props_to_dai_codec(dai_props, 0);
	}

	graph_parse_mclk_fs(top, ep, dai_props);

	ret = graph_util_parse_dai(dev, ep, dlc, cpu);
	if (ret < 0)
		return ret;
@@ -139,26 +130,57 @@ static int graph_parse_node(struct simple_util_priv *priv,
}

static int graph_link_init(struct simple_util_priv *priv,
			   struct device_node *cpu_ep,
			   struct device_node *codec_ep,
			   struct device_node *ep_cpu,
			   struct device_node *ep_codec,
			   struct link_info *li,
			   char *name)
{
	struct device *dev = simple_priv_to_dev(priv);
	struct device_node *top = dev->of_node;
	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 *port_cpu = ep_to_port(ep_cpu);
	struct device_node *port_codec = ep_to_port(ep_codec);
	struct device_node *ports_cpu = port_to_ports(port_cpu);
	struct device_node *ports_codec = port_to_ports(port_codec);
	bool playback_only = 0, capture_only = 0;
	int ret;

	ret = simple_util_parse_daifmt(dev, cpu_ep, codec_ep,
	ret = simple_util_parse_daifmt(dev, ep_cpu, ep_codec,
				       NULL, &dai_link->dai_fmt);
	if (ret < 0)
		return ret;
		goto init_end;

	graph_util_parse_link_direction(top,		&playback_only, &capture_only);
	graph_util_parse_link_direction(port_cpu,	&playback_only, &capture_only);
	graph_util_parse_link_direction(port_codec,	&playback_only, &capture_only);
	graph_util_parse_link_direction(ep_cpu,		&playback_only, &capture_only);
	graph_util_parse_link_direction(ep_codec,	&playback_only, &capture_only);

	of_property_read_u32(top,		"mclk-fs", &dai_props->mclk_fs);
	of_property_read_u32(ports_cpu,		"mclk-fs", &dai_props->mclk_fs);
	of_property_read_u32(ports_codec,	"mclk-fs", &dai_props->mclk_fs);
	of_property_read_u32(port_cpu,		"mclk-fs", &dai_props->mclk_fs);
	of_property_read_u32(port_codec,	"mclk-fs", &dai_props->mclk_fs);
	of_property_read_u32(ep_cpu,		"mclk-fs", &dai_props->mclk_fs);
	of_property_read_u32(ep_codec,		"mclk-fs", &dai_props->mclk_fs);

	dai_link->playback_only	= playback_only;
	dai_link->capture_only	= capture_only;

	dai_link->init		= simple_util_dai_init;
	dai_link->ops		= &graph_ops;
	if (priv->ops)
		dai_link->ops	= priv->ops;

	return simple_util_set_dailink_name(dev, dai_link, name);
	ret = simple_util_set_dailink_name(dev, dai_link, name);
init_end:
	of_node_put(ports_cpu);
	of_node_put(ports_codec);
	of_node_put(port_cpu);
	of_node_put(port_codec);

	return ret;
}

static int graph_dai_link_of_dpcm(struct simple_util_priv *priv,
@@ -231,14 +253,11 @@ static int graph_dai_link_of_dpcm(struct simple_util_priv *priv,
			 "be.%pOFP.%s", codecs->of_node, codecs->dai_name);

		/* check "prefix" from top node */
		port = of_get_parent(ep);
		ports = of_get_parent(port);
		snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node,
					      "prefix");
		if (of_node_name_eq(ports, "ports"))
		port  = ep_to_port(ep);
		ports = port_to_ports(port);
		snd_soc_of_parse_node_prefix(top,   cconf, codecs->of_node, "prefix");
		snd_soc_of_parse_node_prefix(ports, cconf, codecs->of_node, "prefix");
		snd_soc_of_parse_node_prefix(port, cconf, codecs->of_node,
					     "prefix");
		snd_soc_of_parse_node_prefix(port,  cconf, codecs->of_node, "prefix");

		of_node_put(ports);
		of_node_put(port);
@@ -350,7 +369,7 @@ static int __graph_for_each_link(struct simple_util_priv *priv,

			/* get codec */
			codec_ep = of_graph_get_remote_endpoint(cpu_ep);
			codec_port = of_get_parent(codec_ep);
			codec_port = ep_to_port(codec_ep);

			/* get convert-xxx property */
			memset(&adata, 0, sizeof(adata));
+100 −71
Original line number Diff line number Diff line
@@ -236,6 +236,18 @@ enum graph_type {

#define port_to_endpoint(port) of_get_child_by_name(port, "endpoint")

#define ep_to_port(ep)	of_get_parent(ep)
static struct device_node *port_to_ports(struct device_node *port)
{
	struct device_node *ports = of_get_parent(port);

	if (!of_node_name_eq(ports, "ports")) {
		of_node_put(ports);
		return NULL;
	}
	return ports;
}

static enum graph_type __graph_get_type(struct device_node *lnk)
{
	struct device_node *np, *parent_np;
@@ -320,7 +332,7 @@ static int graph_lnk_is_multi(struct device_node *lnk)

static struct device_node *graph_get_next_multi_ep(struct device_node **port)
{
	struct device_node *ports = of_get_parent(*port);
	struct device_node *ports = port_to_ports(*port);
	struct device_node *ep = NULL;
	struct device_node *rep = NULL;

@@ -365,11 +377,10 @@ static const struct snd_soc_ops graph_ops = {
static void graph_parse_convert(struct device_node *ep,
				struct simple_dai_props *props)
{
	struct device_node *port = of_get_parent(ep);
	struct device_node *ports = of_get_parent(port);
	struct device_node *port = ep_to_port(ep);
	struct device_node *ports = port_to_ports(port);
	struct simple_util_data *adata = &props->adata;

	if (of_node_name_eq(ports, "ports"))
	simple_util_parse_convert(ports, NULL, adata);
	simple_util_parse_convert(port, NULL, adata);
	simple_util_parse_convert(ep,   NULL, adata);
@@ -378,21 +389,6 @@ static void graph_parse_convert(struct device_node *ep,
	of_node_put(ports);
}

static void graph_parse_mclk_fs(struct device_node *ep,
				struct simple_dai_props *props)
{
	struct device_node *port	= of_get_parent(ep);
	struct device_node *ports	= of_get_parent(port);

	if (of_node_name_eq(ports, "ports"))
		of_property_read_u32(ports, "mclk-fs", &props->mclk_fs);
	of_property_read_u32(port,	"mclk-fs", &props->mclk_fs);
	of_property_read_u32(ep,	"mclk-fs", &props->mclk_fs);

	of_node_put(port);
	of_node_put(ports);
}

static int __graph_parse_node(struct simple_util_priv *priv,
			      enum graph_type gtype,
			      struct device_node *ep,
@@ -414,8 +410,6 @@ static int __graph_parse_node(struct simple_util_priv *priv,
		dai = simple_props_to_dai_codec(dai_props, idx);
	}

	graph_parse_mclk_fs(ep, dai_props);

	ret = graph_util_parse_dai(dev, ep, dlc, &is_single_links);
	if (ret < 0)
		return ret;
@@ -481,10 +475,9 @@ static int __graph_parse_node(struct simple_util_priv *priv,
	if (!is_cpu && gtype == GRAPH_DPCM) {
		struct snd_soc_dai_link_component *codecs = snd_soc_link_to_codec(dai_link, idx);
		struct snd_soc_codec_conf *cconf = simple_props_to_codec_conf(dai_props, idx);
		struct device_node *rport  = of_get_parent(ep);
		struct device_node *rports = of_get_parent(rport);
		struct device_node *rport  = ep_to_port(ep);
		struct device_node *rports = port_to_ports(rport);

		if (of_node_name_eq(rports, "ports"))
		snd_soc_of_parse_node_prefix(rports, cconf, codecs->of_node, "prefix");
		snd_soc_of_parse_node_prefix(rport,  cconf, codecs->of_node, "prefix");

@@ -539,11 +532,11 @@ static int graph_parse_node_multi_nm(struct snd_soc_dai_link *dai_link,
	 */
	struct device_node *mcpu_ep		= port_to_endpoint(mcpu_port);
	struct device_node *mcpu_ep_n		= mcpu_ep;
	struct device_node *mcpu_port_top	= of_get_next_child(of_get_parent(mcpu_port), NULL);
	struct device_node *mcpu_port_top	= of_get_next_child(port_to_ports(mcpu_port), NULL);
	struct device_node *mcpu_ep_top		= port_to_endpoint(mcpu_port_top);
	struct device_node *mcodec_ep_top	= of_graph_get_remote_endpoint(mcpu_ep_top);
	struct device_node *mcodec_port_top	= of_get_parent(mcodec_ep_top);
	struct device_node *mcodec_ports	= of_get_parent(mcodec_port_top);
	struct device_node *mcodec_port_top	= ep_to_port(mcodec_ep_top);
	struct device_node *mcodec_ports	= port_to_ports(mcodec_port_top);
	int nm_max = max(dai_link->num_cpus, dai_link->num_codecs);
	int ret = -EINVAL;

@@ -566,9 +559,9 @@ static int graph_parse_node_multi_nm(struct snd_soc_dai_link *dai_link,
		}

		mcodec_ep_n	= of_graph_get_remote_endpoint(mcpu_ep_n);
		mcodec_port	= of_get_parent(mcodec_ep_n);
		mcodec_port	= ep_to_port(mcodec_ep_n);

		if (mcodec_ports != of_get_parent(mcodec_port))
		if (mcodec_ports != port_to_ports(mcodec_port))
			goto mcpu_err;

		codec_idx = 0;
@@ -705,6 +698,9 @@ static void graph_parse_daifmt(struct device_node *node,
{
	unsigned int fmt;

	if (!node)
		return;

	/*
	 * see also above "daifmt" explanation
	 * and samples.
@@ -751,43 +747,64 @@ static void graph_parse_daifmt(struct device_node *node,
}

static void graph_link_init(struct simple_util_priv *priv,
			    struct device_node *port,
			    struct device_node *lnk,
			    struct device_node *port_cpu,
			    struct device_node *port_codec,
			    struct link_info *li,
			    int is_cpu_node)
{
	struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
	struct device_node *ep;
	struct device_node *ports;
	struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
	struct device_node *ep_cpu, *ep_codec;
	struct device_node *ports_cpu, *ports_codec;
	unsigned int daifmt = 0, daiclk = 0;
	bool playback_only = 0, capture_only = 0;
	unsigned int bit_frame = 0;

	if (graph_lnk_is_multi(port)) {
		of_node_get(port);
		ep = graph_get_next_multi_ep(&port);
		port = of_get_parent(ep);
	of_node_get(port_cpu);
	if (graph_lnk_is_multi(port_cpu)) {
		ep_cpu = graph_get_next_multi_ep(&port_cpu);
		of_node_put(port_cpu);
		port_cpu = ep_to_port(ep_cpu);
	} else {
		ep = port_to_endpoint(port);
		ep_cpu = port_to_endpoint(port_cpu);
	}
	ports_cpu = port_to_ports(port_cpu);

	ports = of_get_parent(port);

	/*
	 *	ports {
	 * (A)
	 *		port {
	 * (B)
	 *			endpoint {
	 * (C)
	 *			};
	 *		};
	 *	};
	 * };
	 */
	graph_parse_daifmt(ep,    &daifmt, &bit_frame);		/* (C) */
	graph_parse_daifmt(port,  &daifmt, &bit_frame);		/* (B) */
	if (of_node_name_eq(ports, "ports"))
		graph_parse_daifmt(ports, &daifmt, &bit_frame);	/* (A) */
	of_node_get(port_codec);
	if (graph_lnk_is_multi(port_codec)) {
		ep_codec = graph_get_next_multi_ep(&port_codec);
		of_node_put(port_cpu);
		port_codec = ep_to_port(ep_codec);
	} else {
		ep_codec = port_to_endpoint(port_codec);
	}
	ports_codec = 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_util_parse_link_direction(lnk,		&playback_only, &capture_only);
	graph_util_parse_link_direction(ports_cpu,	&playback_only, &capture_only);
	graph_util_parse_link_direction(ports_codec,	&playback_only, &capture_only);
	graph_util_parse_link_direction(port_cpu,	&playback_only, &capture_only);
	graph_util_parse_link_direction(port_codec,	&playback_only, &capture_only);
	graph_util_parse_link_direction(ep_cpu,		&playback_only, &capture_only);
	graph_util_parse_link_direction(ep_codec,	&playback_only, &capture_only);

	of_property_read_u32(lnk,		"mclk-fs", &dai_props->mclk_fs);
	of_property_read_u32(ports_cpu,		"mclk-fs", &dai_props->mclk_fs);
	of_property_read_u32(ports_codec,	"mclk-fs", &dai_props->mclk_fs);
	of_property_read_u32(port_cpu,		"mclk-fs", &dai_props->mclk_fs);
	of_property_read_u32(port_codec,	"mclk-fs", &dai_props->mclk_fs);
	of_property_read_u32(ep_cpu,		"mclk-fs", &dai_props->mclk_fs);
	of_property_read_u32(ep_codec,		"mclk-fs", &dai_props->mclk_fs);

	/*
	 * convert bit_frame
@@ -798,8 +815,6 @@ static void graph_link_init(struct simple_util_priv *priv,
	if (is_cpu_node)
		daiclk = snd_soc_daifmt_clock_provider_flipped(daiclk);

	graph_util_parse_link_direction(port, &playback_only, &capture_only);

	dai_link->playback_only	= playback_only;
	dai_link->capture_only	= capture_only;

@@ -808,6 +823,13 @@ static void graph_link_init(struct simple_util_priv *priv,
	dai_link->ops		= &graph_ops;
	if (priv->ops)
		dai_link->ops	= priv->ops;

	of_node_put(ports_cpu);
	of_node_put(ports_codec);
	of_node_put(port_cpu);
	of_node_put(port_codec);
	of_node_put(ep_cpu);
	of_node_put(ep_codec);
}

int audio_graph2_link_normal(struct simple_util_priv *priv,
@@ -835,7 +857,7 @@ int audio_graph2_link_normal(struct simple_util_priv *priv,
	if (ret < 0)
		goto err;

	graph_link_init(priv, cpu_port, li, 1);
	graph_link_init(priv, lnk, cpu_port, codec_port, li, 1);
err:
	of_node_put(codec_port);
	of_node_put(cpu_ep);
@@ -850,13 +872,16 @@ int audio_graph2_link_dpcm(struct simple_util_priv *priv,
{
	struct device_node *ep = port_to_endpoint(lnk);
	struct device_node *rep = of_graph_get_remote_endpoint(ep);
	struct device_node *rport = of_graph_get_remote_port(ep);
	struct device_node *cpu_port = NULL;
	struct device_node *codec_port = NULL;
	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);
	int is_cpu = graph_util_is_ports0(lnk);
	int ret;

	if (is_cpu) {
		cpu_port = of_graph_get_remote_port(ep); /* rport */

		/*
		 * dpcm {
		 *	// Front-End
@@ -884,10 +909,13 @@ int audio_graph2_link_dpcm(struct simple_util_priv *priv,
		dai_link->dynamic		= 1;
		dai_link->dpcm_merged_format	= 1;

		ret = graph_parse_node(priv, GRAPH_DPCM, rport, li, 1);
		ret = graph_parse_node(priv, GRAPH_DPCM, cpu_port, li, 1);
		if (ret)
			goto err;

	} else {
		codec_port = of_graph_get_remote_port(ep); /* rport */

		/*
		 * dpcm {
		 *	// Front-End
@@ -917,7 +945,7 @@ int audio_graph2_link_dpcm(struct simple_util_priv *priv,
		dai_link->no_pcm		= 1;
		dai_link->be_hw_params_fixup	= simple_util_be_hw_params_fixup;

		ret = graph_parse_node(priv, GRAPH_DPCM, rport, li, 0);
		ret = graph_parse_node(priv, GRAPH_DPCM, codec_port, li, 0);
		if (ret < 0)
			goto err;
	}
@@ -927,11 +955,12 @@ int audio_graph2_link_dpcm(struct simple_util_priv *priv,

	snd_soc_dai_link_set_capabilities(dai_link);

	graph_link_init(priv, rport, li, is_cpu);
	graph_link_init(priv, lnk, cpu_port, codec_port, li, is_cpu);
err:
	of_node_put(ep);
	of_node_put(rep);
	of_node_put(rport);
	of_node_put(cpu_port);
	of_node_put(codec_port);

	return ret;
}
@@ -966,7 +995,7 @@ int audio_graph2_link_c2c(struct simple_util_priv *priv,
	 */
	of_node_get(lnk);
	port0 = lnk;
	ports = of_get_parent(port0);
	ports = port_to_ports(port0);
	port1 = of_get_next_child(ports, lnk);

	/*
@@ -1019,7 +1048,7 @@ int audio_graph2_link_c2c(struct simple_util_priv *priv,
	if (ret < 0)
		goto err2;

	graph_link_init(priv, codec0_port, li, 1);
	graph_link_init(priv, lnk, codec0_port, codec1_port, li, 1);
err2:
	of_node_put(ep0);
	of_node_put(ep1);
@@ -1098,7 +1127,7 @@ static int graph_counter(struct device_node *lnk)
	 * ignore first lnk part
	 */
	if (graph_lnk_is_multi(lnk)) {
		struct device_node *ports = of_get_parent(lnk);
		struct device_node *ports = port_to_ports(lnk);
		struct device_node *port = NULL;
		int cnt = 0;

@@ -1195,7 +1224,7 @@ static int graph_count_c2c(struct simple_util_priv *priv,
			   struct device_node *lnk,
			   struct link_info *li)
{
	struct device_node *ports = of_get_parent(lnk);
	struct device_node *ports = port_to_ports(lnk);
	struct device_node *port0 = lnk;
	struct device_node *port1 = of_get_next_child(ports, of_node_get(lnk));
	struct device_node *ep0 = port_to_endpoint(port0);
+10 −13
Original line number Diff line number Diff line
@@ -60,6 +60,9 @@ void simple_util_parse_convert(struct device_node *np,
{
	char prop[128];

	if (!np)
		return;

	if (!prefix)
		prefix = "";

@@ -1140,22 +1143,16 @@ int graph_util_parse_dai(struct device *dev, struct device_node *ep,
}
EXPORT_SYMBOL_GPL(graph_util_parse_dai);

int graph_util_parse_link_direction(struct device_node *np,
void graph_util_parse_link_direction(struct device_node *np,
				    bool *playback_only, bool *capture_only)
{
	bool is_playback_only = false;
	bool is_capture_only = false;

	is_playback_only = of_property_read_bool(np, "playback-only");
	is_capture_only = of_property_read_bool(np, "capture-only");

	if (is_playback_only && is_capture_only)
		return -EINVAL;
	bool is_playback_only = of_property_read_bool(np, "playback-only");
	bool is_capture_only  = of_property_read_bool(np, "capture-only");

	if (is_playback_only)
		*playback_only = is_playback_only;
	if (is_capture_only)
		*capture_only = is_capture_only;

	return 0;
}
EXPORT_SYMBOL_GPL(graph_util_parse_link_direction);

+30 −26
Original line number Diff line number Diff line
@@ -129,24 +129,6 @@ static void simple_parse_convert(struct device *dev,
	of_node_put(node);
}

static void simple_parse_mclk_fs(struct device_node *top,
				 struct device_node *np,
				 struct simple_dai_props *props,
				 char *prefix)
{
	struct device_node *node = of_get_parent(np);
	char prop[128];

	snprintf(prop, sizeof(prop), "%smclk-fs", PREFIX);
	of_property_read_u32(top,	prop, &props->mclk_fs);

	snprintf(prop, sizeof(prop), "%smclk-fs", prefix);
	of_property_read_u32(node,	prop, &props->mclk_fs);
	of_property_read_u32(np,	prop, &props->mclk_fs);

	of_node_put(node);
}

static int simple_parse_node(struct simple_util_priv *priv,
			     struct device_node *np,
			     struct link_info *li,
@@ -154,7 +136,6 @@ static int simple_parse_node(struct simple_util_priv *priv,
			     int *cpu)
{
	struct device *dev = simple_priv_to_dev(priv);
	struct device_node *top = dev->of_node;
	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 snd_soc_dai_link_component *dlc;
@@ -169,8 +150,6 @@ static int simple_parse_node(struct simple_util_priv *priv,
		dai = simple_props_to_dai_codec(dai_props, 0);
	}

	simple_parse_mclk_fs(top, np, dai_props, prefix);

	ret = simple_parse_dai(dev, np, dlc, cpu);
	if (ret)
		return ret;
@@ -187,24 +166,49 @@ static int simple_parse_node(struct simple_util_priv *priv,
}

static int simple_link_init(struct simple_util_priv *priv,
			    struct device_node *node,
			    struct device_node *cpu,
			    struct device_node *codec,
			    struct link_info *li,
			    char *prefix, char *name)
{
	struct device *dev = simple_priv_to_dev(priv);
	struct device_node *top = dev->of_node;
	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 *node = of_get_parent(cpu);
	bool playback_only = 0, capture_only = 0;
	int ret;

	ret = simple_util_parse_daifmt(dev, node, codec,
				       prefix, &dai_link->dai_fmt);
	if (ret < 0)
		return 0;
		goto init_end;

	graph_util_parse_link_direction(top,	&playback_only, &capture_only);
	graph_util_parse_link_direction(node,	&playback_only, &capture_only);
	graph_util_parse_link_direction(cpu,	&playback_only, &capture_only);
	graph_util_parse_link_direction(codec,	&playback_only, &capture_only);

	of_property_read_u32(top,		"mclk-fs", &dai_props->mclk_fs);
	of_property_read_u32(top,	PREFIX	"mclk-fs", &dai_props->mclk_fs);
	of_property_read_u32(node,		"mclk-fs", &dai_props->mclk_fs);
	of_property_read_u32(node,	PREFIX	"mclk-fs", &dai_props->mclk_fs);
	of_property_read_u32(cpu,		"mclk-fs", &dai_props->mclk_fs);
	of_property_read_u32(cpu,	PREFIX	"mclk-fs", &dai_props->mclk_fs);
	of_property_read_u32(codec,		"mclk-fs", &dai_props->mclk_fs);
	of_property_read_u32(codec,	PREFIX	"mclk-fs", &dai_props->mclk_fs);

	dai_link->playback_only		= playback_only;
	dai_link->capture_only		= capture_only;

	dai_link->init			= simple_util_dai_init;
	dai_link->ops			= &simple_ops;

	return simple_util_set_dailink_name(dev, dai_link, name);
	ret = simple_util_set_dailink_name(dev, dai_link, name);
init_end:
	of_node_put(node);

	return ret;
}

static int simple_dai_link_of_dpcm(struct simple_util_priv *priv,
@@ -278,7 +282,7 @@ static int simple_dai_link_of_dpcm(struct simple_util_priv *priv,

	snd_soc_dai_link_set_capabilities(dai_link);

	ret = simple_link_init(priv, node, codec, li, prefix, dai_name);
	ret = simple_link_init(priv, np, codec, li, prefix, dai_name);

out_put_node:
	li->link++;
@@ -336,7 +340,7 @@ static int simple_dai_link_of(struct simple_util_priv *priv,
	simple_util_canonicalize_cpu(cpus, single_cpu);
	simple_util_canonicalize_platform(platforms, cpus);

	ret = simple_link_init(priv, node, codec, li, prefix, dai_name);
	ret = simple_link_init(priv, cpu, codec, li, prefix, dai_name);

dai_link_of_err:
	of_node_put(plat);