All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/10] Realtek auto-parser updates
@ 2011-04-29 17:18 Takashi Iwai
  2011-04-29 17:18 ` [PATCH 01/10] ALSA: hda - Minor update for alc662-parser functions Takashi Iwai
                   ` (10 more replies)
  0 siblings, 11 replies; 24+ messages in thread
From: Takashi Iwai @ 2011-04-29 17:18 UTC (permalink / raw)
  To: alsa-devel

Hi, this is a series of patches I'm going to apply as 2.6.40 material.
Basically this adds the missing features to BIOS auto-parser mode, the
support of multi-channel setup (2/4/6-channels) and the auto-mute of
line-out jacks as well as speakers.

Many changes have been done but mostly in systematic manner.
I've checked through hda-emu and a few machines with Realtek codecs,
but of course can't cover all changes I made.

If you see any issues with the updated tree, please let me know.


thanks,

Takashi

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

* [PATCH 01/10] ALSA: hda - Minor update for alc662-parser functions
  2011-04-29 17:18 [PATCH 0/10] Realtek auto-parser updates Takashi Iwai
@ 2011-04-29 17:18 ` Takashi Iwai
  2011-04-29 17:18 ` [PATCH 02/10] ALSA: hda - Add channel-mode support to Realtek auto-parser Takashi Iwai
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Takashi Iwai @ 2011-04-29 17:18 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai

Allow alc662_dac_to_mix() and alc662_look_for_dac() to parse
down the selector widget that is found in ALC880-type codecs,
and rename them to alc_auto_*() accordingly.
This is for the next coming multi-io extensions.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c |   38 +++++++++++++++++++++++++-------------
 1 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index e631874..0ed95dd 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -19135,9 +19135,9 @@ static struct alc_config_preset alc662_presets[] = {
  */
 
 /* convert from MIX nid to DAC */
-static hda_nid_t alc662_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
+static hda_nid_t alc_auto_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
 {
-	hda_nid_t list[4];
+	hda_nid_t list[5];
 	int i, num;
 
 	num = snd_hda_get_connections(codec, nid, list, ARRAY_SIZE(list));
@@ -19148,33 +19148,45 @@ static hda_nid_t alc662_mix_to_dac(struct hda_codec *codec, hda_nid_t nid)
 	return 0;
 }
 
+/* go down to the selector widget before the mixer */
+static hda_nid_t alc_go_down_to_selector(struct hda_codec *codec, hda_nid_t pin)
+{
+	hda_nid_t srcs[5];
+	int num = snd_hda_get_connections(codec, pin, srcs,
+					  ARRAY_SIZE(srcs));
+	if (num != 1 ||
+	    get_wcaps_type(get_wcaps(codec, srcs[0])) != AC_WID_AUD_SEL)
+		return pin;
+	return srcs[0];
+}
+
 /* get MIX nid connected to the given pin targeted to DAC */
-static hda_nid_t alc662_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
+static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
 				   hda_nid_t dac)
 {
 	hda_nid_t mix[5];
 	int i, num;
 
+	pin = alc_go_down_to_selector(codec, pin);
 	num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
 	for (i = 0; i < num; i++) {
-		if (alc662_mix_to_dac(codec, mix[i]) == dac)
+		if (alc_auto_mix_to_dac(codec, mix[i]) == dac)
 			return mix[i];
 	}
 	return 0;
 }
 
 /* look for an empty DAC slot */
-static hda_nid_t alc662_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
+static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
 {
 	struct alc_spec *spec = codec->spec;
 	hda_nid_t srcs[5];
 	int i, j, num;
 
+	pin = alc_go_down_to_selector(codec, pin);
 	num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
-	if (num < 0)
-		return 0;
 	for (i = 0; i < num; i++) {
-		hda_nid_t nid = alc662_mix_to_dac(codec, srcs[i]);
+		hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
 		if (!nid)
 			continue;
 		for (j = 0; j < spec->multiout.num_dacs; j++)
@@ -19196,7 +19208,7 @@ static int alc662_auto_fill_dac_nids(struct hda_codec *codec,
 
 	spec->multiout.dac_nids = spec->private_dac_nids;
 	for (i = 0; i < cfg->line_outs; i++) {
-		dac = alc662_look_for_dac(codec, cfg->line_out_pins[i]);
+		dac = alc_auto_look_for_dac(codec, cfg->line_out_pins[i]);
 		if (!dac)
 			continue;
 		spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
@@ -19243,7 +19255,7 @@ static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec,
 		nid = spec->multiout.dac_nids[i];
 		if (!nid)
 			continue;
-		mix = alc662_dac_to_mix(codec, cfg->line_out_pins[i], nid);
+		mix = alc_auto_dac_to_mix(codec, cfg->line_out_pins[i], nid);
 		if (!mix)
 			continue;
 		if (!pfx && i == 2) {
@@ -19289,7 +19301,7 @@ static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
 
 	if (!pin)
 		return 0;
-	nid = alc662_look_for_dac(codec, pin);
+	nid = alc_auto_look_for_dac(codec, pin);
 	if (!nid) {
 		/* the corresponding DAC is already occupied */
 		if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
@@ -19299,7 +19311,7 @@ static int alc662_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
 				   HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
 	}
 
-	mix = alc662_dac_to_mix(codec, pin, nid);
+	mix = alc_auto_dac_to_mix(codec, pin, nid);
 	if (!mix)
 		return 0;
 	err = alc662_add_vol_ctl(spec, pfx, nid, 3);
@@ -19325,7 +19337,7 @@ static void alc662_auto_set_output_and_unmute(struct hda_codec *codec,
 	alc_set_pin_output(codec, nid, pin_type);
 	num = snd_hda_get_connections(codec, nid, srcs, ARRAY_SIZE(srcs));
 	for (i = 0; i < num; i++) {
-		if (alc662_mix_to_dac(codec, srcs[i]) != dac)
+		if (alc_auto_mix_to_dac(codec, srcs[i]) != dac)
 			continue;
 		/* need the manual connection? */
 		if (num > 1)
-- 
1.7.4.2

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

* [PATCH 02/10] ALSA: hda - Add channel-mode support to Realtek auto-parser
  2011-04-29 17:18 [PATCH 0/10] Realtek auto-parser updates Takashi Iwai
  2011-04-29 17:18 ` [PATCH 01/10] ALSA: hda - Minor update for alc662-parser functions Takashi Iwai
@ 2011-04-29 17:18 ` Takashi Iwai
       [not found]   ` <BANLkTim4sF9_66O-cb7+THZBC-fbxWbe6Q@mail.gmail.com>
  2011-04-29 17:18 ` [PATCH 03/10] ALSA: hda - Consolidate default automute functions for Realtek Takashi Iwai
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 24+ messages in thread
From: Takashi Iwai @ 2011-04-29 17:18 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai

This patch adds the support of "Channel Mode" enum control to Realtek
auto-parser.  When line-in or mic-in jacks are capable to output and
free DACs are available, the driver allows to switch to multi-channel
mode via "Channel Mode" enum switch, as already implemented in some
preset cases.

Not implemented in all Realtek codecs.  Currently, ALC880, 882, 861,
662 and the compatible codecs are supported.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c |  269 ++++++++++++++++++++++++++++++++++++++---
 1 files changed, 249 insertions(+), 20 deletions(-)

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 0ed95dd..4c4d51a2 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -299,6 +299,12 @@ struct alc_customize_define {
 
 struct alc_fixup;
 
+struct alc_multi_io {
+	hda_nid_t pin;		/* multi-io widget pin NID */
+	hda_nid_t dac;		/* DAC to be connected */
+	unsigned int ctl_in;	/* cached input-pin control value */
+};
+
 struct alc_spec {
 	/* codec parameterization */
 	struct snd_kcontrol_new *mixers[5];	/* mixer arrays */
@@ -404,6 +410,10 @@ struct alc_spec {
 	int fixup_id;
 	const struct alc_fixup *fixup_list;
 	const char *fixup_name;
+
+	/* multi-io */
+	int multi_ios;
+	struct alc_multi_io multi_io[4];
 };
 
 /*
@@ -4992,14 +5002,19 @@ static struct snd_kcontrol_new alc880_control_templates[] = {
 	HDA_BIND_MUTE(NULL, 0, 0, 0),
 };
 
+static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec)
+{
+	snd_array_init(&spec->kctls, sizeof(struct snd_kcontrol_new), 32);
+	return snd_array_new(&spec->kctls);
+}
+
 /* add dynamic controls */
 static int add_control(struct alc_spec *spec, int type, const char *name,
 		       int cidx, unsigned long val)
 {
 	struct snd_kcontrol_new *knew;
 
-	snd_array_init(&spec->kctls, sizeof(*knew), 32);
-	knew = snd_array_new(&spec->kctls);
+	knew = alc_kcontrol_new(spec);
 	if (!knew)
 		return -ENOMEM;
 	*knew = alc880_control_templates[type];
@@ -5080,10 +5095,13 @@ static int alc880_auto_fill_dac_nids(struct alc_spec *spec,
 	return 0;
 }
 
-static const char *alc_get_line_out_pfx(const struct auto_pin_cfg *cfg,
+static const char *alc_get_line_out_pfx(struct alc_spec *spec,
 					bool can_be_master)
 {
-	if (!cfg->hp_outs && !cfg->speaker_outs && can_be_master)
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+
+	if (cfg->line_outs == 1 && !spec->multi_ios &&
+	    !cfg->hp_outs && !cfg->speaker_outs && can_be_master)
 		return "Master";
 
 	switch (cfg->line_out_type) {
@@ -5094,7 +5112,7 @@ static const char *alc_get_line_out_pfx(const struct auto_pin_cfg *cfg,
 	case AUTO_PIN_HP_OUT:
 		return "Headphone";
 	default:
-		if (cfg->line_outs == 1)
+		if (cfg->line_outs == 1 && !spec->multi_ios)
 			return "PCM";
 		break;
 	}
@@ -5108,11 +5126,15 @@ static int alc880_auto_create_multi_out_ctls(struct alc_spec *spec,
 	static const char * const chname[4] = {
 		"Front", "Surround", NULL /*CLFE*/, "Side"
 	};
-	const char *pfx = alc_get_line_out_pfx(cfg, false);
+	const char *pfx = alc_get_line_out_pfx(spec, false);
 	hda_nid_t nid;
-	int i, err;
+	int i, err, noutputs;
 
-	for (i = 0; i < cfg->line_outs; i++) {
+	noutputs = cfg->line_outs;
+	if (spec->multi_ios > 0)
+		noutputs += spec->multi_ios;
+
+	for (i = 0; i < noutputs; i++) {
 		if (!spec->multiout.dac_nids[i])
 			continue;
 		nid = alc880_idx_to_mixer(alc880_dac_to_idx(spec->multiout.dac_nids[i]));
@@ -5378,6 +5400,8 @@ static void alc880_auto_init_input_src(struct hda_codec *codec)
 	}
 }
 
+static int alc_auto_add_multi_channel_mode(struct hda_codec *codec);
+
 /* parse the BIOS configuration and set up the alc_spec */
 /* return 1 if successful, 0 if the proper config is not found,
  * or a negative error code
@@ -5398,6 +5422,9 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
 	err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
 	if (err < 0)
 		return err;
+	err = alc_auto_add_multi_channel_mode(codec);
+	if (err < 0)
+		return err;
 	err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
 	if (err < 0)
 		return err;
@@ -10949,6 +10976,9 @@ static int alc882_parse_auto_config(struct hda_codec *codec)
 	err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
 	if (err < 0)
 		return err;
+	err = alc_auto_add_multi_channel_mode(codec);
+	if (err < 0)
+		return err;
 	err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);
 	if (err < 0)
 		return err;
@@ -12165,7 +12195,7 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec,
 	spec->multiout.dac_nids = spec->private_dac_nids;
 	spec->multiout.dac_nids[0] = 2;
 
-	pfx = alc_get_line_out_pfx(cfg, true);
+	pfx = alc_get_line_out_pfx(spec, true);
 	if (!pfx)
 		pfx = "Front";
 	for (i = 0; i < 2; i++) {
@@ -16020,11 +16050,15 @@ static int alc861_auto_create_multi_out_ctls(struct hda_codec *codec,
 	static const char * const chname[4] = {
 		"Front", "Surround", NULL /*CLFE*/, "Side"
 	};
-	const char *pfx = alc_get_line_out_pfx(cfg, true);
+	const char *pfx = alc_get_line_out_pfx(spec, true);
 	hda_nid_t nid;
-	int i, err;
+	int i, err, noutputs;
 
-	for (i = 0; i < cfg->line_outs; i++) {
+	noutputs = cfg->line_outs;
+	if (spec->multi_ios > 0)
+		noutputs += spec->multi_ios;
+
+	for (i = 0; i < noutputs; i++) {
 		nid = spec->multiout.dac_nids[i];
 		if (!nid)
 			continue;
@@ -16169,6 +16203,9 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
 	err = alc861_auto_fill_dac_nids(codec, &spec->autocfg);
 	if (err < 0)
 		return err;
+	err = alc_auto_add_multi_channel_mode(codec);
+	if (err < 0)
+		return err;
 	err = alc861_auto_create_multi_out_ctls(codec, &spec->autocfg);
 	if (err < 0)
 		return err;
@@ -17152,11 +17189,15 @@ static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
 	static const char * const chname[4] = {
 		"Front", "Surround", "CLFE", "Side"
 	};
-	const char *pfx = alc_get_line_out_pfx(cfg, true);
+	const char *pfx = alc_get_line_out_pfx(spec, true);
 	hda_nid_t nid_v, nid_s;
-	int i, err;
+	int i, err, noutputs;
 
-	for (i = 0; i < cfg->line_outs; i++) {
+	noutputs = cfg->line_outs;
+	if (spec->multi_ios > 0)
+		noutputs += spec->multi_ios;
+
+	for (i = 0; i < noutputs; i++) {
 		if (!spec->multiout.dac_nids[i])
 			continue;
 		nid_v = alc861vd_idx_to_mixer_vol(
@@ -17281,6 +17322,9 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
 	err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);
 	if (err < 0)
 		return err;
+	err = alc_auto_add_multi_channel_mode(codec);
+	if (err < 0)
+		return err;
 	err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg);
 	if (err < 0)
 		return err;
@@ -19176,6 +19220,27 @@ static hda_nid_t alc_auto_dac_to_mix(struct hda_codec *codec, hda_nid_t pin,
 	return 0;
 }
 
+/* select the connection from pin to DAC if needed */
+static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
+			       hda_nid_t dac)
+{
+	hda_nid_t mix[5];
+	int i, num;
+
+	pin = alc_go_down_to_selector(codec, pin);
+	num = snd_hda_get_connections(codec, pin, mix, ARRAY_SIZE(mix));
+	if (num < 2)
+		return 0;
+	for (i = 0; i < num; i++) {
+		if (alc_auto_mix_to_dac(codec, mix[i]) == dac) {
+			snd_hda_codec_update_cache(codec, pin, 0,
+						   AC_VERB_SET_CONNECT_SEL, i);
+			return 0;
+		}
+	}
+	return 0;
+}
+
 /* look for an empty DAC slot */
 static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
 {
@@ -19247,15 +19312,23 @@ static int alc662_auto_create_multi_out_ctls(struct hda_codec *codec,
 	static const char * const chname[4] = {
 		"Front", "Surround", NULL /*CLFE*/, "Side"
 	};
-	const char *pfx = alc_get_line_out_pfx(cfg, true);
-	hda_nid_t nid, mix;
-	int i, err;
+	const char *pfx = alc_get_line_out_pfx(spec, true);
+	hda_nid_t nid, mix, pin;
+	int i, err, noutputs;
 
-	for (i = 0; i < cfg->line_outs; i++) {
+	noutputs = cfg->line_outs;
+	if (spec->multi_ios > 0)
+		noutputs += spec->multi_ios;
+
+	for (i = 0; i < noutputs; i++) {
 		nid = spec->multiout.dac_nids[i];
 		if (!nid)
 			continue;
-		mix = alc_auto_dac_to_mix(codec, cfg->line_out_pins[i], nid);
+		if (i >= cfg->line_outs)
+			pin = spec->multi_io[i - 1].pin;
+		else
+			pin = cfg->line_out_pins[i];
+		mix = alc_auto_dac_to_mix(codec, pin, nid);
 		if (!mix)
 			continue;
 		if (!pfx && i == 2) {
@@ -19406,6 +19479,159 @@ static void alc662_auto_init_analog_input(struct hda_codec *codec)
 
 #define alc662_auto_init_input_src	alc882_auto_init_input_src
 
+/*
+ * multi-io helper
+ */
+static int alc_auto_fill_multi_ios(struct hda_codec *codec,
+				   unsigned int location)
+{
+	struct alc_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	int type, i, num_pins = 0;
+
+	for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
+		for (i = 0; i < cfg->num_inputs; i++) {
+			hda_nid_t nid = cfg->inputs[i].pin;
+			hda_nid_t dac;
+			unsigned int defcfg, caps;
+			if (cfg->inputs[i].type != type)
+				continue;
+			defcfg = snd_hda_codec_get_pincfg(codec, nid);
+			if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
+				continue;
+			if (location && get_defcfg_location(defcfg) != location)
+				continue;
+			caps = snd_hda_query_pin_caps(codec, nid);
+			if (!(caps & AC_PINCAP_OUT))
+				continue;
+			dac = alc_auto_look_for_dac(codec, nid);
+			if (!dac)
+				continue;
+			spec->multi_io[num_pins].pin = nid;
+			spec->multi_io[num_pins].dac = dac;
+			num_pins++;
+			spec->multiout.dac_nids[spec->multiout.num_dacs++] = dac;
+		}
+	}
+	spec->multiout.num_dacs = 1;
+	if (num_pins < 2)
+		return 0;
+	return num_pins;
+}
+
+static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_info *uinfo)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = spec->multi_ios + 1;
+	if (uinfo->value.enumerated.item > spec->multi_ios)
+		uinfo->value.enumerated.item = spec->multi_ios;
+	sprintf(uinfo->value.enumerated.name, "%dch",
+		(uinfo->value.enumerated.item + 1) * 2);
+	return 0;
+}
+
+static int alc_auto_ch_mode_get(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	ucontrol->value.enumerated.item[0] = (spec->ext_channel_count - 1) / 2;
+	return 0;
+}
+
+static int alc_set_multi_io(struct hda_codec *codec, int idx, bool output)
+{
+	struct alc_spec *spec = codec->spec;
+	hda_nid_t nid = spec->multi_io[idx].pin;
+
+	if (!spec->multi_io[idx].ctl_in)
+		spec->multi_io[idx].ctl_in =
+			snd_hda_codec_read(codec, nid, 0,
+					   AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+	if (output) {
+		snd_hda_codec_update_cache(codec, nid, 0,
+					   AC_VERB_SET_PIN_WIDGET_CONTROL,
+					   PIN_OUT);
+		if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
+			snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+						 HDA_AMP_MUTE, 0);
+		alc_auto_select_dac(codec, nid, spec->multi_io[idx].dac);
+	} else {
+		if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
+			snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
+						 HDA_AMP_MUTE, HDA_AMP_MUTE);
+		snd_hda_codec_update_cache(codec, nid, 0,
+					   AC_VERB_SET_PIN_WIDGET_CONTROL,
+					   spec->multi_io[idx].ctl_in);
+	}
+	return 0;
+}
+
+static int alc_auto_ch_mode_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	int i, ch;
+
+	ch = ucontrol->value.enumerated.item[0];
+	if (ch < 0 || ch > spec->multi_ios)
+		return -EINVAL;
+	if (ch == (spec->ext_channel_count - 1) / 2)
+		return 0;
+	spec->ext_channel_count = (ch + 1) * 2;
+	for (i = 0; i < spec->multi_ios; i++)
+		alc_set_multi_io(codec, i, i < ch);
+	spec->multiout.max_channels = spec->ext_channel_count;
+	return 1;
+}
+
+static struct snd_kcontrol_new alc_auto_channel_mode_enum = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Channel Mode",
+	.info = alc_auto_ch_mode_info,
+	.get = alc_auto_ch_mode_get,
+	.put = alc_auto_ch_mode_put,
+};
+
+static int alc_auto_add_multi_channel_mode(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	struct auto_pin_cfg *cfg = &spec->autocfg;
+	unsigned int location, defcfg;
+	int num_pins;
+
+	if (cfg->line_outs != 1 ||
+	    cfg->line_out_type != AUTO_PIN_LINE_OUT)
+		return 0;
+
+	defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
+	location = get_defcfg_location(defcfg);
+
+	num_pins = alc_auto_fill_multi_ios(codec, location);
+	if (num_pins > 0) {
+		struct snd_kcontrol_new *knew;
+
+		knew = alc_kcontrol_new(spec);
+		if (!knew)
+			return -ENOMEM;
+		*knew = alc_auto_channel_mode_enum;
+		knew->name = kstrdup("Channel Mode", GFP_KERNEL);
+		if (!knew->name)
+			return -ENOMEM;
+
+		spec->multi_ios = num_pins;
+		spec->ext_channel_count = 2;
+		spec->multiout.num_dacs = num_pins + 1;
+	}
+	return 0;
+}
+
 static int alc662_parse_auto_config(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
@@ -19422,6 +19648,9 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
 	err = alc662_auto_fill_dac_nids(codec, &spec->autocfg);
 	if (err < 0)
 		return err;
+	err = alc_auto_add_multi_channel_mode(codec);
+	if (err < 0)
+		return err;
 	err = alc662_auto_create_multi_out_ctls(codec, &spec->autocfg);
 	if (err < 0)
 		return err;
-- 
1.7.4.2

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

* [PATCH 03/10] ALSA: hda - Consolidate default automute functions for Realtek
  2011-04-29 17:18 [PATCH 0/10] Realtek auto-parser updates Takashi Iwai
  2011-04-29 17:18 ` [PATCH 01/10] ALSA: hda - Minor update for alc662-parser functions Takashi Iwai
  2011-04-29 17:18 ` [PATCH 02/10] ALSA: hda - Add channel-mode support to Realtek auto-parser Takashi Iwai
@ 2011-04-29 17:18 ` Takashi Iwai
  2011-04-29 17:18 ` [PATCH 04/10] ALSA: hda - Add common automute support for mxier-amp on/off for Reatek Takashi Iwai
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Takashi Iwai @ 2011-04-29 17:18 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai

There are two entry points for the headphone automute functions for
Realtek, alc_automute_amp() and alc_automute_pin().  These call the
same function in the end, so we can basically consolidate these
with a flag in spec.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c |  260 ++++++++++++++++++++++++++---------------
 1 files changed, 163 insertions(+), 97 deletions(-)

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 4c4d51a2..5715b6f 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -305,6 +305,11 @@ struct alc_multi_io {
 	unsigned int ctl_in;	/* cached input-pin control value */
 };
 
+enum {
+	ALC_AUTOMUTE_PIN,
+	ALC_AUTOMUTE_AMP,
+};
+
 struct alc_spec {
 	/* codec parameterization */
 	struct snd_kcontrol_new *mixers[5];	/* mixer arrays */
@@ -388,11 +393,16 @@ struct alc_spec {
 	unsigned int jack_present: 1;
 	unsigned int master_sw: 1;
 	unsigned int auto_mic:1;
+	unsigned int automute:1;	/* HP automute enabled */
 
 	/* other flags */
 	unsigned int no_analog :1; /* digital I/O only */
 	unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */
 	unsigned int single_input_src:1;
+
+	/* auto-mute control */
+	int automute_mode;
+
 	int init_amp;
 	int codec_variant;	/* flag for other variants */
 
@@ -1062,13 +1072,16 @@ static int alc_init_jacks(struct hda_codec *codec)
 	return 0;
 }
 
-static void alc_automute_speaker(struct hda_codec *codec, int pinctl)
+static void alc_hp_automute(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
 	unsigned int mute;
 	hda_nid_t nid;
 	int i;
 
+	if (!spec->automute)
+		return;
+
 	spec->jack_present = 0;
 	for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
 		nid = spec->autocfg.hp_pins[i];
@@ -1084,7 +1097,7 @@ static void alc_automute_speaker(struct hda_codec *codec, int pinctl)
 		nid = spec->autocfg.speaker_pins[i];
 		if (!nid)
 			break;
-		if (pinctl) {
+		if (spec->automute_mode == ALC_AUTOMUTE_PIN) {
 			snd_hda_codec_write(codec, nid, 0,
 				    AC_VERB_SET_PIN_WIDGET_CONTROL,
 				    spec->jack_present ? 0 : PIN_OUT);
@@ -1095,11 +1108,6 @@ static void alc_automute_speaker(struct hda_codec *codec, int pinctl)
 	}
 }
 
-static void alc_automute_pin(struct hda_codec *codec)
-{
-	alc_automute_speaker(codec, 1);
-}
-
 static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
 				hda_nid_t nid)
 {
@@ -1195,7 +1203,7 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
 		res >>= 26;
 	switch (res) {
 	case ALC880_HP_EVENT:
-		alc_automute_pin(codec);
+		alc_hp_automute(codec);
 		break;
 	case ALC880_MIC_EVENT:
 		alc_mic_automute(codec);
@@ -1205,7 +1213,7 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
 
 static void alc_inithook(struct hda_codec *codec)
 {
-	alc_automute_pin(codec);
+	alc_hp_automute(codec);
 	alc_mic_automute(codec);
 }
 
@@ -1374,6 +1382,8 @@ static void alc_init_auto_hp(struct hda_codec *codec)
 		snd_hda_codec_write_cache(codec, cfg->hp_pins[i], 0,
 				  AC_VERB_SET_UNSOLICITED_ENABLE,
 				  AC_USRSP_EN | ALC880_HP_EVENT);
+		spec->automute = 1;
+		spec->automute_mode = ALC_AUTOMUTE_PIN;
 	}
 	spec->unsol_event = alc_sku_unsol_event;
 }
@@ -1971,22 +1981,6 @@ static struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
 	{}
 };
 
-static void alc_automute_amp(struct hda_codec *codec)
-{
-	alc_automute_speaker(codec, 0);
-}
-
-static void alc_automute_amp_unsol_event(struct hda_codec *codec,
-					 unsigned int res)
-{
-	if (codec->vendor_id == 0x10ec0880)
-		res >>= 28;
-	else
-		res >>= 26;
-	if (res == ALC880_HP_EVENT)
-		alc_automute_amp(codec);
-}
-
 static void alc889_automute_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
@@ -1997,12 +1991,14 @@ static void alc889_automute_setup(struct hda_codec *codec)
 	spec->autocfg.speaker_pins[2] = 0x17;
 	spec->autocfg.speaker_pins[3] = 0x19;
 	spec->autocfg.speaker_pins[4] = 0x1a;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc889_intel_init_hook(struct hda_codec *codec)
 {
 	alc889_coef_init(codec);
-	alc_automute_amp(codec);
+	alc_hp_automute(codec);
 }
 
 static void alc888_fujitsu_xa3530_setup(struct hda_codec *codec)
@@ -2013,6 +2009,8 @@ static void alc888_fujitsu_xa3530_setup(struct hda_codec *codec)
 	spec->autocfg.hp_pins[1] = 0x1b; /* hp */
 	spec->autocfg.speaker_pins[0] = 0x14; /* speaker */
 	spec->autocfg.speaker_pins[1] = 0x15; /* bass */
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 /*
@@ -2295,6 +2293,8 @@ static void alc888_acer_aspire_4930g_setup(struct hda_codec *codec)
 	spec->autocfg.speaker_pins[0] = 0x14;
 	spec->autocfg.speaker_pins[1] = 0x16;
 	spec->autocfg.speaker_pins[2] = 0x17;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
@@ -2305,6 +2305,8 @@ static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
 	spec->autocfg.speaker_pins[0] = 0x14;
 	spec->autocfg.speaker_pins[1] = 0x16;
 	spec->autocfg.speaker_pins[2] = 0x17;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc888_acer_aspire_7730g_setup(struct hda_codec *codec)
@@ -2315,6 +2317,8 @@ static void alc888_acer_aspire_7730g_setup(struct hda_codec *codec)
 	spec->autocfg.speaker_pins[0] = 0x14;
 	spec->autocfg.speaker_pins[1] = 0x16;
 	spec->autocfg.speaker_pins[2] = 0x17;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
@@ -2325,6 +2329,8 @@ static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
 	spec->autocfg.speaker_pins[0] = 0x14;
 	spec->autocfg.speaker_pins[1] = 0x16;
 	spec->autocfg.speaker_pins[2] = 0x1b;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 /*
@@ -3400,11 +3406,13 @@ static void alc880_uniwill_setup(struct hda_codec *codec)
 	spec->autocfg.hp_pins[0] = 0x14;
 	spec->autocfg.speaker_pins[0] = 0x15;
 	spec->autocfg.speaker_pins[0] = 0x16;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc880_uniwill_init_hook(struct hda_codec *codec)
 {
-	alc_automute_amp(codec);
+	alc_hp_automute(codec);
 	alc88x_simple_mic_automute(codec);
 }
 
@@ -3419,7 +3427,7 @@ static void alc880_uniwill_unsol_event(struct hda_codec *codec,
 		alc88x_simple_mic_automute(codec);
 		break;
 	default:
-		alc_automute_amp_unsol_event(codec, res);
+		alc_sku_unsol_event(codec, res);
 		break;
 	}
 }
@@ -3430,6 +3438,8 @@ static void alc880_uniwill_p53_setup(struct hda_codec *codec)
 
 	spec->autocfg.hp_pins[0] = 0x14;
 	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
@@ -3454,7 +3464,7 @@ static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
 	if ((res >> 28) == ALC880_DCVOL_EVENT)
 		alc880_uniwill_p53_dcvol_automute(codec);
 	else
-		alc_automute_amp_unsol_event(codec, res);
+		alc_sku_unsol_event(codec, res);
 }
 
 /*
@@ -3698,6 +3708,8 @@ static void alc880_lg_setup(struct hda_codec *codec)
 
 	spec->autocfg.hp_pins[0] = 0x1b;
 	spec->autocfg.speaker_pins[0] = 0x17;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 /*
@@ -3782,6 +3794,8 @@ static void alc880_lg_lw_setup(struct hda_codec *codec)
 
 	spec->autocfg.hp_pins[0] = 0x1b;
 	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static struct snd_kcontrol_new alc880_medion_rim_mixer[] = {
@@ -3829,7 +3843,7 @@ static struct hda_verb alc880_medion_rim_init_verbs[] = {
 static void alc880_medion_rim_automute(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
-	alc_automute_amp(codec);
+	alc_hp_automute(codec);
 	/* toggle EAPD */
 	if (spec->jack_present)
 		snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
@@ -3853,6 +3867,8 @@ static void alc880_medion_rim_setup(struct hda_codec *codec)
 
 	spec->autocfg.hp_pins[0] = 0x14;
 	spec->autocfg.speaker_pins[0] = 0x1b;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -4806,7 +4822,7 @@ static struct alc_config_preset alc880_presets[] = {
 		.input_mux = &alc880_f1734_capture_source,
 		.unsol_event = alc880_uniwill_p53_unsol_event,
 		.setup = alc880_uniwill_p53_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC880_ASUS] = {
 		.mixers = { alc880_asus_mixer },
@@ -4897,7 +4913,7 @@ static struct alc_config_preset alc880_presets[] = {
 		.input_mux = &alc880_capture_source,
 		.unsol_event = alc880_uniwill_p53_unsol_event,
 		.setup = alc880_uniwill_p53_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC880_FUJITSU] = {
 		.mixers = { alc880_fujitsu_mixer },
@@ -4912,7 +4928,7 @@ static struct alc_config_preset alc880_presets[] = {
 		.input_mux = &alc880_capture_source,
 		.unsol_event = alc880_uniwill_p53_unsol_event,
 		.setup = alc880_uniwill_p53_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC880_CLEVO] = {
 		.mixers = { alc880_three_stack_mixer },
@@ -4937,9 +4953,9 @@ static struct alc_config_preset alc880_presets[] = {
 		.channel_mode = alc880_lg_ch_modes,
 		.need_dac_fix = 1,
 		.input_mux = &alc880_lg_capture_source,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc880_lg_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 		.loopbacks = alc880_lg_loopbacks,
 #endif
@@ -4954,9 +4970,9 @@ static struct alc_config_preset alc880_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc880_lg_lw_modes),
 		.channel_mode = alc880_lg_lw_modes,
 		.input_mux = &alc880_lg_lw_capture_source,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc880_lg_lw_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC880_MEDION_RIM] = {
 		.mixers = { alc880_medion_rim_mixer },
@@ -8629,6 +8645,8 @@ static void alc885_imac24_setup(struct hda_codec *codec)
 	spec->autocfg.hp_pins[0] = 0x14;
 	spec->autocfg.speaker_pins[0] = 0x18;
 	spec->autocfg.speaker_pins[1] = 0x1a;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 #define alc885_mb5_setup	alc885_imac24_setup
@@ -8641,6 +8659,8 @@ static void alc885_mba21_setup(struct hda_codec *codec)
 
        spec->autocfg.hp_pins[0] = 0x14;
        spec->autocfg.speaker_pins[0] = 0x18;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 
@@ -8651,6 +8671,8 @@ static void alc885_mbp3_setup(struct hda_codec *codec)
 
 	spec->autocfg.hp_pins[0] = 0x15;
 	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc885_imac91_setup(struct hda_codec *codec)
@@ -8660,6 +8682,8 @@ static void alc885_imac91_setup(struct hda_codec *codec)
 	spec->autocfg.hp_pins[0] = 0x14;
 	spec->autocfg.speaker_pins[0] = 0x18;
 	spec->autocfg.speaker_pins[1] = 0x1a;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static struct hda_verb alc882_targa_verbs[] = {
@@ -8681,7 +8705,7 @@ static struct hda_verb alc882_targa_verbs[] = {
 static void alc882_targa_automute(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
-	alc_automute_amp(codec);
+	alc_hp_automute(codec);
 	snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
 				  spec->jack_present ? 1 : 3);
 }
@@ -8692,6 +8716,8 @@ static void alc882_targa_setup(struct hda_codec *codec)
 
 	spec->autocfg.hp_pins[0] = 0x14;
 	spec->autocfg.speaker_pins[0] = 0x1b;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
@@ -8779,7 +8805,7 @@ static void alc885_macpro_init_hook(struct hda_codec *codec)
 static void alc885_imac24_init_hook(struct hda_codec *codec)
 {
 	alc885_macpro_init_hook(codec);
-	alc_automute_amp(codec);
+	alc_hp_automute(codec);
 }
 
 /*
@@ -9137,6 +9163,8 @@ static void alc883_medion_wim2160_setup(struct hda_codec *codec)
 
 	spec->autocfg.hp_pins[0] = 0x1a;
 	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
@@ -9289,6 +9317,8 @@ static void alc883_mitac_setup(struct hda_codec *codec)
 	spec->autocfg.hp_pins[0] = 0x15;
 	spec->autocfg.speaker_pins[0] = 0x14;
 	spec->autocfg.speaker_pins[1] = 0x17;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static struct hda_verb alc883_mitac_verbs[] = {
@@ -9453,6 +9483,8 @@ static void alc888_3st_hp_setup(struct hda_codec *codec)
 	spec->autocfg.speaker_pins[0] = 0x14;
 	spec->autocfg.speaker_pins[1] = 0x16;
 	spec->autocfg.speaker_pins[2] = 0x18;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static struct hda_verb alc888_3st_hp_verbs[] = {
@@ -9541,6 +9573,8 @@ static void alc883_lenovo_nb0763_setup(struct hda_codec *codec)
 
 	spec->autocfg.hp_pins[0] = 0x14;
 	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 /* toggle speaker-output according to the hp-jack state */
@@ -9553,11 +9587,13 @@ static void alc883_clevo_m720_setup(struct hda_codec *codec)
 
 	spec->autocfg.hp_pins[0] = 0x15;
 	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc883_clevo_m720_init_hook(struct hda_codec *codec)
 {
-	alc_automute_amp(codec);
+	alc_hp_automute(codec);
 	alc88x_simple_mic_automute(codec);
 }
 
@@ -9569,7 +9605,7 @@ static void alc883_clevo_m720_unsol_event(struct hda_codec *codec,
 		alc88x_simple_mic_automute(codec);
 		break;
 	default:
-		alc_automute_amp_unsol_event(codec, res);
+		alc_sku_unsol_event(codec, res);
 		break;
 	}
 }
@@ -9581,6 +9617,8 @@ static void alc883_2ch_fujitsu_pi2515_setup(struct hda_codec *codec)
 
 	spec->autocfg.hp_pins[0] = 0x14;
 	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc883_haier_w66_setup(struct hda_codec *codec)
@@ -9589,6 +9627,8 @@ static void alc883_haier_w66_setup(struct hda_codec *codec)
 
 	spec->autocfg.hp_pins[0] = 0x1b;
 	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
@@ -9626,6 +9666,8 @@ static void alc883_acer_aspire_setup(struct hda_codec *codec)
 	spec->autocfg.hp_pins[0] = 0x14;
 	spec->autocfg.speaker_pins[0] = 0x15;
 	spec->autocfg.speaker_pins[1] = 0x16;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static struct hda_verb alc883_acer_eapd_verbs[] = {
@@ -9655,6 +9697,8 @@ static void alc888_6st_dell_setup(struct hda_codec *codec)
 	spec->autocfg.speaker_pins[1] = 0x15;
 	spec->autocfg.speaker_pins[2] = 0x16;
 	spec->autocfg.speaker_pins[3] = 0x17;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc888_lenovo_sky_setup(struct hda_codec *codec)
@@ -9667,6 +9711,8 @@ static void alc888_lenovo_sky_setup(struct hda_codec *codec)
 	spec->autocfg.speaker_pins[2] = 0x16;
 	spec->autocfg.speaker_pins[3] = 0x17;
 	spec->autocfg.speaker_pins[4] = 0x1a;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc883_vaiott_setup(struct hda_codec *codec)
@@ -9676,6 +9722,8 @@ static void alc883_vaiott_setup(struct hda_codec *codec)
 	spec->autocfg.hp_pins[0] = 0x15;
 	spec->autocfg.speaker_pins[0] = 0x14;
 	spec->autocfg.speaker_pins[1] = 0x17;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static struct hda_verb alc888_asus_m90v_verbs[] = {
@@ -9701,6 +9749,8 @@ static void alc883_mode2_setup(struct hda_codec *codec)
 	spec->ext_mic.mux_idx = 0;
 	spec->int_mic.mux_idx = 1;
 	spec->auto_mic = 1;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static struct hda_verb alc888_asus_eee1601_verbs[] = {
@@ -9722,7 +9772,7 @@ static void alc883_eee1601_inithook(struct hda_codec *codec)
 
 	spec->autocfg.hp_pins[0] = 0x14;
 	spec->autocfg.speaker_pins[0] = 0x1b;
-	alc_automute_pin(codec);
+	alc_hp_automute(codec);
 }
 
 static struct hda_verb alc889A_mb31_verbs[] = {
@@ -10043,9 +10093,9 @@ static struct alc_config_preset alc882_presets[] = {
 			.channel_mode = alc885_mba21_ch_modes,
 			.num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
 			.input_mux = &alc882_capture_source,
-			.unsol_event = alc_automute_amp_unsol_event,
+			.unsol_event = alc_sku_unsol_event,
 			.setup = alc885_mba21_setup,
-			.init_hook = alc_automute_amp,
+			.init_hook = alc_hp_automute,
        },
 	[ALC885_MBP3] = {
 		.mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
@@ -10059,9 +10109,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.input_mux = &alc882_capture_source,
 		.dig_out_nid = ALC882_DIGOUT_NID,
 		.dig_in_nid = ALC882_DIGIN_NID,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc885_mbp3_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC885_MB5] = {
 		.mixers = { alc885_mb5_mixer, alc882_chmode_mixer },
@@ -10074,9 +10124,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.input_mux = &mb5_capture_source,
 		.dig_out_nid = ALC882_DIGOUT_NID,
 		.dig_in_nid = ALC882_DIGIN_NID,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc885_mb5_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC885_MACMINI3] = {
 		.mixers = { alc885_macmini3_mixer, alc882_chmode_mixer },
@@ -10089,9 +10139,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.input_mux = &macmini3_capture_source,
 		.dig_out_nid = ALC882_DIGOUT_NID,
 		.dig_in_nid = ALC882_DIGIN_NID,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc885_macmini3_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC885_MACPRO] = {
 		.mixers = { alc882_macpro_mixer },
@@ -10115,7 +10165,7 @@ static struct alc_config_preset alc882_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
 		.channel_mode = alc882_ch_modes,
 		.input_mux = &alc882_capture_source,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc885_imac24_setup,
 		.init_hook = alc885_imac24_init_hook,
 	},
@@ -10130,9 +10180,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.input_mux = &alc889A_imac91_capture_source,
 		.dig_out_nid = ALC882_DIGOUT_NID,
 		.dig_in_nid = ALC882_DIGIN_NID,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc885_imac91_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC882_TARGA] = {
 		.mixers = { alc882_targa_mixer, alc882_chmode_mixer },
@@ -10148,7 +10198,7 @@ static struct alc_config_preset alc882_presets[] = {
 		.channel_mode = alc882_3ST_6ch_modes,
 		.need_dac_fix = 1,
 		.input_mux = &alc882_capture_source,
-		.unsol_event = alc882_targa_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc882_targa_setup,
 		.init_hook = alc882_targa_automute,
 	},
@@ -10242,8 +10292,8 @@ static struct alc_config_preset alc882_presets[] = {
 		.capsrc_nids = alc889_capsrc_nids,
 		.input_mux = &alc889_capture_source,
 		.setup = alc889_automute_setup,
-		.init_hook = alc_automute_amp,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.init_hook = alc_hp_automute,
+		.unsol_event = alc_sku_unsol_event,
 		.need_dac_fix = 1,
 	},
 	[ALC889_INTEL] = {
@@ -10263,7 +10313,7 @@ static struct alc_config_preset alc882_presets[] = {
 		.input_mux = &alc889_capture_source,
 		.setup = alc889_automute_setup,
 		.init_hook = alc889_intel_init_hook,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.need_dac_fix = 1,
 	},
 	[ALC883_6ST_DIG] = {
@@ -10352,9 +10402,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_capture_source,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc883_acer_aspire_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC888_ACER_ASPIRE_4930G] = {
 		.mixers = { alc888_acer_aspire_4930g_mixer,
@@ -10374,9 +10424,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.num_mux_defs =
 			ARRAY_SIZE(alc888_2_capture_sources),
 		.input_mux = alc888_2_capture_sources,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc888_acer_aspire_4930g_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC888_ACER_ASPIRE_6530G] = {
 		.mixers = { alc888_acer_aspire_6530_mixer },
@@ -10393,9 +10443,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.num_mux_defs =
 			ARRAY_SIZE(alc888_2_capture_sources),
 		.input_mux = alc888_acer_aspire_6530_sources,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc888_acer_aspire_6530g_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC888_ACER_ASPIRE_8930G] = {
 		.mixers = { alc889_acer_aspire_8930g_mixer,
@@ -10416,9 +10466,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.num_mux_defs =
 			ARRAY_SIZE(alc889_capture_sources),
 		.input_mux = alc889_capture_sources,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc889_acer_aspire_8930g_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 		.power_hook = alc_power_eapd,
 #endif
@@ -10439,9 +10489,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.need_dac_fix = 1,
 		.const_channel_count = 6,
 		.input_mux = &alc883_capture_source,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc888_acer_aspire_7730g_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC883_MEDION] = {
 		.mixers = { alc883_fivestack_mixer,
@@ -10468,9 +10518,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_capture_source,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc883_medion_wim2160_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC883_LAPTOP_EAPD] = {
 		.mixers = { alc883_base_mixer },
@@ -10532,9 +10582,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.channel_mode = alc883_3ST_2ch_modes,
 		.need_dac_fix = 1,
 		.input_mux = &alc883_lenovo_nb0763_capture_source,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc883_lenovo_nb0763_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC888_LENOVO_MS7195_DIG] = {
 		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
@@ -10558,9 +10608,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_capture_source,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc883_haier_w66_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC888_3ST_HP] = {
 		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
@@ -10571,9 +10621,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.channel_mode = alc888_3st_hp_modes,
 		.need_dac_fix = 1,
 		.input_mux = &alc883_capture_source,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc888_3st_hp_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC888_6ST_DELL] = {
 		.mixers = { alc883_base_mixer, alc883_chmode_mixer },
@@ -10585,9 +10635,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
 		.channel_mode = alc883_sixstack_modes,
 		.input_mux = &alc883_capture_source,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc888_6st_dell_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC883_MITAC] = {
 		.mixers = { alc883_mitac_mixer },
@@ -10597,9 +10647,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_capture_source,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc883_mitac_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC883_FUJITSU_PI2515] = {
 		.mixers = { alc883_2ch_fujitsu_pi2515_mixer },
@@ -10611,9 +10661,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_fujitsu_pi2515_capture_source,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc883_2ch_fujitsu_pi2515_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC888_FUJITSU_XA3530] = {
 		.mixers = { alc888_base_mixer, alc883_chmode_mixer },
@@ -10630,9 +10680,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.num_mux_defs =
 			ARRAY_SIZE(alc888_2_capture_sources),
 		.input_mux = alc888_2_capture_sources,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc888_fujitsu_xa3530_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC888_LENOVO_SKY] = {
 		.mixers = { alc888_lenovo_sky_mixer, alc883_chmode_mixer },
@@ -10644,9 +10694,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.channel_mode = alc883_sixstack_modes,
 		.need_dac_fix = 1,
 		.input_mux = &alc883_lenovo_sky_capture_source,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc888_lenovo_sky_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC888_ASUS_M90V] = {
 		.mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
@@ -10714,9 +10764,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_capture_source,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc883_vaiott_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 };
 
@@ -11347,6 +11397,8 @@ static void alc262_hp_t5735_setup(struct hda_codec *codec)
 
 	spec->autocfg.hp_pins[0] = 0x15;
 	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
 }
 
 static struct snd_kcontrol_new alc262_hp_t5735_mixer[] = {
@@ -11580,6 +11632,8 @@ static void alc262_tyan_setup(struct hda_codec *codec)
 
 	spec->autocfg.hp_pins[0] = 0x1b;
 	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 
@@ -11723,6 +11777,8 @@ static void alc262_toshiba_s06_setup(struct hda_codec *codec)
 	spec->int_mic.pin = 0x12;
 	spec->int_mic.mux_idx = 9;
 	spec->auto_mic = 1;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
 }
 
 /*
@@ -12933,9 +12989,9 @@ static struct alc_config_preset alc262_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc262_modes),
 		.channel_mode = alc262_modes,
 		.input_mux = &alc262_capture_source,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc262_tyan_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 };
 
@@ -13349,6 +13405,8 @@ static void alc268_dell_setup(struct hda_codec *codec)
 	spec->int_mic.pin = 0x19;
 	spec->int_mic.mux_idx = 1;
 	spec->auto_mic = 1;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
 }
 
 static struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
@@ -13379,6 +13437,8 @@ static void alc267_quanta_il1_setup(struct hda_codec *codec)
 	spec->int_mic.pin = 0x19;
 	spec->int_mic.mux_idx = 1;
 	spec->auto_mic = 1;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
 }
 
 /*
@@ -16878,11 +16938,13 @@ static void alc861vd_lenovo_setup(struct hda_codec *codec)
 	struct alc_spec *spec = codec->spec;
 	spec->autocfg.hp_pins[0] = 0x1b;
 	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc861vd_lenovo_init_hook(struct hda_codec *codec)
 {
-	alc_automute_amp(codec);
+	alc_hp_automute(codec);
 	alc88x_simple_mic_automute(codec);
 }
 
@@ -16894,7 +16956,7 @@ static void alc861vd_lenovo_unsol_event(struct hda_codec *codec,
 		alc88x_simple_mic_automute(codec);
 		break;
 	default:
-		alc_automute_amp_unsol_event(codec, res);
+		alc_sku_unsol_event(codec, res);
 		break;
 	}
 }
@@ -16951,6 +17013,8 @@ static void alc861vd_dallas_setup(struct hda_codec *codec)
 
 	spec->autocfg.hp_pins[0] = 0x15;
 	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -17075,9 +17139,9 @@ static struct alc_config_preset alc861vd_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
 		.channel_mode = alc861vd_3stack_2ch_modes,
 		.input_mux = &alc861vd_dallas_capture_source,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc861vd_dallas_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC861VD_HP] = {
 		.mixers = { alc861vd_hp_mixer },
@@ -17088,9 +17152,9 @@ static struct alc_config_preset alc861vd_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
 		.channel_mode = alc861vd_3stack_2ch_modes,
 		.input_mux = &alc861vd_hp_capture_source,
-		.unsol_event = alc_automute_amp_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc861vd_dallas_setup,
-		.init_hook = alc_automute_amp,
+		.init_hook = alc_hp_automute,
 	},
 	[ALC660VD_ASUS_V1S] = {
 		.mixers = { alc861vd_lenovo_mixer },
@@ -20081,20 +20145,22 @@ static void alc680_base_setup(struct hda_codec *codec)
 	spec->autocfg.inputs[0].type = AUTO_PIN_MIC;
 	spec->autocfg.inputs[1].pin = 0x19;
 	spec->autocfg.inputs[1].type = AUTO_PIN_LINE_IN;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc680_unsol_event(struct hda_codec *codec,
 					   unsigned int res)
 {
 	if ((res >> 26) == ALC880_HP_EVENT)
-		alc_automute_amp(codec);
+		alc_hp_automute(codec);
 	if ((res >> 26) == ALC880_MIC_EVENT)
 		alc680_rec_autoswitch(codec);
 }
 
 static void alc680_inithook(struct hda_codec *codec)
 {
-	alc_automute_amp(codec);
+	alc_hp_automute(codec);
 	alc680_rec_autoswitch(codec);
 }
 
-- 
1.7.4.2

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

* [PATCH 04/10] ALSA: hda - Add common automute support for mxier-amp on/off for Reatek
  2011-04-29 17:18 [PATCH 0/10] Realtek auto-parser updates Takashi Iwai
                   ` (2 preceding siblings ...)
  2011-04-29 17:18 ` [PATCH 03/10] ALSA: hda - Consolidate default automute functions for Realtek Takashi Iwai
@ 2011-04-29 17:18 ` Takashi Iwai
  2011-04-29 17:18 ` [PATCH 05/10] ALSA: hda - Add support of line-out automute for Realtek Takashi Iwai
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Takashi Iwai @ 2011-04-29 17:18 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai

Some models do mute on/off the connected mixer widget for the automatic
muting, instead of controlling the pin widget itself.  This patch adds
the implementation of such type of auto-mute in the common helper
function, and reduces the redundant codes for each model preset.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c |  651 ++++++++++++-----------------------------
 1 files changed, 194 insertions(+), 457 deletions(-)

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 5715b6f..af9bb96 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -306,8 +306,9 @@ struct alc_multi_io {
 };
 
 enum {
-	ALC_AUTOMUTE_PIN,
-	ALC_AUTOMUTE_AMP,
+	ALC_AUTOMUTE_PIN,	/* change the pin control */
+	ALC_AUTOMUTE_AMP,	/* mute/unmute the pin AMP */
+	ALC_AUTOMUTE_MIXER,	/* mute/unmute mixer widget AMP */
 };
 
 struct alc_spec {
@@ -402,6 +403,7 @@ struct alc_spec {
 
 	/* auto-mute control */
 	int automute_mode;
+	hda_nid_t automute_mixer_nid[AUTO_CFG_MAX_OUTS];
 
 	int init_amp;
 	int codec_variant;	/* flag for other variants */
@@ -1097,13 +1099,25 @@ static void alc_hp_automute(struct hda_codec *codec)
 		nid = spec->autocfg.speaker_pins[i];
 		if (!nid)
 			break;
-		if (spec->automute_mode == ALC_AUTOMUTE_PIN) {
+		switch (spec->automute_mode) {
+		case ALC_AUTOMUTE_PIN:
 			snd_hda_codec_write(codec, nid, 0,
 				    AC_VERB_SET_PIN_WIDGET_CONTROL,
 				    spec->jack_present ? 0 : PIN_OUT);
-		} else {
+			break;
+		case ALC_AUTOMUTE_AMP:
 			snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
 					 HDA_AMP_MUTE, mute);
+			break;
+		case ALC_AUTOMUTE_MIXER:
+			nid = spec->automute_mixer_nid[i];
+			if (!nid)
+				break;
+			snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
+						 HDA_AMP_MUTE, mute);
+			snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 1,
+						 HDA_AMP_MUTE, mute);
+			break;
 		}
 	}
 }
@@ -13331,36 +13345,14 @@ static void alc268_acer_init_hook(struct hda_codec *codec)
 	alc268_acer_automute(codec, 1);
 }
 
-/* toggle speaker-output according to the hp-jack state */
-static void alc268_aspire_one_speaker_automute(struct hda_codec *codec)
-{
-	unsigned int present;
-	unsigned char bits;
-
-	present = snd_hda_jack_detect(codec, 0x15);
-	bits = present ? HDA_AMP_MUTE : 0;
-	snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 0,
-				 HDA_AMP_MUTE, bits);
-	snd_hda_codec_amp_stereo(codec, 0x0f, HDA_INPUT, 1,
-				 HDA_AMP_MUTE, bits);
-}
-
-static void alc268_acer_lc_unsol_event(struct hda_codec *codec,
-				    unsigned int res)
-{
-	switch (res >> 26) {
-	case ALC880_HP_EVENT:
-		alc268_aspire_one_speaker_automute(codec);
-		break;
-	case ALC880_MIC_EVENT:
-		alc_mic_automute(codec);
-		break;
-	}
-}
-
 static void alc268_acer_lc_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute_mixer_nid[0] = 0x0f;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
 	spec->ext_mic.pin = 0x18;
 	spec->ext_mic.mux_idx = 0;
 	spec->int_mic.pin = 0x12;
@@ -13368,12 +13360,6 @@ static void alc268_acer_lc_setup(struct hda_codec *codec)
 	spec->auto_mic = 1;
 }
 
-static void alc268_acer_lc_init_hook(struct hda_codec *codec)
-{
-	alc268_aspire_one_speaker_automute(codec);
-	alc_mic_automute(codec);
-}
-
 static struct snd_kcontrol_new alc268_dell_mixer[] = {
 	/* output mixer control */
 	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
@@ -14032,9 +14018,9 @@ static struct alc_config_preset alc268_presets[] = {
 		.hp_nid = 0x03,
 		.num_channel_mode = ARRAY_SIZE(alc268_modes),
 		.channel_mode = alc268_modes,
-		.unsol_event = alc268_acer_lc_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc268_acer_lc_setup,
-		.init_hook = alc268_acer_lc_init_hook,
+		.init_hook = alc_inithook,
 	},
 	[ALC268_DELL] = {
 		.mixers = { alc268_dell_mixer, alc268_beep_mixer,
@@ -14374,15 +14360,7 @@ static struct hda_verb alc269_lifebook_verbs[] = {
 /* toggle speaker-output according to the hp-jack state */
 static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
 {
-	unsigned int present;
-	unsigned char bits;
-
-	present = snd_hda_jack_detect(codec, 0x15);
-	bits = present ? HDA_AMP_MUTE : 0;
-	snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
-				 HDA_AMP_MUTE, bits);
-	snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
-				 HDA_AMP_MUTE, bits);
+	alc_hp_automute(codec);
 
 	snd_hda_codec_write(codec, 0x20, 0,
 			AC_VERB_SET_COEF_INDEX, 0x0c);
@@ -14395,34 +14373,8 @@ static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
 			AC_VERB_SET_PROC_COEF, 0x480);
 }
 
-/* toggle speaker-output according to the hp-jacks state */
-static void alc269_lifebook_speaker_automute(struct hda_codec *codec)
-{
-	unsigned int present;
-	unsigned char bits;
-
-	/* Check laptop headphone socket */
-	present = snd_hda_jack_detect(codec, 0x15);
-
-	/* Check port replicator headphone socket */
-	present |= snd_hda_jack_detect(codec, 0x1a);
-
-	bits = present ? HDA_AMP_MUTE : 0;
-	snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
-				 HDA_AMP_MUTE, bits);
-	snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
-				 HDA_AMP_MUTE, bits);
-
-	snd_hda_codec_write(codec, 0x20, 0,
-			AC_VERB_SET_COEF_INDEX, 0x0c);
-	snd_hda_codec_write(codec, 0x20, 0,
-			AC_VERB_SET_PROC_COEF, 0x680);
-
-	snd_hda_codec_write(codec, 0x20, 0,
-			AC_VERB_SET_COEF_INDEX, 0x0c);
-	snd_hda_codec_write(codec, 0x20, 0,
-			AC_VERB_SET_PROC_COEF, 0x480);
-}
+#define alc269_lifebook_speaker_automute \
+	alc269_quanta_fl1_speaker_automute
 
 static void alc269_lifebook_mic_autoswitch(struct hda_codec *codec)
 {
@@ -14471,6 +14423,9 @@ static void alc269_quanta_fl1_setup(struct hda_codec *codec)
 	struct alc_spec *spec = codec->spec;
 	spec->autocfg.hp_pins[0] = 0x15;
 	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
 	spec->ext_mic.pin = 0x18;
 	spec->ext_mic.mux_idx = 0;
 	spec->int_mic.pin = 0x19;
@@ -14484,6 +14439,17 @@ static void alc269_quanta_fl1_init_hook(struct hda_codec *codec)
 	alc_mic_automute(codec);
 }
 
+static void alc269_lifebook_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.hp_pins[1] = 0x1a;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
+}
+
 static void alc269_lifebook_init_hook(struct hda_codec *codec)
 {
 	alc269_lifebook_speaker_automute(codec);
@@ -14547,42 +14513,14 @@ static struct hda_verb alc271_acer_dmic_verbs[] = {
 	{ }
 };
 
-/* toggle speaker-output according to the hp-jack state */
-static void alc269_speaker_automute(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	unsigned int nid = spec->autocfg.hp_pins[0];
-	unsigned int present;
-	unsigned char bits;
-
-	present = snd_hda_jack_detect(codec, nid);
-	bits = present ? HDA_AMP_MUTE : 0;
-	snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
-				 HDA_AMP_MUTE, bits);
-	snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
-				 HDA_AMP_MUTE, bits);
-	snd_hda_input_jack_report(codec, nid);
-}
-
-/* unsolicited event for HP jack sensing */
-static void alc269_laptop_unsol_event(struct hda_codec *codec,
-				     unsigned int res)
-{
-	switch (res >> 26) {
-	case ALC880_HP_EVENT:
-		alc269_speaker_automute(codec);
-		break;
-	case ALC880_MIC_EVENT:
-		alc_mic_automute(codec);
-		break;
-	}
-}
-
 static void alc269_laptop_amic_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
 	spec->autocfg.hp_pins[0] = 0x15;
 	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
 	spec->ext_mic.pin = 0x18;
 	spec->ext_mic.mux_idx = 0;
 	spec->int_mic.pin = 0x19;
@@ -14595,6 +14533,9 @@ static void alc269_laptop_dmic_setup(struct hda_codec *codec)
 	struct alc_spec *spec = codec->spec;
 	spec->autocfg.hp_pins[0] = 0x15;
 	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
 	spec->ext_mic.pin = 0x18;
 	spec->ext_mic.mux_idx = 0;
 	spec->int_mic.pin = 0x12;
@@ -14607,6 +14548,9 @@ static void alc269vb_laptop_amic_setup(struct hda_codec *codec)
 	struct alc_spec *spec = codec->spec;
 	spec->autocfg.hp_pins[0] = 0x21;
 	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
 	spec->ext_mic.pin = 0x18;
 	spec->ext_mic.mux_idx = 0;
 	spec->int_mic.pin = 0x19;
@@ -14619,6 +14563,9 @@ static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
 	struct alc_spec *spec = codec->spec;
 	spec->autocfg.hp_pins[0] = 0x21;
 	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
 	spec->ext_mic.pin = 0x18;
 	spec->ext_mic.mux_idx = 0;
 	spec->int_mic.pin = 0x12;
@@ -14626,12 +14573,6 @@ static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
 	spec->auto_mic = 1;
 }
 
-static void alc269_laptop_inithook(struct hda_codec *codec)
-{
-	alc269_speaker_automute(codec);
-	alc_mic_automute(codec);
-}
-
 /*
  * generic initialization of ADC, input mixers and output mixers
  */
@@ -15168,9 +15109,9 @@ static struct alc_config_preset alc269_presets[] = {
 		.hp_nid = 0x03,
 		.num_channel_mode = ARRAY_SIZE(alc269_modes),
 		.channel_mode = alc269_modes,
-		.unsol_event = alc269_laptop_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc269_laptop_amic_setup,
-		.init_hook = alc269_laptop_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC269_DMIC] = {
 		.mixers = { alc269_laptop_mixer },
@@ -15182,9 +15123,9 @@ static struct alc_config_preset alc269_presets[] = {
 		.hp_nid = 0x03,
 		.num_channel_mode = ARRAY_SIZE(alc269_modes),
 		.channel_mode = alc269_modes,
-		.unsol_event = alc269_laptop_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc269_laptop_dmic_setup,
-		.init_hook = alc269_laptop_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC269VB_AMIC] = {
 		.mixers = { alc269vb_laptop_mixer },
@@ -15196,9 +15137,9 @@ static struct alc_config_preset alc269_presets[] = {
 		.hp_nid = 0x03,
 		.num_channel_mode = ARRAY_SIZE(alc269_modes),
 		.channel_mode = alc269_modes,
-		.unsol_event = alc269_laptop_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc269vb_laptop_amic_setup,
-		.init_hook = alc269_laptop_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC269VB_DMIC] = {
 		.mixers = { alc269vb_laptop_mixer },
@@ -15210,9 +15151,9 @@ static struct alc_config_preset alc269_presets[] = {
 		.hp_nid = 0x03,
 		.num_channel_mode = ARRAY_SIZE(alc269_modes),
 		.channel_mode = alc269_modes,
-		.unsol_event = alc269_laptop_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc269vb_laptop_dmic_setup,
-		.init_hook = alc269_laptop_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC269_FUJITSU] = {
 		.mixers = { alc269_fujitsu_mixer },
@@ -15224,9 +15165,9 @@ static struct alc_config_preset alc269_presets[] = {
 		.hp_nid = 0x03,
 		.num_channel_mode = ARRAY_SIZE(alc269_modes),
 		.channel_mode = alc269_modes,
-		.unsol_event = alc269_laptop_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc269_laptop_dmic_setup,
-		.init_hook = alc269_laptop_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC269_LIFEBOOK] = {
 		.mixers = { alc269_lifebook_mixer },
@@ -15238,6 +15179,7 @@ static struct alc_config_preset alc269_presets[] = {
 		.channel_mode = alc269_modes,
 		.input_mux = &alc269_capture_source,
 		.unsol_event = alc269_lifebook_unsol_event,
+		.setup = alc269_lifebook_setup,
 		.init_hook = alc269_lifebook_init_hook,
 	},
 	[ALC271_ACER] = {
@@ -18348,164 +18290,14 @@ static void alc662_eeepc_ep20_setup(struct hda_codec *codec)
 
 #define alc662_eeepc_ep20_inithook	alc262_hippo_master_update
 
-static void alc663_m51va_speaker_automute(struct hda_codec *codec)
-{
-	unsigned int present;
-	unsigned char bits;
-
-	present = snd_hda_jack_detect(codec, 0x21);
-	bits = present ? HDA_AMP_MUTE : 0;
-	snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
-				 HDA_AMP_MUTE, bits);
-	snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
-				 HDA_AMP_MUTE, bits);
-}
-
-static void alc663_21jd_two_speaker_automute(struct hda_codec *codec)
-{
-	unsigned int present;
-	unsigned char bits;
-
-	present = snd_hda_jack_detect(codec, 0x21);
-	bits = present ? HDA_AMP_MUTE : 0;
-	snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
-				 HDA_AMP_MUTE, bits);
-	snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
-				 HDA_AMP_MUTE, bits);
-	snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0,
-				 HDA_AMP_MUTE, bits);
-	snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1,
-				 HDA_AMP_MUTE, bits);
-}
-
-static void alc663_15jd_two_speaker_automute(struct hda_codec *codec)
-{
-	unsigned int present;
-	unsigned char bits;
-
-	present = snd_hda_jack_detect(codec, 0x15);
-	bits = present ? HDA_AMP_MUTE : 0;
-	snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
-				 HDA_AMP_MUTE, bits);
-	snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
-				 HDA_AMP_MUTE, bits);
-	snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 0,
-				 HDA_AMP_MUTE, bits);
-	snd_hda_codec_amp_stereo(codec, 0x0e, HDA_INPUT, 1,
-				 HDA_AMP_MUTE, bits);
-}
-
-static void alc662_f5z_speaker_automute(struct hda_codec *codec)
-{
-	unsigned int present;
-	unsigned char bits;
-
-	present = snd_hda_jack_detect(codec, 0x1b);
-	bits = present ? 0 : PIN_OUT;
-	snd_hda_codec_write(codec, 0x14, 0,
-			 AC_VERB_SET_PIN_WIDGET_CONTROL, bits);
-}
-
-static void alc663_two_hp_m1_speaker_automute(struct hda_codec *codec)
-{
-	unsigned int present1, present2;
-
-	present1 = snd_hda_jack_detect(codec, 0x21);
-	present2 = snd_hda_jack_detect(codec, 0x15);
-
-	if (present1 || present2) {
-		snd_hda_codec_write_cache(codec, 0x14, 0,
-			AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
-	} else {
-		snd_hda_codec_write_cache(codec, 0x14, 0,
-			AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-	}
-}
-
-static void alc663_two_hp_m2_speaker_automute(struct hda_codec *codec)
-{
-	unsigned int present1, present2;
-
-	present1 = snd_hda_jack_detect(codec, 0x1b);
-	present2 = snd_hda_jack_detect(codec, 0x15);
-
-	if (present1 || present2) {
-		snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
-					 HDA_AMP_MUTE, HDA_AMP_MUTE);
-		snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
-					 HDA_AMP_MUTE, HDA_AMP_MUTE);
-	} else {
-		snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
-					 HDA_AMP_MUTE, 0);
-		snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
-					 HDA_AMP_MUTE, 0);
-	}
-}
-
-static void alc663_two_hp_m7_speaker_automute(struct hda_codec *codec)
-{
-	unsigned int present1, present2;
-
-	present1 = snd_hda_codec_read(codec, 0x1b, 0,
-			AC_VERB_GET_PIN_SENSE, 0)
-			& AC_PINSENSE_PRESENCE;
-	present2 = snd_hda_codec_read(codec, 0x21, 0,
-			AC_VERB_GET_PIN_SENSE, 0)
-			& AC_PINSENSE_PRESENCE;
-
-	if (present1 || present2) {
-		snd_hda_codec_write_cache(codec, 0x14, 0,
-			AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
-		snd_hda_codec_write_cache(codec, 0x17, 0,
-			AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
-	} else {
-		snd_hda_codec_write_cache(codec, 0x14, 0,
-			AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-		snd_hda_codec_write_cache(codec, 0x17, 0,
-			AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-	}
-}
-
-static void alc663_two_hp_m8_speaker_automute(struct hda_codec *codec)
-{
-	unsigned int present1, present2;
-
-	present1 = snd_hda_codec_read(codec, 0x21, 0,
-			AC_VERB_GET_PIN_SENSE, 0)
-			& AC_PINSENSE_PRESENCE;
-	present2 = snd_hda_codec_read(codec, 0x15, 0,
-			AC_VERB_GET_PIN_SENSE, 0)
-			& AC_PINSENSE_PRESENCE;
-
-	if (present1 || present2) {
-		snd_hda_codec_write_cache(codec, 0x14, 0,
-			AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
-		snd_hda_codec_write_cache(codec, 0x17, 0,
-			AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
-	} else {
-		snd_hda_codec_write_cache(codec, 0x14, 0,
-			AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-		snd_hda_codec_write_cache(codec, 0x17, 0,
-			AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-	}
-}
-
-static void alc663_m51va_unsol_event(struct hda_codec *codec,
-					   unsigned int res)
-{
-	switch (res >> 26) {
-	case ALC880_HP_EVENT:
-		alc663_m51va_speaker_automute(codec);
-		break;
-	case ALC880_MIC_EVENT:
-		alc_mic_automute(codec);
-		break;
-	}
-}
-
 static void alc663_m51va_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x21;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
 	spec->ext_mic.pin = 0x18;
 	spec->ext_mic.mux_idx = 0;
 	spec->int_mic.pin = 0x12;
@@ -18513,18 +18305,15 @@ static void alc663_m51va_setup(struct hda_codec *codec)
 	spec->auto_mic = 1;
 }
 
-static void alc663_m51va_inithook(struct hda_codec *codec)
-{
-	alc663_m51va_speaker_automute(codec);
-	alc_mic_automute(codec);
-}
-
 /* ***************** Mode1 ******************************/
-#define alc663_mode1_unsol_event	alc663_m51va_unsol_event
-
 static void alc663_mode1_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x21;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
 	spec->ext_mic.pin = 0x18;
 	spec->ext_mic.mux_idx = 0;
 	spec->int_mic.pin = 0x19;
@@ -18532,156 +18321,122 @@ static void alc663_mode1_setup(struct hda_codec *codec)
 	spec->auto_mic = 1;
 }
 
-#define alc663_mode1_inithook		alc663_m51va_inithook
-
 /* ***************** Mode2 ******************************/
-static void alc662_mode2_unsol_event(struct hda_codec *codec,
-					   unsigned int res)
+static void alc662_mode2_setup(struct hda_codec *codec)
 {
-	switch (res >> 26) {
-	case ALC880_HP_EVENT:
-		alc662_f5z_speaker_automute(codec);
-		break;
-	case ALC880_MIC_EVENT:
-		alc_mic_automute(codec);
-		break;
-	}
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
+	spec->ext_mic.pin = 0x18;
+	spec->ext_mic.mux_idx = 0;
+	spec->int_mic.pin = 0x19;
+	spec->int_mic.mux_idx = 1;
+	spec->auto_mic = 1;
 }
 
-#define alc662_mode2_setup	alc663_mode1_setup
-
-static void alc662_mode2_inithook(struct hda_codec *codec)
-{
-	alc662_f5z_speaker_automute(codec);
-	alc_mic_automute(codec);
-}
 /* ***************** Mode3 ******************************/
-static void alc663_mode3_unsol_event(struct hda_codec *codec,
-					   unsigned int res)
+static void alc663_mode3_setup(struct hda_codec *codec)
 {
-	switch (res >> 26) {
-	case ALC880_HP_EVENT:
-		alc663_two_hp_m1_speaker_automute(codec);
-		break;
-	case ALC880_MIC_EVENT:
-		alc_mic_automute(codec);
-		break;
-	}
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x21;
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
+	spec->ext_mic.pin = 0x18;
+	spec->ext_mic.mux_idx = 0;
+	spec->int_mic.pin = 0x19;
+	spec->int_mic.mux_idx = 1;
+	spec->auto_mic = 1;
 }
 
-#define alc663_mode3_setup	alc663_mode1_setup
-
-static void alc663_mode3_inithook(struct hda_codec *codec)
-{
-	alc663_two_hp_m1_speaker_automute(codec);
-	alc_mic_automute(codec);
-}
 /* ***************** Mode4 ******************************/
-static void alc663_mode4_unsol_event(struct hda_codec *codec,
-					   unsigned int res)
+static void alc663_mode4_setup(struct hda_codec *codec)
 {
-	switch (res >> 26) {
-	case ALC880_HP_EVENT:
-		alc663_21jd_two_speaker_automute(codec);
-		break;
-	case ALC880_MIC_EVENT:
-		alc_mic_automute(codec);
-		break;
-	}
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x21;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[1] = 0x16;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute_mixer_nid[1] = 0x0e;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
+	spec->ext_mic.pin = 0x18;
+	spec->ext_mic.mux_idx = 0;
+	spec->int_mic.pin = 0x19;
+	spec->int_mic.mux_idx = 1;
+	spec->auto_mic = 1;
 }
 
-#define alc663_mode4_setup	alc663_mode1_setup
-
-static void alc663_mode4_inithook(struct hda_codec *codec)
-{
-	alc663_21jd_two_speaker_automute(codec);
-	alc_mic_automute(codec);
-}
 /* ***************** Mode5 ******************************/
-static void alc663_mode5_unsol_event(struct hda_codec *codec,
-					   unsigned int res)
+static void alc663_mode5_setup(struct hda_codec *codec)
 {
-	switch (res >> 26) {
-	case ALC880_HP_EVENT:
-		alc663_15jd_two_speaker_automute(codec);
-		break;
-	case ALC880_MIC_EVENT:
-		alc_mic_automute(codec);
-		break;
-	}
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[1] = 0x16;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute_mixer_nid[1] = 0x0e;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
+	spec->ext_mic.pin = 0x18;
+	spec->ext_mic.mux_idx = 0;
+	spec->int_mic.pin = 0x19;
+	spec->int_mic.mux_idx = 1;
+	spec->auto_mic = 1;
 }
 
-#define alc663_mode5_setup	alc663_mode1_setup
-
-static void alc663_mode5_inithook(struct hda_codec *codec)
-{
-	alc663_15jd_two_speaker_automute(codec);
-	alc_mic_automute(codec);
-}
 /* ***************** Mode6 ******************************/
-static void alc663_mode6_unsol_event(struct hda_codec *codec,
-					   unsigned int res)
+static void alc663_mode6_setup(struct hda_codec *codec)
 {
-	switch (res >> 26) {
-	case ALC880_HP_EVENT:
-		alc663_two_hp_m2_speaker_automute(codec);
-		break;
-	case ALC880_MIC_EVENT:
-		alc_mic_automute(codec);
-		break;
-	}
-}
-
-#define alc663_mode6_setup	alc663_mode1_setup
-
-static void alc663_mode6_inithook(struct hda_codec *codec)
-{
-	alc663_two_hp_m2_speaker_automute(codec);
-	alc_mic_automute(codec);
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute_mixer_nid[0] = 0x0c;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_MIXER;
+	spec->ext_mic.pin = 0x18;
+	spec->ext_mic.mux_idx = 0;
+	spec->int_mic.pin = 0x19;
+	spec->int_mic.mux_idx = 1;
+	spec->auto_mic = 1;
 }
 
 /* ***************** Mode7 ******************************/
-static void alc663_mode7_unsol_event(struct hda_codec *codec,
-					   unsigned int res)
-{
-	switch (res >> 26) {
-	case ALC880_HP_EVENT:
-		alc663_two_hp_m7_speaker_automute(codec);
-		break;
-	case ALC880_MIC_EVENT:
-		alc_mic_automute(codec);
-		break;
-	}
-}
-
-#define alc663_mode7_setup	alc663_mode1_setup
-
-static void alc663_mode7_inithook(struct hda_codec *codec)
+static void alc663_mode7_setup(struct hda_codec *codec)
 {
-	alc663_two_hp_m7_speaker_automute(codec);
-	alc_mic_automute(codec);
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.hp_pins[0] = 0x21;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x17;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
+	spec->ext_mic.pin = 0x18;
+	spec->ext_mic.mux_idx = 0;
+	spec->int_mic.pin = 0x19;
+	spec->int_mic.mux_idx = 1;
+	spec->auto_mic = 1;
 }
 
 /* ***************** Mode8 ******************************/
-static void alc663_mode8_unsol_event(struct hda_codec *codec,
-					   unsigned int res)
-{
-	switch (res >> 26) {
-	case ALC880_HP_EVENT:
-		alc663_two_hp_m8_speaker_automute(codec);
-		break;
-	case ALC880_MIC_EVENT:
-		alc_mic_automute(codec);
-		break;
-	}
-}
-
-#define alc663_mode8_setup	alc663_m51va_setup
-
-static void alc663_mode8_inithook(struct hda_codec *codec)
+static void alc663_mode8_setup(struct hda_codec *codec)
 {
-	alc663_two_hp_m8_speaker_automute(codec);
-	alc_mic_automute(codec);
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x21;
+	spec->autocfg.hp_pins[1] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x17;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
+	spec->ext_mic.pin = 0x18;
+	spec->ext_mic.mux_idx = 0;
+	spec->int_mic.pin = 0x12;
+	spec->int_mic.mux_idx = 9;
+	spec->auto_mic = 1;
 }
 
 static void alc663_g71v_hp_automute(struct hda_codec *codec)
@@ -18733,27 +18488,8 @@ static void alc663_g71v_inithook(struct hda_codec *codec)
 	alc_mic_automute(codec);
 }
 
-static void alc663_g50v_unsol_event(struct hda_codec *codec,
-					   unsigned int res)
-{
-	switch (res >> 26) {
-	case ALC880_HP_EVENT:
-		alc663_m51va_speaker_automute(codec);
-		break;
-	case ALC880_MIC_EVENT:
-		alc_mic_automute(codec);
-		break;
-	}
-}
-
 #define alc663_g50v_setup	alc663_m51va_setup
 
-static void alc663_g50v_inithook(struct hda_codec *codec)
-{
-	alc663_m51va_speaker_automute(codec);
-	alc_mic_automute(codec);
-}
-
 static struct snd_kcontrol_new alc662_ecs_mixer[] = {
 	HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
 	ALC262_HIPPO_MASTER_SWITCH,
@@ -19015,9 +18751,9 @@ static struct alc_config_preset alc662_presets[] = {
 		.dig_out_nid = ALC662_DIGOUT_NID,
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
 		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc663_m51va_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc663_m51va_setup,
-		.init_hook = alc663_m51va_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC663_ASUS_G71V] = {
 		.mixers = { alc663_g71v_mixer },
@@ -19042,8 +18778,9 @@ static struct alc_config_preset alc662_presets[] = {
 		.dac_nids = alc662_dac_nids,
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
 		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc663_m51va_unsol_event,
-		.init_hook = alc663_m51va_inithook,
+		.setup = alc663_m51va_setup,
+		.unsol_event = alc_sku_unsol_event,
+		.init_hook = alc_inithook,
 	},
 	[ALC663_ASUS_G50V] = {
 		.mixers = { alc663_g50v_mixer },
@@ -19056,9 +18793,9 @@ static struct alc_config_preset alc662_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
 		.channel_mode = alc662_3ST_6ch_modes,
 		.input_mux = &alc663_capture_source,
-		.unsol_event = alc663_g50v_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc663_g50v_setup,
-		.init_hook = alc663_g50v_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC663_ASUS_MODE1] = {
 		.mixers = { alc663_m51va_mixer },
@@ -19072,9 +18809,9 @@ static struct alc_config_preset alc662_presets[] = {
 		.dig_out_nid = ALC662_DIGOUT_NID,
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
 		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc663_mode1_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc663_mode1_setup,
-		.init_hook = alc663_mode1_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC662_ASUS_MODE2] = {
 		.mixers = { alc662_1bjd_mixer },
@@ -19087,9 +18824,9 @@ static struct alc_config_preset alc662_presets[] = {
 		.dig_out_nid = ALC662_DIGOUT_NID,
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
 		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc662_mode2_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc662_mode2_setup,
-		.init_hook = alc662_mode2_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC663_ASUS_MODE3] = {
 		.mixers = { alc663_two_hp_m1_mixer },
@@ -19103,9 +18840,9 @@ static struct alc_config_preset alc662_presets[] = {
 		.dig_out_nid = ALC662_DIGOUT_NID,
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
 		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc663_mode3_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc663_mode3_setup,
-		.init_hook = alc663_mode3_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC663_ASUS_MODE4] = {
 		.mixers = { alc663_asus_21jd_clfe_mixer },
@@ -19119,9 +18856,9 @@ static struct alc_config_preset alc662_presets[] = {
 		.dig_out_nid = ALC662_DIGOUT_NID,
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
 		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc663_mode4_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc663_mode4_setup,
-		.init_hook = alc663_mode4_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC663_ASUS_MODE5] = {
 		.mixers = { alc663_asus_15jd_clfe_mixer },
@@ -19135,9 +18872,9 @@ static struct alc_config_preset alc662_presets[] = {
 		.dig_out_nid = ALC662_DIGOUT_NID,
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
 		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc663_mode5_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc663_mode5_setup,
-		.init_hook = alc663_mode5_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC663_ASUS_MODE6] = {
 		.mixers = { alc663_two_hp_m2_mixer },
@@ -19151,9 +18888,9 @@ static struct alc_config_preset alc662_presets[] = {
 		.dig_out_nid = ALC662_DIGOUT_NID,
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
 		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc663_mode6_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc663_mode6_setup,
-		.init_hook = alc663_mode6_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC663_ASUS_MODE7] = {
 		.mixers = { alc663_mode7_mixer },
@@ -19167,9 +18904,9 @@ static struct alc_config_preset alc662_presets[] = {
 		.dig_out_nid = ALC662_DIGOUT_NID,
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
 		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc663_mode7_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc663_mode7_setup,
-		.init_hook = alc663_mode7_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC663_ASUS_MODE8] = {
 		.mixers = { alc663_mode8_mixer },
@@ -19183,9 +18920,9 @@ static struct alc_config_preset alc662_presets[] = {
 		.dig_out_nid = ALC662_DIGOUT_NID,
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
 		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc663_mode8_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc663_mode8_setup,
-		.init_hook = alc663_mode8_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC272_DELL] = {
 		.mixers = { alc663_m51va_mixer },
@@ -19200,9 +18937,9 @@ static struct alc_config_preset alc662_presets[] = {
 		.num_adc_nids = ARRAY_SIZE(alc272_adc_nids),
 		.capsrc_nids = alc272_capsrc_nids,
 		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc663_m51va_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc663_m51va_setup,
-		.init_hook = alc663_m51va_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC272_DELL_ZM1] = {
 		.mixers = { alc663_m51va_mixer },
@@ -19217,9 +18954,9 @@ static struct alc_config_preset alc662_presets[] = {
 		.num_adc_nids = 1,
 		.capsrc_nids = alc662_capsrc_nids,
 		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc663_m51va_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc663_m51va_setup,
-		.init_hook = alc663_m51va_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC272_SAMSUNG_NC10] = {
 		.mixers = { alc272_nc10_mixer },
@@ -19231,9 +18968,9 @@ static struct alc_config_preset alc662_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
 		.channel_mode = alc662_3ST_2ch_modes,
 		/*.input_mux = &alc272_nc10_capture_source,*/
-		.unsol_event = alc663_mode4_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc663_mode4_setup,
-		.init_hook = alc663_mode4_inithook,
+		.init_hook = alc_inithook,
 	},
 };
 
-- 
1.7.4.2

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

* [PATCH 05/10] ALSA: hda - Add support of line-out automute for Realtek
  2011-04-29 17:18 [PATCH 0/10] Realtek auto-parser updates Takashi Iwai
                   ` (3 preceding siblings ...)
  2011-04-29 17:18 ` [PATCH 04/10] ALSA: hda - Add common automute support for mxier-amp on/off for Reatek Takashi Iwai
@ 2011-04-29 17:18 ` Takashi Iwai
  2011-04-29 17:18 ` [PATCH 06/10] ALSA: hda - Consolidate auto-mute with master-switch " Takashi Iwai
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Takashi Iwai @ 2011-04-29 17:18 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai

Add the common helper function and flags to support the auto-mute
per line-out jack detection, and also the mute of line-out jacks.

A few model-specific implementations are replaced with the common
helpers.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c |  274 ++++++++++++++++++-----------------------
 1 files changed, 120 insertions(+), 154 deletions(-)

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index af9bb96..222abba 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -392,9 +392,12 @@ struct alc_spec {
 	/* for pin sensing */
 	unsigned int sense_updated: 1;
 	unsigned int jack_present: 1;
+	unsigned int line_jack_present:1;
 	unsigned int master_sw: 1;
 	unsigned int auto_mic:1;
 	unsigned int automute:1;	/* HP automute enabled */
+	unsigned int detect_line:1;	/* Line-out detection enabled */
+	unsigned int automute_lines:1;	/* automute line-out as well */
 
 	/* other flags */
 	unsigned int no_analog :1; /* digital I/O only */
@@ -1074,54 +1077,96 @@ static int alc_init_jacks(struct hda_codec *codec)
 	return 0;
 }
 
-static void alc_hp_automute(struct hda_codec *codec)
+static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
 {
-	struct alc_spec *spec = codec->spec;
-	unsigned int mute;
-	hda_nid_t nid;
-	int i;
+	int i, present = 0;
 
-	if (!spec->automute)
-		return;
-
-	spec->jack_present = 0;
-	for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) {
-		nid = spec->autocfg.hp_pins[i];
+	for (i = 0; i < num_pins; i++) {
+		hda_nid_t nid = pins[i];
 		if (!nid)
 			break;
 		snd_hda_input_jack_report(codec, nid);
-		spec->jack_present |= snd_hda_jack_detect(codec, nid);
+		present |= snd_hda_jack_detect(codec, nid);
 	}
+	return present;
+}
 
-	mute = spec->jack_present ? HDA_AMP_MUTE : 0;
-	/* Toggle internal speakers muting */
-	for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) {
-		nid = spec->autocfg.speaker_pins[i];
+static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
+			bool mute)
+{
+	struct alc_spec *spec = codec->spec;
+	unsigned int mute_bits = mute ? HDA_AMP_MUTE : 0;
+	unsigned int pin_bits = mute ? 0 : PIN_OUT;
+	int i;
+
+	for (i = 0; i < num_pins; i++) {
+		hda_nid_t nid = pins[i];
 		if (!nid)
 			break;
 		switch (spec->automute_mode) {
 		case ALC_AUTOMUTE_PIN:
 			snd_hda_codec_write(codec, nid, 0,
-				    AC_VERB_SET_PIN_WIDGET_CONTROL,
-				    spec->jack_present ? 0 : PIN_OUT);
+					    AC_VERB_SET_PIN_WIDGET_CONTROL,
+					    pin_bits);
 			break;
 		case ALC_AUTOMUTE_AMP:
 			snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
-					 HDA_AMP_MUTE, mute);
+						 HDA_AMP_MUTE, mute_bits);
 			break;
 		case ALC_AUTOMUTE_MIXER:
 			nid = spec->automute_mixer_nid[i];
 			if (!nid)
 				break;
 			snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
-						 HDA_AMP_MUTE, mute);
+						 HDA_AMP_MUTE, mute_bits);
 			snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 1,
-						 HDA_AMP_MUTE, mute);
+						 HDA_AMP_MUTE, mute_bits);
 			break;
 		}
 	}
 }
 
+/* Toggle internal speakers muting */
+static void update_speakers(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
+		    spec->autocfg.speaker_pins,
+		    spec->jack_present | spec->line_jack_present);
+
+	/* toggle line-out mutes if needed, too */
+	if (!spec->automute_lines)
+		return;
+	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
+		    spec->autocfg.line_out_pins,
+		    spec->jack_present);
+}
+
+static void alc_hp_automute(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	if (!spec->automute)
+		return;
+	spec->jack_present =
+		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
+			     spec->autocfg.hp_pins);
+	update_speakers(codec);
+}
+
+static void alc_line_automute(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	if (!spec->automute || !spec->detect_line)
+		return;
+	spec->line_jack_present =
+		detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
+			     spec->autocfg.line_out_pins);
+	update_speakers(codec);
+}
+
 static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
 				hda_nid_t nid)
 {
@@ -1219,6 +1264,9 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
 	case ALC880_HP_EVENT:
 		alc_hp_automute(codec);
 		break;
+	case ALC880_FRONT_EVENT:
+		alc_line_automute(codec);
+		break;
 	case ALC880_MIC_EVENT:
 		alc_mic_automute(codec);
 		break;
@@ -1228,6 +1276,7 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
 static void alc_inithook(struct hda_codec *codec)
 {
 	alc_hp_automute(codec);
+	alc_line_automute(codec);
 	alc_mic_automute(codec);
 }
 
@@ -9551,33 +9600,15 @@ static struct hda_channel_mode alc888_3st_hp_modes[3] = {
 	{ 6, alc888_3st_hp_6ch_init },
 };
 
-/* toggle front-jack and RCA according to the hp-jack state */
-static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec)
-{
- 	unsigned int present = snd_hda_jack_detect(codec, 0x1b);
-
-	snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
-	snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
-}
-
-/* toggle RCA according to the front-jack state */
-static void alc888_lenovo_ms7195_rca_automute(struct hda_codec *codec)
+static void alc888_lenovo_ms7195_setup(struct hda_codec *codec)
 {
- 	unsigned int present = snd_hda_jack_detect(codec, 0x14);
-
-	snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
-}
+	struct alc_spec *spec = codec->spec;
 
-static void alc883_lenovo_ms7195_unsol_event(struct hda_codec *codec,
-					     unsigned int res)
-{
-	if ((res >> 26) == ALC880_HP_EVENT)
-		alc888_lenovo_ms7195_front_automute(codec);
-	if ((res >> 26) == ALC880_FRONT_EVENT)
-		alc888_lenovo_ms7195_rca_automute(codec);
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.line_out_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 /* toggle speaker-output according to the hp-jack state */
@@ -9645,31 +9676,17 @@ static void alc883_haier_w66_setup(struct hda_codec *codec)
 	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
-static void alc883_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
+static void alc883_lenovo_101e_setup(struct hda_codec *codec)
 {
-	int bits = snd_hda_jack_detect(codec, 0x14) ? HDA_AMP_MUTE : 0;
-
-	snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, bits);
-}
-
-static void alc883_lenovo_101e_all_automute(struct hda_codec *codec)
-{
-	int bits = snd_hda_jack_detect(codec, 0x1b) ? HDA_AMP_MUTE : 0;
-
-	snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, bits);
-	snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, bits);
-}
+	struct alc_spec *spec = codec->spec;
 
-static void alc883_lenovo_101e_unsol_event(struct hda_codec *codec,
-					   unsigned int res)
-{
-	if ((res >> 26) == ALC880_HP_EVENT)
-		alc883_lenovo_101e_all_automute(codec);
-	if ((res >> 26) == ALC880_FRONT_EVENT)
-		alc883_lenovo_101e_ispeaker_automute(codec);
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.line_out_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->automute = 1;
+	spec->detect_line = 1;
+	spec->automute_lines = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 /* toggle speaker-output according to the hp-jack state */
@@ -10584,8 +10601,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
 		.channel_mode = alc883_3ST_2ch_modes,
 		.input_mux = &alc883_lenovo_101e_capture_source,
-		.unsol_event = alc883_lenovo_101e_unsol_event,
-		.init_hook = alc883_lenovo_101e_all_automute,
+		.setup = alc883_lenovo_101e_setup,
+		.unsol_event = alc_sku_unsol_event,
+		.init_hook = alc_inithook,
 	},
 	[ALC883_LENOVO_NB0763] = {
 		.mixers = { alc883_lenovo_nb0763_mixer },
@@ -10610,8 +10628,9 @@ static struct alc_config_preset alc882_presets[] = {
 		.channel_mode = alc883_3ST_6ch_modes,
 		.need_dac_fix = 1,
 		.input_mux = &alc883_capture_source,
-		.unsol_event = alc883_lenovo_ms7195_unsol_event,
-		.init_hook = alc888_lenovo_ms7195_front_automute,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc888_lenovo_ms7195_setup,
+		.init_hook = alc_inithook,
 	},
 	[ALC883_HAIER_W66] = {
 		.mixers = { alc883_targa_2ch_mixer},
@@ -18217,39 +18236,17 @@ static struct snd_kcontrol_new alc272_auto_capture_mixer[] = {
 	{ } /* end */
 };
 
-static void alc662_lenovo_101e_ispeaker_automute(struct hda_codec *codec)
+static void alc662_lenovo_101e_setup(struct hda_codec *codec)
 {
-	unsigned int present;
-	unsigned char bits;
-
-	present = snd_hda_jack_detect(codec, 0x14);
-	bits = present ? HDA_AMP_MUTE : 0;
-
-	snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, bits);
-}
-
-static void alc662_lenovo_101e_all_automute(struct hda_codec *codec)
-{
-	unsigned int present;
-	unsigned char bits;
-
- 	present = snd_hda_jack_detect(codec, 0x1b);
-	bits = present ? HDA_AMP_MUTE : 0;
-
-	snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, bits);
-	snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, bits);
-}
+	struct alc_spec *spec = codec->spec;
 
-static void alc662_lenovo_101e_unsol_event(struct hda_codec *codec,
-					   unsigned int res)
-{
-	if ((res >> 26) == ALC880_HP_EVENT)
-		alc662_lenovo_101e_all_automute(codec);
-	if ((res >> 26) == ALC880_FRONT_EVENT)
-		alc662_lenovo_101e_ispeaker_automute(codec);
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.line_out_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->automute = 1;
+	spec->detect_line = 1;
+	spec->automute_lines = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 /* unsolicited event for HP jack sensing */
@@ -18439,53 +18436,21 @@ static void alc663_mode8_setup(struct hda_codec *codec)
 	spec->auto_mic = 1;
 }
 
-static void alc663_g71v_hp_automute(struct hda_codec *codec)
-{
-	unsigned int present;
-	unsigned char bits;
-
-	present = snd_hda_jack_detect(codec, 0x21);
-	bits = present ? HDA_AMP_MUTE : 0;
-	snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, bits);
-	snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, bits);
-}
-
-static void alc663_g71v_front_automute(struct hda_codec *codec)
+static void alc663_g71v_setup(struct hda_codec *codec)
 {
-	unsigned int present;
-	unsigned char bits;
-
-	present = snd_hda_jack_detect(codec, 0x15);
-	bits = present ? HDA_AMP_MUTE : 0;
-	snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, bits);
-}
-
-static void alc663_g71v_unsol_event(struct hda_codec *codec,
-					   unsigned int res)
-{
-	switch (res >> 26) {
-	case ALC880_HP_EVENT:
-		alc663_g71v_hp_automute(codec);
-		break;
-	case ALC880_FRONT_EVENT:
-		alc663_g71v_front_automute(codec);
-		break;
-	case ALC880_MIC_EVENT:
-		alc_mic_automute(codec);
-		break;
-	}
-}
-
-#define alc663_g71v_setup	alc663_m51va_setup
-
-static void alc663_g71v_inithook(struct hda_codec *codec)
-{
-	alc663_g71v_front_automute(codec);
-	alc663_g71v_hp_automute(codec);
-	alc_mic_automute(codec);
+	struct alc_spec *spec = codec->spec;
+	spec->autocfg.hp_pins[0] = 0x21;
+	spec->autocfg.line_out_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
+	spec->detect_line = 1;
+	spec->automute_lines = 1;
+	spec->ext_mic.pin = 0x18;
+	spec->ext_mic.mux_idx = 0;
+	spec->int_mic.pin = 0x12;
+	spec->int_mic.mux_idx = 9;
+	spec->auto_mic = 1;
 }
 
 #define alc663_g50v_setup	alc663_m51va_setup
@@ -18697,8 +18662,9 @@ static struct alc_config_preset alc662_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
 		.channel_mode = alc662_3ST_2ch_modes,
 		.input_mux = &alc662_lenovo_101e_capture_source,
-		.unsol_event = alc662_lenovo_101e_unsol_event,
-		.init_hook = alc662_lenovo_101e_all_automute,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc662_lenovo_101e_setup,
+		.init_hook = alc_inithook,
 	},
 	[ALC662_ASUS_EEEPC_P701] = {
 		.mixers = { alc662_eeepc_p701_mixer },
@@ -18765,9 +18731,9 @@ static struct alc_config_preset alc662_presets[] = {
 		.dig_out_nid = ALC662_DIGOUT_NID,
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
 		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc663_g71v_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc663_g71v_setup,
-		.init_hook = alc663_g71v_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC663_ASUS_H13] = {
 		.mixers = { alc663_m51va_mixer },
-- 
1.7.4.2

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

* [PATCH 06/10] ALSA: hda - Consolidate auto-mute with master-switch for Realtek
  2011-04-29 17:18 [PATCH 0/10] Realtek auto-parser updates Takashi Iwai
                   ` (4 preceding siblings ...)
  2011-04-29 17:18 ` [PATCH 05/10] ALSA: hda - Add support of line-out automute for Realtek Takashi Iwai
@ 2011-04-29 17:18 ` Takashi Iwai
  2011-04-29 17:18 ` [PATCH 07/10] ALSA: hda - More reduction of redundant automute codes in Realtek parser Takashi Iwai
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Takashi Iwai @ 2011-04-29 17:18 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai

Yet another consolidation of auto-mute functions for the devices
controlling the output muts together with the master mixer switch,
typically found for ALC262 machines.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c |  323 +++++++++++++----------------------------
 1 files changed, 99 insertions(+), 224 deletions(-)

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 222abba..a97e460 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -393,7 +393,7 @@ struct alc_spec {
 	unsigned int sense_updated: 1;
 	unsigned int jack_present: 1;
 	unsigned int line_jack_present:1;
-	unsigned int master_sw: 1;
+	unsigned int master_mute:1;
 	unsigned int auto_mic:1;
 	unsigned int automute:1;	/* HP automute enabled */
 	unsigned int detect_line:1;	/* Line-out detection enabled */
@@ -1092,11 +1092,11 @@ static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
 }
 
 static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
-			bool mute)
+			bool mute, bool hp_out)
 {
 	struct alc_spec *spec = codec->spec;
 	unsigned int mute_bits = mute ? HDA_AMP_MUTE : 0;
-	unsigned int pin_bits = mute ? 0 : PIN_OUT;
+	unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT);
 	int i;
 
 	for (i = 0; i < num_pins; i++) {
@@ -1133,14 +1133,15 @@ static void update_speakers(struct hda_codec *codec)
 
 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
 		    spec->autocfg.speaker_pins,
-		    spec->jack_present | spec->line_jack_present);
+		    spec->jack_present | spec->line_jack_present |
+		    spec->master_mute, false);
 
 	/* toggle line-out mutes if needed, too */
 	if (!spec->automute_lines)
 		return;
 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
 		    spec->autocfg.line_out_pins,
-		    spec->jack_present);
+		    spec->jack_present | spec->master_mute, false);
 }
 
 static void alc_hp_automute(struct hda_codec *codec)
@@ -6010,21 +6011,14 @@ static struct snd_kcontrol_new alc260_input_mixer[] = {
 };
 
 /* update HP, line and mono out pins according to the master switch */
-static void alc260_hp_master_update(struct hda_codec *codec,
-				    hda_nid_t hp, hda_nid_t line,
-				    hda_nid_t mono)
+static void alc260_hp_master_update(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
-	unsigned int val = spec->master_sw ? PIN_HP : 0;
-	/* change HP and line-out pins */
-	snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-			    val);
-	snd_hda_codec_write(codec, line, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-			    val);
-	/* mono (speaker) depending on the HP jack sense */
-	val = (val && !spec->jack_present) ? PIN_OUT : 0;
-	snd_hda_codec_write(codec, mono, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-			    val);
+
+	/* change HP pins */
+	do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
+		    spec->autocfg.hp_pins, spec->master_mute, true);
+	update_speakers(codec);
 }
 
 static int alc260_hp_master_sw_get(struct snd_kcontrol *kcontrol,
@@ -6032,7 +6026,7 @@ static int alc260_hp_master_sw_get(struct snd_kcontrol *kcontrol,
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct alc_spec *spec = codec->spec;
-	*ucontrol->value.integer.value = spec->master_sw;
+	*ucontrol->value.integer.value = !spec->master_mute;
 	return 0;
 }
 
@@ -6041,16 +6035,12 @@ static int alc260_hp_master_sw_put(struct snd_kcontrol *kcontrol,
 {
 	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
 	struct alc_spec *spec = codec->spec;
-	int val = !!*ucontrol->value.integer.value;
-	hda_nid_t hp, line, mono;
+	int val = !*ucontrol->value.integer.value;
 
-	if (val == spec->master_sw)
+	if (val == spec->master_mute)
 		return 0;
-	spec->master_sw = val;
-	hp = (kcontrol->private_value >> 16) & 0xff;
-	line = (kcontrol->private_value >> 8) & 0xff;
-	mono = kcontrol->private_value & 0xff;
-	alc260_hp_master_update(codec, hp, line, mono);
+	spec->master_mute = val;
+	alc260_hp_master_update(codec);
 	return 1;
 }
 
@@ -6062,7 +6052,6 @@ static struct snd_kcontrol_new alc260_hp_output_mixer[] = {
 		.info = snd_ctl_boolean_mono_info,
 		.get = alc260_hp_master_sw_get,
 		.put = alc260_hp_master_sw_put,
-		.private_value = (0x0f << 16) | (0x10 << 8) | 0x11
 	},
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
 	HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
@@ -6079,18 +6068,15 @@ static struct hda_verb alc260_hp_unsol_verbs[] = {
 	{},
 };
 
-static void alc260_hp_automute(struct hda_codec *codec)
+static void alc260_hp_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
 
-	spec->jack_present = snd_hda_jack_detect(codec, 0x10);
-	alc260_hp_master_update(codec, 0x0f, 0x10, 0x11);
-}
-
-static void alc260_hp_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	if ((res >> 26) == ALC880_HP_EVENT)
-		alc260_hp_automute(codec);
+	spec->autocfg.hp_pins[0] = 0x0f;
+	spec->autocfg.speaker_pins[0] = 0x10;
+	spec->autocfg.speaker_pins[1] = 0x11;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
 }
 
 static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
@@ -6101,7 +6087,6 @@ static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
 		.info = snd_ctl_boolean_mono_info,
 		.get = alc260_hp_master_sw_get,
 		.put = alc260_hp_master_sw_put,
-		.private_value = (0x15 << 16) | (0x10 << 8) | 0x11
 	},
 	HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
 	HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
@@ -6114,6 +6099,17 @@ static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
 	{ } /* end */
 };
 
+static void alc260_hp_3013_setup(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x10;
+	spec->autocfg.speaker_pins[1] = 0x11;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
+}
+
 static struct hda_bind_ctls alc260_dc7600_bind_master_vol = {
 	.ops = &snd_hda_bind_vol,
 	.values = {
@@ -6146,38 +6142,16 @@ static struct hda_verb alc260_hp_3013_unsol_verbs[] = {
 	{},
 };
 
-static void alc260_hp_3013_automute(struct hda_codec *codec)
+static void alc260_hp_3012_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
 
-	spec->jack_present = snd_hda_jack_detect(codec, 0x15);
-	alc260_hp_master_update(codec, 0x15, 0x10, 0x11);
-}
-
-static void alc260_hp_3013_unsol_event(struct hda_codec *codec,
-				       unsigned int res)
-{
-	if ((res >> 26) == ALC880_HP_EVENT)
-		alc260_hp_3013_automute(codec);
-}
-
-static void alc260_hp_3012_automute(struct hda_codec *codec)
-{
-	unsigned int bits = snd_hda_jack_detect(codec, 0x10) ? 0 : PIN_OUT;
-
-	snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-			    bits);
-	snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-			    bits);
-	snd_hda_codec_write(codec, 0x15, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
-			    bits);
-}
-
-static void alc260_hp_3012_unsol_event(struct hda_codec *codec,
-				       unsigned int res)
-{
-	if ((res >> 26) == ALC880_HP_EVENT)
-		alc260_hp_3012_automute(codec);
+	spec->autocfg.hp_pins[0] = 0x10;
+	spec->autocfg.speaker_pins[0] = 0x0f;
+	spec->autocfg.speaker_pins[1] = 0x11;
+	spec->autocfg.speaker_pins[2] = 0x15;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
 }
 
 /* Fujitsu S702x series laptops.  ALC260 pin usage: Mic/Line jack = 0x12,
@@ -7302,8 +7276,9 @@ static struct alc_config_preset alc260_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc260_modes),
 		.channel_mode = alc260_modes,
 		.input_mux = &alc260_capture_source,
-		.unsol_event = alc260_hp_unsol_event,
-		.init_hook = alc260_hp_automute,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc260_hp_setup,
+		.init_hook = alc_inithook,
 	},
 	[ALC260_HP_DC7600] = {
 		.mixers = { alc260_hp_dc7600_mixer,
@@ -7317,8 +7292,9 @@ static struct alc_config_preset alc260_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc260_modes),
 		.channel_mode = alc260_modes,
 		.input_mux = &alc260_capture_source,
-		.unsol_event = alc260_hp_3012_unsol_event,
-		.init_hook = alc260_hp_3012_automute,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc260_hp_3012_setup,
+		.init_hook = alc_inithook,
 	},
 	[ALC260_HP_3013] = {
 		.mixers = { alc260_hp_3013_mixer,
@@ -7332,8 +7308,9 @@ static struct alc_config_preset alc260_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc260_modes),
 		.channel_mode = alc260_modes,
 		.input_mux = &alc260_capture_source,
-		.unsol_event = alc260_hp_3013_unsol_event,
-		.init_hook = alc260_hp_3013_automute,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc260_hp_3013_setup,
+		.init_hook = alc_inithook,
 	},
 	[ALC260_FUJITSU_S702X] = {
 		.mixers = { alc260_fujitsu_mixer },
@@ -11291,71 +11268,30 @@ static struct snd_kcontrol_new alc262_base_mixer[] = {
 };
 
 /* update HP, line and mono-out pins according to the master switch */
-static void alc262_hp_master_update(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	int val = spec->master_sw;
-
-	/* HP & line-out */
-	snd_hda_codec_write_cache(codec, 0x1b, 0,
-				  AC_VERB_SET_PIN_WIDGET_CONTROL,
-				  val ? PIN_HP : 0);
-	snd_hda_codec_write_cache(codec, 0x15, 0,
-				  AC_VERB_SET_PIN_WIDGET_CONTROL,
-				  val ? PIN_HP : 0);
-	/* mono (speaker) depending on the HP jack sense */
-	val = val && !spec->jack_present;
-	snd_hda_codec_write_cache(codec, 0x16, 0,
-				  AC_VERB_SET_PIN_WIDGET_CONTROL,
-				  val ? PIN_OUT : 0);
-}
+#define alc262_hp_master_update		alc260_hp_master_update
 
-static void alc262_hp_bpc_automute(struct hda_codec *codec)
+static void alc262_hp_bpc_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
 
-	spec->jack_present = snd_hda_jack_detect(codec, 0x1b);
-	alc262_hp_master_update(codec);
-}
-
-static void alc262_hp_bpc_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	if ((res >> 26) != ALC880_HP_EVENT)
-		return;
-	alc262_hp_bpc_automute(codec);
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.speaker_pins[0] = 0x16;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
 }
 
-static void alc262_hp_wildwest_automute(struct hda_codec *codec)
+static void alc262_hp_wildwest_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
 
-	spec->jack_present = snd_hda_jack_detect(codec, 0x15);
-	alc262_hp_master_update(codec);
-}
-
-static void alc262_hp_wildwest_unsol_event(struct hda_codec *codec,
-					   unsigned int res)
-{
-	if ((res >> 26) != ALC880_HP_EVENT)
-		return;
-	alc262_hp_wildwest_automute(codec);
+	spec->autocfg.hp_pins[0] = 0x15;
+	spec->autocfg.speaker_pins[0] = 0x16;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_PIN;
 }
 
 #define alc262_hp_master_sw_get		alc260_hp_master_sw_get
-
-static int alc262_hp_master_sw_put(struct snd_kcontrol *kcontrol,
-				   struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct alc_spec *spec = codec->spec;
-	int val = !!*ucontrol->value.integer.value;
-
-	if (val == spec->master_sw)
-		return 0;
-	spec->master_sw = val;
-	alc262_hp_master_update(codec);
-	return 1;
-}
+#define alc262_hp_master_sw_put		alc260_hp_master_sw_put
 
 #define ALC262_HP_MASTER_SWITCH					\
 	{							\
@@ -11485,44 +11421,9 @@ static struct hda_input_mux alc262_hp_rp5700_capture_source = {
 };
 
 /* bind hp and internal speaker mute (with plug check) as master switch */
-static void alc262_hippo_master_update(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
-	hda_nid_t line_nid = spec->autocfg.line_out_pins[0];
-	hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0];
-	unsigned int mute;
-
-	/* HP */
-	mute = spec->master_sw ? 0 : HDA_AMP_MUTE;
-	snd_hda_codec_amp_stereo(codec, hp_nid, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, mute);
-	/* mute internal speaker per jack sense */
-	if (spec->jack_present)
-		mute = HDA_AMP_MUTE;
-	if (line_nid)
-		snd_hda_codec_amp_stereo(codec, line_nid, HDA_OUTPUT, 0,
-					 HDA_AMP_MUTE, mute);
-	if (speaker_nid && speaker_nid != line_nid)
-		snd_hda_codec_amp_stereo(codec, speaker_nid, HDA_OUTPUT, 0,
-					 HDA_AMP_MUTE, mute);
-}
-
+#define alc262_hippo_master_update	alc262_hp_master_update
 #define alc262_hippo_master_sw_get	alc262_hp_master_sw_get
-
-static int alc262_hippo_master_sw_put(struct snd_kcontrol *kcontrol,
-				      struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct alc_spec *spec = codec->spec;
-	int val = !!*ucontrol->value.integer.value;
-
-	if (val == spec->master_sw)
-		return 0;
-	spec->master_sw = val;
-	alc262_hippo_master_update(codec);
-	return 1;
-}
+#define alc262_hippo_master_sw_put	alc262_hp_master_sw_put
 
 #define ALC262_HIPPO_MASTER_SWITCH				\
 	{							\
@@ -11573,28 +11474,14 @@ static struct snd_kcontrol_new alc262_hippo1_mixer[] = {
 };
 
 /* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc262_hippo_automute(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-	hda_nid_t hp_nid = spec->autocfg.hp_pins[0];
-
-	spec->jack_present = snd_hda_jack_detect(codec, hp_nid);
-	alc262_hippo_master_update(codec);
-}
-
-static void alc262_hippo_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	if ((res >> 26) != ALC880_HP_EVENT)
-		return;
-	alc262_hippo_automute(codec);
-}
-
 static void alc262_hippo_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
 
 	spec->autocfg.hp_pins[0] = 0x15;
 	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static void alc262_hippo1_setup(struct hda_codec *codec)
@@ -11603,6 +11490,8 @@ static void alc262_hippo1_setup(struct hda_codec *codec)
 
 	spec->autocfg.hp_pins[0] = 0x1b;
 	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 
@@ -12816,9 +12705,9 @@ static struct alc_config_preset alc262_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc262_modes),
 		.channel_mode = alc262_modes,
 		.input_mux = &alc262_capture_source,
-		.unsol_event = alc262_hippo_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc262_hippo_setup,
-		.init_hook = alc262_hippo_automute,
+		.init_hook = alc_inithook,
 	},
 	[ALC262_HIPPO_1] = {
 		.mixers = { alc262_hippo1_mixer },
@@ -12830,9 +12719,9 @@ static struct alc_config_preset alc262_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc262_modes),
 		.channel_mode = alc262_modes,
 		.input_mux = &alc262_capture_source,
-		.unsol_event = alc262_hippo_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc262_hippo1_setup,
-		.init_hook = alc262_hippo_automute,
+		.init_hook = alc_inithook,
 	},
 	[ALC262_FUJITSU] = {
 		.mixers = { alc262_fujitsu_mixer },
@@ -12857,8 +12746,9 @@ static struct alc_config_preset alc262_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc262_modes),
 		.channel_mode = alc262_modes,
 		.input_mux = &alc262_HP_capture_source,
-		.unsol_event = alc262_hp_bpc_unsol_event,
-		.init_hook = alc262_hp_bpc_automute,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc262_hp_bpc_setup,
+		.init_hook = alc_inithook,
 	},
 	[ALC262_HP_BPC_D7000_WF] = {
 		.mixers = { alc262_HP_BPC_WildWest_mixer },
@@ -12869,8 +12759,9 @@ static struct alc_config_preset alc262_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc262_modes),
 		.channel_mode = alc262_modes,
 		.input_mux = &alc262_HP_D7000_capture_source,
-		.unsol_event = alc262_hp_wildwest_unsol_event,
-		.init_hook = alc262_hp_wildwest_automute,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc262_hp_wildwest_setup,
+		.init_hook = alc_inithook,
 	},
 	[ALC262_HP_BPC_D7000_WL] = {
 		.mixers = { alc262_HP_BPC_WildWest_mixer,
@@ -12882,8 +12773,9 @@ static struct alc_config_preset alc262_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc262_modes),
 		.channel_mode = alc262_modes,
 		.input_mux = &alc262_HP_D7000_capture_source,
-		.unsol_event = alc262_hp_wildwest_unsol_event,
-		.init_hook = alc262_hp_wildwest_automute,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc262_hp_wildwest_setup,
+		.init_hook = alc_inithook,
 	},
 	[ALC262_HP_TC_T5735] = {
 		.mixers = { alc262_hp_t5735_mixer },
@@ -12926,9 +12818,9 @@ static struct alc_config_preset alc262_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc262_modes),
 		.channel_mode = alc262_modes,
 		.input_mux = &alc262_capture_source,
-		.unsol_event = alc262_hippo_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc262_hippo_setup,
-		.init_hook = alc262_hippo_automute,
+		.init_hook = alc_inithook,
 	},
 	[ALC262_BENQ_T31] = {
 		.mixers = { alc262_benq_t31_mixer },
@@ -12940,9 +12832,9 @@ static struct alc_config_preset alc262_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc262_modes),
 		.channel_mode = alc262_modes,
 		.input_mux = &alc262_capture_source,
-		.unsol_event = alc262_hippo_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc262_hippo_setup,
-		.init_hook = alc262_hippo_automute,
+		.init_hook = alc_inithook,
 	},
 	[ALC262_ULTRA] = {
 		.mixers = { alc262_ultra_mixer },
@@ -13008,9 +12900,9 @@ static struct alc_config_preset alc262_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc262_modes),
 		.channel_mode = alc262_modes,
 		.input_mux = &alc262_capture_source,
-		.unsol_event = alc262_hippo_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc262_hippo_setup,
-		.init_hook = alc262_hippo_automute,
+		.init_hook = alc_inithook,
 	},
 	[ALC262_TYAN] = {
 		.mixers = { alc262_tyan_mixer },
@@ -13347,9 +13239,7 @@ static struct hda_verb alc268_acer_verbs[] = {
 };
 
 /* unsolicited event for HP jack sensing */
-#define alc268_toshiba_unsol_event	alc262_hippo_unsol_event
 #define alc268_toshiba_setup		alc262_hippo_setup
-#define alc268_toshiba_automute		alc262_hippo_automute
 
 static void alc268_acer_unsol_event(struct hda_codec *codec,
 				       unsigned int res)
@@ -13985,9 +13875,9 @@ static struct alc_config_preset alc268_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc268_modes),
 		.channel_mode = alc268_modes,
 		.input_mux = &alc268_capture_source,
-		.unsol_event = alc268_toshiba_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc268_toshiba_setup,
-		.init_hook = alc268_toshiba_automute,
+		.init_hook = alc_inithook,
 	},
 	[ALC268_ACER] = {
 		.mixers = { alc268_acer_mixer, alc268_capture_alt_mixer,
@@ -14073,8 +13963,9 @@ static struct alc_config_preset alc268_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc268_modes),
 		.channel_mode = alc268_modes,
 		.input_mux = &alc268_capture_source,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc268_toshiba_setup,
-		.init_hook = alc268_toshiba_automute,
+		.init_hook = alc_inithook,
 	},
 #ifdef CONFIG_SND_DEBUG
 	[ALC268_TEST] = {
@@ -18249,16 +18140,6 @@ static void alc662_lenovo_101e_setup(struct hda_codec *codec)
 	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
-/* unsolicited event for HP jack sensing */
-static void alc662_eeepc_unsol_event(struct hda_codec *codec,
-				     unsigned int res)
-{
-	if ((res >> 26) == ALC880_MIC_EVENT)
-		alc_mic_automute(codec);
-	else
-		alc262_hippo_unsol_event(codec, res);
-}
-
 static void alc662_eeepc_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
@@ -18271,22 +18152,16 @@ static void alc662_eeepc_setup(struct hda_codec *codec)
 	spec->auto_mic = 1;
 }
 
-static void alc662_eeepc_inithook(struct hda_codec *codec)
-{
-	alc262_hippo_automute(codec);
-	alc_mic_automute(codec);
-}
-
 static void alc662_eeepc_ep20_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
 
 	spec->autocfg.hp_pins[0] = 0x14;
 	spec->autocfg.speaker_pins[0] = 0x1b;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
-#define alc662_eeepc_ep20_inithook	alc262_hippo_master_update
-
 static void alc663_m51va_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
@@ -18675,9 +18550,9 @@ static struct alc_config_preset alc662_presets[] = {
 		.dac_nids = alc662_dac_nids,
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
 		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc662_eeepc_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc662_eeepc_setup,
-		.init_hook = alc662_eeepc_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC662_ASUS_EEEPC_EP20] = {
 		.mixers = { alc662_eeepc_ep20_mixer,
@@ -18690,9 +18565,9 @@ static struct alc_config_preset alc662_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
 		.channel_mode = alc662_3ST_6ch_modes,
 		.input_mux = &alc662_lenovo_101e_capture_source,
-		.unsol_event = alc662_eeepc_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc662_eeepc_ep20_setup,
-		.init_hook = alc662_eeepc_ep20_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC662_ECS] = {
 		.mixers = { alc662_ecs_mixer },
@@ -18703,9 +18578,9 @@ static struct alc_config_preset alc662_presets[] = {
 		.dac_nids = alc662_dac_nids,
 		.num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
 		.channel_mode = alc662_3ST_2ch_modes,
-		.unsol_event = alc662_eeepc_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
 		.setup = alc662_eeepc_setup,
-		.init_hook = alc662_eeepc_inithook,
+		.init_hook = alc_inithook,
 	},
 	[ALC663_ASUS_M51VA] = {
 		.mixers = { alc663_m51va_mixer },
-- 
1.7.4.2

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

* [PATCH 07/10] ALSA: hda - More reduction of redundant automute codes in Realtek parser
  2011-04-29 17:18 [PATCH 0/10] Realtek auto-parser updates Takashi Iwai
                   ` (5 preceding siblings ...)
  2011-04-29 17:18 ` [PATCH 06/10] ALSA: hda - Consolidate auto-mute with master-switch " Takashi Iwai
@ 2011-04-29 17:18 ` Takashi Iwai
  2011-04-29 17:18 ` [PATCH 08/10] ALSA: hda - Add support for Line-Out automute to Realtek auto-parser Takashi Iwai
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 24+ messages in thread
From: Takashi Iwai @ 2011-04-29 17:18 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai

Removed the redundant codes by replacing with the common helper
functions.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c |  222 +++++++++--------------------------------
 1 files changed, 49 insertions(+), 173 deletions(-)

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index a97e460..b76d3b3 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -390,7 +390,6 @@ struct alc_spec {
 	void (*shutup)(struct hda_codec *codec);
 
 	/* for pin sensing */
-	unsigned int sense_updated: 1;
 	unsigned int jack_present: 1;
 	unsigned int line_jack_present:1;
 	unsigned int master_mute:1;
@@ -11797,40 +11796,15 @@ static struct hda_input_mux alc262_HP_D7000_capture_source = {
 	},
 };
 
-/* mute/unmute internal speaker according to the hp jacks and mute state */
-static void alc262_fujitsu_automute(struct hda_codec *codec, int force)
+static void alc262_fujitsu_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
-	unsigned int mute;
-
-	if (force || !spec->sense_updated) {
-		spec->jack_present = snd_hda_jack_detect(codec, 0x14) ||
-				     snd_hda_jack_detect(codec, 0x1b);
-		spec->sense_updated = 1;
-	}
-	/* unmute internal speaker only if both HPs are unplugged and
-	 * master switch is on
-	 */
-	if (spec->jack_present)
-		mute = HDA_AMP_MUTE;
-	else
-		mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);
-	snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, mute);
-}
-
-/* unsolicited event for HP jack sensing */
-static void alc262_fujitsu_unsol_event(struct hda_codec *codec,
-				       unsigned int res)
-{
-	if ((res >> 26) != ALC_HP_EVENT)
-		return;
-	alc262_fujitsu_automute(codec, 1);
-}
 
-static void alc262_fujitsu_init_hook(struct hda_codec *codec)
-{
-	alc262_fujitsu_automute(codec, 1);
+	spec->autocfg.hp_pins[0] = 0x14;
+	spec->autocfg.hp_pins[1] = 0x1b;
+	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 /* bind volumes of both NID 0x0c and 0x0d */
@@ -11843,78 +11817,15 @@ static struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
 	},
 };
 
-/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc262_lenovo_3000_automute(struct hda_codec *codec, int force)
-{
-	struct alc_spec *spec = codec->spec;
-	unsigned int mute;
-
-	if (force || !spec->sense_updated) {
-		spec->jack_present = snd_hda_jack_detect(codec, 0x1b);
-		spec->sense_updated = 1;
-	}
-	if (spec->jack_present) {
-		/* mute internal speaker */
-		snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
-					 HDA_AMP_MUTE, HDA_AMP_MUTE);
-		snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
-					 HDA_AMP_MUTE, HDA_AMP_MUTE);
-	} else {
-		/* unmute internal speaker if necessary */
-		mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
-		snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
-					 HDA_AMP_MUTE, mute);
-		snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
-					 HDA_AMP_MUTE, mute);
-	}
-}
-
-/* unsolicited event for HP jack sensing */
-static void alc262_lenovo_3000_unsol_event(struct hda_codec *codec,
-				       unsigned int res)
-{
-	if ((res >> 26) != ALC_HP_EVENT)
-		return;
-	alc262_lenovo_3000_automute(codec, 1);
-}
-
-static int amp_stereo_mute_update(struct hda_codec *codec, hda_nid_t nid,
-				  int dir, int idx, long *valp)
-{
-	int i, change = 0;
-
-	for (i = 0; i < 2; i++, valp++)
-		change |= snd_hda_codec_amp_update(codec, nid, i, dir, idx,
-						   HDA_AMP_MUTE,
-						   *valp ? 0 : HDA_AMP_MUTE);
-	return change;
-}
-
-/* bind hp and internal speaker mute (with plug check) */
-static int alc262_fujitsu_master_sw_put(struct snd_kcontrol *kcontrol,
-					 struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	long *valp = ucontrol->value.integer.value;
-	int change;
-
-	change = amp_stereo_mute_update(codec, 0x14, HDA_OUTPUT, 0, valp);
-	change |= amp_stereo_mute_update(codec, 0x1b, HDA_OUTPUT, 0, valp);
-	if (change)
-		alc262_fujitsu_automute(codec, 0);
-	return change;
-}
-
 static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
 	HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Master Playback Switch",
-		.subdevice = HDA_SUBDEV_AMP_FLAG,
-		.info = snd_hda_mixer_amp_switch_info,
-		.get = snd_hda_mixer_amp_switch_get,
-		.put = alc262_fujitsu_master_sw_put,
-		.private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
+		.subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
+		.info = snd_ctl_boolean_mono_info,
+		.get = alc262_hp_master_sw_get,
+		.put = alc262_hp_master_sw_put,
 	},
 	{
 		.iface = NID_MAPPING,
@@ -11932,18 +11843,15 @@ static struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
 	{ } /* end */
 };
 
-/* bind hp and internal speaker mute (with plug check) */
-static int alc262_lenovo_3000_master_sw_put(struct snd_kcontrol *kcontrol,
-					 struct snd_ctl_elem_value *ucontrol)
+static void alc262_lenovo_3000_setup(struct hda_codec *codec)
 {
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	long *valp = ucontrol->value.integer.value;
-	int change;
+	struct alc_spec *spec = codec->spec;
 
-	change = amp_stereo_mute_update(codec, 0x1b, HDA_OUTPUT, 0, valp);
-	if (change)
-		alc262_lenovo_3000_automute(codec, 0);
-	return change;
+	spec->autocfg.hp_pins[0] = 0x1b;
+	spec->autocfg.speaker_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[1] = 0x16;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
 static struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
@@ -11951,11 +11859,10 @@ static struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Master Playback Switch",
-		.subdevice = HDA_SUBDEV_AMP_FLAG,
-		.info = snd_hda_mixer_amp_switch_info,
-		.get = snd_hda_mixer_amp_switch_get,
-		.put = alc262_lenovo_3000_master_sw_put,
-		.private_value = HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
+		.subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
+		.info = snd_ctl_boolean_mono_info,
+		.get = alc262_hp_master_sw_get,
+		.put = alc262_hp_master_sw_put,
 	},
 	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
 	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
@@ -12734,8 +12641,9 @@ static struct alc_config_preset alc262_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc262_modes),
 		.channel_mode = alc262_modes,
 		.input_mux = &alc262_fujitsu_capture_source,
-		.unsol_event = alc262_fujitsu_unsol_event,
-		.init_hook = alc262_fujitsu_init_hook,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc262_fujitsu_setup,
+		.init_hook = alc_inithook,
 	},
 	[ALC262_HP_BPC] = {
 		.mixers = { alc262_HP_BPC_mixer },
@@ -12863,7 +12771,9 @@ static struct alc_config_preset alc262_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc262_modes),
 		.channel_mode = alc262_modes,
 		.input_mux = &alc262_fujitsu_capture_source,
-		.unsol_event = alc262_lenovo_3000_unsol_event,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc262_lenovo_3000_setup,
+		.init_hook = alc_inithook,
 	},
 	[ALC262_NEC] = {
 		.mixers = { alc262_nec_mixer },
@@ -13133,38 +13043,18 @@ static struct hda_bind_ctls alc268_acer_bind_master_vol = {
 	},
 };
 
-/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc268_acer_automute(struct hda_codec *codec, int force)
+static void alc268_acer_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
-	unsigned int mute;
 
-	if (force || !spec->sense_updated) {
-		spec->jack_present = snd_hda_jack_detect(codec, 0x14);
-		spec->sense_updated = 1;
-	}
-	if (spec->jack_present)
-		mute = HDA_AMP_MUTE; /* mute internal speaker */
-	else /* unmute internal speaker if necessary */
-		mute = snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0);
-	snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, mute);
+	spec->autocfg.hp_pins[0] = 0x14;
+	spec->autocfg.speaker_pins[0] = 0x15;
+	spec->automute = 1;
+	spec->automute_mode = ALC_AUTOMUTE_AMP;
 }
 
-
-/* bind hp and internal speaker mute (with plug check) */
-static int alc268_acer_master_sw_put(struct snd_kcontrol *kcontrol,
-				     struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	long *valp = ucontrol->value.integer.value;
-	int change;
-
-	change = amp_stereo_mute_update(codec, 0x14, HDA_OUTPUT, 0, valp);
-	if (change)
-		alc268_acer_automute(codec, 0);
-	return change;
-}
+#define alc268_acer_master_sw_get	alc262_hp_master_sw_get
+#define alc268_acer_master_sw_put	alc262_hp_master_sw_put
 
 static struct snd_kcontrol_new alc268_acer_aspire_one_mixer[] = {
 	/* output mixer control */
@@ -13172,11 +13062,10 @@ static struct snd_kcontrol_new alc268_acer_aspire_one_mixer[] = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Master Playback Switch",
-		.subdevice = HDA_SUBDEV_AMP_FLAG,
-		.info = snd_hda_mixer_amp_switch_info,
-		.get = snd_hda_mixer_amp_switch_get,
+		.subdevice = HDA_SUBDEV_NID_FLAG | 0x15,
+		.info = snd_ctl_boolean_mono_info,
+		.get = alc268_acer_master_sw_get,
 		.put = alc268_acer_master_sw_put,
-		.private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
 	},
 	HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x18, 0, HDA_INPUT),
 	{ }
@@ -13188,11 +13077,10 @@ static struct snd_kcontrol_new alc268_acer_mixer[] = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Master Playback Switch",
-		.subdevice = HDA_SUBDEV_AMP_FLAG,
-		.info = snd_hda_mixer_amp_switch_info,
-		.get = snd_hda_mixer_amp_switch_get,
+		.subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
+		.info = snd_ctl_boolean_mono_info,
+		.get = alc268_acer_master_sw_get,
 		.put = alc268_acer_master_sw_put,
-		.private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
 	},
 	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
@@ -13206,11 +13094,10 @@ static struct snd_kcontrol_new alc268_acer_dmic_mixer[] = {
 	{
 		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 		.name = "Master Playback Switch",
-		.subdevice = HDA_SUBDEV_AMP_FLAG,
-		.info = snd_hda_mixer_amp_switch_info,
-		.get = snd_hda_mixer_amp_switch_get,
+		.subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
+		.info = snd_ctl_boolean_mono_info,
+		.get = alc268_acer_master_sw_get,
 		.put = alc268_acer_master_sw_put,
-		.private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
 	},
 	HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
 	HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
@@ -13241,19 +13128,6 @@ static struct hda_verb alc268_acer_verbs[] = {
 /* unsolicited event for HP jack sensing */
 #define alc268_toshiba_setup		alc262_hippo_setup
 
-static void alc268_acer_unsol_event(struct hda_codec *codec,
-				       unsigned int res)
-{
-	if ((res >> 26) != ALC880_HP_EVENT)
-		return;
-	alc268_acer_automute(codec, 1);
-}
-
-static void alc268_acer_init_hook(struct hda_codec *codec)
-{
-	alc268_acer_automute(codec, 1);
-}
-
 static void alc268_acer_lc_setup(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
@@ -13893,8 +13767,9 @@ static struct alc_config_preset alc268_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc268_modes),
 		.channel_mode = alc268_modes,
 		.input_mux = &alc268_acer_capture_source,
-		.unsol_event = alc268_acer_unsol_event,
-		.init_hook = alc268_acer_init_hook,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc268_acer_setup,
+		.init_hook = alc_inithook,
 	},
 	[ALC268_ACER_DMIC] = {
 		.mixers = { alc268_acer_dmic_mixer, alc268_capture_alt_mixer,
@@ -13910,8 +13785,9 @@ static struct alc_config_preset alc268_presets[] = {
 		.num_channel_mode = ARRAY_SIZE(alc268_modes),
 		.channel_mode = alc268_modes,
 		.input_mux = &alc268_acer_dmic_capture_source,
-		.unsol_event = alc268_acer_unsol_event,
-		.init_hook = alc268_acer_init_hook,
+		.unsol_event = alc_sku_unsol_event,
+		.setup = alc268_acer_setup,
+		.init_hook = alc_inithook,
 	},
 	[ALC268_ACER_ASPIRE_ONE] = {
 		.mixers = { alc268_acer_aspire_one_mixer,
-- 
1.7.4.2

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

* [PATCH 08/10] ALSA: hda - Add support for Line-Out automute to Realtek auto-parser
  2011-04-29 17:18 [PATCH 0/10] Realtek auto-parser updates Takashi Iwai
                   ` (6 preceding siblings ...)
  2011-04-29 17:18 ` [PATCH 07/10] ALSA: hda - More reduction of redundant automute codes in Realtek parser Takashi Iwai
@ 2011-04-29 17:18 ` Takashi Iwai
  2011-04-30  6:52   ` David Henningsson
  2011-04-29 17:18 ` [PATCH 09/10] ALSA: hda - More line-out auto-mute support for Realtek Takashi Iwai
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 24+ messages in thread
From: Takashi Iwai @ 2011-04-29 17:18 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai

By popular demands, I add the functionality to mute / unmute the
line-out jacks per the headphone plug / unplug.  For achieving this
and keeping the compatibility with the old behavior, the new mixer
enum "Auto-Mute Mode" is added.  With this, user can control the
auto-mute behavior either disabled, speaker-only or lineout+speaker.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c |  146 +++++++++++++++++++++++++++++++++++++----
 1 files changed, 133 insertions(+), 13 deletions(-)

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index b76d3b3..9e2594d 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1129,18 +1129,28 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
 static void update_speakers(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
+	int on;
 
+	if (!spec->automute)
+		on = 0;
+	else
+		on = spec->jack_present | spec->line_jack_present;
+	on |= spec->master_mute;
 	do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
-		    spec->autocfg.speaker_pins,
-		    spec->jack_present | spec->line_jack_present |
-		    spec->master_mute, false);
+		    spec->autocfg.speaker_pins, on, false);
 
 	/* toggle line-out mutes if needed, too */
-	if (!spec->automute_lines)
+	/* if LO is a copy of either HP or Speaker, don't need to handle it */
+	if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
+	    spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
 		return;
+	if (!spec->automute_lines || !spec->automute)
+		on = 0;
+	else
+		on = spec->jack_present;
+	on |= spec->master_mute;
 	do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
-		    spec->autocfg.line_out_pins,
-		    spec->jack_present | spec->master_mute, false);
+		    spec->autocfg.line_out_pins, on, false);
 }
 
 static void alc_hp_automute(struct hda_codec *codec)
@@ -1414,6 +1424,95 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
 	}
 }
 
+static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
+				  struct snd_ctl_elem_info *uinfo)
+{
+	static const char * const texts[] = {
+		"Disabled", "Speaker Only", "Line-Out+Speaker"
+	};
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 3;
+	if (uinfo->value.enumerated.item >= 3)
+		uinfo->value.enumerated.item = 2;
+	strcpy(uinfo->value.enumerated.name,
+	       texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int alc_automute_mode_get(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	unsigned int val;
+	if (!spec->automute)
+		val = 0;
+	else if (!spec->automute_lines)
+		val = 1;
+	else
+		val = 2;
+	ucontrol->value.enumerated.item[0] = val;
+	return 0;
+}
+
+static int alc_automute_mode_put(struct snd_kcontrol *kcontrol,
+				 struct snd_ctl_elem_value *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+
+	switch (ucontrol->value.enumerated.item[0]) {
+	case 0:
+		if (!spec->automute)
+			return 0;
+		spec->automute = 0;
+		break;
+	case 1:
+		if (spec->automute && !spec->automute_lines)
+			return 0;
+		spec->automute = 1;
+		spec->automute_lines = 0;
+		break;
+	case 2:
+		if (spec->automute && spec->automute_lines)
+			return 0;
+		spec->automute = 1;
+		spec->automute_lines = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+	update_speakers(codec);
+	return 1;
+}
+
+static struct snd_kcontrol_new alc_automute_mode_enum = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Auto-Mute Mode",
+	.info = alc_automute_mode_info,
+	.get = alc_automute_mode_get,
+	.put = alc_automute_mode_put,
+};
+
+static struct snd_kcontrol_new *alc_kcontrol_new(struct alc_spec *spec);
+
+static int alc_add_automute_mode_enum(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	struct snd_kcontrol_new *knew;
+
+	knew = alc_kcontrol_new(spec);
+	if (!knew)
+		return -ENOMEM;
+	*knew = alc_automute_mode_enum;
+	knew->name = kstrdup("Auto-Mute Mode", GFP_KERNEL);
+	if (!knew->name)
+		return -ENOMEM;
+	return 0;
+}
+
 static void alc_init_auto_hp(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
@@ -1440,14 +1539,37 @@ static void alc_init_auto_hp(struct hda_codec *codec)
 	}
 
 	for (i = 0; i < cfg->hp_outs; i++) {
+		hda_nid_t nid = cfg->hp_pins[i];
+		if (!(snd_hda_query_pin_caps(codec, nid) &
+		      AC_PINCAP_PRES_DETECT))
+			continue;
 		snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
-			    cfg->hp_pins[i]);
-		snd_hda_codec_write_cache(codec, cfg->hp_pins[i], 0,
+			    nid);
+		snd_hda_codec_write_cache(codec, nid, 0,
 				  AC_VERB_SET_UNSOLICITED_ENABLE,
 				  AC_USRSP_EN | ALC880_HP_EVENT);
 		spec->automute = 1;
 		spec->automute_mode = ALC_AUTOMUTE_PIN;
 	}
+	if (spec->automute && cfg->line_out_pins[0] &&
+	    cfg->line_out_pins[0] != cfg->hp_pins[0] &&
+	    cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
+		for (i = 0; i < cfg->line_outs; i++) {
+			hda_nid_t nid = cfg->line_out_pins[i];
+			if (!(snd_hda_query_pin_caps(codec, nid) &
+			      AC_PINCAP_PRES_DETECT))
+				continue;
+			snd_printdd("realtek: Enable Line-Out auto-muting "
+				    "on NID 0x%x\n", nid);
+			snd_hda_codec_write_cache(codec, nid, 0,
+					AC_VERB_SET_UNSOLICITED_ENABLE,
+					AC_USRSP_EN | ALC880_FRONT_EVENT);
+			spec->detect_line = 1;
+		}
+		/* create a control for automute mode */
+		alc_add_automute_mode_enum(codec);
+		spec->automute_lines = 1;
+	}
 	spec->unsol_event = alc_sku_unsol_event;
 }
 
@@ -1684,9 +1806,6 @@ do_sku:
 				return 1;
 		spec->autocfg.hp_pins[0] = nid;
 	}
-
-	alc_init_auto_hp(codec);
-	alc_init_auto_mic(codec);
 	return 1;
 }
 
@@ -1699,9 +1818,10 @@ static void alc_ssid_check(struct hda_codec *codec,
 		snd_printd("realtek: "
 			   "Enable default setup for auto mode as fallback\n");
 		spec->init_amp = ALC_INIT_DEFAULT;
-		alc_init_auto_hp(codec);
-		alc_init_auto_mic(codec);
 	}
+
+	alc_init_auto_hp(codec);
+	alc_init_auto_mic(codec);
 }
 
 /*
-- 
1.7.4.2

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

* [PATCH 09/10] ALSA: hda - More line-out auto-mute support for Realtek
  2011-04-29 17:18 [PATCH 0/10] Realtek auto-parser updates Takashi Iwai
                   ` (7 preceding siblings ...)
  2011-04-29 17:18 ` [PATCH 08/10] ALSA: hda - Add support for Line-Out automute to Realtek auto-parser Takashi Iwai
@ 2011-04-29 17:18 ` Takashi Iwai
  2011-04-29 17:18 ` [PATCH 10/10] ALSA: hda - Add Auto-Mute Mode enum for two-output cases Takashi Iwai
  2011-04-30  2:44 ` [PATCH 0/10] Realtek auto-parser updates Raymond Yau
  10 siblings, 0 replies; 24+ messages in thread
From: Takashi Iwai @ 2011-04-29 17:18 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai

Not only supporting the line-out automute as additional feature
to the existing headphone automute, now the headphone jack can
mute the line-out alone even without the speaker outs.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c |   15 +++++++++------
 1 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 9e2594d..3e41d56 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -1517,16 +1517,19 @@ static void alc_init_auto_hp(struct hda_codec *codec)
 {
 	struct alc_spec *spec = codec->spec;
 	struct auto_pin_cfg *cfg = &spec->autocfg;
+	int present = 0;
 	int i;
 
-	if (!cfg->hp_pins[0]) {
-		if (cfg->line_out_type != AUTO_PIN_HP_OUT)
-			return;
-	}
+	if (cfg->hp_pins[0])
+		present++;
+	if (cfg->line_out_pins[0])
+		present++;
+	if (cfg->speaker_pins[0])
+		present++;
+	if (present < 2) /* need two different output types */
+		return;
 
 	if (!cfg->speaker_pins[0]) {
-		if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
-			return;
 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
 		       sizeof(cfg->speaker_pins));
 		cfg->speaker_outs = cfg->line_outs;
-- 
1.7.4.2

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

* [PATCH 10/10] ALSA: hda - Add Auto-Mute Mode enum for two-output cases
  2011-04-29 17:18 [PATCH 0/10] Realtek auto-parser updates Takashi Iwai
                   ` (8 preceding siblings ...)
  2011-04-29 17:18 ` [PATCH 09/10] ALSA: hda - More line-out auto-mute support for Realtek Takashi Iwai
@ 2011-04-29 17:18 ` Takashi Iwai
  2011-04-30  2:44 ` [PATCH 0/10] Realtek auto-parser updates Raymond Yau
  10 siblings, 0 replies; 24+ messages in thread
From: Takashi Iwai @ 2011-04-29 17:18 UTC (permalink / raw)
  To: alsa-devel; +Cc: Takashi Iwai

The Auto-Mute Mode control is useful even when only two outputs
(e.g. HP and speaker) are available.  Then user can enable/disable
the auto-mute behavior on the fly.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c |   32 ++++++++++++++++++++++++++------
 1 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 3e41d56..faede0f 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -397,6 +397,7 @@ struct alc_spec {
 	unsigned int automute:1;	/* HP automute enabled */
 	unsigned int detect_line:1;	/* Line-out detection enabled */
 	unsigned int automute_lines:1;	/* automute line-out as well */
+	unsigned int automute_hp_lo:1;	/* both HP and LO available */
 
 	/* other flags */
 	unsigned int no_analog :1; /* digital I/O only */
@@ -1427,15 +1428,27 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
 static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
 				  struct snd_ctl_elem_info *uinfo)
 {
-	static const char * const texts[] = {
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	static const char * const texts2[] = {
+		"Disabled", "Enabled"
+	};
+	static const char * const texts3[] = {
 		"Disabled", "Speaker Only", "Line-Out+Speaker"
 	};
+	const char * const *texts;
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
 	uinfo->count = 1;
-	uinfo->value.enumerated.items = 3;
-	if (uinfo->value.enumerated.item >= 3)
-		uinfo->value.enumerated.item = 2;
+	if (spec->automute_hp_lo) {
+		uinfo->value.enumerated.items = 3;
+		texts = texts3;
+	} else {
+		uinfo->value.enumerated.items = 2;
+		texts = texts2;
+	}
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
 	strcpy(uinfo->value.enumerated.name,
 	       texts[uinfo->value.enumerated.item]);
 	return 0;
@@ -1476,6 +1489,8 @@ static int alc_automute_mode_put(struct snd_kcontrol *kcontrol,
 		spec->automute_lines = 0;
 		break;
 	case 2:
+		if (!spec->automute_hp_lo)
+			return -EINVAL;
 		if (spec->automute && spec->automute_lines)
 			return 0;
 		spec->automute = 1;
@@ -1528,6 +1543,8 @@ static void alc_init_auto_hp(struct hda_codec *codec)
 		present++;
 	if (present < 2) /* need two different output types */
 		return;
+	if (present == 3)
+		spec->automute_hp_lo = 1; /* both HP and LO automute */
 
 	if (!cfg->speaker_pins[0]) {
 		memcpy(cfg->speaker_pins, cfg->line_out_pins,
@@ -1569,11 +1586,14 @@ static void alc_init_auto_hp(struct hda_codec *codec)
 					AC_USRSP_EN | ALC880_FRONT_EVENT);
 			spec->detect_line = 1;
 		}
+		spec->automute_lines = 1;
+	}
+
+	if (spec->automute) {
 		/* create a control for automute mode */
 		alc_add_automute_mode_enum(codec);
-		spec->automute_lines = 1;
+		spec->unsol_event = alc_sku_unsol_event;
 	}
-	spec->unsol_event = alc_sku_unsol_event;
 }
 
 static void alc_init_auto_mic(struct hda_codec *codec)
-- 
1.7.4.2

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

* Re: [PATCH 0/10] Realtek auto-parser updates
  2011-04-29 17:18 [PATCH 0/10] Realtek auto-parser updates Takashi Iwai
                   ` (9 preceding siblings ...)
  2011-04-29 17:18 ` [PATCH 10/10] ALSA: hda - Add Auto-Mute Mode enum for two-output cases Takashi Iwai
@ 2011-04-30  2:44 ` Raymond Yau
  2011-04-30 10:24   ` Takashi Iwai
  10 siblings, 1 reply; 24+ messages in thread
From: Raymond Yau @ 2011-04-30  2:44 UTC (permalink / raw)
  To: Takashi Iwai, ALSA Development Mailing List

2011/4/30 Takashi Iwai <tiwai@suse.de>

> Hi, this is a series of patches I'm going to apply as 2.6.40 material.
> Basically this adds the missing features to BIOS auto-parser mode, the
> support of multi-channel setup (2/4/6-channels) and the auto-mute of
> line-out jacks as well as speakers.
>
> Many changes have been done but mostly in systematic manner.
> I've checked through hda-emu and a few machines with Realtek codecs,
> but of course can't cover all changes I made.
>
> If you see any issues with the updated tree, please let me know.
>
>
How about those 4 jacks 8 channels notebook (e.g. ms-1656)  ?

using hda-emu and codec info from

https://bugtrack.alsa-project.org/alsa-bug/view.php?id=5244

0x1b is internal speaker
0x14 is the green jack
0x17 is the grey jack
0x18 is the pink jack
0x1a is the blue jack


autoconfig: line_outs=1 (0x17/0x0/0x0/0x0/0x0) type:line
   speaker_outs=1 (0x1b/0x0/0x0/0x0/0x0)
   hp_outs=1 (0x14/0x0/0x0/0x0/0x0)
   mono: mono_out=0x0
   dig-out=0x1e/0x0
   inputs: Mic=0x18 Internal Mic=0x19 Line=0x1a

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

* Re: [PATCH 08/10] ALSA: hda - Add support for Line-Out automute to Realtek auto-parser
  2011-04-29 17:18 ` [PATCH 08/10] ALSA: hda - Add support for Line-Out automute to Realtek auto-parser Takashi Iwai
@ 2011-04-30  6:52   ` David Henningsson
  2011-04-30 10:23     ` Takashi Iwai
  0 siblings, 1 reply; 24+ messages in thread
From: David Henningsson @ 2011-04-30  6:52 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: alsa-devel

On 2011-04-29 19:18, Takashi Iwai wrote:
> By popular demands, I add the functionality to mute / unmute the
> line-out jacks per the headphone plug / unplug.  For achieving this
> and keeping the compatibility with the old behavior, the new mixer
> enum "Auto-Mute Mode" is added.  With this, user can control the
> auto-mute behavior either disabled, speaker-only or lineout+speaker.

Hi Takashi,

Great to see these improvements! I have a question about this patch:

There are three ways we can auto-mute:

Headphones might mute Internal Speakers.
Headphones might mute Line out.
Line out might mute Internal Speakers.

Are we considering the third option here or is that still unsupported?

Also, it might be slightly confusing for the end-user to have options 
that are irrelevant, e g if there are no internal speakers (or line-out 
for that matter), that option will still show up. Right?

-- 
David Henningsson, Canonical Ltd.
http://launchpad.net/~diwic

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

* Re: [PATCH 08/10] ALSA: hda - Add support for Line-Out automute to Realtek auto-parser
  2011-04-30  6:52   ` David Henningsson
@ 2011-04-30 10:23     ` Takashi Iwai
  2011-05-02  0:56       ` Raymond Yau
  2011-05-02  5:55       ` Raymond Yau
  0 siblings, 2 replies; 24+ messages in thread
From: Takashi Iwai @ 2011-04-30 10:23 UTC (permalink / raw)
  To: David Henningsson; +Cc: alsa-devel

At Sat, 30 Apr 2011 08:52:58 +0200,
David Henningsson wrote:
> 
> On 2011-04-29 19:18, Takashi Iwai wrote:
> > By popular demands, I add the functionality to mute / unmute the
> > line-out jacks per the headphone plug / unplug.  For achieving this
> > and keeping the compatibility with the old behavior, the new mixer
> > enum "Auto-Mute Mode" is added.  With this, user can control the
> > auto-mute behavior either disabled, speaker-only or lineout+speaker.
> 
> Hi Takashi,
> 
> Great to see these improvements! I have a question about this patch:
> 
> There are three ways we can auto-mute:
> 
> Headphones might mute Internal Speakers.
> Headphones might mute Line out.
> Line out might mute Internal Speakers.
> 
> Are we considering the third option here or is that still unsupported?

Yes, it'll behave so.  Now we have "Auto-Mute Mode" enum control, and
it provides "Disable", "Speaker only" and "Line-Out+Speaker" choice in
the case of LO+HP+SPK case.  When only HP+LO, LO+SPK  or HP+SPK are
present, this enum gives only "Disable" and "Enable" choice.

> Also, it might be slightly confusing for the end-user to have options 
> that are irrelevant, e g if there are no internal speakers (or line-out 
> for that matter), that option will still show up. Right?

If there is only one output type, this enum won't appear.

I guess this should cover most of use-cases, and flexible enough for
covering both old and new behavior.


thanks,

Takashi

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

* Re: [PATCH 0/10] Realtek auto-parser updates
  2011-04-30  2:44 ` [PATCH 0/10] Realtek auto-parser updates Raymond Yau
@ 2011-04-30 10:24   ` Takashi Iwai
  2011-05-01  0:35     ` Raymond Yau
  0 siblings, 1 reply; 24+ messages in thread
From: Takashi Iwai @ 2011-04-30 10:24 UTC (permalink / raw)
  To: Raymond Yau; +Cc: ALSA Development Mailing List

At Sat, 30 Apr 2011 10:44:13 +0800,
Raymond Yau wrote:
> 
> [1  <text/plain; ISO-8859-1 (7bit)>]
> 2011/4/30 Takashi Iwai <tiwai@suse.de>
> 
> > Hi, this is a series of patches I'm going to apply as 2.6.40 material.
> > Basically this adds the missing features to BIOS auto-parser mode, the
> > support of multi-channel setup (2/4/6-channels) and the auto-mute of
> > line-out jacks as well as speakers.
> >
> > Many changes have been done but mostly in systematic manner.
> > I've checked through hda-emu and a few machines with Realtek codecs,
> > but of course can't cover all changes I made.
> >
> > If you see any issues with the updated tree, please let me know.
> >
> >
> How about those 4 jacks 8 channels notebook (e.g. ms-1656)  ?

Currently, the detection of LO/MIC extension depends on the location
of the jacks.  It assumes that these jacks are located at the same
place as the corresponding line-out jack(s).

I wrote in that way to avoid mis-detection.  It'd be easy to change it
to look through other locations.


Takashi


> using hda-emu and codec info from
> 
> https://bugtrack.alsa-project.org/alsa-bug/view.php?id=5244
> 
> 0x1b is internal speaker
> 0x14 is the green jack
> 0x17 is the grey jack
> 0x18 is the pink jack
> 0x1a is the blue jack
> 
> 
> autoconfig: line_outs=1 (0x17/0x0/0x0/0x0/0x0) type:line
>    speaker_outs=1 (0x1b/0x0/0x0/0x0/0x0)
>    hp_outs=1 (0x14/0x0/0x0/0x0/0x0)
>    mono: mono_out=0x0
>    dig-out=0x1e/0x0
>    inputs: Mic=0x18 Internal Mic=0x19 Line=0x1a
> 

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

* Re: [PATCH 0/10] Realtek auto-parser updates
  2011-04-30 10:24   ` Takashi Iwai
@ 2011-05-01  0:35     ` Raymond Yau
  2011-05-02  7:22       ` Takashi Iwai
  0 siblings, 1 reply; 24+ messages in thread
From: Raymond Yau @ 2011-05-01  0:35 UTC (permalink / raw)
  To: Takashi Iwai, ALSA Development Mailing List

2011/4/30 Takashi Iwai <tiwai@suse.de>

> At Sat, 30 Apr 2011 10:44:13 +0800,
> Raymond Yau wrote:
> >
> > [1  <text/plain; ISO-8859-1 (7bit)>]
> > 2011/4/30 Takashi Iwai <tiwai@suse.de>
> >
> > > Hi, this is a series of patches I'm going to apply as 2.6.40 material.
> > > Basically this adds the missing features to BIOS auto-parser mode, the
> > > support of multi-channel setup (2/4/6-channels) and the auto-mute of
> > > line-out jacks as well as speakers.
> > >
> > > Many changes have been done but mostly in systematic manner.
> > > I've checked through hda-emu and a few machines with Realtek codecs,
> > > but of course can't cover all changes I made.
> > >
> > > If you see any issues with the updated tree, please let me know.
> > >
> > >
> > How about those 4 jacks 8 channels notebook (e.g. ms-1656)  ?
>
> Currently, the detection of LO/MIC extension depends on the location
> of the jacks.  It assumes that these jacks are located at the same
> place as the corresponding line-out jack(s).
>
> I wrote in that way to avoid mis-detection.  It'd be easy to change it
> to look through other locations.
>
>
Refer to 2-17 of the user manual

Left Side View

Those four jacks are at the left side

Headphone out/SPDIF out : Used for speakers or headphones. The SPDIF
connector is also provided for digital audio transmission to external
speakers through an optical fiber cable.

How can the auto parser know it is a combo jack ?

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

* Re: [PATCH 08/10] ALSA: hda - Add support for Line-Out automute to Realtek auto-parser
  2011-04-30 10:23     ` Takashi Iwai
@ 2011-05-02  0:56       ` Raymond Yau
  2011-05-02  6:32         ` Takashi Iwai
  2011-05-02  5:55       ` Raymond Yau
  1 sibling, 1 reply; 24+ messages in thread
From: Raymond Yau @ 2011-05-02  0:56 UTC (permalink / raw)
  To: Takashi Iwai, ALSA Development Mailing List

2011/4/30 Takashi Iwai <tiwai@suse.de>

> At Sat, 30 Apr 2011 08:52:58 +0200,
> David Henningsson wrote:
> >
> > On 2011-04-29 19:18, Takashi Iwai wrote:
> > > By popular demands, I add the functionality to mute / unmute the
> > > line-out jacks per the headphone plug / unplug.  For achieving this
> > > and keeping the compatibility with the old behavior, the new mixer
> > > enum "Auto-Mute Mode" is added.  With this, user can control the
> > > auto-mute behavior either disabled, speaker-only or lineout+speaker.
> >
> > Hi Takashi,
> >
> > Great to see these improvements! I have a question about this patch:
> >
> > There are three ways we can auto-mute:
> >
> > Headphones might mute Internal Speakers.
> > Headphones might mute Line out.
>

Why just only HPs just mute one line out ?

as all HDA codec except ad1986 use copy-front mode, stereo are copy to all
output jacks at rear panel for a motherboard with a 6 , 8 or 10 channel HDA
codec





> > Line out might mute Internal Speakers.
> >
> > Are we considering the third option here or is that still unsupported?
>
> Yes, it'll behave so.  Now we have "Auto-Mute Mode" enum control, and
> it provides "Disable", "Speaker only" and "Line-Out+Speaker" choice in
> the case of LO+HP+SPK case.  When only HP+LO, LO+SPK  or HP+SPK are
> present, this enum gives only "Disable" and "Enable" choice.
>

For desktop if the computer chassis does not has a HDA Front Audio panel,
you need to set Front Audio Panel from [HD] to [AC97] in BIOS setup

The BIOS set the Jack Detect Override bit to 1 to indicate the jack has no
presence detect capability


7.3.3.31 Configuration Default

Misc[3:0] is a bit field used to indicate other information about the jack.
Currently, only bit 0 is defined. If bit 0 is set, it indicates that the
jack has no presence detect capability, so even if a Pin Complex indicates
that the codec hardware supports the presence detect functionality on the
jack, the external circuitry is not capable of supporting the functionality.
The bit definitions for the Misc field are in Table 106.



>
> > Also, it might be slightly confusing for the end-user to have options
> > that are irrelevant, e g if there are no internal speakers (or line-out
> > for that matter), that option will still show up. Right?
>
> If there is only one output type, this enum won't appear.
>

Do you mean there will be no "auto mute" control if the desktop has no HD
compilant front audio panel ?


> I guess this should cover most of use-cases, and flexible enough for
> covering both old and new behavior.
>
>
> thanks,
>
> Takashi
>

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

* Re: [PATCH 08/10] ALSA: hda - Add support for Line-Out automute to Realtek auto-parser
  2011-04-30 10:23     ` Takashi Iwai
  2011-05-02  0:56       ` Raymond Yau
@ 2011-05-02  5:55       ` Raymond Yau
  2011-05-02  7:18         ` Takashi Iwai
  1 sibling, 1 reply; 24+ messages in thread
From: Raymond Yau @ 2011-05-02  5:55 UTC (permalink / raw)
  To: Takashi Iwai, ALSA Development Mailing List

2011/4/30 Takashi Iwai <tiwai@suse.de>

> A
> I guess this should cover most of use-cases, and flexible enough for
> covering both old and new behavior.
>
>
>
But it still not easy to implement multi streaming playback using Front
Panel HP for those 8 or channels codec for the desktop

This would require switch "Independent HP" switch ON will need to turn off
"Auto mute" control and make this control  write protect and inactive

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

* Re: [PATCH 02/10] ALSA: hda - Add channel-mode support to Realtek auto-parser
       [not found]   ` <BANLkTim4sF9_66O-cb7+THZBC-fbxWbe6Q@mail.gmail.com>
@ 2011-05-02  6:27     ` Takashi Iwai
  2011-05-02  6:57       ` Raymond Yau
  0 siblings, 1 reply; 24+ messages in thread
From: Takashi Iwai @ 2011-05-02  6:27 UTC (permalink / raw)
  To: Raymond Yau; +Cc: alsa-devel

At Mon, 2 May 2011 10:06:15 +0800,
Raymond Yau wrote:
> 
> 2011/4/30 Takashi Iwai <tiwai@suse.de>
> 
> > This patch adds the support of "Channel Mode" enum control to Realtek
> > auto-parser.  When line-in or mic-in jacks are capable to output and
> > free DACs are available, the driver allows to switch to multi-channel
> > mode via "Channel Mode" enum switch, as already implemented in some
> > preset cases.
> >
> > Not implemented in all Realtek codecs.  Currently, ALC880, 882, 861,
> > 662 and the compatible codecs are supported.
> >
> > Signed-off-by: Takashi Iwai <tiwai@suse.de>
> > ---
> >
> 
> Why the line out become "speaker" for G41M-ES2L with 3 audio jacks at rear
> panel ?
> The driver won't  create "Channel Mode" control and it cannot support
> surround51

It's just because of pin fixup that I'm going to revert.


Takashi

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

* Re: [PATCH 08/10] ALSA: hda - Add support for Line-Out automute to Realtek auto-parser
  2011-05-02  0:56       ` Raymond Yau
@ 2011-05-02  6:32         ` Takashi Iwai
  0 siblings, 0 replies; 24+ messages in thread
From: Takashi Iwai @ 2011-05-02  6:32 UTC (permalink / raw)
  To: Raymond Yau; +Cc: ALSA Development Mailing List

At Mon, 2 May 2011 08:56:07 +0800,
Raymond Yau wrote:
> 
> 2011/4/30 Takashi Iwai <tiwai@suse.de>
> 
> > At Sat, 30 Apr 2011 08:52:58 +0200,
> > David Henningsson wrote:
> > >
> > > On 2011-04-29 19:18, Takashi Iwai wrote:
> > > > By popular demands, I add the functionality to mute / unmute the
> > > > line-out jacks per the headphone plug / unplug.  For achieving this
> > > > and keeping the compatibility with the old behavior, the new mixer
> > > > enum "Auto-Mute Mode" is added.  With this, user can control the
> > > > auto-mute behavior either disabled, speaker-only or lineout+speaker.
> > >
> > > Hi Takashi,
> > >
> > > Great to see these improvements! I have a question about this patch:
> > >
> > > There are three ways we can auto-mute:
> > >
> > > Headphones might mute Internal Speakers.
> > > Headphones might mute Line out.
> >
> 
> Why just only HPs just mute one line out ?

Who said that it mutes only one line out? :)
Actually it mutes all line-outs.

> as all HDA codec except ad1986 use copy-front mode, stereo are copy to all
> output jacks at rear panel for a motherboard with a 6 , 8 or 10 channel HDA
> codec
> 
> 
> 
> 
> 
> > > Line out might mute Internal Speakers.
> > >
> > > Are we considering the third option here or is that still unsupported?
> >
> > Yes, it'll behave so.  Now we have "Auto-Mute Mode" enum control, and
> > it provides "Disable", "Speaker only" and "Line-Out+Speaker" choice in
> > the case of LO+HP+SPK case.  When only HP+LO, LO+SPK  or HP+SPK are
> > present, this enum gives only "Disable" and "Enable" choice.
> >
> 
> For desktop if the computer chassis does not has a HDA Front Audio panel,
> you need to set Front Audio Panel from [HD] to [AC97] in BIOS setup
> 
> The BIOS set the Jack Detect Override bit to 1 to indicate the jack has no
> presence detect capability
> 
> 
> 7.3.3.31 Configuration Default
> 
> Misc[3:0] is a bit field used to indicate other information about the jack.
> Currently, only bit 0 is defined. If bit 0 is set, it indicates that the
> jack has no presence detect capability, so even if a Pin Complex indicates
> that the codec hardware supports the presence detect functionality on the
> jack, the external circuitry is not capable of supporting the functionality.
> The bit definitions for the Misc field are in Table 106.

If the pin detection bit constantly reports the wrong status (as if
it's plugged in), yes, it'd be better fixed in the driver not to
enable auto-mute.  But, even in the current state, you can switch off
the auto-mute switch always in that case, so it should cover most
problems.


> > > Also, it might be slightly confusing for the end-user to have options
> > > that are irrelevant, e g if there are no internal speakers (or line-out
> > > for that matter), that option will still show up. Right?
> >
> > If there is only one output type, this enum won't appear.
> >
> 
> Do you mean there will be no "auto mute" control if the desktop has no HD
> compilant front audio panel ?

No, auto-mute control is always created when the auto-mute feature is
available on the machine, independent from such a broken desktop.
And, the desktop FP connection mode can't be detected from the driver,
unfortunately...


Takashi

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

* Re: [PATCH 02/10] ALSA: hda - Add channel-mode support to Realtek auto-parser
  2011-05-02  6:27     ` Takashi Iwai
@ 2011-05-02  6:57       ` Raymond Yau
  2011-05-02  7:16         ` Takashi Iwai
  0 siblings, 1 reply; 24+ messages in thread
From: Raymond Yau @ 2011-05-02  6:57 UTC (permalink / raw)
  To: Takashi Iwai, ALSA Development Mailing List

2011/5/2 Takashi Iwai <tiwai@suse.de>

> At Mon, 2 May 2011 10:06:15 +0800,
> Raymond Yau wrote:
> >
> > 2011/4/30 Takashi Iwai <tiwai@suse.de>
> >
> > > This patch adds the support of "Channel Mode" enum control to Realtek
> > > auto-parser.  When line-in or mic-in jacks are capable to output and
> > > free DACs are available, the driver allows to switch to multi-channel
> > > mode via "Channel Mode" enum switch, as already implemented in some
> > > preset cases.
> > >
> > > Not implemented in all Realtek codecs.  Currently, ALC880, 882, 861,
> > > 662 and the compatible codecs are supported.
> > >
> > > Signed-off-by: Takashi Iwai <tiwai@suse.de>
> > > ---
> > >
> >
> > Why the line out become "speaker" for G41M-ES2L with 3 audio jacks at
> rear
> > panel ?
> > The driver won't  create "Channel Mode" control and it cannot support
> > surround51
>
> It's just because of pin fixup that I'm going to revert.
>
> Even revert  the pin config, and distable auto mute,
the channel mode still allow 2, 4 or 6 channels

IT seem that there is no way to use "HP" as "Side" to support surround 7.1
as mentioned in the user manual (Chapter 5 Appendix)

5-1-1 Configuring 2/4/5.1/7.1-Channel Audio

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

* Re: [PATCH 02/10] ALSA: hda - Add channel-mode support to Realtek auto-parser
  2011-05-02  6:57       ` Raymond Yau
@ 2011-05-02  7:16         ` Takashi Iwai
  0 siblings, 0 replies; 24+ messages in thread
From: Takashi Iwai @ 2011-05-02  7:16 UTC (permalink / raw)
  To: Raymond Yau; +Cc: ALSA Development Mailing List

At Mon, 2 May 2011 14:57:51 +0800,
Raymond Yau wrote:
> 
> 2011/5/2 Takashi Iwai <tiwai@suse.de>
> 
> > At Mon, 2 May 2011 10:06:15 +0800,
> > Raymond Yau wrote:
> > >
> > > 2011/4/30 Takashi Iwai <tiwai@suse.de>
> > >
> > > > This patch adds the support of "Channel Mode" enum control to Realtek
> > > > auto-parser.  When line-in or mic-in jacks are capable to output and
> > > > free DACs are available, the driver allows to switch to multi-channel
> > > > mode via "Channel Mode" enum switch, as already implemented in some
> > > > preset cases.
> > > >
> > > > Not implemented in all Realtek codecs.  Currently, ALC880, 882, 861,
> > > > 662 and the compatible codecs are supported.
> > > >
> > > > Signed-off-by: Takashi Iwai <tiwai@suse.de>
> > > > ---
> > > >
> > >
> > > Why the line out become "speaker" for G41M-ES2L with 3 audio jacks at
> > rear
> > > panel ?
> > > The driver won't  create "Channel Mode" control and it cannot support
> > > surround51
> >
> > It's just because of pin fixup that I'm going to revert.
> >
> > Even revert  the pin config, and distable auto mute,
> the channel mode still allow 2, 4 or 6 channels
> 
> IT seem that there is no way to use "HP" as "Side" to support surround 7.1
> as mentioned in the user manual (Chapter 5 Appendix)

It's simply not supported for now.  As already mentioned, all multi-io
jacks have to be in the same location.  And, it must be line-in or
mic-in jacks.

The implementation of hp-i/o switching wouldn't be too difficult, but
a bigger missing piece is how to detect such a configuration
reliably.


Takashi

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

* Re: [PATCH 08/10] ALSA: hda - Add support for Line-Out automute to Realtek auto-parser
  2011-05-02  5:55       ` Raymond Yau
@ 2011-05-02  7:18         ` Takashi Iwai
  0 siblings, 0 replies; 24+ messages in thread
From: Takashi Iwai @ 2011-05-02  7:18 UTC (permalink / raw)
  To: Raymond Yau; +Cc: ALSA Development Mailing List

At Mon, 2 May 2011 13:55:55 +0800,
Raymond Yau wrote:
> 
> 2011/4/30 Takashi Iwai <tiwai@suse.de>
> 
> > A
> > I guess this should cover most of use-cases, and flexible enough for
> > covering both old and new behavior.
> >
> >
> >
> But it still not easy to implement multi streaming playback using Front
> Panel HP for those 8 or channels codec for the desktop
> 
> This would require switch "Independent HP" switch ON will need to turn off
> "Auto mute" control and make this control  write protect and inactive

The independent-HP switch and the 8-channel automute using hp as side
are different issues.  The latter can be implemented without the
former.  Of course, when the former switch is implemented, the
conflict has to be resolved.


Takashi

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

* Re: [PATCH 0/10] Realtek auto-parser updates
  2011-05-01  0:35     ` Raymond Yau
@ 2011-05-02  7:22       ` Takashi Iwai
  0 siblings, 0 replies; 24+ messages in thread
From: Takashi Iwai @ 2011-05-02  7:22 UTC (permalink / raw)
  To: Raymond Yau; +Cc: ALSA Development Mailing List

At Sun, 1 May 2011 08:35:17 +0800,
Raymond Yau wrote:
> 
> 2011/4/30 Takashi Iwai <tiwai@suse.de>
> 
> > At Sat, 30 Apr 2011 10:44:13 +0800,
> > Raymond Yau wrote:
> > >
> > > [1  <text/plain; ISO-8859-1 (7bit)>]
> > > 2011/4/30 Takashi Iwai <tiwai@suse.de>
> > >
> > > > Hi, this is a series of patches I'm going to apply as 2.6.40 material.
> > > > Basically this adds the missing features to BIOS auto-parser mode, the
> > > > support of multi-channel setup (2/4/6-channels) and the auto-mute of
> > > > line-out jacks as well as speakers.
> > > >
> > > > Many changes have been done but mostly in systematic manner.
> > > > I've checked through hda-emu and a few machines with Realtek codecs,
> > > > but of course can't cover all changes I made.
> > > >
> > > > If you see any issues with the updated tree, please let me know.
> > > >
> > > >
> > > How about those 4 jacks 8 channels notebook (e.g. ms-1656)  ?
> >
> > Currently, the detection of LO/MIC extension depends on the location
> > of the jacks.  It assumes that these jacks are located at the same
> > place as the corresponding line-out jack(s).
> >
> > I wrote in that way to avoid mis-detection.  It'd be easy to change it
> > to look through other locations.
> >
> >
> Refer to 2-17 of the user manual
> 
> Left Side View
> 
> Those four jacks are at the left side
> 
> Headphone out/SPDIF out : Used for speakers or headphones. The SPDIF
> connector is also provided for digital audio transmission to external
> speakers through an optical fiber cable.
> 
> How can the auto parser know it is a combo jack ?

Usually in the case of HP/SPDIF combo jack, the jack detection works
only for the headphone jack.  And SPDIF works anyway independently
which jack is plugged.  Both are obvious when you look at how the
combo jack works.


Takashi

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

end of thread, other threads:[~2011-05-02  7:22 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-29 17:18 [PATCH 0/10] Realtek auto-parser updates Takashi Iwai
2011-04-29 17:18 ` [PATCH 01/10] ALSA: hda - Minor update for alc662-parser functions Takashi Iwai
2011-04-29 17:18 ` [PATCH 02/10] ALSA: hda - Add channel-mode support to Realtek auto-parser Takashi Iwai
     [not found]   ` <BANLkTim4sF9_66O-cb7+THZBC-fbxWbe6Q@mail.gmail.com>
2011-05-02  6:27     ` Takashi Iwai
2011-05-02  6:57       ` Raymond Yau
2011-05-02  7:16         ` Takashi Iwai
2011-04-29 17:18 ` [PATCH 03/10] ALSA: hda - Consolidate default automute functions for Realtek Takashi Iwai
2011-04-29 17:18 ` [PATCH 04/10] ALSA: hda - Add common automute support for mxier-amp on/off for Reatek Takashi Iwai
2011-04-29 17:18 ` [PATCH 05/10] ALSA: hda - Add support of line-out automute for Realtek Takashi Iwai
2011-04-29 17:18 ` [PATCH 06/10] ALSA: hda - Consolidate auto-mute with master-switch " Takashi Iwai
2011-04-29 17:18 ` [PATCH 07/10] ALSA: hda - More reduction of redundant automute codes in Realtek parser Takashi Iwai
2011-04-29 17:18 ` [PATCH 08/10] ALSA: hda - Add support for Line-Out automute to Realtek auto-parser Takashi Iwai
2011-04-30  6:52   ` David Henningsson
2011-04-30 10:23     ` Takashi Iwai
2011-05-02  0:56       ` Raymond Yau
2011-05-02  6:32         ` Takashi Iwai
2011-05-02  5:55       ` Raymond Yau
2011-05-02  7:18         ` Takashi Iwai
2011-04-29 17:18 ` [PATCH 09/10] ALSA: hda - More line-out auto-mute support for Realtek Takashi Iwai
2011-04-29 17:18 ` [PATCH 10/10] ALSA: hda - Add Auto-Mute Mode enum for two-output cases Takashi Iwai
2011-04-30  2:44 ` [PATCH 0/10] Realtek auto-parser updates Raymond Yau
2011-04-30 10:24   ` Takashi Iwai
2011-05-01  0:35     ` Raymond Yau
2011-05-02  7:22       ` Takashi Iwai

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.