[alsa-devel] [PATCH RESEND 0/4] ASoC: fsl_esai: Fix some issues
Sorry for this resend. I just found my previous patches have not been delivered successfully to the alsa maillist.
This series of patches fix the following problems: PATCH-1 for an incorrect ratio range check. PATCH-2 for an incorrect bypass settings of FSYS clock source. PATCH-3 for duplicated calculations and configurations of dividers PATCH-4 for mismatched init flow of configuration comparing to RM.
Nicolin Chen (4): ASoC: fsl_esai: Fix incorrect condition within ratio range check for FP ASoC: fsl_esai: Only bypass sck_div for EXTAL source ASoC: fsl_esai: Bypass divider settings if clock requirement is not changed ASoC: fsl_esai: Set PCRC and PRRC registers at the end of hw_params()
sound/soc/fsl/fsl_esai.c | 45 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-)
The range here from 1 to 16 is confined to FP divider only while the sck_div indicates if the calculation contains PSR and PM dividers. So for the case using PSR and PM since the sck_div is true, the range of ratio would simply become bigger than 16.
So this patch fixes the condition here and adds one line comments to make the purpose here clear.
Signed-off-by: Nicolin Chen Guangyu.Chen@freescale.com --- sound/soc/fsl/fsl_esai.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index b49b78d..d098a48 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -308,7 +308,8 @@ static int fsl_esai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq) return -EINVAL; }
- if (esai_priv->sck_div[tx] && (ratio > 16 || ratio == 0)) { + /* The ratio should be contented by FP alone if bypassing PM and PSR */ + if (!esai_priv->sck_div[tx] && (ratio > 16 || ratio == 0)) { dev_err(dai->dev, "the ratio is out of range (1 ~ 16)\n"); return -EINVAL; }
ESAI can only output EXTAL clock source directly. But for FSYS clock source, ESAI can not output it without getting through PSR PM dividers.
So this patch adds an extra check in the code.
Signed-off-by: Nicolin Chen Guangyu.Chen@freescale.com --- sound/soc/fsl/fsl_esai.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index d098a48..7e1916e 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -259,10 +259,16 @@ static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, return -EINVAL; }
- if (ratio == 1) { + /* Only EXTAL source can be output directly without using PSR and PM */ + if (ratio == 1 && clksrc == esai_priv->extalclk) { /* Bypass all the dividers if not being needed */ ecr |= tx ? ESAI_ECR_ETO : ESAI_ECR_ERO; goto out; + } else if (ratio < 2) { + /* The ratio should be no less than 2 if using other sources */ + dev_err(dai->dev, "failed to derive required HCK%c rate\n", + tx ? 'T' : 'R'); + return -EINVAL; }
ret = fsl_esai_divisor_cal(dai, tx, ratio, false, 0);
We don't need to change those dividers if bclk and mclk remains the same directions and values.
Signed-off-by: Nicolin Chen Guangyu.Chen@freescale.com --- sound/soc/fsl/fsl_esai.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 7e1916e..dd0b171 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -39,6 +39,8 @@ * @fifo_depth: depth of tx/rx FIFO * @slot_width: width of each DAI slot * @hck_rate: clock rate of desired HCKx clock + * @sck_rate: clock rate of desired SCKx clock + * @hck_dir: the direction of HCKx pads * @sck_div: if using PSR/PM dividers for SCKx clock * @slave_mode: if fully using DAI slave mode * @synchronous: if using tx/rx synchronous mode @@ -55,6 +57,8 @@ struct fsl_esai { u32 fifo_depth; u32 slot_width; u32 hck_rate[2]; + u32 sck_rate[2]; + bool hck_dir[2]; bool sck_div[2]; bool slave_mode; bool synchronous; @@ -213,6 +217,10 @@ static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned long clk_rate; int ret;
+ /* Bypass divider settings if the requirement doesn't change */ + if (freq == esai_priv->hck_rate[tx] && dir == esai_priv->hck_dir[tx]) + return 0; + /* sck_div can be only bypassed if ETO/ERO=0 and SNC_SOC_CLOCK_OUT */ esai_priv->sck_div[tx] = true;
@@ -278,6 +286,7 @@ static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, esai_priv->sck_div[tx] = false;
out: + esai_priv->hck_dir[tx] = dir; esai_priv->hck_rate[tx] = freq;
regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR, @@ -295,9 +304,10 @@ static int fsl_esai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq) struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai); u32 hck_rate = esai_priv->hck_rate[tx]; u32 sub, ratio = hck_rate / freq; + int ret;
- /* Don't apply for fully slave mode*/ - if (esai_priv->slave_mode) + /* Don't apply for fully slave mode or unchanged bclk */ + if (esai_priv->slave_mode || esai_priv->sck_rate[tx] == freq) return 0;
if (ratio * freq > hck_rate) @@ -320,8 +330,15 @@ static int fsl_esai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq) return -EINVAL; }
- return fsl_esai_divisor_cal(dai, tx, ratio, true, + ret = fsl_esai_divisor_cal(dai, tx, ratio, true, esai_priv->sck_div[tx] ? 0 : ratio); + if (ret) + return ret; + + /* Save current bclk rate */ + esai_priv->sck_rate[tx] = freq; + + return 0; }
static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask,
According to Reference Manual -- ESAI Initialization chapter, as the standard procedure of ESAI personal reset, the PCRC and PRRC registers should be remained in its reset value and then configured after T/RCCR and T/RCR configurations's done but before TE/RE's enabling.
So this patch moves PCRC and PRRC settings to the end of hw_params().
Signed-off-by: Nicolin Chen Guangyu.Chen@freescale.com --- sound/soc/fsl/fsl_esai.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index dd0b171..d719caf 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -479,12 +479,6 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream, }
if (!dai->active) { - /* Reset Port C */ - regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC, - ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO)); - regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC, - ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO)); - /* Set synchronous mode */ regmap_update_bits(esai_priv->regmap, REG_ESAI_SAICR, ESAI_SAICR_SYNC, esai_priv->synchronous ? @@ -545,6 +539,11 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), mask, val);
+ /* Remove ESAI personal reset by configuring ESAI_PCRC and ESAI_PRRC */ + regmap_update_bits(esai_priv->regmap, REG_ESAI_PRRC, + ESAI_PRRC_PDC_MASK, ESAI_PRRC_PDC(ESAI_GPIO)); + regmap_update_bits(esai_priv->regmap, REG_ESAI_PCRC, + ESAI_PCRC_PC_MASK, ESAI_PCRC_PC(ESAI_GPIO)); return 0; }
participants (2)
-
Mark Brown
-
Nicolin Chen