blob: 1de33025669a1147eabd9e1e3449b5205d51fd6d [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 */
Takashi Iwai1541c662014-10-20 18:16:48 +020086static const char * const emu1010_src_texts[] = {
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +010087 "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
Takashi Iwai1541c662014-10-20 18:16:48 +0200144static const char * const emu1616_src_texts[] = {
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100145 "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);
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100396
Takashi Iwai1541c662014-10-20 18:16:48 +0200397 if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616)
398 return snd_ctl_enum_info(uinfo, 1, 49, emu1616_src_texts);
399 else
400 return snd_ctl_enum_info(uinfo, 1, 53, emu1010_src_texts);
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100401}
402
403static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol,
404 struct snd_ctl_elem_value *ucontrol)
405{
406 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000407 unsigned int channel;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100408
409 channel = (kcontrol->private_value) & 0xff;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000410 /* Limit: emu1010_output_dst, emu->emu1010.output_source */
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100411 if (channel >= 24 ||
Takashi Iwai3839e4f2007-12-21 16:33:32 +0100412 (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616 &&
413 channel >= 18))
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000414 return -EINVAL;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100415 ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel];
416 return 0;
417}
418
419static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol,
420 struct snd_ctl_elem_value *ucontrol)
421{
422 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100423 unsigned int val;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000424 unsigned int channel;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100425
Takashi Iwaiaa299d02007-11-15 13:16:02 +0100426 val = ucontrol->value.enumerated.item[0];
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100427 if (val >= 53 ||
Takashi Iwai3839e4f2007-12-21 16:33:32 +0100428 (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616 &&
429 val >= 49))
Takashi Iwaiaa299d02007-11-15 13:16:02 +0100430 return -EINVAL;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100431 channel = (kcontrol->private_value) & 0xff;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000432 /* Limit: emu1010_output_dst, emu->emu1010.output_source */
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100433 if (channel >= 24 ||
Takashi Iwai3839e4f2007-12-21 16:33:32 +0100434 (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616 &&
435 channel >= 18))
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000436 return -EINVAL;
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100437 if (emu->emu1010.output_source[channel] == val)
438 return 0;
439 emu->emu1010.output_source[channel] = val;
Takashi Iwai3839e4f2007-12-21 16:33:32 +0100440 if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616)
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100441 snd_emu1010_fpga_link_dst_src_write(emu,
442 emu1616_output_dst[channel], emu1616_src_regs[val]);
443 else
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100444 snd_emu1010_fpga_link_dst_src_write(emu,
445 emu1010_output_dst[channel], emu1010_src_regs[val]);
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100446 return 1;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100447}
448
449static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol,
450 struct snd_ctl_elem_value *ucontrol)
451{
452 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000453 unsigned int channel;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100454
455 channel = (kcontrol->private_value) & 0xff;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000456 /* Limit: emu1010_input_dst, emu->emu1010.input_source */
457 if (channel >= 22)
458 return -EINVAL;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100459 ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel];
460 return 0;
461}
462
463static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
464 struct snd_ctl_elem_value *ucontrol)
465{
466 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100467 unsigned int val;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000468 unsigned int channel;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100469
Takashi Iwaiaa299d02007-11-15 13:16:02 +0100470 val = ucontrol->value.enumerated.item[0];
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100471 if (val >= 53 ||
Takashi Iwai3839e4f2007-12-21 16:33:32 +0100472 (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616 &&
473 val >= 49))
Takashi Iwaiaa299d02007-11-15 13:16:02 +0100474 return -EINVAL;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100475 channel = (kcontrol->private_value) & 0xff;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000476 /* Limit: emu1010_input_dst, emu->emu1010.input_source */
477 if (channel >= 22)
478 return -EINVAL;
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100479 if (emu->emu1010.input_source[channel] == val)
480 return 0;
481 emu->emu1010.input_source[channel] = val;
Takashi Iwai3839e4f2007-12-21 16:33:32 +0100482 if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616)
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100483 snd_emu1010_fpga_link_dst_src_write(emu,
484 emu1010_input_dst[channel], emu1616_src_regs[val]);
485 else
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100486 snd_emu1010_fpga_link_dst_src_write(emu,
487 emu1010_input_dst[channel], emu1010_src_regs[val]);
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100488 return 1;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100489}
490
491#define EMU1010_SOURCE_OUTPUT(xname,chid) \
492{ \
493 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
494 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
495 .info = snd_emu1010_input_output_source_info, \
496 .get = snd_emu1010_output_source_get, \
497 .put = snd_emu1010_output_source_put, \
498 .private_value = chid \
499}
500
Bill Pembertone23e7a12012-12-06 12:35:10 -0500501static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] = {
James Courtier-Dutton4c07c812006-11-11 10:48:58 +0000502 EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0),
503 EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1),
504 EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2),
505 EMU1010_SOURCE_OUTPUT("Dock DAC2 Right Playback Enum", 3),
506 EMU1010_SOURCE_OUTPUT("Dock DAC3 Left Playback Enum", 4),
507 EMU1010_SOURCE_OUTPUT("Dock DAC3 Right Playback Enum", 5),
508 EMU1010_SOURCE_OUTPUT("Dock DAC4 Left Playback Enum", 6),
509 EMU1010_SOURCE_OUTPUT("Dock DAC4 Right Playback Enum", 7),
510 EMU1010_SOURCE_OUTPUT("Dock Phones Left Playback Enum", 8),
511 EMU1010_SOURCE_OUTPUT("Dock Phones Right Playback Enum", 9),
512 EMU1010_SOURCE_OUTPUT("Dock SPDIF Left Playback Enum", 0xa),
513 EMU1010_SOURCE_OUTPUT("Dock SPDIF Right Playback Enum", 0xb),
514 EMU1010_SOURCE_OUTPUT("1010 SPDIF Left Playback Enum", 0xc),
515 EMU1010_SOURCE_OUTPUT("1010 SPDIF Right Playback Enum", 0xd),
516 EMU1010_SOURCE_OUTPUT("0202 DAC Left Playback Enum", 0xe),
517 EMU1010_SOURCE_OUTPUT("0202 DAC Right Playback Enum", 0xf),
518 EMU1010_SOURCE_OUTPUT("1010 ADAT 0 Playback Enum", 0x10),
519 EMU1010_SOURCE_OUTPUT("1010 ADAT 1 Playback Enum", 0x11),
520 EMU1010_SOURCE_OUTPUT("1010 ADAT 2 Playback Enum", 0x12),
521 EMU1010_SOURCE_OUTPUT("1010 ADAT 3 Playback Enum", 0x13),
522 EMU1010_SOURCE_OUTPUT("1010 ADAT 4 Playback Enum", 0x14),
523 EMU1010_SOURCE_OUTPUT("1010 ADAT 5 Playback Enum", 0x15),
524 EMU1010_SOURCE_OUTPUT("1010 ADAT 6 Playback Enum", 0x16),
525 EMU1010_SOURCE_OUTPUT("1010 ADAT 7 Playback Enum", 0x17),
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100526};
527
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100528
529/* 1616(m) cardbus */
Bill Pembertone23e7a12012-12-06 12:35:10 -0500530static struct snd_kcontrol_new snd_emu1616_output_enum_ctls[] = {
Ctirad Fertr1c02e362007-12-13 16:27:13 +0100531 EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0),
532 EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1),
533 EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2),
534 EMU1010_SOURCE_OUTPUT("Dock DAC2 Right Playback Enum", 3),
535 EMU1010_SOURCE_OUTPUT("Dock DAC3 Left Playback Enum", 4),
536 EMU1010_SOURCE_OUTPUT("Dock DAC3 Right Playback Enum", 5),
537 EMU1010_SOURCE_OUTPUT("Dock SPDIF Left Playback Enum", 6),
538 EMU1010_SOURCE_OUTPUT("Dock SPDIF Right Playback Enum", 7),
539 EMU1010_SOURCE_OUTPUT("Dock ADAT 0 Playback Enum", 8),
540 EMU1010_SOURCE_OUTPUT("Dock ADAT 1 Playback Enum", 9),
541 EMU1010_SOURCE_OUTPUT("Dock ADAT 2 Playback Enum", 0xa),
542 EMU1010_SOURCE_OUTPUT("Dock ADAT 3 Playback Enum", 0xb),
543 EMU1010_SOURCE_OUTPUT("Dock ADAT 4 Playback Enum", 0xc),
544 EMU1010_SOURCE_OUTPUT("Dock ADAT 5 Playback Enum", 0xd),
545 EMU1010_SOURCE_OUTPUT("Dock ADAT 6 Playback Enum", 0xe),
546 EMU1010_SOURCE_OUTPUT("Dock ADAT 7 Playback Enum", 0xf),
547 EMU1010_SOURCE_OUTPUT("Mana DAC Left Playback Enum", 0x10),
548 EMU1010_SOURCE_OUTPUT("Mana DAC Right Playback Enum", 0x11),
549};
550
551
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100552#define EMU1010_SOURCE_INPUT(xname,chid) \
553{ \
554 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
555 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
556 .info = snd_emu1010_input_output_source_info, \
557 .get = snd_emu1010_input_source_get, \
558 .put = snd_emu1010_input_source_put, \
559 .private_value = chid \
560}
561
Bill Pembertone23e7a12012-12-06 12:35:10 -0500562static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] = {
James Courtier-Dutton4c07c812006-11-11 10:48:58 +0000563 EMU1010_SOURCE_INPUT("DSP 0 Capture Enum", 0),
564 EMU1010_SOURCE_INPUT("DSP 1 Capture Enum", 1),
565 EMU1010_SOURCE_INPUT("DSP 2 Capture Enum", 2),
566 EMU1010_SOURCE_INPUT("DSP 3 Capture Enum", 3),
567 EMU1010_SOURCE_INPUT("DSP 4 Capture Enum", 4),
568 EMU1010_SOURCE_INPUT("DSP 5 Capture Enum", 5),
569 EMU1010_SOURCE_INPUT("DSP 6 Capture Enum", 6),
570 EMU1010_SOURCE_INPUT("DSP 7 Capture Enum", 7),
571 EMU1010_SOURCE_INPUT("DSP 8 Capture Enum", 8),
572 EMU1010_SOURCE_INPUT("DSP 9 Capture Enum", 9),
573 EMU1010_SOURCE_INPUT("DSP A Capture Enum", 0xa),
574 EMU1010_SOURCE_INPUT("DSP B Capture Enum", 0xb),
575 EMU1010_SOURCE_INPUT("DSP C Capture Enum", 0xc),
576 EMU1010_SOURCE_INPUT("DSP D Capture Enum", 0xd),
577 EMU1010_SOURCE_INPUT("DSP E Capture Enum", 0xe),
578 EMU1010_SOURCE_INPUT("DSP F Capture Enum", 0xf),
579 EMU1010_SOURCE_INPUT("DSP 10 Capture Enum", 0x10),
580 EMU1010_SOURCE_INPUT("DSP 11 Capture Enum", 0x11),
581 EMU1010_SOURCE_INPUT("DSP 12 Capture Enum", 0x12),
582 EMU1010_SOURCE_INPUT("DSP 13 Capture Enum", 0x13),
583 EMU1010_SOURCE_INPUT("DSP 14 Capture Enum", 0x14),
584 EMU1010_SOURCE_INPUT("DSP 15 Capture Enum", 0x15),
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100585};
586
587
588
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200589#define snd_emu1010_adc_pads_info snd_ctl_boolean_mono_info
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100590
591static int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
592{
593 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
594 unsigned int mask = kcontrol->private_value & 0xff;
595 ucontrol->value.integer.value[0] = (emu->emu1010.adc_pads & mask) ? 1 : 0;
596 return 0;
597}
598
599static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
600{
601 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
602 unsigned int mask = kcontrol->private_value & 0xff;
603 unsigned int val, cache;
604 val = ucontrol->value.integer.value[0];
605 cache = emu->emu1010.adc_pads;
606 if (val == 1)
607 cache = cache | mask;
608 else
609 cache = cache & ~mask;
610 if (cache != emu->emu1010.adc_pads) {
611 snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache );
612 emu->emu1010.adc_pads = cache;
613 }
614
615 return 0;
616}
617
618
619
620#define EMU1010_ADC_PADS(xname,chid) \
621{ \
622 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
623 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
624 .info = snd_emu1010_adc_pads_info, \
625 .get = snd_emu1010_adc_pads_get, \
626 .put = snd_emu1010_adc_pads_put, \
627 .private_value = chid \
628}
629
Bill Pembertone23e7a12012-12-06 12:35:10 -0500630static struct snd_kcontrol_new snd_emu1010_adc_pads[] = {
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100631 EMU1010_ADC_PADS("ADC1 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD1),
632 EMU1010_ADC_PADS("ADC2 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD2),
633 EMU1010_ADC_PADS("ADC3 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD3),
634 EMU1010_ADC_PADS("ADC1 14dB PAD 0202 Capture Switch", EMU_HANA_0202_ADC_PAD1),
635};
636
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200637#define snd_emu1010_dac_pads_info snd_ctl_boolean_mono_info
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100638
639static int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
640{
641 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
642 unsigned int mask = kcontrol->private_value & 0xff;
643 ucontrol->value.integer.value[0] = (emu->emu1010.dac_pads & mask) ? 1 : 0;
644 return 0;
645}
646
647static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
648{
649 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
650 unsigned int mask = kcontrol->private_value & 0xff;
651 unsigned int val, cache;
652 val = ucontrol->value.integer.value[0];
653 cache = emu->emu1010.dac_pads;
654 if (val == 1)
655 cache = cache | mask;
656 else
657 cache = cache & ~mask;
658 if (cache != emu->emu1010.dac_pads) {
659 snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache );
660 emu->emu1010.dac_pads = cache;
661 }
662
663 return 0;
664}
665
666
667
668#define EMU1010_DAC_PADS(xname,chid) \
669{ \
670 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
671 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
672 .info = snd_emu1010_dac_pads_info, \
673 .get = snd_emu1010_dac_pads_get, \
674 .put = snd_emu1010_dac_pads_put, \
675 .private_value = chid \
676}
677
Bill Pembertone23e7a12012-12-06 12:35:10 -0500678static struct snd_kcontrol_new snd_emu1010_dac_pads[] = {
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100679 EMU1010_DAC_PADS("DAC1 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD1),
680 EMU1010_DAC_PADS("DAC2 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD2),
681 EMU1010_DAC_PADS("DAC3 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD3),
682 EMU1010_DAC_PADS("DAC4 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD4),
683 EMU1010_DAC_PADS("DAC1 0202 14dB PAD Playback Switch", EMU_HANA_0202_DAC_PAD1),
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100684};
685
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100686
687static int snd_emu1010_internal_clock_info(struct snd_kcontrol *kcontrol,
688 struct snd_ctl_elem_info *uinfo)
689{
Takashi Iwai1541c662014-10-20 18:16:48 +0200690 static const char * const texts[4] = {
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100691 "44100", "48000", "SPDIF", "ADAT"
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100692 };
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100693
Takashi Iwai1541c662014-10-20 18:16:48 +0200694 return snd_ctl_enum_info(uinfo, 1, 4, texts);
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100695}
696
697static int snd_emu1010_internal_clock_get(struct snd_kcontrol *kcontrol,
698 struct snd_ctl_elem_value *ucontrol)
699{
700 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
701
702 ucontrol->value.enumerated.item[0] = emu->emu1010.internal_clock;
703 return 0;
704}
705
706static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol,
707 struct snd_ctl_elem_value *ucontrol)
708{
709 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
710 unsigned int val;
711 int change = 0;
712
713 val = ucontrol->value.enumerated.item[0] ;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000714 /* Limit: uinfo->value.enumerated.items = 4; */
715 if (val >= 4)
716 return -EINVAL;
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100717 change = (emu->emu1010.internal_clock != val);
718 if (change) {
719 emu->emu1010.internal_clock = val;
720 switch (val) {
721 case 0:
722 /* 44100 */
723 /* Mute all */
724 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
725 /* Default fallback clock 48kHz */
726 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_44_1K );
727 /* Word Clock source, Internal 44.1kHz x1 */
728 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
729 EMU_HANA_WCLOCK_INT_44_1K | EMU_HANA_WCLOCK_1X );
730 /* Set LEDs on Audio Dock */
731 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
732 EMU_HANA_DOCK_LEDS_2_44K | EMU_HANA_DOCK_LEDS_2_LOCK );
733 /* Allow DLL to settle */
James Courtier-Duttone40a0b22006-10-10 18:44:29 +0100734 msleep(10);
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100735 /* Unmute all */
736 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
737 break;
738 case 1:
739 /* 48000 */
740 /* Mute all */
741 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
742 /* Default fallback clock 48kHz */
743 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
744 /* Word Clock source, Internal 48kHz x1 */
745 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
746 EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_1X );
747 /* Set LEDs on Audio Dock */
748 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
749 EMU_HANA_DOCK_LEDS_2_48K | EMU_HANA_DOCK_LEDS_2_LOCK );
750 /* Allow DLL to settle */
James Courtier-Duttone40a0b22006-10-10 18:44:29 +0100751 msleep(10);
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100752 /* Unmute all */
753 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
754 break;
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100755
756 case 2: /* Take clock from S/PDIF IN */
757 /* Mute all */
758 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
759 /* Default fallback clock 48kHz */
760 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
761 /* Word Clock source, sync to S/PDIF input */
762 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
763 EMU_HANA_WCLOCK_HANA_SPDIF_IN | EMU_HANA_WCLOCK_1X );
764 /* Set LEDs on Audio Dock */
765 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
766 EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK );
767 /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */
768 /* Allow DLL to settle */
769 msleep(10);
770 /* Unmute all */
771 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
772 break;
773
774 case 3:
775 /* Take clock from ADAT IN */
776 /* Mute all */
777 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
778 /* Default fallback clock 48kHz */
779 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
780 /* Word Clock source, sync to ADAT input */
781 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
782 EMU_HANA_WCLOCK_HANA_ADAT_IN | EMU_HANA_WCLOCK_1X );
783 /* Set LEDs on Audio Dock */
784 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK );
785 /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */
786 /* Allow DLL to settle */
787 msleep(10);
788 /* Unmute all */
789 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
790
791
792 break;
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100793 }
794 }
795 return change;
796}
797
798static struct snd_kcontrol_new snd_emu1010_internal_clock =
799{
800 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
801 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
802 .name = "Clock Internal Rate",
803 .count = 1,
804 .info = snd_emu1010_internal_clock_info,
805 .get = snd_emu1010_internal_clock_get,
806 .put = snd_emu1010_internal_clock_put
807};
808
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000809static int snd_audigy_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
810 struct snd_ctl_elem_info *uinfo)
811{
812#if 0
Takashi Iwai1541c662014-10-20 18:16:48 +0200813 static const char * const texts[4] = {
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000814 "Unknown1", "Unknown2", "Mic", "Line"
815 };
816#endif
Takashi Iwai1541c662014-10-20 18:16:48 +0200817 static const char * const texts[2] = {
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000818 "Mic", "Line"
819 };
820
Takashi Iwai1541c662014-10-20 18:16:48 +0200821 return snd_ctl_enum_info(uinfo, 1, 2, texts);
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000822}
823
824static int snd_audigy_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
825 struct snd_ctl_elem_value *ucontrol)
826{
827 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
828
829 ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
830 return 0;
831}
832
833static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
834 struct snd_ctl_elem_value *ucontrol)
835{
836 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
837 unsigned int source_id;
838 unsigned int ngain, ogain;
839 u32 gpio;
840 int change = 0;
841 unsigned long flags;
842 u32 source;
843 /* If the capture source has changed,
844 * update the capture volume from the cached value
845 * for the particular source.
846 */
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000847 source_id = ucontrol->value.enumerated.item[0];
848 /* Limit: uinfo->value.enumerated.items = 2; */
849 /* emu->i2c_capture_volume */
850 if (source_id >= 2)
851 return -EINVAL;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000852 change = (emu->i2c_capture_source != source_id);
853 if (change) {
854 snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */
855 spin_lock_irqsave(&emu->emu_lock, flags);
856 gpio = inl(emu->port + A_IOCFG);
857 if (source_id==0)
858 outl(gpio | 0x4, emu->port + A_IOCFG);
859 else
860 outl(gpio & ~0x4, emu->port + A_IOCFG);
861 spin_unlock_irqrestore(&emu->emu_lock, flags);
862
863 ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
864 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
865 if (ngain != ogain)
866 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
867 ngain = emu->i2c_capture_volume[source_id][1]; /* Right */
868 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
869 if (ngain != ogain)
870 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
871
872 source = 1 << (source_id + 2);
873 snd_emu10k1_i2c_write(emu, ADC_MUX, source); /* Set source */
874 emu->i2c_capture_source = source_id;
875 }
876 return change;
877}
878
879static struct snd_kcontrol_new snd_audigy_i2c_capture_source =
880{
881 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
882 .name = "Capture Source",
883 .info = snd_audigy_i2c_capture_source_info,
884 .get = snd_audigy_i2c_capture_source_get,
885 .put = snd_audigy_i2c_capture_source_put
886};
887
888static int snd_audigy_i2c_volume_info(struct snd_kcontrol *kcontrol,
889 struct snd_ctl_elem_info *uinfo)
890{
891 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
892 uinfo->count = 2;
893 uinfo->value.integer.min = 0;
894 uinfo->value.integer.max = 255;
895 return 0;
896}
897
898static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol,
899 struct snd_ctl_elem_value *ucontrol)
900{
901 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000902 unsigned int source_id;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000903
904 source_id = kcontrol->private_value;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000905 /* Limit: emu->i2c_capture_volume */
906 /* capture_source: uinfo->value.enumerated.items = 2 */
907 if (source_id >= 2)
908 return -EINVAL;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000909
910 ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
911 ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
912 return 0;
913}
914
915static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
916 struct snd_ctl_elem_value *ucontrol)
917{
918 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
919 unsigned int ogain;
920 unsigned int ngain;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000921 unsigned int source_id;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000922 int change = 0;
923
924 source_id = kcontrol->private_value;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000925 /* Limit: emu->i2c_capture_volume */
926 /* capture_source: uinfo->value.enumerated.items = 2 */
927 if (source_id >= 2)
928 return -EINVAL;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000929 ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
930 ngain = ucontrol->value.integer.value[0];
931 if (ngain > 0xff)
932 return 0;
933 if (ogain != ngain) {
934 if (emu->i2c_capture_source == source_id)
935 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000936 emu->i2c_capture_volume[source_id][0] = ngain;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000937 change = 1;
938 }
939 ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
940 ngain = ucontrol->value.integer.value[1];
941 if (ngain > 0xff)
942 return 0;
943 if (ogain != ngain) {
944 if (emu->i2c_capture_source == source_id)
945 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000946 emu->i2c_capture_volume[source_id][1] = ngain;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000947 change = 1;
948 }
949
950 return change;
951}
952
953#define I2C_VOLUME(xname,chid) \
954{ \
955 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
956 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
957 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
958 .info = snd_audigy_i2c_volume_info, \
959 .get = snd_audigy_i2c_volume_get, \
960 .put = snd_audigy_i2c_volume_put, \
961 .tlv = { .p = snd_audigy_db_scale2 }, \
962 .private_value = chid \
963}
964
965
Bill Pembertone23e7a12012-12-06 12:35:10 -0500966static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] = {
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000967 I2C_VOLUME("Mic Capture Volume", 0),
968 I2C_VOLUME("Line Capture Volume", 0)
969};
970
Takashi Iwai0af68e52005-04-11 17:03:03 +0200971#if 0
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100972static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973{
Takashi Iwai1541c662014-10-20 18:16:48 +0200974 static const char * const texts[] = {"44100", "48000", "96000"};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975
Takashi Iwai1541c662014-10-20 18:16:48 +0200976 return snd_ctl_enum_info(uinfo, 1, 3, texts);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977}
978
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100979static int snd_audigy_spdif_output_rate_get(struct snd_kcontrol *kcontrol,
980 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100982 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 unsigned int tmp;
984 unsigned long flags;
985
986
987 spin_lock_irqsave(&emu->reg_lock, flags);
988 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
989 switch (tmp & A_SPDIF_RATE_MASK) {
990 case A_SPDIF_44100:
991 ucontrol->value.enumerated.item[0] = 0;
992 break;
993 case A_SPDIF_48000:
994 ucontrol->value.enumerated.item[0] = 1;
995 break;
996 case A_SPDIF_96000:
997 ucontrol->value.enumerated.item[0] = 2;
998 break;
999 default:
1000 ucontrol->value.enumerated.item[0] = 1;
1001 }
1002 spin_unlock_irqrestore(&emu->reg_lock, flags);
1003 return 0;
1004}
1005
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001006static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol,
1007 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001009 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 int change;
1011 unsigned int reg, val, tmp;
1012 unsigned long flags;
1013
1014 switch(ucontrol->value.enumerated.item[0]) {
1015 case 0:
1016 val = A_SPDIF_44100;
1017 break;
1018 case 1:
1019 val = A_SPDIF_48000;
1020 break;
1021 case 2:
1022 val = A_SPDIF_96000;
1023 break;
1024 default:
1025 val = A_SPDIF_48000;
1026 break;
1027 }
1028
1029
1030 spin_lock_irqsave(&emu->reg_lock, flags);
1031 reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
1032 tmp = reg & ~A_SPDIF_RATE_MASK;
1033 tmp |= val;
1034 if ((change = (tmp != reg)))
1035 snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
1036 spin_unlock_irqrestore(&emu->reg_lock, flags);
1037 return change;
1038}
1039
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001040static struct snd_kcontrol_new snd_audigy_spdif_output_rate =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041{
1042 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1043 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1044 .name = "Audigy SPDIF Output Sample Rate",
1045 .count = 1,
1046 .info = snd_audigy_spdif_output_rate_info,
1047 .get = snd_audigy_spdif_output_rate_get,
1048 .put = snd_audigy_spdif_output_rate_put
1049};
Takashi Iwai0af68e52005-04-11 17:03:03 +02001050#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001052static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol,
1053 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001055 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1057 int change;
1058 unsigned int val;
1059 unsigned long flags;
1060
James Courtier-Dutton74415a32007-11-12 14:55:19 +00001061 /* Limit: emu->spdif_bits */
1062 if (idx >= 3)
1063 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 val = (ucontrol->value.iec958.status[0] << 0) |
1065 (ucontrol->value.iec958.status[1] << 8) |
1066 (ucontrol->value.iec958.status[2] << 16) |
1067 (ucontrol->value.iec958.status[3] << 24);
1068 spin_lock_irqsave(&emu->reg_lock, flags);
1069 change = val != emu->spdif_bits[idx];
1070 if (change) {
1071 snd_emu10k1_ptr_write(emu, SPCS0 + idx, 0, val);
1072 emu->spdif_bits[idx] = val;
1073 }
1074 spin_unlock_irqrestore(&emu->reg_lock, flags);
1075 return change;
1076}
1077
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001078static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079{
1080 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +02001081 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
Takashi Iwai7583cb52007-08-16 19:32:16 +02001083 .count = 3,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 .info = snd_emu10k1_spdif_info,
1085 .get = snd_emu10k1_spdif_get_mask
1086};
1087
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001088static struct snd_kcontrol_new snd_emu10k1_spdif_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089{
Clemens Ladisch5549d542005-08-03 13:50:30 +02001090 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
Takashi Iwai7583cb52007-08-16 19:32:16 +02001092 .count = 3,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 .info = snd_emu10k1_spdif_info,
1094 .get = snd_emu10k1_spdif_get,
1095 .put = snd_emu10k1_spdif_put
1096};
1097
1098
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001099static void update_emu10k1_fxrt(struct snd_emu10k1 *emu, int voice, unsigned char *route)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100{
1101 if (emu->audigy) {
1102 snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
1103 snd_emu10k1_compose_audigy_fxrt1(route));
1104 snd_emu10k1_ptr_write(emu, A_FXRT2, voice,
1105 snd_emu10k1_compose_audigy_fxrt2(route));
1106 } else {
1107 snd_emu10k1_ptr_write(emu, FXRT, voice,
1108 snd_emu10k1_compose_send_routing(route));
1109 }
1110}
1111
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001112static void update_emu10k1_send_volume(struct snd_emu10k1 *emu, int voice, unsigned char *volume)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113{
1114 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]);
1115 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]);
1116 snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, volume[2]);
1117 snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, volume[3]);
1118 if (emu->audigy) {
1119 unsigned int val = ((unsigned int)volume[4] << 24) |
1120 ((unsigned int)volume[5] << 16) |
1121 ((unsigned int)volume[6] << 8) |
1122 (unsigned int)volume[7];
1123 snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, val);
1124 }
1125}
1126
1127/* PCM stream controls */
1128
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001129static int snd_emu10k1_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001131 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1133 uinfo->count = emu->audigy ? 3*8 : 3*4;
1134 uinfo->value.integer.min = 0;
1135 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
1136 return 0;
1137}
1138
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001139static int snd_emu10k1_send_routing_get(struct snd_kcontrol *kcontrol,
1140 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141{
1142 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001143 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1144 struct snd_emu10k1_pcm_mixer *mix =
1145 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 int voice, idx;
1147 int num_efx = emu->audigy ? 8 : 4;
1148 int mask = emu->audigy ? 0x3f : 0x0f;
1149
1150 spin_lock_irqsave(&emu->reg_lock, flags);
1151 for (voice = 0; voice < 3; voice++)
1152 for (idx = 0; idx < num_efx; idx++)
1153 ucontrol->value.integer.value[(voice * num_efx) + idx] =
1154 mix->send_routing[voice][idx] & mask;
1155 spin_unlock_irqrestore(&emu->reg_lock, flags);
1156 return 0;
1157}
1158
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001159static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol,
1160 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161{
1162 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001163 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1164 struct snd_emu10k1_pcm_mixer *mix =
1165 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 int change = 0, voice, idx, val;
1167 int num_efx = emu->audigy ? 8 : 4;
1168 int mask = emu->audigy ? 0x3f : 0x0f;
1169
1170 spin_lock_irqsave(&emu->reg_lock, flags);
1171 for (voice = 0; voice < 3; voice++)
1172 for (idx = 0; idx < num_efx; idx++) {
1173 val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask;
1174 if (mix->send_routing[voice][idx] != val) {
1175 mix->send_routing[voice][idx] = val;
1176 change = 1;
1177 }
1178 }
1179 if (change && mix->epcm) {
1180 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1181 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
1182 &mix->send_routing[1][0]);
1183 update_emu10k1_fxrt(emu, mix->epcm->voices[1]->number,
1184 &mix->send_routing[2][0]);
1185 } else if (mix->epcm->voices[0]) {
1186 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
1187 &mix->send_routing[0][0]);
1188 }
1189 }
1190 spin_unlock_irqrestore(&emu->reg_lock, flags);
1191 return change;
1192}
1193
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001194static struct snd_kcontrol_new snd_emu10k1_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195{
1196 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001197 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 .name = "EMU10K1 PCM Send Routing",
1199 .count = 32,
1200 .info = snd_emu10k1_send_routing_info,
1201 .get = snd_emu10k1_send_routing_get,
1202 .put = snd_emu10k1_send_routing_put
1203};
1204
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001205static int snd_emu10k1_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001207 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1209 uinfo->count = emu->audigy ? 3*8 : 3*4;
1210 uinfo->value.integer.min = 0;
1211 uinfo->value.integer.max = 255;
1212 return 0;
1213}
1214
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001215static int snd_emu10k1_send_volume_get(struct snd_kcontrol *kcontrol,
1216 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217{
1218 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001219 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1220 struct snd_emu10k1_pcm_mixer *mix =
1221 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 int idx;
1223 int num_efx = emu->audigy ? 8 : 4;
1224
1225 spin_lock_irqsave(&emu->reg_lock, flags);
1226 for (idx = 0; idx < 3*num_efx; idx++)
1227 ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx];
1228 spin_unlock_irqrestore(&emu->reg_lock, flags);
1229 return 0;
1230}
1231
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001232static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol,
1233 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234{
1235 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001236 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1237 struct snd_emu10k1_pcm_mixer *mix =
1238 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 int change = 0, idx, val;
1240 int num_efx = emu->audigy ? 8 : 4;
1241
1242 spin_lock_irqsave(&emu->reg_lock, flags);
1243 for (idx = 0; idx < 3*num_efx; idx++) {
1244 val = ucontrol->value.integer.value[idx] & 255;
1245 if (mix->send_volume[idx/num_efx][idx%num_efx] != val) {
1246 mix->send_volume[idx/num_efx][idx%num_efx] = val;
1247 change = 1;
1248 }
1249 }
1250 if (change && mix->epcm) {
1251 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1252 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
1253 &mix->send_volume[1][0]);
1254 update_emu10k1_send_volume(emu, mix->epcm->voices[1]->number,
1255 &mix->send_volume[2][0]);
1256 } else if (mix->epcm->voices[0]) {
1257 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
1258 &mix->send_volume[0][0]);
1259 }
1260 }
1261 spin_unlock_irqrestore(&emu->reg_lock, flags);
1262 return change;
1263}
1264
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001265static struct snd_kcontrol_new snd_emu10k1_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266{
1267 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001268 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269 .name = "EMU10K1 PCM Send Volume",
1270 .count = 32,
1271 .info = snd_emu10k1_send_volume_info,
1272 .get = snd_emu10k1_send_volume_get,
1273 .put = snd_emu10k1_send_volume_put
1274};
1275
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001276static int snd_emu10k1_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277{
1278 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1279 uinfo->count = 3;
1280 uinfo->value.integer.min = 0;
1281 uinfo->value.integer.max = 0xffff;
1282 return 0;
1283}
1284
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001285static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol,
1286 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001288 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1289 struct snd_emu10k1_pcm_mixer *mix =
1290 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 unsigned long flags;
1292 int idx;
1293
1294 spin_lock_irqsave(&emu->reg_lock, flags);
1295 for (idx = 0; idx < 3; idx++)
1296 ucontrol->value.integer.value[idx] = mix->attn[idx];
1297 spin_unlock_irqrestore(&emu->reg_lock, flags);
1298 return 0;
1299}
1300
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001301static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol,
1302 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303{
1304 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001305 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1306 struct snd_emu10k1_pcm_mixer *mix =
1307 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 int change = 0, idx, val;
1309
1310 spin_lock_irqsave(&emu->reg_lock, flags);
1311 for (idx = 0; idx < 3; idx++) {
1312 val = ucontrol->value.integer.value[idx] & 0xffff;
1313 if (mix->attn[idx] != val) {
1314 mix->attn[idx] = val;
1315 change = 1;
1316 }
1317 }
1318 if (change && mix->epcm) {
1319 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1320 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[1]);
1321 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[1]->number, mix->attn[2]);
1322 } else if (mix->epcm->voices[0]) {
1323 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]);
1324 }
1325 }
1326 spin_unlock_irqrestore(&emu->reg_lock, flags);
1327 return change;
1328}
1329
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001330static struct snd_kcontrol_new snd_emu10k1_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331{
1332 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001333 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 .name = "EMU10K1 PCM Volume",
1335 .count = 32,
1336 .info = snd_emu10k1_attn_info,
1337 .get = snd_emu10k1_attn_get,
1338 .put = snd_emu10k1_attn_put
1339};
1340
1341/* Mutichannel PCM stream controls */
1342
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001343static int snd_emu10k1_efx_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001345 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1347 uinfo->count = emu->audigy ? 8 : 4;
1348 uinfo->value.integer.min = 0;
1349 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
1350 return 0;
1351}
1352
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001353static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol,
1354 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355{
1356 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001357 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1358 struct snd_emu10k1_pcm_mixer *mix =
1359 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 int idx;
1361 int num_efx = emu->audigy ? 8 : 4;
1362 int mask = emu->audigy ? 0x3f : 0x0f;
1363
1364 spin_lock_irqsave(&emu->reg_lock, flags);
1365 for (idx = 0; idx < num_efx; idx++)
1366 ucontrol->value.integer.value[idx] =
1367 mix->send_routing[0][idx] & mask;
1368 spin_unlock_irqrestore(&emu->reg_lock, flags);
1369 return 0;
1370}
1371
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001372static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol,
1373 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374{
1375 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001376 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001378 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 int change = 0, idx, val;
1380 int num_efx = emu->audigy ? 8 : 4;
1381 int mask = emu->audigy ? 0x3f : 0x0f;
1382
1383 spin_lock_irqsave(&emu->reg_lock, flags);
1384 for (idx = 0; idx < num_efx; idx++) {
1385 val = ucontrol->value.integer.value[idx] & mask;
1386 if (mix->send_routing[0][idx] != val) {
1387 mix->send_routing[0][idx] = val;
1388 change = 1;
1389 }
1390 }
1391
1392 if (change && mix->epcm) {
1393 if (mix->epcm->voices[ch]) {
1394 update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number,
1395 &mix->send_routing[0][0]);
1396 }
1397 }
1398 spin_unlock_irqrestore(&emu->reg_lock, flags);
1399 return change;
1400}
1401
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001402static struct snd_kcontrol_new snd_emu10k1_efx_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403{
1404 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1405 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1406 .name = "Multichannel PCM Send Routing",
1407 .count = 16,
1408 .info = snd_emu10k1_efx_send_routing_info,
1409 .get = snd_emu10k1_efx_send_routing_get,
1410 .put = snd_emu10k1_efx_send_routing_put
1411};
1412
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001413static int snd_emu10k1_efx_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001415 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1417 uinfo->count = emu->audigy ? 8 : 4;
1418 uinfo->value.integer.min = 0;
1419 uinfo->value.integer.max = 255;
1420 return 0;
1421}
1422
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001423static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol,
1424 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425{
1426 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001427 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1428 struct snd_emu10k1_pcm_mixer *mix =
1429 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430 int idx;
1431 int num_efx = emu->audigy ? 8 : 4;
1432
1433 spin_lock_irqsave(&emu->reg_lock, flags);
1434 for (idx = 0; idx < num_efx; idx++)
1435 ucontrol->value.integer.value[idx] = mix->send_volume[0][idx];
1436 spin_unlock_irqrestore(&emu->reg_lock, flags);
1437 return 0;
1438}
1439
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001440static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol,
1441 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442{
1443 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001444 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001446 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 int change = 0, idx, val;
1448 int num_efx = emu->audigy ? 8 : 4;
1449
1450 spin_lock_irqsave(&emu->reg_lock, flags);
1451 for (idx = 0; idx < num_efx; idx++) {
1452 val = ucontrol->value.integer.value[idx] & 255;
1453 if (mix->send_volume[0][idx] != val) {
1454 mix->send_volume[0][idx] = val;
1455 change = 1;
1456 }
1457 }
1458 if (change && mix->epcm) {
1459 if (mix->epcm->voices[ch]) {
1460 update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number,
1461 &mix->send_volume[0][0]);
1462 }
1463 }
1464 spin_unlock_irqrestore(&emu->reg_lock, flags);
1465 return change;
1466}
1467
1468
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001469static struct snd_kcontrol_new snd_emu10k1_efx_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470{
1471 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1472 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1473 .name = "Multichannel PCM Send Volume",
1474 .count = 16,
1475 .info = snd_emu10k1_efx_send_volume_info,
1476 .get = snd_emu10k1_efx_send_volume_get,
1477 .put = snd_emu10k1_efx_send_volume_put
1478};
1479
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001480static int snd_emu10k1_efx_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481{
1482 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1483 uinfo->count = 1;
1484 uinfo->value.integer.min = 0;
1485 uinfo->value.integer.max = 0xffff;
1486 return 0;
1487}
1488
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001489static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol,
1490 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001492 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1493 struct snd_emu10k1_pcm_mixer *mix =
1494 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 unsigned long flags;
1496
1497 spin_lock_irqsave(&emu->reg_lock, flags);
1498 ucontrol->value.integer.value[0] = mix->attn[0];
1499 spin_unlock_irqrestore(&emu->reg_lock, flags);
1500 return 0;
1501}
1502
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001503static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol,
1504 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505{
1506 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001507 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001509 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 int change = 0, val;
1511
1512 spin_lock_irqsave(&emu->reg_lock, flags);
1513 val = ucontrol->value.integer.value[0] & 0xffff;
1514 if (mix->attn[0] != val) {
1515 mix->attn[0] = val;
1516 change = 1;
1517 }
1518 if (change && mix->epcm) {
1519 if (mix->epcm->voices[ch]) {
1520 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]);
1521 }
1522 }
1523 spin_unlock_irqrestore(&emu->reg_lock, flags);
1524 return change;
1525}
1526
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001527static struct snd_kcontrol_new snd_emu10k1_efx_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528{
1529 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1530 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1531 .name = "Multichannel PCM Volume",
1532 .count = 16,
1533 .info = snd_emu10k1_efx_attn_info,
1534 .get = snd_emu10k1_efx_attn_get,
1535 .put = snd_emu10k1_efx_attn_put
1536};
1537
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001538#define snd_emu10k1_shared_spdif_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001540static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol,
1541 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001543 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544
1545 if (emu->audigy)
1546 ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0;
1547 else
1548 ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0;
Takashi Iwaid2cd74b2008-06-02 11:45:53 +02001549 if (emu->card_capabilities->invert_shared_spdif)
1550 ucontrol->value.integer.value[0] =
1551 !ucontrol->value.integer.value[0];
1552
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 return 0;
1554}
1555
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001556static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
1557 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558{
1559 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001560 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Takashi Iwaid2cd74b2008-06-02 11:45:53 +02001561 unsigned int reg, val, sw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 int change = 0;
1563
Takashi Iwaid2cd74b2008-06-02 11:45:53 +02001564 sw = ucontrol->value.integer.value[0];
1565 if (emu->card_capabilities->invert_shared_spdif)
1566 sw = !sw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 spin_lock_irqsave(&emu->reg_lock, flags);
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001568 if ( emu->card_capabilities->i2c_adc) {
1569 /* Do nothing for Audigy 2 ZS Notebook */
1570 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571 reg = inl(emu->port + A_IOCFG);
Takashi Iwaid2cd74b2008-06-02 11:45:53 +02001572 val = sw ? A_IOCFG_GPOUT0 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 change = (reg & A_IOCFG_GPOUT0) != val;
1574 if (change) {
1575 reg &= ~A_IOCFG_GPOUT0;
1576 reg |= val;
1577 outl(reg | val, emu->port + A_IOCFG);
1578 }
1579 }
1580 reg = inl(emu->port + HCFG);
Takashi Iwaid2cd74b2008-06-02 11:45:53 +02001581 val = sw ? HCFG_GPOUT0 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 change |= (reg & HCFG_GPOUT0) != val;
1583 if (change) {
1584 reg &= ~HCFG_GPOUT0;
1585 reg |= val;
1586 outl(reg | val, emu->port + HCFG);
1587 }
1588 spin_unlock_irqrestore(&emu->reg_lock, flags);
1589 return change;
1590}
1591
Bill Pembertone23e7a12012-12-06 12:35:10 -05001592static struct snd_kcontrol_new snd_emu10k1_shared_spdif =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593{
1594 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1595 .name = "SB Live Analog/Digital Output Jack",
1596 .info = snd_emu10k1_shared_spdif_info,
1597 .get = snd_emu10k1_shared_spdif_get,
1598 .put = snd_emu10k1_shared_spdif_put
1599};
1600
Bill Pembertone23e7a12012-12-06 12:35:10 -05001601static struct snd_kcontrol_new snd_audigy_shared_spdif =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602{
1603 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1604 .name = "Audigy Analog/Digital Output Jack",
1605 .info = snd_emu10k1_shared_spdif_info,
1606 .get = snd_emu10k1_shared_spdif_get,
1607 .put = snd_emu10k1_shared_spdif_put
1608};
1609
Takashi Iwai16950e02008-12-02 09:31:16 +01001610/* workaround for too low volume on Audigy due to 16bit/24bit conversion */
1611
1612#define snd_audigy_capture_boost_info snd_ctl_boolean_mono_info
1613
1614static int snd_audigy_capture_boost_get(struct snd_kcontrol *kcontrol,
1615 struct snd_ctl_elem_value *ucontrol)
1616{
1617 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1618 unsigned int val;
1619
1620 /* FIXME: better to use a cached version */
1621 val = snd_ac97_read(emu->ac97, AC97_REC_GAIN);
1622 ucontrol->value.integer.value[0] = !!val;
1623 return 0;
1624}
1625
1626static int snd_audigy_capture_boost_put(struct snd_kcontrol *kcontrol,
1627 struct snd_ctl_elem_value *ucontrol)
1628{
1629 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1630 unsigned int val;
1631
1632 if (ucontrol->value.integer.value[0])
1633 val = 0x0f0f;
1634 else
1635 val = 0;
1636 return snd_ac97_update(emu->ac97, AC97_REC_GAIN, val);
1637}
1638
Bill Pembertone23e7a12012-12-06 12:35:10 -05001639static struct snd_kcontrol_new snd_audigy_capture_boost =
Takashi Iwai16950e02008-12-02 09:31:16 +01001640{
1641 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1642 .name = "Analog Capture Boost",
1643 .info = snd_audigy_capture_boost_info,
1644 .get = snd_audigy_capture_boost_get,
1645 .put = snd_audigy_capture_boost_put
1646};
1647
1648
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649/*
1650 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001651static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001653 struct snd_emu10k1 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 emu->ac97 = NULL;
1655}
1656
1657/*
1658 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001659static int remove_ctl(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001661 struct snd_ctl_elem_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 memset(&id, 0, sizeof(id));
1663 strcpy(id.name, name);
1664 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1665 return snd_ctl_remove_id(card, &id);
1666}
1667
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001668static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001670 struct snd_ctl_elem_id sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 memset(&sid, 0, sizeof(sid));
1672 strcpy(sid.name, name);
1673 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1674 return snd_ctl_find_id(card, &sid);
1675}
1676
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001677static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001679 struct snd_kcontrol *kctl = ctl_find(card, src);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680 if (kctl) {
1681 strcpy(kctl->id.name, dst);
1682 return 0;
1683 }
1684 return -ENOENT;
1685}
1686
Bill Pembertone23e7a12012-12-06 12:35:10 -05001687int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
1688 int pcm_device, int multi_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689{
1690 int err, pcm;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001691 struct snd_kcontrol *kctl;
1692 struct snd_card *card = emu->card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 char **c;
1694 static char *emu10k1_remove_ctls[] = {
1695 /* no AC97 mono, surround, center/lfe */
1696 "Master Mono Playback Switch",
1697 "Master Mono Playback Volume",
1698 "PCM Out Path & Mute",
1699 "Mono Output Select",
1700 "Surround Playback Switch",
1701 "Surround Playback Volume",
1702 "Center Playback Switch",
1703 "Center Playback Volume",
1704 "LFE Playback Switch",
1705 "LFE Playback Volume",
1706 NULL
1707 };
1708 static char *emu10k1_rename_ctls[] = {
1709 "Surround Digital Playback Volume", "Surround Playback Volume",
1710 "Center Digital Playback Volume", "Center Playback Volume",
1711 "LFE Digital Playback Volume", "LFE Playback Volume",
1712 NULL
1713 };
1714 static char *audigy_remove_ctls[] = {
1715 /* Master/PCM controls on ac97 of Audigy has no effect */
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001716 /* On the Audigy2 the AC97 playback is piped into
1717 * the Philips ADC for 24bit capture */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718 "PCM Playback Switch",
1719 "PCM Playback Volume",
1720 "Master Mono Playback Switch",
1721 "Master Mono Playback Volume",
1722 "Master Playback Switch",
1723 "Master Playback Volume",
1724 "PCM Out Path & Mute",
1725 "Mono Output Select",
1726 /* remove unused AC97 capture controls */
1727 "Capture Source",
1728 "Capture Switch",
1729 "Capture Volume",
1730 "Mic Select",
1731 "Video Playback Switch",
1732 "Video Playback Volume",
1733 "Mic Playback Switch",
1734 "Mic Playback Volume",
1735 NULL
1736 };
1737 static char *audigy_rename_ctls[] = {
1738 /* use conventional names */
1739 "Wave Playback Volume", "PCM Playback Volume",
1740 /* "Wave Capture Volume", "PCM Capture Volume", */
1741 "Wave Master Playback Volume", "Master Playback Volume",
1742 "AMic Playback Volume", "Mic Playback Volume",
1743 NULL
1744 };
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001745 static char *audigy_rename_ctls_i2c_adc[] = {
1746 //"Analog Mix Capture Volume","OLD Analog Mix Capture Volume",
1747 "Line Capture Volume", "Analog Mix Capture Volume",
1748 "Wave Playback Volume", "OLD PCM Playback Volume",
1749 "Wave Master Playback Volume", "Master Playback Volume",
1750 "AMic Playback Volume", "Old Mic Playback Volume",
James Courtier-Duttoneb41dab2006-12-06 20:38:45 +00001751 "CD Capture Volume", "IEC958 Optical Capture Volume",
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001752 NULL
1753 };
1754 static char *audigy_remove_ctls_i2c_adc[] = {
1755 /* On the Audigy2 ZS Notebook
1756 * Capture via WM8775 */
1757 "Mic Capture Volume",
1758 "Analog Mix Capture Volume",
1759 "Aux Capture Volume",
James Courtier-Duttoneb41dab2006-12-06 20:38:45 +00001760 "IEC958 Optical Capture Volume",
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001761 NULL
1762 };
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001763 static char *audigy_remove_ctls_1361t_adc[] = {
1764 /* On the Audigy2 the AC97 playback is piped into
1765 * the Philips ADC for 24bit capture */
1766 "PCM Playback Switch",
1767 "PCM Playback Volume",
1768 "Master Mono Playback Switch",
1769 "Master Mono Playback Volume",
1770 "Capture Source",
1771 "Capture Switch",
1772 "Capture Volume",
1773 "Mic Capture Volume",
1774 "Headphone Playback Switch",
1775 "Headphone Playback Volume",
1776 "3D Control - Center",
1777 "3D Control - Depth",
1778 "3D Control - Switch",
1779 "Line2 Playback Volume",
1780 "Line2 Capture Volume",
1781 NULL
1782 };
1783 static char *audigy_rename_ctls_1361t_adc[] = {
1784 "Master Playback Switch", "Master Capture Switch",
1785 "Master Playback Volume", "Master Capture Volume",
1786 "Wave Master Playback Volume", "Master Playback Volume",
Jaroslav Kyselad355c82a2009-11-03 15:47:25 +01001787 "Beep Playback Switch", "Beep Capture Switch",
1788 "Beep Playback Volume", "Beep Capture Volume",
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001789 "Phone Playback Switch", "Phone Capture Switch",
1790 "Phone Playback Volume", "Phone Capture Volume",
1791 "Mic Playback Switch", "Mic Capture Switch",
1792 "Mic Playback Volume", "Mic Capture Volume",
1793 "Line Playback Switch", "Line Capture Switch",
1794 "Line Playback Volume", "Line Capture Volume",
1795 "CD Playback Switch", "CD Capture Switch",
1796 "CD Playback Volume", "CD Capture Volume",
1797 "Aux Playback Switch", "Aux Capture Switch",
1798 "Aux Playback Volume", "Aux Capture Volume",
1799 "Video Playback Switch", "Video Capture Switch",
1800 "Video Playback Volume", "Video Capture Volume",
1801
1802 NULL
1803 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804
Lee Revell2b637da2005-03-30 13:51:18 +02001805 if (emu->card_capabilities->ac97_chip) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001806 struct snd_ac97_bus *pbus;
1807 struct snd_ac97_template ac97;
1808 static struct snd_ac97_bus_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 .write = snd_emu10k1_ac97_write,
1810 .read = snd_emu10k1_ac97_read,
1811 };
1812
Takashi Iwaib1508692005-10-04 13:49:32 +02001813 if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0)
1814 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 pbus->no_vra = 1; /* we don't need VRA */
1816
1817 memset(&ac97, 0, sizeof(ac97));
1818 ac97.private_data = emu;
1819 ac97.private_free = snd_emu10k1_mixer_free_ac97;
1820 ac97.scaps = AC97_SCAP_NO_SPDIF;
Takashi Iwaib1508692005-10-04 13:49:32 +02001821 if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) {
1822 if (emu->card_capabilities->ac97_chip == 1)
1823 return err;
Takashi Iwai6f002b02014-02-25 17:02:09 +01001824 dev_info(emu->card->dev,
1825 "AC97 is optional on this board\n");
1826 dev_info(emu->card->dev,
1827 "Proceeding without ac97 mixers...\n");
Takashi Iwaib1508692005-10-04 13:49:32 +02001828 snd_device_free(emu->card, pbus);
1829 goto no_ac97; /* FIXME: get rid of ugly gotos.. */
1830 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 if (emu->audigy) {
1832 /* set master volume to 0 dB */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001833 snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 /* set capture source to mic */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001835 snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001836 if (emu->card_capabilities->adc_1361t)
1837 c = audigy_remove_ctls_1361t_adc;
1838 else
1839 c = audigy_remove_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001840 } else {
1841 /*
1842 * Credits for cards based on STAC9758:
1843 * James Courtier-Dutton <James@superbug.demon.co.uk>
1844 * Voluspa <voluspa@comhem.se>
1845 */
1846 if (emu->ac97->id == AC97_ID_STAC9758) {
1847 emu->rear_ac97 = 1;
1848 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 +01001849 snd_ac97_write_cache(emu->ac97, AC97_HEADPHONE, 0x0202);
Raymond Yaub6a48402011-04-15 11:42:42 +08001850 remove_ctl(card,"Front Playback Volume");
1851 remove_ctl(card,"Front Playback Switch");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 }
1853 /* remove unused AC97 controls */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001854 snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
1855 snd_ac97_write_cache(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856 c = emu10k1_remove_ctls;
1857 }
1858 for (; *c; c++)
1859 remove_ctl(card, *c);
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001860 } else if (emu->card_capabilities->i2c_adc) {
1861 c = audigy_remove_ctls_i2c_adc;
1862 for (; *c; c++)
1863 remove_ctl(card, *c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864 } else {
Takashi Iwaif12aa402005-09-30 16:56:59 +02001865 no_ac97:
Lee Revell2b637da2005-03-30 13:51:18 +02001866 if (emu->card_capabilities->ecard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867 strcpy(emu->card->mixername, "EMU APS");
1868 else if (emu->audigy)
1869 strcpy(emu->card->mixername, "SB Audigy");
1870 else
1871 strcpy(emu->card->mixername, "Emu10k1");
1872 }
1873
1874 if (emu->audigy)
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001875 if (emu->card_capabilities->adc_1361t)
1876 c = audigy_rename_ctls_1361t_adc;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001877 else if (emu->card_capabilities->i2c_adc)
1878 c = audigy_rename_ctls_i2c_adc;
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001879 else
1880 c = audigy_rename_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881 else
1882 c = emu10k1_rename_ctls;
1883 for (; *c; c += 2)
1884 rename_ctl(card, c[0], c[1]);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001885
Raymond Yaue217b962011-03-30 20:00:39 +08001886 if (emu->card_capabilities->subsystem == 0x80401102) { /* SB Live! Platinum CT4760P */
1887 remove_ctl(card, "Center Playback Volume");
1888 remove_ctl(card, "LFE Playback Volume");
1889 remove_ctl(card, "Wave Center Playback Volume");
1890 remove_ctl(card, "Wave LFE Playback Volume");
1891 }
James Courtier-Duttone3b9bc02005-12-24 16:54:51 +01001892 if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */
1893 rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume");
1894 rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume");
1895 rename_ctl(card, "Aux2 Capture Volume", "Line3 Capture Volume");
1896 rename_ctl(card, "Mic Capture Volume", "Unknown1 Capture Volume");
1897 remove_ctl(card, "Headphone Playback Switch");
1898 remove_ctl(card, "Headphone Playback Volume");
1899 remove_ctl(card, "3D Control - Center");
1900 remove_ctl(card, "3D Control - Depth");
1901 remove_ctl(card, "3D Control - Switch");
1902 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL)
1904 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001905 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906 if ((err = snd_ctl_add(card, kctl)))
1907 return err;
1908 if ((kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL)
1909 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001910 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 if ((err = snd_ctl_add(card, kctl)))
1912 return err;
1913 if ((kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu)) == NULL)
1914 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001915 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 if ((err = snd_ctl_add(card, kctl)))
1917 return err;
1918
1919 if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL)
1920 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001921 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922 if ((err = snd_ctl_add(card, kctl)))
1923 return err;
1924
1925 if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL)
1926 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001927 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928 if ((err = snd_ctl_add(card, kctl)))
1929 return err;
1930
1931 if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL)
1932 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001933 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934 if ((err = snd_ctl_add(card, kctl)))
1935 return err;
1936
1937 /* initialize the routing and volume table for each pcm playback stream */
1938 for (pcm = 0; pcm < 32; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001939 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940 int v;
1941
1942 mix = &emu->pcm_mixer[pcm];
1943 mix->epcm = NULL;
1944
1945 for (v = 0; v < 4; v++)
1946 mix->send_routing[0][v] =
1947 mix->send_routing[1][v] =
1948 mix->send_routing[2][v] = v;
1949
1950 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1951 mix->send_volume[0][0] = mix->send_volume[0][1] =
1952 mix->send_volume[1][0] = mix->send_volume[2][1] = 255;
1953
1954 mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
1955 }
1956
1957 /* initialize the routing and volume table for the multichannel playback stream */
1958 for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001959 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 int v;
1961
1962 mix = &emu->efx_pcm_mixer[pcm];
1963 mix->epcm = NULL;
1964
1965 mix->send_routing[0][0] = pcm;
1966 mix->send_routing[0][1] = (pcm == 0) ? 1 : 0;
1967 for (v = 0; v < 2; v++)
1968 mix->send_routing[0][2+v] = 13+v;
1969 if (emu->audigy)
1970 for (v = 0; v < 4; v++)
1971 mix->send_routing[0][4+v] = 60+v;
1972
1973 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1974 mix->send_volume[0][0] = 255;
1975
1976 mix->attn[0] = 0xffff;
1977 }
1978
Lee Revell2b637da2005-03-30 13:51:18 +02001979 if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980 /* sb live! and audigy */
1981 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
1982 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02001983 if (!emu->audigy)
1984 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 if ((err = snd_ctl_add(card, kctl)))
1986 return err;
1987 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
1988 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02001989 if (!emu->audigy)
1990 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001991 if ((err = snd_ctl_add(card, kctl)))
1992 return err;
1993 }
1994
James Courtier-Dutton190d2c42007-11-04 14:08:26 +00001995 if (emu->card_capabilities->emu_model) {
James Courtier-Dutton19b99fb2005-12-04 18:03:03 +01001996 ; /* Disable the snd_audigy_spdif_shared_spdif */
1997 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001998 if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
1999 return -ENOMEM;
2000 if ((err = snd_ctl_add(card, kctl)))
2001 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02002002#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003 if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
2004 return -ENOMEM;
2005 if ((err = snd_ctl_add(card, kctl)))
2006 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02002007#endif
Lee Revell2b637da2005-03-30 13:51:18 +02002008 } else if (! emu->card_capabilities->ecard) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002009 /* sb live! */
2010 if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
2011 return -ENOMEM;
2012 if ((err = snd_ctl_add(card, kctl)))
2013 return err;
2014 }
Lee Revell2b637da2005-03-30 13:51:18 +02002015 if (emu->card_capabilities->ca0151_chip) { /* P16V */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016 if ((err = snd_p16v_mixer(emu)))
2017 return err;
2018 }
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01002019
Takashi Iwai3839e4f2007-12-21 16:33:32 +01002020 if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) {
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002021 /* 1616(m) cardbus */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01002022 int i;
2023
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002024 for (i = 0; i < ARRAY_SIZE(snd_emu1616_output_enum_ctls); i++) {
2025 err = snd_ctl_add(card,
2026 snd_ctl_new1(&snd_emu1616_output_enum_ctls[i],
2027 emu));
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01002028 if (err < 0)
2029 return err;
2030 }
2031 for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) {
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002032 err = snd_ctl_add(card,
2033 snd_ctl_new1(&snd_emu1010_input_enum_ctls[i],
2034 emu));
2035 if (err < 0)
2036 return err;
2037 }
2038 for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads) - 2; i++) {
2039 err = snd_ctl_add(card,
2040 snd_ctl_new1(&snd_emu1010_adc_pads[i], emu));
2041 if (err < 0)
2042 return err;
2043 }
2044 for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads) - 2; i++) {
2045 err = snd_ctl_add(card,
2046 snd_ctl_new1(&snd_emu1010_dac_pads[i], emu));
2047 if (err < 0)
2048 return err;
2049 }
2050 err = snd_ctl_add(card,
2051 snd_ctl_new1(&snd_emu1010_internal_clock, emu));
2052 if (err < 0)
2053 return err;
2054
Takashi Iwai88aa1392007-12-21 16:20:12 +01002055 } else if (emu->card_capabilities->emu_model) {
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002056 /* all other e-mu cards for now */
2057 int i;
2058
2059 for (i = 0; i < ARRAY_SIZE(snd_emu1010_output_enum_ctls); i++) {
2060 err = snd_ctl_add(card,
2061 snd_ctl_new1(&snd_emu1010_output_enum_ctls[i],
2062 emu));
2063 if (err < 0)
2064 return err;
2065 }
2066 for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) {
2067 err = snd_ctl_add(card,
2068 snd_ctl_new1(&snd_emu1010_input_enum_ctls[i],
2069 emu));
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01002070 if (err < 0)
2071 return err;
2072 }
James Courtier-Dutton9148cc52006-10-09 23:08:00 +01002073 for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads); i++) {
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002074 err = snd_ctl_add(card,
2075 snd_ctl_new1(&snd_emu1010_adc_pads[i], emu));
James Courtier-Dutton9148cc52006-10-09 23:08:00 +01002076 if (err < 0)
2077 return err;
2078 }
2079 for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads); i++) {
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002080 err = snd_ctl_add(card,
2081 snd_ctl_new1(&snd_emu1010_dac_pads[i], emu));
James Courtier-Dutton9148cc52006-10-09 23:08:00 +01002082 if (err < 0)
2083 return err;
2084 }
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002085 err = snd_ctl_add(card,
2086 snd_ctl_new1(&snd_emu1010_internal_clock, emu));
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +01002087 if (err < 0)
2088 return err;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01002089 }
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00002090
2091 if ( emu->card_capabilities->i2c_adc) {
2092 int i;
2093
2094 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_capture_source, emu));
2095 if (err < 0)
2096 return err;
2097
2098 for (i = 0; i < ARRAY_SIZE(snd_audigy_i2c_volume_ctls); i++) {
2099 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_volume_ctls[i], emu));
2100 if (err < 0)
2101 return err;
2102 }
2103 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104
Takashi Iwai16950e02008-12-02 09:31:16 +01002105 if (emu->card_capabilities->ac97_chip && emu->audigy) {
2106 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_capture_boost,
2107 emu));
2108 if (err < 0)
2109 return err;
2110 }
2111
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112 return 0;
2113}