|
@@ -66,6 +66,8 @@ struct conexant_spec {
|
|
|
hda_nid_t eapds[4];
|
|
|
bool dynamic_eapd;
|
|
|
|
|
|
+ unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */
|
|
|
+
|
|
|
#ifdef ENABLE_CXT_STATIC_QUIRKS
|
|
|
const struct snd_kcontrol_new *mixers[5];
|
|
|
int num_mixers;
|
|
@@ -3200,6 +3202,9 @@ static int cx_auto_init(struct hda_codec *codec)
|
|
|
snd_hda_gen_init(codec);
|
|
|
if (!spec->dynamic_eapd)
|
|
|
cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true);
|
|
|
+
|
|
|
+ snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -3224,6 +3229,8 @@ enum {
|
|
|
CXT_PINCFG_LEMOTE_A1205,
|
|
|
CXT_FIXUP_STEREO_DMIC,
|
|
|
CXT_FIXUP_INC_MIC_BOOST,
|
|
|
+ CXT_FIXUP_HEADPHONE_MIC_PIN,
|
|
|
+ CXT_FIXUP_HEADPHONE_MIC,
|
|
|
};
|
|
|
|
|
|
static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
|
|
@@ -3246,6 +3253,59 @@ static void cxt5066_increase_mic_boost(struct hda_codec *codec,
|
|
|
(0 << AC_AMPCAP_MUTE_SHIFT));
|
|
|
}
|
|
|
|
|
|
+static void cxt_update_headset_mode(struct hda_codec *codec)
|
|
|
+{
|
|
|
+ /* The verbs used in this function were tested on a Conexant CX20751/2 codec. */
|
|
|
+ int i;
|
|
|
+ bool mic_mode = false;
|
|
|
+ struct conexant_spec *spec = codec->spec;
|
|
|
+ struct auto_pin_cfg *cfg = &spec->gen.autocfg;
|
|
|
+
|
|
|
+ hda_nid_t mux_pin = spec->gen.imux_pins[spec->gen.cur_mux[0]];
|
|
|
+
|
|
|
+ for (i = 0; i < cfg->num_inputs; i++)
|
|
|
+ if (cfg->inputs[i].pin == mux_pin) {
|
|
|
+ mic_mode = !!cfg->inputs[i].is_headphone_mic;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mic_mode) {
|
|
|
+ snd_hda_codec_write_cache(codec, 0x1c, 0, 0x410, 0x7c); /* enable merged mode for analog int-mic */
|
|
|
+ spec->gen.hp_jack_present = false;
|
|
|
+ } else {
|
|
|
+ snd_hda_codec_write_cache(codec, 0x1c, 0, 0x410, 0x54); /* disable merged mode for analog int-mic */
|
|
|
+ spec->gen.hp_jack_present = snd_hda_jack_detect(codec, spec->gen.autocfg.hp_pins[0]);
|
|
|
+ }
|
|
|
+
|
|
|
+ snd_hda_gen_update_outputs(codec);
|
|
|
+}
|
|
|
+
|
|
|
+static void cxt_update_headset_mode_hook(struct hda_codec *codec,
|
|
|
+ struct snd_ctl_elem_value *ucontrol)
|
|
|
+{
|
|
|
+ cxt_update_headset_mode(codec);
|
|
|
+}
|
|
|
+
|
|
|
+static void cxt_fixup_headphone_mic(struct hda_codec *codec,
|
|
|
+ const struct hda_fixup *fix, int action)
|
|
|
+{
|
|
|
+ struct conexant_spec *spec = codec->spec;
|
|
|
+
|
|
|
+ switch (action) {
|
|
|
+ case HDA_FIXUP_ACT_PRE_PROBE:
|
|
|
+ spec->parse_flags |= HDA_PINCFG_HEADPHONE_MIC;
|
|
|
+ break;
|
|
|
+ case HDA_FIXUP_ACT_PROBE:
|
|
|
+ spec->gen.cap_sync_hook = cxt_update_headset_mode_hook;
|
|
|
+ spec->gen.automute_hook = cxt_update_headset_mode;
|
|
|
+ break;
|
|
|
+ case HDA_FIXUP_ACT_INIT:
|
|
|
+ cxt_update_headset_mode(codec);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
/* ThinkPad X200 & co with cxt5051 */
|
|
|
static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = {
|
|
|
{ 0x16, 0x042140ff }, /* HP (seq# overridden) */
|
|
@@ -3302,6 +3362,19 @@ static const struct hda_fixup cxt_fixups[] = {
|
|
|
.type = HDA_FIXUP_FUNC,
|
|
|
.v.func = cxt5066_increase_mic_boost,
|
|
|
},
|
|
|
+ [CXT_FIXUP_HEADPHONE_MIC_PIN] = {
|
|
|
+ .type = HDA_FIXUP_PINS,
|
|
|
+ .chained = true,
|
|
|
+ .chain_id = CXT_FIXUP_HEADPHONE_MIC,
|
|
|
+ .v.pins = (const struct hda_pintbl[]) {
|
|
|
+ { 0x18, 0x03a1913d }, /* use as headphone mic, without its own jack detect */
|
|
|
+ { }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ [CXT_FIXUP_HEADPHONE_MIC] = {
|
|
|
+ .type = HDA_FIXUP_FUNC,
|
|
|
+ .v.func = cxt_fixup_headphone_mic,
|
|
|
+ },
|
|
|
};
|
|
|
|
|
|
static const struct snd_pci_quirk cxt5051_fixups[] = {
|
|
@@ -3311,6 +3384,7 @@ static const struct snd_pci_quirk cxt5051_fixups[] = {
|
|
|
|
|
|
static const struct snd_pci_quirk cxt5066_fixups[] = {
|
|
|
SND_PCI_QUIRK(0x1025, 0x0543, "Acer Aspire One 522", CXT_FIXUP_STEREO_DMIC),
|
|
|
+ SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN),
|
|
|
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),
|
|
|
SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T410", CXT_PINCFG_LENOVO_TP410),
|
|
|
SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410),
|
|
@@ -3395,7 +3469,8 @@ static int patch_conexant_auto(struct hda_codec *codec)
|
|
|
|
|
|
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
|
|
|
|
|
|
- err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL, 0);
|
|
|
+ err = snd_hda_parse_pin_defcfg(codec, &spec->gen.autocfg, NULL,
|
|
|
+ spec->parse_flags);
|
|
|
if (err < 0)
|
|
|
goto error;
|
|
|
|
|
@@ -3416,6 +3491,8 @@ static int patch_conexant_auto(struct hda_codec *codec)
|
|
|
codec->bus->allow_bus_reset = 1;
|
|
|
}
|
|
|
|
|
|
+ snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
|
|
|
+
|
|
|
return 0;
|
|
|
|
|
|
error:
|