diff options
Diffstat (limited to 'sound/pci/hda/patch_analog.c')
-rw-r--r-- | sound/pci/hda/patch_analog.c | 85 |
1 files changed, 48 insertions, 37 deletions
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index f94f1f22889e..0e1a879663fa 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -192,6 +192,17 @@ static int ad198x_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | |||
192 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 192 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); |
193 | } | 193 | } |
194 | 194 | ||
195 | static int ad198x_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
196 | struct hda_codec *codec, | ||
197 | unsigned int stream_tag, | ||
198 | unsigned int format, | ||
199 | struct snd_pcm_substream *substream) | ||
200 | { | ||
201 | struct ad198x_spec *spec = codec->spec; | ||
202 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, | ||
203 | format, substream); | ||
204 | } | ||
205 | |||
195 | /* | 206 | /* |
196 | * Analog capture | 207 | * Analog capture |
197 | */ | 208 | */ |
@@ -250,7 +261,8 @@ static struct hda_pcm_stream ad198x_pcm_digital_playback = { | |||
250 | .nid = 0, /* fill later */ | 261 | .nid = 0, /* fill later */ |
251 | .ops = { | 262 | .ops = { |
252 | .open = ad198x_dig_playback_pcm_open, | 263 | .open = ad198x_dig_playback_pcm_open, |
253 | .close = ad198x_dig_playback_pcm_close | 264 | .close = ad198x_dig_playback_pcm_close, |
265 | .prepare = ad198x_dig_playback_pcm_prepare | ||
254 | }, | 266 | }, |
255 | }; | 267 | }; |
256 | 268 | ||
@@ -739,41 +751,35 @@ static struct hda_verb ad1986a_init_verbs[] = { | |||
739 | { } /* end */ | 751 | { } /* end */ |
740 | }; | 752 | }; |
741 | 753 | ||
742 | /* additional verbs for 3-stack model */ | ||
743 | static struct hda_verb ad1986a_3st_init_verbs[] = { | ||
744 | /* Mic and line-in selectors */ | ||
745 | {0x0f, AC_VERB_SET_CONNECT_SEL, 0x2}, | ||
746 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
747 | { } /* end */ | ||
748 | }; | ||
749 | |||
750 | static struct hda_verb ad1986a_ch2_init[] = { | 754 | static struct hda_verb ad1986a_ch2_init[] = { |
751 | /* Surround out -> Line In */ | 755 | /* Surround out -> Line In */ |
752 | { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | 756 | { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, |
753 | { 0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 757 | /* Line-in selectors */ |
758 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x1 }, | ||
754 | /* CLFE -> Mic in */ | 759 | /* CLFE -> Mic in */ |
755 | { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | 760 | { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, |
756 | { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 761 | /* Mic selector, mix C/LFE (backmic) and Mic (frontmic) */ |
762 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 }, | ||
757 | { } /* end */ | 763 | { } /* end */ |
758 | }; | 764 | }; |
759 | 765 | ||
760 | static struct hda_verb ad1986a_ch4_init[] = { | 766 | static struct hda_verb ad1986a_ch4_init[] = { |
761 | /* Surround out -> Surround */ | 767 | /* Surround out -> Surround */ |
762 | { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | 768 | { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, |
763 | { 0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 769 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, |
764 | /* CLFE -> Mic in */ | 770 | /* CLFE -> Mic in */ |
765 | { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, | 771 | { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, |
766 | { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080}, | 772 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x4 }, |
767 | { } /* end */ | 773 | { } /* end */ |
768 | }; | 774 | }; |
769 | 775 | ||
770 | static struct hda_verb ad1986a_ch6_init[] = { | 776 | static struct hda_verb ad1986a_ch6_init[] = { |
771 | /* Surround out -> Surround out */ | 777 | /* Surround out -> Surround out */ |
772 | { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | 778 | { 0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, |
773 | { 0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 779 | { 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 }, |
774 | /* CLFE -> CLFE */ | 780 | /* CLFE -> CLFE */ |
775 | { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 }, | 781 | { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, |
776 | { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000}, | 782 | { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x0 }, |
777 | { } /* end */ | 783 | { } /* end */ |
778 | }; | 784 | }; |
779 | 785 | ||
@@ -828,6 +834,7 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = { | |||
828 | SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD), | 834 | SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD), |
829 | SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD), | 835 | SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD), |
830 | SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD), | 836 | SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD), |
837 | SND_PCI_QUIRK(0x1043, 0x1447, "ASUS A8J", AD1986A_3STACK), | ||
831 | SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK), | 838 | SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK), |
832 | SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP), | 839 | SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP), |
833 | SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK), | 840 | SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK), |
@@ -882,9 +889,8 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
882 | case AD1986A_3STACK: | 889 | case AD1986A_3STACK: |
883 | spec->num_mixers = 2; | 890 | spec->num_mixers = 2; |
884 | spec->mixers[1] = ad1986a_3st_mixers; | 891 | spec->mixers[1] = ad1986a_3st_mixers; |
885 | spec->num_init_verbs = 3; | 892 | spec->num_init_verbs = 2; |
886 | spec->init_verbs[1] = ad1986a_3st_init_verbs; | 893 | spec->init_verbs[1] = ad1986a_ch2_init; |
887 | spec->init_verbs[2] = ad1986a_ch2_init; | ||
888 | spec->channel_mode = ad1986a_modes; | 894 | spec->channel_mode = ad1986a_modes; |
889 | spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes); | 895 | spec->num_channel_mode = ARRAY_SIZE(ad1986a_modes); |
890 | spec->need_dac_fix = 1; | 896 | spec->need_dac_fix = 1; |
@@ -1892,8 +1898,9 @@ static int ad1988_spdif_playback_source_get(struct snd_kcontrol *kcontrol, | |||
1892 | 1898 | ||
1893 | sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0); | 1899 | sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0); |
1894 | if (sel > 0) { | 1900 | if (sel > 0) { |
1895 | sel = snd_hda_codec_read(codec, 0x0b, 0, AC_VERB_GET_CONNECT_SEL, 0); | 1901 | sel = snd_hda_codec_read(codec, 0x0b, 0, |
1896 | if (sel <= 3) | 1902 | AC_VERB_GET_CONNECT_SEL, 0); |
1903 | if (sel < 3) | ||
1897 | sel++; | 1904 | sel++; |
1898 | else | 1905 | else |
1899 | sel = 0; | 1906 | sel = 0; |
@@ -1906,23 +1913,27 @@ static int ad1988_spdif_playback_source_put(struct snd_kcontrol *kcontrol, | |||
1906 | struct snd_ctl_elem_value *ucontrol) | 1913 | struct snd_ctl_elem_value *ucontrol) |
1907 | { | 1914 | { |
1908 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1915 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
1909 | unsigned int sel; | 1916 | unsigned int val, sel; |
1910 | int change; | 1917 | int change; |
1911 | 1918 | ||
1919 | val = ucontrol->value.enumerated.item[0]; | ||
1912 | sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0); | 1920 | sel = snd_hda_codec_read(codec, 0x02, 0, AC_VERB_GET_CONNECT_SEL, 0); |
1913 | if (! ucontrol->value.enumerated.item[0]) { | 1921 | if (!val) { |
1914 | change = sel != 0; | 1922 | change = sel != 0; |
1915 | if (change) | 1923 | if (change || codec->in_resume) |
1916 | snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, 0); | 1924 | snd_hda_codec_write(codec, 0x02, 0, |
1925 | AC_VERB_SET_CONNECT_SEL, 0); | ||
1917 | } else { | 1926 | } else { |
1918 | change = sel == 0; | 1927 | change = sel == 0; |
1919 | if (change) | 1928 | if (change || codec->in_resume) |
1920 | snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, 1); | 1929 | snd_hda_codec_write(codec, 0x02, 0, |
1921 | sel = snd_hda_codec_read(codec, 0x0b, 0, AC_VERB_GET_CONNECT_SEL, 0) + 1; | 1930 | AC_VERB_SET_CONNECT_SEL, 1); |
1922 | change |= sel == ucontrol->value.enumerated.item[0]; | 1931 | sel = snd_hda_codec_read(codec, 0x0b, 0, |
1923 | if (change) | 1932 | AC_VERB_GET_CONNECT_SEL, 0) + 1; |
1924 | snd_hda_codec_write(codec, 0x02, 0, AC_VERB_SET_CONNECT_SEL, | 1933 | change |= sel != val; |
1925 | ucontrol->value.enumerated.item[0] - 1); | 1934 | if (change || codec->in_resume) |
1935 | snd_hda_codec_write(codec, 0x0b, 0, | ||
1936 | AC_VERB_SET_CONNECT_SEL, val - 1); | ||
1926 | } | 1937 | } |
1927 | return change; | 1938 | return change; |
1928 | } | 1939 | } |