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

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

Version: ~ [ linux-5.10-rc1 ] ~ [ linux-5.9.1 ] ~ [ linux-5.8.16 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.72 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.152 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.202 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.240 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.240 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ 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.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp