[alsa-devel] [PATCH 1/2] ALSA: hda - Fix ALC283 headphone pop-noise better
From: Kailang Yang kailang@realtek.com
Fixed ALC283 D3 to D0 and D0 to D3 Headphone pop noise. The previous fix [c5177c86: ALSA: hda - Fix the noise after suspend on ALC283 codec] doesn't work sufficiently for some laptops.
Signed-off-by: Kailang Yang kailang@realtek.com Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_realtek.c | 111 +++++++++++++++++++++++++++++------------- 1 file changed, 76 insertions(+), 35 deletions(-)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 7d00639..4bdccd1 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -2527,6 +2527,7 @@ enum { ALC269_TYPE_ALC269VD, ALC269_TYPE_ALC280, ALC269_TYPE_ALC282, + ALC269_TYPE_ALC283, ALC269_TYPE_ALC284, ALC269_TYPE_ALC286, }; @@ -2552,6 +2553,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) case ALC269_TYPE_ALC269VB: case ALC269_TYPE_ALC269VD: case ALC269_TYPE_ALC282: + case ALC269_TYPE_ALC283: case ALC269_TYPE_ALC286: ssids = alc269_ssids; break; @@ -2586,6 +2588,74 @@ static void alc269_shutup(struct hda_codec *codec) snd_hda_shutup_pins(codec); }
+static void alc283_init(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + bool hp_pin_sense; + int val; + + if (!hp_pin) + return; + hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); + + /* Index 0x43 Direct Drive HP AMP LPM Control 1 */ + /* Headphone capless set to high power mode */ + alc_write_coef_idx(codec, 0x43, 0x9004); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + + if (hp_pin_sense) + msleep(85); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); + + if (hp_pin_sense) + msleep(85); + /* Index 0x46 Combo jack auto switch control 2 */ + /* 3k pull low control for Headset jack. */ + val = alc_read_coef_idx(codec, 0x46); + alc_write_coef_idx(codec, 0x46, val & ~(3 << 12)); + /* Headphone capless set to normal mode */ + alc_write_coef_idx(codec, 0x43, 0x9614); +} + +static void alc283_shutup(struct hda_codec *codec) +{ + struct alc_spec *spec = codec->spec; + hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0]; + bool hp_pin_sense; + int val; + + if (!hp_pin) { + alc269_shutup(codec); + return; + } + + hp_pin_sense = snd_hda_jack_detect(codec, hp_pin); + + alc_write_coef_idx(codec, 0x43, 0x9004); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); + + if (hp_pin_sense) + msleep(85); + + snd_hda_codec_write(codec, hp_pin, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0); + + val = alc_read_coef_idx(codec, 0x46); + alc_write_coef_idx(codec, 0x46, val | (3 << 12)); + + if (hp_pin_sense) + msleep(85); + snd_hda_shutup_pins(codec); + alc_write_coef_idx(codec, 0x43, 0x9614); +} + static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg, unsigned int val) { @@ -2715,12 +2785,6 @@ static int alc269_resume(struct hda_codec *codec) if (spec->has_alc5505_dsp) alc5505_dsp_resume(codec);
- /* clear the power-save mode for ALC283 */ - if (codec->vendor_id == 0x10ec0283) { - alc_write_coef_idx(codec, 0x4, 0xaf01); - alc_write_coef_idx(codec, 0x6, 0x2104); - } - return 0; } #endif /* CONFIG_PM */ @@ -3815,30 +3879,6 @@ static void alc269_fill_coef(struct hda_codec *codec) alc_write_coef_idx(codec, 0x4, val | (1<<11)); }
-/* don't clear mic pin; otherwise it results in noise in D3 */ -static void alc283_headset_shutup(struct hda_codec *codec) -{ - int i; - - if (codec->bus->shutdown) - return; - - for (i = 0; i < codec->init_pins.used; i++) { - struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i); - /* use read here for syncing after issuing each verb */ - if (pin->nid != 0x19) - snd_hda_codec_read(codec, pin->nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, 0); - } - - alc_write_coef_idx(codec, 0x4, 0x0f01); /* power save */ - alc_write_coef_idx(codec, 0x6, 0x2100); /* power save */ - snd_hda_codec_write(codec, 0x19, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - PIN_VREFHIZ); - codec->pins_shutup = 1; -} - /* */ static int patch_alc269(struct hda_codec *codec) @@ -3853,9 +3893,6 @@ static int patch_alc269(struct hda_codec *codec) spec = codec->spec; spec->gen.shared_mic_vref_pin = 0x18;
- if (codec->vendor_id == 0x10ec0283) - spec->shutup = alc283_headset_shutup; - snd_hda_pick_fixup(codec, alc269_fixup_models, alc269_fixup_tbl, alc269_fixups); snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); @@ -3897,11 +3934,15 @@ static int patch_alc269(struct hda_codec *codec) case 0x10ec0290: spec->codec_variant = ALC269_TYPE_ALC280; break; - case 0x10ec0233: case 0x10ec0282: - case 0x10ec0283: spec->codec_variant = ALC269_TYPE_ALC282; break; + case 0x10ec0233: + case 0x10ec0283: + spec->codec_variant = ALC269_TYPE_ALC283; + spec->shutup = alc283_shutup; + spec->init_hook = alc283_init; + break; case 0x10ec0284: case 0x10ec0292: spec->codec_variant = ALC269_TYPE_ALC284;
From: Kailang Yang kailang@realtek.com
The headphone automute on this machine triggers annoying pop noises. It seems that only the first DAC can be used, the secondary DAC always results in this problem. This patch disables the secondary DAC with a few additional workarounds.
Signed-off-by: Kailang Yang kailang@realtek.com Signed-off-by: Takashi Iwai tiwai@suse.de --- sound/pci/hda/patch_realtek.c | 45 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4bdccd1..a97dbba 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3394,6 +3394,45 @@ static void alc269_fixup_limit_int_mic_boost(struct hda_codec *codec, } }
+static void alc283_hp_automute_hook(struct hda_codec *codec, + struct hda_jack_tbl *jack) +{ + struct alc_spec *spec = codec->spec; + int vref; + + msleep(200); + snd_hda_gen_hp_automute(codec, jack); + + vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0; + + msleep(600); + snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, + vref); +} + +static void alc283_chromebook_caps(struct hda_codec *codec) +{ + snd_hda_override_wcaps(codec, 0x03, 0); +} + +static void alc283_fixup_chromebook(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + int val; + + switch (action) { + case HDA_FIXUP_ACT_PRE_PROBE: + alc283_chromebook_caps(codec); + spec->gen.hp_automute_hook = alc283_hp_automute_hook; + /* MIC2-VREF control */ + /* Set to manual mode */ + val = alc_read_coef_idx(codec, 0x06); + alc_write_coef_idx(codec, 0x06, val & ~0x000c); + break; + } +} + enum { ALC269_FIXUP_SONY_VAIO, ALC275_FIXUP_SONY_VAIO_GPIO2, @@ -3430,6 +3469,7 @@ enum { ALC269_FIXUP_ACER_AC700, ALC269_FIXUP_LIMIT_INT_MIC_BOOST, ALC269VB_FIXUP_ORDISSIMO_EVE2, + ALC283_FIXUP_CHROME_BOOK, };
static const struct hda_fixup alc269_fixups[] = { @@ -3681,6 +3721,10 @@ static const struct hda_fixup alc269_fixups[] = { { } }, }, + [ALC283_FIXUP_CHROME_BOOK] = { + .type = HDA_FIXUP_FUNC, + .v.func = alc283_fixup_chromebook, + }, };
static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -3729,6 +3773,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED), + SND_PCI_QUIRK(0x103c, 0x21ed, "HP Falco ChromeBook", ALC283_FIXUP_CHROME_BOOK), SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC),
On 08/22/2013 10:21 AM, Takashi Iwai wrote:
From: Kailang Yang kailang@realtek.com
The headphone automute on this machine triggers annoying pop noises. It seems that only the first DAC can be used, the secondary DAC always results in this problem. This patch disables the secondary DAC with a few additional workarounds.
Interesting. I have not heard of any such problems on the ALC283 machines we have been dealing with. But a secondary DAC problem does sound like something codec specific rather than machine specific...
Also a nitpick: It's probably Chromebook, not ChromeBook or Chrome_book.
Signed-off-by: Kailang Yang kailang@realtek.com Signed-off-by: Takashi Iwai tiwai@suse.de
sound/pci/hda/patch_realtek.c | 45 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4bdccd1..a97dbba 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3394,6 +3394,45 @@ static void alc269_fixup_limit_int_mic_boost(struct hda_codec *codec, } }
+static void alc283_hp_automute_hook(struct hda_codec *codec,
struct hda_jack_tbl *jack)
+{
- struct alc_spec *spec = codec->spec;
- int vref;
- msleep(200);
- snd_hda_gen_hp_automute(codec, jack);
- vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0;
- msleep(600);
- snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
vref);
+}
+static void alc283_chromebook_caps(struct hda_codec *codec) +{
- snd_hda_override_wcaps(codec, 0x03, 0);
+}
+static void alc283_fixup_chromebook(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
+{
- struct alc_spec *spec = codec->spec;
- int val;
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
alc283_chromebook_caps(codec);
spec->gen.hp_automute_hook = alc283_hp_automute_hook;
/* MIC2-VREF control */
/* Set to manual mode */
val = alc_read_coef_idx(codec, 0x06);
alc_write_coef_idx(codec, 0x06, val & ~0x000c);
break;
- }
+}
enum { ALC269_FIXUP_SONY_VAIO, ALC275_FIXUP_SONY_VAIO_GPIO2, @@ -3430,6 +3469,7 @@ enum { ALC269_FIXUP_ACER_AC700, ALC269_FIXUP_LIMIT_INT_MIC_BOOST, ALC269VB_FIXUP_ORDISSIMO_EVE2,
- ALC283_FIXUP_CHROME_BOOK,
};
static const struct hda_fixup alc269_fixups[] = { @@ -3681,6 +3721,10 @@ static const struct hda_fixup alc269_fixups[] = { { } }, },
- [ALC283_FIXUP_CHROME_BOOK] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc283_fixup_chromebook,
- },
};
static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -3729,6 +3773,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
- SND_PCI_QUIRK(0x103c, 0x21ed, "HP Falco ChromeBook", ALC283_FIXUP_CHROME_BOOK), SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC),
At Thu, 22 Aug 2013 11:45:57 +0200, David Henningsson wrote:
On 08/22/2013 10:21 AM, Takashi Iwai wrote:
From: Kailang Yang kailang@realtek.com
The headphone automute on this machine triggers annoying pop noises. It seems that only the first DAC can be used, the secondary DAC always results in this problem. This patch disables the secondary DAC with a few additional workarounds.
Interesting. I have not heard of any such problems on the ALC283 machines we have been dealing with. But a secondary DAC problem does sound like something codec specific rather than machine specific...
It's easy to escalate the fixup as codec-generic. But disabling the second DAC reduces the functionality pretty much, so I'd take a safer approach for now.
Also a nitpick: It's probably Chromebook, not ChromeBook or Chrome_book.
Corrected. Also I found that the fixup won't work as is, since it's added after the vendor-generic entry. Fixed that too.
thanks,
Takashi
Signed-off-by: Kailang Yang kailang@realtek.com Signed-off-by: Takashi Iwai tiwai@suse.de
sound/pci/hda/patch_realtek.c | 45 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4bdccd1..a97dbba 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -3394,6 +3394,45 @@ static void alc269_fixup_limit_int_mic_boost(struct hda_codec *codec, } }
+static void alc283_hp_automute_hook(struct hda_codec *codec,
struct hda_jack_tbl *jack)
+{
- struct alc_spec *spec = codec->spec;
- int vref;
- msleep(200);
- snd_hda_gen_hp_automute(codec, jack);
- vref = spec->gen.hp_jack_present ? PIN_VREF80 : 0;
- msleep(600);
- snd_hda_codec_write(codec, 0x19, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
vref);
+}
+static void alc283_chromebook_caps(struct hda_codec *codec) +{
- snd_hda_override_wcaps(codec, 0x03, 0);
+}
+static void alc283_fixup_chromebook(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
+{
- struct alc_spec *spec = codec->spec;
- int val;
- switch (action) {
- case HDA_FIXUP_ACT_PRE_PROBE:
alc283_chromebook_caps(codec);
spec->gen.hp_automute_hook = alc283_hp_automute_hook;
/* MIC2-VREF control */
/* Set to manual mode */
val = alc_read_coef_idx(codec, 0x06);
alc_write_coef_idx(codec, 0x06, val & ~0x000c);
break;
- }
+}
enum { ALC269_FIXUP_SONY_VAIO, ALC275_FIXUP_SONY_VAIO_GPIO2, @@ -3430,6 +3469,7 @@ enum { ALC269_FIXUP_ACER_AC700, ALC269_FIXUP_LIMIT_INT_MIC_BOOST, ALC269VB_FIXUP_ORDISSIMO_EVE2,
- ALC283_FIXUP_CHROME_BOOK,
};
static const struct hda_fixup alc269_fixups[] = { @@ -3681,6 +3721,10 @@ static const struct hda_fixup alc269_fixups[] = { { } }, },
- [ALC283_FIXUP_CHROME_BOOK] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc283_fixup_chromebook,
- },
};
static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -3729,6 +3773,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x1973, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1), SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
- SND_PCI_QUIRK(0x103c, 0x21ed, "HP Falco ChromeBook", ALC283_FIXUP_CHROME_BOOK), SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST), SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC),
-- David Henningsson, Canonical Ltd. https://launchpad.net/~diwic
participants (2)
-
David Henningsson
-
Takashi Iwai