blob: 5ceb8dd5cb385313d8fb93b8a30998c0a9dfd638 [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>
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +010038#include <linux/delay.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039
40#define AC97_ID_STAC9758 0x83847658
41
Takashi Iwaieb4698f2005-11-17 14:50:13 +010042static int snd_emu10k1_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -070043{
44 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
45 uinfo->count = 1;
46 return 0;
47}
48
Takashi Iwaieb4698f2005-11-17 14:50:13 +010049static int snd_emu10k1_spdif_get(struct snd_kcontrol *kcontrol,
50 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -070051{
Takashi Iwaieb4698f2005-11-17 14:50:13 +010052 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -070053 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
54 unsigned long flags;
55
56 spin_lock_irqsave(&emu->reg_lock, flags);
57 ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff;
58 ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff;
59 ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff;
60 ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff;
61 spin_unlock_irqrestore(&emu->reg_lock, flags);
62 return 0;
63}
64
Takashi Iwaieb4698f2005-11-17 14:50:13 +010065static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol,
66 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -070067{
68 ucontrol->value.iec958.status[0] = 0xff;
69 ucontrol->value.iec958.status[1] = 0xff;
70 ucontrol->value.iec958.status[2] = 0xff;
71 ucontrol->value.iec958.status[3] = 0xff;
72 return 0;
73}
74
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +010075static char *emu1010_src_texts[] = {
76 "Silence",
77 "Dock Mic A",
78 "Dock Mic B",
79 "Dock ADC1 Left",
80 "Dock ADC1 Right",
81 "Dock ADC2 Left",
82 "Dock ADC2 Right",
83 "Dock ADC3 Left",
84 "Dock ADC3 Right",
85 "0202 ADC Left",
86 "0202 ADC Right",
87 "0202 SPDIF Left",
88 "0202 SPDIF Right",
89 "ADAT 0",
90 "ADAT 1",
91 "ADAT 2",
92 "ADAT 3",
93 "ADAT 4",
94 "ADAT 5",
95 "ADAT 6",
96 "ADAT 7",
97 "DSP 0",
98 "DSP 1",
99 "DSP 2",
100 "DSP 3",
101 "DSP 4",
102 "DSP 5",
103 "DSP 6",
104 "DSP 7",
105 "DSP 8",
106 "DSP 9",
107 "DSP 10",
108 "DSP 11",
109 "DSP 12",
110 "DSP 13",
111 "DSP 14",
112 "DSP 15",
113 "DSP 16",
114 "DSP 17",
115 "DSP 18",
116 "DSP 19",
117 "DSP 20",
118 "DSP 21",
119 "DSP 22",
120 "DSP 23",
121 "DSP 24",
122 "DSP 25",
123 "DSP 26",
124 "DSP 27",
125 "DSP 28",
126 "DSP 29",
127 "DSP 30",
128 "DSP 31",
129};
130
131static unsigned int emu1010_src_regs[] = {
132 EMU_SRC_SILENCE,/* 0 */
133 EMU_SRC_DOCK_MIC_A1, /* 1 */
134 EMU_SRC_DOCK_MIC_B1, /* 2 */
135 EMU_SRC_DOCK_ADC1_LEFT1, /* 3 */
136 EMU_SRC_DOCK_ADC1_RIGHT1, /* 4 */
137 EMU_SRC_DOCK_ADC2_LEFT1, /* 5 */
138 EMU_SRC_DOCK_ADC2_RIGHT1, /* 6 */
139 EMU_SRC_DOCK_ADC3_LEFT1, /* 7 */
140 EMU_SRC_DOCK_ADC3_RIGHT1, /* 8 */
141 EMU_SRC_HAMOA_ADC_LEFT1, /* 9 */
142 EMU_SRC_HAMOA_ADC_RIGHT1, /* 10 */
143 EMU_SRC_HANA_SPDIF_LEFT1, /* 11 */
144 EMU_SRC_HANA_SPDIF_RIGHT1, /* 12 */
145 EMU_SRC_HANA_ADAT, /* 13 */
146 EMU_SRC_HANA_ADAT+1, /* 14 */
147 EMU_SRC_HANA_ADAT+2, /* 15 */
148 EMU_SRC_HANA_ADAT+3, /* 16 */
149 EMU_SRC_HANA_ADAT+4, /* 17 */
150 EMU_SRC_HANA_ADAT+5, /* 18 */
151 EMU_SRC_HANA_ADAT+6, /* 19 */
152 EMU_SRC_HANA_ADAT+7, /* 20 */
153 EMU_SRC_ALICE_EMU32A, /* 21 */
154 EMU_SRC_ALICE_EMU32A+1, /* 22 */
155 EMU_SRC_ALICE_EMU32A+2, /* 23 */
156 EMU_SRC_ALICE_EMU32A+3, /* 24 */
157 EMU_SRC_ALICE_EMU32A+4, /* 25 */
158 EMU_SRC_ALICE_EMU32A+5, /* 26 */
159 EMU_SRC_ALICE_EMU32A+6, /* 27 */
160 EMU_SRC_ALICE_EMU32A+7, /* 28 */
161 EMU_SRC_ALICE_EMU32A+8, /* 29 */
162 EMU_SRC_ALICE_EMU32A+9, /* 30 */
163 EMU_SRC_ALICE_EMU32A+0xa, /* 31 */
164 EMU_SRC_ALICE_EMU32A+0xb, /* 32 */
165 EMU_SRC_ALICE_EMU32A+0xc, /* 33 */
166 EMU_SRC_ALICE_EMU32A+0xd, /* 34 */
167 EMU_SRC_ALICE_EMU32A+0xe, /* 35 */
168 EMU_SRC_ALICE_EMU32A+0xf, /* 36 */
169 EMU_SRC_ALICE_EMU32B, /* 37 */
170 EMU_SRC_ALICE_EMU32B+1, /* 38 */
171 EMU_SRC_ALICE_EMU32B+2, /* 39 */
172 EMU_SRC_ALICE_EMU32B+3, /* 40 */
173 EMU_SRC_ALICE_EMU32B+4, /* 41 */
174 EMU_SRC_ALICE_EMU32B+5, /* 42 */
175 EMU_SRC_ALICE_EMU32B+6, /* 43 */
176 EMU_SRC_ALICE_EMU32B+7, /* 44 */
177 EMU_SRC_ALICE_EMU32B+8, /* 45 */
178 EMU_SRC_ALICE_EMU32B+9, /* 46 */
179 EMU_SRC_ALICE_EMU32B+0xa, /* 47 */
180 EMU_SRC_ALICE_EMU32B+0xb, /* 48 */
181 EMU_SRC_ALICE_EMU32B+0xc, /* 49 */
182 EMU_SRC_ALICE_EMU32B+0xd, /* 50 */
183 EMU_SRC_ALICE_EMU32B+0xe, /* 51 */
184 EMU_SRC_ALICE_EMU32B+0xf, /* 52 */
185};
186
187static unsigned int emu1010_output_dst[] = {
188 EMU_DST_DOCK_DAC1_LEFT1, /* 0 */
189 EMU_DST_DOCK_DAC1_RIGHT1, /* 1 */
190 EMU_DST_DOCK_DAC2_LEFT1, /* 2 */
191 EMU_DST_DOCK_DAC2_RIGHT1, /* 3 */
192 EMU_DST_DOCK_DAC3_LEFT1, /* 4 */
193 EMU_DST_DOCK_DAC3_RIGHT1, /* 5 */
194 EMU_DST_DOCK_DAC4_LEFT1, /* 6 */
195 EMU_DST_DOCK_DAC4_RIGHT1, /* 7 */
196 EMU_DST_DOCK_PHONES_LEFT1, /* 8 */
197 EMU_DST_DOCK_PHONES_RIGHT1, /* 9 */
198 EMU_DST_DOCK_SPDIF_LEFT1, /* 10 */
199 EMU_DST_DOCK_SPDIF_RIGHT1, /* 11 */
200 EMU_DST_HANA_SPDIF_LEFT1, /* 12 */
201 EMU_DST_HANA_SPDIF_RIGHT1, /* 13 */
202 EMU_DST_HAMOA_DAC_LEFT1, /* 14 */
203 EMU_DST_HAMOA_DAC_RIGHT1, /* 15 */
204 EMU_DST_HANA_ADAT, /* 16 */
205 EMU_DST_HANA_ADAT+1, /* 17 */
206 EMU_DST_HANA_ADAT+2, /* 18 */
207 EMU_DST_HANA_ADAT+3, /* 19 */
208 EMU_DST_HANA_ADAT+4, /* 20 */
209 EMU_DST_HANA_ADAT+5, /* 21 */
210 EMU_DST_HANA_ADAT+6, /* 22 */
211 EMU_DST_HANA_ADAT+7, /* 23 */
212};
213
214static unsigned int emu1010_input_dst[] = {
215 EMU_DST_ALICE2_EMU32_0,
216 EMU_DST_ALICE2_EMU32_1,
217 EMU_DST_ALICE2_EMU32_2,
218 EMU_DST_ALICE2_EMU32_3,
219 EMU_DST_ALICE2_EMU32_4,
220 EMU_DST_ALICE2_EMU32_5,
221 EMU_DST_ALICE2_EMU32_6,
222 EMU_DST_ALICE2_EMU32_7,
223 EMU_DST_ALICE2_EMU32_8,
224 EMU_DST_ALICE2_EMU32_9,
225 EMU_DST_ALICE2_EMU32_A,
226 EMU_DST_ALICE2_EMU32_B,
227 EMU_DST_ALICE2_EMU32_C,
228 EMU_DST_ALICE2_EMU32_D,
229 EMU_DST_ALICE2_EMU32_E,
230 EMU_DST_ALICE2_EMU32_F,
231 EMU_DST_ALICE_I2S0_LEFT,
232 EMU_DST_ALICE_I2S0_RIGHT,
233 EMU_DST_ALICE_I2S1_LEFT,
234 EMU_DST_ALICE_I2S1_RIGHT,
235 EMU_DST_ALICE_I2S2_LEFT,
236 EMU_DST_ALICE_I2S2_RIGHT,
237};
238
239static int snd_emu1010_input_output_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
240{
241 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
242 uinfo->count = 1;
243 uinfo->value.enumerated.items = 53;
244 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
245 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
246 strcpy(uinfo->value.enumerated.name, emu1010_src_texts[uinfo->value.enumerated.item]);
247 return 0;
248}
249
250static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol,
251 struct snd_ctl_elem_value *ucontrol)
252{
253 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
254 int channel;
255
256 channel = (kcontrol->private_value) & 0xff;
257 ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel];
258 return 0;
259}
260
261static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol,
262 struct snd_ctl_elem_value *ucontrol)
263{
264 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
265 int change = 0;
266 unsigned int val;
267 int channel;
268
269 channel = (kcontrol->private_value) & 0xff;
270 if (emu->emu1010.output_source[channel] != ucontrol->value.enumerated.item[0]) {
271 val = emu->emu1010.output_source[channel] = ucontrol->value.enumerated.item[0];
272 change = 1;
273 snd_emu1010_fpga_link_dst_src_write(emu,
274 emu1010_output_dst[channel], emu1010_src_regs[val]);
275 }
276 return change;
277}
278
279static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol,
280 struct snd_ctl_elem_value *ucontrol)
281{
282 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
283 int channel;
284
285 channel = (kcontrol->private_value) & 0xff;
286 ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel];
287 return 0;
288}
289
290static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
291 struct snd_ctl_elem_value *ucontrol)
292{
293 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
294 int change = 0;
295 unsigned int val;
296 int channel;
297
298 channel = (kcontrol->private_value) & 0xff;
299 if (emu->emu1010.input_source[channel] != ucontrol->value.enumerated.item[0]) {
300 val = emu->emu1010.input_source[channel] = ucontrol->value.enumerated.item[0];
301 change = 1;
302 snd_emu1010_fpga_link_dst_src_write(emu,
303 emu1010_input_dst[channel], emu1010_src_regs[val]);
304 }
305 return change;
306}
307
308#define EMU1010_SOURCE_OUTPUT(xname,chid) \
309{ \
310 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
311 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
312 .info = snd_emu1010_input_output_source_info, \
313 .get = snd_emu1010_output_source_get, \
314 .put = snd_emu1010_output_source_put, \
315 .private_value = chid \
316}
317
318static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = {
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100319 EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Switch", 0),
320 EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Switch", 1),
321 EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Switch", 2),
322 EMU1010_SOURCE_OUTPUT("Dock DAC2 Right Playback Switch", 3),
323 EMU1010_SOURCE_OUTPUT("Dock DAC3 Left Playback Switch", 4),
324 EMU1010_SOURCE_OUTPUT("Dock DAC3 Right Playback Switch", 5),
325 EMU1010_SOURCE_OUTPUT("Dock DAC4 Left Playback Switch", 6),
326 EMU1010_SOURCE_OUTPUT("Dock DAC4 Right Playback Switch", 7),
327 EMU1010_SOURCE_OUTPUT("Dock Phones Left Playback Switch", 8),
328 EMU1010_SOURCE_OUTPUT("Dock Phones Right Playback Switch", 9),
329 EMU1010_SOURCE_OUTPUT("Dock SPDIF Left Playback Switch", 0xa),
330 EMU1010_SOURCE_OUTPUT("Dock SPDIF Right Playback Switch", 0xb),
331 EMU1010_SOURCE_OUTPUT("1010 SPDIF Left Playback Switch", 0xc),
332 EMU1010_SOURCE_OUTPUT("1010 SPDIF Right Playback Switch", 0xd),
333 EMU1010_SOURCE_OUTPUT("0202 DAC Left Playback Switch", 0xe),
334 EMU1010_SOURCE_OUTPUT("0202 DAC Right Playback Switch", 0xf),
335 EMU1010_SOURCE_OUTPUT("1010 ADAT 0 Playback Switch", 0x10),
336 EMU1010_SOURCE_OUTPUT("1010 ADAT 1 Playback Switch", 0x11),
337 EMU1010_SOURCE_OUTPUT("1010 ADAT 2 Playback Switch", 0x12),
338 EMU1010_SOURCE_OUTPUT("1010 ADAT 3 Playback Switch", 0x13),
339 EMU1010_SOURCE_OUTPUT("1010 ADAT 4 Playback Switch", 0x14),
340 EMU1010_SOURCE_OUTPUT("1010 ADAT 5 Playback Switch", 0x15),
341 EMU1010_SOURCE_OUTPUT("1010 ADAT 6 Playback Switch", 0x16),
342 EMU1010_SOURCE_OUTPUT("1010 ADAT 7 Playback Switch", 0x17),
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100343};
344
345#define EMU1010_SOURCE_INPUT(xname,chid) \
346{ \
347 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
348 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
349 .info = snd_emu1010_input_output_source_info, \
350 .get = snd_emu1010_input_source_get, \
351 .put = snd_emu1010_input_source_put, \
352 .private_value = chid \
353}
354
355static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] __devinitdata = {
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100356 EMU1010_SOURCE_INPUT("DSP 0 Capture Switch", 0),
357 EMU1010_SOURCE_INPUT("DSP 1 Capture Switch", 1),
358 EMU1010_SOURCE_INPUT("DSP 2 Capture Switch", 2),
359 EMU1010_SOURCE_INPUT("DSP 3 Capture Switch", 3),
360 EMU1010_SOURCE_INPUT("DSP 4 Capture Switch", 4),
361 EMU1010_SOURCE_INPUT("DSP 5 Capture Switch", 5),
362 EMU1010_SOURCE_INPUT("DSP 6 Capture Switch", 6),
363 EMU1010_SOURCE_INPUT("DSP 7 Capture Switch", 7),
364 EMU1010_SOURCE_INPUT("DSP 8 Capture Switch", 8),
365 EMU1010_SOURCE_INPUT("DSP 9 Capture Switch", 9),
366 EMU1010_SOURCE_INPUT("DSP A Capture Switch", 0xa),
367 EMU1010_SOURCE_INPUT("DSP B Capture Switch", 0xb),
368 EMU1010_SOURCE_INPUT("DSP C Capture Switch", 0xc),
369 EMU1010_SOURCE_INPUT("DSP D Capture Switch", 0xd),
370 EMU1010_SOURCE_INPUT("DSP E Capture Switch", 0xe),
371 EMU1010_SOURCE_INPUT("DSP F Capture Switch", 0xf),
372 EMU1010_SOURCE_INPUT("DSP 10 Capture Switch", 0x10),
373 EMU1010_SOURCE_INPUT("DSP 11 Capture Switch", 0x11),
374 EMU1010_SOURCE_INPUT("DSP 12 Capture Switch", 0x12),
375 EMU1010_SOURCE_INPUT("DSP 13 Capture Switch", 0x13),
376 EMU1010_SOURCE_INPUT("DSP 14 Capture Switch", 0x14),
377 EMU1010_SOURCE_INPUT("DSP 15 Capture Switch", 0x15),
378};
379
380
381
382
383static int snd_emu1010_adc_pads_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
384{
385 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
386 uinfo->count = 1;
387 uinfo->value.integer.min = 0;
388 uinfo->value.integer.max = 1;
389 return 0;
390}
391
392static int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
393{
394 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
395 unsigned int mask = kcontrol->private_value & 0xff;
396 ucontrol->value.integer.value[0] = (emu->emu1010.adc_pads & mask) ? 1 : 0;
397 return 0;
398}
399
400static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
401{
402 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
403 unsigned int mask = kcontrol->private_value & 0xff;
404 unsigned int val, cache;
405 val = ucontrol->value.integer.value[0];
406 cache = emu->emu1010.adc_pads;
407 if (val == 1)
408 cache = cache | mask;
409 else
410 cache = cache & ~mask;
411 if (cache != emu->emu1010.adc_pads) {
412 snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache );
413 emu->emu1010.adc_pads = cache;
414 }
415
416 return 0;
417}
418
419
420
421#define EMU1010_ADC_PADS(xname,chid) \
422{ \
423 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
424 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
425 .info = snd_emu1010_adc_pads_info, \
426 .get = snd_emu1010_adc_pads_get, \
427 .put = snd_emu1010_adc_pads_put, \
428 .private_value = chid \
429}
430
431static struct snd_kcontrol_new snd_emu1010_adc_pads[] __devinitdata = {
432 EMU1010_ADC_PADS("ADC1 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD1),
433 EMU1010_ADC_PADS("ADC2 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD2),
434 EMU1010_ADC_PADS("ADC3 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD3),
435 EMU1010_ADC_PADS("ADC1 14dB PAD 0202 Capture Switch", EMU_HANA_0202_ADC_PAD1),
436};
437
438static int snd_emu1010_dac_pads_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
439{
440 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
441 uinfo->count = 1;
442 uinfo->value.integer.min = 0;
443 uinfo->value.integer.max = 1;
444 return 0;
445}
446
447static int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
448{
449 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
450 unsigned int mask = kcontrol->private_value & 0xff;
451 ucontrol->value.integer.value[0] = (emu->emu1010.dac_pads & mask) ? 1 : 0;
452 return 0;
453}
454
455static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
456{
457 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
458 unsigned int mask = kcontrol->private_value & 0xff;
459 unsigned int val, cache;
460 val = ucontrol->value.integer.value[0];
461 cache = emu->emu1010.dac_pads;
462 if (val == 1)
463 cache = cache | mask;
464 else
465 cache = cache & ~mask;
466 if (cache != emu->emu1010.dac_pads) {
467 snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache );
468 emu->emu1010.dac_pads = cache;
469 }
470
471 return 0;
472}
473
474
475
476#define EMU1010_DAC_PADS(xname,chid) \
477{ \
478 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
479 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
480 .info = snd_emu1010_dac_pads_info, \
481 .get = snd_emu1010_dac_pads_get, \
482 .put = snd_emu1010_dac_pads_put, \
483 .private_value = chid \
484}
485
486static struct snd_kcontrol_new snd_emu1010_dac_pads[] __devinitdata = {
487 EMU1010_DAC_PADS("DAC1 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD1),
488 EMU1010_DAC_PADS("DAC2 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD2),
489 EMU1010_DAC_PADS("DAC3 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD3),
490 EMU1010_DAC_PADS("DAC4 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD4),
491 EMU1010_DAC_PADS("DAC1 0202 14dB PAD Playback Switch", EMU_HANA_0202_DAC_PAD1),
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100492};
493
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100494
495static int snd_emu1010_internal_clock_info(struct snd_kcontrol *kcontrol,
496 struct snd_ctl_elem_info *uinfo)
497{
498 static char *texts[2] = {
499 "44100", "48000"
500 };
501
502 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
503 uinfo->count = 1;
504 uinfo->value.enumerated.items = 2;
505 if (uinfo->value.enumerated.item > 1)
506 uinfo->value.enumerated.item = 1;
507 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
508 return 0;
509}
510
511static int snd_emu1010_internal_clock_get(struct snd_kcontrol *kcontrol,
512 struct snd_ctl_elem_value *ucontrol)
513{
514 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
515
516 ucontrol->value.enumerated.item[0] = emu->emu1010.internal_clock;
517 return 0;
518}
519
520static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol,
521 struct snd_ctl_elem_value *ucontrol)
522{
523 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
524 unsigned int val;
525 int change = 0;
526
527 val = ucontrol->value.enumerated.item[0] ;
528 change = (emu->emu1010.internal_clock != val);
529 if (change) {
530 emu->emu1010.internal_clock = val;
531 switch (val) {
532 case 0:
533 /* 44100 */
534 /* Mute all */
535 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
536 /* Default fallback clock 48kHz */
537 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_44_1K );
538 /* Word Clock source, Internal 44.1kHz x1 */
539 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
540 EMU_HANA_WCLOCK_INT_44_1K | EMU_HANA_WCLOCK_1X );
541 /* Set LEDs on Audio Dock */
542 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
543 EMU_HANA_DOCK_LEDS_2_44K | EMU_HANA_DOCK_LEDS_2_LOCK );
544 /* Allow DLL to settle */
James Courtier-Duttone40a0b22006-10-10 18:44:29 +0100545 msleep(10);
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100546 /* Unmute all */
547 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
548 break;
549 case 1:
550 /* 48000 */
551 /* Mute all */
552 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
553 /* Default fallback clock 48kHz */
554 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
555 /* Word Clock source, Internal 48kHz x1 */
556 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
557 EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_1X );
558 /* Set LEDs on Audio Dock */
559 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
560 EMU_HANA_DOCK_LEDS_2_48K | EMU_HANA_DOCK_LEDS_2_LOCK );
561 /* Allow DLL to settle */
James Courtier-Duttone40a0b22006-10-10 18:44:29 +0100562 msleep(10);
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100563 /* Unmute all */
564 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
565 break;
566 }
567 }
568 return change;
569}
570
571static struct snd_kcontrol_new snd_emu1010_internal_clock =
572{
573 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
574 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
575 .name = "Clock Internal Rate",
576 .count = 1,
577 .info = snd_emu1010_internal_clock_info,
578 .get = snd_emu1010_internal_clock_get,
579 .put = snd_emu1010_internal_clock_put
580};
581
Takashi Iwai0af68e52005-04-11 17:03:03 +0200582#if 0
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100583static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584{
585 static char *texts[] = {"44100", "48000", "96000"};
586
587 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
588 uinfo->count = 1;
589 uinfo->value.enumerated.items = 3;
590 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
591 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
592 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
593 return 0;
594}
595
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100596static int snd_audigy_spdif_output_rate_get(struct snd_kcontrol *kcontrol,
597 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100599 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 unsigned int tmp;
601 unsigned long flags;
602
603
604 spin_lock_irqsave(&emu->reg_lock, flags);
605 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
606 switch (tmp & A_SPDIF_RATE_MASK) {
607 case A_SPDIF_44100:
608 ucontrol->value.enumerated.item[0] = 0;
609 break;
610 case A_SPDIF_48000:
611 ucontrol->value.enumerated.item[0] = 1;
612 break;
613 case A_SPDIF_96000:
614 ucontrol->value.enumerated.item[0] = 2;
615 break;
616 default:
617 ucontrol->value.enumerated.item[0] = 1;
618 }
619 spin_unlock_irqrestore(&emu->reg_lock, flags);
620 return 0;
621}
622
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100623static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol,
624 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100626 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 int change;
628 unsigned int reg, val, tmp;
629 unsigned long flags;
630
631 switch(ucontrol->value.enumerated.item[0]) {
632 case 0:
633 val = A_SPDIF_44100;
634 break;
635 case 1:
636 val = A_SPDIF_48000;
637 break;
638 case 2:
639 val = A_SPDIF_96000;
640 break;
641 default:
642 val = A_SPDIF_48000;
643 break;
644 }
645
646
647 spin_lock_irqsave(&emu->reg_lock, flags);
648 reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
649 tmp = reg & ~A_SPDIF_RATE_MASK;
650 tmp |= val;
651 if ((change = (tmp != reg)))
652 snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
653 spin_unlock_irqrestore(&emu->reg_lock, flags);
654 return change;
655}
656
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100657static struct snd_kcontrol_new snd_audigy_spdif_output_rate =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658{
659 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
660 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
661 .name = "Audigy SPDIF Output Sample Rate",
662 .count = 1,
663 .info = snd_audigy_spdif_output_rate_info,
664 .get = snd_audigy_spdif_output_rate_get,
665 .put = snd_audigy_spdif_output_rate_put
666};
Takashi Iwai0af68e52005-04-11 17:03:03 +0200667#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100669static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol,
670 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100672 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
674 int change;
675 unsigned int val;
676 unsigned long flags;
677
678 val = (ucontrol->value.iec958.status[0] << 0) |
679 (ucontrol->value.iec958.status[1] << 8) |
680 (ucontrol->value.iec958.status[2] << 16) |
681 (ucontrol->value.iec958.status[3] << 24);
682 spin_lock_irqsave(&emu->reg_lock, flags);
683 change = val != emu->spdif_bits[idx];
684 if (change) {
685 snd_emu10k1_ptr_write(emu, SPCS0 + idx, 0, val);
686 emu->spdif_bits[idx] = val;
687 }
688 spin_unlock_irqrestore(&emu->reg_lock, flags);
689 return change;
690}
691
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100692static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693{
694 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +0200695 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
697 .count = 4,
698 .info = snd_emu10k1_spdif_info,
699 .get = snd_emu10k1_spdif_get_mask
700};
701
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100702static struct snd_kcontrol_new snd_emu10k1_spdif_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703{
Clemens Ladisch5549d542005-08-03 13:50:30 +0200704 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
706 .count = 4,
707 .info = snd_emu10k1_spdif_info,
708 .get = snd_emu10k1_spdif_get,
709 .put = snd_emu10k1_spdif_put
710};
711
712
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100713static void update_emu10k1_fxrt(struct snd_emu10k1 *emu, int voice, unsigned char *route)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714{
715 if (emu->audigy) {
716 snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
717 snd_emu10k1_compose_audigy_fxrt1(route));
718 snd_emu10k1_ptr_write(emu, A_FXRT2, voice,
719 snd_emu10k1_compose_audigy_fxrt2(route));
720 } else {
721 snd_emu10k1_ptr_write(emu, FXRT, voice,
722 snd_emu10k1_compose_send_routing(route));
723 }
724}
725
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100726static void update_emu10k1_send_volume(struct snd_emu10k1 *emu, int voice, unsigned char *volume)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727{
728 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]);
729 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]);
730 snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, volume[2]);
731 snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, volume[3]);
732 if (emu->audigy) {
733 unsigned int val = ((unsigned int)volume[4] << 24) |
734 ((unsigned int)volume[5] << 16) |
735 ((unsigned int)volume[6] << 8) |
736 (unsigned int)volume[7];
737 snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, val);
738 }
739}
740
741/* PCM stream controls */
742
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100743static int snd_emu10k1_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100745 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
747 uinfo->count = emu->audigy ? 3*8 : 3*4;
748 uinfo->value.integer.min = 0;
749 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
750 return 0;
751}
752
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100753static int snd_emu10k1_send_routing_get(struct snd_kcontrol *kcontrol,
754 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755{
756 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100757 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
758 struct snd_emu10k1_pcm_mixer *mix =
759 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 int voice, idx;
761 int num_efx = emu->audigy ? 8 : 4;
762 int mask = emu->audigy ? 0x3f : 0x0f;
763
764 spin_lock_irqsave(&emu->reg_lock, flags);
765 for (voice = 0; voice < 3; voice++)
766 for (idx = 0; idx < num_efx; idx++)
767 ucontrol->value.integer.value[(voice * num_efx) + idx] =
768 mix->send_routing[voice][idx] & mask;
769 spin_unlock_irqrestore(&emu->reg_lock, flags);
770 return 0;
771}
772
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100773static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol,
774 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775{
776 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100777 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
778 struct snd_emu10k1_pcm_mixer *mix =
779 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 int change = 0, voice, idx, val;
781 int num_efx = emu->audigy ? 8 : 4;
782 int mask = emu->audigy ? 0x3f : 0x0f;
783
784 spin_lock_irqsave(&emu->reg_lock, flags);
785 for (voice = 0; voice < 3; voice++)
786 for (idx = 0; idx < num_efx; idx++) {
787 val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask;
788 if (mix->send_routing[voice][idx] != val) {
789 mix->send_routing[voice][idx] = val;
790 change = 1;
791 }
792 }
793 if (change && mix->epcm) {
794 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
795 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
796 &mix->send_routing[1][0]);
797 update_emu10k1_fxrt(emu, mix->epcm->voices[1]->number,
798 &mix->send_routing[2][0]);
799 } else if (mix->epcm->voices[0]) {
800 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
801 &mix->send_routing[0][0]);
802 }
803 }
804 spin_unlock_irqrestore(&emu->reg_lock, flags);
805 return change;
806}
807
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100808static struct snd_kcontrol_new snd_emu10k1_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809{
810 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +0200811 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 .name = "EMU10K1 PCM Send Routing",
813 .count = 32,
814 .info = snd_emu10k1_send_routing_info,
815 .get = snd_emu10k1_send_routing_get,
816 .put = snd_emu10k1_send_routing_put
817};
818
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100819static int snd_emu10k1_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100821 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
823 uinfo->count = emu->audigy ? 3*8 : 3*4;
824 uinfo->value.integer.min = 0;
825 uinfo->value.integer.max = 255;
826 return 0;
827}
828
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100829static int snd_emu10k1_send_volume_get(struct snd_kcontrol *kcontrol,
830 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831{
832 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100833 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
834 struct snd_emu10k1_pcm_mixer *mix =
835 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 int idx;
837 int num_efx = emu->audigy ? 8 : 4;
838
839 spin_lock_irqsave(&emu->reg_lock, flags);
840 for (idx = 0; idx < 3*num_efx; idx++)
841 ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx];
842 spin_unlock_irqrestore(&emu->reg_lock, flags);
843 return 0;
844}
845
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100846static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol,
847 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848{
849 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100850 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
851 struct snd_emu10k1_pcm_mixer *mix =
852 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 int change = 0, idx, val;
854 int num_efx = emu->audigy ? 8 : 4;
855
856 spin_lock_irqsave(&emu->reg_lock, flags);
857 for (idx = 0; idx < 3*num_efx; idx++) {
858 val = ucontrol->value.integer.value[idx] & 255;
859 if (mix->send_volume[idx/num_efx][idx%num_efx] != val) {
860 mix->send_volume[idx/num_efx][idx%num_efx] = val;
861 change = 1;
862 }
863 }
864 if (change && mix->epcm) {
865 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
866 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
867 &mix->send_volume[1][0]);
868 update_emu10k1_send_volume(emu, mix->epcm->voices[1]->number,
869 &mix->send_volume[2][0]);
870 } else if (mix->epcm->voices[0]) {
871 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
872 &mix->send_volume[0][0]);
873 }
874 }
875 spin_unlock_irqrestore(&emu->reg_lock, flags);
876 return change;
877}
878
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100879static struct snd_kcontrol_new snd_emu10k1_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880{
881 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +0200882 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 .name = "EMU10K1 PCM Send Volume",
884 .count = 32,
885 .info = snd_emu10k1_send_volume_info,
886 .get = snd_emu10k1_send_volume_get,
887 .put = snd_emu10k1_send_volume_put
888};
889
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100890static int snd_emu10k1_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891{
892 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
893 uinfo->count = 3;
894 uinfo->value.integer.min = 0;
895 uinfo->value.integer.max = 0xffff;
896 return 0;
897}
898
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100899static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol,
900 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100902 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
903 struct snd_emu10k1_pcm_mixer *mix =
904 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 unsigned long flags;
906 int idx;
907
908 spin_lock_irqsave(&emu->reg_lock, flags);
909 for (idx = 0; idx < 3; idx++)
910 ucontrol->value.integer.value[idx] = mix->attn[idx];
911 spin_unlock_irqrestore(&emu->reg_lock, flags);
912 return 0;
913}
914
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100915static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol,
916 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917{
918 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100919 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
920 struct snd_emu10k1_pcm_mixer *mix =
921 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 int change = 0, idx, val;
923
924 spin_lock_irqsave(&emu->reg_lock, flags);
925 for (idx = 0; idx < 3; idx++) {
926 val = ucontrol->value.integer.value[idx] & 0xffff;
927 if (mix->attn[idx] != val) {
928 mix->attn[idx] = val;
929 change = 1;
930 }
931 }
932 if (change && mix->epcm) {
933 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
934 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[1]);
935 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[1]->number, mix->attn[2]);
936 } else if (mix->epcm->voices[0]) {
937 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]);
938 }
939 }
940 spin_unlock_irqrestore(&emu->reg_lock, flags);
941 return change;
942}
943
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100944static struct snd_kcontrol_new snd_emu10k1_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945{
946 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +0200947 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 .name = "EMU10K1 PCM Volume",
949 .count = 32,
950 .info = snd_emu10k1_attn_info,
951 .get = snd_emu10k1_attn_get,
952 .put = snd_emu10k1_attn_put
953};
954
955/* Mutichannel PCM stream controls */
956
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100957static int snd_emu10k1_efx_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100959 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
961 uinfo->count = emu->audigy ? 8 : 4;
962 uinfo->value.integer.min = 0;
963 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
964 return 0;
965}
966
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100967static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol,
968 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969{
970 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100971 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
972 struct snd_emu10k1_pcm_mixer *mix =
973 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 int idx;
975 int num_efx = emu->audigy ? 8 : 4;
976 int mask = emu->audigy ? 0x3f : 0x0f;
977
978 spin_lock_irqsave(&emu->reg_lock, flags);
979 for (idx = 0; idx < num_efx; idx++)
980 ucontrol->value.integer.value[idx] =
981 mix->send_routing[0][idx] & mask;
982 spin_unlock_irqrestore(&emu->reg_lock, flags);
983 return 0;
984}
985
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100986static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol,
987 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988{
989 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100990 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100992 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 int change = 0, idx, val;
994 int num_efx = emu->audigy ? 8 : 4;
995 int mask = emu->audigy ? 0x3f : 0x0f;
996
997 spin_lock_irqsave(&emu->reg_lock, flags);
998 for (idx = 0; idx < num_efx; idx++) {
999 val = ucontrol->value.integer.value[idx] & mask;
1000 if (mix->send_routing[0][idx] != val) {
1001 mix->send_routing[0][idx] = val;
1002 change = 1;
1003 }
1004 }
1005
1006 if (change && mix->epcm) {
1007 if (mix->epcm->voices[ch]) {
1008 update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number,
1009 &mix->send_routing[0][0]);
1010 }
1011 }
1012 spin_unlock_irqrestore(&emu->reg_lock, flags);
1013 return change;
1014}
1015
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001016static struct snd_kcontrol_new snd_emu10k1_efx_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017{
1018 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1019 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1020 .name = "Multichannel PCM Send Routing",
1021 .count = 16,
1022 .info = snd_emu10k1_efx_send_routing_info,
1023 .get = snd_emu10k1_efx_send_routing_get,
1024 .put = snd_emu10k1_efx_send_routing_put
1025};
1026
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001027static int snd_emu10k1_efx_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001029 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1031 uinfo->count = emu->audigy ? 8 : 4;
1032 uinfo->value.integer.min = 0;
1033 uinfo->value.integer.max = 255;
1034 return 0;
1035}
1036
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001037static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol,
1038 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039{
1040 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001041 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1042 struct snd_emu10k1_pcm_mixer *mix =
1043 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 int idx;
1045 int num_efx = emu->audigy ? 8 : 4;
1046
1047 spin_lock_irqsave(&emu->reg_lock, flags);
1048 for (idx = 0; idx < num_efx; idx++)
1049 ucontrol->value.integer.value[idx] = mix->send_volume[0][idx];
1050 spin_unlock_irqrestore(&emu->reg_lock, flags);
1051 return 0;
1052}
1053
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001054static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol,
1055 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056{
1057 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001058 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001060 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 int change = 0, idx, val;
1062 int num_efx = emu->audigy ? 8 : 4;
1063
1064 spin_lock_irqsave(&emu->reg_lock, flags);
1065 for (idx = 0; idx < num_efx; idx++) {
1066 val = ucontrol->value.integer.value[idx] & 255;
1067 if (mix->send_volume[0][idx] != val) {
1068 mix->send_volume[0][idx] = val;
1069 change = 1;
1070 }
1071 }
1072 if (change && mix->epcm) {
1073 if (mix->epcm->voices[ch]) {
1074 update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number,
1075 &mix->send_volume[0][0]);
1076 }
1077 }
1078 spin_unlock_irqrestore(&emu->reg_lock, flags);
1079 return change;
1080}
1081
1082
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001083static struct snd_kcontrol_new snd_emu10k1_efx_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084{
1085 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1086 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1087 .name = "Multichannel PCM Send Volume",
1088 .count = 16,
1089 .info = snd_emu10k1_efx_send_volume_info,
1090 .get = snd_emu10k1_efx_send_volume_get,
1091 .put = snd_emu10k1_efx_send_volume_put
1092};
1093
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001094static int snd_emu10k1_efx_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095{
1096 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1097 uinfo->count = 1;
1098 uinfo->value.integer.min = 0;
1099 uinfo->value.integer.max = 0xffff;
1100 return 0;
1101}
1102
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001103static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol,
1104 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001106 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1107 struct snd_emu10k1_pcm_mixer *mix =
1108 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 unsigned long flags;
1110
1111 spin_lock_irqsave(&emu->reg_lock, flags);
1112 ucontrol->value.integer.value[0] = mix->attn[0];
1113 spin_unlock_irqrestore(&emu->reg_lock, flags);
1114 return 0;
1115}
1116
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001117static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol,
1118 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119{
1120 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001121 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001123 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 int change = 0, val;
1125
1126 spin_lock_irqsave(&emu->reg_lock, flags);
1127 val = ucontrol->value.integer.value[0] & 0xffff;
1128 if (mix->attn[0] != val) {
1129 mix->attn[0] = val;
1130 change = 1;
1131 }
1132 if (change && mix->epcm) {
1133 if (mix->epcm->voices[ch]) {
1134 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]);
1135 }
1136 }
1137 spin_unlock_irqrestore(&emu->reg_lock, flags);
1138 return change;
1139}
1140
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001141static struct snd_kcontrol_new snd_emu10k1_efx_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142{
1143 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1144 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1145 .name = "Multichannel PCM Volume",
1146 .count = 16,
1147 .info = snd_emu10k1_efx_attn_info,
1148 .get = snd_emu10k1_efx_attn_get,
1149 .put = snd_emu10k1_efx_attn_put
1150};
1151
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001152static int snd_emu10k1_shared_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153{
1154 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1155 uinfo->count = 1;
1156 uinfo->value.integer.min = 0;
1157 uinfo->value.integer.max = 1;
1158 return 0;
1159}
1160
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001161static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol,
1162 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001164 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165
1166 if (emu->audigy)
1167 ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0;
1168 else
1169 ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0;
1170 return 0;
1171}
1172
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001173static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
1174 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175{
1176 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001177 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 unsigned int reg, val;
1179 int change = 0;
1180
1181 spin_lock_irqsave(&emu->reg_lock, flags);
1182 if (emu->audigy) {
1183 reg = inl(emu->port + A_IOCFG);
1184 val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0;
1185 change = (reg & A_IOCFG_GPOUT0) != val;
1186 if (change) {
1187 reg &= ~A_IOCFG_GPOUT0;
1188 reg |= val;
1189 outl(reg | val, emu->port + A_IOCFG);
1190 }
1191 }
1192 reg = inl(emu->port + HCFG);
1193 val = ucontrol->value.integer.value[0] ? HCFG_GPOUT0 : 0;
1194 change |= (reg & HCFG_GPOUT0) != val;
1195 if (change) {
1196 reg &= ~HCFG_GPOUT0;
1197 reg |= val;
1198 outl(reg | val, emu->port + HCFG);
1199 }
1200 spin_unlock_irqrestore(&emu->reg_lock, flags);
1201 return change;
1202}
1203
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001204static struct snd_kcontrol_new snd_emu10k1_shared_spdif __devinitdata =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205{
1206 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1207 .name = "SB Live Analog/Digital Output Jack",
1208 .info = snd_emu10k1_shared_spdif_info,
1209 .get = snd_emu10k1_shared_spdif_get,
1210 .put = snd_emu10k1_shared_spdif_put
1211};
1212
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001213static struct snd_kcontrol_new snd_audigy_shared_spdif __devinitdata =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214{
1215 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1216 .name = "Audigy Analog/Digital Output Jack",
1217 .info = snd_emu10k1_shared_spdif_info,
1218 .get = snd_emu10k1_shared_spdif_get,
1219 .put = snd_emu10k1_shared_spdif_put
1220};
1221
1222/*
1223 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001224static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001226 struct snd_emu10k1 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 emu->ac97 = NULL;
1228}
1229
1230/*
1231 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001232static int remove_ctl(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001234 struct snd_ctl_elem_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 memset(&id, 0, sizeof(id));
1236 strcpy(id.name, name);
1237 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1238 return snd_ctl_remove_id(card, &id);
1239}
1240
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001241static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001243 struct snd_ctl_elem_id sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 memset(&sid, 0, sizeof(sid));
1245 strcpy(sid.name, name);
1246 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1247 return snd_ctl_find_id(card, &sid);
1248}
1249
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001250static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001252 struct snd_kcontrol *kctl = ctl_find(card, src);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 if (kctl) {
1254 strcpy(kctl->id.name, dst);
1255 return 0;
1256 }
1257 return -ENOENT;
1258}
1259
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001260int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001261 int pcm_device, int multi_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262{
1263 int err, pcm;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001264 struct snd_kcontrol *kctl;
1265 struct snd_card *card = emu->card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 char **c;
1267 static char *emu10k1_remove_ctls[] = {
1268 /* no AC97 mono, surround, center/lfe */
1269 "Master Mono Playback Switch",
1270 "Master Mono Playback Volume",
1271 "PCM Out Path & Mute",
1272 "Mono Output Select",
Takashi Iwai7eae36f2006-01-05 18:40:56 +01001273 "Front Playback Switch",
1274 "Front Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 "Surround Playback Switch",
1276 "Surround Playback Volume",
1277 "Center Playback Switch",
1278 "Center Playback Volume",
1279 "LFE Playback Switch",
1280 "LFE Playback Volume",
1281 NULL
1282 };
1283 static char *emu10k1_rename_ctls[] = {
1284 "Surround Digital Playback Volume", "Surround Playback Volume",
1285 "Center Digital Playback Volume", "Center Playback Volume",
1286 "LFE Digital Playback Volume", "LFE Playback Volume",
1287 NULL
1288 };
1289 static char *audigy_remove_ctls[] = {
1290 /* Master/PCM controls on ac97 of Audigy has no effect */
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001291 /* On the Audigy2 the AC97 playback is piped into
1292 * the Philips ADC for 24bit capture */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 "PCM Playback Switch",
1294 "PCM Playback Volume",
1295 "Master Mono Playback Switch",
1296 "Master Mono Playback Volume",
1297 "Master Playback Switch",
1298 "Master Playback Volume",
1299 "PCM Out Path & Mute",
1300 "Mono Output Select",
1301 /* remove unused AC97 capture controls */
1302 "Capture Source",
1303 "Capture Switch",
1304 "Capture Volume",
1305 "Mic Select",
1306 "Video Playback Switch",
1307 "Video Playback Volume",
1308 "Mic Playback Switch",
1309 "Mic Playback Volume",
1310 NULL
1311 };
1312 static char *audigy_rename_ctls[] = {
1313 /* use conventional names */
1314 "Wave Playback Volume", "PCM Playback Volume",
1315 /* "Wave Capture Volume", "PCM Capture Volume", */
1316 "Wave Master Playback Volume", "Master Playback Volume",
1317 "AMic Playback Volume", "Mic Playback Volume",
1318 NULL
1319 };
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001320 static char *audigy_remove_ctls_1361t_adc[] = {
1321 /* On the Audigy2 the AC97 playback is piped into
1322 * the Philips ADC for 24bit capture */
1323 "PCM Playback Switch",
1324 "PCM Playback Volume",
1325 "Master Mono Playback Switch",
1326 "Master Mono Playback Volume",
1327 "Capture Source",
1328 "Capture Switch",
1329 "Capture Volume",
1330 "Mic Capture Volume",
1331 "Headphone Playback Switch",
1332 "Headphone Playback Volume",
1333 "3D Control - Center",
1334 "3D Control - Depth",
1335 "3D Control - Switch",
1336 "Line2 Playback Volume",
1337 "Line2 Capture Volume",
1338 NULL
1339 };
1340 static char *audigy_rename_ctls_1361t_adc[] = {
1341 "Master Playback Switch", "Master Capture Switch",
1342 "Master Playback Volume", "Master Capture Volume",
1343 "Wave Master Playback Volume", "Master Playback Volume",
1344 "PC Speaker Playback Switch", "PC Speaker Capture Switch",
1345 "PC Speaker Playback Volume", "PC Speaker Capture Volume",
1346 "Phone Playback Switch", "Phone Capture Switch",
1347 "Phone Playback Volume", "Phone Capture Volume",
1348 "Mic Playback Switch", "Mic Capture Switch",
1349 "Mic Playback Volume", "Mic Capture Volume",
1350 "Line Playback Switch", "Line Capture Switch",
1351 "Line Playback Volume", "Line Capture Volume",
1352 "CD Playback Switch", "CD Capture Switch",
1353 "CD Playback Volume", "CD Capture Volume",
1354 "Aux Playback Switch", "Aux Capture Switch",
1355 "Aux Playback Volume", "Aux Capture Volume",
1356 "Video Playback Switch", "Video Capture Switch",
1357 "Video Playback Volume", "Video Capture Volume",
1358
1359 NULL
1360 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361
Lee Revell2b637da2005-03-30 13:51:18 +02001362 if (emu->card_capabilities->ac97_chip) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001363 struct snd_ac97_bus *pbus;
1364 struct snd_ac97_template ac97;
1365 static struct snd_ac97_bus_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 .write = snd_emu10k1_ac97_write,
1367 .read = snd_emu10k1_ac97_read,
1368 };
1369
Takashi Iwaib1508692005-10-04 13:49:32 +02001370 if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0)
1371 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 pbus->no_vra = 1; /* we don't need VRA */
1373
1374 memset(&ac97, 0, sizeof(ac97));
1375 ac97.private_data = emu;
1376 ac97.private_free = snd_emu10k1_mixer_free_ac97;
1377 ac97.scaps = AC97_SCAP_NO_SPDIF;
Takashi Iwaib1508692005-10-04 13:49:32 +02001378 if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) {
1379 if (emu->card_capabilities->ac97_chip == 1)
1380 return err;
1381 snd_printd(KERN_INFO "emu10k1: AC97 is optional on this board\n");
1382 snd_printd(KERN_INFO" Proceeding without ac97 mixers...\n");
1383 snd_device_free(emu->card, pbus);
1384 goto no_ac97; /* FIXME: get rid of ugly gotos.. */
1385 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386 if (emu->audigy) {
1387 /* set master volume to 0 dB */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001388 snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 /* set capture source to mic */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001390 snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001391 if (emu->card_capabilities->adc_1361t)
1392 c = audigy_remove_ctls_1361t_adc;
1393 else
1394 c = audigy_remove_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 } else {
1396 /*
1397 * Credits for cards based on STAC9758:
1398 * James Courtier-Dutton <James@superbug.demon.co.uk>
1399 * Voluspa <voluspa@comhem.se>
1400 */
1401 if (emu->ac97->id == AC97_ID_STAC9758) {
1402 emu->rear_ac97 = 1;
1403 snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT);
1404 }
1405 /* remove unused AC97 controls */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001406 snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
1407 snd_ac97_write_cache(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 c = emu10k1_remove_ctls;
1409 }
1410 for (; *c; c++)
1411 remove_ctl(card, *c);
1412 } else {
Takashi Iwaif12aa402005-09-30 16:56:59 +02001413 no_ac97:
Lee Revell2b637da2005-03-30 13:51:18 +02001414 if (emu->card_capabilities->ecard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 strcpy(emu->card->mixername, "EMU APS");
1416 else if (emu->audigy)
1417 strcpy(emu->card->mixername, "SB Audigy");
1418 else
1419 strcpy(emu->card->mixername, "Emu10k1");
1420 }
1421
1422 if (emu->audigy)
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001423 if (emu->card_capabilities->adc_1361t)
1424 c = audigy_rename_ctls_1361t_adc;
1425 else
1426 c = audigy_rename_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 else
1428 c = emu10k1_rename_ctls;
1429 for (; *c; c += 2)
1430 rename_ctl(card, c[0], c[1]);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001431
James Courtier-Duttone3b9bc02005-12-24 16:54:51 +01001432 if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */
1433 rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume");
1434 rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume");
1435 rename_ctl(card, "Aux2 Capture Volume", "Line3 Capture Volume");
1436 rename_ctl(card, "Mic Capture Volume", "Unknown1 Capture Volume");
1437 remove_ctl(card, "Headphone Playback Switch");
1438 remove_ctl(card, "Headphone Playback Volume");
1439 remove_ctl(card, "3D Control - Center");
1440 remove_ctl(card, "3D Control - Depth");
1441 remove_ctl(card, "3D Control - Switch");
1442 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL)
1444 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001445 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 if ((err = snd_ctl_add(card, kctl)))
1447 return err;
1448 if ((kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL)
1449 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001450 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 if ((err = snd_ctl_add(card, kctl)))
1452 return err;
1453 if ((kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu)) == NULL)
1454 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001455 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 if ((err = snd_ctl_add(card, kctl)))
1457 return err;
1458
1459 if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL)
1460 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001461 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 if ((err = snd_ctl_add(card, kctl)))
1463 return err;
1464
1465 if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL)
1466 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001467 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 if ((err = snd_ctl_add(card, kctl)))
1469 return err;
1470
1471 if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL)
1472 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001473 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 if ((err = snd_ctl_add(card, kctl)))
1475 return err;
1476
1477 /* initialize the routing and volume table for each pcm playback stream */
1478 for (pcm = 0; pcm < 32; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001479 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 int v;
1481
1482 mix = &emu->pcm_mixer[pcm];
1483 mix->epcm = NULL;
1484
1485 for (v = 0; v < 4; v++)
1486 mix->send_routing[0][v] =
1487 mix->send_routing[1][v] =
1488 mix->send_routing[2][v] = v;
1489
1490 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1491 mix->send_volume[0][0] = mix->send_volume[0][1] =
1492 mix->send_volume[1][0] = mix->send_volume[2][1] = 255;
1493
1494 mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
1495 }
1496
1497 /* initialize the routing and volume table for the multichannel playback stream */
1498 for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001499 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 int v;
1501
1502 mix = &emu->efx_pcm_mixer[pcm];
1503 mix->epcm = NULL;
1504
1505 mix->send_routing[0][0] = pcm;
1506 mix->send_routing[0][1] = (pcm == 0) ? 1 : 0;
1507 for (v = 0; v < 2; v++)
1508 mix->send_routing[0][2+v] = 13+v;
1509 if (emu->audigy)
1510 for (v = 0; v < 4; v++)
1511 mix->send_routing[0][4+v] = 60+v;
1512
1513 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1514 mix->send_volume[0][0] = 255;
1515
1516 mix->attn[0] = 0xffff;
1517 }
1518
Lee Revell2b637da2005-03-30 13:51:18 +02001519 if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 /* sb live! and audigy */
1521 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
1522 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02001523 if (!emu->audigy)
1524 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525 if ((err = snd_ctl_add(card, kctl)))
1526 return err;
1527 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
1528 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02001529 if (!emu->audigy)
1530 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531 if ((err = snd_ctl_add(card, kctl)))
1532 return err;
1533 }
1534
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001535 if ( emu->card_capabilities->emu1010) {
James Courtier-Dutton19b99fb2005-12-04 18:03:03 +01001536 ; /* Disable the snd_audigy_spdif_shared_spdif */
1537 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
1539 return -ENOMEM;
1540 if ((err = snd_ctl_add(card, kctl)))
1541 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02001542#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
1544 return -ENOMEM;
1545 if ((err = snd_ctl_add(card, kctl)))
1546 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02001547#endif
Lee Revell2b637da2005-03-30 13:51:18 +02001548 } else if (! emu->card_capabilities->ecard) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 /* sb live! */
1550 if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
1551 return -ENOMEM;
1552 if ((err = snd_ctl_add(card, kctl)))
1553 return err;
1554 }
Lee Revell2b637da2005-03-30 13:51:18 +02001555 if (emu->card_capabilities->ca0151_chip) { /* P16V */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 if ((err = snd_p16v_mixer(emu)))
1557 return err;
1558 }
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001559
1560 if ( emu->card_capabilities->emu1010) {
1561 int i;
1562
1563 for (i = 0; i < ARRAY_SIZE(snd_emu1010_output_enum_ctls); i++) {
1564 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_output_enum_ctls[i], emu));
1565 if (err < 0)
1566 return err;
1567 }
1568 for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) {
1569 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], emu));
1570 if (err < 0)
1571 return err;
1572 }
James Courtier-Dutton9148cc52006-10-09 23:08:00 +01001573 for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads); i++) {
1574 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_adc_pads[i], emu));
1575 if (err < 0)
1576 return err;
1577 }
1578 for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads); i++) {
1579 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_dac_pads[i], emu));
1580 if (err < 0)
1581 return err;
1582 }
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +01001583 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_internal_clock, emu));
1584 if (err < 0)
1585 return err;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001586 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587
1588 return 0;
1589}