aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-05-17 06:05:02 -0400
committerTakashi Iwai <tiwai@suse.de>2011-05-17 06:34:57 -0400
commit8ed99d976812d1e14a254b9ac1fe6255af8270ff (patch)
tree21e25f9c6a69ec21a72a5580f40c1e414b4b5ff0 /sound
parente35d9d6a153493055fc888add70786154f00edd4 (diff)
ALSA: hda - Add dock-mic detection support to Realtek auto-parser
In addition to the normal mic jack, the mic (or line-in) jack on the docking-station is checked also as a candidate for auto-selection. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/patch_realtek.c82
1 files changed, 65 insertions, 17 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 24bc8a67a39d..cee89b1ef393 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -360,6 +360,7 @@ struct alc_spec {
360 const struct hda_input_mux *input_mux; 360 const struct hda_input_mux *input_mux;
361 unsigned int cur_mux[3]; 361 unsigned int cur_mux[3];
362 struct alc_mic_route ext_mic; 362 struct alc_mic_route ext_mic;
363 struct alc_mic_route dock_mic;
363 struct alc_mic_route int_mic; 364 struct alc_mic_route int_mic;
364 365
365 /* channel model */ 366 /* channel model */
@@ -1057,6 +1058,7 @@ static int alc_init_jacks(struct hda_codec *codec)
1057 int err; 1058 int err;
1058 unsigned int hp_nid = spec->autocfg.hp_pins[0]; 1059 unsigned int hp_nid = spec->autocfg.hp_pins[0];
1059 unsigned int mic_nid = spec->ext_mic.pin; 1060 unsigned int mic_nid = spec->ext_mic.pin;
1061 unsigned int dock_nid = spec->dock_mic.pin;
1060 1062
1061 if (hp_nid) { 1063 if (hp_nid) {
1062 err = snd_hda_input_jack_add(codec, hp_nid, 1064 err = snd_hda_input_jack_add(codec, hp_nid,
@@ -1073,6 +1075,13 @@ static int alc_init_jacks(struct hda_codec *codec)
1073 return err; 1075 return err;
1074 snd_hda_input_jack_report(codec, mic_nid); 1076 snd_hda_input_jack_report(codec, mic_nid);
1075 } 1077 }
1078 if (dock_nid) {
1079 err = snd_hda_input_jack_add(codec, dock_nid,
1080 SND_JACK_MICROPHONE, NULL);
1081 if (err < 0)
1082 return err;
1083 snd_hda_input_jack_report(codec, dock_nid);
1084 }
1076#endif /* CONFIG_SND_HDA_INPUT_JACK */ 1085#endif /* CONFIG_SND_HDA_INPUT_JACK */
1077 return 0; 1086 return 0;
1078} 1087}
@@ -1217,7 +1226,7 @@ static void alc_dual_mic_adc_auto_switch(struct hda_codec *codec)
1217static void alc_mic_automute(struct hda_codec *codec) 1226static void alc_mic_automute(struct hda_codec *codec)
1218{ 1227{
1219 struct alc_spec *spec = codec->spec; 1228 struct alc_spec *spec = codec->spec;
1220 struct alc_mic_route *dead, *alive; 1229 struct alc_mic_route *dead1, *dead2, *alive;
1221 unsigned int present, type; 1230 unsigned int present, type;
1222 hda_nid_t cap_nid; 1231 hda_nid_t cap_nid;
1223 1232
@@ -1235,13 +1244,24 @@ static void alc_mic_automute(struct hda_codec *codec)
1235 1244
1236 cap_nid = spec->capsrc_nids ? spec->capsrc_nids[0] : spec->adc_nids[0]; 1245 cap_nid = spec->capsrc_nids ? spec->capsrc_nids[0] : spec->adc_nids[0];
1237 1246
1247 alive = &spec->int_mic;
1248 dead1 = &spec->ext_mic;
1249 dead2 = &spec->dock_mic;
1250
1238 present = snd_hda_jack_detect(codec, spec->ext_mic.pin); 1251 present = snd_hda_jack_detect(codec, spec->ext_mic.pin);
1239 if (present) { 1252 if (present) {
1240 alive = &spec->ext_mic; 1253 alive = &spec->ext_mic;
1241 dead = &spec->int_mic; 1254 dead1 = &spec->int_mic;
1242 } else { 1255 dead2 = &spec->dock_mic;
1243 alive = &spec->int_mic; 1256 }
1244 dead = &spec->ext_mic; 1257 if (!present && spec->dock_mic.pin > 0) {
1258 present = snd_hda_jack_detect(codec, spec->dock_mic.pin);
1259 if (present) {
1260 alive = &spec->dock_mic;
1261 dead1 = &spec->int_mic;
1262 dead2 = &spec->ext_mic;
1263 }
1264 snd_hda_input_jack_report(codec, spec->dock_mic.pin);
1245 } 1265 }
1246 1266
1247 type = get_wcaps_type(get_wcaps(codec, cap_nid)); 1267 type = get_wcaps_type(get_wcaps(codec, cap_nid));
@@ -1250,9 +1270,14 @@ static void alc_mic_automute(struct hda_codec *codec)
1250 snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT, 1270 snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
1251 alive->mux_idx, 1271 alive->mux_idx,
1252 HDA_AMP_MUTE, 0); 1272 HDA_AMP_MUTE, 0);
1253 snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT, 1273 if (dead1->pin > 0)
1254 dead->mux_idx, 1274 snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
1255 HDA_AMP_MUTE, HDA_AMP_MUTE); 1275 dead1->mux_idx,
1276 HDA_AMP_MUTE, HDA_AMP_MUTE);
1277 if (dead2->pin > 0)
1278 snd_hda_codec_amp_stereo(codec, cap_nid, HDA_INPUT,
1279 dead2->mux_idx,
1280 HDA_AMP_MUTE, HDA_AMP_MUTE);
1256 } else { 1281 } else {
1257 /* MUX style (e.g. ALC880) */ 1282 /* MUX style (e.g. ALC880) */
1258 snd_hda_codec_write_cache(codec, cap_nid, 0, 1283 snd_hda_codec_write_cache(codec, cap_nid, 0,
@@ -1598,15 +1623,10 @@ static void alc_init_auto_mic(struct hda_codec *codec)
1598{ 1623{
1599 struct alc_spec *spec = codec->spec; 1624 struct alc_spec *spec = codec->spec;
1600 struct auto_pin_cfg *cfg = &spec->autocfg; 1625 struct auto_pin_cfg *cfg = &spec->autocfg;
1601 hda_nid_t fixed, ext; 1626 hda_nid_t fixed, ext, dock;
1602 int i; 1627 int i;
1603 1628
1604 /* there must be only two mic inputs exclusively */ 1629 fixed = ext = dock = 0;
1605 for (i = 0; i < cfg->num_inputs; i++)
1606 if (cfg->inputs[i].type >= AUTO_PIN_LINE_IN)
1607 return;
1608
1609 fixed = ext = 0;
1610 for (i = 0; i < cfg->num_inputs; i++) { 1630 for (i = 0; i < cfg->num_inputs; i++) {
1611 hda_nid_t nid = cfg->inputs[i].pin; 1631 hda_nid_t nid = cfg->inputs[i].pin;
1612 unsigned int defcfg; 1632 unsigned int defcfg;
@@ -1615,26 +1635,45 @@ static void alc_init_auto_mic(struct hda_codec *codec)
1615 case INPUT_PIN_ATTR_INT: 1635 case INPUT_PIN_ATTR_INT:
1616 if (fixed) 1636 if (fixed)
1617 return; /* already occupied */ 1637 return; /* already occupied */
1638 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1639 return; /* invalid type */
1618 fixed = nid; 1640 fixed = nid;
1619 break; 1641 break;
1620 case INPUT_PIN_ATTR_UNUSED: 1642 case INPUT_PIN_ATTR_UNUSED:
1621 return; /* invalid entry */ 1643 return; /* invalid entry */
1644 case INPUT_PIN_ATTR_DOCK:
1645 if (dock)
1646 return; /* already occupied */
1647 if (cfg->inputs[i].type > AUTO_PIN_LINE_IN)
1648 return; /* invalid type */
1649 dock = nid;
1650 break;
1622 default: 1651 default:
1623 if (ext) 1652 if (ext)
1624 return; /* already occupied */ 1653 return; /* already occupied */
1654 if (cfg->inputs[i].type != AUTO_PIN_MIC)
1655 return; /* invalid type */
1625 ext = nid; 1656 ext = nid;
1626 break; 1657 break;
1627 } 1658 }
1628 } 1659 }
1660 if (!ext && dock) {
1661 ext = dock;
1662 dock = 0;
1663 }
1629 if (!ext || !fixed) 1664 if (!ext || !fixed)
1630 return; 1665 return;
1631 if (!is_jack_detectable(codec, ext)) 1666 if (!is_jack_detectable(codec, ext))
1632 return; /* no unsol support */ 1667 return; /* no unsol support */
1633 snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x\n", 1668 if (dock && !is_jack_detectable(codec, dock))
1634 ext, fixed); 1669 return; /* no unsol support */
1670 snd_printdd("realtek: Enable auto-mic switch on NID 0x%x/0x%x/0x%x\n",
1671 ext, fixed, dock);
1635 spec->ext_mic.pin = ext; 1672 spec->ext_mic.pin = ext;
1673 spec->dock_mic.pin = dock;
1636 spec->int_mic.pin = fixed; 1674 spec->int_mic.pin = fixed;
1637 spec->ext_mic.mux_idx = MUX_IDX_UNDEF; /* set later */ 1675 spec->ext_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
1676 spec->dock_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
1638 spec->int_mic.mux_idx = MUX_IDX_UNDEF; /* set later */ 1677 spec->int_mic.mux_idx = MUX_IDX_UNDEF; /* set later */
1639 spec->auto_mic = 1; 1678 spec->auto_mic = 1;
1640 snd_hda_codec_write_cache(codec, spec->ext_mic.pin, 0, 1679 snd_hda_codec_write_cache(codec, spec->ext_mic.pin, 0,
@@ -5716,6 +5755,12 @@ static void fixup_automic_adc(struct hda_codec *codec)
5716 spec->capsrc_nids += i; 5755 spec->capsrc_nids += i;
5717 spec->adc_nids += i; 5756 spec->adc_nids += i;
5718 spec->num_adc_nids = 1; 5757 spec->num_adc_nids = 1;
5758 /* optional dock-mic */
5759 eidx = get_connection_index(codec, cap, spec->dock_mic.pin);
5760 if (eidx < 0)
5761 spec->dock_mic.pin = 0;
5762 else
5763 spec->dock_mic.mux_idx = eidx;
5719 return; 5764 return;
5720 } 5765 }
5721 snd_printd(KERN_INFO "hda_codec: %s: " 5766 snd_printd(KERN_INFO "hda_codec: %s: "
@@ -5743,6 +5788,8 @@ static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
5743 struct alc_spec *spec = codec->spec; 5788 struct alc_spec *spec = codec->spec;
5744 int i; 5789 int i;
5745 5790
5791 if (!pin)
5792 return 0;
5746 for (i = 0; i < spec->num_adc_nids; i++) { 5793 for (i = 0; i < spec->num_adc_nids; i++) {
5747 hda_nid_t cap = spec->capsrc_nids ? 5794 hda_nid_t cap = spec->capsrc_nids ?
5748 spec->capsrc_nids[i] : spec->adc_nids[i]; 5795 spec->capsrc_nids[i] : spec->adc_nids[i];
@@ -5783,6 +5830,7 @@ static void fixup_dual_adc_switch(struct hda_codec *codec)
5783{ 5830{
5784 struct alc_spec *spec = codec->spec; 5831 struct alc_spec *spec = codec->spec;
5785 init_capsrc_for_pin(codec, spec->ext_mic.pin); 5832 init_capsrc_for_pin(codec, spec->ext_mic.pin);
5833 init_capsrc_for_pin(codec, spec->dock_mic.pin);
5786 init_capsrc_for_pin(codec, spec->int_mic.pin); 5834 init_capsrc_for_pin(codec, spec->int_mic.pin);
5787} 5835}
5788 5836