diff options
Diffstat (limited to 'sound/pci/hda/hda_generic.c')
-rw-r--r-- | sound/pci/hda/hda_generic.c | 91 |
1 files changed, 25 insertions, 66 deletions
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index c4671d0..b7c89df 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -549,15 +549,11 @@ static hda_nid_t look_for_out_mute_nid(struct hda_codec *codec, static hda_nid_t look_for_out_vol_nid(struct hda_codec *codec, struct nid_path *path) { - struct hda_gen_spec *spec = codec->spec; int i; for (i = path->depth - 1; i >= 0; i--) { - hda_nid_t nid = path->path[i]; - if ((spec->out_vol_mask >> nid) & 1) - continue; - if (nid_has_volume(codec, nid, HDA_OUTPUT)) - return nid; + if (nid_has_volume(codec, path->path[i], HDA_OUTPUT)) + return path->path[i]; } return 0; } @@ -796,10 +792,10 @@ static void set_pin_eapd(struct hda_codec *codec, hda_nid_t pin, bool enable) if (spec->own_eapd_ctl || !(snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_EAPD)) return; - if (spec->keep_eapd_on && !enable) - return; if (codec->inv_eapd) enable = !enable; + if (spec->keep_eapd_on && !enable) + return; snd_hda_codec_update_cache(codec, pin, 0, AC_VERB_SET_EAPD_BTLENABLE, enable ? 0x02 : 0x00); @@ -2506,8 +2502,12 @@ static int create_out_jack_modes(struct hda_codec *codec, int num_pins, for (i = 0; i < num_pins; i++) { hda_nid_t pin = pins[i]; - if (pin == spec->hp_mic_pin) + if (pin == spec->hp_mic_pin) { + int ret = create_hp_mic_jack_mode(codec, pin); + if (ret < 0) + return ret; continue; + } if (get_out_jack_num_items(codec, pin) > 1) { struct snd_kcontrol_new *knew; char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; @@ -2760,7 +2760,7 @@ static int hp_mic_jack_mode_put(struct snd_kcontrol *kcontrol, val &= ~(AC_PINCTL_VREFEN | PIN_HP); val |= get_vref_idx(vref_caps, idx) | PIN_IN; } else - val = snd_hda_get_default_vref(codec, nid) | PIN_IN; + val = snd_hda_get_default_vref(codec, nid); } snd_hda_set_pin_ctl_cache(codec, nid, val); call_hp_automute(codec, NULL); @@ -2780,6 +2780,9 @@ static int create_hp_mic_jack_mode(struct hda_codec *codec, hda_nid_t pin) struct hda_gen_spec *spec = codec->spec; struct snd_kcontrol_new *knew; + if (get_out_jack_num_items(codec, pin) <= 1 && + get_in_jack_num_items(codec, pin) <= 1) + return 0; /* no need */ knew = snd_hda_gen_add_kctl(spec, "Headphone Mic Jack Mode", &hp_mic_jack_mode_enum); if (!knew) @@ -2808,42 +2811,6 @@ static int add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx) return 0; } -/* return true if either a volume or a mute amp is found for the given - * aamix path; the amp has to be either in the mixer node or its direct leaf - */ -static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid, - hda_nid_t pin, unsigned int *mix_val, - unsigned int *mute_val) -{ - int idx, num_conns; - const hda_nid_t *list; - hda_nid_t nid; - - idx = snd_hda_get_conn_index(codec, mix_nid, pin, true); - if (idx < 0) - return false; - - *mix_val = *mute_val = 0; - if (nid_has_volume(codec, mix_nid, HDA_INPUT)) - *mix_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT); - if (nid_has_mute(codec, mix_nid, HDA_INPUT)) - *mute_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT); - if (*mix_val && *mute_val) - return true; - - /* check leaf node */ - num_conns = snd_hda_get_conn_list(codec, mix_nid, &list); - if (num_conns < idx) - return false; - nid = list[idx]; - if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT)) - *mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); - if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT)) - *mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); - - return *mix_val || *mute_val; -} - /* create input playback/capture controls for the given pin */ static int new_analog_input(struct hda_codec *codec, int input_idx, hda_nid_t pin, const char *ctlname, int ctlidx, @@ -2851,11 +2818,12 @@ static int new_analog_input(struct hda_codec *codec, int input_idx, { struct hda_gen_spec *spec = codec->spec; struct nid_path *path; - unsigned int mix_val, mute_val; + unsigned int val; int err, idx; - if (!look_for_mix_leaf_ctls(codec, mix_nid, pin, &mix_val, &mute_val)) - return 0; + if (!nid_has_volume(codec, mix_nid, HDA_INPUT) && + !nid_has_mute(codec, mix_nid, HDA_INPUT)) + return 0; /* no need for analog loopback */ path = snd_hda_add_new_path(codec, pin, mix_nid, 0); if (!path) @@ -2864,18 +2832,20 @@ static int new_analog_input(struct hda_codec *codec, int input_idx, spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path); idx = path->idx[path->depth - 1]; - if (mix_val) { - err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, mix_val); + if (nid_has_volume(codec, mix_nid, HDA_INPUT)) { + val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT); + err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, val); if (err < 0) return err; - path->ctls[NID_PATH_VOL_CTL] = mix_val; + path->ctls[NID_PATH_VOL_CTL] = val; } - if (mute_val) { - err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, mute_val); + if (nid_has_mute(codec, mix_nid, HDA_INPUT)) { + val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT); + err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, val); if (err < 0) return err; - path->ctls[NID_PATH_MUTE_CTL] = mute_val; + path->ctls[NID_PATH_MUTE_CTL] = val; } path->active = true; @@ -4409,17 +4379,6 @@ int snd_hda_gen_parse_auto_config(struct hda_codec *codec, if (err < 0) return err; - /* create "Headphone Mic Jack Mode" if no input selection is - * available (or user specifies add_jack_modes hint) - */ - if (spec->hp_mic_pin && - (spec->auto_mic || spec->input_mux.num_items == 1 || - spec->add_jack_modes)) { - err = create_hp_mic_jack_mode(codec, spec->hp_mic_pin); - if (err < 0) - return err; - } - if (spec->add_jack_modes) { if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { err = create_out_jack_modes(codec, cfg->line_outs, |