ALSA: ca0106: Create a nice spot for mapping channels to dacs.
[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
LT
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 */
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>
6473d160 73#include <asm/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{
95a98265 188 static char *texts[6] = {
39596dc8 189 "IEC958 out", "i2s mixer out", "IEC958 in", "i2s in", "AC97 in", "SRC out"
95a98265 190 };
1da177e4
LT
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
e4a3d145
TI
201static int snd_ca0106_capture_source_get(struct snd_kcontrol *kcontrol,
202 struct snd_ctl_elem_value *ucontrol)
1da177e4 203{
e4a3d145 204 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
1da177e4
LT
205
206 ucontrol->value.enumerated.item[0] = emu->capture_source;
207 return 0;
208}
209
e4a3d145
TI
210static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
211 struct snd_ctl_elem_value *ucontrol)
1da177e4 212{
e4a3d145 213 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
1da177e4
LT
214 unsigned int val;
215 int change = 0;
1da177e4
LT
216
217 val = ucontrol->value.enumerated.item[0] ;
5fe619f9
TI
218 if (val >= 6)
219 return -EINVAL;
1da177e4
LT
220 change = (emu->capture_source != val);
221 if (change) {
222 emu->capture_source = val;
5da95273 223 ca0106_set_capture_source(emu);
1da177e4
LT
224 }
225 return change;
226}
227
6129daaa
JCD
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;
6129daaa 258 int change = 0;
6129daaa
JCD
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] ;
5fe619f9
TI
264 if (source_id >= 4)
265 return -EINVAL;
6129daaa
JCD
266 change = (emu->i2c_capture_source != source_id);
267 if (change) {
5da95273 268 ca0106_set_i2c_capture_source(emu, source_id, 0);
6129daaa
JCD
269 }
270 return change;
271}
272
be0b7b01
JCD
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
e4a3d145
TI
287static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol,
288 struct snd_ctl_elem_info *uinfo)
ed144f3c
JCD
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
e4a3d145
TI
301static int snd_ca0106_capture_mic_line_in_get(struct snd_kcontrol *kcontrol,
302 struct snd_ctl_elem_value *ucontrol)
ed144f3c 303{
e4a3d145 304 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
ed144f3c
JCD
305
306 ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in;
307 return 0;
308}
309
e4a3d145
TI
310static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
311 struct snd_ctl_elem_value *ucontrol)
ed144f3c 312{
e4a3d145 313 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
ed144f3c
JCD
314 unsigned int val;
315 int change = 0;
ed144f3c
JCD
316
317 val = ucontrol->value.enumerated.item[0] ;
5fe619f9
TI
318 if (val > 1)
319 return -EINVAL;
ed144f3c
JCD
320 change = (emu->capture_mic_line_in != val);
321 if (change) {
322 emu->capture_mic_line_in = val;
5da95273 323 ca0106_set_capture_mic_line_in(emu);
ed144f3c
JCD
324 }
325 return change;
326}
327
e4a3d145 328static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata =
ed144f3c
JCD
329{
330 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6129daaa 331 .name = "Shared Mic/Line in Capture Switch",
ed144f3c
JCD
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
be0b7b01
JCD
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
e4a3d145
TI
347static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol,
348 struct snd_ctl_elem_info *uinfo)
1da177e4
LT
349{
350 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
351 uinfo->count = 1;
352 return 0;
353}
354
3d475829
TI
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,
e4a3d145 364 struct snd_ctl_elem_value *ucontrol)
1da177e4 365{
e4a3d145 366 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
1da177e4
LT
367 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
368
3d475829
TI
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]);
1da177e4
LT
382 return 0;
383}
384
e4a3d145
TI
385static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol,
386 struct snd_ctl_elem_value *ucontrol)
1da177e4
LT
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
3d475829
TI
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,
e4a3d145 404 struct snd_ctl_elem_value *ucontrol)
1da177e4 405{
e4a3d145 406 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
1da177e4 407 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1da177e4
LT
408 unsigned int val;
409
3d475829
TI
410 val = encode_spdif_bits(ucontrol->value.iec958.status);
411 if (val != emu->spdif_bits[idx]) {
1da177e4 412 emu->spdif_bits[idx] = val;
3d475829
TI
413 /* FIXME: this isn't safe, but needed to keep the compatibility
414 * with older alsa-lib config
415 */
416 emu->spdif_str_bits[idx] = val;
5da95273 417 ca0106_set_spdif_bits(emu, idx);
3d475829 418 return 1;
1da177e4 419 }
3d475829
TI
420 return 0;
421}
422
423static int snd_ca0106_spdif_put_stream(struct snd_kcontrol *kcontrol,
424 struct snd_ctl_elem_value *ucontrol)
425{
426 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
427 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
428 unsigned int val;
429
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);
434 return 1;
435 }
436 return 0;
1da177e4
LT
437}
438
e4a3d145
TI
439static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol,
440 struct snd_ctl_elem_info *uinfo)
1da177e4
LT
441{
442 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
443 uinfo->count = 2;
444 uinfo->value.integer.min = 0;
445 uinfo->value.integer.max = 255;
446 return 0;
447}
448
e4a3d145
TI
449static int snd_ca0106_volume_get(struct snd_kcontrol *kcontrol,
450 struct snd_ctl_elem_value *ucontrol)
1da177e4 451{
e4a3d145 452 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
1da177e4 453 unsigned int value;
95a98265
TI
454 int channel_id, reg;
455
456 channel_id = (kcontrol->private_value >> 8) & 0xff;
457 reg = kcontrol->private_value & 0xff;
1da177e4
LT
458
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 */
462 return 0;
463}
464
e4a3d145
TI
465static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol,
466 struct snd_ctl_elem_value *ucontrol)
1da177e4 467{
e4a3d145 468 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
95a98265
TI
469 unsigned int oval, nval;
470 int channel_id, reg;
471
472 channel_id = (kcontrol->private_value >> 8) & 0xff;
473 reg = kcontrol->private_value & 0xff;
474
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]) );
480 if (oval == nval)
481 return 0;
482 snd_ca0106_ptr_write(emu, reg, channel_id, nval);
483 return 1;
484}
485
6129daaa
JCD
486static int snd_ca0106_i2c_volume_info(struct snd_kcontrol *kcontrol,
487 struct snd_ctl_elem_info *uinfo)
488{
489 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
490 uinfo->count = 2;
491 uinfo->value.integer.min = 0;
492 uinfo->value.integer.max = 255;
493 return 0;
494}
495
496static int snd_ca0106_i2c_volume_get(struct snd_kcontrol *kcontrol,
497 struct snd_ctl_elem_value *ucontrol)
498{
499 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
500 int source_id;
501
502 source_id = kcontrol->private_value;
503
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];
506 return 0;
507}
508
509static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol,
510 struct snd_ctl_elem_value *ucontrol)
511{
512 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
513 unsigned int ogain;
514 unsigned int ngain;
515 int source_id;
516 int change = 0;
517
518 source_id = kcontrol->private_value;
519 ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
520 ngain = ucontrol->value.integer.value[0];
521 if (ngain > 0xff)
5fe619f9 522 return -EINVAL;
6129daaa
JCD
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];
527 change = 1;
528 }
529 ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
530 ngain = ucontrol->value.integer.value[1];
531 if (ngain > 0xff)
5fe619f9 532 return -EINVAL;
6129daaa
JCD
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];
537 change = 1;
538 }
539
540 return change;
541}
542
b18cd538
TP
543#define spi_mute_info snd_ctl_boolean_mono_info
544
545static int spi_mute_get(struct snd_kcontrol *kcontrol,
546 struct snd_ctl_elem_value *ucontrol)
547{
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;
551
552 ucontrol->value.integer.value[0] = !(emu->spi_dac_reg[reg] & bit);
553 return 0;
554}
555
556static int spi_mute_put(struct snd_kcontrol *kcontrol,
557 struct snd_ctl_elem_value *ucontrol)
558{
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;
562 int ret;
563
564 ret = emu->spi_dac_reg[reg] & bit;
565 if (ucontrol->value.integer.value[0]) {
566 if (!ret) /* bit already cleared, do nothing */
567 return 0;
568 emu->spi_dac_reg[reg] &= ~bit;
569 } else {
570 if (ret) /* bit already set, do nothing */
571 return 0;
572 emu->spi_dac_reg[reg] |= bit;
573 }
574
575 ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]);
5fe619f9 576 return ret ? -EINVAL : 1;
b18cd538
TP
577}
578
95a98265
TI
579#define CA_VOLUME(xname,chid,reg) \
580{ \
581 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
302e9c5a
JK
582 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
583 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
6129daaa
JCD
584 .info = snd_ca0106_volume_info, \
585 .get = snd_ca0106_volume_get, \
586 .put = snd_ca0106_volume_put, \
7cf0a953 587 .tlv = { .p = snd_ca0106_db_scale1 }, \
95a98265
TI
588 .private_value = ((chid) << 8) | (reg) \
589}
590
e4a3d145 591static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
95a98265
TI
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),
600
39596dc8 601 CA_VOLUME("IEC958 Front Playback Volume",
95a98265 602 CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1),
39596dc8 603 CA_VOLUME("IEC958 Rear Playback Volume",
95a98265 604 CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1),
39596dc8 605 CA_VOLUME("IEC958 Center/LFE Playback Volume",
95a98265 606 CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1),
39596dc8 607 CA_VOLUME("IEC958 Unknown Playback Volume",
95a98265
TI
608 CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1),
609
610 CA_VOLUME("CAPTURE feedback Playback Volume",
611 1, CAPTURE_CONTROL),
612
613 {
614 .access = SNDRV_CTL_ELEM_ACCESS_READ,
615 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
616 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
617 .count = 4,
618 .info = snd_ca0106_spdif_info,
619 .get = snd_ca0106_spdif_get_mask
620 },
621 {
622 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
39596dc8 623 .name = "IEC958 Playback Switch",
95a98265
TI
624 .info = snd_ca0106_shared_spdif_info,
625 .get = snd_ca0106_shared_spdif_get,
626 .put = snd_ca0106_shared_spdif_put
627 },
628 {
629 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
e6327cf9 630 .name = "Digital Source Capture Enum",
95a98265
TI
631 .info = snd_ca0106_capture_source_info,
632 .get = snd_ca0106_capture_source_get,
633 .put = snd_ca0106_capture_source_put
634 },
6129daaa
JCD
635 {
636 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
e6327cf9 637 .name = "Analog Source Capture Enum",
6129daaa
JCD
638 .info = snd_ca0106_i2c_capture_source_info,
639 .get = snd_ca0106_i2c_capture_source_get,
640 .put = snd_ca0106_i2c_capture_source_put
641 },
95a98265
TI
642 {
643 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
644 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
645 .count = 4,
646 .info = snd_ca0106_spdif_info,
3d475829
TI
647 .get = snd_ca0106_spdif_get_default,
648 .put = snd_ca0106_spdif_put_default
649 },
650 {
651 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
652 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
653 .count = 4,
654 .info = snd_ca0106_spdif_info,
655 .get = snd_ca0106_spdif_get_stream,
656 .put = snd_ca0106_spdif_put_stream
95a98265 657 },
1da177e4
LT
658};
659
7c157069
JCD
660#define I2C_VOLUME(xname,chid) \
661{ \
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 \
670}
671
672static 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),
677};
678
b18cd538
TP
679#define SPI_SWITCH(xname,reg,bit) \
680{ \
681 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
682 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
683 .info = spi_mute_info, \
684 .get = spi_mute_get, \
685 .put = spi_mute_put, \
18b5d32f 686 .private_value = (reg<<SPI_REG_SHIFT) | (bit) \
b18cd538
TP
687}
688
689static struct snd_kcontrol_new snd_ca0106_volume_spi_dac_ctls[]
690__devinitdata = {
691 SPI_SWITCH("Analog Front Playback Switch",
692 SPI_DMUTE4_REG, SPI_DMUTE4_BIT),
693 SPI_SWITCH("Analog Rear Playback Switch",
694 SPI_DMUTE0_REG, SPI_DMUTE0_BIT),
695 SPI_SWITCH("Analog Center/LFE Playback Switch",
696 SPI_DMUTE2_REG, SPI_DMUTE2_BIT),
697 SPI_SWITCH("Analog Side Playback Switch",
698 SPI_DMUTE1_REG, SPI_DMUTE1_BIT),
699};
700
e4a3d145 701static int __devinit remove_ctl(struct snd_card *card, const char *name)
1da177e4 702{
e4a3d145 703 struct snd_ctl_elem_id id;
1da177e4
LT
704 memset(&id, 0, sizeof(id));
705 strcpy(id.name, name);
706 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
707 return snd_ctl_remove_id(card, &id);
708}
709
e4a3d145 710static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, const char *name)
1da177e4 711{
e4a3d145 712 struct snd_ctl_elem_id sid;
1da177e4
LT
713 memset(&sid, 0, sizeof(sid));
714 /* FIXME: strcpy is bad. */
715 strcpy(sid.name, name);
716 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
717 return snd_ctl_find_id(card, &sid);
718}
719
e4a3d145 720static int __devinit rename_ctl(struct snd_card *card, const char *src, const char *dst)
1da177e4 721{
e4a3d145 722 struct snd_kcontrol *kctl = ctl_find(card, src);
1da177e4
LT
723 if (kctl) {
724 strcpy(kctl->id.name, dst);
725 return 0;
726 }
727 return -ENOENT;
728}
729
fca7f388
TP
730#define ADD_CTLS(emu, ctls) \
731 do { \
bed515b0 732 int i, _err; \
fca7f388 733 for (i = 0; i < ARRAY_SIZE(ctls); i++) { \
bed515b0
HH
734 _err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \
735 if (_err < 0) \
736 return _err; \
fca7f388
TP
737 } \
738 } while (0)
739
49c88b85 740static __devinitdata
c4865679 741DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 25, 1);
49c88b85
TI
742
743static char *slave_vols[] __devinitdata = {
744 "Analog Front Playback Volume",
745 "Analog Rear Playback Volume",
746 "Analog Center/LFE Playback Volume",
747 "Analog Side Playback Volume",
748 "IEC958 Front Playback Volume",
749 "IEC958 Rear Playback Volume",
750 "IEC958 Center/LFE Playback Volume",
751 "IEC958 Unknown Playback Volume",
752 "CAPTURE feedback Playback Volume",
753 NULL
754};
755
756static char *slave_sws[] __devinitdata = {
757 "Analog Front Playback Switch",
758 "Analog Rear Playback Switch",
759 "Analog Center/LFE Playback Switch",
760 "Analog Side Playback Switch",
761 "IEC958 Playback Switch",
762 NULL
763};
764
765static void __devinit add_slaves(struct snd_card *card,
766 struct snd_kcontrol *master, char **list)
767{
768 for (; *list; list++) {
769 struct snd_kcontrol *slave = ctl_find(card, *list);
770 if (slave)
771 snd_ctl_add_slave(master, slave);
772 }
773}
774
e4a3d145 775int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
1da177e4 776{
fca7f388 777 int err;
e4a3d145 778 struct snd_card *card = emu->card;
1da177e4 779 char **c;
49c88b85 780 struct snd_kcontrol *vmaster;
1da177e4
LT
781 static char *ca0106_remove_ctls[] = {
782 "Master Mono Playback Switch",
783 "Master Mono Playback Volume",
784 "3D Control - Switch",
785 "3D Control Sigmatel - Depth",
786 "PCM Playback Switch",
787 "PCM Playback Volume",
788 "CD Playback Switch",
789 "CD Playback Volume",
790 "Phone Playback Switch",
791 "Phone Playback Volume",
792 "Video Playback Switch",
793 "Video Playback Volume",
d355c82a
JK
794 "Beep Playback Switch",
795 "Beep Playback Volume",
1da177e4
LT
796 "Mono Output Select",
797 "Capture Source",
798 "Capture Switch",
799 "Capture Volume",
800 "External Amplifier",
801 "Sigmatel 4-Speaker Stereo Playback Switch",
afe6d7e3 802 "Surround Phase Inversion Playback Switch",
1da177e4
LT
803 NULL
804 };
805 static char *ca0106_rename_ctls[] = {
806 "Master Playback Switch", "Capture Switch",
807 "Master Playback Volume", "Capture Volume",
808 "Line Playback Switch", "AC97 Line Capture Switch",
809 "Line Playback Volume", "AC97 Line Capture Volume",
810 "Aux Playback Switch", "AC97 Aux Capture Switch",
811 "Aux Playback Volume", "AC97 Aux Capture Volume",
812 "Mic Playback Switch", "AC97 Mic Capture Switch",
813 "Mic Playback Volume", "AC97 Mic Capture Volume",
814 "Mic Select", "AC97 Mic Select",
815 "Mic Boost (+20dB)", "AC97 Mic Boost (+20dB)",
816 NULL
817 };
818#if 1
95a98265 819 for (c = ca0106_remove_ctls; *c; c++)
1da177e4 820 remove_ctl(card, *c);
95a98265 821 for (c = ca0106_rename_ctls; *c; c += 2)
1da177e4
LT
822 rename_ctl(card, c[0], c[1]);
823#endif
824
fca7f388 825 ADD_CTLS(emu, snd_ca0106_volume_ctls);
ed144f3c 826 if (emu->details->i2c_adc == 1) {
fca7f388 827 ADD_CTLS(emu, snd_ca0106_volume_i2c_adc_ctls);
be0b7b01
JCD
828 if (emu->details->gpio_type == 1)
829 err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu));
830 else /* gpio_type == 2 */
831 err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_line_in_side_out, emu));
95a98265 832 if (err < 0)
ed144f3c
JCD
833 return err;
834 }
fca7f388
TP
835 if (emu->details->spi_dac == 1)
836 ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls);
49c88b85
TI
837
838 /* Create virtual master controls */
839 vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
840 snd_ca0106_master_db_scale);
841 if (!vmaster)
842 return -ENOMEM;
601e1cc5
TI
843 err = snd_ctl_add(card, vmaster);
844 if (err < 0)
845 return err;
49c88b85
TI
846 add_slaves(card, vmaster, slave_vols);
847
848 if (emu->details->spi_dac == 1) {
849 vmaster = snd_ctl_make_virtual_master("Master Playback Switch",
850 NULL);
851 if (!vmaster)
852 return -ENOMEM;
601e1cc5
TI
853 err = snd_ctl_add(card, vmaster);
854 if (err < 0)
855 return err;
49c88b85
TI
856 add_slaves(card, vmaster, slave_sws);
857 }
eeaf100d
TI
858
859 strcpy(card->mixername, "CA0106");
1da177e4
LT
860 return 0;
861}
862
5da95273
TI
863#ifdef CONFIG_PM
864struct ca0106_vol_tbl {
5da95273 865 unsigned int channel_id;
8df0f707 866 unsigned int reg;
5da95273
TI
867};
868
869static struct ca0106_vol_tbl saved_volumes[NUM_SAVED_VOLUMES] = {
870 { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2 },
871 { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2 },
872 { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2 },
873 { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2 },
874 { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1 },
875 { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1 },
876 { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1 },
877 { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1 },
878 { 1, CAPTURE_CONTROL },
879};
880
881void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip)
882{
883 int i;
884
885 /* save volumes */
886 for (i = 0; i < NUM_SAVED_VOLUMES; i++)
887 chip->saved_vol[i] =
888 snd_ca0106_ptr_read(chip, saved_volumes[i].reg,
889 saved_volumes[i].channel_id);
890}
891
892void snd_ca0106_mixer_resume(struct snd_ca0106 *chip)
893{
894 int i;
895
896 for (i = 0; i < NUM_SAVED_VOLUMES; i++)
897 snd_ca0106_ptr_write(chip, saved_volumes[i].reg,
898 saved_volumes[i].channel_id,
899 chip->saved_vol[i]);
900
901 ca0106_spdif_enable(chip);
902 ca0106_set_capture_source(chip);
903 ca0106_set_i2c_capture_source(chip, chip->i2c_capture_source, 1);
904 for (i = 0; i < 4; i++)
905 ca0106_set_spdif_bits(chip, i);
906 if (chip->details->i2c_adc)
907 ca0106_set_capture_mic_line_in(chip);
908}
909#endif /* CONFIG_PM */
This page took 0.549219 seconds and 5 git commands to generate.