Commit 1997ee89 authored by S.j. Wang's avatar S.j. Wang Committed by Mark Brown

ASoC: fsl_esai: Support synchronous mode

In ESAI synchronous mode, the clock is generated by Tx, So
we should always set registers of Tx which relate with the
bit clock and frame clock generation (TCCR, TCR, ECR), even
there is only Rx is working.
Signed-off-by: default avatarShengjiu Wang <shengjiu.wang@nxp.com>
Acked-by: default avatarNicolin Chen <nicoleotsuka@gmail.com>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 2114171d
...@@ -218,7 +218,7 @@ static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, ...@@ -218,7 +218,7 @@ static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
{ {
struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
struct clk *clksrc = esai_priv->extalclk; struct clk *clksrc = esai_priv->extalclk;
bool tx = clk_id <= ESAI_HCKT_EXTAL; bool tx = (clk_id <= ESAI_HCKT_EXTAL || esai_priv->synchronous);
bool in = dir == SND_SOC_CLOCK_IN; bool in = dir == SND_SOC_CLOCK_IN;
u32 ratio, ecr = 0; u32 ratio, ecr = 0;
unsigned long clk_rate; unsigned long clk_rate;
...@@ -253,7 +253,7 @@ static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, ...@@ -253,7 +253,7 @@ static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
ecr |= ESAI_ECR_ETI; ecr |= ESAI_ECR_ETI;
/* fall through */ /* fall through */
case ESAI_HCKR_EXTAL: case ESAI_HCKR_EXTAL:
ecr |= ESAI_ECR_ERI; ecr |= esai_priv->synchronous ? ESAI_ECR_ETI : ESAI_ECR_ERI;
break; break;
default: default:
return -EINVAL; return -EINVAL;
...@@ -537,10 +537,18 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream, ...@@ -537,10 +537,18 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
bclk = params_rate(params) * slot_width * esai_priv->slots; bclk = params_rate(params) * slot_width * esai_priv->slots;
ret = fsl_esai_set_bclk(dai, tx, bclk); ret = fsl_esai_set_bclk(dai, esai_priv->synchronous || tx, bclk);
if (ret) if (ret)
return ret; return ret;
mask = ESAI_xCR_xSWS_MASK;
val = ESAI_xCR_xSWS(slot_width, width);
regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), mask, val);
/* Recording in synchronous mode needs to set TCR also */
if (!tx && esai_priv->synchronous)
regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR, mask, val);
/* Use Normal mode to support monaural audio */ /* Use Normal mode to support monaural audio */
regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
ESAI_xCR_xMOD_MASK, params_channels(params) > 1 ? ESAI_xCR_xMOD_MASK, params_channels(params) > 1 ?
...@@ -556,10 +564,9 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream, ...@@ -556,10 +564,9 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), mask, val); regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx), mask, val);
mask = ESAI_xCR_xSWS_MASK | (tx ? ESAI_xCR_PADC : 0); if (tx)
val = ESAI_xCR_xSWS(slot_width, width) | (tx ? ESAI_xCR_PADC : 0); regmap_update_bits(esai_priv->regmap, REG_ESAI_TCR,
ESAI_xCR_PADC, ESAI_xCR_PADC);
regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), mask, val);
/* Remove ESAI personal reset by configuring ESAI_PCRC and ESAI_PRRC */ /* Remove ESAI personal reset by configuring ESAI_PCRC and ESAI_PRRC */
regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC, regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment