blob: 7b2c1dcc53376c76dbdd61928d2b8574043a51c4 [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>
James Courtier-Dutton184c1e22006-12-06 15:58:02 +000039#include <sound/tlv.h>
40
41#include "p17v.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
43#define AC97_ID_STAC9758 0x83847658
44
Takashi Iwai0cb29ea2007-01-29 15:33:49 +010045static const DECLARE_TLV_DB_SCALE(snd_audigy_db_scale2, -10350, 50, 1); /* WM8775 gain scale */
James Courtier-Dutton184c1e22006-12-06 15:58:02 +000046
Takashi Iwaieb4698f2005-11-17 14:50:13 +010047static int snd_emu10k1_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -070048{
49 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
50 uinfo->count = 1;
51 return 0;
52}
53
Takashi Iwaieb4698f2005-11-17 14:50:13 +010054static int snd_emu10k1_spdif_get(struct snd_kcontrol *kcontrol,
55 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -070056{
Takashi Iwaieb4698f2005-11-17 14:50:13 +010057 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -070058 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
59 unsigned long flags;
60
61 spin_lock_irqsave(&emu->reg_lock, flags);
62 ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff;
63 ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff;
64 ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff;
65 ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff;
66 spin_unlock_irqrestore(&emu->reg_lock, flags);
67 return 0;
68}
69
Takashi Iwaieb4698f2005-11-17 14:50:13 +010070static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol,
71 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -070072{
73 ucontrol->value.iec958.status[0] = 0xff;
74 ucontrol->value.iec958.status[1] = 0xff;
75 ucontrol->value.iec958.status[2] = 0xff;
76 ucontrol->value.iec958.status[3] = 0xff;
77 return 0;
78}
79
Pavel Hofman13d45702007-06-11 12:21:20 +020080/*
81 * Items labels in enum mixer controls assigning source data to
82 * each destination
83 */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +010084static char *emu1010_src_texts[] = {
85 "Silence",
86 "Dock Mic A",
87 "Dock Mic B",
88 "Dock ADC1 Left",
89 "Dock ADC1 Right",
90 "Dock ADC2 Left",
91 "Dock ADC2 Right",
92 "Dock ADC3 Left",
93 "Dock ADC3 Right",
94 "0202 ADC Left",
95 "0202 ADC Right",
96 "0202 SPDIF Left",
97 "0202 SPDIF Right",
98 "ADAT 0",
99 "ADAT 1",
100 "ADAT 2",
101 "ADAT 3",
102 "ADAT 4",
103 "ADAT 5",
104 "ADAT 6",
105 "ADAT 7",
106 "DSP 0",
107 "DSP 1",
108 "DSP 2",
109 "DSP 3",
110 "DSP 4",
111 "DSP 5",
112 "DSP 6",
113 "DSP 7",
114 "DSP 8",
115 "DSP 9",
116 "DSP 10",
117 "DSP 11",
118 "DSP 12",
119 "DSP 13",
120 "DSP 14",
121 "DSP 15",
122 "DSP 16",
123 "DSP 17",
124 "DSP 18",
125 "DSP 19",
126 "DSP 20",
127 "DSP 21",
128 "DSP 22",
129 "DSP 23",
130 "DSP 24",
131 "DSP 25",
132 "DSP 26",
133 "DSP 27",
134 "DSP 28",
135 "DSP 29",
136 "DSP 30",
137 "DSP 31",
138};
139
Pavel Hofman13d45702007-06-11 12:21:20 +0200140/*
141 * List of data sources available for each destination
142 */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100143static unsigned int emu1010_src_regs[] = {
144 EMU_SRC_SILENCE,/* 0 */
145 EMU_SRC_DOCK_MIC_A1, /* 1 */
146 EMU_SRC_DOCK_MIC_B1, /* 2 */
147 EMU_SRC_DOCK_ADC1_LEFT1, /* 3 */
148 EMU_SRC_DOCK_ADC1_RIGHT1, /* 4 */
149 EMU_SRC_DOCK_ADC2_LEFT1, /* 5 */
150 EMU_SRC_DOCK_ADC2_RIGHT1, /* 6 */
151 EMU_SRC_DOCK_ADC3_LEFT1, /* 7 */
152 EMU_SRC_DOCK_ADC3_RIGHT1, /* 8 */
153 EMU_SRC_HAMOA_ADC_LEFT1, /* 9 */
154 EMU_SRC_HAMOA_ADC_RIGHT1, /* 10 */
155 EMU_SRC_HANA_SPDIF_LEFT1, /* 11 */
156 EMU_SRC_HANA_SPDIF_RIGHT1, /* 12 */
157 EMU_SRC_HANA_ADAT, /* 13 */
158 EMU_SRC_HANA_ADAT+1, /* 14 */
159 EMU_SRC_HANA_ADAT+2, /* 15 */
160 EMU_SRC_HANA_ADAT+3, /* 16 */
161 EMU_SRC_HANA_ADAT+4, /* 17 */
162 EMU_SRC_HANA_ADAT+5, /* 18 */
163 EMU_SRC_HANA_ADAT+6, /* 19 */
164 EMU_SRC_HANA_ADAT+7, /* 20 */
165 EMU_SRC_ALICE_EMU32A, /* 21 */
166 EMU_SRC_ALICE_EMU32A+1, /* 22 */
167 EMU_SRC_ALICE_EMU32A+2, /* 23 */
168 EMU_SRC_ALICE_EMU32A+3, /* 24 */
169 EMU_SRC_ALICE_EMU32A+4, /* 25 */
170 EMU_SRC_ALICE_EMU32A+5, /* 26 */
171 EMU_SRC_ALICE_EMU32A+6, /* 27 */
172 EMU_SRC_ALICE_EMU32A+7, /* 28 */
173 EMU_SRC_ALICE_EMU32A+8, /* 29 */
174 EMU_SRC_ALICE_EMU32A+9, /* 30 */
175 EMU_SRC_ALICE_EMU32A+0xa, /* 31 */
176 EMU_SRC_ALICE_EMU32A+0xb, /* 32 */
177 EMU_SRC_ALICE_EMU32A+0xc, /* 33 */
178 EMU_SRC_ALICE_EMU32A+0xd, /* 34 */
179 EMU_SRC_ALICE_EMU32A+0xe, /* 35 */
180 EMU_SRC_ALICE_EMU32A+0xf, /* 36 */
181 EMU_SRC_ALICE_EMU32B, /* 37 */
182 EMU_SRC_ALICE_EMU32B+1, /* 38 */
183 EMU_SRC_ALICE_EMU32B+2, /* 39 */
184 EMU_SRC_ALICE_EMU32B+3, /* 40 */
185 EMU_SRC_ALICE_EMU32B+4, /* 41 */
186 EMU_SRC_ALICE_EMU32B+5, /* 42 */
187 EMU_SRC_ALICE_EMU32B+6, /* 43 */
188 EMU_SRC_ALICE_EMU32B+7, /* 44 */
189 EMU_SRC_ALICE_EMU32B+8, /* 45 */
190 EMU_SRC_ALICE_EMU32B+9, /* 46 */
191 EMU_SRC_ALICE_EMU32B+0xa, /* 47 */
192 EMU_SRC_ALICE_EMU32B+0xb, /* 48 */
193 EMU_SRC_ALICE_EMU32B+0xc, /* 49 */
194 EMU_SRC_ALICE_EMU32B+0xd, /* 50 */
195 EMU_SRC_ALICE_EMU32B+0xe, /* 51 */
196 EMU_SRC_ALICE_EMU32B+0xf, /* 52 */
197};
198
Pavel Hofman13d45702007-06-11 12:21:20 +0200199/*
200 * Data destinations - physical EMU outputs.
201 * Each destination has an enum mixer control to choose a data source
202 */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100203static unsigned int emu1010_output_dst[] = {
204 EMU_DST_DOCK_DAC1_LEFT1, /* 0 */
205 EMU_DST_DOCK_DAC1_RIGHT1, /* 1 */
206 EMU_DST_DOCK_DAC2_LEFT1, /* 2 */
207 EMU_DST_DOCK_DAC2_RIGHT1, /* 3 */
208 EMU_DST_DOCK_DAC3_LEFT1, /* 4 */
209 EMU_DST_DOCK_DAC3_RIGHT1, /* 5 */
210 EMU_DST_DOCK_DAC4_LEFT1, /* 6 */
211 EMU_DST_DOCK_DAC4_RIGHT1, /* 7 */
212 EMU_DST_DOCK_PHONES_LEFT1, /* 8 */
213 EMU_DST_DOCK_PHONES_RIGHT1, /* 9 */
214 EMU_DST_DOCK_SPDIF_LEFT1, /* 10 */
215 EMU_DST_DOCK_SPDIF_RIGHT1, /* 11 */
216 EMU_DST_HANA_SPDIF_LEFT1, /* 12 */
217 EMU_DST_HANA_SPDIF_RIGHT1, /* 13 */
218 EMU_DST_HAMOA_DAC_LEFT1, /* 14 */
219 EMU_DST_HAMOA_DAC_RIGHT1, /* 15 */
220 EMU_DST_HANA_ADAT, /* 16 */
221 EMU_DST_HANA_ADAT+1, /* 17 */
222 EMU_DST_HANA_ADAT+2, /* 18 */
223 EMU_DST_HANA_ADAT+3, /* 19 */
224 EMU_DST_HANA_ADAT+4, /* 20 */
225 EMU_DST_HANA_ADAT+5, /* 21 */
226 EMU_DST_HANA_ADAT+6, /* 22 */
227 EMU_DST_HANA_ADAT+7, /* 23 */
228};
229
Pavel Hofman13d45702007-06-11 12:21:20 +0200230/*
231 * Data destinations - HANA outputs going to Alice2 (audigy) for
232 * capture (EMU32 + I2S links)
233 * Each destination has an enum mixer control to choose a data source
234 */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100235static unsigned int emu1010_input_dst[] = {
236 EMU_DST_ALICE2_EMU32_0,
237 EMU_DST_ALICE2_EMU32_1,
238 EMU_DST_ALICE2_EMU32_2,
239 EMU_DST_ALICE2_EMU32_3,
240 EMU_DST_ALICE2_EMU32_4,
241 EMU_DST_ALICE2_EMU32_5,
242 EMU_DST_ALICE2_EMU32_6,
243 EMU_DST_ALICE2_EMU32_7,
244 EMU_DST_ALICE2_EMU32_8,
245 EMU_DST_ALICE2_EMU32_9,
246 EMU_DST_ALICE2_EMU32_A,
247 EMU_DST_ALICE2_EMU32_B,
248 EMU_DST_ALICE2_EMU32_C,
249 EMU_DST_ALICE2_EMU32_D,
250 EMU_DST_ALICE2_EMU32_E,
251 EMU_DST_ALICE2_EMU32_F,
252 EMU_DST_ALICE_I2S0_LEFT,
253 EMU_DST_ALICE_I2S0_RIGHT,
254 EMU_DST_ALICE_I2S1_LEFT,
255 EMU_DST_ALICE_I2S1_RIGHT,
256 EMU_DST_ALICE_I2S2_LEFT,
257 EMU_DST_ALICE_I2S2_RIGHT,
258};
259
260static int snd_emu1010_input_output_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
261{
262 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
263 uinfo->count = 1;
264 uinfo->value.enumerated.items = 53;
265 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
266 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
267 strcpy(uinfo->value.enumerated.name, emu1010_src_texts[uinfo->value.enumerated.item]);
268 return 0;
269}
270
271static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol,
272 struct snd_ctl_elem_value *ucontrol)
273{
274 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
275 int channel;
276
277 channel = (kcontrol->private_value) & 0xff;
278 ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel];
279 return 0;
280}
281
282static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol,
283 struct snd_ctl_elem_value *ucontrol)
284{
285 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
286 int change = 0;
287 unsigned int val;
288 int channel;
289
290 channel = (kcontrol->private_value) & 0xff;
291 if (emu->emu1010.output_source[channel] != ucontrol->value.enumerated.item[0]) {
292 val = emu->emu1010.output_source[channel] = ucontrol->value.enumerated.item[0];
293 change = 1;
294 snd_emu1010_fpga_link_dst_src_write(emu,
295 emu1010_output_dst[channel], emu1010_src_regs[val]);
296 }
297 return change;
298}
299
300static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol,
301 struct snd_ctl_elem_value *ucontrol)
302{
303 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
304 int channel;
305
306 channel = (kcontrol->private_value) & 0xff;
307 ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel];
308 return 0;
309}
310
311static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
312 struct snd_ctl_elem_value *ucontrol)
313{
314 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
315 int change = 0;
316 unsigned int val;
317 int channel;
318
319 channel = (kcontrol->private_value) & 0xff;
320 if (emu->emu1010.input_source[channel] != ucontrol->value.enumerated.item[0]) {
321 val = emu->emu1010.input_source[channel] = ucontrol->value.enumerated.item[0];
322 change = 1;
323 snd_emu1010_fpga_link_dst_src_write(emu,
324 emu1010_input_dst[channel], emu1010_src_regs[val]);
325 }
326 return change;
327}
328
329#define EMU1010_SOURCE_OUTPUT(xname,chid) \
330{ \
331 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
332 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
333 .info = snd_emu1010_input_output_source_info, \
334 .get = snd_emu1010_output_source_get, \
335 .put = snd_emu1010_output_source_put, \
336 .private_value = chid \
337}
338
339static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = {
James Courtier-Dutton4c07c812006-11-11 10:48:58 +0000340 EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0),
341 EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1),
342 EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2),
343 EMU1010_SOURCE_OUTPUT("Dock DAC2 Right Playback Enum", 3),
344 EMU1010_SOURCE_OUTPUT("Dock DAC3 Left Playback Enum", 4),
345 EMU1010_SOURCE_OUTPUT("Dock DAC3 Right Playback Enum", 5),
346 EMU1010_SOURCE_OUTPUT("Dock DAC4 Left Playback Enum", 6),
347 EMU1010_SOURCE_OUTPUT("Dock DAC4 Right Playback Enum", 7),
348 EMU1010_SOURCE_OUTPUT("Dock Phones Left Playback Enum", 8),
349 EMU1010_SOURCE_OUTPUT("Dock Phones Right Playback Enum", 9),
350 EMU1010_SOURCE_OUTPUT("Dock SPDIF Left Playback Enum", 0xa),
351 EMU1010_SOURCE_OUTPUT("Dock SPDIF Right Playback Enum", 0xb),
352 EMU1010_SOURCE_OUTPUT("1010 SPDIF Left Playback Enum", 0xc),
353 EMU1010_SOURCE_OUTPUT("1010 SPDIF Right Playback Enum", 0xd),
354 EMU1010_SOURCE_OUTPUT("0202 DAC Left Playback Enum", 0xe),
355 EMU1010_SOURCE_OUTPUT("0202 DAC Right Playback Enum", 0xf),
356 EMU1010_SOURCE_OUTPUT("1010 ADAT 0 Playback Enum", 0x10),
357 EMU1010_SOURCE_OUTPUT("1010 ADAT 1 Playback Enum", 0x11),
358 EMU1010_SOURCE_OUTPUT("1010 ADAT 2 Playback Enum", 0x12),
359 EMU1010_SOURCE_OUTPUT("1010 ADAT 3 Playback Enum", 0x13),
360 EMU1010_SOURCE_OUTPUT("1010 ADAT 4 Playback Enum", 0x14),
361 EMU1010_SOURCE_OUTPUT("1010 ADAT 5 Playback Enum", 0x15),
362 EMU1010_SOURCE_OUTPUT("1010 ADAT 6 Playback Enum", 0x16),
363 EMU1010_SOURCE_OUTPUT("1010 ADAT 7 Playback Enum", 0x17),
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100364};
365
366#define EMU1010_SOURCE_INPUT(xname,chid) \
367{ \
368 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
369 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
370 .info = snd_emu1010_input_output_source_info, \
371 .get = snd_emu1010_input_source_get, \
372 .put = snd_emu1010_input_source_put, \
373 .private_value = chid \
374}
375
376static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] __devinitdata = {
James Courtier-Dutton4c07c812006-11-11 10:48:58 +0000377 EMU1010_SOURCE_INPUT("DSP 0 Capture Enum", 0),
378 EMU1010_SOURCE_INPUT("DSP 1 Capture Enum", 1),
379 EMU1010_SOURCE_INPUT("DSP 2 Capture Enum", 2),
380 EMU1010_SOURCE_INPUT("DSP 3 Capture Enum", 3),
381 EMU1010_SOURCE_INPUT("DSP 4 Capture Enum", 4),
382 EMU1010_SOURCE_INPUT("DSP 5 Capture Enum", 5),
383 EMU1010_SOURCE_INPUT("DSP 6 Capture Enum", 6),
384 EMU1010_SOURCE_INPUT("DSP 7 Capture Enum", 7),
385 EMU1010_SOURCE_INPUT("DSP 8 Capture Enum", 8),
386 EMU1010_SOURCE_INPUT("DSP 9 Capture Enum", 9),
387 EMU1010_SOURCE_INPUT("DSP A Capture Enum", 0xa),
388 EMU1010_SOURCE_INPUT("DSP B Capture Enum", 0xb),
389 EMU1010_SOURCE_INPUT("DSP C Capture Enum", 0xc),
390 EMU1010_SOURCE_INPUT("DSP D Capture Enum", 0xd),
391 EMU1010_SOURCE_INPUT("DSP E Capture Enum", 0xe),
392 EMU1010_SOURCE_INPUT("DSP F Capture Enum", 0xf),
393 EMU1010_SOURCE_INPUT("DSP 10 Capture Enum", 0x10),
394 EMU1010_SOURCE_INPUT("DSP 11 Capture Enum", 0x11),
395 EMU1010_SOURCE_INPUT("DSP 12 Capture Enum", 0x12),
396 EMU1010_SOURCE_INPUT("DSP 13 Capture Enum", 0x13),
397 EMU1010_SOURCE_INPUT("DSP 14 Capture Enum", 0x14),
398 EMU1010_SOURCE_INPUT("DSP 15 Capture Enum", 0x15),
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100399};
400
401
402
403
404static int snd_emu1010_adc_pads_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
405{
406 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
407 uinfo->count = 1;
408 uinfo->value.integer.min = 0;
409 uinfo->value.integer.max = 1;
410 return 0;
411}
412
413static int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
414{
415 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
416 unsigned int mask = kcontrol->private_value & 0xff;
417 ucontrol->value.integer.value[0] = (emu->emu1010.adc_pads & mask) ? 1 : 0;
418 return 0;
419}
420
421static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
422{
423 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
424 unsigned int mask = kcontrol->private_value & 0xff;
425 unsigned int val, cache;
426 val = ucontrol->value.integer.value[0];
427 cache = emu->emu1010.adc_pads;
428 if (val == 1)
429 cache = cache | mask;
430 else
431 cache = cache & ~mask;
432 if (cache != emu->emu1010.adc_pads) {
433 snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache );
434 emu->emu1010.adc_pads = cache;
435 }
436
437 return 0;
438}
439
440
441
442#define EMU1010_ADC_PADS(xname,chid) \
443{ \
444 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
445 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
446 .info = snd_emu1010_adc_pads_info, \
447 .get = snd_emu1010_adc_pads_get, \
448 .put = snd_emu1010_adc_pads_put, \
449 .private_value = chid \
450}
451
452static struct snd_kcontrol_new snd_emu1010_adc_pads[] __devinitdata = {
453 EMU1010_ADC_PADS("ADC1 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD1),
454 EMU1010_ADC_PADS("ADC2 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD2),
455 EMU1010_ADC_PADS("ADC3 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD3),
456 EMU1010_ADC_PADS("ADC1 14dB PAD 0202 Capture Switch", EMU_HANA_0202_ADC_PAD1),
457};
458
459static int snd_emu1010_dac_pads_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
460{
461 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
462 uinfo->count = 1;
463 uinfo->value.integer.min = 0;
464 uinfo->value.integer.max = 1;
465 return 0;
466}
467
468static int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
469{
470 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
471 unsigned int mask = kcontrol->private_value & 0xff;
472 ucontrol->value.integer.value[0] = (emu->emu1010.dac_pads & mask) ? 1 : 0;
473 return 0;
474}
475
476static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
477{
478 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
479 unsigned int mask = kcontrol->private_value & 0xff;
480 unsigned int val, cache;
481 val = ucontrol->value.integer.value[0];
482 cache = emu->emu1010.dac_pads;
483 if (val == 1)
484 cache = cache | mask;
485 else
486 cache = cache & ~mask;
487 if (cache != emu->emu1010.dac_pads) {
488 snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache );
489 emu->emu1010.dac_pads = cache;
490 }
491
492 return 0;
493}
494
495
496
497#define EMU1010_DAC_PADS(xname,chid) \
498{ \
499 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
500 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
501 .info = snd_emu1010_dac_pads_info, \
502 .get = snd_emu1010_dac_pads_get, \
503 .put = snd_emu1010_dac_pads_put, \
504 .private_value = chid \
505}
506
507static struct snd_kcontrol_new snd_emu1010_dac_pads[] __devinitdata = {
508 EMU1010_DAC_PADS("DAC1 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD1),
509 EMU1010_DAC_PADS("DAC2 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD2),
510 EMU1010_DAC_PADS("DAC3 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD3),
511 EMU1010_DAC_PADS("DAC4 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD4),
512 EMU1010_DAC_PADS("DAC1 0202 14dB PAD Playback Switch", EMU_HANA_0202_DAC_PAD1),
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100513};
514
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100515
516static int snd_emu1010_internal_clock_info(struct snd_kcontrol *kcontrol,
517 struct snd_ctl_elem_info *uinfo)
518{
519 static char *texts[2] = {
520 "44100", "48000"
521 };
522
523 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
524 uinfo->count = 1;
525 uinfo->value.enumerated.items = 2;
526 if (uinfo->value.enumerated.item > 1)
527 uinfo->value.enumerated.item = 1;
528 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
529 return 0;
530}
531
532static int snd_emu1010_internal_clock_get(struct snd_kcontrol *kcontrol,
533 struct snd_ctl_elem_value *ucontrol)
534{
535 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
536
537 ucontrol->value.enumerated.item[0] = emu->emu1010.internal_clock;
538 return 0;
539}
540
541static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol,
542 struct snd_ctl_elem_value *ucontrol)
543{
544 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
545 unsigned int val;
546 int change = 0;
547
548 val = ucontrol->value.enumerated.item[0] ;
549 change = (emu->emu1010.internal_clock != val);
550 if (change) {
551 emu->emu1010.internal_clock = val;
552 switch (val) {
553 case 0:
554 /* 44100 */
555 /* Mute all */
556 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
557 /* Default fallback clock 48kHz */
558 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_44_1K );
559 /* Word Clock source, Internal 44.1kHz x1 */
560 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
561 EMU_HANA_WCLOCK_INT_44_1K | EMU_HANA_WCLOCK_1X );
562 /* Set LEDs on Audio Dock */
563 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
564 EMU_HANA_DOCK_LEDS_2_44K | EMU_HANA_DOCK_LEDS_2_LOCK );
565 /* Allow DLL to settle */
James Courtier-Duttone40a0b22006-10-10 18:44:29 +0100566 msleep(10);
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100567 /* Unmute all */
568 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
569 break;
570 case 1:
571 /* 48000 */
572 /* Mute all */
573 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
574 /* Default fallback clock 48kHz */
575 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
576 /* Word Clock source, Internal 48kHz x1 */
577 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
578 EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_1X );
579 /* Set LEDs on Audio Dock */
580 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
581 EMU_HANA_DOCK_LEDS_2_48K | EMU_HANA_DOCK_LEDS_2_LOCK );
582 /* Allow DLL to settle */
James Courtier-Duttone40a0b22006-10-10 18:44:29 +0100583 msleep(10);
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100584 /* Unmute all */
585 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
586 break;
587 }
588 }
589 return change;
590}
591
592static struct snd_kcontrol_new snd_emu1010_internal_clock =
593{
594 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
595 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
596 .name = "Clock Internal Rate",
597 .count = 1,
598 .info = snd_emu1010_internal_clock_info,
599 .get = snd_emu1010_internal_clock_get,
600 .put = snd_emu1010_internal_clock_put
601};
602
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000603static int snd_audigy_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
604 struct snd_ctl_elem_info *uinfo)
605{
606#if 0
607 static char *texts[4] = {
608 "Unknown1", "Unknown2", "Mic", "Line"
609 };
610#endif
611 static char *texts[2] = {
612 "Mic", "Line"
613 };
614
615 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
616 uinfo->count = 1;
617 uinfo->value.enumerated.items = 2;
618 if (uinfo->value.enumerated.item > 1)
619 uinfo->value.enumerated.item = 1;
620 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
621 return 0;
622}
623
624static int snd_audigy_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
625 struct snd_ctl_elem_value *ucontrol)
626{
627 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
628
629 ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
630 return 0;
631}
632
633static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
634 struct snd_ctl_elem_value *ucontrol)
635{
636 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
637 unsigned int source_id;
638 unsigned int ngain, ogain;
639 u32 gpio;
640 int change = 0;
641 unsigned long flags;
642 u32 source;
643 /* If the capture source has changed,
644 * update the capture volume from the cached value
645 * for the particular source.
646 */
647 source_id = ucontrol->value.enumerated.item[0]; /* Use 2 and 3 */
648 change = (emu->i2c_capture_source != source_id);
649 if (change) {
650 snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */
651 spin_lock_irqsave(&emu->emu_lock, flags);
652 gpio = inl(emu->port + A_IOCFG);
653 if (source_id==0)
654 outl(gpio | 0x4, emu->port + A_IOCFG);
655 else
656 outl(gpio & ~0x4, emu->port + A_IOCFG);
657 spin_unlock_irqrestore(&emu->emu_lock, flags);
658
659 ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
660 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
661 if (ngain != ogain)
662 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
663 ngain = emu->i2c_capture_volume[source_id][1]; /* Right */
664 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
665 if (ngain != ogain)
666 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
667
668 source = 1 << (source_id + 2);
669 snd_emu10k1_i2c_write(emu, ADC_MUX, source); /* Set source */
670 emu->i2c_capture_source = source_id;
671 }
672 return change;
673}
674
675static struct snd_kcontrol_new snd_audigy_i2c_capture_source =
676{
677 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
678 .name = "Capture Source",
679 .info = snd_audigy_i2c_capture_source_info,
680 .get = snd_audigy_i2c_capture_source_get,
681 .put = snd_audigy_i2c_capture_source_put
682};
683
684static int snd_audigy_i2c_volume_info(struct snd_kcontrol *kcontrol,
685 struct snd_ctl_elem_info *uinfo)
686{
687 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
688 uinfo->count = 2;
689 uinfo->value.integer.min = 0;
690 uinfo->value.integer.max = 255;
691 return 0;
692}
693
694static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol,
695 struct snd_ctl_elem_value *ucontrol)
696{
697 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
698 int source_id;
699
700 source_id = kcontrol->private_value;
701
702 ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
703 ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
704 return 0;
705}
706
707static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
708 struct snd_ctl_elem_value *ucontrol)
709{
710 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
711 unsigned int ogain;
712 unsigned int ngain;
713 int source_id;
714 int change = 0;
715
716 source_id = kcontrol->private_value;
717 ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
718 ngain = ucontrol->value.integer.value[0];
719 if (ngain > 0xff)
720 return 0;
721 if (ogain != ngain) {
722 if (emu->i2c_capture_source == source_id)
723 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
724 emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0];
725 change = 1;
726 }
727 ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
728 ngain = ucontrol->value.integer.value[1];
729 if (ngain > 0xff)
730 return 0;
731 if (ogain != ngain) {
732 if (emu->i2c_capture_source == source_id)
733 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
734 emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1];
735 change = 1;
736 }
737
738 return change;
739}
740
741#define I2C_VOLUME(xname,chid) \
742{ \
743 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
744 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
745 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
746 .info = snd_audigy_i2c_volume_info, \
747 .get = snd_audigy_i2c_volume_get, \
748 .put = snd_audigy_i2c_volume_put, \
749 .tlv = { .p = snd_audigy_db_scale2 }, \
750 .private_value = chid \
751}
752
753
754static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] __devinitdata = {
755 I2C_VOLUME("Mic Capture Volume", 0),
756 I2C_VOLUME("Line Capture Volume", 0)
757};
758
Takashi Iwai0af68e52005-04-11 17:03:03 +0200759#if 0
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100760static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761{
762 static char *texts[] = {"44100", "48000", "96000"};
763
764 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
765 uinfo->count = 1;
766 uinfo->value.enumerated.items = 3;
767 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
768 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
769 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
770 return 0;
771}
772
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100773static int snd_audigy_spdif_output_rate_get(struct snd_kcontrol *kcontrol,
774 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100776 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 unsigned int tmp;
778 unsigned long flags;
779
780
781 spin_lock_irqsave(&emu->reg_lock, flags);
782 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
783 switch (tmp & A_SPDIF_RATE_MASK) {
784 case A_SPDIF_44100:
785 ucontrol->value.enumerated.item[0] = 0;
786 break;
787 case A_SPDIF_48000:
788 ucontrol->value.enumerated.item[0] = 1;
789 break;
790 case A_SPDIF_96000:
791 ucontrol->value.enumerated.item[0] = 2;
792 break;
793 default:
794 ucontrol->value.enumerated.item[0] = 1;
795 }
796 spin_unlock_irqrestore(&emu->reg_lock, flags);
797 return 0;
798}
799
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100800static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol,
801 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100803 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 int change;
805 unsigned int reg, val, tmp;
806 unsigned long flags;
807
808 switch(ucontrol->value.enumerated.item[0]) {
809 case 0:
810 val = A_SPDIF_44100;
811 break;
812 case 1:
813 val = A_SPDIF_48000;
814 break;
815 case 2:
816 val = A_SPDIF_96000;
817 break;
818 default:
819 val = A_SPDIF_48000;
820 break;
821 }
822
823
824 spin_lock_irqsave(&emu->reg_lock, flags);
825 reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
826 tmp = reg & ~A_SPDIF_RATE_MASK;
827 tmp |= val;
828 if ((change = (tmp != reg)))
829 snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
830 spin_unlock_irqrestore(&emu->reg_lock, flags);
831 return change;
832}
833
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100834static struct snd_kcontrol_new snd_audigy_spdif_output_rate =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835{
836 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
837 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
838 .name = "Audigy SPDIF Output Sample Rate",
839 .count = 1,
840 .info = snd_audigy_spdif_output_rate_info,
841 .get = snd_audigy_spdif_output_rate_get,
842 .put = snd_audigy_spdif_output_rate_put
843};
Takashi Iwai0af68e52005-04-11 17:03:03 +0200844#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100846static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol,
847 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100849 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
851 int change;
852 unsigned int val;
853 unsigned long flags;
854
855 val = (ucontrol->value.iec958.status[0] << 0) |
856 (ucontrol->value.iec958.status[1] << 8) |
857 (ucontrol->value.iec958.status[2] << 16) |
858 (ucontrol->value.iec958.status[3] << 24);
859 spin_lock_irqsave(&emu->reg_lock, flags);
860 change = val != emu->spdif_bits[idx];
861 if (change) {
862 snd_emu10k1_ptr_write(emu, SPCS0 + idx, 0, val);
863 emu->spdif_bits[idx] = val;
864 }
865 spin_unlock_irqrestore(&emu->reg_lock, flags);
866 return change;
867}
868
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100869static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870{
871 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +0200872 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
874 .count = 4,
875 .info = snd_emu10k1_spdif_info,
876 .get = snd_emu10k1_spdif_get_mask
877};
878
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100879static struct snd_kcontrol_new snd_emu10k1_spdif_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880{
Clemens Ladisch5549d542005-08-03 13:50:30 +0200881 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
883 .count = 4,
884 .info = snd_emu10k1_spdif_info,
885 .get = snd_emu10k1_spdif_get,
886 .put = snd_emu10k1_spdif_put
887};
888
889
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100890static void update_emu10k1_fxrt(struct snd_emu10k1 *emu, int voice, unsigned char *route)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891{
892 if (emu->audigy) {
893 snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
894 snd_emu10k1_compose_audigy_fxrt1(route));
895 snd_emu10k1_ptr_write(emu, A_FXRT2, voice,
896 snd_emu10k1_compose_audigy_fxrt2(route));
897 } else {
898 snd_emu10k1_ptr_write(emu, FXRT, voice,
899 snd_emu10k1_compose_send_routing(route));
900 }
901}
902
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100903static void update_emu10k1_send_volume(struct snd_emu10k1 *emu, int voice, unsigned char *volume)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904{
905 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]);
906 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]);
907 snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, volume[2]);
908 snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, volume[3]);
909 if (emu->audigy) {
910 unsigned int val = ((unsigned int)volume[4] << 24) |
911 ((unsigned int)volume[5] << 16) |
912 ((unsigned int)volume[6] << 8) |
913 (unsigned int)volume[7];
914 snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, val);
915 }
916}
917
918/* PCM stream controls */
919
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100920static int snd_emu10k1_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100922 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
924 uinfo->count = emu->audigy ? 3*8 : 3*4;
925 uinfo->value.integer.min = 0;
926 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
927 return 0;
928}
929
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100930static int snd_emu10k1_send_routing_get(struct snd_kcontrol *kcontrol,
931 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932{
933 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100934 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
935 struct snd_emu10k1_pcm_mixer *mix =
936 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 int voice, idx;
938 int num_efx = emu->audigy ? 8 : 4;
939 int mask = emu->audigy ? 0x3f : 0x0f;
940
941 spin_lock_irqsave(&emu->reg_lock, flags);
942 for (voice = 0; voice < 3; voice++)
943 for (idx = 0; idx < num_efx; idx++)
944 ucontrol->value.integer.value[(voice * num_efx) + idx] =
945 mix->send_routing[voice][idx] & mask;
946 spin_unlock_irqrestore(&emu->reg_lock, flags);
947 return 0;
948}
949
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100950static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol,
951 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952{
953 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100954 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
955 struct snd_emu10k1_pcm_mixer *mix =
956 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 int change = 0, voice, idx, val;
958 int num_efx = emu->audigy ? 8 : 4;
959 int mask = emu->audigy ? 0x3f : 0x0f;
960
961 spin_lock_irqsave(&emu->reg_lock, flags);
962 for (voice = 0; voice < 3; voice++)
963 for (idx = 0; idx < num_efx; idx++) {
964 val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask;
965 if (mix->send_routing[voice][idx] != val) {
966 mix->send_routing[voice][idx] = val;
967 change = 1;
968 }
969 }
970 if (change && mix->epcm) {
971 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
972 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
973 &mix->send_routing[1][0]);
974 update_emu10k1_fxrt(emu, mix->epcm->voices[1]->number,
975 &mix->send_routing[2][0]);
976 } else if (mix->epcm->voices[0]) {
977 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
978 &mix->send_routing[0][0]);
979 }
980 }
981 spin_unlock_irqrestore(&emu->reg_lock, flags);
982 return change;
983}
984
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100985static struct snd_kcontrol_new snd_emu10k1_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986{
987 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +0200988 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 .name = "EMU10K1 PCM Send Routing",
990 .count = 32,
991 .info = snd_emu10k1_send_routing_info,
992 .get = snd_emu10k1_send_routing_get,
993 .put = snd_emu10k1_send_routing_put
994};
995
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100996static int snd_emu10k1_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100998 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1000 uinfo->count = emu->audigy ? 3*8 : 3*4;
1001 uinfo->value.integer.min = 0;
1002 uinfo->value.integer.max = 255;
1003 return 0;
1004}
1005
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001006static int snd_emu10k1_send_volume_get(struct snd_kcontrol *kcontrol,
1007 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008{
1009 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001010 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1011 struct snd_emu10k1_pcm_mixer *mix =
1012 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 int idx;
1014 int num_efx = emu->audigy ? 8 : 4;
1015
1016 spin_lock_irqsave(&emu->reg_lock, flags);
1017 for (idx = 0; idx < 3*num_efx; idx++)
1018 ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx];
1019 spin_unlock_irqrestore(&emu->reg_lock, flags);
1020 return 0;
1021}
1022
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001023static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol,
1024 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025{
1026 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001027 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1028 struct snd_emu10k1_pcm_mixer *mix =
1029 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 int change = 0, idx, val;
1031 int num_efx = emu->audigy ? 8 : 4;
1032
1033 spin_lock_irqsave(&emu->reg_lock, flags);
1034 for (idx = 0; idx < 3*num_efx; idx++) {
1035 val = ucontrol->value.integer.value[idx] & 255;
1036 if (mix->send_volume[idx/num_efx][idx%num_efx] != val) {
1037 mix->send_volume[idx/num_efx][idx%num_efx] = val;
1038 change = 1;
1039 }
1040 }
1041 if (change && mix->epcm) {
1042 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1043 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
1044 &mix->send_volume[1][0]);
1045 update_emu10k1_send_volume(emu, mix->epcm->voices[1]->number,
1046 &mix->send_volume[2][0]);
1047 } else if (mix->epcm->voices[0]) {
1048 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
1049 &mix->send_volume[0][0]);
1050 }
1051 }
1052 spin_unlock_irqrestore(&emu->reg_lock, flags);
1053 return change;
1054}
1055
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001056static struct snd_kcontrol_new snd_emu10k1_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057{
1058 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001059 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 .name = "EMU10K1 PCM Send Volume",
1061 .count = 32,
1062 .info = snd_emu10k1_send_volume_info,
1063 .get = snd_emu10k1_send_volume_get,
1064 .put = snd_emu10k1_send_volume_put
1065};
1066
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001067static int snd_emu10k1_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068{
1069 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1070 uinfo->count = 3;
1071 uinfo->value.integer.min = 0;
1072 uinfo->value.integer.max = 0xffff;
1073 return 0;
1074}
1075
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001076static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol,
1077 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001079 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1080 struct snd_emu10k1_pcm_mixer *mix =
1081 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 unsigned long flags;
1083 int idx;
1084
1085 spin_lock_irqsave(&emu->reg_lock, flags);
1086 for (idx = 0; idx < 3; idx++)
1087 ucontrol->value.integer.value[idx] = mix->attn[idx];
1088 spin_unlock_irqrestore(&emu->reg_lock, flags);
1089 return 0;
1090}
1091
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001092static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol,
1093 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094{
1095 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001096 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1097 struct snd_emu10k1_pcm_mixer *mix =
1098 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 int change = 0, idx, val;
1100
1101 spin_lock_irqsave(&emu->reg_lock, flags);
1102 for (idx = 0; idx < 3; idx++) {
1103 val = ucontrol->value.integer.value[idx] & 0xffff;
1104 if (mix->attn[idx] != val) {
1105 mix->attn[idx] = val;
1106 change = 1;
1107 }
1108 }
1109 if (change && mix->epcm) {
1110 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1111 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[1]);
1112 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[1]->number, mix->attn[2]);
1113 } else if (mix->epcm->voices[0]) {
1114 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]);
1115 }
1116 }
1117 spin_unlock_irqrestore(&emu->reg_lock, flags);
1118 return change;
1119}
1120
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001121static struct snd_kcontrol_new snd_emu10k1_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122{
1123 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001124 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 .name = "EMU10K1 PCM Volume",
1126 .count = 32,
1127 .info = snd_emu10k1_attn_info,
1128 .get = snd_emu10k1_attn_get,
1129 .put = snd_emu10k1_attn_put
1130};
1131
1132/* Mutichannel PCM stream controls */
1133
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001134static int snd_emu10k1_efx_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001136 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1138 uinfo->count = emu->audigy ? 8 : 4;
1139 uinfo->value.integer.min = 0;
1140 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
1141 return 0;
1142}
1143
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001144static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol,
1145 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146{
1147 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001148 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1149 struct snd_emu10k1_pcm_mixer *mix =
1150 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 int idx;
1152 int num_efx = emu->audigy ? 8 : 4;
1153 int mask = emu->audigy ? 0x3f : 0x0f;
1154
1155 spin_lock_irqsave(&emu->reg_lock, flags);
1156 for (idx = 0; idx < num_efx; idx++)
1157 ucontrol->value.integer.value[idx] =
1158 mix->send_routing[0][idx] & mask;
1159 spin_unlock_irqrestore(&emu->reg_lock, flags);
1160 return 0;
1161}
1162
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001163static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol,
1164 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165{
1166 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001167 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001169 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 int change = 0, idx, val;
1171 int num_efx = emu->audigy ? 8 : 4;
1172 int mask = emu->audigy ? 0x3f : 0x0f;
1173
1174 spin_lock_irqsave(&emu->reg_lock, flags);
1175 for (idx = 0; idx < num_efx; idx++) {
1176 val = ucontrol->value.integer.value[idx] & mask;
1177 if (mix->send_routing[0][idx] != val) {
1178 mix->send_routing[0][idx] = val;
1179 change = 1;
1180 }
1181 }
1182
1183 if (change && mix->epcm) {
1184 if (mix->epcm->voices[ch]) {
1185 update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number,
1186 &mix->send_routing[0][0]);
1187 }
1188 }
1189 spin_unlock_irqrestore(&emu->reg_lock, flags);
1190 return change;
1191}
1192
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001193static struct snd_kcontrol_new snd_emu10k1_efx_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194{
1195 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1196 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1197 .name = "Multichannel PCM Send Routing",
1198 .count = 16,
1199 .info = snd_emu10k1_efx_send_routing_info,
1200 .get = snd_emu10k1_efx_send_routing_get,
1201 .put = snd_emu10k1_efx_send_routing_put
1202};
1203
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001204static int snd_emu10k1_efx_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001206 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1208 uinfo->count = emu->audigy ? 8 : 4;
1209 uinfo->value.integer.min = 0;
1210 uinfo->value.integer.max = 255;
1211 return 0;
1212}
1213
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001214static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol,
1215 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216{
1217 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001218 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1219 struct snd_emu10k1_pcm_mixer *mix =
1220 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 int idx;
1222 int num_efx = emu->audigy ? 8 : 4;
1223
1224 spin_lock_irqsave(&emu->reg_lock, flags);
1225 for (idx = 0; idx < num_efx; idx++)
1226 ucontrol->value.integer.value[idx] = mix->send_volume[0][idx];
1227 spin_unlock_irqrestore(&emu->reg_lock, flags);
1228 return 0;
1229}
1230
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001231static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol,
1232 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233{
1234 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001235 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001237 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 int change = 0, idx, val;
1239 int num_efx = emu->audigy ? 8 : 4;
1240
1241 spin_lock_irqsave(&emu->reg_lock, flags);
1242 for (idx = 0; idx < num_efx; idx++) {
1243 val = ucontrol->value.integer.value[idx] & 255;
1244 if (mix->send_volume[0][idx] != val) {
1245 mix->send_volume[0][idx] = val;
1246 change = 1;
1247 }
1248 }
1249 if (change && mix->epcm) {
1250 if (mix->epcm->voices[ch]) {
1251 update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number,
1252 &mix->send_volume[0][0]);
1253 }
1254 }
1255 spin_unlock_irqrestore(&emu->reg_lock, flags);
1256 return change;
1257}
1258
1259
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001260static struct snd_kcontrol_new snd_emu10k1_efx_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261{
1262 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1263 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1264 .name = "Multichannel PCM Send Volume",
1265 .count = 16,
1266 .info = snd_emu10k1_efx_send_volume_info,
1267 .get = snd_emu10k1_efx_send_volume_get,
1268 .put = snd_emu10k1_efx_send_volume_put
1269};
1270
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001271static int snd_emu10k1_efx_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272{
1273 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1274 uinfo->count = 1;
1275 uinfo->value.integer.min = 0;
1276 uinfo->value.integer.max = 0xffff;
1277 return 0;
1278}
1279
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001280static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol,
1281 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001283 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1284 struct snd_emu10k1_pcm_mixer *mix =
1285 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 unsigned long flags;
1287
1288 spin_lock_irqsave(&emu->reg_lock, flags);
1289 ucontrol->value.integer.value[0] = mix->attn[0];
1290 spin_unlock_irqrestore(&emu->reg_lock, flags);
1291 return 0;
1292}
1293
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001294static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol,
1295 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296{
1297 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001298 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001300 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 int change = 0, val;
1302
1303 spin_lock_irqsave(&emu->reg_lock, flags);
1304 val = ucontrol->value.integer.value[0] & 0xffff;
1305 if (mix->attn[0] != val) {
1306 mix->attn[0] = val;
1307 change = 1;
1308 }
1309 if (change && mix->epcm) {
1310 if (mix->epcm->voices[ch]) {
1311 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]);
1312 }
1313 }
1314 spin_unlock_irqrestore(&emu->reg_lock, flags);
1315 return change;
1316}
1317
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001318static struct snd_kcontrol_new snd_emu10k1_efx_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319{
1320 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1321 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1322 .name = "Multichannel PCM Volume",
1323 .count = 16,
1324 .info = snd_emu10k1_efx_attn_info,
1325 .get = snd_emu10k1_efx_attn_get,
1326 .put = snd_emu10k1_efx_attn_put
1327};
1328
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001329static int snd_emu10k1_shared_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330{
1331 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1332 uinfo->count = 1;
1333 uinfo->value.integer.min = 0;
1334 uinfo->value.integer.max = 1;
1335 return 0;
1336}
1337
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001338static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol,
1339 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001341 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342
1343 if (emu->audigy)
1344 ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0;
1345 else
1346 ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0;
1347 return 0;
1348}
1349
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001350static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
1351 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352{
1353 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001354 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 unsigned int reg, val;
1356 int change = 0;
1357
1358 spin_lock_irqsave(&emu->reg_lock, flags);
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001359 if ( emu->card_capabilities->i2c_adc) {
1360 /* Do nothing for Audigy 2 ZS Notebook */
1361 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 reg = inl(emu->port + A_IOCFG);
1363 val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0;
1364 change = (reg & A_IOCFG_GPOUT0) != val;
1365 if (change) {
1366 reg &= ~A_IOCFG_GPOUT0;
1367 reg |= val;
1368 outl(reg | val, emu->port + A_IOCFG);
1369 }
1370 }
1371 reg = inl(emu->port + HCFG);
1372 val = ucontrol->value.integer.value[0] ? HCFG_GPOUT0 : 0;
1373 change |= (reg & HCFG_GPOUT0) != val;
1374 if (change) {
1375 reg &= ~HCFG_GPOUT0;
1376 reg |= val;
1377 outl(reg | val, emu->port + HCFG);
1378 }
1379 spin_unlock_irqrestore(&emu->reg_lock, flags);
1380 return change;
1381}
1382
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001383static struct snd_kcontrol_new snd_emu10k1_shared_spdif __devinitdata =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384{
1385 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1386 .name = "SB Live Analog/Digital Output Jack",
1387 .info = snd_emu10k1_shared_spdif_info,
1388 .get = snd_emu10k1_shared_spdif_get,
1389 .put = snd_emu10k1_shared_spdif_put
1390};
1391
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001392static struct snd_kcontrol_new snd_audigy_shared_spdif __devinitdata =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393{
1394 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1395 .name = "Audigy Analog/Digital Output Jack",
1396 .info = snd_emu10k1_shared_spdif_info,
1397 .get = snd_emu10k1_shared_spdif_get,
1398 .put = snd_emu10k1_shared_spdif_put
1399};
1400
1401/*
1402 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001403static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001405 struct snd_emu10k1 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 emu->ac97 = NULL;
1407}
1408
1409/*
1410 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001411static int remove_ctl(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001413 struct snd_ctl_elem_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414 memset(&id, 0, sizeof(id));
1415 strcpy(id.name, name);
1416 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1417 return snd_ctl_remove_id(card, &id);
1418}
1419
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001420static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001422 struct snd_ctl_elem_id sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 memset(&sid, 0, sizeof(sid));
1424 strcpy(sid.name, name);
1425 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1426 return snd_ctl_find_id(card, &sid);
1427}
1428
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001429static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001431 struct snd_kcontrol *kctl = ctl_find(card, src);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 if (kctl) {
1433 strcpy(kctl->id.name, dst);
1434 return 0;
1435 }
1436 return -ENOENT;
1437}
1438
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001439int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001440 int pcm_device, int multi_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441{
1442 int err, pcm;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001443 struct snd_kcontrol *kctl;
1444 struct snd_card *card = emu->card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 char **c;
1446 static char *emu10k1_remove_ctls[] = {
1447 /* no AC97 mono, surround, center/lfe */
1448 "Master Mono Playback Switch",
1449 "Master Mono Playback Volume",
1450 "PCM Out Path & Mute",
1451 "Mono Output Select",
Takashi Iwai7eae36f2006-01-05 18:40:56 +01001452 "Front Playback Switch",
1453 "Front Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 "Surround Playback Switch",
1455 "Surround Playback Volume",
1456 "Center Playback Switch",
1457 "Center Playback Volume",
1458 "LFE Playback Switch",
1459 "LFE Playback Volume",
1460 NULL
1461 };
1462 static char *emu10k1_rename_ctls[] = {
1463 "Surround Digital Playback Volume", "Surround Playback Volume",
1464 "Center Digital Playback Volume", "Center Playback Volume",
1465 "LFE Digital Playback Volume", "LFE Playback Volume",
1466 NULL
1467 };
1468 static char *audigy_remove_ctls[] = {
1469 /* Master/PCM controls on ac97 of Audigy has no effect */
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001470 /* On the Audigy2 the AC97 playback is piped into
1471 * the Philips ADC for 24bit capture */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 "PCM Playback Switch",
1473 "PCM Playback Volume",
1474 "Master Mono Playback Switch",
1475 "Master Mono Playback Volume",
1476 "Master Playback Switch",
1477 "Master Playback Volume",
1478 "PCM Out Path & Mute",
1479 "Mono Output Select",
1480 /* remove unused AC97 capture controls */
1481 "Capture Source",
1482 "Capture Switch",
1483 "Capture Volume",
1484 "Mic Select",
1485 "Video Playback Switch",
1486 "Video Playback Volume",
1487 "Mic Playback Switch",
1488 "Mic Playback Volume",
1489 NULL
1490 };
1491 static char *audigy_rename_ctls[] = {
1492 /* use conventional names */
1493 "Wave Playback Volume", "PCM Playback Volume",
1494 /* "Wave Capture Volume", "PCM Capture Volume", */
1495 "Wave Master Playback Volume", "Master Playback Volume",
1496 "AMic Playback Volume", "Mic Playback Volume",
1497 NULL
1498 };
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001499 static char *audigy_rename_ctls_i2c_adc[] = {
1500 //"Analog Mix Capture Volume","OLD Analog Mix Capture Volume",
1501 "Line Capture Volume", "Analog Mix Capture Volume",
1502 "Wave Playback Volume", "OLD PCM Playback Volume",
1503 "Wave Master Playback Volume", "Master Playback Volume",
1504 "AMic Playback Volume", "Old Mic Playback Volume",
James Courtier-Duttoneb41dab2006-12-06 20:38:45 +00001505 "CD Capture Volume", "IEC958 Optical Capture Volume",
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001506 NULL
1507 };
1508 static char *audigy_remove_ctls_i2c_adc[] = {
1509 /* On the Audigy2 ZS Notebook
1510 * Capture via WM8775 */
1511 "Mic Capture Volume",
1512 "Analog Mix Capture Volume",
1513 "Aux Capture Volume",
James Courtier-Duttoneb41dab2006-12-06 20:38:45 +00001514 "IEC958 Optical Capture Volume",
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001515 NULL
1516 };
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001517 static char *audigy_remove_ctls_1361t_adc[] = {
1518 /* On the Audigy2 the AC97 playback is piped into
1519 * the Philips ADC for 24bit capture */
1520 "PCM Playback Switch",
1521 "PCM Playback Volume",
1522 "Master Mono Playback Switch",
1523 "Master Mono Playback Volume",
1524 "Capture Source",
1525 "Capture Switch",
1526 "Capture Volume",
1527 "Mic Capture Volume",
1528 "Headphone Playback Switch",
1529 "Headphone Playback Volume",
1530 "3D Control - Center",
1531 "3D Control - Depth",
1532 "3D Control - Switch",
1533 "Line2 Playback Volume",
1534 "Line2 Capture Volume",
1535 NULL
1536 };
1537 static char *audigy_rename_ctls_1361t_adc[] = {
1538 "Master Playback Switch", "Master Capture Switch",
1539 "Master Playback Volume", "Master Capture Volume",
1540 "Wave Master Playback Volume", "Master Playback Volume",
1541 "PC Speaker Playback Switch", "PC Speaker Capture Switch",
1542 "PC Speaker Playback Volume", "PC Speaker Capture Volume",
1543 "Phone Playback Switch", "Phone Capture Switch",
1544 "Phone Playback Volume", "Phone Capture Volume",
1545 "Mic Playback Switch", "Mic Capture Switch",
1546 "Mic Playback Volume", "Mic Capture Volume",
1547 "Line Playback Switch", "Line Capture Switch",
1548 "Line Playback Volume", "Line Capture Volume",
1549 "CD Playback Switch", "CD Capture Switch",
1550 "CD Playback Volume", "CD Capture Volume",
1551 "Aux Playback Switch", "Aux Capture Switch",
1552 "Aux Playback Volume", "Aux Capture Volume",
1553 "Video Playback Switch", "Video Capture Switch",
1554 "Video Playback Volume", "Video Capture Volume",
1555
1556 NULL
1557 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558
Lee Revell2b637da2005-03-30 13:51:18 +02001559 if (emu->card_capabilities->ac97_chip) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001560 struct snd_ac97_bus *pbus;
1561 struct snd_ac97_template ac97;
1562 static struct snd_ac97_bus_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563 .write = snd_emu10k1_ac97_write,
1564 .read = snd_emu10k1_ac97_read,
1565 };
1566
Takashi Iwaib1508692005-10-04 13:49:32 +02001567 if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0)
1568 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569 pbus->no_vra = 1; /* we don't need VRA */
1570
1571 memset(&ac97, 0, sizeof(ac97));
1572 ac97.private_data = emu;
1573 ac97.private_free = snd_emu10k1_mixer_free_ac97;
1574 ac97.scaps = AC97_SCAP_NO_SPDIF;
Takashi Iwaib1508692005-10-04 13:49:32 +02001575 if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) {
1576 if (emu->card_capabilities->ac97_chip == 1)
1577 return err;
1578 snd_printd(KERN_INFO "emu10k1: AC97 is optional on this board\n");
1579 snd_printd(KERN_INFO" Proceeding without ac97 mixers...\n");
1580 snd_device_free(emu->card, pbus);
1581 goto no_ac97; /* FIXME: get rid of ugly gotos.. */
1582 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 if (emu->audigy) {
1584 /* set master volume to 0 dB */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001585 snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 /* set capture source to mic */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001587 snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001588 if (emu->card_capabilities->adc_1361t)
1589 c = audigy_remove_ctls_1361t_adc;
1590 else
1591 c = audigy_remove_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 } else {
1593 /*
1594 * Credits for cards based on STAC9758:
1595 * James Courtier-Dutton <James@superbug.demon.co.uk>
1596 * Voluspa <voluspa@comhem.se>
1597 */
1598 if (emu->ac97->id == AC97_ID_STAC9758) {
1599 emu->rear_ac97 = 1;
1600 snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT);
Rolf Stefan Wilke2594d962007-02-06 19:18:14 +01001601 snd_ac97_write_cache(emu->ac97, AC97_HEADPHONE, 0x0202);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 }
1603 /* remove unused AC97 controls */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001604 snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
1605 snd_ac97_write_cache(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 c = emu10k1_remove_ctls;
1607 }
1608 for (; *c; c++)
1609 remove_ctl(card, *c);
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001610 } else if (emu->card_capabilities->i2c_adc) {
1611 c = audigy_remove_ctls_i2c_adc;
1612 for (; *c; c++)
1613 remove_ctl(card, *c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 } else {
Takashi Iwaif12aa402005-09-30 16:56:59 +02001615 no_ac97:
Lee Revell2b637da2005-03-30 13:51:18 +02001616 if (emu->card_capabilities->ecard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 strcpy(emu->card->mixername, "EMU APS");
1618 else if (emu->audigy)
1619 strcpy(emu->card->mixername, "SB Audigy");
1620 else
1621 strcpy(emu->card->mixername, "Emu10k1");
1622 }
1623
1624 if (emu->audigy)
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001625 if (emu->card_capabilities->adc_1361t)
1626 c = audigy_rename_ctls_1361t_adc;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001627 else if (emu->card_capabilities->i2c_adc)
1628 c = audigy_rename_ctls_i2c_adc;
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001629 else
1630 c = audigy_rename_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 else
1632 c = emu10k1_rename_ctls;
1633 for (; *c; c += 2)
1634 rename_ctl(card, c[0], c[1]);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001635
James Courtier-Duttone3b9bc02005-12-24 16:54:51 +01001636 if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */
1637 rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume");
1638 rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume");
1639 rename_ctl(card, "Aux2 Capture Volume", "Line3 Capture Volume");
1640 rename_ctl(card, "Mic Capture Volume", "Unknown1 Capture Volume");
1641 remove_ctl(card, "Headphone Playback Switch");
1642 remove_ctl(card, "Headphone Playback Volume");
1643 remove_ctl(card, "3D Control - Center");
1644 remove_ctl(card, "3D Control - Depth");
1645 remove_ctl(card, "3D Control - Switch");
1646 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL)
1648 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001649 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 if ((err = snd_ctl_add(card, kctl)))
1651 return err;
1652 if ((kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL)
1653 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001654 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 if ((err = snd_ctl_add(card, kctl)))
1656 return err;
1657 if ((kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu)) == NULL)
1658 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001659 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 if ((err = snd_ctl_add(card, kctl)))
1661 return err;
1662
1663 if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL)
1664 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001665 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 if ((err = snd_ctl_add(card, kctl)))
1667 return err;
1668
1669 if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL)
1670 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001671 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 if ((err = snd_ctl_add(card, kctl)))
1673 return err;
1674
1675 if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL)
1676 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001677 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 if ((err = snd_ctl_add(card, kctl)))
1679 return err;
1680
1681 /* initialize the routing and volume table for each pcm playback stream */
1682 for (pcm = 0; pcm < 32; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001683 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 int v;
1685
1686 mix = &emu->pcm_mixer[pcm];
1687 mix->epcm = NULL;
1688
1689 for (v = 0; v < 4; v++)
1690 mix->send_routing[0][v] =
1691 mix->send_routing[1][v] =
1692 mix->send_routing[2][v] = v;
1693
1694 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1695 mix->send_volume[0][0] = mix->send_volume[0][1] =
1696 mix->send_volume[1][0] = mix->send_volume[2][1] = 255;
1697
1698 mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
1699 }
1700
1701 /* initialize the routing and volume table for the multichannel playback stream */
1702 for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001703 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 int v;
1705
1706 mix = &emu->efx_pcm_mixer[pcm];
1707 mix->epcm = NULL;
1708
1709 mix->send_routing[0][0] = pcm;
1710 mix->send_routing[0][1] = (pcm == 0) ? 1 : 0;
1711 for (v = 0; v < 2; v++)
1712 mix->send_routing[0][2+v] = 13+v;
1713 if (emu->audigy)
1714 for (v = 0; v < 4; v++)
1715 mix->send_routing[0][4+v] = 60+v;
1716
1717 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1718 mix->send_volume[0][0] = 255;
1719
1720 mix->attn[0] = 0xffff;
1721 }
1722
Lee Revell2b637da2005-03-30 13:51:18 +02001723 if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724 /* sb live! and audigy */
1725 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
1726 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02001727 if (!emu->audigy)
1728 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 if ((err = snd_ctl_add(card, kctl)))
1730 return err;
1731 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
1732 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02001733 if (!emu->audigy)
1734 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 if ((err = snd_ctl_add(card, kctl)))
1736 return err;
1737 }
1738
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001739 if ( emu->card_capabilities->emu1010) {
James Courtier-Dutton19b99fb2005-12-04 18:03:03 +01001740 ; /* Disable the snd_audigy_spdif_shared_spdif */
1741 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
1743 return -ENOMEM;
1744 if ((err = snd_ctl_add(card, kctl)))
1745 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02001746#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747 if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
1748 return -ENOMEM;
1749 if ((err = snd_ctl_add(card, kctl)))
1750 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02001751#endif
Lee Revell2b637da2005-03-30 13:51:18 +02001752 } else if (! emu->card_capabilities->ecard) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 /* sb live! */
1754 if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
1755 return -ENOMEM;
1756 if ((err = snd_ctl_add(card, kctl)))
1757 return err;
1758 }
Lee Revell2b637da2005-03-30 13:51:18 +02001759 if (emu->card_capabilities->ca0151_chip) { /* P16V */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 if ((err = snd_p16v_mixer(emu)))
1761 return err;
1762 }
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001763
1764 if ( emu->card_capabilities->emu1010) {
1765 int i;
1766
1767 for (i = 0; i < ARRAY_SIZE(snd_emu1010_output_enum_ctls); i++) {
1768 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_output_enum_ctls[i], emu));
1769 if (err < 0)
1770 return err;
1771 }
1772 for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) {
1773 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], emu));
1774 if (err < 0)
1775 return err;
1776 }
James Courtier-Dutton9148cc52006-10-09 23:08:00 +01001777 for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads); i++) {
1778 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_adc_pads[i], emu));
1779 if (err < 0)
1780 return err;
1781 }
1782 for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads); i++) {
1783 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_dac_pads[i], emu));
1784 if (err < 0)
1785 return err;
1786 }
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +01001787 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_internal_clock, emu));
1788 if (err < 0)
1789 return err;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001790 }
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001791
1792 if ( emu->card_capabilities->i2c_adc) {
1793 int i;
1794
1795 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_capture_source, emu));
1796 if (err < 0)
1797 return err;
1798
1799 for (i = 0; i < ARRAY_SIZE(snd_audigy_i2c_volume_ctls); i++) {
1800 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_volume_ctls[i], emu));
1801 if (err < 0)
1802 return err;
1803 }
1804 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805
1806 return 0;
1807}