diff options
author | Harald Welte <HaraldWelte@viatech.com> | 2008-09-09 04:02:09 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-09-09 12:52:04 -0400 |
commit | 98aa34c0501f78bf7d3de82d96d27f4a2b450477 (patch) | |
tree | 809ffe2b2652c5358bff374952c698bcd1f69147 | |
parent | 0aa62aef611006704226095bad9cd80246ce00c9 (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.c | 81 |
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 */ | ||
671 | static 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 | |||
685 | static 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 | ||
2520 | static 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 */ |
2470 | static int vt1708S_auto_fill_dac_nids(struct via_spec *spec, | 2531 | static 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 | ||
2935 | static 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 */ |
2871 | static int vt1702_auto_fill_dac_nids(struct via_spec *spec, | 2946 | static 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; |