blob: 71ad5a038e811970bc724a0dd3780df5b86b0277 [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{
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100504 static char *texts[4] = {
505 "44100", "48000", "SPDIF", "ADAT"
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100506 };
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100507
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100508 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
509 uinfo->count = 1;
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100510 uinfo->value.enumerated.items = 4;
511 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
512 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100513 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
514 return 0;
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100515
516
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100517}
518
519static int snd_emu1010_internal_clock_get(struct snd_kcontrol *kcontrol,
520 struct snd_ctl_elem_value *ucontrol)
521{
522 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
523
524 ucontrol->value.enumerated.item[0] = emu->emu1010.internal_clock;
525 return 0;
526}
527
528static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol,
529 struct snd_ctl_elem_value *ucontrol)
530{
531 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
532 unsigned int val;
533 int change = 0;
534
535 val = ucontrol->value.enumerated.item[0] ;
536 change = (emu->emu1010.internal_clock != val);
537 if (change) {
538 emu->emu1010.internal_clock = val;
539 switch (val) {
540 case 0:
541 /* 44100 */
542 /* Mute all */
543 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
544 /* Default fallback clock 48kHz */
545 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_44_1K );
546 /* Word Clock source, Internal 44.1kHz x1 */
547 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
548 EMU_HANA_WCLOCK_INT_44_1K | EMU_HANA_WCLOCK_1X );
549 /* Set LEDs on Audio Dock */
550 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
551 EMU_HANA_DOCK_LEDS_2_44K | EMU_HANA_DOCK_LEDS_2_LOCK );
552 /* Allow DLL to settle */
James Courtier-Duttone40a0b22006-10-10 18:44:29 +0100553 msleep(10);
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100554 /* Unmute all */
555 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
556 break;
557 case 1:
558 /* 48000 */
559 /* Mute all */
560 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
561 /* Default fallback clock 48kHz */
562 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
563 /* Word Clock source, Internal 48kHz x1 */
564 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
565 EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_1X );
566 /* Set LEDs on Audio Dock */
567 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
568 EMU_HANA_DOCK_LEDS_2_48K | EMU_HANA_DOCK_LEDS_2_LOCK );
569 /* Allow DLL to settle */
James Courtier-Duttone40a0b22006-10-10 18:44:29 +0100570 msleep(10);
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100571 /* Unmute all */
572 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
573 break;
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100574
575 case 2: /* Take clock from S/PDIF IN */
576 /* Mute all */
577 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
578 /* Default fallback clock 48kHz */
579 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
580 /* Word Clock source, sync to S/PDIF input */
581 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
582 EMU_HANA_WCLOCK_HANA_SPDIF_IN | EMU_HANA_WCLOCK_1X );
583 /* Set LEDs on Audio Dock */
584 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
585 EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK );
586 /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */
587 /* Allow DLL to settle */
588 msleep(10);
589 /* Unmute all */
590 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
591 break;
592
593 case 3:
594 /* Take clock from ADAT IN */
595 /* Mute all */
596 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
597 /* Default fallback clock 48kHz */
598 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
599 /* Word Clock source, sync to ADAT input */
600 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
601 EMU_HANA_WCLOCK_HANA_ADAT_IN | EMU_HANA_WCLOCK_1X );
602 /* Set LEDs on Audio Dock */
603 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK );
604 /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */
605 /* Allow DLL to settle */
606 msleep(10);
607 /* Unmute all */
608 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
609
610
611 break;
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100612 }
613 }
614 return change;
615}
616
617static struct snd_kcontrol_new snd_emu1010_internal_clock =
618{
619 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
620 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
621 .name = "Clock Internal Rate",
622 .count = 1,
623 .info = snd_emu1010_internal_clock_info,
624 .get = snd_emu1010_internal_clock_get,
625 .put = snd_emu1010_internal_clock_put
626};
627
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000628static int snd_audigy_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
629 struct snd_ctl_elem_info *uinfo)
630{
631#if 0
632 static char *texts[4] = {
633 "Unknown1", "Unknown2", "Mic", "Line"
634 };
635#endif
636 static char *texts[2] = {
637 "Mic", "Line"
638 };
639
640 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
641 uinfo->count = 1;
642 uinfo->value.enumerated.items = 2;
643 if (uinfo->value.enumerated.item > 1)
644 uinfo->value.enumerated.item = 1;
645 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
646 return 0;
647}
648
649static int snd_audigy_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
650 struct snd_ctl_elem_value *ucontrol)
651{
652 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
653
654 ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
655 return 0;
656}
657
658static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
659 struct snd_ctl_elem_value *ucontrol)
660{
661 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
662 unsigned int source_id;
663 unsigned int ngain, ogain;
664 u32 gpio;
665 int change = 0;
666 unsigned long flags;
667 u32 source;
668 /* If the capture source has changed,
669 * update the capture volume from the cached value
670 * for the particular source.
671 */
672 source_id = ucontrol->value.enumerated.item[0]; /* Use 2 and 3 */
673 change = (emu->i2c_capture_source != source_id);
674 if (change) {
675 snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */
676 spin_lock_irqsave(&emu->emu_lock, flags);
677 gpio = inl(emu->port + A_IOCFG);
678 if (source_id==0)
679 outl(gpio | 0x4, emu->port + A_IOCFG);
680 else
681 outl(gpio & ~0x4, emu->port + A_IOCFG);
682 spin_unlock_irqrestore(&emu->emu_lock, flags);
683
684 ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
685 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
686 if (ngain != ogain)
687 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
688 ngain = emu->i2c_capture_volume[source_id][1]; /* Right */
689 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
690 if (ngain != ogain)
691 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
692
693 source = 1 << (source_id + 2);
694 snd_emu10k1_i2c_write(emu, ADC_MUX, source); /* Set source */
695 emu->i2c_capture_source = source_id;
696 }
697 return change;
698}
699
700static struct snd_kcontrol_new snd_audigy_i2c_capture_source =
701{
702 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
703 .name = "Capture Source",
704 .info = snd_audigy_i2c_capture_source_info,
705 .get = snd_audigy_i2c_capture_source_get,
706 .put = snd_audigy_i2c_capture_source_put
707};
708
709static int snd_audigy_i2c_volume_info(struct snd_kcontrol *kcontrol,
710 struct snd_ctl_elem_info *uinfo)
711{
712 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
713 uinfo->count = 2;
714 uinfo->value.integer.min = 0;
715 uinfo->value.integer.max = 255;
716 return 0;
717}
718
719static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol,
720 struct snd_ctl_elem_value *ucontrol)
721{
722 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
723 int source_id;
724
725 source_id = kcontrol->private_value;
726
727 ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
728 ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
729 return 0;
730}
731
732static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
733 struct snd_ctl_elem_value *ucontrol)
734{
735 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
736 unsigned int ogain;
737 unsigned int ngain;
738 int source_id;
739 int change = 0;
740
741 source_id = kcontrol->private_value;
742 ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
743 ngain = ucontrol->value.integer.value[0];
744 if (ngain > 0xff)
745 return 0;
746 if (ogain != ngain) {
747 if (emu->i2c_capture_source == source_id)
748 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
749 emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0];
750 change = 1;
751 }
752 ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
753 ngain = ucontrol->value.integer.value[1];
754 if (ngain > 0xff)
755 return 0;
756 if (ogain != ngain) {
757 if (emu->i2c_capture_source == source_id)
758 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
759 emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1];
760 change = 1;
761 }
762
763 return change;
764}
765
766#define I2C_VOLUME(xname,chid) \
767{ \
768 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
769 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
770 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
771 .info = snd_audigy_i2c_volume_info, \
772 .get = snd_audigy_i2c_volume_get, \
773 .put = snd_audigy_i2c_volume_put, \
774 .tlv = { .p = snd_audigy_db_scale2 }, \
775 .private_value = chid \
776}
777
778
779static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] __devinitdata = {
780 I2C_VOLUME("Mic Capture Volume", 0),
781 I2C_VOLUME("Line Capture Volume", 0)
782};
783
Takashi Iwai0af68e52005-04-11 17:03:03 +0200784#if 0
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100785static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786{
787 static char *texts[] = {"44100", "48000", "96000"};
788
789 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
790 uinfo->count = 1;
791 uinfo->value.enumerated.items = 3;
792 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
793 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
794 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
795 return 0;
796}
797
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100798static int snd_audigy_spdif_output_rate_get(struct snd_kcontrol *kcontrol,
799 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100801 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 unsigned int tmp;
803 unsigned long flags;
804
805
806 spin_lock_irqsave(&emu->reg_lock, flags);
807 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
808 switch (tmp & A_SPDIF_RATE_MASK) {
809 case A_SPDIF_44100:
810 ucontrol->value.enumerated.item[0] = 0;
811 break;
812 case A_SPDIF_48000:
813 ucontrol->value.enumerated.item[0] = 1;
814 break;
815 case A_SPDIF_96000:
816 ucontrol->value.enumerated.item[0] = 2;
817 break;
818 default:
819 ucontrol->value.enumerated.item[0] = 1;
820 }
821 spin_unlock_irqrestore(&emu->reg_lock, flags);
822 return 0;
823}
824
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100825static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol,
826 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100828 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 int change;
830 unsigned int reg, val, tmp;
831 unsigned long flags;
832
833 switch(ucontrol->value.enumerated.item[0]) {
834 case 0:
835 val = A_SPDIF_44100;
836 break;
837 case 1:
838 val = A_SPDIF_48000;
839 break;
840 case 2:
841 val = A_SPDIF_96000;
842 break;
843 default:
844 val = A_SPDIF_48000;
845 break;
846 }
847
848
849 spin_lock_irqsave(&emu->reg_lock, flags);
850 reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
851 tmp = reg & ~A_SPDIF_RATE_MASK;
852 tmp |= val;
853 if ((change = (tmp != reg)))
854 snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
855 spin_unlock_irqrestore(&emu->reg_lock, flags);
856 return change;
857}
858
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100859static struct snd_kcontrol_new snd_audigy_spdif_output_rate =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860{
861 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
862 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
863 .name = "Audigy SPDIF Output Sample Rate",
864 .count = 1,
865 .info = snd_audigy_spdif_output_rate_info,
866 .get = snd_audigy_spdif_output_rate_get,
867 .put = snd_audigy_spdif_output_rate_put
868};
Takashi Iwai0af68e52005-04-11 17:03:03 +0200869#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100871static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol,
872 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100874 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
876 int change;
877 unsigned int val;
878 unsigned long flags;
879
880 val = (ucontrol->value.iec958.status[0] << 0) |
881 (ucontrol->value.iec958.status[1] << 8) |
882 (ucontrol->value.iec958.status[2] << 16) |
883 (ucontrol->value.iec958.status[3] << 24);
884 spin_lock_irqsave(&emu->reg_lock, flags);
885 change = val != emu->spdif_bits[idx];
886 if (change) {
887 snd_emu10k1_ptr_write(emu, SPCS0 + idx, 0, val);
888 emu->spdif_bits[idx] = val;
889 }
890 spin_unlock_irqrestore(&emu->reg_lock, flags);
891 return change;
892}
893
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100894static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895{
896 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +0200897 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
Takashi Iwai7583cb52007-08-16 19:32:16 +0200899 .count = 3,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 .info = snd_emu10k1_spdif_info,
901 .get = snd_emu10k1_spdif_get_mask
902};
903
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100904static struct snd_kcontrol_new snd_emu10k1_spdif_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905{
Clemens Ladisch5549d542005-08-03 13:50:30 +0200906 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
Takashi Iwai7583cb52007-08-16 19:32:16 +0200908 .count = 3,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 .info = snd_emu10k1_spdif_info,
910 .get = snd_emu10k1_spdif_get,
911 .put = snd_emu10k1_spdif_put
912};
913
914
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100915static void update_emu10k1_fxrt(struct snd_emu10k1 *emu, int voice, unsigned char *route)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916{
917 if (emu->audigy) {
918 snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
919 snd_emu10k1_compose_audigy_fxrt1(route));
920 snd_emu10k1_ptr_write(emu, A_FXRT2, voice,
921 snd_emu10k1_compose_audigy_fxrt2(route));
922 } else {
923 snd_emu10k1_ptr_write(emu, FXRT, voice,
924 snd_emu10k1_compose_send_routing(route));
925 }
926}
927
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100928static void update_emu10k1_send_volume(struct snd_emu10k1 *emu, int voice, unsigned char *volume)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929{
930 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]);
931 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]);
932 snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, volume[2]);
933 snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, volume[3]);
934 if (emu->audigy) {
935 unsigned int val = ((unsigned int)volume[4] << 24) |
936 ((unsigned int)volume[5] << 16) |
937 ((unsigned int)volume[6] << 8) |
938 (unsigned int)volume[7];
939 snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, val);
940 }
941}
942
943/* PCM stream controls */
944
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100945static int snd_emu10k1_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100947 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
949 uinfo->count = emu->audigy ? 3*8 : 3*4;
950 uinfo->value.integer.min = 0;
951 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
952 return 0;
953}
954
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100955static int snd_emu10k1_send_routing_get(struct snd_kcontrol *kcontrol,
956 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957{
958 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100959 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
960 struct snd_emu10k1_pcm_mixer *mix =
961 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 int voice, idx;
963 int num_efx = emu->audigy ? 8 : 4;
964 int mask = emu->audigy ? 0x3f : 0x0f;
965
966 spin_lock_irqsave(&emu->reg_lock, flags);
967 for (voice = 0; voice < 3; voice++)
968 for (idx = 0; idx < num_efx; idx++)
969 ucontrol->value.integer.value[(voice * num_efx) + idx] =
970 mix->send_routing[voice][idx] & mask;
971 spin_unlock_irqrestore(&emu->reg_lock, flags);
972 return 0;
973}
974
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100975static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol,
976 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977{
978 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100979 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
980 struct snd_emu10k1_pcm_mixer *mix =
981 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 int change = 0, voice, idx, val;
983 int num_efx = emu->audigy ? 8 : 4;
984 int mask = emu->audigy ? 0x3f : 0x0f;
985
986 spin_lock_irqsave(&emu->reg_lock, flags);
987 for (voice = 0; voice < 3; voice++)
988 for (idx = 0; idx < num_efx; idx++) {
989 val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask;
990 if (mix->send_routing[voice][idx] != val) {
991 mix->send_routing[voice][idx] = val;
992 change = 1;
993 }
994 }
995 if (change && mix->epcm) {
996 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
997 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
998 &mix->send_routing[1][0]);
999 update_emu10k1_fxrt(emu, mix->epcm->voices[1]->number,
1000 &mix->send_routing[2][0]);
1001 } else if (mix->epcm->voices[0]) {
1002 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
1003 &mix->send_routing[0][0]);
1004 }
1005 }
1006 spin_unlock_irqrestore(&emu->reg_lock, flags);
1007 return change;
1008}
1009
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001010static struct snd_kcontrol_new snd_emu10k1_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011{
1012 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001013 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 .name = "EMU10K1 PCM Send Routing",
1015 .count = 32,
1016 .info = snd_emu10k1_send_routing_info,
1017 .get = snd_emu10k1_send_routing_get,
1018 .put = snd_emu10k1_send_routing_put
1019};
1020
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001021static int snd_emu10k1_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001023 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1025 uinfo->count = emu->audigy ? 3*8 : 3*4;
1026 uinfo->value.integer.min = 0;
1027 uinfo->value.integer.max = 255;
1028 return 0;
1029}
1030
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001031static int snd_emu10k1_send_volume_get(struct snd_kcontrol *kcontrol,
1032 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033{
1034 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001035 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1036 struct snd_emu10k1_pcm_mixer *mix =
1037 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 int idx;
1039 int num_efx = emu->audigy ? 8 : 4;
1040
1041 spin_lock_irqsave(&emu->reg_lock, flags);
1042 for (idx = 0; idx < 3*num_efx; idx++)
1043 ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx];
1044 spin_unlock_irqrestore(&emu->reg_lock, flags);
1045 return 0;
1046}
1047
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001048static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol,
1049 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050{
1051 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001052 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1053 struct snd_emu10k1_pcm_mixer *mix =
1054 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 int change = 0, idx, val;
1056 int num_efx = emu->audigy ? 8 : 4;
1057
1058 spin_lock_irqsave(&emu->reg_lock, flags);
1059 for (idx = 0; idx < 3*num_efx; idx++) {
1060 val = ucontrol->value.integer.value[idx] & 255;
1061 if (mix->send_volume[idx/num_efx][idx%num_efx] != val) {
1062 mix->send_volume[idx/num_efx][idx%num_efx] = val;
1063 change = 1;
1064 }
1065 }
1066 if (change && mix->epcm) {
1067 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1068 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
1069 &mix->send_volume[1][0]);
1070 update_emu10k1_send_volume(emu, mix->epcm->voices[1]->number,
1071 &mix->send_volume[2][0]);
1072 } else if (mix->epcm->voices[0]) {
1073 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
1074 &mix->send_volume[0][0]);
1075 }
1076 }
1077 spin_unlock_irqrestore(&emu->reg_lock, flags);
1078 return change;
1079}
1080
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001081static struct snd_kcontrol_new snd_emu10k1_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082{
1083 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001084 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 .name = "EMU10K1 PCM Send Volume",
1086 .count = 32,
1087 .info = snd_emu10k1_send_volume_info,
1088 .get = snd_emu10k1_send_volume_get,
1089 .put = snd_emu10k1_send_volume_put
1090};
1091
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001092static int snd_emu10k1_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093{
1094 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1095 uinfo->count = 3;
1096 uinfo->value.integer.min = 0;
1097 uinfo->value.integer.max = 0xffff;
1098 return 0;
1099}
1100
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001101static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol,
1102 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001104 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1105 struct snd_emu10k1_pcm_mixer *mix =
1106 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 unsigned long flags;
1108 int idx;
1109
1110 spin_lock_irqsave(&emu->reg_lock, flags);
1111 for (idx = 0; idx < 3; idx++)
1112 ucontrol->value.integer.value[idx] = mix->attn[idx];
1113 spin_unlock_irqrestore(&emu->reg_lock, flags);
1114 return 0;
1115}
1116
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001117static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol,
1118 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119{
1120 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001121 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1122 struct snd_emu10k1_pcm_mixer *mix =
1123 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 int change = 0, idx, val;
1125
1126 spin_lock_irqsave(&emu->reg_lock, flags);
1127 for (idx = 0; idx < 3; idx++) {
1128 val = ucontrol->value.integer.value[idx] & 0xffff;
1129 if (mix->attn[idx] != val) {
1130 mix->attn[idx] = val;
1131 change = 1;
1132 }
1133 }
1134 if (change && mix->epcm) {
1135 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1136 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[1]);
1137 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[1]->number, mix->attn[2]);
1138 } else if (mix->epcm->voices[0]) {
1139 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]);
1140 }
1141 }
1142 spin_unlock_irqrestore(&emu->reg_lock, flags);
1143 return change;
1144}
1145
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001146static struct snd_kcontrol_new snd_emu10k1_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147{
1148 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001149 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 .name = "EMU10K1 PCM Volume",
1151 .count = 32,
1152 .info = snd_emu10k1_attn_info,
1153 .get = snd_emu10k1_attn_get,
1154 .put = snd_emu10k1_attn_put
1155};
1156
1157/* Mutichannel PCM stream controls */
1158
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001159static int snd_emu10k1_efx_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001161 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1163 uinfo->count = emu->audigy ? 8 : 4;
1164 uinfo->value.integer.min = 0;
1165 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
1166 return 0;
1167}
1168
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001169static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol,
1170 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171{
1172 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001173 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1174 struct snd_emu10k1_pcm_mixer *mix =
1175 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 int idx;
1177 int num_efx = emu->audigy ? 8 : 4;
1178 int mask = emu->audigy ? 0x3f : 0x0f;
1179
1180 spin_lock_irqsave(&emu->reg_lock, flags);
1181 for (idx = 0; idx < num_efx; idx++)
1182 ucontrol->value.integer.value[idx] =
1183 mix->send_routing[0][idx] & mask;
1184 spin_unlock_irqrestore(&emu->reg_lock, flags);
1185 return 0;
1186}
1187
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001188static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol,
1189 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190{
1191 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001192 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001194 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 int change = 0, idx, val;
1196 int num_efx = emu->audigy ? 8 : 4;
1197 int mask = emu->audigy ? 0x3f : 0x0f;
1198
1199 spin_lock_irqsave(&emu->reg_lock, flags);
1200 for (idx = 0; idx < num_efx; idx++) {
1201 val = ucontrol->value.integer.value[idx] & mask;
1202 if (mix->send_routing[0][idx] != val) {
1203 mix->send_routing[0][idx] = val;
1204 change = 1;
1205 }
1206 }
1207
1208 if (change && mix->epcm) {
1209 if (mix->epcm->voices[ch]) {
1210 update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number,
1211 &mix->send_routing[0][0]);
1212 }
1213 }
1214 spin_unlock_irqrestore(&emu->reg_lock, flags);
1215 return change;
1216}
1217
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001218static struct snd_kcontrol_new snd_emu10k1_efx_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219{
1220 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1221 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1222 .name = "Multichannel PCM Send Routing",
1223 .count = 16,
1224 .info = snd_emu10k1_efx_send_routing_info,
1225 .get = snd_emu10k1_efx_send_routing_get,
1226 .put = snd_emu10k1_efx_send_routing_put
1227};
1228
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001229static int snd_emu10k1_efx_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001231 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1233 uinfo->count = emu->audigy ? 8 : 4;
1234 uinfo->value.integer.min = 0;
1235 uinfo->value.integer.max = 255;
1236 return 0;
1237}
1238
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001239static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol,
1240 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241{
1242 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001243 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1244 struct snd_emu10k1_pcm_mixer *mix =
1245 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 int idx;
1247 int num_efx = emu->audigy ? 8 : 4;
1248
1249 spin_lock_irqsave(&emu->reg_lock, flags);
1250 for (idx = 0; idx < num_efx; idx++)
1251 ucontrol->value.integer.value[idx] = mix->send_volume[0][idx];
1252 spin_unlock_irqrestore(&emu->reg_lock, flags);
1253 return 0;
1254}
1255
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001256static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol,
1257 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258{
1259 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001260 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001262 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 int change = 0, idx, val;
1264 int num_efx = emu->audigy ? 8 : 4;
1265
1266 spin_lock_irqsave(&emu->reg_lock, flags);
1267 for (idx = 0; idx < num_efx; idx++) {
1268 val = ucontrol->value.integer.value[idx] & 255;
1269 if (mix->send_volume[0][idx] != val) {
1270 mix->send_volume[0][idx] = val;
1271 change = 1;
1272 }
1273 }
1274 if (change && mix->epcm) {
1275 if (mix->epcm->voices[ch]) {
1276 update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number,
1277 &mix->send_volume[0][0]);
1278 }
1279 }
1280 spin_unlock_irqrestore(&emu->reg_lock, flags);
1281 return change;
1282}
1283
1284
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001285static struct snd_kcontrol_new snd_emu10k1_efx_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286{
1287 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1288 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1289 .name = "Multichannel PCM Send Volume",
1290 .count = 16,
1291 .info = snd_emu10k1_efx_send_volume_info,
1292 .get = snd_emu10k1_efx_send_volume_get,
1293 .put = snd_emu10k1_efx_send_volume_put
1294};
1295
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001296static int snd_emu10k1_efx_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297{
1298 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1299 uinfo->count = 1;
1300 uinfo->value.integer.min = 0;
1301 uinfo->value.integer.max = 0xffff;
1302 return 0;
1303}
1304
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001305static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol,
1306 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001308 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1309 struct snd_emu10k1_pcm_mixer *mix =
1310 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 unsigned long flags;
1312
1313 spin_lock_irqsave(&emu->reg_lock, flags);
1314 ucontrol->value.integer.value[0] = mix->attn[0];
1315 spin_unlock_irqrestore(&emu->reg_lock, flags);
1316 return 0;
1317}
1318
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001319static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol,
1320 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321{
1322 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001323 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001325 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 int change = 0, val;
1327
1328 spin_lock_irqsave(&emu->reg_lock, flags);
1329 val = ucontrol->value.integer.value[0] & 0xffff;
1330 if (mix->attn[0] != val) {
1331 mix->attn[0] = val;
1332 change = 1;
1333 }
1334 if (change && mix->epcm) {
1335 if (mix->epcm->voices[ch]) {
1336 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]);
1337 }
1338 }
1339 spin_unlock_irqrestore(&emu->reg_lock, flags);
1340 return change;
1341}
1342
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001343static struct snd_kcontrol_new snd_emu10k1_efx_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344{
1345 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1346 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1347 .name = "Multichannel PCM Volume",
1348 .count = 16,
1349 .info = snd_emu10k1_efx_attn_info,
1350 .get = snd_emu10k1_efx_attn_get,
1351 .put = snd_emu10k1_efx_attn_put
1352};
1353
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001354#define snd_emu10k1_shared_spdif_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001356static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol,
1357 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001359 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
1361 if (emu->audigy)
1362 ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0;
1363 else
1364 ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0;
1365 return 0;
1366}
1367
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001368static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
1369 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370{
1371 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001372 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 unsigned int reg, val;
1374 int change = 0;
1375
1376 spin_lock_irqsave(&emu->reg_lock, flags);
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001377 if ( emu->card_capabilities->i2c_adc) {
1378 /* Do nothing for Audigy 2 ZS Notebook */
1379 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 reg = inl(emu->port + A_IOCFG);
1381 val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0;
1382 change = (reg & A_IOCFG_GPOUT0) != val;
1383 if (change) {
1384 reg &= ~A_IOCFG_GPOUT0;
1385 reg |= val;
1386 outl(reg | val, emu->port + A_IOCFG);
1387 }
1388 }
1389 reg = inl(emu->port + HCFG);
1390 val = ucontrol->value.integer.value[0] ? HCFG_GPOUT0 : 0;
1391 change |= (reg & HCFG_GPOUT0) != val;
1392 if (change) {
1393 reg &= ~HCFG_GPOUT0;
1394 reg |= val;
1395 outl(reg | val, emu->port + HCFG);
1396 }
1397 spin_unlock_irqrestore(&emu->reg_lock, flags);
1398 return change;
1399}
1400
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001401static struct snd_kcontrol_new snd_emu10k1_shared_spdif __devinitdata =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402{
1403 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1404 .name = "SB Live Analog/Digital Output Jack",
1405 .info = snd_emu10k1_shared_spdif_info,
1406 .get = snd_emu10k1_shared_spdif_get,
1407 .put = snd_emu10k1_shared_spdif_put
1408};
1409
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001410static struct snd_kcontrol_new snd_audigy_shared_spdif __devinitdata =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411{
1412 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1413 .name = "Audigy Analog/Digital Output Jack",
1414 .info = snd_emu10k1_shared_spdif_info,
1415 .get = snd_emu10k1_shared_spdif_get,
1416 .put = snd_emu10k1_shared_spdif_put
1417};
1418
1419/*
1420 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001421static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001423 struct snd_emu10k1 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 emu->ac97 = NULL;
1425}
1426
1427/*
1428 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001429static int remove_ctl(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001431 struct snd_ctl_elem_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 memset(&id, 0, sizeof(id));
1433 strcpy(id.name, name);
1434 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1435 return snd_ctl_remove_id(card, &id);
1436}
1437
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001438static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001440 struct snd_ctl_elem_id sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 memset(&sid, 0, sizeof(sid));
1442 strcpy(sid.name, name);
1443 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1444 return snd_ctl_find_id(card, &sid);
1445}
1446
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001447static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001449 struct snd_kcontrol *kctl = ctl_find(card, src);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 if (kctl) {
1451 strcpy(kctl->id.name, dst);
1452 return 0;
1453 }
1454 return -ENOENT;
1455}
1456
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001457int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001458 int pcm_device, int multi_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459{
1460 int err, pcm;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001461 struct snd_kcontrol *kctl;
1462 struct snd_card *card = emu->card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 char **c;
1464 static char *emu10k1_remove_ctls[] = {
1465 /* no AC97 mono, surround, center/lfe */
1466 "Master Mono Playback Switch",
1467 "Master Mono Playback Volume",
1468 "PCM Out Path & Mute",
1469 "Mono Output Select",
Takashi Iwai7eae36f2006-01-05 18:40:56 +01001470 "Front Playback Switch",
1471 "Front Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 "Surround Playback Switch",
1473 "Surround Playback Volume",
1474 "Center Playback Switch",
1475 "Center Playback Volume",
1476 "LFE Playback Switch",
1477 "LFE Playback Volume",
1478 NULL
1479 };
1480 static char *emu10k1_rename_ctls[] = {
1481 "Surround Digital Playback Volume", "Surround Playback Volume",
1482 "Center Digital Playback Volume", "Center Playback Volume",
1483 "LFE Digital Playback Volume", "LFE Playback Volume",
1484 NULL
1485 };
1486 static char *audigy_remove_ctls[] = {
1487 /* Master/PCM controls on ac97 of Audigy has no effect */
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001488 /* On the Audigy2 the AC97 playback is piped into
1489 * the Philips ADC for 24bit capture */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 "PCM Playback Switch",
1491 "PCM Playback Volume",
1492 "Master Mono Playback Switch",
1493 "Master Mono Playback Volume",
1494 "Master Playback Switch",
1495 "Master Playback Volume",
1496 "PCM Out Path & Mute",
1497 "Mono Output Select",
1498 /* remove unused AC97 capture controls */
1499 "Capture Source",
1500 "Capture Switch",
1501 "Capture Volume",
1502 "Mic Select",
1503 "Video Playback Switch",
1504 "Video Playback Volume",
1505 "Mic Playback Switch",
1506 "Mic Playback Volume",
1507 NULL
1508 };
1509 static char *audigy_rename_ctls[] = {
1510 /* use conventional names */
1511 "Wave Playback Volume", "PCM Playback Volume",
1512 /* "Wave Capture Volume", "PCM Capture Volume", */
1513 "Wave Master Playback Volume", "Master Playback Volume",
1514 "AMic Playback Volume", "Mic Playback Volume",
1515 NULL
1516 };
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001517 static char *audigy_rename_ctls_i2c_adc[] = {
1518 //"Analog Mix Capture Volume","OLD Analog Mix Capture Volume",
1519 "Line Capture Volume", "Analog Mix Capture Volume",
1520 "Wave Playback Volume", "OLD PCM Playback Volume",
1521 "Wave Master Playback Volume", "Master Playback Volume",
1522 "AMic Playback Volume", "Old Mic Playback Volume",
James Courtier-Duttoneb41dab2006-12-06 20:38:45 +00001523 "CD Capture Volume", "IEC958 Optical Capture Volume",
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001524 NULL
1525 };
1526 static char *audigy_remove_ctls_i2c_adc[] = {
1527 /* On the Audigy2 ZS Notebook
1528 * Capture via WM8775 */
1529 "Mic Capture Volume",
1530 "Analog Mix Capture Volume",
1531 "Aux Capture Volume",
James Courtier-Duttoneb41dab2006-12-06 20:38:45 +00001532 "IEC958 Optical Capture Volume",
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001533 NULL
1534 };
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001535 static char *audigy_remove_ctls_1361t_adc[] = {
1536 /* On the Audigy2 the AC97 playback is piped into
1537 * the Philips ADC for 24bit capture */
1538 "PCM Playback Switch",
1539 "PCM Playback Volume",
1540 "Master Mono Playback Switch",
1541 "Master Mono Playback Volume",
1542 "Capture Source",
1543 "Capture Switch",
1544 "Capture Volume",
1545 "Mic Capture Volume",
1546 "Headphone Playback Switch",
1547 "Headphone Playback Volume",
1548 "3D Control - Center",
1549 "3D Control - Depth",
1550 "3D Control - Switch",
1551 "Line2 Playback Volume",
1552 "Line2 Capture Volume",
1553 NULL
1554 };
1555 static char *audigy_rename_ctls_1361t_adc[] = {
1556 "Master Playback Switch", "Master Capture Switch",
1557 "Master Playback Volume", "Master Capture Volume",
1558 "Wave Master Playback Volume", "Master Playback Volume",
1559 "PC Speaker Playback Switch", "PC Speaker Capture Switch",
1560 "PC Speaker Playback Volume", "PC Speaker Capture Volume",
1561 "Phone Playback Switch", "Phone Capture Switch",
1562 "Phone Playback Volume", "Phone Capture Volume",
1563 "Mic Playback Switch", "Mic Capture Switch",
1564 "Mic Playback Volume", "Mic Capture Volume",
1565 "Line Playback Switch", "Line Capture Switch",
1566 "Line Playback Volume", "Line Capture Volume",
1567 "CD Playback Switch", "CD Capture Switch",
1568 "CD Playback Volume", "CD Capture Volume",
1569 "Aux Playback Switch", "Aux Capture Switch",
1570 "Aux Playback Volume", "Aux Capture Volume",
1571 "Video Playback Switch", "Video Capture Switch",
1572 "Video Playback Volume", "Video Capture Volume",
1573
1574 NULL
1575 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576
Lee Revell2b637da2005-03-30 13:51:18 +02001577 if (emu->card_capabilities->ac97_chip) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001578 struct snd_ac97_bus *pbus;
1579 struct snd_ac97_template ac97;
1580 static struct snd_ac97_bus_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 .write = snd_emu10k1_ac97_write,
1582 .read = snd_emu10k1_ac97_read,
1583 };
1584
Takashi Iwaib1508692005-10-04 13:49:32 +02001585 if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0)
1586 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 pbus->no_vra = 1; /* we don't need VRA */
1588
1589 memset(&ac97, 0, sizeof(ac97));
1590 ac97.private_data = emu;
1591 ac97.private_free = snd_emu10k1_mixer_free_ac97;
1592 ac97.scaps = AC97_SCAP_NO_SPDIF;
Takashi Iwaib1508692005-10-04 13:49:32 +02001593 if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) {
1594 if (emu->card_capabilities->ac97_chip == 1)
1595 return err;
1596 snd_printd(KERN_INFO "emu10k1: AC97 is optional on this board\n");
1597 snd_printd(KERN_INFO" Proceeding without ac97 mixers...\n");
1598 snd_device_free(emu->card, pbus);
1599 goto no_ac97; /* FIXME: get rid of ugly gotos.. */
1600 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 if (emu->audigy) {
1602 /* set master volume to 0 dB */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001603 snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 /* set capture source to mic */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001605 snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001606 if (emu->card_capabilities->adc_1361t)
1607 c = audigy_remove_ctls_1361t_adc;
1608 else
1609 c = audigy_remove_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 } else {
1611 /*
1612 * Credits for cards based on STAC9758:
1613 * James Courtier-Dutton <James@superbug.demon.co.uk>
1614 * Voluspa <voluspa@comhem.se>
1615 */
1616 if (emu->ac97->id == AC97_ID_STAC9758) {
1617 emu->rear_ac97 = 1;
1618 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 +01001619 snd_ac97_write_cache(emu->ac97, AC97_HEADPHONE, 0x0202);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 }
1621 /* remove unused AC97 controls */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001622 snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
1623 snd_ac97_write_cache(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624 c = emu10k1_remove_ctls;
1625 }
1626 for (; *c; c++)
1627 remove_ctl(card, *c);
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001628 } else if (emu->card_capabilities->i2c_adc) {
1629 c = audigy_remove_ctls_i2c_adc;
1630 for (; *c; c++)
1631 remove_ctl(card, *c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 } else {
Takashi Iwaif12aa402005-09-30 16:56:59 +02001633 no_ac97:
Lee Revell2b637da2005-03-30 13:51:18 +02001634 if (emu->card_capabilities->ecard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 strcpy(emu->card->mixername, "EMU APS");
1636 else if (emu->audigy)
1637 strcpy(emu->card->mixername, "SB Audigy");
1638 else
1639 strcpy(emu->card->mixername, "Emu10k1");
1640 }
1641
1642 if (emu->audigy)
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001643 if (emu->card_capabilities->adc_1361t)
1644 c = audigy_rename_ctls_1361t_adc;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001645 else if (emu->card_capabilities->i2c_adc)
1646 c = audigy_rename_ctls_i2c_adc;
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001647 else
1648 c = audigy_rename_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649 else
1650 c = emu10k1_rename_ctls;
1651 for (; *c; c += 2)
1652 rename_ctl(card, c[0], c[1]);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001653
James Courtier-Duttone3b9bc02005-12-24 16:54:51 +01001654 if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */
1655 rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume");
1656 rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume");
1657 rename_ctl(card, "Aux2 Capture Volume", "Line3 Capture Volume");
1658 rename_ctl(card, "Mic Capture Volume", "Unknown1 Capture Volume");
1659 remove_ctl(card, "Headphone Playback Switch");
1660 remove_ctl(card, "Headphone Playback Volume");
1661 remove_ctl(card, "3D Control - Center");
1662 remove_ctl(card, "3D Control - Depth");
1663 remove_ctl(card, "3D Control - Switch");
1664 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL)
1666 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001667 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 if ((err = snd_ctl_add(card, kctl)))
1669 return err;
1670 if ((kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL)
1671 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001672 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 if ((err = snd_ctl_add(card, kctl)))
1674 return err;
1675 if ((kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu)) == NULL)
1676 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001677 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 if ((err = snd_ctl_add(card, kctl)))
1679 return err;
1680
1681 if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL)
1682 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001683 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 if ((err = snd_ctl_add(card, kctl)))
1685 return err;
1686
1687 if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL)
1688 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001689 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 if ((err = snd_ctl_add(card, kctl)))
1691 return err;
1692
1693 if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL)
1694 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001695 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 if ((err = snd_ctl_add(card, kctl)))
1697 return err;
1698
1699 /* initialize the routing and volume table for each pcm playback stream */
1700 for (pcm = 0; pcm < 32; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001701 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 int v;
1703
1704 mix = &emu->pcm_mixer[pcm];
1705 mix->epcm = NULL;
1706
1707 for (v = 0; v < 4; v++)
1708 mix->send_routing[0][v] =
1709 mix->send_routing[1][v] =
1710 mix->send_routing[2][v] = v;
1711
1712 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1713 mix->send_volume[0][0] = mix->send_volume[0][1] =
1714 mix->send_volume[1][0] = mix->send_volume[2][1] = 255;
1715
1716 mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
1717 }
1718
1719 /* initialize the routing and volume table for the multichannel playback stream */
1720 for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001721 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 int v;
1723
1724 mix = &emu->efx_pcm_mixer[pcm];
1725 mix->epcm = NULL;
1726
1727 mix->send_routing[0][0] = pcm;
1728 mix->send_routing[0][1] = (pcm == 0) ? 1 : 0;
1729 for (v = 0; v < 2; v++)
1730 mix->send_routing[0][2+v] = 13+v;
1731 if (emu->audigy)
1732 for (v = 0; v < 4; v++)
1733 mix->send_routing[0][4+v] = 60+v;
1734
1735 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1736 mix->send_volume[0][0] = 255;
1737
1738 mix->attn[0] = 0xffff;
1739 }
1740
Lee Revell2b637da2005-03-30 13:51:18 +02001741 if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742 /* sb live! and audigy */
1743 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
1744 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02001745 if (!emu->audigy)
1746 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747 if ((err = snd_ctl_add(card, kctl)))
1748 return err;
1749 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
1750 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02001751 if (!emu->audigy)
1752 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753 if ((err = snd_ctl_add(card, kctl)))
1754 return err;
1755 }
1756
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001757 if ( emu->card_capabilities->emu1010) {
James Courtier-Dutton19b99fb2005-12-04 18:03:03 +01001758 ; /* Disable the snd_audigy_spdif_shared_spdif */
1759 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
1761 return -ENOMEM;
1762 if ((err = snd_ctl_add(card, kctl)))
1763 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02001764#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765 if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
1766 return -ENOMEM;
1767 if ((err = snd_ctl_add(card, kctl)))
1768 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02001769#endif
Lee Revell2b637da2005-03-30 13:51:18 +02001770 } else if (! emu->card_capabilities->ecard) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771 /* sb live! */
1772 if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
1773 return -ENOMEM;
1774 if ((err = snd_ctl_add(card, kctl)))
1775 return err;
1776 }
Lee Revell2b637da2005-03-30 13:51:18 +02001777 if (emu->card_capabilities->ca0151_chip) { /* P16V */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 if ((err = snd_p16v_mixer(emu)))
1779 return err;
1780 }
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001781
1782 if ( emu->card_capabilities->emu1010) {
1783 int i;
1784
1785 for (i = 0; i < ARRAY_SIZE(snd_emu1010_output_enum_ctls); i++) {
1786 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_output_enum_ctls[i], emu));
1787 if (err < 0)
1788 return err;
1789 }
1790 for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) {
1791 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], emu));
1792 if (err < 0)
1793 return err;
1794 }
James Courtier-Dutton9148cc52006-10-09 23:08:00 +01001795 for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads); i++) {
1796 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_adc_pads[i], emu));
1797 if (err < 0)
1798 return err;
1799 }
1800 for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads); i++) {
1801 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_dac_pads[i], emu));
1802 if (err < 0)
1803 return err;
1804 }
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +01001805 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_internal_clock, emu));
1806 if (err < 0)
1807 return err;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001808 }
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001809
1810 if ( emu->card_capabilities->i2c_adc) {
1811 int i;
1812
1813 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_capture_source, emu));
1814 if (err < 0)
1815 return err;
1816
1817 for (i = 0; i < ARRAY_SIZE(snd_audigy_i2c_volume_ctls); i++) {
1818 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_volume_ctls[i], emu));
1819 if (err < 0)
1820 return err;
1821 }
1822 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823
1824 return 0;
1825}