aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_sigmatel.c
diff options
context:
space:
mode:
authorCharles Chin <Charles.Chin@idt.com>2010-09-17 04:22:32 -0400
committerTakashi Iwai <tiwai@suse.de>2010-09-17 04:22:32 -0400
commit9907790aa06bfc04bf78b445e732ea10039c61e4 (patch)
tree786b7b9a31095278019d2389ed1980e8bbf71eef /sound/pci/hda/patch_sigmatel.c
parent30ea098fc000bb05081a1999269658f1a88af36a (diff)
ALSA: hda - Fix automatic MIC switching and include dock MIC for IDT codecs
Signed-off-by: Charles Chin <Charles.Chin@idt.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r--sound/pci/hda/patch_sigmatel.c40
1 files changed, 29 insertions, 11 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index e4e7d43f911e..7eb359a030de 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -263,6 +263,7 @@ struct sigmatel_spec {
263 263
264 struct sigmatel_mic_route ext_mic; 264 struct sigmatel_mic_route ext_mic;
265 struct sigmatel_mic_route int_mic; 265 struct sigmatel_mic_route int_mic;
266 struct sigmatel_mic_route dock_mic;
266 267
267 const char **spdif_labels; 268 const char **spdif_labels;
268 269
@@ -3488,7 +3489,7 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
3488} 3489}
3489 3490
3490static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid, 3491static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid,
3491 hda_nid_t *fixed, hda_nid_t *ext) 3492 hda_nid_t *fixed, hda_nid_t *ext, hda_nid_t *dock)
3492{ 3493{
3493 unsigned int cfg; 3494 unsigned int cfg;
3494 3495
@@ -3496,15 +3497,22 @@ static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid,
3496 return 0; 3497 return 0;
3497 cfg = snd_hda_codec_get_pincfg(codec, nid); 3498 cfg = snd_hda_codec_get_pincfg(codec, nid);
3498 switch (get_defcfg_connect(cfg)) { 3499 switch (get_defcfg_connect(cfg)) {
3500 case AC_JACK_PORT_BOTH:
3499 case AC_JACK_PORT_FIXED: 3501 case AC_JACK_PORT_FIXED:
3500 if (*fixed) 3502 if (*fixed)
3501 return 1; /* already occupied */ 3503 return 1; /* already occupied */
3502 *fixed = nid; 3504 *fixed = nid;
3503 break; 3505 break;
3504 case AC_JACK_PORT_COMPLEX: 3506 case AC_JACK_PORT_COMPLEX:
3505 if (*ext) 3507 if ((get_defcfg_location(cfg) & 0xF0) == AC_JACK_LOC_SEPARATE) {
3506 return 1; /* already occupied */ 3508 if (*dock)
3507 *ext = nid; 3509 return 1; /* already occupied */
3510 *dock = nid;
3511 } else {
3512 if (*ext)
3513 return 1; /* already occupied */
3514 *ext = nid;
3515 }
3508 break; 3516 break;
3509 } 3517 }
3510 return 0; 3518 return 0;
@@ -3519,6 +3527,8 @@ static int set_mic_route(struct hda_codec *codec,
3519 int i; 3527 int i;
3520 3528
3521 mic->pin = pin; 3529 mic->pin = pin;
3530 if (pin == 0)
3531 return 0;
3522 for (i = 0; i < cfg->num_inputs; i++) { 3532 for (i = 0; i < cfg->num_inputs; i++) {
3523 if (pin == cfg->inputs[i].pin) 3533 if (pin == cfg->inputs[i].pin)
3524 break; 3534 break;
@@ -3554,26 +3564,29 @@ static int stac_check_auto_mic(struct hda_codec *codec)
3554{ 3564{
3555 struct sigmatel_spec *spec = codec->spec; 3565 struct sigmatel_spec *spec = codec->spec;
3556 struct auto_pin_cfg *cfg = &spec->autocfg; 3566 struct auto_pin_cfg *cfg = &spec->autocfg;
3557 hda_nid_t fixed, ext; 3567 hda_nid_t fixed, ext, dock;
3558 int i; 3568 int i;
3559 3569
3560 for (i = 0; i < cfg->num_inputs; i++) { 3570 for (i = 0; i < cfg->num_inputs; i++) {
3561 if (cfg->inputs[i].type >= AUTO_PIN_LINE_IN) 3571 if (cfg->inputs[i].type >= AUTO_PIN_LINE_IN)
3562 return 0; /* must be exclusively mics */ 3572 return 0; /* must be exclusively mics */
3563 } 3573 }
3564 fixed = ext = 0; 3574 fixed = ext = dock = 0;
3565 for (i = 0; i < cfg->num_inputs; i++) 3575 for (i = 0; i < cfg->num_inputs; i++)
3566 if (check_mic_pin(codec, cfg->inputs[i].pin, &fixed, &ext)) 3576 if (check_mic_pin(codec, cfg->inputs[i].pin,
3577 &fixed, &ext, &dock))
3567 return 0; 3578 return 0;
3568 for (i = 0; i < spec->num_dmics; i++) 3579 for (i = 0; i < spec->num_dmics; i++)
3569 if (check_mic_pin(codec, spec->dmic_nids[i], &fixed, &ext)) 3580 if (check_mic_pin(codec, spec->dmic_nids[i],
3581 &fixed, &ext, &dock))
3570 return 0; 3582 return 0;
3571 if (!fixed || !ext) 3583 if (!fixed && !ext && !dock)
3572 return 0; 3584 return 0; /* no input to switch */
3573 if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP)) 3585 if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP))
3574 return 0; /* no unsol support */ 3586 return 0; /* no unsol support */
3575 if (set_mic_route(codec, &spec->ext_mic, ext) || 3587 if (set_mic_route(codec, &spec->ext_mic, ext) ||
3576 set_mic_route(codec, &spec->int_mic, fixed)) 3588 set_mic_route(codec, &spec->int_mic, fixed) ||
3589 set_mic_route(codec, &spec->dock_mic, dock))
3577 return 0; /* something is wrong */ 3590 return 0; /* something is wrong */
3578 return 1; 3591 return 1;
3579} 3592}
@@ -4281,6 +4294,9 @@ static int stac92xx_init(struct hda_codec *codec)
4281 AC_VERB_SET_CONNECT_SEL, 0); 4294 AC_VERB_SET_CONNECT_SEL, 0);
4282 if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT)) 4295 if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT))
4283 stac_issue_unsol_event(codec, spec->ext_mic.pin); 4296 stac_issue_unsol_event(codec, spec->ext_mic.pin);
4297 if (enable_pin_detect(codec, spec->dock_mic.pin,
4298 STAC_MIC_EVENT))
4299 stac_issue_unsol_event(codec, spec->dock_mic.pin);
4284 } 4300 }
4285 for (i = 0; i < cfg->num_inputs; i++) { 4301 for (i = 0; i < cfg->num_inputs; i++) {
4286 hda_nid_t nid = cfg->inputs[i].pin; 4302 hda_nid_t nid = cfg->inputs[i].pin;
@@ -4698,6 +4714,8 @@ static void stac92xx_mic_detect(struct hda_codec *codec)
4698 4714
4699 if (get_pin_presence(codec, spec->ext_mic.pin)) 4715 if (get_pin_presence(codec, spec->ext_mic.pin))
4700 mic = &spec->ext_mic; 4716 mic = &spec->ext_mic;
4717 else if (get_pin_presence(codec, spec->dock_mic.pin))
4718 mic = &spec->dock_mic;
4701 else 4719 else
4702 mic = &spec->int_mic; 4720 mic = &spec->int_mic;
4703 if (mic->dmux_idx >= 0) 4721 if (mic->dmux_idx >= 0)