aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/pci/hda/hda_generic.c57
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 */
2814static 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 */
2812static int new_analog_input(struct hda_codec *codec, int input_idx, 2848static 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;