diff options
author | Takashi Iwai <tiwai@suse.de> | 2007-04-05 08:51:48 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2007-05-11 10:55:56 -0400 |
commit | 6b97eb45f2edca51250b6c1e3142801f069245fe (patch) | |
tree | be20e5e69f05499091ee9d83005b2712babb5431 /sound/pci/hda/hda_codec.c | |
parent | f9ab2b1c3ab5345f9003bf7ebc1eaa0f9b8cf99e (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.c | 44 |
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 */ | ||
1894 | static 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 | ||
1923 | int 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); |