diff options
| -rw-r--r-- | sound/pci/hda/hda_generic.c | 57 |
1 files changed, 45 insertions, 12 deletions
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index faefff1d3e81..c4671d00babd 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
| @@ -2808,6 +2808,42 @@ static int add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx) | |||
| 2808 | return 0; | 2808 | return 0; |
| 2809 | } | 2809 | } |
| 2810 | 2810 | ||
| 2811 | /* return true if either a volume or a mute amp is found for the given | ||
| 2812 | * aamix path; the amp has to be either in the mixer node or its direct leaf | ||
| 2813 | */ | ||
| 2814 | static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid, | ||
| 2815 | hda_nid_t pin, unsigned int *mix_val, | ||
| 2816 | unsigned int *mute_val) | ||
| 2817 | { | ||
| 2818 | int idx, num_conns; | ||
| 2819 | const hda_nid_t *list; | ||
| 2820 | hda_nid_t nid; | ||
| 2821 | |||
| 2822 | idx = snd_hda_get_conn_index(codec, mix_nid, pin, true); | ||
| 2823 | if (idx < 0) | ||
| 2824 | return false; | ||
| 2825 | |||
| 2826 | *mix_val = *mute_val = 0; | ||
| 2827 | if (nid_has_volume(codec, mix_nid, HDA_INPUT)) | ||
| 2828 | *mix_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT); | ||
| 2829 | if (nid_has_mute(codec, mix_nid, HDA_INPUT)) | ||
| 2830 | *mute_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT); | ||
| 2831 | if (*mix_val && *mute_val) | ||
| 2832 | return true; | ||
| 2833 | |||
| 2834 | /* check leaf node */ | ||
| 2835 | num_conns = snd_hda_get_conn_list(codec, mix_nid, &list); | ||
| 2836 | if (num_conns < idx) | ||
| 2837 | return false; | ||
| 2838 | nid = list[idx]; | ||
| 2839 | if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT)) | ||
| 2840 | *mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); | ||
| 2841 | if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT)) | ||
| 2842 | *mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); | ||
| 2843 | |||
| 2844 | return *mix_val || *mute_val; | ||
| 2845 | } | ||
| 2846 | |||
| 2811 | /* create input playback/capture controls for the given pin */ | 2847 | /* create input playback/capture controls for the given pin */ |
| 2812 | static int new_analog_input(struct hda_codec *codec, int input_idx, | 2848 | static int new_analog_input(struct hda_codec *codec, int input_idx, |
| 2813 | hda_nid_t pin, const char *ctlname, int ctlidx, | 2849 | hda_nid_t pin, const char *ctlname, int ctlidx, |
| @@ -2815,12 +2851,11 @@ static int new_analog_input(struct hda_codec *codec, int input_idx, | |||
| 2815 | { | 2851 | { |
| 2816 | struct hda_gen_spec *spec = codec->spec; | 2852 | struct hda_gen_spec *spec = codec->spec; |
| 2817 | struct nid_path *path; | 2853 | struct nid_path *path; |
| 2818 | unsigned int val; | 2854 | unsigned int mix_val, mute_val; |
| 2819 | int err, idx; | 2855 | int err, idx; |
| 2820 | 2856 | ||
| 2821 | if (!nid_has_volume(codec, mix_nid, HDA_INPUT) && | 2857 | if (!look_for_mix_leaf_ctls(codec, mix_nid, pin, &mix_val, &mute_val)) |
| 2822 | !nid_has_mute(codec, mix_nid, HDA_INPUT)) | 2858 | return 0; |
| 2823 | return 0; /* no need for analog loopback */ | ||
| 2824 | 2859 | ||
| 2825 | path = snd_hda_add_new_path(codec, pin, mix_nid, 0); | 2860 | path = snd_hda_add_new_path(codec, pin, mix_nid, 0); |
| 2826 | if (!path) | 2861 | if (!path) |
| @@ -2829,20 +2864,18 @@ static int new_analog_input(struct hda_codec *codec, int input_idx, | |||
| 2829 | spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path); | 2864 | spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path); |
| 2830 | 2865 | ||
| 2831 | idx = path->idx[path->depth - 1]; | 2866 | idx = path->idx[path->depth - 1]; |
| 2832 | if (nid_has_volume(codec, mix_nid, HDA_INPUT)) { | 2867 | if (mix_val) { |
| 2833 | val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT); | 2868 | err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, mix_val); |
| 2834 | err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, val); | ||
| 2835 | if (err < 0) | 2869 | if (err < 0) |
| 2836 | return err; | 2870 | return err; |
| 2837 | path->ctls[NID_PATH_VOL_CTL] = val; | 2871 | path->ctls[NID_PATH_VOL_CTL] = mix_val; |
| 2838 | } | 2872 | } |
| 2839 | 2873 | ||
| 2840 | if (nid_has_mute(codec, mix_nid, HDA_INPUT)) { | 2874 | if (mute_val) { |
| 2841 | val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT); | 2875 | err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, mute_val); |
| 2842 | err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, val); | ||
| 2843 | if (err < 0) | 2876 | if (err < 0) |
| 2844 | return err; | 2877 | return err; |
| 2845 | path->ctls[NID_PATH_MUTE_CTL] = val; | 2878 | path->ctls[NID_PATH_MUTE_CTL] = mute_val; |
| 2846 | } | 2879 | } |
| 2847 | 2880 | ||
| 2848 | path->active = true; | 2881 | path->active = true; |
