diff options
author | Takashi Iwai <tiwai@suse.de> | 2008-02-18 06:23:13 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2008-04-24 06:00:11 -0400 |
commit | 4235a31784f59c9be5ff71534743c055091f9735 (patch) | |
tree | 87080055fed0c3f25a3c816c182a6db5739430b6 /sound/pci/ac97 | |
parent | 2eef1258e54722b1c4efac6e5760d2153f96c4b4 (diff) |
[ALSA] intel8x0 - Add support of 8 channel sound
Added the support of 8 channel sound for codecs that are known to work.
So far, only ALC850 is marked as a 8ch-support codec.
This fix is a modified version of the patch on ALSA BTS#2097 by
Martin Ellis:
https://bugtrack.alsa-project.org/alsa-bug/view.php?id=2097
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/ac97')
-rw-r--r-- | sound/pci/ac97/ac97_patch.c | 46 |
1 files changed, 33 insertions, 13 deletions
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 50c637e55ffa..39198e505b12 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c | |||
@@ -114,10 +114,9 @@ static int ac97_surround_jack_mode_put(struct snd_kcontrol *kcontrol, struct snd | |||
114 | 114 | ||
115 | static int ac97_channel_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 115 | static int ac97_channel_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
116 | { | 116 | { |
117 | static const char *texts[] = { "2ch", "4ch", "6ch" }; | 117 | static const char *texts[] = { "2ch", "4ch", "6ch", "8ch" }; |
118 | if (kcontrol->private_value) | 118 | return ac97_enum_text_info(kcontrol, uinfo, texts, |
119 | return ac97_enum_text_info(kcontrol, uinfo, texts, 2); /* 4ch only */ | 119 | kcontrol->private_value); |
120 | return ac97_enum_text_info(kcontrol, uinfo, texts, 3); | ||
121 | } | 120 | } |
122 | 121 | ||
123 | static int ac97_channel_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 122 | static int ac97_channel_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
@@ -133,13 +132,8 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
133 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); | 132 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); |
134 | unsigned char mode = ucontrol->value.enumerated.item[0]; | 133 | unsigned char mode = ucontrol->value.enumerated.item[0]; |
135 | 134 | ||
136 | if (kcontrol->private_value) { | 135 | if (mode >= kcontrol->private_value) |
137 | if (mode >= 2) | 136 | return -EINVAL; |
138 | return -EINVAL; | ||
139 | } else { | ||
140 | if (mode >= 3) | ||
141 | return -EINVAL; | ||
142 | } | ||
143 | 137 | ||
144 | if (mode != ac97->channel_mode) { | 138 | if (mode != ac97->channel_mode) { |
145 | ac97->channel_mode = mode; | 139 | ac97->channel_mode = mode; |
@@ -158,6 +152,7 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
158 | .get = ac97_surround_jack_mode_get, \ | 152 | .get = ac97_surround_jack_mode_get, \ |
159 | .put = ac97_surround_jack_mode_put, \ | 153 | .put = ac97_surround_jack_mode_put, \ |
160 | } | 154 | } |
155 | /* 6ch */ | ||
161 | #define AC97_CHANNEL_MODE_CTL \ | 156 | #define AC97_CHANNEL_MODE_CTL \ |
162 | { \ | 157 | { \ |
163 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 158 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
@@ -165,7 +160,9 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
165 | .info = ac97_channel_mode_info, \ | 160 | .info = ac97_channel_mode_info, \ |
166 | .get = ac97_channel_mode_get, \ | 161 | .get = ac97_channel_mode_get, \ |
167 | .put = ac97_channel_mode_put, \ | 162 | .put = ac97_channel_mode_put, \ |
163 | .private_value = 3, \ | ||
168 | } | 164 | } |
165 | /* 4ch */ | ||
169 | #define AC97_CHANNEL_MODE_4CH_CTL \ | 166 | #define AC97_CHANNEL_MODE_4CH_CTL \ |
170 | { \ | 167 | { \ |
171 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | 168 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
@@ -173,7 +170,17 @@ static int ac97_channel_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
173 | .info = ac97_channel_mode_info, \ | 170 | .info = ac97_channel_mode_info, \ |
174 | .get = ac97_channel_mode_get, \ | 171 | .get = ac97_channel_mode_get, \ |
175 | .put = ac97_channel_mode_put, \ | 172 | .put = ac97_channel_mode_put, \ |
176 | .private_value = 1, \ | 173 | .private_value = 2, \ |
174 | } | ||
175 | /* 8ch */ | ||
176 | #define AC97_CHANNEL_MODE_8CH_CTL \ | ||
177 | { \ | ||
178 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
179 | .name = "Channel Mode", \ | ||
180 | .info = ac97_channel_mode_info, \ | ||
181 | .get = ac97_channel_mode_get, \ | ||
182 | .put = ac97_channel_mode_put, \ | ||
183 | .private_value = 4, \ | ||
177 | } | 184 | } |
178 | 185 | ||
179 | static inline int is_surround_on(struct snd_ac97 *ac97) | 186 | static inline int is_surround_on(struct snd_ac97 *ac97) |
@@ -210,6 +217,10 @@ static inline int is_shared_micin(struct snd_ac97 *ac97) | |||
210 | return !ac97->indep_surround && !is_clfe_on(ac97); | 217 | return !ac97->indep_surround && !is_clfe_on(ac97); |
211 | } | 218 | } |
212 | 219 | ||
220 | static inline int alc850_is_aux_back_surround(struct snd_ac97 *ac97) | ||
221 | { | ||
222 | return is_surround_on(ac97); | ||
223 | } | ||
213 | 224 | ||
214 | /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */ | 225 | /* The following snd_ac97_ymf753_... items added by David Shust (dshust@shustring.com) */ |
215 | /* Modified for YMF743 by Keita Maehara <maehara@debian.org> */ | 226 | /* Modified for YMF743 by Keita Maehara <maehara@debian.org> */ |
@@ -2816,10 +2827,12 @@ static int patch_alc655(struct snd_ac97 * ac97) | |||
2816 | 2827 | ||
2817 | #define AC97_ALC850_JACK_SELECT 0x76 | 2828 | #define AC97_ALC850_JACK_SELECT 0x76 |
2818 | #define AC97_ALC850_MISC1 0x7a | 2829 | #define AC97_ALC850_MISC1 0x7a |
2830 | #define AC97_ALC850_MULTICH 0x6a | ||
2819 | 2831 | ||
2820 | static void alc850_update_jacks(struct snd_ac97 *ac97) | 2832 | static void alc850_update_jacks(struct snd_ac97 *ac97) |
2821 | { | 2833 | { |
2822 | int shared; | 2834 | int shared; |
2835 | int aux_is_back_surround; | ||
2823 | 2836 | ||
2824 | /* shared Line-In / Surround Out */ | 2837 | /* shared Line-In / Surround Out */ |
2825 | shared = is_shared_surrout(ac97); | 2838 | shared = is_shared_surrout(ac97); |
@@ -2837,13 +2850,18 @@ static void alc850_update_jacks(struct snd_ac97 *ac97) | |||
2837 | /* MIC-IN = 1, CENTER-LFE = 5 */ | 2850 | /* MIC-IN = 1, CENTER-LFE = 5 */ |
2838 | snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4, | 2851 | snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 4, |
2839 | shared ? (5<<4) : (1<<4)); | 2852 | shared ? (5<<4) : (1<<4)); |
2853 | |||
2854 | aux_is_back_surround = alc850_is_aux_back_surround(ac97); | ||
2855 | /* Aux is Back Surround */ | ||
2856 | snd_ac97_update_bits(ac97, AC97_ALC850_MULTICH, 1 << 10, | ||
2857 | aux_is_back_surround ? (1<<10) : (0<<10)); | ||
2840 | } | 2858 | } |
2841 | 2859 | ||
2842 | static const struct snd_kcontrol_new snd_ac97_controls_alc850[] = { | 2860 | static const struct snd_kcontrol_new snd_ac97_controls_alc850[] = { |
2843 | AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0), | 2861 | AC97_PAGE_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0, 0), |
2844 | AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1), | 2862 | AC97_SINGLE("Mic Front Input Switch", AC97_ALC850_JACK_SELECT, 15, 1, 1), |
2845 | AC97_SURROUND_JACK_MODE_CTL, | 2863 | AC97_SURROUND_JACK_MODE_CTL, |
2846 | AC97_CHANNEL_MODE_CTL, | 2864 | AC97_CHANNEL_MODE_8CH_CTL, |
2847 | }; | 2865 | }; |
2848 | 2866 | ||
2849 | static int patch_alc850_specific(struct snd_ac97 *ac97) | 2867 | static int patch_alc850_specific(struct snd_ac97 *ac97) |
@@ -2869,6 +2887,7 @@ static int patch_alc850(struct snd_ac97 *ac97) | |||
2869 | ac97->build_ops = &patch_alc850_ops; | 2887 | ac97->build_ops = &patch_alc850_ops; |
2870 | 2888 | ||
2871 | ac97->spec.dev_flags = 0; /* for IEC958 playback route - ALC655 compatible */ | 2889 | ac97->spec.dev_flags = 0; /* for IEC958 playback route - ALC655 compatible */ |
2890 | ac97->flags |= AC97_HAS_8CH; | ||
2872 | 2891 | ||
2873 | /* assume only page 0 for writing cache */ | 2892 | /* assume only page 0 for writing cache */ |
2874 | snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR); | 2893 | snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR); |
@@ -2878,6 +2897,7 @@ static int patch_alc850(struct snd_ac97 *ac97) | |||
2878 | spdif-in monitor off, spdif-in PCM off | 2897 | spdif-in monitor off, spdif-in PCM off |
2879 | center on mic off, surround on line-in off | 2898 | center on mic off, surround on line-in off |
2880 | duplicate front off | 2899 | duplicate front off |
2900 | NB default bit 10=0 = Aux is Capture, not Back Surround | ||
2881 | */ | 2901 | */ |
2882 | snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15); | 2902 | snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, 1<<15); |
2883 | /* SURR_OUT: on, Surr 1kOhm: on, Surr Amp: off, Front 1kOhm: off | 2903 | /* SURR_OUT: on, Surr 1kOhm: on, Surr Amp: off, Front 1kOhm: off |