~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to sound/pci/ca0106/ca0106_mixer.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
 
3
 *  Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
 
4
 *  Version: 0.0.18
 
5
 *
 
6
 *  FEATURES currently supported:
 
7
 *    See ca0106_main.c for features.
 
8
 * 
 
9
 *  Changelog:
 
10
 *    Support interrupts per period.
 
11
 *    Removed noise from Center/LFE channel when in Analog mode.
 
12
 *    Rename and remove mixer controls.
 
13
 *  0.0.6
 
14
 *    Use separate card based DMA buffer for periods table list.
 
15
 *  0.0.7
 
16
 *    Change remove and rename ctrls into lists.
 
17
 *  0.0.8
 
18
 *    Try to fix capture sources.
 
19
 *  0.0.9
 
20
 *    Fix AC3 output.
 
21
 *    Enable S32_LE format support.
 
22
 *  0.0.10
 
23
 *    Enable playback 48000 and 96000 rates. (Rates other that these do not work, even with "plug:front".)
 
24
 *  0.0.11
 
25
 *    Add Model name recognition.
 
26
 *  0.0.12
 
27
 *    Correct interrupt timing. interrupt at end of period, instead of in the middle of a playback period.
 
28
 *    Remove redundent "voice" handling.
 
29
 *  0.0.13
 
30
 *    Single trigger call for multi channels.
 
31
 *  0.0.14
 
32
 *    Set limits based on what the sound card hardware can do.
 
33
 *    playback periods_min=2, periods_max=8
 
34
 *    capture hw constraints require period_size = n * 64 bytes.
 
35
 *    playback hw constraints require period_size = n * 64 bytes.
 
36
 *  0.0.15
 
37
 *    Separated ca0106.c into separate functional .c files.
 
38
 *  0.0.16
 
39
 *    Modified Copyright message.
 
40
 *  0.0.17
 
41
 *    Implement Mic and Line in Capture.
 
42
 *  0.0.18
 
43
 *    Add support for mute control on SB Live 24bit (cards w/ SPI DAC)
 
44
 *
 
45
 *  This code was initially based on code from ALSA's emu10k1x.c which is:
 
46
 *  Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
 
47
 *
 
48
 *   This program is free software; you can redistribute it and/or modify
 
49
 *   it under the terms of the GNU General Public License as published by
 
50
 *   the Free Software Foundation; either version 2 of the License, or
 
51
 *   (at your option) any later version.
 
52
 *
 
53
 *   This program is distributed in the hope that it will be useful,
 
54
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
55
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
56
 *   GNU General Public License for more details.
 
57
 *
 
58
 *   You should have received a copy of the GNU General Public License
 
59
 *   along with this program; if not, write to the Free Software
 
60
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 
61
 *
 
62
 */
 
63
#include <linux/delay.h>
 
64
#include <linux/init.h>
 
65
#include <linux/interrupt.h>
 
66
#include <linux/moduleparam.h>
 
67
#include <sound/core.h>
 
68
#include <sound/initval.h>
 
69
#include <sound/pcm.h>
 
70
#include <sound/ac97_codec.h>
 
71
#include <sound/info.h>
 
72
#include <sound/tlv.h>
 
73
#include <asm/io.h>
 
74
 
 
75
#include "ca0106.h"
 
76
 
 
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 */