Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/pci/ca0106/ca0106_mixer.c
10817 views
1
/*
2
* Copyright (c) 2004 James Courtier-Dutton <[email protected]>
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 initially based on code from ALSA's emu10k1x.c which is:
46
* Copyright (c) by Francisco Moraes <[email protected]>
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
77
static 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
101
static 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
110
static 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
130
static 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
148
static 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
*/
155
static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1);
156
static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1);
157
158
#define snd_ca0106_shared_spdif_info snd_ctl_boolean_mono_info
159
160
static 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
169
static 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
185
static 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
201
static 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
210
static 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
228
static 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
244
static 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
253
static 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
273
static 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
287
static 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
301
static 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
310
static 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
328
static 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
337
static 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
347
static 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
355
static 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
363
static 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
374
static 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
385
static 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
395
static 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
403
static 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
/* 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;
417
ca0106_set_spdif_bits(emu, idx);
418
return 1;
419
}
420
return 0;
421
}
422
423
static 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;
437
}
438
439
static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol,
440
struct snd_ctl_elem_info *uinfo)
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
449
static int snd_ca0106_volume_get(struct snd_kcontrol *kcontrol,
450
struct snd_ctl_elem_value *ucontrol)
451
{
452
struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
453
unsigned int value;
454
int channel_id, reg;
455
456
channel_id = (kcontrol->private_value >> 8) & 0xff;
457
reg = kcontrol->private_value & 0xff;
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
465
static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol,
466
struct snd_ctl_elem_value *ucontrol)
467
{
468
struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
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
486
static 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
496
static 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
509
static 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)
522
return -EINVAL;
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)
532
return -EINVAL;
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
543
#define spi_mute_info snd_ctl_boolean_mono_info
544
545
static 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
556
static 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]);
576
return ret ? -EINVAL : 1;
577
}
578
579
#define CA_VOLUME(xname,chid,reg) \
580
{ \
581
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
582
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
583
SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
584
.info = snd_ca0106_volume_info, \
585
.get = snd_ca0106_volume_get, \
586
.put = snd_ca0106_volume_put, \
587
.tlv = { .p = snd_ca0106_db_scale1 }, \
588
.private_value = ((chid) << 8) | (reg) \
589
}
590
591
static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
592
CA_VOLUME("Analog Front Playback Volume",
593
CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2),
594
CA_VOLUME("Analog Rear Playback Volume",
595
CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2),
596
CA_VOLUME("Analog Center/LFE Playback Volume",
597
CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2),
598
CA_VOLUME("Analog Side Playback Volume",
599
CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2),
600
601
CA_VOLUME("IEC958 Front Playback Volume",
602
CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1),
603
CA_VOLUME("IEC958 Rear Playback Volume",
604
CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1),
605
CA_VOLUME("IEC958 Center/LFE Playback Volume",
606
CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1),
607
CA_VOLUME("IEC958 Unknown Playback Volume",
608
CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1),
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,
623
.name = "IEC958 Playback Switch",
624
.info = snd_ca0106_shared_spdif_info,
625
.get = snd_ca0106_shared_spdif_get,
626
.put = snd_ca0106_shared_spdif_put
627
},
628
{
629
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
630
.name = "Digital Source Capture Enum",
631
.info = snd_ca0106_capture_source_info,
632
.get = snd_ca0106_capture_source_get,
633
.put = snd_ca0106_capture_source_put
634
},
635
{
636
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
637
.name = "Analog Source Capture Enum",
638
.info = snd_ca0106_i2c_capture_source_info,
639
.get = snd_ca0106_i2c_capture_source_get,
640
.put = snd_ca0106_i2c_capture_source_put
641
},
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,
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
657
},
658
};
659
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
672
static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata = {
673
I2C_VOLUME("Phone Capture Volume", 0),
674
I2C_VOLUME("Mic Capture Volume", 1),
675
I2C_VOLUME("Line in Capture Volume", 2),
676
I2C_VOLUME("Aux Capture Volume", 3),
677
};
678
679
static const int spi_dmute_reg[] = {
680
SPI_DMUTE0_REG,
681
SPI_DMUTE1_REG,
682
SPI_DMUTE2_REG,
683
0,
684
SPI_DMUTE4_REG,
685
};
686
static const int spi_dmute_bit[] = {
687
SPI_DMUTE0_BIT,
688
SPI_DMUTE1_BIT,
689
SPI_DMUTE2_BIT,
690
0,
691
SPI_DMUTE4_BIT,
692
};
693
694
static struct snd_kcontrol_new __devinit
695
snd_ca0106_volume_spi_dac_ctl(struct snd_ca0106_details *details,
696
int channel_id)
697
{
698
struct snd_kcontrol_new spi_switch = {0};
699
int reg, bit;
700
int dac_id;
701
702
spi_switch.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
703
spi_switch.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
704
spi_switch.info = spi_mute_info;
705
spi_switch.get = spi_mute_get;
706
spi_switch.put = spi_mute_put;
707
708
switch (channel_id) {
709
case PCM_FRONT_CHANNEL:
710
spi_switch.name = "Analog Front Playback Switch";
711
dac_id = (details->spi_dac & 0xf000) >> (4 * 3);
712
break;
713
case PCM_REAR_CHANNEL:
714
spi_switch.name = "Analog Rear Playback Switch";
715
dac_id = (details->spi_dac & 0x0f00) >> (4 * 2);
716
break;
717
case PCM_CENTER_LFE_CHANNEL:
718
spi_switch.name = "Analog Center/LFE Playback Switch";
719
dac_id = (details->spi_dac & 0x00f0) >> (4 * 1);
720
break;
721
case PCM_UNKNOWN_CHANNEL:
722
spi_switch.name = "Analog Side Playback Switch";
723
dac_id = (details->spi_dac & 0x000f) >> (4 * 0);
724
break;
725
default:
726
/* Unused channel */
727
spi_switch.name = NULL;
728
dac_id = 0;
729
}
730
reg = spi_dmute_reg[dac_id];
731
bit = spi_dmute_bit[dac_id];
732
733
spi_switch.private_value = (reg << SPI_REG_SHIFT) | bit;
734
735
return spi_switch;
736
}
737
738
static int __devinit remove_ctl(struct snd_card *card, const char *name)
739
{
740
struct snd_ctl_elem_id id;
741
memset(&id, 0, sizeof(id));
742
strcpy(id.name, name);
743
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
744
return snd_ctl_remove_id(card, &id);
745
}
746
747
static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, const char *name)
748
{
749
struct snd_ctl_elem_id sid;
750
memset(&sid, 0, sizeof(sid));
751
/* FIXME: strcpy is bad. */
752
strcpy(sid.name, name);
753
sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
754
return snd_ctl_find_id(card, &sid);
755
}
756
757
static int __devinit rename_ctl(struct snd_card *card, const char *src, const char *dst)
758
{
759
struct snd_kcontrol *kctl = ctl_find(card, src);
760
if (kctl) {
761
strcpy(kctl->id.name, dst);
762
return 0;
763
}
764
return -ENOENT;
765
}
766
767
#define ADD_CTLS(emu, ctls) \
768
do { \
769
int i, _err; \
770
for (i = 0; i < ARRAY_SIZE(ctls); i++) { \
771
_err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \
772
if (_err < 0) \
773
return _err; \
774
} \
775
} while (0)
776
777
static __devinitdata
778
DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 25, 1);
779
780
static char *slave_vols[] __devinitdata = {
781
"Analog Front Playback Volume",
782
"Analog Rear Playback Volume",
783
"Analog Center/LFE Playback Volume",
784
"Analog Side Playback Volume",
785
"IEC958 Front Playback Volume",
786
"IEC958 Rear Playback Volume",
787
"IEC958 Center/LFE Playback Volume",
788
"IEC958 Unknown Playback Volume",
789
"CAPTURE feedback Playback Volume",
790
NULL
791
};
792
793
static char *slave_sws[] __devinitdata = {
794
"Analog Front Playback Switch",
795
"Analog Rear Playback Switch",
796
"Analog Center/LFE Playback Switch",
797
"Analog Side Playback Switch",
798
"IEC958 Playback Switch",
799
NULL
800
};
801
802
static void __devinit add_slaves(struct snd_card *card,
803
struct snd_kcontrol *master, char **list)
804
{
805
for (; *list; list++) {
806
struct snd_kcontrol *slave = ctl_find(card, *list);
807
if (slave)
808
snd_ctl_add_slave(master, slave);
809
}
810
}
811
812
int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
813
{
814
int err;
815
struct snd_card *card = emu->card;
816
char **c;
817
struct snd_kcontrol *vmaster;
818
static char *ca0106_remove_ctls[] = {
819
"Master Mono Playback Switch",
820
"Master Mono Playback Volume",
821
"3D Control - Switch",
822
"3D Control Sigmatel - Depth",
823
"PCM Playback Switch",
824
"PCM Playback Volume",
825
"CD Playback Switch",
826
"CD Playback Volume",
827
"Phone Playback Switch",
828
"Phone Playback Volume",
829
"Video Playback Switch",
830
"Video Playback Volume",
831
"Beep Playback Switch",
832
"Beep Playback Volume",
833
"Mono Output Select",
834
"Capture Source",
835
"Capture Switch",
836
"Capture Volume",
837
"External Amplifier",
838
"Sigmatel 4-Speaker Stereo Playback Switch",
839
"Surround Phase Inversion Playback Switch",
840
NULL
841
};
842
static char *ca0106_rename_ctls[] = {
843
"Master Playback Switch", "Capture Switch",
844
"Master Playback Volume", "Capture Volume",
845
"Line Playback Switch", "AC97 Line Capture Switch",
846
"Line Playback Volume", "AC97 Line Capture Volume",
847
"Aux Playback Switch", "AC97 Aux Capture Switch",
848
"Aux Playback Volume", "AC97 Aux Capture Volume",
849
"Mic Playback Switch", "AC97 Mic Capture Switch",
850
"Mic Playback Volume", "AC97 Mic Capture Volume",
851
"Mic Select", "AC97 Mic Select",
852
"Mic Boost (+20dB)", "AC97 Mic Boost (+20dB)",
853
NULL
854
};
855
#if 1
856
for (c = ca0106_remove_ctls; *c; c++)
857
remove_ctl(card, *c);
858
for (c = ca0106_rename_ctls; *c; c += 2)
859
rename_ctl(card, c[0], c[1]);
860
#endif
861
862
ADD_CTLS(emu, snd_ca0106_volume_ctls);
863
if (emu->details->i2c_adc == 1) {
864
ADD_CTLS(emu, snd_ca0106_volume_i2c_adc_ctls);
865
if (emu->details->gpio_type == 1)
866
err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu));
867
else /* gpio_type == 2 */
868
err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_line_in_side_out, emu));
869
if (err < 0)
870
return err;
871
}
872
if (emu->details->spi_dac) {
873
int i;
874
for (i = 0;; i++) {
875
struct snd_kcontrol_new ctl;
876
ctl = snd_ca0106_volume_spi_dac_ctl(emu->details, i);
877
if (!ctl.name)
878
break;
879
err = snd_ctl_add(card, snd_ctl_new1(&ctl, emu));
880
if (err < 0)
881
return err;
882
}
883
}
884
885
/* Create virtual master controls */
886
vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
887
snd_ca0106_master_db_scale);
888
if (!vmaster)
889
return -ENOMEM;
890
err = snd_ctl_add(card, vmaster);
891
if (err < 0)
892
return err;
893
add_slaves(card, vmaster, slave_vols);
894
895
if (emu->details->spi_dac) {
896
vmaster = snd_ctl_make_virtual_master("Master Playback Switch",
897
NULL);
898
if (!vmaster)
899
return -ENOMEM;
900
err = snd_ctl_add(card, vmaster);
901
if (err < 0)
902
return err;
903
add_slaves(card, vmaster, slave_sws);
904
}
905
906
strcpy(card->mixername, "CA0106");
907
return 0;
908
}
909
910
#ifdef CONFIG_PM
911
struct ca0106_vol_tbl {
912
unsigned int channel_id;
913
unsigned int reg;
914
};
915
916
static struct ca0106_vol_tbl saved_volumes[NUM_SAVED_VOLUMES] = {
917
{ CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2 },
918
{ CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2 },
919
{ CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2 },
920
{ CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2 },
921
{ CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1 },
922
{ CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1 },
923
{ CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1 },
924
{ CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1 },
925
{ 1, CAPTURE_CONTROL },
926
};
927
928
void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip)
929
{
930
int i;
931
932
/* save volumes */
933
for (i = 0; i < NUM_SAVED_VOLUMES; i++)
934
chip->saved_vol[i] =
935
snd_ca0106_ptr_read(chip, saved_volumes[i].reg,
936
saved_volumes[i].channel_id);
937
}
938
939
void snd_ca0106_mixer_resume(struct snd_ca0106 *chip)
940
{
941
int i;
942
943
for (i = 0; i < NUM_SAVED_VOLUMES; i++)
944
snd_ca0106_ptr_write(chip, saved_volumes[i].reg,
945
saved_volumes[i].channel_id,
946
chip->saved_vol[i]);
947
948
ca0106_spdif_enable(chip);
949
ca0106_set_capture_source(chip);
950
ca0106_set_i2c_capture_source(chip, chip->i2c_capture_source, 1);
951
for (i = 0; i < 4; i++)
952
ca0106_set_spdif_bits(chip, i);
953
if (chip->details->i2c_adc)
954
ca0106_set_capture_mic_line_in(chip);
955
}
956
#endif /* CONFIG_PM */
957
958