From 2e891d3d62f5fd51e33ae6e614198ce0b3b48e95 Mon Sep 17 00:00:00 2001
From: Viorel Suman <viorel.suman@nxp.com>
Date: Wed, 6 Jun 2018 13:36:20 +0300
Subject: [PATCH] MLK-18534-1: ASoC: fsl: sai: introduce 1:1 bclk:mclk ratio
 support

Since IP version 3.01 (845s) SAI has support for 1:1
bclk:mclk ratio.

Signed-off-by: Viorel Suman <viorel.suman@nxp.com>
---
 sound/soc/fsl/fsl_sai.c | 69 +++++++++++++++++++++++++------------------------
 sound/soc/fsl/fsl_sai.h |  2 +-
 2 files changed, 36 insertions(+), 35 deletions(-)

--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -471,7 +471,8 @@ static int fsl_sai_set_bclk(struct snd_s
 	struct fsl_sai *sai = snd_soc_dai_get_drvdata(dai);
 	unsigned char offset = sai->soc->reg_offset;
 	unsigned long clk_rate;
-	u32 savediv = 0, ratio, savesub = freq;
+	unsigned int reg = 0;
+	u32 ratio, savesub = freq, saveratio = 0, savediv = 0;
 	u32 id;
 	int ret = 0;
 
@@ -479,6 +480,8 @@ static int fsl_sai_set_bclk(struct snd_s
 	if (sai->slave_mode[tx])
 		return 0;
 
+	fsl_sai_check_ver(dai);
+
 	for (id = 0; id < FSL_SAI_MCLK_MAX; id++) {
 		clk_rate = clk_get_rate(sai->mclk_clk[id]);
 		if (!clk_rate)
@@ -499,22 +502,21 @@ static int fsl_sai_set_bclk(struct snd_s
 			"ratio %d for freq %dHz based on clock %ldHz\n",
 			ratio, freq, clk_rate);
 
-		if (ratio % 2 == 0 && ratio >= 2 && ratio <= 512)
-			ratio /= 2;
-		else
-			continue;
+		if ((ratio % 2 == 0 && ratio >= 2 && ratio <= 512) ||
+		    (ratio == 1 && sai->verid.id >= FSL_SAI_VERID_0301)) {
 
-		if (ret < savesub) {
-			savediv = ratio;
-			sai->mclk_id[tx] = id;
-			savesub = ret;
-		}
+			if (ret < savesub) {
+				saveratio = ratio;
+				sai->mclk_id[tx] = id;
+				savesub = ret;
+			}
 
-		if (ret == 0)
-			break;
+			if (ret == 0)
+				break;
+		}
 	}
 
-	if (savediv == 0) {
+	if (saveratio == 0) {
 		dev_err(dai->dev, "failed to derive required %cx rate: %d\n",
 				tx ? 'T' : 'R', freq);
 		return -EINVAL;
@@ -530,33 +532,32 @@ static int fsl_sai_set_bclk(struct snd_s
 	 * 4) For Tx and Rx are both Synchronous with another SAI, we just
 	 *    ignore it.
 	 */
-	if ((sai->synchronous[TX] && !sai->synchronous[RX]) ||
-	    (!tx && !sai->synchronous[RX])) {
-		regmap_update_bits(sai->regmap, FSL_SAI_RCR2(offset),
-				   FSL_SAI_CR2_MSEL_MASK,
-				   FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
-		regmap_update_bits(sai->regmap, FSL_SAI_RCR2(offset),
-				   FSL_SAI_CR2_DIV_MASK, savediv - 1);
-	} else if ((sai->synchronous[RX] && !sai->synchronous[TX]) ||
-		   (tx && !sai->synchronous[TX])) {
-		regmap_update_bits(sai->regmap, FSL_SAI_TCR2(offset),
-				   FSL_SAI_CR2_MSEL_MASK,
-				   FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
-		regmap_update_bits(sai->regmap, FSL_SAI_TCR2(offset),
-				   FSL_SAI_CR2_DIV_MASK, savediv - 1);
+	if ((!tx || sai->synchronous[TX]) && !sai->synchronous[RX])
+		reg = FSL_SAI_RCR2(offset);
+	else if ((tx || sai->synchronous[RX]) && !sai->synchronous[TX])
+		reg = FSL_SAI_TCR2(offset);
+
+	if (reg) {
+		regmap_update_bits(sai->regmap, reg, FSL_SAI_CR2_MSEL_MASK,
+			   FSL_SAI_CR2_MSEL(sai->mclk_id[tx]));
+
+		savediv = (saveratio == 1 ? 0 : (saveratio >> 1) - 1);
+		regmap_update_bits(sai->regmap, reg, FSL_SAI_CR2_DIV_MASK, savediv);
+
+		if (sai->verid.id >= FSL_SAI_VERID_0301) {
+			regmap_update_bits(sai->regmap, reg, FSL_SAI_CR2_BYP,
+				   (saveratio == 1 ? FSL_SAI_CR2_BYP : 0));
+		}
 	}
 
-	fsl_sai_check_ver(dai);
-	switch (sai->verid.id) {
-	case FSL_SAI_VERID_0301:
+	if (sai->verid.id >= FSL_SAI_VERID_0301) {
 		/* SAI is in master mode at this point, so enable MCLK */
 		regmap_update_bits(sai->regmap, FSL_SAI_MCTL,
-				FSL_SAI_MCTL_MCLK_EN, FSL_SAI_MCTL_MCLK_EN);
-		break;
+			FSL_SAI_MCTL_MCLK_EN, FSL_SAI_MCTL_MCLK_EN);
 	}
 
-	dev_dbg(dai->dev, "best fit: clock id=%d, div=%d, deviation =%d\n",
-			sai->mclk_id[tx], savediv, savesub);
+	dev_dbg(dai->dev, "best fit: clock id=%d, ratio=%d, deviation=%d\n",
+			sai->mclk_id[tx], saveratio, savesub);
 
 	return 0;
 }
--- a/sound/soc/fsl/fsl_sai.h
+++ b/sound/soc/fsl/fsl_sai.h
@@ -122,7 +122,7 @@
 #define FSL_SAI_CR2_MSEL(ID)	((ID) << 26)
 #define FSL_SAI_CR2_BCP		BIT(25)
 #define FSL_SAI_CR2_BCD_MSTR	BIT(24)
-#define FSL_SAI_CR2_BCBP	BIT(23) /* BCLK bypass */
+#define FSL_SAI_CR2_BYP		BIT(23) /* BCLK bypass */
 #define FSL_SAI_CR2_DIV_MASK	0xff
 
 /* SAI Transmit and Receive Configuration 3 Register */