blob: 6c26319430d7046472c00f8333ad5d31d573b702 [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
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200403#define snd_emu1010_adc_pads_info snd_ctl_boolean_mono_info
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100404
405static int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
406{
407 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
408 unsigned int mask = kcontrol->private_value & 0xff;
409 ucontrol->value.integer.value[0] = (emu->emu1010.adc_pads & mask) ? 1 : 0;
410 return 0;
411}
412
413static int snd_emu1010_adc_pads_put(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 unsigned int val, cache;
418 val = ucontrol->value.integer.value[0];
419 cache = emu->emu1010.adc_pads;
420 if (val == 1)
421 cache = cache | mask;
422 else
423 cache = cache & ~mask;
424 if (cache != emu->emu1010.adc_pads) {
425 snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache );
426 emu->emu1010.adc_pads = cache;
427 }
428
429 return 0;
430}
431
432
433
434#define EMU1010_ADC_PADS(xname,chid) \
435{ \
436 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
437 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
438 .info = snd_emu1010_adc_pads_info, \
439 .get = snd_emu1010_adc_pads_get, \
440 .put = snd_emu1010_adc_pads_put, \
441 .private_value = chid \
442}
443
444static struct snd_kcontrol_new snd_emu1010_adc_pads[] __devinitdata = {
445 EMU1010_ADC_PADS("ADC1 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD1),
446 EMU1010_ADC_PADS("ADC2 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD2),
447 EMU1010_ADC_PADS("ADC3 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD3),
448 EMU1010_ADC_PADS("ADC1 14dB PAD 0202 Capture Switch", EMU_HANA_0202_ADC_PAD1),
449};
450
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200451#define snd_emu1010_dac_pads_info snd_ctl_boolean_mono_info
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100452
453static int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
454{
455 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
456 unsigned int mask = kcontrol->private_value & 0xff;
457 ucontrol->value.integer.value[0] = (emu->emu1010.dac_pads & mask) ? 1 : 0;
458 return 0;
459}
460
461static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
462{
463 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
464 unsigned int mask = kcontrol->private_value & 0xff;
465 unsigned int val, cache;
466 val = ucontrol->value.integer.value[0];
467 cache = emu->emu1010.dac_pads;
468 if (val == 1)
469 cache = cache | mask;
470 else
471 cache = cache & ~mask;
472 if (cache != emu->emu1010.dac_pads) {
473 snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache );
474 emu->emu1010.dac_pads = cache;
475 }
476
477 return 0;
478}
479
480
481
482#define EMU1010_DAC_PADS(xname,chid) \
483{ \
484 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
485 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
486 .info = snd_emu1010_dac_pads_info, \
487 .get = snd_emu1010_dac_pads_get, \
488 .put = snd_emu1010_dac_pads_put, \
489 .private_value = chid \
490}
491
492static struct snd_kcontrol_new snd_emu1010_dac_pads[] __devinitdata = {
493 EMU1010_DAC_PADS("DAC1 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD1),
494 EMU1010_DAC_PADS("DAC2 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD2),
495 EMU1010_DAC_PADS("DAC3 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD3),
496 EMU1010_DAC_PADS("DAC4 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD4),
497 EMU1010_DAC_PADS("DAC1 0202 14dB PAD Playback Switch", EMU_HANA_0202_DAC_PAD1),
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100498};
499
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100500
501static int snd_emu1010_internal_clock_info(struct snd_kcontrol *kcontrol,
502 struct snd_ctl_elem_info *uinfo)
503{
504 static char *texts[2] = {
505 "44100", "48000"
506 };
507
508 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
509 uinfo->count = 1;
510 uinfo->value.enumerated.items = 2;
511 if (uinfo->value.enumerated.item > 1)
512 uinfo->value.enumerated.item = 1;
513 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
514 return 0;
515}
516
517static int snd_emu1010_internal_clock_get(struct snd_kcontrol *kcontrol,
518 struct snd_ctl_elem_value *ucontrol)
519{
520 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
521
522 ucontrol->value.enumerated.item[0] = emu->emu1010.internal_clock;
523 return 0;
524}
525
526static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol,
527 struct snd_ctl_elem_value *ucontrol)
528{
529 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
530 unsigned int val;
531 int change = 0;
532
533 val = ucontrol->value.enumerated.item[0] ;
534 change = (emu->emu1010.internal_clock != val);
535 if (change) {
536 emu->emu1010.internal_clock = val;
537 switch (val) {
538 case 0:
539 /* 44100 */
540 /* Mute all */
541 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
542 /* Default fallback clock 48kHz */
543 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_44_1K );
544 /* Word Clock source, Internal 44.1kHz x1 */
545 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
546 EMU_HANA_WCLOCK_INT_44_1K | EMU_HANA_WCLOCK_1X );
547 /* Set LEDs on Audio Dock */
548 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
549 EMU_HANA_DOCK_LEDS_2_44K | EMU_HANA_DOCK_LEDS_2_LOCK );
550 /* Allow DLL to settle */
James Courtier-Duttone40a0b22006-10-10 18:44:29 +0100551 msleep(10);
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100552 /* Unmute all */
553 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
554 break;
555 case 1:
556 /* 48000 */
557 /* Mute all */
558 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
559 /* Default fallback clock 48kHz */
560 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
561 /* Word Clock source, Internal 48kHz x1 */
562 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
563 EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_1X );
564 /* Set LEDs on Audio Dock */
565 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
566 EMU_HANA_DOCK_LEDS_2_48K | EMU_HANA_DOCK_LEDS_2_LOCK );
567 /* Allow DLL to settle */
James Courtier-Duttone40a0b22006-10-10 18:44:29 +0100568 msleep(10);
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100569 /* Unmute all */
570 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
571 break;
572 }
573 }
574 return change;
575}
576
577static struct snd_kcontrol_new snd_emu1010_internal_clock =
578{
579 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
580 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
581 .name = "Clock Internal Rate",
582 .count = 1,
583 .info = snd_emu1010_internal_clock_info,
584 .get = snd_emu1010_internal_clock_get,
585 .put = snd_emu1010_internal_clock_put
586};
587
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000588static int snd_audigy_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
589 struct snd_ctl_elem_info *uinfo)
590{
591#if 0
592 static char *texts[4] = {
593 "Unknown1", "Unknown2", "Mic", "Line"
594 };
595#endif
596 static char *texts[2] = {
597 "Mic", "Line"
598 };
599
600 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
601 uinfo->count = 1;
602 uinfo->value.enumerated.items = 2;
603 if (uinfo->value.enumerated.item > 1)
604 uinfo->value.enumerated.item = 1;
605 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
606 return 0;
607}
608
609static int snd_audigy_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
610 struct snd_ctl_elem_value *ucontrol)
611{
612 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
613
614 ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
615 return 0;
616}
617
618static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
619 struct snd_ctl_elem_value *ucontrol)
620{
621 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
622 unsigned int source_id;
623 unsigned int ngain, ogain;
624 u32 gpio;
625 int change = 0;
626 unsigned long flags;
627 u32 source;
628 /* If the capture source has changed,
629 * update the capture volume from the cached value
630 * for the particular source.
631 */
632 source_id = ucontrol->value.enumerated.item[0]; /* Use 2 and 3 */
633 change = (emu->i2c_capture_source != source_id);
634 if (change) {
635 snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */
636 spin_lock_irqsave(&emu->emu_lock, flags);
637 gpio = inl(emu->port + A_IOCFG);
638 if (source_id==0)
639 outl(gpio | 0x4, emu->port + A_IOCFG);
640 else
641 outl(gpio & ~0x4, emu->port + A_IOCFG);
642 spin_unlock_irqrestore(&emu->emu_lock, flags);
643
644 ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
645 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
646 if (ngain != ogain)
647 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
648 ngain = emu->i2c_capture_volume[source_id][1]; /* Right */
649 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
650 if (ngain != ogain)
651 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
652
653 source = 1 << (source_id + 2);
654 snd_emu10k1_i2c_write(emu, ADC_MUX, source); /* Set source */
655 emu->i2c_capture_source = source_id;
656 }
657 return change;
658}
659
660static struct snd_kcontrol_new snd_audigy_i2c_capture_source =
661{
662 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
663 .name = "Capture Source",
664 .info = snd_audigy_i2c_capture_source_info,
665 .get = snd_audigy_i2c_capture_source_get,
666 .put = snd_audigy_i2c_capture_source_put
667};
668
669static int snd_audigy_i2c_volume_info(struct snd_kcontrol *kcontrol,
670 struct snd_ctl_elem_info *uinfo)
671{
672 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
673 uinfo->count = 2;
674 uinfo->value.integer.min = 0;
675 uinfo->value.integer.max = 255;
676 return 0;
677}
678
679static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol,
680 struct snd_ctl_elem_value *ucontrol)
681{
682 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
683 int source_id;
684
685 source_id = kcontrol->private_value;
686
687 ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
688 ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
689 return 0;
690}
691
692static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
693 struct snd_ctl_elem_value *ucontrol)
694{
695 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
696 unsigned int ogain;
697 unsigned int ngain;
698 int source_id;
699 int change = 0;
700
701 source_id = kcontrol->private_value;
702 ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
703 ngain = ucontrol->value.integer.value[0];
704 if (ngain > 0xff)
705 return 0;
706 if (ogain != ngain) {
707 if (emu->i2c_capture_source == source_id)
708 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
709 emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0];
710 change = 1;
711 }
712 ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
713 ngain = ucontrol->value.integer.value[1];
714 if (ngain > 0xff)
715 return 0;
716 if (ogain != ngain) {
717 if (emu->i2c_capture_source == source_id)
718 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
719 emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1];
720 change = 1;
721 }
722
723 return change;
724}
725
726#define I2C_VOLUME(xname,chid) \
727{ \
728 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
729 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
730 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
731 .info = snd_audigy_i2c_volume_info, \
732 .get = snd_audigy_i2c_volume_get, \
733 .put = snd_audigy_i2c_volume_put, \
734 .tlv = { .p = snd_audigy_db_scale2 }, \
735 .private_value = chid \
736}
737
738
739static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] __devinitdata = {
740 I2C_VOLUME("Mic Capture Volume", 0),
741 I2C_VOLUME("Line Capture Volume", 0)
742};
743
Takashi Iwai0af68e52005-04-11 17:03:03 +0200744#if 0
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100745static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746{
747 static char *texts[] = {"44100", "48000", "96000"};
748
749 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
750 uinfo->count = 1;
751 uinfo->value.enumerated.items = 3;
752 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
753 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
754 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
755 return 0;
756}
757
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100758static int snd_audigy_spdif_output_rate_get(struct snd_kcontrol *kcontrol,
759 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100761 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 unsigned int tmp;
763 unsigned long flags;
764
765
766 spin_lock_irqsave(&emu->reg_lock, flags);
767 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
768 switch (tmp & A_SPDIF_RATE_MASK) {
769 case A_SPDIF_44100:
770 ucontrol->value.enumerated.item[0] = 0;
771 break;
772 case A_SPDIF_48000:
773 ucontrol->value.enumerated.item[0] = 1;
774 break;
775 case A_SPDIF_96000:
776 ucontrol->value.enumerated.item[0] = 2;
777 break;
778 default:
779 ucontrol->value.enumerated.item[0] = 1;
780 }
781 spin_unlock_irqrestore(&emu->reg_lock, flags);
782 return 0;
783}
784
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100785static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol,
786 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100788 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 int change;
790 unsigned int reg, val, tmp;
791 unsigned long flags;
792
793 switch(ucontrol->value.enumerated.item[0]) {
794 case 0:
795 val = A_SPDIF_44100;
796 break;
797 case 1:
798 val = A_SPDIF_48000;
799 break;
800 case 2:
801 val = A_SPDIF_96000;
802 break;
803 default:
804 val = A_SPDIF_48000;
805 break;
806 }
807
808
809 spin_lock_irqsave(&emu->reg_lock, flags);
810 reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
811 tmp = reg & ~A_SPDIF_RATE_MASK;
812 tmp |= val;
813 if ((change = (tmp != reg)))
814 snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
815 spin_unlock_irqrestore(&emu->reg_lock, flags);
816 return change;
817}
818
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100819static struct snd_kcontrol_new snd_audigy_spdif_output_rate =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820{
821 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
822 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
823 .name = "Audigy SPDIF Output Sample Rate",
824 .count = 1,
825 .info = snd_audigy_spdif_output_rate_info,
826 .get = snd_audigy_spdif_output_rate_get,
827 .put = snd_audigy_spdif_output_rate_put
828};
Takashi Iwai0af68e52005-04-11 17:03:03 +0200829#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100831static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol,
832 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100834 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
836 int change;
837 unsigned int val;
838 unsigned long flags;
839
840 val = (ucontrol->value.iec958.status[0] << 0) |
841 (ucontrol->value.iec958.status[1] << 8) |
842 (ucontrol->value.iec958.status[2] << 16) |
843 (ucontrol->value.iec958.status[3] << 24);
844 spin_lock_irqsave(&emu->reg_lock, flags);
845 change = val != emu->spdif_bits[idx];
846 if (change) {
847 snd_emu10k1_ptr_write(emu, SPCS0 + idx, 0, val);
848 emu->spdif_bits[idx] = val;
849 }
850 spin_unlock_irqrestore(&emu->reg_lock, flags);
851 return change;
852}
853
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100854static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855{
856 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +0200857 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
859 .count = 4,
860 .info = snd_emu10k1_spdif_info,
861 .get = snd_emu10k1_spdif_get_mask
862};
863
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100864static struct snd_kcontrol_new snd_emu10k1_spdif_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865{
Clemens Ladisch5549d542005-08-03 13:50:30 +0200866 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
868 .count = 4,
869 .info = snd_emu10k1_spdif_info,
870 .get = snd_emu10k1_spdif_get,
871 .put = snd_emu10k1_spdif_put
872};
873
874
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100875static void update_emu10k1_fxrt(struct snd_emu10k1 *emu, int voice, unsigned char *route)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876{
877 if (emu->audigy) {
878 snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
879 snd_emu10k1_compose_audigy_fxrt1(route));
880 snd_emu10k1_ptr_write(emu, A_FXRT2, voice,
881 snd_emu10k1_compose_audigy_fxrt2(route));
882 } else {
883 snd_emu10k1_ptr_write(emu, FXRT, voice,
884 snd_emu10k1_compose_send_routing(route));
885 }
886}
887
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100888static void update_emu10k1_send_volume(struct snd_emu10k1 *emu, int voice, unsigned char *volume)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889{
890 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]);
891 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]);
892 snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, volume[2]);
893 snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, volume[3]);
894 if (emu->audigy) {
895 unsigned int val = ((unsigned int)volume[4] << 24) |
896 ((unsigned int)volume[5] << 16) |
897 ((unsigned int)volume[6] << 8) |
898 (unsigned int)volume[7];
899 snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, val);
900 }
901}
902
903/* PCM stream controls */
904
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100905static int snd_emu10k1_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100907 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
909 uinfo->count = emu->audigy ? 3*8 : 3*4;
910 uinfo->value.integer.min = 0;
911 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
912 return 0;
913}
914
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100915static int snd_emu10k1_send_routing_get(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 voice, idx;
923 int num_efx = emu->audigy ? 8 : 4;
924 int mask = emu->audigy ? 0x3f : 0x0f;
925
926 spin_lock_irqsave(&emu->reg_lock, flags);
927 for (voice = 0; voice < 3; voice++)
928 for (idx = 0; idx < num_efx; idx++)
929 ucontrol->value.integer.value[(voice * num_efx) + idx] =
930 mix->send_routing[voice][idx] & mask;
931 spin_unlock_irqrestore(&emu->reg_lock, flags);
932 return 0;
933}
934
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100935static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol,
936 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937{
938 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100939 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
940 struct snd_emu10k1_pcm_mixer *mix =
941 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 int change = 0, voice, idx, val;
943 int num_efx = emu->audigy ? 8 : 4;
944 int mask = emu->audigy ? 0x3f : 0x0f;
945
946 spin_lock_irqsave(&emu->reg_lock, flags);
947 for (voice = 0; voice < 3; voice++)
948 for (idx = 0; idx < num_efx; idx++) {
949 val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask;
950 if (mix->send_routing[voice][idx] != val) {
951 mix->send_routing[voice][idx] = val;
952 change = 1;
953 }
954 }
955 if (change && mix->epcm) {
956 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
957 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
958 &mix->send_routing[1][0]);
959 update_emu10k1_fxrt(emu, mix->epcm->voices[1]->number,
960 &mix->send_routing[2][0]);
961 } else if (mix->epcm->voices[0]) {
962 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
963 &mix->send_routing[0][0]);
964 }
965 }
966 spin_unlock_irqrestore(&emu->reg_lock, flags);
967 return change;
968}
969
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100970static struct snd_kcontrol_new snd_emu10k1_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971{
972 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +0200973 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 .name = "EMU10K1 PCM Send Routing",
975 .count = 32,
976 .info = snd_emu10k1_send_routing_info,
977 .get = snd_emu10k1_send_routing_get,
978 .put = snd_emu10k1_send_routing_put
979};
980
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100981static int snd_emu10k1_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100983 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
985 uinfo->count = emu->audigy ? 3*8 : 3*4;
986 uinfo->value.integer.min = 0;
987 uinfo->value.integer.max = 255;
988 return 0;
989}
990
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100991static int snd_emu10k1_send_volume_get(struct snd_kcontrol *kcontrol,
992 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993{
994 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100995 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
996 struct snd_emu10k1_pcm_mixer *mix =
997 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 int idx;
999 int num_efx = emu->audigy ? 8 : 4;
1000
1001 spin_lock_irqsave(&emu->reg_lock, flags);
1002 for (idx = 0; idx < 3*num_efx; idx++)
1003 ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx];
1004 spin_unlock_irqrestore(&emu->reg_lock, flags);
1005 return 0;
1006}
1007
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001008static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol,
1009 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010{
1011 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001012 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1013 struct snd_emu10k1_pcm_mixer *mix =
1014 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 int change = 0, idx, val;
1016 int num_efx = emu->audigy ? 8 : 4;
1017
1018 spin_lock_irqsave(&emu->reg_lock, flags);
1019 for (idx = 0; idx < 3*num_efx; idx++) {
1020 val = ucontrol->value.integer.value[idx] & 255;
1021 if (mix->send_volume[idx/num_efx][idx%num_efx] != val) {
1022 mix->send_volume[idx/num_efx][idx%num_efx] = val;
1023 change = 1;
1024 }
1025 }
1026 if (change && mix->epcm) {
1027 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1028 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
1029 &mix->send_volume[1][0]);
1030 update_emu10k1_send_volume(emu, mix->epcm->voices[1]->number,
1031 &mix->send_volume[2][0]);
1032 } else if (mix->epcm->voices[0]) {
1033 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
1034 &mix->send_volume[0][0]);
1035 }
1036 }
1037 spin_unlock_irqrestore(&emu->reg_lock, flags);
1038 return change;
1039}
1040
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001041static struct snd_kcontrol_new snd_emu10k1_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042{
1043 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001044 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 .name = "EMU10K1 PCM Send Volume",
1046 .count = 32,
1047 .info = snd_emu10k1_send_volume_info,
1048 .get = snd_emu10k1_send_volume_get,
1049 .put = snd_emu10k1_send_volume_put
1050};
1051
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001052static int snd_emu10k1_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053{
1054 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1055 uinfo->count = 3;
1056 uinfo->value.integer.min = 0;
1057 uinfo->value.integer.max = 0xffff;
1058 return 0;
1059}
1060
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001061static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol,
1062 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001064 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1065 struct snd_emu10k1_pcm_mixer *mix =
1066 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 unsigned long flags;
1068 int idx;
1069
1070 spin_lock_irqsave(&emu->reg_lock, flags);
1071 for (idx = 0; idx < 3; idx++)
1072 ucontrol->value.integer.value[idx] = mix->attn[idx];
1073 spin_unlock_irqrestore(&emu->reg_lock, flags);
1074 return 0;
1075}
1076
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001077static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol,
1078 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079{
1080 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001081 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1082 struct snd_emu10k1_pcm_mixer *mix =
1083 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 int change = 0, idx, val;
1085
1086 spin_lock_irqsave(&emu->reg_lock, flags);
1087 for (idx = 0; idx < 3; idx++) {
1088 val = ucontrol->value.integer.value[idx] & 0xffff;
1089 if (mix->attn[idx] != val) {
1090 mix->attn[idx] = val;
1091 change = 1;
1092 }
1093 }
1094 if (change && mix->epcm) {
1095 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1096 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[1]);
1097 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[1]->number, mix->attn[2]);
1098 } else if (mix->epcm->voices[0]) {
1099 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]);
1100 }
1101 }
1102 spin_unlock_irqrestore(&emu->reg_lock, flags);
1103 return change;
1104}
1105
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001106static struct snd_kcontrol_new snd_emu10k1_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107{
1108 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001109 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 .name = "EMU10K1 PCM Volume",
1111 .count = 32,
1112 .info = snd_emu10k1_attn_info,
1113 .get = snd_emu10k1_attn_get,
1114 .put = snd_emu10k1_attn_put
1115};
1116
1117/* Mutichannel PCM stream controls */
1118
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001119static int snd_emu10k1_efx_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001121 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1123 uinfo->count = emu->audigy ? 8 : 4;
1124 uinfo->value.integer.min = 0;
1125 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
1126 return 0;
1127}
1128
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001129static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol,
1130 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131{
1132 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001133 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1134 struct snd_emu10k1_pcm_mixer *mix =
1135 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 int idx;
1137 int num_efx = emu->audigy ? 8 : 4;
1138 int mask = emu->audigy ? 0x3f : 0x0f;
1139
1140 spin_lock_irqsave(&emu->reg_lock, flags);
1141 for (idx = 0; idx < num_efx; idx++)
1142 ucontrol->value.integer.value[idx] =
1143 mix->send_routing[0][idx] & mask;
1144 spin_unlock_irqrestore(&emu->reg_lock, flags);
1145 return 0;
1146}
1147
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001148static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol,
1149 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150{
1151 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001152 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001154 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 int change = 0, idx, val;
1156 int num_efx = emu->audigy ? 8 : 4;
1157 int mask = emu->audigy ? 0x3f : 0x0f;
1158
1159 spin_lock_irqsave(&emu->reg_lock, flags);
1160 for (idx = 0; idx < num_efx; idx++) {
1161 val = ucontrol->value.integer.value[idx] & mask;
1162 if (mix->send_routing[0][idx] != val) {
1163 mix->send_routing[0][idx] = val;
1164 change = 1;
1165 }
1166 }
1167
1168 if (change && mix->epcm) {
1169 if (mix->epcm->voices[ch]) {
1170 update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number,
1171 &mix->send_routing[0][0]);
1172 }
1173 }
1174 spin_unlock_irqrestore(&emu->reg_lock, flags);
1175 return change;
1176}
1177
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001178static struct snd_kcontrol_new snd_emu10k1_efx_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179{
1180 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1181 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1182 .name = "Multichannel PCM Send Routing",
1183 .count = 16,
1184 .info = snd_emu10k1_efx_send_routing_info,
1185 .get = snd_emu10k1_efx_send_routing_get,
1186 .put = snd_emu10k1_efx_send_routing_put
1187};
1188
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001189static int snd_emu10k1_efx_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001191 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1193 uinfo->count = emu->audigy ? 8 : 4;
1194 uinfo->value.integer.min = 0;
1195 uinfo->value.integer.max = 255;
1196 return 0;
1197}
1198
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001199static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol,
1200 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201{
1202 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001203 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1204 struct snd_emu10k1_pcm_mixer *mix =
1205 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 int idx;
1207 int num_efx = emu->audigy ? 8 : 4;
1208
1209 spin_lock_irqsave(&emu->reg_lock, flags);
1210 for (idx = 0; idx < num_efx; idx++)
1211 ucontrol->value.integer.value[idx] = mix->send_volume[0][idx];
1212 spin_unlock_irqrestore(&emu->reg_lock, flags);
1213 return 0;
1214}
1215
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001216static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol,
1217 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218{
1219 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001220 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001222 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 int change = 0, idx, val;
1224 int num_efx = emu->audigy ? 8 : 4;
1225
1226 spin_lock_irqsave(&emu->reg_lock, flags);
1227 for (idx = 0; idx < num_efx; idx++) {
1228 val = ucontrol->value.integer.value[idx] & 255;
1229 if (mix->send_volume[0][idx] != val) {
1230 mix->send_volume[0][idx] = val;
1231 change = 1;
1232 }
1233 }
1234 if (change && mix->epcm) {
1235 if (mix->epcm->voices[ch]) {
1236 update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number,
1237 &mix->send_volume[0][0]);
1238 }
1239 }
1240 spin_unlock_irqrestore(&emu->reg_lock, flags);
1241 return change;
1242}
1243
1244
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001245static struct snd_kcontrol_new snd_emu10k1_efx_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246{
1247 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1248 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1249 .name = "Multichannel PCM Send Volume",
1250 .count = 16,
1251 .info = snd_emu10k1_efx_send_volume_info,
1252 .get = snd_emu10k1_efx_send_volume_get,
1253 .put = snd_emu10k1_efx_send_volume_put
1254};
1255
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001256static int snd_emu10k1_efx_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257{
1258 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1259 uinfo->count = 1;
1260 uinfo->value.integer.min = 0;
1261 uinfo->value.integer.max = 0xffff;
1262 return 0;
1263}
1264
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001265static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol,
1266 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001268 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1269 struct snd_emu10k1_pcm_mixer *mix =
1270 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 unsigned long flags;
1272
1273 spin_lock_irqsave(&emu->reg_lock, flags);
1274 ucontrol->value.integer.value[0] = mix->attn[0];
1275 spin_unlock_irqrestore(&emu->reg_lock, flags);
1276 return 0;
1277}
1278
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001279static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol,
1280 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281{
1282 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001283 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001285 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 int change = 0, val;
1287
1288 spin_lock_irqsave(&emu->reg_lock, flags);
1289 val = ucontrol->value.integer.value[0] & 0xffff;
1290 if (mix->attn[0] != val) {
1291 mix->attn[0] = val;
1292 change = 1;
1293 }
1294 if (change && mix->epcm) {
1295 if (mix->epcm->voices[ch]) {
1296 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]);
1297 }
1298 }
1299 spin_unlock_irqrestore(&emu->reg_lock, flags);
1300 return change;
1301}
1302
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001303static struct snd_kcontrol_new snd_emu10k1_efx_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304{
1305 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1306 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1307 .name = "Multichannel PCM Volume",
1308 .count = 16,
1309 .info = snd_emu10k1_efx_attn_info,
1310 .get = snd_emu10k1_efx_attn_get,
1311 .put = snd_emu10k1_efx_attn_put
1312};
1313
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001314#define snd_emu10k1_shared_spdif_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001316static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol,
1317 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001319 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320
1321 if (emu->audigy)
1322 ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0;
1323 else
1324 ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0;
1325 return 0;
1326}
1327
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001328static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
1329 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330{
1331 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001332 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 unsigned int reg, val;
1334 int change = 0;
1335
1336 spin_lock_irqsave(&emu->reg_lock, flags);
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001337 if ( emu->card_capabilities->i2c_adc) {
1338 /* Do nothing for Audigy 2 ZS Notebook */
1339 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 reg = inl(emu->port + A_IOCFG);
1341 val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0;
1342 change = (reg & A_IOCFG_GPOUT0) != val;
1343 if (change) {
1344 reg &= ~A_IOCFG_GPOUT0;
1345 reg |= val;
1346 outl(reg | val, emu->port + A_IOCFG);
1347 }
1348 }
1349 reg = inl(emu->port + HCFG);
1350 val = ucontrol->value.integer.value[0] ? HCFG_GPOUT0 : 0;
1351 change |= (reg & HCFG_GPOUT0) != val;
1352 if (change) {
1353 reg &= ~HCFG_GPOUT0;
1354 reg |= val;
1355 outl(reg | val, emu->port + HCFG);
1356 }
1357 spin_unlock_irqrestore(&emu->reg_lock, flags);
1358 return change;
1359}
1360
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001361static struct snd_kcontrol_new snd_emu10k1_shared_spdif __devinitdata =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362{
1363 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1364 .name = "SB Live Analog/Digital Output Jack",
1365 .info = snd_emu10k1_shared_spdif_info,
1366 .get = snd_emu10k1_shared_spdif_get,
1367 .put = snd_emu10k1_shared_spdif_put
1368};
1369
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001370static struct snd_kcontrol_new snd_audigy_shared_spdif __devinitdata =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371{
1372 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1373 .name = "Audigy Analog/Digital Output Jack",
1374 .info = snd_emu10k1_shared_spdif_info,
1375 .get = snd_emu10k1_shared_spdif_get,
1376 .put = snd_emu10k1_shared_spdif_put
1377};
1378
1379/*
1380 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001381static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001383 struct snd_emu10k1 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 emu->ac97 = NULL;
1385}
1386
1387/*
1388 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001389static int remove_ctl(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001391 struct snd_ctl_elem_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 memset(&id, 0, sizeof(id));
1393 strcpy(id.name, name);
1394 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1395 return snd_ctl_remove_id(card, &id);
1396}
1397
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001398static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001400 struct snd_ctl_elem_id sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 memset(&sid, 0, sizeof(sid));
1402 strcpy(sid.name, name);
1403 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1404 return snd_ctl_find_id(card, &sid);
1405}
1406
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001407static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001409 struct snd_kcontrol *kctl = ctl_find(card, src);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 if (kctl) {
1411 strcpy(kctl->id.name, dst);
1412 return 0;
1413 }
1414 return -ENOENT;
1415}
1416
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001417int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001418 int pcm_device, int multi_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419{
1420 int err, pcm;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001421 struct snd_kcontrol *kctl;
1422 struct snd_card *card = emu->card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 char **c;
1424 static char *emu10k1_remove_ctls[] = {
1425 /* no AC97 mono, surround, center/lfe */
1426 "Master Mono Playback Switch",
1427 "Master Mono Playback Volume",
1428 "PCM Out Path & Mute",
1429 "Mono Output Select",
Takashi Iwai7eae36f2006-01-05 18:40:56 +01001430 "Front Playback Switch",
1431 "Front Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 "Surround Playback Switch",
1433 "Surround Playback Volume",
1434 "Center Playback Switch",
1435 "Center Playback Volume",
1436 "LFE Playback Switch",
1437 "LFE Playback Volume",
1438 NULL
1439 };
1440 static char *emu10k1_rename_ctls[] = {
1441 "Surround Digital Playback Volume", "Surround Playback Volume",
1442 "Center Digital Playback Volume", "Center Playback Volume",
1443 "LFE Digital Playback Volume", "LFE Playback Volume",
1444 NULL
1445 };
1446 static char *audigy_remove_ctls[] = {
1447 /* Master/PCM controls on ac97 of Audigy has no effect */
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001448 /* On the Audigy2 the AC97 playback is piped into
1449 * the Philips ADC for 24bit capture */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 "PCM Playback Switch",
1451 "PCM Playback Volume",
1452 "Master Mono Playback Switch",
1453 "Master Mono Playback Volume",
1454 "Master Playback Switch",
1455 "Master Playback Volume",
1456 "PCM Out Path & Mute",
1457 "Mono Output Select",
1458 /* remove unused AC97 capture controls */
1459 "Capture Source",
1460 "Capture Switch",
1461 "Capture Volume",
1462 "Mic Select",
1463 "Video Playback Switch",
1464 "Video Playback Volume",
1465 "Mic Playback Switch",
1466 "Mic Playback Volume",
1467 NULL
1468 };
1469 static char *audigy_rename_ctls[] = {
1470 /* use conventional names */
1471 "Wave Playback Volume", "PCM Playback Volume",
1472 /* "Wave Capture Volume", "PCM Capture Volume", */
1473 "Wave Master Playback Volume", "Master Playback Volume",
1474 "AMic Playback Volume", "Mic Playback Volume",
1475 NULL
1476 };
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001477 static char *audigy_rename_ctls_i2c_adc[] = {
1478 //"Analog Mix Capture Volume","OLD Analog Mix Capture Volume",
1479 "Line Capture Volume", "Analog Mix Capture Volume",
1480 "Wave Playback Volume", "OLD PCM Playback Volume",
1481 "Wave Master Playback Volume", "Master Playback Volume",
1482 "AMic Playback Volume", "Old Mic Playback Volume",
James Courtier-Duttoneb41dab2006-12-06 20:38:45 +00001483 "CD Capture Volume", "IEC958 Optical Capture Volume",
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001484 NULL
1485 };
1486 static char *audigy_remove_ctls_i2c_adc[] = {
1487 /* On the Audigy2 ZS Notebook
1488 * Capture via WM8775 */
1489 "Mic Capture Volume",
1490 "Analog Mix Capture Volume",
1491 "Aux Capture Volume",
James Courtier-Duttoneb41dab2006-12-06 20:38:45 +00001492 "IEC958 Optical Capture Volume",
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001493 NULL
1494 };
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001495 static char *audigy_remove_ctls_1361t_adc[] = {
1496 /* On the Audigy2 the AC97 playback is piped into
1497 * the Philips ADC for 24bit capture */
1498 "PCM Playback Switch",
1499 "PCM Playback Volume",
1500 "Master Mono Playback Switch",
1501 "Master Mono Playback Volume",
1502 "Capture Source",
1503 "Capture Switch",
1504 "Capture Volume",
1505 "Mic Capture Volume",
1506 "Headphone Playback Switch",
1507 "Headphone Playback Volume",
1508 "3D Control - Center",
1509 "3D Control - Depth",
1510 "3D Control - Switch",
1511 "Line2 Playback Volume",
1512 "Line2 Capture Volume",
1513 NULL
1514 };
1515 static char *audigy_rename_ctls_1361t_adc[] = {
1516 "Master Playback Switch", "Master Capture Switch",
1517 "Master Playback Volume", "Master Capture Volume",
1518 "Wave Master Playback Volume", "Master Playback Volume",
1519 "PC Speaker Playback Switch", "PC Speaker Capture Switch",
1520 "PC Speaker Playback Volume", "PC Speaker Capture Volume",
1521 "Phone Playback Switch", "Phone Capture Switch",
1522 "Phone Playback Volume", "Phone Capture Volume",
1523 "Mic Playback Switch", "Mic Capture Switch",
1524 "Mic Playback Volume", "Mic Capture Volume",
1525 "Line Playback Switch", "Line Capture Switch",
1526 "Line Playback Volume", "Line Capture Volume",
1527 "CD Playback Switch", "CD Capture Switch",
1528 "CD Playback Volume", "CD Capture Volume",
1529 "Aux Playback Switch", "Aux Capture Switch",
1530 "Aux Playback Volume", "Aux Capture Volume",
1531 "Video Playback Switch", "Video Capture Switch",
1532 "Video Playback Volume", "Video Capture Volume",
1533
1534 NULL
1535 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536
Lee Revell2b637da2005-03-30 13:51:18 +02001537 if (emu->card_capabilities->ac97_chip) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001538 struct snd_ac97_bus *pbus;
1539 struct snd_ac97_template ac97;
1540 static struct snd_ac97_bus_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 .write = snd_emu10k1_ac97_write,
1542 .read = snd_emu10k1_ac97_read,
1543 };
1544
Takashi Iwaib1508692005-10-04 13:49:32 +02001545 if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0)
1546 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 pbus->no_vra = 1; /* we don't need VRA */
1548
1549 memset(&ac97, 0, sizeof(ac97));
1550 ac97.private_data = emu;
1551 ac97.private_free = snd_emu10k1_mixer_free_ac97;
1552 ac97.scaps = AC97_SCAP_NO_SPDIF;
Takashi Iwaib1508692005-10-04 13:49:32 +02001553 if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) {
1554 if (emu->card_capabilities->ac97_chip == 1)
1555 return err;
1556 snd_printd(KERN_INFO "emu10k1: AC97 is optional on this board\n");
1557 snd_printd(KERN_INFO" Proceeding without ac97 mixers...\n");
1558 snd_device_free(emu->card, pbus);
1559 goto no_ac97; /* FIXME: get rid of ugly gotos.. */
1560 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561 if (emu->audigy) {
1562 /* set master volume to 0 dB */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001563 snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564 /* set capture source to mic */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001565 snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001566 if (emu->card_capabilities->adc_1361t)
1567 c = audigy_remove_ctls_1361t_adc;
1568 else
1569 c = audigy_remove_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 } else {
1571 /*
1572 * Credits for cards based on STAC9758:
1573 * James Courtier-Dutton <James@superbug.demon.co.uk>
1574 * Voluspa <voluspa@comhem.se>
1575 */
1576 if (emu->ac97->id == AC97_ID_STAC9758) {
1577 emu->rear_ac97 = 1;
1578 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 +01001579 snd_ac97_write_cache(emu->ac97, AC97_HEADPHONE, 0x0202);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 }
1581 /* remove unused AC97 controls */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001582 snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
1583 snd_ac97_write_cache(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 c = emu10k1_remove_ctls;
1585 }
1586 for (; *c; c++)
1587 remove_ctl(card, *c);
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001588 } else if (emu->card_capabilities->i2c_adc) {
1589 c = audigy_remove_ctls_i2c_adc;
1590 for (; *c; c++)
1591 remove_ctl(card, *c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 } else {
Takashi Iwaif12aa402005-09-30 16:56:59 +02001593 no_ac97:
Lee Revell2b637da2005-03-30 13:51:18 +02001594 if (emu->card_capabilities->ecard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595 strcpy(emu->card->mixername, "EMU APS");
1596 else if (emu->audigy)
1597 strcpy(emu->card->mixername, "SB Audigy");
1598 else
1599 strcpy(emu->card->mixername, "Emu10k1");
1600 }
1601
1602 if (emu->audigy)
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001603 if (emu->card_capabilities->adc_1361t)
1604 c = audigy_rename_ctls_1361t_adc;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001605 else if (emu->card_capabilities->i2c_adc)
1606 c = audigy_rename_ctls_i2c_adc;
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001607 else
1608 c = audigy_rename_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609 else
1610 c = emu10k1_rename_ctls;
1611 for (; *c; c += 2)
1612 rename_ctl(card, c[0], c[1]);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001613
James Courtier-Duttone3b9bc02005-12-24 16:54:51 +01001614 if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */
1615 rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume");
1616 rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume");
1617 rename_ctl(card, "Aux2 Capture Volume", "Line3 Capture Volume");
1618 rename_ctl(card, "Mic Capture Volume", "Unknown1 Capture Volume");
1619 remove_ctl(card, "Headphone Playback Switch");
1620 remove_ctl(card, "Headphone Playback Volume");
1621 remove_ctl(card, "3D Control - Center");
1622 remove_ctl(card, "3D Control - Depth");
1623 remove_ctl(card, "3D Control - Switch");
1624 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL)
1626 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001627 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 if ((err = snd_ctl_add(card, kctl)))
1629 return err;
1630 if ((kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL)
1631 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001632 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 if ((err = snd_ctl_add(card, kctl)))
1634 return err;
1635 if ((kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu)) == NULL)
1636 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001637 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 if ((err = snd_ctl_add(card, kctl)))
1639 return err;
1640
1641 if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL)
1642 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001643 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 if ((err = snd_ctl_add(card, kctl)))
1645 return err;
1646
1647 if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL)
1648 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001649 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 if ((err = snd_ctl_add(card, kctl)))
1651 return err;
1652
1653 if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL)
1654 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001655 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656 if ((err = snd_ctl_add(card, kctl)))
1657 return err;
1658
1659 /* initialize the routing and volume table for each pcm playback stream */
1660 for (pcm = 0; pcm < 32; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001661 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 int v;
1663
1664 mix = &emu->pcm_mixer[pcm];
1665 mix->epcm = NULL;
1666
1667 for (v = 0; v < 4; v++)
1668 mix->send_routing[0][v] =
1669 mix->send_routing[1][v] =
1670 mix->send_routing[2][v] = v;
1671
1672 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1673 mix->send_volume[0][0] = mix->send_volume[0][1] =
1674 mix->send_volume[1][0] = mix->send_volume[2][1] = 255;
1675
1676 mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
1677 }
1678
1679 /* initialize the routing and volume table for the multichannel playback stream */
1680 for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001681 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 int v;
1683
1684 mix = &emu->efx_pcm_mixer[pcm];
1685 mix->epcm = NULL;
1686
1687 mix->send_routing[0][0] = pcm;
1688 mix->send_routing[0][1] = (pcm == 0) ? 1 : 0;
1689 for (v = 0; v < 2; v++)
1690 mix->send_routing[0][2+v] = 13+v;
1691 if (emu->audigy)
1692 for (v = 0; v < 4; v++)
1693 mix->send_routing[0][4+v] = 60+v;
1694
1695 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1696 mix->send_volume[0][0] = 255;
1697
1698 mix->attn[0] = 0xffff;
1699 }
1700
Lee Revell2b637da2005-03-30 13:51:18 +02001701 if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 /* sb live! and audigy */
1703 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
1704 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02001705 if (!emu->audigy)
1706 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 if ((err = snd_ctl_add(card, kctl)))
1708 return err;
1709 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
1710 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02001711 if (!emu->audigy)
1712 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 if ((err = snd_ctl_add(card, kctl)))
1714 return err;
1715 }
1716
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001717 if ( emu->card_capabilities->emu1010) {
James Courtier-Dutton19b99fb2005-12-04 18:03:03 +01001718 ; /* Disable the snd_audigy_spdif_shared_spdif */
1719 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
1721 return -ENOMEM;
1722 if ((err = snd_ctl_add(card, kctl)))
1723 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02001724#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
1726 return -ENOMEM;
1727 if ((err = snd_ctl_add(card, kctl)))
1728 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02001729#endif
Lee Revell2b637da2005-03-30 13:51:18 +02001730 } else if (! emu->card_capabilities->ecard) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 /* sb live! */
1732 if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
1733 return -ENOMEM;
1734 if ((err = snd_ctl_add(card, kctl)))
1735 return err;
1736 }
Lee Revell2b637da2005-03-30 13:51:18 +02001737 if (emu->card_capabilities->ca0151_chip) { /* P16V */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 if ((err = snd_p16v_mixer(emu)))
1739 return err;
1740 }
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001741
1742 if ( emu->card_capabilities->emu1010) {
1743 int i;
1744
1745 for (i = 0; i < ARRAY_SIZE(snd_emu1010_output_enum_ctls); i++) {
1746 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_output_enum_ctls[i], emu));
1747 if (err < 0)
1748 return err;
1749 }
1750 for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) {
1751 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], emu));
1752 if (err < 0)
1753 return err;
1754 }
James Courtier-Dutton9148cc52006-10-09 23:08:00 +01001755 for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads); i++) {
1756 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_adc_pads[i], emu));
1757 if (err < 0)
1758 return err;
1759 }
1760 for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads); i++) {
1761 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_dac_pads[i], emu));
1762 if (err < 0)
1763 return err;
1764 }
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +01001765 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_internal_clock, emu));
1766 if (err < 0)
1767 return err;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001768 }
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001769
1770 if ( emu->card_capabilities->i2c_adc) {
1771 int i;
1772
1773 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_capture_source, emu));
1774 if (err < 0)
1775 return err;
1776
1777 for (i = 0; i < ARRAY_SIZE(snd_audigy_i2c_volume_ctls); i++) {
1778 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_volume_ctls[i], emu));
1779 if (err < 0)
1780 return err;
1781 }
1782 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783
1784 return 0;
1785}