Skip to content

Commit 97d64b7

Browse files
Ricard Wanderlofgregkh
authored andcommitted
ASoC: adau17x1: Workaround for noise bug in ADC
commit 1e6f4fc06f6411adf98bbbe7fcd79442cd2b2a75 upstream. 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 618b930 commit 97d64b7

2 files changed

Lines changed: 25 additions & 1 deletion

File tree

sound/soc/codecs/adau17x1.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,27 @@ static int adau17x1_pll_event(struct snd_soc_dapm_widget *w,
8989
return 0;
9090
}
9191

92+
static int adau17x1_adc_fixup(struct snd_soc_dapm_widget *w,
93+
struct snd_kcontrol *kcontrol, int event)
94+
{
95+
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
96+
struct adau *adau = snd_soc_codec_get_drvdata(codec);
97+
98+
/*
99+
* If we are capturing, toggle the ADOSR bit in Converter Control 0 to
100+
* avoid losing SNR (workaround from ADI). This must be done after
101+
* the ADC(s) have been enabled. According to the data sheet, it is
102+
* normally illegal to set this bit when the sampling rate is 96 kHz,
103+
* but according to ADI it is acceptable for this workaround.
104+
*/
105+
regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0,
106+
ADAU17X1_CONVERTER0_ADOSR, ADAU17X1_CONVERTER0_ADOSR);
107+
regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0,
108+
ADAU17X1_CONVERTER0_ADOSR, 0);
109+
110+
return 0;
111+
}
112+
92113
static const char * const adau17x1_mono_stereo_text[] = {
93114
"Stereo",
94115
"Mono Left Channel (L+R)",
@@ -120,7 +141,8 @@ static const struct snd_soc_dapm_widget adau17x1_dapm_widgets[] = {
120141
SND_SOC_DAPM_MUX("Right DAC Mode Mux", SND_SOC_NOPM, 0, 0,
121142
&adau17x1_dac_mode_mux),
122143

123-
SND_SOC_DAPM_ADC("Left Decimator", NULL, ADAU17X1_ADC_CONTROL, 0, 0),
144+
SND_SOC_DAPM_ADC_E("Left Decimator", NULL, ADAU17X1_ADC_CONTROL, 0, 0,
145+
adau17x1_adc_fixup, SND_SOC_DAPM_POST_PMU),
124146
SND_SOC_DAPM_ADC("Right Decimator", NULL, ADAU17X1_ADC_CONTROL, 1, 0),
125147
SND_SOC_DAPM_DAC("Left DAC", NULL, ADAU17X1_DAC_CONTROL0, 0, 0),
126148
SND_SOC_DAPM_DAC("Right DAC", NULL, ADAU17X1_DAC_CONTROL0, 1, 0),

sound/soc/codecs/adau17x1.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,5 +123,7 @@ bool adau17x1_has_dsp(struct adau *adau);
123123

124124
#define ADAU17X1_CONVERTER0_CONVSR_MASK 0x7
125125

126+
#define ADAU17X1_CONVERTER0_ADOSR BIT(3)
127+
126128

127129
#endif

0 commit comments

Comments
 (0)