Commit 98aa34c0 authored by Harald Welte's avatar Harald Welte Committed by Jaroslav Kysela

ALSA: HDA patch_via.c: Second S/PDIF (HDMI) support

The VT1702 and VT1708S have a second S/PDIF output which is used to
connect to a HDMI transmitter.  This patch adds support for it.
Signed-off-by: default avatarHarald Welte <HaraldWelte@viatech.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarJaroslav Kysela <perex@perex.cz>
parent 0aa62aef
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
/* 2008-03-06 Lydia Wang Add VT1702 codec and VT1708S codec support */ /* 2008-03-06 Lydia Wang Add VT1702 codec and VT1708S codec support */
/* 2008-04-09 Lydia Wang Add mute front speaker when HP plugin */ /* 2008-04-09 Lydia Wang Add mute front speaker when HP plugin */
/* 2008-04-09 Lydia Wang Add Independent HP feature */ /* 2008-04-09 Lydia Wang Add Independent HP feature */
/* 2008-05-28 Lydia Wang Add second S/PDIF Out support for VT1702 */
/* */ /* */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
...@@ -122,9 +123,11 @@ struct via_spec { ...@@ -122,9 +123,11 @@ struct via_spec {
char *stream_name_digital; char *stream_name_digital;
struct hda_pcm_stream *stream_digital_playback; struct hda_pcm_stream *stream_digital_playback;
struct hda_pcm_stream *stream_digital_capture; struct hda_pcm_stream *stream_digital_capture;
struct hda_pcm_stream *stream_extra_digital_playback;
/* playback */ /* playback */
struct hda_multi_out multiout; struct hda_multi_out multiout;
hda_nid_t extra_dig_out_nid;
/* capture */ /* capture */
unsigned int num_adc_nids; unsigned int num_adc_nids;
...@@ -136,7 +139,7 @@ struct via_spec { ...@@ -136,7 +139,7 @@ struct via_spec {
unsigned int cur_mux[3]; unsigned int cur_mux[3];
/* PCM information */ /* PCM information */
struct hda_pcm pcm_rec[2]; struct hda_pcm pcm_rec[3];
/* dynamic controls, init_verbs and input_mux */ /* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg; struct auto_pin_cfg autocfg;
...@@ -664,6 +667,36 @@ static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, ...@@ -664,6 +667,36 @@ static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
stream_tag, format, substream); stream_tag, format, substream);
} }
/* setup SPDIF output stream */
static void setup_dig_playback_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);
}
static int via_extra_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
unsigned int stream_tag,
unsigned int format,
struct snd_pcm_substream *substream)
{
struct via_spec *spec = codec->spec;
mutex_lock(&codec->spdif_mutex);
setup_dig_playback_stream(codec, spec->extra_dig_out_nid, stream_tag,
format);
mutex_unlock(&codec->spdif_mutex);
return 0;
}
/* /*
* Analog capture * Analog capture
*/ */
...@@ -769,6 +802,13 @@ static int via_build_controls(struct hda_codec *codec) ...@@ -769,6 +802,13 @@ static int via_build_controls(struct hda_codec *codec)
if (err < 0) if (err < 0)
return err; return err;
spec->multiout.share_spdif = 1; spec->multiout.share_spdif = 1;
if (spec->extra_dig_out_nid) {
err = snd_hda_create_spdif_out_ctls(codec,
spec->extra_dig_out_nid);
if (err < 0)
return err;
}
} }
if (spec->dig_in_nid) { if (spec->dig_in_nid) {
err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
...@@ -814,6 +854,17 @@ static int via_build_pcms(struct hda_codec *codec) ...@@ -814,6 +854,17 @@ static int via_build_pcms(struct hda_codec *codec)
} }
} }
if (spec->extra_dig_out_nid) {
codec->num_pcms++;
info++;
info->name = spec->stream_name_digital;
info->pcm_type = HDA_PCM_TYPE_HDMI;
info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
*(spec->stream_extra_digital_playback);
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
spec->extra_dig_out_nid;
}
return 0; return 0;
} }
...@@ -2466,6 +2517,16 @@ static struct hda_pcm_stream vt1708S_pcm_digital_playback = { ...@@ -2466,6 +2517,16 @@ static struct hda_pcm_stream vt1708S_pcm_digital_playback = {
}, },
}; };
static struct hda_pcm_stream vt1708S_pcm_extra_digital_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
/* NID is set in via_build_pcms */
.ops = {
.prepare = via_extra_dig_playback_pcm_prepare
},
};
/* fill in the dac_nids table from the parsed pin configuration */ /* fill in the dac_nids table from the parsed pin configuration */
static int vt1708S_auto_fill_dac_nids(struct via_spec *spec, static int vt1708S_auto_fill_dac_nids(struct via_spec *spec,
const struct auto_pin_cfg *cfg) const struct auto_pin_cfg *cfg)
...@@ -2702,6 +2763,8 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec) ...@@ -2702,6 +2763,8 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin) if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = VT1708S_DIGOUT_NID; spec->multiout.dig_out_nid = VT1708S_DIGOUT_NID;
spec->extra_dig_out_nid = 0x15;
if (spec->kctl_alloc) if (spec->kctl_alloc)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc; spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
...@@ -2753,6 +2816,8 @@ static int patch_vt1708S(struct hda_codec *codec) ...@@ -2753,6 +2816,8 @@ static int patch_vt1708S(struct hda_codec *codec)
spec->stream_name_digital = "VT1708S Digital"; spec->stream_name_digital = "VT1708S Digital";
spec->stream_digital_playback = &vt1708S_pcm_digital_playback; spec->stream_digital_playback = &vt1708S_pcm_digital_playback;
spec->stream_extra_digital_playback =
&vt1708S_pcm_extra_digital_playback;
if (!spec->adc_nids && spec->input_mux) { if (!spec->adc_nids && spec->input_mux) {
spec->adc_nids = vt1708S_adc_nids; spec->adc_nids = vt1708S_adc_nids;
...@@ -2867,6 +2932,16 @@ static struct hda_pcm_stream vt1702_pcm_digital_playback = { ...@@ -2867,6 +2932,16 @@ static struct hda_pcm_stream vt1702_pcm_digital_playback = {
}, },
}; };
static struct hda_pcm_stream vt1702_pcm_extra_digital_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
/* NID is set in via_build_pcms */
.ops = {
.prepare = via_extra_dig_playback_pcm_prepare
},
};
/* fill in the dac_nids table from the parsed pin configuration */ /* fill in the dac_nids table from the parsed pin configuration */
static int vt1702_auto_fill_dac_nids(struct via_spec *spec, static int vt1702_auto_fill_dac_nids(struct via_spec *spec,
const struct auto_pin_cfg *cfg) const struct auto_pin_cfg *cfg)
...@@ -3018,6 +3093,8 @@ static int vt1702_parse_auto_config(struct hda_codec *codec) ...@@ -3018,6 +3093,8 @@ static int vt1702_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin) if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = VT1702_DIGOUT_NID; spec->multiout.dig_out_nid = VT1702_DIGOUT_NID;
spec->extra_dig_out_nid = 0x1B;
if (spec->kctl_alloc) if (spec->kctl_alloc)
spec->mixers[spec->num_mixers++] = spec->kctl_alloc; spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
...@@ -3071,6 +3148,8 @@ static int patch_vt1702(struct hda_codec *codec) ...@@ -3071,6 +3148,8 @@ static int patch_vt1702(struct hda_codec *codec)
spec->stream_name_digital = "VT1702 Digital"; spec->stream_name_digital = "VT1702 Digital";
spec->stream_digital_playback = &vt1702_pcm_digital_playback; spec->stream_digital_playback = &vt1702_pcm_digital_playback;
spec->stream_extra_digital_playback =
&vt1702_pcm_extra_digital_playback;
if (!spec->adc_nids && spec->input_mux) { if (!spec->adc_nids && spec->input_mux) {
spec->adc_nids = vt1702_adc_nids; spec->adc_nids = vt1702_adc_nids;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment