Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/usb/mixer_us16x08.c
51969 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Tascam US-16x08 ALSA driver
4
*
5
* Copyright (c) 2016 by Detlef Urban ([email protected])
6
*/
7
8
#include <linux/slab.h>
9
#include <linux/usb.h>
10
#include <linux/usb/audio-v2.h>
11
12
#include <sound/core.h>
13
#include <sound/control.h>
14
15
#include "usbaudio.h"
16
#include "mixer.h"
17
#include "helper.h"
18
19
#include "mixer_us16x08.h"
20
21
/* USB control message templates */
22
static const char route_msg[] = {
23
0x61,
24
0x02,
25
0x03, /* input from master (0x02) or input from computer bus (0x03) */
26
0x62,
27
0x02,
28
0x01, /* input index (0x01/0x02 eq. left/right) or bus (0x01-0x08) */
29
0x41,
30
0x01,
31
0x61,
32
0x02,
33
0x01,
34
0x62,
35
0x02,
36
0x01, /* output index (0x01-0x08) */
37
0x42,
38
0x01,
39
0x43,
40
0x01,
41
0x00,
42
0x00
43
};
44
45
static const char mix_init_msg1[] = {
46
0x71, 0x01, 0x00, 0x00
47
};
48
49
static const char mix_init_msg2[] = {
50
0x62, 0x02, 0x00, 0x61, 0x02, 0x04, 0xb1, 0x01, 0x00, 0x00
51
};
52
53
static const char mix_msg_in[] = {
54
/* default message head, equal to all mixers */
55
0x61, 0x02, 0x04, 0x62, 0x02, 0x01,
56
0x81, /* 0x06: Controller ID */
57
0x02, /* 0x07: */
58
0x00, /* 0x08: Value of common mixer */
59
0x00,
60
0x00
61
};
62
63
static const char mix_msg_out[] = {
64
/* default message head, equal to all mixers */
65
0x61, 0x02, 0x02, 0x62, 0x02, 0x01,
66
0x81, /* 0x06: Controller ID */
67
0x02, /* 0x07: */
68
0x00, /* 0x08: Value of common mixer */
69
0x00,
70
0x00
71
};
72
73
static const char bypass_msg_out[] = {
74
0x45,
75
0x02,
76
0x01, /* on/off flag */
77
0x00,
78
0x00
79
};
80
81
static const char bus_msg_out[] = {
82
0x44,
83
0x02,
84
0x01, /* on/off flag */
85
0x00,
86
0x00
87
};
88
89
static const char comp_msg[] = {
90
/* default message head, equal to all mixers */
91
0x61, 0x02, 0x04, 0x62, 0x02, 0x01,
92
0x91,
93
0x02,
94
0xf0, /* 0x08: Threshold db (8) (e0 ... 00) (+-0dB -- -32dB) x-32 */
95
0x92,
96
0x02,
97
0x0a, /* 0x0b: Ratio (0a,0b,0d,0f,11,14,19,1e,23,28,32,3c,50,a0,ff) */
98
0x93,
99
0x02,
100
0x02, /* 0x0e: Attack (0x02 ... 0xc0) (2ms ... 200ms) */
101
0x94,
102
0x02,
103
0x01, /* 0x11: Release (0x01 ... 0x64) (10ms ... 1000ms) x*10 */
104
0x95,
105
0x02,
106
0x03, /* 0x14: gain (0 ... 20) (0dB .. 20dB) */
107
0x96,
108
0x02,
109
0x01,
110
0x97,
111
0x02,
112
0x01, /* 0x1a: main Comp switch (0 ... 1) (off ... on)) */
113
0x00,
114
0x00
115
};
116
117
static const char eqs_msq[] = {
118
/* default message head, equal to all mixers */
119
0x61, 0x02, 0x04, 0x62, 0x02, 0x01,
120
0x51, /* 0x06: Controller ID */
121
0x02,
122
0x04, /* 0x08: EQ set num (0x01..0x04) (LOW, LOWMID, HIGHMID, HIGH)) */
123
0x52,
124
0x02,
125
0x0c, /* 0x0b: value dB (0 ... 12) (-12db .. +12db) x-6 */
126
0x53,
127
0x02,
128
0x0f, /* 0x0e: value freq (32-47) (1.7kHz..18kHz) */
129
0x54,
130
0x02,
131
0x02, /* 0x11: band width (0-6) (Q16-Q0.25) 2^x/4 (EQ xxMID only) */
132
0x55,
133
0x02,
134
0x01, /* 0x14: main EQ switch (0 ... 1) (off ... on)) */
135
0x00,
136
0x00
137
};
138
139
/* compressor ratio map */
140
static const char ratio_map[] = {
141
0x0a, 0x0b, 0x0d, 0x0f, 0x11, 0x14, 0x19, 0x1e,
142
0x23, 0x28, 0x32, 0x3c, 0x50, 0xa0, 0xff
143
};
144
145
/* route enumeration names */
146
static const char *const route_names[] = {
147
"Master Left", "Master Right", "Output 1", "Output 2", "Output 3",
148
"Output 4", "Output 5", "Output 6", "Output 7", "Output 8",
149
};
150
151
static int snd_us16x08_recv_urb(struct snd_usb_audio *chip,
152
unsigned char *buf, int size)
153
{
154
155
guard(mutex)(&chip->mutex);
156
snd_usb_ctl_msg(chip->dev,
157
usb_rcvctrlpipe(chip->dev, 0),
158
SND_US16X08_URB_METER_REQUEST,
159
SND_US16X08_URB_METER_REQUESTTYPE, 0, 0, buf, size);
160
return 0;
161
}
162
163
/* wrapper function to send prepared URB buffer to usb device. Return an error
164
* code if something went wrong
165
*/
166
static int snd_us16x08_send_urb(struct snd_usb_audio *chip, char *buf, int size)
167
{
168
return snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
169
SND_US16X08_URB_REQUEST, SND_US16X08_URB_REQUESTTYPE,
170
0, 0, buf, size);
171
}
172
173
static int snd_us16x08_route_info(struct snd_kcontrol *kcontrol,
174
struct snd_ctl_elem_info *uinfo)
175
{
176
return snd_ctl_enum_info(uinfo, 1, 10, route_names);
177
}
178
179
static int snd_us16x08_route_get(struct snd_kcontrol *kcontrol,
180
struct snd_ctl_elem_value *ucontrol)
181
{
182
struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
183
int index = ucontrol->id.index;
184
185
/* route has no bias */
186
ucontrol->value.enumerated.item[0] = elem->cache_val[index];
187
188
return 0;
189
}
190
191
static int snd_us16x08_route_put(struct snd_kcontrol *kcontrol,
192
struct snd_ctl_elem_value *ucontrol)
193
{
194
struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
195
struct snd_usb_audio *chip = elem->head.mixer->chip;
196
int index = ucontrol->id.index;
197
char buf[sizeof(route_msg)];
198
int val, val_org, err;
199
200
/* get the new value (no bias for routes) */
201
val = ucontrol->value.enumerated.item[0];
202
203
/* sanity check */
204
if (val < 0 || val > 9)
205
return -EINVAL;
206
207
/* prepare the message buffer from template */
208
memcpy(buf, route_msg, sizeof(route_msg));
209
210
if (val < 2) {
211
/* input comes from a master channel */
212
val_org = val;
213
buf[2] = 0x02;
214
} else {
215
/* input comes from a computer channel */
216
buf[2] = 0x03;
217
val_org = val - 2;
218
}
219
220
/* place new route selection in URB message */
221
buf[5] = (unsigned char) (val_org & 0x0f) + 1;
222
/* place route selector in URB message */
223
buf[13] = index + 1;
224
225
err = snd_us16x08_send_urb(chip, buf, sizeof(route_msg));
226
227
if (err > 0) {
228
elem->cached |= 1 << index;
229
elem->cache_val[index] = val;
230
} else {
231
usb_audio_dbg(chip, "Failed to set routing, err:%d\n", err);
232
}
233
234
return err > 0 ? 1 : 0;
235
}
236
237
static int snd_us16x08_master_info(struct snd_kcontrol *kcontrol,
238
struct snd_ctl_elem_info *uinfo)
239
{
240
uinfo->count = 1;
241
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
242
uinfo->value.integer.max = SND_US16X08_KCMAX(kcontrol);
243
uinfo->value.integer.min = SND_US16X08_KCMIN(kcontrol);
244
uinfo->value.integer.step = SND_US16X08_KCSTEP(kcontrol);
245
return 0;
246
}
247
248
static int snd_us16x08_master_get(struct snd_kcontrol *kcontrol,
249
struct snd_ctl_elem_value *ucontrol)
250
{
251
struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
252
int index = ucontrol->id.index;
253
254
ucontrol->value.integer.value[0] = elem->cache_val[index];
255
256
return 0;
257
}
258
259
static int snd_us16x08_master_put(struct snd_kcontrol *kcontrol,
260
struct snd_ctl_elem_value *ucontrol)
261
{
262
struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
263
struct snd_usb_audio *chip = elem->head.mixer->chip;
264
char buf[sizeof(mix_msg_out)];
265
int val, err;
266
int index = ucontrol->id.index;
267
268
/* new control value incl. bias*/
269
val = ucontrol->value.integer.value[0];
270
271
/* sanity check */
272
if (val < SND_US16X08_KCMIN(kcontrol)
273
|| val > SND_US16X08_KCMAX(kcontrol))
274
return -EINVAL;
275
276
/* prepare the message buffer from template */
277
memcpy(buf, mix_msg_out, sizeof(mix_msg_out));
278
279
buf[8] = val - SND_US16X08_KCBIAS(kcontrol);
280
buf[6] = elem->head.id;
281
282
/* place channel selector in URB message */
283
buf[5] = index + 1;
284
err = snd_us16x08_send_urb(chip, buf, sizeof(mix_msg_out));
285
286
if (err > 0) {
287
elem->cached |= 1 << index;
288
elem->cache_val[index] = val;
289
} else {
290
usb_audio_dbg(chip, "Failed to set master, err:%d\n", err);
291
}
292
293
return err > 0 ? 1 : 0;
294
}
295
296
static int snd_us16x08_bus_put(struct snd_kcontrol *kcontrol,
297
struct snd_ctl_elem_value *ucontrol)
298
{
299
struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
300
struct snd_usb_audio *chip = elem->head.mixer->chip;
301
char buf[sizeof(mix_msg_out)];
302
int val, err = 0;
303
304
val = ucontrol->value.integer.value[0];
305
306
/* prepare the message buffer from template */
307
switch (elem->head.id) {
308
case SND_US16X08_ID_BYPASS:
309
memcpy(buf, bypass_msg_out, sizeof(bypass_msg_out));
310
buf[2] = val;
311
err = snd_us16x08_send_urb(chip, buf, sizeof(bypass_msg_out));
312
break;
313
case SND_US16X08_ID_BUSS_OUT:
314
memcpy(buf, bus_msg_out, sizeof(bus_msg_out));
315
buf[2] = val;
316
err = snd_us16x08_send_urb(chip, buf, sizeof(bus_msg_out));
317
break;
318
case SND_US16X08_ID_MUTE:
319
memcpy(buf, mix_msg_out, sizeof(mix_msg_out));
320
buf[8] = val;
321
buf[6] = elem->head.id;
322
buf[5] = 1;
323
err = snd_us16x08_send_urb(chip, buf, sizeof(mix_msg_out));
324
break;
325
}
326
327
if (err > 0) {
328
elem->cached |= 1;
329
elem->cache_val[0] = val;
330
} else {
331
usb_audio_dbg(chip, "Failed to set bus parameter, err:%d\n", err);
332
}
333
334
return err > 0 ? 1 : 0;
335
}
336
337
static int snd_us16x08_bus_get(struct snd_kcontrol *kcontrol,
338
struct snd_ctl_elem_value *ucontrol)
339
{
340
struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
341
342
switch (elem->head.id) {
343
case SND_US16X08_ID_BUSS_OUT:
344
ucontrol->value.integer.value[0] = elem->cache_val[0];
345
break;
346
case SND_US16X08_ID_BYPASS:
347
ucontrol->value.integer.value[0] = elem->cache_val[0];
348
break;
349
case SND_US16X08_ID_MUTE:
350
ucontrol->value.integer.value[0] = elem->cache_val[0];
351
break;
352
}
353
354
return 0;
355
}
356
357
/* gets a current mixer value from common store */
358
static int snd_us16x08_channel_get(struct snd_kcontrol *kcontrol,
359
struct snd_ctl_elem_value *ucontrol)
360
{
361
struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
362
int index = ucontrol->id.index;
363
364
ucontrol->value.integer.value[0] = elem->cache_val[index];
365
366
return 0;
367
}
368
369
static int snd_us16x08_channel_put(struct snd_kcontrol *kcontrol,
370
struct snd_ctl_elem_value *ucontrol)
371
{
372
struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
373
struct snd_usb_audio *chip = elem->head.mixer->chip;
374
char buf[sizeof(mix_msg_in)];
375
int val, err;
376
int index = ucontrol->id.index;
377
378
val = ucontrol->value.integer.value[0];
379
380
/* sanity check */
381
if (val < SND_US16X08_KCMIN(kcontrol)
382
|| val > SND_US16X08_KCMAX(kcontrol))
383
return -EINVAL;
384
385
/* prepare URB message from template */
386
memcpy(buf, mix_msg_in, sizeof(mix_msg_in));
387
388
/* add the bias to the new value */
389
buf[8] = val - SND_US16X08_KCBIAS(kcontrol);
390
buf[6] = elem->head.id;
391
buf[5] = index + 1;
392
393
err = snd_us16x08_send_urb(chip, buf, sizeof(mix_msg_in));
394
395
if (err > 0) {
396
elem->cached |= 1 << index;
397
elem->cache_val[index] = val;
398
} else {
399
usb_audio_dbg(chip, "Failed to set channel, err:%d\n", err);
400
}
401
402
return err > 0 ? 1 : 0;
403
}
404
405
static int snd_us16x08_mix_info(struct snd_kcontrol *kcontrol,
406
struct snd_ctl_elem_info *uinfo)
407
{
408
uinfo->count = 1;
409
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
410
uinfo->value.integer.max = SND_US16X08_KCMAX(kcontrol);
411
uinfo->value.integer.min = SND_US16X08_KCMIN(kcontrol);
412
uinfo->value.integer.step = SND_US16X08_KCSTEP(kcontrol);
413
return 0;
414
}
415
416
static int snd_us16x08_comp_get(struct snd_kcontrol *kcontrol,
417
struct snd_ctl_elem_value *ucontrol)
418
{
419
struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
420
struct snd_us16x08_comp_store *store = elem->private_data;
421
int index = ucontrol->id.index;
422
int val_idx = COMP_STORE_IDX(elem->head.id);
423
424
ucontrol->value.integer.value[0] = store->val[val_idx][index];
425
426
return 0;
427
}
428
429
static int snd_us16x08_comp_put(struct snd_kcontrol *kcontrol,
430
struct snd_ctl_elem_value *ucontrol)
431
{
432
struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
433
struct snd_usb_audio *chip = elem->head.mixer->chip;
434
struct snd_us16x08_comp_store *store = elem->private_data;
435
int index = ucontrol->id.index;
436
char buf[sizeof(comp_msg)];
437
int val_idx, val;
438
int err;
439
440
val = ucontrol->value.integer.value[0];
441
442
/* sanity check */
443
if (val < SND_US16X08_KCMIN(kcontrol)
444
|| val > SND_US16X08_KCMAX(kcontrol))
445
return -EINVAL;
446
447
/* new control value incl. bias*/
448
val_idx = elem->head.id - SND_US16X08_ID_COMP_BASE;
449
450
store->val[val_idx][index] = ucontrol->value.integer.value[0];
451
452
/* prepare compressor URB message from template */
453
memcpy(buf, comp_msg, sizeof(comp_msg));
454
455
/* place comp values in message buffer watch bias! */
456
buf[8] = store->val[
457
COMP_STORE_IDX(SND_US16X08_ID_COMP_THRESHOLD)][index]
458
- SND_US16X08_COMP_THRESHOLD_BIAS;
459
buf[11] = ratio_map[store->val[
460
COMP_STORE_IDX(SND_US16X08_ID_COMP_RATIO)][index]];
461
buf[14] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_ATTACK)][index]
462
+ SND_US16X08_COMP_ATTACK_BIAS;
463
buf[17] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RELEASE)][index]
464
+ SND_US16X08_COMP_RELEASE_BIAS;
465
buf[20] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_GAIN)][index];
466
buf[26] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)][index];
467
468
/* place channel selector in message buffer */
469
buf[5] = index + 1;
470
471
err = snd_us16x08_send_urb(chip, buf, sizeof(comp_msg));
472
473
if (err > 0) {
474
elem->cached |= 1 << index;
475
elem->cache_val[index] = val;
476
} else {
477
usb_audio_dbg(chip, "Failed to set compressor, err:%d\n", err);
478
}
479
480
return 1;
481
}
482
483
static int snd_us16x08_eqswitch_get(struct snd_kcontrol *kcontrol,
484
struct snd_ctl_elem_value *ucontrol)
485
{
486
int val;
487
struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
488
struct snd_us16x08_eq_store *store = elem->private_data;
489
int index = ucontrol->id.index;
490
491
/* get low switch from cache is enough, cause all bands are together */
492
val = store->val[EQ_STORE_BAND_IDX(elem->head.id)]
493
[EQ_STORE_PARAM_IDX(elem->head.id)][index];
494
ucontrol->value.integer.value[0] = val;
495
496
return 0;
497
}
498
499
static int snd_us16x08_eqswitch_put(struct snd_kcontrol *kcontrol,
500
struct snd_ctl_elem_value *ucontrol)
501
{
502
struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
503
struct snd_usb_audio *chip = elem->head.mixer->chip;
504
struct snd_us16x08_eq_store *store = elem->private_data;
505
int index = ucontrol->id.index;
506
char buf[sizeof(eqs_msq)];
507
int val, err = 0;
508
int b_idx;
509
510
/* new control value incl. bias*/
511
val = ucontrol->value.integer.value[0] + SND_US16X08_KCBIAS(kcontrol);
512
513
/* prepare URB message from EQ template */
514
memcpy(buf, eqs_msq, sizeof(eqs_msq));
515
516
/* place channel index in URB message */
517
buf[5] = index + 1;
518
for (b_idx = 0; b_idx < SND_US16X08_ID_EQ_BAND_COUNT; b_idx++) {
519
/* all four EQ bands have to be enabled/disabled in once */
520
buf[20] = val;
521
buf[17] = store->val[b_idx][2][index];
522
buf[14] = store->val[b_idx][1][index];
523
buf[11] = store->val[b_idx][0][index];
524
buf[8] = b_idx + 1;
525
err = snd_us16x08_send_urb(chip, buf, sizeof(eqs_msq));
526
if (err < 0)
527
break;
528
store->val[b_idx][3][index] = val;
529
msleep(15);
530
}
531
532
if (err > 0) {
533
elem->cached |= 1 << index;
534
elem->cache_val[index] = val;
535
} else {
536
usb_audio_dbg(chip, "Failed to set eq switch, err:%d\n", err);
537
}
538
539
return 1;
540
}
541
542
static int snd_us16x08_eq_get(struct snd_kcontrol *kcontrol,
543
struct snd_ctl_elem_value *ucontrol)
544
{
545
int val;
546
struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
547
struct snd_us16x08_eq_store *store = elem->private_data;
548
int index = ucontrol->id.index;
549
int b_idx = EQ_STORE_BAND_IDX(elem->head.id) - 1;
550
int p_idx = EQ_STORE_PARAM_IDX(elem->head.id);
551
552
val = store->val[b_idx][p_idx][index];
553
554
ucontrol->value.integer.value[0] = val;
555
556
return 0;
557
}
558
559
static int snd_us16x08_eq_put(struct snd_kcontrol *kcontrol,
560
struct snd_ctl_elem_value *ucontrol)
561
{
562
struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
563
struct snd_usb_audio *chip = elem->head.mixer->chip;
564
struct snd_us16x08_eq_store *store = elem->private_data;
565
int index = ucontrol->id.index;
566
char buf[sizeof(eqs_msq)];
567
int val, err;
568
int b_idx = EQ_STORE_BAND_IDX(elem->head.id) - 1;
569
int p_idx = EQ_STORE_PARAM_IDX(elem->head.id);
570
571
val = ucontrol->value.integer.value[0];
572
573
/* sanity check */
574
if (val < SND_US16X08_KCMIN(kcontrol)
575
|| val > SND_US16X08_KCMAX(kcontrol))
576
return -EINVAL;
577
578
/* copy URB buffer from EQ template */
579
memcpy(buf, eqs_msq, sizeof(eqs_msq));
580
581
store->val[b_idx][p_idx][index] = val;
582
buf[20] = store->val[b_idx][3][index];
583
buf[17] = store->val[b_idx][2][index];
584
buf[14] = store->val[b_idx][1][index];
585
buf[11] = store->val[b_idx][0][index];
586
587
/* place channel index in URB buffer */
588
buf[5] = index + 1;
589
590
/* place EQ band in URB buffer */
591
buf[8] = b_idx + 1;
592
593
err = snd_us16x08_send_urb(chip, buf, sizeof(eqs_msq));
594
595
if (err > 0) {
596
/* store new value in EQ band cache */
597
elem->cached |= 1 << index;
598
elem->cache_val[index] = val;
599
} else {
600
usb_audio_dbg(chip, "Failed to set eq param, err:%d\n", err);
601
}
602
603
return 1;
604
}
605
606
static int snd_us16x08_meter_info(struct snd_kcontrol *kcontrol,
607
struct snd_ctl_elem_info *uinfo)
608
{
609
uinfo->count = 34;
610
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
611
uinfo->value.integer.max = 0x7FFF;
612
uinfo->value.integer.min = 0;
613
614
return 0;
615
}
616
617
/* calculate compressor index for reduction level request */
618
static int snd_get_meter_comp_index(struct snd_us16x08_meter_store *store)
619
{
620
int ret;
621
622
/* any channel active */
623
if (store->comp_active_index) {
624
/* check for stereo link */
625
if (store->comp_active_index & 0x20) {
626
/* reset comp_index to left channel*/
627
if (store->comp_index -
628
store->comp_active_index > 1)
629
store->comp_index =
630
store->comp_active_index;
631
632
ret = store->comp_index++ & 0x1F;
633
} else {
634
/* no stereo link */
635
ret = store->comp_active_index;
636
}
637
} else {
638
/* skip channels with no compressor active */
639
while (store->comp_index <= SND_US16X08_MAX_CHANNELS
640
&& !store->comp_store->val[
641
COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)]
642
[store->comp_index - 1]) {
643
store->comp_index++;
644
}
645
ret = store->comp_index++;
646
if (store->comp_index > SND_US16X08_MAX_CHANNELS)
647
store->comp_index = 1;
648
}
649
return ret;
650
}
651
652
/* retrieve the meter level values from URB message */
653
static void get_meter_levels_from_urb(int s,
654
struct snd_us16x08_meter_store *store,
655
u8 *meter_urb)
656
{
657
int val = MUC2(meter_urb, s) + (MUC3(meter_urb, s) << 8);
658
int ch = MUB2(meter_urb, s) - 1;
659
660
if (ch < 0)
661
return;
662
663
if (MUA0(meter_urb, s) == 0x61 && MUA1(meter_urb, s) == 0x02 &&
664
MUA2(meter_urb, s) == 0x04 && MUB0(meter_urb, s) == 0x62) {
665
if (ch < SND_US16X08_MAX_CHANNELS) {
666
if (MUC0(meter_urb, s) == 0x72)
667
store->meter_level[ch] = val;
668
if (MUC0(meter_urb, s) == 0xb2)
669
store->comp_level[ch] = val;
670
}
671
}
672
if (MUA0(meter_urb, s) == 0x61 && MUA1(meter_urb, s) == 0x02 &&
673
MUA2(meter_urb, s) == 0x02 && MUB0(meter_urb, s) == 0x62) {
674
if (ch < ARRAY_SIZE(store->master_level))
675
store->master_level[ch] = val;
676
}
677
}
678
679
/* Function to retrieve current meter values from the device.
680
*
681
* The device needs to be polled for meter values with an initial
682
* requests. It will return with a sequence of different meter value
683
* packages. The first request (case 0:) initiate this meter response sequence.
684
* After the third response, an additional request can be placed,
685
* to retrieve compressor reduction level value for given channel. This round
686
* trip channel selector will skip all inactive compressors.
687
* A mixer can interrupt this round-trip by selecting one ore two (stereo-link)
688
* specific channels.
689
*/
690
static int snd_us16x08_meter_get(struct snd_kcontrol *kcontrol,
691
struct snd_ctl_elem_value *ucontrol)
692
{
693
int i, set;
694
struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
695
struct snd_usb_audio *chip = elem->head.mixer->chip;
696
struct snd_us16x08_meter_store *store = elem->private_data;
697
u8 meter_urb[64] = {0};
698
699
switch (kcontrol->private_value) {
700
case 0: {
701
char tmp[sizeof(mix_init_msg1)];
702
703
memcpy(tmp, mix_init_msg1, sizeof(mix_init_msg1));
704
snd_us16x08_send_urb(chip, tmp, 4);
705
snd_us16x08_recv_urb(chip, meter_urb,
706
sizeof(meter_urb));
707
kcontrol->private_value++;
708
break;
709
}
710
case 1:
711
snd_us16x08_recv_urb(chip, meter_urb,
712
sizeof(meter_urb));
713
kcontrol->private_value++;
714
break;
715
case 2:
716
snd_us16x08_recv_urb(chip, meter_urb,
717
sizeof(meter_urb));
718
kcontrol->private_value++;
719
break;
720
case 3: {
721
char tmp[sizeof(mix_init_msg2)];
722
723
memcpy(tmp, mix_init_msg2, sizeof(mix_init_msg2));
724
tmp[2] = snd_get_meter_comp_index(store);
725
snd_us16x08_send_urb(chip, tmp, 10);
726
snd_us16x08_recv_urb(chip, meter_urb,
727
sizeof(meter_urb));
728
kcontrol->private_value = 0;
729
break;
730
}
731
}
732
733
for (set = 0; set < 6; set++)
734
get_meter_levels_from_urb(set, store, meter_urb);
735
736
for (i = 0; i < SND_US16X08_MAX_CHANNELS; i++) {
737
ucontrol->value.integer.value[i] =
738
store ? store->meter_level[i] : 0;
739
}
740
741
ucontrol->value.integer.value[i++] = store ? store->master_level[0] : 0;
742
ucontrol->value.integer.value[i++] = store ? store->master_level[1] : 0;
743
744
for (i = 2; i < SND_US16X08_MAX_CHANNELS + 2; i++)
745
ucontrol->value.integer.value[i + SND_US16X08_MAX_CHANNELS] =
746
store ? store->comp_level[i - 2] : 0;
747
748
return 1;
749
}
750
751
static int snd_us16x08_meter_put(struct snd_kcontrol *kcontrol,
752
struct snd_ctl_elem_value *ucontrol)
753
{
754
struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
755
struct snd_us16x08_meter_store *store = elem->private_data;
756
int val;
757
758
val = ucontrol->value.integer.value[0];
759
760
/* sanity check */
761
if (val < 0 || val >= SND_US16X08_MAX_CHANNELS)
762
return -EINVAL;
763
764
store->comp_active_index = val;
765
store->comp_index = val;
766
767
return 1;
768
}
769
770
static const struct snd_kcontrol_new snd_us16x08_ch_boolean_ctl = {
771
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
772
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
773
.count = 16,
774
.info = snd_us16x08_switch_info,
775
.get = snd_us16x08_channel_get,
776
.put = snd_us16x08_channel_put,
777
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 1)
778
};
779
780
static const struct snd_kcontrol_new snd_us16x08_ch_int_ctl = {
781
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
782
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
783
.count = 16,
784
.info = snd_us16x08_mix_info,
785
.get = snd_us16x08_channel_get,
786
.put = snd_us16x08_channel_put,
787
.private_value = SND_US16X08_KCSET(SND_US16X08_FADER_BIAS, 1, 0, 133)
788
};
789
790
static const struct snd_kcontrol_new snd_us16x08_pan_int_ctl = {
791
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
792
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
793
.count = 16,
794
.info = snd_us16x08_mix_info,
795
.get = snd_us16x08_channel_get,
796
.put = snd_us16x08_channel_put,
797
.private_value = SND_US16X08_KCSET(SND_US16X08_FADER_BIAS, 1, 0, 255)
798
};
799
800
static const struct snd_kcontrol_new snd_us16x08_master_ctl = {
801
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
802
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
803
.count = 1,
804
.info = snd_us16x08_master_info,
805
.get = snd_us16x08_master_get,
806
.put = snd_us16x08_master_put,
807
.private_value = SND_US16X08_KCSET(SND_US16X08_FADER_BIAS, 1, 0, 133)
808
};
809
810
static const struct snd_kcontrol_new snd_us16x08_route_ctl = {
811
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
812
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
813
.count = 8,
814
.info = snd_us16x08_route_info,
815
.get = snd_us16x08_route_get,
816
.put = snd_us16x08_route_put,
817
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 9)
818
};
819
820
static const struct snd_kcontrol_new snd_us16x08_bus_ctl = {
821
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
822
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
823
.count = 1,
824
.info = snd_us16x08_switch_info,
825
.get = snd_us16x08_bus_get,
826
.put = snd_us16x08_bus_put,
827
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 1)
828
};
829
830
static const struct snd_kcontrol_new snd_us16x08_compswitch_ctl = {
831
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
832
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
833
.count = 16,
834
.info = snd_us16x08_switch_info,
835
.get = snd_us16x08_comp_get,
836
.put = snd_us16x08_comp_put,
837
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 1)
838
};
839
840
static const struct snd_kcontrol_new snd_us16x08_comp_threshold_ctl = {
841
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
842
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
843
.count = 16,
844
.info = snd_us16x08_mix_info,
845
.get = snd_us16x08_comp_get,
846
.put = snd_us16x08_comp_put,
847
.private_value = SND_US16X08_KCSET(SND_US16X08_COMP_THRESHOLD_BIAS, 1,
848
0, 0x20)
849
};
850
851
static const struct snd_kcontrol_new snd_us16x08_comp_ratio_ctl = {
852
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
853
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
854
.count = 16,
855
.info = snd_us16x08_mix_info,
856
.get = snd_us16x08_comp_get,
857
.put = snd_us16x08_comp_put,
858
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0,
859
sizeof(ratio_map) - 1), /*max*/
860
};
861
862
static const struct snd_kcontrol_new snd_us16x08_comp_gain_ctl = {
863
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
864
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
865
.count = 16,
866
.info = snd_us16x08_mix_info,
867
.get = snd_us16x08_comp_get,
868
.put = snd_us16x08_comp_put,
869
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 0x14)
870
};
871
872
static const struct snd_kcontrol_new snd_us16x08_comp_attack_ctl = {
873
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
874
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
875
.count = 16,
876
.info = snd_us16x08_mix_info,
877
.get = snd_us16x08_comp_get,
878
.put = snd_us16x08_comp_put,
879
.private_value =
880
SND_US16X08_KCSET(SND_US16X08_COMP_ATTACK_BIAS, 1, 0, 0xc6),
881
};
882
883
static const struct snd_kcontrol_new snd_us16x08_comp_release_ctl = {
884
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
885
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
886
.count = 16,
887
.info = snd_us16x08_mix_info,
888
.get = snd_us16x08_comp_get,
889
.put = snd_us16x08_comp_put,
890
.private_value =
891
SND_US16X08_KCSET(SND_US16X08_COMP_RELEASE_BIAS, 1, 0, 0x63),
892
};
893
894
static const struct snd_kcontrol_new snd_us16x08_eq_gain_ctl = {
895
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
896
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
897
.count = 16,
898
.info = snd_us16x08_mix_info,
899
.get = snd_us16x08_eq_get,
900
.put = snd_us16x08_eq_put,
901
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 24),
902
};
903
904
static const struct snd_kcontrol_new snd_us16x08_eq_low_freq_ctl = {
905
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
906
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
907
.count = 16,
908
.info = snd_us16x08_mix_info,
909
.get = snd_us16x08_eq_get,
910
.put = snd_us16x08_eq_put,
911
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 0x1F),
912
};
913
914
static const struct snd_kcontrol_new snd_us16x08_eq_mid_freq_ctl = {
915
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
916
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
917
.count = 16,
918
.info = snd_us16x08_mix_info,
919
.get = snd_us16x08_eq_get,
920
.put = snd_us16x08_eq_put,
921
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 0x3F)
922
};
923
924
static const struct snd_kcontrol_new snd_us16x08_eq_mid_width_ctl = {
925
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
926
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
927
.count = 16,
928
.info = snd_us16x08_mix_info,
929
.get = snd_us16x08_eq_get,
930
.put = snd_us16x08_eq_put,
931
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 0x06)
932
};
933
934
static const struct snd_kcontrol_new snd_us16x08_eq_high_freq_ctl = {
935
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
936
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
937
.count = 16,
938
.info = snd_us16x08_mix_info,
939
.get = snd_us16x08_eq_get,
940
.put = snd_us16x08_eq_put,
941
.private_value =
942
SND_US16X08_KCSET(SND_US16X08_EQ_HIGHFREQ_BIAS, 1, 0, 0x1F)
943
};
944
945
static const struct snd_kcontrol_new snd_us16x08_eq_switch_ctl = {
946
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
947
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
948
.count = 16,
949
.info = snd_us16x08_switch_info,
950
.get = snd_us16x08_eqswitch_get,
951
.put = snd_us16x08_eqswitch_put,
952
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 1)
953
};
954
955
static const struct snd_kcontrol_new snd_us16x08_meter_ctl = {
956
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
957
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
958
.count = 1,
959
.info = snd_us16x08_meter_info,
960
.get = snd_us16x08_meter_get,
961
.put = snd_us16x08_meter_put
962
};
963
964
/* control store preparation */
965
966
/* setup compressor store and assign default value */
967
static struct snd_us16x08_comp_store *snd_us16x08_create_comp_store(void)
968
{
969
int i;
970
struct snd_us16x08_comp_store *tmp;
971
972
tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
973
if (!tmp)
974
return NULL;
975
976
for (i = 0; i < SND_US16X08_MAX_CHANNELS; i++) {
977
tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_THRESHOLD)][i]
978
= 0x20;
979
tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RATIO)][i] = 0x00;
980
tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_GAIN)][i] = 0x00;
981
tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)][i] = 0x00;
982
tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_ATTACK)][i] = 0x00;
983
tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RELEASE)][i] = 0x00;
984
}
985
return tmp;
986
}
987
988
/* setup EQ store and assign default values */
989
static struct snd_us16x08_eq_store *snd_us16x08_create_eq_store(void)
990
{
991
int i, b_idx;
992
struct snd_us16x08_eq_store *tmp;
993
994
tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
995
if (!tmp)
996
return NULL;
997
998
for (i = 0; i < SND_US16X08_MAX_CHANNELS; i++) {
999
for (b_idx = 0; b_idx < SND_US16X08_ID_EQ_BAND_COUNT; b_idx++) {
1000
tmp->val[b_idx][0][i] = 0x0c;
1001
tmp->val[b_idx][3][i] = 0x00;
1002
switch (b_idx) {
1003
case 0: /* EQ Low */
1004
tmp->val[b_idx][1][i] = 0x05;
1005
tmp->val[b_idx][2][i] = 0xff;
1006
break;
1007
case 1: /* EQ Mid low */
1008
tmp->val[b_idx][1][i] = 0x0e;
1009
tmp->val[b_idx][2][i] = 0x02;
1010
break;
1011
case 2: /* EQ Mid High */
1012
tmp->val[b_idx][1][i] = 0x1b;
1013
tmp->val[b_idx][2][i] = 0x02;
1014
break;
1015
case 3: /* EQ High */
1016
tmp->val[b_idx][1][i] = 0x2f
1017
- SND_US16X08_EQ_HIGHFREQ_BIAS;
1018
tmp->val[b_idx][2][i] = 0xff;
1019
break;
1020
}
1021
}
1022
}
1023
return tmp;
1024
}
1025
1026
static struct snd_us16x08_meter_store *snd_us16x08_create_meter_store(void)
1027
{
1028
struct snd_us16x08_meter_store *tmp;
1029
1030
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
1031
if (!tmp)
1032
return NULL;
1033
tmp->comp_index = 1;
1034
tmp->comp_active_index = 0;
1035
return tmp;
1036
}
1037
1038
/* release elem->private_free as well; called only once for each *_store */
1039
static void elem_private_free(struct snd_kcontrol *kctl)
1040
{
1041
struct usb_mixer_elem_info *elem = kctl->private_data;
1042
1043
if (elem)
1044
kfree(elem->private_data);
1045
kfree(elem);
1046
kctl->private_data = NULL;
1047
}
1048
1049
static int add_new_ctl(struct usb_mixer_interface *mixer,
1050
const struct snd_kcontrol_new *ncontrol,
1051
int index, int val_type, int channels,
1052
const char *name, void *opt,
1053
bool do_private_free,
1054
struct usb_mixer_elem_info **elem_ret)
1055
{
1056
struct snd_kcontrol *kctl;
1057
struct usb_mixer_elem_info *elem;
1058
int err;
1059
1060
usb_audio_dbg(mixer->chip, "us16x08 add mixer %s\n", name);
1061
1062
elem = kzalloc(sizeof(*elem), GFP_KERNEL);
1063
if (!elem)
1064
return -ENOMEM;
1065
1066
elem->head.mixer = mixer;
1067
elem->head.resume = NULL;
1068
elem->control = 0;
1069
elem->idx_off = 0;
1070
elem->head.id = index;
1071
elem->val_type = val_type;
1072
elem->channels = channels;
1073
elem->private_data = opt;
1074
1075
kctl = snd_ctl_new1(ncontrol, elem);
1076
if (!kctl) {
1077
kfree(elem);
1078
return -ENOMEM;
1079
}
1080
1081
if (do_private_free)
1082
kctl->private_free = elem_private_free;
1083
else
1084
kctl->private_free = snd_usb_mixer_elem_free;
1085
1086
strscpy(kctl->id.name, name, sizeof(kctl->id.name));
1087
1088
err = snd_usb_mixer_add_control(&elem->head, kctl);
1089
if (err < 0)
1090
return err;
1091
1092
if (elem_ret)
1093
*elem_ret = elem;
1094
1095
return 0;
1096
}
1097
1098
/* table of EQ controls */
1099
static const struct snd_us16x08_control_params eq_controls[] = {
1100
{ /* EQ switch */
1101
.kcontrol_new = &snd_us16x08_eq_switch_ctl,
1102
.control_id = SND_US16X08_ID_EQENABLE,
1103
.type = USB_MIXER_BOOLEAN,
1104
.num_channels = 16,
1105
.name = "EQ Switch",
1106
},
1107
{ /* EQ low gain */
1108
.kcontrol_new = &snd_us16x08_eq_gain_ctl,
1109
.control_id = SND_US16X08_ID_EQLOWLEVEL,
1110
.type = USB_MIXER_U8,
1111
.num_channels = 16,
1112
.name = "EQ Low Volume",
1113
},
1114
{ /* EQ low freq */
1115
.kcontrol_new = &snd_us16x08_eq_low_freq_ctl,
1116
.control_id = SND_US16X08_ID_EQLOWFREQ,
1117
.type = USB_MIXER_U8,
1118
.num_channels = 16,
1119
.name = "EQ Low Frequency",
1120
},
1121
{ /* EQ mid low gain */
1122
.kcontrol_new = &snd_us16x08_eq_gain_ctl,
1123
.control_id = SND_US16X08_ID_EQLOWMIDLEVEL,
1124
.type = USB_MIXER_U8,
1125
.num_channels = 16,
1126
.name = "EQ MidLow Volume",
1127
},
1128
{ /* EQ mid low freq */
1129
.kcontrol_new = &snd_us16x08_eq_mid_freq_ctl,
1130
.control_id = SND_US16X08_ID_EQLOWMIDFREQ,
1131
.type = USB_MIXER_U8,
1132
.num_channels = 16,
1133
.name = "EQ MidLow Frequency",
1134
},
1135
{ /* EQ mid low Q */
1136
.kcontrol_new = &snd_us16x08_eq_mid_width_ctl,
1137
.control_id = SND_US16X08_ID_EQLOWMIDWIDTH,
1138
.type = USB_MIXER_U8,
1139
.num_channels = 16,
1140
.name = "EQ MidLow Q",
1141
},
1142
{ /* EQ mid high gain */
1143
.kcontrol_new = &snd_us16x08_eq_gain_ctl,
1144
.control_id = SND_US16X08_ID_EQHIGHMIDLEVEL,
1145
.type = USB_MIXER_U8,
1146
.num_channels = 16,
1147
.name = "EQ MidHigh Volume",
1148
},
1149
{ /* EQ mid high freq */
1150
.kcontrol_new = &snd_us16x08_eq_mid_freq_ctl,
1151
.control_id = SND_US16X08_ID_EQHIGHMIDFREQ,
1152
.type = USB_MIXER_U8,
1153
.num_channels = 16,
1154
.name = "EQ MidHigh Frequency",
1155
},
1156
{ /* EQ mid high Q */
1157
.kcontrol_new = &snd_us16x08_eq_mid_width_ctl,
1158
.control_id = SND_US16X08_ID_EQHIGHMIDWIDTH,
1159
.type = USB_MIXER_U8,
1160
.num_channels = 16,
1161
.name = "EQ MidHigh Q",
1162
},
1163
{ /* EQ high gain */
1164
.kcontrol_new = &snd_us16x08_eq_gain_ctl,
1165
.control_id = SND_US16X08_ID_EQHIGHLEVEL,
1166
.type = USB_MIXER_U8,
1167
.num_channels = 16,
1168
.name = "EQ High Volume",
1169
},
1170
{ /* EQ low freq */
1171
.kcontrol_new = &snd_us16x08_eq_high_freq_ctl,
1172
.control_id = SND_US16X08_ID_EQHIGHFREQ,
1173
.type = USB_MIXER_U8,
1174
.num_channels = 16,
1175
.name = "EQ High Frequency",
1176
},
1177
};
1178
1179
/* table of compressor controls */
1180
static const struct snd_us16x08_control_params comp_controls[] = {
1181
{ /* Comp enable */
1182
.kcontrol_new = &snd_us16x08_compswitch_ctl,
1183
.control_id = SND_US16X08_ID_COMP_SWITCH,
1184
.type = USB_MIXER_BOOLEAN,
1185
.num_channels = 16,
1186
.name = "Compressor Switch",
1187
},
1188
{ /* Comp threshold */
1189
.kcontrol_new = &snd_us16x08_comp_threshold_ctl,
1190
.control_id = SND_US16X08_ID_COMP_THRESHOLD,
1191
.type = USB_MIXER_U8,
1192
.num_channels = 16,
1193
.name = "Compressor Threshold Volume",
1194
},
1195
{ /* Comp ratio */
1196
.kcontrol_new = &snd_us16x08_comp_ratio_ctl,
1197
.control_id = SND_US16X08_ID_COMP_RATIO,
1198
.type = USB_MIXER_U8,
1199
.num_channels = 16,
1200
.name = "Compressor Ratio",
1201
},
1202
{ /* Comp attack */
1203
.kcontrol_new = &snd_us16x08_comp_attack_ctl,
1204
.control_id = SND_US16X08_ID_COMP_ATTACK,
1205
.type = USB_MIXER_U8,
1206
.num_channels = 16,
1207
.name = "Compressor Attack",
1208
},
1209
{ /* Comp release */
1210
.kcontrol_new = &snd_us16x08_comp_release_ctl,
1211
.control_id = SND_US16X08_ID_COMP_RELEASE,
1212
.type = USB_MIXER_U8,
1213
.num_channels = 16,
1214
.name = "Compressor Release",
1215
},
1216
{ /* Comp gain */
1217
.kcontrol_new = &snd_us16x08_comp_gain_ctl,
1218
.control_id = SND_US16X08_ID_COMP_GAIN,
1219
.type = USB_MIXER_U8,
1220
.num_channels = 16,
1221
.name = "Compressor Volume",
1222
},
1223
};
1224
1225
/* table of channel controls */
1226
static const struct snd_us16x08_control_params channel_controls[] = {
1227
{ /* Phase */
1228
.kcontrol_new = &snd_us16x08_ch_boolean_ctl,
1229
.control_id = SND_US16X08_ID_PHASE,
1230
.type = USB_MIXER_BOOLEAN,
1231
.num_channels = 16,
1232
.name = "Phase Switch",
1233
.default_val = 0
1234
},
1235
{ /* Fader */
1236
.kcontrol_new = &snd_us16x08_ch_int_ctl,
1237
.control_id = SND_US16X08_ID_FADER,
1238
.type = USB_MIXER_U8,
1239
.num_channels = 16,
1240
.name = "Line Volume",
1241
.default_val = 127
1242
},
1243
{ /* Mute */
1244
.kcontrol_new = &snd_us16x08_ch_boolean_ctl,
1245
.control_id = SND_US16X08_ID_MUTE,
1246
.type = USB_MIXER_BOOLEAN,
1247
.num_channels = 16,
1248
.name = "Mute Switch",
1249
.default_val = 0
1250
},
1251
{ /* Pan */
1252
.kcontrol_new = &snd_us16x08_pan_int_ctl,
1253
.control_id = SND_US16X08_ID_PAN,
1254
.type = USB_MIXER_U16,
1255
.num_channels = 16,
1256
.name = "Pan Left-Right Volume",
1257
.default_val = 127
1258
},
1259
};
1260
1261
/* table of master controls */
1262
static const struct snd_us16x08_control_params master_controls[] = {
1263
{ /* Master */
1264
.kcontrol_new = &snd_us16x08_master_ctl,
1265
.control_id = SND_US16X08_ID_FADER,
1266
.type = USB_MIXER_U8,
1267
.num_channels = 16,
1268
.name = "Master Volume",
1269
.default_val = 127
1270
},
1271
{ /* Bypass */
1272
.kcontrol_new = &snd_us16x08_bus_ctl,
1273
.control_id = SND_US16X08_ID_BYPASS,
1274
.type = USB_MIXER_BOOLEAN,
1275
.num_channels = 16,
1276
.name = "DSP Bypass Switch",
1277
.default_val = 0
1278
},
1279
{ /* Buss out */
1280
.kcontrol_new = &snd_us16x08_bus_ctl,
1281
.control_id = SND_US16X08_ID_BUSS_OUT,
1282
.type = USB_MIXER_BOOLEAN,
1283
.num_channels = 16,
1284
.name = "Buss Out Switch",
1285
.default_val = 0
1286
},
1287
{ /* Master mute */
1288
.kcontrol_new = &snd_us16x08_bus_ctl,
1289
.control_id = SND_US16X08_ID_MUTE,
1290
.type = USB_MIXER_BOOLEAN,
1291
.num_channels = 16,
1292
.name = "Master Mute Switch",
1293
.default_val = 0
1294
},
1295
1296
};
1297
1298
int snd_us16x08_controls_create(struct usb_mixer_interface *mixer)
1299
{
1300
int i, j;
1301
int err;
1302
struct usb_mixer_elem_info *elem;
1303
struct snd_us16x08_comp_store *comp_store;
1304
struct snd_us16x08_meter_store *meter_store;
1305
struct snd_us16x08_eq_store *eq_store;
1306
1307
/* just check for non-MIDI interface */
1308
if (mixer->hostif->desc.bInterfaceNumber == 3) {
1309
1310
/* add routing control */
1311
err = add_new_ctl(mixer, &snd_us16x08_route_ctl,
1312
SND_US16X08_ID_ROUTE, USB_MIXER_U8, 8, "Line Out Route",
1313
NULL, false, &elem);
1314
if (err < 0) {
1315
usb_audio_dbg(mixer->chip,
1316
"Failed to create route control, err:%d\n",
1317
err);
1318
return err;
1319
}
1320
for (i = 0; i < 8; i++)
1321
elem->cache_val[i] = i < 2 ? i : i + 2;
1322
elem->cached = 0xff;
1323
1324
/* create compressor mixer elements */
1325
comp_store = snd_us16x08_create_comp_store();
1326
if (!comp_store)
1327
return -ENOMEM;
1328
1329
/* add master controls */
1330
for (i = 0; i < ARRAY_SIZE(master_controls); i++) {
1331
1332
err = add_new_ctl(mixer,
1333
master_controls[i].kcontrol_new,
1334
master_controls[i].control_id,
1335
master_controls[i].type,
1336
master_controls[i].num_channels,
1337
master_controls[i].name,
1338
comp_store,
1339
i == 0, /* release comp_store only once */
1340
&elem);
1341
if (err < 0)
1342
return err;
1343
elem->cache_val[0] = master_controls[i].default_val;
1344
elem->cached = 1;
1345
}
1346
1347
/* add channel controls */
1348
for (i = 0; i < ARRAY_SIZE(channel_controls); i++) {
1349
1350
err = add_new_ctl(mixer,
1351
channel_controls[i].kcontrol_new,
1352
channel_controls[i].control_id,
1353
channel_controls[i].type,
1354
channel_controls[i].num_channels,
1355
channel_controls[i].name,
1356
comp_store,
1357
false, &elem);
1358
if (err < 0)
1359
return err;
1360
for (j = 0; j < SND_US16X08_MAX_CHANNELS; j++) {
1361
elem->cache_val[j] =
1362
channel_controls[i].default_val;
1363
}
1364
elem->cached = 0xffff;
1365
}
1366
1367
/* create eq store */
1368
eq_store = snd_us16x08_create_eq_store();
1369
if (!eq_store)
1370
return -ENOMEM;
1371
1372
/* add EQ controls */
1373
for (i = 0; i < ARRAY_SIZE(eq_controls); i++) {
1374
1375
err = add_new_ctl(mixer,
1376
eq_controls[i].kcontrol_new,
1377
eq_controls[i].control_id,
1378
eq_controls[i].type,
1379
eq_controls[i].num_channels,
1380
eq_controls[i].name,
1381
eq_store,
1382
i == 0, /* release eq_store only once */
1383
NULL);
1384
if (err < 0)
1385
return err;
1386
}
1387
1388
/* add compressor controls */
1389
for (i = 0; i < ARRAY_SIZE(comp_controls); i++) {
1390
1391
err = add_new_ctl(mixer,
1392
comp_controls[i].kcontrol_new,
1393
comp_controls[i].control_id,
1394
comp_controls[i].type,
1395
comp_controls[i].num_channels,
1396
comp_controls[i].name,
1397
comp_store,
1398
false, NULL);
1399
if (err < 0)
1400
return err;
1401
}
1402
1403
/* create meters store */
1404
meter_store = snd_us16x08_create_meter_store();
1405
if (!meter_store)
1406
return -ENOMEM;
1407
1408
/* meter function 'get' must access to compressor store
1409
* so place a reference here
1410
*/
1411
meter_store->comp_store = comp_store;
1412
err = add_new_ctl(mixer, &snd_us16x08_meter_ctl,
1413
SND_US16X08_ID_METER, USB_MIXER_U16, 0, "Level Meter",
1414
meter_store, true, NULL);
1415
if (err < 0)
1416
return err;
1417
}
1418
1419
return 0;
1420
}
1421
1422
1423