aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2010-03-29 11:21:45 -0400
committerTakashi Iwai <tiwai@suse.de>2010-03-29 11:27:31 -0400
commit6694635d3ae1b038d7a0e38b80637db867c7c8e2 (patch)
tree34070c19ffa64654109fdb7775da604f8413a62d /sound
parent5dbd5ec6e1cf2e49128025d80813a275744a7ac5 (diff)
ALSA: hda - Fix ADC/MUX assignment of ALC269 codec
ALC269 codec has a few different variants, and each of them may have different ADC and MUX widgets. For example, one model has ADC 0x08 with MUX 0x23 while others has ADC 0x09 or ADC 0x07 with MUX 022 or 0x24. The difference of ADC appears usually as the capability of the digital mic pin (0x12), and the current driver sometimes misses the internal mic pin due to the mismatching ADC. This patch adds a bit more clever way to find the matching ADC instead of the static list. Now the driver checks all active input pins and fills only the ADC/MUX's that contain all of them. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/patch_realtek.c95
1 files changed, 80 insertions, 15 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index bc55c1e96df5..22aea7b089c6 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -4984,6 +4984,69 @@ static void set_capture_mixer(struct hda_codec *codec)
4984 } 4984 }
4985} 4985}
4986 4986
4987/* fill adc_nids (and capsrc_nids) containing all active input pins */
4988static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids,
4989 int num_nids)
4990{
4991 struct alc_spec *spec = codec->spec;
4992 int n;
4993 hda_nid_t fallback_adc = 0, fallback_cap = 0;
4994
4995 for (n = 0; n < num_nids; n++) {
4996 hda_nid_t adc, cap;
4997 hda_nid_t conn[HDA_MAX_NUM_INPUTS];
4998 int nconns, i, j;
4999
5000 adc = nids[n];
5001 if (get_wcaps_type(get_wcaps(codec, adc)) != AC_WID_AUD_IN)
5002 continue;
5003 cap = adc;
5004 nconns = snd_hda_get_connections(codec, cap, conn,
5005 ARRAY_SIZE(conn));
5006 if (nconns == 1) {
5007 cap = conn[0];
5008 nconns = snd_hda_get_connections(codec, cap, conn,
5009 ARRAY_SIZE(conn));
5010 }
5011 if (nconns <= 0)
5012 continue;
5013 if (!fallback_adc) {
5014 fallback_adc = adc;
5015 fallback_cap = cap;
5016 }
5017 for (i = 0; i < AUTO_PIN_LAST; i++) {
5018 hda_nid_t nid = spec->autocfg.input_pins[i];
5019 if (!nid)
5020 continue;
5021 for (j = 0; j < nconns; j++) {
5022 if (conn[j] == nid)
5023 break;
5024 }
5025 if (j >= nconns)
5026 break;
5027 }
5028 if (i >= AUTO_PIN_LAST) {
5029 int num_adcs = spec->num_adc_nids;
5030 spec->private_adc_nids[num_adcs] = adc;
5031 spec->private_capsrc_nids[num_adcs] = cap;
5032 spec->num_adc_nids++;
5033 spec->adc_nids = spec->private_adc_nids;
5034 if (adc != cap)
5035 spec->capsrc_nids = spec->private_capsrc_nids;
5036 }
5037 }
5038 if (!spec->num_adc_nids) {
5039 printk(KERN_WARNING "hda_codec: %s: no valid ADC found;"
5040 " using fallback 0x%x\n", fallback_adc);
5041 spec->private_adc_nids[0] = fallback_adc;
5042 spec->adc_nids = spec->private_adc_nids;
5043 if (fallback_adc != fallback_cap) {
5044 spec->private_capsrc_nids[0] = fallback_cap;
5045 spec->capsrc_nids = spec->private_adc_nids;
5046 }
5047 }
5048}
5049
4987#ifdef CONFIG_SND_HDA_INPUT_BEEP 5050#ifdef CONFIG_SND_HDA_INPUT_BEEP
4988#define set_beep_amp(spec, nid, idx, dir) \ 5051#define set_beep_amp(spec, nid, idx, dir) \
4989 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir)) 5052 ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir))
@@ -13333,9 +13396,9 @@ static hda_nid_t alc269vb_capsrc_nids[1] = {
13333 0x22, 13396 0x22,
13334}; 13397};
13335 13398
13336/* NOTE: ADC2 (0x07) is connected from a recording *MIXER* (0x24), 13399static hda_nid_t alc269_adc_candidates[] = {
13337 * not a mux! 13400 0x08, 0x09, 0x07,
13338 */ 13401};
13339 13402
13340#define alc269_modes alc260_modes 13403#define alc269_modes alc260_modes
13341#define alc269_capture_source alc880_lg_lw_capture_source 13404#define alc269_capture_source alc880_lg_lw_capture_source
@@ -13842,7 +13905,6 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
13842 struct alc_spec *spec = codec->spec; 13905 struct alc_spec *spec = codec->spec;
13843 int err; 13906 int err;
13844 static hda_nid_t alc269_ignore[] = { 0x1d, 0 }; 13907 static hda_nid_t alc269_ignore[] = { 0x1d, 0 };
13845 hda_nid_t real_capsrc_nids;
13846 13908
13847 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, 13909 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
13848 alc269_ignore); 13910 alc269_ignore);
@@ -13866,18 +13928,19 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
13866 13928
13867 if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010) { 13929 if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010) {
13868 add_verb(spec, alc269vb_init_verbs); 13930 add_verb(spec, alc269vb_init_verbs);
13869 real_capsrc_nids = alc269vb_capsrc_nids[0];
13870 alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21); 13931 alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21);
13871 } else { 13932 } else {
13872 add_verb(spec, alc269_init_verbs); 13933 add_verb(spec, alc269_init_verbs);
13873 real_capsrc_nids = alc269_capsrc_nids[0];
13874 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0); 13934 alc_ssid_check(codec, 0x15, 0x1b, 0x14, 0);
13875 } 13935 }
13876 13936
13877 spec->num_mux_defs = 1; 13937 spec->num_mux_defs = 1;
13878 spec->input_mux = &spec->private_imux[0]; 13938 spec->input_mux = &spec->private_imux[0];
13939 fillup_priv_adc_nids(codec, alc269_adc_candidates,
13940 sizeof(alc269_adc_candidates));
13941
13879 /* set default input source */ 13942 /* set default input source */
13880 snd_hda_codec_write_cache(codec, real_capsrc_nids, 13943 snd_hda_codec_write_cache(codec, spec->capsrc_nids[0],
13881 0, AC_VERB_SET_CONNECT_SEL, 13944 0, AC_VERB_SET_CONNECT_SEL,
13882 spec->input_mux->items[0].index); 13945 spec->input_mux->items[0].index);
13883 13946
@@ -14156,14 +14219,16 @@ static int patch_alc269(struct hda_codec *codec)
14156 spec->stream_digital_playback = &alc269_pcm_digital_playback; 14219 spec->stream_digital_playback = &alc269_pcm_digital_playback;
14157 spec->stream_digital_capture = &alc269_pcm_digital_capture; 14220 spec->stream_digital_capture = &alc269_pcm_digital_capture;
14158 14221
14159 if (!is_alc269vb) { 14222 if (!spec->adc_nids) { /* wasn't filled automatically? use default */
14160 spec->adc_nids = alc269_adc_nids; 14223 if (!is_alc269vb) {
14161 spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); 14224 spec->adc_nids = alc269_adc_nids;
14162 spec->capsrc_nids = alc269_capsrc_nids; 14225 spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
14163 } else { 14226 spec->capsrc_nids = alc269_capsrc_nids;
14164 spec->adc_nids = alc269vb_adc_nids; 14227 } else {
14165 spec->num_adc_nids = ARRAY_SIZE(alc269vb_adc_nids); 14228 spec->adc_nids = alc269vb_adc_nids;
14166 spec->capsrc_nids = alc269vb_capsrc_nids; 14229 spec->num_adc_nids = ARRAY_SIZE(alc269vb_adc_nids);
14230 spec->capsrc_nids = alc269vb_capsrc_nids;
14231 }
14167 } 14232 }
14168 14233
14169 if (!spec->cap_mixer) 14234 if (!spec->cap_mixer)