diff options
author | David Henningsson <david.henningsson@canonical.com> | 2012-06-27 18:45:44 +0200 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2012-06-27 20:20:40 +0200 |
commit | 00227f15a0ad8401d2b0b67905da63e75b544895 (patch) | |
tree | 06e4aaddddbb819a5beb014612cd58151e98238d /sound/pci | |
parent | b54f8abad63fa409fa637e86d2bebd597342c0f8 (diff) | |
download | lwn-00227f15a0ad8401d2b0b67905da63e75b544895.tar.gz lwn-00227f15a0ad8401d2b0b67905da63e75b544895.zip |
ALSA: HDA: Support single 3-pin jack without VREF on the actual pin
Some ASUS device has a single 3-pin jack that can either be a mic or
a headphone, but the pin does not have VREF capabilities. We've been
told by Realtek to instead enable VREF on pin 0x18 in that case.
BugLink: https://bugs.launchpad.net/bugs/1018262
Tested-by: Chih-Hsyuan Ho <chih.ho@canonical.com>
Signed-off-by: David Henningsson <david.henningsson@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 49 |
1 files changed, 34 insertions, 15 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 5c81ee95d7f0..40dda2a83774 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -303,6 +303,38 @@ static inline hda_nid_t get_capsrc(struct alc_spec *spec, int idx) static void call_update_outputs(struct hda_codec *codec); static void alc_inv_dmic_sync(struct hda_codec *codec, bool force); +/* for shared I/O, change the pin-control accordingly */ +static void update_shared_mic_hp(struct hda_codec *codec, bool set_as_mic) +{ + struct alc_spec *spec = codec->spec; + unsigned int val; + hda_nid_t pin = spec->autocfg.inputs[1].pin; + /* NOTE: this assumes that there are only two inputs, the + * first is the real internal mic and the second is HP/mic jack. + */ + + val = snd_hda_get_default_vref(codec, pin); + + /* This pin does not have vref caps - let's enable vref on pin 0x18 + instead, as suggested by Realtek */ + if (val == AC_PINCTL_VREF_HIZ) { + const hda_nid_t vref_pin = 0x18; + /* Sanity check pin 0x18 */ + if (get_wcaps_type(get_wcaps(codec, vref_pin)) == AC_WID_PIN && + get_defcfg_connect(snd_hda_codec_get_pincfg(codec, vref_pin)) == AC_JACK_PORT_NONE) { + unsigned int vref_val = snd_hda_get_default_vref(codec, vref_pin); + if (vref_val != AC_PINCTL_VREF_HIZ) + snd_hda_set_pin_ctl(codec, vref_pin, PIN_IN | (set_as_mic ? vref_val : 0)); + } + } + + val = set_as_mic ? val | PIN_IN : PIN_HP; + snd_hda_set_pin_ctl(codec, pin, val); + + spec->automute_speaker = !set_as_mic; + call_update_outputs(codec); +} + /* select the given imux item; either unmute exclusively or select the route */ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, unsigned int idx, bool force) @@ -329,21 +361,8 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, return 0; spec->cur_mux[adc_idx] = idx; - /* for shared I/O, change the pin-control accordingly */ - if (spec->shared_mic_hp) { - unsigned int val; - hda_nid_t pin = spec->autocfg.inputs[1].pin; - /* NOTE: this assumes that there are only two inputs, the - * first is the real internal mic and the second is HP jack. - */ - if (spec->cur_mux[adc_idx]) - val = snd_hda_get_default_vref(codec, pin) | PIN_IN; - else - val = PIN_HP; - snd_hda_set_pin_ctl(codec, pin, val); - spec->automute_speaker = !spec->cur_mux[adc_idx]; - call_update_outputs(codec); - } + if (spec->shared_mic_hp) + update_shared_mic_hp(codec, spec->cur_mux[adc_idx]); if (spec->dyn_adc_switch) { alc_dyn_adc_pcm_resetup(codec, idx); |