aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2008-02-18 06:23:13 -0500
committerTakashi Iwai <tiwai@suse.de>2008-04-24 06:00:11 -0400
commit4235a31784f59c9be5ff71534743c055091f9735 (patch)
tree87080055fed0c3f25a3c816c182a6db5739430b6 /sound/pci
parent2eef1258e54722b1c4efac6e5760d2153f96c4b4 (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')
-rw-r--r--sound/pci/ac97/ac97_patch.c46
-rw-r--r--sound/pci/intel8x0.c28
2 files changed, 58 insertions, 16 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
115static int ac97_channel_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 115static 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
123static int ac97_channel_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 122static 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
179static inline int is_surround_on(struct snd_ac97 *ac97) 186static 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
220static 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
2820static void alc850_update_jacks(struct snd_ac97 *ac97) 2832static 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
2842static const struct snd_kcontrol_new snd_ac97_controls_alc850[] = { 2860static 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
2849static int patch_alc850_specific(struct snd_ac97 *ac97) 2867static 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
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index c52abd0bf22e..07782ba9c74d 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -155,7 +155,8 @@ DEFINE_REGSET(SP, 0x60); /* SPDIF out */
155#define ICH_PCM_SPDIF_69 0x80000000 /* s/pdif pcm on slots 6&9 */ 155#define ICH_PCM_SPDIF_69 0x80000000 /* s/pdif pcm on slots 6&9 */
156#define ICH_PCM_SPDIF_1011 0xc0000000 /* s/pdif pcm on slots 10&11 */ 156#define ICH_PCM_SPDIF_1011 0xc0000000 /* s/pdif pcm on slots 10&11 */
157#define ICH_PCM_20BIT 0x00400000 /* 20-bit samples (ICH4) */ 157#define ICH_PCM_20BIT 0x00400000 /* 20-bit samples (ICH4) */
158#define ICH_PCM_246_MASK 0x00300000 /* 6 channels (not all chips) */ 158#define ICH_PCM_246_MASK 0x00300000 /* chan mask (not all chips) */
159#define ICH_PCM_8 0x00300000 /* 8 channels (not all chips) */
159#define ICH_PCM_6 0x00200000 /* 6 channels (not all chips) */ 160#define ICH_PCM_6 0x00200000 /* 6 channels (not all chips) */
160#define ICH_PCM_4 0x00100000 /* 4 channels (not all chips) */ 161#define ICH_PCM_4 0x00100000 /* 4 channels (not all chips) */
161#define ICH_PCM_2 0x00000000 /* 2 channels (stereo) */ 162#define ICH_PCM_2 0x00000000 /* 2 channels (stereo) */
@@ -382,6 +383,7 @@ struct intel8x0 {
382 383
383 unsigned multi4: 1, 384 unsigned multi4: 1,
384 multi6: 1, 385 multi6: 1,
386 multi8 :1,
385 dra: 1, 387 dra: 1,
386 smp20bit: 1; 388 smp20bit: 1;
387 unsigned in_ac97_init: 1, 389 unsigned in_ac97_init: 1,
@@ -997,6 +999,8 @@ static void snd_intel8x0_setup_pcm_out(struct intel8x0 *chip,
997 cnt |= ICH_PCM_4; 999 cnt |= ICH_PCM_4;
998 else if (runtime->channels == 6) 1000 else if (runtime->channels == 6)
999 cnt |= ICH_PCM_6; 1001 cnt |= ICH_PCM_6;
1002 else if (runtime->channels == 8)
1003 cnt |= ICH_PCM_8;
1000 if (chip->device_type == DEVICE_NFORCE) { 1004 if (chip->device_type == DEVICE_NFORCE) {
1001 /* reset to 2ch once to keep the 6 channel data in alignment, 1005 /* reset to 2ch once to keep the 6 channel data in alignment,
1002 * to start from Front Left always 1006 * to start from Front Left always
@@ -1106,6 +1110,16 @@ static struct snd_pcm_hw_constraint_list hw_constraints_channels6 = {
1106 .mask = 0, 1110 .mask = 0,
1107}; 1111};
1108 1112
1113static unsigned int channels8[] = {
1114 2, 4, 6, 8,
1115};
1116
1117static struct snd_pcm_hw_constraint_list hw_constraints_channels8 = {
1118 .count = ARRAY_SIZE(channels8),
1119 .list = channels8,
1120 .mask = 0,
1121};
1122
1109static int snd_intel8x0_pcm_open(struct snd_pcm_substream *substream, struct ichdev *ichdev) 1123static int snd_intel8x0_pcm_open(struct snd_pcm_substream *substream, struct ichdev *ichdev)
1110{ 1124{
1111 struct intel8x0 *chip = snd_pcm_substream_chip(substream); 1125 struct intel8x0 *chip = snd_pcm_substream_chip(substream);
@@ -1136,7 +1150,12 @@ static int snd_intel8x0_playback_open(struct snd_pcm_substream *substream)
1136 if (err < 0) 1150 if (err < 0)
1137 return err; 1151 return err;
1138 1152
1139 if (chip->multi6) { 1153 if (chip->multi8) {
1154 runtime->hw.channels_max = 8;
1155 snd_pcm_hw_constraint_list(runtime, 0,
1156 SNDRV_PCM_HW_PARAM_CHANNELS,
1157 &hw_constraints_channels8);
1158 } else if (chip->multi6) {
1140 runtime->hw.channels_max = 6; 1159 runtime->hw.channels_max = 6;
1141 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, 1160 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
1142 &hw_constraints_channels6); 1161 &hw_constraints_channels6);
@@ -2203,8 +2222,11 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
2203 } 2222 }
2204 if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_PCM_SLEFT)) { 2223 if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_PCM_SLEFT)) {
2205 chip->multi4 = 1; 2224 chip->multi4 = 1;
2206 if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_LFE)) 2225 if (pbus->pcms[0].r[0].slots & (1 << AC97_SLOT_LFE)) {
2207 chip->multi6 = 1; 2226 chip->multi6 = 1;
2227 if (chip->ac97[0]->flags & AC97_HAS_8CH)
2228 chip->multi8 = 1;
2229 }
2208 } 2230 }
2209 if (pbus->pcms[0].r[1].rslots[0]) { 2231 if (pbus->pcms[0].r[1].rslots[0]) {
2210 chip->dra = 1; 2232 chip->dra = 1;