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