ASoC: fsl_esai: Bypass divider settings if clock requirement is not changed

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>
Signed-off-by: Mark Brown <broonie@linaro.org>
This commit is contained in:
Nicolin Chen 2014-05-06 16:56:01 +08:00 committed by Mark Brown
parent 3e185238a3
commit f975ca46f6

View File

@ -39,6 +39,8 @@
* @fifo_depth: depth of tx/rx FIFO * @fifo_depth: depth of tx/rx FIFO
* @slot_width: width of each DAI slot * @slot_width: width of each DAI slot
* @hck_rate: clock rate of desired HCKx clock * @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 * @sck_div: if using PSR/PM dividers for SCKx clock
* @slave_mode: if fully using DAI slave mode * @slave_mode: if fully using DAI slave mode
* @synchronous: if using tx/rx synchronous mode * @synchronous: if using tx/rx synchronous mode
@ -55,6 +57,8 @@ struct fsl_esai {
u32 fifo_depth; u32 fifo_depth;
u32 slot_width; u32 slot_width;
u32 hck_rate[2]; u32 hck_rate[2];
u32 sck_rate[2];
bool hck_dir[2];
bool sck_div[2]; bool sck_div[2];
bool slave_mode; bool slave_mode;
bool synchronous; 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; unsigned long clk_rate;
int ret; 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 */ /* sck_div can be only bypassed if ETO/ERO=0 and SNC_SOC_CLOCK_OUT */
esai_priv->sck_div[tx] = true; esai_priv->sck_div[tx] = true;
@ -272,6 +280,7 @@ static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
esai_priv->sck_div[tx] = false; esai_priv->sck_div[tx] = false;
out: out:
esai_priv->hck_dir[tx] = dir;
esai_priv->hck_rate[tx] = freq; esai_priv->hck_rate[tx] = freq;
regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR, regmap_update_bits(esai_priv->regmap, REG_ESAI_ECR,
@ -289,9 +298,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); struct fsl_esai *esai_priv = snd_soc_dai_get_drvdata(dai);
u32 hck_rate = esai_priv->hck_rate[tx]; u32 hck_rate = esai_priv->hck_rate[tx];
u32 sub, ratio = hck_rate / freq; u32 sub, ratio = hck_rate / freq;
int ret;
/* Don't apply for fully slave mode*/ /* Don't apply for fully slave mode or unchanged bclk */
if (esai_priv->slave_mode) if (esai_priv->slave_mode || esai_priv->sck_rate[tx] == freq)
return 0; return 0;
if (ratio * freq > hck_rate) if (ratio * freq > hck_rate)
@ -313,8 +323,15 @@ static int fsl_esai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
return -EINVAL; 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); 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, static int fsl_esai_set_dai_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask,