aboutsummaryrefslogtreecommitdiff
path: root/sound/pci/hda/hda_auto_parser.c
diff options
context:
space:
mode:
authorDavid Henningsson <david.henningsson@canonical.com>2013-04-11 11:30:28 +0200
committerTakashi Iwai <tiwai@suse.de>2013-04-11 11:59:20 +0200
commitcb420b1186e0090f24137855e14e6f3bf7cb769d (patch)
treeebd0bbf1c57e79562dda04a9deca0194f10d3316 /sound/pci/hda/hda_auto_parser.c
parent01f9326ae4087bd278783811e5e6b6c0058dd455 (diff)
ALSA: hda - allow "Headphone Mic" parser flag
This allows a specific mic to get the "Headphone Mic" name, in addition to the existing "Headset Mic" name. Also, it allows for a special mark: if the sequence number is set to 0xc, that's an indication to prefer it for headset mic, and if it's set to 0xd, that's an indication to prefer it for headphone mic. Signed-off-by: David Henningsson <david.henningsson@canonical.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/hda_auto_parser.c')
-rw-r--r--sound/pci/hda/hda_auto_parser.c68
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 6b173b34369..7c11d46b84d 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);