blob: c8176dc8142ff483ecd27d1dba660bfd83918cd2 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>,
3 * Takashi Iwai <tiwai@suse.de>
4 * Creative Labs, Inc.
5 * Routines for control of EMU10K1 chips / mixer routines
6 * Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com>
7 *
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01008 * Copyright (c) by James Courtier-Dutton <James@superbug.co.uk>
9 * Added EMU 1010 support.
10 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 * BUGS:
12 * --
13 *
14 * TODO:
15 * --
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 *
31 */
32
33#include <sound/driver.h>
34#include <linux/time.h>
35#include <linux/init.h>
36#include <sound/core.h>
37#include <sound/emu10k1.h>
38
39#define AC97_ID_STAC9758 0x83847658
40
Takashi Iwaieb4698f2005-11-17 14:50:13 +010041static int snd_emu10k1_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -070042{
43 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
44 uinfo->count = 1;
45 return 0;
46}
47
Takashi Iwaieb4698f2005-11-17 14:50:13 +010048static int snd_emu10k1_spdif_get(struct snd_kcontrol *kcontrol,
49 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -070050{
Takashi Iwaieb4698f2005-11-17 14:50:13 +010051 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -070052 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
53 unsigned long flags;
54
55 spin_lock_irqsave(&emu->reg_lock, flags);
56 ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff;
57 ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff;
58 ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff;
59 ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff;
60 spin_unlock_irqrestore(&emu->reg_lock, flags);
61 return 0;
62}
63
Takashi Iwaieb4698f2005-11-17 14:50:13 +010064static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol,
65 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -070066{
67 ucontrol->value.iec958.status[0] = 0xff;
68 ucontrol->value.iec958.status[1] = 0xff;
69 ucontrol->value.iec958.status[2] = 0xff;
70 ucontrol->value.iec958.status[3] = 0xff;
71 return 0;
72}
73
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +010074static char *emu1010_src_texts[] = {
75 "Silence",
76 "Dock Mic A",
77 "Dock Mic B",
78 "Dock ADC1 Left",
79 "Dock ADC1 Right",
80 "Dock ADC2 Left",
81 "Dock ADC2 Right",
82 "Dock ADC3 Left",
83 "Dock ADC3 Right",
84 "0202 ADC Left",
85 "0202 ADC Right",
86 "0202 SPDIF Left",
87 "0202 SPDIF Right",
88 "ADAT 0",
89 "ADAT 1",
90 "ADAT 2",
91 "ADAT 3",
92 "ADAT 4",
93 "ADAT 5",
94 "ADAT 6",
95 "ADAT 7",
96 "DSP 0",
97 "DSP 1",
98 "DSP 2",
99 "DSP 3",
100 "DSP 4",
101 "DSP 5",
102 "DSP 6",
103 "DSP 7",
104 "DSP 8",
105 "DSP 9",
106 "DSP 10",
107 "DSP 11",
108 "DSP 12",
109 "DSP 13",
110 "DSP 14",
111 "DSP 15",
112 "DSP 16",
113 "DSP 17",
114 "DSP 18",
115 "DSP 19",
116 "DSP 20",
117 "DSP 21",
118 "DSP 22",
119 "DSP 23",
120 "DSP 24",
121 "DSP 25",
122 "DSP 26",
123 "DSP 27",
124 "DSP 28",
125 "DSP 29",
126 "DSP 30",
127 "DSP 31",
128};
129
130static unsigned int emu1010_src_regs[] = {
131 EMU_SRC_SILENCE,/* 0 */
132 EMU_SRC_DOCK_MIC_A1, /* 1 */
133 EMU_SRC_DOCK_MIC_B1, /* 2 */
134 EMU_SRC_DOCK_ADC1_LEFT1, /* 3 */
135 EMU_SRC_DOCK_ADC1_RIGHT1, /* 4 */
136 EMU_SRC_DOCK_ADC2_LEFT1, /* 5 */
137 EMU_SRC_DOCK_ADC2_RIGHT1, /* 6 */
138 EMU_SRC_DOCK_ADC3_LEFT1, /* 7 */
139 EMU_SRC_DOCK_ADC3_RIGHT1, /* 8 */
140 EMU_SRC_HAMOA_ADC_LEFT1, /* 9 */
141 EMU_SRC_HAMOA_ADC_RIGHT1, /* 10 */
142 EMU_SRC_HANA_SPDIF_LEFT1, /* 11 */
143 EMU_SRC_HANA_SPDIF_RIGHT1, /* 12 */
144 EMU_SRC_HANA_ADAT, /* 13 */
145 EMU_SRC_HANA_ADAT+1, /* 14 */
146 EMU_SRC_HANA_ADAT+2, /* 15 */
147 EMU_SRC_HANA_ADAT+3, /* 16 */
148 EMU_SRC_HANA_ADAT+4, /* 17 */
149 EMU_SRC_HANA_ADAT+5, /* 18 */
150 EMU_SRC_HANA_ADAT+6, /* 19 */
151 EMU_SRC_HANA_ADAT+7, /* 20 */
152 EMU_SRC_ALICE_EMU32A, /* 21 */
153 EMU_SRC_ALICE_EMU32A+1, /* 22 */
154 EMU_SRC_ALICE_EMU32A+2, /* 23 */
155 EMU_SRC_ALICE_EMU32A+3, /* 24 */
156 EMU_SRC_ALICE_EMU32A+4, /* 25 */
157 EMU_SRC_ALICE_EMU32A+5, /* 26 */
158 EMU_SRC_ALICE_EMU32A+6, /* 27 */
159 EMU_SRC_ALICE_EMU32A+7, /* 28 */
160 EMU_SRC_ALICE_EMU32A+8, /* 29 */
161 EMU_SRC_ALICE_EMU32A+9, /* 30 */
162 EMU_SRC_ALICE_EMU32A+0xa, /* 31 */
163 EMU_SRC_ALICE_EMU32A+0xb, /* 32 */
164 EMU_SRC_ALICE_EMU32A+0xc, /* 33 */
165 EMU_SRC_ALICE_EMU32A+0xd, /* 34 */
166 EMU_SRC_ALICE_EMU32A+0xe, /* 35 */
167 EMU_SRC_ALICE_EMU32A+0xf, /* 36 */
168 EMU_SRC_ALICE_EMU32B, /* 37 */
169 EMU_SRC_ALICE_EMU32B+1, /* 38 */
170 EMU_SRC_ALICE_EMU32B+2, /* 39 */
171 EMU_SRC_ALICE_EMU32B+3, /* 40 */
172 EMU_SRC_ALICE_EMU32B+4, /* 41 */
173 EMU_SRC_ALICE_EMU32B+5, /* 42 */
174 EMU_SRC_ALICE_EMU32B+6, /* 43 */
175 EMU_SRC_ALICE_EMU32B+7, /* 44 */
176 EMU_SRC_ALICE_EMU32B+8, /* 45 */
177 EMU_SRC_ALICE_EMU32B+9, /* 46 */
178 EMU_SRC_ALICE_EMU32B+0xa, /* 47 */
179 EMU_SRC_ALICE_EMU32B+0xb, /* 48 */
180 EMU_SRC_ALICE_EMU32B+0xc, /* 49 */
181 EMU_SRC_ALICE_EMU32B+0xd, /* 50 */
182 EMU_SRC_ALICE_EMU32B+0xe, /* 51 */
183 EMU_SRC_ALICE_EMU32B+0xf, /* 52 */
184};
185
186static unsigned int emu1010_output_dst[] = {
187 EMU_DST_DOCK_DAC1_LEFT1, /* 0 */
188 EMU_DST_DOCK_DAC1_RIGHT1, /* 1 */
189 EMU_DST_DOCK_DAC2_LEFT1, /* 2 */
190 EMU_DST_DOCK_DAC2_RIGHT1, /* 3 */
191 EMU_DST_DOCK_DAC3_LEFT1, /* 4 */
192 EMU_DST_DOCK_DAC3_RIGHT1, /* 5 */
193 EMU_DST_DOCK_DAC4_LEFT1, /* 6 */
194 EMU_DST_DOCK_DAC4_RIGHT1, /* 7 */
195 EMU_DST_DOCK_PHONES_LEFT1, /* 8 */
196 EMU_DST_DOCK_PHONES_RIGHT1, /* 9 */
197 EMU_DST_DOCK_SPDIF_LEFT1, /* 10 */
198 EMU_DST_DOCK_SPDIF_RIGHT1, /* 11 */
199 EMU_DST_HANA_SPDIF_LEFT1, /* 12 */
200 EMU_DST_HANA_SPDIF_RIGHT1, /* 13 */
201 EMU_DST_HAMOA_DAC_LEFT1, /* 14 */
202 EMU_DST_HAMOA_DAC_RIGHT1, /* 15 */
203 EMU_DST_HANA_ADAT, /* 16 */
204 EMU_DST_HANA_ADAT+1, /* 17 */
205 EMU_DST_HANA_ADAT+2, /* 18 */
206 EMU_DST_HANA_ADAT+3, /* 19 */
207 EMU_DST_HANA_ADAT+4, /* 20 */
208 EMU_DST_HANA_ADAT+5, /* 21 */
209 EMU_DST_HANA_ADAT+6, /* 22 */
210 EMU_DST_HANA_ADAT+7, /* 23 */
211};
212
213static unsigned int emu1010_input_dst[] = {
214 EMU_DST_ALICE2_EMU32_0,
215 EMU_DST_ALICE2_EMU32_1,
216 EMU_DST_ALICE2_EMU32_2,
217 EMU_DST_ALICE2_EMU32_3,
218 EMU_DST_ALICE2_EMU32_4,
219 EMU_DST_ALICE2_EMU32_5,
220 EMU_DST_ALICE2_EMU32_6,
221 EMU_DST_ALICE2_EMU32_7,
222 EMU_DST_ALICE2_EMU32_8,
223 EMU_DST_ALICE2_EMU32_9,
224 EMU_DST_ALICE2_EMU32_A,
225 EMU_DST_ALICE2_EMU32_B,
226 EMU_DST_ALICE2_EMU32_C,
227 EMU_DST_ALICE2_EMU32_D,
228 EMU_DST_ALICE2_EMU32_E,
229 EMU_DST_ALICE2_EMU32_F,
230 EMU_DST_ALICE_I2S0_LEFT,
231 EMU_DST_ALICE_I2S0_RIGHT,
232 EMU_DST_ALICE_I2S1_LEFT,
233 EMU_DST_ALICE_I2S1_RIGHT,
234 EMU_DST_ALICE_I2S2_LEFT,
235 EMU_DST_ALICE_I2S2_RIGHT,
236};
237
238static int snd_emu1010_input_output_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
239{
240 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
241 uinfo->count = 1;
242 uinfo->value.enumerated.items = 53;
243 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
244 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
245 strcpy(uinfo->value.enumerated.name, emu1010_src_texts[uinfo->value.enumerated.item]);
246 return 0;
247}
248
249static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol,
250 struct snd_ctl_elem_value *ucontrol)
251{
252 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
253 int channel;
254
255 channel = (kcontrol->private_value) & 0xff;
256 ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel];
257 return 0;
258}
259
260static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol,
261 struct snd_ctl_elem_value *ucontrol)
262{
263 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
264 int change = 0;
265 unsigned int val;
266 int channel;
267
268 channel = (kcontrol->private_value) & 0xff;
269 if (emu->emu1010.output_source[channel] != ucontrol->value.enumerated.item[0]) {
270 val = emu->emu1010.output_source[channel] = ucontrol->value.enumerated.item[0];
271 change = 1;
272 snd_emu1010_fpga_link_dst_src_write(emu,
273 emu1010_output_dst[channel], emu1010_src_regs[val]);
274 }
275 return change;
276}
277
278static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol,
279 struct snd_ctl_elem_value *ucontrol)
280{
281 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
282 int channel;
283
284 channel = (kcontrol->private_value) & 0xff;
285 ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel];
286 return 0;
287}
288
289static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
290 struct snd_ctl_elem_value *ucontrol)
291{
292 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
293 int change = 0;
294 unsigned int val;
295 int channel;
296
297 channel = (kcontrol->private_value) & 0xff;
298 if (emu->emu1010.input_source[channel] != ucontrol->value.enumerated.item[0]) {
299 val = emu->emu1010.input_source[channel] = ucontrol->value.enumerated.item[0];
300 change = 1;
301 snd_emu1010_fpga_link_dst_src_write(emu,
302 emu1010_input_dst[channel], emu1010_src_regs[val]);
303 }
304 return change;
305}
306
307#define EMU1010_SOURCE_OUTPUT(xname,chid) \
308{ \
309 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
310 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
311 .info = snd_emu1010_input_output_source_info, \
312 .get = snd_emu1010_output_source_get, \
313 .put = snd_emu1010_output_source_put, \
314 .private_value = chid \
315}
316
317static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = {
318 EMU1010_SOURCE_OUTPUT("Playback Dock DAC1 Left", 0),
319 EMU1010_SOURCE_OUTPUT("Playback Dock DAC1 Right", 1),
320 EMU1010_SOURCE_OUTPUT("Playback Dock DAC2 Left", 2),
321 EMU1010_SOURCE_OUTPUT("Playback Dock DAC2 Right", 3),
322 EMU1010_SOURCE_OUTPUT("Playback Dock DAC3 Left", 4),
323 EMU1010_SOURCE_OUTPUT("Playback Dock DAC3 Right", 5),
324 EMU1010_SOURCE_OUTPUT("Playback Dock DAC4 Left", 6),
325 EMU1010_SOURCE_OUTPUT("Playback Dock DAC4 Right", 7),
326 EMU1010_SOURCE_OUTPUT("Playback Dock Phones Left", 8),
327 EMU1010_SOURCE_OUTPUT("Playback Dock Phones Right", 9),
328 EMU1010_SOURCE_OUTPUT("Playback Dock SPDIF Left", 0xa),
329 EMU1010_SOURCE_OUTPUT("Playback Dock SPDIF Right", 0xb),
330 EMU1010_SOURCE_OUTPUT("Playback 1010 SPDIF Left", 0xc),
331 EMU1010_SOURCE_OUTPUT("Playback 1010 SPDIF Right", 0xd),
332 EMU1010_SOURCE_OUTPUT("Playback 0202 DAC Left", 0xe),
333 EMU1010_SOURCE_OUTPUT("Playback 0202 DAC Right", 0xf),
334 EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 0", 0x10),
335 EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 1", 0x11),
336 EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 2", 0x12),
337 EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 3", 0x13),
338 EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 4", 0x14),
339 EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 5", 0x15),
340 EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 6", 0x16),
341 EMU1010_SOURCE_OUTPUT("Playback 1010 ADAT 7", 0x17),
342};
343
344#define EMU1010_SOURCE_INPUT(xname,chid) \
345{ \
346 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
347 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
348 .info = snd_emu1010_input_output_source_info, \
349 .get = snd_emu1010_input_source_get, \
350 .put = snd_emu1010_input_source_put, \
351 .private_value = chid \
352}
353
354static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] __devinitdata = {
355 EMU1010_SOURCE_INPUT("DSP 0 CAPTURE ENUM", 0),
356 EMU1010_SOURCE_INPUT("DSP 1 CAPTURE ENUM", 1),
357 EMU1010_SOURCE_INPUT("DSP 2 CAPTURE ENUM", 2),
358 EMU1010_SOURCE_INPUT("DSP 3 CAPTURE ENUM", 3),
359 EMU1010_SOURCE_INPUT("DSP 4 CAPTURE ENUM", 4),
360 EMU1010_SOURCE_INPUT("DSP 5 CAPTURE ENUM", 5),
361 EMU1010_SOURCE_INPUT("DSP 6 CAPTURE ENUM", 6),
362 EMU1010_SOURCE_INPUT("DSP 7 CAPTURE ENUM", 7),
363 EMU1010_SOURCE_INPUT("DSP 8 CAPTURE ENUM", 8),
364 EMU1010_SOURCE_INPUT("DSP 9 CAPTURE ENUM", 9),
365 EMU1010_SOURCE_INPUT("DSP A CAPTURE ENUM", 0xa),
366 EMU1010_SOURCE_INPUT("DSP B CAPTURE ENUM", 0xb),
367 EMU1010_SOURCE_INPUT("DSP C CAPTURE ENUM", 0xc),
368 EMU1010_SOURCE_INPUT("DSP D CAPTURE ENUM", 0xd),
369 EMU1010_SOURCE_INPUT("DSP E CAPTURE ENUM", 0xe),
370 EMU1010_SOURCE_INPUT("DSP F CAPTURE ENUM", 0xf),
371 EMU1010_SOURCE_INPUT("DSP 10 CAPTURE ENUM", 0x10),
372 EMU1010_SOURCE_INPUT("DSP 11 CAPTURE ENUM", 0x11),
373 EMU1010_SOURCE_INPUT("DSP 12 CAPTURE ENUM", 0x12),
374 EMU1010_SOURCE_INPUT("DSP 13 CAPTURE ENUM", 0x13),
375 EMU1010_SOURCE_INPUT("DSP 14 CAPTURE ENUM", 0x14),
376 EMU1010_SOURCE_INPUT("DSP 15 CAPTURE ENUM", 0x15),
377};
378
Takashi Iwai0af68e52005-04-11 17:03:03 +0200379#if 0
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100380static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381{
382 static char *texts[] = {"44100", "48000", "96000"};
383
384 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
385 uinfo->count = 1;
386 uinfo->value.enumerated.items = 3;
387 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
388 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
389 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
390 return 0;
391}
392
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100393static int snd_audigy_spdif_output_rate_get(struct snd_kcontrol *kcontrol,
394 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100396 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 unsigned int tmp;
398 unsigned long flags;
399
400
401 spin_lock_irqsave(&emu->reg_lock, flags);
402 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
403 switch (tmp & A_SPDIF_RATE_MASK) {
404 case A_SPDIF_44100:
405 ucontrol->value.enumerated.item[0] = 0;
406 break;
407 case A_SPDIF_48000:
408 ucontrol->value.enumerated.item[0] = 1;
409 break;
410 case A_SPDIF_96000:
411 ucontrol->value.enumerated.item[0] = 2;
412 break;
413 default:
414 ucontrol->value.enumerated.item[0] = 1;
415 }
416 spin_unlock_irqrestore(&emu->reg_lock, flags);
417 return 0;
418}
419
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100420static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol,
421 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100423 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 int change;
425 unsigned int reg, val, tmp;
426 unsigned long flags;
427
428 switch(ucontrol->value.enumerated.item[0]) {
429 case 0:
430 val = A_SPDIF_44100;
431 break;
432 case 1:
433 val = A_SPDIF_48000;
434 break;
435 case 2:
436 val = A_SPDIF_96000;
437 break;
438 default:
439 val = A_SPDIF_48000;
440 break;
441 }
442
443
444 spin_lock_irqsave(&emu->reg_lock, flags);
445 reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
446 tmp = reg & ~A_SPDIF_RATE_MASK;
447 tmp |= val;
448 if ((change = (tmp != reg)))
449 snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
450 spin_unlock_irqrestore(&emu->reg_lock, flags);
451 return change;
452}
453
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100454static struct snd_kcontrol_new snd_audigy_spdif_output_rate =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455{
456 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
457 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
458 .name = "Audigy SPDIF Output Sample Rate",
459 .count = 1,
460 .info = snd_audigy_spdif_output_rate_info,
461 .get = snd_audigy_spdif_output_rate_get,
462 .put = snd_audigy_spdif_output_rate_put
463};
Takashi Iwai0af68e52005-04-11 17:03:03 +0200464#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100466static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol,
467 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100469 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
471 int change;
472 unsigned int val;
473 unsigned long flags;
474
475 val = (ucontrol->value.iec958.status[0] << 0) |
476 (ucontrol->value.iec958.status[1] << 8) |
477 (ucontrol->value.iec958.status[2] << 16) |
478 (ucontrol->value.iec958.status[3] << 24);
479 spin_lock_irqsave(&emu->reg_lock, flags);
480 change = val != emu->spdif_bits[idx];
481 if (change) {
482 snd_emu10k1_ptr_write(emu, SPCS0 + idx, 0, val);
483 emu->spdif_bits[idx] = val;
484 }
485 spin_unlock_irqrestore(&emu->reg_lock, flags);
486 return change;
487}
488
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100489static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490{
491 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +0200492 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
494 .count = 4,
495 .info = snd_emu10k1_spdif_info,
496 .get = snd_emu10k1_spdif_get_mask
497};
498
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100499static struct snd_kcontrol_new snd_emu10k1_spdif_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500{
Clemens Ladisch5549d542005-08-03 13:50:30 +0200501 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
503 .count = 4,
504 .info = snd_emu10k1_spdif_info,
505 .get = snd_emu10k1_spdif_get,
506 .put = snd_emu10k1_spdif_put
507};
508
509
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100510static void update_emu10k1_fxrt(struct snd_emu10k1 *emu, int voice, unsigned char *route)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511{
512 if (emu->audigy) {
513 snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
514 snd_emu10k1_compose_audigy_fxrt1(route));
515 snd_emu10k1_ptr_write(emu, A_FXRT2, voice,
516 snd_emu10k1_compose_audigy_fxrt2(route));
517 } else {
518 snd_emu10k1_ptr_write(emu, FXRT, voice,
519 snd_emu10k1_compose_send_routing(route));
520 }
521}
522
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100523static void update_emu10k1_send_volume(struct snd_emu10k1 *emu, int voice, unsigned char *volume)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524{
525 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]);
526 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]);
527 snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, volume[2]);
528 snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, volume[3]);
529 if (emu->audigy) {
530 unsigned int val = ((unsigned int)volume[4] << 24) |
531 ((unsigned int)volume[5] << 16) |
532 ((unsigned int)volume[6] << 8) |
533 (unsigned int)volume[7];
534 snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, val);
535 }
536}
537
538/* PCM stream controls */
539
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100540static int snd_emu10k1_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100542 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
544 uinfo->count = emu->audigy ? 3*8 : 3*4;
545 uinfo->value.integer.min = 0;
546 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
547 return 0;
548}
549
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100550static int snd_emu10k1_send_routing_get(struct snd_kcontrol *kcontrol,
551 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552{
553 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100554 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
555 struct snd_emu10k1_pcm_mixer *mix =
556 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 int voice, idx;
558 int num_efx = emu->audigy ? 8 : 4;
559 int mask = emu->audigy ? 0x3f : 0x0f;
560
561 spin_lock_irqsave(&emu->reg_lock, flags);
562 for (voice = 0; voice < 3; voice++)
563 for (idx = 0; idx < num_efx; idx++)
564 ucontrol->value.integer.value[(voice * num_efx) + idx] =
565 mix->send_routing[voice][idx] & mask;
566 spin_unlock_irqrestore(&emu->reg_lock, flags);
567 return 0;
568}
569
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100570static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol,
571 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572{
573 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100574 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
575 struct snd_emu10k1_pcm_mixer *mix =
576 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 int change = 0, voice, idx, val;
578 int num_efx = emu->audigy ? 8 : 4;
579 int mask = emu->audigy ? 0x3f : 0x0f;
580
581 spin_lock_irqsave(&emu->reg_lock, flags);
582 for (voice = 0; voice < 3; voice++)
583 for (idx = 0; idx < num_efx; idx++) {
584 val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask;
585 if (mix->send_routing[voice][idx] != val) {
586 mix->send_routing[voice][idx] = val;
587 change = 1;
588 }
589 }
590 if (change && mix->epcm) {
591 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
592 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
593 &mix->send_routing[1][0]);
594 update_emu10k1_fxrt(emu, mix->epcm->voices[1]->number,
595 &mix->send_routing[2][0]);
596 } else if (mix->epcm->voices[0]) {
597 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
598 &mix->send_routing[0][0]);
599 }
600 }
601 spin_unlock_irqrestore(&emu->reg_lock, flags);
602 return change;
603}
604
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100605static struct snd_kcontrol_new snd_emu10k1_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606{
607 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +0200608 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 .name = "EMU10K1 PCM Send Routing",
610 .count = 32,
611 .info = snd_emu10k1_send_routing_info,
612 .get = snd_emu10k1_send_routing_get,
613 .put = snd_emu10k1_send_routing_put
614};
615
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100616static int snd_emu10k1_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100618 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
620 uinfo->count = emu->audigy ? 3*8 : 3*4;
621 uinfo->value.integer.min = 0;
622 uinfo->value.integer.max = 255;
623 return 0;
624}
625
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100626static int snd_emu10k1_send_volume_get(struct snd_kcontrol *kcontrol,
627 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628{
629 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100630 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
631 struct snd_emu10k1_pcm_mixer *mix =
632 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 int idx;
634 int num_efx = emu->audigy ? 8 : 4;
635
636 spin_lock_irqsave(&emu->reg_lock, flags);
637 for (idx = 0; idx < 3*num_efx; idx++)
638 ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx];
639 spin_unlock_irqrestore(&emu->reg_lock, flags);
640 return 0;
641}
642
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100643static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol,
644 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645{
646 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100647 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
648 struct snd_emu10k1_pcm_mixer *mix =
649 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 int change = 0, idx, val;
651 int num_efx = emu->audigy ? 8 : 4;
652
653 spin_lock_irqsave(&emu->reg_lock, flags);
654 for (idx = 0; idx < 3*num_efx; idx++) {
655 val = ucontrol->value.integer.value[idx] & 255;
656 if (mix->send_volume[idx/num_efx][idx%num_efx] != val) {
657 mix->send_volume[idx/num_efx][idx%num_efx] = val;
658 change = 1;
659 }
660 }
661 if (change && mix->epcm) {
662 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
663 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
664 &mix->send_volume[1][0]);
665 update_emu10k1_send_volume(emu, mix->epcm->voices[1]->number,
666 &mix->send_volume[2][0]);
667 } else if (mix->epcm->voices[0]) {
668 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
669 &mix->send_volume[0][0]);
670 }
671 }
672 spin_unlock_irqrestore(&emu->reg_lock, flags);
673 return change;
674}
675
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100676static struct snd_kcontrol_new snd_emu10k1_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677{
678 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +0200679 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 .name = "EMU10K1 PCM Send Volume",
681 .count = 32,
682 .info = snd_emu10k1_send_volume_info,
683 .get = snd_emu10k1_send_volume_get,
684 .put = snd_emu10k1_send_volume_put
685};
686
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100687static int snd_emu10k1_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688{
689 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
690 uinfo->count = 3;
691 uinfo->value.integer.min = 0;
692 uinfo->value.integer.max = 0xffff;
693 return 0;
694}
695
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100696static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol,
697 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100699 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
700 struct snd_emu10k1_pcm_mixer *mix =
701 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 unsigned long flags;
703 int idx;
704
705 spin_lock_irqsave(&emu->reg_lock, flags);
706 for (idx = 0; idx < 3; idx++)
707 ucontrol->value.integer.value[idx] = mix->attn[idx];
708 spin_unlock_irqrestore(&emu->reg_lock, flags);
709 return 0;
710}
711
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100712static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol,
713 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714{
715 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100716 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
717 struct snd_emu10k1_pcm_mixer *mix =
718 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 int change = 0, idx, val;
720
721 spin_lock_irqsave(&emu->reg_lock, flags);
722 for (idx = 0; idx < 3; idx++) {
723 val = ucontrol->value.integer.value[idx] & 0xffff;
724 if (mix->attn[idx] != val) {
725 mix->attn[idx] = val;
726 change = 1;
727 }
728 }
729 if (change && mix->epcm) {
730 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
731 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[1]);
732 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[1]->number, mix->attn[2]);
733 } else if (mix->epcm->voices[0]) {
734 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]);
735 }
736 }
737 spin_unlock_irqrestore(&emu->reg_lock, flags);
738 return change;
739}
740
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100741static struct snd_kcontrol_new snd_emu10k1_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742{
743 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +0200744 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745 .name = "EMU10K1 PCM Volume",
746 .count = 32,
747 .info = snd_emu10k1_attn_info,
748 .get = snd_emu10k1_attn_get,
749 .put = snd_emu10k1_attn_put
750};
751
752/* Mutichannel PCM stream controls */
753
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100754static int snd_emu10k1_efx_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100756 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
758 uinfo->count = emu->audigy ? 8 : 4;
759 uinfo->value.integer.min = 0;
760 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
761 return 0;
762}
763
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100764static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol,
765 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766{
767 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100768 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
769 struct snd_emu10k1_pcm_mixer *mix =
770 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 int idx;
772 int num_efx = emu->audigy ? 8 : 4;
773 int mask = emu->audigy ? 0x3f : 0x0f;
774
775 spin_lock_irqsave(&emu->reg_lock, flags);
776 for (idx = 0; idx < num_efx; idx++)
777 ucontrol->value.integer.value[idx] =
778 mix->send_routing[0][idx] & mask;
779 spin_unlock_irqrestore(&emu->reg_lock, flags);
780 return 0;
781}
782
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100783static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol,
784 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785{
786 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100787 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100789 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 int change = 0, idx, val;
791 int num_efx = emu->audigy ? 8 : 4;
792 int mask = emu->audigy ? 0x3f : 0x0f;
793
794 spin_lock_irqsave(&emu->reg_lock, flags);
795 for (idx = 0; idx < num_efx; idx++) {
796 val = ucontrol->value.integer.value[idx] & mask;
797 if (mix->send_routing[0][idx] != val) {
798 mix->send_routing[0][idx] = val;
799 change = 1;
800 }
801 }
802
803 if (change && mix->epcm) {
804 if (mix->epcm->voices[ch]) {
805 update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number,
806 &mix->send_routing[0][0]);
807 }
808 }
809 spin_unlock_irqrestore(&emu->reg_lock, flags);
810 return change;
811}
812
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100813static struct snd_kcontrol_new snd_emu10k1_efx_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814{
815 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
816 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
817 .name = "Multichannel PCM Send Routing",
818 .count = 16,
819 .info = snd_emu10k1_efx_send_routing_info,
820 .get = snd_emu10k1_efx_send_routing_get,
821 .put = snd_emu10k1_efx_send_routing_put
822};
823
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100824static int snd_emu10k1_efx_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100826 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
828 uinfo->count = emu->audigy ? 8 : 4;
829 uinfo->value.integer.min = 0;
830 uinfo->value.integer.max = 255;
831 return 0;
832}
833
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100834static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol,
835 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836{
837 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100838 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
839 struct snd_emu10k1_pcm_mixer *mix =
840 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 int idx;
842 int num_efx = emu->audigy ? 8 : 4;
843
844 spin_lock_irqsave(&emu->reg_lock, flags);
845 for (idx = 0; idx < num_efx; idx++)
846 ucontrol->value.integer.value[idx] = mix->send_volume[0][idx];
847 spin_unlock_irqrestore(&emu->reg_lock, flags);
848 return 0;
849}
850
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100851static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol,
852 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853{
854 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100855 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100857 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 int change = 0, idx, val;
859 int num_efx = emu->audigy ? 8 : 4;
860
861 spin_lock_irqsave(&emu->reg_lock, flags);
862 for (idx = 0; idx < num_efx; idx++) {
863 val = ucontrol->value.integer.value[idx] & 255;
864 if (mix->send_volume[0][idx] != val) {
865 mix->send_volume[0][idx] = val;
866 change = 1;
867 }
868 }
869 if (change && mix->epcm) {
870 if (mix->epcm->voices[ch]) {
871 update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number,
872 &mix->send_volume[0][0]);
873 }
874 }
875 spin_unlock_irqrestore(&emu->reg_lock, flags);
876 return change;
877}
878
879
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100880static struct snd_kcontrol_new snd_emu10k1_efx_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881{
882 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
883 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
884 .name = "Multichannel PCM Send Volume",
885 .count = 16,
886 .info = snd_emu10k1_efx_send_volume_info,
887 .get = snd_emu10k1_efx_send_volume_get,
888 .put = snd_emu10k1_efx_send_volume_put
889};
890
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100891static int snd_emu10k1_efx_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892{
893 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
894 uinfo->count = 1;
895 uinfo->value.integer.min = 0;
896 uinfo->value.integer.max = 0xffff;
897 return 0;
898}
899
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100900static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol,
901 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100903 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
904 struct snd_emu10k1_pcm_mixer *mix =
905 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 unsigned long flags;
907
908 spin_lock_irqsave(&emu->reg_lock, flags);
909 ucontrol->value.integer.value[0] = mix->attn[0];
910 spin_unlock_irqrestore(&emu->reg_lock, flags);
911 return 0;
912}
913
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100914static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol,
915 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916{
917 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100918 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100920 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 int change = 0, val;
922
923 spin_lock_irqsave(&emu->reg_lock, flags);
924 val = ucontrol->value.integer.value[0] & 0xffff;
925 if (mix->attn[0] != val) {
926 mix->attn[0] = val;
927 change = 1;
928 }
929 if (change && mix->epcm) {
930 if (mix->epcm->voices[ch]) {
931 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]);
932 }
933 }
934 spin_unlock_irqrestore(&emu->reg_lock, flags);
935 return change;
936}
937
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100938static struct snd_kcontrol_new snd_emu10k1_efx_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939{
940 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
941 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
942 .name = "Multichannel PCM Volume",
943 .count = 16,
944 .info = snd_emu10k1_efx_attn_info,
945 .get = snd_emu10k1_efx_attn_get,
946 .put = snd_emu10k1_efx_attn_put
947};
948
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100949static int snd_emu10k1_shared_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950{
951 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
952 uinfo->count = 1;
953 uinfo->value.integer.min = 0;
954 uinfo->value.integer.max = 1;
955 return 0;
956}
957
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100958static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol,
959 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100961 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962
963 if (emu->audigy)
964 ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0;
965 else
966 ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0;
967 return 0;
968}
969
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100970static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
971 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972{
973 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100974 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 unsigned int reg, val;
976 int change = 0;
977
978 spin_lock_irqsave(&emu->reg_lock, flags);
979 if (emu->audigy) {
980 reg = inl(emu->port + A_IOCFG);
981 val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0;
982 change = (reg & A_IOCFG_GPOUT0) != val;
983 if (change) {
984 reg &= ~A_IOCFG_GPOUT0;
985 reg |= val;
986 outl(reg | val, emu->port + A_IOCFG);
987 }
988 }
989 reg = inl(emu->port + HCFG);
990 val = ucontrol->value.integer.value[0] ? HCFG_GPOUT0 : 0;
991 change |= (reg & HCFG_GPOUT0) != val;
992 if (change) {
993 reg &= ~HCFG_GPOUT0;
994 reg |= val;
995 outl(reg | val, emu->port + HCFG);
996 }
997 spin_unlock_irqrestore(&emu->reg_lock, flags);
998 return change;
999}
1000
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001001static struct snd_kcontrol_new snd_emu10k1_shared_spdif __devinitdata =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002{
1003 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1004 .name = "SB Live Analog/Digital Output Jack",
1005 .info = snd_emu10k1_shared_spdif_info,
1006 .get = snd_emu10k1_shared_spdif_get,
1007 .put = snd_emu10k1_shared_spdif_put
1008};
1009
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001010static struct snd_kcontrol_new snd_audigy_shared_spdif __devinitdata =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011{
1012 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1013 .name = "Audigy Analog/Digital Output Jack",
1014 .info = snd_emu10k1_shared_spdif_info,
1015 .get = snd_emu10k1_shared_spdif_get,
1016 .put = snd_emu10k1_shared_spdif_put
1017};
1018
1019/*
1020 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001021static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001023 struct snd_emu10k1 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 emu->ac97 = NULL;
1025}
1026
1027/*
1028 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001029static int remove_ctl(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001031 struct snd_ctl_elem_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 memset(&id, 0, sizeof(id));
1033 strcpy(id.name, name);
1034 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1035 return snd_ctl_remove_id(card, &id);
1036}
1037
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001038static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001040 struct snd_ctl_elem_id sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 memset(&sid, 0, sizeof(sid));
1042 strcpy(sid.name, name);
1043 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1044 return snd_ctl_find_id(card, &sid);
1045}
1046
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001047static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001049 struct snd_kcontrol *kctl = ctl_find(card, src);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 if (kctl) {
1051 strcpy(kctl->id.name, dst);
1052 return 0;
1053 }
1054 return -ENOENT;
1055}
1056
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001057int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001058 int pcm_device, int multi_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059{
1060 int err, pcm;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001061 struct snd_kcontrol *kctl;
1062 struct snd_card *card = emu->card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 char **c;
1064 static char *emu10k1_remove_ctls[] = {
1065 /* no AC97 mono, surround, center/lfe */
1066 "Master Mono Playback Switch",
1067 "Master Mono Playback Volume",
1068 "PCM Out Path & Mute",
1069 "Mono Output Select",
Takashi Iwai7eae36f2006-01-05 18:40:56 +01001070 "Front Playback Switch",
1071 "Front Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 "Surround Playback Switch",
1073 "Surround Playback Volume",
1074 "Center Playback Switch",
1075 "Center Playback Volume",
1076 "LFE Playback Switch",
1077 "LFE Playback Volume",
1078 NULL
1079 };
1080 static char *emu10k1_rename_ctls[] = {
1081 "Surround Digital Playback Volume", "Surround Playback Volume",
1082 "Center Digital Playback Volume", "Center Playback Volume",
1083 "LFE Digital Playback Volume", "LFE Playback Volume",
1084 NULL
1085 };
1086 static char *audigy_remove_ctls[] = {
1087 /* Master/PCM controls on ac97 of Audigy has no effect */
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001088 /* On the Audigy2 the AC97 playback is piped into
1089 * the Philips ADC for 24bit capture */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 "PCM Playback Switch",
1091 "PCM Playback Volume",
1092 "Master Mono Playback Switch",
1093 "Master Mono Playback Volume",
1094 "Master Playback Switch",
1095 "Master Playback Volume",
1096 "PCM Out Path & Mute",
1097 "Mono Output Select",
1098 /* remove unused AC97 capture controls */
1099 "Capture Source",
1100 "Capture Switch",
1101 "Capture Volume",
1102 "Mic Select",
1103 "Video Playback Switch",
1104 "Video Playback Volume",
1105 "Mic Playback Switch",
1106 "Mic Playback Volume",
1107 NULL
1108 };
1109 static char *audigy_rename_ctls[] = {
1110 /* use conventional names */
1111 "Wave Playback Volume", "PCM Playback Volume",
1112 /* "Wave Capture Volume", "PCM Capture Volume", */
1113 "Wave Master Playback Volume", "Master Playback Volume",
1114 "AMic Playback Volume", "Mic Playback Volume",
1115 NULL
1116 };
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001117 static char *audigy_remove_ctls_1361t_adc[] = {
1118 /* On the Audigy2 the AC97 playback is piped into
1119 * the Philips ADC for 24bit capture */
1120 "PCM Playback Switch",
1121 "PCM Playback Volume",
1122 "Master Mono Playback Switch",
1123 "Master Mono Playback Volume",
1124 "Capture Source",
1125 "Capture Switch",
1126 "Capture Volume",
1127 "Mic Capture Volume",
1128 "Headphone Playback Switch",
1129 "Headphone Playback Volume",
1130 "3D Control - Center",
1131 "3D Control - Depth",
1132 "3D Control - Switch",
1133 "Line2 Playback Volume",
1134 "Line2 Capture Volume",
1135 NULL
1136 };
1137 static char *audigy_rename_ctls_1361t_adc[] = {
1138 "Master Playback Switch", "Master Capture Switch",
1139 "Master Playback Volume", "Master Capture Volume",
1140 "Wave Master Playback Volume", "Master Playback Volume",
1141 "PC Speaker Playback Switch", "PC Speaker Capture Switch",
1142 "PC Speaker Playback Volume", "PC Speaker Capture Volume",
1143 "Phone Playback Switch", "Phone Capture Switch",
1144 "Phone Playback Volume", "Phone Capture Volume",
1145 "Mic Playback Switch", "Mic Capture Switch",
1146 "Mic Playback Volume", "Mic Capture Volume",
1147 "Line Playback Switch", "Line Capture Switch",
1148 "Line Playback Volume", "Line Capture Volume",
1149 "CD Playback Switch", "CD Capture Switch",
1150 "CD Playback Volume", "CD Capture Volume",
1151 "Aux Playback Switch", "Aux Capture Switch",
1152 "Aux Playback Volume", "Aux Capture Volume",
1153 "Video Playback Switch", "Video Capture Switch",
1154 "Video Playback Volume", "Video Capture Volume",
1155
1156 NULL
1157 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158
Lee Revell2b637da2005-03-30 13:51:18 +02001159 if (emu->card_capabilities->ac97_chip) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001160 struct snd_ac97_bus *pbus;
1161 struct snd_ac97_template ac97;
1162 static struct snd_ac97_bus_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 .write = snd_emu10k1_ac97_write,
1164 .read = snd_emu10k1_ac97_read,
1165 };
1166
Takashi Iwaib1508692005-10-04 13:49:32 +02001167 if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0)
1168 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 pbus->no_vra = 1; /* we don't need VRA */
1170
1171 memset(&ac97, 0, sizeof(ac97));
1172 ac97.private_data = emu;
1173 ac97.private_free = snd_emu10k1_mixer_free_ac97;
1174 ac97.scaps = AC97_SCAP_NO_SPDIF;
Takashi Iwaib1508692005-10-04 13:49:32 +02001175 if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) {
1176 if (emu->card_capabilities->ac97_chip == 1)
1177 return err;
1178 snd_printd(KERN_INFO "emu10k1: AC97 is optional on this board\n");
1179 snd_printd(KERN_INFO" Proceeding without ac97 mixers...\n");
1180 snd_device_free(emu->card, pbus);
1181 goto no_ac97; /* FIXME: get rid of ugly gotos.. */
1182 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 if (emu->audigy) {
1184 /* set master volume to 0 dB */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001185 snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 /* set capture source to mic */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001187 snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001188 if (emu->card_capabilities->adc_1361t)
1189 c = audigy_remove_ctls_1361t_adc;
1190 else
1191 c = audigy_remove_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 } else {
1193 /*
1194 * Credits for cards based on STAC9758:
1195 * James Courtier-Dutton <James@superbug.demon.co.uk>
1196 * Voluspa <voluspa@comhem.se>
1197 */
1198 if (emu->ac97->id == AC97_ID_STAC9758) {
1199 emu->rear_ac97 = 1;
1200 snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT);
1201 }
1202 /* remove unused AC97 controls */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001203 snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
1204 snd_ac97_write_cache(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 c = emu10k1_remove_ctls;
1206 }
1207 for (; *c; c++)
1208 remove_ctl(card, *c);
1209 } else {
Takashi Iwaif12aa402005-09-30 16:56:59 +02001210 no_ac97:
Lee Revell2b637da2005-03-30 13:51:18 +02001211 if (emu->card_capabilities->ecard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 strcpy(emu->card->mixername, "EMU APS");
1213 else if (emu->audigy)
1214 strcpy(emu->card->mixername, "SB Audigy");
1215 else
1216 strcpy(emu->card->mixername, "Emu10k1");
1217 }
1218
1219 if (emu->audigy)
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001220 if (emu->card_capabilities->adc_1361t)
1221 c = audigy_rename_ctls_1361t_adc;
1222 else
1223 c = audigy_rename_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 else
1225 c = emu10k1_rename_ctls;
1226 for (; *c; c += 2)
1227 rename_ctl(card, c[0], c[1]);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001228
James Courtier-Duttone3b9bc02005-12-24 16:54:51 +01001229 if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */
1230 rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume");
1231 rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume");
1232 rename_ctl(card, "Aux2 Capture Volume", "Line3 Capture Volume");
1233 rename_ctl(card, "Mic Capture Volume", "Unknown1 Capture Volume");
1234 remove_ctl(card, "Headphone Playback Switch");
1235 remove_ctl(card, "Headphone Playback Volume");
1236 remove_ctl(card, "3D Control - Center");
1237 remove_ctl(card, "3D Control - Depth");
1238 remove_ctl(card, "3D Control - Switch");
1239 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL)
1241 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001242 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 if ((err = snd_ctl_add(card, kctl)))
1244 return err;
1245 if ((kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL)
1246 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001247 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 if ((err = snd_ctl_add(card, kctl)))
1249 return err;
1250 if ((kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu)) == NULL)
1251 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001252 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 if ((err = snd_ctl_add(card, kctl)))
1254 return err;
1255
1256 if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL)
1257 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001258 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 if ((err = snd_ctl_add(card, kctl)))
1260 return err;
1261
1262 if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL)
1263 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001264 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 if ((err = snd_ctl_add(card, kctl)))
1266 return err;
1267
1268 if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL)
1269 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001270 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 if ((err = snd_ctl_add(card, kctl)))
1272 return err;
1273
1274 /* initialize the routing and volume table for each pcm playback stream */
1275 for (pcm = 0; pcm < 32; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001276 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 int v;
1278
1279 mix = &emu->pcm_mixer[pcm];
1280 mix->epcm = NULL;
1281
1282 for (v = 0; v < 4; v++)
1283 mix->send_routing[0][v] =
1284 mix->send_routing[1][v] =
1285 mix->send_routing[2][v] = v;
1286
1287 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1288 mix->send_volume[0][0] = mix->send_volume[0][1] =
1289 mix->send_volume[1][0] = mix->send_volume[2][1] = 255;
1290
1291 mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
1292 }
1293
1294 /* initialize the routing and volume table for the multichannel playback stream */
1295 for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001296 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 int v;
1298
1299 mix = &emu->efx_pcm_mixer[pcm];
1300 mix->epcm = NULL;
1301
1302 mix->send_routing[0][0] = pcm;
1303 mix->send_routing[0][1] = (pcm == 0) ? 1 : 0;
1304 for (v = 0; v < 2; v++)
1305 mix->send_routing[0][2+v] = 13+v;
1306 if (emu->audigy)
1307 for (v = 0; v < 4; v++)
1308 mix->send_routing[0][4+v] = 60+v;
1309
1310 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1311 mix->send_volume[0][0] = 255;
1312
1313 mix->attn[0] = 0xffff;
1314 }
1315
Lee Revell2b637da2005-03-30 13:51:18 +02001316 if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 /* sb live! and audigy */
1318 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
1319 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02001320 if (!emu->audigy)
1321 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 if ((err = snd_ctl_add(card, kctl)))
1323 return err;
1324 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
1325 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02001326 if (!emu->audigy)
1327 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 if ((err = snd_ctl_add(card, kctl)))
1329 return err;
1330 }
1331
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001332 if ( emu->card_capabilities->emu1010) {
James Courtier-Dutton19b99fb2005-12-04 18:03:03 +01001333 ; /* Disable the snd_audigy_spdif_shared_spdif */
1334 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
1336 return -ENOMEM;
1337 if ((err = snd_ctl_add(card, kctl)))
1338 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02001339#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
1341 return -ENOMEM;
1342 if ((err = snd_ctl_add(card, kctl)))
1343 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02001344#endif
Lee Revell2b637da2005-03-30 13:51:18 +02001345 } else if (! emu->card_capabilities->ecard) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 /* sb live! */
1347 if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
1348 return -ENOMEM;
1349 if ((err = snd_ctl_add(card, kctl)))
1350 return err;
1351 }
Lee Revell2b637da2005-03-30 13:51:18 +02001352 if (emu->card_capabilities->ca0151_chip) { /* P16V */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 if ((err = snd_p16v_mixer(emu)))
1354 return err;
1355 }
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001356
1357 if ( emu->card_capabilities->emu1010) {
1358 int i;
1359
1360 for (i = 0; i < ARRAY_SIZE(snd_emu1010_output_enum_ctls); i++) {
1361 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_output_enum_ctls[i], emu));
1362 if (err < 0)
1363 return err;
1364 }
1365 for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) {
1366 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], emu));
1367 if (err < 0)
1368 return err;
1369 }
1370 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
1372 return 0;
1373}