blob: 55e57166256e99fa43d545c23200675c5aeea31b [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
Michael Gernoth99dcab42015-04-11 18:00:19 +0200809static int snd_emu1010_optical_out_info(struct snd_kcontrol *kcontrol,
810 struct snd_ctl_elem_info *uinfo)
811{
812 static const char * const texts[2] = {
813 "SPDIF", "ADAT"
814 };
815
816 return snd_ctl_enum_info(uinfo, 1, 2, texts);
817}
818
819static int snd_emu1010_optical_out_get(struct snd_kcontrol *kcontrol,
820 struct snd_ctl_elem_value *ucontrol)
821{
822 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
823
824 ucontrol->value.enumerated.item[0] = emu->emu1010.optical_out;
825 return 0;
826}
827
828static int snd_emu1010_optical_out_put(struct snd_kcontrol *kcontrol,
829 struct snd_ctl_elem_value *ucontrol)
830{
831 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
832 unsigned int val;
833 u32 tmp;
834 int change = 0;
835
836 val = ucontrol->value.enumerated.item[0];
837 /* Limit: uinfo->value.enumerated.items = 2; */
838 if (val >= 2)
839 return -EINVAL;
840 change = (emu->emu1010.optical_out != val);
841 if (change) {
842 emu->emu1010.optical_out = val;
843 tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : 0) |
844 (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : 0);
845 snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp);
846 }
847 return change;
848}
849
850static struct snd_kcontrol_new snd_emu1010_optical_out = {
851 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
852 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
853 .name = "Optical Output Mode",
854 .count = 1,
855 .info = snd_emu1010_optical_out_info,
856 .get = snd_emu1010_optical_out_get,
857 .put = snd_emu1010_optical_out_put
858};
859
860static int snd_emu1010_optical_in_info(struct snd_kcontrol *kcontrol,
861 struct snd_ctl_elem_info *uinfo)
862{
863 static const char * const texts[2] = {
864 "SPDIF", "ADAT"
865 };
866
867 return snd_ctl_enum_info(uinfo, 1, 2, texts);
868}
869
870static int snd_emu1010_optical_in_get(struct snd_kcontrol *kcontrol,
871 struct snd_ctl_elem_value *ucontrol)
872{
873 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
874
875 ucontrol->value.enumerated.item[0] = emu->emu1010.optical_in;
876 return 0;
877}
878
879static int snd_emu1010_optical_in_put(struct snd_kcontrol *kcontrol,
880 struct snd_ctl_elem_value *ucontrol)
881{
882 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
883 unsigned int val;
884 u32 tmp;
885 int change = 0;
886
887 val = ucontrol->value.enumerated.item[0];
888 /* Limit: uinfo->value.enumerated.items = 2; */
889 if (val >= 2)
890 return -EINVAL;
891 change = (emu->emu1010.optical_in != val);
892 if (change) {
893 emu->emu1010.optical_in = val;
894 tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : 0) |
895 (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : 0);
896 snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp);
897 }
898 return change;
899}
900
901static struct snd_kcontrol_new snd_emu1010_optical_in = {
902 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
903 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
904 .name = "Optical Input Mode",
905 .count = 1,
906 .info = snd_emu1010_optical_in_info,
907 .get = snd_emu1010_optical_in_get,
908 .put = snd_emu1010_optical_in_put
909};
910
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000911static int snd_audigy_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
912 struct snd_ctl_elem_info *uinfo)
913{
914#if 0
Takashi Iwai1541c662014-10-20 18:16:48 +0200915 static const char * const texts[4] = {
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000916 "Unknown1", "Unknown2", "Mic", "Line"
917 };
918#endif
Takashi Iwai1541c662014-10-20 18:16:48 +0200919 static const char * const texts[2] = {
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000920 "Mic", "Line"
921 };
922
Takashi Iwai1541c662014-10-20 18:16:48 +0200923 return snd_ctl_enum_info(uinfo, 1, 2, texts);
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000924}
925
926static int snd_audigy_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
927 struct snd_ctl_elem_value *ucontrol)
928{
929 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
930
931 ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
932 return 0;
933}
934
935static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
936 struct snd_ctl_elem_value *ucontrol)
937{
938 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
939 unsigned int source_id;
940 unsigned int ngain, ogain;
941 u32 gpio;
942 int change = 0;
943 unsigned long flags;
944 u32 source;
945 /* If the capture source has changed,
946 * update the capture volume from the cached value
947 * for the particular source.
948 */
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000949 source_id = ucontrol->value.enumerated.item[0];
950 /* Limit: uinfo->value.enumerated.items = 2; */
951 /* emu->i2c_capture_volume */
952 if (source_id >= 2)
953 return -EINVAL;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000954 change = (emu->i2c_capture_source != source_id);
955 if (change) {
956 snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */
957 spin_lock_irqsave(&emu->emu_lock, flags);
958 gpio = inl(emu->port + A_IOCFG);
959 if (source_id==0)
960 outl(gpio | 0x4, emu->port + A_IOCFG);
961 else
962 outl(gpio & ~0x4, emu->port + A_IOCFG);
963 spin_unlock_irqrestore(&emu->emu_lock, flags);
964
965 ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
966 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
967 if (ngain != ogain)
968 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
969 ngain = emu->i2c_capture_volume[source_id][1]; /* Right */
970 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
971 if (ngain != ogain)
972 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
973
974 source = 1 << (source_id + 2);
975 snd_emu10k1_i2c_write(emu, ADC_MUX, source); /* Set source */
976 emu->i2c_capture_source = source_id;
977 }
978 return change;
979}
980
981static struct snd_kcontrol_new snd_audigy_i2c_capture_source =
982{
983 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
984 .name = "Capture Source",
985 .info = snd_audigy_i2c_capture_source_info,
986 .get = snd_audigy_i2c_capture_source_get,
987 .put = snd_audigy_i2c_capture_source_put
988};
989
990static int snd_audigy_i2c_volume_info(struct snd_kcontrol *kcontrol,
991 struct snd_ctl_elem_info *uinfo)
992{
993 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
994 uinfo->count = 2;
995 uinfo->value.integer.min = 0;
996 uinfo->value.integer.max = 255;
997 return 0;
998}
999
1000static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol,
1001 struct snd_ctl_elem_value *ucontrol)
1002{
1003 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +00001004 unsigned int source_id;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001005
1006 source_id = kcontrol->private_value;
James Courtier-Dutton74415a32007-11-12 14:55:19 +00001007 /* Limit: emu->i2c_capture_volume */
1008 /* capture_source: uinfo->value.enumerated.items = 2 */
1009 if (source_id >= 2)
1010 return -EINVAL;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001011
1012 ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
1013 ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
1014 return 0;
1015}
1016
1017static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
1018 struct snd_ctl_elem_value *ucontrol)
1019{
1020 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1021 unsigned int ogain;
1022 unsigned int ngain;
James Courtier-Dutton74415a32007-11-12 14:55:19 +00001023 unsigned int source_id;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001024 int change = 0;
1025
1026 source_id = kcontrol->private_value;
James Courtier-Dutton74415a32007-11-12 14:55:19 +00001027 /* Limit: emu->i2c_capture_volume */
1028 /* capture_source: uinfo->value.enumerated.items = 2 */
1029 if (source_id >= 2)
1030 return -EINVAL;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001031 ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
1032 ngain = ucontrol->value.integer.value[0];
1033 if (ngain > 0xff)
1034 return 0;
1035 if (ogain != ngain) {
1036 if (emu->i2c_capture_source == source_id)
1037 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
James Courtier-Dutton74415a32007-11-12 14:55:19 +00001038 emu->i2c_capture_volume[source_id][0] = ngain;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001039 change = 1;
1040 }
1041 ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
1042 ngain = ucontrol->value.integer.value[1];
1043 if (ngain > 0xff)
1044 return 0;
1045 if (ogain != ngain) {
1046 if (emu->i2c_capture_source == source_id)
1047 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
James Courtier-Dutton74415a32007-11-12 14:55:19 +00001048 emu->i2c_capture_volume[source_id][1] = ngain;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001049 change = 1;
1050 }
1051
1052 return change;
1053}
1054
1055#define I2C_VOLUME(xname,chid) \
1056{ \
1057 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
1058 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
1059 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
1060 .info = snd_audigy_i2c_volume_info, \
1061 .get = snd_audigy_i2c_volume_get, \
1062 .put = snd_audigy_i2c_volume_put, \
1063 .tlv = { .p = snd_audigy_db_scale2 }, \
1064 .private_value = chid \
1065}
1066
1067
Bill Pembertone23e7a12012-12-06 12:35:10 -05001068static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] = {
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001069 I2C_VOLUME("Mic Capture Volume", 0),
1070 I2C_VOLUME("Line Capture Volume", 0)
1071};
1072
Takashi Iwai0af68e52005-04-11 17:03:03 +02001073#if 0
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001074static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075{
Takashi Iwai1541c662014-10-20 18:16:48 +02001076 static const char * const texts[] = {"44100", "48000", "96000"};
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077
Takashi Iwai1541c662014-10-20 18:16:48 +02001078 return snd_ctl_enum_info(uinfo, 1, 3, texts);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079}
1080
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001081static int snd_audigy_spdif_output_rate_get(struct snd_kcontrol *kcontrol,
1082 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001084 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 unsigned int tmp;
1086 unsigned long flags;
1087
1088
1089 spin_lock_irqsave(&emu->reg_lock, flags);
1090 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
1091 switch (tmp & A_SPDIF_RATE_MASK) {
1092 case A_SPDIF_44100:
1093 ucontrol->value.enumerated.item[0] = 0;
1094 break;
1095 case A_SPDIF_48000:
1096 ucontrol->value.enumerated.item[0] = 1;
1097 break;
1098 case A_SPDIF_96000:
1099 ucontrol->value.enumerated.item[0] = 2;
1100 break;
1101 default:
1102 ucontrol->value.enumerated.item[0] = 1;
1103 }
1104 spin_unlock_irqrestore(&emu->reg_lock, flags);
1105 return 0;
1106}
1107
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001108static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol,
1109 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001111 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 int change;
1113 unsigned int reg, val, tmp;
1114 unsigned long flags;
1115
1116 switch(ucontrol->value.enumerated.item[0]) {
1117 case 0:
1118 val = A_SPDIF_44100;
1119 break;
1120 case 1:
1121 val = A_SPDIF_48000;
1122 break;
1123 case 2:
1124 val = A_SPDIF_96000;
1125 break;
1126 default:
1127 val = A_SPDIF_48000;
1128 break;
1129 }
1130
1131
1132 spin_lock_irqsave(&emu->reg_lock, flags);
1133 reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
1134 tmp = reg & ~A_SPDIF_RATE_MASK;
1135 tmp |= val;
1136 if ((change = (tmp != reg)))
1137 snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
1138 spin_unlock_irqrestore(&emu->reg_lock, flags);
1139 return change;
1140}
1141
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001142static struct snd_kcontrol_new snd_audigy_spdif_output_rate =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143{
1144 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1145 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1146 .name = "Audigy SPDIF Output Sample Rate",
1147 .count = 1,
1148 .info = snd_audigy_spdif_output_rate_info,
1149 .get = snd_audigy_spdif_output_rate_get,
1150 .put = snd_audigy_spdif_output_rate_put
1151};
Takashi Iwai0af68e52005-04-11 17:03:03 +02001152#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001154static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol,
1155 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001157 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1159 int change;
1160 unsigned int val;
1161 unsigned long flags;
1162
James Courtier-Dutton74415a32007-11-12 14:55:19 +00001163 /* Limit: emu->spdif_bits */
1164 if (idx >= 3)
1165 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 val = (ucontrol->value.iec958.status[0] << 0) |
1167 (ucontrol->value.iec958.status[1] << 8) |
1168 (ucontrol->value.iec958.status[2] << 16) |
1169 (ucontrol->value.iec958.status[3] << 24);
1170 spin_lock_irqsave(&emu->reg_lock, flags);
1171 change = val != emu->spdif_bits[idx];
1172 if (change) {
1173 snd_emu10k1_ptr_write(emu, SPCS0 + idx, 0, val);
1174 emu->spdif_bits[idx] = val;
1175 }
1176 spin_unlock_irqrestore(&emu->reg_lock, flags);
1177 return change;
1178}
1179
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001180static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181{
1182 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +02001183 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
Takashi Iwai7583cb52007-08-16 19:32:16 +02001185 .count = 3,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 .info = snd_emu10k1_spdif_info,
1187 .get = snd_emu10k1_spdif_get_mask
1188};
1189
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001190static struct snd_kcontrol_new snd_emu10k1_spdif_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001191{
Clemens Ladisch5549d542005-08-03 13:50:30 +02001192 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
Takashi Iwai7583cb52007-08-16 19:32:16 +02001194 .count = 3,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 .info = snd_emu10k1_spdif_info,
1196 .get = snd_emu10k1_spdif_get,
1197 .put = snd_emu10k1_spdif_put
1198};
1199
1200
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001201static void update_emu10k1_fxrt(struct snd_emu10k1 *emu, int voice, unsigned char *route)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202{
1203 if (emu->audigy) {
1204 snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
1205 snd_emu10k1_compose_audigy_fxrt1(route));
1206 snd_emu10k1_ptr_write(emu, A_FXRT2, voice,
1207 snd_emu10k1_compose_audigy_fxrt2(route));
1208 } else {
1209 snd_emu10k1_ptr_write(emu, FXRT, voice,
1210 snd_emu10k1_compose_send_routing(route));
1211 }
1212}
1213
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001214static void update_emu10k1_send_volume(struct snd_emu10k1 *emu, int voice, unsigned char *volume)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215{
1216 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]);
1217 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]);
1218 snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, volume[2]);
1219 snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, volume[3]);
1220 if (emu->audigy) {
1221 unsigned int val = ((unsigned int)volume[4] << 24) |
1222 ((unsigned int)volume[5] << 16) |
1223 ((unsigned int)volume[6] << 8) |
1224 (unsigned int)volume[7];
1225 snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, val);
1226 }
1227}
1228
1229/* PCM stream controls */
1230
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001231static int snd_emu10k1_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001233 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1235 uinfo->count = emu->audigy ? 3*8 : 3*4;
1236 uinfo->value.integer.min = 0;
1237 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
1238 return 0;
1239}
1240
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001241static int snd_emu10k1_send_routing_get(struct snd_kcontrol *kcontrol,
1242 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243{
1244 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001245 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1246 struct snd_emu10k1_pcm_mixer *mix =
1247 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 int voice, idx;
1249 int num_efx = emu->audigy ? 8 : 4;
1250 int mask = emu->audigy ? 0x3f : 0x0f;
1251
1252 spin_lock_irqsave(&emu->reg_lock, flags);
1253 for (voice = 0; voice < 3; voice++)
1254 for (idx = 0; idx < num_efx; idx++)
1255 ucontrol->value.integer.value[(voice * num_efx) + idx] =
1256 mix->send_routing[voice][idx] & mask;
1257 spin_unlock_irqrestore(&emu->reg_lock, flags);
1258 return 0;
1259}
1260
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001261static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol,
1262 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263{
1264 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001265 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1266 struct snd_emu10k1_pcm_mixer *mix =
1267 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 int change = 0, voice, idx, val;
1269 int num_efx = emu->audigy ? 8 : 4;
1270 int mask = emu->audigy ? 0x3f : 0x0f;
1271
1272 spin_lock_irqsave(&emu->reg_lock, flags);
1273 for (voice = 0; voice < 3; voice++)
1274 for (idx = 0; idx < num_efx; idx++) {
1275 val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask;
1276 if (mix->send_routing[voice][idx] != val) {
1277 mix->send_routing[voice][idx] = val;
1278 change = 1;
1279 }
1280 }
1281 if (change && mix->epcm) {
1282 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1283 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
1284 &mix->send_routing[1][0]);
1285 update_emu10k1_fxrt(emu, mix->epcm->voices[1]->number,
1286 &mix->send_routing[2][0]);
1287 } else if (mix->epcm->voices[0]) {
1288 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
1289 &mix->send_routing[0][0]);
1290 }
1291 }
1292 spin_unlock_irqrestore(&emu->reg_lock, flags);
1293 return change;
1294}
1295
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001296static struct snd_kcontrol_new snd_emu10k1_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297{
1298 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001299 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 .name = "EMU10K1 PCM Send Routing",
1301 .count = 32,
1302 .info = snd_emu10k1_send_routing_info,
1303 .get = snd_emu10k1_send_routing_get,
1304 .put = snd_emu10k1_send_routing_put
1305};
1306
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001307static int snd_emu10k1_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001309 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1311 uinfo->count = emu->audigy ? 3*8 : 3*4;
1312 uinfo->value.integer.min = 0;
1313 uinfo->value.integer.max = 255;
1314 return 0;
1315}
1316
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001317static int snd_emu10k1_send_volume_get(struct snd_kcontrol *kcontrol,
1318 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319{
1320 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001321 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1322 struct snd_emu10k1_pcm_mixer *mix =
1323 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 int idx;
1325 int num_efx = emu->audigy ? 8 : 4;
1326
1327 spin_lock_irqsave(&emu->reg_lock, flags);
1328 for (idx = 0; idx < 3*num_efx; idx++)
1329 ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx];
1330 spin_unlock_irqrestore(&emu->reg_lock, flags);
1331 return 0;
1332}
1333
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001334static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol,
1335 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336{
1337 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001338 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1339 struct snd_emu10k1_pcm_mixer *mix =
1340 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 int change = 0, idx, val;
1342 int num_efx = emu->audigy ? 8 : 4;
1343
1344 spin_lock_irqsave(&emu->reg_lock, flags);
1345 for (idx = 0; idx < 3*num_efx; idx++) {
1346 val = ucontrol->value.integer.value[idx] & 255;
1347 if (mix->send_volume[idx/num_efx][idx%num_efx] != val) {
1348 mix->send_volume[idx/num_efx][idx%num_efx] = val;
1349 change = 1;
1350 }
1351 }
1352 if (change && mix->epcm) {
1353 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1354 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
1355 &mix->send_volume[1][0]);
1356 update_emu10k1_send_volume(emu, mix->epcm->voices[1]->number,
1357 &mix->send_volume[2][0]);
1358 } else if (mix->epcm->voices[0]) {
1359 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
1360 &mix->send_volume[0][0]);
1361 }
1362 }
1363 spin_unlock_irqrestore(&emu->reg_lock, flags);
1364 return change;
1365}
1366
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001367static struct snd_kcontrol_new snd_emu10k1_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368{
1369 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001370 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 .name = "EMU10K1 PCM Send Volume",
1372 .count = 32,
1373 .info = snd_emu10k1_send_volume_info,
1374 .get = snd_emu10k1_send_volume_get,
1375 .put = snd_emu10k1_send_volume_put
1376};
1377
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001378static int snd_emu10k1_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379{
1380 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1381 uinfo->count = 3;
1382 uinfo->value.integer.min = 0;
1383 uinfo->value.integer.max = 0xffff;
1384 return 0;
1385}
1386
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001387static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol,
1388 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001390 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1391 struct snd_emu10k1_pcm_mixer *mix =
1392 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 unsigned long flags;
1394 int idx;
1395
1396 spin_lock_irqsave(&emu->reg_lock, flags);
1397 for (idx = 0; idx < 3; idx++)
1398 ucontrol->value.integer.value[idx] = mix->attn[idx];
1399 spin_unlock_irqrestore(&emu->reg_lock, flags);
1400 return 0;
1401}
1402
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001403static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol,
1404 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405{
1406 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001407 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1408 struct snd_emu10k1_pcm_mixer *mix =
1409 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 int change = 0, idx, val;
1411
1412 spin_lock_irqsave(&emu->reg_lock, flags);
1413 for (idx = 0; idx < 3; idx++) {
1414 val = ucontrol->value.integer.value[idx] & 0xffff;
1415 if (mix->attn[idx] != val) {
1416 mix->attn[idx] = val;
1417 change = 1;
1418 }
1419 }
1420 if (change && mix->epcm) {
1421 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1422 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[1]);
1423 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[1]->number, mix->attn[2]);
1424 } else if (mix->epcm->voices[0]) {
1425 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]);
1426 }
1427 }
1428 spin_unlock_irqrestore(&emu->reg_lock, flags);
1429 return change;
1430}
1431
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001432static struct snd_kcontrol_new snd_emu10k1_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433{
1434 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001435 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 .name = "EMU10K1 PCM Volume",
1437 .count = 32,
1438 .info = snd_emu10k1_attn_info,
1439 .get = snd_emu10k1_attn_get,
1440 .put = snd_emu10k1_attn_put
1441};
1442
1443/* Mutichannel PCM stream controls */
1444
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001445static int snd_emu10k1_efx_send_routing_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 = emu->audigy ? 0x3f : 0x0f;
1452 return 0;
1453}
1454
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001455static int snd_emu10k1_efx_send_routing_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 int mask = emu->audigy ? 0x3f : 0x0f;
1465
1466 spin_lock_irqsave(&emu->reg_lock, flags);
1467 for (idx = 0; idx < num_efx; idx++)
1468 ucontrol->value.integer.value[idx] =
1469 mix->send_routing[0][idx] & mask;
1470 spin_unlock_irqrestore(&emu->reg_lock, flags);
1471 return 0;
1472}
1473
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001474static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol,
1475 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476{
1477 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001478 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001480 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 int change = 0, idx, val;
1482 int num_efx = emu->audigy ? 8 : 4;
1483 int mask = emu->audigy ? 0x3f : 0x0f;
1484
1485 spin_lock_irqsave(&emu->reg_lock, flags);
1486 for (idx = 0; idx < num_efx; idx++) {
1487 val = ucontrol->value.integer.value[idx] & mask;
1488 if (mix->send_routing[0][idx] != val) {
1489 mix->send_routing[0][idx] = val;
1490 change = 1;
1491 }
1492 }
1493
1494 if (change && mix->epcm) {
1495 if (mix->epcm->voices[ch]) {
1496 update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number,
1497 &mix->send_routing[0][0]);
1498 }
1499 }
1500 spin_unlock_irqrestore(&emu->reg_lock, flags);
1501 return change;
1502}
1503
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001504static struct snd_kcontrol_new snd_emu10k1_efx_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505{
1506 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1507 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1508 .name = "Multichannel PCM Send Routing",
1509 .count = 16,
1510 .info = snd_emu10k1_efx_send_routing_info,
1511 .get = snd_emu10k1_efx_send_routing_get,
1512 .put = snd_emu10k1_efx_send_routing_put
1513};
1514
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001515static int snd_emu10k1_efx_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001517 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1519 uinfo->count = emu->audigy ? 8 : 4;
1520 uinfo->value.integer.min = 0;
1521 uinfo->value.integer.max = 255;
1522 return 0;
1523}
1524
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001525static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol,
1526 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527{
1528 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001529 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1530 struct snd_emu10k1_pcm_mixer *mix =
1531 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 int idx;
1533 int num_efx = emu->audigy ? 8 : 4;
1534
1535 spin_lock_irqsave(&emu->reg_lock, flags);
1536 for (idx = 0; idx < num_efx; idx++)
1537 ucontrol->value.integer.value[idx] = mix->send_volume[0][idx];
1538 spin_unlock_irqrestore(&emu->reg_lock, flags);
1539 return 0;
1540}
1541
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001542static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol,
1543 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544{
1545 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001546 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001548 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 int change = 0, idx, val;
1550 int num_efx = emu->audigy ? 8 : 4;
1551
1552 spin_lock_irqsave(&emu->reg_lock, flags);
1553 for (idx = 0; idx < num_efx; idx++) {
1554 val = ucontrol->value.integer.value[idx] & 255;
1555 if (mix->send_volume[0][idx] != val) {
1556 mix->send_volume[0][idx] = val;
1557 change = 1;
1558 }
1559 }
1560 if (change && mix->epcm) {
1561 if (mix->epcm->voices[ch]) {
1562 update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number,
1563 &mix->send_volume[0][0]);
1564 }
1565 }
1566 spin_unlock_irqrestore(&emu->reg_lock, flags);
1567 return change;
1568}
1569
1570
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001571static struct snd_kcontrol_new snd_emu10k1_efx_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572{
1573 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1574 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1575 .name = "Multichannel PCM Send Volume",
1576 .count = 16,
1577 .info = snd_emu10k1_efx_send_volume_info,
1578 .get = snd_emu10k1_efx_send_volume_get,
1579 .put = snd_emu10k1_efx_send_volume_put
1580};
1581
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001582static int snd_emu10k1_efx_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583{
1584 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1585 uinfo->count = 1;
1586 uinfo->value.integer.min = 0;
1587 uinfo->value.integer.max = 0xffff;
1588 return 0;
1589}
1590
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001591static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol,
1592 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001594 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1595 struct snd_emu10k1_pcm_mixer *mix =
1596 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597 unsigned long flags;
1598
1599 spin_lock_irqsave(&emu->reg_lock, flags);
1600 ucontrol->value.integer.value[0] = mix->attn[0];
1601 spin_unlock_irqrestore(&emu->reg_lock, flags);
1602 return 0;
1603}
1604
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001605static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol,
1606 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607{
1608 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001609 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001611 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 int change = 0, val;
1613
1614 spin_lock_irqsave(&emu->reg_lock, flags);
1615 val = ucontrol->value.integer.value[0] & 0xffff;
1616 if (mix->attn[0] != val) {
1617 mix->attn[0] = val;
1618 change = 1;
1619 }
1620 if (change && mix->epcm) {
1621 if (mix->epcm->voices[ch]) {
1622 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]);
1623 }
1624 }
1625 spin_unlock_irqrestore(&emu->reg_lock, flags);
1626 return change;
1627}
1628
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001629static struct snd_kcontrol_new snd_emu10k1_efx_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630{
1631 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1632 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1633 .name = "Multichannel PCM Volume",
1634 .count = 16,
1635 .info = snd_emu10k1_efx_attn_info,
1636 .get = snd_emu10k1_efx_attn_get,
1637 .put = snd_emu10k1_efx_attn_put
1638};
1639
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001640#define snd_emu10k1_shared_spdif_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001642static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol,
1643 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001645 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646
1647 if (emu->audigy)
1648 ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0;
1649 else
1650 ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0;
Takashi Iwaid2cd74b2008-06-02 11:45:53 +02001651 if (emu->card_capabilities->invert_shared_spdif)
1652 ucontrol->value.integer.value[0] =
1653 !ucontrol->value.integer.value[0];
1654
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 return 0;
1656}
1657
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001658static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
1659 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660{
1661 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001662 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Takashi Iwaid2cd74b2008-06-02 11:45:53 +02001663 unsigned int reg, val, sw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 int change = 0;
1665
Takashi Iwaid2cd74b2008-06-02 11:45:53 +02001666 sw = ucontrol->value.integer.value[0];
1667 if (emu->card_capabilities->invert_shared_spdif)
1668 sw = !sw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669 spin_lock_irqsave(&emu->reg_lock, flags);
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001670 if ( emu->card_capabilities->i2c_adc) {
1671 /* Do nothing for Audigy 2 ZS Notebook */
1672 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 reg = inl(emu->port + A_IOCFG);
Takashi Iwaid2cd74b2008-06-02 11:45:53 +02001674 val = sw ? A_IOCFG_GPOUT0 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675 change = (reg & A_IOCFG_GPOUT0) != val;
1676 if (change) {
1677 reg &= ~A_IOCFG_GPOUT0;
1678 reg |= val;
1679 outl(reg | val, emu->port + A_IOCFG);
1680 }
1681 }
1682 reg = inl(emu->port + HCFG);
Takashi Iwaid2cd74b2008-06-02 11:45:53 +02001683 val = sw ? HCFG_GPOUT0 : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 change |= (reg & HCFG_GPOUT0) != val;
1685 if (change) {
1686 reg &= ~HCFG_GPOUT0;
1687 reg |= val;
1688 outl(reg | val, emu->port + HCFG);
1689 }
1690 spin_unlock_irqrestore(&emu->reg_lock, flags);
1691 return change;
1692}
1693
Bill Pembertone23e7a12012-12-06 12:35:10 -05001694static struct snd_kcontrol_new snd_emu10k1_shared_spdif =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695{
1696 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1697 .name = "SB Live Analog/Digital Output Jack",
1698 .info = snd_emu10k1_shared_spdif_info,
1699 .get = snd_emu10k1_shared_spdif_get,
1700 .put = snd_emu10k1_shared_spdif_put
1701};
1702
Bill Pembertone23e7a12012-12-06 12:35:10 -05001703static struct snd_kcontrol_new snd_audigy_shared_spdif =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704{
1705 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1706 .name = "Audigy Analog/Digital Output Jack",
1707 .info = snd_emu10k1_shared_spdif_info,
1708 .get = snd_emu10k1_shared_spdif_get,
1709 .put = snd_emu10k1_shared_spdif_put
1710};
1711
Takashi Iwai16950e02008-12-02 09:31:16 +01001712/* workaround for too low volume on Audigy due to 16bit/24bit conversion */
1713
1714#define snd_audigy_capture_boost_info snd_ctl_boolean_mono_info
1715
1716static int snd_audigy_capture_boost_get(struct snd_kcontrol *kcontrol,
1717 struct snd_ctl_elem_value *ucontrol)
1718{
1719 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1720 unsigned int val;
1721
1722 /* FIXME: better to use a cached version */
1723 val = snd_ac97_read(emu->ac97, AC97_REC_GAIN);
1724 ucontrol->value.integer.value[0] = !!val;
1725 return 0;
1726}
1727
1728static int snd_audigy_capture_boost_put(struct snd_kcontrol *kcontrol,
1729 struct snd_ctl_elem_value *ucontrol)
1730{
1731 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1732 unsigned int val;
1733
1734 if (ucontrol->value.integer.value[0])
1735 val = 0x0f0f;
1736 else
1737 val = 0;
1738 return snd_ac97_update(emu->ac97, AC97_REC_GAIN, val);
1739}
1740
Bill Pembertone23e7a12012-12-06 12:35:10 -05001741static struct snd_kcontrol_new snd_audigy_capture_boost =
Takashi Iwai16950e02008-12-02 09:31:16 +01001742{
1743 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1744 .name = "Analog Capture Boost",
1745 .info = snd_audigy_capture_boost_info,
1746 .get = snd_audigy_capture_boost_get,
1747 .put = snd_audigy_capture_boost_put
1748};
1749
1750
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751/*
1752 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001753static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001755 struct snd_emu10k1 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 emu->ac97 = NULL;
1757}
1758
1759/*
1760 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001761static int remove_ctl(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001763 struct snd_ctl_elem_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 memset(&id, 0, sizeof(id));
1765 strcpy(id.name, name);
1766 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1767 return snd_ctl_remove_id(card, &id);
1768}
1769
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001770static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001772 struct snd_ctl_elem_id sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773 memset(&sid, 0, sizeof(sid));
1774 strcpy(sid.name, name);
1775 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1776 return snd_ctl_find_id(card, &sid);
1777}
1778
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001779static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001781 struct snd_kcontrol *kctl = ctl_find(card, src);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782 if (kctl) {
1783 strcpy(kctl->id.name, dst);
1784 return 0;
1785 }
1786 return -ENOENT;
1787}
1788
Bill Pembertone23e7a12012-12-06 12:35:10 -05001789int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
1790 int pcm_device, int multi_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791{
1792 int err, pcm;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001793 struct snd_kcontrol *kctl;
1794 struct snd_card *card = emu->card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795 char **c;
1796 static char *emu10k1_remove_ctls[] = {
1797 /* no AC97 mono, surround, center/lfe */
1798 "Master Mono Playback Switch",
1799 "Master Mono Playback Volume",
1800 "PCM Out Path & Mute",
1801 "Mono Output Select",
1802 "Surround Playback Switch",
1803 "Surround Playback Volume",
1804 "Center Playback Switch",
1805 "Center Playback Volume",
1806 "LFE Playback Switch",
1807 "LFE Playback Volume",
1808 NULL
1809 };
1810 static char *emu10k1_rename_ctls[] = {
1811 "Surround Digital Playback Volume", "Surround Playback Volume",
1812 "Center Digital Playback Volume", "Center Playback Volume",
1813 "LFE Digital Playback Volume", "LFE Playback Volume",
1814 NULL
1815 };
1816 static char *audigy_remove_ctls[] = {
1817 /* Master/PCM controls on ac97 of Audigy has no effect */
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001818 /* On the Audigy2 the AC97 playback is piped into
1819 * the Philips ADC for 24bit capture */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820 "PCM Playback Switch",
1821 "PCM Playback Volume",
1822 "Master Mono Playback Switch",
1823 "Master Mono Playback Volume",
1824 "Master Playback Switch",
1825 "Master Playback Volume",
1826 "PCM Out Path & Mute",
1827 "Mono Output Select",
1828 /* remove unused AC97 capture controls */
1829 "Capture Source",
1830 "Capture Switch",
1831 "Capture Volume",
1832 "Mic Select",
1833 "Video Playback Switch",
1834 "Video Playback Volume",
1835 "Mic Playback Switch",
1836 "Mic Playback Volume",
1837 NULL
1838 };
1839 static char *audigy_rename_ctls[] = {
1840 /* use conventional names */
1841 "Wave Playback Volume", "PCM Playback Volume",
1842 /* "Wave Capture Volume", "PCM Capture Volume", */
1843 "Wave Master Playback Volume", "Master Playback Volume",
1844 "AMic Playback Volume", "Mic Playback Volume",
1845 NULL
1846 };
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001847 static char *audigy_rename_ctls_i2c_adc[] = {
1848 //"Analog Mix Capture Volume","OLD Analog Mix Capture Volume",
1849 "Line Capture Volume", "Analog Mix Capture Volume",
1850 "Wave Playback Volume", "OLD PCM Playback Volume",
1851 "Wave Master Playback Volume", "Master Playback Volume",
1852 "AMic Playback Volume", "Old Mic Playback Volume",
James Courtier-Duttoneb41dab2006-12-06 20:38:45 +00001853 "CD Capture Volume", "IEC958 Optical Capture Volume",
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001854 NULL
1855 };
1856 static char *audigy_remove_ctls_i2c_adc[] = {
1857 /* On the Audigy2 ZS Notebook
1858 * Capture via WM8775 */
1859 "Mic Capture Volume",
1860 "Analog Mix Capture Volume",
1861 "Aux Capture Volume",
James Courtier-Duttoneb41dab2006-12-06 20:38:45 +00001862 "IEC958 Optical Capture Volume",
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001863 NULL
1864 };
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001865 static char *audigy_remove_ctls_1361t_adc[] = {
1866 /* On the Audigy2 the AC97 playback is piped into
1867 * the Philips ADC for 24bit capture */
1868 "PCM Playback Switch",
1869 "PCM Playback Volume",
1870 "Master Mono Playback Switch",
1871 "Master Mono Playback Volume",
1872 "Capture Source",
1873 "Capture Switch",
1874 "Capture Volume",
1875 "Mic Capture Volume",
1876 "Headphone Playback Switch",
1877 "Headphone Playback Volume",
1878 "3D Control - Center",
1879 "3D Control - Depth",
1880 "3D Control - Switch",
1881 "Line2 Playback Volume",
1882 "Line2 Capture Volume",
1883 NULL
1884 };
1885 static char *audigy_rename_ctls_1361t_adc[] = {
1886 "Master Playback Switch", "Master Capture Switch",
1887 "Master Playback Volume", "Master Capture Volume",
1888 "Wave Master Playback Volume", "Master Playback Volume",
Jaroslav Kyselad355c82a2009-11-03 15:47:25 +01001889 "Beep Playback Switch", "Beep Capture Switch",
1890 "Beep Playback Volume", "Beep Capture Volume",
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001891 "Phone Playback Switch", "Phone Capture Switch",
1892 "Phone Playback Volume", "Phone Capture Volume",
1893 "Mic Playback Switch", "Mic Capture Switch",
1894 "Mic Playback Volume", "Mic Capture Volume",
1895 "Line Playback Switch", "Line Capture Switch",
1896 "Line Playback Volume", "Line Capture Volume",
1897 "CD Playback Switch", "CD Capture Switch",
1898 "CD Playback Volume", "CD Capture Volume",
1899 "Aux Playback Switch", "Aux Capture Switch",
1900 "Aux Playback Volume", "Aux Capture Volume",
1901 "Video Playback Switch", "Video Capture Switch",
1902 "Video Playback Volume", "Video Capture Volume",
1903
1904 NULL
1905 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906
Lee Revell2b637da2005-03-30 13:51:18 +02001907 if (emu->card_capabilities->ac97_chip) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001908 struct snd_ac97_bus *pbus;
1909 struct snd_ac97_template ac97;
1910 static struct snd_ac97_bus_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 .write = snd_emu10k1_ac97_write,
1912 .read = snd_emu10k1_ac97_read,
1913 };
1914
Takashi Iwaib1508692005-10-04 13:49:32 +02001915 if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0)
1916 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001917 pbus->no_vra = 1; /* we don't need VRA */
1918
1919 memset(&ac97, 0, sizeof(ac97));
1920 ac97.private_data = emu;
1921 ac97.private_free = snd_emu10k1_mixer_free_ac97;
1922 ac97.scaps = AC97_SCAP_NO_SPDIF;
Takashi Iwaib1508692005-10-04 13:49:32 +02001923 if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) {
1924 if (emu->card_capabilities->ac97_chip == 1)
1925 return err;
Takashi Iwai6f002b02014-02-25 17:02:09 +01001926 dev_info(emu->card->dev,
1927 "AC97 is optional on this board\n");
1928 dev_info(emu->card->dev,
1929 "Proceeding without ac97 mixers...\n");
Takashi Iwaib1508692005-10-04 13:49:32 +02001930 snd_device_free(emu->card, pbus);
1931 goto no_ac97; /* FIXME: get rid of ugly gotos.. */
1932 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001933 if (emu->audigy) {
1934 /* set master volume to 0 dB */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001935 snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 /* set capture source to mic */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001937 snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001938 if (emu->card_capabilities->adc_1361t)
1939 c = audigy_remove_ctls_1361t_adc;
1940 else
1941 c = audigy_remove_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001942 } else {
1943 /*
1944 * Credits for cards based on STAC9758:
1945 * James Courtier-Dutton <James@superbug.demon.co.uk>
1946 * Voluspa <voluspa@comhem.se>
1947 */
1948 if (emu->ac97->id == AC97_ID_STAC9758) {
1949 emu->rear_ac97 = 1;
1950 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 +01001951 snd_ac97_write_cache(emu->ac97, AC97_HEADPHONE, 0x0202);
Raymond Yaub6a48402011-04-15 11:42:42 +08001952 remove_ctl(card,"Front Playback Volume");
1953 remove_ctl(card,"Front Playback Switch");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954 }
1955 /* remove unused AC97 controls */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001956 snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
1957 snd_ac97_write_cache(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 c = emu10k1_remove_ctls;
1959 }
1960 for (; *c; c++)
1961 remove_ctl(card, *c);
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001962 } else if (emu->card_capabilities->i2c_adc) {
1963 c = audigy_remove_ctls_i2c_adc;
1964 for (; *c; c++)
1965 remove_ctl(card, *c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966 } else {
Takashi Iwaif12aa402005-09-30 16:56:59 +02001967 no_ac97:
Lee Revell2b637da2005-03-30 13:51:18 +02001968 if (emu->card_capabilities->ecard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 strcpy(emu->card->mixername, "EMU APS");
1970 else if (emu->audigy)
1971 strcpy(emu->card->mixername, "SB Audigy");
1972 else
1973 strcpy(emu->card->mixername, "Emu10k1");
1974 }
1975
1976 if (emu->audigy)
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001977 if (emu->card_capabilities->adc_1361t)
1978 c = audigy_rename_ctls_1361t_adc;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001979 else if (emu->card_capabilities->i2c_adc)
1980 c = audigy_rename_ctls_i2c_adc;
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001981 else
1982 c = audigy_rename_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001983 else
1984 c = emu10k1_rename_ctls;
1985 for (; *c; c += 2)
1986 rename_ctl(card, c[0], c[1]);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001987
Raymond Yaue217b962011-03-30 20:00:39 +08001988 if (emu->card_capabilities->subsystem == 0x80401102) { /* SB Live! Platinum CT4760P */
1989 remove_ctl(card, "Center Playback Volume");
1990 remove_ctl(card, "LFE Playback Volume");
1991 remove_ctl(card, "Wave Center Playback Volume");
1992 remove_ctl(card, "Wave LFE Playback Volume");
1993 }
James Courtier-Duttone3b9bc02005-12-24 16:54:51 +01001994 if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */
1995 rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume");
1996 rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume");
1997 rename_ctl(card, "Aux2 Capture Volume", "Line3 Capture Volume");
1998 rename_ctl(card, "Mic Capture Volume", "Unknown1 Capture Volume");
1999 remove_ctl(card, "Headphone Playback Switch");
2000 remove_ctl(card, "Headphone Playback Volume");
2001 remove_ctl(card, "3D Control - Center");
2002 remove_ctl(card, "3D Control - Depth");
2003 remove_ctl(card, "3D Control - Switch");
2004 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005 if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL)
2006 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002007 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008 if ((err = snd_ctl_add(card, kctl)))
2009 return err;
2010 if ((kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL)
2011 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002012 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013 if ((err = snd_ctl_add(card, kctl)))
2014 return err;
2015 if ((kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu)) == NULL)
2016 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002017 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 if ((err = snd_ctl_add(card, kctl)))
2019 return err;
2020
2021 if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL)
2022 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002023 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024 if ((err = snd_ctl_add(card, kctl)))
2025 return err;
2026
2027 if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL)
2028 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002029 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030 if ((err = snd_ctl_add(card, kctl)))
2031 return err;
2032
2033 if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL)
2034 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02002035 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 if ((err = snd_ctl_add(card, kctl)))
2037 return err;
2038
2039 /* initialize the routing and volume table for each pcm playback stream */
2040 for (pcm = 0; pcm < 32; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002041 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042 int v;
2043
2044 mix = &emu->pcm_mixer[pcm];
2045 mix->epcm = NULL;
2046
2047 for (v = 0; v < 4; v++)
2048 mix->send_routing[0][v] =
2049 mix->send_routing[1][v] =
2050 mix->send_routing[2][v] = v;
2051
2052 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
2053 mix->send_volume[0][0] = mix->send_volume[0][1] =
2054 mix->send_volume[1][0] = mix->send_volume[2][1] = 255;
2055
2056 mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
2057 }
2058
2059 /* initialize the routing and volume table for the multichannel playback stream */
2060 for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002061 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 int v;
2063
2064 mix = &emu->efx_pcm_mixer[pcm];
2065 mix->epcm = NULL;
2066
2067 mix->send_routing[0][0] = pcm;
2068 mix->send_routing[0][1] = (pcm == 0) ? 1 : 0;
2069 for (v = 0; v < 2; v++)
2070 mix->send_routing[0][2+v] = 13+v;
2071 if (emu->audigy)
2072 for (v = 0; v < 4; v++)
2073 mix->send_routing[0][4+v] = 60+v;
2074
2075 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
2076 mix->send_volume[0][0] = 255;
2077
2078 mix->attn[0] = 0xffff;
2079 }
2080
Lee Revell2b637da2005-03-30 13:51:18 +02002081 if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082 /* sb live! and audigy */
2083 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
2084 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02002085 if (!emu->audigy)
2086 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 if ((err = snd_ctl_add(card, kctl)))
2088 return err;
2089 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
2090 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02002091 if (!emu->audigy)
2092 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093 if ((err = snd_ctl_add(card, kctl)))
2094 return err;
2095 }
2096
James Courtier-Dutton190d2c42007-11-04 14:08:26 +00002097 if (emu->card_capabilities->emu_model) {
James Courtier-Dutton19b99fb2005-12-04 18:03:03 +01002098 ; /* Disable the snd_audigy_spdif_shared_spdif */
2099 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
2101 return -ENOMEM;
2102 if ((err = snd_ctl_add(card, kctl)))
2103 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02002104#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
2106 return -ENOMEM;
2107 if ((err = snd_ctl_add(card, kctl)))
2108 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02002109#endif
Lee Revell2b637da2005-03-30 13:51:18 +02002110 } else if (! emu->card_capabilities->ecard) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111 /* sb live! */
2112 if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
2113 return -ENOMEM;
2114 if ((err = snd_ctl_add(card, kctl)))
2115 return err;
2116 }
Lee Revell2b637da2005-03-30 13:51:18 +02002117 if (emu->card_capabilities->ca0151_chip) { /* P16V */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 if ((err = snd_p16v_mixer(emu)))
2119 return err;
2120 }
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01002121
Takashi Iwai3839e4f2007-12-21 16:33:32 +01002122 if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1616) {
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002123 /* 1616(m) cardbus */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01002124 int i;
2125
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002126 for (i = 0; i < ARRAY_SIZE(snd_emu1616_output_enum_ctls); i++) {
2127 err = snd_ctl_add(card,
2128 snd_ctl_new1(&snd_emu1616_output_enum_ctls[i],
2129 emu));
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01002130 if (err < 0)
2131 return err;
2132 }
2133 for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) {
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002134 err = snd_ctl_add(card,
2135 snd_ctl_new1(&snd_emu1010_input_enum_ctls[i],
2136 emu));
2137 if (err < 0)
2138 return err;
2139 }
2140 for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads) - 2; i++) {
2141 err = snd_ctl_add(card,
2142 snd_ctl_new1(&snd_emu1010_adc_pads[i], emu));
2143 if (err < 0)
2144 return err;
2145 }
2146 for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads) - 2; i++) {
2147 err = snd_ctl_add(card,
2148 snd_ctl_new1(&snd_emu1010_dac_pads[i], emu));
2149 if (err < 0)
2150 return err;
2151 }
2152 err = snd_ctl_add(card,
2153 snd_ctl_new1(&snd_emu1010_internal_clock, emu));
2154 if (err < 0)
2155 return err;
Michael Gernoth99dcab42015-04-11 18:00:19 +02002156 err = snd_ctl_add(card,
2157 snd_ctl_new1(&snd_emu1010_optical_out, emu));
2158 if (err < 0)
2159 return err;
2160 err = snd_ctl_add(card,
2161 snd_ctl_new1(&snd_emu1010_optical_in, emu));
2162 if (err < 0)
2163 return err;
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002164
Takashi Iwai88aa1392007-12-21 16:20:12 +01002165 } else if (emu->card_capabilities->emu_model) {
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002166 /* all other e-mu cards for now */
2167 int i;
2168
2169 for (i = 0; i < ARRAY_SIZE(snd_emu1010_output_enum_ctls); i++) {
2170 err = snd_ctl_add(card,
2171 snd_ctl_new1(&snd_emu1010_output_enum_ctls[i],
2172 emu));
2173 if (err < 0)
2174 return err;
2175 }
2176 for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) {
2177 err = snd_ctl_add(card,
2178 snd_ctl_new1(&snd_emu1010_input_enum_ctls[i],
2179 emu));
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01002180 if (err < 0)
2181 return err;
2182 }
James Courtier-Dutton9148cc52006-10-09 23:08:00 +01002183 for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads); i++) {
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002184 err = snd_ctl_add(card,
2185 snd_ctl_new1(&snd_emu1010_adc_pads[i], emu));
James Courtier-Dutton9148cc52006-10-09 23:08:00 +01002186 if (err < 0)
2187 return err;
2188 }
2189 for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads); i++) {
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002190 err = snd_ctl_add(card,
2191 snd_ctl_new1(&snd_emu1010_dac_pads[i], emu));
James Courtier-Dutton9148cc52006-10-09 23:08:00 +01002192 if (err < 0)
2193 return err;
2194 }
Ctirad Fertr1c02e362007-12-13 16:27:13 +01002195 err = snd_ctl_add(card,
2196 snd_ctl_new1(&snd_emu1010_internal_clock, emu));
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +01002197 if (err < 0)
2198 return err;
Michael Gernoth99dcab42015-04-11 18:00:19 +02002199 err = snd_ctl_add(card,
2200 snd_ctl_new1(&snd_emu1010_optical_out, emu));
2201 if (err < 0)
2202 return err;
2203 err = snd_ctl_add(card,
2204 snd_ctl_new1(&snd_emu1010_optical_in, emu));
2205 if (err < 0)
2206 return err;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01002207 }
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00002208
2209 if ( emu->card_capabilities->i2c_adc) {
2210 int i;
2211
2212 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_capture_source, emu));
2213 if (err < 0)
2214 return err;
2215
2216 for (i = 0; i < ARRAY_SIZE(snd_audigy_i2c_volume_ctls); i++) {
2217 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_volume_ctls[i], emu));
2218 if (err < 0)
2219 return err;
2220 }
2221 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222
Takashi Iwai16950e02008-12-02 09:31:16 +01002223 if (emu->card_capabilities->ac97_chip && emu->audigy) {
2224 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_capture_boost,
2225 emu));
2226 if (err < 0)
2227 return err;
2228 }
2229
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230 return 0;
2231}