diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-06-20 07:52:33 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-06-20 10:24:12 -0400 |
commit | e3d7a1431f1d8851d11b2262dda5bb67158450eb (patch) | |
tree | d9c5edb4ba34f2adb2899fe8012cfc8db7e26a2b /sound/pci | |
parent | 370bafbdae3d78c9081ebe3028a3ff5f0e91357b (diff) |
ALSA: hda - Fix smart51 handling again
Fix the broken detection of smart51 and its handling.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/patch_via.c | 147 |
1 files changed, 64 insertions, 83 deletions
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index deb33ae109c8..c3be9f124b68 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -165,12 +165,17 @@ struct via_spec { | |||
165 | const struct hda_input_mux *hp_mux; | 165 | const struct hda_input_mux *hp_mux; |
166 | unsigned int hp_independent_mode; | 166 | unsigned int hp_independent_mode; |
167 | unsigned int hp_independent_mode_index; | 167 | unsigned int hp_independent_mode_index; |
168 | unsigned int can_smart51; | ||
169 | unsigned int smart51_enabled; | ||
170 | unsigned int dmic_enabled; | 168 | unsigned int dmic_enabled; |
171 | unsigned int no_pin_power_ctl; | 169 | unsigned int no_pin_power_ctl; |
172 | enum VIA_HDA_CODEC codec_type; | 170 | enum VIA_HDA_CODEC codec_type; |
173 | 171 | ||
172 | /* smart51 setup */ | ||
173 | unsigned int smart51_nums; | ||
174 | hda_nid_t smart51_pins[2]; | ||
175 | int smart51_idxs[2]; | ||
176 | const char *smart51_labels[2]; | ||
177 | unsigned int smart51_enabled; | ||
178 | |||
174 | /* work to check hp jack state */ | 179 | /* work to check hp jack state */ |
175 | struct hda_codec *codec; | 180 | struct hda_codec *codec; |
176 | struct delayed_work vt1708_hp_work; | 181 | struct delayed_work vt1708_hp_work; |
@@ -508,7 +513,7 @@ static void via_auto_init_multi_out(struct hda_codec *codec) | |||
508 | struct via_spec *spec = codec->spec; | 513 | struct via_spec *spec = codec->spec; |
509 | int i; | 514 | int i; |
510 | 515 | ||
511 | for (i = 0; i < spec->autocfg.line_outs; i++) | 516 | for (i = 0; i < spec->autocfg.line_outs + spec->smart51_nums; i++) |
512 | via_auto_init_output(codec, spec->autocfg.line_out_pins[i], | 517 | via_auto_init_output(codec, spec->autocfg.line_out_pins[i], |
513 | PIN_OUT, &spec->out_path[i]); | 518 | PIN_OUT, &spec->out_path[i]); |
514 | } | 519 | } |
@@ -771,15 +776,15 @@ static int via_hp_build(struct hda_codec *codec) | |||
771 | 776 | ||
772 | static void notify_aa_path_ctls(struct hda_codec *codec) | 777 | static void notify_aa_path_ctls(struct hda_codec *codec) |
773 | { | 778 | { |
779 | struct via_spec *spec = codec->spec; | ||
774 | int i; | 780 | int i; |
775 | struct snd_ctl_elem_id id; | 781 | |
776 | const char *labels[] = {"Mic", "Front Mic", "Line", "Rear Mic"}; | 782 | for (i = 0; i < spec->smart51_nums; i++) { |
777 | struct snd_kcontrol *ctl; | 783 | struct snd_kcontrol *ctl; |
778 | 784 | struct snd_ctl_elem_id id; | |
779 | memset(&id, 0, sizeof(id)); | 785 | memset(&id, 0, sizeof(id)); |
780 | id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | 786 | id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; |
781 | for (i = 0; i < ARRAY_SIZE(labels); i++) { | 787 | sprintf(id.name, "%s Playback Volume", spec->smart51_labels[i]); |
782 | sprintf(id.name, "%s Playback Volume", labels[i]); | ||
783 | ctl = snd_hda_find_mixer_ctl(codec, id.name); | 788 | ctl = snd_hda_find_mixer_ctl(codec, id.name); |
784 | if (ctl) | 789 | if (ctl) |
785 | snd_ctl_notify(codec->bus->card, | 790 | snd_ctl_notify(codec->bus->card, |
@@ -791,43 +796,20 @@ static void notify_aa_path_ctls(struct hda_codec *codec) | |||
791 | static void mute_aa_path(struct hda_codec *codec, int mute) | 796 | static void mute_aa_path(struct hda_codec *codec, int mute) |
792 | { | 797 | { |
793 | struct via_spec *spec = codec->spec; | 798 | struct via_spec *spec = codec->spec; |
794 | int start_idx; | 799 | int val = mute ? HDA_AMP_MUTE : HDA_AMP_UNMUTE; |
795 | int end_idx; | ||
796 | int i; | 800 | int i; |
797 | /* get nid of MW0 and start & end index */ | 801 | |
798 | switch (spec->codec_type) { | ||
799 | case VT1708: | ||
800 | start_idx = 2; | ||
801 | end_idx = 4; | ||
802 | break; | ||
803 | case VT1709_10CH: | ||
804 | case VT1709_6CH: | ||
805 | start_idx = 2; | ||
806 | end_idx = 4; | ||
807 | break; | ||
808 | case VT1708B_8CH: | ||
809 | case VT1708B_4CH: | ||
810 | case VT1708S: | ||
811 | case VT1716S: | ||
812 | start_idx = 2; | ||
813 | end_idx = 4; | ||
814 | break; | ||
815 | case VT1718S: | ||
816 | start_idx = 1; | ||
817 | end_idx = 3; | ||
818 | break; | ||
819 | default: | ||
820 | return; | ||
821 | } | ||
822 | /* check AA path's mute status */ | 802 | /* check AA path's mute status */ |
823 | for (i = start_idx; i <= end_idx; i++) { | 803 | for (i = 0; i < spec->smart51_nums; i++) { |
824 | int val = mute ? HDA_AMP_MUTE : HDA_AMP_UNMUTE; | 804 | if (spec->smart51_idxs[i] < 0) |
825 | snd_hda_codec_amp_stereo(codec, spec->aa_mix_nid, HDA_INPUT, i, | 805 | continue; |
806 | snd_hda_codec_amp_stereo(codec, spec->aa_mix_nid, | ||
807 | HDA_INPUT, spec->smart51_idxs[i], | ||
826 | HDA_AMP_MUTE, val); | 808 | HDA_AMP_MUTE, val); |
827 | } | 809 | } |
828 | } | 810 | } |
829 | 811 | ||
830 | static bool is_smart51_pins(struct hda_codec *codec, hda_nid_t pin) | 812 | static bool is_smart51_candidate(struct hda_codec *codec, hda_nid_t pin) |
831 | { | 813 | { |
832 | struct via_spec *spec = codec->spec; | 814 | struct via_spec *spec = codec->spec; |
833 | const struct auto_pin_cfg *cfg = &spec->autocfg; | 815 | const struct auto_pin_cfg *cfg = &spec->autocfg; |
@@ -847,6 +829,17 @@ static bool is_smart51_pins(struct hda_codec *codec, hda_nid_t pin) | |||
847 | return false; | 829 | return false; |
848 | } | 830 | } |
849 | 831 | ||
832 | static bool is_smart51_pins(struct hda_codec *codec, hda_nid_t pin) | ||
833 | { | ||
834 | struct via_spec *spec = codec->spec; | ||
835 | int i; | ||
836 | |||
837 | for (i = 0; i < spec->smart51_nums; i++) | ||
838 | if (spec->smart51_pins[i] == pin) | ||
839 | return true; | ||
840 | return false; | ||
841 | } | ||
842 | |||
850 | static int via_smart51_info(struct snd_kcontrol *kcontrol, | 843 | static int via_smart51_info(struct snd_kcontrol *kcontrol, |
851 | struct snd_ctl_elem_info *uinfo) | 844 | struct snd_ctl_elem_info *uinfo) |
852 | { | 845 | { |
@@ -862,18 +855,12 @@ static int via_smart51_get(struct snd_kcontrol *kcontrol, | |||
862 | { | 855 | { |
863 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 856 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
864 | struct via_spec *spec = codec->spec; | 857 | struct via_spec *spec = codec->spec; |
865 | const struct auto_pin_cfg *cfg = &spec->autocfg; | ||
866 | int on = 1; | 858 | int on = 1; |
867 | int i; | 859 | int i; |
868 | 860 | ||
869 | for (i = 0; i < cfg->num_inputs; i++) { | 861 | for (i = 0; i < spec->smart51_nums; i++) { |
870 | hda_nid_t nid = cfg->inputs[i].pin; | 862 | hda_nid_t nid = spec->smart51_pins[i]; |
871 | unsigned int ctl; | 863 | unsigned int ctl; |
872 | if (cfg->inputs[i].type == AUTO_PIN_MIC && | ||
873 | spec->hp_independent_mode && spec->codec_type != VT1718S) | ||
874 | continue; /* ignore FMic for independent HP */ | ||
875 | if (!is_smart51_pins(codec, nid)) | ||
876 | continue; | ||
877 | ctl = snd_hda_codec_read(codec, nid, 0, | 864 | ctl = snd_hda_codec_read(codec, nid, 0, |
878 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 865 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
879 | if ((ctl & AC_PINCTL_IN_EN) && !(ctl & AC_PINCTL_OUT_EN)) | 866 | if ((ctl & AC_PINCTL_IN_EN) && !(ctl & AC_PINCTL_OUT_EN)) |
@@ -888,21 +875,14 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol, | |||
888 | { | 875 | { |
889 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 876 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
890 | struct via_spec *spec = codec->spec; | 877 | struct via_spec *spec = codec->spec; |
891 | const struct auto_pin_cfg *cfg = &spec->autocfg; | ||
892 | int out_in = *ucontrol->value.integer.value | 878 | int out_in = *ucontrol->value.integer.value |
893 | ? AC_PINCTL_OUT_EN : AC_PINCTL_IN_EN; | 879 | ? AC_PINCTL_OUT_EN : AC_PINCTL_IN_EN; |
894 | int i; | 880 | int i; |
895 | 881 | ||
896 | for (i = 0; i < cfg->num_inputs; i++) { | 882 | for (i = 0; i < spec->smart51_nums; i++) { |
897 | hda_nid_t nid = cfg->inputs[i].pin; | 883 | hda_nid_t nid = spec->smart51_pins[i]; |
898 | unsigned int parm; | 884 | unsigned int parm; |
899 | 885 | ||
900 | if (cfg->inputs[i].type == AUTO_PIN_MIC && | ||
901 | spec->hp_independent_mode && spec->codec_type != VT1718S) | ||
902 | continue; /* don't retask FMic for independent HP */ | ||
903 | if (!is_smart51_pins(codec, nid)) | ||
904 | continue; | ||
905 | |||
906 | parm = snd_hda_codec_read(codec, nid, 0, | 886 | parm = snd_hda_codec_read(codec, nid, 0, |
907 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 887 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
908 | parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); | 888 | parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); |
@@ -932,26 +912,11 @@ static const struct snd_kcontrol_new via_smart51_mixer = { | |||
932 | static int via_smart51_build(struct hda_codec *codec) | 912 | static int via_smart51_build(struct hda_codec *codec) |
933 | { | 913 | { |
934 | struct via_spec *spec = codec->spec; | 914 | struct via_spec *spec = codec->spec; |
935 | struct snd_kcontrol_new *knew; | ||
936 | const struct auto_pin_cfg *cfg = &spec->autocfg; | ||
937 | hda_nid_t nid; | ||
938 | int i; | ||
939 | 915 | ||
940 | if (!spec->can_smart51) | 916 | if (!spec->smart51_nums) |
941 | return 0; | 917 | return 0; |
942 | 918 | if (!via_clone_control(spec, &via_smart51_mixer)) | |
943 | knew = via_clone_control(spec, &via_smart51_mixer); | ||
944 | if (knew == NULL) | ||
945 | return -ENOMEM; | 919 | return -ENOMEM; |
946 | |||
947 | for (i = 0; i < cfg->num_inputs; i++) { | ||
948 | nid = cfg->inputs[i].pin; | ||
949 | if (is_smart51_pins(codec, nid)) { | ||
950 | knew->subdevice = HDA_SUBDEV_NID_FLAG | nid; | ||
951 | break; | ||
952 | } | ||
953 | } | ||
954 | |||
955 | return 0; | 920 | return 0; |
956 | } | 921 | } |
957 | 922 | ||
@@ -1751,12 +1716,18 @@ static void mangle_smart51(struct hda_codec *codec) | |||
1751 | { | 1716 | { |
1752 | struct via_spec *spec = codec->spec; | 1717 | struct via_spec *spec = codec->spec; |
1753 | struct auto_pin_cfg *cfg = &spec->autocfg; | 1718 | struct auto_pin_cfg *cfg = &spec->autocfg; |
1754 | int i; | 1719 | int i, nums = 0; |
1755 | 1720 | ||
1756 | for (i = 0; i < cfg->num_inputs; i++) { | 1721 | for (i = 0; i < cfg->num_inputs; i++) { |
1757 | if (!is_smart51_pins(codec, cfg->inputs[i].pin)) | 1722 | if (is_smart51_candidate(codec, cfg->inputs[i].pin)) |
1723 | nums++; | ||
1724 | } | ||
1725 | if (cfg->line_outs + nums < 3) | ||
1726 | return; | ||
1727 | for (i = 0; i < cfg->num_inputs; i++) { | ||
1728 | if (!is_smart51_candidate(codec, cfg->inputs[i].pin)) | ||
1758 | continue; | 1729 | continue; |
1759 | spec->can_smart51 = 1; | 1730 | spec->smart51_pins[spec->smart51_nums++] = cfg->inputs[i].pin; |
1760 | cfg->line_out_pins[cfg->line_outs++] = cfg->inputs[i].pin; | 1731 | cfg->line_out_pins[cfg->line_outs++] = cfg->inputs[i].pin; |
1761 | if (cfg->line_outs == 3) | 1732 | if (cfg->line_outs == 3) |
1762 | break; | 1733 | break; |
@@ -1779,6 +1750,10 @@ static int via_auto_create_multi_out_ctls(struct hda_codec *codec) | |||
1779 | if (cfg->line_outs == 1) | 1750 | if (cfg->line_outs == 1) |
1780 | mangle_smart51(codec); | 1751 | mangle_smart51(codec); |
1781 | 1752 | ||
1753 | err = via_auto_fill_dac_nids(codec); | ||
1754 | if (err < 0) | ||
1755 | return err; | ||
1756 | |||
1782 | for (i = 0; i < cfg->line_outs; i++) { | 1757 | for (i = 0; i < cfg->line_outs; i++) { |
1783 | hda_nid_t pin, dac; | 1758 | hda_nid_t pin, dac; |
1784 | pin = cfg->line_out_pins[i]; | 1759 | pin = cfg->line_out_pins[i]; |
@@ -1926,7 +1901,7 @@ static int via_auto_create_analog_input_ctls(struct hda_codec *codec, | |||
1926 | { | 1901 | { |
1927 | struct via_spec *spec = codec->spec; | 1902 | struct via_spec *spec = codec->spec; |
1928 | struct hda_input_mux *imux = &spec->private_imux[0]; | 1903 | struct hda_input_mux *imux = &spec->private_imux[0]; |
1929 | int i, err, idx, idx2, type, type_idx = 0; | 1904 | int i, j, err, idx, idx2, type, type_idx = 0; |
1930 | hda_nid_t cap_nid; | 1905 | hda_nid_t cap_nid; |
1931 | hda_nid_t pin_idxs[8]; | 1906 | hda_nid_t pin_idxs[8]; |
1932 | int num_idxs; | 1907 | int num_idxs; |
@@ -1973,6 +1948,15 @@ static int via_auto_create_analog_input_ctls(struct hda_codec *codec, | |||
1973 | if (err < 0) | 1948 | if (err < 0) |
1974 | return err; | 1949 | return err; |
1975 | snd_hda_add_imux_item(imux, label, idx, NULL); | 1950 | snd_hda_add_imux_item(imux, label, idx, NULL); |
1951 | |||
1952 | /* remember the label for smart51 control */ | ||
1953 | for (j = 0; j < spec->smart51_nums; j++) { | ||
1954 | if (spec->smart51_pins[j] == cfg->inputs[i].pin) { | ||
1955 | spec->smart51_idxs[j] = idx; | ||
1956 | spec->smart51_labels[j] = label; | ||
1957 | break; | ||
1958 | } | ||
1959 | } | ||
1976 | } | 1960 | } |
1977 | 1961 | ||
1978 | /* create capture mixer elements */ | 1962 | /* create capture mixer elements */ |
@@ -2107,9 +2091,6 @@ static int via_parse_auto_config(struct hda_codec *codec) | |||
2107 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL); | 2091 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL); |
2108 | if (err < 0) | 2092 | if (err < 0) |
2109 | return err; | 2093 | return err; |
2110 | err = via_auto_fill_dac_nids(codec); | ||
2111 | if (err < 0) | ||
2112 | return err; | ||
2113 | if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0]) | 2094 | if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0]) |
2114 | return -EINVAL; | 2095 | return -EINVAL; |
2115 | 2096 | ||