mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
b54f8abad6
commit
00227f15a0
|
@ -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 call_update_outputs(struct hda_codec *codec);
|
||||||
static void alc_inv_dmic_sync(struct hda_codec *codec, bool force);
|
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 */
|
/* 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,
|
static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
|
||||||
unsigned int idx, bool force)
|
unsigned int idx, bool force)
|
||||||
|
@ -329,21 +361,8 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
|
||||||
return 0;
|
return 0;
|
||||||
spec->cur_mux[adc_idx] = idx;
|
spec->cur_mux[adc_idx] = idx;
|
||||||
|
|
||||||
/* for shared I/O, change the pin-control accordingly */
|
if (spec->shared_mic_hp)
|
||||||
if (spec->shared_mic_hp) {
|
update_shared_mic_hp(codec, spec->cur_mux[adc_idx]);
|
||||||
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->dyn_adc_switch) {
|
if (spec->dyn_adc_switch) {
|
||||||
alc_dyn_adc_pcm_resetup(codec, idx);
|
alc_dyn_adc_pcm_resetup(codec, idx);
|
||||||
|
|
Loading…
Reference in New Issue