blob: 2edf92a4f0650e8e449d1e6c3a36f08d56924590 [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 = {
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100318 EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Switch", 0),
319 EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Switch", 1),
320 EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Switch", 2),
321 EMU1010_SOURCE_OUTPUT("Dock DAC2 Right Playback Switch", 3),
322 EMU1010_SOURCE_OUTPUT("Dock DAC3 Left Playback Switch", 4),
323 EMU1010_SOURCE_OUTPUT("Dock DAC3 Right Playback Switch", 5),
324 EMU1010_SOURCE_OUTPUT("Dock DAC4 Left Playback Switch", 6),
325 EMU1010_SOURCE_OUTPUT("Dock DAC4 Right Playback Switch", 7),
326 EMU1010_SOURCE_OUTPUT("Dock Phones Left Playback Switch", 8),
327 EMU1010_SOURCE_OUTPUT("Dock Phones Right Playback Switch", 9),
328 EMU1010_SOURCE_OUTPUT("Dock SPDIF Left Playback Switch", 0xa),
329 EMU1010_SOURCE_OUTPUT("Dock SPDIF Right Playback Switch", 0xb),
330 EMU1010_SOURCE_OUTPUT("1010 SPDIF Left Playback Switch", 0xc),
331 EMU1010_SOURCE_OUTPUT("1010 SPDIF Right Playback Switch", 0xd),
332 EMU1010_SOURCE_OUTPUT("0202 DAC Left Playback Switch", 0xe),
333 EMU1010_SOURCE_OUTPUT("0202 DAC Right Playback Switch", 0xf),
334 EMU1010_SOURCE_OUTPUT("1010 ADAT 0 Playback Switch", 0x10),
335 EMU1010_SOURCE_OUTPUT("1010 ADAT 1 Playback Switch", 0x11),
336 EMU1010_SOURCE_OUTPUT("1010 ADAT 2 Playback Switch", 0x12),
337 EMU1010_SOURCE_OUTPUT("1010 ADAT 3 Playback Switch", 0x13),
338 EMU1010_SOURCE_OUTPUT("1010 ADAT 4 Playback Switch", 0x14),
339 EMU1010_SOURCE_OUTPUT("1010 ADAT 5 Playback Switch", 0x15),
340 EMU1010_SOURCE_OUTPUT("1010 ADAT 6 Playback Switch", 0x16),
341 EMU1010_SOURCE_OUTPUT("1010 ADAT 7 Playback Switch", 0x17),
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100342};
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 = {
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100355 EMU1010_SOURCE_INPUT("DSP 0 Capture Switch", 0),
356 EMU1010_SOURCE_INPUT("DSP 1 Capture Switch", 1),
357 EMU1010_SOURCE_INPUT("DSP 2 Capture Switch", 2),
358 EMU1010_SOURCE_INPUT("DSP 3 Capture Switch", 3),
359 EMU1010_SOURCE_INPUT("DSP 4 Capture Switch", 4),
360 EMU1010_SOURCE_INPUT("DSP 5 Capture Switch", 5),
361 EMU1010_SOURCE_INPUT("DSP 6 Capture Switch", 6),
362 EMU1010_SOURCE_INPUT("DSP 7 Capture Switch", 7),
363 EMU1010_SOURCE_INPUT("DSP 8 Capture Switch", 8),
364 EMU1010_SOURCE_INPUT("DSP 9 Capture Switch", 9),
365 EMU1010_SOURCE_INPUT("DSP A Capture Switch", 0xa),
366 EMU1010_SOURCE_INPUT("DSP B Capture Switch", 0xb),
367 EMU1010_SOURCE_INPUT("DSP C Capture Switch", 0xc),
368 EMU1010_SOURCE_INPUT("DSP D Capture Switch", 0xd),
369 EMU1010_SOURCE_INPUT("DSP E Capture Switch", 0xe),
370 EMU1010_SOURCE_INPUT("DSP F Capture Switch", 0xf),
371 EMU1010_SOURCE_INPUT("DSP 10 Capture Switch", 0x10),
372 EMU1010_SOURCE_INPUT("DSP 11 Capture Switch", 0x11),
373 EMU1010_SOURCE_INPUT("DSP 12 Capture Switch", 0x12),
374 EMU1010_SOURCE_INPUT("DSP 13 Capture Switch", 0x13),
375 EMU1010_SOURCE_INPUT("DSP 14 Capture Switch", 0x14),
376 EMU1010_SOURCE_INPUT("DSP 15 Capture Switch", 0x15),
377};
378
379
380
381
382static int snd_emu1010_adc_pads_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
383{
384 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
385 uinfo->count = 1;
386 uinfo->value.integer.min = 0;
387 uinfo->value.integer.max = 1;
388 return 0;
389}
390
391static int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
392{
393 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
394 unsigned int mask = kcontrol->private_value & 0xff;
395 ucontrol->value.integer.value[0] = (emu->emu1010.adc_pads & mask) ? 1 : 0;
396 return 0;
397}
398
399static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
400{
401 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
402 unsigned int mask = kcontrol->private_value & 0xff;
403 unsigned int val, cache;
404 val = ucontrol->value.integer.value[0];
405 cache = emu->emu1010.adc_pads;
406 if (val == 1)
407 cache = cache | mask;
408 else
409 cache = cache & ~mask;
410 if (cache != emu->emu1010.adc_pads) {
411 snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache );
412 emu->emu1010.adc_pads = cache;
413 }
414
415 return 0;
416}
417
418
419
420#define EMU1010_ADC_PADS(xname,chid) \
421{ \
422 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
423 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
424 .info = snd_emu1010_adc_pads_info, \
425 .get = snd_emu1010_adc_pads_get, \
426 .put = snd_emu1010_adc_pads_put, \
427 .private_value = chid \
428}
429
430static struct snd_kcontrol_new snd_emu1010_adc_pads[] __devinitdata = {
431 EMU1010_ADC_PADS("ADC1 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD1),
432 EMU1010_ADC_PADS("ADC2 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD2),
433 EMU1010_ADC_PADS("ADC3 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD3),
434 EMU1010_ADC_PADS("ADC1 14dB PAD 0202 Capture Switch", EMU_HANA_0202_ADC_PAD1),
435};
436
437static int snd_emu1010_dac_pads_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
438{
439 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
440 uinfo->count = 1;
441 uinfo->value.integer.min = 0;
442 uinfo->value.integer.max = 1;
443 return 0;
444}
445
446static int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
447{
448 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
449 unsigned int mask = kcontrol->private_value & 0xff;
450 ucontrol->value.integer.value[0] = (emu->emu1010.dac_pads & mask) ? 1 : 0;
451 return 0;
452}
453
454static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
455{
456 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
457 unsigned int mask = kcontrol->private_value & 0xff;
458 unsigned int val, cache;
459 val = ucontrol->value.integer.value[0];
460 cache = emu->emu1010.dac_pads;
461 if (val == 1)
462 cache = cache | mask;
463 else
464 cache = cache & ~mask;
465 if (cache != emu->emu1010.dac_pads) {
466 snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache );
467 emu->emu1010.dac_pads = cache;
468 }
469
470 return 0;
471}
472
473
474
475#define EMU1010_DAC_PADS(xname,chid) \
476{ \
477 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
478 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
479 .info = snd_emu1010_dac_pads_info, \
480 .get = snd_emu1010_dac_pads_get, \
481 .put = snd_emu1010_dac_pads_put, \
482 .private_value = chid \
483}
484
485static struct snd_kcontrol_new snd_emu1010_dac_pads[] __devinitdata = {
486 EMU1010_DAC_PADS("DAC1 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD1),
487 EMU1010_DAC_PADS("DAC2 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD2),
488 EMU1010_DAC_PADS("DAC3 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD3),
489 EMU1010_DAC_PADS("DAC4 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD4),
490 EMU1010_DAC_PADS("DAC1 0202 14dB PAD Playback Switch", EMU_HANA_0202_DAC_PAD1),
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100491};
492
Takashi Iwai0af68e52005-04-11 17:03:03 +0200493#if 0
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100494static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495{
496 static char *texts[] = {"44100", "48000", "96000"};
497
498 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
499 uinfo->count = 1;
500 uinfo->value.enumerated.items = 3;
501 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
502 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
503 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
504 return 0;
505}
506
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100507static int snd_audigy_spdif_output_rate_get(struct snd_kcontrol *kcontrol,
508 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100510 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 unsigned int tmp;
512 unsigned long flags;
513
514
515 spin_lock_irqsave(&emu->reg_lock, flags);
516 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
517 switch (tmp & A_SPDIF_RATE_MASK) {
518 case A_SPDIF_44100:
519 ucontrol->value.enumerated.item[0] = 0;
520 break;
521 case A_SPDIF_48000:
522 ucontrol->value.enumerated.item[0] = 1;
523 break;
524 case A_SPDIF_96000:
525 ucontrol->value.enumerated.item[0] = 2;
526 break;
527 default:
528 ucontrol->value.enumerated.item[0] = 1;
529 }
530 spin_unlock_irqrestore(&emu->reg_lock, flags);
531 return 0;
532}
533
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100534static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol,
535 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100537 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 int change;
539 unsigned int reg, val, tmp;
540 unsigned long flags;
541
542 switch(ucontrol->value.enumerated.item[0]) {
543 case 0:
544 val = A_SPDIF_44100;
545 break;
546 case 1:
547 val = A_SPDIF_48000;
548 break;
549 case 2:
550 val = A_SPDIF_96000;
551 break;
552 default:
553 val = A_SPDIF_48000;
554 break;
555 }
556
557
558 spin_lock_irqsave(&emu->reg_lock, flags);
559 reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
560 tmp = reg & ~A_SPDIF_RATE_MASK;
561 tmp |= val;
562 if ((change = (tmp != reg)))
563 snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
564 spin_unlock_irqrestore(&emu->reg_lock, flags);
565 return change;
566}
567
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100568static struct snd_kcontrol_new snd_audigy_spdif_output_rate =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569{
570 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
571 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
572 .name = "Audigy SPDIF Output Sample Rate",
573 .count = 1,
574 .info = snd_audigy_spdif_output_rate_info,
575 .get = snd_audigy_spdif_output_rate_get,
576 .put = snd_audigy_spdif_output_rate_put
577};
Takashi Iwai0af68e52005-04-11 17:03:03 +0200578#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100580static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol,
581 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100583 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
585 int change;
586 unsigned int val;
587 unsigned long flags;
588
589 val = (ucontrol->value.iec958.status[0] << 0) |
590 (ucontrol->value.iec958.status[1] << 8) |
591 (ucontrol->value.iec958.status[2] << 16) |
592 (ucontrol->value.iec958.status[3] << 24);
593 spin_lock_irqsave(&emu->reg_lock, flags);
594 change = val != emu->spdif_bits[idx];
595 if (change) {
596 snd_emu10k1_ptr_write(emu, SPCS0 + idx, 0, val);
597 emu->spdif_bits[idx] = val;
598 }
599 spin_unlock_irqrestore(&emu->reg_lock, flags);
600 return change;
601}
602
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100603static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604{
605 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +0200606 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
608 .count = 4,
609 .info = snd_emu10k1_spdif_info,
610 .get = snd_emu10k1_spdif_get_mask
611};
612
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100613static struct snd_kcontrol_new snd_emu10k1_spdif_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614{
Clemens Ladisch5549d542005-08-03 13:50:30 +0200615 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
617 .count = 4,
618 .info = snd_emu10k1_spdif_info,
619 .get = snd_emu10k1_spdif_get,
620 .put = snd_emu10k1_spdif_put
621};
622
623
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100624static void update_emu10k1_fxrt(struct snd_emu10k1 *emu, int voice, unsigned char *route)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625{
626 if (emu->audigy) {
627 snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
628 snd_emu10k1_compose_audigy_fxrt1(route));
629 snd_emu10k1_ptr_write(emu, A_FXRT2, voice,
630 snd_emu10k1_compose_audigy_fxrt2(route));
631 } else {
632 snd_emu10k1_ptr_write(emu, FXRT, voice,
633 snd_emu10k1_compose_send_routing(route));
634 }
635}
636
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100637static void update_emu10k1_send_volume(struct snd_emu10k1 *emu, int voice, unsigned char *volume)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638{
639 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]);
640 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]);
641 snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, volume[2]);
642 snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, volume[3]);
643 if (emu->audigy) {
644 unsigned int val = ((unsigned int)volume[4] << 24) |
645 ((unsigned int)volume[5] << 16) |
646 ((unsigned int)volume[6] << 8) |
647 (unsigned int)volume[7];
648 snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, val);
649 }
650}
651
652/* PCM stream controls */
653
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100654static int snd_emu10k1_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100656 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
658 uinfo->count = emu->audigy ? 3*8 : 3*4;
659 uinfo->value.integer.min = 0;
660 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
661 return 0;
662}
663
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100664static int snd_emu10k1_send_routing_get(struct snd_kcontrol *kcontrol,
665 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666{
667 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100668 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
669 struct snd_emu10k1_pcm_mixer *mix =
670 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 int voice, idx;
672 int num_efx = emu->audigy ? 8 : 4;
673 int mask = emu->audigy ? 0x3f : 0x0f;
674
675 spin_lock_irqsave(&emu->reg_lock, flags);
676 for (voice = 0; voice < 3; voice++)
677 for (idx = 0; idx < num_efx; idx++)
678 ucontrol->value.integer.value[(voice * num_efx) + idx] =
679 mix->send_routing[voice][idx] & mask;
680 spin_unlock_irqrestore(&emu->reg_lock, flags);
681 return 0;
682}
683
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100684static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol,
685 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686{
687 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100688 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
689 struct snd_emu10k1_pcm_mixer *mix =
690 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 int change = 0, voice, idx, val;
692 int num_efx = emu->audigy ? 8 : 4;
693 int mask = emu->audigy ? 0x3f : 0x0f;
694
695 spin_lock_irqsave(&emu->reg_lock, flags);
696 for (voice = 0; voice < 3; voice++)
697 for (idx = 0; idx < num_efx; idx++) {
698 val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask;
699 if (mix->send_routing[voice][idx] != val) {
700 mix->send_routing[voice][idx] = val;
701 change = 1;
702 }
703 }
704 if (change && mix->epcm) {
705 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
706 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
707 &mix->send_routing[1][0]);
708 update_emu10k1_fxrt(emu, mix->epcm->voices[1]->number,
709 &mix->send_routing[2][0]);
710 } else if (mix->epcm->voices[0]) {
711 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
712 &mix->send_routing[0][0]);
713 }
714 }
715 spin_unlock_irqrestore(&emu->reg_lock, flags);
716 return change;
717}
718
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100719static struct snd_kcontrol_new snd_emu10k1_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720{
721 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +0200722 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 .name = "EMU10K1 PCM Send Routing",
724 .count = 32,
725 .info = snd_emu10k1_send_routing_info,
726 .get = snd_emu10k1_send_routing_get,
727 .put = snd_emu10k1_send_routing_put
728};
729
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100730static int snd_emu10k1_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100732 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
734 uinfo->count = emu->audigy ? 3*8 : 3*4;
735 uinfo->value.integer.min = 0;
736 uinfo->value.integer.max = 255;
737 return 0;
738}
739
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100740static int snd_emu10k1_send_volume_get(struct snd_kcontrol *kcontrol,
741 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742{
743 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100744 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
745 struct snd_emu10k1_pcm_mixer *mix =
746 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747 int idx;
748 int num_efx = emu->audigy ? 8 : 4;
749
750 spin_lock_irqsave(&emu->reg_lock, flags);
751 for (idx = 0; idx < 3*num_efx; idx++)
752 ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx];
753 spin_unlock_irqrestore(&emu->reg_lock, flags);
754 return 0;
755}
756
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100757static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol,
758 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759{
760 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100761 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
762 struct snd_emu10k1_pcm_mixer *mix =
763 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 int change = 0, idx, val;
765 int num_efx = emu->audigy ? 8 : 4;
766
767 spin_lock_irqsave(&emu->reg_lock, flags);
768 for (idx = 0; idx < 3*num_efx; idx++) {
769 val = ucontrol->value.integer.value[idx] & 255;
770 if (mix->send_volume[idx/num_efx][idx%num_efx] != val) {
771 mix->send_volume[idx/num_efx][idx%num_efx] = val;
772 change = 1;
773 }
774 }
775 if (change && mix->epcm) {
776 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
777 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
778 &mix->send_volume[1][0]);
779 update_emu10k1_send_volume(emu, mix->epcm->voices[1]->number,
780 &mix->send_volume[2][0]);
781 } else if (mix->epcm->voices[0]) {
782 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
783 &mix->send_volume[0][0]);
784 }
785 }
786 spin_unlock_irqrestore(&emu->reg_lock, flags);
787 return change;
788}
789
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100790static struct snd_kcontrol_new snd_emu10k1_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791{
792 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +0200793 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794 .name = "EMU10K1 PCM Send Volume",
795 .count = 32,
796 .info = snd_emu10k1_send_volume_info,
797 .get = snd_emu10k1_send_volume_get,
798 .put = snd_emu10k1_send_volume_put
799};
800
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100801static int snd_emu10k1_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802{
803 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
804 uinfo->count = 3;
805 uinfo->value.integer.min = 0;
806 uinfo->value.integer.max = 0xffff;
807 return 0;
808}
809
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100810static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol,
811 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100813 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
814 struct snd_emu10k1_pcm_mixer *mix =
815 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 unsigned long flags;
817 int idx;
818
819 spin_lock_irqsave(&emu->reg_lock, flags);
820 for (idx = 0; idx < 3; idx++)
821 ucontrol->value.integer.value[idx] = mix->attn[idx];
822 spin_unlock_irqrestore(&emu->reg_lock, flags);
823 return 0;
824}
825
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100826static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol,
827 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828{
829 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100830 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
831 struct snd_emu10k1_pcm_mixer *mix =
832 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 int change = 0, idx, val;
834
835 spin_lock_irqsave(&emu->reg_lock, flags);
836 for (idx = 0; idx < 3; idx++) {
837 val = ucontrol->value.integer.value[idx] & 0xffff;
838 if (mix->attn[idx] != val) {
839 mix->attn[idx] = val;
840 change = 1;
841 }
842 }
843 if (change && mix->epcm) {
844 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
845 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[1]);
846 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[1]->number, mix->attn[2]);
847 } else if (mix->epcm->voices[0]) {
848 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]);
849 }
850 }
851 spin_unlock_irqrestore(&emu->reg_lock, flags);
852 return change;
853}
854
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100855static struct snd_kcontrol_new snd_emu10k1_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856{
857 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +0200858 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 .name = "EMU10K1 PCM Volume",
860 .count = 32,
861 .info = snd_emu10k1_attn_info,
862 .get = snd_emu10k1_attn_get,
863 .put = snd_emu10k1_attn_put
864};
865
866/* Mutichannel PCM stream controls */
867
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100868static int snd_emu10k1_efx_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100870 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
872 uinfo->count = emu->audigy ? 8 : 4;
873 uinfo->value.integer.min = 0;
874 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
875 return 0;
876}
877
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100878static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol,
879 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880{
881 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100882 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
883 struct snd_emu10k1_pcm_mixer *mix =
884 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 int idx;
886 int num_efx = emu->audigy ? 8 : 4;
887 int mask = emu->audigy ? 0x3f : 0x0f;
888
889 spin_lock_irqsave(&emu->reg_lock, flags);
890 for (idx = 0; idx < num_efx; idx++)
891 ucontrol->value.integer.value[idx] =
892 mix->send_routing[0][idx] & mask;
893 spin_unlock_irqrestore(&emu->reg_lock, flags);
894 return 0;
895}
896
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100897static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol,
898 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899{
900 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100901 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100903 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 int change = 0, idx, val;
905 int num_efx = emu->audigy ? 8 : 4;
906 int mask = emu->audigy ? 0x3f : 0x0f;
907
908 spin_lock_irqsave(&emu->reg_lock, flags);
909 for (idx = 0; idx < num_efx; idx++) {
910 val = ucontrol->value.integer.value[idx] & mask;
911 if (mix->send_routing[0][idx] != val) {
912 mix->send_routing[0][idx] = val;
913 change = 1;
914 }
915 }
916
917 if (change && mix->epcm) {
918 if (mix->epcm->voices[ch]) {
919 update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number,
920 &mix->send_routing[0][0]);
921 }
922 }
923 spin_unlock_irqrestore(&emu->reg_lock, flags);
924 return change;
925}
926
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100927static struct snd_kcontrol_new snd_emu10k1_efx_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928{
929 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
930 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
931 .name = "Multichannel PCM Send Routing",
932 .count = 16,
933 .info = snd_emu10k1_efx_send_routing_info,
934 .get = snd_emu10k1_efx_send_routing_get,
935 .put = snd_emu10k1_efx_send_routing_put
936};
937
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100938static int snd_emu10k1_efx_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100940 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
942 uinfo->count = emu->audigy ? 8 : 4;
943 uinfo->value.integer.min = 0;
944 uinfo->value.integer.max = 255;
945 return 0;
946}
947
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100948static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol,
949 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950{
951 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100952 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
953 struct snd_emu10k1_pcm_mixer *mix =
954 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 int idx;
956 int num_efx = emu->audigy ? 8 : 4;
957
958 spin_lock_irqsave(&emu->reg_lock, flags);
959 for (idx = 0; idx < num_efx; idx++)
960 ucontrol->value.integer.value[idx] = mix->send_volume[0][idx];
961 spin_unlock_irqrestore(&emu->reg_lock, flags);
962 return 0;
963}
964
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100965static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol,
966 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967{
968 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100969 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100971 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 int change = 0, idx, val;
973 int num_efx = emu->audigy ? 8 : 4;
974
975 spin_lock_irqsave(&emu->reg_lock, flags);
976 for (idx = 0; idx < num_efx; idx++) {
977 val = ucontrol->value.integer.value[idx] & 255;
978 if (mix->send_volume[0][idx] != val) {
979 mix->send_volume[0][idx] = val;
980 change = 1;
981 }
982 }
983 if (change && mix->epcm) {
984 if (mix->epcm->voices[ch]) {
985 update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number,
986 &mix->send_volume[0][0]);
987 }
988 }
989 spin_unlock_irqrestore(&emu->reg_lock, flags);
990 return change;
991}
992
993
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100994static struct snd_kcontrol_new snd_emu10k1_efx_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995{
996 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
997 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
998 .name = "Multichannel PCM Send Volume",
999 .count = 16,
1000 .info = snd_emu10k1_efx_send_volume_info,
1001 .get = snd_emu10k1_efx_send_volume_get,
1002 .put = snd_emu10k1_efx_send_volume_put
1003};
1004
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001005static int snd_emu10k1_efx_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006{
1007 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1008 uinfo->count = 1;
1009 uinfo->value.integer.min = 0;
1010 uinfo->value.integer.max = 0xffff;
1011 return 0;
1012}
1013
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001014static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol,
1015 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001017 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1018 struct snd_emu10k1_pcm_mixer *mix =
1019 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 unsigned long flags;
1021
1022 spin_lock_irqsave(&emu->reg_lock, flags);
1023 ucontrol->value.integer.value[0] = mix->attn[0];
1024 spin_unlock_irqrestore(&emu->reg_lock, flags);
1025 return 0;
1026}
1027
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001028static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol,
1029 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030{
1031 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001032 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001034 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 int change = 0, val;
1036
1037 spin_lock_irqsave(&emu->reg_lock, flags);
1038 val = ucontrol->value.integer.value[0] & 0xffff;
1039 if (mix->attn[0] != val) {
1040 mix->attn[0] = val;
1041 change = 1;
1042 }
1043 if (change && mix->epcm) {
1044 if (mix->epcm->voices[ch]) {
1045 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]);
1046 }
1047 }
1048 spin_unlock_irqrestore(&emu->reg_lock, flags);
1049 return change;
1050}
1051
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001052static struct snd_kcontrol_new snd_emu10k1_efx_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053{
1054 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1055 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1056 .name = "Multichannel PCM Volume",
1057 .count = 16,
1058 .info = snd_emu10k1_efx_attn_info,
1059 .get = snd_emu10k1_efx_attn_get,
1060 .put = snd_emu10k1_efx_attn_put
1061};
1062
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001063static int snd_emu10k1_shared_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064{
1065 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1066 uinfo->count = 1;
1067 uinfo->value.integer.min = 0;
1068 uinfo->value.integer.max = 1;
1069 return 0;
1070}
1071
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001072static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol,
1073 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001075 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076
1077 if (emu->audigy)
1078 ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0;
1079 else
1080 ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0;
1081 return 0;
1082}
1083
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001084static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
1085 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086{
1087 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001088 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 unsigned int reg, val;
1090 int change = 0;
1091
1092 spin_lock_irqsave(&emu->reg_lock, flags);
1093 if (emu->audigy) {
1094 reg = inl(emu->port + A_IOCFG);
1095 val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0;
1096 change = (reg & A_IOCFG_GPOUT0) != val;
1097 if (change) {
1098 reg &= ~A_IOCFG_GPOUT0;
1099 reg |= val;
1100 outl(reg | val, emu->port + A_IOCFG);
1101 }
1102 }
1103 reg = inl(emu->port + HCFG);
1104 val = ucontrol->value.integer.value[0] ? HCFG_GPOUT0 : 0;
1105 change |= (reg & HCFG_GPOUT0) != val;
1106 if (change) {
1107 reg &= ~HCFG_GPOUT0;
1108 reg |= val;
1109 outl(reg | val, emu->port + HCFG);
1110 }
1111 spin_unlock_irqrestore(&emu->reg_lock, flags);
1112 return change;
1113}
1114
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001115static struct snd_kcontrol_new snd_emu10k1_shared_spdif __devinitdata =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116{
1117 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1118 .name = "SB Live Analog/Digital Output Jack",
1119 .info = snd_emu10k1_shared_spdif_info,
1120 .get = snd_emu10k1_shared_spdif_get,
1121 .put = snd_emu10k1_shared_spdif_put
1122};
1123
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001124static struct snd_kcontrol_new snd_audigy_shared_spdif __devinitdata =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125{
1126 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1127 .name = "Audigy Analog/Digital Output Jack",
1128 .info = snd_emu10k1_shared_spdif_info,
1129 .get = snd_emu10k1_shared_spdif_get,
1130 .put = snd_emu10k1_shared_spdif_put
1131};
1132
1133/*
1134 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001135static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001137 struct snd_emu10k1 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 emu->ac97 = NULL;
1139}
1140
1141/*
1142 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001143static int remove_ctl(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001145 struct snd_ctl_elem_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 memset(&id, 0, sizeof(id));
1147 strcpy(id.name, name);
1148 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1149 return snd_ctl_remove_id(card, &id);
1150}
1151
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001152static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001154 struct snd_ctl_elem_id sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 memset(&sid, 0, sizeof(sid));
1156 strcpy(sid.name, name);
1157 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1158 return snd_ctl_find_id(card, &sid);
1159}
1160
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001161static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001163 struct snd_kcontrol *kctl = ctl_find(card, src);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 if (kctl) {
1165 strcpy(kctl->id.name, dst);
1166 return 0;
1167 }
1168 return -ENOENT;
1169}
1170
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001171int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001172 int pcm_device, int multi_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173{
1174 int err, pcm;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001175 struct snd_kcontrol *kctl;
1176 struct snd_card *card = emu->card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 char **c;
1178 static char *emu10k1_remove_ctls[] = {
1179 /* no AC97 mono, surround, center/lfe */
1180 "Master Mono Playback Switch",
1181 "Master Mono Playback Volume",
1182 "PCM Out Path & Mute",
1183 "Mono Output Select",
Takashi Iwai7eae36f2006-01-05 18:40:56 +01001184 "Front Playback Switch",
1185 "Front Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 "Surround Playback Switch",
1187 "Surround Playback Volume",
1188 "Center Playback Switch",
1189 "Center Playback Volume",
1190 "LFE Playback Switch",
1191 "LFE Playback Volume",
1192 NULL
1193 };
1194 static char *emu10k1_rename_ctls[] = {
1195 "Surround Digital Playback Volume", "Surround Playback Volume",
1196 "Center Digital Playback Volume", "Center Playback Volume",
1197 "LFE Digital Playback Volume", "LFE Playback Volume",
1198 NULL
1199 };
1200 static char *audigy_remove_ctls[] = {
1201 /* Master/PCM controls on ac97 of Audigy has no effect */
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001202 /* On the Audigy2 the AC97 playback is piped into
1203 * the Philips ADC for 24bit capture */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 "PCM Playback Switch",
1205 "PCM Playback Volume",
1206 "Master Mono Playback Switch",
1207 "Master Mono Playback Volume",
1208 "Master Playback Switch",
1209 "Master Playback Volume",
1210 "PCM Out Path & Mute",
1211 "Mono Output Select",
1212 /* remove unused AC97 capture controls */
1213 "Capture Source",
1214 "Capture Switch",
1215 "Capture Volume",
1216 "Mic Select",
1217 "Video Playback Switch",
1218 "Video Playback Volume",
1219 "Mic Playback Switch",
1220 "Mic Playback Volume",
1221 NULL
1222 };
1223 static char *audigy_rename_ctls[] = {
1224 /* use conventional names */
1225 "Wave Playback Volume", "PCM Playback Volume",
1226 /* "Wave Capture Volume", "PCM Capture Volume", */
1227 "Wave Master Playback Volume", "Master Playback Volume",
1228 "AMic Playback Volume", "Mic Playback Volume",
1229 NULL
1230 };
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001231 static char *audigy_remove_ctls_1361t_adc[] = {
1232 /* On the Audigy2 the AC97 playback is piped into
1233 * the Philips ADC for 24bit capture */
1234 "PCM Playback Switch",
1235 "PCM Playback Volume",
1236 "Master Mono Playback Switch",
1237 "Master Mono Playback Volume",
1238 "Capture Source",
1239 "Capture Switch",
1240 "Capture Volume",
1241 "Mic Capture Volume",
1242 "Headphone Playback Switch",
1243 "Headphone Playback Volume",
1244 "3D Control - Center",
1245 "3D Control - Depth",
1246 "3D Control - Switch",
1247 "Line2 Playback Volume",
1248 "Line2 Capture Volume",
1249 NULL
1250 };
1251 static char *audigy_rename_ctls_1361t_adc[] = {
1252 "Master Playback Switch", "Master Capture Switch",
1253 "Master Playback Volume", "Master Capture Volume",
1254 "Wave Master Playback Volume", "Master Playback Volume",
1255 "PC Speaker Playback Switch", "PC Speaker Capture Switch",
1256 "PC Speaker Playback Volume", "PC Speaker Capture Volume",
1257 "Phone Playback Switch", "Phone Capture Switch",
1258 "Phone Playback Volume", "Phone Capture Volume",
1259 "Mic Playback Switch", "Mic Capture Switch",
1260 "Mic Playback Volume", "Mic Capture Volume",
1261 "Line Playback Switch", "Line Capture Switch",
1262 "Line Playback Volume", "Line Capture Volume",
1263 "CD Playback Switch", "CD Capture Switch",
1264 "CD Playback Volume", "CD Capture Volume",
1265 "Aux Playback Switch", "Aux Capture Switch",
1266 "Aux Playback Volume", "Aux Capture Volume",
1267 "Video Playback Switch", "Video Capture Switch",
1268 "Video Playback Volume", "Video Capture Volume",
1269
1270 NULL
1271 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272
Lee Revell2b637da2005-03-30 13:51:18 +02001273 if (emu->card_capabilities->ac97_chip) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001274 struct snd_ac97_bus *pbus;
1275 struct snd_ac97_template ac97;
1276 static struct snd_ac97_bus_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 .write = snd_emu10k1_ac97_write,
1278 .read = snd_emu10k1_ac97_read,
1279 };
1280
Takashi Iwaib1508692005-10-04 13:49:32 +02001281 if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0)
1282 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 pbus->no_vra = 1; /* we don't need VRA */
1284
1285 memset(&ac97, 0, sizeof(ac97));
1286 ac97.private_data = emu;
1287 ac97.private_free = snd_emu10k1_mixer_free_ac97;
1288 ac97.scaps = AC97_SCAP_NO_SPDIF;
Takashi Iwaib1508692005-10-04 13:49:32 +02001289 if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) {
1290 if (emu->card_capabilities->ac97_chip == 1)
1291 return err;
1292 snd_printd(KERN_INFO "emu10k1: AC97 is optional on this board\n");
1293 snd_printd(KERN_INFO" Proceeding without ac97 mixers...\n");
1294 snd_device_free(emu->card, pbus);
1295 goto no_ac97; /* FIXME: get rid of ugly gotos.. */
1296 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 if (emu->audigy) {
1298 /* set master volume to 0 dB */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001299 snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 /* set capture source to mic */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001301 snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001302 if (emu->card_capabilities->adc_1361t)
1303 c = audigy_remove_ctls_1361t_adc;
1304 else
1305 c = audigy_remove_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 } else {
1307 /*
1308 * Credits for cards based on STAC9758:
1309 * James Courtier-Dutton <James@superbug.demon.co.uk>
1310 * Voluspa <voluspa@comhem.se>
1311 */
1312 if (emu->ac97->id == AC97_ID_STAC9758) {
1313 emu->rear_ac97 = 1;
1314 snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT);
1315 }
1316 /* remove unused AC97 controls */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001317 snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
1318 snd_ac97_write_cache(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 c = emu10k1_remove_ctls;
1320 }
1321 for (; *c; c++)
1322 remove_ctl(card, *c);
1323 } else {
Takashi Iwaif12aa402005-09-30 16:56:59 +02001324 no_ac97:
Lee Revell2b637da2005-03-30 13:51:18 +02001325 if (emu->card_capabilities->ecard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 strcpy(emu->card->mixername, "EMU APS");
1327 else if (emu->audigy)
1328 strcpy(emu->card->mixername, "SB Audigy");
1329 else
1330 strcpy(emu->card->mixername, "Emu10k1");
1331 }
1332
1333 if (emu->audigy)
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001334 if (emu->card_capabilities->adc_1361t)
1335 c = audigy_rename_ctls_1361t_adc;
1336 else
1337 c = audigy_rename_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 else
1339 c = emu10k1_rename_ctls;
1340 for (; *c; c += 2)
1341 rename_ctl(card, c[0], c[1]);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001342
James Courtier-Duttone3b9bc02005-12-24 16:54:51 +01001343 if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */
1344 rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume");
1345 rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume");
1346 rename_ctl(card, "Aux2 Capture Volume", "Line3 Capture Volume");
1347 rename_ctl(card, "Mic Capture Volume", "Unknown1 Capture Volume");
1348 remove_ctl(card, "Headphone Playback Switch");
1349 remove_ctl(card, "Headphone Playback Volume");
1350 remove_ctl(card, "3D Control - Center");
1351 remove_ctl(card, "3D Control - Depth");
1352 remove_ctl(card, "3D Control - Switch");
1353 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL)
1355 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001356 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 if ((err = snd_ctl_add(card, kctl)))
1358 return err;
1359 if ((kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL)
1360 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001361 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 if ((err = snd_ctl_add(card, kctl)))
1363 return err;
1364 if ((kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu)) == NULL)
1365 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001366 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 if ((err = snd_ctl_add(card, kctl)))
1368 return err;
1369
1370 if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL)
1371 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001372 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 if ((err = snd_ctl_add(card, kctl)))
1374 return err;
1375
1376 if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL)
1377 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001378 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 if ((err = snd_ctl_add(card, kctl)))
1380 return err;
1381
1382 if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL)
1383 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001384 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 if ((err = snd_ctl_add(card, kctl)))
1386 return err;
1387
1388 /* initialize the routing and volume table for each pcm playback stream */
1389 for (pcm = 0; pcm < 32; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001390 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 int v;
1392
1393 mix = &emu->pcm_mixer[pcm];
1394 mix->epcm = NULL;
1395
1396 for (v = 0; v < 4; v++)
1397 mix->send_routing[0][v] =
1398 mix->send_routing[1][v] =
1399 mix->send_routing[2][v] = v;
1400
1401 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1402 mix->send_volume[0][0] = mix->send_volume[0][1] =
1403 mix->send_volume[1][0] = mix->send_volume[2][1] = 255;
1404
1405 mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
1406 }
1407
1408 /* initialize the routing and volume table for the multichannel playback stream */
1409 for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001410 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 int v;
1412
1413 mix = &emu->efx_pcm_mixer[pcm];
1414 mix->epcm = NULL;
1415
1416 mix->send_routing[0][0] = pcm;
1417 mix->send_routing[0][1] = (pcm == 0) ? 1 : 0;
1418 for (v = 0; v < 2; v++)
1419 mix->send_routing[0][2+v] = 13+v;
1420 if (emu->audigy)
1421 for (v = 0; v < 4; v++)
1422 mix->send_routing[0][4+v] = 60+v;
1423
1424 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1425 mix->send_volume[0][0] = 255;
1426
1427 mix->attn[0] = 0xffff;
1428 }
1429
Lee Revell2b637da2005-03-30 13:51:18 +02001430 if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 /* sb live! and audigy */
1432 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
1433 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02001434 if (!emu->audigy)
1435 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 if ((err = snd_ctl_add(card, kctl)))
1437 return err;
1438 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
1439 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02001440 if (!emu->audigy)
1441 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442 if ((err = snd_ctl_add(card, kctl)))
1443 return err;
1444 }
1445
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001446 if ( emu->card_capabilities->emu1010) {
James Courtier-Dutton19b99fb2005-12-04 18:03:03 +01001447 ; /* Disable the snd_audigy_spdif_shared_spdif */
1448 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
1450 return -ENOMEM;
1451 if ((err = snd_ctl_add(card, kctl)))
1452 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02001453#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
1455 return -ENOMEM;
1456 if ((err = snd_ctl_add(card, kctl)))
1457 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02001458#endif
Lee Revell2b637da2005-03-30 13:51:18 +02001459 } else if (! emu->card_capabilities->ecard) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 /* sb live! */
1461 if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
1462 return -ENOMEM;
1463 if ((err = snd_ctl_add(card, kctl)))
1464 return err;
1465 }
Lee Revell2b637da2005-03-30 13:51:18 +02001466 if (emu->card_capabilities->ca0151_chip) { /* P16V */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 if ((err = snd_p16v_mixer(emu)))
1468 return err;
1469 }
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001470
1471 if ( emu->card_capabilities->emu1010) {
1472 int i;
1473
1474 for (i = 0; i < ARRAY_SIZE(snd_emu1010_output_enum_ctls); i++) {
1475 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_output_enum_ctls[i], emu));
1476 if (err < 0)
1477 return err;
1478 }
1479 for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) {
1480 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], emu));
1481 if (err < 0)
1482 return err;
1483 }
James Courtier-Dutton9148cc52006-10-09 23:08:00 +01001484 for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads); i++) {
1485 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_adc_pads[i], emu));
1486 if (err < 0)
1487 return err;
1488 }
1489 for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads); i++) {
1490 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_dac_pads[i], emu));
1491 if (err < 0)
1492 return err;
1493 }
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001494 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495
1496 return 0;
1497}