RT-AC56 3.0.0.4.374.37 core
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / sound / pci / ca0106 / ca0106_mixer.c
blobdc6b821003cc7b0d1dd9eeb4ef638050055f686f
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
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)
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>
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.
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.
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
63 #include <linux/delay.h>
64 #include <linux/init.h>
65 #include <linux/interrupt.h>
66 #include <linux/moduleparam.h>
67 #include <sound/core.h>
68 #include <sound/initval.h>
69 #include <sound/pcm.h>
70 #include <sound/ac97_codec.h>
71 #include <sound/info.h>
72 #include <sound/tlv.h>
73 #include <asm/io.h>
75 #include "ca0106.h"
77 static void ca0106_spdif_enable(struct snd_ca0106 *emu)
79 unsigned int val;
81 if (emu->spdif_enable) {
82 /* Digital */
83 snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
84 snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000);
85 val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000;
86 snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val);
87 val = inl(emu->port + GPIO) & ~0x101;
88 outl(val, emu->port + GPIO);
90 } else {
91 /* Analog */
92 snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
93 snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000);
94 val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000;
95 snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val);
96 val = inl(emu->port + GPIO) | 0x101;
97 outl(val, emu->port + GPIO);
101 static void ca0106_set_capture_source(struct snd_ca0106 *emu)
103 unsigned int val = emu->capture_source;
104 unsigned int source, mask;
105 source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
106 mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff;
107 snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask);
110 static void ca0106_set_i2c_capture_source(struct snd_ca0106 *emu,
111 unsigned int val, int force)
113 unsigned int ngain, ogain;
114 u32 source;
116 snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
117 ngain = emu->i2c_capture_volume[val][0]; /* Left */
118 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
119 if (force || ngain != ogain)
120 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ngain & 0xff);
121 ngain = emu->i2c_capture_volume[val][1]; /* Right */
122 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
123 if (force || ngain != ogain)
124 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ngain & 0xff);
125 source = 1 << val;
126 snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */
127 emu->i2c_capture_source = val;
130 static void ca0106_set_capture_mic_line_in(struct snd_ca0106 *emu)
132 u32 tmp;
134 if (emu->capture_mic_line_in) {
135 /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */
136 tmp = inl(emu->port+GPIO) & ~0x400;
137 tmp = tmp | 0x400;
138 outl(tmp, emu->port+GPIO);
139 /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); */
140 } else {
141 /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */
142 tmp = inl(emu->port+GPIO) & ~0x400;
143 outl(tmp, emu->port+GPIO);
144 /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); */
148 static void ca0106_set_spdif_bits(struct snd_ca0106 *emu, int idx)
150 snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_str_bits[idx]);
155 static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1);
156 static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1);
158 #define snd_ca0106_shared_spdif_info snd_ctl_boolean_mono_info
160 static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol,
161 struct snd_ctl_elem_value *ucontrol)
163 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
165 ucontrol->value.integer.value[0] = emu->spdif_enable;
166 return 0;
169 static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol,
170 struct snd_ctl_elem_value *ucontrol)
172 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
173 unsigned int val;
174 int change = 0;
176 val = !!ucontrol->value.integer.value[0];
177 change = (emu->spdif_enable != val);
178 if (change) {
179 emu->spdif_enable = val;
180 ca0106_spdif_enable(emu);
182 return change;
185 static int snd_ca0106_capture_source_info(struct snd_kcontrol *kcontrol,
186 struct snd_ctl_elem_info *uinfo)
188 static char *texts[6] = {
189 "IEC958 out", "i2s mixer out", "IEC958 in", "i2s in", "AC97 in", "SRC out"
192 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
193 uinfo->count = 1;
194 uinfo->value.enumerated.items = 6;
195 if (uinfo->value.enumerated.item > 5)
196 uinfo->value.enumerated.item = 5;
197 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
198 return 0;
201 static int snd_ca0106_capture_source_get(struct snd_kcontrol *kcontrol,
202 struct snd_ctl_elem_value *ucontrol)
204 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
206 ucontrol->value.enumerated.item[0] = emu->capture_source;
207 return 0;
210 static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
211 struct snd_ctl_elem_value *ucontrol)
213 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
214 unsigned int val;
215 int change = 0;
217 val = ucontrol->value.enumerated.item[0] ;
218 if (val >= 6)
219 return -EINVAL;
220 change = (emu->capture_source != val);
221 if (change) {
222 emu->capture_source = val;
223 ca0106_set_capture_source(emu);
225 return change;
228 static int snd_ca0106_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
229 struct snd_ctl_elem_info *uinfo)
231 static char *texts[6] = {
232 "Phone", "Mic", "Line in", "Aux"
235 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
236 uinfo->count = 1;
237 uinfo->value.enumerated.items = 4;
238 if (uinfo->value.enumerated.item > 3)
239 uinfo->value.enumerated.item = 3;
240 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
241 return 0;
244 static int snd_ca0106_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
245 struct snd_ctl_elem_value *ucontrol)
247 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
249 ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
250 return 0;
253 static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
254 struct snd_ctl_elem_value *ucontrol)
256 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
257 unsigned int source_id;
258 int change = 0;
259 /* If the capture source has changed,
260 * update the capture volume from the cached value
261 * for the particular source.
263 source_id = ucontrol->value.enumerated.item[0] ;
264 if (source_id >= 4)
265 return -EINVAL;
266 change = (emu->i2c_capture_source != source_id);
267 if (change) {
268 ca0106_set_i2c_capture_source(emu, source_id, 0);
270 return change;
273 static int snd_ca0106_capture_line_in_side_out_info(struct snd_kcontrol *kcontrol,
274 struct snd_ctl_elem_info *uinfo)
276 static char *texts[2] = { "Side out", "Line in" };
278 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
279 uinfo->count = 1;
280 uinfo->value.enumerated.items = 2;
281 if (uinfo->value.enumerated.item > 1)
282 uinfo->value.enumerated.item = 1;
283 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
284 return 0;
287 static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol,
288 struct snd_ctl_elem_info *uinfo)
290 static char *texts[2] = { "Line in", "Mic in" };
292 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
293 uinfo->count = 1;
294 uinfo->value.enumerated.items = 2;
295 if (uinfo->value.enumerated.item > 1)
296 uinfo->value.enumerated.item = 1;
297 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
298 return 0;
301 static int snd_ca0106_capture_mic_line_in_get(struct snd_kcontrol *kcontrol,
302 struct snd_ctl_elem_value *ucontrol)
304 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
306 ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in;
307 return 0;
310 static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
311 struct snd_ctl_elem_value *ucontrol)
313 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
314 unsigned int val;
315 int change = 0;
317 val = ucontrol->value.enumerated.item[0] ;
318 if (val > 1)
319 return -EINVAL;
320 change = (emu->capture_mic_line_in != val);
321 if (change) {
322 emu->capture_mic_line_in = val;
323 ca0106_set_capture_mic_line_in(emu);
325 return change;
328 static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata =
330 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
331 .name = "Shared Mic/Line in Capture Switch",
332 .info = snd_ca0106_capture_mic_line_in_info,
333 .get = snd_ca0106_capture_mic_line_in_get,
334 .put = snd_ca0106_capture_mic_line_in_put
337 static struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out __devinitdata =
339 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
340 .name = "Shared Line in/Side out Capture Switch",
341 .info = snd_ca0106_capture_line_in_side_out_info,
342 .get = snd_ca0106_capture_mic_line_in_get,
343 .put = snd_ca0106_capture_mic_line_in_put
347 static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol,
348 struct snd_ctl_elem_info *uinfo)
350 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
351 uinfo->count = 1;
352 return 0;
355 static void decode_spdif_bits(unsigned char *status, unsigned int bits)
357 status[0] = (bits >> 0) & 0xff;
358 status[1] = (bits >> 8) & 0xff;
359 status[2] = (bits >> 16) & 0xff;
360 status[3] = (bits >> 24) & 0xff;
363 static int snd_ca0106_spdif_get_default(struct snd_kcontrol *kcontrol,
364 struct snd_ctl_elem_value *ucontrol)
366 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
367 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
369 decode_spdif_bits(ucontrol->value.iec958.status,
370 emu->spdif_bits[idx]);
371 return 0;
374 static int snd_ca0106_spdif_get_stream(struct snd_kcontrol *kcontrol,
375 struct snd_ctl_elem_value *ucontrol)
377 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
378 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
380 decode_spdif_bits(ucontrol->value.iec958.status,
381 emu->spdif_str_bits[idx]);
382 return 0;
385 static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol,
386 struct snd_ctl_elem_value *ucontrol)
388 ucontrol->value.iec958.status[0] = 0xff;
389 ucontrol->value.iec958.status[1] = 0xff;
390 ucontrol->value.iec958.status[2] = 0xff;
391 ucontrol->value.iec958.status[3] = 0xff;
392 return 0;
395 static unsigned int encode_spdif_bits(unsigned char *status)
397 return ((unsigned int)status[0] << 0) |
398 ((unsigned int)status[1] << 8) |
399 ((unsigned int)status[2] << 16) |
400 ((unsigned int)status[3] << 24);
403 static int snd_ca0106_spdif_put_default(struct snd_kcontrol *kcontrol,
404 struct snd_ctl_elem_value *ucontrol)
406 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
407 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
408 unsigned int val;
410 val = encode_spdif_bits(ucontrol->value.iec958.status);
411 if (val != emu->spdif_bits[idx]) {
412 emu->spdif_bits[idx] = val;
413 emu->spdif_str_bits[idx] = val;
414 ca0106_set_spdif_bits(emu, idx);
415 return 1;
417 return 0;
420 static int snd_ca0106_spdif_put_stream(struct snd_kcontrol *kcontrol,
421 struct snd_ctl_elem_value *ucontrol)
423 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
424 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
425 unsigned int val;
427 val = encode_spdif_bits(ucontrol->value.iec958.status);
428 if (val != emu->spdif_str_bits[idx]) {
429 emu->spdif_str_bits[idx] = val;
430 ca0106_set_spdif_bits(emu, idx);
431 return 1;
433 return 0;
436 static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol,
437 struct snd_ctl_elem_info *uinfo)
439 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
440 uinfo->count = 2;
441 uinfo->value.integer.min = 0;
442 uinfo->value.integer.max = 255;
443 return 0;
446 static int snd_ca0106_volume_get(struct snd_kcontrol *kcontrol,
447 struct snd_ctl_elem_value *ucontrol)
449 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
450 unsigned int value;
451 int channel_id, reg;
453 channel_id = (kcontrol->private_value >> 8) & 0xff;
454 reg = kcontrol->private_value & 0xff;
456 value = snd_ca0106_ptr_read(emu, reg, channel_id);
457 ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */
458 ucontrol->value.integer.value[1] = 0xff - ((value >> 16) & 0xff); /* Right */
459 return 0;
462 static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol,
463 struct snd_ctl_elem_value *ucontrol)
465 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
466 unsigned int oval, nval;
467 int channel_id, reg;
469 channel_id = (kcontrol->private_value >> 8) & 0xff;
470 reg = kcontrol->private_value & 0xff;
472 oval = snd_ca0106_ptr_read(emu, reg, channel_id);
473 nval = ((0xff - ucontrol->value.integer.value[0]) << 24) |
474 ((0xff - ucontrol->value.integer.value[1]) << 16);
475 nval |= ((0xff - ucontrol->value.integer.value[0]) << 8) |
476 ((0xff - ucontrol->value.integer.value[1]) );
477 if (oval == nval)
478 return 0;
479 snd_ca0106_ptr_write(emu, reg, channel_id, nval);
480 return 1;
483 static int snd_ca0106_i2c_volume_info(struct snd_kcontrol *kcontrol,
484 struct snd_ctl_elem_info *uinfo)
486 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
487 uinfo->count = 2;
488 uinfo->value.integer.min = 0;
489 uinfo->value.integer.max = 255;
490 return 0;
493 static int snd_ca0106_i2c_volume_get(struct snd_kcontrol *kcontrol,
494 struct snd_ctl_elem_value *ucontrol)
496 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
497 int source_id;
499 source_id = kcontrol->private_value;
501 ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
502 ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
503 return 0;
506 static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol,
507 struct snd_ctl_elem_value *ucontrol)
509 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
510 unsigned int ogain;
511 unsigned int ngain;
512 int source_id;
513 int change = 0;
515 source_id = kcontrol->private_value;
516 ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
517 ngain = ucontrol->value.integer.value[0];
518 if (ngain > 0xff)
519 return -EINVAL;
520 if (ogain != ngain) {
521 if (emu->i2c_capture_source == source_id)
522 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
523 emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0];
524 change = 1;
526 ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
527 ngain = ucontrol->value.integer.value[1];
528 if (ngain > 0xff)
529 return -EINVAL;
530 if (ogain != ngain) {
531 if (emu->i2c_capture_source == source_id)
532 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
533 emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1];
534 change = 1;
537 return change;
540 #define spi_mute_info snd_ctl_boolean_mono_info
542 static int spi_mute_get(struct snd_kcontrol *kcontrol,
543 struct snd_ctl_elem_value *ucontrol)
545 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
546 unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT;
547 unsigned int bit = kcontrol->private_value & SPI_REG_MASK;
549 ucontrol->value.integer.value[0] = !(emu->spi_dac_reg[reg] & bit);
550 return 0;
553 static int spi_mute_put(struct snd_kcontrol *kcontrol,
554 struct snd_ctl_elem_value *ucontrol)
556 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
557 unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT;
558 unsigned int bit = kcontrol->private_value & SPI_REG_MASK;
559 int ret;
561 ret = emu->spi_dac_reg[reg] & bit;
562 if (ucontrol->value.integer.value[0]) {
563 if (!ret) /* bit already cleared, do nothing */
564 return 0;
565 emu->spi_dac_reg[reg] &= ~bit;
566 } else {
567 if (ret) /* bit already set, do nothing */
568 return 0;
569 emu->spi_dac_reg[reg] |= bit;
572 ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]);
573 return ret ? -EINVAL : 1;
576 #define CA_VOLUME(xname,chid,reg) \
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_volume_info, \
582 .get = snd_ca0106_volume_get, \
583 .put = snd_ca0106_volume_put, \
584 .tlv = { .p = snd_ca0106_db_scale1 }, \
585 .private_value = ((chid) << 8) | (reg) \
588 static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
589 CA_VOLUME("Analog Front Playback Volume",
590 CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2),
591 CA_VOLUME("Analog Rear Playback Volume",
592 CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2),
593 CA_VOLUME("Analog Center/LFE Playback Volume",
594 CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2),
595 CA_VOLUME("Analog Side Playback Volume",
596 CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2),
598 CA_VOLUME("IEC958 Front Playback Volume",
599 CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1),
600 CA_VOLUME("IEC958 Rear Playback Volume",
601 CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1),
602 CA_VOLUME("IEC958 Center/LFE Playback Volume",
603 CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1),
604 CA_VOLUME("IEC958 Unknown Playback Volume",
605 CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1),
607 CA_VOLUME("CAPTURE feedback Playback Volume",
608 1, CAPTURE_CONTROL),
611 .access = SNDRV_CTL_ELEM_ACCESS_READ,
612 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
613 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
614 .count = 4,
615 .info = snd_ca0106_spdif_info,
616 .get = snd_ca0106_spdif_get_mask
619 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
620 .name = "IEC958 Playback Switch",
621 .info = snd_ca0106_shared_spdif_info,
622 .get = snd_ca0106_shared_spdif_get,
623 .put = snd_ca0106_shared_spdif_put
626 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
627 .name = "Digital Source Capture Enum",
628 .info = snd_ca0106_capture_source_info,
629 .get = snd_ca0106_capture_source_get,
630 .put = snd_ca0106_capture_source_put
633 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
634 .name = "Analog Source Capture Enum",
635 .info = snd_ca0106_i2c_capture_source_info,
636 .get = snd_ca0106_i2c_capture_source_get,
637 .put = snd_ca0106_i2c_capture_source_put
640 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
641 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
642 .count = 4,
643 .info = snd_ca0106_spdif_info,
644 .get = snd_ca0106_spdif_get_default,
645 .put = snd_ca0106_spdif_put_default
648 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
649 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
650 .count = 4,
651 .info = snd_ca0106_spdif_info,
652 .get = snd_ca0106_spdif_get_stream,
653 .put = snd_ca0106_spdif_put_stream
657 #define I2C_VOLUME(xname,chid) \
659 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
660 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
661 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
662 .info = snd_ca0106_i2c_volume_info, \
663 .get = snd_ca0106_i2c_volume_get, \
664 .put = snd_ca0106_i2c_volume_put, \
665 .tlv = { .p = snd_ca0106_db_scale2 }, \
666 .private_value = chid \
669 static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata = {
670 I2C_VOLUME("Phone Capture Volume", 0),
671 I2C_VOLUME("Mic Capture Volume", 1),
672 I2C_VOLUME("Line in Capture Volume", 2),
673 I2C_VOLUME("Aux Capture Volume", 3),
676 #define SPI_SWITCH(xname,reg,bit) \
678 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
679 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
680 .info = spi_mute_info, \
681 .get = spi_mute_get, \
682 .put = spi_mute_put, \
683 .private_value = (reg<<SPI_REG_SHIFT) | (bit) \
686 static struct snd_kcontrol_new snd_ca0106_volume_spi_dac_ctls[]
687 __devinitdata = {
688 SPI_SWITCH("Analog Front Playback Switch",
689 SPI_DMUTE4_REG, SPI_DMUTE4_BIT),
690 SPI_SWITCH("Analog Rear Playback Switch",
691 SPI_DMUTE0_REG, SPI_DMUTE0_BIT),
692 SPI_SWITCH("Analog Center/LFE Playback Switch",
693 SPI_DMUTE2_REG, SPI_DMUTE2_BIT),
694 SPI_SWITCH("Analog Side Playback Switch",
695 SPI_DMUTE1_REG, SPI_DMUTE1_BIT),
698 static int __devinit remove_ctl(struct snd_card *card, const char *name)
700 struct snd_ctl_elem_id id;
701 memset(&id, 0, sizeof(id));
702 strcpy(id.name, name);
703 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
704 return snd_ctl_remove_id(card, &id);
707 static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, const char *name)
709 struct snd_ctl_elem_id sid;
710 memset(&sid, 0, sizeof(sid));
711 strcpy(sid.name, name);
712 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
713 return snd_ctl_find_id(card, &sid);
716 static int __devinit rename_ctl(struct snd_card *card, const char *src, const char *dst)
718 struct snd_kcontrol *kctl = ctl_find(card, src);
719 if (kctl) {
720 strcpy(kctl->id.name, dst);
721 return 0;
723 return -ENOENT;
726 #define ADD_CTLS(emu, ctls) \
727 do { \
728 int i, _err; \
729 for (i = 0; i < ARRAY_SIZE(ctls); i++) { \
730 _err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \
731 if (_err < 0) \
732 return _err; \
734 } while (0)
736 static __devinitdata
737 DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 25, 1);
739 static char *slave_vols[] __devinitdata = {
740 "Analog Front Playback Volume",
741 "Analog Rear Playback Volume",
742 "Analog Center/LFE Playback Volume",
743 "Analog Side Playback Volume",
744 "IEC958 Front Playback Volume",
745 "IEC958 Rear Playback Volume",
746 "IEC958 Center/LFE Playback Volume",
747 "IEC958 Unknown Playback Volume",
748 "CAPTURE feedback Playback Volume",
749 NULL
752 static char *slave_sws[] __devinitdata = {
753 "Analog Front Playback Switch",
754 "Analog Rear Playback Switch",
755 "Analog Center/LFE Playback Switch",
756 "Analog Side Playback Switch",
757 "IEC958 Playback Switch",
758 NULL
761 static void __devinit add_slaves(struct snd_card *card,
762 struct snd_kcontrol *master, char **list)
764 for (; *list; list++) {
765 struct snd_kcontrol *slave = ctl_find(card, *list);
766 if (slave)
767 snd_ctl_add_slave(master, slave);
771 int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
773 int err;
774 struct snd_card *card = emu->card;
775 char **c;
776 struct snd_kcontrol *vmaster;
777 static char *ca0106_remove_ctls[] = {
778 "Master Mono Playback Switch",
779 "Master Mono Playback Volume",
780 "3D Control - Switch",
781 "3D Control Sigmatel - Depth",
782 "PCM Playback Switch",
783 "PCM Playback Volume",
784 "CD Playback Switch",
785 "CD Playback Volume",
786 "Phone Playback Switch",
787 "Phone Playback Volume",
788 "Video Playback Switch",
789 "Video Playback Volume",
790 "Beep Playback Switch",
791 "Beep Playback Volume",
792 "Mono Output Select",
793 "Capture Source",
794 "Capture Switch",
795 "Capture Volume",
796 "External Amplifier",
797 "Sigmatel 4-Speaker Stereo Playback Switch",
798 "Surround Phase Inversion Playback Switch",
799 NULL
801 static char *ca0106_rename_ctls[] = {
802 "Master Playback Switch", "Capture Switch",
803 "Master Playback Volume", "Capture Volume",
804 "Line Playback Switch", "AC97 Line Capture Switch",
805 "Line Playback Volume", "AC97 Line Capture Volume",
806 "Aux Playback Switch", "AC97 Aux Capture Switch",
807 "Aux Playback Volume", "AC97 Aux Capture Volume",
808 "Mic Playback Switch", "AC97 Mic Capture Switch",
809 "Mic Playback Volume", "AC97 Mic Capture Volume",
810 "Mic Select", "AC97 Mic Select",
811 "Mic Boost (+20dB)", "AC97 Mic Boost (+20dB)",
812 NULL
814 for (c = ca0106_remove_ctls; *c; c++)
815 remove_ctl(card, *c);
816 for (c = ca0106_rename_ctls; *c; c += 2)
817 rename_ctl(card, c[0], c[1]);
819 ADD_CTLS(emu, snd_ca0106_volume_ctls);
820 if (emu->details->i2c_adc == 1) {
821 ADD_CTLS(emu, snd_ca0106_volume_i2c_adc_ctls);
822 if (emu->details->gpio_type == 1)
823 err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu));
824 else /* gpio_type == 2 */
825 err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_line_in_side_out, emu));
826 if (err < 0)
827 return err;
829 if (emu->details->spi_dac == 1)
830 ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls);
832 /* Create virtual master controls */
833 vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
834 snd_ca0106_master_db_scale);
835 if (!vmaster)
836 return -ENOMEM;
837 err = snd_ctl_add(card, vmaster);
838 if (err < 0)
839 return err;
840 add_slaves(card, vmaster, slave_vols);
842 if (emu->details->spi_dac == 1) {
843 vmaster = snd_ctl_make_virtual_master("Master Playback Switch",
844 NULL);
845 if (!vmaster)
846 return -ENOMEM;
847 err = snd_ctl_add(card, vmaster);
848 if (err < 0)
849 return err;
850 add_slaves(card, vmaster, slave_sws);
853 strcpy(card->mixername, "CA0106");
854 return 0;
857 #ifdef CONFIG_PM
858 struct ca0106_vol_tbl {
859 unsigned int channel_id;
860 unsigned int reg;
863 static struct ca0106_vol_tbl saved_volumes[NUM_SAVED_VOLUMES] = {
864 { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2 },
865 { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2 },
866 { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2 },
867 { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2 },
868 { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1 },
869 { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1 },
870 { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1 },
871 { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1 },
872 { 1, CAPTURE_CONTROL },
875 void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip)
877 int i;
879 /* save volumes */
880 for (i = 0; i < NUM_SAVED_VOLUMES; i++)
881 chip->saved_vol[i] =
882 snd_ca0106_ptr_read(chip, saved_volumes[i].reg,
883 saved_volumes[i].channel_id);
886 void snd_ca0106_mixer_resume(struct snd_ca0106 *chip)
888 int i;
890 for (i = 0; i < NUM_SAVED_VOLUMES; i++)
891 snd_ca0106_ptr_write(chip, saved_volumes[i].reg,
892 saved_volumes[i].channel_id,
893 chip->saved_vol[i]);
895 ca0106_spdif_enable(chip);
896 ca0106_set_capture_source(chip);
897 ca0106_set_i2c_capture_source(chip, chip->i2c_capture_source, 1);
898 for (i = 0; i < 4; i++)
899 ca0106_set_spdif_bits(chip, i);
900 if (chip->details->i2c_adc)
901 ca0106_set_capture_mic_line_in(chip);
903 #endif /* CONFIG_PM */