aboutsummaryrefslogtreecommitdiff
path: root/sound/soc/fsl/fsl_esai.c
diff options
context:
space:
mode:
authorNicolin Chen <Guangyu.Chen@freescale.com>2014-05-06 16:56:01 +0800
committerMark Brown <broonie@linaro.org>2014-05-12 23:15:25 +0100
commitf975ca46f634660a52d8c815b465258ae9bce3b7 (patch)
tree781c34ceec8d6463c57f59f8305db607eaca9f0f /sound/soc/fsl/fsl_esai.c
parent3e185238a37d1f0a37a1d910344cdcff578bf333 (diff)
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>
Diffstat (limited to 'sound/soc/fsl/fsl_esai.c')
-rw-r--r--sound/soc/fsl/fsl_esai.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c
index 67d5417e0933..0edc837ea3d7 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;
@@ -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;
out:
+ esai_priv->hck_dir[tx] = dir;
esai_priv->hck_rate[tx] = freq;
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);
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)
@@ -313,8 +323,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,