ALSA: hda - Fix automatic MIC switching and include dock MIC for IDT codecs
authorCharles Chin <Charles.Chin@idt.com>
Fri, 17 Sep 2010 08:22:32 +0000 (10:22 +0200)
committerTakashi Iwai <tiwai@suse.de>
Fri, 17 Sep 2010 08:22:32 +0000 (10:22 +0200)
Signed-off-by: Charles Chin <Charles.Chin@idt.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/hda/patch_sigmatel.c

index e4e7d43f911e94a6cc900b1c94351c525ecbb1b5..7eb359a030de5ac52eeba3b3a521a4caca4e1423 100644 (file)
@@ -263,6 +263,7 @@ struct sigmatel_spec {
 
        struct sigmatel_mic_route ext_mic;
        struct sigmatel_mic_route int_mic;
+       struct sigmatel_mic_route dock_mic;
 
        const char **spdif_labels;
 
@@ -3488,7 +3489,7 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
 }
 
 static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid,
-                        hda_nid_t *fixed, hda_nid_t *ext)
+                        hda_nid_t *fixed, hda_nid_t *ext, hda_nid_t *dock)
 {
        unsigned int cfg;
 
@@ -3496,15 +3497,22 @@ static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid,
                return 0;
        cfg = snd_hda_codec_get_pincfg(codec, nid);
        switch (get_defcfg_connect(cfg)) {
+       case AC_JACK_PORT_BOTH:
        case AC_JACK_PORT_FIXED:
                if (*fixed)
                        return 1; /* already occupied */
                *fixed = nid;
                break;
        case AC_JACK_PORT_COMPLEX:
-               if (*ext)
-                       return 1; /* already occupied */
-               *ext = nid;
+               if ((get_defcfg_location(cfg) & 0xF0) == AC_JACK_LOC_SEPARATE) {
+                       if (*dock)
+                               return 1; /* already occupied */
+                       *dock = nid;
+               } else {
+                       if (*ext)
+                               return 1; /* already occupied */
+                       *ext = nid;
+               }
                break;
        }
        return 0;
@@ -3519,6 +3527,8 @@ static int set_mic_route(struct hda_codec *codec,
        int i;
 
        mic->pin = pin;
+       if (pin == 0)
+               return 0;
        for (i = 0; i < cfg->num_inputs; i++) {
                if (pin == cfg->inputs[i].pin)
                        break;
@@ -3554,26 +3564,29 @@ static int stac_check_auto_mic(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
-       hda_nid_t fixed, ext;
+       hda_nid_t fixed, ext, dock;
        int i;
 
        for (i = 0; i < cfg->num_inputs; i++) {
                if (cfg->inputs[i].type >= AUTO_PIN_LINE_IN)
                        return 0; /* must be exclusively mics */
        }
-       fixed = ext = 0;
+       fixed = ext = dock = 0;
        for (i = 0; i < cfg->num_inputs; i++)
-               if (check_mic_pin(codec, cfg->inputs[i].pin, &fixed, &ext))
+               if (check_mic_pin(codec, cfg->inputs[i].pin,
+                   &fixed, &ext, &dock))
                        return 0;
        for (i = 0; i < spec->num_dmics; i++)
-               if (check_mic_pin(codec, spec->dmic_nids[i], &fixed, &ext))
+               if (check_mic_pin(codec, spec->dmic_nids[i],
+                   &fixed, &ext, &dock))
                        return 0;
-       if (!fixed || !ext)
-               return 0;
+       if (!fixed && !ext && !dock)
+               return 0; /* no input to switch */
        if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP))
                return 0; /* no unsol support */
        if (set_mic_route(codec, &spec->ext_mic, ext) ||
-           set_mic_route(codec, &spec->int_mic, fixed))
+           set_mic_route(codec, &spec->int_mic, fixed) ||
+           set_mic_route(codec, &spec->dock_mic, dock))
                return 0; /* something is wrong */
        return 1;
 }
@@ -4281,6 +4294,9 @@ static int stac92xx_init(struct hda_codec *codec)
                                          AC_VERB_SET_CONNECT_SEL, 0);
                if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT))
                        stac_issue_unsol_event(codec, spec->ext_mic.pin);
+               if (enable_pin_detect(codec, spec->dock_mic.pin,
+                   STAC_MIC_EVENT))
+                       stac_issue_unsol_event(codec, spec->dock_mic.pin);
        }
        for (i = 0; i < cfg->num_inputs; i++) {
                hda_nid_t nid = cfg->inputs[i].pin;
@@ -4698,6 +4714,8 @@ static void stac92xx_mic_detect(struct hda_codec *codec)
 
        if (get_pin_presence(codec, spec->ext_mic.pin))
                mic = &spec->ext_mic;
+       else if (get_pin_presence(codec, spec->dock_mic.pin))
+               mic = &spec->dock_mic;
        else
                mic = &spec->int_mic;
        if (mic->dmux_idx >= 0)