diff options
Diffstat (limited to 'sound')
-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 3a3abfa6150c..7975031312cb 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -2747,6 +2747,42 @@ static int add_loopback_list(struct hda_gen_spec *spec, hda_nid_t mix, int idx) | |||
2747 | return 0; | 2747 | return 0; |
2748 | } | 2748 | } |
2749 | 2749 | ||
2750 | /* return true if either a volume or a mute amp is found for the given | ||
2751 | * aamix path; the amp has to be either in the mixer node or its direct leaf | ||
2752 | */ | ||
2753 | static bool look_for_mix_leaf_ctls(struct hda_codec *codec, hda_nid_t mix_nid, | ||
2754 | hda_nid_t pin, unsigned int *mix_val, | ||
2755 | unsigned int *mute_val) | ||
2756 | { | ||
2757 | int idx, num_conns; | ||
2758 | const hda_nid_t *list; | ||
2759 | hda_nid_t nid; | ||
2760 | |||
2761 | idx = snd_hda_get_conn_index(codec, mix_nid, pin, true); | ||
2762 | if (idx < 0) | ||
2763 | return false; | ||
2764 | |||
2765 | *mix_val = *mute_val = 0; | ||
2766 | if (nid_has_volume(codec, mix_nid, HDA_INPUT)) | ||
2767 | *mix_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT); | ||
2768 | if (nid_has_mute(codec, mix_nid, HDA_INPUT)) | ||
2769 | *mute_val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT); | ||
2770 | if (*mix_val && *mute_val) | ||
2771 | return true; | ||
2772 | |||
2773 | /* check leaf node */ | ||
2774 | num_conns = snd_hda_get_conn_list(codec, mix_nid, &list); | ||
2775 | if (num_conns < idx) | ||
2776 | return false; | ||
2777 | nid = list[idx]; | ||
2778 | if (!*mix_val && nid_has_volume(codec, nid, HDA_OUTPUT)) | ||
2779 | *mix_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); | ||
2780 | if (!*mute_val && nid_has_mute(codec, nid, HDA_OUTPUT)) | ||
2781 | *mute_val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); | ||
2782 | |||
2783 | return *mix_val || *mute_val; | ||
2784 | } | ||
2785 | |||
2750 | /* create input playback/capture controls for the given pin */ | 2786 | /* create input playback/capture controls for the given pin */ |
2751 | static int new_analog_input(struct hda_codec *codec, int input_idx, | 2787 | static int new_analog_input(struct hda_codec *codec, int input_idx, |
2752 | hda_nid_t pin, const char *ctlname, int ctlidx, | 2788 | hda_nid_t pin, const char *ctlname, int ctlidx, |
@@ -2754,12 +2790,11 @@ static int new_analog_input(struct hda_codec *codec, int input_idx, | |||
2754 | { | 2790 | { |
2755 | struct hda_gen_spec *spec = codec->spec; | 2791 | struct hda_gen_spec *spec = codec->spec; |
2756 | struct nid_path *path; | 2792 | struct nid_path *path; |
2757 | unsigned int val; | 2793 | unsigned int mix_val, mute_val; |
2758 | int err, idx; | 2794 | int err, idx; |
2759 | 2795 | ||
2760 | if (!nid_has_volume(codec, mix_nid, HDA_INPUT) && | 2796 | if (!look_for_mix_leaf_ctls(codec, mix_nid, pin, &mix_val, &mute_val)) |
2761 | !nid_has_mute(codec, mix_nid, HDA_INPUT)) | 2797 | return 0; |
2762 | return 0; /* no need for analog loopback */ | ||
2763 | 2798 | ||
2764 | path = snd_hda_add_new_path(codec, pin, mix_nid, 0); | 2799 | path = snd_hda_add_new_path(codec, pin, mix_nid, 0); |
2765 | if (!path) | 2800 | if (!path) |
@@ -2768,20 +2803,18 @@ static int new_analog_input(struct hda_codec *codec, int input_idx, | |||
2768 | spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path); | 2803 | spec->loopback_paths[input_idx] = snd_hda_get_path_idx(codec, path); |
2769 | 2804 | ||
2770 | idx = path->idx[path->depth - 1]; | 2805 | idx = path->idx[path->depth - 1]; |
2771 | if (nid_has_volume(codec, mix_nid, HDA_INPUT)) { | 2806 | if (mix_val) { |
2772 | val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT); | 2807 | err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, mix_val); |
2773 | err = __add_pb_vol_ctrl(spec, HDA_CTL_WIDGET_VOL, ctlname, ctlidx, val); | ||
2774 | if (err < 0) | 2808 | if (err < 0) |
2775 | return err; | 2809 | return err; |
2776 | path->ctls[NID_PATH_VOL_CTL] = val; | 2810 | path->ctls[NID_PATH_VOL_CTL] = mix_val; |
2777 | } | 2811 | } |
2778 | 2812 | ||
2779 | if (nid_has_mute(codec, mix_nid, HDA_INPUT)) { | 2813 | if (mute_val) { |
2780 | val = HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT); | 2814 | err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, mute_val); |
2781 | err = __add_pb_sw_ctrl(spec, HDA_CTL_WIDGET_MUTE, ctlname, ctlidx, val); | ||
2782 | if (err < 0) | 2815 | if (err < 0) |
2783 | return err; | 2816 | return err; |
2784 | path->ctls[NID_PATH_MUTE_CTL] = val; | 2817 | path->ctls[NID_PATH_MUTE_CTL] = mute_val; |
2785 | } | 2818 | } |
2786 | 2819 | ||
2787 | path->active = true; | 2820 | path->active = true; |