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