|
@@ -258,10 +258,16 @@ static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
|
|
return -EINVAL;
|
|
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 */
|
|
/* Bypass all the dividers if not being needed */
|
|
ecr |= tx ? ESAI_ECR_ETO : ESAI_ECR_ERO;
|
|
ecr |= tx ? ESAI_ECR_ETO : ESAI_ECR_ERO;
|
|
goto out;
|
|
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);
|
|
ret = fsl_esai_divisor_cal(dai, tx, ratio, false, 0);
|
|
@@ -307,7 +313,8 @@ static int fsl_esai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
|
|
return -EINVAL;
|
|
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");
|
|
dev_err(dai->dev, "the ratio is out of range (1 ~ 16)\n");
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
@@ -454,12 +461,6 @@ static int fsl_esai_startup(struct snd_pcm_substream *substream,
|
|
}
|
|
}
|
|
|
|
|
|
if (!dai->active) {
|
|
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 */
|
|
/* Set synchronous mode */
|
|
regmap_update_bits(esai_priv->regmap, REG_ESAI_SAICR,
|
|
regmap_update_bits(esai_priv->regmap, REG_ESAI_SAICR,
|
|
ESAI_SAICR_SYNC, esai_priv->synchronous ?
|
|
ESAI_SAICR_SYNC, esai_priv->synchronous ?
|
|
@@ -519,6 +520,11 @@ static int fsl_esai_hw_params(struct snd_pcm_substream *substream,
|
|
|
|
|
|
regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx), mask, val);
|
|
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;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|