UPSTREAM: ASoC: simple card: Add mclk-fs property in dai-link

Add mclk-fs ratio property per dai-link sub node. This will
allow to manage several codecs with different ratio.

Signed-off-by: Arnaud Pouliquen <arnaud.pouliquen@st.com>
Signed-off-by: Mark Brown <broonie@kernel.org>

Bug: 25923642
Patchset: update upstream simple card at here.

(cherry picked from git.kernel.org torvalds/linux.git master
 commit 85a4bfd895778960dc2d655087ac7ff442b6ab9e)
Signed-off-by: Caesar Wang <wxt@rock-chips.com>

Change-Id: I88c68eb826ecd82ca50b7ee09d2cf10e63ed8b7a
diff --git a/Documentation/devicetree/bindings/sound/simple-card.txt b/Documentation/devicetree/bindings/sound/simple-card.txt
index 73bf314..cf3979e 100644
--- a/Documentation/devicetree/bindings/sound/simple-card.txt
+++ b/Documentation/devicetree/bindings/sound/simple-card.txt
@@ -16,7 +16,8 @@
 					  connection's sink, the second being the connection's
 					  source.
 - simple-audio-card,mclk-fs             : Multiplication factor between stream rate and codec
-  					  mclk.
+					  mclk. When defined, mclk-fs property defined in
+					  dai-link sub nodes are ignored.
 - simple-audio-card,hp-det-gpio		: Reference to GPIO that signals when
 					  headphones are attached.
 - simple-audio-card,mic-det-gpio	: Reference to GPIO that signals when
@@ -55,6 +56,9 @@
 					  dai-link uses bit clock inversion.
 - frame-inversion			: bool property. Add this if the
 					  dai-link uses frame clock inversion.
+- mclk-fs             			: Multiplication factor between stream
+					  rate and codec mclk, applied only for
+					  the dai-link.
 
 For backward compatibility the frame-master and bitclock-master
 properties can be used as booleans in codec subnode to indicate if the
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index 8496efc..3ff76d4 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -26,6 +26,7 @@
 	struct simple_dai_props {
 		struct asoc_simple_dai cpu_dai;
 		struct asoc_simple_dai codec_dai;
+		unsigned int mclk_fs;
 	} *dai_props;
 	unsigned int mclk_fs;
 	int gpio_hp_det;
@@ -77,11 +78,18 @@
 	struct snd_soc_dai *codec_dai = rtd->codec_dai;
 	struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
 	struct simple_card_data *priv = snd_soc_card_get_drvdata(rtd->card);
-	unsigned int mclk;
+	struct simple_dai_props *dai_props =
+		&priv->dai_props[rtd - rtd->card->rtd];
+	unsigned int mclk, mclk_fs = 0;
 	int ret = 0;
 
-	if (priv->mclk_fs) {
-		mclk = params_rate(params) * priv->mclk_fs;
+	if (priv->mclk_fs)
+		mclk_fs = priv->mclk_fs;
+	else if (dai_props->mclk_fs)
+		mclk_fs = dai_props->mclk_fs;
+
+	if (mclk_fs) {
+		mclk = params_rate(params) * mclk_fs;
 		ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
 					     SND_SOC_CLOCK_IN);
 		if (ret && ret != -ENOTSUPP)
@@ -322,6 +330,7 @@
 	char prop[128];
 	char *prefix = "";
 	int ret, cpu_args;
+	u32 val;
 
 	/* For single DAI link & old style of DT node */
 	if (is_top_level_node)
@@ -347,6 +356,9 @@
 	if (ret < 0)
 		goto dai_link_of_err;
 
+	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,