From 4ea2cc2a65b7273cd05c0c0adf98504cd05d03ec Mon Sep 17 00:00:00 2001 From: Xing Zheng Date: Wed, 9 May 2018 10:11:10 +0800 Subject: [PATCH] ASoC: rk3308_codec: clear ADC/DAC digital registers before configuration We need to clear previous residual configuration for ADC/DAC digital registers before enable them, otherwise, the acodec maybe abnormal. Change-Id: I2eeb6ccf1508cf10d214d97c29273d70d16f3417 Signed-off-by: Xing Zheng --- sound/soc/codecs/rk3308_codec.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/sound/soc/codecs/rk3308_codec.c b/sound/soc/codecs/rk3308_codec.c index 25e62301639f..0d426fc2ed3a 100644 --- a/sound/soc/codecs/rk3308_codec.c +++ b/sound/soc/codecs/rk3308_codec.c @@ -455,6 +455,32 @@ static int rk3308_codec_reset(struct snd_soc_codec *codec) return 0; } +static int rk3308_codec_adc_dig_reset(struct rk3308_codec_priv *rk3308) +{ + regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, + RK3308_ADC_DIG_WORK, + RK3308_ADC_DIG_RESET); + udelay(50); + regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, + RK3308_ADC_DIG_WORK, + RK3308_ADC_DIG_WORK); + + return 0; +} + +static int rk3308_codec_dac_dig_reset(struct rk3308_codec_priv *rk3308) +{ + regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, + RK3308_DAC_DIG_WORK, + RK3308_DAC_DIG_RESET); + udelay(50); + regmap_update_bits(rk3308->regmap, RK3308_GLB_CON, + RK3308_DAC_DIG_WORK, + RK3308_DAC_DIG_WORK); + + return 0; +} + static int rk3308_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { @@ -606,6 +632,9 @@ static int rk3308_hw_params(struct snd_pcm_substream *substream, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { unsigned int dac_aif1 = 0, dac_aif2 = 0; + /* Clear the status of DAC DIG Digital reigisters */ + rk3308_codec_dac_dig_reset(rk3308); + switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_16BITS; @@ -637,6 +666,9 @@ static int rk3308_hw_params(struct snd_pcm_substream *substream, unsigned int adc_aif1 = 0, adc_aif2 = 0; int grp, cur_grp_max; + /* Clear the status of ADC DIG Digital reigisters */ + rk3308_codec_adc_dig_reset(rk3308); + switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_16BITS;