Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[deliverable/linux.git] / sound / pci / ca0106 / ca0106_mixer.c
CommitLineData
1da177e4
LT
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
b18cd538 4 * Version: 0.0.18
1da177e4
LT
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.
ed144f3c
JCD
40 * 0.0.17
41 * Implement Mic and Line in Capture.
b18cd538
TP
42 * 0.0.18
43 * Add support for mute control on SB Live 24bit (cards w/ SPI DAC)
1da177e4 44 *
25985edc 45 * This code was initially based on code from ALSA's emu10k1x.c which is:
1da177e4
LT
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 */
1da177e4
LT
63#include <linux/delay.h>
64#include <linux/init.h>
65#include <linux/interrupt.h>
1da177e4
LT
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>
42750b04 72#include <sound/tlv.h>
6cbbfe1c 73#include <linux/io.h>
1da177e4
LT
74
75#include "ca0106.h"
76
5da95273
TI
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{
3d475829 150 snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_str_bits[idx]);
5da95273
TI
151}
152
153/*
154 */
0cb29ea0
TI
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);
42750b04 157
a5ce8890 158#define snd_ca0106_shared_spdif_info snd_ctl_boolean_mono_info
1da177e4 159
e4a3d145
TI
160static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol,
161 struct snd_ctl_elem_value *ucontrol)
1da177e4 162{
e4a3d145 163 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
1da177e4 164
5fe619f9 165 ucontrol->value.integer.value[0] = emu->spdif_enable;
1da177e4
LT
166 return 0;
167}
168
e4a3d145
TI
169static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol,
170 struct snd_ctl_elem_value *ucontrol)
1da177e4 171{
e4a3d145 172 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
1da177e4
LT
173 unsigned int val;
174 int change = 0;
1da177e4 175
5fe619f9 176 val = !!ucontrol->value.integer.value[0];
1da177e4
LT
177 change = (emu->spdif_enable != val);
178 if (change) {
179 emu->spdif_enable = val;
5da95273 180 ca0106_spdif_enable(emu);
1da177e4
LT
181 }
182 return change;
183}
184
e4a3d145
TI
185static int snd_ca0106_capture_source_info(struct snd_kcontrol *kcontrol,
186 struct snd_ctl_elem_info *uinfo)
1da177e4 187{
de95eae2 188 static const char * const texts[6] = {
39596dc8 189 "IEC958 out", "i2s mixer out", "IEC958 in", "i2s in", "AC97 in", "SRC out"
95a98265 190 };
1da177e4 191
de95eae2 192 return snd_ctl_enum_info(uinfo, 1, 6, texts);
1da177e4
LT
193}
194
e4a3d145
TI
195static int snd_ca0106_capture_source_get(struct snd_kcontrol *kcontrol,
196 struct snd_ctl_elem_value *ucontrol)
1da177e4 197{
e4a3d145 198 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
1da177e4
LT
199
200 ucontrol->value.enumerated.item[0] = emu->capture_source;
201 return 0;
202}
203
e4a3d145
TI
204static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
205 struct snd_ctl_elem_value *ucontrol)
1da177e4 206{
e4a3d145 207 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
1da177e4
LT
208 unsigned int val;
209 int change = 0;
1da177e4
LT
210
211 val = ucontrol->value.enumerated.item[0] ;
5fe619f9
TI
212 if (val >= 6)
213 return -EINVAL;
1da177e4
LT
214 change = (emu->capture_source != val);
215 if (change) {
216 emu->capture_source = val;
5da95273 217 ca0106_set_capture_source(emu);
1da177e4
LT
218 }
219 return change;
220}
221
6129daaa
JCD
222static int snd_ca0106_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
223 struct snd_ctl_elem_info *uinfo)
224{
de95eae2 225 static const char * const texts[4] = {
6129daaa
JCD
226 "Phone", "Mic", "Line in", "Aux"
227 };
228
de95eae2 229 return snd_ctl_enum_info(uinfo, 1, 4, texts);
6129daaa
JCD
230}
231
232static int snd_ca0106_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
233 struct snd_ctl_elem_value *ucontrol)
234{
235 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
236
237 ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
238 return 0;
239}
240
241static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
242 struct snd_ctl_elem_value *ucontrol)
243{
244 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
245 unsigned int source_id;
6129daaa 246 int change = 0;
6129daaa
JCD
247 /* If the capture source has changed,
248 * update the capture volume from the cached value
249 * for the particular source.
250 */
251 source_id = ucontrol->value.enumerated.item[0] ;
5fe619f9
TI
252 if (source_id >= 4)
253 return -EINVAL;
6129daaa
JCD
254 change = (emu->i2c_capture_source != source_id);
255 if (change) {
5da95273 256 ca0106_set_i2c_capture_source(emu, source_id, 0);
6129daaa
JCD
257 }
258 return change;
259}
260
be0b7b01
JCD
261static int snd_ca0106_capture_line_in_side_out_info(struct snd_kcontrol *kcontrol,
262 struct snd_ctl_elem_info *uinfo)
263{
de95eae2
TI
264 static const char * const texts[2] = { "Side out", "Line in" };
265
266 return snd_ctl_enum_info(uinfo, 1, 2, texts);
be0b7b01
JCD
267}
268
e4a3d145
TI
269static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol,
270 struct snd_ctl_elem_info *uinfo)
ed144f3c 271{
de95eae2
TI
272 static const char * const texts[2] = { "Line in", "Mic in" };
273
274 return snd_ctl_enum_info(uinfo, 1, 2, texts);
ed144f3c
JCD
275}
276
e4a3d145
TI
277static int snd_ca0106_capture_mic_line_in_get(struct snd_kcontrol *kcontrol,
278 struct snd_ctl_elem_value *ucontrol)
ed144f3c 279{
e4a3d145 280 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
ed144f3c
JCD
281
282 ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in;
283 return 0;
284}
285
e4a3d145
TI
286static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
287 struct snd_ctl_elem_value *ucontrol)
ed144f3c 288{
e4a3d145 289 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
ed144f3c
JCD
290 unsigned int val;
291 int change = 0;
ed144f3c
JCD
292
293 val = ucontrol->value.enumerated.item[0] ;
5fe619f9
TI
294 if (val > 1)
295 return -EINVAL;
ed144f3c
JCD
296 change = (emu->capture_mic_line_in != val);
297 if (change) {
298 emu->capture_mic_line_in = val;
5da95273 299 ca0106_set_capture_mic_line_in(emu);
ed144f3c
JCD
300 }
301 return change;
302}
303
e23e7a14 304static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in =
ed144f3c
JCD
305{
306 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6129daaa 307 .name = "Shared Mic/Line in Capture Switch",
ed144f3c
JCD
308 .info = snd_ca0106_capture_mic_line_in_info,
309 .get = snd_ca0106_capture_mic_line_in_get,
310 .put = snd_ca0106_capture_mic_line_in_put
311};
312
e23e7a14 313static struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out =
be0b7b01
JCD
314{
315 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
316 .name = "Shared Line in/Side out Capture Switch",
317 .info = snd_ca0106_capture_line_in_side_out_info,
318 .get = snd_ca0106_capture_mic_line_in_get,
319 .put = snd_ca0106_capture_mic_line_in_put
320};
321
322
e4a3d145
TI
323static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol,
324 struct snd_ctl_elem_info *uinfo)
1da177e4
LT
325{
326 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
327 uinfo->count = 1;
328 return 0;
329}
330
3d475829
TI
331static void decode_spdif_bits(unsigned char *status, unsigned int bits)
332{
333 status[0] = (bits >> 0) & 0xff;
334 status[1] = (bits >> 8) & 0xff;
335 status[2] = (bits >> 16) & 0xff;
336 status[3] = (bits >> 24) & 0xff;
337}
338
339static int snd_ca0106_spdif_get_default(struct snd_kcontrol *kcontrol,
e4a3d145 340 struct snd_ctl_elem_value *ucontrol)
1da177e4 341{
e4a3d145 342 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
1da177e4
LT
343 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
344
3d475829
TI
345 decode_spdif_bits(ucontrol->value.iec958.status,
346 emu->spdif_bits[idx]);
347 return 0;
348}
349
350static int snd_ca0106_spdif_get_stream(struct snd_kcontrol *kcontrol,
351 struct snd_ctl_elem_value *ucontrol)
352{
353 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
354 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
355
356 decode_spdif_bits(ucontrol->value.iec958.status,
357 emu->spdif_str_bits[idx]);
1da177e4
LT
358 return 0;
359}
360
e4a3d145
TI
361static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol,
362 struct snd_ctl_elem_value *ucontrol)
1da177e4
LT
363{
364 ucontrol->value.iec958.status[0] = 0xff;
365 ucontrol->value.iec958.status[1] = 0xff;
366 ucontrol->value.iec958.status[2] = 0xff;
367 ucontrol->value.iec958.status[3] = 0xff;
368 return 0;
369}
370
3d475829
TI
371static unsigned int encode_spdif_bits(unsigned char *status)
372{
373 return ((unsigned int)status[0] << 0) |
374 ((unsigned int)status[1] << 8) |
375 ((unsigned int)status[2] << 16) |
376 ((unsigned int)status[3] << 24);
377}
378
379static int snd_ca0106_spdif_put_default(struct snd_kcontrol *kcontrol,
e4a3d145 380 struct snd_ctl_elem_value *ucontrol)
1da177e4 381{
e4a3d145 382 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
1da177e4 383 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1da177e4
LT
384 unsigned int val;
385
3d475829
TI
386 val = encode_spdif_bits(ucontrol->value.iec958.status);
387 if (val != emu->spdif_bits[idx]) {
1da177e4 388 emu->spdif_bits[idx] = val;
3d475829
TI
389 /* FIXME: this isn't safe, but needed to keep the compatibility
390 * with older alsa-lib config
391 */
392 emu->spdif_str_bits[idx] = val;
5da95273 393 ca0106_set_spdif_bits(emu, idx);
3d475829 394 return 1;
1da177e4 395 }
3d475829
TI
396 return 0;
397}
398
399static int snd_ca0106_spdif_put_stream(struct snd_kcontrol *kcontrol,
400 struct snd_ctl_elem_value *ucontrol)
401{
402 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
403 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
404 unsigned int val;
405
406 val = encode_spdif_bits(ucontrol->value.iec958.status);
407 if (val != emu->spdif_str_bits[idx]) {
408 emu->spdif_str_bits[idx] = val;
409 ca0106_set_spdif_bits(emu, idx);
410 return 1;
411 }
412 return 0;
1da177e4
LT
413}
414
e4a3d145
TI
415static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol,
416 struct snd_ctl_elem_info *uinfo)
1da177e4
LT
417{
418 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
419 uinfo->count = 2;
420 uinfo->value.integer.min = 0;
421 uinfo->value.integer.max = 255;
422 return 0;
423}
424
e4a3d145
TI
425static int snd_ca0106_volume_get(struct snd_kcontrol *kcontrol,
426 struct snd_ctl_elem_value *ucontrol)
1da177e4 427{
e4a3d145 428 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
1da177e4 429 unsigned int value;
95a98265
TI
430 int channel_id, reg;
431
432 channel_id = (kcontrol->private_value >> 8) & 0xff;
433 reg = kcontrol->private_value & 0xff;
1da177e4
LT
434
435 value = snd_ca0106_ptr_read(emu, reg, channel_id);
436 ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */
437 ucontrol->value.integer.value[1] = 0xff - ((value >> 16) & 0xff); /* Right */
438 return 0;
439}
440
e4a3d145
TI
441static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol,
442 struct snd_ctl_elem_value *ucontrol)
1da177e4 443{
e4a3d145 444 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
95a98265
TI
445 unsigned int oval, nval;
446 int channel_id, reg;
447
448 channel_id = (kcontrol->private_value >> 8) & 0xff;
449 reg = kcontrol->private_value & 0xff;
450
451 oval = snd_ca0106_ptr_read(emu, reg, channel_id);
452 nval = ((0xff - ucontrol->value.integer.value[0]) << 24) |
453 ((0xff - ucontrol->value.integer.value[1]) << 16);
454 nval |= ((0xff - ucontrol->value.integer.value[0]) << 8) |
455 ((0xff - ucontrol->value.integer.value[1]) );
456 if (oval == nval)
457 return 0;
458 snd_ca0106_ptr_write(emu, reg, channel_id, nval);
459 return 1;
460}
461
6129daaa
JCD
462static int snd_ca0106_i2c_volume_info(struct snd_kcontrol *kcontrol,
463 struct snd_ctl_elem_info *uinfo)
464{
465 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
466 uinfo->count = 2;
467 uinfo->value.integer.min = 0;
468 uinfo->value.integer.max = 255;
469 return 0;
470}
471
472static int snd_ca0106_i2c_volume_get(struct snd_kcontrol *kcontrol,
473 struct snd_ctl_elem_value *ucontrol)
474{
475 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
476 int source_id;
477
478 source_id = kcontrol->private_value;
479
480 ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
481 ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
482 return 0;
483}
484
485static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol,
486 struct snd_ctl_elem_value *ucontrol)
487{
488 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
489 unsigned int ogain;
490 unsigned int ngain;
491 int source_id;
492 int change = 0;
493
494 source_id = kcontrol->private_value;
495 ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
496 ngain = ucontrol->value.integer.value[0];
497 if (ngain > 0xff)
5fe619f9 498 return -EINVAL;
6129daaa
JCD
499 if (ogain != ngain) {
500 if (emu->i2c_capture_source == source_id)
501 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
502 emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0];
503 change = 1;
504 }
505 ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
506 ngain = ucontrol->value.integer.value[1];
507 if (ngain > 0xff)
5fe619f9 508 return -EINVAL;
6129daaa
JCD
509 if (ogain != ngain) {
510 if (emu->i2c_capture_source == source_id)
511 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
512 emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1];
513 change = 1;
514 }
515
516 return change;
517}
518
b18cd538
TP
519#define spi_mute_info snd_ctl_boolean_mono_info
520
521static int spi_mute_get(struct snd_kcontrol *kcontrol,
522 struct snd_ctl_elem_value *ucontrol)
523{
524 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
525 unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT;
526 unsigned int bit = kcontrol->private_value & SPI_REG_MASK;
527
528 ucontrol->value.integer.value[0] = !(emu->spi_dac_reg[reg] & bit);
529 return 0;
530}
531
532static int spi_mute_put(struct snd_kcontrol *kcontrol,
533 struct snd_ctl_elem_value *ucontrol)
534{
535 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
536 unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT;
537 unsigned int bit = kcontrol->private_value & SPI_REG_MASK;
538 int ret;
539
540 ret = emu->spi_dac_reg[reg] & bit;
541 if (ucontrol->value.integer.value[0]) {
542 if (!ret) /* bit already cleared, do nothing */
543 return 0;
544 emu->spi_dac_reg[reg] &= ~bit;
545 } else {
546 if (ret) /* bit already set, do nothing */
547 return 0;
548 emu->spi_dac_reg[reg] |= bit;
549 }
550
551 ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]);
5fe619f9 552 return ret ? -EINVAL : 1;
b18cd538
TP
553}
554
95a98265
TI
555#define CA_VOLUME(xname,chid,reg) \
556{ \
557 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
302e9c5a
JK
558 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
559 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
6129daaa
JCD
560 .info = snd_ca0106_volume_info, \
561 .get = snd_ca0106_volume_get, \
562 .put = snd_ca0106_volume_put, \
7cf0a953 563 .tlv = { .p = snd_ca0106_db_scale1 }, \
95a98265
TI
564 .private_value = ((chid) << 8) | (reg) \
565}
566
e23e7a14 567static struct snd_kcontrol_new snd_ca0106_volume_ctls[] = {
95a98265
TI
568 CA_VOLUME("Analog Front Playback Volume",
569 CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2),
570 CA_VOLUME("Analog Rear Playback Volume",
571 CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2),
572 CA_VOLUME("Analog Center/LFE Playback Volume",
573 CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2),
574 CA_VOLUME("Analog Side Playback Volume",
575 CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2),
576
39596dc8 577 CA_VOLUME("IEC958 Front Playback Volume",
95a98265 578 CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1),
39596dc8 579 CA_VOLUME("IEC958 Rear Playback Volume",
95a98265 580 CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1),
39596dc8 581 CA_VOLUME("IEC958 Center/LFE Playback Volume",
95a98265 582 CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1),
39596dc8 583 CA_VOLUME("IEC958 Unknown Playback Volume",
95a98265
TI
584 CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1),
585
586 CA_VOLUME("CAPTURE feedback Playback Volume",
587 1, CAPTURE_CONTROL),
588
589 {
590 .access = SNDRV_CTL_ELEM_ACCESS_READ,
591 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
592 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
593 .count = 4,
594 .info = snd_ca0106_spdif_info,
595 .get = snd_ca0106_spdif_get_mask
596 },
597 {
598 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
39596dc8 599 .name = "IEC958 Playback Switch",
95a98265
TI
600 .info = snd_ca0106_shared_spdif_info,
601 .get = snd_ca0106_shared_spdif_get,
602 .put = snd_ca0106_shared_spdif_put
603 },
604 {
605 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
e6327cf9 606 .name = "Digital Source Capture Enum",
95a98265
TI
607 .info = snd_ca0106_capture_source_info,
608 .get = snd_ca0106_capture_source_get,
609 .put = snd_ca0106_capture_source_put
610 },
6129daaa
JCD
611 {
612 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
e6327cf9 613 .name = "Analog Source Capture Enum",
6129daaa
JCD
614 .info = snd_ca0106_i2c_capture_source_info,
615 .get = snd_ca0106_i2c_capture_source_get,
616 .put = snd_ca0106_i2c_capture_source_put
617 },
95a98265
TI
618 {
619 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
620 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
621 .count = 4,
622 .info = snd_ca0106_spdif_info,
3d475829
TI
623 .get = snd_ca0106_spdif_get_default,
624 .put = snd_ca0106_spdif_put_default
625 },
626 {
627 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
628 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
629 .count = 4,
630 .info = snd_ca0106_spdif_info,
631 .get = snd_ca0106_spdif_get_stream,
632 .put = snd_ca0106_spdif_put_stream
95a98265 633 },
1da177e4
LT
634};
635
7c157069
JCD
636#define I2C_VOLUME(xname,chid) \
637{ \
638 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
639 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
640 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
641 .info = snd_ca0106_i2c_volume_info, \
642 .get = snd_ca0106_i2c_volume_get, \
643 .put = snd_ca0106_i2c_volume_put, \
644 .tlv = { .p = snd_ca0106_db_scale2 }, \
645 .private_value = chid \
646}
647
e23e7a14 648static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] = {
7c157069
JCD
649 I2C_VOLUME("Phone Capture Volume", 0),
650 I2C_VOLUME("Mic Capture Volume", 1),
651 I2C_VOLUME("Line in Capture Volume", 2),
652 I2C_VOLUME("Aux Capture Volume", 3),
653};
654
64e5310a
AO
655static const int spi_dmute_reg[] = {
656 SPI_DMUTE0_REG,
657 SPI_DMUTE1_REG,
658 SPI_DMUTE2_REG,
659 0,
660 SPI_DMUTE4_REG,
661};
662static const int spi_dmute_bit[] = {
663 SPI_DMUTE0_BIT,
664 SPI_DMUTE1_BIT,
665 SPI_DMUTE2_BIT,
666 0,
667 SPI_DMUTE4_BIT,
b18cd538
TP
668};
669
e23e7a14 670static struct snd_kcontrol_new
64e5310a
AO
671snd_ca0106_volume_spi_dac_ctl(struct snd_ca0106_details *details,
672 int channel_id)
673{
674 struct snd_kcontrol_new spi_switch = {0};
675 int reg, bit;
676 int dac_id;
677
678 spi_switch.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
679 spi_switch.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
680 spi_switch.info = spi_mute_info;
681 spi_switch.get = spi_mute_get;
682 spi_switch.put = spi_mute_put;
683
684 switch (channel_id) {
685 case PCM_FRONT_CHANNEL:
686 spi_switch.name = "Analog Front Playback Switch";
687 dac_id = (details->spi_dac & 0xf000) >> (4 * 3);
688 break;
689 case PCM_REAR_CHANNEL:
690 spi_switch.name = "Analog Rear Playback Switch";
691 dac_id = (details->spi_dac & 0x0f00) >> (4 * 2);
692 break;
693 case PCM_CENTER_LFE_CHANNEL:
694 spi_switch.name = "Analog Center/LFE Playback Switch";
695 dac_id = (details->spi_dac & 0x00f0) >> (4 * 1);
696 break;
697 case PCM_UNKNOWN_CHANNEL:
698 spi_switch.name = "Analog Side Playback Switch";
699 dac_id = (details->spi_dac & 0x000f) >> (4 * 0);
700 break;
701 default:
702 /* Unused channel */
703 spi_switch.name = NULL;
704 dac_id = 0;
705 }
706 reg = spi_dmute_reg[dac_id];
707 bit = spi_dmute_bit[dac_id];
708
709 spi_switch.private_value = (reg << SPI_REG_SHIFT) | bit;
710
711 return spi_switch;
712}
713
e23e7a14 714static int remove_ctl(struct snd_card *card, const char *name)
1da177e4 715{
e4a3d145 716 struct snd_ctl_elem_id id;
1da177e4
LT
717 memset(&id, 0, sizeof(id));
718 strcpy(id.name, name);
719 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
720 return snd_ctl_remove_id(card, &id);
721}
722
e23e7a14 723static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
1da177e4 724{
e4a3d145 725 struct snd_ctl_elem_id sid;
1da177e4
LT
726 memset(&sid, 0, sizeof(sid));
727 /* FIXME: strcpy is bad. */
728 strcpy(sid.name, name);
729 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
730 return snd_ctl_find_id(card, &sid);
731}
732
e23e7a14 733static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
1da177e4 734{
e4a3d145 735 struct snd_kcontrol *kctl = ctl_find(card, src);
1da177e4
LT
736 if (kctl) {
737 strcpy(kctl->id.name, dst);
738 return 0;
739 }
740 return -ENOENT;
741}
742
fca7f388
TP
743#define ADD_CTLS(emu, ctls) \
744 do { \
bed515b0 745 int i, _err; \
fca7f388 746 for (i = 0; i < ARRAY_SIZE(ctls); i++) { \
bed515b0
HH
747 _err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \
748 if (_err < 0) \
749 return _err; \
fca7f388
TP
750 } \
751 } while (0)
752
e23e7a14 753static
c4865679 754DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 25, 1);
49c88b85 755
e23e7a14 756static char *slave_vols[] = {
49c88b85
TI
757 "Analog Front Playback Volume",
758 "Analog Rear Playback Volume",
759 "Analog Center/LFE Playback Volume",
760 "Analog Side Playback Volume",
761 "IEC958 Front Playback Volume",
762 "IEC958 Rear Playback Volume",
763 "IEC958 Center/LFE Playback Volume",
764 "IEC958 Unknown Playback Volume",
765 "CAPTURE feedback Playback Volume",
766 NULL
767};
768
e23e7a14 769static char *slave_sws[] = {
49c88b85
TI
770 "Analog Front Playback Switch",
771 "Analog Rear Playback Switch",
772 "Analog Center/LFE Playback Switch",
773 "Analog Side Playback Switch",
774 "IEC958 Playback Switch",
775 NULL
776};
777
e23e7a14 778static void add_slaves(struct snd_card *card,
49c88b85
TI
779 struct snd_kcontrol *master, char **list)
780{
781 for (; *list; list++) {
782 struct snd_kcontrol *slave = ctl_find(card, *list);
783 if (slave)
784 snd_ctl_add_slave(master, slave);
785 }
786}
787
e23e7a14 788int snd_ca0106_mixer(struct snd_ca0106 *emu)
1da177e4 789{
fca7f388 790 int err;
e4a3d145 791 struct snd_card *card = emu->card;
1da177e4 792 char **c;
49c88b85 793 struct snd_kcontrol *vmaster;
1da177e4
LT
794 static char *ca0106_remove_ctls[] = {
795 "Master Mono Playback Switch",
796 "Master Mono Playback Volume",
797 "3D Control - Switch",
798 "3D Control Sigmatel - Depth",
799 "PCM Playback Switch",
800 "PCM Playback Volume",
801 "CD Playback Switch",
802 "CD Playback Volume",
803 "Phone Playback Switch",
804 "Phone Playback Volume",
805 "Video Playback Switch",
806 "Video Playback Volume",
d355c82a
JK
807 "Beep Playback Switch",
808 "Beep Playback Volume",
1da177e4
LT
809 "Mono Output Select",
810 "Capture Source",
811 "Capture Switch",
812 "Capture Volume",
813 "External Amplifier",
814 "Sigmatel 4-Speaker Stereo Playback Switch",
afe6d7e3 815 "Surround Phase Inversion Playback Switch",
1da177e4
LT
816 NULL
817 };
818 static char *ca0106_rename_ctls[] = {
819 "Master Playback Switch", "Capture Switch",
820 "Master Playback Volume", "Capture Volume",
821 "Line Playback Switch", "AC97 Line Capture Switch",
822 "Line Playback Volume", "AC97 Line Capture Volume",
823 "Aux Playback Switch", "AC97 Aux Capture Switch",
824 "Aux Playback Volume", "AC97 Aux Capture Volume",
825 "Mic Playback Switch", "AC97 Mic Capture Switch",
826 "Mic Playback Volume", "AC97 Mic Capture Volume",
827 "Mic Select", "AC97 Mic Select",
828 "Mic Boost (+20dB)", "AC97 Mic Boost (+20dB)",
829 NULL
830 };
831#if 1
95a98265 832 for (c = ca0106_remove_ctls; *c; c++)
1da177e4 833 remove_ctl(card, *c);
95a98265 834 for (c = ca0106_rename_ctls; *c; c += 2)
1da177e4
LT
835 rename_ctl(card, c[0], c[1]);
836#endif
837
fca7f388 838 ADD_CTLS(emu, snd_ca0106_volume_ctls);
ed144f3c 839 if (emu->details->i2c_adc == 1) {
fca7f388 840 ADD_CTLS(emu, snd_ca0106_volume_i2c_adc_ctls);
be0b7b01
JCD
841 if (emu->details->gpio_type == 1)
842 err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu));
843 else /* gpio_type == 2 */
844 err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_line_in_side_out, emu));
95a98265 845 if (err < 0)
ed144f3c
JCD
846 return err;
847 }
64e5310a
AO
848 if (emu->details->spi_dac) {
849 int i;
850 for (i = 0;; i++) {
851 struct snd_kcontrol_new ctl;
852 ctl = snd_ca0106_volume_spi_dac_ctl(emu->details, i);
853 if (!ctl.name)
854 break;
855 err = snd_ctl_add(card, snd_ctl_new1(&ctl, emu));
856 if (err < 0)
857 return err;
858 }
859 }
49c88b85
TI
860
861 /* Create virtual master controls */
862 vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
863 snd_ca0106_master_db_scale);
864 if (!vmaster)
865 return -ENOMEM;
601e1cc5
TI
866 err = snd_ctl_add(card, vmaster);
867 if (err < 0)
868 return err;
49c88b85
TI
869 add_slaves(card, vmaster, slave_vols);
870
6fef153a 871 if (emu->details->spi_dac) {
49c88b85
TI
872 vmaster = snd_ctl_make_virtual_master("Master Playback Switch",
873 NULL);
874 if (!vmaster)
875 return -ENOMEM;
601e1cc5
TI
876 err = snd_ctl_add(card, vmaster);
877 if (err < 0)
878 return err;
49c88b85
TI
879 add_slaves(card, vmaster, slave_sws);
880 }
eeaf100d
TI
881
882 strcpy(card->mixername, "CA0106");
1da177e4
LT
883 return 0;
884}
885
c7561cd8 886#ifdef CONFIG_PM_SLEEP
5da95273 887struct ca0106_vol_tbl {
5da95273 888 unsigned int channel_id;
8df0f707 889 unsigned int reg;
5da95273
TI
890};
891
892static struct ca0106_vol_tbl saved_volumes[NUM_SAVED_VOLUMES] = {
893 { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2 },
894 { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2 },
895 { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2 },
896 { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2 },
897 { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1 },
898 { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1 },
899 { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1 },
900 { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1 },
901 { 1, CAPTURE_CONTROL },
902};
903
904void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip)
905{
906 int i;
907
908 /* save volumes */
909 for (i = 0; i < NUM_SAVED_VOLUMES; i++)
910 chip->saved_vol[i] =
911 snd_ca0106_ptr_read(chip, saved_volumes[i].reg,
912 saved_volumes[i].channel_id);
913}
914
915void snd_ca0106_mixer_resume(struct snd_ca0106 *chip)
916{
917 int i;
918
919 for (i = 0; i < NUM_SAVED_VOLUMES; i++)
920 snd_ca0106_ptr_write(chip, saved_volumes[i].reg,
921 saved_volumes[i].channel_id,
922 chip->saved_vol[i]);
923
924 ca0106_spdif_enable(chip);
925 ca0106_set_capture_source(chip);
926 ca0106_set_i2c_capture_source(chip, chip->i2c_capture_source, 1);
927 for (i = 0; i < 4; i++)
928 ca0106_set_spdif_bits(chip, i);
929 if (chip->details->i2c_adc)
930 ca0106_set_capture_mic_line_in(chip);
931}
c7561cd8 932#endif /* CONFIG_PM_SLEEP */
This page took 0.797892 seconds and 5 git commands to generate.