Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/usb/mixer_us16x08.c
29265 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
659
if (MUA0(meter_urb, s) == 0x61 && MUA1(meter_urb, s) == 0x02 &&
660
MUA2(meter_urb, s) == 0x04 && MUB0(meter_urb, s) == 0x62) {
661
if (MUC0(meter_urb, s) == 0x72)
662
store->meter_level[MUB2(meter_urb, s) - 1] = val;
663
if (MUC0(meter_urb, s) == 0xb2)
664
store->comp_level[MUB2(meter_urb, s) - 1] = val;
665
}
666
if (MUA0(meter_urb, s) == 0x61 && MUA1(meter_urb, s) == 0x02 &&
667
MUA2(meter_urb, s) == 0x02 && MUB0(meter_urb, s) == 0x62)
668
store->master_level[MUB2(meter_urb, s) - 1] = val;
669
}
670
671
/* Function to retrieve current meter values from the device.
672
*
673
* The device needs to be polled for meter values with an initial
674
* requests. It will return with a sequence of different meter value
675
* packages. The first request (case 0:) initiate this meter response sequence.
676
* After the third response, an additional request can be placed,
677
* to retrieve compressor reduction level value for given channel. This round
678
* trip channel selector will skip all inactive compressors.
679
* A mixer can interrupt this round-trip by selecting one ore two (stereo-link)
680
* specific channels.
681
*/
682
static int snd_us16x08_meter_get(struct snd_kcontrol *kcontrol,
683
struct snd_ctl_elem_value *ucontrol)
684
{
685
int i, set;
686
struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
687
struct snd_usb_audio *chip = elem->head.mixer->chip;
688
struct snd_us16x08_meter_store *store = elem->private_data;
689
u8 meter_urb[64] = {0};
690
691
switch (kcontrol->private_value) {
692
case 0: {
693
char tmp[sizeof(mix_init_msg1)];
694
695
memcpy(tmp, mix_init_msg1, sizeof(mix_init_msg1));
696
snd_us16x08_send_urb(chip, tmp, 4);
697
snd_us16x08_recv_urb(chip, meter_urb,
698
sizeof(meter_urb));
699
kcontrol->private_value++;
700
break;
701
}
702
case 1:
703
snd_us16x08_recv_urb(chip, meter_urb,
704
sizeof(meter_urb));
705
kcontrol->private_value++;
706
break;
707
case 2:
708
snd_us16x08_recv_urb(chip, meter_urb,
709
sizeof(meter_urb));
710
kcontrol->private_value++;
711
break;
712
case 3: {
713
char tmp[sizeof(mix_init_msg2)];
714
715
memcpy(tmp, mix_init_msg2, sizeof(mix_init_msg2));
716
tmp[2] = snd_get_meter_comp_index(store);
717
snd_us16x08_send_urb(chip, tmp, 10);
718
snd_us16x08_recv_urb(chip, meter_urb,
719
sizeof(meter_urb));
720
kcontrol->private_value = 0;
721
break;
722
}
723
}
724
725
for (set = 0; set < 6; set++)
726
get_meter_levels_from_urb(set, store, meter_urb);
727
728
for (i = 0; i < SND_US16X08_MAX_CHANNELS; i++) {
729
ucontrol->value.integer.value[i] =
730
store ? store->meter_level[i] : 0;
731
}
732
733
ucontrol->value.integer.value[i++] = store ? store->master_level[0] : 0;
734
ucontrol->value.integer.value[i++] = store ? store->master_level[1] : 0;
735
736
for (i = 2; i < SND_US16X08_MAX_CHANNELS + 2; i++)
737
ucontrol->value.integer.value[i + SND_US16X08_MAX_CHANNELS] =
738
store ? store->comp_level[i - 2] : 0;
739
740
return 1;
741
}
742
743
static int snd_us16x08_meter_put(struct snd_kcontrol *kcontrol,
744
struct snd_ctl_elem_value *ucontrol)
745
{
746
struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
747
struct snd_us16x08_meter_store *store = elem->private_data;
748
int val;
749
750
val = ucontrol->value.integer.value[0];
751
752
/* sanity check */
753
if (val < 0 || val >= SND_US16X08_MAX_CHANNELS)
754
return -EINVAL;
755
756
store->comp_active_index = val;
757
store->comp_index = val;
758
759
return 1;
760
}
761
762
static const struct snd_kcontrol_new snd_us16x08_ch_boolean_ctl = {
763
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
764
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
765
.count = 16,
766
.info = snd_us16x08_switch_info,
767
.get = snd_us16x08_channel_get,
768
.put = snd_us16x08_channel_put,
769
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 1)
770
};
771
772
static const struct snd_kcontrol_new snd_us16x08_ch_int_ctl = {
773
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
774
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
775
.count = 16,
776
.info = snd_us16x08_mix_info,
777
.get = snd_us16x08_channel_get,
778
.put = snd_us16x08_channel_put,
779
.private_value = SND_US16X08_KCSET(SND_US16X08_FADER_BIAS, 1, 0, 133)
780
};
781
782
static const struct snd_kcontrol_new snd_us16x08_pan_int_ctl = {
783
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
784
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
785
.count = 16,
786
.info = snd_us16x08_mix_info,
787
.get = snd_us16x08_channel_get,
788
.put = snd_us16x08_channel_put,
789
.private_value = SND_US16X08_KCSET(SND_US16X08_FADER_BIAS, 1, 0, 255)
790
};
791
792
static const struct snd_kcontrol_new snd_us16x08_master_ctl = {
793
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
794
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
795
.count = 1,
796
.info = snd_us16x08_master_info,
797
.get = snd_us16x08_master_get,
798
.put = snd_us16x08_master_put,
799
.private_value = SND_US16X08_KCSET(SND_US16X08_FADER_BIAS, 1, 0, 133)
800
};
801
802
static const struct snd_kcontrol_new snd_us16x08_route_ctl = {
803
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
804
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
805
.count = 8,
806
.info = snd_us16x08_route_info,
807
.get = snd_us16x08_route_get,
808
.put = snd_us16x08_route_put,
809
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 9)
810
};
811
812
static const struct snd_kcontrol_new snd_us16x08_bus_ctl = {
813
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
814
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
815
.count = 1,
816
.info = snd_us16x08_switch_info,
817
.get = snd_us16x08_bus_get,
818
.put = snd_us16x08_bus_put,
819
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 1)
820
};
821
822
static const struct snd_kcontrol_new snd_us16x08_compswitch_ctl = {
823
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
824
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
825
.count = 16,
826
.info = snd_us16x08_switch_info,
827
.get = snd_us16x08_comp_get,
828
.put = snd_us16x08_comp_put,
829
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 1)
830
};
831
832
static const struct snd_kcontrol_new snd_us16x08_comp_threshold_ctl = {
833
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
834
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
835
.count = 16,
836
.info = snd_us16x08_mix_info,
837
.get = snd_us16x08_comp_get,
838
.put = snd_us16x08_comp_put,
839
.private_value = SND_US16X08_KCSET(SND_US16X08_COMP_THRESHOLD_BIAS, 1,
840
0, 0x20)
841
};
842
843
static const struct snd_kcontrol_new snd_us16x08_comp_ratio_ctl = {
844
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
845
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
846
.count = 16,
847
.info = snd_us16x08_mix_info,
848
.get = snd_us16x08_comp_get,
849
.put = snd_us16x08_comp_put,
850
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0,
851
sizeof(ratio_map) - 1), /*max*/
852
};
853
854
static const struct snd_kcontrol_new snd_us16x08_comp_gain_ctl = {
855
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
856
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
857
.count = 16,
858
.info = snd_us16x08_mix_info,
859
.get = snd_us16x08_comp_get,
860
.put = snd_us16x08_comp_put,
861
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 0x14)
862
};
863
864
static const struct snd_kcontrol_new snd_us16x08_comp_attack_ctl = {
865
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
866
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
867
.count = 16,
868
.info = snd_us16x08_mix_info,
869
.get = snd_us16x08_comp_get,
870
.put = snd_us16x08_comp_put,
871
.private_value =
872
SND_US16X08_KCSET(SND_US16X08_COMP_ATTACK_BIAS, 1, 0, 0xc6),
873
};
874
875
static const struct snd_kcontrol_new snd_us16x08_comp_release_ctl = {
876
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
877
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
878
.count = 16,
879
.info = snd_us16x08_mix_info,
880
.get = snd_us16x08_comp_get,
881
.put = snd_us16x08_comp_put,
882
.private_value =
883
SND_US16X08_KCSET(SND_US16X08_COMP_RELEASE_BIAS, 1, 0, 0x63),
884
};
885
886
static const struct snd_kcontrol_new snd_us16x08_eq_gain_ctl = {
887
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
888
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
889
.count = 16,
890
.info = snd_us16x08_mix_info,
891
.get = snd_us16x08_eq_get,
892
.put = snd_us16x08_eq_put,
893
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 24),
894
};
895
896
static const struct snd_kcontrol_new snd_us16x08_eq_low_freq_ctl = {
897
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
898
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
899
.count = 16,
900
.info = snd_us16x08_mix_info,
901
.get = snd_us16x08_eq_get,
902
.put = snd_us16x08_eq_put,
903
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 0x1F),
904
};
905
906
static const struct snd_kcontrol_new snd_us16x08_eq_mid_freq_ctl = {
907
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
908
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
909
.count = 16,
910
.info = snd_us16x08_mix_info,
911
.get = snd_us16x08_eq_get,
912
.put = snd_us16x08_eq_put,
913
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 0x3F)
914
};
915
916
static const struct snd_kcontrol_new snd_us16x08_eq_mid_width_ctl = {
917
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
918
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
919
.count = 16,
920
.info = snd_us16x08_mix_info,
921
.get = snd_us16x08_eq_get,
922
.put = snd_us16x08_eq_put,
923
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 0x06)
924
};
925
926
static const struct snd_kcontrol_new snd_us16x08_eq_high_freq_ctl = {
927
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
928
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
929
.count = 16,
930
.info = snd_us16x08_mix_info,
931
.get = snd_us16x08_eq_get,
932
.put = snd_us16x08_eq_put,
933
.private_value =
934
SND_US16X08_KCSET(SND_US16X08_EQ_HIGHFREQ_BIAS, 1, 0, 0x1F)
935
};
936
937
static const struct snd_kcontrol_new snd_us16x08_eq_switch_ctl = {
938
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
939
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
940
.count = 16,
941
.info = snd_us16x08_switch_info,
942
.get = snd_us16x08_eqswitch_get,
943
.put = snd_us16x08_eqswitch_put,
944
.private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 1)
945
};
946
947
static const struct snd_kcontrol_new snd_us16x08_meter_ctl = {
948
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
949
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
950
.count = 1,
951
.info = snd_us16x08_meter_info,
952
.get = snd_us16x08_meter_get,
953
.put = snd_us16x08_meter_put
954
};
955
956
/* control store preparation */
957
958
/* setup compressor store and assign default value */
959
static struct snd_us16x08_comp_store *snd_us16x08_create_comp_store(void)
960
{
961
int i;
962
struct snd_us16x08_comp_store *tmp;
963
964
tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
965
if (!tmp)
966
return NULL;
967
968
for (i = 0; i < SND_US16X08_MAX_CHANNELS; i++) {
969
tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_THRESHOLD)][i]
970
= 0x20;
971
tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RATIO)][i] = 0x00;
972
tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_GAIN)][i] = 0x00;
973
tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)][i] = 0x00;
974
tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_ATTACK)][i] = 0x00;
975
tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RELEASE)][i] = 0x00;
976
}
977
return tmp;
978
}
979
980
/* setup EQ store and assign default values */
981
static struct snd_us16x08_eq_store *snd_us16x08_create_eq_store(void)
982
{
983
int i, b_idx;
984
struct snd_us16x08_eq_store *tmp;
985
986
tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
987
if (!tmp)
988
return NULL;
989
990
for (i = 0; i < SND_US16X08_MAX_CHANNELS; i++) {
991
for (b_idx = 0; b_idx < SND_US16X08_ID_EQ_BAND_COUNT; b_idx++) {
992
tmp->val[b_idx][0][i] = 0x0c;
993
tmp->val[b_idx][3][i] = 0x00;
994
switch (b_idx) {
995
case 0: /* EQ Low */
996
tmp->val[b_idx][1][i] = 0x05;
997
tmp->val[b_idx][2][i] = 0xff;
998
break;
999
case 1: /* EQ Mid low */
1000
tmp->val[b_idx][1][i] = 0x0e;
1001
tmp->val[b_idx][2][i] = 0x02;
1002
break;
1003
case 2: /* EQ Mid High */
1004
tmp->val[b_idx][1][i] = 0x1b;
1005
tmp->val[b_idx][2][i] = 0x02;
1006
break;
1007
case 3: /* EQ High */
1008
tmp->val[b_idx][1][i] = 0x2f
1009
- SND_US16X08_EQ_HIGHFREQ_BIAS;
1010
tmp->val[b_idx][2][i] = 0xff;
1011
break;
1012
}
1013
}
1014
}
1015
return tmp;
1016
}
1017
1018
static struct snd_us16x08_meter_store *snd_us16x08_create_meter_store(void)
1019
{
1020
struct snd_us16x08_meter_store *tmp;
1021
1022
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
1023
if (!tmp)
1024
return NULL;
1025
tmp->comp_index = 1;
1026
tmp->comp_active_index = 0;
1027
return tmp;
1028
}
1029
1030
/* release elem->private_free as well; called only once for each *_store */
1031
static void elem_private_free(struct snd_kcontrol *kctl)
1032
{
1033
struct usb_mixer_elem_info *elem = kctl->private_data;
1034
1035
if (elem)
1036
kfree(elem->private_data);
1037
kfree(elem);
1038
kctl->private_data = NULL;
1039
}
1040
1041
static int add_new_ctl(struct usb_mixer_interface *mixer,
1042
const struct snd_kcontrol_new *ncontrol,
1043
int index, int val_type, int channels,
1044
const char *name, void *opt,
1045
bool do_private_free,
1046
struct usb_mixer_elem_info **elem_ret)
1047
{
1048
struct snd_kcontrol *kctl;
1049
struct usb_mixer_elem_info *elem;
1050
int err;
1051
1052
usb_audio_dbg(mixer->chip, "us16x08 add mixer %s\n", name);
1053
1054
elem = kzalloc(sizeof(*elem), GFP_KERNEL);
1055
if (!elem)
1056
return -ENOMEM;
1057
1058
elem->head.mixer = mixer;
1059
elem->head.resume = NULL;
1060
elem->control = 0;
1061
elem->idx_off = 0;
1062
elem->head.id = index;
1063
elem->val_type = val_type;
1064
elem->channels = channels;
1065
elem->private_data = opt;
1066
1067
kctl = snd_ctl_new1(ncontrol, elem);
1068
if (!kctl) {
1069
kfree(elem);
1070
return -ENOMEM;
1071
}
1072
1073
if (do_private_free)
1074
kctl->private_free = elem_private_free;
1075
else
1076
kctl->private_free = snd_usb_mixer_elem_free;
1077
1078
strscpy(kctl->id.name, name, sizeof(kctl->id.name));
1079
1080
err = snd_usb_mixer_add_control(&elem->head, kctl);
1081
if (err < 0)
1082
return err;
1083
1084
if (elem_ret)
1085
*elem_ret = elem;
1086
1087
return 0;
1088
}
1089
1090
/* table of EQ controls */
1091
static const struct snd_us16x08_control_params eq_controls[] = {
1092
{ /* EQ switch */
1093
.kcontrol_new = &snd_us16x08_eq_switch_ctl,
1094
.control_id = SND_US16X08_ID_EQENABLE,
1095
.type = USB_MIXER_BOOLEAN,
1096
.num_channels = 16,
1097
.name = "EQ Switch",
1098
},
1099
{ /* EQ low gain */
1100
.kcontrol_new = &snd_us16x08_eq_gain_ctl,
1101
.control_id = SND_US16X08_ID_EQLOWLEVEL,
1102
.type = USB_MIXER_U8,
1103
.num_channels = 16,
1104
.name = "EQ Low Volume",
1105
},
1106
{ /* EQ low freq */
1107
.kcontrol_new = &snd_us16x08_eq_low_freq_ctl,
1108
.control_id = SND_US16X08_ID_EQLOWFREQ,
1109
.type = USB_MIXER_U8,
1110
.num_channels = 16,
1111
.name = "EQ Low Frequency",
1112
},
1113
{ /* EQ mid low gain */
1114
.kcontrol_new = &snd_us16x08_eq_gain_ctl,
1115
.control_id = SND_US16X08_ID_EQLOWMIDLEVEL,
1116
.type = USB_MIXER_U8,
1117
.num_channels = 16,
1118
.name = "EQ MidLow Volume",
1119
},
1120
{ /* EQ mid low freq */
1121
.kcontrol_new = &snd_us16x08_eq_mid_freq_ctl,
1122
.control_id = SND_US16X08_ID_EQLOWMIDFREQ,
1123
.type = USB_MIXER_U8,
1124
.num_channels = 16,
1125
.name = "EQ MidLow Frequency",
1126
},
1127
{ /* EQ mid low Q */
1128
.kcontrol_new = &snd_us16x08_eq_mid_width_ctl,
1129
.control_id = SND_US16X08_ID_EQLOWMIDWIDTH,
1130
.type = USB_MIXER_U8,
1131
.num_channels = 16,
1132
.name = "EQ MidLow Q",
1133
},
1134
{ /* EQ mid high gain */
1135
.kcontrol_new = &snd_us16x08_eq_gain_ctl,
1136
.control_id = SND_US16X08_ID_EQHIGHMIDLEVEL,
1137
.type = USB_MIXER_U8,
1138
.num_channels = 16,
1139
.name = "EQ MidHigh Volume",
1140
},
1141
{ /* EQ mid high freq */
1142
.kcontrol_new = &snd_us16x08_eq_mid_freq_ctl,
1143
.control_id = SND_US16X08_ID_EQHIGHMIDFREQ,
1144
.type = USB_MIXER_U8,
1145
.num_channels = 16,
1146
.name = "EQ MidHigh Frequency",
1147
},
1148
{ /* EQ mid high Q */
1149
.kcontrol_new = &snd_us16x08_eq_mid_width_ctl,
1150
.control_id = SND_US16X08_ID_EQHIGHMIDWIDTH,
1151
.type = USB_MIXER_U8,
1152
.num_channels = 16,
1153
.name = "EQ MidHigh Q",
1154
},
1155
{ /* EQ high gain */
1156
.kcontrol_new = &snd_us16x08_eq_gain_ctl,
1157
.control_id = SND_US16X08_ID_EQHIGHLEVEL,
1158
.type = USB_MIXER_U8,
1159
.num_channels = 16,
1160
.name = "EQ High Volume",
1161
},
1162
{ /* EQ low freq */
1163
.kcontrol_new = &snd_us16x08_eq_high_freq_ctl,
1164
.control_id = SND_US16X08_ID_EQHIGHFREQ,
1165
.type = USB_MIXER_U8,
1166
.num_channels = 16,
1167
.name = "EQ High Frequency",
1168
},
1169
};
1170
1171
/* table of compressor controls */
1172
static const struct snd_us16x08_control_params comp_controls[] = {
1173
{ /* Comp enable */
1174
.kcontrol_new = &snd_us16x08_compswitch_ctl,
1175
.control_id = SND_US16X08_ID_COMP_SWITCH,
1176
.type = USB_MIXER_BOOLEAN,
1177
.num_channels = 16,
1178
.name = "Compressor Switch",
1179
},
1180
{ /* Comp threshold */
1181
.kcontrol_new = &snd_us16x08_comp_threshold_ctl,
1182
.control_id = SND_US16X08_ID_COMP_THRESHOLD,
1183
.type = USB_MIXER_U8,
1184
.num_channels = 16,
1185
.name = "Compressor Threshold Volume",
1186
},
1187
{ /* Comp ratio */
1188
.kcontrol_new = &snd_us16x08_comp_ratio_ctl,
1189
.control_id = SND_US16X08_ID_COMP_RATIO,
1190
.type = USB_MIXER_U8,
1191
.num_channels = 16,
1192
.name = "Compressor Ratio",
1193
},
1194
{ /* Comp attack */
1195
.kcontrol_new = &snd_us16x08_comp_attack_ctl,
1196
.control_id = SND_US16X08_ID_COMP_ATTACK,
1197
.type = USB_MIXER_U8,
1198
.num_channels = 16,
1199
.name = "Compressor Attack",
1200
},
1201
{ /* Comp release */
1202
.kcontrol_new = &snd_us16x08_comp_release_ctl,
1203
.control_id = SND_US16X08_ID_COMP_RELEASE,
1204
.type = USB_MIXER_U8,
1205
.num_channels = 16,
1206
.name = "Compressor Release",
1207
},
1208
{ /* Comp gain */
1209
.kcontrol_new = &snd_us16x08_comp_gain_ctl,
1210
.control_id = SND_US16X08_ID_COMP_GAIN,
1211
.type = USB_MIXER_U8,
1212
.num_channels = 16,
1213
.name = "Compressor Volume",
1214
},
1215
};
1216
1217
/* table of channel controls */
1218
static const struct snd_us16x08_control_params channel_controls[] = {
1219
{ /* Phase */
1220
.kcontrol_new = &snd_us16x08_ch_boolean_ctl,
1221
.control_id = SND_US16X08_ID_PHASE,
1222
.type = USB_MIXER_BOOLEAN,
1223
.num_channels = 16,
1224
.name = "Phase Switch",
1225
.default_val = 0
1226
},
1227
{ /* Fader */
1228
.kcontrol_new = &snd_us16x08_ch_int_ctl,
1229
.control_id = SND_US16X08_ID_FADER,
1230
.type = USB_MIXER_U8,
1231
.num_channels = 16,
1232
.name = "Line Volume",
1233
.default_val = 127
1234
},
1235
{ /* Mute */
1236
.kcontrol_new = &snd_us16x08_ch_boolean_ctl,
1237
.control_id = SND_US16X08_ID_MUTE,
1238
.type = USB_MIXER_BOOLEAN,
1239
.num_channels = 16,
1240
.name = "Mute Switch",
1241
.default_val = 0
1242
},
1243
{ /* Pan */
1244
.kcontrol_new = &snd_us16x08_pan_int_ctl,
1245
.control_id = SND_US16X08_ID_PAN,
1246
.type = USB_MIXER_U16,
1247
.num_channels = 16,
1248
.name = "Pan Left-Right Volume",
1249
.default_val = 127
1250
},
1251
};
1252
1253
/* table of master controls */
1254
static const struct snd_us16x08_control_params master_controls[] = {
1255
{ /* Master */
1256
.kcontrol_new = &snd_us16x08_master_ctl,
1257
.control_id = SND_US16X08_ID_FADER,
1258
.type = USB_MIXER_U8,
1259
.num_channels = 16,
1260
.name = "Master Volume",
1261
.default_val = 127
1262
},
1263
{ /* Bypass */
1264
.kcontrol_new = &snd_us16x08_bus_ctl,
1265
.control_id = SND_US16X08_ID_BYPASS,
1266
.type = USB_MIXER_BOOLEAN,
1267
.num_channels = 16,
1268
.name = "DSP Bypass Switch",
1269
.default_val = 0
1270
},
1271
{ /* Buss out */
1272
.kcontrol_new = &snd_us16x08_bus_ctl,
1273
.control_id = SND_US16X08_ID_BUSS_OUT,
1274
.type = USB_MIXER_BOOLEAN,
1275
.num_channels = 16,
1276
.name = "Buss Out Switch",
1277
.default_val = 0
1278
},
1279
{ /* Master mute */
1280
.kcontrol_new = &snd_us16x08_bus_ctl,
1281
.control_id = SND_US16X08_ID_MUTE,
1282
.type = USB_MIXER_BOOLEAN,
1283
.num_channels = 16,
1284
.name = "Master Mute Switch",
1285
.default_val = 0
1286
},
1287
1288
};
1289
1290
int snd_us16x08_controls_create(struct usb_mixer_interface *mixer)
1291
{
1292
int i, j;
1293
int err;
1294
struct usb_mixer_elem_info *elem;
1295
struct snd_us16x08_comp_store *comp_store;
1296
struct snd_us16x08_meter_store *meter_store;
1297
struct snd_us16x08_eq_store *eq_store;
1298
1299
/* just check for non-MIDI interface */
1300
if (mixer->hostif->desc.bInterfaceNumber == 3) {
1301
1302
/* add routing control */
1303
err = add_new_ctl(mixer, &snd_us16x08_route_ctl,
1304
SND_US16X08_ID_ROUTE, USB_MIXER_U8, 8, "Line Out Route",
1305
NULL, false, &elem);
1306
if (err < 0) {
1307
usb_audio_dbg(mixer->chip,
1308
"Failed to create route control, err:%d\n",
1309
err);
1310
return err;
1311
}
1312
for (i = 0; i < 8; i++)
1313
elem->cache_val[i] = i < 2 ? i : i + 2;
1314
elem->cached = 0xff;
1315
1316
/* create compressor mixer elements */
1317
comp_store = snd_us16x08_create_comp_store();
1318
if (!comp_store)
1319
return -ENOMEM;
1320
1321
/* add master controls */
1322
for (i = 0; i < ARRAY_SIZE(master_controls); i++) {
1323
1324
err = add_new_ctl(mixer,
1325
master_controls[i].kcontrol_new,
1326
master_controls[i].control_id,
1327
master_controls[i].type,
1328
master_controls[i].num_channels,
1329
master_controls[i].name,
1330
comp_store,
1331
i == 0, /* release comp_store only once */
1332
&elem);
1333
if (err < 0)
1334
return err;
1335
elem->cache_val[0] = master_controls[i].default_val;
1336
elem->cached = 1;
1337
}
1338
1339
/* add channel controls */
1340
for (i = 0; i < ARRAY_SIZE(channel_controls); i++) {
1341
1342
err = add_new_ctl(mixer,
1343
channel_controls[i].kcontrol_new,
1344
channel_controls[i].control_id,
1345
channel_controls[i].type,
1346
channel_controls[i].num_channels,
1347
channel_controls[i].name,
1348
comp_store,
1349
false, &elem);
1350
if (err < 0)
1351
return err;
1352
for (j = 0; j < SND_US16X08_MAX_CHANNELS; j++) {
1353
elem->cache_val[j] =
1354
channel_controls[i].default_val;
1355
}
1356
elem->cached = 0xffff;
1357
}
1358
1359
/* create eq store */
1360
eq_store = snd_us16x08_create_eq_store();
1361
if (!eq_store)
1362
return -ENOMEM;
1363
1364
/* add EQ controls */
1365
for (i = 0; i < ARRAY_SIZE(eq_controls); i++) {
1366
1367
err = add_new_ctl(mixer,
1368
eq_controls[i].kcontrol_new,
1369
eq_controls[i].control_id,
1370
eq_controls[i].type,
1371
eq_controls[i].num_channels,
1372
eq_controls[i].name,
1373
eq_store,
1374
i == 0, /* release eq_store only once */
1375
NULL);
1376
if (err < 0)
1377
return err;
1378
}
1379
1380
/* add compressor controls */
1381
for (i = 0; i < ARRAY_SIZE(comp_controls); i++) {
1382
1383
err = add_new_ctl(mixer,
1384
comp_controls[i].kcontrol_new,
1385
comp_controls[i].control_id,
1386
comp_controls[i].type,
1387
comp_controls[i].num_channels,
1388
comp_controls[i].name,
1389
comp_store,
1390
false, NULL);
1391
if (err < 0)
1392
return err;
1393
}
1394
1395
/* create meters store */
1396
meter_store = snd_us16x08_create_meter_store();
1397
if (!meter_store)
1398
return -ENOMEM;
1399
1400
/* meter function 'get' must access to compressor store
1401
* so place a reference here
1402
*/
1403
meter_store->comp_store = comp_store;
1404
err = add_new_ctl(mixer, &snd_us16x08_meter_ctl,
1405
SND_US16X08_ID_METER, USB_MIXER_U16, 0, "Level Meter",
1406
meter_store, true, NULL);
1407
if (err < 0)
1408
return err;
1409
}
1410
1411
return 0;
1412
}
1413
1414
1415