1
2
3
4
5
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
22static const char route_msg[] = {
23 0x61,
24 0x02,
25 0x03,
26 0x62,
27 0x02,
28 0x01,
29 0x41,
30 0x01,
31 0x61,
32 0x02,
33 0x01,
34 0x62,
35 0x02,
36 0x01,
37 0x42,
38 0x01,
39 0x43,
40 0x01,
41 0x00,
42 0x00
43};
44
45static const char mix_init_msg1[] = {
46 0x71, 0x01, 0x00, 0x00
47};
48
49static const char mix_init_msg2[] = {
50 0x62, 0x02, 0x00, 0x61, 0x02, 0x04, 0xb1, 0x01, 0x00, 0x00
51};
52
53static const char mix_msg_in[] = {
54
55 0x61, 0x02, 0x04, 0x62, 0x02, 0x01,
56 0x81,
57 0x02,
58 0x00,
59 0x00,
60 0x00
61};
62
63static const char mix_msg_out[] = {
64
65 0x61, 0x02, 0x02, 0x62, 0x02, 0x01,
66 0x81,
67 0x02,
68 0x00,
69 0x00,
70 0x00
71};
72
73static const char bypass_msg_out[] = {
74 0x45,
75 0x02,
76 0x01,
77 0x00,
78 0x00
79};
80
81static const char bus_msg_out[] = {
82 0x44,
83 0x02,
84 0x01,
85 0x00,
86 0x00
87};
88
89static const char comp_msg[] = {
90
91 0x61, 0x02, 0x04, 0x62, 0x02, 0x01,
92 0x91,
93 0x02,
94 0xf0,
95 0x92,
96 0x02,
97 0x0a,
98 0x93,
99 0x02,
100 0x02,
101 0x94,
102 0x02,
103 0x01,
104 0x95,
105 0x02,
106 0x03,
107 0x96,
108 0x02,
109 0x01,
110 0x97,
111 0x02,
112 0x01,
113 0x00,
114 0x00
115};
116
117static const char eqs_msq[] = {
118
119 0x61, 0x02, 0x04, 0x62, 0x02, 0x01,
120 0x51,
121 0x02,
122 0x04,
123 0x52,
124 0x02,
125 0x0c,
126 0x53,
127 0x02,
128 0x0f,
129 0x54,
130 0x02,
131 0x02,
132 0x55,
133 0x02,
134 0x01,
135 0x00,
136 0x00
137};
138
139
140static const char ratio_map[] = {
141 0x0a, 0x0b, 0x0d, 0x0f, 0x11, 0x14, 0x19, 0x1e,
142 0x23, 0x28, 0x32, 0x3c, 0x50, 0xa0, 0xff
143};
144
145
146static 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
151static 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
165
166
167static 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
174static 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
180static int snd_us16x08_route_get(struct snd_kcontrol *kcontrol,
181 struct snd_ctl_elem_value *ucontrol)
182{
183 struct usb_mixer_elem_info *elem = kcontrol->private_data;
184 int index = ucontrol->id.index;
185
186
187 ucontrol->value.enumerated.item[0] = elem->cache_val[index];
188
189 return 0;
190}
191
192static int snd_us16x08_route_put(struct snd_kcontrol *kcontrol,
193 struct snd_ctl_elem_value *ucontrol)
194{
195 struct usb_mixer_elem_info *elem = kcontrol->private_data;
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
202 val = ucontrol->value.enumerated.item[0];
203
204
205 if (val < 0 || val > 9)
206 return -EINVAL;
207
208
209 memcpy(buf, route_msg, sizeof(route_msg));
210
211 if (val < 2) {
212
213 val_org = val;
214 buf[2] = 0x02;
215 } else {
216
217 buf[2] = 0x03;
218 val_org = val - 2;
219 }
220
221
222 buf[5] = (unsigned char) (val_org & 0x0f) + 1;
223
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
238static 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
249static int snd_us16x08_master_get(struct snd_kcontrol *kcontrol,
250 struct snd_ctl_elem_value *ucontrol)
251{
252 struct usb_mixer_elem_info *elem = kcontrol->private_data;
253 int index = ucontrol->id.index;
254
255 ucontrol->value.integer.value[0] = elem->cache_val[index];
256
257 return 0;
258}
259
260static int snd_us16x08_master_put(struct snd_kcontrol *kcontrol,
261 struct snd_ctl_elem_value *ucontrol)
262{
263 struct usb_mixer_elem_info *elem = kcontrol->private_data;
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
270 val = ucontrol->value.integer.value[0];
271
272
273 if (val < SND_US16X08_KCMIN(kcontrol)
274 || val > SND_US16X08_KCMAX(kcontrol))
275 return -EINVAL;
276
277
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
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
297static int snd_us16x08_bus_put(struct snd_kcontrol *kcontrol,
298 struct snd_ctl_elem_value *ucontrol)
299{
300 struct usb_mixer_elem_info *elem = kcontrol->private_data;
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
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
338static int snd_us16x08_bus_get(struct snd_kcontrol *kcontrol,
339 struct snd_ctl_elem_value *ucontrol)
340{
341 struct usb_mixer_elem_info *elem = kcontrol->private_data;
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
359static int snd_us16x08_channel_get(struct snd_kcontrol *kcontrol,
360 struct snd_ctl_elem_value *ucontrol)
361{
362 struct usb_mixer_elem_info *elem = kcontrol->private_data;
363 int index = ucontrol->id.index;
364
365 ucontrol->value.integer.value[0] = elem->cache_val[index];
366
367 return 0;
368}
369
370static int snd_us16x08_channel_put(struct snd_kcontrol *kcontrol,
371 struct snd_ctl_elem_value *ucontrol)
372{
373 struct usb_mixer_elem_info *elem = kcontrol->private_data;
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
382 if (val < SND_US16X08_KCMIN(kcontrol)
383 || val > SND_US16X08_KCMAX(kcontrol))
384 return -EINVAL;
385
386
387 memcpy(buf, mix_msg_in, sizeof(mix_msg_in));
388
389
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
406static 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
417static int snd_us16x08_comp_get(struct snd_kcontrol *kcontrol,
418 struct snd_ctl_elem_value *ucontrol)
419{
420 struct usb_mixer_elem_info *elem = kcontrol->private_data;
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
430static int snd_us16x08_comp_put(struct snd_kcontrol *kcontrol,
431 struct snd_ctl_elem_value *ucontrol)
432{
433 struct usb_mixer_elem_info *elem = kcontrol->private_data;
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
444 if (val < SND_US16X08_KCMIN(kcontrol)
445 || val > SND_US16X08_KCMAX(kcontrol))
446 return -EINVAL;
447
448
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
454 memcpy(buf, comp_msg, sizeof(comp_msg));
455
456
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
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
484static 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 = kcontrol->private_data;
489 struct snd_us16x08_eq_store *store = elem->private_data;
490 int index = ucontrol->id.index;
491
492
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
500static int snd_us16x08_eqswitch_put(struct snd_kcontrol *kcontrol,
501 struct snd_ctl_elem_value *ucontrol)
502{
503 struct usb_mixer_elem_info *elem = kcontrol->private_data;
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
512 val = ucontrol->value.integer.value[0] + SND_US16X08_KCBIAS(kcontrol);
513
514
515 memcpy(buf, eqs_msq, sizeof(eqs_msq));
516
517
518 buf[5] = index + 1;
519 for (b_idx = 0; b_idx < SND_US16X08_ID_EQ_BAND_COUNT; b_idx++) {
520
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
543static 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 = kcontrol->private_data;
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
560static int snd_us16x08_eq_put(struct snd_kcontrol *kcontrol,
561 struct snd_ctl_elem_value *ucontrol)
562{
563 struct usb_mixer_elem_info *elem = kcontrol->private_data;
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
575 if (val < SND_US16X08_KCMIN(kcontrol)
576 || val > SND_US16X08_KCMAX(kcontrol))
577 return -EINVAL;
578
579
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
589 buf[5] = index + 1;
590
591
592 buf[8] = b_idx + 1;
593
594 err = snd_us16x08_send_urb(chip, buf, sizeof(eqs_msq));
595
596 if (err > 0) {
597
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
607static 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
619static int snd_get_meter_comp_index(struct snd_us16x08_meter_store *store)
620{
621 int ret;
622
623
624 if (store->comp_active_index) {
625
626 if (store->comp_active_index & 0x20) {
627
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
636 ret = store->comp_active_index;
637 }
638 } else {
639
640 while (!store->comp_store->val[
641 COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)]
642 [store->comp_index - 1]
643 && store->comp_index <= SND_US16X08_MAX_CHANNELS) {
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
654static 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
673
674
675
676
677
678
679
680
681
682
683static 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 = kcontrol->private_data;
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];
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
744static int snd_us16x08_meter_put(struct snd_kcontrol *kcontrol,
745 struct snd_ctl_elem_value *ucontrol)
746{
747 struct usb_mixer_elem_info *elem = kcontrol->private_data;
748 struct snd_us16x08_meter_store *store = elem->private_data;
749 int val;
750
751 val = ucontrol->value.integer.value[0];
752
753
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
763static 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
773static 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
783static 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
793static 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
803static 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
813static 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
823static 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
833static 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
844static 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),
853};
854
855static 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
865static 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
876static 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
887static 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
897static 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
907static 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
917static 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
927static 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
938static 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
948static 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
958
959
960static 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
982static 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:
997 tmp->val[b_idx][1][i] = 0x05;
998 tmp->val[b_idx][2][i] = 0xff;
999 break;
1000 case 1:
1001 tmp->val[b_idx][1][i] = 0x0e;
1002 tmp->val[b_idx][2][i] = 0x02;
1003 break;
1004 case 2:
1005 tmp->val[b_idx][1][i] = 0x1b;
1006 tmp->val[b_idx][2][i] = 0x02;
1007 break;
1008 case 3:
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
1019static 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
1032static 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
1042static 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
1092static const struct snd_us16x08_control_params eq_controls[] = {
1093 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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
1173static const struct snd_us16x08_control_params comp_controls[] = {
1174 {
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 {
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 {
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 {
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 {
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 {
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
1219static const struct snd_us16x08_control_params channel_controls[] = {
1220 {
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 {
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 {
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 {
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
1255static const struct snd_us16x08_control_params master_controls[] = {
1256 {
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 {
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 {
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 {
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
1291int 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
1301 if (mixer->hostif->desc.bInterfaceNumber == 3) {
1302
1303
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
1318 comp_store = snd_us16x08_create_comp_store();
1319 if (!comp_store)
1320 return -ENOMEM;
1321
1322
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,
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
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
1361 eq_store = snd_us16x08_create_eq_store();
1362 if (!eq_store)
1363 return -ENOMEM;
1364
1365
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,
1376 NULL);
1377 if (err < 0)
1378 return err;
1379 }
1380
1381
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
1397 meter_store = snd_us16x08_create_meter_store();
1398 if (!meter_store)
1399 return -ENOMEM;
1400
1401
1402
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