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