1// SPDX-License-Identifier: GPL-2.0-or-later
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
5 * Version: 0.0.18
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.
41 * 0.0.17
42 * Implement Mic and Line in Capture.
43 * 0.0.18
44 * Add support for mute control on SB Live 24bit (cards w/ SPI DAC)
45 *
46 * This code was initially based on code from ALSA's emu10k1x.c which is:
47 * Copyright (c) by Francisco Moraes <fmoraes@nc.rr.com>
48 */
49#include <linux/delay.h>
50#include <linux/init.h>
51#include <linux/interrupt.h>
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>
58#include <sound/tlv.h>
59#include <linux/io.h>
60
61#include "ca0106.h"
62
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, chn: 0, data: 0xf);
70 snd_ca0106_ptr_write(emu, SPDIF_SELECT2, chn: 0, data: 0x0b000000);
71 val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, chn: 0) & ~0x1000;
72 snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, chn: 0, data: val);
73 val = inl(port: emu->port + CA0106_GPIO) & ~0x101;
74 outl(value: val, port: emu->port + CA0106_GPIO);
75
76 } else {
77 /* Analog */
78 snd_ca0106_ptr_write(emu, SPDIF_SELECT1, chn: 0, data: 0xf);
79 snd_ca0106_ptr_write(emu, SPDIF_SELECT2, chn: 0, data: 0x000f0000);
80 val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, chn: 0) | 0x1000;
81 snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, chn: 0, data: val);
82 val = inl(port: emu->port + CA0106_GPIO) | 0x101;
83 outl(value: val, port: emu->port + CA0106_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, chn: 0) & 0xffff;
93 snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, chn: 0, data: 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, value: 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, value: 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, value: ngain & 0xff);
111 source = 1 << val;
112 snd_ca0106_i2c_write(emu, ADC_MUX, value: 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(port: emu->port + CA0106_GPIO) & ~0x400;
123 tmp = tmp | 0x400;
124 outl(value: tmp, port: emu->port + CA0106_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(port: emu->port + CA0106_GPIO) & ~0x400;
129 outl(value: tmp, port: emu->port + CA0106_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{
136 snd_ca0106_ptr_write(emu, SPCS0 + idx, chn: 0, data: emu->spdif_str_bits[idx]);
137}
138
139/*
140 */
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);
143
144#define snd_ca0106_shared_spdif_info snd_ctl_boolean_mono_info
145
146static int snd_ca0106_shared_spdif_get(struct snd_kcontrol *kcontrol,
147 struct snd_ctl_elem_value *ucontrol)
148{
149 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
150
151 ucontrol->value.integer.value[0] = emu->spdif_enable;
152 return 0;
153}
154
155static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol,
156 struct snd_ctl_elem_value *ucontrol)
157{
158 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
159 unsigned int val;
160 int change = 0;
161
162 val = !!ucontrol->value.integer.value[0];
163 change = (emu->spdif_enable != val);
164 if (change) {
165 emu->spdif_enable = val;
166 ca0106_spdif_enable(emu);
167 }
168 return change;
169}
170
171static int snd_ca0106_capture_source_info(struct snd_kcontrol *kcontrol,
172 struct snd_ctl_elem_info *uinfo)
173{
174 static const char * const texts[6] = {
175 "IEC958 out", "i2s mixer out", "IEC958 in", "i2s in", "AC97 in", "SRC out"
176 };
177
178 return snd_ctl_enum_info(info: uinfo, channels: 1, items: 6, names: texts);
179}
180
181static int snd_ca0106_capture_source_get(struct snd_kcontrol *kcontrol,
182 struct snd_ctl_elem_value *ucontrol)
183{
184 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
185
186 ucontrol->value.enumerated.item[0] = emu->capture_source;
187 return 0;
188}
189
190static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
191 struct snd_ctl_elem_value *ucontrol)
192{
193 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
194 unsigned int val;
195 int change = 0;
196
197 val = ucontrol->value.enumerated.item[0] ;
198 if (val >= 6)
199 return -EINVAL;
200 change = (emu->capture_source != val);
201 if (change) {
202 emu->capture_source = val;
203 ca0106_set_capture_source(emu);
204 }
205 return change;
206}
207
208static int snd_ca0106_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
209 struct snd_ctl_elem_info *uinfo)
210{
211 static const char * const texts[4] = {
212 "Phone", "Mic", "Line in", "Aux"
213 };
214
215 return snd_ctl_enum_info(info: uinfo, channels: 1, items: 4, names: texts);
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;
232 int change = 0;
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] ;
238 if (source_id >= 4)
239 return -EINVAL;
240 change = (emu->i2c_capture_source != source_id);
241 if (change) {
242 ca0106_set_i2c_capture_source(emu, val: source_id, force: 0);
243 }
244 return change;
245}
246
247static int snd_ca0106_capture_line_in_side_out_info(struct snd_kcontrol *kcontrol,
248 struct snd_ctl_elem_info *uinfo)
249{
250 static const char * const texts[2] = { "Side out", "Line in" };
251
252 return snd_ctl_enum_info(info: uinfo, channels: 1, items: 2, names: texts);
253}
254
255static int snd_ca0106_capture_mic_line_in_info(struct snd_kcontrol *kcontrol,
256 struct snd_ctl_elem_info *uinfo)
257{
258 static const char * const texts[2] = { "Line in", "Mic in" };
259
260 return snd_ctl_enum_info(info: uinfo, channels: 1, items: 2, names: texts);
261}
262
263static int snd_ca0106_capture_mic_line_in_get(struct snd_kcontrol *kcontrol,
264 struct snd_ctl_elem_value *ucontrol)
265{
266 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
267
268 ucontrol->value.enumerated.item[0] = emu->capture_mic_line_in;
269 return 0;
270}
271
272static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
273 struct snd_ctl_elem_value *ucontrol)
274{
275 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
276 unsigned int val;
277 int change = 0;
278
279 val = ucontrol->value.enumerated.item[0] ;
280 if (val > 1)
281 return -EINVAL;
282 change = (emu->capture_mic_line_in != val);
283 if (change) {
284 emu->capture_mic_line_in = val;
285 ca0106_set_capture_mic_line_in(emu);
286 }
287 return change;
288}
289
290static const struct snd_kcontrol_new snd_ca0106_capture_mic_line_in =
291{
292 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
293 .name = "Shared Mic/Line in Capture Switch",
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
299static const struct snd_kcontrol_new snd_ca0106_capture_line_in_side_out =
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
309static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol,
310 struct snd_ctl_elem_info *uinfo)
311{
312 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
313 uinfo->count = 1;
314 return 0;
315}
316
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,
326 struct snd_ctl_elem_value *ucontrol)
327{
328 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
329 unsigned int idx = snd_ctl_get_ioffidx(kctl: kcontrol, id: &ucontrol->id);
330
331 decode_spdif_bits(status: ucontrol->value.iec958.status,
332 bits: 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(kctl: kcontrol, id: &ucontrol->id);
341
342 decode_spdif_bits(status: ucontrol->value.iec958.status,
343 bits: emu->spdif_str_bits[idx]);
344 return 0;
345}
346
347static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol,
348 struct snd_ctl_elem_value *ucontrol)
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
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,
366 struct snd_ctl_elem_value *ucontrol)
367{
368 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
369 unsigned int idx = snd_ctl_get_ioffidx(kctl: kcontrol, id: &ucontrol->id);
370 unsigned int val;
371
372 val = encode_spdif_bits(status: ucontrol->value.iec958.status);
373 if (val != emu->spdif_bits[idx]) {
374 emu->spdif_bits[idx] = val;
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;
379 ca0106_set_spdif_bits(emu, idx);
380 return 1;
381 }
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(kctl: kcontrol, id: &ucontrol->id);
390 unsigned int val;
391
392 val = encode_spdif_bits(status: 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;
399}
400
401static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol,
402 struct snd_ctl_elem_info *uinfo)
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
411static int snd_ca0106_volume_get(struct snd_kcontrol *kcontrol,
412 struct snd_ctl_elem_value *ucontrol)
413{
414 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
415 unsigned int value;
416 int channel_id, reg;
417
418 channel_id = (kcontrol->private_value >> 8) & 0xff;
419 reg = kcontrol->private_value & 0xff;
420
421 value = snd_ca0106_ptr_read(emu, reg, chn: 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
427static int snd_ca0106_volume_put(struct snd_kcontrol *kcontrol,
428 struct snd_ctl_elem_value *ucontrol)
429{
430 struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
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, chn: 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, chn: channel_id, data: nval);
445 return 1;
446}
447
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)
484 return -EINVAL;
485 if (ogain != ngain) {
486 if (emu->i2c_capture_source == source_id)
487 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, value: ((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)
494 return -EINVAL;
495 if (ogain != ngain) {
496 if (emu->i2c_capture_source == source_id)
497 snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, value: ((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
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, data: emu->spi_dac_reg[reg]);
538 return ret ? -EINVAL : 1;
539}
540
541#define CA_VOLUME(xname,chid,reg) \
542{ \
543 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
544 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
545 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
546 .info = snd_ca0106_volume_info, \
547 .get = snd_ca0106_volume_get, \
548 .put = snd_ca0106_volume_put, \
549 .tlv = { .p = snd_ca0106_db_scale1 }, \
550 .private_value = ((chid) << 8) | (reg) \
551}
552
553static const struct snd_kcontrol_new snd_ca0106_volume_ctls[] = {
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
563 CA_VOLUME("IEC958 Front Playback Volume",
564 CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1),
565 CA_VOLUME("IEC958 Rear Playback Volume",
566 CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1),
567 CA_VOLUME("IEC958 Center/LFE Playback Volume",
568 CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1),
569 CA_VOLUME("IEC958 Unknown Playback Volume",
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,
585 .name = "IEC958 Playback Switch",
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,
592 .name = "Digital Source Capture Enum",
593 .info = snd_ca0106_capture_source_info,
594 .get = snd_ca0106_capture_source_get,
595 .put = snd_ca0106_capture_source_put
596 },
597 {
598 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
599 .name = "Analog Source Capture Enum",
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 },
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,
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
619 },
620};
621
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
634static const struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] = {
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
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,
654};
655
656static struct snd_kcontrol_new
657snd_ca0106_volume_spi_dac_ctl(const 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
700static int remove_ctl(struct snd_card *card, const char *name)
701{
702 struct snd_ctl_elem_id id;
703 memset(&id, 0, sizeof(id));
704 strcpy(p: id.name, q: name);
705 id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
706 return snd_ctl_remove_id(card, id: &id);
707}
708
709static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
710{
711 struct snd_kcontrol *kctl = snd_ctl_find_id_mixer(card, name: src);
712 if (kctl) {
713 snd_ctl_rename(card, kctl, name: dst);
714 return 0;
715 }
716 return -ENOENT;
717}
718
719#define ADD_CTLS(emu, ctls) \
720 do { \
721 int i, _err; \
722 for (i = 0; i < ARRAY_SIZE(ctls); i++) { \
723 _err = snd_ctl_add(card, snd_ctl_new1(&ctls[i], emu)); \
724 if (_err < 0) \
725 return _err; \
726 } \
727 } while (0)
728
729static
730DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 25, 1);
731
732static const char * const follower_vols[] = {
733 "Analog Front Playback Volume",
734 "Analog Rear Playback Volume",
735 "Analog Center/LFE Playback Volume",
736 "Analog Side Playback Volume",
737 "IEC958 Front Playback Volume",
738 "IEC958 Rear Playback Volume",
739 "IEC958 Center/LFE Playback Volume",
740 "IEC958 Unknown Playback Volume",
741 "CAPTURE feedback Playback Volume",
742 NULL
743};
744
745static const char * const follower_sws[] = {
746 "Analog Front Playback Switch",
747 "Analog Rear Playback Switch",
748 "Analog Center/LFE Playback Switch",
749 "Analog Side Playback Switch",
750 "IEC958 Playback Switch",
751 NULL
752};
753
754int snd_ca0106_mixer(struct snd_ca0106 *emu)
755{
756 int err;
757 struct snd_card *card = emu->card;
758 const char * const *c;
759 struct snd_kcontrol *vmaster;
760 static const char * const ca0106_remove_ctls[] = {
761 "Master Mono Playback Switch",
762 "Master Mono Playback Volume",
763 "3D Control - Switch",
764 "3D Control Sigmatel - Depth",
765 "PCM Playback Switch",
766 "PCM Playback Volume",
767 "CD Playback Switch",
768 "CD Playback Volume",
769 "Phone Playback Switch",
770 "Phone Playback Volume",
771 "Video Playback Switch",
772 "Video Playback Volume",
773 "Beep Playback Switch",
774 "Beep Playback Volume",
775 "Mono Output Select",
776 "Capture Source",
777 "Capture Switch",
778 "Capture Volume",
779 "External Amplifier",
780 "Sigmatel 4-Speaker Stereo Playback Switch",
781 "Surround Phase Inversion Playback Switch",
782 NULL
783 };
784 static const char * const ca0106_rename_ctls[] = {
785 "Master Playback Switch", "Capture Switch",
786 "Master Playback Volume", "Capture Volume",
787 "Line Playback Switch", "AC97 Line Capture Switch",
788 "Line Playback Volume", "AC97 Line Capture Volume",
789 "Aux Playback Switch", "AC97 Aux Capture Switch",
790 "Aux Playback Volume", "AC97 Aux Capture Volume",
791 "Mic Playback Switch", "AC97 Mic Capture Switch",
792 "Mic Playback Volume", "AC97 Mic Capture Volume",
793 "Mic Select", "AC97 Mic Select",
794 "Mic Boost (+20dB)", "AC97 Mic Boost (+20dB)",
795 NULL
796 };
797#if 1
798 for (c = ca0106_remove_ctls; *c; c++)
799 remove_ctl(card, name: *c);
800 for (c = ca0106_rename_ctls; *c; c += 2)
801 rename_ctl(card, src: c[0], dst: c[1]);
802#endif
803
804 ADD_CTLS(emu, snd_ca0106_volume_ctls);
805 if (emu->details->i2c_adc == 1) {
806 ADD_CTLS(emu, snd_ca0106_volume_i2c_adc_ctls);
807 if (emu->details->gpio_type == 1)
808 err = snd_ctl_add(card, kcontrol: snd_ctl_new1(kcontrolnew: &snd_ca0106_capture_mic_line_in, private_data: emu));
809 else /* gpio_type == 2 */
810 err = snd_ctl_add(card, kcontrol: snd_ctl_new1(kcontrolnew: &snd_ca0106_capture_line_in_side_out, private_data: emu));
811 if (err < 0)
812 return err;
813 }
814 if (emu->details->spi_dac) {
815 int i;
816 for (i = 0;; i++) {
817 struct snd_kcontrol_new ctl;
818 ctl = snd_ca0106_volume_spi_dac_ctl(details: emu->details, channel_id: i);
819 if (!ctl.name)
820 break;
821 err = snd_ctl_add(card, kcontrol: snd_ctl_new1(kcontrolnew: &ctl, private_data: emu));
822 if (err < 0)
823 return err;
824 }
825 }
826
827 /* Create virtual master controls */
828 vmaster = snd_ctl_make_virtual_master(name: "Master Playback Volume",
829 tlv: snd_ca0106_master_db_scale);
830 if (!vmaster)
831 return -ENOMEM;
832 err = snd_ctl_add(card, kcontrol: vmaster);
833 if (err < 0)
834 return err;
835 err = snd_ctl_add_followers(card, master: vmaster, list: follower_vols);
836 if (err < 0)
837 return err;
838
839 if (emu->details->spi_dac) {
840 vmaster = snd_ctl_make_virtual_master(name: "Master Playback Switch",
841 NULL);
842 if (!vmaster)
843 return -ENOMEM;
844 err = snd_ctl_add(card, kcontrol: vmaster);
845 if (err < 0)
846 return err;
847 err = snd_ctl_add_followers(card, master: vmaster, list: follower_sws);
848 if (err < 0)
849 return err;
850 }
851
852 strcpy(p: card->mixername, q: "CA0106");
853 return 0;
854}
855
856#ifdef CONFIG_PM_SLEEP
857struct ca0106_vol_tbl {
858 unsigned int channel_id;
859 unsigned int reg;
860};
861
862static const struct ca0106_vol_tbl saved_volumes[NUM_SAVED_VOLUMES] = {
863 { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2 },
864 { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2 },
865 { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2 },
866 { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2 },
867 { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1 },
868 { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1 },
869 { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1 },
870 { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1 },
871 { 1, CAPTURE_CONTROL },
872};
873
874void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip)
875{
876 int i;
877
878 /* save volumes */
879 for (i = 0; i < NUM_SAVED_VOLUMES; i++)
880 chip->saved_vol[i] =
881 snd_ca0106_ptr_read(emu: chip, reg: saved_volumes[i].reg,
882 chn: saved_volumes[i].channel_id);
883}
884
885void snd_ca0106_mixer_resume(struct snd_ca0106 *chip)
886{
887 int i;
888
889 for (i = 0; i < NUM_SAVED_VOLUMES; i++)
890 snd_ca0106_ptr_write(emu: chip, reg: saved_volumes[i].reg,
891 chn: saved_volumes[i].channel_id,
892 data: chip->saved_vol[i]);
893
894 ca0106_spdif_enable(emu: chip);
895 ca0106_set_capture_source(emu: chip);
896 ca0106_set_i2c_capture_source(emu: chip, val: chip->i2c_capture_source, force: 1);
897 for (i = 0; i < 4; i++)
898 ca0106_set_spdif_bits(emu: chip, idx: i);
899 if (chip->details->i2c_adc)
900 ca0106_set_capture_mic_line_in(emu: chip);
901}
902#endif /* CONFIG_PM_SLEEP */
903

source code of linux/sound/pci/ca0106/ca0106_mixer.c