소스 검색

ALSA: hda - Fix capture source widgets on ALC codecs

On some Realtek codecs like ALC882 or ALC883, the capture source is
no mux but sum widget.  We have to initialize all channels properly
for this type, otherwise noises may come in from the unused route.

The patch assures to mute unused routes, and unmute the currently
selected route.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Tested-by: Daniel J Blueman <daniel.blueman@gmail.com>
Takashi Iwai 16 년 전
부모
커밋
f511b01c8e
1개의 변경된 파일45개의 추가작업 그리고 0개의 파일을 삭제
  1. 45 0
      sound/pci/hda/patch_realtek.c

+ 45 - 0
sound/pci/hda/patch_realtek.c

@@ -6437,6 +6437,39 @@ static void alc882_auto_init_analog_input(struct hda_codec *codec)
 	}
 	}
 }
 }
 
 
+static void alc882_auto_init_input_src(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	const struct hda_input_mux *imux = spec->input_mux;
+	int c;
+
+	for (c = 0; c < spec->num_adc_nids; c++) {
+		hda_nid_t conn_list[HDA_MAX_NUM_INPUTS];
+		hda_nid_t nid = spec->capsrc_nids[c];
+		int conns, mute, idx, item;
+
+		conns = snd_hda_get_connections(codec, nid, conn_list,
+						ARRAY_SIZE(conn_list));
+		if (conns < 0)
+			continue;
+		for (idx = 0; idx < conns; idx++) {
+			/* if the current connection is the selected one,
+			 * unmute it as default - otherwise mute it
+			 */
+			mute = AMP_IN_MUTE(idx);
+			for (item = 0; item < imux->num_items; item++) {
+				if (imux->items[item].index == idx) {
+					if (spec->cur_mux[c] == item)
+						mute = AMP_IN_UNMUTE(idx);
+					break;
+				}
+			}
+			snd_hda_codec_write(codec, nid, 0,
+					    AC_VERB_SET_AMP_GAIN_MUTE, mute);
+		}
+	}
+}
+
 /* add mic boosts if needed */
 /* add mic boosts if needed */
 static int alc_auto_add_mic_boost(struct hda_codec *codec)
 static int alc_auto_add_mic_boost(struct hda_codec *codec)
 {
 {
@@ -6491,6 +6524,7 @@ static void alc882_auto_init(struct hda_codec *codec)
 	alc882_auto_init_multi_out(codec);
 	alc882_auto_init_multi_out(codec);
 	alc882_auto_init_hp_out(codec);
 	alc882_auto_init_hp_out(codec);
 	alc882_auto_init_analog_input(codec);
 	alc882_auto_init_analog_input(codec);
+	alc882_auto_init_input_src(codec);
 	if (spec->unsol_event)
 	if (spec->unsol_event)
 		alc_sku_automute(codec);
 		alc_sku_automute(codec);
 }
 }
@@ -8285,6 +8319,8 @@ static void alc883_auto_init_analog_input(struct hda_codec *codec)
 	}
 	}
 }
 }
 
 
+#define alc883_auto_init_input_src	alc882_auto_init_input_src
+
 /* almost identical with ALC880 parser... */
 /* almost identical with ALC880 parser... */
 static int alc883_parse_auto_config(struct hda_codec *codec)
 static int alc883_parse_auto_config(struct hda_codec *codec)
 {
 {
@@ -8315,6 +8351,7 @@ static void alc883_auto_init(struct hda_codec *codec)
 	alc883_auto_init_multi_out(codec);
 	alc883_auto_init_multi_out(codec);
 	alc883_auto_init_hp_out(codec);
 	alc883_auto_init_hp_out(codec);
 	alc883_auto_init_analog_input(codec);
 	alc883_auto_init_analog_input(codec);
+	alc883_auto_init_input_src(codec);
 	if (spec->unsol_event)
 	if (spec->unsol_event)
 		alc_sku_automute(codec);
 		alc_sku_automute(codec);
 }
 }
@@ -9663,6 +9700,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
 #define alc262_auto_init_multi_out	alc882_auto_init_multi_out
 #define alc262_auto_init_multi_out	alc882_auto_init_multi_out
 #define alc262_auto_init_hp_out		alc882_auto_init_hp_out
 #define alc262_auto_init_hp_out		alc882_auto_init_hp_out
 #define alc262_auto_init_analog_input	alc882_auto_init_analog_input
 #define alc262_auto_init_analog_input	alc882_auto_init_analog_input
+#define alc262_auto_init_input_src	alc882_auto_init_input_src
 
 
 
 
 /* init callback for auto-configuration model -- overriding the default init */
 /* init callback for auto-configuration model -- overriding the default init */
@@ -9672,6 +9710,7 @@ static void alc262_auto_init(struct hda_codec *codec)
 	alc262_auto_init_multi_out(codec);
 	alc262_auto_init_multi_out(codec);
 	alc262_auto_init_hp_out(codec);
 	alc262_auto_init_hp_out(codec);
 	alc262_auto_init_analog_input(codec);
 	alc262_auto_init_analog_input(codec);
+	alc262_auto_init_input_src(codec);
 	if (spec->unsol_event)
 	if (spec->unsol_event)
 		alc_sku_automute(codec);
 		alc_sku_automute(codec);
 }
 }
@@ -13330,6 +13369,8 @@ static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
 	}
 	}
 }
 }
 
 
+#define alc861vd_auto_init_input_src	alc882_auto_init_input_src
+
 #define alc861vd_idx_to_mixer_vol(nid)		((nid) + 0x02)
 #define alc861vd_idx_to_mixer_vol(nid)		((nid) + 0x02)
 #define alc861vd_idx_to_mixer_switch(nid)	((nid) + 0x0c)
 #define alc861vd_idx_to_mixer_switch(nid)	((nid) + 0x0c)
 
 
@@ -13512,6 +13553,7 @@ static void alc861vd_auto_init(struct hda_codec *codec)
 	alc861vd_auto_init_multi_out(codec);
 	alc861vd_auto_init_multi_out(codec);
 	alc861vd_auto_init_hp_out(codec);
 	alc861vd_auto_init_hp_out(codec);
 	alc861vd_auto_init_analog_input(codec);
 	alc861vd_auto_init_analog_input(codec);
+	alc861vd_auto_init_input_src(codec);
 	if (spec->unsol_event)
 	if (spec->unsol_event)
 		alc_sku_automute(codec);
 		alc_sku_automute(codec);
 }
 }
@@ -14677,6 +14719,8 @@ static void alc662_auto_init_analog_input(struct hda_codec *codec)
 	}
 	}
 }
 }
 
 
+#define alc662_auto_init_input_src	alc882_auto_init_input_src
+
 static int alc662_parse_auto_config(struct hda_codec *codec)
 static int alc662_parse_auto_config(struct hda_codec *codec)
 {
 {
 	struct alc_spec *spec = codec->spec;
 	struct alc_spec *spec = codec->spec;
@@ -14733,6 +14777,7 @@ static void alc662_auto_init(struct hda_codec *codec)
 	alc662_auto_init_multi_out(codec);
 	alc662_auto_init_multi_out(codec);
 	alc662_auto_init_hp_out(codec);
 	alc662_auto_init_hp_out(codec);
 	alc662_auto_init_analog_input(codec);
 	alc662_auto_init_analog_input(codec);
+	alc662_auto_init_input_src(codec);
 	if (spec->unsol_event)
 	if (spec->unsol_event)
 		alc_sku_automute(codec);
 		alc_sku_automute(codec);
 }
 }