diff options
Diffstat (limited to 'sound/pci/hda/hda_auto_parser.c')
-rw-r--r-- | sound/pci/hda/hda_auto_parser.c | 68 |
1 files changed, 56 insertions, 12 deletions
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index 6b173b343697..7c11d46b84d3 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c @@ -119,6 +119,32 @@ static bool check_pincap_validity(struct hda_codec *codec, hda_nid_t pin, } } +static bool can_be_headset_mic(struct hda_codec *codec, + struct auto_pin_cfg_item *item, + int seq_number) +{ + int attr; + unsigned int def_conf; + if (item->type != AUTO_PIN_MIC) + return false; + + if (item->is_headset_mic || item->is_headphone_mic) + return false; /* Already assigned */ + + def_conf = snd_hda_codec_get_pincfg(codec, item->pin); + attr = snd_hda_get_input_pin_attr(def_conf); + if (attr <= INPUT_PIN_ATTR_DOCK) + return false; + + if (seq_number >= 0) { + int seq = get_defcfg_sequence(def_conf); + if (seq != seq_number) + return false; + } + + return true; +} + /* * Parse all pin widgets and store the useful pin nids to cfg * @@ -260,20 +286,36 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, } } - /* Take first mic to be a headset mic pin */ - if (cond_flags & HDA_PINCFG_HEADSET_MIC) { - for (i = 0; i < cfg->num_inputs; i++) { - int attr; - unsigned int def_conf; - if (cfg->inputs[i].type != AUTO_PIN_MIC) - continue; - def_conf = snd_hda_codec_get_pincfg(codec, cfg->inputs[i].pin); - attr = snd_hda_get_input_pin_attr(def_conf); - if (attr <= INPUT_PIN_ATTR_DOCK) + /* Find a pin that could be a headset or headphone mic */ + if (cond_flags & HDA_PINCFG_HEADSET_MIC || cond_flags & HDA_PINCFG_HEADPHONE_MIC) { + bool hsmic = !!(cond_flags & HDA_PINCFG_HEADSET_MIC); + bool hpmic = !!(cond_flags & HDA_PINCFG_HEADPHONE_MIC); + for (i = 0; (hsmic || hpmic) && (i < cfg->num_inputs); i++) + if (hsmic && can_be_headset_mic(codec, &cfg->inputs[i], 0xc)) { + cfg->inputs[i].is_headset_mic = 1; + hsmic = false; + } else if (hpmic && can_be_headset_mic(codec, &cfg->inputs[i], 0xd)) { + cfg->inputs[i].is_headphone_mic = 1; + hpmic = false; + } + + /* If we didn't find our sequence number mark, fall back to any sequence number */ + for (i = 0; (hsmic || hpmic) && (i < cfg->num_inputs); i++) { + if (!can_be_headset_mic(codec, &cfg->inputs[i], -1)) continue; - cfg->inputs[i].is_headset_mic = 1; - break; + if (hsmic) { + cfg->inputs[i].is_headset_mic = 1; + hsmic = false; + } else if (hpmic) { + cfg->inputs[i].is_headphone_mic = 1; + hpmic = false; + } } + + if (hsmic) + snd_printdd("Told to look for a headset mic, but didn't find any.\n"); + if (hpmic) + snd_printdd("Told to look for a headphone mic, but didn't find any.\n"); } /* FIX-UP: @@ -419,6 +461,8 @@ static const char *hda_get_input_pin_label(struct hda_codec *codec, case AC_JACK_MIC_IN: if (item && item->is_headset_mic) return "Headset Mic"; + if (item && item->is_headphone_mic) + return "Headphone Mic"; if (!check_location) return "Mic"; attr = snd_hda_get_input_pin_attr(def_conf); |