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