Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/pci/ctxfi/ctmixer.c
26451 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
4
*
5
* @File ctmixer.c
6
*
7
* @Brief
8
* This file contains the implementation of alsa mixer device functions.
9
*
10
* @Author Liu Chun
11
* @Date May 28 2008
12
*/
13
14
15
#include "ctmixer.h"
16
#include "ctamixer.h"
17
#include <linux/slab.h>
18
#include <sound/core.h>
19
#include <sound/control.h>
20
#include <sound/asoundef.h>
21
#include <sound/pcm.h>
22
#include <sound/tlv.h>
23
24
enum CT_SUM_CTL {
25
SUM_IN_F,
26
SUM_IN_R,
27
SUM_IN_C,
28
SUM_IN_S,
29
SUM_IN_F_C,
30
31
NUM_CT_SUMS
32
};
33
34
enum CT_AMIXER_CTL {
35
/* volume control mixers */
36
AMIXER_MASTER_F,
37
AMIXER_MASTER_R,
38
AMIXER_MASTER_C,
39
AMIXER_MASTER_S,
40
AMIXER_PCM_F,
41
AMIXER_PCM_R,
42
AMIXER_PCM_C,
43
AMIXER_PCM_S,
44
AMIXER_SPDIFI,
45
AMIXER_LINEIN,
46
AMIXER_MIC,
47
AMIXER_SPDIFO,
48
AMIXER_WAVE_F,
49
AMIXER_WAVE_R,
50
AMIXER_WAVE_C,
51
AMIXER_WAVE_S,
52
AMIXER_MASTER_F_C,
53
AMIXER_PCM_F_C,
54
AMIXER_SPDIFI_C,
55
AMIXER_LINEIN_C,
56
AMIXER_MIC_C,
57
58
/* this should always be the last one */
59
NUM_CT_AMIXERS
60
};
61
62
enum CTALSA_MIXER_CTL {
63
/* volume control mixers */
64
MIXER_MASTER_P,
65
MIXER_PCM_P,
66
MIXER_LINEIN_P,
67
MIXER_MIC_P,
68
MIXER_SPDIFI_P,
69
MIXER_SPDIFO_P,
70
MIXER_WAVEF_P,
71
MIXER_WAVER_P,
72
MIXER_WAVEC_P,
73
MIXER_WAVES_P,
74
MIXER_MASTER_C,
75
MIXER_PCM_C,
76
MIXER_LINEIN_C,
77
MIXER_MIC_C,
78
MIXER_SPDIFI_C,
79
80
/* switch control mixers */
81
MIXER_PCM_C_S,
82
MIXER_LINEIN_C_S,
83
MIXER_MIC_C_S,
84
MIXER_SPDIFI_C_S,
85
MIXER_SPDIFO_P_S,
86
MIXER_WAVEF_P_S,
87
MIXER_WAVER_P_S,
88
MIXER_WAVEC_P_S,
89
MIXER_WAVES_P_S,
90
MIXER_DIGITAL_IO_S,
91
MIXER_IEC958_MASK,
92
MIXER_IEC958_DEFAULT,
93
MIXER_IEC958_STREAM,
94
95
/* this should always be the last one */
96
NUM_CTALSA_MIXERS
97
};
98
99
#define VOL_MIXER_START MIXER_MASTER_P
100
#define VOL_MIXER_END MIXER_SPDIFI_C
101
#define VOL_MIXER_NUM (VOL_MIXER_END - VOL_MIXER_START + 1)
102
#define SWH_MIXER_START MIXER_PCM_C_S
103
#define SWH_MIXER_END MIXER_DIGITAL_IO_S
104
#define SWH_CAPTURE_START MIXER_PCM_C_S
105
#define SWH_CAPTURE_END MIXER_SPDIFI_C_S
106
107
#define CHN_NUM 2
108
109
struct ct_kcontrol_init {
110
unsigned char ctl;
111
char *name;
112
};
113
114
static struct ct_kcontrol_init
115
ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = {
116
[MIXER_MASTER_P] = {
117
.ctl = 1,
118
.name = "Master Playback Volume",
119
},
120
[MIXER_MASTER_C] = {
121
.ctl = 1,
122
.name = "Master Capture Volume",
123
},
124
[MIXER_PCM_P] = {
125
.ctl = 1,
126
.name = "PCM Playback Volume",
127
},
128
[MIXER_PCM_C] = {
129
.ctl = 1,
130
.name = "PCM Capture Volume",
131
},
132
[MIXER_LINEIN_P] = {
133
.ctl = 1,
134
.name = "Line Playback Volume",
135
},
136
[MIXER_LINEIN_C] = {
137
.ctl = 1,
138
.name = "Line Capture Volume",
139
},
140
[MIXER_MIC_P] = {
141
.ctl = 1,
142
.name = "Mic Playback Volume",
143
},
144
[MIXER_MIC_C] = {
145
.ctl = 1,
146
.name = "Mic Capture Volume",
147
},
148
[MIXER_SPDIFI_P] = {
149
.ctl = 1,
150
.name = "IEC958 Playback Volume",
151
},
152
[MIXER_SPDIFI_C] = {
153
.ctl = 1,
154
.name = "IEC958 Capture Volume",
155
},
156
[MIXER_SPDIFO_P] = {
157
.ctl = 1,
158
.name = "Digital Playback Volume",
159
},
160
[MIXER_WAVEF_P] = {
161
.ctl = 1,
162
.name = "Front Playback Volume",
163
},
164
[MIXER_WAVES_P] = {
165
.ctl = 1,
166
.name = "Side Playback Volume",
167
},
168
[MIXER_WAVEC_P] = {
169
.ctl = 1,
170
.name = "Center/LFE Playback Volume",
171
},
172
[MIXER_WAVER_P] = {
173
.ctl = 1,
174
.name = "Surround Playback Volume",
175
},
176
[MIXER_PCM_C_S] = {
177
.ctl = 1,
178
.name = "PCM Capture Switch",
179
},
180
[MIXER_LINEIN_C_S] = {
181
.ctl = 1,
182
.name = "Line Capture Switch",
183
},
184
[MIXER_MIC_C_S] = {
185
.ctl = 1,
186
.name = "Mic Capture Switch",
187
},
188
[MIXER_SPDIFI_C_S] = {
189
.ctl = 1,
190
.name = "IEC958 Capture Switch",
191
},
192
[MIXER_SPDIFO_P_S] = {
193
.ctl = 1,
194
.name = "Digital Playback Switch",
195
},
196
[MIXER_WAVEF_P_S] = {
197
.ctl = 1,
198
.name = "Front Playback Switch",
199
},
200
[MIXER_WAVES_P_S] = {
201
.ctl = 1,
202
.name = "Side Playback Switch",
203
},
204
[MIXER_WAVEC_P_S] = {
205
.ctl = 1,
206
.name = "Center/LFE Playback Switch",
207
},
208
[MIXER_WAVER_P_S] = {
209
.ctl = 1,
210
.name = "Surround Playback Switch",
211
},
212
[MIXER_DIGITAL_IO_S] = {
213
.ctl = 0,
214
.name = "Digit-IO Playback Switch",
215
},
216
};
217
218
static void
219
ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
220
221
static void
222
ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
223
224
/* FIXME: this static looks like it would fail if more than one card was */
225
/* installed. */
226
static struct snd_kcontrol *kctls[2] = {NULL};
227
228
static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index)
229
{
230
switch (alsa_index) {
231
case MIXER_MASTER_P: return AMIXER_MASTER_F;
232
case MIXER_MASTER_C: return AMIXER_MASTER_F_C;
233
case MIXER_PCM_P: return AMIXER_PCM_F;
234
case MIXER_PCM_C:
235
case MIXER_PCM_C_S: return AMIXER_PCM_F_C;
236
case MIXER_LINEIN_P: return AMIXER_LINEIN;
237
case MIXER_LINEIN_C:
238
case MIXER_LINEIN_C_S: return AMIXER_LINEIN_C;
239
case MIXER_MIC_P: return AMIXER_MIC;
240
case MIXER_MIC_C:
241
case MIXER_MIC_C_S: return AMIXER_MIC_C;
242
case MIXER_SPDIFI_P: return AMIXER_SPDIFI;
243
case MIXER_SPDIFI_C:
244
case MIXER_SPDIFI_C_S: return AMIXER_SPDIFI_C;
245
case MIXER_SPDIFO_P: return AMIXER_SPDIFO;
246
case MIXER_WAVEF_P: return AMIXER_WAVE_F;
247
case MIXER_WAVES_P: return AMIXER_WAVE_S;
248
case MIXER_WAVEC_P: return AMIXER_WAVE_C;
249
case MIXER_WAVER_P: return AMIXER_WAVE_R;
250
default: return NUM_CT_AMIXERS;
251
}
252
}
253
254
static enum CT_AMIXER_CTL get_recording_amixer(enum CT_AMIXER_CTL index)
255
{
256
switch (index) {
257
case AMIXER_MASTER_F: return AMIXER_MASTER_F_C;
258
case AMIXER_PCM_F: return AMIXER_PCM_F_C;
259
case AMIXER_SPDIFI: return AMIXER_SPDIFI_C;
260
case AMIXER_LINEIN: return AMIXER_LINEIN_C;
261
case AMIXER_MIC: return AMIXER_MIC_C;
262
default: return NUM_CT_AMIXERS;
263
}
264
}
265
266
static unsigned char
267
get_switch_state(struct ct_mixer *mixer, enum CTALSA_MIXER_CTL type)
268
{
269
return (mixer->switch_state & (0x1 << (type - SWH_MIXER_START)))
270
? 1 : 0;
271
}
272
273
static void
274
set_switch_state(struct ct_mixer *mixer,
275
enum CTALSA_MIXER_CTL type, unsigned char state)
276
{
277
if (state)
278
mixer->switch_state |= (0x1 << (type - SWH_MIXER_START));
279
else
280
mixer->switch_state &= ~(0x1 << (type - SWH_MIXER_START));
281
}
282
283
#if 0 /* not used */
284
/* Map integer value ranging from 0 to 65535 to 14-bit float value ranging
285
* from 2^-6 to (1+1023/1024) */
286
static unsigned int uint16_to_float14(unsigned int x)
287
{
288
unsigned int i;
289
290
if (x < 17)
291
return 0;
292
293
x *= 2031;
294
x /= 65535;
295
x += 16;
296
297
/* i <= 6 */
298
for (i = 0; !(x & 0x400); i++)
299
x <<= 1;
300
301
x = (((7 - i) & 0x7) << 10) | (x & 0x3ff);
302
303
return x;
304
}
305
306
static unsigned int float14_to_uint16(unsigned int x)
307
{
308
unsigned int e;
309
310
if (!x)
311
return x;
312
313
e = (x >> 10) & 0x7;
314
x &= 0x3ff;
315
x += 1024;
316
x >>= (7 - e);
317
x -= 16;
318
x *= 65535;
319
x /= 2031;
320
321
return x;
322
}
323
#endif /* not used */
324
325
#define VOL_SCALE 0x1c
326
#define VOL_MAX 0x100
327
328
static const DECLARE_TLV_DB_SCALE(ct_vol_db_scale, -6400, 25, 1);
329
330
static int ct_alsa_mix_volume_info(struct snd_kcontrol *kcontrol,
331
struct snd_ctl_elem_info *uinfo)
332
{
333
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
334
uinfo->count = 2;
335
uinfo->value.integer.min = 0;
336
uinfo->value.integer.max = VOL_MAX;
337
338
return 0;
339
}
340
341
static int ct_alsa_mix_volume_get(struct snd_kcontrol *kcontrol,
342
struct snd_ctl_elem_value *ucontrol)
343
{
344
struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
345
enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value);
346
struct amixer *amixer;
347
int i, val;
348
349
for (i = 0; i < 2; i++) {
350
amixer = ((struct ct_mixer *)atc->mixer)->
351
amixers[type*CHN_NUM+i];
352
val = amixer->ops->get_scale(amixer) / VOL_SCALE;
353
if (val < 0)
354
val = 0;
355
else if (val > VOL_MAX)
356
val = VOL_MAX;
357
ucontrol->value.integer.value[i] = val;
358
}
359
360
return 0;
361
}
362
363
static int ct_alsa_mix_volume_put(struct snd_kcontrol *kcontrol,
364
struct snd_ctl_elem_value *ucontrol)
365
{
366
struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
367
struct ct_mixer *mixer = atc->mixer;
368
enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value);
369
struct amixer *amixer;
370
int i, j, val, oval, change = 0;
371
372
for (i = 0; i < 2; i++) {
373
val = ucontrol->value.integer.value[i];
374
if (val < 0)
375
val = 0;
376
else if (val > VOL_MAX)
377
val = VOL_MAX;
378
val *= VOL_SCALE;
379
amixer = mixer->amixers[type*CHN_NUM+i];
380
oval = amixer->ops->get_scale(amixer);
381
if (val != oval) {
382
amixer->ops->set_scale(amixer, val);
383
amixer->ops->commit_write(amixer);
384
change = 1;
385
/* Synchronize Master/PCM playback AMIXERs. */
386
if (AMIXER_MASTER_F == type || AMIXER_PCM_F == type) {
387
for (j = 1; j < 4; j++) {
388
amixer = mixer->
389
amixers[(type+j)*CHN_NUM+i];
390
amixer->ops->set_scale(amixer, val);
391
amixer->ops->commit_write(amixer);
392
}
393
}
394
}
395
}
396
397
return change;
398
}
399
400
static struct snd_kcontrol_new vol_ctl = {
401
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
402
SNDRV_CTL_ELEM_ACCESS_TLV_READ,
403
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
404
.info = ct_alsa_mix_volume_info,
405
.get = ct_alsa_mix_volume_get,
406
.put = ct_alsa_mix_volume_put,
407
.tlv = { .p = ct_vol_db_scale },
408
};
409
410
static int output_switch_info(struct snd_kcontrol *kcontrol,
411
struct snd_ctl_elem_info *info)
412
{
413
static const char *const names[3] = {
414
"FP Headphones", "Headphones", "Speakers"
415
};
416
417
return snd_ctl_enum_info(info, 1, 3, names);
418
}
419
420
static int output_switch_get(struct snd_kcontrol *kcontrol,
421
struct snd_ctl_elem_value *ucontrol)
422
{
423
struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
424
ucontrol->value.enumerated.item[0] = atc->output_switch_get(atc);
425
return 0;
426
}
427
428
static int output_switch_put(struct snd_kcontrol *kcontrol,
429
struct snd_ctl_elem_value *ucontrol)
430
{
431
struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
432
if (ucontrol->value.enumerated.item[0] > 2)
433
return -EINVAL;
434
return atc->output_switch_put(atc, ucontrol->value.enumerated.item[0]);
435
}
436
437
static struct snd_kcontrol_new output_ctl = {
438
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
439
.name = "Analog Output Playback Enum",
440
.info = output_switch_info,
441
.get = output_switch_get,
442
.put = output_switch_put,
443
};
444
445
static int mic_source_switch_info(struct snd_kcontrol *kcontrol,
446
struct snd_ctl_elem_info *info)
447
{
448
static const char *const names[3] = {
449
"Mic", "FP Mic", "Aux"
450
};
451
452
return snd_ctl_enum_info(info, 1, 3, names);
453
}
454
455
static int mic_source_switch_get(struct snd_kcontrol *kcontrol,
456
struct snd_ctl_elem_value *ucontrol)
457
{
458
struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
459
ucontrol->value.enumerated.item[0] = atc->mic_source_switch_get(atc);
460
return 0;
461
}
462
463
static int mic_source_switch_put(struct snd_kcontrol *kcontrol,
464
struct snd_ctl_elem_value *ucontrol)
465
{
466
struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
467
if (ucontrol->value.enumerated.item[0] > 2)
468
return -EINVAL;
469
return atc->mic_source_switch_put(atc,
470
ucontrol->value.enumerated.item[0]);
471
}
472
473
static struct snd_kcontrol_new mic_source_ctl = {
474
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
475
.name = "Mic Source Capture Enum",
476
.info = mic_source_switch_info,
477
.get = mic_source_switch_get,
478
.put = mic_source_switch_put,
479
};
480
481
static void
482
do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type)
483
{
484
485
if (MIXER_LINEIN_C_S == type) {
486
atc->select_line_in(atc);
487
set_switch_state(atc->mixer, MIXER_MIC_C_S, 0);
488
snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE,
489
&kctls[1]->id);
490
} else if (MIXER_MIC_C_S == type) {
491
atc->select_mic_in(atc);
492
set_switch_state(atc->mixer, MIXER_LINEIN_C_S, 0);
493
snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE,
494
&kctls[0]->id);
495
}
496
}
497
498
static void
499
do_digit_io_switch(struct ct_atc *atc, int state)
500
{
501
struct ct_mixer *mixer = atc->mixer;
502
503
if (state) {
504
atc->select_digit_io(atc);
505
atc->spdif_out_unmute(atc,
506
get_switch_state(mixer, MIXER_SPDIFO_P_S));
507
atc->spdif_in_unmute(atc, 1);
508
atc->line_in_unmute(atc, 0);
509
return;
510
}
511
512
if (get_switch_state(mixer, MIXER_LINEIN_C_S))
513
atc->select_line_in(atc);
514
else if (get_switch_state(mixer, MIXER_MIC_C_S))
515
atc->select_mic_in(atc);
516
517
atc->spdif_out_unmute(atc, 0);
518
atc->spdif_in_unmute(atc, 0);
519
atc->line_in_unmute(atc, 1);
520
return;
521
}
522
523
static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state)
524
{
525
struct ct_mixer *mixer = atc->mixer;
526
struct capabilities cap = atc->capabilities(atc);
527
528
/* Do changes in mixer. */
529
if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) {
530
if (state) {
531
ct_mixer_recording_select(mixer,
532
get_amixer_index(type));
533
} else {
534
ct_mixer_recording_unselect(mixer,
535
get_amixer_index(type));
536
}
537
}
538
/* Do changes out of mixer. */
539
if (!cap.dedicated_mic &&
540
(MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type)) {
541
if (state)
542
do_line_mic_switch(atc, type);
543
atc->line_in_unmute(atc, state);
544
} else if (cap.dedicated_mic && (MIXER_LINEIN_C_S == type))
545
atc->line_in_unmute(atc, state);
546
else if (cap.dedicated_mic && (MIXER_MIC_C_S == type))
547
atc->mic_unmute(atc, state);
548
else if (MIXER_SPDIFI_C_S == type)
549
atc->spdif_in_unmute(atc, state);
550
else if (MIXER_WAVEF_P_S == type)
551
atc->line_front_unmute(atc, state);
552
else if (MIXER_WAVES_P_S == type)
553
atc->line_surround_unmute(atc, state);
554
else if (MIXER_WAVEC_P_S == type)
555
atc->line_clfe_unmute(atc, state);
556
else if (MIXER_WAVER_P_S == type)
557
atc->line_rear_unmute(atc, state);
558
else if (MIXER_SPDIFO_P_S == type)
559
atc->spdif_out_unmute(atc, state);
560
else if (MIXER_DIGITAL_IO_S == type)
561
do_digit_io_switch(atc, state);
562
563
return;
564
}
565
566
static int ct_alsa_mix_switch_info(struct snd_kcontrol *kcontrol,
567
struct snd_ctl_elem_info *uinfo)
568
{
569
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
570
uinfo->count = 1;
571
uinfo->value.integer.min = 0;
572
uinfo->value.integer.max = 1;
573
uinfo->value.integer.step = 1;
574
575
return 0;
576
}
577
578
static int ct_alsa_mix_switch_get(struct snd_kcontrol *kcontrol,
579
struct snd_ctl_elem_value *ucontrol)
580
{
581
struct ct_mixer *mixer =
582
((struct ct_atc *)snd_kcontrol_chip(kcontrol))->mixer;
583
enum CTALSA_MIXER_CTL type = kcontrol->private_value;
584
585
ucontrol->value.integer.value[0] = get_switch_state(mixer, type);
586
return 0;
587
}
588
589
static int ct_alsa_mix_switch_put(struct snd_kcontrol *kcontrol,
590
struct snd_ctl_elem_value *ucontrol)
591
{
592
struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
593
struct ct_mixer *mixer = atc->mixer;
594
enum CTALSA_MIXER_CTL type = kcontrol->private_value;
595
int state;
596
597
state = ucontrol->value.integer.value[0];
598
if (get_switch_state(mixer, type) == state)
599
return 0;
600
601
set_switch_state(mixer, type, state);
602
do_switch(atc, type, state);
603
604
return 1;
605
}
606
607
static struct snd_kcontrol_new swh_ctl = {
608
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
609
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
610
.info = ct_alsa_mix_switch_info,
611
.get = ct_alsa_mix_switch_get,
612
.put = ct_alsa_mix_switch_put
613
};
614
615
static int ct_spdif_info(struct snd_kcontrol *kcontrol,
616
struct snd_ctl_elem_info *uinfo)
617
{
618
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
619
uinfo->count = 1;
620
return 0;
621
}
622
623
static int ct_spdif_get_mask(struct snd_kcontrol *kcontrol,
624
struct snd_ctl_elem_value *ucontrol)
625
{
626
ucontrol->value.iec958.status[0] = 0xff;
627
ucontrol->value.iec958.status[1] = 0xff;
628
ucontrol->value.iec958.status[2] = 0xff;
629
ucontrol->value.iec958.status[3] = 0xff;
630
return 0;
631
}
632
633
static int ct_spdif_get(struct snd_kcontrol *kcontrol,
634
struct snd_ctl_elem_value *ucontrol)
635
{
636
struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
637
unsigned int status;
638
639
atc->spdif_out_get_status(atc, &status);
640
641
if (status == 0)
642
status = SNDRV_PCM_DEFAULT_CON_SPDIF;
643
644
ucontrol->value.iec958.status[0] = (status >> 0) & 0xff;
645
ucontrol->value.iec958.status[1] = (status >> 8) & 0xff;
646
ucontrol->value.iec958.status[2] = (status >> 16) & 0xff;
647
ucontrol->value.iec958.status[3] = (status >> 24) & 0xff;
648
649
return 0;
650
}
651
652
static int ct_spdif_put(struct snd_kcontrol *kcontrol,
653
struct snd_ctl_elem_value *ucontrol)
654
{
655
struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
656
int change;
657
unsigned int status, old_status;
658
659
status = (ucontrol->value.iec958.status[0] << 0) |
660
(ucontrol->value.iec958.status[1] << 8) |
661
(ucontrol->value.iec958.status[2] << 16) |
662
(ucontrol->value.iec958.status[3] << 24);
663
664
atc->spdif_out_get_status(atc, &old_status);
665
change = (old_status != status);
666
if (change)
667
atc->spdif_out_set_status(atc, status);
668
669
return change;
670
}
671
672
static struct snd_kcontrol_new iec958_mask_ctl = {
673
.access = SNDRV_CTL_ELEM_ACCESS_READ,
674
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
675
.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),
676
.count = 1,
677
.info = ct_spdif_info,
678
.get = ct_spdif_get_mask,
679
.private_value = MIXER_IEC958_MASK
680
};
681
682
static struct snd_kcontrol_new iec958_default_ctl = {
683
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
684
.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
685
.count = 1,
686
.info = ct_spdif_info,
687
.get = ct_spdif_get,
688
.put = ct_spdif_put,
689
.private_value = MIXER_IEC958_DEFAULT
690
};
691
692
static struct snd_kcontrol_new iec958_ctl = {
693
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
694
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
695
.name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM),
696
.count = 1,
697
.info = ct_spdif_info,
698
.get = ct_spdif_get,
699
.put = ct_spdif_put,
700
.private_value = MIXER_IEC958_STREAM
701
};
702
703
#define NUM_IEC958_CTL 3
704
705
static int
706
ct_mixer_kcontrol_new(struct ct_mixer *mixer, struct snd_kcontrol_new *new)
707
{
708
struct snd_kcontrol *kctl;
709
int err;
710
711
kctl = snd_ctl_new1(new, mixer->atc);
712
if (!kctl)
713
return -ENOMEM;
714
715
if (SNDRV_CTL_ELEM_IFACE_PCM == kctl->id.iface)
716
kctl->id.device = IEC958;
717
718
err = snd_ctl_add(mixer->atc->card, kctl);
719
if (err)
720
return err;
721
722
switch (new->private_value) {
723
case MIXER_LINEIN_C_S:
724
kctls[0] = kctl; break;
725
case MIXER_MIC_C_S:
726
kctls[1] = kctl; break;
727
default:
728
break;
729
}
730
731
return 0;
732
}
733
734
static int ct_mixer_kcontrols_create(struct ct_mixer *mixer)
735
{
736
enum CTALSA_MIXER_CTL type;
737
struct ct_atc *atc = mixer->atc;
738
struct capabilities cap = atc->capabilities(atc);
739
int err;
740
741
/* Create snd kcontrol instances on demand */
742
for (type = VOL_MIXER_START; type <= VOL_MIXER_END; type++) {
743
if (ct_kcontrol_init_table[type].ctl) {
744
vol_ctl.name = ct_kcontrol_init_table[type].name;
745
vol_ctl.private_value = (unsigned long)type;
746
err = ct_mixer_kcontrol_new(mixer, &vol_ctl);
747
if (err)
748
return err;
749
}
750
}
751
752
ct_kcontrol_init_table[MIXER_DIGITAL_IO_S].ctl = cap.digit_io_switch;
753
754
for (type = SWH_MIXER_START; type <= SWH_MIXER_END; type++) {
755
if (ct_kcontrol_init_table[type].ctl) {
756
swh_ctl.name = ct_kcontrol_init_table[type].name;
757
swh_ctl.private_value = (unsigned long)type;
758
err = ct_mixer_kcontrol_new(mixer, &swh_ctl);
759
if (err)
760
return err;
761
}
762
}
763
764
err = ct_mixer_kcontrol_new(mixer, &iec958_mask_ctl);
765
if (err)
766
return err;
767
768
err = ct_mixer_kcontrol_new(mixer, &iec958_default_ctl);
769
if (err)
770
return err;
771
772
err = ct_mixer_kcontrol_new(mixer, &iec958_ctl);
773
if (err)
774
return err;
775
776
if (cap.output_switch) {
777
err = ct_mixer_kcontrol_new(mixer, &output_ctl);
778
if (err)
779
return err;
780
}
781
782
if (cap.mic_source_switch) {
783
err = ct_mixer_kcontrol_new(mixer, &mic_source_ctl);
784
if (err)
785
return err;
786
}
787
atc->line_front_unmute(atc, 1);
788
set_switch_state(mixer, MIXER_WAVEF_P_S, 1);
789
atc->line_surround_unmute(atc, 0);
790
set_switch_state(mixer, MIXER_WAVES_P_S, 0);
791
atc->line_clfe_unmute(atc, 0);
792
set_switch_state(mixer, MIXER_WAVEC_P_S, 0);
793
atc->line_rear_unmute(atc, 0);
794
set_switch_state(mixer, MIXER_WAVER_P_S, 0);
795
atc->spdif_out_unmute(atc, 0);
796
set_switch_state(mixer, MIXER_SPDIFO_P_S, 0);
797
atc->line_in_unmute(atc, 0);
798
if (cap.dedicated_mic)
799
atc->mic_unmute(atc, 0);
800
atc->spdif_in_unmute(atc, 0);
801
set_switch_state(mixer, MIXER_PCM_C_S, 0);
802
set_switch_state(mixer, MIXER_LINEIN_C_S, 0);
803
set_switch_state(mixer, MIXER_SPDIFI_C_S, 0);
804
805
return 0;
806
}
807
808
static void
809
ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type)
810
{
811
struct amixer *amix_d;
812
struct sum *sum_c;
813
int i;
814
815
for (i = 0; i < 2; i++) {
816
amix_d = mixer->amixers[type*CHN_NUM+i];
817
sum_c = mixer->sums[SUM_IN_F_C*CHN_NUM+i];
818
amix_d->ops->set_sum(amix_d, sum_c);
819
amix_d->ops->commit_write(amix_d);
820
}
821
}
822
823
static void
824
ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type)
825
{
826
struct amixer *amix_d;
827
int i;
828
829
for (i = 0; i < 2; i++) {
830
amix_d = mixer->amixers[type*CHN_NUM+i];
831
amix_d->ops->set_sum(amix_d, NULL);
832
amix_d->ops->commit_write(amix_d);
833
}
834
}
835
836
static int ct_mixer_get_resources(struct ct_mixer *mixer)
837
{
838
struct sum_mgr *sum_mgr;
839
struct sum *sum;
840
struct sum_desc sum_desc = {0};
841
struct amixer_mgr *amixer_mgr;
842
struct amixer *amixer;
843
struct amixer_desc am_desc = {0};
844
int err;
845
int i;
846
847
/* Allocate sum resources for mixer obj */
848
sum_mgr = (struct sum_mgr *)mixer->atc->rsc_mgrs[SUM];
849
sum_desc.msr = mixer->atc->msr;
850
for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
851
err = sum_mgr->get_sum(sum_mgr, &sum_desc, &sum);
852
if (err) {
853
dev_err(mixer->atc->card->dev,
854
"Failed to get sum resources for front output!\n");
855
break;
856
}
857
mixer->sums[i] = sum;
858
}
859
if (err)
860
goto error1;
861
862
/* Allocate amixer resources for mixer obj */
863
amixer_mgr = (struct amixer_mgr *)mixer->atc->rsc_mgrs[AMIXER];
864
am_desc.msr = mixer->atc->msr;
865
for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
866
err = amixer_mgr->get_amixer(amixer_mgr, &am_desc, &amixer);
867
if (err) {
868
dev_err(mixer->atc->card->dev,
869
"Failed to get amixer resources for mixer obj!\n");
870
break;
871
}
872
mixer->amixers[i] = amixer;
873
}
874
if (err)
875
goto error2;
876
877
return 0;
878
879
error2:
880
for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
881
if (NULL != mixer->amixers[i]) {
882
amixer = mixer->amixers[i];
883
amixer_mgr->put_amixer(amixer_mgr, amixer);
884
mixer->amixers[i] = NULL;
885
}
886
}
887
error1:
888
for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
889
if (NULL != mixer->sums[i]) {
890
sum_mgr->put_sum(sum_mgr, (struct sum *)mixer->sums[i]);
891
mixer->sums[i] = NULL;
892
}
893
}
894
895
return err;
896
}
897
898
static int ct_mixer_get_mem(struct ct_mixer **rmixer)
899
{
900
struct ct_mixer *mixer;
901
int err;
902
903
*rmixer = NULL;
904
/* Allocate mem for mixer obj */
905
mixer = kzalloc(sizeof(*mixer), GFP_KERNEL);
906
if (!mixer)
907
return -ENOMEM;
908
909
mixer->amixers = kcalloc(NUM_CT_AMIXERS * CHN_NUM, sizeof(void *),
910
GFP_KERNEL);
911
if (!mixer->amixers) {
912
err = -ENOMEM;
913
goto error1;
914
}
915
mixer->sums = kcalloc(NUM_CT_SUMS * CHN_NUM, sizeof(void *),
916
GFP_KERNEL);
917
if (!mixer->sums) {
918
err = -ENOMEM;
919
goto error2;
920
}
921
922
*rmixer = mixer;
923
return 0;
924
925
error2:
926
kfree(mixer->amixers);
927
error1:
928
kfree(mixer);
929
return err;
930
}
931
932
static int ct_mixer_topology_build(struct ct_mixer *mixer)
933
{
934
struct sum *sum;
935
struct amixer *amix_d, *amix_s;
936
enum CT_AMIXER_CTL i, j;
937
enum CT_SUM_CTL k;
938
939
/* Build topology from destination to source */
940
941
/* Set up Master mixer */
942
for (i = AMIXER_MASTER_F, k = SUM_IN_F;
943
i <= AMIXER_MASTER_S; i++, k++) {
944
amix_d = mixer->amixers[i*CHN_NUM];
945
sum = mixer->sums[k*CHN_NUM];
946
amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
947
amix_d = mixer->amixers[i*CHN_NUM+1];
948
sum = mixer->sums[k*CHN_NUM+1];
949
amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
950
}
951
952
/* Set up Wave-out mixer */
953
for (i = AMIXER_WAVE_F, j = AMIXER_MASTER_F;
954
i <= AMIXER_WAVE_S; i++, j++) {
955
amix_d = mixer->amixers[i*CHN_NUM];
956
amix_s = mixer->amixers[j*CHN_NUM];
957
amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
958
amix_d = mixer->amixers[i*CHN_NUM+1];
959
amix_s = mixer->amixers[j*CHN_NUM+1];
960
amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
961
}
962
963
/* Set up S/PDIF-out mixer */
964
amix_d = mixer->amixers[AMIXER_SPDIFO*CHN_NUM];
965
amix_s = mixer->amixers[AMIXER_MASTER_F*CHN_NUM];
966
amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
967
amix_d = mixer->amixers[AMIXER_SPDIFO*CHN_NUM+1];
968
amix_s = mixer->amixers[AMIXER_MASTER_F*CHN_NUM+1];
969
amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
970
971
/* Set up PCM-in mixer */
972
for (i = AMIXER_PCM_F, k = SUM_IN_F; i <= AMIXER_PCM_S; i++, k++) {
973
amix_d = mixer->amixers[i*CHN_NUM];
974
sum = mixer->sums[k*CHN_NUM];
975
amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
976
amix_d = mixer->amixers[i*CHN_NUM+1];
977
sum = mixer->sums[k*CHN_NUM+1];
978
amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
979
}
980
981
/* Set up Line-in mixer */
982
amix_d = mixer->amixers[AMIXER_LINEIN*CHN_NUM];
983
sum = mixer->sums[SUM_IN_F*CHN_NUM];
984
amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
985
amix_d = mixer->amixers[AMIXER_LINEIN*CHN_NUM+1];
986
sum = mixer->sums[SUM_IN_F*CHN_NUM+1];
987
amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
988
989
/* Set up Mic-in mixer */
990
amix_d = mixer->amixers[AMIXER_MIC*CHN_NUM];
991
sum = mixer->sums[SUM_IN_F*CHN_NUM];
992
amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
993
amix_d = mixer->amixers[AMIXER_MIC*CHN_NUM+1];
994
sum = mixer->sums[SUM_IN_F*CHN_NUM+1];
995
amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
996
997
/* Set up S/PDIF-in mixer */
998
amix_d = mixer->amixers[AMIXER_SPDIFI*CHN_NUM];
999
sum = mixer->sums[SUM_IN_F*CHN_NUM];
1000
amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1001
amix_d = mixer->amixers[AMIXER_SPDIFI*CHN_NUM+1];
1002
sum = mixer->sums[SUM_IN_F*CHN_NUM+1];
1003
amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1004
1005
/* Set up Master recording mixer */
1006
amix_d = mixer->amixers[AMIXER_MASTER_F_C*CHN_NUM];
1007
sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
1008
amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
1009
amix_d = mixer->amixers[AMIXER_MASTER_F_C*CHN_NUM+1];
1010
sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
1011
amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
1012
1013
/* Set up PCM-in recording mixer */
1014
amix_d = mixer->amixers[AMIXER_PCM_F_C*CHN_NUM];
1015
sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
1016
amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1017
amix_d = mixer->amixers[AMIXER_PCM_F_C*CHN_NUM+1];
1018
sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
1019
amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1020
1021
/* Set up Line-in recording mixer */
1022
amix_d = mixer->amixers[AMIXER_LINEIN_C*CHN_NUM];
1023
sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
1024
amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1025
amix_d = mixer->amixers[AMIXER_LINEIN_C*CHN_NUM+1];
1026
sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
1027
amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1028
1029
/* Set up Mic-in recording mixer */
1030
amix_d = mixer->amixers[AMIXER_MIC_C*CHN_NUM];
1031
sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
1032
amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1033
amix_d = mixer->amixers[AMIXER_MIC_C*CHN_NUM+1];
1034
sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
1035
amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1036
1037
/* Set up S/PDIF-in recording mixer */
1038
amix_d = mixer->amixers[AMIXER_SPDIFI_C*CHN_NUM];
1039
sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
1040
amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1041
amix_d = mixer->amixers[AMIXER_SPDIFI_C*CHN_NUM+1];
1042
sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
1043
amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1044
1045
return 0;
1046
}
1047
1048
static int mixer_set_input_port(struct amixer *amixer, struct rsc *rsc)
1049
{
1050
amixer->ops->set_input(amixer, rsc);
1051
amixer->ops->commit_write(amixer);
1052
1053
return 0;
1054
}
1055
1056
static enum CT_AMIXER_CTL port_to_amixer(enum MIXER_PORT_T type)
1057
{
1058
switch (type) {
1059
case MIX_WAVE_FRONT: return AMIXER_WAVE_F;
1060
case MIX_WAVE_SURROUND: return AMIXER_WAVE_S;
1061
case MIX_WAVE_CENTLFE: return AMIXER_WAVE_C;
1062
case MIX_WAVE_REAR: return AMIXER_WAVE_R;
1063
case MIX_PCMO_FRONT: return AMIXER_MASTER_F_C;
1064
case MIX_SPDIF_OUT: return AMIXER_SPDIFO;
1065
case MIX_LINE_IN: return AMIXER_LINEIN;
1066
case MIX_MIC_IN: return AMIXER_MIC;
1067
case MIX_SPDIF_IN: return AMIXER_SPDIFI;
1068
case MIX_PCMI_FRONT: return AMIXER_PCM_F;
1069
case MIX_PCMI_SURROUND: return AMIXER_PCM_S;
1070
case MIX_PCMI_CENTLFE: return AMIXER_PCM_C;
1071
case MIX_PCMI_REAR: return AMIXER_PCM_R;
1072
default: return 0;
1073
}
1074
}
1075
1076
static int mixer_get_output_ports(struct ct_mixer *mixer,
1077
enum MIXER_PORT_T type,
1078
struct rsc **rleft, struct rsc **rright)
1079
{
1080
enum CT_AMIXER_CTL amix = port_to_amixer(type);
1081
1082
if (NULL != rleft)
1083
*rleft = &((struct amixer *)mixer->amixers[amix*CHN_NUM])->rsc;
1084
1085
if (NULL != rright)
1086
*rright =
1087
&((struct amixer *)mixer->amixers[amix*CHN_NUM+1])->rsc;
1088
1089
return 0;
1090
}
1091
1092
static int mixer_set_input_left(struct ct_mixer *mixer,
1093
enum MIXER_PORT_T type, struct rsc *rsc)
1094
{
1095
enum CT_AMIXER_CTL amix = port_to_amixer(type);
1096
1097
mixer_set_input_port(mixer->amixers[amix*CHN_NUM], rsc);
1098
amix = get_recording_amixer(amix);
1099
if (amix < NUM_CT_AMIXERS)
1100
mixer_set_input_port(mixer->amixers[amix*CHN_NUM], rsc);
1101
1102
return 0;
1103
}
1104
1105
static int
1106
mixer_set_input_right(struct ct_mixer *mixer,
1107
enum MIXER_PORT_T type, struct rsc *rsc)
1108
{
1109
enum CT_AMIXER_CTL amix = port_to_amixer(type);
1110
1111
mixer_set_input_port(mixer->amixers[amix*CHN_NUM+1], rsc);
1112
amix = get_recording_amixer(amix);
1113
if (amix < NUM_CT_AMIXERS)
1114
mixer_set_input_port(mixer->amixers[amix*CHN_NUM+1], rsc);
1115
1116
return 0;
1117
}
1118
1119
#ifdef CONFIG_PM_SLEEP
1120
static int mixer_resume(struct ct_mixer *mixer)
1121
{
1122
int i, state;
1123
struct amixer *amixer;
1124
1125
/* resume topology and volume gain. */
1126
for (i = 0; i < NUM_CT_AMIXERS*CHN_NUM; i++) {
1127
amixer = mixer->amixers[i];
1128
amixer->ops->commit_write(amixer);
1129
}
1130
1131
/* resume switch state. */
1132
for (i = SWH_MIXER_START; i <= SWH_MIXER_END; i++) {
1133
state = get_switch_state(mixer, i);
1134
do_switch(mixer->atc, i, state);
1135
}
1136
1137
return 0;
1138
}
1139
#endif
1140
1141
int ct_mixer_destroy(struct ct_mixer *mixer)
1142
{
1143
struct sum_mgr *sum_mgr = (struct sum_mgr *)mixer->atc->rsc_mgrs[SUM];
1144
struct amixer_mgr *amixer_mgr =
1145
(struct amixer_mgr *)mixer->atc->rsc_mgrs[AMIXER];
1146
struct amixer *amixer;
1147
int i = 0;
1148
1149
/* Release amixer resources */
1150
for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
1151
if (NULL != mixer->amixers[i]) {
1152
amixer = mixer->amixers[i];
1153
amixer_mgr->put_amixer(amixer_mgr, amixer);
1154
}
1155
}
1156
1157
/* Release sum resources */
1158
for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
1159
if (NULL != mixer->sums[i])
1160
sum_mgr->put_sum(sum_mgr, (struct sum *)mixer->sums[i]);
1161
}
1162
1163
/* Release mem assigned to mixer object */
1164
kfree(mixer->sums);
1165
kfree(mixer->amixers);
1166
kfree(mixer);
1167
1168
return 0;
1169
}
1170
1171
int ct_mixer_create(struct ct_atc *atc, struct ct_mixer **rmixer)
1172
{
1173
struct ct_mixer *mixer;
1174
int err;
1175
1176
*rmixer = NULL;
1177
1178
/* Allocate mem for mixer obj */
1179
err = ct_mixer_get_mem(&mixer);
1180
if (err)
1181
return err;
1182
1183
mixer->switch_state = 0;
1184
mixer->atc = atc;
1185
/* Set operations */
1186
mixer->get_output_ports = mixer_get_output_ports;
1187
mixer->set_input_left = mixer_set_input_left;
1188
mixer->set_input_right = mixer_set_input_right;
1189
#ifdef CONFIG_PM_SLEEP
1190
mixer->resume = mixer_resume;
1191
#endif
1192
1193
/* Allocate chip resources for mixer obj */
1194
err = ct_mixer_get_resources(mixer);
1195
if (err)
1196
goto error;
1197
1198
/* Build internal mixer topology */
1199
ct_mixer_topology_build(mixer);
1200
1201
*rmixer = mixer;
1202
1203
return 0;
1204
1205
error:
1206
ct_mixer_destroy(mixer);
1207
return err;
1208
}
1209
1210
int ct_alsa_mix_create(struct ct_atc *atc,
1211
enum CTALSADEVS device,
1212
const char *device_name)
1213
{
1214
int err;
1215
1216
/* Create snd kcontrol instances on demand */
1217
/* vol_ctl.device = swh_ctl.device = device; */ /* better w/ device 0 */
1218
err = ct_mixer_kcontrols_create((struct ct_mixer *)atc->mixer);
1219
if (err)
1220
return err;
1221
1222
strscpy(atc->card->mixername, device_name);
1223
1224
return 0;
1225
}
1226
1227