[meta-freescale] Audio glitch with SGTL5000
Nikolay Dimitrov
picmaster at mail.bg
Tue Jan 20 16:34:25 PST 2015
Hi Fabio,
On 01/21/2015 12:23 AM, Fabio Estevam wrote:
> On Tue, Jan 20, 2015 at 8:12 PM, Nikolay Dimitrov <picmaster at mail.bg> wrote:
>> Hi guys,
>>
>> I'm observing a specific issue with SGTL5000 - after I stop the audio
>> playback, after several seconds there's a single strong audio glitch
>> (thump, pulse). In my case the audio codec is directly connected to the
>> product speaker amps (without any attenuators) and the experience can
>> be hardly described as pleasant...
>
> Does this patch help?
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/sound/soc/codecs/sgtl5000.c?id=c251ea7bd7a04f1f2575467e0de76e803cf59149
Thanks for your fast answer! Just tried the patch, but unfortunately it
doesn't solve my issue - the pop is still observed on line-out.
I tried to reproduce the issue also with the integrated headphone amp,
just to find out that my board design has an issue (oops!) - the
headphones' ground is connected to the power supply ground instead of
the virtual ground, so I can't test the VAG ramp fix this way. So I can
only speculate that you tested your fix on a properly wired headphone
output, and that's where it worked OK.
Btw, I verified with a protocol analyzer whether the kernel actually
sends the proper I2C commands to the audio codec, and I can confirm
that all commands are sent and acknowledged as expected (including the
SMALL_POP bit setting).
My quick-fix for this was to remove almost all DAPM widgets and
configure the registers only once at start, and this avoid the
pop/click on line-out:
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index ea47938..1223fb7 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -142,32 +142,6 @@ static int mic_bias_event(struct
snd_soc_dapm_widget *w,
return 0;
}
-/*
- * As manual described, ADC/DAC only works when VAG powerup,
- * So enabled VAG before ADC/DAC up.
- * In power down case, we need wait 400ms when vag fully ramped down.
- */
-static int power_vag_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER,
- SGTL5000_VAG_POWERUP, SGTL5000_VAG_POWERUP);
- break;
-
- case SND_SOC_DAPM_POST_PMD:
- snd_soc_update_bits(w->codec, SGTL5000_CHIP_ANA_POWER,
- SGTL5000_VAG_POWERUP, 0);
- msleep(400);
- break;
- default:
- break;
- }
-
- return 0;
-}
-
/* input sources for ADC */
static const char *adc_mux_text[] = {
"MIC_IN", "LINE_IN"
@@ -201,50 +175,15 @@ static const struct snd_soc_dapm_widget
sgtl5000_dapm_widgets[] = {
mic_bias_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
- SND_SOC_DAPM_PGA("HP", SGTL5000_CHIP_ANA_POWER, 4, 0, NULL, 0),
- SND_SOC_DAPM_PGA("LO", SGTL5000_CHIP_ANA_POWER, 0, 0, NULL, 0),
-
SND_SOC_DAPM_MUX("Capture Mux", SND_SOC_NOPM, 0, 0, &adc_mux),
SND_SOC_DAPM_MUX("Headphone Mux", SND_SOC_NOPM, 0, 0, &dac_mux),
-
- /* aif for i2s input */
- SND_SOC_DAPM_AIF_IN("AIFIN", "Playback",
- 0, SGTL5000_CHIP_DIG_POWER,
- 0, 0),
-
- /* aif for i2s output */
- SND_SOC_DAPM_AIF_OUT("AIFOUT", "Capture",
- 0, SGTL5000_CHIP_DIG_POWER,
- 1, 0),
-
- SND_SOC_DAPM_SUPPLY("VAG_POWER", SGTL5000_CHIP_ANA_POWER, 7, 0,
- power_vag_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
-
- SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_ANA_POWER, 1, 0),
- SND_SOC_DAPM_DAC("DAC", "Playback", SGTL5000_CHIP_ANA_POWER, 3, 0),
};
/* routes for sgtl5000 */
static const struct snd_soc_dapm_route sgtl5000_dapm_routes[] = {
{"Capture Mux", "LINE_IN", "LINE_IN"}, /* line_in --> adc_mux */
{"Capture Mux", "MIC_IN", "MIC_IN"}, /* mic_in --> adc_mux */
-
- {"ADC", NULL, "VAG_POWER"},
- {"ADC", NULL, "Capture Mux"}, /* adc_mux --> adc */
- {"AIFOUT", NULL, "ADC"}, /* adc --> i2s_out */
-
- {"DAC", NULL, "VAG_POWER"},
- {"DAC", NULL, "AIFIN"}, /* i2s-->dac,skip audio mux */
- {"Headphone Mux", "DAC", "DAC"}, /* dac --> hp_mux */
- {"LO", NULL, "DAC"}, /* dac --> line_out */
-
- {"LINE_IN", NULL, "VAG_POWER"},
{"Headphone Mux", "LINE_IN", "LINE_IN"},/* line_in --> hp_mux */
- {"HP", NULL, "Headphone Mux"}, /* hp_mux --> hp */
-
- {"LINE_OUT", NULL, "LO"},
- {"HP_OUT", NULL, "HP"},
};
/* custom function to fetch info of PCM playback volume */
@@ -1100,7 +1039,13 @@ static int sgtl5000_set_power_regs(struct
snd_soc_codec *codec)
ana_pwr = snd_soc_read(codec, SGTL5000_CHIP_ANA_POWER);
ana_pwr |= SGTL5000_DAC_STEREO |
SGTL5000_ADC_STEREO |
- SGTL5000_REFTOP_POWERUP;
+ SGTL5000_VAG_POWERUP |
+ SGTL5000_REFTOP_POWERUP |
+ SGTL5000_DAC_POWERUP |
+ SGTL5000_CAPLESS_HP_POWERUP |
+ SGTL5000_ADC_POWERUP |
+ SGTL5000_LINE_OUT_POWERUP;
+
lreg_ctrl = snd_soc_read(codec, SGTL5000_CHIP_LINREG_CTRL);
if (vddio < 3100 && vdda < 3100) {
@@ -1330,7 +1275,10 @@ static int sgtl5000_probe(struct snd_soc_codec
*codec)
snd_soc_write(codec, SGTL5000_CHIP_SSS_CTRL,
SGTL5000_DAC_SEL_I2S_IN << SGTL5000_DAC_SEL_SHIFT);
snd_soc_write(codec, SGTL5000_CHIP_DIG_POWER,
- SGTL5000_ADC_EN | SGTL5000_DAC_EN);
+ SGTL5000_ADC_EN |
+ SGTL5000_DAC_EN |
+ SGTL5000_I2S_OUT_POWERUP |
+ SGTL5000_I2S_IN_POWERUP);
/* enable dac volume ramp by default */
snd_soc_write(codec, SGTL5000_CHIP_ADCDAC_CTRL,
Well, I don't like this brute-force approach and that's why I'm looking
for a more intelligent one.
Kind regards,
Nikolay
More information about the meta-freescale
mailing list