xref: /linux/sound/pci/ca0106/ca0106_mixer.c (revision 5e8d780d745c1619aba81fe7166c5a4b5cad2b84)
1 /*
2  *  Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
3  *  Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
4  *  Version: 0.0.17
5  *
6  *  FEATURES currently supported:
7  *    See ca0106_main.c for features.
8  *
9  *  Changelog:
10  *    Support interrupts per period.
11  *    Removed noise from Center/LFE channel when in Analog mode.
12  *    Rename and remove mixer controls.
13  *  0.0.6
14  *    Use separate card based DMA buffer for periods table list.
15  *  0.0.7
16  *    Change remove and rename ctrls into lists.
17  *  0.0.8
18  *    Try to fix capture sources.
19  *  0.0.9
20  *    Fix AC3 output.
21  *    Enable S32_LE format support.
22  *  0.0.10
23  *    Enable playback 48000 and 96000 rates. (Rates other that these do not work, even with "plug:front".)
24  *  0.0.11
25  *    Add Model name recognition.
26  *  0.0.12
27  *    Correct interrupt timing. interrupt at end of period, instead of in the middle of a playback period.
28  *    Remove redundent "voice" handling.
29  *  0.0.13
30  *    Single trigger call for multi channels.
31  *  0.0.14
32  *    Set limits based on what the sound card hardware can do.
33  *    playback periods_min=2, periods_max=8
34  *    capture hw constraints require period_size = n * 64 bytes.
35  *    playback hw constraints require period_size = n * 64 bytes.
36  *  0.0.15
37  *    Separated ca0106.c into separate functional .c files.
38  *  0.0.16
39  *    Modified Copyright message.
40  *  0.0.17
41  *    Implement Mic and Line in Capture.
42  *
43  *  This code was initally based on code from ALSA's emu10k1x.c which is:
44  *  Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
45  *
46  *   This program is free software; you can redistribute it and/or modify
47  *   it under the terms of the GNU General Public License as published by
48  *   the Free Software Foundation; either version 2 of the License, or
49  *   (at your option) any later version.
50  *
51  *   This program is distributed in the hope that it will be useful,
52  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
53  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
54  *   GNU General Public License for more details.
55  *
56  *   You should have received a copy of the GNU General Public License
57  *   along with this program; if not, write to the Free Software
58  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
59  *
60  */
61 #include <sound/driver.h>
62 #include <linux/delay.h>
63 #include <linux/init.h>
64 #include <linux/interrupt.h>
65 #include <linux/pci.h>
66 #include <linux/slab.h>
67 #include <linux/moduleparam.h>
68 #include <sound/core.h>
69 #include <sound/initval.h>
70 #include <sound/pcm.h>
71 #include <sound/ac97_codec.h>
72 #include <sound/info.h>
73 
74 #include "ca0106.h"
75 
76 static int snd_ca0106_shared_spdif_info(struct snd_kcontrol *kcontrol,
77 					struct snd_ctl_elem_info *uinfo)
78 {
79 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
80 	uinfo->count = 1;
81 	uinfo->value.integer.min = 0;
82 	uinfo->value.integer.max = 1;
83 	return 0;
84 }
85 
86 static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol,
87 					struct snd_ctl_elem_value *ucontrol)
88 {
89 	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
90 
91 	ucontrol->value.enumerated.item[0] = emu->spdif_enable;
92 	return 0;
93 }
94 
95 static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol,
96 					struct snd_ctl_elem_value *ucontrol)
97 {
98 	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
99 	unsigned int val;
100 	int change = 0;
101 	u32 mask;
102 
103 	val = ucontrol->value.enumerated.item[0] ;
104 	change = (emu->spdif_enable != val);
105 	if (change) {
106 		emu->spdif_enable = val;
107 		if (val == 1) {
108 			/* Digital */
109 			snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
110 			snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000);
111 			snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0,
112 				snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000);
113 			mask = inl(emu->port + GPIO) & ~0x101;
114 			outl(mask, emu->port + GPIO);
115 
116 		} else {
117 			/* Analog */
118 			snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
119 			snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000);
120 			snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0,
121 				snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000);
122 			mask = inl(emu->port + GPIO) | 0x101;
123 			outl(mask, emu->port + GPIO);
124 		}
125 	}
126         return change;
127 }
128 
129 static int snd_ca0106_capture_source_info(struct snd_kcontrol *kcontrol,
130 					  struct snd_ctl_elem_info *uinfo)
131 {
132 	static char *texts[6] = {
133 		"IEC958 out", "i2s mixer out", "IEC958 in", "i2s in", "AC97 in", "SRC out"
134 	};
135 
136 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
137 	uinfo->count = 1;
138 	uinfo->value.enumerated.items = 6;
139 	if (uinfo->value.enumerated.item > 5)
140                 uinfo->value.enumerated.item = 5;
141 	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
142 	return 0;
143 }
144 
145 static int snd_ca0106_capture_source_get(struct snd_kcontrol *kcontrol,
146 					struct snd_ctl_elem_value *ucontrol)
147 {
148 	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
149 
150 	ucontrol->value.enumerated.item[0] = emu->capture_source;
151 	return 0;
152 }
153 
154 static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
155 					struct snd_ctl_elem_value *ucontrol)
156 {
157 	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
158 	unsigned int val;
159 	int change = 0;
160 	u32 mask;
161 	u32 source;
162 
163 	val = ucontrol->value.enumerated.item[0] ;
164 	change = (emu->capture_source != val);
165 	if (change) {
166 		emu->capture_source = val;
167 		source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
168 		mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff;
169 		snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask);
170 	}
171         return change;
172 }
173 
174 static int snd_ca0106_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
175 					  struct snd_ctl_elem_info *uinfo)
176 {
177 	static char *texts[6] = {
178 		"Phone", "Mic", "Line in", "Aux"
179 	};
180 
181 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
182 	uinfo->count = 1;
183 	uinfo->value.enumerated.items = 4;
184 	if (uinfo->value.enumerated.item > 3)
185                 uinfo->value.enumerated.item = 3;
186 	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
187 	return 0;
188 }
189 
190 static int snd_ca0106_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
191 					struct snd_ctl_elem_value *ucontrol)
192 {
193 	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
194 
195 	ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
196 	return 0;
197 }
198 
199 static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
200 					struct snd_ctl_elem_value *ucontrol)
201 {
202 	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
203 	unsigned int source_id;
204 	unsigned int ngain, ogain;
205 	int change = 0;
206 	u32 source;
207 	/* If the capture source has changed,
208 	 * update the capture volume from the cached value
209 	 * for the particular source.
210 	 */
211 	source_id = ucontrol->value.enumerated.item[0] ;
212 	change = (emu->i2c_capture_source != source_id);
213 	if (change) {
214 		snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
215 		ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
216 		ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
217 		if (ngain != ogain)
218 			snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
219 		ngain = emu->i2c_capture_volume[source_id][1]; /* Left */
220 		ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Left */
221 		if (ngain != ogain)
222 			snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
223 		source = 1 << source_id;
224 		snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */
225 		emu->i2c_capture_source = source_id;
226 	}
227         return change;
228 }
229 
230 static int snd_ca0106_capture_line_in_side_out_info(struct snd_kcontrol *kcontrol,
231 					       struct snd_ctl_elem_info *uinfo)
232 {
233 	static char *texts[2] = { "Side out", "Line in" };
234 
235 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
236 	uinfo->count = 1;
237 	uinfo->value.enumerated.items = 2;
238 	if (uinfo->value.enumerated.item > 1)
239                 uinfo->value.enumerated.item = 1;
240 	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
241 	return 0;
242 }
243 
244 static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol,
245 					       struct snd_ctl_elem_info *uinfo)
246 {
247 	static char *texts[2] = { "Line in", "Mic in" };
248 
249 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
250 	uinfo->count = 1;
251 	uinfo->value.enumerated.items = 2;
252 	if (uinfo->value.enumerated.item > 1)
253                 uinfo->value.enumerated.item = 1;
254 	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
255 	return 0;
256 }
257 
258 static int snd_ca0106_capture_mic_line_in_get(struct snd_kcontrol *kcontrol,
259 					struct snd_ctl_elem_value *ucontrol)
260 {
261 	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
262 
263 	ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in;
264 	return 0;
265 }
266 
267 static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
268 					struct snd_ctl_elem_value *ucontrol)
269 {
270 	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
271 	unsigned int val;
272 	int change = 0;
273 	u32 tmp;
274 
275 	val = ucontrol->value.enumerated.item[0] ;
276 	change = (emu->capture_mic_line_in != val);
277 	if (change) {
278 		emu->capture_mic_line_in = val;
279 		if (val) {
280 			//snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
281 			tmp = inl(emu->port+GPIO) & ~0x400;
282 			tmp = tmp | 0x400;
283 			outl(tmp, emu->port+GPIO);
284 			//snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC);
285 		} else {
286 			//snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
287 			tmp = inl(emu->port+GPIO) & ~0x400;
288 			outl(tmp, emu->port+GPIO);
289 			//snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN);
290 		}
291 	}
292         return change;
293 }
294 
295 static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata =
296 {
297 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
298 	.name =		"Shared Mic/Line in Capture Switch",
299 	.info =		snd_ca0106_capture_mic_line_in_info,
300 	.get =		snd_ca0106_capture_mic_line_in_get,
301 	.put =		snd_ca0106_capture_mic_line_in_put
302 };
303 
304 static struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out __devinitdata =
305 {
306 	.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
307 	.name =		"Shared Line in/Side out Capture Switch",
308 	.info =		snd_ca0106_capture_line_in_side_out_info,
309 	.get =		snd_ca0106_capture_mic_line_in_get,
310 	.put =		snd_ca0106_capture_mic_line_in_put
311 };
312 
313 
314 static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol,
315 				 struct snd_ctl_elem_info *uinfo)
316 {
317 	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
318 	uinfo->count = 1;
319 	return 0;
320 }
321 
322 static int snd_ca0106_spdif_get(struct snd_kcontrol *kcontrol,
323                                  struct snd_ctl_elem_value *ucontrol)
324 {
325 	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
326 	unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
327 
328 	ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff;
329 	ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff;
330 	ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff;
331 	ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff;
332         return 0;
333 }
334 
335 static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol,
336 				      struct snd_ctl_elem_value *ucontrol)
337 {
338 	ucontrol->value.iec958.status[0] = 0xff;
339 	ucontrol->value.iec958.status[1] = 0xff;
340 	ucontrol->value.iec958.status[2] = 0xff;
341 	ucontrol->value.iec958.status[3] = 0xff;
342         return 0;
343 }
344 
345 static int snd_ca0106_spdif_put(struct snd_kcontrol *kcontrol,
346                                  struct snd_ctl_elem_value *ucontrol)
347 {
348 	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
349 	unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
350 	int change;
351 	unsigned int val;
352 
353 	val = (ucontrol->value.iec958.status[0] << 0) |
354 	      (ucontrol->value.iec958.status[1] << 8) |
355 	      (ucontrol->value.iec958.status[2] << 16) |
356 	      (ucontrol->value.iec958.status[3] << 24);
357 	change = val != emu->spdif_bits[idx];
358 	if (change) {
359 		snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, val);
360 		emu->spdif_bits[idx] = val;
361 	}
362         return change;
363 }
364 
365 static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol,
366 				  struct snd_ctl_elem_info *uinfo)
367 {
368         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
369         uinfo->count = 2;
370         uinfo->value.integer.min = 0;
371         uinfo->value.integer.max = 255;
372         return 0;
373 }
374 
375 static int snd_ca0106_volume_get(struct snd_kcontrol *kcontrol,
376 				 struct snd_ctl_elem_value *ucontrol)
377 {
378         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
379         unsigned int value;
380 	int channel_id, reg;
381 
382 	channel_id = (kcontrol->private_value >> 8) & 0xff;
383 	reg = kcontrol->private_value & 0xff;
384 
385         value = snd_ca0106_ptr_read(emu, reg, channel_id);
386         ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */
387         ucontrol->value.integer.value[1] = 0xff - ((value >> 16) & 0xff); /* Right */
388         return 0;
389 }
390 
391 static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol,
392 				 struct snd_ctl_elem_value *ucontrol)
393 {
394         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
395         unsigned int oval, nval;
396 	int channel_id, reg;
397 
398 	channel_id = (kcontrol->private_value >> 8) & 0xff;
399 	reg = kcontrol->private_value & 0xff;
400 
401 	oval = snd_ca0106_ptr_read(emu, reg, channel_id);
402 	nval = ((0xff - ucontrol->value.integer.value[0]) << 24) |
403 		((0xff - ucontrol->value.integer.value[1]) << 16);
404         nval |= ((0xff - ucontrol->value.integer.value[0]) << 8) |
405 		((0xff - ucontrol->value.integer.value[1]) );
406 	if (oval == nval)
407 		return 0;
408 	snd_ca0106_ptr_write(emu, reg, channel_id, nval);
409 	return 1;
410 }
411 
412 static int snd_ca0106_i2c_volume_info(struct snd_kcontrol *kcontrol,
413 				  struct snd_ctl_elem_info *uinfo)
414 {
415         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
416         uinfo->count = 2;
417         uinfo->value.integer.min = 0;
418         uinfo->value.integer.max = 255;
419         return 0;
420 }
421 
422 static int snd_ca0106_i2c_volume_get(struct snd_kcontrol *kcontrol,
423 				 struct snd_ctl_elem_value *ucontrol)
424 {
425         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
426 	int source_id;
427 
428 	source_id = kcontrol->private_value;
429 
430         ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
431         ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
432         return 0;
433 }
434 
435 static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol,
436 				 struct snd_ctl_elem_value *ucontrol)
437 {
438         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
439         unsigned int ogain;
440         unsigned int ngain;
441 	int source_id;
442 	int change = 0;
443 
444 	source_id = kcontrol->private_value;
445 	ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
446 	ngain = ucontrol->value.integer.value[0];
447 	if (ngain > 0xff)
448 		return 0;
449 	if (ogain != ngain) {
450 		if (emu->i2c_capture_source == source_id)
451 			snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
452 		emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0];
453 		change = 1;
454 	}
455 	ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
456 	ngain = ucontrol->value.integer.value[1];
457 	if (ngain > 0xff)
458 		return 0;
459 	if (ogain != ngain) {
460 		if (emu->i2c_capture_source == source_id)
461 			snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
462 		emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1];
463 		change = 1;
464 	}
465 
466 	return change;
467 }
468 
469 #define CA_VOLUME(xname,chid,reg) \
470 {								\
471 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,	\
472 	.info =	 snd_ca0106_volume_info,			\
473 	.get =   snd_ca0106_volume_get,				\
474 	.put =   snd_ca0106_volume_put,				\
475 	.private_value = ((chid) << 8) | (reg)			\
476 }
477 
478 #define I2C_VOLUME(xname,chid) \
479 {								\
480 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,	\
481 	.info =  snd_ca0106_i2c_volume_info,			\
482 	.get =   snd_ca0106_i2c_volume_get,			\
483 	.put =   snd_ca0106_i2c_volume_put,			\
484 	.private_value = chid					\
485 }
486 
487 
488 static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
489 	CA_VOLUME("Analog Front Playback Volume",
490 		  CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2),
491         CA_VOLUME("Analog Rear Playback Volume",
492 		  CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2),
493 	CA_VOLUME("Analog Center/LFE Playback Volume",
494 		  CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2),
495         CA_VOLUME("Analog Side Playback Volume",
496 		  CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2),
497 
498         CA_VOLUME("IEC958 Front Playback Volume",
499 		  CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1),
500 	CA_VOLUME("IEC958 Rear Playback Volume",
501 		  CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1),
502 	CA_VOLUME("IEC958 Center/LFE Playback Volume",
503 		  CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1),
504 	CA_VOLUME("IEC958 Unknown Playback Volume",
505 		  CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1),
506 
507         CA_VOLUME("CAPTURE feedback Playback Volume",
508 		  1, CAPTURE_CONTROL),
509 
510         I2C_VOLUME("Phone Capture Volume", 0),
511         I2C_VOLUME("Mic Capture Volume", 1),
512         I2C_VOLUME("Line in Capture Volume", 2),
513         I2C_VOLUME("Aux Capture Volume", 3),
514 
515 	{
516 		.access =	SNDRV_CTL_ELEM_ACCESS_READ,
517 		.iface =        SNDRV_CTL_ELEM_IFACE_PCM,
518 		.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
519 		.count =	4,
520 		.info =         snd_ca0106_spdif_info,
521 		.get =          snd_ca0106_spdif_get_mask
522 	},
523 	{
524 		.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
525 		.name =		"IEC958 Playback Switch",
526 		.info =		snd_ca0106_shared_spdif_info,
527 		.get =		snd_ca0106_shared_spdif_get,
528 		.put =		snd_ca0106_shared_spdif_put
529 	},
530 	{
531 		.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
532 		.name =		"Digital Capture Source",
533 		.info =		snd_ca0106_capture_source_info,
534 		.get =		snd_ca0106_capture_source_get,
535 		.put =		snd_ca0106_capture_source_put
536 	},
537 	{
538 		.iface =	SNDRV_CTL_ELEM_IFACE_MIXER,
539 		.name =		"Capture Source",
540 		.info =		snd_ca0106_i2c_capture_source_info,
541 		.get =		snd_ca0106_i2c_capture_source_get,
542 		.put =		snd_ca0106_i2c_capture_source_put
543 	},
544 	{
545 		.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
546 		.name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
547 		.count =	4,
548 		.info =         snd_ca0106_spdif_info,
549 		.get =          snd_ca0106_spdif_get,
550 		.put =          snd_ca0106_spdif_put
551 	},
552 };
553 
554 static int __devinit remove_ctl(struct snd_card *card, const char *name)
555 {
556 	struct snd_ctl_elem_id id;
557 	memset(&id, 0, sizeof(id));
558 	strcpy(id.name, name);
559 	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
560 	return snd_ctl_remove_id(card, &id);
561 }
562 
563 static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, const char *name)
564 {
565 	struct snd_ctl_elem_id sid;
566 	memset(&sid, 0, sizeof(sid));
567 	/* FIXME: strcpy is bad. */
568 	strcpy(sid.name, name);
569 	sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
570 	return snd_ctl_find_id(card, &sid);
571 }
572 
573 static int __devinit rename_ctl(struct snd_card *card, const char *src, const char *dst)
574 {
575 	struct snd_kcontrol *kctl = ctl_find(card, src);
576 	if (kctl) {
577 		strcpy(kctl->id.name, dst);
578 		return 0;
579 	}
580 	return -ENOENT;
581 }
582 
583 int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
584 {
585 	int i, err;
586         struct snd_card *card = emu->card;
587 	char **c;
588 	static char *ca0106_remove_ctls[] = {
589 		"Master Mono Playback Switch",
590 		"Master Mono Playback Volume",
591 		"3D Control - Switch",
592 		"3D Control Sigmatel - Depth",
593 		"PCM Playback Switch",
594 		"PCM Playback Volume",
595 		"CD Playback Switch",
596 		"CD Playback Volume",
597 		"Phone Playback Switch",
598 		"Phone Playback Volume",
599 		"Video Playback Switch",
600 		"Video Playback Volume",
601 		"PC Speaker Playback Switch",
602 		"PC Speaker Playback Volume",
603 		"Mono Output Select",
604 		"Capture Source",
605 		"Capture Switch",
606 		"Capture Volume",
607 		"External Amplifier",
608 		"Sigmatel 4-Speaker Stereo Playback Switch",
609 		"Sigmatel Surround Phase Inversion Playback ",
610 		NULL
611 	};
612 	static char *ca0106_rename_ctls[] = {
613 		"Master Playback Switch", "Capture Switch",
614 		"Master Playback Volume", "Capture Volume",
615 		"Line Playback Switch", "AC97 Line Capture Switch",
616 		"Line Playback Volume", "AC97 Line Capture Volume",
617 		"Aux Playback Switch", "AC97 Aux Capture Switch",
618 		"Aux Playback Volume", "AC97 Aux Capture Volume",
619 		"Mic Playback Switch", "AC97 Mic Capture Switch",
620 		"Mic Playback Volume", "AC97 Mic Capture Volume",
621 		"Mic Select", "AC97 Mic Select",
622 		"Mic Boost (+20dB)", "AC97 Mic Boost (+20dB)",
623 		NULL
624 	};
625 #if 1
626 	for (c = ca0106_remove_ctls; *c; c++)
627 		remove_ctl(card, *c);
628 	for (c = ca0106_rename_ctls; *c; c += 2)
629 		rename_ctl(card, c[0], c[1]);
630 #endif
631 
632 	for (i = 0; i < ARRAY_SIZE(snd_ca0106_volume_ctls); i++) {
633 		err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_volume_ctls[i], emu));
634 		if (err < 0)
635 			return err;
636 	}
637 	if (emu->details->i2c_adc == 1) {
638 		if (emu->details->gpio_type == 1)
639 			err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu));
640 		else  /* gpio_type == 2 */
641 			err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_line_in_side_out, emu));
642 		if (err < 0)
643 			return err;
644 	}
645         return 0;
646 }
647 
648