aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <HaraldWelte@viatech.com>2008-09-09 04:02:09 -0400
committerJaroslav Kysela <perex@perex.cz>2008-09-09 12:52:04 -0400
commit98aa34c0501f78bf7d3de82d96d27f4a2b450477 (patch)
tree809ffe2b2652c5358bff374952c698bcd1f69147
parent0aa62aef611006704226095bad9cd80246ce00c9 (diff)
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: Harald Welte <HaraldWelte@viatech.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
-rw-r--r--sound/pci/hda/patch_via.c81
1 files changed, 80 insertions, 1 deletions
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 4e4d2c5b261f..6e360d39c02e 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -34,6 +34,7 @@
34/* 2008-03-06 Lydia Wang Add VT1702 codec and VT1708S codec support */ 34/* 2008-03-06 Lydia Wang Add VT1702 codec and VT1708S codec support */
35/* 2008-04-09 Lydia Wang Add mute front speaker when HP plugin */ 35/* 2008-04-09 Lydia Wang Add mute front speaker when HP plugin */
36/* 2008-04-09 Lydia Wang Add Independent HP feature */ 36/* 2008-04-09 Lydia Wang Add Independent HP feature */
37/* 2008-05-28 Lydia Wang Add second S/PDIF Out support for VT1702 */
37/* */ 38/* */
38/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 39/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
39 40
@@ -122,9 +123,11 @@ struct via_spec {
122 char *stream_name_digital; 123 char *stream_name_digital;
123 struct hda_pcm_stream *stream_digital_playback; 124 struct hda_pcm_stream *stream_digital_playback;
124 struct hda_pcm_stream *stream_digital_capture; 125 struct hda_pcm_stream *stream_digital_capture;
126 struct hda_pcm_stream *stream_extra_digital_playback;
125 127
126 /* playback */ 128 /* playback */
127 struct hda_multi_out multiout; 129 struct hda_multi_out multiout;
130 hda_nid_t extra_dig_out_nid;
128 131
129 /* capture */ 132 /* capture */
130 unsigned int num_adc_nids; 133 unsigned int num_adc_nids;
@@ -136,7 +139,7 @@ struct via_spec {
136 unsigned int cur_mux[3]; 139 unsigned int cur_mux[3];
137 140
138 /* PCM information */ 141 /* PCM information */
139 struct hda_pcm pcm_rec[2]; 142 struct hda_pcm pcm_rec[3];
140 143
141 /* dynamic controls, init_verbs and input_mux */ 144 /* dynamic controls, init_verbs and input_mux */
142 struct auto_pin_cfg autocfg; 145 struct auto_pin_cfg autocfg;
@@ -664,6 +667,36 @@ static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
664 stream_tag, format, substream); 667 stream_tag, format, substream);
665} 668}
666 669
670/* setup SPDIF output stream */
671static void setup_dig_playback_stream(struct hda_codec *codec, hda_nid_t nid,
672 unsigned int stream_tag, unsigned int format)
673{
674 /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
675 if (codec->spdif_ctls & AC_DIG1_ENABLE)
676 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
677 codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
678 snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
679 /* turn on again (if needed) */
680 if (codec->spdif_ctls & AC_DIG1_ENABLE)
681 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
682 codec->spdif_ctls & 0xff);
683}
684
685static int via_extra_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
686 struct hda_codec *codec,
687 unsigned int stream_tag,
688 unsigned int format,
689 struct snd_pcm_substream *substream)
690{
691 struct via_spec *spec = codec->spec;
692
693 mutex_lock(&codec->spdif_mutex);
694 setup_dig_playback_stream(codec, spec->extra_dig_out_nid, stream_tag,
695 format);
696 mutex_unlock(&codec->spdif_mutex);
697 return 0;
698}
699
667/* 700/*
668 * Analog capture 701 * Analog capture
669 */ 702 */
@@ -769,6 +802,13 @@ static int via_build_controls(struct hda_codec *codec)
769 if (err < 0) 802 if (err < 0)
770 return err; 803 return err;
771 spec->multiout.share_spdif = 1; 804 spec->multiout.share_spdif = 1;
805
806 if (spec->extra_dig_out_nid) {
807 err = snd_hda_create_spdif_out_ctls(codec,
808 spec->extra_dig_out_nid);
809 if (err < 0)
810 return err;
811 }
772 } 812 }
773 if (spec->dig_in_nid) { 813 if (spec->dig_in_nid) {
774 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); 814 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 } 854 }
815 } 855 }
816 856
857 if (spec->extra_dig_out_nid) {
858 codec->num_pcms++;
859 info++;
860 info->name = spec->stream_name_digital;
861 info->pcm_type = HDA_PCM_TYPE_HDMI;
862 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
863 *(spec->stream_extra_digital_playback);
864 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
865 spec->extra_dig_out_nid;
866 }
867
817 return 0; 868 return 0;
818} 869}
819 870
@@ -2466,6 +2517,16 @@ static struct hda_pcm_stream vt1708S_pcm_digital_playback = {
2466 }, 2517 },
2467}; 2518};
2468 2519
2520static struct hda_pcm_stream vt1708S_pcm_extra_digital_playback = {
2521 .substreams = 1,
2522 .channels_min = 2,
2523 .channels_max = 2,
2524 /* NID is set in via_build_pcms */
2525 .ops = {
2526 .prepare = via_extra_dig_playback_pcm_prepare
2527 },
2528};
2529
2469/* fill in the dac_nids table from the parsed pin configuration */ 2530/* fill in the dac_nids table from the parsed pin configuration */
2470static int vt1708S_auto_fill_dac_nids(struct via_spec *spec, 2531static int vt1708S_auto_fill_dac_nids(struct via_spec *spec,
2471 const struct auto_pin_cfg *cfg) 2532 const struct auto_pin_cfg *cfg)
@@ -2702,6 +2763,8 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec)
2702 if (spec->autocfg.dig_out_pin) 2763 if (spec->autocfg.dig_out_pin)
2703 spec->multiout.dig_out_nid = VT1708S_DIGOUT_NID; 2764 spec->multiout.dig_out_nid = VT1708S_DIGOUT_NID;
2704 2765
2766 spec->extra_dig_out_nid = 0x15;
2767
2705 if (spec->kctl_alloc) 2768 if (spec->kctl_alloc)
2706 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 2769 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
2707 2770
@@ -2753,6 +2816,8 @@ static int patch_vt1708S(struct hda_codec *codec)
2753 2816
2754 spec->stream_name_digital = "VT1708S Digital"; 2817 spec->stream_name_digital = "VT1708S Digital";
2755 spec->stream_digital_playback = &vt1708S_pcm_digital_playback; 2818 spec->stream_digital_playback = &vt1708S_pcm_digital_playback;
2819 spec->stream_extra_digital_playback =
2820 &vt1708S_pcm_extra_digital_playback;
2756 2821
2757 if (!spec->adc_nids && spec->input_mux) { 2822 if (!spec->adc_nids && spec->input_mux) {
2758 spec->adc_nids = vt1708S_adc_nids; 2823 spec->adc_nids = vt1708S_adc_nids;
@@ -2867,6 +2932,16 @@ static struct hda_pcm_stream vt1702_pcm_digital_playback = {
2867 }, 2932 },
2868}; 2933};
2869 2934
2935static struct hda_pcm_stream vt1702_pcm_extra_digital_playback = {
2936 .substreams = 1,
2937 .channels_min = 2,
2938 .channels_max = 2,
2939 /* NID is set in via_build_pcms */
2940 .ops = {
2941 .prepare = via_extra_dig_playback_pcm_prepare
2942 },
2943};
2944
2870/* fill in the dac_nids table from the parsed pin configuration */ 2945/* fill in the dac_nids table from the parsed pin configuration */
2871static int vt1702_auto_fill_dac_nids(struct via_spec *spec, 2946static int vt1702_auto_fill_dac_nids(struct via_spec *spec,
2872 const struct auto_pin_cfg *cfg) 2947 const struct auto_pin_cfg *cfg)
@@ -3018,6 +3093,8 @@ static int vt1702_parse_auto_config(struct hda_codec *codec)
3018 if (spec->autocfg.dig_out_pin) 3093 if (spec->autocfg.dig_out_pin)
3019 spec->multiout.dig_out_nid = VT1702_DIGOUT_NID; 3094 spec->multiout.dig_out_nid = VT1702_DIGOUT_NID;
3020 3095
3096 spec->extra_dig_out_nid = 0x1B;
3097
3021 if (spec->kctl_alloc) 3098 if (spec->kctl_alloc)
3022 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 3099 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
3023 3100
@@ -3071,6 +3148,8 @@ static int patch_vt1702(struct hda_codec *codec)
3071 3148
3072 spec->stream_name_digital = "VT1702 Digital"; 3149 spec->stream_name_digital = "VT1702 Digital";
3073 spec->stream_digital_playback = &vt1702_pcm_digital_playback; 3150 spec->stream_digital_playback = &vt1702_pcm_digital_playback;
3151 spec->stream_extra_digital_playback =
3152 &vt1702_pcm_extra_digital_playback;
3074 3153
3075 if (!spec->adc_nids && spec->input_mux) { 3154 if (!spec->adc_nids && spec->input_mux) {
3076 spec->adc_nids = vt1702_adc_nids; 3155 spec->adc_nids = vt1702_adc_nids;