aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-11-28 05:05:28 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-12-04 13:57:17 -0500
commitfe070ad95a7f94a658273f5f359a6875ad3cd38c (patch)
tree1436bd85d2b0947582043c242c0517199e3d68a2 /sound
parent7f9bf8ad0ea7457c6f3d5c6b04fe6c7b99fec63d (diff)
ALSA: hda - Check leaf nodes to find aamix amps
commit 2ded3e5b61d61d0bc90bebb8004db6184c7db6eb upstream. The current generic parser assumes blindly that the volume and mute amps are found in the aamix node itself. But on some codecs, typically Analog Devices ones, the aamix amps are separately implemented in each leaf node of the aamix node, and the current driver can't establish the correct amp controls. This is a regression compared with the previous static quirks. This patch extends the search for the amps to the leaf nodes for allowing the aamix controls again on such codecs. In this implementation, I didn't code to loop through the whole paths, since usually one depth should suffice, and we can't search too deeply, as it may result in the conflicting control assignments. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=65641 Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'sound')
-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 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 */
2753static 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 */
2751static int new_analog_input(struct hda_codec *codec, int input_idx, 2787static 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;