]> err.no Git - linux-2.6/blob - sound/pci/ca0106/ca0106_mixer.c
Merge branch 'task_killable' of git://git.kernel.org/pub/scm/linux/kernel/git/willy...
[linux-2.6] / 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.18
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  *  0.0.18
43  *    Add support for mute control on SB Live 24bit (cards w/ SPI DAC)
44  *
45  *  This code was initally based on code from ALSA's emu10k1x.c which is:
46  *  Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
47  *
48  *   This program is free software; you can redistribute it and/or modify
49  *   it under the terms of the GNU General Public License as published by
50  *   the Free Software Foundation; either version 2 of the License, or
51  *   (at your option) any later version.
52  *
53  *   This program is distributed in the hope that it will be useful,
54  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
55  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
56  *   GNU General Public License for more details.
57  *
58  *   You should have received a copy of the GNU General Public License
59  *   along with this program; if not, write to the Free Software
60  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
61  *
62  */
63 #include <linux/delay.h>
64 #include <linux/init.h>
65 #include <linux/interrupt.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 #include <asm/io.h>
75
76 #include "ca0106.h"
77
78 static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1);
79 static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1);
80
81 #define snd_ca0106_shared_spdif_info    snd_ctl_boolean_mono_info
82
83 static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol,
84                                         struct snd_ctl_elem_value *ucontrol)
85 {
86         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
87
88         ucontrol->value.integer.value[0] = emu->spdif_enable;
89         return 0;
90 }
91
92 static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol,
93                                         struct snd_ctl_elem_value *ucontrol)
94 {
95         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
96         unsigned int val;
97         int change = 0;
98         u32 mask;
99
100         val = !!ucontrol->value.integer.value[0];
101         change = (emu->spdif_enable != val);
102         if (change) {
103                 emu->spdif_enable = val;
104                 if (val) {
105                         /* Digital */
106                         snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
107                         snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000);
108                         snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0,
109                                 snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000);
110                         mask = inl(emu->port + GPIO) & ~0x101;
111                         outl(mask, emu->port + GPIO);
112
113                 } else {
114                         /* Analog */
115                         snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
116                         snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000);
117                         snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0,
118                                 snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000);
119                         mask = inl(emu->port + GPIO) | 0x101;
120                         outl(mask, emu->port + GPIO);
121                 }
122         }
123         return change;
124 }
125
126 static int snd_ca0106_capture_source_info(struct snd_kcontrol *kcontrol,
127                                           struct snd_ctl_elem_info *uinfo)
128 {
129         static char *texts[6] = {
130                 "IEC958 out", "i2s mixer out", "IEC958 in", "i2s in", "AC97 in", "SRC out"
131         };
132
133         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
134         uinfo->count = 1;
135         uinfo->value.enumerated.items = 6;
136         if (uinfo->value.enumerated.item > 5)
137                 uinfo->value.enumerated.item = 5;
138         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
139         return 0;
140 }
141
142 static int snd_ca0106_capture_source_get(struct snd_kcontrol *kcontrol,
143                                         struct snd_ctl_elem_value *ucontrol)
144 {
145         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
146
147         ucontrol->value.enumerated.item[0] = emu->capture_source;
148         return 0;
149 }
150
151 static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
152                                         struct snd_ctl_elem_value *ucontrol)
153 {
154         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
155         unsigned int val;
156         int change = 0;
157         u32 mask;
158         u32 source;
159
160         val = ucontrol->value.enumerated.item[0] ;
161         if (val >= 6)
162                 return -EINVAL;
163         change = (emu->capture_source != val);
164         if (change) {
165                 emu->capture_source = val;
166                 source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
167                 mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff;
168                 snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask);
169         }
170         return change;
171 }
172
173 static int snd_ca0106_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
174                                           struct snd_ctl_elem_info *uinfo)
175 {
176         static char *texts[6] = {
177                 "Phone", "Mic", "Line in", "Aux"
178         };
179
180         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
181         uinfo->count = 1;
182         uinfo->value.enumerated.items = 4;
183         if (uinfo->value.enumerated.item > 3)
184                 uinfo->value.enumerated.item = 3;
185         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
186         return 0;
187 }
188
189 static int snd_ca0106_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
190                                         struct snd_ctl_elem_value *ucontrol)
191 {
192         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
193
194         ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
195         return 0;
196 }
197
198 static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
199                                         struct snd_ctl_elem_value *ucontrol)
200 {
201         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
202         unsigned int source_id;
203         unsigned int ngain, ogain;
204         int change = 0;
205         u32 source;
206         /* If the capture source has changed,
207          * update the capture volume from the cached value
208          * for the particular source.
209          */
210         source_id = ucontrol->value.enumerated.item[0] ;
211         if (source_id >= 4)
212                 return -EINVAL;
213         change = (emu->i2c_capture_source != source_id);
214         if (change) {
215                 snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
216                 ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
217                 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
218                 if (ngain != ogain)
219                         snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
220                 ngain = emu->i2c_capture_volume[source_id][1]; /* Left */
221                 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Left */
222                 if (ngain != ogain)
223                         snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
224                 source = 1 << source_id;
225                 snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */
226                 emu->i2c_capture_source = source_id;
227         }
228         return change;
229 }
230
231 static int snd_ca0106_capture_line_in_side_out_info(struct snd_kcontrol *kcontrol,
232                                                struct snd_ctl_elem_info *uinfo)
233 {
234         static char *texts[2] = { "Side out", "Line in" };
235
236         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
237         uinfo->count = 1;
238         uinfo->value.enumerated.items = 2;
239         if (uinfo->value.enumerated.item > 1)
240                 uinfo->value.enumerated.item = 1;
241         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
242         return 0;
243 }
244
245 static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol,
246                                                struct snd_ctl_elem_info *uinfo)
247 {
248         static char *texts[2] = { "Line in", "Mic in" };
249
250         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
251         uinfo->count = 1;
252         uinfo->value.enumerated.items = 2;
253         if (uinfo->value.enumerated.item > 1)
254                 uinfo->value.enumerated.item = 1;
255         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
256         return 0;
257 }
258
259 static int snd_ca0106_capture_mic_line_in_get(struct snd_kcontrol *kcontrol,
260                                         struct snd_ctl_elem_value *ucontrol)
261 {
262         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
263
264         ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in;
265         return 0;
266 }
267
268 static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
269                                         struct snd_ctl_elem_value *ucontrol)
270 {
271         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
272         unsigned int val;
273         int change = 0;
274         u32 tmp;
275
276         val = ucontrol->value.enumerated.item[0] ;
277         if (val > 1)
278                 return -EINVAL;
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 -EINVAL;
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 -EINVAL;
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 spi_mute_info   snd_ctl_boolean_mono_info
473
474 static int spi_mute_get(struct snd_kcontrol *kcontrol,
475                         struct snd_ctl_elem_value *ucontrol)
476 {
477         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
478         unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT;
479         unsigned int bit = kcontrol->private_value & SPI_REG_MASK;
480
481         ucontrol->value.integer.value[0] = !(emu->spi_dac_reg[reg] & bit);
482         return 0;
483 }
484
485 static int spi_mute_put(struct snd_kcontrol *kcontrol,
486                         struct snd_ctl_elem_value *ucontrol)
487 {
488         struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
489         unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT;
490         unsigned int bit = kcontrol->private_value & SPI_REG_MASK;
491         int ret;
492
493         ret = emu->spi_dac_reg[reg] & bit;
494         if (ucontrol->value.integer.value[0]) {
495                 if (!ret)       /* bit already cleared, do nothing */
496                         return 0;
497                 emu->spi_dac_reg[reg] &= ~bit;
498         } else {
499                 if (ret)        /* bit already set, do nothing */
500                         return 0;
501                 emu->spi_dac_reg[reg] |= bit;
502         }
503
504         ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]);
505         return ret ? -EINVAL : 1;
506 }
507
508 #define CA_VOLUME(xname,chid,reg) \
509 {                                                               \
510         .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,     \
511         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |             \
512                   SNDRV_CTL_ELEM_ACCESS_TLV_READ,               \
513         .info =  snd_ca0106_volume_info,                        \
514         .get =   snd_ca0106_volume_get,                         \
515         .put =   snd_ca0106_volume_put,                         \
516         .tlv = { .p = snd_ca0106_db_scale1 },                   \
517         .private_value = ((chid) << 8) | (reg)                  \
518 }
519
520 static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
521         CA_VOLUME("Analog Front Playback Volume",
522                   CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2),
523         CA_VOLUME("Analog Rear Playback Volume",
524                   CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2),
525         CA_VOLUME("Analog Center/LFE Playback Volume",
526                   CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2),
527         CA_VOLUME("Analog Side Playback Volume",
528                   CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2),
529
530         CA_VOLUME("IEC958 Front Playback Volume",
531                   CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1),
532         CA_VOLUME("IEC958 Rear Playback Volume",
533                   CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1),
534         CA_VOLUME("IEC958 Center/LFE Playback Volume",
535                   CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1),
536         CA_VOLUME("IEC958 Unknown Playback Volume",
537                   CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1),
538
539         CA_VOLUME("CAPTURE feedback Playback Volume",
540                   1, CAPTURE_CONTROL),
541
542         {
543                 .access =       SNDRV_CTL_ELEM_ACCESS_READ,
544                 .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
545                 .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
546                 .count =        4,
547                 .info =         snd_ca0106_spdif_info,
548                 .get =          snd_ca0106_spdif_get_mask
549         },
550         {
551                 .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
552                 .name =         "IEC958 Playback Switch",
553                 .info =         snd_ca0106_shared_spdif_info,
554                 .get =          snd_ca0106_shared_spdif_get,
555                 .put =          snd_ca0106_shared_spdif_put
556         },
557         {
558                 .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
559                 .name =         "Digital Source Capture Enum",
560                 .info =         snd_ca0106_capture_source_info,
561                 .get =          snd_ca0106_capture_source_get,
562                 .put =          snd_ca0106_capture_source_put
563         },
564         {
565                 .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
566                 .name =         "Analog Source Capture Enum",
567                 .info =         snd_ca0106_i2c_capture_source_info,
568                 .get =          snd_ca0106_i2c_capture_source_get,
569                 .put =          snd_ca0106_i2c_capture_source_put
570         },
571         {
572                 .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
573                 .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
574                 .count =        4,
575                 .info =         snd_ca0106_spdif_info,
576                 .get =          snd_ca0106_spdif_get,
577                 .put =          snd_ca0106_spdif_put
578         },
579 };
580
581 #define I2C_VOLUME(xname,chid) \
582 {                                                               \
583         .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,     \
584         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |             \
585                   SNDRV_CTL_ELEM_ACCESS_TLV_READ,               \
586         .info =  snd_ca0106_i2c_volume_info,                    \
587         .get =   snd_ca0106_i2c_volume_get,                     \
588         .put =   snd_ca0106_i2c_volume_put,                     \
589         .tlv = { .p = snd_ca0106_db_scale2 },                   \
590         .private_value = chid                                   \
591 }
592
593 static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata = {
594         I2C_VOLUME("Phone Capture Volume", 0),
595         I2C_VOLUME("Mic Capture Volume", 1),
596         I2C_VOLUME("Line in Capture Volume", 2),
597         I2C_VOLUME("Aux Capture Volume", 3),
598 };
599
600 #define SPI_SWITCH(xname,reg,bit) \
601 {                                                               \
602         .iface  = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,    \
603         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,              \
604         .info   = spi_mute_info,                                \
605         .get    = spi_mute_get,                                 \
606         .put    = spi_mute_put,                                 \
607         .private_value = (reg<<SPI_REG_SHIFT) | (bit)           \
608 }
609
610 static struct snd_kcontrol_new snd_ca0106_volume_spi_dac_ctls[]
611 __devinitdata = {
612         SPI_SWITCH("Analog Front Playback Switch",
613                    SPI_DMUTE4_REG, SPI_DMUTE4_BIT),
614         SPI_SWITCH("Analog Rear Playback Switch",
615                    SPI_DMUTE0_REG, SPI_DMUTE0_BIT),
616         SPI_SWITCH("Analog Center/LFE Playback Switch",
617                    SPI_DMUTE2_REG, SPI_DMUTE2_BIT),
618         SPI_SWITCH("Analog Side Playback Switch",
619                    SPI_DMUTE1_REG, SPI_DMUTE1_BIT),
620 };
621
622 static int __devinit remove_ctl(struct snd_card *card, const char *name)
623 {
624         struct snd_ctl_elem_id id;
625         memset(&id, 0, sizeof(id));
626         strcpy(id.name, name);
627         id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
628         return snd_ctl_remove_id(card, &id);
629 }
630
631 static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, const char *name)
632 {
633         struct snd_ctl_elem_id sid;
634         memset(&sid, 0, sizeof(sid));
635         /* FIXME: strcpy is bad. */
636         strcpy(sid.name, name);
637         sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
638         return snd_ctl_find_id(card, &sid);
639 }
640
641 static int __devinit rename_ctl(struct snd_card *card, const char *src, const char *dst)
642 {
643         struct snd_kcontrol *kctl = ctl_find(card, src);
644         if (kctl) {
645                 strcpy(kctl->id.name, dst);
646                 return 0;
647         }
648         return -ENOENT;
649 }
650
651 #define ADD_CTLS(emu, ctls)                                             \
652         do {                                                            \
653                 int i, err;                                             \
654                 for (i = 0; i < ARRAY_SIZE(ctls); i++) {                \
655                         err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \
656                         if (err < 0)                                    \
657                                 return err;                             \
658                 }                                                       \
659         } while (0)
660
661 int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
662 {
663         int err;
664         struct snd_card *card = emu->card;
665         char **c;
666         static char *ca0106_remove_ctls[] = {
667                 "Master Mono Playback Switch",
668                 "Master Mono Playback Volume",
669                 "3D Control - Switch",
670                 "3D Control Sigmatel - Depth",
671                 "PCM Playback Switch",
672                 "PCM Playback Volume",
673                 "CD Playback Switch",
674                 "CD Playback Volume",
675                 "Phone Playback Switch",
676                 "Phone Playback Volume",
677                 "Video Playback Switch",
678                 "Video Playback Volume",
679                 "PC Speaker Playback Switch",
680                 "PC Speaker Playback Volume",
681                 "Mono Output Select",
682                 "Capture Source",
683                 "Capture Switch",
684                 "Capture Volume",
685                 "External Amplifier",
686                 "Sigmatel 4-Speaker Stereo Playback Switch",
687                 "Sigmatel Surround Phase Inversion Playback ",
688                 NULL
689         };
690         static char *ca0106_rename_ctls[] = {
691                 "Master Playback Switch", "Capture Switch",
692                 "Master Playback Volume", "Capture Volume",
693                 "Line Playback Switch", "AC97 Line Capture Switch",
694                 "Line Playback Volume", "AC97 Line Capture Volume",
695                 "Aux Playback Switch", "AC97 Aux Capture Switch",
696                 "Aux Playback Volume", "AC97 Aux Capture Volume",
697                 "Mic Playback Switch", "AC97 Mic Capture Switch",
698                 "Mic Playback Volume", "AC97 Mic Capture Volume",
699                 "Mic Select", "AC97 Mic Select",
700                 "Mic Boost (+20dB)", "AC97 Mic Boost (+20dB)",
701                 NULL
702         };
703 #if 1
704         for (c = ca0106_remove_ctls; *c; c++)
705                 remove_ctl(card, *c);
706         for (c = ca0106_rename_ctls; *c; c += 2)
707                 rename_ctl(card, c[0], c[1]);
708 #endif
709
710         ADD_CTLS(emu, snd_ca0106_volume_ctls);
711         if (emu->details->i2c_adc == 1) {
712                 ADD_CTLS(emu, snd_ca0106_volume_i2c_adc_ctls);
713                 if (emu->details->gpio_type == 1)
714                         err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu));
715                 else  /* gpio_type == 2 */
716                         err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_line_in_side_out, emu));
717                 if (err < 0)
718                         return err;
719         }
720         if (emu->details->spi_dac == 1)
721                 ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls);
722         return 0;
723 }
724