All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ASoC: rt286: fix headphone click/crack noise on Dell XPS 9343 I2S mode
@ 2017-01-23  5:35 Kai-Heng Feng
  2017-02-16  5:10 ` Kai-Heng Feng
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Kai-Heng Feng @ 2017-01-23  5:35 UTC (permalink / raw)
  To: bardliao; +Cc: oder_chiou, Kai-Heng Feng, alsa-devel, broonie, lgirdwood

HDA mode does not have these issues because necessary workarounds in
linux/sound/pci/hda/patch_realtek.c are already applied. So we can
leverage these workaournds into rt286.

When jack is plugged, it rapidly generates I2C interrupts, which
triggers rt286_irq() and rt286_jack_detect(), which causes the noise.
alc_fixup_dell_xps13() in patch_realtek.c sets up a pin that can stop
the frantic interrupts, hence fixes the click noise.

When rt286 is under powersaving state, play a sound with headphone or
plug a headphone in will produce a loud crack sound.
alc_shutup_dell_xps13() patch_realtek.c mutes the headphone at plugging.
Apply the same workaround to LDO2 power event can make the loud crack
sound to a more tolerable pop sound. I found that unconditionally apply
the workaround to all related power event can help a little further.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=112611
Link: https://bugzilla.redhat.com/show_bug.cgi?id=1313434
Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
---
 sound/soc/codecs/rt286.c | 67 +++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 63 insertions(+), 4 deletions(-)

diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c
index 74c0e4e..d041937 100644
--- a/sound/soc/codecs/rt286.c
+++ b/sound/soc/codecs/rt286.c
@@ -36,6 +36,8 @@
 #define RT286_VENDOR_ID 0x10ec0286
 #define RT288_VENDOR_ID 0x10ec0288
 
+#define AMP_OUT_MUTE 0xb080
+
 struct rt286_priv {
 	struct reg_default *index_cache;
 	int index_cache_size;
@@ -47,6 +49,7 @@ struct rt286_priv {
 	struct delayed_work jack_detect_work;
 	int sys_clk;
 	int clk_id;
+	void (*mute_hpo_func)(struct snd_soc_codec *codec);
 };
 
 static const struct reg_default rt286_index_def[] = {
@@ -472,10 +475,51 @@ static int rt286_set_dmic1_event(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
+/* Add HV, VREF and LDO1 event functions to workaround headphone crack noise */
+static int rt286_hv_event(struct snd_soc_dapm_widget *w,
+			     struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+	struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
+
+	if (rt286->mute_hpo_func)
+		rt286->mute_hpo_func(codec);
+
+	return 0;
+}
+
+static int rt286_vref_event(struct snd_soc_dapm_widget *w,
+			     struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+	struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
+
+	if (rt286->mute_hpo_func)
+		rt286->mute_hpo_func(codec);
+
+	return 0;
+}
+
+static int rt286_ldo1_event(struct snd_soc_dapm_widget *w,
+			     struct snd_kcontrol *kcontrol, int event)
+{
+	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+	struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
+
+	if (rt286->mute_hpo_func)
+		rt286->mute_hpo_func(codec);
+
+	return 0;
+}
+
 static int rt286_ldo2_event(struct snd_soc_dapm_widget *w,
 			     struct snd_kcontrol *kcontrol, int event)
 {
 	struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+	struct rt286_priv *rt286 = snd_soc_codec_get_drvdata(codec);
+
+	if (rt286->mute_hpo_func)
+		rt286->mute_hpo_func(codec);
 
 	switch (event) {
 	case SND_SOC_DAPM_POST_PMU:
@@ -516,16 +560,24 @@ static int rt286_mic1_event(struct snd_soc_dapm_widget *w,
 	return 0;
 }
 
+static void dell_dino_mute_hpo(struct snd_soc_codec *codec)
+{
+	snd_soc_write(codec, RT286_SET_AMP_GAIN_HPO, AMP_OUT_MUTE);
+}
+
 static const struct snd_soc_dapm_widget rt286_dapm_widgets[] = {
 	SND_SOC_DAPM_SUPPLY_S("HV", 1, RT286_POWER_CTRL1,
-		12, 1, NULL, 0),
+		12, 1, rt286_hv_event, SND_SOC_DAPM_PRE_PMD |
+		SND_SOC_DAPM_PRE_PMU),
 	SND_SOC_DAPM_SUPPLY("VREF", RT286_POWER_CTRL1,
-		0, 1, NULL, 0),
+		0, 1, rt286_vref_event, SND_SOC_DAPM_PRE_PMD |
+		SND_SOC_DAPM_PRE_PMU),
 	SND_SOC_DAPM_SUPPLY_S("LDO1", 1, RT286_POWER_CTRL2,
-		2, 0, NULL, 0),
+		2, 0, rt286_ldo1_event, SND_SOC_DAPM_PRE_PMD |
+		SND_SOC_DAPM_PRE_PMU),
 	SND_SOC_DAPM_SUPPLY_S("LDO2", 2, RT286_POWER_CTRL1,
 		13, 1, rt286_ldo2_event, SND_SOC_DAPM_PRE_PMD |
-		SND_SOC_DAPM_POST_PMU),
+		SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU),
 	SND_SOC_DAPM_SUPPLY("MCLK MODE", RT286_PLL_CTRL1,
 		5, 0, NULL, 0),
 	SND_SOC_DAPM_SUPPLY("MIC1 Input Buffer", SND_SOC_NOPM,
@@ -1190,6 +1242,11 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
 		regmap_update_bits(rt286->regmap,
 					RT286_CBJ_CTRL1, 0xf000, 0xb000);
 	} else {
+		/* Fix headphone click noise */
+		if (dmi_check_system(dmi_dell_dino))
+			regmap_write(rt286->regmap,
+					RT286_MIC1_DET_CTRL, 0x0020);
+
 		regmap_update_bits(rt286->regmap,
 					RT286_CBJ_CTRL1, 0xf000, 0x5000);
 	}
@@ -1204,6 +1261,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
 	mdelay(10);
 
 	regmap_write(rt286->regmap, RT286_MISC_CTRL1, 0x0000);
+
 	/* Power down LDO, VREF */
 	regmap_update_bits(rt286->regmap, RT286_POWER_CTRL2, 0xc, 0x0);
 	regmap_update_bits(rt286->regmap, RT286_POWER_CTRL1, 0x1001, 0x1001);
@@ -1222,6 +1280,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c,
 			RT286_SET_GPIO_DATA, 0x40, 0x40);
 		regmap_update_bits(rt286->regmap,
 			RT286_GPIO_CTRL, 0xc, 0x8);
+		rt286->mute_hpo_func = dell_dino_mute_hpo;
 	}
 
 	if (rt286->i2c->irq) {
-- 
2.10.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread
* Re: [PATCH] ASoC: rt286: fix headphone click/crack noise on Dell XPS 9343 I2S mode
@ 2017-04-18  0:02 Garrett Thornburg
  0 siblings, 0 replies; 9+ messages in thread
From: Garrett Thornburg @ 2017-04-18  0:02 UTC (permalink / raw)
  To: alsa-devel

This is my first time posting in any type of mailing list, so
hopefully I'm doing this right. I recently encountered the audio
trouble with I2S mode via the headphone jack on my Dell XPS 9343 as
well and found your patch.

I applied the patch to the latest stable kernel (4.10) on arch linux
mostly using their tools and the repeated clicking sound is fixed when
no sound is playing. However, sometimes when sound is playing, the
clicking returns but it's much more mild. If I pause/ resume music,
for example, it might "click.. click.. click.." very quietly, but not
always. It's audible when I turn the volume level down low, but
overall it's much better.

I do still get somewhat loud pops when resuming music after the sound
card has been idle for a while, or a pop when the card switches to an
idle state.

This patch has really improved my situation though, so thank you :).

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2017-04-18  0:02 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-23  5:35 [PATCH] ASoC: rt286: fix headphone click/crack noise on Dell XPS 9343 I2S mode Kai-Heng Feng
2017-02-16  5:10 ` Kai-Heng Feng
2017-02-16 19:13   ` Mark Brown
2017-02-16  6:53 ` Bard Liao
2017-02-16  7:15   ` Kai-Heng Feng
2017-02-16 19:22 ` Mark Brown
2017-03-13  8:41   ` Kai-Heng Feng
2017-03-13 13:30     ` Mark Brown
2017-04-18  0:02 Garrett Thornburg

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.