[ALSA] Control API - TLV implementation for additional information like dB scale
[pandora-kernel.git] / sound / pci / ca0106 / ca0106_mixer.c
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 #include <sound/tlv.h>
74
75 #include "ca0106.h"
76
77 static DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale, -5150, 75, 1);
78
79 static int snd_ca0106_shared_spdif_info(struct snd_kcontrol *kcontrol,
80                                         struct snd_ctl_elem_info *uinfo)
81 {
82         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
83         uinfo->count = 1;
84         uinfo->value.integer.min = 0;
85         uinfo->value.integer.max = 1;
86         return 0;
87 }
88
89 static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol,
90                                         struct snd_ctl_elem_value *ucontrol)
91 {
92         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
93
94         ucontrol->value.enumerated.item[0] = emu->spdif_enable;
95         return 0;
96 }
97
98 static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol,
99                                         struct snd_ctl_elem_value *ucontrol)
100 {
101         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
102         unsigned int val;
103         int change = 0;
104         u32 mask;
105
106         val = ucontrol->value.enumerated.item[0] ;
107         change = (emu->spdif_enable != val);
108         if (change) {
109                 emu->spdif_enable = val;
110                 if (val == 1) {
111                         /* Digital */
112                         snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
113                         snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000);
114                         snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0,
115                                 snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000);
116                         mask = inl(emu->port + GPIO) & ~0x101;
117                         outl(mask, emu->port + GPIO);
118
119                 } else {
120                         /* Analog */
121                         snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
122                         snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000);
123                         snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0,
124                                 snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000);
125                         mask = inl(emu->port + GPIO) | 0x101;
126                         outl(mask, emu->port + GPIO);
127                 }
128         }
129         return change;
130 }
131
132 static int snd_ca0106_capture_source_info(struct snd_kcontrol *kcontrol,
133                                           struct snd_ctl_elem_info *uinfo)
134 {
135         static char *texts[6] = {
136                 "IEC958 out", "i2s mixer out", "IEC958 in", "i2s in", "AC97 in", "SRC out"
137         };
138
139         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
140         uinfo->count = 1;
141         uinfo->value.enumerated.items = 6;
142         if (uinfo->value.enumerated.item > 5)
143                 uinfo->value.enumerated.item = 5;
144         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
145         return 0;
146 }
147
148 static int snd_ca0106_capture_source_get(struct snd_kcontrol *kcontrol,
149                                         struct snd_ctl_elem_value *ucontrol)
150 {
151         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
152
153         ucontrol->value.enumerated.item[0] = emu->capture_source;
154         return 0;
155 }
156
157 static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
158                                         struct snd_ctl_elem_value *ucontrol)
159 {
160         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
161         unsigned int val;
162         int change = 0;
163         u32 mask;
164         u32 source;
165
166         val = ucontrol->value.enumerated.item[0] ;
167         change = (emu->capture_source != val);
168         if (change) {
169                 emu->capture_source = val;
170                 source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
171                 mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff;
172                 snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask);
173         }
174         return change;
175 }
176
177 static int snd_ca0106_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
178                                           struct snd_ctl_elem_info *uinfo)
179 {
180         static char *texts[6] = {
181                 "Phone", "Mic", "Line in", "Aux"
182         };
183
184         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
185         uinfo->count = 1;
186         uinfo->value.enumerated.items = 4;
187         if (uinfo->value.enumerated.item > 3)
188                 uinfo->value.enumerated.item = 3;
189         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
190         return 0;
191 }
192
193 static int snd_ca0106_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
194                                         struct snd_ctl_elem_value *ucontrol)
195 {
196         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
197
198         ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
199         return 0;
200 }
201
202 static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
203                                         struct snd_ctl_elem_value *ucontrol)
204 {
205         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
206         unsigned int source_id;
207         unsigned int ngain, ogain;
208         int change = 0;
209         u32 source;
210         /* If the capture source has changed,
211          * update the capture volume from the cached value
212          * for the particular source.
213          */
214         source_id = ucontrol->value.enumerated.item[0] ;
215         change = (emu->i2c_capture_source != source_id);
216         if (change) {
217                 snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
218                 ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
219                 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
220                 if (ngain != ogain)
221                         snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
222                 ngain = emu->i2c_capture_volume[source_id][1]; /* Left */
223                 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Left */
224                 if (ngain != ogain)
225                         snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
226                 source = 1 << source_id;
227                 snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */
228                 emu->i2c_capture_source = source_id;
229         }
230         return change;
231 }
232
233 static int snd_ca0106_capture_line_in_side_out_info(struct snd_kcontrol *kcontrol,
234                                                struct snd_ctl_elem_info *uinfo)
235 {
236         static char *texts[2] = { "Side out", "Line in" };
237
238         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
239         uinfo->count = 1;
240         uinfo->value.enumerated.items = 2;
241         if (uinfo->value.enumerated.item > 1)
242                 uinfo->value.enumerated.item = 1;
243         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
244         return 0;
245 }
246
247 static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol,
248                                                struct snd_ctl_elem_info *uinfo)
249 {
250         static char *texts[2] = { "Line in", "Mic in" };
251
252         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
253         uinfo->count = 1;
254         uinfo->value.enumerated.items = 2;
255         if (uinfo->value.enumerated.item > 1)
256                 uinfo->value.enumerated.item = 1;
257         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
258         return 0;
259 }
260
261 static int snd_ca0106_capture_mic_line_in_get(struct snd_kcontrol *kcontrol,
262                                         struct snd_ctl_elem_value *ucontrol)
263 {
264         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
265
266         ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in;
267         return 0;
268 }
269
270 static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
271                                         struct snd_ctl_elem_value *ucontrol)
272 {
273         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
274         unsigned int val;
275         int change = 0;
276         u32 tmp;
277
278         val = ucontrol->value.enumerated.item[0] ;
279         change = (emu->capture_mic_line_in != val);
280         if (change) {
281                 emu->capture_mic_line_in = val;
282                 if (val) {
283                         //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
284                         tmp = inl(emu->port+GPIO) & ~0x400;
285                         tmp = tmp | 0x400;
286                         outl(tmp, emu->port+GPIO);
287                         //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC);
288                 } else {
289                         //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
290                         tmp = inl(emu->port+GPIO) & ~0x400;
291                         outl(tmp, emu->port+GPIO);
292                         //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN);
293                 }
294         }
295         return change;
296 }
297
298 static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata =
299 {
300         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
301         .name =         "Shared Mic/Line in Capture Switch",
302         .info =         snd_ca0106_capture_mic_line_in_info,
303         .get =          snd_ca0106_capture_mic_line_in_get,
304         .put =          snd_ca0106_capture_mic_line_in_put
305 };
306
307 static struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out __devinitdata =
308 {
309         .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
310         .name =         "Shared Line in/Side out Capture Switch",
311         .info =         snd_ca0106_capture_line_in_side_out_info,
312         .get =          snd_ca0106_capture_mic_line_in_get,
313         .put =          snd_ca0106_capture_mic_line_in_put
314 };
315
316
317 static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol,
318                                  struct snd_ctl_elem_info *uinfo)
319 {
320         uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
321         uinfo->count = 1;
322         return 0;
323 }
324
325 static int snd_ca0106_spdif_get(struct snd_kcontrol *kcontrol,
326                                  struct snd_ctl_elem_value *ucontrol)
327 {
328         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
329         unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
330
331         ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff;
332         ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff;
333         ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff;
334         ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff;
335         return 0;
336 }
337
338 static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol,
339                                       struct snd_ctl_elem_value *ucontrol)
340 {
341         ucontrol->value.iec958.status[0] = 0xff;
342         ucontrol->value.iec958.status[1] = 0xff;
343         ucontrol->value.iec958.status[2] = 0xff;
344         ucontrol->value.iec958.status[3] = 0xff;
345         return 0;
346 }
347
348 static int snd_ca0106_spdif_put(struct snd_kcontrol *kcontrol,
349                                  struct snd_ctl_elem_value *ucontrol)
350 {
351         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
352         unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
353         int change;
354         unsigned int val;
355
356         val = (ucontrol->value.iec958.status[0] << 0) |
357               (ucontrol->value.iec958.status[1] << 8) |
358               (ucontrol->value.iec958.status[2] << 16) |
359               (ucontrol->value.iec958.status[3] << 24);
360         change = val != emu->spdif_bits[idx];
361         if (change) {
362                 snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, val);
363                 emu->spdif_bits[idx] = val;
364         }
365         return change;
366 }
367
368 static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol,
369                                   struct snd_ctl_elem_info *uinfo)
370 {
371         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
372         uinfo->count = 2;
373         uinfo->value.integer.min = 0;
374         uinfo->value.integer.max = 255;
375         return 0;
376 }
377
378 static int snd_ca0106_volume_get(struct snd_kcontrol *kcontrol,
379                                  struct snd_ctl_elem_value *ucontrol)
380 {
381         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
382         unsigned int value;
383         int channel_id, reg;
384
385         channel_id = (kcontrol->private_value >> 8) & 0xff;
386         reg = kcontrol->private_value & 0xff;
387
388         value = snd_ca0106_ptr_read(emu, reg, channel_id);
389         ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */
390         ucontrol->value.integer.value[1] = 0xff - ((value >> 16) & 0xff); /* Right */
391         return 0;
392 }
393
394 static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol,
395                                  struct snd_ctl_elem_value *ucontrol)
396 {
397         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
398         unsigned int oval, nval;
399         int channel_id, reg;
400
401         channel_id = (kcontrol->private_value >> 8) & 0xff;
402         reg = kcontrol->private_value & 0xff;
403
404         oval = snd_ca0106_ptr_read(emu, reg, channel_id);
405         nval = ((0xff - ucontrol->value.integer.value[0]) << 24) |
406                 ((0xff - ucontrol->value.integer.value[1]) << 16);
407         nval |= ((0xff - ucontrol->value.integer.value[0]) << 8) |
408                 ((0xff - ucontrol->value.integer.value[1]) );
409         if (oval == nval)
410                 return 0;
411         snd_ca0106_ptr_write(emu, reg, channel_id, nval);
412         return 1;
413 }
414
415 static int snd_ca0106_i2c_volume_info(struct snd_kcontrol *kcontrol,
416                                   struct snd_ctl_elem_info *uinfo)
417 {
418         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
419         uinfo->count = 2;
420         uinfo->value.integer.min = 0;
421         uinfo->value.integer.max = 255;
422         return 0;
423 }
424
425 static int snd_ca0106_i2c_volume_get(struct snd_kcontrol *kcontrol,
426                                  struct snd_ctl_elem_value *ucontrol)
427 {
428         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
429         int source_id;
430
431         source_id = kcontrol->private_value;
432
433         ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
434         ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
435         return 0;
436 }
437
438 static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol,
439                                  struct snd_ctl_elem_value *ucontrol)
440 {
441         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
442         unsigned int ogain;
443         unsigned int ngain;
444         int source_id;
445         int change = 0;
446
447         source_id = kcontrol->private_value;
448         ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
449         ngain = ucontrol->value.integer.value[0];
450         if (ngain > 0xff)
451                 return 0;
452         if (ogain != ngain) {
453                 if (emu->i2c_capture_source == source_id)
454                         snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
455                 emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0];
456                 change = 1;
457         }
458         ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
459         ngain = ucontrol->value.integer.value[1];
460         if (ngain > 0xff)
461                 return 0;
462         if (ogain != ngain) {
463                 if (emu->i2c_capture_source == source_id)
464                         snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
465                 emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1];
466                 change = 1;
467         }
468
469         return change;
470 }
471
472 #define CA_VOLUME(xname,chid,reg) \
473 {                                                               \
474         .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,     \
475         .info =  snd_ca0106_volume_info,                        \
476         .get =   snd_ca0106_volume_get,                         \
477         .put =   snd_ca0106_volume_put,                         \
478         .tlv =   snd_ca0106_db_scale,                           \
479         .private_value = ((chid) << 8) | (reg)                  \
480 }
481
482 #define I2C_VOLUME(xname,chid) \
483 {                                                               \
484         .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,     \
485         .info =  snd_ca0106_i2c_volume_info,                    \
486         .get =   snd_ca0106_i2c_volume_get,                     \
487         .put =   snd_ca0106_i2c_volume_put,                     \
488         .private_value = chid                                   \
489 }
490
491
492 static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
493         CA_VOLUME("Analog Front Playback Volume",
494                   CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2),
495         CA_VOLUME("Analog Rear Playback Volume",
496                   CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2),
497         CA_VOLUME("Analog Center/LFE Playback Volume",
498                   CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2),
499         CA_VOLUME("Analog Side Playback Volume",
500                   CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2),
501
502         CA_VOLUME("IEC958 Front Playback Volume",
503                   CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1),
504         CA_VOLUME("IEC958 Rear Playback Volume",
505                   CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1),
506         CA_VOLUME("IEC958 Center/LFE Playback Volume",
507                   CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1),
508         CA_VOLUME("IEC958 Unknown Playback Volume",
509                   CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1),
510
511         CA_VOLUME("CAPTURE feedback Playback Volume",
512                   1, CAPTURE_CONTROL),
513
514         I2C_VOLUME("Phone Capture Volume", 0),
515         I2C_VOLUME("Mic Capture Volume", 1),
516         I2C_VOLUME("Line in Capture Volume", 2),
517         I2C_VOLUME("Aux Capture Volume", 3),
518
519         {
520                 .access =       SNDRV_CTL_ELEM_ACCESS_READ,
521                 .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
522                 .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
523                 .count =        4,
524                 .info =         snd_ca0106_spdif_info,
525                 .get =          snd_ca0106_spdif_get_mask
526         },
527         {
528                 .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
529                 .name =         "IEC958 Playback Switch",
530                 .info =         snd_ca0106_shared_spdif_info,
531                 .get =          snd_ca0106_shared_spdif_get,
532                 .put =          snd_ca0106_shared_spdif_put
533         },
534         {
535                 .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
536                 .name =         "Digital Capture Source",
537                 .info =         snd_ca0106_capture_source_info,
538                 .get =          snd_ca0106_capture_source_get,
539                 .put =          snd_ca0106_capture_source_put
540         },
541         {
542                 .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
543                 .name =         "Capture Source",
544                 .info =         snd_ca0106_i2c_capture_source_info,
545                 .get =          snd_ca0106_i2c_capture_source_get,
546                 .put =          snd_ca0106_i2c_capture_source_put
547         },
548         {
549                 .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
550                 .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
551                 .count =        4,
552                 .info =         snd_ca0106_spdif_info,
553                 .get =          snd_ca0106_spdif_get,
554                 .put =          snd_ca0106_spdif_put
555         },
556 };
557
558 static int __devinit remove_ctl(struct snd_card *card, const char *name)
559 {
560         struct snd_ctl_elem_id id;
561         memset(&id, 0, sizeof(id));
562         strcpy(id.name, name);
563         id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
564         return snd_ctl_remove_id(card, &id);
565 }
566
567 static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, const char *name)
568 {
569         struct snd_ctl_elem_id sid;
570         memset(&sid, 0, sizeof(sid));
571         /* FIXME: strcpy is bad. */
572         strcpy(sid.name, name);
573         sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
574         return snd_ctl_find_id(card, &sid);
575 }
576
577 static int __devinit rename_ctl(struct snd_card *card, const char *src, const char *dst)
578 {
579         struct snd_kcontrol *kctl = ctl_find(card, src);
580         if (kctl) {
581                 strcpy(kctl->id.name, dst);
582                 return 0;
583         }
584         return -ENOENT;
585 }
586
587 int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
588 {
589         int i, err;
590         struct snd_card *card = emu->card;
591         char **c;
592         static char *ca0106_remove_ctls[] = {
593                 "Master Mono Playback Switch",
594                 "Master Mono Playback Volume",
595                 "3D Control - Switch",
596                 "3D Control Sigmatel - Depth",
597                 "PCM Playback Switch",
598                 "PCM Playback Volume",
599                 "CD Playback Switch",
600                 "CD Playback Volume",
601                 "Phone Playback Switch",
602                 "Phone Playback Volume",
603                 "Video Playback Switch",
604                 "Video Playback Volume",
605                 "PC Speaker Playback Switch",
606                 "PC Speaker Playback Volume",
607                 "Mono Output Select",
608                 "Capture Source",
609                 "Capture Switch",
610                 "Capture Volume",
611                 "External Amplifier",
612                 "Sigmatel 4-Speaker Stereo Playback Switch",
613                 "Sigmatel Surround Phase Inversion Playback ",
614                 NULL
615         };
616         static char *ca0106_rename_ctls[] = {
617                 "Master Playback Switch", "Capture Switch",
618                 "Master Playback Volume", "Capture Volume",
619                 "Line Playback Switch", "AC97 Line Capture Switch",
620                 "Line Playback Volume", "AC97 Line Capture Volume",
621                 "Aux Playback Switch", "AC97 Aux Capture Switch",
622                 "Aux Playback Volume", "AC97 Aux Capture Volume",
623                 "Mic Playback Switch", "AC97 Mic Capture Switch",
624                 "Mic Playback Volume", "AC97 Mic Capture Volume",
625                 "Mic Select", "AC97 Mic Select",
626                 "Mic Boost (+20dB)", "AC97 Mic Boost (+20dB)",
627                 NULL
628         };
629 #if 1
630         for (c = ca0106_remove_ctls; *c; c++)
631                 remove_ctl(card, *c);
632         for (c = ca0106_rename_ctls; *c; c += 2)
633                 rename_ctl(card, c[0], c[1]);
634 #endif
635
636         for (i = 0; i < ARRAY_SIZE(snd_ca0106_volume_ctls); i++) {
637                 err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_volume_ctls[i], emu));
638                 if (err < 0)
639                         return err;
640         }
641         if (emu->details->i2c_adc == 1) {
642                 if (emu->details->gpio_type == 1)
643                         err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu));
644                 else  /* gpio_type == 2 */
645                         err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_line_in_side_out, emu));
646                 if (err < 0)
647                         return err;
648         }
649         return 0;
650 }
651