blob: 83acfa6e93173db36e2503ddaa3785a843aa7a78 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Jaroslav Kyselac1017a42007-10-15 09:50:19 +02002 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 * Takashi Iwai <tiwai@suse.de>
4 * Creative Labs, Inc.
5 * Routines for control of EMU10K1 chips / mixer routines
6 * Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com>
7 *
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01008 * Copyright (c) by James Courtier-Dutton <James@superbug.co.uk>
9 * Added EMU 1010 support.
10 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 * BUGS:
12 * --
13 *
14 * TODO:
15 * --
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 *
31 */
32
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/time.h>
34#include <linux/init.h>
35#include <sound/core.h>
36#include <sound/emu10k1.h>
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +010037#include <linux/delay.h>
James Courtier-Dutton184c1e22006-12-06 15:58:02 +000038#include <sound/tlv.h>
39
40#include "p17v.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
42#define AC97_ID_STAC9758 0x83847658
43
Takashi Iwai0cb29ea2007-01-29 15:33:49 +010044static const DECLARE_TLV_DB_SCALE(snd_audigy_db_scale2, -10350, 50, 1); /* WM8775 gain scale */
James Courtier-Dutton184c1e22006-12-06 15:58:02 +000045
Takashi Iwaieb4698f2005-11-17 14:50:13 +010046static int snd_emu10k1_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -070047{
48 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
49 uinfo->count = 1;
50 return 0;
51}
52
Takashi Iwaieb4698f2005-11-17 14:50:13 +010053static int snd_emu10k1_spdif_get(struct snd_kcontrol *kcontrol,
54 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -070055{
Takashi Iwaieb4698f2005-11-17 14:50:13 +010056 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -070057 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
58 unsigned long flags;
59
James Courtier-Dutton74415a32007-11-12 14:55:19 +000060 /* Limit: emu->spdif_bits */
61 if (idx >= 3)
62 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070063 spin_lock_irqsave(&emu->reg_lock, flags);
64 ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff;
65 ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff;
66 ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff;
67 ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff;
68 spin_unlock_irqrestore(&emu->reg_lock, flags);
69 return 0;
70}
71
Takashi Iwaieb4698f2005-11-17 14:50:13 +010072static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol,
73 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -070074{
75 ucontrol->value.iec958.status[0] = 0xff;
76 ucontrol->value.iec958.status[1] = 0xff;
77 ucontrol->value.iec958.status[2] = 0xff;
78 ucontrol->value.iec958.status[3] = 0xff;
79 return 0;
80}
81
Pavel Hofman13d45702007-06-11 12:21:20 +020082/*
83 * Items labels in enum mixer controls assigning source data to
84 * each destination
85 */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +010086static char *emu1010_src_texts[] = {
87 "Silence",
88 "Dock Mic A",
89 "Dock Mic B",
90 "Dock ADC1 Left",
91 "Dock ADC1 Right",
92 "Dock ADC2 Left",
93 "Dock ADC2 Right",
94 "Dock ADC3 Left",
95 "Dock ADC3 Right",
96 "0202 ADC Left",
97 "0202 ADC Right",
98 "0202 SPDIF Left",
99 "0202 SPDIF Right",
100 "ADAT 0",
101 "ADAT 1",
102 "ADAT 2",
103 "ADAT 3",
104 "ADAT 4",
105 "ADAT 5",
106 "ADAT 6",
107 "ADAT 7",
108 "DSP 0",
109 "DSP 1",
110 "DSP 2",
111 "DSP 3",
112 "DSP 4",
113 "DSP 5",
114 "DSP 6",
115 "DSP 7",
116 "DSP 8",
117 "DSP 9",
118 "DSP 10",
119 "DSP 11",
120 "DSP 12",
121 "DSP 13",
122 "DSP 14",
123 "DSP 15",
124 "DSP 16",
125 "DSP 17",
126 "DSP 18",
127 "DSP 19",
128 "DSP 20",
129 "DSP 21",
130 "DSP 22",
131 "DSP 23",
132 "DSP 24",
133 "DSP 25",
134 "DSP 26",
135 "DSP 27",
136 "DSP 28",
137 "DSP 29",
138 "DSP 30",
139 "DSP 31",
140};
141
Pavel Hofman13d45702007-06-11 12:21:20 +0200142/*
143 * List of data sources available for each destination
144 */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100145static unsigned int emu1010_src_regs[] = {
146 EMU_SRC_SILENCE,/* 0 */
147 EMU_SRC_DOCK_MIC_A1, /* 1 */
148 EMU_SRC_DOCK_MIC_B1, /* 2 */
149 EMU_SRC_DOCK_ADC1_LEFT1, /* 3 */
150 EMU_SRC_DOCK_ADC1_RIGHT1, /* 4 */
151 EMU_SRC_DOCK_ADC2_LEFT1, /* 5 */
152 EMU_SRC_DOCK_ADC2_RIGHT1, /* 6 */
153 EMU_SRC_DOCK_ADC3_LEFT1, /* 7 */
154 EMU_SRC_DOCK_ADC3_RIGHT1, /* 8 */
155 EMU_SRC_HAMOA_ADC_LEFT1, /* 9 */
156 EMU_SRC_HAMOA_ADC_RIGHT1, /* 10 */
157 EMU_SRC_HANA_SPDIF_LEFT1, /* 11 */
158 EMU_SRC_HANA_SPDIF_RIGHT1, /* 12 */
159 EMU_SRC_HANA_ADAT, /* 13 */
160 EMU_SRC_HANA_ADAT+1, /* 14 */
161 EMU_SRC_HANA_ADAT+2, /* 15 */
162 EMU_SRC_HANA_ADAT+3, /* 16 */
163 EMU_SRC_HANA_ADAT+4, /* 17 */
164 EMU_SRC_HANA_ADAT+5, /* 18 */
165 EMU_SRC_HANA_ADAT+6, /* 19 */
166 EMU_SRC_HANA_ADAT+7, /* 20 */
167 EMU_SRC_ALICE_EMU32A, /* 21 */
168 EMU_SRC_ALICE_EMU32A+1, /* 22 */
169 EMU_SRC_ALICE_EMU32A+2, /* 23 */
170 EMU_SRC_ALICE_EMU32A+3, /* 24 */
171 EMU_SRC_ALICE_EMU32A+4, /* 25 */
172 EMU_SRC_ALICE_EMU32A+5, /* 26 */
173 EMU_SRC_ALICE_EMU32A+6, /* 27 */
174 EMU_SRC_ALICE_EMU32A+7, /* 28 */
175 EMU_SRC_ALICE_EMU32A+8, /* 29 */
176 EMU_SRC_ALICE_EMU32A+9, /* 30 */
177 EMU_SRC_ALICE_EMU32A+0xa, /* 31 */
178 EMU_SRC_ALICE_EMU32A+0xb, /* 32 */
179 EMU_SRC_ALICE_EMU32A+0xc, /* 33 */
180 EMU_SRC_ALICE_EMU32A+0xd, /* 34 */
181 EMU_SRC_ALICE_EMU32A+0xe, /* 35 */
182 EMU_SRC_ALICE_EMU32A+0xf, /* 36 */
183 EMU_SRC_ALICE_EMU32B, /* 37 */
184 EMU_SRC_ALICE_EMU32B+1, /* 38 */
185 EMU_SRC_ALICE_EMU32B+2, /* 39 */
186 EMU_SRC_ALICE_EMU32B+3, /* 40 */
187 EMU_SRC_ALICE_EMU32B+4, /* 41 */
188 EMU_SRC_ALICE_EMU32B+5, /* 42 */
189 EMU_SRC_ALICE_EMU32B+6, /* 43 */
190 EMU_SRC_ALICE_EMU32B+7, /* 44 */
191 EMU_SRC_ALICE_EMU32B+8, /* 45 */
192 EMU_SRC_ALICE_EMU32B+9, /* 46 */
193 EMU_SRC_ALICE_EMU32B+0xa, /* 47 */
194 EMU_SRC_ALICE_EMU32B+0xb, /* 48 */
195 EMU_SRC_ALICE_EMU32B+0xc, /* 49 */
196 EMU_SRC_ALICE_EMU32B+0xd, /* 50 */
197 EMU_SRC_ALICE_EMU32B+0xe, /* 51 */
198 EMU_SRC_ALICE_EMU32B+0xf, /* 52 */
199};
200
Pavel Hofman13d45702007-06-11 12:21:20 +0200201/*
202 * Data destinations - physical EMU outputs.
203 * Each destination has an enum mixer control to choose a data source
204 */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100205static unsigned int emu1010_output_dst[] = {
206 EMU_DST_DOCK_DAC1_LEFT1, /* 0 */
207 EMU_DST_DOCK_DAC1_RIGHT1, /* 1 */
208 EMU_DST_DOCK_DAC2_LEFT1, /* 2 */
209 EMU_DST_DOCK_DAC2_RIGHT1, /* 3 */
210 EMU_DST_DOCK_DAC3_LEFT1, /* 4 */
211 EMU_DST_DOCK_DAC3_RIGHT1, /* 5 */
212 EMU_DST_DOCK_DAC4_LEFT1, /* 6 */
213 EMU_DST_DOCK_DAC4_RIGHT1, /* 7 */
214 EMU_DST_DOCK_PHONES_LEFT1, /* 8 */
215 EMU_DST_DOCK_PHONES_RIGHT1, /* 9 */
216 EMU_DST_DOCK_SPDIF_LEFT1, /* 10 */
217 EMU_DST_DOCK_SPDIF_RIGHT1, /* 11 */
218 EMU_DST_HANA_SPDIF_LEFT1, /* 12 */
219 EMU_DST_HANA_SPDIF_RIGHT1, /* 13 */
220 EMU_DST_HAMOA_DAC_LEFT1, /* 14 */
221 EMU_DST_HAMOA_DAC_RIGHT1, /* 15 */
222 EMU_DST_HANA_ADAT, /* 16 */
223 EMU_DST_HANA_ADAT+1, /* 17 */
224 EMU_DST_HANA_ADAT+2, /* 18 */
225 EMU_DST_HANA_ADAT+3, /* 19 */
226 EMU_DST_HANA_ADAT+4, /* 20 */
227 EMU_DST_HANA_ADAT+5, /* 21 */
228 EMU_DST_HANA_ADAT+6, /* 22 */
229 EMU_DST_HANA_ADAT+7, /* 23 */
230};
231
Pavel Hofman13d45702007-06-11 12:21:20 +0200232/*
233 * Data destinations - HANA outputs going to Alice2 (audigy) for
234 * capture (EMU32 + I2S links)
235 * Each destination has an enum mixer control to choose a data source
236 */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100237static unsigned int emu1010_input_dst[] = {
238 EMU_DST_ALICE2_EMU32_0,
239 EMU_DST_ALICE2_EMU32_1,
240 EMU_DST_ALICE2_EMU32_2,
241 EMU_DST_ALICE2_EMU32_3,
242 EMU_DST_ALICE2_EMU32_4,
243 EMU_DST_ALICE2_EMU32_5,
244 EMU_DST_ALICE2_EMU32_6,
245 EMU_DST_ALICE2_EMU32_7,
246 EMU_DST_ALICE2_EMU32_8,
247 EMU_DST_ALICE2_EMU32_9,
248 EMU_DST_ALICE2_EMU32_A,
249 EMU_DST_ALICE2_EMU32_B,
250 EMU_DST_ALICE2_EMU32_C,
251 EMU_DST_ALICE2_EMU32_D,
252 EMU_DST_ALICE2_EMU32_E,
253 EMU_DST_ALICE2_EMU32_F,
254 EMU_DST_ALICE_I2S0_LEFT,
255 EMU_DST_ALICE_I2S0_RIGHT,
256 EMU_DST_ALICE_I2S1_LEFT,
257 EMU_DST_ALICE_I2S1_RIGHT,
258 EMU_DST_ALICE_I2S2_LEFT,
259 EMU_DST_ALICE_I2S2_RIGHT,
260};
261
262static int snd_emu1010_input_output_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
263{
264 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
265 uinfo->count = 1;
266 uinfo->value.enumerated.items = 53;
267 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
268 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
269 strcpy(uinfo->value.enumerated.name, emu1010_src_texts[uinfo->value.enumerated.item]);
270 return 0;
271}
272
273static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol,
274 struct snd_ctl_elem_value *ucontrol)
275{
276 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000277 unsigned int channel;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100278
279 channel = (kcontrol->private_value) & 0xff;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000280 /* Limit: emu1010_output_dst, emu->emu1010.output_source */
281 if (channel >= 24)
282 return -EINVAL;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100283 ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel];
284 return 0;
285}
286
287static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol,
288 struct snd_ctl_elem_value *ucontrol)
289{
290 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
291 int change = 0;
292 unsigned int val;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000293 unsigned int channel;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100294
Takashi Iwaiaa299d02007-11-15 13:16:02 +0100295 val = ucontrol->value.enumerated.item[0];
296 if (val >= 53)
297 return -EINVAL;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100298 channel = (kcontrol->private_value) & 0xff;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000299 /* Limit: emu1010_output_dst, emu->emu1010.output_source */
300 if (channel >= 24)
301 return -EINVAL;
Takashi Iwaiaa299d02007-11-15 13:16:02 +0100302 if (emu->emu1010.output_source[channel] != val) {
303 emu->emu1010.output_source[channel] = val;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100304 change = 1;
305 snd_emu1010_fpga_link_dst_src_write(emu,
306 emu1010_output_dst[channel], emu1010_src_regs[val]);
307 }
308 return change;
309}
310
311static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol,
312 struct snd_ctl_elem_value *ucontrol)
313{
314 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000315 unsigned int channel;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100316
317 channel = (kcontrol->private_value) & 0xff;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000318 /* Limit: emu1010_input_dst, emu->emu1010.input_source */
319 if (channel >= 22)
320 return -EINVAL;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100321 ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel];
322 return 0;
323}
324
325static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
326 struct snd_ctl_elem_value *ucontrol)
327{
328 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
329 int change = 0;
330 unsigned int val;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000331 unsigned int channel;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100332
Takashi Iwaiaa299d02007-11-15 13:16:02 +0100333 val = ucontrol->value.enumerated.item[0];
334 if (val >= 53)
335 return -EINVAL;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100336 channel = (kcontrol->private_value) & 0xff;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000337 /* Limit: emu1010_input_dst, emu->emu1010.input_source */
338 if (channel >= 22)
339 return -EINVAL;
Takashi Iwaiaa299d02007-11-15 13:16:02 +0100340 if (emu->emu1010.input_source[channel] != val) {
341 emu->emu1010.input_source[channel] = val;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100342 change = 1;
343 snd_emu1010_fpga_link_dst_src_write(emu,
344 emu1010_input_dst[channel], emu1010_src_regs[val]);
345 }
346 return change;
347}
348
349#define EMU1010_SOURCE_OUTPUT(xname,chid) \
350{ \
351 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
352 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
353 .info = snd_emu1010_input_output_source_info, \
354 .get = snd_emu1010_output_source_get, \
355 .put = snd_emu1010_output_source_put, \
356 .private_value = chid \
357}
358
359static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = {
James Courtier-Dutton4c07c812006-11-11 10:48:58 +0000360 EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0),
361 EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1),
362 EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2),
363 EMU1010_SOURCE_OUTPUT("Dock DAC2 Right Playback Enum", 3),
364 EMU1010_SOURCE_OUTPUT("Dock DAC3 Left Playback Enum", 4),
365 EMU1010_SOURCE_OUTPUT("Dock DAC3 Right Playback Enum", 5),
366 EMU1010_SOURCE_OUTPUT("Dock DAC4 Left Playback Enum", 6),
367 EMU1010_SOURCE_OUTPUT("Dock DAC4 Right Playback Enum", 7),
368 EMU1010_SOURCE_OUTPUT("Dock Phones Left Playback Enum", 8),
369 EMU1010_SOURCE_OUTPUT("Dock Phones Right Playback Enum", 9),
370 EMU1010_SOURCE_OUTPUT("Dock SPDIF Left Playback Enum", 0xa),
371 EMU1010_SOURCE_OUTPUT("Dock SPDIF Right Playback Enum", 0xb),
372 EMU1010_SOURCE_OUTPUT("1010 SPDIF Left Playback Enum", 0xc),
373 EMU1010_SOURCE_OUTPUT("1010 SPDIF Right Playback Enum", 0xd),
374 EMU1010_SOURCE_OUTPUT("0202 DAC Left Playback Enum", 0xe),
375 EMU1010_SOURCE_OUTPUT("0202 DAC Right Playback Enum", 0xf),
376 EMU1010_SOURCE_OUTPUT("1010 ADAT 0 Playback Enum", 0x10),
377 EMU1010_SOURCE_OUTPUT("1010 ADAT 1 Playback Enum", 0x11),
378 EMU1010_SOURCE_OUTPUT("1010 ADAT 2 Playback Enum", 0x12),
379 EMU1010_SOURCE_OUTPUT("1010 ADAT 3 Playback Enum", 0x13),
380 EMU1010_SOURCE_OUTPUT("1010 ADAT 4 Playback Enum", 0x14),
381 EMU1010_SOURCE_OUTPUT("1010 ADAT 5 Playback Enum", 0x15),
382 EMU1010_SOURCE_OUTPUT("1010 ADAT 6 Playback Enum", 0x16),
383 EMU1010_SOURCE_OUTPUT("1010 ADAT 7 Playback Enum", 0x17),
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100384};
385
386#define EMU1010_SOURCE_INPUT(xname,chid) \
387{ \
388 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
389 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
390 .info = snd_emu1010_input_output_source_info, \
391 .get = snd_emu1010_input_source_get, \
392 .put = snd_emu1010_input_source_put, \
393 .private_value = chid \
394}
395
396static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] __devinitdata = {
James Courtier-Dutton4c07c812006-11-11 10:48:58 +0000397 EMU1010_SOURCE_INPUT("DSP 0 Capture Enum", 0),
398 EMU1010_SOURCE_INPUT("DSP 1 Capture Enum", 1),
399 EMU1010_SOURCE_INPUT("DSP 2 Capture Enum", 2),
400 EMU1010_SOURCE_INPUT("DSP 3 Capture Enum", 3),
401 EMU1010_SOURCE_INPUT("DSP 4 Capture Enum", 4),
402 EMU1010_SOURCE_INPUT("DSP 5 Capture Enum", 5),
403 EMU1010_SOURCE_INPUT("DSP 6 Capture Enum", 6),
404 EMU1010_SOURCE_INPUT("DSP 7 Capture Enum", 7),
405 EMU1010_SOURCE_INPUT("DSP 8 Capture Enum", 8),
406 EMU1010_SOURCE_INPUT("DSP 9 Capture Enum", 9),
407 EMU1010_SOURCE_INPUT("DSP A Capture Enum", 0xa),
408 EMU1010_SOURCE_INPUT("DSP B Capture Enum", 0xb),
409 EMU1010_SOURCE_INPUT("DSP C Capture Enum", 0xc),
410 EMU1010_SOURCE_INPUT("DSP D Capture Enum", 0xd),
411 EMU1010_SOURCE_INPUT("DSP E Capture Enum", 0xe),
412 EMU1010_SOURCE_INPUT("DSP F Capture Enum", 0xf),
413 EMU1010_SOURCE_INPUT("DSP 10 Capture Enum", 0x10),
414 EMU1010_SOURCE_INPUT("DSP 11 Capture Enum", 0x11),
415 EMU1010_SOURCE_INPUT("DSP 12 Capture Enum", 0x12),
416 EMU1010_SOURCE_INPUT("DSP 13 Capture Enum", 0x13),
417 EMU1010_SOURCE_INPUT("DSP 14 Capture Enum", 0x14),
418 EMU1010_SOURCE_INPUT("DSP 15 Capture Enum", 0x15),
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100419};
420
421
422
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200423#define snd_emu1010_adc_pads_info snd_ctl_boolean_mono_info
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100424
425static int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
426{
427 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
428 unsigned int mask = kcontrol->private_value & 0xff;
429 ucontrol->value.integer.value[0] = (emu->emu1010.adc_pads & mask) ? 1 : 0;
430 return 0;
431}
432
433static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
434{
435 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
436 unsigned int mask = kcontrol->private_value & 0xff;
437 unsigned int val, cache;
438 val = ucontrol->value.integer.value[0];
439 cache = emu->emu1010.adc_pads;
440 if (val == 1)
441 cache = cache | mask;
442 else
443 cache = cache & ~mask;
444 if (cache != emu->emu1010.adc_pads) {
445 snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache );
446 emu->emu1010.adc_pads = cache;
447 }
448
449 return 0;
450}
451
452
453
454#define EMU1010_ADC_PADS(xname,chid) \
455{ \
456 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
457 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
458 .info = snd_emu1010_adc_pads_info, \
459 .get = snd_emu1010_adc_pads_get, \
460 .put = snd_emu1010_adc_pads_put, \
461 .private_value = chid \
462}
463
464static struct snd_kcontrol_new snd_emu1010_adc_pads[] __devinitdata = {
465 EMU1010_ADC_PADS("ADC1 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD1),
466 EMU1010_ADC_PADS("ADC2 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD2),
467 EMU1010_ADC_PADS("ADC3 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD3),
468 EMU1010_ADC_PADS("ADC1 14dB PAD 0202 Capture Switch", EMU_HANA_0202_ADC_PAD1),
469};
470
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200471#define snd_emu1010_dac_pads_info snd_ctl_boolean_mono_info
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100472
473static int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
474{
475 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
476 unsigned int mask = kcontrol->private_value & 0xff;
477 ucontrol->value.integer.value[0] = (emu->emu1010.dac_pads & mask) ? 1 : 0;
478 return 0;
479}
480
481static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
482{
483 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
484 unsigned int mask = kcontrol->private_value & 0xff;
485 unsigned int val, cache;
486 val = ucontrol->value.integer.value[0];
487 cache = emu->emu1010.dac_pads;
488 if (val == 1)
489 cache = cache | mask;
490 else
491 cache = cache & ~mask;
492 if (cache != emu->emu1010.dac_pads) {
493 snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache );
494 emu->emu1010.dac_pads = cache;
495 }
496
497 return 0;
498}
499
500
501
502#define EMU1010_DAC_PADS(xname,chid) \
503{ \
504 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
505 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
506 .info = snd_emu1010_dac_pads_info, \
507 .get = snd_emu1010_dac_pads_get, \
508 .put = snd_emu1010_dac_pads_put, \
509 .private_value = chid \
510}
511
512static struct snd_kcontrol_new snd_emu1010_dac_pads[] __devinitdata = {
513 EMU1010_DAC_PADS("DAC1 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD1),
514 EMU1010_DAC_PADS("DAC2 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD2),
515 EMU1010_DAC_PADS("DAC3 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD3),
516 EMU1010_DAC_PADS("DAC4 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD4),
517 EMU1010_DAC_PADS("DAC1 0202 14dB PAD Playback Switch", EMU_HANA_0202_DAC_PAD1),
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100518};
519
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100520
521static int snd_emu1010_internal_clock_info(struct snd_kcontrol *kcontrol,
522 struct snd_ctl_elem_info *uinfo)
523{
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100524 static char *texts[4] = {
525 "44100", "48000", "SPDIF", "ADAT"
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100526 };
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100527
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100528 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
529 uinfo->count = 1;
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100530 uinfo->value.enumerated.items = 4;
531 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
532 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100533 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
534 return 0;
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100535
536
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100537}
538
539static int snd_emu1010_internal_clock_get(struct snd_kcontrol *kcontrol,
540 struct snd_ctl_elem_value *ucontrol)
541{
542 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
543
544 ucontrol->value.enumerated.item[0] = emu->emu1010.internal_clock;
545 return 0;
546}
547
548static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol,
549 struct snd_ctl_elem_value *ucontrol)
550{
551 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
552 unsigned int val;
553 int change = 0;
554
555 val = ucontrol->value.enumerated.item[0] ;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000556 /* Limit: uinfo->value.enumerated.items = 4; */
557 if (val >= 4)
558 return -EINVAL;
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100559 change = (emu->emu1010.internal_clock != val);
560 if (change) {
561 emu->emu1010.internal_clock = val;
562 switch (val) {
563 case 0:
564 /* 44100 */
565 /* Mute all */
566 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
567 /* Default fallback clock 48kHz */
568 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_44_1K );
569 /* Word Clock source, Internal 44.1kHz x1 */
570 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
571 EMU_HANA_WCLOCK_INT_44_1K | EMU_HANA_WCLOCK_1X );
572 /* Set LEDs on Audio Dock */
573 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
574 EMU_HANA_DOCK_LEDS_2_44K | EMU_HANA_DOCK_LEDS_2_LOCK );
575 /* Allow DLL to settle */
James Courtier-Duttone40a0b22006-10-10 18:44:29 +0100576 msleep(10);
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100577 /* Unmute all */
578 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
579 break;
580 case 1:
581 /* 48000 */
582 /* Mute all */
583 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
584 /* Default fallback clock 48kHz */
585 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
586 /* Word Clock source, Internal 48kHz x1 */
587 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
588 EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_1X );
589 /* Set LEDs on Audio Dock */
590 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
591 EMU_HANA_DOCK_LEDS_2_48K | EMU_HANA_DOCK_LEDS_2_LOCK );
592 /* Allow DLL to settle */
James Courtier-Duttone40a0b22006-10-10 18:44:29 +0100593 msleep(10);
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100594 /* Unmute all */
595 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
596 break;
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100597
598 case 2: /* Take clock from S/PDIF IN */
599 /* Mute all */
600 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
601 /* Default fallback clock 48kHz */
602 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
603 /* Word Clock source, sync to S/PDIF input */
604 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
605 EMU_HANA_WCLOCK_HANA_SPDIF_IN | EMU_HANA_WCLOCK_1X );
606 /* Set LEDs on Audio Dock */
607 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
608 EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK );
609 /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */
610 /* Allow DLL to settle */
611 msleep(10);
612 /* Unmute all */
613 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
614 break;
615
616 case 3:
617 /* Take clock from ADAT IN */
618 /* Mute all */
619 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
620 /* Default fallback clock 48kHz */
621 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
622 /* Word Clock source, sync to ADAT input */
623 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
624 EMU_HANA_WCLOCK_HANA_ADAT_IN | EMU_HANA_WCLOCK_1X );
625 /* Set LEDs on Audio Dock */
626 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK );
627 /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */
628 /* Allow DLL to settle */
629 msleep(10);
630 /* Unmute all */
631 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
632
633
634 break;
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100635 }
636 }
637 return change;
638}
639
640static struct snd_kcontrol_new snd_emu1010_internal_clock =
641{
642 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
643 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
644 .name = "Clock Internal Rate",
645 .count = 1,
646 .info = snd_emu1010_internal_clock_info,
647 .get = snd_emu1010_internal_clock_get,
648 .put = snd_emu1010_internal_clock_put
649};
650
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000651static int snd_audigy_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
652 struct snd_ctl_elem_info *uinfo)
653{
654#if 0
655 static char *texts[4] = {
656 "Unknown1", "Unknown2", "Mic", "Line"
657 };
658#endif
659 static char *texts[2] = {
660 "Mic", "Line"
661 };
662
663 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
664 uinfo->count = 1;
665 uinfo->value.enumerated.items = 2;
666 if (uinfo->value.enumerated.item > 1)
667 uinfo->value.enumerated.item = 1;
668 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
669 return 0;
670}
671
672static int snd_audigy_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
673 struct snd_ctl_elem_value *ucontrol)
674{
675 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
676
677 ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
678 return 0;
679}
680
681static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
682 struct snd_ctl_elem_value *ucontrol)
683{
684 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
685 unsigned int source_id;
686 unsigned int ngain, ogain;
687 u32 gpio;
688 int change = 0;
689 unsigned long flags;
690 u32 source;
691 /* If the capture source has changed,
692 * update the capture volume from the cached value
693 * for the particular source.
694 */
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000695 source_id = ucontrol->value.enumerated.item[0];
696 /* Limit: uinfo->value.enumerated.items = 2; */
697 /* emu->i2c_capture_volume */
698 if (source_id >= 2)
699 return -EINVAL;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000700 change = (emu->i2c_capture_source != source_id);
701 if (change) {
702 snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */
703 spin_lock_irqsave(&emu->emu_lock, flags);
704 gpio = inl(emu->port + A_IOCFG);
705 if (source_id==0)
706 outl(gpio | 0x4, emu->port + A_IOCFG);
707 else
708 outl(gpio & ~0x4, emu->port + A_IOCFG);
709 spin_unlock_irqrestore(&emu->emu_lock, flags);
710
711 ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
712 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
713 if (ngain != ogain)
714 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
715 ngain = emu->i2c_capture_volume[source_id][1]; /* Right */
716 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
717 if (ngain != ogain)
718 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
719
720 source = 1 << (source_id + 2);
721 snd_emu10k1_i2c_write(emu, ADC_MUX, source); /* Set source */
722 emu->i2c_capture_source = source_id;
723 }
724 return change;
725}
726
727static struct snd_kcontrol_new snd_audigy_i2c_capture_source =
728{
729 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
730 .name = "Capture Source",
731 .info = snd_audigy_i2c_capture_source_info,
732 .get = snd_audigy_i2c_capture_source_get,
733 .put = snd_audigy_i2c_capture_source_put
734};
735
736static int snd_audigy_i2c_volume_info(struct snd_kcontrol *kcontrol,
737 struct snd_ctl_elem_info *uinfo)
738{
739 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
740 uinfo->count = 2;
741 uinfo->value.integer.min = 0;
742 uinfo->value.integer.max = 255;
743 return 0;
744}
745
746static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol,
747 struct snd_ctl_elem_value *ucontrol)
748{
749 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000750 unsigned int source_id;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000751
752 source_id = kcontrol->private_value;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000753 /* Limit: emu->i2c_capture_volume */
754 /* capture_source: uinfo->value.enumerated.items = 2 */
755 if (source_id >= 2)
756 return -EINVAL;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000757
758 ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
759 ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
760 return 0;
761}
762
763static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
764 struct snd_ctl_elem_value *ucontrol)
765{
766 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
767 unsigned int ogain;
768 unsigned int ngain;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000769 unsigned int source_id;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000770 int change = 0;
771
772 source_id = kcontrol->private_value;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000773 /* Limit: emu->i2c_capture_volume */
774 /* capture_source: uinfo->value.enumerated.items = 2 */
775 if (source_id >= 2)
776 return -EINVAL;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000777 ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
778 ngain = ucontrol->value.integer.value[0];
779 if (ngain > 0xff)
780 return 0;
781 if (ogain != ngain) {
782 if (emu->i2c_capture_source == source_id)
783 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000784 emu->i2c_capture_volume[source_id][0] = ngain;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000785 change = 1;
786 }
787 ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
788 ngain = ucontrol->value.integer.value[1];
789 if (ngain > 0xff)
790 return 0;
791 if (ogain != ngain) {
792 if (emu->i2c_capture_source == source_id)
793 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000794 emu->i2c_capture_volume[source_id][1] = ngain;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000795 change = 1;
796 }
797
798 return change;
799}
800
801#define I2C_VOLUME(xname,chid) \
802{ \
803 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
804 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
805 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
806 .info = snd_audigy_i2c_volume_info, \
807 .get = snd_audigy_i2c_volume_get, \
808 .put = snd_audigy_i2c_volume_put, \
809 .tlv = { .p = snd_audigy_db_scale2 }, \
810 .private_value = chid \
811}
812
813
814static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] __devinitdata = {
815 I2C_VOLUME("Mic Capture Volume", 0),
816 I2C_VOLUME("Line Capture Volume", 0)
817};
818
Takashi Iwai0af68e52005-04-11 17:03:03 +0200819#if 0
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100820static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821{
822 static char *texts[] = {"44100", "48000", "96000"};
823
824 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
825 uinfo->count = 1;
826 uinfo->value.enumerated.items = 3;
827 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
828 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
829 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
830 return 0;
831}
832
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100833static int snd_audigy_spdif_output_rate_get(struct snd_kcontrol *kcontrol,
834 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100836 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 unsigned int tmp;
838 unsigned long flags;
839
840
841 spin_lock_irqsave(&emu->reg_lock, flags);
842 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
843 switch (tmp & A_SPDIF_RATE_MASK) {
844 case A_SPDIF_44100:
845 ucontrol->value.enumerated.item[0] = 0;
846 break;
847 case A_SPDIF_48000:
848 ucontrol->value.enumerated.item[0] = 1;
849 break;
850 case A_SPDIF_96000:
851 ucontrol->value.enumerated.item[0] = 2;
852 break;
853 default:
854 ucontrol->value.enumerated.item[0] = 1;
855 }
856 spin_unlock_irqrestore(&emu->reg_lock, flags);
857 return 0;
858}
859
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100860static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol,
861 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100863 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 int change;
865 unsigned int reg, val, tmp;
866 unsigned long flags;
867
868 switch(ucontrol->value.enumerated.item[0]) {
869 case 0:
870 val = A_SPDIF_44100;
871 break;
872 case 1:
873 val = A_SPDIF_48000;
874 break;
875 case 2:
876 val = A_SPDIF_96000;
877 break;
878 default:
879 val = A_SPDIF_48000;
880 break;
881 }
882
883
884 spin_lock_irqsave(&emu->reg_lock, flags);
885 reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
886 tmp = reg & ~A_SPDIF_RATE_MASK;
887 tmp |= val;
888 if ((change = (tmp != reg)))
889 snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
890 spin_unlock_irqrestore(&emu->reg_lock, flags);
891 return change;
892}
893
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100894static struct snd_kcontrol_new snd_audigy_spdif_output_rate =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895{
896 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
897 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
898 .name = "Audigy SPDIF Output Sample Rate",
899 .count = 1,
900 .info = snd_audigy_spdif_output_rate_info,
901 .get = snd_audigy_spdif_output_rate_get,
902 .put = snd_audigy_spdif_output_rate_put
903};
Takashi Iwai0af68e52005-04-11 17:03:03 +0200904#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100906static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol,
907 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100909 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
911 int change;
912 unsigned int val;
913 unsigned long flags;
914
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000915 /* Limit: emu->spdif_bits */
916 if (idx >= 3)
917 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 val = (ucontrol->value.iec958.status[0] << 0) |
919 (ucontrol->value.iec958.status[1] << 8) |
920 (ucontrol->value.iec958.status[2] << 16) |
921 (ucontrol->value.iec958.status[3] << 24);
922 spin_lock_irqsave(&emu->reg_lock, flags);
923 change = val != emu->spdif_bits[idx];
924 if (change) {
925 snd_emu10k1_ptr_write(emu, SPCS0 + idx, 0, val);
926 emu->spdif_bits[idx] = val;
927 }
928 spin_unlock_irqrestore(&emu->reg_lock, flags);
929 return change;
930}
931
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100932static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933{
934 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +0200935 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
Takashi Iwai7583cb52007-08-16 19:32:16 +0200937 .count = 3,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 .info = snd_emu10k1_spdif_info,
939 .get = snd_emu10k1_spdif_get_mask
940};
941
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100942static struct snd_kcontrol_new snd_emu10k1_spdif_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943{
Clemens Ladisch5549d542005-08-03 13:50:30 +0200944 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
Takashi Iwai7583cb52007-08-16 19:32:16 +0200946 .count = 3,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 .info = snd_emu10k1_spdif_info,
948 .get = snd_emu10k1_spdif_get,
949 .put = snd_emu10k1_spdif_put
950};
951
952
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100953static void update_emu10k1_fxrt(struct snd_emu10k1 *emu, int voice, unsigned char *route)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954{
955 if (emu->audigy) {
956 snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
957 snd_emu10k1_compose_audigy_fxrt1(route));
958 snd_emu10k1_ptr_write(emu, A_FXRT2, voice,
959 snd_emu10k1_compose_audigy_fxrt2(route));
960 } else {
961 snd_emu10k1_ptr_write(emu, FXRT, voice,
962 snd_emu10k1_compose_send_routing(route));
963 }
964}
965
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100966static void update_emu10k1_send_volume(struct snd_emu10k1 *emu, int voice, unsigned char *volume)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967{
968 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]);
969 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]);
970 snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, volume[2]);
971 snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, volume[3]);
972 if (emu->audigy) {
973 unsigned int val = ((unsigned int)volume[4] << 24) |
974 ((unsigned int)volume[5] << 16) |
975 ((unsigned int)volume[6] << 8) |
976 (unsigned int)volume[7];
977 snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, val);
978 }
979}
980
981/* PCM stream controls */
982
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100983static int snd_emu10k1_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100985 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
987 uinfo->count = emu->audigy ? 3*8 : 3*4;
988 uinfo->value.integer.min = 0;
989 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
990 return 0;
991}
992
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100993static int snd_emu10k1_send_routing_get(struct snd_kcontrol *kcontrol,
994 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995{
996 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100997 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
998 struct snd_emu10k1_pcm_mixer *mix =
999 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 int voice, idx;
1001 int num_efx = emu->audigy ? 8 : 4;
1002 int mask = emu->audigy ? 0x3f : 0x0f;
1003
1004 spin_lock_irqsave(&emu->reg_lock, flags);
1005 for (voice = 0; voice < 3; voice++)
1006 for (idx = 0; idx < num_efx; idx++)
1007 ucontrol->value.integer.value[(voice * num_efx) + idx] =
1008 mix->send_routing[voice][idx] & mask;
1009 spin_unlock_irqrestore(&emu->reg_lock, flags);
1010 return 0;
1011}
1012
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001013static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol,
1014 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015{
1016 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001017 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1018 struct snd_emu10k1_pcm_mixer *mix =
1019 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 int change = 0, voice, idx, val;
1021 int num_efx = emu->audigy ? 8 : 4;
1022 int mask = emu->audigy ? 0x3f : 0x0f;
1023
1024 spin_lock_irqsave(&emu->reg_lock, flags);
1025 for (voice = 0; voice < 3; voice++)
1026 for (idx = 0; idx < num_efx; idx++) {
1027 val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask;
1028 if (mix->send_routing[voice][idx] != val) {
1029 mix->send_routing[voice][idx] = val;
1030 change = 1;
1031 }
1032 }
1033 if (change && mix->epcm) {
1034 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1035 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
1036 &mix->send_routing[1][0]);
1037 update_emu10k1_fxrt(emu, mix->epcm->voices[1]->number,
1038 &mix->send_routing[2][0]);
1039 } else if (mix->epcm->voices[0]) {
1040 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
1041 &mix->send_routing[0][0]);
1042 }
1043 }
1044 spin_unlock_irqrestore(&emu->reg_lock, flags);
1045 return change;
1046}
1047
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001048static struct snd_kcontrol_new snd_emu10k1_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049{
1050 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001051 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 .name = "EMU10K1 PCM Send Routing",
1053 .count = 32,
1054 .info = snd_emu10k1_send_routing_info,
1055 .get = snd_emu10k1_send_routing_get,
1056 .put = snd_emu10k1_send_routing_put
1057};
1058
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001059static int snd_emu10k1_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001061 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1063 uinfo->count = emu->audigy ? 3*8 : 3*4;
1064 uinfo->value.integer.min = 0;
1065 uinfo->value.integer.max = 255;
1066 return 0;
1067}
1068
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001069static int snd_emu10k1_send_volume_get(struct snd_kcontrol *kcontrol,
1070 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071{
1072 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001073 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1074 struct snd_emu10k1_pcm_mixer *mix =
1075 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 int idx;
1077 int num_efx = emu->audigy ? 8 : 4;
1078
1079 spin_lock_irqsave(&emu->reg_lock, flags);
1080 for (idx = 0; idx < 3*num_efx; idx++)
1081 ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx];
1082 spin_unlock_irqrestore(&emu->reg_lock, flags);
1083 return 0;
1084}
1085
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001086static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol,
1087 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088{
1089 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001090 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1091 struct snd_emu10k1_pcm_mixer *mix =
1092 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 int change = 0, idx, val;
1094 int num_efx = emu->audigy ? 8 : 4;
1095
1096 spin_lock_irqsave(&emu->reg_lock, flags);
1097 for (idx = 0; idx < 3*num_efx; idx++) {
1098 val = ucontrol->value.integer.value[idx] & 255;
1099 if (mix->send_volume[idx/num_efx][idx%num_efx] != val) {
1100 mix->send_volume[idx/num_efx][idx%num_efx] = val;
1101 change = 1;
1102 }
1103 }
1104 if (change && mix->epcm) {
1105 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1106 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
1107 &mix->send_volume[1][0]);
1108 update_emu10k1_send_volume(emu, mix->epcm->voices[1]->number,
1109 &mix->send_volume[2][0]);
1110 } else if (mix->epcm->voices[0]) {
1111 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
1112 &mix->send_volume[0][0]);
1113 }
1114 }
1115 spin_unlock_irqrestore(&emu->reg_lock, flags);
1116 return change;
1117}
1118
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001119static struct snd_kcontrol_new snd_emu10k1_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120{
1121 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001122 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 .name = "EMU10K1 PCM Send Volume",
1124 .count = 32,
1125 .info = snd_emu10k1_send_volume_info,
1126 .get = snd_emu10k1_send_volume_get,
1127 .put = snd_emu10k1_send_volume_put
1128};
1129
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001130static int snd_emu10k1_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131{
1132 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1133 uinfo->count = 3;
1134 uinfo->value.integer.min = 0;
1135 uinfo->value.integer.max = 0xffff;
1136 return 0;
1137}
1138
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001139static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol,
1140 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001142 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1143 struct snd_emu10k1_pcm_mixer *mix =
1144 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 unsigned long flags;
1146 int idx;
1147
1148 spin_lock_irqsave(&emu->reg_lock, flags);
1149 for (idx = 0; idx < 3; idx++)
1150 ucontrol->value.integer.value[idx] = mix->attn[idx];
1151 spin_unlock_irqrestore(&emu->reg_lock, flags);
1152 return 0;
1153}
1154
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001155static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol,
1156 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157{
1158 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001159 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1160 struct snd_emu10k1_pcm_mixer *mix =
1161 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 int change = 0, idx, val;
1163
1164 spin_lock_irqsave(&emu->reg_lock, flags);
1165 for (idx = 0; idx < 3; idx++) {
1166 val = ucontrol->value.integer.value[idx] & 0xffff;
1167 if (mix->attn[idx] != val) {
1168 mix->attn[idx] = val;
1169 change = 1;
1170 }
1171 }
1172 if (change && mix->epcm) {
1173 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1174 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[1]);
1175 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[1]->number, mix->attn[2]);
1176 } else if (mix->epcm->voices[0]) {
1177 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]);
1178 }
1179 }
1180 spin_unlock_irqrestore(&emu->reg_lock, flags);
1181 return change;
1182}
1183
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001184static struct snd_kcontrol_new snd_emu10k1_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185{
1186 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001187 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 .name = "EMU10K1 PCM Volume",
1189 .count = 32,
1190 .info = snd_emu10k1_attn_info,
1191 .get = snd_emu10k1_attn_get,
1192 .put = snd_emu10k1_attn_put
1193};
1194
1195/* Mutichannel PCM stream controls */
1196
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001197static int snd_emu10k1_efx_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001199 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1201 uinfo->count = emu->audigy ? 8 : 4;
1202 uinfo->value.integer.min = 0;
1203 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
1204 return 0;
1205}
1206
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001207static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol,
1208 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209{
1210 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001211 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1212 struct snd_emu10k1_pcm_mixer *mix =
1213 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 int idx;
1215 int num_efx = emu->audigy ? 8 : 4;
1216 int mask = emu->audigy ? 0x3f : 0x0f;
1217
1218 spin_lock_irqsave(&emu->reg_lock, flags);
1219 for (idx = 0; idx < num_efx; idx++)
1220 ucontrol->value.integer.value[idx] =
1221 mix->send_routing[0][idx] & mask;
1222 spin_unlock_irqrestore(&emu->reg_lock, flags);
1223 return 0;
1224}
1225
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001226static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol,
1227 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228{
1229 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001230 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001232 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 int change = 0, idx, val;
1234 int num_efx = emu->audigy ? 8 : 4;
1235 int mask = emu->audigy ? 0x3f : 0x0f;
1236
1237 spin_lock_irqsave(&emu->reg_lock, flags);
1238 for (idx = 0; idx < num_efx; idx++) {
1239 val = ucontrol->value.integer.value[idx] & mask;
1240 if (mix->send_routing[0][idx] != val) {
1241 mix->send_routing[0][idx] = val;
1242 change = 1;
1243 }
1244 }
1245
1246 if (change && mix->epcm) {
1247 if (mix->epcm->voices[ch]) {
1248 update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number,
1249 &mix->send_routing[0][0]);
1250 }
1251 }
1252 spin_unlock_irqrestore(&emu->reg_lock, flags);
1253 return change;
1254}
1255
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001256static struct snd_kcontrol_new snd_emu10k1_efx_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257{
1258 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1259 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1260 .name = "Multichannel PCM Send Routing",
1261 .count = 16,
1262 .info = snd_emu10k1_efx_send_routing_info,
1263 .get = snd_emu10k1_efx_send_routing_get,
1264 .put = snd_emu10k1_efx_send_routing_put
1265};
1266
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001267static int snd_emu10k1_efx_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001269 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1271 uinfo->count = emu->audigy ? 8 : 4;
1272 uinfo->value.integer.min = 0;
1273 uinfo->value.integer.max = 255;
1274 return 0;
1275}
1276
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001277static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol,
1278 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279{
1280 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001281 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1282 struct snd_emu10k1_pcm_mixer *mix =
1283 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 int idx;
1285 int num_efx = emu->audigy ? 8 : 4;
1286
1287 spin_lock_irqsave(&emu->reg_lock, flags);
1288 for (idx = 0; idx < num_efx; idx++)
1289 ucontrol->value.integer.value[idx] = mix->send_volume[0][idx];
1290 spin_unlock_irqrestore(&emu->reg_lock, flags);
1291 return 0;
1292}
1293
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001294static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol,
1295 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296{
1297 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001298 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001300 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 int change = 0, idx, val;
1302 int num_efx = emu->audigy ? 8 : 4;
1303
1304 spin_lock_irqsave(&emu->reg_lock, flags);
1305 for (idx = 0; idx < num_efx; idx++) {
1306 val = ucontrol->value.integer.value[idx] & 255;
1307 if (mix->send_volume[0][idx] != val) {
1308 mix->send_volume[0][idx] = val;
1309 change = 1;
1310 }
1311 }
1312 if (change && mix->epcm) {
1313 if (mix->epcm->voices[ch]) {
1314 update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number,
1315 &mix->send_volume[0][0]);
1316 }
1317 }
1318 spin_unlock_irqrestore(&emu->reg_lock, flags);
1319 return change;
1320}
1321
1322
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001323static struct snd_kcontrol_new snd_emu10k1_efx_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324{
1325 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1326 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1327 .name = "Multichannel PCM Send Volume",
1328 .count = 16,
1329 .info = snd_emu10k1_efx_send_volume_info,
1330 .get = snd_emu10k1_efx_send_volume_get,
1331 .put = snd_emu10k1_efx_send_volume_put
1332};
1333
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001334static int snd_emu10k1_efx_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335{
1336 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1337 uinfo->count = 1;
1338 uinfo->value.integer.min = 0;
1339 uinfo->value.integer.max = 0xffff;
1340 return 0;
1341}
1342
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001343static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol,
1344 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001346 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1347 struct snd_emu10k1_pcm_mixer *mix =
1348 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 unsigned long flags;
1350
1351 spin_lock_irqsave(&emu->reg_lock, flags);
1352 ucontrol->value.integer.value[0] = mix->attn[0];
1353 spin_unlock_irqrestore(&emu->reg_lock, flags);
1354 return 0;
1355}
1356
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001357static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol,
1358 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359{
1360 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001361 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001363 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 int change = 0, val;
1365
1366 spin_lock_irqsave(&emu->reg_lock, flags);
1367 val = ucontrol->value.integer.value[0] & 0xffff;
1368 if (mix->attn[0] != val) {
1369 mix->attn[0] = val;
1370 change = 1;
1371 }
1372 if (change && mix->epcm) {
1373 if (mix->epcm->voices[ch]) {
1374 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]);
1375 }
1376 }
1377 spin_unlock_irqrestore(&emu->reg_lock, flags);
1378 return change;
1379}
1380
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001381static struct snd_kcontrol_new snd_emu10k1_efx_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382{
1383 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1384 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1385 .name = "Multichannel PCM Volume",
1386 .count = 16,
1387 .info = snd_emu10k1_efx_attn_info,
1388 .get = snd_emu10k1_efx_attn_get,
1389 .put = snd_emu10k1_efx_attn_put
1390};
1391
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001392#define snd_emu10k1_shared_spdif_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001394static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol,
1395 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001397 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398
1399 if (emu->audigy)
1400 ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0;
1401 else
1402 ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0;
1403 return 0;
1404}
1405
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001406static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
1407 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408{
1409 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001410 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 unsigned int reg, val;
1412 int change = 0;
1413
1414 spin_lock_irqsave(&emu->reg_lock, flags);
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001415 if ( emu->card_capabilities->i2c_adc) {
1416 /* Do nothing for Audigy 2 ZS Notebook */
1417 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 reg = inl(emu->port + A_IOCFG);
1419 val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0;
1420 change = (reg & A_IOCFG_GPOUT0) != val;
1421 if (change) {
1422 reg &= ~A_IOCFG_GPOUT0;
1423 reg |= val;
1424 outl(reg | val, emu->port + A_IOCFG);
1425 }
1426 }
1427 reg = inl(emu->port + HCFG);
1428 val = ucontrol->value.integer.value[0] ? HCFG_GPOUT0 : 0;
1429 change |= (reg & HCFG_GPOUT0) != val;
1430 if (change) {
1431 reg &= ~HCFG_GPOUT0;
1432 reg |= val;
1433 outl(reg | val, emu->port + HCFG);
1434 }
1435 spin_unlock_irqrestore(&emu->reg_lock, flags);
1436 return change;
1437}
1438
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001439static struct snd_kcontrol_new snd_emu10k1_shared_spdif __devinitdata =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440{
1441 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1442 .name = "SB Live Analog/Digital Output Jack",
1443 .info = snd_emu10k1_shared_spdif_info,
1444 .get = snd_emu10k1_shared_spdif_get,
1445 .put = snd_emu10k1_shared_spdif_put
1446};
1447
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001448static struct snd_kcontrol_new snd_audigy_shared_spdif __devinitdata =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449{
1450 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1451 .name = "Audigy Analog/Digital Output Jack",
1452 .info = snd_emu10k1_shared_spdif_info,
1453 .get = snd_emu10k1_shared_spdif_get,
1454 .put = snd_emu10k1_shared_spdif_put
1455};
1456
1457/*
1458 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001459static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001461 struct snd_emu10k1 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 emu->ac97 = NULL;
1463}
1464
1465/*
1466 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001467static int remove_ctl(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001469 struct snd_ctl_elem_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 memset(&id, 0, sizeof(id));
1471 strcpy(id.name, name);
1472 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1473 return snd_ctl_remove_id(card, &id);
1474}
1475
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001476static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001478 struct snd_ctl_elem_id sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 memset(&sid, 0, sizeof(sid));
1480 strcpy(sid.name, name);
1481 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1482 return snd_ctl_find_id(card, &sid);
1483}
1484
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001485static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001487 struct snd_kcontrol *kctl = ctl_find(card, src);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 if (kctl) {
1489 strcpy(kctl->id.name, dst);
1490 return 0;
1491 }
1492 return -ENOENT;
1493}
1494
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001495int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001496 int pcm_device, int multi_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497{
1498 int err, pcm;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001499 struct snd_kcontrol *kctl;
1500 struct snd_card *card = emu->card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 char **c;
1502 static char *emu10k1_remove_ctls[] = {
1503 /* no AC97 mono, surround, center/lfe */
1504 "Master Mono Playback Switch",
1505 "Master Mono Playback Volume",
1506 "PCM Out Path & Mute",
1507 "Mono Output Select",
Takashi Iwai7eae36f2006-01-05 18:40:56 +01001508 "Front Playback Switch",
1509 "Front Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 "Surround Playback Switch",
1511 "Surround Playback Volume",
1512 "Center Playback Switch",
1513 "Center Playback Volume",
1514 "LFE Playback Switch",
1515 "LFE Playback Volume",
1516 NULL
1517 };
1518 static char *emu10k1_rename_ctls[] = {
1519 "Surround Digital Playback Volume", "Surround Playback Volume",
1520 "Center Digital Playback Volume", "Center Playback Volume",
1521 "LFE Digital Playback Volume", "LFE Playback Volume",
1522 NULL
1523 };
1524 static char *audigy_remove_ctls[] = {
1525 /* Master/PCM controls on ac97 of Audigy has no effect */
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001526 /* On the Audigy2 the AC97 playback is piped into
1527 * the Philips ADC for 24bit capture */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 "PCM Playback Switch",
1529 "PCM Playback Volume",
1530 "Master Mono Playback Switch",
1531 "Master Mono Playback Volume",
1532 "Master Playback Switch",
1533 "Master Playback Volume",
1534 "PCM Out Path & Mute",
1535 "Mono Output Select",
1536 /* remove unused AC97 capture controls */
1537 "Capture Source",
1538 "Capture Switch",
1539 "Capture Volume",
1540 "Mic Select",
1541 "Video Playback Switch",
1542 "Video Playback Volume",
1543 "Mic Playback Switch",
1544 "Mic Playback Volume",
1545 NULL
1546 };
1547 static char *audigy_rename_ctls[] = {
1548 /* use conventional names */
1549 "Wave Playback Volume", "PCM Playback Volume",
1550 /* "Wave Capture Volume", "PCM Capture Volume", */
1551 "Wave Master Playback Volume", "Master Playback Volume",
1552 "AMic Playback Volume", "Mic Playback Volume",
1553 NULL
1554 };
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001555 static char *audigy_rename_ctls_i2c_adc[] = {
1556 //"Analog Mix Capture Volume","OLD Analog Mix Capture Volume",
1557 "Line Capture Volume", "Analog Mix Capture Volume",
1558 "Wave Playback Volume", "OLD PCM Playback Volume",
1559 "Wave Master Playback Volume", "Master Playback Volume",
1560 "AMic Playback Volume", "Old Mic Playback Volume",
James Courtier-Duttoneb41dab2006-12-06 20:38:45 +00001561 "CD Capture Volume", "IEC958 Optical Capture Volume",
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001562 NULL
1563 };
1564 static char *audigy_remove_ctls_i2c_adc[] = {
1565 /* On the Audigy2 ZS Notebook
1566 * Capture via WM8775 */
1567 "Mic Capture Volume",
1568 "Analog Mix Capture Volume",
1569 "Aux Capture Volume",
James Courtier-Duttoneb41dab2006-12-06 20:38:45 +00001570 "IEC958 Optical Capture Volume",
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001571 NULL
1572 };
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001573 static char *audigy_remove_ctls_1361t_adc[] = {
1574 /* On the Audigy2 the AC97 playback is piped into
1575 * the Philips ADC for 24bit capture */
1576 "PCM Playback Switch",
1577 "PCM Playback Volume",
1578 "Master Mono Playback Switch",
1579 "Master Mono Playback Volume",
1580 "Capture Source",
1581 "Capture Switch",
1582 "Capture Volume",
1583 "Mic Capture Volume",
1584 "Headphone Playback Switch",
1585 "Headphone Playback Volume",
1586 "3D Control - Center",
1587 "3D Control - Depth",
1588 "3D Control - Switch",
1589 "Line2 Playback Volume",
1590 "Line2 Capture Volume",
1591 NULL
1592 };
1593 static char *audigy_rename_ctls_1361t_adc[] = {
1594 "Master Playback Switch", "Master Capture Switch",
1595 "Master Playback Volume", "Master Capture Volume",
1596 "Wave Master Playback Volume", "Master Playback Volume",
1597 "PC Speaker Playback Switch", "PC Speaker Capture Switch",
1598 "PC Speaker Playback Volume", "PC Speaker Capture Volume",
1599 "Phone Playback Switch", "Phone Capture Switch",
1600 "Phone Playback Volume", "Phone Capture Volume",
1601 "Mic Playback Switch", "Mic Capture Switch",
1602 "Mic Playback Volume", "Mic Capture Volume",
1603 "Line Playback Switch", "Line Capture Switch",
1604 "Line Playback Volume", "Line Capture Volume",
1605 "CD Playback Switch", "CD Capture Switch",
1606 "CD Playback Volume", "CD Capture Volume",
1607 "Aux Playback Switch", "Aux Capture Switch",
1608 "Aux Playback Volume", "Aux Capture Volume",
1609 "Video Playback Switch", "Video Capture Switch",
1610 "Video Playback Volume", "Video Capture Volume",
1611
1612 NULL
1613 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614
Lee Revell2b637da2005-03-30 13:51:18 +02001615 if (emu->card_capabilities->ac97_chip) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001616 struct snd_ac97_bus *pbus;
1617 struct snd_ac97_template ac97;
1618 static struct snd_ac97_bus_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619 .write = snd_emu10k1_ac97_write,
1620 .read = snd_emu10k1_ac97_read,
1621 };
1622
Takashi Iwaib1508692005-10-04 13:49:32 +02001623 if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0)
1624 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 pbus->no_vra = 1; /* we don't need VRA */
1626
1627 memset(&ac97, 0, sizeof(ac97));
1628 ac97.private_data = emu;
1629 ac97.private_free = snd_emu10k1_mixer_free_ac97;
1630 ac97.scaps = AC97_SCAP_NO_SPDIF;
Takashi Iwaib1508692005-10-04 13:49:32 +02001631 if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) {
1632 if (emu->card_capabilities->ac97_chip == 1)
1633 return err;
1634 snd_printd(KERN_INFO "emu10k1: AC97 is optional on this board\n");
1635 snd_printd(KERN_INFO" Proceeding without ac97 mixers...\n");
1636 snd_device_free(emu->card, pbus);
1637 goto no_ac97; /* FIXME: get rid of ugly gotos.. */
1638 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 if (emu->audigy) {
1640 /* set master volume to 0 dB */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001641 snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 /* set capture source to mic */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001643 snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001644 if (emu->card_capabilities->adc_1361t)
1645 c = audigy_remove_ctls_1361t_adc;
1646 else
1647 c = audigy_remove_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 } else {
1649 /*
1650 * Credits for cards based on STAC9758:
1651 * James Courtier-Dutton <James@superbug.demon.co.uk>
1652 * Voluspa <voluspa@comhem.se>
1653 */
1654 if (emu->ac97->id == AC97_ID_STAC9758) {
1655 emu->rear_ac97 = 1;
1656 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 +01001657 snd_ac97_write_cache(emu->ac97, AC97_HEADPHONE, 0x0202);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 }
1659 /* remove unused AC97 controls */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001660 snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
1661 snd_ac97_write_cache(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 c = emu10k1_remove_ctls;
1663 }
1664 for (; *c; c++)
1665 remove_ctl(card, *c);
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001666 } else if (emu->card_capabilities->i2c_adc) {
1667 c = audigy_remove_ctls_i2c_adc;
1668 for (; *c; c++)
1669 remove_ctl(card, *c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670 } else {
Takashi Iwaif12aa402005-09-30 16:56:59 +02001671 no_ac97:
Lee Revell2b637da2005-03-30 13:51:18 +02001672 if (emu->card_capabilities->ecard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 strcpy(emu->card->mixername, "EMU APS");
1674 else if (emu->audigy)
1675 strcpy(emu->card->mixername, "SB Audigy");
1676 else
1677 strcpy(emu->card->mixername, "Emu10k1");
1678 }
1679
1680 if (emu->audigy)
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001681 if (emu->card_capabilities->adc_1361t)
1682 c = audigy_rename_ctls_1361t_adc;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001683 else if (emu->card_capabilities->i2c_adc)
1684 c = audigy_rename_ctls_i2c_adc;
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001685 else
1686 c = audigy_rename_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687 else
1688 c = emu10k1_rename_ctls;
1689 for (; *c; c += 2)
1690 rename_ctl(card, c[0], c[1]);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001691
James Courtier-Duttone3b9bc02005-12-24 16:54:51 +01001692 if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */
1693 rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume");
1694 rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume");
1695 rename_ctl(card, "Aux2 Capture Volume", "Line3 Capture Volume");
1696 rename_ctl(card, "Mic Capture Volume", "Unknown1 Capture Volume");
1697 remove_ctl(card, "Headphone Playback Switch");
1698 remove_ctl(card, "Headphone Playback Volume");
1699 remove_ctl(card, "3D Control - Center");
1700 remove_ctl(card, "3D Control - Depth");
1701 remove_ctl(card, "3D Control - Switch");
1702 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL)
1704 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001705 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 if ((err = snd_ctl_add(card, kctl)))
1707 return err;
1708 if ((kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL)
1709 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001710 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 if ((err = snd_ctl_add(card, kctl)))
1712 return err;
1713 if ((kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu)) == NULL)
1714 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001715 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 if ((err = snd_ctl_add(card, kctl)))
1717 return err;
1718
1719 if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL)
1720 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001721 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 if ((err = snd_ctl_add(card, kctl)))
1723 return err;
1724
1725 if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL)
1726 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001727 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728 if ((err = snd_ctl_add(card, kctl)))
1729 return err;
1730
1731 if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL)
1732 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001733 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 if ((err = snd_ctl_add(card, kctl)))
1735 return err;
1736
1737 /* initialize the routing and volume table for each pcm playback stream */
1738 for (pcm = 0; pcm < 32; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001739 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 int v;
1741
1742 mix = &emu->pcm_mixer[pcm];
1743 mix->epcm = NULL;
1744
1745 for (v = 0; v < 4; v++)
1746 mix->send_routing[0][v] =
1747 mix->send_routing[1][v] =
1748 mix->send_routing[2][v] = v;
1749
1750 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1751 mix->send_volume[0][0] = mix->send_volume[0][1] =
1752 mix->send_volume[1][0] = mix->send_volume[2][1] = 255;
1753
1754 mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
1755 }
1756
1757 /* initialize the routing and volume table for the multichannel playback stream */
1758 for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001759 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760 int v;
1761
1762 mix = &emu->efx_pcm_mixer[pcm];
1763 mix->epcm = NULL;
1764
1765 mix->send_routing[0][0] = pcm;
1766 mix->send_routing[0][1] = (pcm == 0) ? 1 : 0;
1767 for (v = 0; v < 2; v++)
1768 mix->send_routing[0][2+v] = 13+v;
1769 if (emu->audigy)
1770 for (v = 0; v < 4; v++)
1771 mix->send_routing[0][4+v] = 60+v;
1772
1773 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1774 mix->send_volume[0][0] = 255;
1775
1776 mix->attn[0] = 0xffff;
1777 }
1778
Lee Revell2b637da2005-03-30 13:51:18 +02001779 if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780 /* sb live! and audigy */
1781 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
1782 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02001783 if (!emu->audigy)
1784 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 if ((err = snd_ctl_add(card, kctl)))
1786 return err;
1787 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
1788 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02001789 if (!emu->audigy)
1790 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 if ((err = snd_ctl_add(card, kctl)))
1792 return err;
1793 }
1794
James Courtier-Dutton190d2c42007-11-04 14:08:26 +00001795 if (emu->card_capabilities->emu_model) {
James Courtier-Dutton19b99fb2005-12-04 18:03:03 +01001796 ; /* Disable the snd_audigy_spdif_shared_spdif */
1797 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798 if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
1799 return -ENOMEM;
1800 if ((err = snd_ctl_add(card, kctl)))
1801 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02001802#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803 if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
1804 return -ENOMEM;
1805 if ((err = snd_ctl_add(card, kctl)))
1806 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02001807#endif
Lee Revell2b637da2005-03-30 13:51:18 +02001808 } else if (! emu->card_capabilities->ecard) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809 /* sb live! */
1810 if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
1811 return -ENOMEM;
1812 if ((err = snd_ctl_add(card, kctl)))
1813 return err;
1814 }
Lee Revell2b637da2005-03-30 13:51:18 +02001815 if (emu->card_capabilities->ca0151_chip) { /* P16V */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816 if ((err = snd_p16v_mixer(emu)))
1817 return err;
1818 }
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001819
James Courtier-Dutton190d2c42007-11-04 14:08:26 +00001820 if (emu->card_capabilities->emu_model) {
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001821 int i;
1822
1823 for (i = 0; i < ARRAY_SIZE(snd_emu1010_output_enum_ctls); i++) {
1824 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_output_enum_ctls[i], emu));
1825 if (err < 0)
1826 return err;
1827 }
1828 for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) {
1829 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], emu));
1830 if (err < 0)
1831 return err;
1832 }
James Courtier-Dutton9148cc52006-10-09 23:08:00 +01001833 for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads); i++) {
1834 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_adc_pads[i], emu));
1835 if (err < 0)
1836 return err;
1837 }
1838 for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads); i++) {
1839 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_dac_pads[i], emu));
1840 if (err < 0)
1841 return err;
1842 }
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +01001843 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_internal_clock, emu));
1844 if (err < 0)
1845 return err;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001846 }
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001847
1848 if ( emu->card_capabilities->i2c_adc) {
1849 int i;
1850
1851 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_capture_source, emu));
1852 if (err < 0)
1853 return err;
1854
1855 for (i = 0; i < ARRAY_SIZE(snd_audigy_i2c_volume_ctls); i++) {
1856 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_volume_ctls[i], emu));
1857 if (err < 0)
1858 return err;
1859 }
1860 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861
1862 return 0;
1863}