blob: ccacd7b890e82cb5f3293e622496b3deaf5b813d [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
Takashi Iwaiaa299d02007-11-15 13:16:02 +0100296 val = ucontrol->value.enumerated.item[0];
297 if (val >= 53)
298 return -EINVAL;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100299 channel = (kcontrol->private_value) & 0xff;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000300 /* Limit: emu1010_output_dst, emu->emu1010.output_source */
301 if (channel >= 24)
302 return -EINVAL;
Takashi Iwaiaa299d02007-11-15 13:16:02 +0100303 if (emu->emu1010.output_source[channel] != val) {
304 emu->emu1010.output_source[channel] = val;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100305 change = 1;
306 snd_emu1010_fpga_link_dst_src_write(emu,
307 emu1010_output_dst[channel], emu1010_src_regs[val]);
308 }
309 return change;
310}
311
312static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol,
313 struct snd_ctl_elem_value *ucontrol)
314{
315 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000316 unsigned int channel;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100317
318 channel = (kcontrol->private_value) & 0xff;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000319 /* Limit: emu1010_input_dst, emu->emu1010.input_source */
320 if (channel >= 22)
321 return -EINVAL;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100322 ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel];
323 return 0;
324}
325
326static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
327 struct snd_ctl_elem_value *ucontrol)
328{
329 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
330 int change = 0;
331 unsigned int val;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000332 unsigned int channel;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100333
Takashi Iwaiaa299d02007-11-15 13:16:02 +0100334 val = ucontrol->value.enumerated.item[0];
335 if (val >= 53)
336 return -EINVAL;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100337 channel = (kcontrol->private_value) & 0xff;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000338 /* Limit: emu1010_input_dst, emu->emu1010.input_source */
339 if (channel >= 22)
340 return -EINVAL;
Takashi Iwaiaa299d02007-11-15 13:16:02 +0100341 if (emu->emu1010.input_source[channel] != val) {
342 emu->emu1010.input_source[channel] = val;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100343 change = 1;
344 snd_emu1010_fpga_link_dst_src_write(emu,
345 emu1010_input_dst[channel], emu1010_src_regs[val]);
346 }
347 return change;
348}
349
350#define EMU1010_SOURCE_OUTPUT(xname,chid) \
351{ \
352 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
353 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
354 .info = snd_emu1010_input_output_source_info, \
355 .get = snd_emu1010_output_source_get, \
356 .put = snd_emu1010_output_source_put, \
357 .private_value = chid \
358}
359
360static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = {
James Courtier-Dutton4c07c812006-11-11 10:48:58 +0000361 EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0),
362 EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1),
363 EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2),
364 EMU1010_SOURCE_OUTPUT("Dock DAC2 Right Playback Enum", 3),
365 EMU1010_SOURCE_OUTPUT("Dock DAC3 Left Playback Enum", 4),
366 EMU1010_SOURCE_OUTPUT("Dock DAC3 Right Playback Enum", 5),
367 EMU1010_SOURCE_OUTPUT("Dock DAC4 Left Playback Enum", 6),
368 EMU1010_SOURCE_OUTPUT("Dock DAC4 Right Playback Enum", 7),
369 EMU1010_SOURCE_OUTPUT("Dock Phones Left Playback Enum", 8),
370 EMU1010_SOURCE_OUTPUT("Dock Phones Right Playback Enum", 9),
371 EMU1010_SOURCE_OUTPUT("Dock SPDIF Left Playback Enum", 0xa),
372 EMU1010_SOURCE_OUTPUT("Dock SPDIF Right Playback Enum", 0xb),
373 EMU1010_SOURCE_OUTPUT("1010 SPDIF Left Playback Enum", 0xc),
374 EMU1010_SOURCE_OUTPUT("1010 SPDIF Right Playback Enum", 0xd),
375 EMU1010_SOURCE_OUTPUT("0202 DAC Left Playback Enum", 0xe),
376 EMU1010_SOURCE_OUTPUT("0202 DAC Right Playback Enum", 0xf),
377 EMU1010_SOURCE_OUTPUT("1010 ADAT 0 Playback Enum", 0x10),
378 EMU1010_SOURCE_OUTPUT("1010 ADAT 1 Playback Enum", 0x11),
379 EMU1010_SOURCE_OUTPUT("1010 ADAT 2 Playback Enum", 0x12),
380 EMU1010_SOURCE_OUTPUT("1010 ADAT 3 Playback Enum", 0x13),
381 EMU1010_SOURCE_OUTPUT("1010 ADAT 4 Playback Enum", 0x14),
382 EMU1010_SOURCE_OUTPUT("1010 ADAT 5 Playback Enum", 0x15),
383 EMU1010_SOURCE_OUTPUT("1010 ADAT 6 Playback Enum", 0x16),
384 EMU1010_SOURCE_OUTPUT("1010 ADAT 7 Playback Enum", 0x17),
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100385};
386
387#define EMU1010_SOURCE_INPUT(xname,chid) \
388{ \
389 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
390 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
391 .info = snd_emu1010_input_output_source_info, \
392 .get = snd_emu1010_input_source_get, \
393 .put = snd_emu1010_input_source_put, \
394 .private_value = chid \
395}
396
397static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] __devinitdata = {
James Courtier-Dutton4c07c812006-11-11 10:48:58 +0000398 EMU1010_SOURCE_INPUT("DSP 0 Capture Enum", 0),
399 EMU1010_SOURCE_INPUT("DSP 1 Capture Enum", 1),
400 EMU1010_SOURCE_INPUT("DSP 2 Capture Enum", 2),
401 EMU1010_SOURCE_INPUT("DSP 3 Capture Enum", 3),
402 EMU1010_SOURCE_INPUT("DSP 4 Capture Enum", 4),
403 EMU1010_SOURCE_INPUT("DSP 5 Capture Enum", 5),
404 EMU1010_SOURCE_INPUT("DSP 6 Capture Enum", 6),
405 EMU1010_SOURCE_INPUT("DSP 7 Capture Enum", 7),
406 EMU1010_SOURCE_INPUT("DSP 8 Capture Enum", 8),
407 EMU1010_SOURCE_INPUT("DSP 9 Capture Enum", 9),
408 EMU1010_SOURCE_INPUT("DSP A Capture Enum", 0xa),
409 EMU1010_SOURCE_INPUT("DSP B Capture Enum", 0xb),
410 EMU1010_SOURCE_INPUT("DSP C Capture Enum", 0xc),
411 EMU1010_SOURCE_INPUT("DSP D Capture Enum", 0xd),
412 EMU1010_SOURCE_INPUT("DSP E Capture Enum", 0xe),
413 EMU1010_SOURCE_INPUT("DSP F Capture Enum", 0xf),
414 EMU1010_SOURCE_INPUT("DSP 10 Capture Enum", 0x10),
415 EMU1010_SOURCE_INPUT("DSP 11 Capture Enum", 0x11),
416 EMU1010_SOURCE_INPUT("DSP 12 Capture Enum", 0x12),
417 EMU1010_SOURCE_INPUT("DSP 13 Capture Enum", 0x13),
418 EMU1010_SOURCE_INPUT("DSP 14 Capture Enum", 0x14),
419 EMU1010_SOURCE_INPUT("DSP 15 Capture Enum", 0x15),
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100420};
421
422
423
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200424#define snd_emu1010_adc_pads_info snd_ctl_boolean_mono_info
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100425
426static int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
427{
428 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
429 unsigned int mask = kcontrol->private_value & 0xff;
430 ucontrol->value.integer.value[0] = (emu->emu1010.adc_pads & mask) ? 1 : 0;
431 return 0;
432}
433
434static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
435{
436 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
437 unsigned int mask = kcontrol->private_value & 0xff;
438 unsigned int val, cache;
439 val = ucontrol->value.integer.value[0];
440 cache = emu->emu1010.adc_pads;
441 if (val == 1)
442 cache = cache | mask;
443 else
444 cache = cache & ~mask;
445 if (cache != emu->emu1010.adc_pads) {
446 snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache );
447 emu->emu1010.adc_pads = cache;
448 }
449
450 return 0;
451}
452
453
454
455#define EMU1010_ADC_PADS(xname,chid) \
456{ \
457 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
458 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
459 .info = snd_emu1010_adc_pads_info, \
460 .get = snd_emu1010_adc_pads_get, \
461 .put = snd_emu1010_adc_pads_put, \
462 .private_value = chid \
463}
464
465static struct snd_kcontrol_new snd_emu1010_adc_pads[] __devinitdata = {
466 EMU1010_ADC_PADS("ADC1 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD1),
467 EMU1010_ADC_PADS("ADC2 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD2),
468 EMU1010_ADC_PADS("ADC3 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD3),
469 EMU1010_ADC_PADS("ADC1 14dB PAD 0202 Capture Switch", EMU_HANA_0202_ADC_PAD1),
470};
471
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200472#define snd_emu1010_dac_pads_info snd_ctl_boolean_mono_info
James Courtier-Dutton9148cc52006-10-09 23:08:00 +0100473
474static int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
475{
476 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
477 unsigned int mask = kcontrol->private_value & 0xff;
478 ucontrol->value.integer.value[0] = (emu->emu1010.dac_pads & mask) ? 1 : 0;
479 return 0;
480}
481
482static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
483{
484 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
485 unsigned int mask = kcontrol->private_value & 0xff;
486 unsigned int val, cache;
487 val = ucontrol->value.integer.value[0];
488 cache = emu->emu1010.dac_pads;
489 if (val == 1)
490 cache = cache | mask;
491 else
492 cache = cache & ~mask;
493 if (cache != emu->emu1010.dac_pads) {
494 snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache );
495 emu->emu1010.dac_pads = cache;
496 }
497
498 return 0;
499}
500
501
502
503#define EMU1010_DAC_PADS(xname,chid) \
504{ \
505 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
506 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
507 .info = snd_emu1010_dac_pads_info, \
508 .get = snd_emu1010_dac_pads_get, \
509 .put = snd_emu1010_dac_pads_put, \
510 .private_value = chid \
511}
512
513static struct snd_kcontrol_new snd_emu1010_dac_pads[] __devinitdata = {
514 EMU1010_DAC_PADS("DAC1 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD1),
515 EMU1010_DAC_PADS("DAC2 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD2),
516 EMU1010_DAC_PADS("DAC3 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD3),
517 EMU1010_DAC_PADS("DAC4 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD4),
518 EMU1010_DAC_PADS("DAC1 0202 14dB PAD Playback Switch", EMU_HANA_0202_DAC_PAD1),
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +0100519};
520
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100521
522static int snd_emu1010_internal_clock_info(struct snd_kcontrol *kcontrol,
523 struct snd_ctl_elem_info *uinfo)
524{
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100525 static char *texts[4] = {
526 "44100", "48000", "SPDIF", "ADAT"
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100527 };
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100528
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100529 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
530 uinfo->count = 1;
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100531 uinfo->value.enumerated.items = 4;
532 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
533 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100534 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
535 return 0;
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100536
537
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100538}
539
540static int snd_emu1010_internal_clock_get(struct snd_kcontrol *kcontrol,
541 struct snd_ctl_elem_value *ucontrol)
542{
543 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
544
545 ucontrol->value.enumerated.item[0] = emu->emu1010.internal_clock;
546 return 0;
547}
548
549static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol,
550 struct snd_ctl_elem_value *ucontrol)
551{
552 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
553 unsigned int val;
554 int change = 0;
555
556 val = ucontrol->value.enumerated.item[0] ;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000557 /* Limit: uinfo->value.enumerated.items = 4; */
558 if (val >= 4)
559 return -EINVAL;
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100560 change = (emu->emu1010.internal_clock != val);
561 if (change) {
562 emu->emu1010.internal_clock = val;
563 switch (val) {
564 case 0:
565 /* 44100 */
566 /* Mute all */
567 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
568 /* Default fallback clock 48kHz */
569 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_44_1K );
570 /* Word Clock source, Internal 44.1kHz x1 */
571 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
572 EMU_HANA_WCLOCK_INT_44_1K | EMU_HANA_WCLOCK_1X );
573 /* Set LEDs on Audio Dock */
574 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
575 EMU_HANA_DOCK_LEDS_2_44K | EMU_HANA_DOCK_LEDS_2_LOCK );
576 /* Allow DLL to settle */
James Courtier-Duttone40a0b22006-10-10 18:44:29 +0100577 msleep(10);
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100578 /* Unmute all */
579 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
580 break;
581 case 1:
582 /* 48000 */
583 /* Mute all */
584 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
585 /* Default fallback clock 48kHz */
586 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
587 /* Word Clock source, Internal 48kHz x1 */
588 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
589 EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_1X );
590 /* Set LEDs on Audio Dock */
591 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
592 EMU_HANA_DOCK_LEDS_2_48K | EMU_HANA_DOCK_LEDS_2_LOCK );
593 /* Allow DLL to settle */
James Courtier-Duttone40a0b22006-10-10 18:44:29 +0100594 msleep(10);
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100595 /* Unmute all */
596 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
597 break;
James Courtier-Duttonedec7bb2007-07-23 20:30:22 +0100598
599 case 2: /* Take clock from S/PDIF IN */
600 /* Mute all */
601 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
602 /* Default fallback clock 48kHz */
603 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
604 /* Word Clock source, sync to S/PDIF input */
605 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
606 EMU_HANA_WCLOCK_HANA_SPDIF_IN | EMU_HANA_WCLOCK_1X );
607 /* Set LEDs on Audio Dock */
608 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
609 EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK );
610 /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */
611 /* Allow DLL to settle */
612 msleep(10);
613 /* Unmute all */
614 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
615 break;
616
617 case 3:
618 /* Take clock from ADAT IN */
619 /* Mute all */
620 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
621 /* Default fallback clock 48kHz */
622 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
623 /* Word Clock source, sync to ADAT input */
624 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
625 EMU_HANA_WCLOCK_HANA_ADAT_IN | EMU_HANA_WCLOCK_1X );
626 /* Set LEDs on Audio Dock */
627 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, EMU_HANA_DOCK_LEDS_2_EXT | EMU_HANA_DOCK_LEDS_2_LOCK );
628 /* FIXME: We should set EMU_HANA_DOCK_LEDS_2_LOCK only when clock signal is present and valid */
629 /* Allow DLL to settle */
630 msleep(10);
631 /* Unmute all */
632 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
633
634
635 break;
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +0100636 }
637 }
638 return change;
639}
640
641static struct snd_kcontrol_new snd_emu1010_internal_clock =
642{
643 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
644 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
645 .name = "Clock Internal Rate",
646 .count = 1,
647 .info = snd_emu1010_internal_clock_info,
648 .get = snd_emu1010_internal_clock_get,
649 .put = snd_emu1010_internal_clock_put
650};
651
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000652static int snd_audigy_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
653 struct snd_ctl_elem_info *uinfo)
654{
655#if 0
656 static char *texts[4] = {
657 "Unknown1", "Unknown2", "Mic", "Line"
658 };
659#endif
660 static char *texts[2] = {
661 "Mic", "Line"
662 };
663
664 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
665 uinfo->count = 1;
666 uinfo->value.enumerated.items = 2;
667 if (uinfo->value.enumerated.item > 1)
668 uinfo->value.enumerated.item = 1;
669 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
670 return 0;
671}
672
673static int snd_audigy_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
674 struct snd_ctl_elem_value *ucontrol)
675{
676 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
677
678 ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
679 return 0;
680}
681
682static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
683 struct snd_ctl_elem_value *ucontrol)
684{
685 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
686 unsigned int source_id;
687 unsigned int ngain, ogain;
688 u32 gpio;
689 int change = 0;
690 unsigned long flags;
691 u32 source;
692 /* If the capture source has changed,
693 * update the capture volume from the cached value
694 * for the particular source.
695 */
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000696 source_id = ucontrol->value.enumerated.item[0];
697 /* Limit: uinfo->value.enumerated.items = 2; */
698 /* emu->i2c_capture_volume */
699 if (source_id >= 2)
700 return -EINVAL;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000701 change = (emu->i2c_capture_source != source_id);
702 if (change) {
703 snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */
704 spin_lock_irqsave(&emu->emu_lock, flags);
705 gpio = inl(emu->port + A_IOCFG);
706 if (source_id==0)
707 outl(gpio | 0x4, emu->port + A_IOCFG);
708 else
709 outl(gpio & ~0x4, emu->port + A_IOCFG);
710 spin_unlock_irqrestore(&emu->emu_lock, flags);
711
712 ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
713 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
714 if (ngain != ogain)
715 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
716 ngain = emu->i2c_capture_volume[source_id][1]; /* Right */
717 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
718 if (ngain != ogain)
719 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
720
721 source = 1 << (source_id + 2);
722 snd_emu10k1_i2c_write(emu, ADC_MUX, source); /* Set source */
723 emu->i2c_capture_source = source_id;
724 }
725 return change;
726}
727
728static struct snd_kcontrol_new snd_audigy_i2c_capture_source =
729{
730 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
731 .name = "Capture Source",
732 .info = snd_audigy_i2c_capture_source_info,
733 .get = snd_audigy_i2c_capture_source_get,
734 .put = snd_audigy_i2c_capture_source_put
735};
736
737static int snd_audigy_i2c_volume_info(struct snd_kcontrol *kcontrol,
738 struct snd_ctl_elem_info *uinfo)
739{
740 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
741 uinfo->count = 2;
742 uinfo->value.integer.min = 0;
743 uinfo->value.integer.max = 255;
744 return 0;
745}
746
747static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol,
748 struct snd_ctl_elem_value *ucontrol)
749{
750 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000751 unsigned int source_id;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000752
753 source_id = kcontrol->private_value;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000754 /* Limit: emu->i2c_capture_volume */
755 /* capture_source: uinfo->value.enumerated.items = 2 */
756 if (source_id >= 2)
757 return -EINVAL;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000758
759 ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
760 ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
761 return 0;
762}
763
764static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
765 struct snd_ctl_elem_value *ucontrol)
766{
767 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
768 unsigned int ogain;
769 unsigned int ngain;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000770 unsigned int source_id;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000771 int change = 0;
772
773 source_id = kcontrol->private_value;
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000774 /* Limit: emu->i2c_capture_volume */
775 /* capture_source: uinfo->value.enumerated.items = 2 */
776 if (source_id >= 2)
777 return -EINVAL;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000778 ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
779 ngain = ucontrol->value.integer.value[0];
780 if (ngain > 0xff)
781 return 0;
782 if (ogain != ngain) {
783 if (emu->i2c_capture_source == source_id)
784 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000785 emu->i2c_capture_volume[source_id][0] = ngain;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000786 change = 1;
787 }
788 ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
789 ngain = ucontrol->value.integer.value[1];
790 if (ngain > 0xff)
791 return 0;
792 if (ogain != ngain) {
793 if (emu->i2c_capture_source == source_id)
794 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000795 emu->i2c_capture_volume[source_id][1] = ngain;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +0000796 change = 1;
797 }
798
799 return change;
800}
801
802#define I2C_VOLUME(xname,chid) \
803{ \
804 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
805 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
806 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
807 .info = snd_audigy_i2c_volume_info, \
808 .get = snd_audigy_i2c_volume_get, \
809 .put = snd_audigy_i2c_volume_put, \
810 .tlv = { .p = snd_audigy_db_scale2 }, \
811 .private_value = chid \
812}
813
814
815static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] __devinitdata = {
816 I2C_VOLUME("Mic Capture Volume", 0),
817 I2C_VOLUME("Line Capture Volume", 0)
818};
819
Takashi Iwai0af68e52005-04-11 17:03:03 +0200820#if 0
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100821static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822{
823 static char *texts[] = {"44100", "48000", "96000"};
824
825 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
826 uinfo->count = 1;
827 uinfo->value.enumerated.items = 3;
828 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
829 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
830 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
831 return 0;
832}
833
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100834static int snd_audigy_spdif_output_rate_get(struct snd_kcontrol *kcontrol,
835 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100837 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 unsigned int tmp;
839 unsigned long flags;
840
841
842 spin_lock_irqsave(&emu->reg_lock, flags);
843 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
844 switch (tmp & A_SPDIF_RATE_MASK) {
845 case A_SPDIF_44100:
846 ucontrol->value.enumerated.item[0] = 0;
847 break;
848 case A_SPDIF_48000:
849 ucontrol->value.enumerated.item[0] = 1;
850 break;
851 case A_SPDIF_96000:
852 ucontrol->value.enumerated.item[0] = 2;
853 break;
854 default:
855 ucontrol->value.enumerated.item[0] = 1;
856 }
857 spin_unlock_irqrestore(&emu->reg_lock, flags);
858 return 0;
859}
860
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100861static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol,
862 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100864 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 int change;
866 unsigned int reg, val, tmp;
867 unsigned long flags;
868
869 switch(ucontrol->value.enumerated.item[0]) {
870 case 0:
871 val = A_SPDIF_44100;
872 break;
873 case 1:
874 val = A_SPDIF_48000;
875 break;
876 case 2:
877 val = A_SPDIF_96000;
878 break;
879 default:
880 val = A_SPDIF_48000;
881 break;
882 }
883
884
885 spin_lock_irqsave(&emu->reg_lock, flags);
886 reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
887 tmp = reg & ~A_SPDIF_RATE_MASK;
888 tmp |= val;
889 if ((change = (tmp != reg)))
890 snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
891 spin_unlock_irqrestore(&emu->reg_lock, flags);
892 return change;
893}
894
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100895static struct snd_kcontrol_new snd_audigy_spdif_output_rate =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896{
897 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
898 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
899 .name = "Audigy SPDIF Output Sample Rate",
900 .count = 1,
901 .info = snd_audigy_spdif_output_rate_info,
902 .get = snd_audigy_spdif_output_rate_get,
903 .put = snd_audigy_spdif_output_rate_put
904};
Takashi Iwai0af68e52005-04-11 17:03:03 +0200905#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100907static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol,
908 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100910 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
912 int change;
913 unsigned int val;
914 unsigned long flags;
915
James Courtier-Dutton74415a32007-11-12 14:55:19 +0000916 /* Limit: emu->spdif_bits */
917 if (idx >= 3)
918 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 val = (ucontrol->value.iec958.status[0] << 0) |
920 (ucontrol->value.iec958.status[1] << 8) |
921 (ucontrol->value.iec958.status[2] << 16) |
922 (ucontrol->value.iec958.status[3] << 24);
923 spin_lock_irqsave(&emu->reg_lock, flags);
924 change = val != emu->spdif_bits[idx];
925 if (change) {
926 snd_emu10k1_ptr_write(emu, SPCS0 + idx, 0, val);
927 emu->spdif_bits[idx] = val;
928 }
929 spin_unlock_irqrestore(&emu->reg_lock, flags);
930 return change;
931}
932
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100933static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934{
935 .access = SNDRV_CTL_ELEM_ACCESS_READ,
Clemens Ladisch5549d542005-08-03 13:50:30 +0200936 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
Takashi Iwai7583cb52007-08-16 19:32:16 +0200938 .count = 3,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 .info = snd_emu10k1_spdif_info,
940 .get = snd_emu10k1_spdif_get_mask
941};
942
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100943static struct snd_kcontrol_new snd_emu10k1_spdif_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944{
Clemens Ladisch5549d542005-08-03 13:50:30 +0200945 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
Takashi Iwai7583cb52007-08-16 19:32:16 +0200947 .count = 3,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 .info = snd_emu10k1_spdif_info,
949 .get = snd_emu10k1_spdif_get,
950 .put = snd_emu10k1_spdif_put
951};
952
953
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100954static void update_emu10k1_fxrt(struct snd_emu10k1 *emu, int voice, unsigned char *route)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955{
956 if (emu->audigy) {
957 snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
958 snd_emu10k1_compose_audigy_fxrt1(route));
959 snd_emu10k1_ptr_write(emu, A_FXRT2, voice,
960 snd_emu10k1_compose_audigy_fxrt2(route));
961 } else {
962 snd_emu10k1_ptr_write(emu, FXRT, voice,
963 snd_emu10k1_compose_send_routing(route));
964 }
965}
966
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100967static void update_emu10k1_send_volume(struct snd_emu10k1 *emu, int voice, unsigned char *volume)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968{
969 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]);
970 snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]);
971 snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, volume[2]);
972 snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, volume[3]);
973 if (emu->audigy) {
974 unsigned int val = ((unsigned int)volume[4] << 24) |
975 ((unsigned int)volume[5] << 16) |
976 ((unsigned int)volume[6] << 8) |
977 (unsigned int)volume[7];
978 snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, val);
979 }
980}
981
982/* PCM stream controls */
983
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100984static int snd_emu10k1_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100986 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
988 uinfo->count = emu->audigy ? 3*8 : 3*4;
989 uinfo->value.integer.min = 0;
990 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
991 return 0;
992}
993
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100994static int snd_emu10k1_send_routing_get(struct snd_kcontrol *kcontrol,
995 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996{
997 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100998 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
999 struct snd_emu10k1_pcm_mixer *mix =
1000 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 int voice, idx;
1002 int num_efx = emu->audigy ? 8 : 4;
1003 int mask = emu->audigy ? 0x3f : 0x0f;
1004
1005 spin_lock_irqsave(&emu->reg_lock, flags);
1006 for (voice = 0; voice < 3; voice++)
1007 for (idx = 0; idx < num_efx; idx++)
1008 ucontrol->value.integer.value[(voice * num_efx) + idx] =
1009 mix->send_routing[voice][idx] & mask;
1010 spin_unlock_irqrestore(&emu->reg_lock, flags);
1011 return 0;
1012}
1013
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001014static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol,
1015 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016{
1017 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001018 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1019 struct snd_emu10k1_pcm_mixer *mix =
1020 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 int change = 0, voice, idx, val;
1022 int num_efx = emu->audigy ? 8 : 4;
1023 int mask = emu->audigy ? 0x3f : 0x0f;
1024
1025 spin_lock_irqsave(&emu->reg_lock, flags);
1026 for (voice = 0; voice < 3; voice++)
1027 for (idx = 0; idx < num_efx; idx++) {
1028 val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask;
1029 if (mix->send_routing[voice][idx] != val) {
1030 mix->send_routing[voice][idx] = val;
1031 change = 1;
1032 }
1033 }
1034 if (change && mix->epcm) {
1035 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1036 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
1037 &mix->send_routing[1][0]);
1038 update_emu10k1_fxrt(emu, mix->epcm->voices[1]->number,
1039 &mix->send_routing[2][0]);
1040 } else if (mix->epcm->voices[0]) {
1041 update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
1042 &mix->send_routing[0][0]);
1043 }
1044 }
1045 spin_unlock_irqrestore(&emu->reg_lock, flags);
1046 return change;
1047}
1048
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001049static struct snd_kcontrol_new snd_emu10k1_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050{
1051 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001052 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 .name = "EMU10K1 PCM Send Routing",
1054 .count = 32,
1055 .info = snd_emu10k1_send_routing_info,
1056 .get = snd_emu10k1_send_routing_get,
1057 .put = snd_emu10k1_send_routing_put
1058};
1059
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001060static int snd_emu10k1_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001062 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1064 uinfo->count = emu->audigy ? 3*8 : 3*4;
1065 uinfo->value.integer.min = 0;
1066 uinfo->value.integer.max = 255;
1067 return 0;
1068}
1069
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001070static int snd_emu10k1_send_volume_get(struct snd_kcontrol *kcontrol,
1071 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072{
1073 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001074 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1075 struct snd_emu10k1_pcm_mixer *mix =
1076 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 int idx;
1078 int num_efx = emu->audigy ? 8 : 4;
1079
1080 spin_lock_irqsave(&emu->reg_lock, flags);
1081 for (idx = 0; idx < 3*num_efx; idx++)
1082 ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx];
1083 spin_unlock_irqrestore(&emu->reg_lock, flags);
1084 return 0;
1085}
1086
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001087static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol,
1088 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089{
1090 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001091 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1092 struct snd_emu10k1_pcm_mixer *mix =
1093 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 int change = 0, idx, val;
1095 int num_efx = emu->audigy ? 8 : 4;
1096
1097 spin_lock_irqsave(&emu->reg_lock, flags);
1098 for (idx = 0; idx < 3*num_efx; idx++) {
1099 val = ucontrol->value.integer.value[idx] & 255;
1100 if (mix->send_volume[idx/num_efx][idx%num_efx] != val) {
1101 mix->send_volume[idx/num_efx][idx%num_efx] = val;
1102 change = 1;
1103 }
1104 }
1105 if (change && mix->epcm) {
1106 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1107 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
1108 &mix->send_volume[1][0]);
1109 update_emu10k1_send_volume(emu, mix->epcm->voices[1]->number,
1110 &mix->send_volume[2][0]);
1111 } else if (mix->epcm->voices[0]) {
1112 update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
1113 &mix->send_volume[0][0]);
1114 }
1115 }
1116 spin_unlock_irqrestore(&emu->reg_lock, flags);
1117 return change;
1118}
1119
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001120static struct snd_kcontrol_new snd_emu10k1_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121{
1122 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001123 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 .name = "EMU10K1 PCM Send Volume",
1125 .count = 32,
1126 .info = snd_emu10k1_send_volume_info,
1127 .get = snd_emu10k1_send_volume_get,
1128 .put = snd_emu10k1_send_volume_put
1129};
1130
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001131static int snd_emu10k1_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132{
1133 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1134 uinfo->count = 3;
1135 uinfo->value.integer.min = 0;
1136 uinfo->value.integer.max = 0xffff;
1137 return 0;
1138}
1139
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001140static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol,
1141 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001143 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1144 struct snd_emu10k1_pcm_mixer *mix =
1145 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 unsigned long flags;
1147 int idx;
1148
1149 spin_lock_irqsave(&emu->reg_lock, flags);
1150 for (idx = 0; idx < 3; idx++)
1151 ucontrol->value.integer.value[idx] = mix->attn[idx];
1152 spin_unlock_irqrestore(&emu->reg_lock, flags);
1153 return 0;
1154}
1155
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001156static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol,
1157 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158{
1159 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001160 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1161 struct snd_emu10k1_pcm_mixer *mix =
1162 &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 int change = 0, idx, val;
1164
1165 spin_lock_irqsave(&emu->reg_lock, flags);
1166 for (idx = 0; idx < 3; idx++) {
1167 val = ucontrol->value.integer.value[idx] & 0xffff;
1168 if (mix->attn[idx] != val) {
1169 mix->attn[idx] = val;
1170 change = 1;
1171 }
1172 }
1173 if (change && mix->epcm) {
1174 if (mix->epcm->voices[0] && mix->epcm->voices[1]) {
1175 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[1]);
1176 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[1]->number, mix->attn[2]);
1177 } else if (mix->epcm->voices[0]) {
1178 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]);
1179 }
1180 }
1181 spin_unlock_irqrestore(&emu->reg_lock, flags);
1182 return change;
1183}
1184
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001185static struct snd_kcontrol_new snd_emu10k1_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186{
1187 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001188 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 .name = "EMU10K1 PCM Volume",
1190 .count = 32,
1191 .info = snd_emu10k1_attn_info,
1192 .get = snd_emu10k1_attn_get,
1193 .put = snd_emu10k1_attn_put
1194};
1195
1196/* Mutichannel PCM stream controls */
1197
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001198static int snd_emu10k1_efx_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001200 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1202 uinfo->count = emu->audigy ? 8 : 4;
1203 uinfo->value.integer.min = 0;
1204 uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
1205 return 0;
1206}
1207
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001208static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol,
1209 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210{
1211 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001212 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1213 struct snd_emu10k1_pcm_mixer *mix =
1214 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 int idx;
1216 int num_efx = emu->audigy ? 8 : 4;
1217 int mask = emu->audigy ? 0x3f : 0x0f;
1218
1219 spin_lock_irqsave(&emu->reg_lock, flags);
1220 for (idx = 0; idx < num_efx; idx++)
1221 ucontrol->value.integer.value[idx] =
1222 mix->send_routing[0][idx] & mask;
1223 spin_unlock_irqrestore(&emu->reg_lock, flags);
1224 return 0;
1225}
1226
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001227static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol,
1228 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229{
1230 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001231 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001233 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 int change = 0, idx, val;
1235 int num_efx = emu->audigy ? 8 : 4;
1236 int mask = emu->audigy ? 0x3f : 0x0f;
1237
1238 spin_lock_irqsave(&emu->reg_lock, flags);
1239 for (idx = 0; idx < num_efx; idx++) {
1240 val = ucontrol->value.integer.value[idx] & mask;
1241 if (mix->send_routing[0][idx] != val) {
1242 mix->send_routing[0][idx] = val;
1243 change = 1;
1244 }
1245 }
1246
1247 if (change && mix->epcm) {
1248 if (mix->epcm->voices[ch]) {
1249 update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number,
1250 &mix->send_routing[0][0]);
1251 }
1252 }
1253 spin_unlock_irqrestore(&emu->reg_lock, flags);
1254 return change;
1255}
1256
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001257static struct snd_kcontrol_new snd_emu10k1_efx_send_routing_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258{
1259 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1260 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1261 .name = "Multichannel PCM Send Routing",
1262 .count = 16,
1263 .info = snd_emu10k1_efx_send_routing_info,
1264 .get = snd_emu10k1_efx_send_routing_get,
1265 .put = snd_emu10k1_efx_send_routing_put
1266};
1267
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001268static int snd_emu10k1_efx_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001270 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1272 uinfo->count = emu->audigy ? 8 : 4;
1273 uinfo->value.integer.min = 0;
1274 uinfo->value.integer.max = 255;
1275 return 0;
1276}
1277
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001278static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol,
1279 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280{
1281 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001282 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1283 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);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001301 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 int change = 0, idx, val;
1303 int num_efx = emu->audigy ? 8 : 4;
1304
1305 spin_lock_irqsave(&emu->reg_lock, flags);
1306 for (idx = 0; idx < num_efx; idx++) {
1307 val = ucontrol->value.integer.value[idx] & 255;
1308 if (mix->send_volume[0][idx] != val) {
1309 mix->send_volume[0][idx] = val;
1310 change = 1;
1311 }
1312 }
1313 if (change && mix->epcm) {
1314 if (mix->epcm->voices[ch]) {
1315 update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number,
1316 &mix->send_volume[0][0]);
1317 }
1318 }
1319 spin_unlock_irqrestore(&emu->reg_lock, flags);
1320 return change;
1321}
1322
1323
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001324static struct snd_kcontrol_new snd_emu10k1_efx_send_volume_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325{
1326 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1327 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1328 .name = "Multichannel PCM Send Volume",
1329 .count = 16,
1330 .info = snd_emu10k1_efx_send_volume_info,
1331 .get = snd_emu10k1_efx_send_volume_get,
1332 .put = snd_emu10k1_efx_send_volume_put
1333};
1334
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001335static int snd_emu10k1_efx_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336{
1337 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1338 uinfo->count = 1;
1339 uinfo->value.integer.min = 0;
1340 uinfo->value.integer.max = 0xffff;
1341 return 0;
1342}
1343
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001344static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol,
1345 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001347 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1348 struct snd_emu10k1_pcm_mixer *mix =
1349 &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 unsigned long flags;
1351
1352 spin_lock_irqsave(&emu->reg_lock, flags);
1353 ucontrol->value.integer.value[0] = mix->attn[0];
1354 spin_unlock_irqrestore(&emu->reg_lock, flags);
1355 return 0;
1356}
1357
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001358static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol,
1359 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360{
1361 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001362 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001364 struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 int change = 0, val;
1366
1367 spin_lock_irqsave(&emu->reg_lock, flags);
1368 val = ucontrol->value.integer.value[0] & 0xffff;
1369 if (mix->attn[0] != val) {
1370 mix->attn[0] = val;
1371 change = 1;
1372 }
1373 if (change && mix->epcm) {
1374 if (mix->epcm->voices[ch]) {
1375 snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]);
1376 }
1377 }
1378 spin_unlock_irqrestore(&emu->reg_lock, flags);
1379 return change;
1380}
1381
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001382static struct snd_kcontrol_new snd_emu10k1_efx_attn_control =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383{
1384 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
1385 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1386 .name = "Multichannel PCM Volume",
1387 .count = 16,
1388 .info = snd_emu10k1_efx_attn_info,
1389 .get = snd_emu10k1_efx_attn_get,
1390 .put = snd_emu10k1_efx_attn_put
1391};
1392
Takashi Iwaia5ce8892007-07-23 15:42:26 +02001393#define snd_emu10k1_shared_spdif_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001395static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol,
1396 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001398 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399
1400 if (emu->audigy)
1401 ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0;
1402 else
1403 ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0;
1404 return 0;
1405}
1406
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001407static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
1408 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409{
1410 unsigned long flags;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001411 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 unsigned int reg, val;
1413 int change = 0;
1414
1415 spin_lock_irqsave(&emu->reg_lock, flags);
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001416 if ( emu->card_capabilities->i2c_adc) {
1417 /* Do nothing for Audigy 2 ZS Notebook */
1418 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419 reg = inl(emu->port + A_IOCFG);
1420 val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0;
1421 change = (reg & A_IOCFG_GPOUT0) != val;
1422 if (change) {
1423 reg &= ~A_IOCFG_GPOUT0;
1424 reg |= val;
1425 outl(reg | val, emu->port + A_IOCFG);
1426 }
1427 }
1428 reg = inl(emu->port + HCFG);
1429 val = ucontrol->value.integer.value[0] ? HCFG_GPOUT0 : 0;
1430 change |= (reg & HCFG_GPOUT0) != val;
1431 if (change) {
1432 reg &= ~HCFG_GPOUT0;
1433 reg |= val;
1434 outl(reg | val, emu->port + HCFG);
1435 }
1436 spin_unlock_irqrestore(&emu->reg_lock, flags);
1437 return change;
1438}
1439
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001440static struct snd_kcontrol_new snd_emu10k1_shared_spdif __devinitdata =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441{
1442 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1443 .name = "SB Live Analog/Digital Output Jack",
1444 .info = snd_emu10k1_shared_spdif_info,
1445 .get = snd_emu10k1_shared_spdif_get,
1446 .put = snd_emu10k1_shared_spdif_put
1447};
1448
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001449static struct snd_kcontrol_new snd_audigy_shared_spdif __devinitdata =
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450{
1451 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1452 .name = "Audigy Analog/Digital Output Jack",
1453 .info = snd_emu10k1_shared_spdif_info,
1454 .get = snd_emu10k1_shared_spdif_get,
1455 .put = snd_emu10k1_shared_spdif_put
1456};
1457
1458/*
1459 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001460static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001462 struct snd_emu10k1 *emu = ac97->private_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 emu->ac97 = NULL;
1464}
1465
1466/*
1467 */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001468static int remove_ctl(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001470 struct snd_ctl_elem_id id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 memset(&id, 0, sizeof(id));
1472 strcpy(id.name, name);
1473 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1474 return snd_ctl_remove_id(card, &id);
1475}
1476
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001477static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001479 struct snd_ctl_elem_id sid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 memset(&sid, 0, sizeof(sid));
1481 strcpy(sid.name, name);
1482 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1483 return snd_ctl_find_id(card, &sid);
1484}
1485
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001486static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001488 struct snd_kcontrol *kctl = ctl_find(card, src);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 if (kctl) {
1490 strcpy(kctl->id.name, dst);
1491 return 0;
1492 }
1493 return -ENOENT;
1494}
1495
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001496int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001497 int pcm_device, int multi_device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498{
1499 int err, pcm;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001500 struct snd_kcontrol *kctl;
1501 struct snd_card *card = emu->card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 char **c;
1503 static char *emu10k1_remove_ctls[] = {
1504 /* no AC97 mono, surround, center/lfe */
1505 "Master Mono Playback Switch",
1506 "Master Mono Playback Volume",
1507 "PCM Out Path & Mute",
1508 "Mono Output Select",
Takashi Iwai7eae36f2006-01-05 18:40:56 +01001509 "Front Playback Switch",
1510 "Front Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 "Surround Playback Switch",
1512 "Surround Playback Volume",
1513 "Center Playback Switch",
1514 "Center Playback Volume",
1515 "LFE Playback Switch",
1516 "LFE Playback Volume",
1517 NULL
1518 };
1519 static char *emu10k1_rename_ctls[] = {
1520 "Surround Digital Playback Volume", "Surround Playback Volume",
1521 "Center Digital Playback Volume", "Center Playback Volume",
1522 "LFE Digital Playback Volume", "LFE Playback Volume",
1523 NULL
1524 };
1525 static char *audigy_remove_ctls[] = {
1526 /* Master/PCM controls on ac97 of Audigy has no effect */
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001527 /* On the Audigy2 the AC97 playback is piped into
1528 * the Philips ADC for 24bit capture */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 "PCM Playback Switch",
1530 "PCM Playback Volume",
1531 "Master Mono Playback Switch",
1532 "Master Mono Playback Volume",
1533 "Master Playback Switch",
1534 "Master Playback Volume",
1535 "PCM Out Path & Mute",
1536 "Mono Output Select",
1537 /* remove unused AC97 capture controls */
1538 "Capture Source",
1539 "Capture Switch",
1540 "Capture Volume",
1541 "Mic Select",
1542 "Video Playback Switch",
1543 "Video Playback Volume",
1544 "Mic Playback Switch",
1545 "Mic Playback Volume",
1546 NULL
1547 };
1548 static char *audigy_rename_ctls[] = {
1549 /* use conventional names */
1550 "Wave Playback Volume", "PCM Playback Volume",
1551 /* "Wave Capture Volume", "PCM Capture Volume", */
1552 "Wave Master Playback Volume", "Master Playback Volume",
1553 "AMic Playback Volume", "Mic Playback Volume",
1554 NULL
1555 };
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001556 static char *audigy_rename_ctls_i2c_adc[] = {
1557 //"Analog Mix Capture Volume","OLD Analog Mix Capture Volume",
1558 "Line Capture Volume", "Analog Mix Capture Volume",
1559 "Wave Playback Volume", "OLD PCM Playback Volume",
1560 "Wave Master Playback Volume", "Master Playback Volume",
1561 "AMic Playback Volume", "Old Mic Playback Volume",
James Courtier-Duttoneb41dab2006-12-06 20:38:45 +00001562 "CD Capture Volume", "IEC958 Optical Capture Volume",
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001563 NULL
1564 };
1565 static char *audigy_remove_ctls_i2c_adc[] = {
1566 /* On the Audigy2 ZS Notebook
1567 * Capture via WM8775 */
1568 "Mic Capture Volume",
1569 "Analog Mix Capture Volume",
1570 "Aux Capture Volume",
James Courtier-Duttoneb41dab2006-12-06 20:38:45 +00001571 "IEC958 Optical Capture Volume",
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001572 NULL
1573 };
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001574 static char *audigy_remove_ctls_1361t_adc[] = {
1575 /* On the Audigy2 the AC97 playback is piped into
1576 * the Philips ADC for 24bit capture */
1577 "PCM Playback Switch",
1578 "PCM Playback Volume",
1579 "Master Mono Playback Switch",
1580 "Master Mono Playback Volume",
1581 "Capture Source",
1582 "Capture Switch",
1583 "Capture Volume",
1584 "Mic Capture Volume",
1585 "Headphone Playback Switch",
1586 "Headphone Playback Volume",
1587 "3D Control - Center",
1588 "3D Control - Depth",
1589 "3D Control - Switch",
1590 "Line2 Playback Volume",
1591 "Line2 Capture Volume",
1592 NULL
1593 };
1594 static char *audigy_rename_ctls_1361t_adc[] = {
1595 "Master Playback Switch", "Master Capture Switch",
1596 "Master Playback Volume", "Master Capture Volume",
1597 "Wave Master Playback Volume", "Master Playback Volume",
1598 "PC Speaker Playback Switch", "PC Speaker Capture Switch",
1599 "PC Speaker Playback Volume", "PC Speaker Capture Volume",
1600 "Phone Playback Switch", "Phone Capture Switch",
1601 "Phone Playback Volume", "Phone Capture Volume",
1602 "Mic Playback Switch", "Mic Capture Switch",
1603 "Mic Playback Volume", "Mic Capture Volume",
1604 "Line Playback Switch", "Line Capture Switch",
1605 "Line Playback Volume", "Line Capture Volume",
1606 "CD Playback Switch", "CD Capture Switch",
1607 "CD Playback Volume", "CD Capture Volume",
1608 "Aux Playback Switch", "Aux Capture Switch",
1609 "Aux Playback Volume", "Aux Capture Volume",
1610 "Video Playback Switch", "Video Capture Switch",
1611 "Video Playback Volume", "Video Capture Volume",
1612
1613 NULL
1614 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615
Lee Revell2b637da2005-03-30 13:51:18 +02001616 if (emu->card_capabilities->ac97_chip) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001617 struct snd_ac97_bus *pbus;
1618 struct snd_ac97_template ac97;
1619 static struct snd_ac97_bus_ops ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 .write = snd_emu10k1_ac97_write,
1621 .read = snd_emu10k1_ac97_read,
1622 };
1623
Takashi Iwaib1508692005-10-04 13:49:32 +02001624 if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0)
1625 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 pbus->no_vra = 1; /* we don't need VRA */
1627
1628 memset(&ac97, 0, sizeof(ac97));
1629 ac97.private_data = emu;
1630 ac97.private_free = snd_emu10k1_mixer_free_ac97;
1631 ac97.scaps = AC97_SCAP_NO_SPDIF;
Takashi Iwaib1508692005-10-04 13:49:32 +02001632 if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) {
1633 if (emu->card_capabilities->ac97_chip == 1)
1634 return err;
1635 snd_printd(KERN_INFO "emu10k1: AC97 is optional on this board\n");
1636 snd_printd(KERN_INFO" Proceeding without ac97 mixers...\n");
1637 snd_device_free(emu->card, pbus);
1638 goto no_ac97; /* FIXME: get rid of ugly gotos.. */
1639 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 if (emu->audigy) {
1641 /* set master volume to 0 dB */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001642 snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 /* set capture source to mic */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001644 snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001645 if (emu->card_capabilities->adc_1361t)
1646 c = audigy_remove_ctls_1361t_adc;
1647 else
1648 c = audigy_remove_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649 } else {
1650 /*
1651 * Credits for cards based on STAC9758:
1652 * James Courtier-Dutton <James@superbug.demon.co.uk>
1653 * Voluspa <voluspa@comhem.se>
1654 */
1655 if (emu->ac97->id == AC97_ID_STAC9758) {
1656 emu->rear_ac97 = 1;
1657 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 +01001658 snd_ac97_write_cache(emu->ac97, AC97_HEADPHONE, 0x0202);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 }
1660 /* remove unused AC97 controls */
Takashi Iwai4d7d7592006-01-04 16:00:48 +01001661 snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
1662 snd_ac97_write_cache(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 c = emu10k1_remove_ctls;
1664 }
1665 for (; *c; c++)
1666 remove_ctl(card, *c);
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001667 } else if (emu->card_capabilities->i2c_adc) {
1668 c = audigy_remove_ctls_i2c_adc;
1669 for (; *c; c++)
1670 remove_ctl(card, *c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 } else {
Takashi Iwaif12aa402005-09-30 16:56:59 +02001672 no_ac97:
Lee Revell2b637da2005-03-30 13:51:18 +02001673 if (emu->card_capabilities->ecard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 strcpy(emu->card->mixername, "EMU APS");
1675 else if (emu->audigy)
1676 strcpy(emu->card->mixername, "SB Audigy");
1677 else
1678 strcpy(emu->card->mixername, "Emu10k1");
1679 }
1680
1681 if (emu->audigy)
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001682 if (emu->card_capabilities->adc_1361t)
1683 c = audigy_rename_ctls_1361t_adc;
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001684 else if (emu->card_capabilities->i2c_adc)
1685 c = audigy_rename_ctls_i2c_adc;
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001686 else
1687 c = audigy_rename_ctls;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001688 else
1689 c = emu10k1_rename_ctls;
1690 for (; *c; c += 2)
1691 rename_ctl(card, c[0], c[1]);
James Courtier-Dutton21fddde2006-04-09 17:36:39 +01001692
James Courtier-Duttone3b9bc02005-12-24 16:54:51 +01001693 if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */
1694 rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume");
1695 rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume");
1696 rename_ctl(card, "Aux2 Capture Volume", "Line3 Capture Volume");
1697 rename_ctl(card, "Mic Capture Volume", "Unknown1 Capture Volume");
1698 remove_ctl(card, "Headphone Playback Switch");
1699 remove_ctl(card, "Headphone Playback Volume");
1700 remove_ctl(card, "3D Control - Center");
1701 remove_ctl(card, "3D Control - Depth");
1702 remove_ctl(card, "3D Control - Switch");
1703 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL)
1705 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001706 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 if ((err = snd_ctl_add(card, kctl)))
1708 return err;
1709 if ((kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL)
1710 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001711 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 if ((err = snd_ctl_add(card, kctl)))
1713 return err;
1714 if ((kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu)) == NULL)
1715 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001716 kctl->id.device = pcm_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 if ((err = snd_ctl_add(card, kctl)))
1718 return err;
1719
1720 if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL)
1721 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001722 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723 if ((err = snd_ctl_add(card, kctl)))
1724 return err;
1725
1726 if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL)
1727 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001728 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 if ((err = snd_ctl_add(card, kctl)))
1730 return err;
1731
1732 if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL)
1733 return -ENOMEM;
Clemens Ladisch67ed4162005-07-29 15:32:58 +02001734 kctl->id.device = multi_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 if ((err = snd_ctl_add(card, kctl)))
1736 return err;
1737
1738 /* initialize the routing and volume table for each pcm playback stream */
1739 for (pcm = 0; pcm < 32; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001740 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 int v;
1742
1743 mix = &emu->pcm_mixer[pcm];
1744 mix->epcm = NULL;
1745
1746 for (v = 0; v < 4; v++)
1747 mix->send_routing[0][v] =
1748 mix->send_routing[1][v] =
1749 mix->send_routing[2][v] = v;
1750
1751 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1752 mix->send_volume[0][0] = mix->send_volume[0][1] =
1753 mix->send_volume[1][0] = mix->send_volume[2][1] = 255;
1754
1755 mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
1756 }
1757
1758 /* initialize the routing and volume table for the multichannel playback stream */
1759 for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001760 struct snd_emu10k1_pcm_mixer *mix;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761 int v;
1762
1763 mix = &emu->efx_pcm_mixer[pcm];
1764 mix->epcm = NULL;
1765
1766 mix->send_routing[0][0] = pcm;
1767 mix->send_routing[0][1] = (pcm == 0) ? 1 : 0;
1768 for (v = 0; v < 2; v++)
1769 mix->send_routing[0][2+v] = 13+v;
1770 if (emu->audigy)
1771 for (v = 0; v < 4; v++)
1772 mix->send_routing[0][4+v] = 60+v;
1773
1774 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
1775 mix->send_volume[0][0] = 255;
1776
1777 mix->attn[0] = 0xffff;
1778 }
1779
Lee Revell2b637da2005-03-30 13:51:18 +02001780 if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 /* sb live! and audigy */
1782 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
1783 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02001784 if (!emu->audigy)
1785 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786 if ((err = snd_ctl_add(card, kctl)))
1787 return err;
1788 if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL)
1789 return -ENOMEM;
Clemens Ladisch5549d542005-08-03 13:50:30 +02001790 if (!emu->audigy)
1791 kctl->id.device = emu->pcm_efx->device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792 if ((err = snd_ctl_add(card, kctl)))
1793 return err;
1794 }
1795
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001796 if ( emu->card_capabilities->emu1010) {
James Courtier-Dutton19b99fb2005-12-04 18:03:03 +01001797 ; /* Disable the snd_audigy_spdif_shared_spdif */
1798 } else if (emu->audigy) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799 if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
1800 return -ENOMEM;
1801 if ((err = snd_ctl_add(card, kctl)))
1802 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02001803#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804 if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
1805 return -ENOMEM;
1806 if ((err = snd_ctl_add(card, kctl)))
1807 return err;
James Courtier-Dutton001f7582005-04-09 23:38:25 +02001808#endif
Lee Revell2b637da2005-03-30 13:51:18 +02001809 } else if (! emu->card_capabilities->ecard) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 /* sb live! */
1811 if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL)
1812 return -ENOMEM;
1813 if ((err = snd_ctl_add(card, kctl)))
1814 return err;
1815 }
Lee Revell2b637da2005-03-30 13:51:18 +02001816 if (emu->card_capabilities->ca0151_chip) { /* P16V */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817 if ((err = snd_p16v_mixer(emu)))
1818 return err;
1819 }
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001820
1821 if ( emu->card_capabilities->emu1010) {
1822 int i;
1823
1824 for (i = 0; i < ARRAY_SIZE(snd_emu1010_output_enum_ctls); i++) {
1825 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_output_enum_ctls[i], emu));
1826 if (err < 0)
1827 return err;
1828 }
1829 for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) {
1830 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], emu));
1831 if (err < 0)
1832 return err;
1833 }
James Courtier-Dutton9148cc52006-10-09 23:08:00 +01001834 for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads); i++) {
1835 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_adc_pads[i], emu));
1836 if (err < 0)
1837 return err;
1838 }
1839 for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads); i++) {
1840 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_dac_pads[i], emu));
1841 if (err < 0)
1842 return err;
1843 }
James Courtier-Duttonb0dbdae2006-10-10 18:08:45 +01001844 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_internal_clock, emu));
1845 if (err < 0)
1846 return err;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001847 }
James Courtier-Dutton184c1e22006-12-06 15:58:02 +00001848
1849 if ( emu->card_capabilities->i2c_adc) {
1850 int i;
1851
1852 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_capture_source, emu));
1853 if (err < 0)
1854 return err;
1855
1856 for (i = 0; i < ARRAY_SIZE(snd_audigy_i2c_volume_ctls); i++) {
1857 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_volume_ctls[i], emu));
1858 if (err < 0)
1859 return err;
1860 }
1861 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862
1863 return 0;
1864}