treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 156
[linux-block.git] / sound / pci / ca0106 / ca0106_mixer.c
CommitLineData
1a59d1b8 1// SPDX-License-Identifier: GPL-2.0-or-later
1da177e4
LT
2/*
3 * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
4 * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
b18cd538 5 * Version: 0.0.18
1da177e4
LT
6 *
7 * FEATURES currently supported:
8 * See ca0106_main.c for features.
9 *
10 * Changelog:
11 * Support interrupts per period.
12 * Removed noise from Center/LFE channel when in Analog mode.
13 * Rename and remove mixer controls.
14 * 0.0.6
15 * Use separate card based DMA buffer for periods table list.
16 * 0.0.7
17 * Change remove and rename ctrls into lists.
18 * 0.0.8
19 * Try to fix capture sources.
20 * 0.0.9
21 * Fix AC3 output.
22 * Enable S32_LE format support.
23 * 0.0.10
24 * Enable playback 48000 and 96000 rates. (Rates other that these do not work, even with "plug:front".)
25 * 0.0.11
26 * Add Model name recognition.
27 * 0.0.12
28 * Correct interrupt timing. interrupt at end of period, instead of in the middle of a playback period.
29 * Remove redundent "voice" handling.
30 * 0.0.13
31 * Single trigger call for multi channels.
32 * 0.0.14
33 * Set limits based on what the sound card hardware can do.
34 * playback periods_min=2, periods_max=8
35 * capture hw constraints require period_size = n * 64 bytes.
36 * playback hw constraints require period_size = n * 64 bytes.
37 * 0.0.15
38 * Separated ca0106.c into separate functional .c files.
39 * 0.0.16
40 * Modified Copyright message.
ed144f3c
JCD
41 * 0.0.17
42 * Implement Mic and Line in Capture.
b18cd538
TP
43 * 0.0.18
44 * Add support for mute control on SB Live 24bit (cards w/ SPI DAC)
1da177e4 45 *
25985edc 46 * This code was initially based on code from ALSA's emu10k1x.c which is:
1da177e4 47 * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
1da177e4 48 */
1da177e4
LT
49#include <linux/delay.h>
50#include <linux/init.h>
51#include <linux/interrupt.h>
1da177e4
LT
52#include <linux/moduleparam.h>
53#include <sound/core.h>
54#include <sound/initval.h>
55#include <sound/pcm.h>
56#include <sound/ac97_codec.h>
57#include <sound/info.h>
42750b04 58#include <sound/tlv.h>
6cbbfe1c 59#include <linux/io.h>
1da177e4
LT
60
61#include "ca0106.h"
62
5da95273
TI
63static void ca0106_spdif_enable(struct snd_ca0106 *emu)
64{
65 unsigned int val;
66
67 if (emu->spdif_enable) {
68 /* Digital */
69 snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
70 snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000);
71 val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000;
72 snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val);
73 val = inl(emu->port + GPIO) & ~0x101;
74 outl(val, emu->port + GPIO);
75
76 } else {
77 /* Analog */
78 snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
79 snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000);
80 val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000;
81 snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val);
82 val = inl(emu->port + GPIO) | 0x101;
83 outl(val, emu->port + GPIO);
84 }
85}
86
87static void ca0106_set_capture_source(struct snd_ca0106 *emu)
88{
89 unsigned int val = emu->capture_source;
90 unsigned int source, mask;
91 source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
92 mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff;
93 snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask);
94}
95
96static void ca0106_set_i2c_capture_source(struct snd_ca0106 *emu,
97 unsigned int val, int force)
98{
99 unsigned int ngain, ogain;
100 u32 source;
101
102 snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
103 ngain = emu->i2c_capture_volume[val][0]; /* Left */
104 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
105 if (force || ngain != ogain)
106 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ngain & 0xff);
107 ngain = emu->i2c_capture_volume[val][1]; /* Right */
108 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
109 if (force || ngain != ogain)
110 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ngain & 0xff);
111 source = 1 << val;
112 snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */
113 emu->i2c_capture_source = val;
114}
115
116static void ca0106_set_capture_mic_line_in(struct snd_ca0106 *emu)
117{
118 u32 tmp;
119
120 if (emu->capture_mic_line_in) {
121 /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */
122 tmp = inl(emu->port+GPIO) & ~0x400;
123 tmp = tmp | 0x400;
124 outl(tmp, emu->port+GPIO);
125 /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); */
126 } else {
127 /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */
128 tmp = inl(emu->port+GPIO) & ~0x400;
129 outl(tmp, emu->port+GPIO);
130 /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); */
131 }
132}
133
134static void ca0106_set_spdif_bits(struct snd_ca0106 *emu, int idx)
135{
3d475829 136 snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_str_bits[idx]);
5da95273
TI
137}
138
139/*
140 */
0cb29ea0
TI
141static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1);
142static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1);
42750b04 143
a5ce8890 144#define snd_ca0106_shared_spdif_info snd_ctl_boolean_mono_info
1da177e4 145
e4a3d145
TI
146static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol,
147 struct snd_ctl_elem_value *ucontrol)
1da177e4 148{
e4a3d145 149 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
1da177e4 150
5fe619f9 151 ucontrol->value.integer.value[0] = emu->spdif_enable;
1da177e4
LT
152 return 0;
153}
154
e4a3d145
TI
155static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol,
156 struct snd_ctl_elem_value *ucontrol)
1da177e4 157{
e4a3d145 158 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
1da177e4
LT
159 unsigned int val;
160 int change = 0;
1da177e4 161
5fe619f9 162 val = !!ucontrol->value.integer.value[0];
1da177e4
LT
163 change = (emu->spdif_enable != val);
164 if (change) {
165 emu->spdif_enable = val;
5da95273 166 ca0106_spdif_enable(emu);
1da177e4
LT
167 }
168 return change;
169}
170
e4a3d145
TI
171static int snd_ca0106_capture_source_info(struct snd_kcontrol *kcontrol,
172 struct snd_ctl_elem_info *uinfo)
1da177e4 173{
de95eae2 174 static const char * const texts[6] = {
39596dc8 175 "IEC958 out", "i2s mixer out", "IEC958 in", "i2s in", "AC97 in", "SRC out"
95a98265 176 };
1da177e4 177
de95eae2 178 return snd_ctl_enum_info(uinfo, 1, 6, texts);
1da177e4
LT
179}
180
e4a3d145
TI
181static int snd_ca0106_capture_source_get(struct snd_kcontrol *kcontrol,
182 struct snd_ctl_elem_value *ucontrol)
1da177e4 183{
e4a3d145 184 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
1da177e4
LT
185
186 ucontrol->value.enumerated.item[0] = emu->capture_source;
187 return 0;
188}
189
e4a3d145
TI
190static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
191 struct snd_ctl_elem_value *ucontrol)
1da177e4 192{
e4a3d145 193 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
1da177e4
LT
194 unsigned int val;
195 int change = 0;
1da177e4
LT
196
197 val = ucontrol->value.enumerated.item[0] ;
5fe619f9
TI
198 if (val >= 6)
199 return -EINVAL;
1da177e4
LT
200 change = (emu->capture_source != val);
201 if (change) {
202 emu->capture_source = val;
5da95273 203 ca0106_set_capture_source(emu);
1da177e4
LT
204 }
205 return change;
206}
207
6129daaa
JCD
208static int snd_ca0106_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
209 struct snd_ctl_elem_info *uinfo)
210{
de95eae2 211 static const char * const texts[4] = {
6129daaa
JCD
212 "Phone", "Mic", "Line in", "Aux"
213 };
214
de95eae2 215 return snd_ctl_enum_info(uinfo, 1, 4, texts);
6129daaa
JCD
216}
217
218static int snd_ca0106_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
219 struct snd_ctl_elem_value *ucontrol)
220{
221 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
222
223 ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
224 return 0;
225}
226
227static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
228 struct snd_ctl_elem_value *ucontrol)
229{
230 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
231 unsigned int source_id;
6129daaa 232 int change = 0;
6129daaa
JCD
233 /* If the capture source has changed,
234 * update the capture volume from the cached value
235 * for the particular source.
236 */
237 source_id = ucontrol->value.enumerated.item[0] ;
5fe619f9
TI
238 if (source_id >= 4)
239 return -EINVAL;
6129daaa
JCD
240 change = (emu->i2c_capture_source != source_id);
241 if (change) {
5da95273 242 ca0106_set_i2c_capture_source(emu, source_id, 0);
6129daaa
JCD
243 }
244 return change;
245}
246
be0b7b01
JCD
247static int snd_ca0106_capture_line_in_side_out_info(struct snd_kcontrol *kcontrol,
248 struct snd_ctl_elem_info *uinfo)
249{
de95eae2
TI
250 static const char * const texts[2] = { "Side out", "Line in" };
251
252 return snd_ctl_enum_info(uinfo, 1, 2, texts);
be0b7b01
JCD
253}
254
e4a3d145
TI
255static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol,
256 struct snd_ctl_elem_info *uinfo)
ed144f3c 257{
de95eae2
TI
258 static const char * const texts[2] = { "Line in", "Mic in" };
259
260 return snd_ctl_enum_info(uinfo, 1, 2, texts);
ed144f3c
JCD
261}
262
e4a3d145
TI
263static int snd_ca0106_capture_mic_line_in_get(struct snd_kcontrol *kcontrol,
264 struct snd_ctl_elem_value *ucontrol)
ed144f3c 265{
e4a3d145 266 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
ed144f3c
JCD
267
268 ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in;
269 return 0;
270}
271
e4a3d145
TI
272static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
273 struct snd_ctl_elem_value *ucontrol)
ed144f3c 274{
e4a3d145 275 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
ed144f3c
JCD
276 unsigned int val;
277 int change = 0;
ed144f3c
JCD
278
279 val = ucontrol->value.enumerated.item[0] ;
5fe619f9
TI
280 if (val > 1)
281 return -EINVAL;
ed144f3c
JCD
282 change = (emu->capture_mic_line_in != val);
283 if (change) {
284 emu->capture_mic_line_in = val;
5da95273 285 ca0106_set_capture_mic_line_in(emu);
ed144f3c
JCD
286 }
287 return change;
288}
289
f3b827e0 290static const struct snd_kcontrol_new snd_ca0106_capture_mic_line_in =
ed144f3c
JCD
291{
292 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6129daaa 293 .name = "Shared Mic/Line in Capture Switch",
ed144f3c
JCD
294 .info = snd_ca0106_capture_mic_line_in_info,
295 .get = snd_ca0106_capture_mic_line_in_get,
296 .put = snd_ca0106_capture_mic_line_in_put
297};
298
f3b827e0 299static const struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out =
be0b7b01
JCD
300{
301 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
302 .name = "Shared Line in/Side out Capture Switch",
303 .info = snd_ca0106_capture_line_in_side_out_info,
304 .get = snd_ca0106_capture_mic_line_in_get,
305 .put = snd_ca0106_capture_mic_line_in_put
306};
307
308
e4a3d145
TI
309static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol,
310 struct snd_ctl_elem_info *uinfo)
1da177e4
LT
311{
312 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
313 uinfo->count = 1;
314 return 0;
315}
316
3d475829
TI
317static void decode_spdif_bits(unsigned char *status, unsigned int bits)
318{
319 status[0] = (bits >> 0) & 0xff;
320 status[1] = (bits >> 8) & 0xff;
321 status[2] = (bits >> 16) & 0xff;
322 status[3] = (bits >> 24) & 0xff;
323}
324
325static int snd_ca0106_spdif_get_default(struct snd_kcontrol *kcontrol,
e4a3d145 326 struct snd_ctl_elem_value *ucontrol)
1da177e4 327{
e4a3d145 328 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
1da177e4
LT
329 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
330
3d475829
TI
331 decode_spdif_bits(ucontrol->value.iec958.status,
332 emu->spdif_bits[idx]);
333 return 0;
334}
335
336static int snd_ca0106_spdif_get_stream(struct snd_kcontrol *kcontrol,
337 struct snd_ctl_elem_value *ucontrol)
338{
339 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
340 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
341
342 decode_spdif_bits(ucontrol->value.iec958.status,
343 emu->spdif_str_bits[idx]);
1da177e4
LT
344 return 0;
345}
346
e4a3d145
TI
347static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol,
348 struct snd_ctl_elem_value *ucontrol)
1da177e4
LT
349{
350 ucontrol->value.iec958.status[0] = 0xff;
351 ucontrol->value.iec958.status[1] = 0xff;
352 ucontrol->value.iec958.status[2] = 0xff;
353 ucontrol->value.iec958.status[3] = 0xff;
354 return 0;
355}
356
3d475829
TI
357static unsigned int encode_spdif_bits(unsigned char *status)
358{
359 return ((unsigned int)status[0] << 0) |
360 ((unsigned int)status[1] << 8) |
361 ((unsigned int)status[2] << 16) |
362 ((unsigned int)status[3] << 24);
363}
364
365static int snd_ca0106_spdif_put_default(struct snd_kcontrol *kcontrol,
e4a3d145 366 struct snd_ctl_elem_value *ucontrol)
1da177e4 367{
e4a3d145 368 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
1da177e4 369 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1da177e4
LT
370 unsigned int val;
371
3d475829
TI
372 val = encode_spdif_bits(ucontrol->value.iec958.status);
373 if (val != emu->spdif_bits[idx]) {
1da177e4 374 emu->spdif_bits[idx] = val;
3d475829
TI
375 /* FIXME: this isn't safe, but needed to keep the compatibility
376 * with older alsa-lib config
377 */
378 emu->spdif_str_bits[idx] = val;
5da95273 379 ca0106_set_spdif_bits(emu, idx);
3d475829 380 return 1;
1da177e4 381 }
3d475829
TI
382 return 0;
383}
384
385static int snd_ca0106_spdif_put_stream(struct snd_kcontrol *kcontrol,
386 struct snd_ctl_elem_value *ucontrol)
387{
388 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
389 unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
390 unsigned int val;
391
392 val = encode_spdif_bits(ucontrol->value.iec958.status);
393 if (val != emu->spdif_str_bits[idx]) {
394 emu->spdif_str_bits[idx] = val;
395 ca0106_set_spdif_bits(emu, idx);
396 return 1;
397 }
398 return 0;
1da177e4
LT
399}
400
e4a3d145
TI
401static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol,
402 struct snd_ctl_elem_info *uinfo)
1da177e4
LT
403{
404 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
405 uinfo->count = 2;
406 uinfo->value.integer.min = 0;
407 uinfo->value.integer.max = 255;
408 return 0;
409}
410
e4a3d145
TI
411static int snd_ca0106_volume_get(struct snd_kcontrol *kcontrol,
412 struct snd_ctl_elem_value *ucontrol)
1da177e4 413{
e4a3d145 414 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
1da177e4 415 unsigned int value;
95a98265
TI
416 int channel_id, reg;
417
418 channel_id = (kcontrol->private_value >> 8) & 0xff;
419 reg = kcontrol->private_value & 0xff;
1da177e4
LT
420
421 value = snd_ca0106_ptr_read(emu, reg, channel_id);
422 ucontrol->value.integer.value[0] = 0xff - ((value >> 24) & 0xff); /* Left */
423 ucontrol->value.integer.value[1] = 0xff - ((value >> 16) & 0xff); /* Right */
424 return 0;
425}
426
e4a3d145
TI
427static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol,
428 struct snd_ctl_elem_value *ucontrol)
1da177e4 429{
e4a3d145 430 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
95a98265
TI
431 unsigned int oval, nval;
432 int channel_id, reg;
433
434 channel_id = (kcontrol->private_value >> 8) & 0xff;
435 reg = kcontrol->private_value & 0xff;
436
437 oval = snd_ca0106_ptr_read(emu, reg, channel_id);
438 nval = ((0xff - ucontrol->value.integer.value[0]) << 24) |
439 ((0xff - ucontrol->value.integer.value[1]) << 16);
440 nval |= ((0xff - ucontrol->value.integer.value[0]) << 8) |
441 ((0xff - ucontrol->value.integer.value[1]) );
442 if (oval == nval)
443 return 0;
444 snd_ca0106_ptr_write(emu, reg, channel_id, nval);
445 return 1;
446}
447
6129daaa
JCD
448static int snd_ca0106_i2c_volume_info(struct snd_kcontrol *kcontrol,
449 struct snd_ctl_elem_info *uinfo)
450{
451 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
452 uinfo->count = 2;
453 uinfo->value.integer.min = 0;
454 uinfo->value.integer.max = 255;
455 return 0;
456}
457
458static int snd_ca0106_i2c_volume_get(struct snd_kcontrol *kcontrol,
459 struct snd_ctl_elem_value *ucontrol)
460{
461 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
462 int source_id;
463
464 source_id = kcontrol->private_value;
465
466 ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
467 ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
468 return 0;
469}
470
471static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol,
472 struct snd_ctl_elem_value *ucontrol)
473{
474 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
475 unsigned int ogain;
476 unsigned int ngain;
477 int source_id;
478 int change = 0;
479
480 source_id = kcontrol->private_value;
481 ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
482 ngain = ucontrol->value.integer.value[0];
483 if (ngain > 0xff)
5fe619f9 484 return -EINVAL;
6129daaa
JCD
485 if (ogain != ngain) {
486 if (emu->i2c_capture_source == source_id)
487 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
488 emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0];
489 change = 1;
490 }
491 ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
492 ngain = ucontrol->value.integer.value[1];
493 if (ngain > 0xff)
5fe619f9 494 return -EINVAL;
6129daaa
JCD
495 if (ogain != ngain) {
496 if (emu->i2c_capture_source == source_id)
497 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
498 emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1];
499 change = 1;
500 }
501
502 return change;
503}
504
b18cd538
TP
505#define spi_mute_info snd_ctl_boolean_mono_info
506
507static int spi_mute_get(struct snd_kcontrol *kcontrol,
508 struct snd_ctl_elem_value *ucontrol)
509{
510 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
511 unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT;
512 unsigned int bit = kcontrol->private_value & SPI_REG_MASK;
513
514 ucontrol->value.integer.value[0] = !(emu->spi_dac_reg[reg] & bit);
515 return 0;
516}
517
518static int spi_mute_put(struct snd_kcontrol *kcontrol,
519 struct snd_ctl_elem_value *ucontrol)
520{
521 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
522 unsigned int reg = kcontrol->private_value >> SPI_REG_SHIFT;
523 unsigned int bit = kcontrol->private_value & SPI_REG_MASK;
524 int ret;
525
526 ret = emu->spi_dac_reg[reg] & bit;
527 if (ucontrol->value.integer.value[0]) {
528 if (!ret) /* bit already cleared, do nothing */
529 return 0;
530 emu->spi_dac_reg[reg] &= ~bit;
531 } else {
532 if (ret) /* bit already set, do nothing */
533 return 0;
534 emu->spi_dac_reg[reg] |= bit;
535 }
536
537 ret = snd_ca0106_spi_write(emu, emu->spi_dac_reg[reg]);
5fe619f9 538 return ret ? -EINVAL : 1;
b18cd538
TP
539}
540
95a98265
TI
541#define CA_VOLUME(xname,chid,reg) \
542{ \
543 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
302e9c5a
JK
544 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
545 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
6129daaa
JCD
546 .info = snd_ca0106_volume_info, \
547 .get = snd_ca0106_volume_get, \
548 .put = snd_ca0106_volume_put, \
7cf0a953 549 .tlv = { .p = snd_ca0106_db_scale1 }, \
95a98265
TI
550 .private_value = ((chid) << 8) | (reg) \
551}
552
e23e7a14 553static struct snd_kcontrol_new snd_ca0106_volume_ctls[] = {
95a98265
TI
554 CA_VOLUME("Analog Front Playback Volume",
555 CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2),
556 CA_VOLUME("Analog Rear Playback Volume",
557 CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2),
558 CA_VOLUME("Analog Center/LFE Playback Volume",
559 CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2),
560 CA_VOLUME("Analog Side Playback Volume",
561 CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2),
562
39596dc8 563 CA_VOLUME("IEC958 Front Playback Volume",
95a98265 564 CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1),
39596dc8 565 CA_VOLUME("IEC958 Rear Playback Volume",
95a98265 566 CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1),
39596dc8 567 CA_VOLUME("IEC958 Center/LFE Playback Volume",
95a98265 568 CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1),
39596dc8 569 CA_VOLUME("IEC958 Unknown Playback Volume",
95a98265
TI
570 CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1),
571
572 CA_VOLUME("CAPTURE feedback Playback Volume",
573 1, CAPTURE_CONTROL),
574
575 {
576 .access = SNDRV_CTL_ELEM_ACCESS_READ,
577 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
578 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
579 .count = 4,
580 .info = snd_ca0106_spdif_info,
581 .get = snd_ca0106_spdif_get_mask
582 },
583 {
584 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
39596dc8 585 .name = "IEC958 Playback Switch",
95a98265
TI
586 .info = snd_ca0106_shared_spdif_info,
587 .get = snd_ca0106_shared_spdif_get,
588 .put = snd_ca0106_shared_spdif_put
589 },
590 {
591 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
e6327cf9 592 .name = "Digital Source Capture Enum",
95a98265
TI
593 .info = snd_ca0106_capture_source_info,
594 .get = snd_ca0106_capture_source_get,
595 .put = snd_ca0106_capture_source_put
596 },
6129daaa
JCD
597 {
598 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
e6327cf9 599 .name = "Analog Source Capture Enum",
6129daaa
JCD
600 .info = snd_ca0106_i2c_capture_source_info,
601 .get = snd_ca0106_i2c_capture_source_get,
602 .put = snd_ca0106_i2c_capture_source_put
603 },
95a98265
TI
604 {
605 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
606 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
607 .count = 4,
608 .info = snd_ca0106_spdif_info,
3d475829
TI
609 .get = snd_ca0106_spdif_get_default,
610 .put = snd_ca0106_spdif_put_default
611 },
612 {
613 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
614 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
615 .count = 4,
616 .info = snd_ca0106_spdif_info,
617 .get = snd_ca0106_spdif_get_stream,
618 .put = snd_ca0106_spdif_put_stream
95a98265 619 },
1da177e4
LT
620};
621
7c157069
JCD
622#define I2C_VOLUME(xname,chid) \
623{ \
624 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
625 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
626 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
627 .info = snd_ca0106_i2c_volume_info, \
628 .get = snd_ca0106_i2c_volume_get, \
629 .put = snd_ca0106_i2c_volume_put, \
630 .tlv = { .p = snd_ca0106_db_scale2 }, \
631 .private_value = chid \
632}
633
e23e7a14 634static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] = {
7c157069
JCD
635 I2C_VOLUME("Phone Capture Volume", 0),
636 I2C_VOLUME("Mic Capture Volume", 1),
637 I2C_VOLUME("Line in Capture Volume", 2),
638 I2C_VOLUME("Aux Capture Volume", 3),
639};
640
64e5310a
AO
641static const int spi_dmute_reg[] = {
642 SPI_DMUTE0_REG,
643 SPI_DMUTE1_REG,
644 SPI_DMUTE2_REG,
645 0,
646 SPI_DMUTE4_REG,
647};
648static const int spi_dmute_bit[] = {
649 SPI_DMUTE0_BIT,
650 SPI_DMUTE1_BIT,
651 SPI_DMUTE2_BIT,
652 0,
653 SPI_DMUTE4_BIT,
b18cd538
TP
654};
655
e23e7a14 656static struct snd_kcontrol_new
64e5310a
AO
657snd_ca0106_volume_spi_dac_ctl(struct snd_ca0106_details *details,
658 int channel_id)
659{
660 struct snd_kcontrol_new spi_switch = {0};
661 int reg, bit;
662 int dac_id;
663
664 spi_switch.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
665 spi_switch.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
666 spi_switch.info = spi_mute_info;
667 spi_switch.get = spi_mute_get;
668 spi_switch.put = spi_mute_put;
669
670 switch (channel_id) {
671 case PCM_FRONT_CHANNEL:
672 spi_switch.name = "Analog Front Playback Switch";
673 dac_id = (details->spi_dac & 0xf000) >> (4 * 3);
674 break;
675 case PCM_REAR_CHANNEL:
676 spi_switch.name = "Analog Rear Playback Switch";
677 dac_id = (details->spi_dac & 0x0f00) >> (4 * 2);
678 break;
679 case PCM_CENTER_LFE_CHANNEL:
680 spi_switch.name = "Analog Center/LFE Playback Switch";
681 dac_id = (details->spi_dac & 0x00f0) >> (4 * 1);
682 break;
683 case PCM_UNKNOWN_CHANNEL:
684 spi_switch.name = "Analog Side Playback Switch";
685 dac_id = (details->spi_dac & 0x000f) >> (4 * 0);
686 break;
687 default:
688 /* Unused channel */
689 spi_switch.name = NULL;
690 dac_id = 0;
691 }
692 reg = spi_dmute_reg[dac_id];
693 bit = spi_dmute_bit[dac_id];
694
695 spi_switch.private_value = (reg << SPI_REG_SHIFT) | bit;
696
697 return spi_switch;
698}
699
e23e7a14 700static int remove_ctl(struct snd_card *card, const char *name)
1da177e4 701{
e4a3d145 702 struct snd_ctl_elem_id id;
1da177e4
LT
703 memset(&id, 0, sizeof(id));
704 strcpy(id.name, name);
705 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
706 return snd_ctl_remove_id(card, &id);
707}
708
e23e7a14 709static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name)
1da177e4 710{
e4a3d145 711 struct snd_ctl_elem_id sid;
1da177e4
LT
712 memset(&sid, 0, sizeof(sid));
713 /* FIXME: strcpy is bad. */
714 strcpy(sid.name, name);
715 sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
716 return snd_ctl_find_id(card, &sid);
717}
718
e23e7a14 719static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
1da177e4 720{
e4a3d145 721 struct snd_kcontrol *kctl = ctl_find(card, src);
1da177e4
LT
722 if (kctl) {
723 strcpy(kctl->id.name, dst);
724 return 0;
725 }
726 return -ENOENT;
727}
728
fca7f388
TP
729#define ADD_CTLS(emu, ctls) \
730 do { \
bed515b0 731 int i, _err; \
fca7f388 732 for (i = 0; i < ARRAY_SIZE(ctls); i++) { \
bed515b0
HH
733 _err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \
734 if (_err < 0) \
735 return _err; \
fca7f388
TP
736 } \
737 } while (0)
738
e23e7a14 739static
c4865679 740DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 25, 1);
49c88b85 741
e23e7a14 742static char *slave_vols[] = {
49c88b85
TI
743 "Analog Front Playback Volume",
744 "Analog Rear Playback Volume",
745 "Analog Center/LFE Playback Volume",
746 "Analog Side Playback Volume",
747 "IEC958 Front Playback Volume",
748 "IEC958 Rear Playback Volume",
749 "IEC958 Center/LFE Playback Volume",
750 "IEC958 Unknown Playback Volume",
751 "CAPTURE feedback Playback Volume",
752 NULL
753};
754
e23e7a14 755static char *slave_sws[] = {
49c88b85
TI
756 "Analog Front Playback Switch",
757 "Analog Rear Playback Switch",
758 "Analog Center/LFE Playback Switch",
759 "Analog Side Playback Switch",
760 "IEC958 Playback Switch",
761 NULL
762};
763
e23e7a14 764static void add_slaves(struct snd_card *card,
49c88b85
TI
765 struct snd_kcontrol *master, char **list)
766{
767 for (; *list; list++) {
768 struct snd_kcontrol *slave = ctl_find(card, *list);
769 if (slave)
770 snd_ctl_add_slave(master, slave);
771 }
772}
773
e23e7a14 774int snd_ca0106_mixer(struct snd_ca0106 *emu)
1da177e4 775{
fca7f388 776 int err;
e4a3d145 777 struct snd_card *card = emu->card;
1da177e4 778 char **c;
49c88b85 779 struct snd_kcontrol *vmaster;
1da177e4
LT
780 static char *ca0106_remove_ctls[] = {
781 "Master Mono Playback Switch",
782 "Master Mono Playback Volume",
783 "3D Control - Switch",
784 "3D Control Sigmatel - Depth",
785 "PCM Playback Switch",
786 "PCM Playback Volume",
787 "CD Playback Switch",
788 "CD Playback Volume",
789 "Phone Playback Switch",
790 "Phone Playback Volume",
791 "Video Playback Switch",
792 "Video Playback Volume",
d355c82a
JK
793 "Beep Playback Switch",
794 "Beep Playback Volume",
1da177e4
LT
795 "Mono Output Select",
796 "Capture Source",
797 "Capture Switch",
798 "Capture Volume",
799 "External Amplifier",
800 "Sigmatel 4-Speaker Stereo Playback Switch",
afe6d7e3 801 "Surround Phase Inversion Playback Switch",
1da177e4
LT
802 NULL
803 };
804 static char *ca0106_rename_ctls[] = {
805 "Master Playback Switch", "Capture Switch",
806 "Master Playback Volume", "Capture Volume",
807 "Line Playback Switch", "AC97 Line Capture Switch",
808 "Line Playback Volume", "AC97 Line Capture Volume",
809 "Aux Playback Switch", "AC97 Aux Capture Switch",
810 "Aux Playback Volume", "AC97 Aux Capture Volume",
811 "Mic Playback Switch", "AC97 Mic Capture Switch",
812 "Mic Playback Volume", "AC97 Mic Capture Volume",
813 "Mic Select", "AC97 Mic Select",
814 "Mic Boost (+20dB)", "AC97 Mic Boost (+20dB)",
815 NULL
816 };
817#if 1
95a98265 818 for (c = ca0106_remove_ctls; *c; c++)
1da177e4 819 remove_ctl(card, *c);
95a98265 820 for (c = ca0106_rename_ctls; *c; c += 2)
1da177e4
LT
821 rename_ctl(card, c[0], c[1]);
822#endif
823
fca7f388 824 ADD_CTLS(emu, snd_ca0106_volume_ctls);
ed144f3c 825 if (emu->details->i2c_adc == 1) {
fca7f388 826 ADD_CTLS(emu, snd_ca0106_volume_i2c_adc_ctls);
be0b7b01
JCD
827 if (emu->details->gpio_type == 1)
828 err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu));
829 else /* gpio_type == 2 */
830 err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_line_in_side_out, emu));
95a98265 831 if (err < 0)
ed144f3c
JCD
832 return err;
833 }
64e5310a
AO
834 if (emu->details->spi_dac) {
835 int i;
836 for (i = 0;; i++) {
837 struct snd_kcontrol_new ctl;
838 ctl = snd_ca0106_volume_spi_dac_ctl(emu->details, i);
839 if (!ctl.name)
840 break;
841 err = snd_ctl_add(card, snd_ctl_new1(&ctl, emu));
842 if (err < 0)
843 return err;
844 }
845 }
49c88b85
TI
846
847 /* Create virtual master controls */
848 vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
849 snd_ca0106_master_db_scale);
850 if (!vmaster)
851 return -ENOMEM;
601e1cc5
TI
852 err = snd_ctl_add(card, vmaster);
853 if (err < 0)
854 return err;
49c88b85
TI
855 add_slaves(card, vmaster, slave_vols);
856
6fef153a 857 if (emu->details->spi_dac) {
49c88b85
TI
858 vmaster = snd_ctl_make_virtual_master("Master Playback Switch",
859 NULL);
860 if (!vmaster)
861 return -ENOMEM;
601e1cc5
TI
862 err = snd_ctl_add(card, vmaster);
863 if (err < 0)
864 return err;
49c88b85
TI
865 add_slaves(card, vmaster, slave_sws);
866 }
eeaf100d
TI
867
868 strcpy(card->mixername, "CA0106");
1da177e4
LT
869 return 0;
870}
871
c7561cd8 872#ifdef CONFIG_PM_SLEEP
5da95273 873struct ca0106_vol_tbl {
5da95273 874 unsigned int channel_id;
8df0f707 875 unsigned int reg;
5da95273
TI
876};
877
878static struct ca0106_vol_tbl saved_volumes[NUM_SAVED_VOLUMES] = {
879 { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2 },
880 { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2 },
881 { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2 },
882 { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2 },
883 { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1 },
884 { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1 },
885 { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1 },
886 { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1 },
887 { 1, CAPTURE_CONTROL },
888};
889
890void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip)
891{
892 int i;
893
894 /* save volumes */
895 for (i = 0; i < NUM_SAVED_VOLUMES; i++)
896 chip->saved_vol[i] =
897 snd_ca0106_ptr_read(chip, saved_volumes[i].reg,
898 saved_volumes[i].channel_id);
899}
900
901void snd_ca0106_mixer_resume(struct snd_ca0106 *chip)
902{
903 int i;
904
905 for (i = 0; i < NUM_SAVED_VOLUMES; i++)
906 snd_ca0106_ptr_write(chip, saved_volumes[i].reg,
907 saved_volumes[i].channel_id,
908 chip->saved_vol[i]);
909
910 ca0106_spdif_enable(chip);
911 ca0106_set_capture_source(chip);
912 ca0106_set_i2c_capture_source(chip, chip->i2c_capture_source, 1);
913 for (i = 0; i < 4; i++)
914 ca0106_set_spdif_bits(chip, i);
915 if (chip->details->i2c_adc)
916 ca0106_set_capture_mic_line_in(chip);
917}
c7561cd8 918#endif /* CONFIG_PM_SLEEP */