aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_codec.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2007-04-05 08:51:48 -0400
committerJaroslav Kysela <perex@suse.cz>2007-05-11 10:55:56 -0400
commit6b97eb45f2edca51250b6c1e3142801f069245fe (patch)
treebe20e5e69f05499091ee9d83005b2712babb5431 /sound/pci/hda/hda_codec.c
parentf9ab2b1c3ab5345f9003bf7ebc1eaa0f9b8cf99e (diff)
[ALSA] hda-codec - Fix SPDIF output
Fix SPDIF output (at least on Realtek codecs). The DIGI_CONVERT verbs have to be reset before the PCM stream is set up. Otherwise the digital setup is screwed up. Also, check the AMP capability before setting AMP of the digital out widget. Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r--sound/pci/hda/hda_codec.c44
1 files changed, 37 insertions, 7 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index e768187465e3..2c2fcdc72fcf 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1114,10 +1114,14 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol, struct sn
1114 change = codec->spdif_ctls != val; 1114 change = codec->spdif_ctls != val;
1115 if (change || codec->in_resume) { 1115 if (change || codec->in_resume) {
1116 codec->spdif_ctls = val; 1116 codec->spdif_ctls = val;
1117 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val & 0xff); 1117 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
1118 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, 1118 val & 0xff);
1119 AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | 1119 if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)
1120 AC_AMP_SET_OUTPUT | ((val & 1) ? 0 : 0x80)); 1120 snd_hda_codec_write(codec, nid, 0,
1121 AC_VERB_SET_AMP_GAIN_MUTE,
1122 AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT |
1123 AC_AMP_SET_OUTPUT |
1124 ((val & 1) ? 0 : 0x80));
1121 } 1125 }
1122 mutex_unlock(&codec->spdif_mutex); 1126 mutex_unlock(&codec->spdif_mutex);
1123 return change; 1127 return change;
@@ -1886,6 +1890,21 @@ int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *i
1886 * Multi-channel / digital-out PCM helper functions 1890 * Multi-channel / digital-out PCM helper functions
1887 */ 1891 */
1888 1892
1893/* setup SPDIF output stream */
1894static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
1895 unsigned int stream_tag, unsigned int format)
1896{
1897 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
1898 if (codec->spdif_ctls & AC_DIG1_ENABLE)
1899 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
1900 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
1901 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
1902 /* turn on again (if needed) */
1903 if (codec->spdif_ctls & AC_DIG1_ENABLE)
1904 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
1905 codec->spdif_ctls & 0xff);
1906}
1907
1889/* 1908/*
1890 * open the digital out in the exclusive mode 1909 * open the digital out in the exclusive mode
1891 */ 1910 */
@@ -1901,6 +1920,18 @@ int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mo
1901 return 0; 1920 return 0;
1902} 1921}
1903 1922
1923int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
1924 struct hda_multi_out *mout,
1925 unsigned int stream_tag,
1926 unsigned int format,
1927 struct snd_pcm_substream *substream)
1928{
1929 mutex_lock(&codec->spdif_mutex);
1930 setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format);
1931 mutex_unlock(&codec->spdif_mutex);
1932 return 0;
1933}
1934
1904/* 1935/*
1905 * release the digital out 1936 * release the digital out
1906 */ 1937 */
@@ -1942,9 +1973,8 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o
1942 snd_hda_is_supported_format(codec, mout->dig_out_nid, format) && 1973 snd_hda_is_supported_format(codec, mout->dig_out_nid, format) &&
1943 ! (codec->spdif_status & IEC958_AES0_NONAUDIO)) { 1974 ! (codec->spdif_status & IEC958_AES0_NONAUDIO)) {
1944 mout->dig_out_used = HDA_DIG_ANALOG_DUP; 1975 mout->dig_out_used = HDA_DIG_ANALOG_DUP;
1945 /* setup digital receiver */ 1976 setup_dig_out_stream(codec, mout->dig_out_nid,
1946 snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 1977 stream_tag, format);
1947 stream_tag, 0, format);
1948 } else { 1978 } else {
1949 mout->dig_out_used = 0; 1979 mout->dig_out_used = 0;
1950 snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0); 1980 snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0);