aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRicard Wanderlof <ricard.wanderlof@axis.com>2017-09-07 09:31:38 -0400
committerMark Brown <broonie@kernel.org>2017-09-07 09:46:34 -0400
commit1e6f4fc06f6411adf98bbbe7fcd79442cd2b2a75 (patch)
tree75f148ede163ca0690cd6ed0141b648e6b35b249
parent7051334672e54fae67e02d5d3296fb62b3343be7 (diff)
ASoC: adau17x1: Workaround for noise bug in ADC
The ADC in the ADAU1361 (and possibly other Analog Devices codecs) exhibits a cyclic variation in the noise floor (in our test setup between -87 and -93 dB), a new value being attained within this range whenever a new capture stream is started. The cycle repeats after about 10 or 11 restarts. The workaround recommended by the manufacturer is to toggle the ADOSR bit in the Converter Control 0 register each time a new capture stream is started. I have verified that the patch fixes this problem on the ADAU1361, and according to the manufacturer toggling the bit in question in this manner will at least have no detrimental effect on other chips served by this driver. Signed-off-by: Ricard Wanderlof <ricardw@axis.com> Signed-off-by: Mark Brown <broonie@kernel.org> Cc: stable@vger.kernel.org
-rw-r--r--sound/soc/codecs/adau17x1.c24
-rw-r--r--sound/soc/codecs/adau17x1.h2
2 files changed, 25 insertions, 1 deletions
diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c
index 2c1bd2763864..6758f789b712 100644
--- a/sound/soc/codecs/adau17x1.c
+++ b/sound/soc/codecs/adau17x1.c
@@ -90,6 +90,27 @@ static int adau17x1_pll_event(struct snd_soc_dapm_widget *w,
90 return 0; 90 return 0;
91} 91}
92 92
93static int adau17x1_adc_fixup(struct snd_soc_dapm_widget *w,
94 struct snd_kcontrol *kcontrol, int event)
95{
96 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
97 struct adau *adau = snd_soc_codec_get_drvdata(codec);
98
99 /*
100 * If we are capturing, toggle the ADOSR bit in Converter Control 0 to
101 * avoid losing SNR (workaround from ADI). This must be done after
102 * the ADC(s) have been enabled. According to the data sheet, it is
103 * normally illegal to set this bit when the sampling rate is 96 kHz,
104 * but according to ADI it is acceptable for this workaround.
105 */
106 regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0,
107 ADAU17X1_CONVERTER0_ADOSR, ADAU17X1_CONVERTER0_ADOSR);
108 regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0,
109 ADAU17X1_CONVERTER0_ADOSR, 0);
110
111 return 0;
112}
113
93static const char * const adau17x1_mono_stereo_text[] = { 114static const char * const adau17x1_mono_stereo_text[] = {
94 "Stereo", 115 "Stereo",
95 "Mono Left Channel (L+R)", 116 "Mono Left Channel (L+R)",
@@ -121,7 +142,8 @@ static const struct snd_soc_dapm_widget adau17x1_dapm_widgets[] = {
121 SND_SOC_DAPM_MUX("Right DAC Mode Mux", SND_SOC_NOPM, 0, 0, 142 SND_SOC_DAPM_MUX("Right DAC Mode Mux", SND_SOC_NOPM, 0, 0,
122 &adau17x1_dac_mode_mux), 143 &adau17x1_dac_mode_mux),
123 144
124 SND_SOC_DAPM_ADC("Left Decimator", NULL, ADAU17X1_ADC_CONTROL, 0, 0), 145 SND_SOC_DAPM_ADC_E("Left Decimator", NULL, ADAU17X1_ADC_CONTROL, 0, 0,
146 adau17x1_adc_fixup, SND_SOC_DAPM_POST_PMU),
125 SND_SOC_DAPM_ADC("Right Decimator", NULL, ADAU17X1_ADC_CONTROL, 1, 0), 147 SND_SOC_DAPM_ADC("Right Decimator", NULL, ADAU17X1_ADC_CONTROL, 1, 0),
126 SND_SOC_DAPM_DAC("Left DAC", NULL, ADAU17X1_DAC_CONTROL0, 0, 0), 148 SND_SOC_DAPM_DAC("Left DAC", NULL, ADAU17X1_DAC_CONTROL0, 0, 0),
127 SND_SOC_DAPM_DAC("Right DAC", NULL, ADAU17X1_DAC_CONTROL0, 1, 0), 149 SND_SOC_DAPM_DAC("Right DAC", NULL, ADAU17X1_DAC_CONTROL0, 1, 0),
diff --git a/sound/soc/codecs/adau17x1.h b/sound/soc/codecs/adau17x1.h
index bf04b7efee40..db350035fad7 100644
--- a/sound/soc/codecs/adau17x1.h
+++ b/sound/soc/codecs/adau17x1.h
@@ -129,5 +129,7 @@ bool adau17x1_has_dsp(struct adau *adau);
129 129
130#define ADAU17X1_CONVERTER0_CONVSR_MASK 0x7 130#define ADAU17X1_CONVERTER0_CONVSR_MASK 0x7
131 131
132#define ADAU17X1_CONVERTER0_ADOSR BIT(3)
133
132 134
133#endif 135#endif