summaryrefslogtreecommitdiff
path: root/sound/soc/fsl/fsl_sai.c
diff options
context:
space:
mode:
authorViorel Suman <viorel.suman@nxp.com>2018-06-06 13:36:20 +0300
committerDong Aisheng <aisheng.dong@nxp.com>2019-11-25 15:54:00 +0800
commit06131f164d73f623ce745023bf9207f1690556c0 (patch)
tree7ddba4d3d84d1aeddc84cb83f3a9e1c0084b2431 /sound/soc/fsl/fsl_sai.c
parentf22894516873a00f4dbadc30bb30bce745d99eab (diff)
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>
Diffstat (limited to 'sound/soc/fsl/fsl_sai.c')
-rw-r--r--sound/soc/fsl/fsl_sai.c69
1 files changed, 35 insertions, 34 deletions
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index 37c32183f79c..10dda41249d2 100644
--- 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_soc_dai *dai, bool tx, u32 freq)
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_soc_dai *dai, bool tx, u32 freq)
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_soc_dai *dai, bool tx, u32 freq)
"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_soc_dai *dai, bool tx, u32 freq)
* 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;
}