~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/usb/mixer_us16x08.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php