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

Commit 79e79e2e authored by Mark Brown's avatar Mark Brown
Browse files

Merge branch 'topic/simple' of...

Merge branch 'topic/simple' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into asoc-rcar
parents 1d9d0c65 239486ba
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -33,4 +33,38 @@ int asoc_simple_card_set_dailink_name(struct device *dev,
int asoc_simple_card_parse_card_name(struct snd_soc_card *card,
				     char *prefix);

#define asoc_simple_card_parse_clk_cpu(node, dai_link, simple_dai)		\
	asoc_simple_card_parse_clk(node, dai_link->cpu_of_node, simple_dai)
#define asoc_simple_card_parse_clk_codec(node, dai_link, simple_dai)		\
	asoc_simple_card_parse_clk(node, dai_link->codec_of_node, simple_dai)
int asoc_simple_card_parse_clk(struct device_node *node,
			       struct device_node *dai_of_node,
			       struct asoc_simple_dai *simple_dai);

#define asoc_simple_card_parse_cpu(node, dai_link,				\
				   list_name, cells_name, is_single_link)	\
	asoc_simple_card_parse_dai(node, &dai_link->cpu_of_node,		\
		&dai_link->cpu_dai_name, list_name, cells_name, is_single_link)
#define asoc_simple_card_parse_codec(node, dai_link, list_name, cells_name)	\
	asoc_simple_card_parse_dai(node, &dai_link->codec_of_node,		\
		&dai_link->codec_dai_name, list_name, cells_name, NULL)
#define asoc_simple_card_parse_platform(node, dai_link, list_name, cells_name)	\
	asoc_simple_card_parse_dai(node, &dai_link->platform_of_node,		\
		NULL, list_name, cells_name, NULL)
int asoc_simple_card_parse_dai(struct device_node *node,
				  struct device_node **endpoint_np,
				  const char **dai_name,
				  const char *list_name,
				  const char *cells_name,
				  int *is_single_links);

int asoc_simple_card_init_dai(struct snd_soc_dai *dai,
			      struct asoc_simple_dai *simple_dai);

int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link);
void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link,
				      int is_single_links);

int asoc_simple_card_clean_reference(struct snd_soc_card *card);

#endif /* __SIMPLE_CARD_CORE_H */
+3 −3
Original line number Diff line number Diff line
obj-$(CONFIG_SND_SIMPLE_CARD_UTILS) := simple-card-utils.o

snd-soc-simple-card-utils-objs	:= simple-card-utils.o
snd-soc-simple-card-objs	:= simple-card.o

obj-$(CONFIG_SND_SIMPLE_CARD_UTILS)	+= snd-soc-simple-card-utils.o
obj-$(CONFIG_SND_SIMPLE_CARD)		+= snd-soc-simple-card.o
+147 −0
Original line number Diff line number Diff line
@@ -7,6 +7,8 @@
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/of.h>
#include <sound/simple_card_utils.h>

@@ -95,3 +97,148 @@ int asoc_simple_card_parse_card_name(struct snd_soc_card *card,
	return 0;
}
EXPORT_SYMBOL_GPL(asoc_simple_card_parse_card_name);

int asoc_simple_card_parse_clk(struct device_node *node,
			       struct device_node *dai_of_node,
			       struct asoc_simple_dai *simple_dai)
{
	struct clk *clk;
	u32 val;

	/*
	 * Parse dai->sysclk come from "clocks = <&xxx>"
	 * (if system has common clock)
	 *  or "system-clock-frequency = <xxx>"
	 *  or device's module clock.
	 */
	clk = of_clk_get(node, 0);
	if (!IS_ERR(clk)) {
		simple_dai->sysclk = clk_get_rate(clk);
		simple_dai->clk = clk;
	} else if (!of_property_read_u32(node, "system-clock-frequency", &val)) {
		simple_dai->sysclk = val;
	} else {
		clk = of_clk_get(dai_of_node, 0);
		if (!IS_ERR(clk))
			simple_dai->sysclk = clk_get_rate(clk);
	}

	return 0;
}
EXPORT_SYMBOL_GPL(asoc_simple_card_parse_clk);

int asoc_simple_card_parse_dai(struct device_node *node,
				    struct device_node **dai_of_node,
				    const char **dai_name,
				    const char *list_name,
				    const char *cells_name,
				    int *is_single_link)
{
	struct of_phandle_args args;
	int ret;

	if (!node)
		return 0;

	/*
	 * Get node via "sound-dai = <&phandle port>"
	 * it will be used as xxx_of_node on soc_bind_dai_link()
	 */
	ret = of_parse_phandle_with_args(node, list_name, cells_name, 0, &args);
	if (ret)
		return ret;

	/* Get dai->name */
	if (dai_name) {
		ret = snd_soc_of_get_dai_name(node, dai_name);
		if (ret < 0)
			return ret;
	}

	*dai_of_node = args.np;

	if (is_single_link)
		*is_single_link = !args.args_count;

	return 0;
}
EXPORT_SYMBOL_GPL(asoc_simple_card_parse_dai);

int asoc_simple_card_init_dai(struct snd_soc_dai *dai,
			      struct asoc_simple_dai *simple_dai)
{
	int ret;

	if (simple_dai->sysclk) {
		ret = snd_soc_dai_set_sysclk(dai, 0, simple_dai->sysclk, 0);
		if (ret && ret != -ENOTSUPP) {
			dev_err(dai->dev, "simple-card: set_sysclk error\n");
			return ret;
		}
	}

	if (simple_dai->slots) {
		ret = snd_soc_dai_set_tdm_slot(dai,
					       simple_dai->tx_slot_mask,
					       simple_dai->rx_slot_mask,
					       simple_dai->slots,
					       simple_dai->slot_width);
		if (ret && ret != -ENOTSUPP) {
			dev_err(dai->dev, "simple-card: set_tdm_slot error\n");
			return ret;
		}
	}

	return 0;
}
EXPORT_SYMBOL_GPL(asoc_simple_card_init_dai);

int asoc_simple_card_canonicalize_dailink(struct snd_soc_dai_link *dai_link)
{
	if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name)
		return -EINVAL;

	/* Assumes platform == cpu */
	if (!dai_link->platform_of_node)
		dai_link->platform_of_node = dai_link->cpu_of_node;

	return 0;
}
EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_dailink);

void asoc_simple_card_canonicalize_cpu(struct snd_soc_dai_link *dai_link,
				       int is_single_links)
{
	/*
	 * In soc_bind_dai_link() will check cpu name after
	 * of_node matching if dai_link has cpu_dai_name.
	 * but, it will never match if name was created by
	 * fmt_single_name() remove cpu_dai_name if cpu_args
	 * was 0. See:
	 *	fmt_single_name()
	 *	fmt_multiple_name()
	 */
	if (is_single_links)
		dai_link->cpu_dai_name = NULL;
}
EXPORT_SYMBOL_GPL(asoc_simple_card_canonicalize_cpu);

int asoc_simple_card_clean_reference(struct snd_soc_card *card)
{
	struct snd_soc_dai_link *dai_link;
	int num_links;

	for (num_links = 0, dai_link = card->dai_link;
	     num_links < card->num_links;
	     num_links++, dai_link++) {
		of_node_put(dai_link->cpu_of_node);
		of_node_put(dai_link->codec_of_node);
	}
	return 0;
}
EXPORT_SYMBOL_GPL(asoc_simple_card_clean_reference);

/* Module information */
MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
MODULE_DESCRIPTION("ALSA SoC Simple Card Utils");
MODULE_LICENSE("GPL v2");
+38 −152
Original line number Diff line number Diff line
@@ -44,6 +44,8 @@ struct simple_card_data {
#define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + i)
#define simple_priv_to_props(priv, i) ((priv)->dai_props + i)

#define DAI	"sound-dai"
#define CELL	"#sound-dai-cells"
#define PREFIX	"simple-audio-card,"

#define asoc_simple_card_init_hp(card, sjack, prefix)\
@@ -177,51 +179,19 @@ static struct snd_soc_ops asoc_simple_card_ops = {
	.hw_params = asoc_simple_card_hw_params,
};

static int __asoc_simple_card_dai_init(struct snd_soc_dai *dai,
				       struct asoc_simple_dai *set)
{
	int ret;

	if (set->sysclk) {
		ret = snd_soc_dai_set_sysclk(dai, 0, set->sysclk, 0);
		if (ret && ret != -ENOTSUPP) {
			dev_err(dai->dev, "simple-card: set_sysclk error\n");
			goto err;
		}
	}

	if (set->slots) {
		ret = snd_soc_dai_set_tdm_slot(dai,
					       set->tx_slot_mask,
					       set->rx_slot_mask,
						set->slots,
						set->slot_width);
		if (ret && ret != -ENOTSUPP) {
			dev_err(dai->dev, "simple-card: set_tdm_slot error\n");
			goto err;
		}
	}

	ret = 0;

err:
	return ret;
}

static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
{
	struct simple_card_data *priv =	snd_soc_card_get_drvdata(rtd->card);
	struct snd_soc_dai *codec = rtd->codec_dai;
	struct snd_soc_dai *cpu = rtd->cpu_dai;
	struct simple_dai_props *dai_props;
	struct simple_dai_props *dai_props = &priv->dai_props[rtd->num];
	int ret;

	dai_props = &priv->dai_props[rtd->num];
	ret = __asoc_simple_card_dai_init(codec, &dai_props->codec_dai);
	ret = asoc_simple_card_init_dai(codec, &dai_props->codec_dai);
	if (ret < 0)
		return ret;

	ret = __asoc_simple_card_dai_init(cpu, &dai_props->cpu_dai);
	ret = asoc_simple_card_init_dai(cpu, &dai_props->cpu_dai);
	if (ret < 0)
		return ret;

@@ -236,78 +206,6 @@ static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
	return 0;
}

static int
asoc_simple_card_sub_parse_of(struct device_node *np,
			      struct asoc_simple_dai *dai,
			      struct device_node **p_node,
			      const char **name,
			      int *args_count)
{
	struct of_phandle_args args;
	struct clk *clk;
	u32 val;
	int ret;

	if (!np)
		return 0;

	/*
	 * Get node via "sound-dai = <&phandle port>"
	 * it will be used as xxx_of_node on soc_bind_dai_link()
	 */
	ret = of_parse_phandle_with_args(np, "sound-dai",
					 "#sound-dai-cells", 0, &args);
	if (ret)
		return ret;

	*p_node = args.np;

	if (args_count)
		*args_count = args.args_count;

	/* Get dai->name */
	if (name) {
		ret = snd_soc_of_get_dai_name(np, name);
		if (ret < 0)
			return ret;
	}

	if (!dai)
		return 0;

	/* Parse TDM slot */
	ret = snd_soc_of_parse_tdm_slot(np, &dai->tx_slot_mask,
					&dai->rx_slot_mask,
					&dai->slots, &dai->slot_width);
	if (ret)
		return ret;

	/*
	 * Parse dai->sysclk come from "clocks = <&xxx>"
	 * (if system has common clock)
	 *  or "system-clock-frequency = <xxx>"
	 *  or device's module clock.
	 */
	if (of_property_read_bool(np, "clocks")) {
		clk = of_clk_get(np, 0);
		if (IS_ERR(clk)) {
			ret = PTR_ERR(clk);
			return ret;
		}

		dai->sysclk = clk_get_rate(clk);
		dai->clk = clk;
	} else if (!of_property_read_u32(np, "system-clock-frequency", &val)) {
		dai->sysclk = val;
	} else {
		clk = of_clk_get(args.np, 0);
		if (!IS_ERR(clk))
			dai->sysclk = clk_get_rate(clk);
	}

	return 0;
}

static int asoc_simple_card_dai_link_of(struct device_node *node,
					struct simple_card_data *priv,
					int idx,
@@ -316,12 +214,14 @@ 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 asoc_simple_dai *cpu_dai = &dai_props->cpu_dai;
	struct asoc_simple_dai *codec_dai = &dai_props->codec_dai;
	struct device_node *cpu = NULL;
	struct device_node *plat = NULL;
	struct device_node *codec = NULL;
	char prop[128];
	char *prefix = "";
	int ret, cpu_args;
	int ret, single_cpu;
	u32 val;

	/* For single DAI link & old style of DT node */
@@ -351,33 +251,44 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
	if (!of_property_read_u32(node, "mclk-fs", &val))
		dai_props->mclk_fs = val;

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

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

	ret = asoc_simple_card_sub_parse_of(plat, NULL,
					    &dai_link->platform_of_node,
					    NULL, NULL);
	ret = asoc_simple_card_parse_platform(plat, dai_link, DAI, CELL);
	if (ret < 0)
		goto dai_link_of_err;

	if (!dai_link->cpu_dai_name || !dai_link->codec_dai_name) {
		ret = -EINVAL;
	ret = snd_soc_of_parse_tdm_slot(cpu,	&cpu_dai->tx_slot_mask,
						&cpu_dai->rx_slot_mask,
						&cpu_dai->slots,
						&cpu_dai->slot_width);
	if (ret < 0)
		goto dai_link_of_err;

	ret = snd_soc_of_parse_tdm_slot(codec,	&codec_dai->tx_slot_mask,
						&codec_dai->rx_slot_mask,
						&codec_dai->slots,
						&codec_dai->slot_width);
	if (ret < 0)
		goto dai_link_of_err;
	}

	/* Assumes platform == cpu */
	if (!dai_link->platform_of_node)
		dai_link->platform_of_node = dai_link->cpu_of_node;
	ret = asoc_simple_card_parse_clk_cpu(cpu, dai_link, cpu_dai);
	if (ret < 0)
		goto dai_link_of_err;

	ret = asoc_simple_card_parse_clk_codec(codec, dai_link, codec_dai);
	if (ret < 0)
		goto dai_link_of_err;

	ret = asoc_simple_card_canonicalize_dailink(dai_link);
	if (ret < 0)
		goto dai_link_of_err;

	ret = asoc_simple_card_set_dailink_name(dev, dai_link,
						"%s-%s",
@@ -398,17 +309,7 @@ static int asoc_simple_card_dai_link_of(struct device_node *node,
		dai_link->codec_dai_name,
		dai_props->codec_dai.sysclk);

	/*
	 * In soc_bind_dai_link() will check cpu name after
	 * of_node matching if dai_link has cpu_dai_name.
	 * but, it will never match if name was created by
	 * fmt_single_name() remove cpu_dai_name if cpu_args
	 * was 0. See:
	 *	fmt_single_name()
	 *	fmt_multiple_name()
	 */
	if (!cpu_args)
		dai_link->cpu_dai_name = NULL;
	asoc_simple_card_canonicalize_cpu(dai_link, single_cpu);

dai_link_of_err:
	of_node_put(cpu);
@@ -477,21 +378,6 @@ static int asoc_simple_card_parse_of(struct device_node *node,
	return 0;
}

/* Decrease the reference count of the device nodes */
static int asoc_simple_card_unref(struct snd_soc_card *card)
{
	struct snd_soc_dai_link *dai_link;
	int num_links;

	for (num_links = 0, dai_link = card->dai_link;
	     num_links < card->num_links;
	     num_links++, dai_link++) {
		of_node_put(dai_link->cpu_of_node);
		of_node_put(dai_link->codec_of_node);
	}
	return 0;
}

static int asoc_simple_card_probe(struct platform_device *pdev)
{
	struct simple_card_data *priv;
@@ -577,7 +463,7 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
		return ret;

err:
	asoc_simple_card_unref(&priv->snd_card);
	asoc_simple_card_clean_reference(&priv->snd_card);
	return ret;
}

@@ -589,7 +475,7 @@ static int asoc_simple_card_remove(struct platform_device *pdev)
	asoc_simple_card_remove_jack(&priv->hp_jack);
	asoc_simple_card_remove_jack(&priv->mic_jack);

	return asoc_simple_card_unref(card);
	return asoc_simple_card_clean_reference(card);
}

static const struct of_device_id asoc_simple_of_match[] = {
+28 −127
Original line number Diff line number Diff line
@@ -62,6 +62,9 @@ struct rsrc_card_priv {
#define rsrc_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i))
#define rsrc_priv_to_props(priv, i) ((priv)->dai_props + (i))

#define DAI	"sound-dai"
#define CELL	"#sound-dai-cells"

static int rsrc_card_startup(struct snd_pcm_substream *substream)
{
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -94,7 +97,6 @@ static int rsrc_card_dai_init(struct snd_soc_pcm_runtime *rtd)
	struct snd_soc_dai_link *dai_link;
	struct asoc_simple_dai *dai_props;
	int num = rtd->num;
	int ret;

	dai_link	= rsrc_priv_to_link(priv, num);
	dai_props	= rsrc_priv_to_props(priv, num);
@@ -102,30 +104,7 @@ static int rsrc_card_dai_init(struct snd_soc_pcm_runtime *rtd)
				rtd->cpu_dai :
				rtd->codec_dai;

	if (dai_props->sysclk) {
		ret = snd_soc_dai_set_sysclk(dai, 0, dai_props->sysclk, 0);
		if (ret && ret != -ENOTSUPP) {
			dev_err(dai->dev, "set_sysclk error\n");
			goto err;
		}
	}

	if (dai_props->slots) {
		ret = snd_soc_dai_set_tdm_slot(dai,
					       dai_props->tx_slot_mask,
					       dai_props->rx_slot_mask,
					       dai_props->slots,
					       dai_props->slot_width);
		if (ret && ret != -ENOTSUPP) {
			dev_err(dai->dev, "set_tdm_slot error\n");
			goto err;
		}
	}

	ret = 0;

err:
	return ret;
	return asoc_simple_card_init_dai(dai, dai_props);
}

static int rsrc_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
@@ -155,18 +134,8 @@ static int rsrc_card_parse_links(struct device_node *np,
	struct device *dev = rsrc_priv_to_dev(priv);
	struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx);
	struct asoc_simple_dai *dai_props = rsrc_priv_to_props(priv, idx);
	struct of_phandle_args args;
	int ret;

	/*
	 * Get node via "sound-dai = <&phandle port>"
	 * it will be used as xxx_of_node on soc_bind_dai_link()
	 */
	ret = of_parse_phandle_with_args(np, "sound-dai",
					 "#sound-dai-cells", 0, &args);
	if (ret)
		return ret;

	/* Parse TDM slot */
	ret = snd_soc_of_parse_tdm_slot(np,
					&dai_props->tx_slot_mask,
@@ -177,6 +146,8 @@ static int rsrc_card_parse_links(struct device_node *np,
		return ret;

	if (is_fe) {
		int is_single_links = 0;

		/* BE is dummy */
		dai_link->codec_of_node		= NULL;
		dai_link->codec_dai_name	= "snd-soc-dummy-dai";
@@ -185,8 +156,13 @@ static int rsrc_card_parse_links(struct device_node *np,
		/* FE settings */
		dai_link->dynamic		= 1;
		dai_link->dpcm_merged_format	= 1;
		dai_link->cpu_of_node		= args.np;
		ret = snd_soc_of_get_dai_name(np, &dai_link->cpu_dai_name);

		ret = asoc_simple_card_parse_cpu(np, dai_link, DAI, CELL,
						 &is_single_links);
		if (ret)
			return ret;

		ret = asoc_simple_card_parse_clk_cpu(np, dai_link, dai_props);
		if (ret < 0)
			return ret;

@@ -196,17 +172,7 @@ static int rsrc_card_parse_links(struct device_node *np,
		if (ret < 0)
			return ret;

		/*
		 * In soc_bind_dai_link() will check cpu name after
		 * of_node matching if dai_link has cpu_dai_name.
		 * but, it will never match if name was created by
		 * fmt_single_name() remove cpu_dai_name if cpu_args
		 * was 0. See:
		 *	fmt_single_name()
		 *	fmt_multiple_name()
		 */
		if (!args.args_count)
			dai_link->cpu_dai_name = NULL;
		asoc_simple_card_canonicalize_cpu(dai_link, is_single_links);
	} else {
		const struct rsrc_card_of_data *of_data;

@@ -220,8 +186,12 @@ static int rsrc_card_parse_links(struct device_node *np,
		/* BE settings */
		dai_link->no_pcm		= 1;
		dai_link->be_hw_params_fixup	= rsrc_card_be_hw_params_fixup;
		dai_link->codec_of_node		= args.np;
		ret = snd_soc_of_get_dai_name(np, &dai_link->codec_dai_name);

		ret = asoc_simple_card_parse_codec(np, dai_link, DAI, CELL);
		if (ret < 0)
			return ret;

		ret = asoc_simple_card_parse_clk_codec(np, dai_link, dai_props);
		if (ret < 0)
			return ret;

@@ -243,75 +213,21 @@ static int rsrc_card_parse_links(struct device_node *np,
		}
	}

	/* Simple Card assumes platform == cpu */
	dai_link->platform_of_node	= dai_link->cpu_of_node;
	ret = asoc_simple_card_canonicalize_dailink(dai_link);
	if (ret < 0)
		return ret;

	dai_link->dpcm_playback		= 1;
	dai_link->dpcm_capture		= 1;
	dai_link->ops			= &rsrc_card_ops;
	dai_link->init			= rsrc_card_dai_init;

	return 0;
}

static int rsrc_card_parse_clk(struct device_node *np,
			       struct rsrc_card_priv *priv,
			       int idx, bool is_fe)
{
	struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx);
	struct asoc_simple_dai *dai_props = rsrc_priv_to_props(priv, idx);
	struct clk *clk;
	struct device_node *of_np = is_fe ?	dai_link->cpu_of_node :
						dai_link->codec_of_node;
	u32 val;

	/*
	 * Parse dai->sysclk come from "clocks = <&xxx>"
	 * (if system has common clock)
	 *  or "system-clock-frequency = <xxx>"
	 *  or device's module clock.
	 */
	if (of_property_read_bool(np, "clocks")) {
		clk = of_clk_get(np, 0);
		if (IS_ERR(clk))
			return PTR_ERR(clk);

		dai_props->sysclk = clk_get_rate(clk);
		dai_props->clk = clk;
	} else if (!of_property_read_u32(np, "system-clock-frequency", &val)) {
		dai_props->sysclk = val;
	} else {
		clk = of_clk_get(of_np, 0);
		if (!IS_ERR(clk))
			dai_props->sysclk = clk_get_rate(clk);
	}

	return 0;
}

static int rsrc_card_dai_sub_link_of(struct device_node *node,
				     struct device_node *np,
				     struct rsrc_card_priv *priv,
				     int idx, bool is_fe)
{
	struct device *dev = rsrc_priv_to_dev(priv);
	struct snd_soc_dai_link *dai_link = rsrc_priv_to_link(priv, idx);
	struct asoc_simple_dai *dai_props = rsrc_priv_to_props(priv, idx);
	int ret;

	ret = rsrc_card_parse_links(np, priv, idx, is_fe);
	if (ret < 0)
		return ret;

	ret = rsrc_card_parse_clk(np, priv, idx, is_fe);
	if (ret < 0)
		return ret;

	dev_dbg(dev, "\t%s / %04x / %d\n",
		dai_link->name,
		dai_link->dai_fmt,
		dai_props->sysclk);

	return ret;
	return 0;
}

static int rsrc_card_dai_link_of(struct device_node *node,
@@ -348,7 +264,7 @@ static int rsrc_card_dai_link_of(struct device_node *node,
		if (strcmp(np->name, "cpu") == 0)
			is_fe = true;

		ret = rsrc_card_dai_sub_link_of(node, np, priv, i, is_fe);
		ret = rsrc_card_parse_links(np, priv, i, is_fe);
		if (ret < 0)
			return ret;
		i++;
@@ -417,21 +333,6 @@ static int rsrc_card_parse_of(struct device_node *node,
	return 0;
}

/* Decrease the reference count of the device nodes */
static int rsrc_card_unref(struct snd_soc_card *card)
{
	struct snd_soc_dai_link *dai_link;
	int num_links;

	for (num_links = 0, dai_link = card->dai_link;
	     num_links < card->num_links;
	     num_links++, dai_link++) {
		of_node_put(dai_link->cpu_of_node);
		of_node_put(dai_link->codec_of_node);
	}
	return 0;
}

static int rsrc_card_probe(struct platform_device *pdev)
{
	struct rsrc_card_priv *priv;
@@ -457,7 +358,7 @@ static int rsrc_card_probe(struct platform_device *pdev)
	if (ret >= 0)
		return ret;
err:
	rsrc_card_unref(&priv->snd_card);
	asoc_simple_card_clean_reference(&priv->snd_card);

	return ret;
}
@@ -466,7 +367,7 @@ static int rsrc_card_remove(struct platform_device *pdev)
{
	struct snd_soc_card *card = platform_get_drvdata(pdev);

	return rsrc_card_unref(card);
	return asoc_simple_card_clean_reference(card);
}

static struct platform_driver rsrc_card = {