aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sound/pci/hda/hda_auto_parser.c68
-rw-r--r--sound/pci/hda/hda_auto_parser.h8
-rw-r--r--sound/pci/hda/hda_generic.c1
3 files changed, 62 insertions, 15 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);
diff --git a/sound/pci/hda/hda_auto_parser.h b/sound/pci/hda/hda_auto_parser.h
index c7826ce0818..fe2ba7fafe4 100644
--- a/sound/pci/hda/hda_auto_parser.h
+++ b/sound/pci/hda/hda_auto_parser.h
@@ -37,6 +37,7 @@ struct auto_pin_cfg_item {
hda_nid_t pin;
int type;
unsigned int is_headset_mic:1;
+ unsigned int is_headphone_mic:1; /* Mic-only in headphone jack */
};
struct auto_pin_cfg;
@@ -79,9 +80,10 @@ struct auto_pin_cfg {
};
/* bit-flags for snd_hda_parse_pin_def_config() behavior */
-#define HDA_PINCFG_NO_HP_FIXUP (1 << 0) /* no HP-split */
-#define HDA_PINCFG_NO_LO_FIXUP (1 << 1) /* don't take other outs as LO */
-#define HDA_PINCFG_HEADSET_MIC (1 << 2) /* Take first mic as headset mic */
+#define HDA_PINCFG_NO_HP_FIXUP (1 << 0) /* no HP-split */
+#define HDA_PINCFG_NO_LO_FIXUP (1 << 1) /* don't take other outs as LO */
+#define HDA_PINCFG_HEADSET_MIC (1 << 2) /* Try to find headset mic; mark seq number as 0xc to trigger */
+#define HDA_PINCFG_HEADPHONE_MIC (1 << 3) /* Try to find headphone mic; mark seq number as 0xd to trigger */
int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
struct auto_pin_cfg *cfg,
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index f0a422f5ea4..cc22d754843 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -2333,6 +2333,7 @@ static int create_hp_mic(struct hda_codec *codec)
cfg->inputs[cfg->num_inputs].pin = nid;
cfg->inputs[cfg->num_inputs].type = AUTO_PIN_MIC;
+ cfg->inputs[cfg->num_inputs].is_headphone_mic = 1;
cfg->num_inputs++;
spec->hp_mic = 1;
spec->hp_mic_pin = nid;