blob: 88eab4a461bd1cfcffad35ff3ce98eb7b2044782 [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
33#include <sound/driver.h>
34#include <linux/time.h>
35#include <linux/init.h>
36#include <sound/core.h>
37#include <sound/emu10k1.h>
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +010038#include <linux/delay.h>
James Courtier-Dutton184c1e22006-12-06 15:58:02 +000039#include <sound/tlv.h>
40
41#include "p17v.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
43#define AC97_ID_STAC9758 0x83847658
44
Takashi Iwai0cb29ea2007-01-29 15:33:49 +010045static const DECLARE_TLV_DB_SCALE(snd_audigy_db_scale2, -10350, 50, 1); /* WM8775 gain scale */
James Courtier-Dutton184c1e22006-12-06 15:58:02 +000046
Takashi Iwaieb4698f2005-11-17 14:50:13 +010047static int snd_emu10k1_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -070048{
49 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
50 uinfo->count = 1;
51 return 0;
52}
53
Takashi Iwaieb4698f2005-11-17 14:50:13 +010054static int snd_emu10k1_spdif_get(struct snd_kcontrol *kcontrol,
55 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -070056{
Takashi Iwaieb4698f2005-11-17 14:50:13 +010057 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -070058 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
59 unsigned long flags;
60
James Courtier-Dutton74415a32007-11-12 14:55:19 +000061 /* Limit: emu->spdif_bits */
62 if (idx >= 3)
63 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070064 spin_lock_irqsave(&emu->reg_lock, flags);
65 ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff;
66 ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff;
67 ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff;
68 ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff;
69 spin_unlock_irqrestore(&emu->reg_lock, flags);
70 return 0;
71}
72
Takashi Iwaieb4698f2005-11-17 14:50:13 +010073static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol,
74 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -070075{
76 ucontrol->value.iec958.status[0] = 0xff;
77 ucontrol->value.iec958.status[1] = 0xff;
78 ucontrol->value.iec958.status[2] = 0xff;
79 ucontrol->value.iec958.status[3] = 0xff;
80 return 0;
81}
82
Pavel Hofman13d45702007-06-11 12:21:20 +020083/*
84 * Items labels in enum mixer controls assigning source data to
85 * each destination
86 */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +010087static char *emu1010_src_texts[] = {
88 "Silence",
89 "Dock Mic A",
90 "Dock Mic B",
91 "Dock ADC1 Left",
92 "Dock ADC1 Right",
93 "Dock ADC2 Left",
94 "Dock ADC2 Right",
95 "Dock ADC3 Left",
96 "Dock ADC3 Right",
97 "0202 ADC Left",
98 "0202 ADC Right",
99 "0202 SPDIF Left",
100 "0202 SPDIF Right",
101 "ADAT 0",
102 "ADAT 1",
103 "ADAT 2",
104 "ADAT 3",
105 "ADAT 4",
106 "ADAT 5",
107 "ADAT 6",
108 "ADAT 7",
109 "DSP 0",
110 "DSP 1",
111 "DSP 2",
112 "DSP 3",
113 "DSP 4",
114 "DSP 5",
115 "DSP 6",
116 "DSP 7",
117 "DSP 8",
118 "DSP 9",
119 "DSP 10",
120 "DSP 11",
121 "DSP 12",
122 "DSP 13",
123 "DSP 14",
124 "DSP 15",
125 "DSP 16",
126 "DSP 17",
127 "DSP 18",
128 "DSP 19",
129 "DSP 20",
130 "DSP 21",
131 "DSP 22",
132 "DSP 23",
133 "DSP 24",
134 "DSP 25",
135 "DSP 26",
136 "DSP 27",
137 "DSP 28",
138 "DSP 29",
139 "DSP 30",
140 "DSP 31",
141};
142
Pavel Hofman13d45702007-06-11 12:21:20 +0200143/*
144 * List of data sources available for each destination
145 */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100146static unsigned int emu1010_src_regs[] = {
147 EMU_SRC_SILENCE,/* 0 */
148 EMU_SRC_DOCK_MIC_A1, /* 1 */
149 EMU_SRC_DOCK_MIC_B1, /* 2 */
150 EMU_SRC_DOCK_ADC1_LEFT1, /* 3 */
151 EMU_SRC_DOCK_ADC1_RIGHT1, /* 4 */
152 EMU_SRC_DOCK_ADC2_LEFT1, /* 5 */
153 EMU_SRC_DOCK_ADC2_RIGHT1, /* 6 */
154 EMU_SRC_DOCK_ADC3_LEFT1, /* 7 */
155 EMU_SRC_DOCK_ADC3_RIGHT1, /* 8 */
156 EMU_SRC_HAMOA_ADC_LEFT1, /* 9 */
157 EMU_SRC_HAMOA_ADC_RIGHT1, /* 10 */
158 EMU_SRC_HANA_SPDIF_LEFT1, /* 11 */
159 EMU_SRC_HANA_SPDIF_RIGHT1, /* 12 */
160 EMU_SRC_HANA_ADAT, /* 13 */
161 EMU_SRC_HANA_ADAT+1, /* 14 */
162 EMU_SRC_HANA_ADAT+2, /* 15 */
163 EMU_SRC_HANA_ADAT+3, /* 16 */
164 EMU_SRC_HANA_ADAT+4, /* 17 */
165 EMU_SRC_HANA_ADAT+5, /* 18 */
166 EMU_SRC_HANA_ADAT+6, /* 19 */
167 EMU_SRC_HANA_ADAT+7, /* 20 */
168 EMU_SRC_ALICE_EMU32A, /* 21 */
169 EMU_SRC_ALICE_EMU32A+1, /* 22 */
170 EMU_SRC_ALICE_EMU32A+2, /* 23 */
171 EMU_SRC_ALICE_EMU32A+3, /* 24 */
172 EMU_SRC_ALICE_EMU32A+4, /* 25 */
173 EMU_SRC_ALICE_EMU32A+5, /* 26 */
174 EMU_SRC_ALICE_EMU32A+6, /* 27 */
175 EMU_SRC_ALICE_EMU32A+7, /* 28 */
176 EMU_SRC_ALICE_EMU32A+8, /* 29 */
177 EMU_SRC_ALICE_EMU32A+9, /* 30 */
178 EMU_SRC_ALICE_EMU32A+0xa, /* 31 */
179 EMU_SRC_ALICE_EMU32A+0xb, /* 32 */
180 EMU_SRC_ALICE_EMU32A+0xc, /* 33 */
181 EMU_SRC_ALICE_EMU32A+0xd, /* 34 */
182 EMU_SRC_ALICE_EMU32A+0xe, /* 35 */
183 EMU_SRC_ALICE_EMU32A+0xf, /* 36 */
184 EMU_SRC_ALICE_EMU32B, /* 37 */
185 EMU_SRC_ALICE_EMU32B+1, /* 38 */
186 EMU_SRC_ALICE_EMU32B+2, /* 39 */
187 EMU_SRC_ALICE_EMU32B+3, /* 40 */
188 EMU_SRC_ALICE_EMU32B+4, /* 41 */
189 EMU_SRC_ALICE_EMU32B+5, /* 42 */
190 EMU_SRC_ALICE_EMU32B+6, /* 43 */
191 EMU_SRC_ALICE_EMU32B+7, /* 44 */
192 EMU_SRC_ALICE_EMU32B+8, /* 45 */
193 EMU_SRC_ALICE_EMU32B+9, /* 46 */
194 EMU_SRC_ALICE_EMU32B+0xa, /* 47 */
195 EMU_SRC_ALICE_EMU32B+0xb, /* 48 */
196 EMU_SRC_ALICE_EMU32B+0xc, /* 49 */
197 EMU_SRC_ALICE_EMU32B+0xd, /* 50 */
198 EMU_SRC_ALICE_EMU32B+0xe, /* 51 */
199 EMU_SRC_ALICE_EMU32B+0xf, /* 52 */
200};
201
Pavel Hofman13d45702007-06-11 12:21:20 +0200202/*
203 * Data destinations - physical EMU outputs.
204 * Each destination has an enum mixer control to choose a data source
205 */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100206static unsigned int emu1010_output_dst[] = {
207 EMU_DST_DOCK_DAC1_LEFT1, /* 0 */
208 EMU_DST_DOCK_DAC1_RIGHT1, /* 1 */
209 EMU_DST_DOCK_DAC2_LEFT1, /* 2 */
210 EMU_DST_DOCK_DAC2_RIGHT1, /* 3 */
211 EMU_DST_DOCK_DAC3_LEFT1, /* 4 */
212 EMU_DST_DOCK_DAC3_RIGHT1, /* 5 */
213 EMU_DST_DOCK_DAC4_LEFT1, /* 6 */
214 EMU_DST_DOCK_DAC4_RIGHT1, /* 7 */
215 EMU_DST_DOCK_PHONES_LEFT1, /* 8 */
216 EMU_DST_DOCK_PHONES_RIGHT1, /* 9 */
217 EMU_DST_DOCK_SPDIF_LEFT1, /* 10 */
218 EMU_DST_DOCK_SPDIF_RIGHT1, /* 11 */
219 EMU_DST_HANA_SPDIF_LEFT1, /* 12 */
220 EMU_DST_HANA_SPDIF_RIGHT1, /* 13 */
221 EMU_DST_HAMOA_DAC_LEFT1, /* 14 */
222 EMU_DST_HAMOA_DAC_RIGHT1, /* 15 */
223 EMU_DST_HANA_ADAT, /* 16 */
224 EMU_DST_HANA_ADAT+1, /* 17 */
225 EMU_DST_HANA_ADAT+2, /* 18 */
226 EMU_DST_HANA_ADAT+3, /* 19 */
227 EMU_DST_HANA_ADAT+4, /* 20 */
228 EMU_DST_HANA_ADAT+5, /* 21 */
229 EMU_DST_HANA_ADAT+6, /* 22 */
230 EMU_DST_HANA_ADAT+7, /* 23 */
231};
232
Pavel Hofman13d45702007-06-11 12:21:20 +0200233/*
234 * Data destinations - HANA outputs going to Alice2 (audigy) for
235 * capture (EMU32 + I2S links)
236 * Each destination has an enum mixer control to choose a data source
237 */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100238static unsigned int emu1010_input_dst[] = {
239 EMU_DST_ALICE2_EMU32_0,
240 EMU_DST_ALICE2_EMU32_1,
241 EMU_DST_ALICE2_EMU32_2,
242 EMU_DST_ALICE2_EMU32_3,
243 EMU_DST_ALICE2_EMU32_4,
244 EMU_DST_ALICE2_EMU32_5,
245 EMU_DST_ALICE2_EMU32_6,
246 EMU_DST_ALICE2_EMU32_7,
247 EMU_DST_ALICE2_EMU32_8,
248 EMU_DST_ALICE2_EMU32_9,
249 EMU_DST_ALICE2_EMU32_A,
250 EMU_DST_ALICE2_EMU32_B,
251 EMU_DST_ALICE2_EMU32_C,
252 EMU_DST_ALICE2_EMU32_D,
253 EMU_DST_ALICE2_EMU32_E,
254 EMU_DST_ALICE2_EMU32_F,
255 EMU_DST_ALICE_I2S0_LEFT,
256 EMU_DST_ALICE_I2S0_RIGHT,
257 EMU_DST_ALICE_I2S1_LEFT,
258 EMU_DST_ALICE_I2S1_RIGHT,
259 EMU_DST_ALICE_I2S2_LEFT,
260 EMU_DST_ALICE_I2S2_RIGHT,
261};
262
263static int snd_emu1010_input_output_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
264{
265 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
266 uinfo->count = 1;
267 uinfo->value.enumerated.items = 53;
268 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
269 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
270 strcpy(uinfo->value.enumerated.name, emu1010_src_texts[uinfo->value.enumerated.item]);
271 return 0;
272}
273
274static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol,
275 struct snd_ctl_elem_value *ucontrol)
276{
277 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000278 unsigned int channel;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100279
280 channel = (kcontrol->private_value) & 0xff;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000281 /* Limit: emu1010_output_dst, emu->emu1010.output_source */
282 if (channel >= 24)
283 return -EINVAL;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100284 ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel];
285 return 0;
286}
287
288static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol,
289 struct snd_ctl_elem_value *ucontrol)
290{
291 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
292 int change = 0;
293 unsigned int val;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000294 unsigned int channel;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100295
296 channel = (kcontrol->private_value) & 0xff;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000297 /* Limit: emu1010_output_dst, emu->emu1010.output_source */
298 if (channel >= 24)
299 return -EINVAL;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100300 if (emu->emu1010.output_source[channel] != ucontrol->value.enumerated.item[0]) {
301 val = emu->emu1010.output_source[channel] = ucontrol->value.enumerated.item[0];
302 change = 1;
303 snd_emu1010_fpga_link_dst_src_write(emu,
304 emu1010_output_dst[channel], emu1010_src_regs[val]);
305 }
306 return change;
307}
308
309static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol,
310 struct snd_ctl_elem_value *ucontrol)
311{
312 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000313 unsigned int channel;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100314
315 channel = (kcontrol->private_value) & 0xff;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000316 /* Limit: emu1010_input_dst, emu->emu1010.input_source */
317 if (channel >= 22)
318 return -EINVAL;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100319 ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel];
320 return 0;
321}
322
323static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
324 struct snd_ctl_elem_value *ucontrol)
325{
326 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
327 int change = 0;
328 unsigned int val;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000329 unsigned int channel;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100330
331 channel = (kcontrol->private_value) & 0xff;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000332 /* Limit: emu1010_input_dst, emu->emu1010.input_source */
333 if (channel >= 22)
334 return -EINVAL;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100335 if (emu->emu1010.input_source[channel] != ucontrol->value.enumerated.item[0]) {
336 val = emu->emu1010.input_source[channel] = ucontrol->value.enumerated.item[0];
337 change = 1;
338 snd_emu1010_fpga_link_dst_src_write(emu,
339 emu1010_input_dst[channel], emu1010_src_regs[val]);
340 }
341 return change;
342}
343
344#define EMU1010_SOURCE_OUTPUT(xname,chid) \
345{ \
346 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
347 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
348 .info = snd_emu1010_input_output_source_info, \
349 .get = snd_emu1010_output_source_get, \
350 .put = snd_emu1010_output_source_put, \
351 .private_value = chid \
352}
353
354static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = {
James Courtier-Dutton4c07c812006-11-11 10:48:58 +0000355 EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0),
356 EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1),
357 EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2),
358 EMU1010_SOURCE_OUTPUT("Dock DAC2 Right Playback Enum", 3),
359 EMU1010_SOURCE_OUTPUT("Dock DAC3 Left Playback Enum", 4),
360 EMU1010_SOURCE_OUTPUT("Dock DAC3 Right Playback Enum", 5),
361 EMU1010_SOURCE_OUTPUT("Dock DAC4 Left Playback Enum", 6),
362 EMU1010_SOURCE_OUTPUT("Dock DAC4 Right Playback Enum", 7),
363 EMU1010_SOURCE_OUTPUT("Dock Phones Left Playback Enum", 8),
364 EMU1010_SOURCE_OUTPUT("Dock Phones Right Playback Enum", 9),
365 EMU1010_SOURCE_OUTPUT("Dock SPDIF Left Playback Enum", 0xa),
366 EMU1010_SOURCE_OUTPUT("Dock SPDIF Right Playback Enum", 0xb),
367 EMU1010_SOURCE_OUTPUT("1010 SPDIF Left Playback Enum", 0xc),
368 EMU1010_SOURCE_OUTPUT("1010 SPDIF Right Playback Enum", 0xd),
369 EMU1010_SOURCE_OUTPUT("0202 DAC Left Playback Enum", 0xe),
370 EMU1010_SOURCE_OUTPUT("0202 DAC Right Playback Enum", 0xf),
371 EMU1010_SOURCE_OUTPUT("1010 ADAT 0 Playback Enum", 0x10),
372 EMU1010_SOURCE_OUTPUT("1010 ADAT 1 Playback Enum", 0x11),
373 EMU1010_SOURCE_OUTPUT("1010 ADAT 2 Playback Enum", 0x12),
374 EMU1010_SOURCE_OUTPUT("1010 ADAT 3 Playback Enum", 0x13),
375 EMU1010_SOURCE_OUTPUT("1010 ADAT 4 Playback Enum", 0x14),
376 EMU1010_SOURCE_OUTPUT("1010 ADAT 5 Playback Enum", 0x15),
377 EMU1010_SOURCE_OUTPUT("1010 ADAT 6 Playback Enum", 0x16),
378 EMU1010_SOURCE_OUTPUT("1010 ADAT 7 Playback Enum", 0x17),
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100379};
380
381#define EMU1010_SOURCE_INPUT(xname,chid) \
382{ \
383 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
384 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
385 .info = snd_emu1010_input_output_source_info, \
386 .get = snd_emu1010_input_source_get, \
387 .put = snd_emu1010_input_source_put, \
388 .private_value = chid \
389}
390
391static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] __devinitdata = {
James Courtier-Dutton4c07c812006-11-11 10:48:58 +0000392 EMU1010_SOURCE_INPUT("DSP 0 Capture Enum", 0),
393 EMU1010_SOURCE_INPUT("DSP 1 Capture Enum", 1),
394 EMU1010_SOURCE_INPUT("DSP 2 Capture Enum", 2),
395 EMU1010_SOURCE_INPUT("DSP 3 Capture Enum", 3),
396 EMU1010_SOURCE_INPUT("DSP 4 Capture Enum", 4),
397 EMU1010_SOURCE_INPUT("DSP 5 Capture Enum", 5),
398 EMU1010_SOURCE_INPUT("DSP 6 Capture Enum", 6),
399 EMU1010_SOURCE_INPUT("DSP 7 Capture Enum", 7),
400 EMU1010_SOURCE_INPUT("DSP 8 Capture Enum", 8),
401 EMU1010_SOURCE_INPUT("DSP 9 Capture Enum", 9),
402 EMU1010_SOURCE_INPUT("DSP A Capture Enum", 0xa),
403 EMU1010_SOURCE_INPUT("DSP B Capture Enum", 0xb),
404 EMU1010_SOURCE_INPUT("DSP C Capture Enum", 0xc),
405 EMU1010_SOURCE_INPUT("DSP D Capture Enum", 0xd),
406 EMU1010_SOURCE_INPUT("DSP E Capture Enum", 0xe),
407 EMU1010_SOURCE_INPUT("DSP F Capture Enum", 0xf),
408 EMU1010_SOURCE_INPUT("DSP 10 Capture Enum", 0x10),
409 EMU1010_SOURCE_INPUT("DSP 11 Capture Enum", 0x11),
410 EMU1010_SOURCE_INPUT("DSP 12 Capture Enum", 0x12),
411 EMU1010_SOURCE_INPUT("DSP 13 Capture Enum", 0x13),
412 EMU1010_SOURCE_INPUT("DSP 14 Capture Enum", 0x14),
413 EMU1010_SOURCE_INPUT("DSP 15 Capture Enum", 0x15),
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100414};
415
416
417
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200418#define snd_emu1010_adc_pads_info snd_ctl_boolean_mono_info
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100419
420static int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
421{
422 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
423 unsigned int mask = kcontrol->private_value & 0xff;
424 ucontrol->value.integer.value[0] = (emu->emu1010.adc_pads & mask) ? 1 : 0;
425 return 0;
426}
427
428static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
429{
430 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
431 unsigned int mask = kcontrol->private_value & 0xff;
432 unsigned int val, cache;
433 val = ucontrol->value.integer.value[0];
434 cache = emu->emu1010.adc_pads;
435 if (val == 1)
436 cache = cache | mask;
437 else
438 cache = cache & ~mask;
439 if (cache != emu->emu1010.adc_pads) {
440 snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache );
441 emu->emu1010.adc_pads = cache;
442 }
443
444 return 0;
445}
446
447
448
449#define EMU1010_ADC_PADS(xname,chid) \
450{ \
451 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
452 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
453 .info = snd_emu1010_adc_pads_info, \
454 .get = snd_emu1010_adc_pads_get, \
455 .put = snd_emu1010_adc_pads_put, \
456 .private_value = chid \
457}
458
459static struct snd_kcontrol_new snd_emu1010_adc_pads[] __devinitdata = {
460 EMU1010_ADC_PADS("ADC1 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD1),
461 EMU1010_ADC_PADS("ADC2 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD2),
462 EMU1010_ADC_PADS("ADC3 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD3),
463 EMU1010_ADC_PADS("ADC1 14dB PAD 0202 Capture Switch", EMU_HANA_0202_ADC_PAD1),
464};
465
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200466#define snd_emu1010_dac_pads_info snd_ctl_boolean_mono_info
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100467
468static int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
469{
470 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
471 unsigned int mask = kcontrol->private_value & 0xff;
472 ucontrol->value.integer.value[0] = (emu->emu1010.dac_pads & mask) ? 1 : 0;
473 return 0;
474}
475
476static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
477{
478 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
479 unsigned int mask = kcontrol->private_value & 0xff;
480 unsigned int val, cache;
481 val = ucontrol->value.integer.value[0];
482 cache = emu->emu1010.dac_pads;
483 if (val == 1)
484 cache = cache | mask;
485 else
486 cache = cache & ~mask;
487 if (cache != emu->emu1010.dac_pads) {
488 snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache );
489 emu->emu1010.dac_pads = cache;
490 }
491
492 return 0;
493}
494
495
496
497#define EMU1010_DAC_PADS(xname,chid) \
498{ \
499 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
500 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
501 .info = snd_emu1010_dac_pads_info, \
502 .get = snd_emu1010_dac_pads_get, \
503 .put = snd_emu1010_dac_pads_put, \
504 .private_value = chid \
505}
506
507static struct snd_kcontrol_new snd_emu1010_dac_pads[] __devinitdata = {
508 EMU1010_DAC_PADS("DAC1 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD1),
509 EMU1010_DAC_PADS("DAC2 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD2),
510 EMU1010_DAC_PADS("DAC3 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD3),
511 EMU1010_DAC_PADS("DAC4 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD4),
512 EMU1010_DAC_PADS("DAC1 0202 14dB PAD Playback Switch", EMU_HANA_0202_DAC_PAD1),
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100513};
514
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100515
516static int snd_emu1010_internal_clock_info(struct snd_kcontrol *kcontrol,
517 struct snd_ctl_elem_info *uinfo)
518{
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100519 static char *texts[4] = {
520 "44100", "48000", "SPDIF", "ADAT"
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100521 };
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100522
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100523 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
524 uinfo->count = 1;
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100525 uinfo->value.enumerated.items = 4;
526 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
527 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100528 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
529 return 0;
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100530
531
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100532}
533
534static int snd_emu1010_internal_clock_get(struct snd_kcontrol *kcontrol,
535 struct snd_ctl_elem_value *ucontrol)
536{
537 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
538
539 ucontrol->value.enumerated.item[0] = emu->emu1010.internal_clock;
540 return 0;
541}
542
543static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol,
544 struct snd_ctl_elem_value *ucontrol)
545{
546 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
547 unsigned int val;
548 int change = 0;
549
550 val = ucontrol->value.enumerated.item[0] ;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000551 /* Limit: uinfo->value.enumerated.items = 4; */
552 if (val >= 4)
553 return -EINVAL;
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100554 change = (emu->emu1010.internal_clock != val);
555 if (change) {
556 emu->emu1010.internal_clock = val;
557 switch (val) {
558 case 0:
559 /* 44100 */
560 /* Mute all */
561 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
562 /* Default fallback clock 48kHz */
563 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_44_1K );
564 /* Word Clock source, Internal 44.1kHz x1 */
565 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
566 EMU_HANA_WCLOCK_INT_44_1K | EMU_HANA_WCLOCK_1X );
567 /* Set LEDs on Audio Dock */
568 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
569 EMU_HANA_DOCK_LEDS_2_44K | EMU_HANA_DOCK_LEDS_2_LOCK );
570 /* Allow DLL to settle */
James Courtier-Duttone40a0b22006-10-10 18:44:29 +0100571 msleep(10);
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100572 /* Unmute all */
573 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
574 break;
575 case 1:
576 /* 48000 */
577 /* Mute all */
578 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
579 /* Default fallback clock 48kHz */
580 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
581 /* Word Clock source, Internal 48kHz x1 */
582 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
583 EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_1X );
584 /* Set LEDs on Audio Dock */
585 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
586 EMU_HANA_DOCK_LEDS_2_48K | EMU_HANA_DOCK_LEDS_2_LOCK );
587 /* Allow DLL to settle */
James Courtier-Duttone40a0b22006-10-10 18:44:29 +0100588 msleep(10);
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100589 /* Unmute all */
590 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
591 break;
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100592
593 case 2: /* Take clock from S/PDIF IN */
594 /* Mute all */
595 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
596 /* Default fallback clock 48kHz */
597 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
598 /* Word Clock source, sync to S/PDIF input */
599 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
600 EMU_HANA_WCLOCK_HANA_SPDIF_IN | EMU_HANA_WCLOCK_1X );
601 /* Set LEDs on Audio Dock */
602 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
603 EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK );
604 /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */
605 /* Allow DLL to settle */
606 msleep(10);
607 /* Unmute all */
608 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
609 break;
610
611 case 3:
612 /* Take clock from ADAT IN */
613 /* Mute all */
614 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
615 /* Default fallback clock 48kHz */
616 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
617 /* Word Clock source, sync to ADAT input */
618 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
619 EMU_HANA_WCLOCK_HANA_ADAT_IN | EMU_HANA_WCLOCK_1X );
620 /* Set LEDs on Audio Dock */
621 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK );
622 /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */
623 /* Allow DLL to settle */
624 msleep(10);
625 /* Unmute all */
626 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
627
628
629 break;
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100630 }
631 }
632 return change;
633}
634
635static struct snd_kcontrol_new snd_emu1010_internal_clock =
636{
637 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
638 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
639 .name = "Clock Internal Rate",
640 .count = 1,
641 .info = snd_emu1010_internal_clock_info,
642 .get = snd_emu1010_internal_clock_get,
643 .put = snd_emu1010_internal_clock_put
644};
645
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000646static int snd_audigy_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
647 struct snd_ctl_elem_info *uinfo)
648{
649#if 0
650 static char *texts[4] = {
651 "Unknown1", "Unknown2", "Mic", "Line"
652 };
653#endif
654 static char *texts[2] = {
655 "Mic", "Line"
656 };
657
658 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
659 uinfo->count = 1;
660 uinfo->value.enumerated.items = 2;
661 if (uinfo->value.enumerated.item > 1)
662 uinfo->value.enumerated.item = 1;
663 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
664 return 0;
665}
666
667static int snd_audigy_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
668 struct snd_ctl_elem_value *ucontrol)
669{
670 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
671
672 ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
673 return 0;
674}
675
676static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
677 struct snd_ctl_elem_value *ucontrol)
678{
679 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
680 unsigned int source_id;
681 unsigned int ngain, ogain;
682 u32 gpio;
683 int change = 0;
684 unsigned long flags;
685 u32 source;
686 /* If the capture source has changed,
687 * update the capture volume from the cached value
688 * for the particular source.
689 */
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000690 source_id = ucontrol->value.enumerated.item[0];
691 /* Limit: uinfo->value.enumerated.items = 2; */
692 /* emu->i2c_capture_volume */
693 if (source_id >= 2)
694 return -EINVAL;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000695 change = (emu->i2c_capture_source != source_id);
696 if (change) {
697 snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */
698 spin_lock_irqsave(&emu->emu_lock, flags);
699 gpio = inl(emu->port + A_IOCFG);
700 if (source_id==0)
701 outl(gpio | 0x4, emu->port + A_IOCFG);
702 else
703 outl(gpio & ~0x4, emu->port + A_IOCFG);
704 spin_unlock_irqrestore(&emu->emu_lock, flags);
705
706 ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
707 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
708 if (ngain != ogain)
709 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
710 ngain = emu->i2c_capture_volume[source_id][1]; /* Right */
711 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
712 if (ngain != ogain)
713 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
714
715 source = 1 << (source_id + 2);
716 snd_emu10k1_i2c_write(emu, ADC_MUX, source); /* Set source */
717 emu->i2c_capture_source = source_id;
718 }
719 return change;
720}
721
722static struct snd_kcontrol_new snd_audigy_i2c_capture_source =
723{
724 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
725 .name = "Capture Source",
726 .info = snd_audigy_i2c_capture_source_info,
727 .get = snd_audigy_i2c_capture_source_get,
728 .put = snd_audigy_i2c_capture_source_put
729};
730
731static int snd_audigy_i2c_volume_info(struct snd_kcontrol *kcontrol,
732 struct snd_ctl_elem_info *uinfo)
733{
734 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
735 uinfo->count = 2;
736 uinfo->value.integer.min = 0;
737 uinfo->value.integer.max = 255;
738 return 0;
739}
740
741static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol,
742 struct snd_ctl_elem_value *ucontrol)
743{
744 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000745 unsigned int source_id;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000746
747 source_id = kcontrol->private_value;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000748 /* Limit: emu->i2c_capture_volume */
749 /* capture_source: uinfo->value.enumerated.items = 2 */
750 if (source_id >= 2)
751 return -EINVAL;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000752
753 ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
754 ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
755 return 0;
756}
757
758static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
759 struct snd_ctl_elem_value *ucontrol)
760{
761 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
762 unsigned int ogain;
763 unsigned int ngain;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000764 unsigned int source_id;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000765 int change = 0;
766
767 source_id = kcontrol->private_value;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000768 /* Limit: emu->i2c_capture_volume */
769 /* capture_source: uinfo->value.enumerated.items = 2 */
770 if (source_id >= 2)
771 return -EINVAL;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000772 ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
773 ngain = ucontrol->value.integer.value[0];
774 if (ngain > 0xff)
775 return 0;
776 if (ogain != ngain) {
777 if (emu->i2c_capture_source == source_id)
778 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000779 emu->i2c_capture_volume[source_id][0] = ngain;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000780 change = 1;
781 }
782 ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
783 ngain = ucontrol->value.integer.value[1];
784 if (ngain > 0xff)
785 return 0;
786 if (ogain != ngain) {
787 if (emu->i2c_capture_source == source_id)
788 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000789 emu->i2c_capture_volume[source_id][1] = ngain;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000790 change = 1;
791 }
792
793 return change;
794}
795
796#define I2C_VOLUME(xname,chid) \
797{ \
798 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
799 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
800 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
801 .info = snd_audigy_i2c_volume_info, \
802 .get = snd_audigy_i2c_volume_get, \
803 .put = snd_audigy_i2c_volume_put, \
804 .tlv = { .p = snd_audigy_db_scale2 }, \
805 .private_value = chid \
806}
807
808
809static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] __devinitdata = {
810 I2C_VOLUME("Mic Capture Volume", 0),
811 I2C_VOLUME("Line Capture Volume", 0)
812};
813
Takashi Iwai0af68e52005-04-11 17:03:03 +0200814#if 0
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100815static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816{
817 static char *texts[] = {"44100", "48000", "96000"};
818
819 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
820 uinfo->count = 1;
821 uinfo->value.enumerated.items = 3;
822 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
823 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
824 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
825 return 0;
826}
827
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100828static int snd_audigy_spdif_output_rate_get(struct snd_kcontrol *kcontrol,
829 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100831 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 unsigned int tmp;
833 unsigned long flags;
834
835
836 spin_lock_irqsave(&emu->reg_lock, flags);
837 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
838 switch (tmp & A_SPDIF_RATE_MASK) {
839 case A_SPDIF_44100:
840 ucontrol->value.enumerated.item[0] = 0;
841 break;
842 case A_SPDIF_48000:
843 ucontrol->value.enumerated.item[0] = 1;
844 break;
845 case A_SPDIF_96000:
846 ucontrol->value.enumerated.item[0] = 2;
847 break;
848 default:
849 ucontrol->value.enumerated.item[0] = 1;
850 }
851 spin_unlock_irqrestore(&emu->reg_lock, flags);
852 return 0;
853}
854
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100855static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol,
856 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100858 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 int change;
860 unsigned int reg, val, tmp;
861 unsigned long flags;
862
863 switch(ucontrol->value.enumerated.item[0]) {
864 case 0:
865 val = A_SPDIF_44100;
866 break;
867 case 1:
868 val = A_SPDIF_48000;
869 break;
870 case 2:
871 val = A_SPDIF_96000;
872 break;
873 default:
874 val = A_SPDIF_48000;
875 break;
876 }
877
878
879 spin_lock_irqsave(&emu->reg_lock, flags);
880 reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
881 tmp = reg & ~A_SPDIF_RATE_MASK;
882 tmp |= val;
883 if ((change = (tmp != reg)))
884 snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
885 spin_unlock_irqrestore(&emu->reg_lock, flags);
886 return change;
887}
888
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100889static struct snd_kcontrol_new snd_audigy_spdif_output_rate =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890{
891 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
892 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
893 .name = "Audigy SPDIF Output Sample Rate",
894 .count = 1,
895 .info = snd_audigy_spdif_output_rate_info,
896 .get = snd_audigy_spdif_output_rate_get,
897 .put = snd_audigy_spdif_output_rate_put
898};
Takashi Iwai0af68e52005-04-11 17:03:03 +0200899#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100901static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol,
902 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100904 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
906 int change;
907 unsigned int val;
908 unsigned long flags;
909
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000910 /* Limit: emu->spdif_bits */
911 if (idx >= 3)
912 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 val = (ucontrol->value.iec958.status[0] << 0) |
914 (ucontrol->value.iec958.status[1] << 8) |
915 (ucontrol->value.iec958.status[2] << 16) |
916 (ucontrol->value.iec958.status[3] << 24);
917 spin_lock_irqsave(&emu->reg_lock, flags);
918 change = val != emu->spdif_bits[idx];
919 if (change) {
920 snd_emu10k1_ptr_write(emu, SPCS0 + idx, 0, val);
921 emu->spdif_bits[idx] = val;
922 }
923 spin_unlock_irqrestore(&emu->reg_lock, flags);
924 return change;
925}
926
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100927static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928{
929 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +0200930 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
Takashi Iwai7583cb52007-08-16 19:32:16 +0200932 .count = 3,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 .info = snd_emu10k1_spdif_info,
934 .get = snd_emu10k1_spdif_get_mask
935};
936
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100937static struct snd_kcontrol_new snd_emu10k1_spdif_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938{
Clemens Ladisch5549d542005-08-03 13:50:30 +0200939 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
Takashi Iwai7583cb52007-08-16 19:32:16 +0200941 .count = 3,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 .info = snd_emu10k1_spdif_info,
943 .get = snd_emu10k1_spdif_get,
944 .put = snd_emu10k1_spdif_put
945};
946
947
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100948static void update_emu10k1_fxrt(struct snd_emu10k1 *emu, int voice, unsigned char *route)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949{
950 if (emu->audigy) {
951 snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
952 snd_emu10k1_compose_audigy_fxrt1(route));
953 snd_emu10k1_ptr_write(emu, A_FXRT2, voice,
954 snd_emu10k1_compose_audigy_fxrt2(route));
955 } else {
956 snd_emu10k1_ptr_write(emu, FXRT, voice,
957 snd_emu10k1_compose_send_routing(route));
958 }
959}
960
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100961static void update_emu10k1_send_volume(struct snd_emu10k1 *emu, int voice, unsigned char *volume)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962{
963 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]);
964 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]);
965 snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, volume[2]);
966 snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, volume[3]);
967 if (emu->audigy) {
968 unsigned int val = ((unsigned int)volume[4] << 24) |
969 ((unsigned int)volume[5] << 16) |
970 ((unsigned int)volume[6] << 8) |
971 (unsigned int)volume[7];
972 snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, val);
973 }
974}
975
976/* PCM stream controls */
977
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100978static int snd_emu10k1_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100980 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
982 uinfo->count = emu->audigy ? 3*8 : 3*4;
983 uinfo->value.integer.min = 0;
984 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
985 return 0;
986}
987
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100988static int snd_emu10k1_send_routing_get(struct snd_kcontrol *kcontrol,
989 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990{
991 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100992 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
993 struct snd_emu10k1_pcm_mixer *mix =
994 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 int voice, idx;
996 int num_efx = emu->audigy ? 8 : 4;
997 int mask = emu->audigy ? 0x3f : 0x0f;
998
999 spin_lock_irqsave(&emu->reg_lock, flags);
1000 for (voice = 0; voice < 3; voice++)
1001 for (idx = 0; idx < num_efx; idx++)
1002 ucontrol->value.integer.value[(voice * num_efx) + idx] =
1003 mix->send_routing[voice][idx] & mask;
1004 spin_unlock_irqrestore(&emu->reg_lock, flags);
1005 return 0;
1006}
1007
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001008static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol,
1009 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010{
1011 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001012 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1013 struct snd_emu10k1_pcm_mixer *mix =
1014 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 int change = 0, voice, idx, val;
1016 int num_efx = emu->audigy ? 8 : 4;
1017 int mask = emu->audigy ? 0x3f : 0x0f;
1018
1019 spin_lock_irqsave(&emu->reg_lock, flags);
1020 for (voice = 0; voice < 3; voice++)
1021 for (idx = 0; idx < num_efx; idx++) {
1022 val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask;
1023 if (mix->send_routing[voice][idx] != val) {
1024 mix->send_routing[voice][idx] = val;
1025 change = 1;
1026 }
1027 }
1028 if (change && mix->epcm) {
1029 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1030 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
1031 &mix->send_routing[1][0]);
1032 update_emu10k1_fxrt(emu, mix->epcm->voices[1]->number,
1033 &mix->send_routing[2][0]);
1034 } else if (mix->epcm->voices[0]) {
1035 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
1036 &mix->send_routing[0][0]);
1037 }
1038 }
1039 spin_unlock_irqrestore(&emu->reg_lock, flags);
1040 return change;
1041}
1042
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001043static struct snd_kcontrol_new snd_emu10k1_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044{
1045 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001046 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 .name = "EMU10K1 PCM Send Routing",
1048 .count = 32,
1049 .info = snd_emu10k1_send_routing_info,
1050 .get = snd_emu10k1_send_routing_get,
1051 .put = snd_emu10k1_send_routing_put
1052};
1053
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001054static int snd_emu10k1_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001056 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1058 uinfo->count = emu->audigy ? 3*8 : 3*4;
1059 uinfo->value.integer.min = 0;
1060 uinfo->value.integer.max = 255;
1061 return 0;
1062}
1063
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001064static int snd_emu10k1_send_volume_get(struct snd_kcontrol *kcontrol,
1065 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066{
1067 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001068 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1069 struct snd_emu10k1_pcm_mixer *mix =
1070 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 int idx;
1072 int num_efx = emu->audigy ? 8 : 4;
1073
1074 spin_lock_irqsave(&emu->reg_lock, flags);
1075 for (idx = 0; idx < 3*num_efx; idx++)
1076 ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx];
1077 spin_unlock_irqrestore(&emu->reg_lock, flags);
1078 return 0;
1079}
1080
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001081static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol,
1082 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083{
1084 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001085 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +00001086 /* FIXME: Check limits */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001087 struct snd_emu10k1_pcm_mixer *mix =
1088 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 int change = 0, idx, val;
1090 int num_efx = emu->audigy ? 8 : 4;
1091
1092 spin_lock_irqsave(&emu->reg_lock, flags);
1093 for (idx = 0; idx < 3*num_efx; idx++) {
1094 val = ucontrol->value.integer.value[idx] & 255;
1095 if (mix->send_volume[idx/num_efx][idx%num_efx] != val) {
1096 mix->send_volume[idx/num_efx][idx%num_efx] = val;
1097 change = 1;
1098 }
1099 }
1100 if (change && mix->epcm) {
1101 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1102 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
1103 &mix->send_volume[1][0]);
1104 update_emu10k1_send_volume(emu, mix->epcm->voices[1]->number,
1105 &mix->send_volume[2][0]);
1106 } else if (mix->epcm->voices[0]) {
1107 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
1108 &mix->send_volume[0][0]);
1109 }
1110 }
1111 spin_unlock_irqrestore(&emu->reg_lock, flags);
1112 return change;
1113}
1114
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001115static struct snd_kcontrol_new snd_emu10k1_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116{
1117 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001118 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 .name = "EMU10K1 PCM Send Volume",
1120 .count = 32,
1121 .info = snd_emu10k1_send_volume_info,
1122 .get = snd_emu10k1_send_volume_get,
1123 .put = snd_emu10k1_send_volume_put
1124};
1125
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001126static int snd_emu10k1_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127{
1128 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1129 uinfo->count = 3;
1130 uinfo->value.integer.min = 0;
1131 uinfo->value.integer.max = 0xffff;
1132 return 0;
1133}
1134
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001135static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol,
1136 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001138 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +00001139 /* FIXME: Check limits */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001140 struct snd_emu10k1_pcm_mixer *mix =
1141 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 unsigned long flags;
1143 int idx;
1144
1145 spin_lock_irqsave(&emu->reg_lock, flags);
1146 for (idx = 0; idx < 3; idx++)
1147 ucontrol->value.integer.value[idx] = mix->attn[idx];
1148 spin_unlock_irqrestore(&emu->reg_lock, flags);
1149 return 0;
1150}
1151
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001152static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol,
1153 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154{
1155 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001156 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +00001157 /* FIXME: Check limits */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001158 struct snd_emu10k1_pcm_mixer *mix =
1159 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 int change = 0, idx, val;
1161
1162 spin_lock_irqsave(&emu->reg_lock, flags);
1163 for (idx = 0; idx < 3; idx++) {
1164 val = ucontrol->value.integer.value[idx] & 0xffff;
1165 if (mix->attn[idx] != val) {
1166 mix->attn[idx] = val;
1167 change = 1;
1168 }
1169 }
1170 if (change && mix->epcm) {
1171 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1172 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[1]);
1173 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[1]->number, mix->attn[2]);
1174 } else if (mix->epcm->voices[0]) {
1175 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]);
1176 }
1177 }
1178 spin_unlock_irqrestore(&emu->reg_lock, flags);
1179 return change;
1180}
1181
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001182static struct snd_kcontrol_new snd_emu10k1_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183{
1184 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001185 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 .name = "EMU10K1 PCM Volume",
1187 .count = 32,
1188 .info = snd_emu10k1_attn_info,
1189 .get = snd_emu10k1_attn_get,
1190 .put = snd_emu10k1_attn_put
1191};
1192
1193/* Mutichannel PCM stream controls */
1194
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001195static int snd_emu10k1_efx_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001197 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1199 uinfo->count = emu->audigy ? 8 : 4;
1200 uinfo->value.integer.min = 0;
1201 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
1202 return 0;
1203}
1204
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001205static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol,
1206 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207{
1208 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001209 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +00001210 /* FIXME: Check limits */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001211 struct snd_emu10k1_pcm_mixer *mix =
1212 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 int idx;
1214 int num_efx = emu->audigy ? 8 : 4;
1215 int mask = emu->audigy ? 0x3f : 0x0f;
1216
1217 spin_lock_irqsave(&emu->reg_lock, flags);
1218 for (idx = 0; idx < num_efx; idx++)
1219 ucontrol->value.integer.value[idx] =
1220 mix->send_routing[0][idx] & mask;
1221 spin_unlock_irqrestore(&emu->reg_lock, flags);
1222 return 0;
1223}
1224
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001225static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol,
1226 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227{
1228 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001229 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +00001230 /* FIXME: Check limits */
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);
James Courtier-Dutton74415a32007-11-12 14:55:19 +00001282 /* FIXME: Check limits */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001283 struct snd_emu10k1_pcm_mixer *mix =
1284 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 int idx;
1286 int num_efx = emu->audigy ? 8 : 4;
1287
1288 spin_lock_irqsave(&emu->reg_lock, flags);
1289 for (idx = 0; idx < num_efx; idx++)
1290 ucontrol->value.integer.value[idx] = mix->send_volume[0][idx];
1291 spin_unlock_irqrestore(&emu->reg_lock, flags);
1292 return 0;
1293}
1294
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001295static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol,
1296 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297{
1298 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001299 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +00001300 /* FIXME: Check limits */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001302 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 int change = 0, idx, val;
1304 int num_efx = emu->audigy ? 8 : 4;
1305
1306 spin_lock_irqsave(&emu->reg_lock, flags);
1307 for (idx = 0; idx < num_efx; idx++) {
1308 val = ucontrol->value.integer.value[idx] & 255;
1309 if (mix->send_volume[0][idx] != val) {
1310 mix->send_volume[0][idx] = val;
1311 change = 1;
1312 }
1313 }
1314 if (change && mix->epcm) {
1315 if (mix->epcm->voices[ch]) {
1316 update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number,
1317 &mix->send_volume[0][0]);
1318 }
1319 }
1320 spin_unlock_irqrestore(&emu->reg_lock, flags);
1321 return change;
1322}
1323
1324
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001325static struct snd_kcontrol_new snd_emu10k1_efx_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326{
1327 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1328 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1329 .name = "Multichannel PCM Send Volume",
1330 .count = 16,
1331 .info = snd_emu10k1_efx_send_volume_info,
1332 .get = snd_emu10k1_efx_send_volume_get,
1333 .put = snd_emu10k1_efx_send_volume_put
1334};
1335
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001336static int snd_emu10k1_efx_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337{
1338 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1339 uinfo->count = 1;
1340 uinfo->value.integer.min = 0;
1341 uinfo->value.integer.max = 0xffff;
1342 return 0;
1343}
1344
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001345static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol,
1346 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001348 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +00001349 /* FIXME: Check limits */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001350 struct snd_emu10k1_pcm_mixer *mix =
1351 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 unsigned long flags;
1353
1354 spin_lock_irqsave(&emu->reg_lock, flags);
1355 ucontrol->value.integer.value[0] = mix->attn[0];
1356 spin_unlock_irqrestore(&emu->reg_lock, flags);
1357 return 0;
1358}
1359
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001360static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol,
1361 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362{
1363 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001364 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +00001365 /* FIXME: Check limits */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001367 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 int change = 0, val;
1369
1370 spin_lock_irqsave(&emu->reg_lock, flags);
1371 val = ucontrol->value.integer.value[0] & 0xffff;
1372 if (mix->attn[0] != val) {
1373 mix->attn[0] = val;
1374 change = 1;
1375 }
1376 if (change && mix->epcm) {
1377 if (mix->epcm->voices[ch]) {
1378 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]);
1379 }
1380 }
1381 spin_unlock_irqrestore(&emu->reg_lock, flags);
1382 return change;
1383}
1384
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001385static struct snd_kcontrol_new snd_emu10k1_efx_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386{
1387 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1388 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1389 .name = "Multichannel PCM Volume",
1390 .count = 16,
1391 .info = snd_emu10k1_efx_attn_info,
1392 .get = snd_emu10k1_efx_attn_get,
1393 .put = snd_emu10k1_efx_attn_put
1394};
1395
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001396#define snd_emu10k1_shared_spdif_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001398static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol,
1399 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001401 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402
1403 if (emu->audigy)
1404 ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0;
1405 else
1406 ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0;
1407 return 0;
1408}
1409
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001410static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
1411 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412{
1413 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001414 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 unsigned int reg, val;
1416 int change = 0;
1417
1418 spin_lock_irqsave(&emu->reg_lock, flags);
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001419 if ( emu->card_capabilities->i2c_adc) {
1420 /* Do nothing for Audigy 2 ZS Notebook */
1421 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 reg = inl(emu->port + A_IOCFG);
1423 val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0;
1424 change = (reg & A_IOCFG_GPOUT0) != val;
1425 if (change) {
1426 reg &= ~A_IOCFG_GPOUT0;
1427 reg |= val;
1428 outl(reg | val, emu->port + A_IOCFG);
1429 }
1430 }
1431 reg = inl(emu->port + HCFG);
1432 val = ucontrol->value.integer.value[0] ? HCFG_GPOUT0 : 0;
1433 change |= (reg & HCFG_GPOUT0) != val;
1434 if (change) {
1435 reg &= ~HCFG_GPOUT0;
1436 reg |= val;
1437 outl(reg | val, emu->port + HCFG);
1438 }
1439 spin_unlock_irqrestore(&emu->reg_lock, flags);
1440 return change;
1441}
1442
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001443static struct snd_kcontrol_new snd_emu10k1_shared_spdif __devinitdata =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444{
1445 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1446 .name = "SB Live Analog/Digital Output Jack",
1447 .info = snd_emu10k1_shared_spdif_info,
1448 .get = snd_emu10k1_shared_spdif_get,
1449 .put = snd_emu10k1_shared_spdif_put
1450};
1451
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001452static struct snd_kcontrol_new snd_audigy_shared_spdif __devinitdata =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453{
1454 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1455 .name = "Audigy Analog/Digital Output Jack",
1456 .info = snd_emu10k1_shared_spdif_info,
1457 .get = snd_emu10k1_shared_spdif_get,
1458 .put = snd_emu10k1_shared_spdif_put
1459};
1460
1461/*
1462 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001463static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001465 struct snd_emu10k1 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 emu->ac97 = NULL;
1467}
1468
1469/*
1470 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001471static int remove_ctl(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001473 struct snd_ctl_elem_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 memset(&id, 0, sizeof(id));
1475 strcpy(id.name, name);
1476 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1477 return snd_ctl_remove_id(card, &id);
1478}
1479
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001480static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001482 struct snd_ctl_elem_id sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 memset(&sid, 0, sizeof(sid));
1484 strcpy(sid.name, name);
1485 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1486 return snd_ctl_find_id(card, &sid);
1487}
1488
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001489static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001491 struct snd_kcontrol *kctl = ctl_find(card, src);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 if (kctl) {
1493 strcpy(kctl->id.name, dst);
1494 return 0;
1495 }
1496 return -ENOENT;
1497}
1498
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001499int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001500 int pcm_device, int multi_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501{
1502 int err, pcm;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001503 struct snd_kcontrol *kctl;
1504 struct snd_card *card = emu->card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505 char **c;
1506 static char *emu10k1_remove_ctls[] = {
1507 /* no AC97 mono, surround, center/lfe */
1508 "Master Mono Playback Switch",
1509 "Master Mono Playback Volume",
1510 "PCM Out Path & Mute",
1511 "Mono Output Select",
Takashi Iwai7eae36f2006-01-05 18:40:56 +01001512 "Front Playback Switch",
1513 "Front Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 "Surround Playback Switch",
1515 "Surround Playback Volume",
1516 "Center Playback Switch",
1517 "Center Playback Volume",
1518 "LFE Playback Switch",
1519 "LFE Playback Volume",
1520 NULL
1521 };
1522 static char *emu10k1_rename_ctls[] = {
1523 "Surround Digital Playback Volume", "Surround Playback Volume",
1524 "Center Digital Playback Volume", "Center Playback Volume",
1525 "LFE Digital Playback Volume", "LFE Playback Volume",
1526 NULL
1527 };
1528 static char *audigy_remove_ctls[] = {
1529 /* Master/PCM controls on ac97 of Audigy has no effect */
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001530 /* On the Audigy2 the AC97 playback is piped into
1531 * the Philips ADC for 24bit capture */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 "PCM Playback Switch",
1533 "PCM Playback Volume",
1534 "Master Mono Playback Switch",
1535 "Master Mono Playback Volume",
1536 "Master Playback Switch",
1537 "Master Playback Volume",
1538 "PCM Out Path & Mute",
1539 "Mono Output Select",
1540 /* remove unused AC97 capture controls */
1541 "Capture Source",
1542 "Capture Switch",
1543 "Capture Volume",
1544 "Mic Select",
1545 "Video Playback Switch",
1546 "Video Playback Volume",
1547 "Mic Playback Switch",
1548 "Mic Playback Volume",
1549 NULL
1550 };
1551 static char *audigy_rename_ctls[] = {
1552 /* use conventional names */
1553 "Wave Playback Volume", "PCM Playback Volume",
1554 /* "Wave Capture Volume", "PCM Capture Volume", */
1555 "Wave Master Playback Volume", "Master Playback Volume",
1556 "AMic Playback Volume", "Mic Playback Volume",
1557 NULL
1558 };
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001559 static char *audigy_rename_ctls_i2c_adc[] = {
1560 //"Analog Mix Capture Volume","OLD Analog Mix Capture Volume",
1561 "Line Capture Volume", "Analog Mix Capture Volume",
1562 "Wave Playback Volume", "OLD PCM Playback Volume",
1563 "Wave Master Playback Volume", "Master Playback Volume",
1564 "AMic Playback Volume", "Old Mic Playback Volume",
James Courtier-Duttoneb41dab2006-12-06 20:38:45 +00001565 "CD Capture Volume", "IEC958 Optical Capture Volume",
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001566 NULL
1567 };
1568 static char *audigy_remove_ctls_i2c_adc[] = {
1569 /* On the Audigy2 ZS Notebook
1570 * Capture via WM8775 */
1571 "Mic Capture Volume",
1572 "Analog Mix Capture Volume",
1573 "Aux Capture Volume",
James Courtier-Duttoneb41dab2006-12-06 20:38:45 +00001574 "IEC958 Optical Capture Volume",
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001575 NULL
1576 };
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001577 static char *audigy_remove_ctls_1361t_adc[] = {
1578 /* On the Audigy2 the AC97 playback is piped into
1579 * the Philips ADC for 24bit capture */
1580 "PCM Playback Switch",
1581 "PCM Playback Volume",
1582 "Master Mono Playback Switch",
1583 "Master Mono Playback Volume",
1584 "Capture Source",
1585 "Capture Switch",
1586 "Capture Volume",
1587 "Mic Capture Volume",
1588 "Headphone Playback Switch",
1589 "Headphone Playback Volume",
1590 "3D Control - Center",
1591 "3D Control - Depth",
1592 "3D Control - Switch",
1593 "Line2 Playback Volume",
1594 "Line2 Capture Volume",
1595 NULL
1596 };
1597 static char *audigy_rename_ctls_1361t_adc[] = {
1598 "Master Playback Switch", "Master Capture Switch",
1599 "Master Playback Volume", "Master Capture Volume",
1600 "Wave Master Playback Volume", "Master Playback Volume",
1601 "PC Speaker Playback Switch", "PC Speaker Capture Switch",
1602 "PC Speaker Playback Volume", "PC Speaker Capture Volume",
1603 "Phone Playback Switch", "Phone Capture Switch",
1604 "Phone Playback Volume", "Phone Capture Volume",
1605 "Mic Playback Switch", "Mic Capture Switch",
1606 "Mic Playback Volume", "Mic Capture Volume",
1607 "Line Playback Switch", "Line Capture Switch",
1608 "Line Playback Volume", "Line Capture Volume",
1609 "CD Playback Switch", "CD Capture Switch",
1610 "CD Playback Volume", "CD Capture Volume",
1611 "Aux Playback Switch", "Aux Capture Switch",
1612 "Aux Playback Volume", "Aux Capture Volume",
1613 "Video Playback Switch", "Video Capture Switch",
1614 "Video Playback Volume", "Video Capture Volume",
1615
1616 NULL
1617 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618
Lee Revell2b637da2005-03-30 13:51:18 +02001619 if (emu->card_capabilities->ac97_chip) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001620 struct snd_ac97_bus *pbus;
1621 struct snd_ac97_template ac97;
1622 static struct snd_ac97_bus_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623 .write = snd_emu10k1_ac97_write,
1624 .read = snd_emu10k1_ac97_read,
1625 };
1626
Takashi Iwaib1508692005-10-04 13:49:32 +02001627 if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0)
1628 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 pbus->no_vra = 1; /* we don't need VRA */
1630
1631 memset(&ac97, 0, sizeof(ac97));
1632 ac97.private_data = emu;
1633 ac97.private_free = snd_emu10k1_mixer_free_ac97;
1634 ac97.scaps = AC97_SCAP_NO_SPDIF;
Takashi Iwaib1508692005-10-04 13:49:32 +02001635 if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) {
1636 if (emu->card_capabilities->ac97_chip == 1)
1637 return err;
1638 snd_printd(KERN_INFO "emu10k1: AC97 is optional on this board\n");
1639 snd_printd(KERN_INFO" Proceeding without ac97 mixers...\n");
1640 snd_device_free(emu->card, pbus);
1641 goto no_ac97; /* FIXME: get rid of ugly gotos.. */
1642 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 if (emu->audigy) {
1644 /* set master volume to 0 dB */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001645 snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 /* set capture source to mic */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001647 snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001648 if (emu->card_capabilities->adc_1361t)
1649 c = audigy_remove_ctls_1361t_adc;
1650 else
1651 c = audigy_remove_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 } else {
1653 /*
1654 * Credits for cards based on STAC9758:
1655 * James Courtier-Dutton <James@superbug.demon.co.uk>
1656 * Voluspa <voluspa@comhem.se>
1657 */
1658 if (emu->ac97->id == AC97_ID_STAC9758) {
1659 emu->rear_ac97 = 1;
1660 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 +01001661 snd_ac97_write_cache(emu->ac97, AC97_HEADPHONE, 0x0202);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 }
1663 /* remove unused AC97 controls */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001664 snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
1665 snd_ac97_write_cache(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 c = emu10k1_remove_ctls;
1667 }
1668 for (; *c; c++)
1669 remove_ctl(card, *c);
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001670 } else if (emu->card_capabilities->i2c_adc) {
1671 c = audigy_remove_ctls_i2c_adc;
1672 for (; *c; c++)
1673 remove_ctl(card, *c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 } else {
Takashi Iwaif12aa402005-09-30 16:56:59 +02001675 no_ac97:
Lee Revell2b637da2005-03-30 13:51:18 +02001676 if (emu->card_capabilities->ecard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 strcpy(emu->card->mixername, "EMU APS");
1678 else if (emu->audigy)
1679 strcpy(emu->card->mixername, "SB Audigy");
1680 else
1681 strcpy(emu->card->mixername, "Emu10k1");
1682 }
1683
1684 if (emu->audigy)
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001685 if (emu->card_capabilities->adc_1361t)
1686 c = audigy_rename_ctls_1361t_adc;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001687 else if (emu->card_capabilities->i2c_adc)
1688 c = audigy_rename_ctls_i2c_adc;
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001689 else
1690 c = audigy_rename_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 else
1692 c = emu10k1_rename_ctls;
1693 for (; *c; c += 2)
1694 rename_ctl(card, c[0], c[1]);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001695
James Courtier-Duttone3b9bc02005-12-24 16:54:51 +01001696 if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */
1697 rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume");
1698 rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume");
1699 rename_ctl(card, "Aux2 Capture Volume", "Line3 Capture Volume");
1700 rename_ctl(card, "Mic Capture Volume", "Unknown1 Capture Volume");
1701 remove_ctl(card, "Headphone Playback Switch");
1702 remove_ctl(card, "Headphone Playback Volume");
1703 remove_ctl(card, "3D Control - Center");
1704 remove_ctl(card, "3D Control - Depth");
1705 remove_ctl(card, "3D Control - Switch");
1706 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL)
1708 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001709 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 if ((err = snd_ctl_add(card, kctl)))
1711 return err;
1712 if ((kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL)
1713 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001714 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 if ((err = snd_ctl_add(card, kctl)))
1716 return err;
1717 if ((kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu)) == NULL)
1718 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001719 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 if ((err = snd_ctl_add(card, kctl)))
1721 return err;
1722
1723 if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL)
1724 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001725 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 if ((err = snd_ctl_add(card, kctl)))
1727 return err;
1728
1729 if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL)
1730 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001731 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732 if ((err = snd_ctl_add(card, kctl)))
1733 return err;
1734
1735 if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL)
1736 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001737 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 if ((err = snd_ctl_add(card, kctl)))
1739 return err;
1740
1741 /* initialize the routing and volume table for each pcm playback stream */
1742 for (pcm = 0; pcm < 32; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001743 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744 int v;
1745
1746 mix = &emu->pcm_mixer[pcm];
1747 mix->epcm = NULL;
1748
1749 for (v = 0; v < 4; v++)
1750 mix->send_routing[0][v] =
1751 mix->send_routing[1][v] =
1752 mix->send_routing[2][v] = v;
1753
1754 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1755 mix->send_volume[0][0] = mix->send_volume[0][1] =
1756 mix->send_volume[1][0] = mix->send_volume[2][1] = 255;
1757
1758 mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
1759 }
1760
1761 /* initialize the routing and volume table for the multichannel playback stream */
1762 for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001763 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764 int v;
1765
1766 mix = &emu->efx_pcm_mixer[pcm];
1767 mix->epcm = NULL;
1768
1769 mix->send_routing[0][0] = pcm;
1770 mix->send_routing[0][1] = (pcm == 0) ? 1 : 0;
1771 for (v = 0; v < 2; v++)
1772 mix->send_routing[0][2+v] = 13+v;
1773 if (emu->audigy)
1774 for (v = 0; v < 4; v++)
1775 mix->send_routing[0][4+v] = 60+v;
1776
1777 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1778 mix->send_volume[0][0] = 255;
1779
1780 mix->attn[0] = 0xffff;
1781 }
1782
Lee Revell2b637da2005-03-30 13:51:18 +02001783 if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784 /* sb live! and audigy */
1785 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
1786 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02001787 if (!emu->audigy)
1788 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789 if ((err = snd_ctl_add(card, kctl)))
1790 return err;
1791 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
1792 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02001793 if (!emu->audigy)
1794 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795 if ((err = snd_ctl_add(card, kctl)))
1796 return err;
1797 }
1798
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001799 if ( emu->card_capabilities->emu1010) {
James Courtier-Dutton19b99fb2005-12-04 18:03:03 +01001800 ; /* Disable the snd_audigy_spdif_shared_spdif */
1801 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
1803 return -ENOMEM;
1804 if ((err = snd_ctl_add(card, kctl)))
1805 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02001806#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807 if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
1808 return -ENOMEM;
1809 if ((err = snd_ctl_add(card, kctl)))
1810 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02001811#endif
Lee Revell2b637da2005-03-30 13:51:18 +02001812 } else if (! emu->card_capabilities->ecard) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813 /* sb live! */
1814 if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
1815 return -ENOMEM;
1816 if ((err = snd_ctl_add(card, kctl)))
1817 return err;
1818 }
Lee Revell2b637da2005-03-30 13:51:18 +02001819 if (emu->card_capabilities->ca0151_chip) { /* P16V */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820 if ((err = snd_p16v_mixer(emu)))
1821 return err;
1822 }
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001823
1824 if ( emu->card_capabilities->emu1010) {
1825 int i;
1826
1827 for (i = 0; i < ARRAY_SIZE(snd_emu1010_output_enum_ctls); i++) {
1828 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_output_enum_ctls[i], emu));
1829 if (err < 0)
1830 return err;
1831 }
1832 for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) {
1833 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], emu));
1834 if (err < 0)
1835 return err;
1836 }
James Courtier-Dutton9148cc52006-10-09 23:08:00 +01001837 for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads); i++) {
1838 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_adc_pads[i], emu));
1839 if (err < 0)
1840 return err;
1841 }
1842 for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads); i++) {
1843 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_dac_pads[i], emu));
1844 if (err < 0)
1845 return err;
1846 }
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +01001847 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_internal_clock, emu));
1848 if (err < 0)
1849 return err;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001850 }
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001851
1852 if ( emu->card_capabilities->i2c_adc) {
1853 int i;
1854
1855 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_capture_source, emu));
1856 if (err < 0)
1857 return err;
1858
1859 for (i = 0; i < ARRAY_SIZE(snd_audigy_i2c_volume_ctls); i++) {
1860 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_volume_ctls[i], emu));
1861 if (err < 0)
1862 return err;
1863 }
1864 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865
1866 return 0;
1867}