diff options
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 e768187465e..2c2fcdc72fc 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 change = codec->spdif_ctls != val; if (change || codec->in_resume) { codec->spdif_ctls = val; - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val & 0xff); - snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, - AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | - AC_AMP_SET_OUTPUT | ((val & 1) ? 0 : 0x80)); + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, + val & 0xff); + if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) + snd_hda_codec_write(codec, nid, 0, + AC_VERB_SET_AMP_GAIN_MUTE, + AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | + AC_AMP_SET_OUTPUT | + ((val & 1) ? 0 : 0x80)); } mutex_unlock(&codec->spdif_mutex); return change; @@ -1886,6 +1890,21 @@ int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *i * Multi-channel / digital-out PCM helper functions */ +/* setup SPDIF output stream */ +static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid, + unsigned int stream_tag, unsigned int format) +{ + /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ + if (codec->spdif_ctls & AC_DIG1_ENABLE) + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, + codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); + snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); + /* turn on again (if needed) */ + if (codec->spdif_ctls & AC_DIG1_ENABLE) + snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, + codec->spdif_ctls & 0xff); +} + /* * open the digital out in the exclusive mode */ @@ -1901,6 +1920,18 @@ int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mo return 0; } +int snd_hda_multi_out_dig_prepare(struct hda_codec *codec, + struct hda_multi_out *mout, + unsigned int stream_tag, + unsigned int format, + struct snd_pcm_substream *substream) +{ + mutex_lock(&codec->spdif_mutex); + setup_dig_out_stream(codec, mout->dig_out_nid, stream_tag, format); + mutex_unlock(&codec->spdif_mutex); + return 0; +} + /* * release the digital out */ @@ -1942,9 +1973,8 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_o snd_hda_is_supported_format(codec, mout->dig_out_nid, format) && ! (codec->spdif_status & IEC958_AES0_NONAUDIO)) { mout->dig_out_used = HDA_DIG_ANALOG_DUP; - /* setup digital receiver */ - snd_hda_codec_setup_stream(codec, mout->dig_out_nid, - stream_tag, 0, format); + setup_dig_out_stream(codec, mout->dig_out_nid, + stream_tag, format); } else { mout->dig_out_used = 0; snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0); |