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
6 * FEATURES currently supported:
7 * See ca0106_main.c for features.
10 * Support interrupts per period.
11 * Removed noise from Center/LFE channel when in Analog mode.
12 * Rename and remove mixer controls.
14 * Use separate card based DMA buffer for periods table list.
16 * Change remove and rename ctrls into lists.
18 * Try to fix capture sources.
21 * Enable S32_LE format support.
23 * Enable playback 48000 and 96000 rates. (Rates other that these do not work, even with "plug:front".)
25 * Add Model name recognition.
27 * Correct interrupt timing. interrupt at end of period, instead of in the middle of a playback period.
28 * Remove redundent "voice" handling.
30 * Single trigger call for multi channels.
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.
37 * Separated ca0106.c into separate functional .c files.
39 * Modified Copyright message.
41 * Implement Mic and Line in Capture.
43 * Add support for mute control on SB Live 24bit (cards w/ SPI DAC)
45 * This code was initially 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>
77 static void ca0106_spdif_enable(struct snd_ca0106
*emu
)
81 if (emu
->spdif_enable
) {
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
);
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
;
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);
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
)
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;
138 outl(tmp
, emu
->port
+GPIO
);
139 /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); */
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
;
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
);
176 val
= !!ucontrol
->value
.integer
.value
[0];
177 change
= (emu
->spdif_enable
!= val
);
179 emu
->spdif_enable
= val
;
180 ca0106_spdif_enable(emu
);
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
;
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
]);
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
;
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
);
217 val
= ucontrol
->value
.enumerated
.item
[0] ;
220 change
= (emu
->capture_source
!= val
);
222 emu
->capture_source
= val
;
223 ca0106_set_capture_source(emu
);
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
;
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
]);
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
;
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
;
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] ;
266 change
= (emu
->i2c_capture_source
!= source_id
);
268 ca0106_set_i2c_capture_source(emu
, source_id
, 0);
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
;
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
]);
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
;
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
]);
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
;
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
);
317 val
= ucontrol
->value
.enumerated
.item
[0] ;
320 change
= (emu
->capture_mic_line_in
!= val
);
322 emu
->capture_mic_line_in
= val
;
323 ca0106_set_capture_mic_line_in(emu
);
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
;
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
]);
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
]);
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;
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
);
410 val
= encode_spdif_bits(ucontrol
->value
.iec958
.status
);
411 if (val
!= emu
->spdif_bits
[idx
]) {
412 emu
->spdif_bits
[idx
] = val
;
413 /* FIXME: this isn't safe, but needed to keep the compatibility
414 * with older alsa-lib config
416 emu
->spdif_str_bits
[idx
] = val
;
417 ca0106_set_spdif_bits(emu
, idx
);
423 static int snd_ca0106_spdif_put_stream(struct snd_kcontrol
*kcontrol
,
424 struct snd_ctl_elem_value
*ucontrol
)
426 struct snd_ca0106
*emu
= snd_kcontrol_chip(kcontrol
);
427 unsigned int idx
= snd_ctl_get_ioffidx(kcontrol
, &ucontrol
->id
);
430 val
= encode_spdif_bits(ucontrol
->value
.iec958
.status
);
431 if (val
!= emu
->spdif_str_bits
[idx
]) {
432 emu
->spdif_str_bits
[idx
] = val
;
433 ca0106_set_spdif_bits(emu
, idx
);
439 static int snd_ca0106_volume_info(struct snd_kcontrol
*kcontrol
,
440 struct snd_ctl_elem_info
*uinfo
)
442 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
444 uinfo
->value
.integer
.min
= 0;
445 uinfo
->value
.integer
.max
= 255;
449 static int snd_ca0106_volume_get(struct snd_kcontrol
*kcontrol
,
450 struct snd_ctl_elem_value
*ucontrol
)
452 struct snd_ca0106
*emu
= snd_kcontrol_chip(kcontrol
);
456 channel_id
= (kcontrol
->private_value
>> 8) & 0xff;
457 reg
= kcontrol
->private_value
& 0xff;
459 value
= snd_ca0106_ptr_read(emu
, reg
, channel_id
);
460 ucontrol
->value
.integer
.value
[0] = 0xff - ((value
>> 24) & 0xff); /* Left */
461 ucontrol
->value
.integer
.value
[1] = 0xff - ((value
>> 16) & 0xff); /* Right */
465 static int snd_ca0106_volume_put(struct snd_kcontrol
*kcontrol
,
466 struct snd_ctl_elem_value
*ucontrol
)
468 struct snd_ca0106
*emu
= snd_kcontrol_chip(kcontrol
);
469 unsigned int oval
, nval
;
472 channel_id
= (kcontrol
->private_value
>> 8) & 0xff;
473 reg
= kcontrol
->private_value
& 0xff;
475 oval
= snd_ca0106_ptr_read(emu
, reg
, channel_id
);
476 nval
= ((0xff - ucontrol
->value
.integer
.value
[0]) << 24) |
477 ((0xff - ucontrol
->value
.integer
.value
[1]) << 16);
478 nval
|= ((0xff - ucontrol
->value
.integer
.value
[0]) << 8) |
479 ((0xff - ucontrol
->value
.integer
.value
[1]) );
482 snd_ca0106_ptr_write(emu
, reg
, channel_id
, nval
);
486 static int snd_ca0106_i2c_volume_info(struct snd_kcontrol
*kcontrol
,
487 struct snd_ctl_elem_info
*uinfo
)
489 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
491 uinfo
->value
.integer
.min
= 0;
492 uinfo
->value
.integer
.max
= 255;
496 static int snd_ca0106_i2c_volume_get(struct snd_kcontrol
*kcontrol
,
497 struct snd_ctl_elem_value
*ucontrol
)
499 struct snd_ca0106
*emu
= snd_kcontrol_chip(kcontrol
);
502 source_id
= kcontrol
->private_value
;
504 ucontrol
->value
.integer
.value
[0] = emu
->i2c_capture_volume
[source_id
][0];
505 ucontrol
->value
.integer
.value
[1] = emu
->i2c_capture_volume
[source_id
][1];
509 static int snd_ca0106_i2c_volume_put(struct snd_kcontrol
*kcontrol
,
510 struct snd_ctl_elem_value
*ucontrol
)
512 struct snd_ca0106
*emu
= snd_kcontrol_chip(kcontrol
);
518 source_id
= kcontrol
->private_value
;
519 ogain
= emu
->i2c_capture_volume
[source_id
][0]; /* Left */
520 ngain
= ucontrol
->value
.integer
.value
[0];
523 if (ogain
!= ngain
) {
524 if (emu
->i2c_capture_source
== source_id
)
525 snd_ca0106_i2c_write(emu
, ADC_ATTEN_ADCL
, ((ngain
) & 0xff) );
526 emu
->i2c_capture_volume
[source_id
][0] = ucontrol
->value
.integer
.value
[0];
529 ogain
= emu
->i2c_capture_volume
[source_id
][1]; /* Right */
530 ngain
= ucontrol
->value
.integer
.value
[1];
533 if (ogain
!= ngain
) {
534 if (emu
->i2c_capture_source
== source_id
)
535 snd_ca0106_i2c_write(emu
, ADC_ATTEN_ADCR
, ((ngain
) & 0xff));
536 emu
->i2c_capture_volume
[source_id
][1] = ucontrol
->value
.integer
.value
[1];
543 #define spi_mute_info snd_ctl_boolean_mono_info
545 static int spi_mute_get(struct snd_kcontrol
*kcontrol
,
546 struct snd_ctl_elem_value
*ucontrol
)
548 struct snd_ca0106
*emu
= snd_kcontrol_chip(kcontrol
);
549 unsigned int reg
= kcontrol
->private_value
>> SPI_REG_SHIFT
;
550 unsigned int bit
= kcontrol
->private_value
& SPI_REG_MASK
;
552 ucontrol
->value
.integer
.value
[0] = !(emu
->spi_dac_reg
[reg
] & bit
);
556 static int spi_mute_put(struct snd_kcontrol
*kcontrol
,
557 struct snd_ctl_elem_value
*ucontrol
)
559 struct snd_ca0106
*emu
= snd_kcontrol_chip(kcontrol
);
560 unsigned int reg
= kcontrol
->private_value
>> SPI_REG_SHIFT
;
561 unsigned int bit
= kcontrol
->private_value
& SPI_REG_MASK
;
564 ret
= emu
->spi_dac_reg
[reg
] & bit
;
565 if (ucontrol
->value
.integer
.value
[0]) {
566 if (!ret
) /* bit already cleared, do nothing */
568 emu
->spi_dac_reg
[reg
] &= ~bit
;
570 if (ret
) /* bit already set, do nothing */
572 emu
->spi_dac_reg
[reg
] |= bit
;
575 ret
= snd_ca0106_spi_write(emu
, emu
->spi_dac_reg
[reg
]);
576 return ret
? -EINVAL
: 1;
579 #define CA_VOLUME(xname,chid,reg) \
581 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
582 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
583 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
584 .info = snd_ca0106_volume_info, \
585 .get = snd_ca0106_volume_get, \
586 .put = snd_ca0106_volume_put, \
587 .tlv = { .p = snd_ca0106_db_scale1 }, \
588 .private_value = ((chid) << 8) | (reg) \
591 static struct snd_kcontrol_new snd_ca0106_volume_ctls
[] __devinitdata
= {
592 CA_VOLUME("Analog Front Playback Volume",
593 CONTROL_FRONT_CHANNEL
, PLAYBACK_VOLUME2
),
594 CA_VOLUME("Analog Rear Playback Volume",
595 CONTROL_REAR_CHANNEL
, PLAYBACK_VOLUME2
),
596 CA_VOLUME("Analog Center/LFE Playback Volume",
597 CONTROL_CENTER_LFE_CHANNEL
, PLAYBACK_VOLUME2
),
598 CA_VOLUME("Analog Side Playback Volume",
599 CONTROL_UNKNOWN_CHANNEL
, PLAYBACK_VOLUME2
),
601 CA_VOLUME("IEC958 Front Playback Volume",
602 CONTROL_FRONT_CHANNEL
, PLAYBACK_VOLUME1
),
603 CA_VOLUME("IEC958 Rear Playback Volume",
604 CONTROL_REAR_CHANNEL
, PLAYBACK_VOLUME1
),
605 CA_VOLUME("IEC958 Center/LFE Playback Volume",
606 CONTROL_CENTER_LFE_CHANNEL
, PLAYBACK_VOLUME1
),
607 CA_VOLUME("IEC958 Unknown Playback Volume",
608 CONTROL_UNKNOWN_CHANNEL
, PLAYBACK_VOLUME1
),
610 CA_VOLUME("CAPTURE feedback Playback Volume",
614 .access
= SNDRV_CTL_ELEM_ACCESS_READ
,
615 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
616 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,MASK
),
618 .info
= snd_ca0106_spdif_info
,
619 .get
= snd_ca0106_spdif_get_mask
622 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
623 .name
= "IEC958 Playback Switch",
624 .info
= snd_ca0106_shared_spdif_info
,
625 .get
= snd_ca0106_shared_spdif_get
,
626 .put
= snd_ca0106_shared_spdif_put
629 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
630 .name
= "Digital Source Capture Enum",
631 .info
= snd_ca0106_capture_source_info
,
632 .get
= snd_ca0106_capture_source_get
,
633 .put
= snd_ca0106_capture_source_put
636 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
637 .name
= "Analog Source Capture Enum",
638 .info
= snd_ca0106_i2c_capture_source_info
,
639 .get
= snd_ca0106_i2c_capture_source_get
,
640 .put
= snd_ca0106_i2c_capture_source_put
643 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
644 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,DEFAULT
),
646 .info
= snd_ca0106_spdif_info
,
647 .get
= snd_ca0106_spdif_get_default
,
648 .put
= snd_ca0106_spdif_put_default
651 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
652 .name
= SNDRV_CTL_NAME_IEC958("",PLAYBACK
,PCM_STREAM
),
654 .info
= snd_ca0106_spdif_info
,
655 .get
= snd_ca0106_spdif_get_stream
,
656 .put
= snd_ca0106_spdif_put_stream
660 #define I2C_VOLUME(xname,chid) \
662 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
663 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
664 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
665 .info = snd_ca0106_i2c_volume_info, \
666 .get = snd_ca0106_i2c_volume_get, \
667 .put = snd_ca0106_i2c_volume_put, \
668 .tlv = { .p = snd_ca0106_db_scale2 }, \
669 .private_value = chid \
672 static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls
[] __devinitdata
= {
673 I2C_VOLUME("Phone Capture Volume", 0),
674 I2C_VOLUME("Mic Capture Volume", 1),
675 I2C_VOLUME("Line in Capture Volume", 2),
676 I2C_VOLUME("Aux Capture Volume", 3),
679 static const int spi_dmute_reg
[] = {
686 static const int spi_dmute_bit
[] = {
694 static struct snd_kcontrol_new __devinit
695 snd_ca0106_volume_spi_dac_ctl(struct snd_ca0106_details
*details
,
698 struct snd_kcontrol_new spi_switch
= {0};
702 spi_switch
.iface
= SNDRV_CTL_ELEM_IFACE_MIXER
;
703 spi_switch
.access
= SNDRV_CTL_ELEM_ACCESS_READWRITE
;
704 spi_switch
.info
= spi_mute_info
;
705 spi_switch
.get
= spi_mute_get
;
706 spi_switch
.put
= spi_mute_put
;
708 switch (channel_id
) {
709 case PCM_FRONT_CHANNEL
:
710 spi_switch
.name
= "Analog Front Playback Switch";
711 dac_id
= (details
->spi_dac
& 0xf000) >> (4 * 3);
713 case PCM_REAR_CHANNEL
:
714 spi_switch
.name
= "Analog Rear Playback Switch";
715 dac_id
= (details
->spi_dac
& 0x0f00) >> (4 * 2);
717 case PCM_CENTER_LFE_CHANNEL
:
718 spi_switch
.name
= "Analog Center/LFE Playback Switch";
719 dac_id
= (details
->spi_dac
& 0x00f0) >> (4 * 1);
721 case PCM_UNKNOWN_CHANNEL
:
722 spi_switch
.name
= "Analog Side Playback Switch";
723 dac_id
= (details
->spi_dac
& 0x000f) >> (4 * 0);
727 spi_switch
.name
= NULL
;
730 reg
= spi_dmute_reg
[dac_id
];
731 bit
= spi_dmute_bit
[dac_id
];
733 spi_switch
.private_value
= (reg
<< SPI_REG_SHIFT
) | bit
;
738 static int __devinit
remove_ctl(struct snd_card
*card
, const char *name
)
740 struct snd_ctl_elem_id id
;
741 memset(&id
, 0, sizeof(id
));
742 strcpy(id
.name
, name
);
743 id
.iface
= SNDRV_CTL_ELEM_IFACE_MIXER
;
744 return snd_ctl_remove_id(card
, &id
);
747 static struct snd_kcontrol __devinit
*ctl_find(struct snd_card
*card
, const char *name
)
749 struct snd_ctl_elem_id sid
;
750 memset(&sid
, 0, sizeof(sid
));
751 /* FIXME: strcpy is bad. */
752 strcpy(sid
.name
, name
);
753 sid
.iface
= SNDRV_CTL_ELEM_IFACE_MIXER
;
754 return snd_ctl_find_id(card
, &sid
);
757 static int __devinit
rename_ctl(struct snd_card
*card
, const char *src
, const char *dst
)
759 struct snd_kcontrol
*kctl
= ctl_find(card
, src
);
761 strcpy(kctl
->id
.name
, dst
);
767 #define ADD_CTLS(emu, ctls) \
770 for (i = 0; i < ARRAY_SIZE(ctls); i++) { \
771 _err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \
778 DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale
, -6375, 25, 1);
780 static char *slave_vols
[] __devinitdata
= {
781 "Analog Front Playback Volume",
782 "Analog Rear Playback Volume",
783 "Analog Center/LFE Playback Volume",
784 "Analog Side Playback Volume",
785 "IEC958 Front Playback Volume",
786 "IEC958 Rear Playback Volume",
787 "IEC958 Center/LFE Playback Volume",
788 "IEC958 Unknown Playback Volume",
789 "CAPTURE feedback Playback Volume",
793 static char *slave_sws
[] __devinitdata
= {
794 "Analog Front Playback Switch",
795 "Analog Rear Playback Switch",
796 "Analog Center/LFE Playback Switch",
797 "Analog Side Playback Switch",
798 "IEC958 Playback Switch",
802 static void __devinit
add_slaves(struct snd_card
*card
,
803 struct snd_kcontrol
*master
, char **list
)
805 for (; *list
; list
++) {
806 struct snd_kcontrol
*slave
= ctl_find(card
, *list
);
808 snd_ctl_add_slave(master
, slave
);
812 int __devinit
snd_ca0106_mixer(struct snd_ca0106
*emu
)
815 struct snd_card
*card
= emu
->card
;
817 struct snd_kcontrol
*vmaster
;
818 static char *ca0106_remove_ctls
[] = {
819 "Master Mono Playback Switch",
820 "Master Mono Playback Volume",
821 "3D Control - Switch",
822 "3D Control Sigmatel - Depth",
823 "PCM Playback Switch",
824 "PCM Playback Volume",
825 "CD Playback Switch",
826 "CD Playback Volume",
827 "Phone Playback Switch",
828 "Phone Playback Volume",
829 "Video Playback Switch",
830 "Video Playback Volume",
831 "Beep Playback Switch",
832 "Beep Playback Volume",
833 "Mono Output Select",
837 "External Amplifier",
838 "Sigmatel 4-Speaker Stereo Playback Switch",
839 "Surround Phase Inversion Playback Switch",
842 static char *ca0106_rename_ctls
[] = {
843 "Master Playback Switch", "Capture Switch",
844 "Master Playback Volume", "Capture Volume",
845 "Line Playback Switch", "AC97 Line Capture Switch",
846 "Line Playback Volume", "AC97 Line Capture Volume",
847 "Aux Playback Switch", "AC97 Aux Capture Switch",
848 "Aux Playback Volume", "AC97 Aux Capture Volume",
849 "Mic Playback Switch", "AC97 Mic Capture Switch",
850 "Mic Playback Volume", "AC97 Mic Capture Volume",
851 "Mic Select", "AC97 Mic Select",
852 "Mic Boost (+20dB)", "AC97 Mic Boost (+20dB)",
856 for (c
= ca0106_remove_ctls
; *c
; c
++)
857 remove_ctl(card
, *c
);
858 for (c
= ca0106_rename_ctls
; *c
; c
+= 2)
859 rename_ctl(card
, c
[0], c
[1]);
862 ADD_CTLS(emu
, snd_ca0106_volume_ctls
);
863 if (emu
->details
->i2c_adc
== 1) {
864 ADD_CTLS(emu
, snd_ca0106_volume_i2c_adc_ctls
);
865 if (emu
->details
->gpio_type
== 1)
866 err
= snd_ctl_add(card
, snd_ctl_new1(&snd_ca0106_capture_mic_line_in
, emu
));
867 else /* gpio_type == 2 */
868 err
= snd_ctl_add(card
, snd_ctl_new1(&snd_ca0106_capture_line_in_side_out
, emu
));
872 if (emu
->details
->spi_dac
) {
875 struct snd_kcontrol_new ctl
;
876 ctl
= snd_ca0106_volume_spi_dac_ctl(emu
->details
, i
);
879 err
= snd_ctl_add(card
, snd_ctl_new1(&ctl
, emu
));
885 /* Create virtual master controls */
886 vmaster
= snd_ctl_make_virtual_master("Master Playback Volume",
887 snd_ca0106_master_db_scale
);
890 err
= snd_ctl_add(card
, vmaster
);
893 add_slaves(card
, vmaster
, slave_vols
);
895 if (emu
->details
->spi_dac
) {
896 vmaster
= snd_ctl_make_virtual_master("Master Playback Switch",
900 err
= snd_ctl_add(card
, vmaster
);
903 add_slaves(card
, vmaster
, slave_sws
);
906 strcpy(card
->mixername
, "CA0106");
911 struct ca0106_vol_tbl
{
912 unsigned int channel_id
;
916 static struct ca0106_vol_tbl saved_volumes
[NUM_SAVED_VOLUMES
] = {
917 { CONTROL_FRONT_CHANNEL
, PLAYBACK_VOLUME2
},
918 { CONTROL_REAR_CHANNEL
, PLAYBACK_VOLUME2
},
919 { CONTROL_CENTER_LFE_CHANNEL
, PLAYBACK_VOLUME2
},
920 { CONTROL_UNKNOWN_CHANNEL
, PLAYBACK_VOLUME2
},
921 { CONTROL_FRONT_CHANNEL
, PLAYBACK_VOLUME1
},
922 { CONTROL_REAR_CHANNEL
, PLAYBACK_VOLUME1
},
923 { CONTROL_CENTER_LFE_CHANNEL
, PLAYBACK_VOLUME1
},
924 { CONTROL_UNKNOWN_CHANNEL
, PLAYBACK_VOLUME1
},
925 { 1, CAPTURE_CONTROL
},
928 void snd_ca0106_mixer_suspend(struct snd_ca0106
*chip
)
933 for (i
= 0; i
< NUM_SAVED_VOLUMES
; i
++)
935 snd_ca0106_ptr_read(chip
, saved_volumes
[i
].reg
,
936 saved_volumes
[i
].channel_id
);
939 void snd_ca0106_mixer_resume(struct snd_ca0106
*chip
)
943 for (i
= 0; i
< NUM_SAVED_VOLUMES
; i
++)
944 snd_ca0106_ptr_write(chip
, saved_volumes
[i
].reg
,
945 saved_volumes
[i
].channel_id
,
948 ca0106_spdif_enable(chip
);
949 ca0106_set_capture_source(chip
);
950 ca0106_set_i2c_capture_source(chip
, chip
->i2c_capture_source
, 1);
951 for (i
= 0; i
< 4; i
++)
952 ca0106_set_spdif_bits(chip
, i
);
953 if (chip
->details
->i2c_adc
)
954 ca0106_set_capture_mic_line_in(chip
);
956 #endif /* CONFIG_PM */