Commit cb420b11 authored by David Henningsson's avatar David Henningsson Committed by Takashi Iwai

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: default avatarDavid Henningsson <david.henningsson@canonical.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 01f9326a
...@@ -119,6 +119,32 @@ static bool check_pincap_validity(struct hda_codec *codec, hda_nid_t pin, ...@@ -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 * Parse all pin widgets and store the useful pin nids to cfg
* *
...@@ -260,22 +286,38 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, ...@@ -260,22 +286,38 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
} }
} }
/* Take first mic to be a headset mic pin */ /* Find a pin that could be a headset or headphone mic */
if (cond_flags & HDA_PINCFG_HEADSET_MIC) { if (cond_flags & HDA_PINCFG_HEADSET_MIC || cond_flags & HDA_PINCFG_HEADPHONE_MIC) {
for (i = 0; i < cfg->num_inputs; i++) { bool hsmic = !!(cond_flags & HDA_PINCFG_HEADSET_MIC);
int attr; bool hpmic = !!(cond_flags & HDA_PINCFG_HEADPHONE_MIC);
unsigned int def_conf; for (i = 0; (hsmic || hpmic) && (i < cfg->num_inputs); i++)
if (cfg->inputs[i].type != AUTO_PIN_MIC) if (hsmic && can_be_headset_mic(codec, &cfg->inputs[i], 0xc)) {
continue; cfg->inputs[i].is_headset_mic = 1;
def_conf = snd_hda_codec_get_pincfg(codec, cfg->inputs[i].pin); hsmic = false;
attr = snd_hda_get_input_pin_attr(def_conf); } else if (hpmic && can_be_headset_mic(codec, &cfg->inputs[i], 0xd)) {
if (attr <= INPUT_PIN_ATTR_DOCK) 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; continue;
if (hsmic) {
cfg->inputs[i].is_headset_mic = 1; cfg->inputs[i].is_headset_mic = 1;
break; 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: /* FIX-UP:
* If no line-out is defined but multiple HPs are found, * If no line-out is defined but multiple HPs are found,
* some of them might be the real line-outs. * some of them might be the real line-outs.
...@@ -419,6 +461,8 @@ static const char *hda_get_input_pin_label(struct hda_codec *codec, ...@@ -419,6 +461,8 @@ static const char *hda_get_input_pin_label(struct hda_codec *codec,
case AC_JACK_MIC_IN: case AC_JACK_MIC_IN:
if (item && item->is_headset_mic) if (item && item->is_headset_mic)
return "Headset Mic"; return "Headset Mic";
if (item && item->is_headphone_mic)
return "Headphone Mic";
if (!check_location) if (!check_location)
return "Mic"; return "Mic";
attr = snd_hda_get_input_pin_attr(def_conf); attr = snd_hda_get_input_pin_attr(def_conf);
......
...@@ -37,6 +37,7 @@ struct auto_pin_cfg_item { ...@@ -37,6 +37,7 @@ struct auto_pin_cfg_item {
hda_nid_t pin; hda_nid_t pin;
int type; int type;
unsigned int is_headset_mic:1; unsigned int is_headset_mic:1;
unsigned int is_headphone_mic:1; /* Mic-only in headphone jack */
}; };
struct auto_pin_cfg; struct auto_pin_cfg;
...@@ -81,7 +82,8 @@ struct auto_pin_cfg { ...@@ -81,7 +82,8 @@ struct auto_pin_cfg {
/* bit-flags for snd_hda_parse_pin_def_config() behavior */ /* 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_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_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_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, int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
struct auto_pin_cfg *cfg, struct auto_pin_cfg *cfg,
......
...@@ -2333,6 +2333,7 @@ static int create_hp_mic(struct hda_codec *codec) ...@@ -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].pin = nid;
cfg->inputs[cfg->num_inputs].type = AUTO_PIN_MIC; cfg->inputs[cfg->num_inputs].type = AUTO_PIN_MIC;
cfg->inputs[cfg->num_inputs].is_headphone_mic = 1;
cfg->num_inputs++; cfg->num_inputs++;
spec->hp_mic = 1; spec->hp_mic = 1;
spec->hp_mic_pin = nid; spec->hp_mic_pin = nid;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment