diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-05-11 04:23:36 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-05-11 04:23:36 -0400 |
commit | fa1285b3d1955c3719413d950224977a900f91f9 (patch) | |
tree | 93726708076290a88e6c8e76d74af22c1d985feb | |
parent | 01f2bd48d08c6bbde12d86b66c760612e33e49a9 (diff) | |
parent | 9da29271bea5d831d745f3ceb7f6f6b2def13a5b (diff) |
Merge branch 'topic/hda-vt-spdif' into topic/hda
-rw-r--r-- | sound/pci/hda/patch_via.c | 111 |
1 files changed, 51 insertions, 60 deletions
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index b25a5cc637d6..8e004fb6961a 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -205,7 +205,7 @@ struct via_spec { | |||
205 | 205 | ||
206 | /* playback */ | 206 | /* playback */ |
207 | struct hda_multi_out multiout; | 207 | struct hda_multi_out multiout; |
208 | hda_nid_t extra_dig_out_nid; | 208 | hda_nid_t slave_dig_outs[2]; |
209 | 209 | ||
210 | /* capture */ | 210 | /* capture */ |
211 | unsigned int num_adc_nids; | 211 | unsigned int num_adc_nids; |
@@ -731,21 +731,6 @@ static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | |||
731 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | 731 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); |
732 | } | 732 | } |
733 | 733 | ||
734 | /* setup SPDIF output stream */ | ||
735 | static void setup_dig_playback_stream(struct hda_codec *codec, hda_nid_t nid, | ||
736 | unsigned int stream_tag, unsigned int format) | ||
737 | { | ||
738 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ | ||
739 | if (codec->spdif_ctls & AC_DIG1_ENABLE) | ||
740 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, | ||
741 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | ||
742 | snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format); | ||
743 | /* turn on again (if needed) */ | ||
744 | if (codec->spdif_ctls & AC_DIG1_ENABLE) | ||
745 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, | ||
746 | codec->spdif_ctls & 0xff); | ||
747 | } | ||
748 | |||
749 | static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | 734 | static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, |
750 | struct hda_codec *codec, | 735 | struct hda_codec *codec, |
751 | unsigned int stream_tag, | 736 | unsigned int stream_tag, |
@@ -753,19 +738,16 @@ static int via_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
753 | struct snd_pcm_substream *substream) | 738 | struct snd_pcm_substream *substream) |
754 | { | 739 | { |
755 | struct via_spec *spec = codec->spec; | 740 | struct via_spec *spec = codec->spec; |
756 | hda_nid_t nid; | 741 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, |
757 | 742 | stream_tag, format, substream); | |
758 | /* 1st or 2nd S/PDIF */ | 743 | } |
759 | if (substream->number == 0) | ||
760 | nid = spec->multiout.dig_out_nid; | ||
761 | else if (substream->number == 1) | ||
762 | nid = spec->extra_dig_out_nid; | ||
763 | else | ||
764 | return -1; | ||
765 | 744 | ||
766 | mutex_lock(&codec->spdif_mutex); | 745 | static int via_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, |
767 | setup_dig_playback_stream(codec, nid, stream_tag, format); | 746 | struct hda_codec *codec, |
768 | mutex_unlock(&codec->spdif_mutex); | 747 | struct snd_pcm_substream *substream) |
748 | { | ||
749 | struct via_spec *spec = codec->spec; | ||
750 | snd_hda_multi_out_dig_cleanup(codec, &spec->multiout); | ||
769 | return 0; | 751 | return 0; |
770 | } | 752 | } |
771 | 753 | ||
@@ -842,7 +824,8 @@ static struct hda_pcm_stream vt1708_pcm_digital_playback = { | |||
842 | .ops = { | 824 | .ops = { |
843 | .open = via_dig_playback_pcm_open, | 825 | .open = via_dig_playback_pcm_open, |
844 | .close = via_dig_playback_pcm_close, | 826 | .close = via_dig_playback_pcm_close, |
845 | .prepare = via_dig_playback_pcm_prepare | 827 | .prepare = via_dig_playback_pcm_prepare, |
828 | .cleanup = via_dig_playback_pcm_cleanup | ||
846 | }, | 829 | }, |
847 | }; | 830 | }; |
848 | 831 | ||
@@ -874,13 +857,6 @@ static int via_build_controls(struct hda_codec *codec) | |||
874 | if (err < 0) | 857 | if (err < 0) |
875 | return err; | 858 | return err; |
876 | spec->multiout.share_spdif = 1; | 859 | spec->multiout.share_spdif = 1; |
877 | |||
878 | if (spec->extra_dig_out_nid) { | ||
879 | err = snd_hda_create_spdif_out_ctls(codec, | ||
880 | spec->extra_dig_out_nid); | ||
881 | if (err < 0) | ||
882 | return err; | ||
883 | } | ||
884 | } | 860 | } |
885 | if (spec->dig_in_nid) { | 861 | if (spec->dig_in_nid) { |
886 | err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); | 862 | err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid); |
@@ -1013,10 +989,6 @@ static void via_unsol_event(struct hda_codec *codec, | |||
1013 | via_gpio_control(codec); | 989 | via_gpio_control(codec); |
1014 | } | 990 | } |
1015 | 991 | ||
1016 | static hda_nid_t slave_dig_outs[] = { | ||
1017 | 0, | ||
1018 | }; | ||
1019 | |||
1020 | static int via_init(struct hda_codec *codec) | 992 | static int via_init(struct hda_codec *codec) |
1021 | { | 993 | { |
1022 | struct via_spec *spec = codec->spec; | 994 | struct via_spec *spec = codec->spec; |
@@ -1051,8 +1023,9 @@ static int via_init(struct hda_codec *codec) | |||
1051 | snd_hda_codec_write(codec, spec->autocfg.dig_in_pin, 0, | 1023 | snd_hda_codec_write(codec, spec->autocfg.dig_in_pin, 0, |
1052 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN); | 1024 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN); |
1053 | 1025 | ||
1054 | /* no slave outs */ | 1026 | /* assign slave outs */ |
1055 | codec->slave_dig_outs = slave_dig_outs; | 1027 | if (spec->slave_dig_outs[0]) |
1028 | codec->slave_dig_outs = spec->slave_dig_outs; | ||
1056 | 1029 | ||
1057 | return 0; | 1030 | return 0; |
1058 | } | 1031 | } |
@@ -2134,7 +2107,8 @@ static struct hda_pcm_stream vt1708B_pcm_digital_playback = { | |||
2134 | .ops = { | 2107 | .ops = { |
2135 | .open = via_dig_playback_pcm_open, | 2108 | .open = via_dig_playback_pcm_open, |
2136 | .close = via_dig_playback_pcm_close, | 2109 | .close = via_dig_playback_pcm_close, |
2137 | .prepare = via_dig_playback_pcm_prepare | 2110 | .prepare = via_dig_playback_pcm_prepare, |
2111 | .cleanup = via_dig_playback_pcm_cleanup | ||
2138 | }, | 2112 | }, |
2139 | }; | 2113 | }; |
2140 | 2114 | ||
@@ -2589,14 +2563,15 @@ static struct hda_pcm_stream vt1708S_pcm_analog_capture = { | |||
2589 | }; | 2563 | }; |
2590 | 2564 | ||
2591 | static struct hda_pcm_stream vt1708S_pcm_digital_playback = { | 2565 | static struct hda_pcm_stream vt1708S_pcm_digital_playback = { |
2592 | .substreams = 2, | 2566 | .substreams = 1, |
2593 | .channels_min = 2, | 2567 | .channels_min = 2, |
2594 | .channels_max = 2, | 2568 | .channels_max = 2, |
2595 | /* NID is set in via_build_pcms */ | 2569 | /* NID is set in via_build_pcms */ |
2596 | .ops = { | 2570 | .ops = { |
2597 | .open = via_dig_playback_pcm_open, | 2571 | .open = via_dig_playback_pcm_open, |
2598 | .close = via_dig_playback_pcm_close, | 2572 | .close = via_dig_playback_pcm_close, |
2599 | .prepare = via_dig_playback_pcm_prepare | 2573 | .prepare = via_dig_playback_pcm_prepare, |
2574 | .cleanup = via_dig_playback_pcm_cleanup | ||
2600 | }, | 2575 | }, |
2601 | }; | 2576 | }; |
2602 | 2577 | ||
@@ -2805,14 +2780,37 @@ static int vt1708S_auto_create_analog_input_ctls(struct via_spec *spec, | |||
2805 | return 0; | 2780 | return 0; |
2806 | } | 2781 | } |
2807 | 2782 | ||
2783 | /* fill out digital output widgets; one for master and one for slave outputs */ | ||
2784 | static void fill_dig_outs(struct hda_codec *codec) | ||
2785 | { | ||
2786 | struct via_spec *spec = codec->spec; | ||
2787 | int i; | ||
2788 | |||
2789 | for (i = 0; i < spec->autocfg.dig_outs; i++) { | ||
2790 | hda_nid_t nid; | ||
2791 | int conn; | ||
2792 | |||
2793 | nid = spec->autocfg.dig_out_pins[i]; | ||
2794 | if (!nid) | ||
2795 | continue; | ||
2796 | conn = snd_hda_get_connections(codec, nid, &nid, 1); | ||
2797 | if (conn < 1) | ||
2798 | continue; | ||
2799 | if (!spec->multiout.dig_out_nid) | ||
2800 | spec->multiout.dig_out_nid = nid; | ||
2801 | else { | ||
2802 | spec->slave_dig_outs[0] = nid; | ||
2803 | break; /* at most two dig outs */ | ||
2804 | } | ||
2805 | } | ||
2806 | } | ||
2807 | |||
2808 | static int vt1708S_parse_auto_config(struct hda_codec *codec) | 2808 | static int vt1708S_parse_auto_config(struct hda_codec *codec) |
2809 | { | 2809 | { |
2810 | struct via_spec *spec = codec->spec; | 2810 | struct via_spec *spec = codec->spec; |
2811 | int err; | 2811 | int err; |
2812 | static hda_nid_t vt1708s_ignore[] = {0x21, 0}; | ||
2813 | 2812 | ||
2814 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 2813 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL); |
2815 | vt1708s_ignore); | ||
2816 | if (err < 0) | 2814 | if (err < 0) |
2817 | return err; | 2815 | return err; |
2818 | err = vt1708S_auto_fill_dac_nids(spec, &spec->autocfg); | 2816 | err = vt1708S_auto_fill_dac_nids(spec, &spec->autocfg); |
@@ -2833,10 +2831,7 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec) | |||
2833 | 2831 | ||
2834 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 2832 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
2835 | 2833 | ||
2836 | if (spec->autocfg.dig_outs) | 2834 | fill_dig_outs(codec); |
2837 | spec->multiout.dig_out_nid = VT1708S_DIGOUT_NID; | ||
2838 | |||
2839 | spec->extra_dig_out_nid = 0x15; | ||
2840 | 2835 | ||
2841 | if (spec->kctls.list) | 2836 | if (spec->kctls.list) |
2842 | spec->mixers[spec->num_mixers++] = spec->kctls.list; | 2837 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |
@@ -3000,7 +2995,8 @@ static struct hda_pcm_stream vt1702_pcm_digital_playback = { | |||
3000 | .ops = { | 2995 | .ops = { |
3001 | .open = via_dig_playback_pcm_open, | 2996 | .open = via_dig_playback_pcm_open, |
3002 | .close = via_dig_playback_pcm_close, | 2997 | .close = via_dig_playback_pcm_close, |
3003 | .prepare = via_dig_playback_pcm_prepare | 2998 | .prepare = via_dig_playback_pcm_prepare, |
2999 | .cleanup = via_dig_playback_pcm_cleanup | ||
3004 | }, | 3000 | }, |
3005 | }; | 3001 | }; |
3006 | 3002 | ||
@@ -3128,10 +3124,8 @@ static int vt1702_parse_auto_config(struct hda_codec *codec) | |||
3128 | { | 3124 | { |
3129 | struct via_spec *spec = codec->spec; | 3125 | struct via_spec *spec = codec->spec; |
3130 | int err; | 3126 | int err; |
3131 | static hda_nid_t vt1702_ignore[] = {0x1C, 0}; | ||
3132 | 3127 | ||
3133 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | 3128 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL); |
3134 | vt1702_ignore); | ||
3135 | if (err < 0) | 3129 | if (err < 0) |
3136 | return err; | 3130 | return err; |
3137 | err = vt1702_auto_fill_dac_nids(spec, &spec->autocfg); | 3131 | err = vt1702_auto_fill_dac_nids(spec, &spec->autocfg); |
@@ -3152,10 +3146,7 @@ static int vt1702_parse_auto_config(struct hda_codec *codec) | |||
3152 | 3146 | ||
3153 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 3147 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
3154 | 3148 | ||
3155 | if (spec->autocfg.dig_outs) | 3149 | fill_dig_outs(codec); |
3156 | spec->multiout.dig_out_nid = VT1702_DIGOUT_NID; | ||
3157 | |||
3158 | spec->extra_dig_out_nid = 0x1B; | ||
3159 | 3150 | ||
3160 | if (spec->kctls.list) | 3151 | if (spec->kctls.list) |
3161 | spec->mixers[spec->num_mixers++] = spec->kctls.list; | 3152 | spec->mixers[spec->num_mixers++] = spec->kctls.list; |