blob: f6c3da0d377d19e5a2b0822e07a1c66cd8b7199b [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Jaroslav Kyselac1017a42007-10-15 09:50:19 +02002 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 * 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
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/time.h>
34#include <linux/init.h>
35#include <sound/core.h>
36#include <sound/emu10k1.h>
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +010037#include <linux/delay.h>
James Courtier-Dutton184c1e22006-12-06 15:58:02 +000038#include <sound/tlv.h>
39
40#include "p17v.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
42#define AC97_ID_STAC9758 0x83847658
43
Takashi Iwai0cb29ea2007-01-29 15:33:49 +010044static const DECLARE_TLV_DB_SCALE(snd_audigy_db_scale2, -10350, 50, 1); /* WM8775 gain scale */
James Courtier-Dutton184c1e22006-12-06 15:58:02 +000045
Takashi Iwaieb4698f2005-11-17 14:50:13 +010046static int snd_emu10k1_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -070047{
48 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
49 uinfo->count = 1;
50 return 0;
51}
52
Takashi Iwaieb4698f2005-11-17 14:50:13 +010053static int snd_emu10k1_spdif_get(struct snd_kcontrol *kcontrol,
54 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -070055{
Takashi Iwaieb4698f2005-11-17 14:50:13 +010056 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -070057 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
58 unsigned long flags;
59
James Courtier-Dutton74415a32007-11-12 14:55:19 +000060 /* Limit: emu->spdif_bits */
61 if (idx >= 3)
62 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 spin_lock_irqsave(&emu->reg_lock, flags);
64 ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff;
65 ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff;
66 ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff;
67 ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff;
68 spin_unlock_irqrestore(&emu->reg_lock, flags);
69 return 0;
70}
71
Takashi Iwaieb4698f2005-11-17 14:50:13 +010072static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol,
73 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -070074{
75 ucontrol->value.iec958.status[0] = 0xff;
76 ucontrol->value.iec958.status[1] = 0xff;
77 ucontrol->value.iec958.status[2] = 0xff;
78 ucontrol->value.iec958.status[3] = 0xff;
79 return 0;
80}
81
Pavel Hofman13d45702007-06-11 12:21:20 +020082/*
83 * Items labels in enum mixer controls assigning source data to
84 * each destination
85 */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +010086static char *emu1010_src_texts[] = {
87 "Silence",
88 "Dock Mic A",
89 "Dock Mic B",
90 "Dock ADC1 Left",
91 "Dock ADC1 Right",
92 "Dock ADC2 Left",
93 "Dock ADC2 Right",
94 "Dock ADC3 Left",
95 "Dock ADC3 Right",
96 "0202 ADC Left",
97 "0202 ADC Right",
98 "0202 SPDIF Left",
99 "0202 SPDIF Right",
100 "ADAT 0",
101 "ADAT 1",
102 "ADAT 2",
103 "ADAT 3",
104 "ADAT 4",
105 "ADAT 5",
106 "ADAT 6",
107 "ADAT 7",
108 "DSP 0",
109 "DSP 1",
110 "DSP 2",
111 "DSP 3",
112 "DSP 4",
113 "DSP 5",
114 "DSP 6",
115 "DSP 7",
116 "DSP 8",
117 "DSP 9",
118 "DSP 10",
119 "DSP 11",
120 "DSP 12",
121 "DSP 13",
122 "DSP 14",
123 "DSP 15",
124 "DSP 16",
125 "DSP 17",
126 "DSP 18",
127 "DSP 19",
128 "DSP 20",
129 "DSP 21",
130 "DSP 22",
131 "DSP 23",
132 "DSP 24",
133 "DSP 25",
134 "DSP 26",
135 "DSP 27",
136 "DSP 28",
137 "DSP 29",
138 "DSP 30",
139 "DSP 31",
140};
141
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100142/* 1616(m) cardbus */
143
144static char *emu1616_src_texts[] = {
145 "Silence",
146 "Dock Mic A",
147 "Dock Mic B",
148 "Dock ADC1 Left",
149 "Dock ADC1 Right",
150 "Dock ADC2 Left",
151 "Dock ADC2 Right",
152 "Dock SPDIF Left",
153 "Dock SPDIF Right",
154 "ADAT 0",
155 "ADAT 1",
156 "ADAT 2",
157 "ADAT 3",
158 "ADAT 4",
159 "ADAT 5",
160 "ADAT 6",
161 "ADAT 7",
162 "DSP 0",
163 "DSP 1",
164 "DSP 2",
165 "DSP 3",
166 "DSP 4",
167 "DSP 5",
168 "DSP 6",
169 "DSP 7",
170 "DSP 8",
171 "DSP 9",
172 "DSP 10",
173 "DSP 11",
174 "DSP 12",
175 "DSP 13",
176 "DSP 14",
177 "DSP 15",
178 "DSP 16",
179 "DSP 17",
180 "DSP 18",
181 "DSP 19",
182 "DSP 20",
183 "DSP 21",
184 "DSP 22",
185 "DSP 23",
186 "DSP 24",
187 "DSP 25",
188 "DSP 26",
189 "DSP 27",
190 "DSP 28",
191 "DSP 29",
192 "DSP 30",
193 "DSP 31",
194};
195
196
Pavel Hofman13d45702007-06-11 12:21:20 +0200197/*
198 * List of data sources available for each destination
199 */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100200static unsigned int emu1010_src_regs[] = {
201 EMU_SRC_SILENCE,/* 0 */
202 EMU_SRC_DOCK_MIC_A1, /* 1 */
203 EMU_SRC_DOCK_MIC_B1, /* 2 */
204 EMU_SRC_DOCK_ADC1_LEFT1, /* 3 */
205 EMU_SRC_DOCK_ADC1_RIGHT1, /* 4 */
206 EMU_SRC_DOCK_ADC2_LEFT1, /* 5 */
207 EMU_SRC_DOCK_ADC2_RIGHT1, /* 6 */
208 EMU_SRC_DOCK_ADC3_LEFT1, /* 7 */
209 EMU_SRC_DOCK_ADC3_RIGHT1, /* 8 */
210 EMU_SRC_HAMOA_ADC_LEFT1, /* 9 */
211 EMU_SRC_HAMOA_ADC_RIGHT1, /* 10 */
212 EMU_SRC_HANA_SPDIF_LEFT1, /* 11 */
213 EMU_SRC_HANA_SPDIF_RIGHT1, /* 12 */
214 EMU_SRC_HANA_ADAT, /* 13 */
215 EMU_SRC_HANA_ADAT+1, /* 14 */
216 EMU_SRC_HANA_ADAT+2, /* 15 */
217 EMU_SRC_HANA_ADAT+3, /* 16 */
218 EMU_SRC_HANA_ADAT+4, /* 17 */
219 EMU_SRC_HANA_ADAT+5, /* 18 */
220 EMU_SRC_HANA_ADAT+6, /* 19 */
221 EMU_SRC_HANA_ADAT+7, /* 20 */
222 EMU_SRC_ALICE_EMU32A, /* 21 */
223 EMU_SRC_ALICE_EMU32A+1, /* 22 */
224 EMU_SRC_ALICE_EMU32A+2, /* 23 */
225 EMU_SRC_ALICE_EMU32A+3, /* 24 */
226 EMU_SRC_ALICE_EMU32A+4, /* 25 */
227 EMU_SRC_ALICE_EMU32A+5, /* 26 */
228 EMU_SRC_ALICE_EMU32A+6, /* 27 */
229 EMU_SRC_ALICE_EMU32A+7, /* 28 */
230 EMU_SRC_ALICE_EMU32A+8, /* 29 */
231 EMU_SRC_ALICE_EMU32A+9, /* 30 */
232 EMU_SRC_ALICE_EMU32A+0xa, /* 31 */
233 EMU_SRC_ALICE_EMU32A+0xb, /* 32 */
234 EMU_SRC_ALICE_EMU32A+0xc, /* 33 */
235 EMU_SRC_ALICE_EMU32A+0xd, /* 34 */
236 EMU_SRC_ALICE_EMU32A+0xe, /* 35 */
237 EMU_SRC_ALICE_EMU32A+0xf, /* 36 */
238 EMU_SRC_ALICE_EMU32B, /* 37 */
239 EMU_SRC_ALICE_EMU32B+1, /* 38 */
240 EMU_SRC_ALICE_EMU32B+2, /* 39 */
241 EMU_SRC_ALICE_EMU32B+3, /* 40 */
242 EMU_SRC_ALICE_EMU32B+4, /* 41 */
243 EMU_SRC_ALICE_EMU32B+5, /* 42 */
244 EMU_SRC_ALICE_EMU32B+6, /* 43 */
245 EMU_SRC_ALICE_EMU32B+7, /* 44 */
246 EMU_SRC_ALICE_EMU32B+8, /* 45 */
247 EMU_SRC_ALICE_EMU32B+9, /* 46 */
248 EMU_SRC_ALICE_EMU32B+0xa, /* 47 */
249 EMU_SRC_ALICE_EMU32B+0xb, /* 48 */
250 EMU_SRC_ALICE_EMU32B+0xc, /* 49 */
251 EMU_SRC_ALICE_EMU32B+0xd, /* 50 */
252 EMU_SRC_ALICE_EMU32B+0xe, /* 51 */
253 EMU_SRC_ALICE_EMU32B+0xf, /* 52 */
254};
255
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100256/* 1616(m) cardbus */
257static unsigned int emu1616_src_regs[] = {
258 EMU_SRC_SILENCE,
259 EMU_SRC_DOCK_MIC_A1,
260 EMU_SRC_DOCK_MIC_B1,
261 EMU_SRC_DOCK_ADC1_LEFT1,
262 EMU_SRC_DOCK_ADC1_RIGHT1,
263 EMU_SRC_DOCK_ADC2_LEFT1,
264 EMU_SRC_DOCK_ADC2_RIGHT1,
265 EMU_SRC_MDOCK_SPDIF_LEFT1,
266 EMU_SRC_MDOCK_SPDIF_RIGHT1,
267 EMU_SRC_MDOCK_ADAT,
268 EMU_SRC_MDOCK_ADAT+1,
269 EMU_SRC_MDOCK_ADAT+2,
270 EMU_SRC_MDOCK_ADAT+3,
271 EMU_SRC_MDOCK_ADAT+4,
272 EMU_SRC_MDOCK_ADAT+5,
273 EMU_SRC_MDOCK_ADAT+6,
274 EMU_SRC_MDOCK_ADAT+7,
275 EMU_SRC_ALICE_EMU32A,
276 EMU_SRC_ALICE_EMU32A+1,
277 EMU_SRC_ALICE_EMU32A+2,
278 EMU_SRC_ALICE_EMU32A+3,
279 EMU_SRC_ALICE_EMU32A+4,
280 EMU_SRC_ALICE_EMU32A+5,
281 EMU_SRC_ALICE_EMU32A+6,
282 EMU_SRC_ALICE_EMU32A+7,
283 EMU_SRC_ALICE_EMU32A+8,
284 EMU_SRC_ALICE_EMU32A+9,
285 EMU_SRC_ALICE_EMU32A+0xa,
286 EMU_SRC_ALICE_EMU32A+0xb,
287 EMU_SRC_ALICE_EMU32A+0xc,
288 EMU_SRC_ALICE_EMU32A+0xd,
289 EMU_SRC_ALICE_EMU32A+0xe,
290 EMU_SRC_ALICE_EMU32A+0xf,
291 EMU_SRC_ALICE_EMU32B,
292 EMU_SRC_ALICE_EMU32B+1,
293 EMU_SRC_ALICE_EMU32B+2,
294 EMU_SRC_ALICE_EMU32B+3,
295 EMU_SRC_ALICE_EMU32B+4,
296 EMU_SRC_ALICE_EMU32B+5,
297 EMU_SRC_ALICE_EMU32B+6,
298 EMU_SRC_ALICE_EMU32B+7,
299 EMU_SRC_ALICE_EMU32B+8,
300 EMU_SRC_ALICE_EMU32B+9,
301 EMU_SRC_ALICE_EMU32B+0xa,
302 EMU_SRC_ALICE_EMU32B+0xb,
303 EMU_SRC_ALICE_EMU32B+0xc,
304 EMU_SRC_ALICE_EMU32B+0xd,
305 EMU_SRC_ALICE_EMU32B+0xe,
306 EMU_SRC_ALICE_EMU32B+0xf,
307};
308
Pavel Hofman13d45702007-06-11 12:21:20 +0200309/*
310 * Data destinations - physical EMU outputs.
311 * Each destination has an enum mixer control to choose a data source
312 */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100313static unsigned int emu1010_output_dst[] = {
314 EMU_DST_DOCK_DAC1_LEFT1, /* 0 */
315 EMU_DST_DOCK_DAC1_RIGHT1, /* 1 */
316 EMU_DST_DOCK_DAC2_LEFT1, /* 2 */
317 EMU_DST_DOCK_DAC2_RIGHT1, /* 3 */
318 EMU_DST_DOCK_DAC3_LEFT1, /* 4 */
319 EMU_DST_DOCK_DAC3_RIGHT1, /* 5 */
320 EMU_DST_DOCK_DAC4_LEFT1, /* 6 */
321 EMU_DST_DOCK_DAC4_RIGHT1, /* 7 */
322 EMU_DST_DOCK_PHONES_LEFT1, /* 8 */
323 EMU_DST_DOCK_PHONES_RIGHT1, /* 9 */
324 EMU_DST_DOCK_SPDIF_LEFT1, /* 10 */
325 EMU_DST_DOCK_SPDIF_RIGHT1, /* 11 */
326 EMU_DST_HANA_SPDIF_LEFT1, /* 12 */
327 EMU_DST_HANA_SPDIF_RIGHT1, /* 13 */
328 EMU_DST_HAMOA_DAC_LEFT1, /* 14 */
329 EMU_DST_HAMOA_DAC_RIGHT1, /* 15 */
330 EMU_DST_HANA_ADAT, /* 16 */
331 EMU_DST_HANA_ADAT+1, /* 17 */
332 EMU_DST_HANA_ADAT+2, /* 18 */
333 EMU_DST_HANA_ADAT+3, /* 19 */
334 EMU_DST_HANA_ADAT+4, /* 20 */
335 EMU_DST_HANA_ADAT+5, /* 21 */
336 EMU_DST_HANA_ADAT+6, /* 22 */
337 EMU_DST_HANA_ADAT+7, /* 23 */
338};
339
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100340/* 1616(m) cardbus */
341static unsigned int emu1616_output_dst[] = {
342 EMU_DST_DOCK_DAC1_LEFT1,
343 EMU_DST_DOCK_DAC1_RIGHT1,
344 EMU_DST_DOCK_DAC2_LEFT1,
345 EMU_DST_DOCK_DAC2_RIGHT1,
346 EMU_DST_DOCK_DAC3_LEFT1,
347 EMU_DST_DOCK_DAC3_RIGHT1,
348 EMU_DST_MDOCK_SPDIF_LEFT1,
349 EMU_DST_MDOCK_SPDIF_RIGHT1,
350 EMU_DST_MDOCK_ADAT,
351 EMU_DST_MDOCK_ADAT+1,
352 EMU_DST_MDOCK_ADAT+2,
353 EMU_DST_MDOCK_ADAT+3,
354 EMU_DST_MDOCK_ADAT+4,
355 EMU_DST_MDOCK_ADAT+5,
356 EMU_DST_MDOCK_ADAT+6,
357 EMU_DST_MDOCK_ADAT+7,
358 EMU_DST_MANA_DAC_LEFT,
359 EMU_DST_MANA_DAC_RIGHT,
360};
361
Pavel Hofman13d45702007-06-11 12:21:20 +0200362/*
363 * Data destinations - HANA outputs going to Alice2 (audigy) for
364 * capture (EMU32 + I2S links)
365 * Each destination has an enum mixer control to choose a data source
366 */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100367static unsigned int emu1010_input_dst[] = {
368 EMU_DST_ALICE2_EMU32_0,
369 EMU_DST_ALICE2_EMU32_1,
370 EMU_DST_ALICE2_EMU32_2,
371 EMU_DST_ALICE2_EMU32_3,
372 EMU_DST_ALICE2_EMU32_4,
373 EMU_DST_ALICE2_EMU32_5,
374 EMU_DST_ALICE2_EMU32_6,
375 EMU_DST_ALICE2_EMU32_7,
376 EMU_DST_ALICE2_EMU32_8,
377 EMU_DST_ALICE2_EMU32_9,
378 EMU_DST_ALICE2_EMU32_A,
379 EMU_DST_ALICE2_EMU32_B,
380 EMU_DST_ALICE2_EMU32_C,
381 EMU_DST_ALICE2_EMU32_D,
382 EMU_DST_ALICE2_EMU32_E,
383 EMU_DST_ALICE2_EMU32_F,
384 EMU_DST_ALICE_I2S0_LEFT,
385 EMU_DST_ALICE_I2S0_RIGHT,
386 EMU_DST_ALICE_I2S1_LEFT,
387 EMU_DST_ALICE_I2S1_RIGHT,
388 EMU_DST_ALICE_I2S2_LEFT,
389 EMU_DST_ALICE_I2S2_RIGHT,
390};
391
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100392static int snd_emu1010_input_output_source_info(struct snd_kcontrol *kcontrol,
393 struct snd_ctl_elem_info *uinfo)
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100394{
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100395 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
396 char **items;
397
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100398 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
399 uinfo->count = 1;
Takashi Iwai3839e4f2007-12-21 16:33:32 +0100400 if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) {
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100401 uinfo->value.enumerated.items = 49;
402 items = emu1616_src_texts;
403 } else {
404 uinfo->value.enumerated.items = 53;
405 items = emu1010_src_texts;
406 }
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100407 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100408 uinfo->value.enumerated.item =
409 uinfo->value.enumerated.items - 1;
410 strcpy(uinfo->value.enumerated.name,
411 items[uinfo->value.enumerated.item]);
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100412 return 0;
413}
414
415static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol,
416 struct snd_ctl_elem_value *ucontrol)
417{
418 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000419 unsigned int channel;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100420
421 channel = (kcontrol->private_value) & 0xff;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000422 /* Limit: emu1010_output_dst, emu->emu1010.output_source */
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100423 if (channel >= 24 ||
Takashi Iwai3839e4f2007-12-21 16:33:32 +0100424 (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616 &&
425 channel >= 18))
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000426 return -EINVAL;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100427 ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel];
428 return 0;
429}
430
431static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol,
432 struct snd_ctl_elem_value *ucontrol)
433{
434 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100435 unsigned int val;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000436 unsigned int channel;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100437
Takashi Iwaiaa299d02007-11-15 13:16:02 +0100438 val = ucontrol->value.enumerated.item[0];
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100439 if (val >= 53 ||
Takashi Iwai3839e4f2007-12-21 16:33:32 +0100440 (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616 &&
441 val >= 49))
Takashi Iwaiaa299d02007-11-15 13:16:02 +0100442 return -EINVAL;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100443 channel = (kcontrol->private_value) & 0xff;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000444 /* Limit: emu1010_output_dst, emu->emu1010.output_source */
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100445 if (channel >= 24 ||
Takashi Iwai3839e4f2007-12-21 16:33:32 +0100446 (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616 &&
447 channel >= 18))
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000448 return -EINVAL;
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100449 if (emu->emu1010.output_source[channel] == val)
450 return 0;
451 emu->emu1010.output_source[channel] = val;
Takashi Iwai3839e4f2007-12-21 16:33:32 +0100452 if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616)
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100453 snd_emu1010_fpga_link_dst_src_write(emu,
454 emu1616_output_dst[channel], emu1616_src_regs[val]);
455 else
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100456 snd_emu1010_fpga_link_dst_src_write(emu,
457 emu1010_output_dst[channel], emu1010_src_regs[val]);
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100458 return 1;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100459}
460
461static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol,
462 struct snd_ctl_elem_value *ucontrol)
463{
464 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000465 unsigned int channel;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100466
467 channel = (kcontrol->private_value) & 0xff;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000468 /* Limit: emu1010_input_dst, emu->emu1010.input_source */
469 if (channel >= 22)
470 return -EINVAL;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100471 ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel];
472 return 0;
473}
474
475static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
476 struct snd_ctl_elem_value *ucontrol)
477{
478 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100479 unsigned int val;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000480 unsigned int channel;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100481
Takashi Iwaiaa299d02007-11-15 13:16:02 +0100482 val = ucontrol->value.enumerated.item[0];
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100483 if (val >= 53 ||
Takashi Iwai3839e4f2007-12-21 16:33:32 +0100484 (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616 &&
485 val >= 49))
Takashi Iwaiaa299d02007-11-15 13:16:02 +0100486 return -EINVAL;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100487 channel = (kcontrol->private_value) & 0xff;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000488 /* Limit: emu1010_input_dst, emu->emu1010.input_source */
489 if (channel >= 22)
490 return -EINVAL;
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100491 if (emu->emu1010.input_source[channel] == val)
492 return 0;
493 emu->emu1010.input_source[channel] = val;
Takashi Iwai3839e4f2007-12-21 16:33:32 +0100494 if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616)
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100495 snd_emu1010_fpga_link_dst_src_write(emu,
496 emu1010_input_dst[channel], emu1616_src_regs[val]);
497 else
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100498 snd_emu1010_fpga_link_dst_src_write(emu,
499 emu1010_input_dst[channel], emu1010_src_regs[val]);
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100500 return 1;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100501}
502
503#define EMU1010_SOURCE_OUTPUT(xname,chid) \
504{ \
505 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
506 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
507 .info = snd_emu1010_input_output_source_info, \
508 .get = snd_emu1010_output_source_get, \
509 .put = snd_emu1010_output_source_put, \
510 .private_value = chid \
511}
512
Bill Pembertone23e7a12012-12-06 12:35:10 -0500513static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] = {
James Courtier-Dutton4c07c812006-11-11 10:48:58 +0000514 EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0),
515 EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1),
516 EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2),
517 EMU1010_SOURCE_OUTPUT("Dock DAC2 Right Playback Enum", 3),
518 EMU1010_SOURCE_OUTPUT("Dock DAC3 Left Playback Enum", 4),
519 EMU1010_SOURCE_OUTPUT("Dock DAC3 Right Playback Enum", 5),
520 EMU1010_SOURCE_OUTPUT("Dock DAC4 Left Playback Enum", 6),
521 EMU1010_SOURCE_OUTPUT("Dock DAC4 Right Playback Enum", 7),
522 EMU1010_SOURCE_OUTPUT("Dock Phones Left Playback Enum", 8),
523 EMU1010_SOURCE_OUTPUT("Dock Phones Right Playback Enum", 9),
524 EMU1010_SOURCE_OUTPUT("Dock SPDIF Left Playback Enum", 0xa),
525 EMU1010_SOURCE_OUTPUT("Dock SPDIF Right Playback Enum", 0xb),
526 EMU1010_SOURCE_OUTPUT("1010 SPDIF Left Playback Enum", 0xc),
527 EMU1010_SOURCE_OUTPUT("1010 SPDIF Right Playback Enum", 0xd),
528 EMU1010_SOURCE_OUTPUT("0202 DAC Left Playback Enum", 0xe),
529 EMU1010_SOURCE_OUTPUT("0202 DAC Right Playback Enum", 0xf),
530 EMU1010_SOURCE_OUTPUT("1010 ADAT 0 Playback Enum", 0x10),
531 EMU1010_SOURCE_OUTPUT("1010 ADAT 1 Playback Enum", 0x11),
532 EMU1010_SOURCE_OUTPUT("1010 ADAT 2 Playback Enum", 0x12),
533 EMU1010_SOURCE_OUTPUT("1010 ADAT 3 Playback Enum", 0x13),
534 EMU1010_SOURCE_OUTPUT("1010 ADAT 4 Playback Enum", 0x14),
535 EMU1010_SOURCE_OUTPUT("1010 ADAT 5 Playback Enum", 0x15),
536 EMU1010_SOURCE_OUTPUT("1010 ADAT 6 Playback Enum", 0x16),
537 EMU1010_SOURCE_OUTPUT("1010 ADAT 7 Playback Enum", 0x17),
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100538};
539
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100540
541/* 1616(m) cardbus */
Bill Pembertone23e7a12012-12-06 12:35:10 -0500542static struct snd_kcontrol_new snd_emu1616_output_enum_ctls[] = {
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100543 EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0),
544 EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1),
545 EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2),
546 EMU1010_SOURCE_OUTPUT("Dock DAC2 Right Playback Enum", 3),
547 EMU1010_SOURCE_OUTPUT("Dock DAC3 Left Playback Enum", 4),
548 EMU1010_SOURCE_OUTPUT("Dock DAC3 Right Playback Enum", 5),
549 EMU1010_SOURCE_OUTPUT("Dock SPDIF Left Playback Enum", 6),
550 EMU1010_SOURCE_OUTPUT("Dock SPDIF Right Playback Enum", 7),
551 EMU1010_SOURCE_OUTPUT("Dock ADAT 0 Playback Enum", 8),
552 EMU1010_SOURCE_OUTPUT("Dock ADAT 1 Playback Enum", 9),
553 EMU1010_SOURCE_OUTPUT("Dock ADAT 2 Playback Enum", 0xa),
554 EMU1010_SOURCE_OUTPUT("Dock ADAT 3 Playback Enum", 0xb),
555 EMU1010_SOURCE_OUTPUT("Dock ADAT 4 Playback Enum", 0xc),
556 EMU1010_SOURCE_OUTPUT("Dock ADAT 5 Playback Enum", 0xd),
557 EMU1010_SOURCE_OUTPUT("Dock ADAT 6 Playback Enum", 0xe),
558 EMU1010_SOURCE_OUTPUT("Dock ADAT 7 Playback Enum", 0xf),
559 EMU1010_SOURCE_OUTPUT("Mana DAC Left Playback Enum", 0x10),
560 EMU1010_SOURCE_OUTPUT("Mana DAC Right Playback Enum", 0x11),
561};
562
563
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100564#define EMU1010_SOURCE_INPUT(xname,chid) \
565{ \
566 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
567 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
568 .info = snd_emu1010_input_output_source_info, \
569 .get = snd_emu1010_input_source_get, \
570 .put = snd_emu1010_input_source_put, \
571 .private_value = chid \
572}
573
Bill Pembertone23e7a12012-12-06 12:35:10 -0500574static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] = {
James Courtier-Dutton4c07c812006-11-11 10:48:58 +0000575 EMU1010_SOURCE_INPUT("DSP 0 Capture Enum", 0),
576 EMU1010_SOURCE_INPUT("DSP 1 Capture Enum", 1),
577 EMU1010_SOURCE_INPUT("DSP 2 Capture Enum", 2),
578 EMU1010_SOURCE_INPUT("DSP 3 Capture Enum", 3),
579 EMU1010_SOURCE_INPUT("DSP 4 Capture Enum", 4),
580 EMU1010_SOURCE_INPUT("DSP 5 Capture Enum", 5),
581 EMU1010_SOURCE_INPUT("DSP 6 Capture Enum", 6),
582 EMU1010_SOURCE_INPUT("DSP 7 Capture Enum", 7),
583 EMU1010_SOURCE_INPUT("DSP 8 Capture Enum", 8),
584 EMU1010_SOURCE_INPUT("DSP 9 Capture Enum", 9),
585 EMU1010_SOURCE_INPUT("DSP A Capture Enum", 0xa),
586 EMU1010_SOURCE_INPUT("DSP B Capture Enum", 0xb),
587 EMU1010_SOURCE_INPUT("DSP C Capture Enum", 0xc),
588 EMU1010_SOURCE_INPUT("DSP D Capture Enum", 0xd),
589 EMU1010_SOURCE_INPUT("DSP E Capture Enum", 0xe),
590 EMU1010_SOURCE_INPUT("DSP F Capture Enum", 0xf),
591 EMU1010_SOURCE_INPUT("DSP 10 Capture Enum", 0x10),
592 EMU1010_SOURCE_INPUT("DSP 11 Capture Enum", 0x11),
593 EMU1010_SOURCE_INPUT("DSP 12 Capture Enum", 0x12),
594 EMU1010_SOURCE_INPUT("DSP 13 Capture Enum", 0x13),
595 EMU1010_SOURCE_INPUT("DSP 14 Capture Enum", 0x14),
596 EMU1010_SOURCE_INPUT("DSP 15 Capture Enum", 0x15),
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100597};
598
599
600
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200601#define snd_emu1010_adc_pads_info snd_ctl_boolean_mono_info
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100602
603static int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
604{
605 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
606 unsigned int mask = kcontrol->private_value & 0xff;
607 ucontrol->value.integer.value[0] = (emu->emu1010.adc_pads & mask) ? 1 : 0;
608 return 0;
609}
610
611static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
612{
613 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
614 unsigned int mask = kcontrol->private_value & 0xff;
615 unsigned int val, cache;
616 val = ucontrol->value.integer.value[0];
617 cache = emu->emu1010.adc_pads;
618 if (val == 1)
619 cache = cache | mask;
620 else
621 cache = cache & ~mask;
622 if (cache != emu->emu1010.adc_pads) {
623 snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache );
624 emu->emu1010.adc_pads = cache;
625 }
626
627 return 0;
628}
629
630
631
632#define EMU1010_ADC_PADS(xname,chid) \
633{ \
634 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
635 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
636 .info = snd_emu1010_adc_pads_info, \
637 .get = snd_emu1010_adc_pads_get, \
638 .put = snd_emu1010_adc_pads_put, \
639 .private_value = chid \
640}
641
Bill Pembertone23e7a12012-12-06 12:35:10 -0500642static struct snd_kcontrol_new snd_emu1010_adc_pads[] = {
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100643 EMU1010_ADC_PADS("ADC1 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD1),
644 EMU1010_ADC_PADS("ADC2 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD2),
645 EMU1010_ADC_PADS("ADC3 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD3),
646 EMU1010_ADC_PADS("ADC1 14dB PAD 0202 Capture Switch", EMU_HANA_0202_ADC_PAD1),
647};
648
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200649#define snd_emu1010_dac_pads_info snd_ctl_boolean_mono_info
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100650
651static int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
652{
653 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
654 unsigned int mask = kcontrol->private_value & 0xff;
655 ucontrol->value.integer.value[0] = (emu->emu1010.dac_pads & mask) ? 1 : 0;
656 return 0;
657}
658
659static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
660{
661 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
662 unsigned int mask = kcontrol->private_value & 0xff;
663 unsigned int val, cache;
664 val = ucontrol->value.integer.value[0];
665 cache = emu->emu1010.dac_pads;
666 if (val == 1)
667 cache = cache | mask;
668 else
669 cache = cache & ~mask;
670 if (cache != emu->emu1010.dac_pads) {
671 snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache );
672 emu->emu1010.dac_pads = cache;
673 }
674
675 return 0;
676}
677
678
679
680#define EMU1010_DAC_PADS(xname,chid) \
681{ \
682 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
683 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
684 .info = snd_emu1010_dac_pads_info, \
685 .get = snd_emu1010_dac_pads_get, \
686 .put = snd_emu1010_dac_pads_put, \
687 .private_value = chid \
688}
689
Bill Pembertone23e7a12012-12-06 12:35:10 -0500690static struct snd_kcontrol_new snd_emu1010_dac_pads[] = {
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100691 EMU1010_DAC_PADS("DAC1 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD1),
692 EMU1010_DAC_PADS("DAC2 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD2),
693 EMU1010_DAC_PADS("DAC3 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD3),
694 EMU1010_DAC_PADS("DAC4 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD4),
695 EMU1010_DAC_PADS("DAC1 0202 14dB PAD Playback Switch", EMU_HANA_0202_DAC_PAD1),
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100696};
697
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100698
699static int snd_emu1010_internal_clock_info(struct snd_kcontrol *kcontrol,
700 struct snd_ctl_elem_info *uinfo)
701{
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100702 static char *texts[4] = {
703 "44100", "48000", "SPDIF", "ADAT"
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100704 };
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100705
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100706 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
707 uinfo->count = 1;
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100708 uinfo->value.enumerated.items = 4;
709 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
710 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100711 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
712 return 0;
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100713
714
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100715}
716
717static int snd_emu1010_internal_clock_get(struct snd_kcontrol *kcontrol,
718 struct snd_ctl_elem_value *ucontrol)
719{
720 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
721
722 ucontrol->value.enumerated.item[0] = emu->emu1010.internal_clock;
723 return 0;
724}
725
726static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol,
727 struct snd_ctl_elem_value *ucontrol)
728{
729 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
730 unsigned int val;
731 int change = 0;
732
733 val = ucontrol->value.enumerated.item[0] ;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000734 /* Limit: uinfo->value.enumerated.items = 4; */
735 if (val >= 4)
736 return -EINVAL;
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100737 change = (emu->emu1010.internal_clock != val);
738 if (change) {
739 emu->emu1010.internal_clock = val;
740 switch (val) {
741 case 0:
742 /* 44100 */
743 /* Mute all */
744 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
745 /* Default fallback clock 48kHz */
746 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_44_1K );
747 /* Word Clock source, Internal 44.1kHz x1 */
748 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
749 EMU_HANA_WCLOCK_INT_44_1K | EMU_HANA_WCLOCK_1X );
750 /* Set LEDs on Audio Dock */
751 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
752 EMU_HANA_DOCK_LEDS_2_44K | EMU_HANA_DOCK_LEDS_2_LOCK );
753 /* Allow DLL to settle */
James Courtier-Duttone40a0b22006-10-10 18:44:29 +0100754 msleep(10);
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100755 /* Unmute all */
756 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
757 break;
758 case 1:
759 /* 48000 */
760 /* Mute all */
761 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
762 /* Default fallback clock 48kHz */
763 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
764 /* Word Clock source, Internal 48kHz x1 */
765 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
766 EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_1X );
767 /* Set LEDs on Audio Dock */
768 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
769 EMU_HANA_DOCK_LEDS_2_48K | EMU_HANA_DOCK_LEDS_2_LOCK );
770 /* Allow DLL to settle */
James Courtier-Duttone40a0b22006-10-10 18:44:29 +0100771 msleep(10);
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100772 /* Unmute all */
773 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
774 break;
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100775
776 case 2: /* Take clock from S/PDIF IN */
777 /* Mute all */
778 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
779 /* Default fallback clock 48kHz */
780 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
781 /* Word Clock source, sync to S/PDIF input */
782 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
783 EMU_HANA_WCLOCK_HANA_SPDIF_IN | EMU_HANA_WCLOCK_1X );
784 /* Set LEDs on Audio Dock */
785 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
786 EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK );
787 /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */
788 /* Allow DLL to settle */
789 msleep(10);
790 /* Unmute all */
791 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
792 break;
793
794 case 3:
795 /* Take clock from ADAT IN */
796 /* Mute all */
797 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
798 /* Default fallback clock 48kHz */
799 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
800 /* Word Clock source, sync to ADAT input */
801 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
802 EMU_HANA_WCLOCK_HANA_ADAT_IN | EMU_HANA_WCLOCK_1X );
803 /* Set LEDs on Audio Dock */
804 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK );
805 /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */
806 /* Allow DLL to settle */
807 msleep(10);
808 /* Unmute all */
809 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
810
811
812 break;
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100813 }
814 }
815 return change;
816}
817
818static struct snd_kcontrol_new snd_emu1010_internal_clock =
819{
820 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
821 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
822 .name = "Clock Internal Rate",
823 .count = 1,
824 .info = snd_emu1010_internal_clock_info,
825 .get = snd_emu1010_internal_clock_get,
826 .put = snd_emu1010_internal_clock_put
827};
828
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000829static int snd_audigy_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
830 struct snd_ctl_elem_info *uinfo)
831{
832#if 0
833 static char *texts[4] = {
834 "Unknown1", "Unknown2", "Mic", "Line"
835 };
836#endif
837 static char *texts[2] = {
838 "Mic", "Line"
839 };
840
841 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
842 uinfo->count = 1;
843 uinfo->value.enumerated.items = 2;
844 if (uinfo->value.enumerated.item > 1)
845 uinfo->value.enumerated.item = 1;
846 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
847 return 0;
848}
849
850static int snd_audigy_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
851 struct snd_ctl_elem_value *ucontrol)
852{
853 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
854
855 ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
856 return 0;
857}
858
859static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
860 struct snd_ctl_elem_value *ucontrol)
861{
862 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
863 unsigned int source_id;
864 unsigned int ngain, ogain;
865 u32 gpio;
866 int change = 0;
867 unsigned long flags;
868 u32 source;
869 /* If the capture source has changed,
870 * update the capture volume from the cached value
871 * for the particular source.
872 */
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000873 source_id = ucontrol->value.enumerated.item[0];
874 /* Limit: uinfo->value.enumerated.items = 2; */
875 /* emu->i2c_capture_volume */
876 if (source_id >= 2)
877 return -EINVAL;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000878 change = (emu->i2c_capture_source != source_id);
879 if (change) {
880 snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */
881 spin_lock_irqsave(&emu->emu_lock, flags);
882 gpio = inl(emu->port + A_IOCFG);
883 if (source_id==0)
884 outl(gpio | 0x4, emu->port + A_IOCFG);
885 else
886 outl(gpio & ~0x4, emu->port + A_IOCFG);
887 spin_unlock_irqrestore(&emu->emu_lock, flags);
888
889 ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
890 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
891 if (ngain != ogain)
892 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
893 ngain = emu->i2c_capture_volume[source_id][1]; /* Right */
894 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
895 if (ngain != ogain)
896 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
897
898 source = 1 << (source_id + 2);
899 snd_emu10k1_i2c_write(emu, ADC_MUX, source); /* Set source */
900 emu->i2c_capture_source = source_id;
901 }
902 return change;
903}
904
905static struct snd_kcontrol_new snd_audigy_i2c_capture_source =
906{
907 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
908 .name = "Capture Source",
909 .info = snd_audigy_i2c_capture_source_info,
910 .get = snd_audigy_i2c_capture_source_get,
911 .put = snd_audigy_i2c_capture_source_put
912};
913
914static int snd_audigy_i2c_volume_info(struct snd_kcontrol *kcontrol,
915 struct snd_ctl_elem_info *uinfo)
916{
917 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
918 uinfo->count = 2;
919 uinfo->value.integer.min = 0;
920 uinfo->value.integer.max = 255;
921 return 0;
922}
923
924static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol,
925 struct snd_ctl_elem_value *ucontrol)
926{
927 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000928 unsigned int source_id;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000929
930 source_id = kcontrol->private_value;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000931 /* Limit: emu->i2c_capture_volume */
932 /* capture_source: uinfo->value.enumerated.items = 2 */
933 if (source_id >= 2)
934 return -EINVAL;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000935
936 ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
937 ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
938 return 0;
939}
940
941static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
942 struct snd_ctl_elem_value *ucontrol)
943{
944 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
945 unsigned int ogain;
946 unsigned int ngain;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000947 unsigned int source_id;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000948 int change = 0;
949
950 source_id = kcontrol->private_value;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000951 /* Limit: emu->i2c_capture_volume */
952 /* capture_source: uinfo->value.enumerated.items = 2 */
953 if (source_id >= 2)
954 return -EINVAL;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000955 ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
956 ngain = ucontrol->value.integer.value[0];
957 if (ngain > 0xff)
958 return 0;
959 if (ogain != ngain) {
960 if (emu->i2c_capture_source == source_id)
961 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000962 emu->i2c_capture_volume[source_id][0] = ngain;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000963 change = 1;
964 }
965 ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
966 ngain = ucontrol->value.integer.value[1];
967 if (ngain > 0xff)
968 return 0;
969 if (ogain != ngain) {
970 if (emu->i2c_capture_source == source_id)
971 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000972 emu->i2c_capture_volume[source_id][1] = ngain;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000973 change = 1;
974 }
975
976 return change;
977}
978
979#define I2C_VOLUME(xname,chid) \
980{ \
981 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
982 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
983 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
984 .info = snd_audigy_i2c_volume_info, \
985 .get = snd_audigy_i2c_volume_get, \
986 .put = snd_audigy_i2c_volume_put, \
987 .tlv = { .p = snd_audigy_db_scale2 }, \
988 .private_value = chid \
989}
990
991
Bill Pembertone23e7a12012-12-06 12:35:10 -0500992static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] = {
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000993 I2C_VOLUME("Mic Capture Volume", 0),
994 I2C_VOLUME("Line Capture Volume", 0)
995};
996
Takashi Iwai0af68e52005-04-11 17:03:03 +0200997#if 0
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100998static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999{
1000 static char *texts[] = {"44100", "48000", "96000"};
1001
1002 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1003 uinfo->count = 1;
1004 uinfo->value.enumerated.items = 3;
1005 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1006 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1007 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1008 return 0;
1009}
1010
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001011static int snd_audigy_spdif_output_rate_get(struct snd_kcontrol *kcontrol,
1012 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001014 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 unsigned int tmp;
1016 unsigned long flags;
1017
1018
1019 spin_lock_irqsave(&emu->reg_lock, flags);
1020 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
1021 switch (tmp & A_SPDIF_RATE_MASK) {
1022 case A_SPDIF_44100:
1023 ucontrol->value.enumerated.item[0] = 0;
1024 break;
1025 case A_SPDIF_48000:
1026 ucontrol->value.enumerated.item[0] = 1;
1027 break;
1028 case A_SPDIF_96000:
1029 ucontrol->value.enumerated.item[0] = 2;
1030 break;
1031 default:
1032 ucontrol->value.enumerated.item[0] = 1;
1033 }
1034 spin_unlock_irqrestore(&emu->reg_lock, flags);
1035 return 0;
1036}
1037
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001038static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol,
1039 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001041 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 int change;
1043 unsigned int reg, val, tmp;
1044 unsigned long flags;
1045
1046 switch(ucontrol->value.enumerated.item[0]) {
1047 case 0:
1048 val = A_SPDIF_44100;
1049 break;
1050 case 1:
1051 val = A_SPDIF_48000;
1052 break;
1053 case 2:
1054 val = A_SPDIF_96000;
1055 break;
1056 default:
1057 val = A_SPDIF_48000;
1058 break;
1059 }
1060
1061
1062 spin_lock_irqsave(&emu->reg_lock, flags);
1063 reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
1064 tmp = reg & ~A_SPDIF_RATE_MASK;
1065 tmp |= val;
1066 if ((change = (tmp != reg)))
1067 snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
1068 spin_unlock_irqrestore(&emu->reg_lock, flags);
1069 return change;
1070}
1071
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001072static struct snd_kcontrol_new snd_audigy_spdif_output_rate =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073{
1074 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1075 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1076 .name = "Audigy SPDIF Output Sample Rate",
1077 .count = 1,
1078 .info = snd_audigy_spdif_output_rate_info,
1079 .get = snd_audigy_spdif_output_rate_get,
1080 .put = snd_audigy_spdif_output_rate_put
1081};
Takashi Iwai0af68e52005-04-11 17:03:03 +02001082#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001084static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol,
1085 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001087 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1089 int change;
1090 unsigned int val;
1091 unsigned long flags;
1092
James Courtier-Dutton74415a32007-11-12 14:55:19 +00001093 /* Limit: emu->spdif_bits */
1094 if (idx >= 3)
1095 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 val = (ucontrol->value.iec958.status[0] << 0) |
1097 (ucontrol->value.iec958.status[1] << 8) |
1098 (ucontrol->value.iec958.status[2] << 16) |
1099 (ucontrol->value.iec958.status[3] << 24);
1100 spin_lock_irqsave(&emu->reg_lock, flags);
1101 change = val != emu->spdif_bits[idx];
1102 if (change) {
1103 snd_emu10k1_ptr_write(emu, SPCS0 + idx, 0, val);
1104 emu->spdif_bits[idx] = val;
1105 }
1106 spin_unlock_irqrestore(&emu->reg_lock, flags);
1107 return change;
1108}
1109
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001110static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111{
1112 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +02001113 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
Takashi Iwai7583cb52007-08-16 19:32:16 +02001115 .count = 3,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 .info = snd_emu10k1_spdif_info,
1117 .get = snd_emu10k1_spdif_get_mask
1118};
1119
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001120static struct snd_kcontrol_new snd_emu10k1_spdif_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121{
Clemens Ladisch5549d542005-08-03 13:50:30 +02001122 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
Takashi Iwai7583cb52007-08-16 19:32:16 +02001124 .count = 3,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 .info = snd_emu10k1_spdif_info,
1126 .get = snd_emu10k1_spdif_get,
1127 .put = snd_emu10k1_spdif_put
1128};
1129
1130
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001131static void update_emu10k1_fxrt(struct snd_emu10k1 *emu, int voice, unsigned char *route)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132{
1133 if (emu->audigy) {
1134 snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
1135 snd_emu10k1_compose_audigy_fxrt1(route));
1136 snd_emu10k1_ptr_write(emu, A_FXRT2, voice,
1137 snd_emu10k1_compose_audigy_fxrt2(route));
1138 } else {
1139 snd_emu10k1_ptr_write(emu, FXRT, voice,
1140 snd_emu10k1_compose_send_routing(route));
1141 }
1142}
1143
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001144static void update_emu10k1_send_volume(struct snd_emu10k1 *emu, int voice, unsigned char *volume)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145{
1146 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]);
1147 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]);
1148 snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, volume[2]);
1149 snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, volume[3]);
1150 if (emu->audigy) {
1151 unsigned int val = ((unsigned int)volume[4] << 24) |
1152 ((unsigned int)volume[5] << 16) |
1153 ((unsigned int)volume[6] << 8) |
1154 (unsigned int)volume[7];
1155 snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, val);
1156 }
1157}
1158
1159/* PCM stream controls */
1160
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001161static int snd_emu10k1_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001163 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1165 uinfo->count = emu->audigy ? 3*8 : 3*4;
1166 uinfo->value.integer.min = 0;
1167 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
1168 return 0;
1169}
1170
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001171static int snd_emu10k1_send_routing_get(struct snd_kcontrol *kcontrol,
1172 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173{
1174 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001175 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1176 struct snd_emu10k1_pcm_mixer *mix =
1177 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 int voice, idx;
1179 int num_efx = emu->audigy ? 8 : 4;
1180 int mask = emu->audigy ? 0x3f : 0x0f;
1181
1182 spin_lock_irqsave(&emu->reg_lock, flags);
1183 for (voice = 0; voice < 3; voice++)
1184 for (idx = 0; idx < num_efx; idx++)
1185 ucontrol->value.integer.value[(voice * num_efx) + idx] =
1186 mix->send_routing[voice][idx] & mask;
1187 spin_unlock_irqrestore(&emu->reg_lock, flags);
1188 return 0;
1189}
1190
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001191static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol,
1192 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193{
1194 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001195 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1196 struct snd_emu10k1_pcm_mixer *mix =
1197 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 int change = 0, voice, idx, val;
1199 int num_efx = emu->audigy ? 8 : 4;
1200 int mask = emu->audigy ? 0x3f : 0x0f;
1201
1202 spin_lock_irqsave(&emu->reg_lock, flags);
1203 for (voice = 0; voice < 3; voice++)
1204 for (idx = 0; idx < num_efx; idx++) {
1205 val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask;
1206 if (mix->send_routing[voice][idx] != val) {
1207 mix->send_routing[voice][idx] = val;
1208 change = 1;
1209 }
1210 }
1211 if (change && mix->epcm) {
1212 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1213 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
1214 &mix->send_routing[1][0]);
1215 update_emu10k1_fxrt(emu, mix->epcm->voices[1]->number,
1216 &mix->send_routing[2][0]);
1217 } else if (mix->epcm->voices[0]) {
1218 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
1219 &mix->send_routing[0][0]);
1220 }
1221 }
1222 spin_unlock_irqrestore(&emu->reg_lock, flags);
1223 return change;
1224}
1225
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001226static struct snd_kcontrol_new snd_emu10k1_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227{
1228 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001229 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 .name = "EMU10K1 PCM Send Routing",
1231 .count = 32,
1232 .info = snd_emu10k1_send_routing_info,
1233 .get = snd_emu10k1_send_routing_get,
1234 .put = snd_emu10k1_send_routing_put
1235};
1236
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001237static int snd_emu10k1_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001239 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1241 uinfo->count = emu->audigy ? 3*8 : 3*4;
1242 uinfo->value.integer.min = 0;
1243 uinfo->value.integer.max = 255;
1244 return 0;
1245}
1246
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001247static int snd_emu10k1_send_volume_get(struct snd_kcontrol *kcontrol,
1248 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249{
1250 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001251 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1252 struct snd_emu10k1_pcm_mixer *mix =
1253 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254 int idx;
1255 int num_efx = emu->audigy ? 8 : 4;
1256
1257 spin_lock_irqsave(&emu->reg_lock, flags);
1258 for (idx = 0; idx < 3*num_efx; idx++)
1259 ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx];
1260 spin_unlock_irqrestore(&emu->reg_lock, flags);
1261 return 0;
1262}
1263
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001264static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol,
1265 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266{
1267 unsigned long flags;
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->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 int change = 0, idx, val;
1272 int num_efx = emu->audigy ? 8 : 4;
1273
1274 spin_lock_irqsave(&emu->reg_lock, flags);
1275 for (idx = 0; idx < 3*num_efx; idx++) {
1276 val = ucontrol->value.integer.value[idx] & 255;
1277 if (mix->send_volume[idx/num_efx][idx%num_efx] != val) {
1278 mix->send_volume[idx/num_efx][idx%num_efx] = val;
1279 change = 1;
1280 }
1281 }
1282 if (change && mix->epcm) {
1283 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1284 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
1285 &mix->send_volume[1][0]);
1286 update_emu10k1_send_volume(emu, mix->epcm->voices[1]->number,
1287 &mix->send_volume[2][0]);
1288 } else if (mix->epcm->voices[0]) {
1289 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
1290 &mix->send_volume[0][0]);
1291 }
1292 }
1293 spin_unlock_irqrestore(&emu->reg_lock, flags);
1294 return change;
1295}
1296
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001297static struct snd_kcontrol_new snd_emu10k1_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298{
1299 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001300 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 .name = "EMU10K1 PCM Send Volume",
1302 .count = 32,
1303 .info = snd_emu10k1_send_volume_info,
1304 .get = snd_emu10k1_send_volume_get,
1305 .put = snd_emu10k1_send_volume_put
1306};
1307
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001308static int snd_emu10k1_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309{
1310 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1311 uinfo->count = 3;
1312 uinfo->value.integer.min = 0;
1313 uinfo->value.integer.max = 0xffff;
1314 return 0;
1315}
1316
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001317static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol,
1318 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001320 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1321 struct snd_emu10k1_pcm_mixer *mix =
1322 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 unsigned long flags;
1324 int idx;
1325
1326 spin_lock_irqsave(&emu->reg_lock, flags);
1327 for (idx = 0; idx < 3; idx++)
1328 ucontrol->value.integer.value[idx] = mix->attn[idx];
1329 spin_unlock_irqrestore(&emu->reg_lock, flags);
1330 return 0;
1331}
1332
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001333static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol,
1334 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335{
1336 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001337 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1338 struct snd_emu10k1_pcm_mixer *mix =
1339 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 int change = 0, idx, val;
1341
1342 spin_lock_irqsave(&emu->reg_lock, flags);
1343 for (idx = 0; idx < 3; idx++) {
1344 val = ucontrol->value.integer.value[idx] & 0xffff;
1345 if (mix->attn[idx] != val) {
1346 mix->attn[idx] = val;
1347 change = 1;
1348 }
1349 }
1350 if (change && mix->epcm) {
1351 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1352 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[1]);
1353 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[1]->number, mix->attn[2]);
1354 } else if (mix->epcm->voices[0]) {
1355 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]);
1356 }
1357 }
1358 spin_unlock_irqrestore(&emu->reg_lock, flags);
1359 return change;
1360}
1361
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001362static struct snd_kcontrol_new snd_emu10k1_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363{
1364 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001365 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 .name = "EMU10K1 PCM Volume",
1367 .count = 32,
1368 .info = snd_emu10k1_attn_info,
1369 .get = snd_emu10k1_attn_get,
1370 .put = snd_emu10k1_attn_put
1371};
1372
1373/* Mutichannel PCM stream controls */
1374
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001375static int snd_emu10k1_efx_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001377 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1379 uinfo->count = emu->audigy ? 8 : 4;
1380 uinfo->value.integer.min = 0;
1381 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
1382 return 0;
1383}
1384
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001385static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol,
1386 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387{
1388 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001389 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1390 struct snd_emu10k1_pcm_mixer *mix =
1391 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 int idx;
1393 int num_efx = emu->audigy ? 8 : 4;
1394 int mask = emu->audigy ? 0x3f : 0x0f;
1395
1396 spin_lock_irqsave(&emu->reg_lock, flags);
1397 for (idx = 0; idx < num_efx; idx++)
1398 ucontrol->value.integer.value[idx] =
1399 mix->send_routing[0][idx] & mask;
1400 spin_unlock_irqrestore(&emu->reg_lock, flags);
1401 return 0;
1402}
1403
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001404static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol,
1405 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406{
1407 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001408 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001410 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 int change = 0, idx, val;
1412 int num_efx = emu->audigy ? 8 : 4;
1413 int mask = emu->audigy ? 0x3f : 0x0f;
1414
1415 spin_lock_irqsave(&emu->reg_lock, flags);
1416 for (idx = 0; idx < num_efx; idx++) {
1417 val = ucontrol->value.integer.value[idx] & mask;
1418 if (mix->send_routing[0][idx] != val) {
1419 mix->send_routing[0][idx] = val;
1420 change = 1;
1421 }
1422 }
1423
1424 if (change && mix->epcm) {
1425 if (mix->epcm->voices[ch]) {
1426 update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number,
1427 &mix->send_routing[0][0]);
1428 }
1429 }
1430 spin_unlock_irqrestore(&emu->reg_lock, flags);
1431 return change;
1432}
1433
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001434static struct snd_kcontrol_new snd_emu10k1_efx_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435{
1436 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1437 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1438 .name = "Multichannel PCM Send Routing",
1439 .count = 16,
1440 .info = snd_emu10k1_efx_send_routing_info,
1441 .get = snd_emu10k1_efx_send_routing_get,
1442 .put = snd_emu10k1_efx_send_routing_put
1443};
1444
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001445static int snd_emu10k1_efx_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001447 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1449 uinfo->count = emu->audigy ? 8 : 4;
1450 uinfo->value.integer.min = 0;
1451 uinfo->value.integer.max = 255;
1452 return 0;
1453}
1454
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001455static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol,
1456 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457{
1458 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001459 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1460 struct snd_emu10k1_pcm_mixer *mix =
1461 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 int idx;
1463 int num_efx = emu->audigy ? 8 : 4;
1464
1465 spin_lock_irqsave(&emu->reg_lock, flags);
1466 for (idx = 0; idx < num_efx; idx++)
1467 ucontrol->value.integer.value[idx] = mix->send_volume[0][idx];
1468 spin_unlock_irqrestore(&emu->reg_lock, flags);
1469 return 0;
1470}
1471
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001472static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol,
1473 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474{
1475 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001476 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001478 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 int change = 0, idx, val;
1480 int num_efx = emu->audigy ? 8 : 4;
1481
1482 spin_lock_irqsave(&emu->reg_lock, flags);
1483 for (idx = 0; idx < num_efx; idx++) {
1484 val = ucontrol->value.integer.value[idx] & 255;
1485 if (mix->send_volume[0][idx] != val) {
1486 mix->send_volume[0][idx] = val;
1487 change = 1;
1488 }
1489 }
1490 if (change && mix->epcm) {
1491 if (mix->epcm->voices[ch]) {
1492 update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number,
1493 &mix->send_volume[0][0]);
1494 }
1495 }
1496 spin_unlock_irqrestore(&emu->reg_lock, flags);
1497 return change;
1498}
1499
1500
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001501static struct snd_kcontrol_new snd_emu10k1_efx_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502{
1503 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1504 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1505 .name = "Multichannel PCM Send Volume",
1506 .count = 16,
1507 .info = snd_emu10k1_efx_send_volume_info,
1508 .get = snd_emu10k1_efx_send_volume_get,
1509 .put = snd_emu10k1_efx_send_volume_put
1510};
1511
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001512static int snd_emu10k1_efx_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513{
1514 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1515 uinfo->count = 1;
1516 uinfo->value.integer.min = 0;
1517 uinfo->value.integer.max = 0xffff;
1518 return 0;
1519}
1520
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001521static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol,
1522 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001524 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1525 struct snd_emu10k1_pcm_mixer *mix =
1526 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 unsigned long flags;
1528
1529 spin_lock_irqsave(&emu->reg_lock, flags);
1530 ucontrol->value.integer.value[0] = mix->attn[0];
1531 spin_unlock_irqrestore(&emu->reg_lock, flags);
1532 return 0;
1533}
1534
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001535static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol,
1536 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537{
1538 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001539 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001541 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 int change = 0, val;
1543
1544 spin_lock_irqsave(&emu->reg_lock, flags);
1545 val = ucontrol->value.integer.value[0] & 0xffff;
1546 if (mix->attn[0] != val) {
1547 mix->attn[0] = val;
1548 change = 1;
1549 }
1550 if (change && mix->epcm) {
1551 if (mix->epcm->voices[ch]) {
1552 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]);
1553 }
1554 }
1555 spin_unlock_irqrestore(&emu->reg_lock, flags);
1556 return change;
1557}
1558
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001559static struct snd_kcontrol_new snd_emu10k1_efx_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560{
1561 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1562 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1563 .name = "Multichannel PCM Volume",
1564 .count = 16,
1565 .info = snd_emu10k1_efx_attn_info,
1566 .get = snd_emu10k1_efx_attn_get,
1567 .put = snd_emu10k1_efx_attn_put
1568};
1569
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001570#define snd_emu10k1_shared_spdif_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001572static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol,
1573 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001575 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576
1577 if (emu->audigy)
1578 ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0;
1579 else
1580 ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0;
Takashi Iwaid2cd74b2008-06-02 11:45:53 +02001581 if (emu->card_capabilities->invert_shared_spdif)
1582 ucontrol->value.integer.value[0] =
1583 !ucontrol->value.integer.value[0];
1584
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 return 0;
1586}
1587
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001588static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
1589 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590{
1591 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001592 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Takashi Iwaid2cd74b2008-06-02 11:45:53 +02001593 unsigned int reg, val, sw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 int change = 0;
1595
Takashi Iwaid2cd74b2008-06-02 11:45:53 +02001596 sw = ucontrol->value.integer.value[0];
1597 if (emu->card_capabilities->invert_shared_spdif)
1598 sw = !sw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 spin_lock_irqsave(&emu->reg_lock, flags);
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001600 if ( emu->card_capabilities->i2c_adc) {
1601 /* Do nothing for Audigy 2 ZS Notebook */
1602 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 reg = inl(emu->port + A_IOCFG);
Takashi Iwaid2cd74b2008-06-02 11:45:53 +02001604 val = sw ? A_IOCFG_GPOUT0 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 change = (reg & A_IOCFG_GPOUT0) != val;
1606 if (change) {
1607 reg &= ~A_IOCFG_GPOUT0;
1608 reg |= val;
1609 outl(reg | val, emu->port + A_IOCFG);
1610 }
1611 }
1612 reg = inl(emu->port + HCFG);
Takashi Iwaid2cd74b2008-06-02 11:45:53 +02001613 val = sw ? HCFG_GPOUT0 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 change |= (reg & HCFG_GPOUT0) != val;
1615 if (change) {
1616 reg &= ~HCFG_GPOUT0;
1617 reg |= val;
1618 outl(reg | val, emu->port + HCFG);
1619 }
1620 spin_unlock_irqrestore(&emu->reg_lock, flags);
1621 return change;
1622}
1623
Bill Pembertone23e7a12012-12-06 12:35:10 -05001624static struct snd_kcontrol_new snd_emu10k1_shared_spdif =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625{
1626 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1627 .name = "SB Live Analog/Digital Output Jack",
1628 .info = snd_emu10k1_shared_spdif_info,
1629 .get = snd_emu10k1_shared_spdif_get,
1630 .put = snd_emu10k1_shared_spdif_put
1631};
1632
Bill Pembertone23e7a12012-12-06 12:35:10 -05001633static struct snd_kcontrol_new snd_audigy_shared_spdif =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634{
1635 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1636 .name = "Audigy Analog/Digital Output Jack",
1637 .info = snd_emu10k1_shared_spdif_info,
1638 .get = snd_emu10k1_shared_spdif_get,
1639 .put = snd_emu10k1_shared_spdif_put
1640};
1641
Takashi Iwai16950e02008-12-02 09:31:16 +01001642/* workaround for too low volume on Audigy due to 16bit/24bit conversion */
1643
1644#define snd_audigy_capture_boost_info snd_ctl_boolean_mono_info
1645
1646static int snd_audigy_capture_boost_get(struct snd_kcontrol *kcontrol,
1647 struct snd_ctl_elem_value *ucontrol)
1648{
1649 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1650 unsigned int val;
1651
1652 /* FIXME: better to use a cached version */
1653 val = snd_ac97_read(emu->ac97, AC97_REC_GAIN);
1654 ucontrol->value.integer.value[0] = !!val;
1655 return 0;
1656}
1657
1658static int snd_audigy_capture_boost_put(struct snd_kcontrol *kcontrol,
1659 struct snd_ctl_elem_value *ucontrol)
1660{
1661 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1662 unsigned int val;
1663
1664 if (ucontrol->value.integer.value[0])
1665 val = 0x0f0f;
1666 else
1667 val = 0;
1668 return snd_ac97_update(emu->ac97, AC97_REC_GAIN, val);
1669}
1670
Bill Pembertone23e7a12012-12-06 12:35:10 -05001671static struct snd_kcontrol_new snd_audigy_capture_boost =
Takashi Iwai16950e02008-12-02 09:31:16 +01001672{
1673 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1674 .name = "Analog Capture Boost",
1675 .info = snd_audigy_capture_boost_info,
1676 .get = snd_audigy_capture_boost_get,
1677 .put = snd_audigy_capture_boost_put
1678};
1679
1680
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681/*
1682 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001683static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001685 struct snd_emu10k1 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686 emu->ac97 = NULL;
1687}
1688
1689/*
1690 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001691static int remove_ctl(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001693 struct snd_ctl_elem_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 memset(&id, 0, sizeof(id));
1695 strcpy(id.name, name);
1696 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1697 return snd_ctl_remove_id(card, &id);
1698}
1699
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001700static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001702 struct snd_ctl_elem_id sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 memset(&sid, 0, sizeof(sid));
1704 strcpy(sid.name, name);
1705 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1706 return snd_ctl_find_id(card, &sid);
1707}
1708
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001709static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001711 struct snd_kcontrol *kctl = ctl_find(card, src);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 if (kctl) {
1713 strcpy(kctl->id.name, dst);
1714 return 0;
1715 }
1716 return -ENOENT;
1717}
1718
Bill Pembertone23e7a12012-12-06 12:35:10 -05001719int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
1720 int pcm_device, int multi_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721{
1722 int err, pcm;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001723 struct snd_kcontrol *kctl;
1724 struct snd_card *card = emu->card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 char **c;
1726 static char *emu10k1_remove_ctls[] = {
1727 /* no AC97 mono, surround, center/lfe */
1728 "Master Mono Playback Switch",
1729 "Master Mono Playback Volume",
1730 "PCM Out Path & Mute",
1731 "Mono Output Select",
1732 "Surround Playback Switch",
1733 "Surround Playback Volume",
1734 "Center Playback Switch",
1735 "Center Playback Volume",
1736 "LFE Playback Switch",
1737 "LFE Playback Volume",
1738 NULL
1739 };
1740 static char *emu10k1_rename_ctls[] = {
1741 "Surround Digital Playback Volume", "Surround Playback Volume",
1742 "Center Digital Playback Volume", "Center Playback Volume",
1743 "LFE Digital Playback Volume", "LFE Playback Volume",
1744 NULL
1745 };
1746 static char *audigy_remove_ctls[] = {
1747 /* Master/PCM controls on ac97 of Audigy has no effect */
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001748 /* On the Audigy2 the AC97 playback is piped into
1749 * the Philips ADC for 24bit capture */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 "PCM Playback Switch",
1751 "PCM Playback Volume",
1752 "Master Mono Playback Switch",
1753 "Master Mono Playback Volume",
1754 "Master Playback Switch",
1755 "Master Playback Volume",
1756 "PCM Out Path & Mute",
1757 "Mono Output Select",
1758 /* remove unused AC97 capture controls */
1759 "Capture Source",
1760 "Capture Switch",
1761 "Capture Volume",
1762 "Mic Select",
1763 "Video Playback Switch",
1764 "Video Playback Volume",
1765 "Mic Playback Switch",
1766 "Mic Playback Volume",
1767 NULL
1768 };
1769 static char *audigy_rename_ctls[] = {
1770 /* use conventional names */
1771 "Wave Playback Volume", "PCM Playback Volume",
1772 /* "Wave Capture Volume", "PCM Capture Volume", */
1773 "Wave Master Playback Volume", "Master Playback Volume",
1774 "AMic Playback Volume", "Mic Playback Volume",
1775 NULL
1776 };
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001777 static char *audigy_rename_ctls_i2c_adc[] = {
1778 //"Analog Mix Capture Volume","OLD Analog Mix Capture Volume",
1779 "Line Capture Volume", "Analog Mix Capture Volume",
1780 "Wave Playback Volume", "OLD PCM Playback Volume",
1781 "Wave Master Playback Volume", "Master Playback Volume",
1782 "AMic Playback Volume", "Old Mic Playback Volume",
James Courtier-Duttoneb41dab2006-12-06 20:38:45 +00001783 "CD Capture Volume", "IEC958 Optical Capture Volume",
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001784 NULL
1785 };
1786 static char *audigy_remove_ctls_i2c_adc[] = {
1787 /* On the Audigy2 ZS Notebook
1788 * Capture via WM8775 */
1789 "Mic Capture Volume",
1790 "Analog Mix Capture Volume",
1791 "Aux Capture Volume",
James Courtier-Duttoneb41dab2006-12-06 20:38:45 +00001792 "IEC958 Optical Capture Volume",
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001793 NULL
1794 };
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001795 static char *audigy_remove_ctls_1361t_adc[] = {
1796 /* On the Audigy2 the AC97 playback is piped into
1797 * the Philips ADC for 24bit capture */
1798 "PCM Playback Switch",
1799 "PCM Playback Volume",
1800 "Master Mono Playback Switch",
1801 "Master Mono Playback Volume",
1802 "Capture Source",
1803 "Capture Switch",
1804 "Capture Volume",
1805 "Mic Capture Volume",
1806 "Headphone Playback Switch",
1807 "Headphone Playback Volume",
1808 "3D Control - Center",
1809 "3D Control - Depth",
1810 "3D Control - Switch",
1811 "Line2 Playback Volume",
1812 "Line2 Capture Volume",
1813 NULL
1814 };
1815 static char *audigy_rename_ctls_1361t_adc[] = {
1816 "Master Playback Switch", "Master Capture Switch",
1817 "Master Playback Volume", "Master Capture Volume",
1818 "Wave Master Playback Volume", "Master Playback Volume",
Jaroslav Kyselad355c82a2009-11-03 15:47:25 +01001819 "Beep Playback Switch", "Beep Capture Switch",
1820 "Beep Playback Volume", "Beep Capture Volume",
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001821 "Phone Playback Switch", "Phone Capture Switch",
1822 "Phone Playback Volume", "Phone Capture Volume",
1823 "Mic Playback Switch", "Mic Capture Switch",
1824 "Mic Playback Volume", "Mic Capture Volume",
1825 "Line Playback Switch", "Line Capture Switch",
1826 "Line Playback Volume", "Line Capture Volume",
1827 "CD Playback Switch", "CD Capture Switch",
1828 "CD Playback Volume", "CD Capture Volume",
1829 "Aux Playback Switch", "Aux Capture Switch",
1830 "Aux Playback Volume", "Aux Capture Volume",
1831 "Video Playback Switch", "Video Capture Switch",
1832 "Video Playback Volume", "Video Capture Volume",
1833
1834 NULL
1835 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836
Lee Revell2b637da2005-03-30 13:51:18 +02001837 if (emu->card_capabilities->ac97_chip) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001838 struct snd_ac97_bus *pbus;
1839 struct snd_ac97_template ac97;
1840 static struct snd_ac97_bus_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001841 .write = snd_emu10k1_ac97_write,
1842 .read = snd_emu10k1_ac97_read,
1843 };
1844
Takashi Iwaib1508692005-10-04 13:49:32 +02001845 if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0)
1846 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847 pbus->no_vra = 1; /* we don't need VRA */
1848
1849 memset(&ac97, 0, sizeof(ac97));
1850 ac97.private_data = emu;
1851 ac97.private_free = snd_emu10k1_mixer_free_ac97;
1852 ac97.scaps = AC97_SCAP_NO_SPDIF;
Takashi Iwaib1508692005-10-04 13:49:32 +02001853 if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) {
1854 if (emu->card_capabilities->ac97_chip == 1)
1855 return err;
1856 snd_printd(KERN_INFO "emu10k1: AC97 is optional on this board\n");
1857 snd_printd(KERN_INFO" Proceeding without ac97 mixers...\n");
1858 snd_device_free(emu->card, pbus);
1859 goto no_ac97; /* FIXME: get rid of ugly gotos.. */
1860 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861 if (emu->audigy) {
1862 /* set master volume to 0 dB */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001863 snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 /* set capture source to mic */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001865 snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001866 if (emu->card_capabilities->adc_1361t)
1867 c = audigy_remove_ctls_1361t_adc;
1868 else
1869 c = audigy_remove_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870 } else {
1871 /*
1872 * Credits for cards based on STAC9758:
1873 * James Courtier-Dutton <James@superbug.demon.co.uk>
1874 * Voluspa <voluspa@comhem.se>
1875 */
1876 if (emu->ac97->id == AC97_ID_STAC9758) {
1877 emu->rear_ac97 = 1;
1878 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 +01001879 snd_ac97_write_cache(emu->ac97, AC97_HEADPHONE, 0x0202);
Raymond Yaub6a48402011-04-15 11:42:42 +08001880 remove_ctl(card,"Front Playback Volume");
1881 remove_ctl(card,"Front Playback Switch");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882 }
1883 /* remove unused AC97 controls */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001884 snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
1885 snd_ac97_write_cache(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 c = emu10k1_remove_ctls;
1887 }
1888 for (; *c; c++)
1889 remove_ctl(card, *c);
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001890 } else if (emu->card_capabilities->i2c_adc) {
1891 c = audigy_remove_ctls_i2c_adc;
1892 for (; *c; c++)
1893 remove_ctl(card, *c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894 } else {
Takashi Iwaif12aa402005-09-30 16:56:59 +02001895 no_ac97:
Lee Revell2b637da2005-03-30 13:51:18 +02001896 if (emu->card_capabilities->ecard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897 strcpy(emu->card->mixername, "EMU APS");
1898 else if (emu->audigy)
1899 strcpy(emu->card->mixername, "SB Audigy");
1900 else
1901 strcpy(emu->card->mixername, "Emu10k1");
1902 }
1903
1904 if (emu->audigy)
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001905 if (emu->card_capabilities->adc_1361t)
1906 c = audigy_rename_ctls_1361t_adc;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001907 else if (emu->card_capabilities->i2c_adc)
1908 c = audigy_rename_ctls_i2c_adc;
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001909 else
1910 c = audigy_rename_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 else
1912 c = emu10k1_rename_ctls;
1913 for (; *c; c += 2)
1914 rename_ctl(card, c[0], c[1]);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001915
Raymond Yaue217b962011-03-30 20:00:39 +08001916 if (emu->card_capabilities->subsystem == 0x80401102) { /* SB Live! Platinum CT4760P */
1917 remove_ctl(card, "Center Playback Volume");
1918 remove_ctl(card, "LFE Playback Volume");
1919 remove_ctl(card, "Wave Center Playback Volume");
1920 remove_ctl(card, "Wave LFE Playback Volume");
1921 }
James Courtier-Duttone3b9bc02005-12-24 16:54:51 +01001922 if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */
1923 rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume");
1924 rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume");
1925 rename_ctl(card, "Aux2 Capture Volume", "Line3 Capture Volume");
1926 rename_ctl(card, "Mic Capture Volume", "Unknown1 Capture Volume");
1927 remove_ctl(card, "Headphone Playback Switch");
1928 remove_ctl(card, "Headphone Playback Volume");
1929 remove_ctl(card, "3D Control - Center");
1930 remove_ctl(card, "3D Control - Depth");
1931 remove_ctl(card, "3D Control - Switch");
1932 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL)
1934 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001935 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 if ((err = snd_ctl_add(card, kctl)))
1937 return err;
1938 if ((kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL)
1939 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001940 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001941 if ((err = snd_ctl_add(card, kctl)))
1942 return err;
1943 if ((kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu)) == NULL)
1944 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001945 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001946 if ((err = snd_ctl_add(card, kctl)))
1947 return err;
1948
1949 if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL)
1950 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001951 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001952 if ((err = snd_ctl_add(card, kctl)))
1953 return err;
1954
1955 if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL)
1956 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001957 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 if ((err = snd_ctl_add(card, kctl)))
1959 return err;
1960
1961 if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL)
1962 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001963 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001964 if ((err = snd_ctl_add(card, kctl)))
1965 return err;
1966
1967 /* initialize the routing and volume table for each pcm playback stream */
1968 for (pcm = 0; pcm < 32; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001969 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 int v;
1971
1972 mix = &emu->pcm_mixer[pcm];
1973 mix->epcm = NULL;
1974
1975 for (v = 0; v < 4; v++)
1976 mix->send_routing[0][v] =
1977 mix->send_routing[1][v] =
1978 mix->send_routing[2][v] = v;
1979
1980 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1981 mix->send_volume[0][0] = mix->send_volume[0][1] =
1982 mix->send_volume[1][0] = mix->send_volume[2][1] = 255;
1983
1984 mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
1985 }
1986
1987 /* initialize the routing and volume table for the multichannel playback stream */
1988 for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001989 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 int v;
1991
1992 mix = &emu->efx_pcm_mixer[pcm];
1993 mix->epcm = NULL;
1994
1995 mix->send_routing[0][0] = pcm;
1996 mix->send_routing[0][1] = (pcm == 0) ? 1 : 0;
1997 for (v = 0; v < 2; v++)
1998 mix->send_routing[0][2+v] = 13+v;
1999 if (emu->audigy)
2000 for (v = 0; v < 4; v++)
2001 mix->send_routing[0][4+v] = 60+v;
2002
2003 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
2004 mix->send_volume[0][0] = 255;
2005
2006 mix->attn[0] = 0xffff;
2007 }
2008
Lee Revell2b637da2005-03-30 13:51:18 +02002009 if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010 /* sb live! and audigy */
2011 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
2012 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02002013 if (!emu->audigy)
2014 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 if ((err = snd_ctl_add(card, kctl)))
2016 return err;
2017 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
2018 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02002019 if (!emu->audigy)
2020 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021 if ((err = snd_ctl_add(card, kctl)))
2022 return err;
2023 }
2024
James Courtier-Dutton190d2c42007-11-04 14:08:26 +00002025 if (emu->card_capabilities->emu_model) {
James Courtier-Dutton19b99fb2005-12-04 18:03:03 +01002026 ; /* Disable the snd_audigy_spdif_shared_spdif */
2027 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
2029 return -ENOMEM;
2030 if ((err = snd_ctl_add(card, kctl)))
2031 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02002032#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
2034 return -ENOMEM;
2035 if ((err = snd_ctl_add(card, kctl)))
2036 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02002037#endif
Lee Revell2b637da2005-03-30 13:51:18 +02002038 } else if (! emu->card_capabilities->ecard) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039 /* sb live! */
2040 if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
2041 return -ENOMEM;
2042 if ((err = snd_ctl_add(card, kctl)))
2043 return err;
2044 }
Lee Revell2b637da2005-03-30 13:51:18 +02002045 if (emu->card_capabilities->ca0151_chip) { /* P16V */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046 if ((err = snd_p16v_mixer(emu)))
2047 return err;
2048 }
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01002049
Takashi Iwai3839e4f2007-12-21 16:33:32 +01002050 if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) {
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002051 /* 1616(m) cardbus */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01002052 int i;
2053
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002054 for (i = 0; i < ARRAY_SIZE(snd_emu1616_output_enum_ctls); i++) {
2055 err = snd_ctl_add(card,
2056 snd_ctl_new1(&snd_emu1616_output_enum_ctls[i],
2057 emu));
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01002058 if (err < 0)
2059 return err;
2060 }
2061 for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) {
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002062 err = snd_ctl_add(card,
2063 snd_ctl_new1(&snd_emu1010_input_enum_ctls[i],
2064 emu));
2065 if (err < 0)
2066 return err;
2067 }
2068 for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads) - 2; i++) {
2069 err = snd_ctl_add(card,
2070 snd_ctl_new1(&snd_emu1010_adc_pads[i], emu));
2071 if (err < 0)
2072 return err;
2073 }
2074 for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads) - 2; i++) {
2075 err = snd_ctl_add(card,
2076 snd_ctl_new1(&snd_emu1010_dac_pads[i], emu));
2077 if (err < 0)
2078 return err;
2079 }
2080 err = snd_ctl_add(card,
2081 snd_ctl_new1(&snd_emu1010_internal_clock, emu));
2082 if (err < 0)
2083 return err;
2084
Takashi Iwai88aa1392007-12-21 16:20:12 +01002085 } else if (emu->card_capabilities->emu_model) {
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002086 /* all other e-mu cards for now */
2087 int i;
2088
2089 for (i = 0; i < ARRAY_SIZE(snd_emu1010_output_enum_ctls); i++) {
2090 err = snd_ctl_add(card,
2091 snd_ctl_new1(&snd_emu1010_output_enum_ctls[i],
2092 emu));
2093 if (err < 0)
2094 return err;
2095 }
2096 for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) {
2097 err = snd_ctl_add(card,
2098 snd_ctl_new1(&snd_emu1010_input_enum_ctls[i],
2099 emu));
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01002100 if (err < 0)
2101 return err;
2102 }
James Courtier-Dutton9148cc52006-10-09 23:08:00 +01002103 for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads); i++) {
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002104 err = snd_ctl_add(card,
2105 snd_ctl_new1(&snd_emu1010_adc_pads[i], emu));
James Courtier-Dutton9148cc52006-10-09 23:08:00 +01002106 if (err < 0)
2107 return err;
2108 }
2109 for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads); i++) {
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002110 err = snd_ctl_add(card,
2111 snd_ctl_new1(&snd_emu1010_dac_pads[i], emu));
James Courtier-Dutton9148cc52006-10-09 23:08:00 +01002112 if (err < 0)
2113 return err;
2114 }
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002115 err = snd_ctl_add(card,
2116 snd_ctl_new1(&snd_emu1010_internal_clock, emu));
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +01002117 if (err < 0)
2118 return err;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01002119 }
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00002120
2121 if ( emu->card_capabilities->i2c_adc) {
2122 int i;
2123
2124 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_capture_source, emu));
2125 if (err < 0)
2126 return err;
2127
2128 for (i = 0; i < ARRAY_SIZE(snd_audigy_i2c_volume_ctls); i++) {
2129 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_volume_ctls[i], emu));
2130 if (err < 0)
2131 return err;
2132 }
2133 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134
Takashi Iwai16950e02008-12-02 09:31:16 +01002135 if (emu->card_capabilities->ac97_chip && emu->audigy) {
2136 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_capture_boost,
2137 emu));
2138 if (err < 0)
2139 return err;
2140 }
2141
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142 return 0;
2143}