aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_analog.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_analog.c')
-rw-r--r--sound/pci/hda/patch_analog.c85
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
195static 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 */
743static 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
750static struct hda_verb ad1986a_ch2_init[] = { 754static 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
760static struct hda_verb ad1986a_ch4_init[] = { 766static 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
770static struct hda_verb ad1986a_ch6_init[] = { 776static 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}