OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [sound/] [pci/] [ca0106/] [ca0106_mixer.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 *  Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
3
 *  Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
4
 *  Version: 0.0.18
5
 *
6
 *  FEATURES currently supported:
7
 *    See ca0106_main.c for features.
8
 *
9
 *  Changelog:
10
 *    Support interrupts per period.
11
 *    Removed noise from Center/LFE channel when in Analog mode.
12
 *    Rename and remove mixer controls.
13
 *  0.0.6
14
 *    Use separate card based DMA buffer for periods table list.
15
 *  0.0.7
16
 *    Change remove and rename ctrls into lists.
17
 *  0.0.8
18
 *    Try to fix capture sources.
19
 *  0.0.9
20
 *    Fix AC3 output.
21
 *    Enable S32_LE format support.
22
 *  0.0.10
23
 *    Enable playback 48000 and 96000 rates. (Rates other that these do not work, even with "plug:front".)
24
 *  0.0.11
25
 *    Add Model name recognition.
26
 *  0.0.12
27
 *    Correct interrupt timing. interrupt at end of period, instead of in the middle of a playback period.
28
 *    Remove redundent "voice" handling.
29
 *  0.0.13
30
 *    Single trigger call for multi channels.
31
 *  0.0.14
32
 *    Set limits based on what the sound card hardware can do.
33
 *    playback periods_min=2, periods_max=8
34
 *    capture hw constraints require period_size = n * 64 bytes.
35
 *    playback hw constraints require period_size = n * 64 bytes.
36
 *  0.0.15
37
 *    Separated ca0106.c into separate functional .c files.
38
 *  0.0.16
39
 *    Modified Copyright message.
40
 *  0.0.17
41
 *    Implement Mic and Line in Capture.
42
 *  0.0.18
43
 *    Add support for mute control on SB Live 24bit (cards w/ SPI DAC)
44
 *
45
 *  This code was initally based on code from ALSA's emu10k1x.c which is:
46
 *  Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
47
 *
48
 *   This program is free software; you can redistribute it and/or modify
49
 *   it under the terms of the GNU General Public License as published by
50
 *   the Free Software Foundation; either version 2 of the License, or
51
 *   (at your option) any later version.
52
 *
53
 *   This program is distributed in the hope that it will be useful,
54
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
55
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
56
 *   GNU General Public License for more details.
57
 *
58
 *   You should have received a copy of the GNU General Public License
59
 *   along with this program; if not, write to the Free Software
60
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
61
 *
62
 */
63
#include <sound/driver.h>
64
#include <linux/delay.h>
65
#include <linux/init.h>
66
#include <linux/interrupt.h>
67
#include <linux/slab.h>
68
#include <linux/moduleparam.h>
69
#include <sound/core.h>
70
#include <sound/initval.h>
71
#include <sound/pcm.h>
72
#include <sound/ac97_codec.h>
73
#include <sound/info.h>
74
#include <sound/tlv.h>
75
#include <asm/io.h>
76
 
77
#include "ca0106.h"
78
 
79
static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1);
80
static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1);
81
 
82
#define snd_ca0106_shared_spdif_info    snd_ctl_boolean_mono_info
83
 
84
static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol,
85
                                        struct snd_ctl_elem_value *ucontrol)
86
{
87
        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
88
 
89
        ucontrol->value.integer.value[0] = emu->spdif_enable;
90
        return 0;
91
}
92
 
93
static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol,
94
                                        struct snd_ctl_elem_value *ucontrol)
95
{
96
        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
97
        unsigned int val;
98
        int change = 0;
99
        u32 mask;
100
 
101
        val = !!ucontrol->value.integer.value[0];
102
        change = (emu->spdif_enable != val);
103
        if (change) {
104
                emu->spdif_enable = val;
105
                if (val) {
106
                        /* Digital */
107
                        snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
108
                        snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000);
109
                        snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0,
110
                                snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000);
111
                        mask = inl(emu->port + GPIO) & ~0x101;
112
                        outl(mask, emu->port + GPIO);
113
 
114
                } else {
115
                        /* Analog */
116
                        snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
117
                        snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000);
118
                        snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0,
119
                                snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000);
120
                        mask = inl(emu->port + GPIO) | 0x101;
121
                        outl(mask, emu->port + GPIO);
122
                }
123
        }
124
        return change;
125
}
126
 
127
static int snd_ca0106_capture_source_info(struct snd_kcontrol *kcontrol,
128
                                          struct snd_ctl_elem_info *uinfo)
129
{
130
        static char *texts[6] = {
131
                "IEC958 out", "i2s mixer out", "IEC958 in", "i2s in", "AC97 in", "SRC out"
132
        };
133
 
134
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
135
        uinfo->count = 1;
136
        uinfo->value.enumerated.items = 6;
137
        if (uinfo->value.enumerated.item > 5)
138
                uinfo->value.enumerated.item = 5;
139
        strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
140
        return 0;
141
}
142
 
143
static int snd_ca0106_capture_source_get(struct snd_kcontrol *kcontrol,
144
                                        struct snd_ctl_elem_value *ucontrol)
145
{
146
        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
147
 
148
        ucontrol->value.enumerated.item[0] = emu->capture_source;
149
        return 0;
150
}
151
 
152
static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
153
                                        struct snd_ctl_elem_value *ucontrol)
154
{
155
        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
156
        unsigned int val;
157
        int change = 0;
158
        u32 mask;
159
        u32 source;
160
 
161
        val = ucontrol->value.enumerated.item[0] ;
162
        if (val >= 6)
163
                return -EINVAL;
164
        change = (emu->capture_source != val);
165
        if (change) {
166
                emu->capture_source = val;
167
                source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
168
                mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff;
169
                snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask);
170
        }
171
        return change;
172
}
173
 
174
static int snd_ca0106_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
175
                                          struct snd_ctl_elem_info *uinfo)
176
{
177
        static char *texts[6] = {
178
                "Phone", "Mic", "Line in", "Aux"
179
        };
180
 
181
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
182
        uinfo->count = 1;
183
        uinfo->value.enumerated.items = 4;
184
        if (uinfo->value.enumerated.item > 3)
185
                uinfo->value.enumerated.item = 3;
186
        strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
187
        return 0;
188
}
189
 
190
static int snd_ca0106_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
191
                                        struct snd_ctl_elem_value *ucontrol)
192
{
193
        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
194
 
195
        ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
196
        return 0;
197
}
198
 
199
static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
200
                                        struct snd_ctl_elem_value *ucontrol)
201
{
202
        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
203
        unsigned int source_id;
204
        unsigned int ngain, ogain;
205
        int change = 0;
206
        u32 source;
207
        /* If the capture source has changed,
208
         * update the capture volume from the cached value
209
         * for the particular source.
210
         */
211
        source_id = ucontrol->value.enumerated.item[0] ;
212
        if (source_id >= 4)
213
                return -EINVAL;
214
        change = (emu->i2c_capture_source != source_id);
215
        if (change) {
216
                snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
217
                ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
218
                ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
219
                if (ngain != ogain)
220
                        snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
221
                ngain = emu->i2c_capture_volume[source_id][1]; /* Left */
222
                ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Left */
223
                if (ngain != ogain)
224
                        snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
225
                source = 1 << source_id;
226
                snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */
227
                emu->i2c_capture_source = source_id;
228
        }
229
        return change;
230
}
231
 
232
static int snd_ca0106_capture_line_in_side_out_info(struct snd_kcontrol *kcontrol,
233
                                               struct snd_ctl_elem_info *uinfo)
234
{
235
        static char *texts[2] = { "Side out", "Line in" };
236
 
237
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
238
        uinfo->count = 1;
239
        uinfo->value.enumerated.items = 2;
240
        if (uinfo->value.enumerated.item > 1)
241
                uinfo->value.enumerated.item = 1;
242
        strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
243
        return 0;
244
}
245
 
246
static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol,
247
                                               struct snd_ctl_elem_info *uinfo)
248
{
249
        static char *texts[2] = { "Line in", "Mic in" };
250
 
251
        uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
252
        uinfo->count = 1;
253
        uinfo->value.enumerated.items = 2;
254
        if (uinfo->value.enumerated.item > 1)
255
                uinfo->value.enumerated.item = 1;
256
        strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
257
        return 0;
258
}
259
 
260
static int snd_ca0106_capture_mic_line_in_get(struct snd_kcontrol *kcontrol,
261
                                        struct snd_ctl_elem_value *ucontrol)
262
{
263
        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
264
 
265
        ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in;
266
        return 0;
267
}
268
 
269
static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
270
                                        struct snd_ctl_elem_value *ucontrol)
271
{
272
        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
273
        unsigned int val;
274
        int change = 0;
275
        u32 tmp;
276
 
277
        val = ucontrol->value.enumerated.item[0] ;
278
        if (val > 1)
279
                return -EINVAL;
280
        change = (emu->capture_mic_line_in != val);
281
        if (change) {
282
                emu->capture_mic_line_in = val;
283
                if (val) {
284
                        //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
285
                        tmp = inl(emu->port+GPIO) & ~0x400;
286
                        tmp = tmp | 0x400;
287
                        outl(tmp, emu->port+GPIO);
288
                        //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC);
289
                } else {
290
                        //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
291
                        tmp = inl(emu->port+GPIO) & ~0x400;
292
                        outl(tmp, emu->port+GPIO);
293
                        //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN);
294
                }
295
        }
296
        return change;
297
}
298
 
299
static struct snd_kcontrol_new snd_ca0106_capture_mic_line_in __devinitdata =
300
{
301
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
302
        .name =         "Shared Mic/Line in Capture Switch",
303
        .info =         snd_ca0106_capture_mic_line_in_info,
304
        .get =          snd_ca0106_capture_mic_line_in_get,
305
        .put =          snd_ca0106_capture_mic_line_in_put
306
};
307
 
308
static struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out __devinitdata =
309
{
310
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
311
        .name =         "Shared Line in/Side out Capture Switch",
312
        .info =         snd_ca0106_capture_line_in_side_out_info,
313
        .get =          snd_ca0106_capture_mic_line_in_get,
314
        .put =          snd_ca0106_capture_mic_line_in_put
315
};
316
 
317
 
318
static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol,
319
                                 struct snd_ctl_elem_info *uinfo)
320
{
321
        uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
322
        uinfo->count = 1;
323
        return 0;
324
}
325
 
326
static int snd_ca0106_spdif_get(struct snd_kcontrol *kcontrol,
327
                                 struct snd_ctl_elem_value *ucontrol)
328
{
329
        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
330
        unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
331
 
332
        ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff;
333
        ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff;
334
        ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff;
335
        ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff;
336
        return 0;
337
}
338
 
339
static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol,
340
                                      struct snd_ctl_elem_value *ucontrol)
341
{
342
        ucontrol->value.iec958.status[0] = 0xff;
343
        ucontrol->value.iec958.status[1] = 0xff;
344
        ucontrol->value.iec958.status[2] = 0xff;
345
        ucontrol->value.iec958.status[3] = 0xff;
346
        return 0;
347
}
348
 
349
static int snd_ca0106_spdif_put(struct snd_kcontrol *kcontrol,
350
                                 struct snd_ctl_elem_value *ucontrol)
351
{
352
        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
353
        unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
354
        int change;
355
        unsigned int val;
356
 
357
        val = (ucontrol->value.iec958.status[0] << 0) |
358
              (ucontrol->value.iec958.status[1] << 8) |
359
              (ucontrol->value.iec958.status[2] << 16) |
360
              (ucontrol->value.iec958.status[3] << 24);
361
        change = val != emu->spdif_bits[idx];
362
        if (change) {
363
                snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, val);
364
                emu->spdif_bits[idx] = val;
365
        }
366
        return change;
367
}
368
 
369
static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol,
370
                                  struct snd_ctl_elem_info *uinfo)
371
{
372
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
373
        uinfo->count = 2;
374
        uinfo->value.integer.min = 0;
375
        uinfo->value.integer.max = 255;
376
        return 0;
377
}
378
 
379
static int snd_ca0106_volume_get(struct snd_kcontrol *kcontrol,
380
                                 struct snd_ctl_elem_value *ucontrol)
381
{
382
        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
383
        unsigned int value;
384
        int channel_id, reg;
385
 
386
        channel_id = (kcontrol->private_value >> 8) & 0xff;
387
        reg = kcontrol->private_value & 0xff;
388
 
389
        value = snd_ca0106_ptr_read(emu, reg, channel_id);
390
        ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */
391
        ucontrol->value.integer.value[1] = 0xff - ((value >> 16) & 0xff); /* Right */
392
        return 0;
393
}
394
 
395
static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol,
396
                                 struct snd_ctl_elem_value *ucontrol)
397
{
398
        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
399
        unsigned int oval, nval;
400
        int channel_id, reg;
401
 
402
        channel_id = (kcontrol->private_value >> 8) & 0xff;
403
        reg = kcontrol->private_value & 0xff;
404
 
405
        oval = snd_ca0106_ptr_read(emu, reg, channel_id);
406
        nval = ((0xff - ucontrol->value.integer.value[0]) << 24) |
407
                ((0xff - ucontrol->value.integer.value[1]) << 16);
408
        nval |= ((0xff - ucontrol->value.integer.value[0]) << 8) |
409
                ((0xff - ucontrol->value.integer.value[1]) );
410
        if (oval == nval)
411
                return 0;
412
        snd_ca0106_ptr_write(emu, reg, channel_id, nval);
413
        return 1;
414
}
415
 
416
static int snd_ca0106_i2c_volume_info(struct snd_kcontrol *kcontrol,
417
                                  struct snd_ctl_elem_info *uinfo)
418
{
419
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
420
        uinfo->count = 2;
421
        uinfo->value.integer.min = 0;
422
        uinfo->value.integer.max = 255;
423
        return 0;
424
}
425
 
426
static int snd_ca0106_i2c_volume_get(struct snd_kcontrol *kcontrol,
427
                                 struct snd_ctl_elem_value *ucontrol)
428
{
429
        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
430
        int source_id;
431
 
432
        source_id = kcontrol->private_value;
433
 
434
        ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
435
        ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
436
        return 0;
437
}
438
 
439
static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol,
440
                                 struct snd_ctl_elem_value *ucontrol)
441
{
442
        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
443
        unsigned int ogain;
444
        unsigned int ngain;
445
        int source_id;
446
        int change = 0;
447
 
448
        source_id = kcontrol->private_value;
449
        ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
450
        ngain = ucontrol->value.integer.value[0];
451
        if (ngain > 0xff)
452
                return -EINVAL;
453
        if (ogain != ngain) {
454
                if (emu->i2c_capture_source == source_id)
455
                        snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
456
                emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0];
457
                change = 1;
458
        }
459
        ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
460
        ngain = ucontrol->value.integer.value[1];
461
        if (ngain > 0xff)
462
                return -EINVAL;
463
        if (ogain != ngain) {
464
                if (emu->i2c_capture_source == source_id)
465
                        snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
466
                emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1];
467
                change = 1;
468
        }
469
 
470
        return change;
471
}
472
 
473
#define spi_mute_info   snd_ctl_boolean_mono_info
474
 
475
static int spi_mute_get(struct snd_kcontrol *kcontrol,
476
                        struct snd_ctl_elem_value *ucontrol)
477
{
478
        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
479
        unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT;
480
        unsigned int bit = kcontrol->private_value & SPI_REG_MASK;
481
 
482
        ucontrol->value.integer.value[0] = !(emu->spi_dac_reg[reg] & bit);
483
        return 0;
484
}
485
 
486
static int spi_mute_put(struct snd_kcontrol *kcontrol,
487
                        struct snd_ctl_elem_value *ucontrol)
488
{
489
        struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
490
        unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT;
491
        unsigned int bit = kcontrol->private_value & SPI_REG_MASK;
492
        int ret;
493
 
494
        ret = emu->spi_dac_reg[reg] & bit;
495
        if (ucontrol->value.integer.value[0]) {
496
                if (!ret)       /* bit already cleared, do nothing */
497
                        return 0;
498
                emu->spi_dac_reg[reg] &= ~bit;
499
        } else {
500
                if (ret)        /* bit already set, do nothing */
501
                        return 0;
502
                emu->spi_dac_reg[reg] |= bit;
503
        }
504
 
505
        ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]);
506
        return ret ? -EINVAL : 1;
507
}
508
 
509
#define CA_VOLUME(xname,chid,reg) \
510
{                                                               \
511
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,     \
512
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |             \
513
                  SNDRV_CTL_ELEM_ACCESS_TLV_READ,               \
514
        .info =  snd_ca0106_volume_info,                        \
515
        .get =   snd_ca0106_volume_get,                         \
516
        .put =   snd_ca0106_volume_put,                         \
517
        .tlv = { .p = snd_ca0106_db_scale1 },                   \
518
        .private_value = ((chid) << 8) | (reg)                  \
519
}
520
 
521
static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
522
        CA_VOLUME("Analog Front Playback Volume",
523
                  CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2),
524
        CA_VOLUME("Analog Rear Playback Volume",
525
                  CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2),
526
        CA_VOLUME("Analog Center/LFE Playback Volume",
527
                  CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2),
528
        CA_VOLUME("Analog Side Playback Volume",
529
                  CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2),
530
 
531
        CA_VOLUME("IEC958 Front Playback Volume",
532
                  CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1),
533
        CA_VOLUME("IEC958 Rear Playback Volume",
534
                  CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1),
535
        CA_VOLUME("IEC958 Center/LFE Playback Volume",
536
                  CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1),
537
        CA_VOLUME("IEC958 Unknown Playback Volume",
538
                  CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1),
539
 
540
        CA_VOLUME("CAPTURE feedback Playback Volume",
541
                  1, CAPTURE_CONTROL),
542
 
543
        {
544
                .access =       SNDRV_CTL_ELEM_ACCESS_READ,
545
                .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
546
                .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
547
                .count =        4,
548
                .info =         snd_ca0106_spdif_info,
549
                .get =          snd_ca0106_spdif_get_mask
550
        },
551
        {
552
                .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
553
                .name =         "IEC958 Playback Switch",
554
                .info =         snd_ca0106_shared_spdif_info,
555
                .get =          snd_ca0106_shared_spdif_get,
556
                .put =          snd_ca0106_shared_spdif_put
557
        },
558
        {
559
                .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
560
                .name =         "Digital Source Capture Enum",
561
                .info =         snd_ca0106_capture_source_info,
562
                .get =          snd_ca0106_capture_source_get,
563
                .put =          snd_ca0106_capture_source_put
564
        },
565
        {
566
                .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
567
                .name =         "Analog Source Capture Enum",
568
                .info =         snd_ca0106_i2c_capture_source_info,
569
                .get =          snd_ca0106_i2c_capture_source_get,
570
                .put =          snd_ca0106_i2c_capture_source_put
571
        },
572
        {
573
                .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
574
                .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
575
                .count =        4,
576
                .info =         snd_ca0106_spdif_info,
577
                .get =          snd_ca0106_spdif_get,
578
                .put =          snd_ca0106_spdif_put
579
        },
580
};
581
 
582
#define I2C_VOLUME(xname,chid) \
583
{                                                               \
584
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,     \
585
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |             \
586
                  SNDRV_CTL_ELEM_ACCESS_TLV_READ,               \
587
        .info =  snd_ca0106_i2c_volume_info,                    \
588
        .get =   snd_ca0106_i2c_volume_get,                     \
589
        .put =   snd_ca0106_i2c_volume_put,                     \
590
        .tlv = { .p = snd_ca0106_db_scale2 },                   \
591
        .private_value = chid                                   \
592
}
593
 
594
static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata = {
595
        I2C_VOLUME("Phone Capture Volume", 0),
596
        I2C_VOLUME("Mic Capture Volume", 1),
597
        I2C_VOLUME("Line in Capture Volume", 2),
598
        I2C_VOLUME("Aux Capture Volume", 3),
599
};
600
 
601
#define SPI_SWITCH(xname,reg,bit) \
602
{                                                               \
603
        .iface  = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,    \
604
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,              \
605
        .info   = spi_mute_info,                                \
606
        .get    = spi_mute_get,                                 \
607
        .put    = spi_mute_put,                                 \
608
        .private_value = (reg<<SPI_REG_SHIFT) | (bit)           \
609
}
610
 
611
static struct snd_kcontrol_new snd_ca0106_volume_spi_dac_ctls[]
612
__devinitdata = {
613
        SPI_SWITCH("Analog Front Playback Switch",
614
                   SPI_DMUTE4_REG, SPI_DMUTE4_BIT),
615
        SPI_SWITCH("Analog Rear Playback Switch",
616
                   SPI_DMUTE0_REG, SPI_DMUTE0_BIT),
617
        SPI_SWITCH("Analog Center/LFE Playback Switch",
618
                   SPI_DMUTE2_REG, SPI_DMUTE2_BIT),
619
        SPI_SWITCH("Analog Side Playback Switch",
620
                   SPI_DMUTE1_REG, SPI_DMUTE1_BIT),
621
};
622
 
623
static int __devinit remove_ctl(struct snd_card *card, const char *name)
624
{
625
        struct snd_ctl_elem_id id;
626
        memset(&id, 0, sizeof(id));
627
        strcpy(id.name, name);
628
        id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
629
        return snd_ctl_remove_id(card, &id);
630
}
631
 
632
static struct snd_kcontrol __devinit *ctl_find(struct snd_card *card, const char *name)
633
{
634
        struct snd_ctl_elem_id sid;
635
        memset(&sid, 0, sizeof(sid));
636
        /* FIXME: strcpy is bad. */
637
        strcpy(sid.name, name);
638
        sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
639
        return snd_ctl_find_id(card, &sid);
640
}
641
 
642
static int __devinit rename_ctl(struct snd_card *card, const char *src, const char *dst)
643
{
644
        struct snd_kcontrol *kctl = ctl_find(card, src);
645
        if (kctl) {
646
                strcpy(kctl->id.name, dst);
647
                return 0;
648
        }
649
        return -ENOENT;
650
}
651
 
652
#define ADD_CTLS(emu, ctls)                                             \
653
        do {                                                            \
654
                int i, err;                                             \
655
                for (i = 0; i < ARRAY_SIZE(ctls); i++) {         \
656
                        err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \
657
                        if (err < 0)                                     \
658
                                return err;                             \
659
                }                                                       \
660
        } while (0)
661
 
662
int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
663
{
664
        int err;
665
        struct snd_card *card = emu->card;
666
        char **c;
667
        static char *ca0106_remove_ctls[] = {
668
                "Master Mono Playback Switch",
669
                "Master Mono Playback Volume",
670
                "3D Control - Switch",
671
                "3D Control Sigmatel - Depth",
672
                "PCM Playback Switch",
673
                "PCM Playback Volume",
674
                "CD Playback Switch",
675
                "CD Playback Volume",
676
                "Phone Playback Switch",
677
                "Phone Playback Volume",
678
                "Video Playback Switch",
679
                "Video Playback Volume",
680
                "PC Speaker Playback Switch",
681
                "PC Speaker Playback Volume",
682
                "Mono Output Select",
683
                "Capture Source",
684
                "Capture Switch",
685
                "Capture Volume",
686
                "External Amplifier",
687
                "Sigmatel 4-Speaker Stereo Playback Switch",
688
                "Sigmatel Surround Phase Inversion Playback ",
689
                NULL
690
        };
691
        static char *ca0106_rename_ctls[] = {
692
                "Master Playback Switch", "Capture Switch",
693
                "Master Playback Volume", "Capture Volume",
694
                "Line Playback Switch", "AC97 Line Capture Switch",
695
                "Line Playback Volume", "AC97 Line Capture Volume",
696
                "Aux Playback Switch", "AC97 Aux Capture Switch",
697
                "Aux Playback Volume", "AC97 Aux Capture Volume",
698
                "Mic Playback Switch", "AC97 Mic Capture Switch",
699
                "Mic Playback Volume", "AC97 Mic Capture Volume",
700
                "Mic Select", "AC97 Mic Select",
701
                "Mic Boost (+20dB)", "AC97 Mic Boost (+20dB)",
702
                NULL
703
        };
704
#if 1
705
        for (c = ca0106_remove_ctls; *c; c++)
706
                remove_ctl(card, *c);
707
        for (c = ca0106_rename_ctls; *c; c += 2)
708
                rename_ctl(card, c[0], c[1]);
709
#endif
710
 
711
        ADD_CTLS(emu, snd_ca0106_volume_ctls);
712
        if (emu->details->i2c_adc == 1) {
713
                ADD_CTLS(emu, snd_ca0106_volume_i2c_adc_ctls);
714
                if (emu->details->gpio_type == 1)
715
                        err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu));
716
                else  /* gpio_type == 2 */
717
                        err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_line_in_side_out, emu));
718
                if (err < 0)
719
                        return err;
720
        }
721
        if (emu->details->spi_dac == 1)
722
                ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls);
723
        return 0;
724
}
725
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.