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