• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/sound/pci/ca0106/
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/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>
74
75#include "ca0106.h"
76
77static void ca0106_spdif_enable(struct snd_ca0106 *emu)
78{
79	unsigned int val;
80
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);
89
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);
98	}
99}
100
101static void ca0106_set_capture_source(struct snd_ca0106 *emu)
102{
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);
108}
109
110static void ca0106_set_i2c_capture_source(struct snd_ca0106 *emu,
111					  unsigned int val, int force)
112{
113	unsigned int ngain, ogain;
114	u32 source;
115
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;
128}
129
130static void ca0106_set_capture_mic_line_in(struct snd_ca0106 *emu)
131{
132	u32 tmp;
133
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); */
145	}
146}
147
148static void ca0106_set_spdif_bits(struct snd_ca0106 *emu, int idx)
149{
150	snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_str_bits[idx]);
151}
152
153/*
154 */
155static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1);
156static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1);
157
158#define snd_ca0106_shared_spdif_info	snd_ctl_boolean_mono_info
159
160static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol,
161					struct snd_ctl_elem_value *ucontrol)
162{
163	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
164
165	ucontrol->value.integer.value[0] = emu->spdif_enable;
166	return 0;
167}
168
169static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol,
170					struct snd_ctl_elem_value *ucontrol)
171{
172	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
173	unsigned int val;
174	int change = 0;
175
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);
181	}
182        return change;
183}
184
185static int snd_ca0106_capture_source_info(struct snd_kcontrol *kcontrol,
186					  struct snd_ctl_elem_info *uinfo)
187{
188	static char *texts[6] = {
189		"IEC958 out", "i2s mixer out", "IEC958 in", "i2s in", "AC97 in", "SRC out"
190	};
191
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;
199}
200
201static int snd_ca0106_capture_source_get(struct snd_kcontrol *kcontrol,
202					struct snd_ctl_elem_value *ucontrol)
203{
204	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
205
206	ucontrol->value.enumerated.item[0] = emu->capture_source;
207	return 0;
208}
209
210static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
211					struct snd_ctl_elem_value *ucontrol)
212{
213	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
214	unsigned int val;
215	int change = 0;
216
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);
224	}
225        return change;
226}
227
228static int snd_ca0106_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
229					  struct snd_ctl_elem_info *uinfo)
230{
231	static char *texts[6] = {
232		"Phone", "Mic", "Line in", "Aux"
233	};
234
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;
242}
243
244static int snd_ca0106_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
245					struct snd_ctl_elem_value *ucontrol)
246{
247	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
248
249	ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
250	return 0;
251}
252
253static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
254					struct snd_ctl_elem_value *ucontrol)
255{
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.
262	 */
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);
269	}
270        return change;
271}
272
273static int snd_ca0106_capture_line_in_side_out_info(struct snd_kcontrol *kcontrol,
274					       struct snd_ctl_elem_info *uinfo)
275{
276	static char *texts[2] = { "Side out", "Line in" };
277
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;
285}
286
287static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol,
288					       struct snd_ctl_elem_info *uinfo)
289{
290	static char *texts[2] = { "Line in", "Mic in" };
291
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;
299}
300
301static int snd_ca0106_capture_mic_line_in_get(struct snd_kcontrol *kcontrol,
302					struct snd_ctl_elem_value *ucontrol)
303{
304	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
305
306	ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in;
307	return 0;
308}
309
310static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
311					struct snd_ctl_elem_value *ucontrol)
312{
313	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
314	unsigned int val;
315	int change = 0;
316
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);
324	}
325        return change;
326}
327
328static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata =
329{
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
335};
336
337static struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out __devinitdata =
338{
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
344};
345
346
347static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol,
348				 struct snd_ctl_elem_info *uinfo)
349{
350	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
351	uinfo->count = 1;
352	return 0;
353}
354
355static void decode_spdif_bits(unsigned char *status, unsigned int bits)
356{
357	status[0] = (bits >> 0) & 0xff;
358	status[1] = (bits >> 8) & 0xff;
359	status[2] = (bits >> 16) & 0xff;
360	status[3] = (bits >> 24) & 0xff;
361}
362
363static int snd_ca0106_spdif_get_default(struct snd_kcontrol *kcontrol,
364                                 struct snd_ctl_elem_value *ucontrol)
365{
366	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
367	unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
368
369	decode_spdif_bits(ucontrol->value.iec958.status,
370			  emu->spdif_bits[idx]);
371        return 0;
372}
373
374static int snd_ca0106_spdif_get_stream(struct snd_kcontrol *kcontrol,
375                                 struct snd_ctl_elem_value *ucontrol)
376{
377	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
378	unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
379
380	decode_spdif_bits(ucontrol->value.iec958.status,
381			  emu->spdif_str_bits[idx]);
382        return 0;
383}
384
385static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol,
386				      struct snd_ctl_elem_value *ucontrol)
387{
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;
393}
394
395static unsigned int encode_spdif_bits(unsigned char *status)
396{
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);
401}
402
403static int snd_ca0106_spdif_put_default(struct snd_kcontrol *kcontrol,
404                                 struct snd_ctl_elem_value *ucontrol)
405{
406	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
407	unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
408	unsigned int val;
409
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;
416	}
417	return 0;
418}
419
420static int snd_ca0106_spdif_put_stream(struct snd_kcontrol *kcontrol,
421                                 struct snd_ctl_elem_value *ucontrol)
422{
423	struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
424	unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
425	unsigned int val;
426
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;
432	}
433        return 0;
434}
435
436static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol,
437				  struct snd_ctl_elem_info *uinfo)
438{
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;
444}
445
446static int snd_ca0106_volume_get(struct snd_kcontrol *kcontrol,
447				 struct snd_ctl_elem_value *ucontrol)
448{
449        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
450        unsigned int value;
451	int channel_id, reg;
452
453	channel_id = (kcontrol->private_value >> 8) & 0xff;
454	reg = kcontrol->private_value & 0xff;
455
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;
460}
461
462static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol,
463				 struct snd_ctl_elem_value *ucontrol)
464{
465        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
466        unsigned int oval, nval;
467	int channel_id, reg;
468
469	channel_id = (kcontrol->private_value >> 8) & 0xff;
470	reg = kcontrol->private_value & 0xff;
471
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;
481}
482
483static int snd_ca0106_i2c_volume_info(struct snd_kcontrol *kcontrol,
484				  struct snd_ctl_elem_info *uinfo)
485{
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;
491}
492
493static int snd_ca0106_i2c_volume_get(struct snd_kcontrol *kcontrol,
494				 struct snd_ctl_elem_value *ucontrol)
495{
496        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
497	int source_id;
498
499	source_id = kcontrol->private_value;
500
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;
504}
505
506static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol,
507				 struct snd_ctl_elem_value *ucontrol)
508{
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;
514
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;
525	}
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;
535	}
536
537	return change;
538}
539
540#define spi_mute_info	snd_ctl_boolean_mono_info
541
542static int spi_mute_get(struct snd_kcontrol *kcontrol,
543			struct snd_ctl_elem_value *ucontrol)
544{
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;
548
549	ucontrol->value.integer.value[0] = !(emu->spi_dac_reg[reg] & bit);
550	return 0;
551}
552
553static int spi_mute_put(struct snd_kcontrol *kcontrol,
554			struct snd_ctl_elem_value *ucontrol)
555{
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;
560
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;
570	}
571
572	ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]);
573	return ret ? -EINVAL : 1;
574}
575
576#define CA_VOLUME(xname,chid,reg) \
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_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)			\
586}
587
588static 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),
597
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),
606
607        CA_VOLUME("CAPTURE feedback Playback Volume",
608		  1, CAPTURE_CONTROL),
609
610	{
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
617	},
618	{
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
624	},
625	{
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
631	},
632	{
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
638	},
639	{
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
646	},
647	{
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
654	},
655};
656
657#define I2C_VOLUME(xname,chid) \
658{								\
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					\
667}
668
669static 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),
674};
675
676#define SPI_SWITCH(xname,reg,bit) \
677{								\
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)		\
684}
685
686static 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),
696};
697
698static int __devinit remove_ctl(struct snd_card *card, const char *name)
699{
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);
705}
706
707static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, const char *name)
708{
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);
714}
715
716static int __devinit rename_ctl(struct snd_card *card, const char *src, const char *dst)
717{
718	struct snd_kcontrol *kctl = ctl_find(card, src);
719	if (kctl) {
720		strcpy(kctl->id.name, dst);
721		return 0;
722	}
723	return -ENOENT;
724}
725
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;				\
733		}							\
734	} while (0)
735
736static __devinitdata
737DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 25, 1);
738
739static 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
750};
751
752static 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
759};
760
761static void __devinit add_slaves(struct snd_card *card,
762				 struct snd_kcontrol *master, char **list)
763{
764	for (; *list; list++) {
765		struct snd_kcontrol *slave = ctl_find(card, *list);
766		if (slave)
767			snd_ctl_add_slave(master, slave);
768	}
769}
770
771int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
772{
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
800	};
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
813	};
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]);
818
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;
828	}
829	if (emu->details->spi_dac == 1)
830		ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls);
831
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);
841
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);
851	}
852
853	strcpy(card->mixername, "CA0106");
854        return 0;
855}
856
857#ifdef CONFIG_PM
858struct ca0106_vol_tbl {
859	unsigned int channel_id;
860	unsigned int reg;
861};
862
863static 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 },
873};
874
875void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip)
876{
877	int i;
878
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);
884}
885
886void snd_ca0106_mixer_resume(struct snd_ca0106  *chip)
887{
888	int i;
889
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]);
894
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);
902}
903#endif /* CONFIG_PM */
904