Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *   Tascam US-16x08 ALSA driver
0004  *
0005  *   Copyright (c) 2016 by Detlef Urban (onkel@paraair.de)
0006  */
0007 
0008 #include <linux/slab.h>
0009 #include <linux/usb.h>
0010 #include <linux/usb/audio-v2.h>
0011 
0012 #include <sound/core.h>
0013 #include <sound/control.h>
0014 
0015 #include "usbaudio.h"
0016 #include "mixer.h"
0017 #include "helper.h"
0018 
0019 #include "mixer_us16x08.h"
0020 
0021 /* USB control message templates */
0022 static const char route_msg[] = {
0023     0x61,
0024     0x02,
0025     0x03, /* input from master (0x02) or input from computer bus (0x03) */
0026     0x62,
0027     0x02,
0028     0x01, /* input index (0x01/0x02 eq. left/right) or bus (0x01-0x08) */
0029     0x41,
0030     0x01,
0031     0x61,
0032     0x02,
0033     0x01,
0034     0x62,
0035     0x02,
0036     0x01, /* output index (0x01-0x08) */
0037     0x42,
0038     0x01,
0039     0x43,
0040     0x01,
0041     0x00,
0042     0x00
0043 };
0044 
0045 static const char mix_init_msg1[] = {
0046     0x71, 0x01, 0x00, 0x00
0047 };
0048 
0049 static const char mix_init_msg2[] = {
0050     0x62, 0x02, 0x00, 0x61, 0x02, 0x04, 0xb1, 0x01, 0x00, 0x00
0051 };
0052 
0053 static const char mix_msg_in[] = {
0054     /* default message head, equal to all mixers */
0055     0x61, 0x02, 0x04, 0x62, 0x02, 0x01,
0056     0x81, /* 0x06: Controller ID */
0057     0x02, /* 0x07:  */
0058     0x00, /* 0x08: Value of common mixer */
0059     0x00,
0060     0x00
0061 };
0062 
0063 static const char mix_msg_out[] = {
0064     /* default message head, equal to all mixers */
0065     0x61, 0x02, 0x02, 0x62, 0x02, 0x01,
0066     0x81, /* 0x06: Controller ID */
0067     0x02, /*                    0x07:  */
0068     0x00, /*                    0x08: Value of common mixer */
0069     0x00,
0070     0x00
0071 };
0072 
0073 static const char bypass_msg_out[] = {
0074     0x45,
0075     0x02,
0076     0x01, /* on/off flag */
0077     0x00,
0078     0x00
0079 };
0080 
0081 static const char bus_msg_out[] = {
0082     0x44,
0083     0x02,
0084     0x01, /* on/off flag */
0085     0x00,
0086     0x00
0087 };
0088 
0089 static const char comp_msg[] = {
0090     /* default message head, equal to all mixers */
0091     0x61, 0x02, 0x04, 0x62, 0x02, 0x01,
0092     0x91,
0093     0x02,
0094     0xf0, /* 0x08: Threshold db (8) (e0 ... 00) (+-0dB -- -32dB) x-32 */
0095     0x92,
0096     0x02,
0097     0x0a, /* 0x0b: Ratio (0a,0b,0d,0f,11,14,19,1e,23,28,32,3c,50,a0,ff)  */
0098     0x93,
0099     0x02,
0100     0x02, /* 0x0e: Attack (0x02 ... 0xc0) (2ms ... 200ms) */
0101     0x94,
0102     0x02,
0103     0x01, /* 0x11: Release (0x01 ... 0x64) (10ms ... 1000ms) x*10  */
0104     0x95,
0105     0x02,
0106     0x03, /* 0x14: gain (0 ... 20) (0dB .. 20dB) */
0107     0x96,
0108     0x02,
0109     0x01,
0110     0x97,
0111     0x02,
0112     0x01, /* 0x1a: main Comp switch (0 ... 1) (off ... on)) */
0113     0x00,
0114     0x00
0115 };
0116 
0117 static const char eqs_msq[] = {
0118     /* default message head, equal to all mixers */
0119     0x61, 0x02, 0x04, 0x62, 0x02, 0x01,
0120     0x51, /*                0x06: Controller ID  */
0121     0x02,
0122     0x04, /* 0x08: EQ set num (0x01..0x04) (LOW, LOWMID, HIGHMID, HIGH)) */
0123     0x52,
0124     0x02,
0125     0x0c, /* 0x0b: value dB (0 ... 12) (-12db .. +12db)  x-6 */
0126     0x53,
0127     0x02,
0128     0x0f, /* 0x0e: value freq (32-47) (1.7kHz..18kHz) */
0129     0x54,
0130     0x02,
0131     0x02, /* 0x11: band width (0-6) (Q16-Q0.25)  2^x/4 (EQ xxMID only) */
0132     0x55,
0133     0x02,
0134     0x01, /* 0x14: main EQ switch (0 ... 1) (off ... on)) */
0135     0x00,
0136     0x00
0137 };
0138 
0139 /* compressor ratio map */
0140 static const char ratio_map[] = {
0141     0x0a, 0x0b, 0x0d, 0x0f, 0x11, 0x14, 0x19, 0x1e,
0142     0x23, 0x28, 0x32, 0x3c, 0x50, 0xa0, 0xff
0143 };
0144 
0145 /* route enumeration names */
0146 static const char *const route_names[] = {
0147     "Master Left", "Master Right", "Output 1", "Output 2", "Output 3",
0148     "Output 4", "Output 5", "Output 6", "Output 7", "Output 8",
0149 };
0150 
0151 static int snd_us16x08_recv_urb(struct snd_usb_audio *chip,
0152     unsigned char *buf, int size)
0153 {
0154 
0155     mutex_lock(&chip->mutex);
0156     snd_usb_ctl_msg(chip->dev,
0157         usb_rcvctrlpipe(chip->dev, 0),
0158         SND_US16X08_URB_METER_REQUEST,
0159         SND_US16X08_URB_METER_REQUESTTYPE, 0, 0, buf, size);
0160     mutex_unlock(&chip->mutex);
0161     return 0;
0162 }
0163 
0164 /* wrapper function to send prepared URB buffer to usb device. Return an error
0165  * code if something went wrong
0166  */
0167 static int snd_us16x08_send_urb(struct snd_usb_audio *chip, char *buf, int size)
0168 {
0169     return snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0),
0170             SND_US16X08_URB_REQUEST, SND_US16X08_URB_REQUESTTYPE,
0171             0, 0, buf, size);
0172 }
0173 
0174 static int snd_us16x08_route_info(struct snd_kcontrol *kcontrol,
0175     struct snd_ctl_elem_info *uinfo)
0176 {
0177     return snd_ctl_enum_info(uinfo, 1, 10, route_names);
0178 }
0179 
0180 static int snd_us16x08_route_get(struct snd_kcontrol *kcontrol,
0181     struct snd_ctl_elem_value *ucontrol)
0182 {
0183     struct usb_mixer_elem_info *elem = kcontrol->private_data;
0184     int index = ucontrol->id.index;
0185 
0186     /* route has no bias */
0187     ucontrol->value.enumerated.item[0] = elem->cache_val[index];
0188 
0189     return 0;
0190 }
0191 
0192 static int snd_us16x08_route_put(struct snd_kcontrol *kcontrol,
0193     struct snd_ctl_elem_value *ucontrol)
0194 {
0195     struct usb_mixer_elem_info *elem = kcontrol->private_data;
0196     struct snd_usb_audio *chip = elem->head.mixer->chip;
0197     int index = ucontrol->id.index;
0198     char buf[sizeof(route_msg)];
0199     int val, val_org, err;
0200 
0201     /*  get the new value (no bias for routes) */
0202     val = ucontrol->value.enumerated.item[0];
0203 
0204     /* sanity check */
0205     if (val < 0 || val > 9)
0206         return -EINVAL;
0207 
0208     /* prepare the message buffer from template */
0209     memcpy(buf, route_msg, sizeof(route_msg));
0210 
0211     if (val < 2) {
0212         /* input comes from a master channel */
0213         val_org = val;
0214         buf[2] = 0x02;
0215     } else {
0216         /* input comes from a computer channel */
0217         buf[2] = 0x03;
0218         val_org = val - 2;
0219     }
0220 
0221     /* place new route selection in URB message */
0222     buf[5] = (unsigned char) (val_org & 0x0f) + 1;
0223     /* place route selector in URB message */
0224     buf[13] = index + 1;
0225 
0226     err = snd_us16x08_send_urb(chip, buf, sizeof(route_msg));
0227 
0228     if (err > 0) {
0229         elem->cached |= 1 << index;
0230         elem->cache_val[index] = val;
0231     } else {
0232         usb_audio_dbg(chip, "Failed to set routing, err:%d\n", err);
0233     }
0234 
0235     return err > 0 ? 1 : 0;
0236 }
0237 
0238 static int snd_us16x08_master_info(struct snd_kcontrol *kcontrol,
0239     struct snd_ctl_elem_info *uinfo)
0240 {
0241     uinfo->count = 1;
0242     uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0243     uinfo->value.integer.max = SND_US16X08_KCMAX(kcontrol);
0244     uinfo->value.integer.min = SND_US16X08_KCMIN(kcontrol);
0245     uinfo->value.integer.step = SND_US16X08_KCSTEP(kcontrol);
0246     return 0;
0247 }
0248 
0249 static int snd_us16x08_master_get(struct snd_kcontrol *kcontrol,
0250     struct snd_ctl_elem_value *ucontrol)
0251 {
0252     struct usb_mixer_elem_info *elem = kcontrol->private_data;
0253     int index = ucontrol->id.index;
0254 
0255     ucontrol->value.integer.value[0] = elem->cache_val[index];
0256 
0257     return 0;
0258 }
0259 
0260 static int snd_us16x08_master_put(struct snd_kcontrol *kcontrol,
0261     struct snd_ctl_elem_value *ucontrol)
0262 {
0263     struct usb_mixer_elem_info *elem = kcontrol->private_data;
0264     struct snd_usb_audio *chip = elem->head.mixer->chip;
0265     char buf[sizeof(mix_msg_out)];
0266     int val, err;
0267     int index = ucontrol->id.index;
0268 
0269     /* new control value incl. bias*/
0270     val = ucontrol->value.integer.value[0];
0271 
0272     /* sanity check */
0273     if (val < SND_US16X08_KCMIN(kcontrol)
0274         || val > SND_US16X08_KCMAX(kcontrol))
0275         return -EINVAL;
0276 
0277     /* prepare the message buffer from template */
0278     memcpy(buf, mix_msg_out, sizeof(mix_msg_out));
0279 
0280     buf[8] = val - SND_US16X08_KCBIAS(kcontrol);
0281     buf[6] = elem->head.id;
0282 
0283     /* place channel selector in URB message */
0284     buf[5] = index + 1;
0285     err = snd_us16x08_send_urb(chip, buf, sizeof(mix_msg_out));
0286 
0287     if (err > 0) {
0288         elem->cached |= 1 << index;
0289         elem->cache_val[index] = val;
0290     } else {
0291         usb_audio_dbg(chip, "Failed to set master, err:%d\n", err);
0292     }
0293 
0294     return err > 0 ? 1 : 0;
0295 }
0296 
0297 static int snd_us16x08_bus_put(struct snd_kcontrol *kcontrol,
0298     struct snd_ctl_elem_value *ucontrol)
0299 {
0300     struct usb_mixer_elem_info *elem = kcontrol->private_data;
0301     struct snd_usb_audio *chip = elem->head.mixer->chip;
0302     char buf[sizeof(mix_msg_out)];
0303     int val, err = 0;
0304 
0305     val = ucontrol->value.integer.value[0];
0306 
0307     /* prepare the message buffer from template */
0308     switch (elem->head.id) {
0309     case SND_US16X08_ID_BYPASS:
0310         memcpy(buf, bypass_msg_out, sizeof(bypass_msg_out));
0311         buf[2] = val;
0312         err = snd_us16x08_send_urb(chip, buf, sizeof(bypass_msg_out));
0313         break;
0314     case SND_US16X08_ID_BUSS_OUT:
0315         memcpy(buf, bus_msg_out, sizeof(bus_msg_out));
0316         buf[2] = val;
0317         err = snd_us16x08_send_urb(chip, buf, sizeof(bus_msg_out));
0318         break;
0319     case SND_US16X08_ID_MUTE:
0320         memcpy(buf, mix_msg_out, sizeof(mix_msg_out));
0321         buf[8] = val;
0322         buf[6] = elem->head.id;
0323         buf[5] = 1;
0324         err = snd_us16x08_send_urb(chip, buf, sizeof(mix_msg_out));
0325         break;
0326     }
0327 
0328     if (err > 0) {
0329         elem->cached |= 1;
0330         elem->cache_val[0] = val;
0331     } else {
0332         usb_audio_dbg(chip, "Failed to set bus parameter, err:%d\n", err);
0333     }
0334 
0335     return err > 0 ? 1 : 0;
0336 }
0337 
0338 static int snd_us16x08_bus_get(struct snd_kcontrol *kcontrol,
0339     struct snd_ctl_elem_value *ucontrol)
0340 {
0341     struct usb_mixer_elem_info *elem = kcontrol->private_data;
0342 
0343     switch (elem->head.id) {
0344     case SND_US16X08_ID_BUSS_OUT:
0345         ucontrol->value.integer.value[0] = elem->cache_val[0];
0346         break;
0347     case SND_US16X08_ID_BYPASS:
0348         ucontrol->value.integer.value[0] = elem->cache_val[0];
0349         break;
0350     case SND_US16X08_ID_MUTE:
0351         ucontrol->value.integer.value[0] = elem->cache_val[0];
0352         break;
0353     }
0354 
0355     return 0;
0356 }
0357 
0358 /* gets a current mixer value from common store */
0359 static int snd_us16x08_channel_get(struct snd_kcontrol *kcontrol,
0360     struct snd_ctl_elem_value *ucontrol)
0361 {
0362     struct usb_mixer_elem_info *elem = kcontrol->private_data;
0363     int index = ucontrol->id.index;
0364 
0365     ucontrol->value.integer.value[0] = elem->cache_val[index];
0366 
0367     return 0;
0368 }
0369 
0370 static int snd_us16x08_channel_put(struct snd_kcontrol *kcontrol,
0371     struct snd_ctl_elem_value *ucontrol)
0372 {
0373     struct usb_mixer_elem_info *elem = kcontrol->private_data;
0374     struct snd_usb_audio *chip = elem->head.mixer->chip;
0375     char buf[sizeof(mix_msg_in)];
0376     int val, err;
0377     int index = ucontrol->id.index;
0378 
0379     val = ucontrol->value.integer.value[0];
0380 
0381     /* sanity check */
0382     if (val < SND_US16X08_KCMIN(kcontrol)
0383         || val > SND_US16X08_KCMAX(kcontrol))
0384         return -EINVAL;
0385 
0386     /* prepare URB message from template */
0387     memcpy(buf, mix_msg_in, sizeof(mix_msg_in));
0388 
0389     /* add the bias to the new value */
0390     buf[8] = val - SND_US16X08_KCBIAS(kcontrol);
0391     buf[6] = elem->head.id;
0392     buf[5] = index + 1;
0393 
0394     err = snd_us16x08_send_urb(chip, buf, sizeof(mix_msg_in));
0395 
0396     if (err > 0) {
0397         elem->cached |= 1 << index;
0398         elem->cache_val[index] = val;
0399     } else {
0400         usb_audio_dbg(chip, "Failed to set channel, err:%d\n", err);
0401     }
0402 
0403     return err > 0 ? 1 : 0;
0404 }
0405 
0406 static int snd_us16x08_mix_info(struct snd_kcontrol *kcontrol,
0407     struct snd_ctl_elem_info *uinfo)
0408 {
0409     uinfo->count = 1;
0410     uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0411     uinfo->value.integer.max = SND_US16X08_KCMAX(kcontrol);
0412     uinfo->value.integer.min = SND_US16X08_KCMIN(kcontrol);
0413     uinfo->value.integer.step = SND_US16X08_KCSTEP(kcontrol);
0414     return 0;
0415 }
0416 
0417 static int snd_us16x08_comp_get(struct snd_kcontrol *kcontrol,
0418     struct snd_ctl_elem_value *ucontrol)
0419 {
0420     struct usb_mixer_elem_info *elem = kcontrol->private_data;
0421     struct snd_us16x08_comp_store *store = elem->private_data;
0422     int index = ucontrol->id.index;
0423     int val_idx = COMP_STORE_IDX(elem->head.id);
0424 
0425     ucontrol->value.integer.value[0] = store->val[val_idx][index];
0426 
0427     return 0;
0428 }
0429 
0430 static int snd_us16x08_comp_put(struct snd_kcontrol *kcontrol,
0431     struct snd_ctl_elem_value *ucontrol)
0432 {
0433     struct usb_mixer_elem_info *elem = kcontrol->private_data;
0434     struct snd_usb_audio *chip = elem->head.mixer->chip;
0435     struct snd_us16x08_comp_store *store = elem->private_data;
0436     int index = ucontrol->id.index;
0437     char buf[sizeof(comp_msg)];
0438     int val_idx, val;
0439     int err;
0440 
0441     val = ucontrol->value.integer.value[0];
0442 
0443     /* sanity check */
0444     if (val < SND_US16X08_KCMIN(kcontrol)
0445         || val > SND_US16X08_KCMAX(kcontrol))
0446         return -EINVAL;
0447 
0448     /* new control value incl. bias*/
0449     val_idx = elem->head.id - SND_US16X08_ID_COMP_BASE;
0450 
0451     store->val[val_idx][index] = ucontrol->value.integer.value[0];
0452 
0453     /* prepare compressor URB message from template  */
0454     memcpy(buf, comp_msg, sizeof(comp_msg));
0455 
0456     /* place comp values in message buffer watch bias! */
0457     buf[8] = store->val[
0458         COMP_STORE_IDX(SND_US16X08_ID_COMP_THRESHOLD)][index]
0459         - SND_US16X08_COMP_THRESHOLD_BIAS;
0460     buf[11] = ratio_map[store->val[
0461         COMP_STORE_IDX(SND_US16X08_ID_COMP_RATIO)][index]];
0462     buf[14] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_ATTACK)][index]
0463         + SND_US16X08_COMP_ATTACK_BIAS;
0464     buf[17] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RELEASE)][index]
0465         + SND_US16X08_COMP_RELEASE_BIAS;
0466     buf[20] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_GAIN)][index];
0467     buf[26] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)][index];
0468 
0469     /* place channel selector in message buffer */
0470     buf[5] = index + 1;
0471 
0472     err = snd_us16x08_send_urb(chip, buf, sizeof(comp_msg));
0473 
0474     if (err > 0) {
0475         elem->cached |= 1 << index;
0476         elem->cache_val[index] = val;
0477     } else {
0478         usb_audio_dbg(chip, "Failed to set compressor, err:%d\n", err);
0479     }
0480 
0481     return 1;
0482 }
0483 
0484 static int snd_us16x08_eqswitch_get(struct snd_kcontrol *kcontrol,
0485     struct snd_ctl_elem_value *ucontrol)
0486 {
0487     int val;
0488     struct usb_mixer_elem_info *elem = kcontrol->private_data;
0489     struct snd_us16x08_eq_store *store = elem->private_data;
0490     int index = ucontrol->id.index;
0491 
0492     /* get low switch from cache is enough, cause all bands are together */
0493     val = store->val[EQ_STORE_BAND_IDX(elem->head.id)]
0494         [EQ_STORE_PARAM_IDX(elem->head.id)][index];
0495     ucontrol->value.integer.value[0] = val;
0496 
0497     return 0;
0498 }
0499 
0500 static int snd_us16x08_eqswitch_put(struct snd_kcontrol *kcontrol,
0501     struct snd_ctl_elem_value *ucontrol)
0502 {
0503     struct usb_mixer_elem_info *elem = kcontrol->private_data;
0504     struct snd_usb_audio *chip = elem->head.mixer->chip;
0505     struct snd_us16x08_eq_store *store = elem->private_data;
0506     int index = ucontrol->id.index;
0507     char buf[sizeof(eqs_msq)];
0508     int val, err = 0;
0509     int b_idx;
0510 
0511     /* new control value incl. bias*/
0512     val = ucontrol->value.integer.value[0] + SND_US16X08_KCBIAS(kcontrol);
0513 
0514     /* prepare URB message from EQ template */
0515     memcpy(buf, eqs_msq, sizeof(eqs_msq));
0516 
0517     /* place channel index in URB message */
0518     buf[5] = index + 1;
0519     for (b_idx = 0; b_idx < SND_US16X08_ID_EQ_BAND_COUNT; b_idx++) {
0520         /* all four EQ bands have to be enabled/disabled in once */
0521         buf[20] = val;
0522         buf[17] = store->val[b_idx][2][index];
0523         buf[14] = store->val[b_idx][1][index];
0524         buf[11] = store->val[b_idx][0][index];
0525         buf[8] = b_idx + 1;
0526         err = snd_us16x08_send_urb(chip, buf, sizeof(eqs_msq));
0527         if (err < 0)
0528             break;
0529         store->val[b_idx][3][index] = val;
0530         msleep(15);
0531     }
0532 
0533     if (err > 0) {
0534         elem->cached |= 1 << index;
0535         elem->cache_val[index] = val;
0536     } else {
0537         usb_audio_dbg(chip, "Failed to set eq switch, err:%d\n", err);
0538     }
0539 
0540     return 1;
0541 }
0542 
0543 static int snd_us16x08_eq_get(struct snd_kcontrol *kcontrol,
0544     struct snd_ctl_elem_value *ucontrol)
0545 {
0546     int val;
0547     struct usb_mixer_elem_info *elem = kcontrol->private_data;
0548     struct snd_us16x08_eq_store *store = elem->private_data;
0549     int index = ucontrol->id.index;
0550     int b_idx = EQ_STORE_BAND_IDX(elem->head.id) - 1;
0551     int p_idx = EQ_STORE_PARAM_IDX(elem->head.id);
0552 
0553     val = store->val[b_idx][p_idx][index];
0554 
0555     ucontrol->value.integer.value[0] = val;
0556 
0557     return 0;
0558 }
0559 
0560 static int snd_us16x08_eq_put(struct snd_kcontrol *kcontrol,
0561     struct snd_ctl_elem_value *ucontrol)
0562 {
0563     struct usb_mixer_elem_info *elem = kcontrol->private_data;
0564     struct snd_usb_audio *chip = elem->head.mixer->chip;
0565     struct snd_us16x08_eq_store *store = elem->private_data;
0566     int index = ucontrol->id.index;
0567     char buf[sizeof(eqs_msq)];
0568     int val, err;
0569     int b_idx = EQ_STORE_BAND_IDX(elem->head.id) - 1;
0570     int p_idx = EQ_STORE_PARAM_IDX(elem->head.id);
0571 
0572     val = ucontrol->value.integer.value[0];
0573 
0574     /* sanity check */
0575     if (val < SND_US16X08_KCMIN(kcontrol)
0576         || val > SND_US16X08_KCMAX(kcontrol))
0577         return -EINVAL;
0578 
0579     /* copy URB buffer from EQ template */
0580     memcpy(buf, eqs_msq, sizeof(eqs_msq));
0581 
0582     store->val[b_idx][p_idx][index] = val;
0583     buf[20] = store->val[b_idx][3][index];
0584     buf[17] = store->val[b_idx][2][index];
0585     buf[14] = store->val[b_idx][1][index];
0586     buf[11] = store->val[b_idx][0][index];
0587 
0588     /* place channel index in URB buffer */
0589     buf[5] = index + 1;
0590 
0591     /* place EQ band in URB buffer */
0592     buf[8] = b_idx + 1;
0593 
0594     err = snd_us16x08_send_urb(chip, buf, sizeof(eqs_msq));
0595 
0596     if (err > 0) {
0597         /* store new value in EQ band cache */
0598         elem->cached |= 1 << index;
0599         elem->cache_val[index] = val;
0600     } else {
0601         usb_audio_dbg(chip, "Failed to set eq param, err:%d\n", err);
0602     }
0603 
0604     return 1;
0605 }
0606 
0607 static int snd_us16x08_meter_info(struct snd_kcontrol *kcontrol,
0608     struct snd_ctl_elem_info *uinfo)
0609 {
0610     uinfo->count = 34;
0611     uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0612     uinfo->value.integer.max = 0x7FFF;
0613     uinfo->value.integer.min = 0;
0614 
0615     return 0;
0616 }
0617 
0618 /* calculate compressor index for reduction level request */
0619 static int snd_get_meter_comp_index(struct snd_us16x08_meter_store *store)
0620 {
0621     int ret;
0622 
0623     /* any channel active */
0624     if (store->comp_active_index) {
0625         /* check for stereo link */
0626         if (store->comp_active_index & 0x20) {
0627             /* reset comp_index to left channel*/
0628             if (store->comp_index -
0629                 store->comp_active_index > 1)
0630                 store->comp_index =
0631                 store->comp_active_index;
0632 
0633             ret = store->comp_index++ & 0x1F;
0634         } else {
0635             /* no stereo link */
0636             ret = store->comp_active_index;
0637         }
0638     } else {
0639         /* skip channels with no compressor active */
0640         while (store->comp_index <= SND_US16X08_MAX_CHANNELS
0641             && !store->comp_store->val[
0642             COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)]
0643             [store->comp_index - 1]) {
0644             store->comp_index++;
0645         }
0646         ret = store->comp_index++;
0647         if (store->comp_index > SND_US16X08_MAX_CHANNELS)
0648             store->comp_index = 1;
0649     }
0650     return ret;
0651 }
0652 
0653 /* retrieve the meter level values from URB message */
0654 static void get_meter_levels_from_urb(int s,
0655     struct snd_us16x08_meter_store *store,
0656     u8 *meter_urb)
0657 {
0658     int val = MUC2(meter_urb, s) + (MUC3(meter_urb, s) << 8);
0659 
0660     if (MUA0(meter_urb, s) == 0x61 && MUA1(meter_urb, s) == 0x02 &&
0661         MUA2(meter_urb, s) == 0x04 && MUB0(meter_urb, s) == 0x62) {
0662         if (MUC0(meter_urb, s) == 0x72)
0663             store->meter_level[MUB2(meter_urb, s) - 1] = val;
0664         if (MUC0(meter_urb, s) == 0xb2)
0665             store->comp_level[MUB2(meter_urb, s) - 1] = val;
0666     }
0667     if (MUA0(meter_urb, s) == 0x61 && MUA1(meter_urb, s) == 0x02 &&
0668         MUA2(meter_urb, s) == 0x02 && MUB0(meter_urb, s) == 0x62)
0669         store->master_level[MUB2(meter_urb, s) - 1] = val;
0670 }
0671 
0672 /* Function to retrieve current meter values from the device.
0673  *
0674  * The device needs to be polled for meter values with an initial
0675  * requests. It will return with a sequence of different meter value
0676  * packages. The first request (case 0:) initiate this meter response sequence.
0677  * After the third response, an additional request can be placed,
0678  * to retrieve compressor reduction level value for given channel. This round
0679  * trip channel selector will skip all inactive compressors.
0680  * A mixer can interrupt this round-trip by selecting one ore two (stereo-link)
0681  * specific channels.
0682  */
0683 static int snd_us16x08_meter_get(struct snd_kcontrol *kcontrol,
0684     struct snd_ctl_elem_value *ucontrol)
0685 {
0686     int i, set;
0687     struct usb_mixer_elem_info *elem = kcontrol->private_data;
0688     struct snd_usb_audio *chip = elem->head.mixer->chip;
0689     struct snd_us16x08_meter_store *store = elem->private_data;
0690     u8 meter_urb[64];
0691 
0692     switch (kcontrol->private_value) {
0693     case 0: {
0694         char tmp[sizeof(mix_init_msg1)];
0695 
0696         memcpy(tmp, mix_init_msg1, sizeof(mix_init_msg1));
0697         snd_us16x08_send_urb(chip, tmp, 4);
0698         snd_us16x08_recv_urb(chip, meter_urb,
0699             sizeof(meter_urb));
0700         kcontrol->private_value++;
0701         break;
0702     }
0703     case 1:
0704         snd_us16x08_recv_urb(chip, meter_urb,
0705             sizeof(meter_urb));
0706         kcontrol->private_value++;
0707         break;
0708     case 2:
0709         snd_us16x08_recv_urb(chip, meter_urb,
0710             sizeof(meter_urb));
0711         kcontrol->private_value++;
0712         break;
0713     case 3: {
0714         char tmp[sizeof(mix_init_msg2)];
0715 
0716         memcpy(tmp, mix_init_msg2, sizeof(mix_init_msg2));
0717         tmp[2] = snd_get_meter_comp_index(store);
0718         snd_us16x08_send_urb(chip, tmp, 10);
0719         snd_us16x08_recv_urb(chip, meter_urb,
0720             sizeof(meter_urb));
0721         kcontrol->private_value = 0;
0722         break;
0723     }
0724     }
0725 
0726     for (set = 0; set < 6; set++)
0727         get_meter_levels_from_urb(set, store, meter_urb);
0728 
0729     for (i = 0; i < SND_US16X08_MAX_CHANNELS; i++) {
0730         ucontrol->value.integer.value[i] =
0731             store ? store->meter_level[i] : 0;
0732     }
0733 
0734     ucontrol->value.integer.value[i++] = store ? store->master_level[0] : 0;
0735     ucontrol->value.integer.value[i++] = store ? store->master_level[1] : 0;
0736 
0737     for (i = 2; i < SND_US16X08_MAX_CHANNELS + 2; i++)
0738         ucontrol->value.integer.value[i + SND_US16X08_MAX_CHANNELS] =
0739         store ? store->comp_level[i - 2] : 0;
0740 
0741     return 1;
0742 }
0743 
0744 static int snd_us16x08_meter_put(struct snd_kcontrol *kcontrol,
0745     struct snd_ctl_elem_value *ucontrol)
0746 {
0747     struct usb_mixer_elem_info *elem = kcontrol->private_data;
0748     struct snd_us16x08_meter_store *store = elem->private_data;
0749     int val;
0750 
0751     val = ucontrol->value.integer.value[0];
0752 
0753     /* sanity check */
0754     if (val < 0 || val >= SND_US16X08_MAX_CHANNELS)
0755         return -EINVAL;
0756 
0757     store->comp_active_index = val;
0758     store->comp_index = val;
0759 
0760     return 1;
0761 }
0762 
0763 static const struct snd_kcontrol_new snd_us16x08_ch_boolean_ctl = {
0764     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0765     .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0766     .count = 16,
0767     .info = snd_us16x08_switch_info,
0768     .get = snd_us16x08_channel_get,
0769     .put = snd_us16x08_channel_put,
0770     .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 1)
0771 };
0772 
0773 static const struct snd_kcontrol_new snd_us16x08_ch_int_ctl = {
0774     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0775     .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0776     .count = 16,
0777     .info = snd_us16x08_mix_info,
0778     .get = snd_us16x08_channel_get,
0779     .put = snd_us16x08_channel_put,
0780     .private_value = SND_US16X08_KCSET(SND_US16X08_FADER_BIAS, 1, 0, 133)
0781 };
0782 
0783 static const struct snd_kcontrol_new snd_us16x08_pan_int_ctl = {
0784     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0785     .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0786     .count = 16,
0787     .info = snd_us16x08_mix_info,
0788     .get = snd_us16x08_channel_get,
0789     .put = snd_us16x08_channel_put,
0790     .private_value = SND_US16X08_KCSET(SND_US16X08_FADER_BIAS, 1, 0, 255)
0791 };
0792 
0793 static const struct snd_kcontrol_new snd_us16x08_master_ctl = {
0794     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0795     .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0796     .count = 1,
0797     .info = snd_us16x08_master_info,
0798     .get = snd_us16x08_master_get,
0799     .put = snd_us16x08_master_put,
0800     .private_value = SND_US16X08_KCSET(SND_US16X08_FADER_BIAS, 1, 0, 133)
0801 };
0802 
0803 static const struct snd_kcontrol_new snd_us16x08_route_ctl = {
0804     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0805     .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0806     .count = 8,
0807     .info = snd_us16x08_route_info,
0808     .get = snd_us16x08_route_get,
0809     .put = snd_us16x08_route_put,
0810     .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 9)
0811 };
0812 
0813 static const struct snd_kcontrol_new snd_us16x08_bus_ctl = {
0814     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0815     .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0816     .count = 1,
0817     .info = snd_us16x08_switch_info,
0818     .get = snd_us16x08_bus_get,
0819     .put = snd_us16x08_bus_put,
0820     .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 1)
0821 };
0822 
0823 static const struct snd_kcontrol_new snd_us16x08_compswitch_ctl = {
0824     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0825     .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0826     .count = 16,
0827     .info = snd_us16x08_switch_info,
0828     .get = snd_us16x08_comp_get,
0829     .put = snd_us16x08_comp_put,
0830     .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 1)
0831 };
0832 
0833 static const struct snd_kcontrol_new snd_us16x08_comp_threshold_ctl = {
0834     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0835     .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0836     .count = 16,
0837     .info = snd_us16x08_mix_info,
0838     .get = snd_us16x08_comp_get,
0839     .put = snd_us16x08_comp_put,
0840     .private_value = SND_US16X08_KCSET(SND_US16X08_COMP_THRESHOLD_BIAS, 1,
0841     0, 0x20)
0842 };
0843 
0844 static const struct snd_kcontrol_new snd_us16x08_comp_ratio_ctl = {
0845     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0846     .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0847     .count = 16,
0848     .info = snd_us16x08_mix_info,
0849     .get = snd_us16x08_comp_get,
0850     .put = snd_us16x08_comp_put,
0851     .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0,
0852     sizeof(ratio_map) - 1), /*max*/
0853 };
0854 
0855 static const struct snd_kcontrol_new snd_us16x08_comp_gain_ctl = {
0856     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0857     .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0858     .count = 16,
0859     .info = snd_us16x08_mix_info,
0860     .get = snd_us16x08_comp_get,
0861     .put = snd_us16x08_comp_put,
0862     .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 0x14)
0863 };
0864 
0865 static const struct snd_kcontrol_new snd_us16x08_comp_attack_ctl = {
0866     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0867     .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0868     .count = 16,
0869     .info = snd_us16x08_mix_info,
0870     .get = snd_us16x08_comp_get,
0871     .put = snd_us16x08_comp_put,
0872     .private_value =
0873     SND_US16X08_KCSET(SND_US16X08_COMP_ATTACK_BIAS, 1, 0, 0xc6),
0874 };
0875 
0876 static const struct snd_kcontrol_new snd_us16x08_comp_release_ctl = {
0877     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0878     .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0879     .count = 16,
0880     .info = snd_us16x08_mix_info,
0881     .get = snd_us16x08_comp_get,
0882     .put = snd_us16x08_comp_put,
0883     .private_value =
0884     SND_US16X08_KCSET(SND_US16X08_COMP_RELEASE_BIAS, 1, 0, 0x63),
0885 };
0886 
0887 static const struct snd_kcontrol_new snd_us16x08_eq_gain_ctl = {
0888     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0889     .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0890     .count = 16,
0891     .info = snd_us16x08_mix_info,
0892     .get = snd_us16x08_eq_get,
0893     .put = snd_us16x08_eq_put,
0894     .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 24),
0895 };
0896 
0897 static const struct snd_kcontrol_new snd_us16x08_eq_low_freq_ctl = {
0898     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0899     .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0900     .count = 16,
0901     .info = snd_us16x08_mix_info,
0902     .get = snd_us16x08_eq_get,
0903     .put = snd_us16x08_eq_put,
0904     .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 0x1F),
0905 };
0906 
0907 static const struct snd_kcontrol_new snd_us16x08_eq_mid_freq_ctl = {
0908     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0909     .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0910     .count = 16,
0911     .info = snd_us16x08_mix_info,
0912     .get = snd_us16x08_eq_get,
0913     .put = snd_us16x08_eq_put,
0914     .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 0x3F)
0915 };
0916 
0917 static const struct snd_kcontrol_new snd_us16x08_eq_mid_width_ctl = {
0918     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0919     .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0920     .count = 16,
0921     .info = snd_us16x08_mix_info,
0922     .get = snd_us16x08_eq_get,
0923     .put = snd_us16x08_eq_put,
0924     .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 0x06)
0925 };
0926 
0927 static const struct snd_kcontrol_new snd_us16x08_eq_high_freq_ctl = {
0928     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0929     .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0930     .count = 16,
0931     .info = snd_us16x08_mix_info,
0932     .get = snd_us16x08_eq_get,
0933     .put = snd_us16x08_eq_put,
0934     .private_value =
0935     SND_US16X08_KCSET(SND_US16X08_EQ_HIGHFREQ_BIAS, 1, 0, 0x1F)
0936 };
0937 
0938 static const struct snd_kcontrol_new snd_us16x08_eq_switch_ctl = {
0939     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0940     .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0941     .count = 16,
0942     .info = snd_us16x08_switch_info,
0943     .get = snd_us16x08_eqswitch_get,
0944     .put = snd_us16x08_eqswitch_put,
0945     .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 1)
0946 };
0947 
0948 static const struct snd_kcontrol_new snd_us16x08_meter_ctl = {
0949     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0950     .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0951     .count = 1,
0952     .info = snd_us16x08_meter_info,
0953     .get = snd_us16x08_meter_get,
0954     .put = snd_us16x08_meter_put
0955 };
0956 
0957 /* control store preparation */
0958 
0959 /* setup compressor store and assign default value */
0960 static struct snd_us16x08_comp_store *snd_us16x08_create_comp_store(void)
0961 {
0962     int i;
0963     struct snd_us16x08_comp_store *tmp;
0964 
0965     tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
0966     if (!tmp)
0967         return NULL;
0968 
0969     for (i = 0; i < SND_US16X08_MAX_CHANNELS; i++) {
0970         tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_THRESHOLD)][i]
0971             = 0x20;
0972         tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RATIO)][i] = 0x00;
0973         tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_GAIN)][i] = 0x00;
0974         tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)][i] = 0x00;
0975         tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_ATTACK)][i] = 0x00;
0976         tmp->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RELEASE)][i] = 0x00;
0977     }
0978     return tmp;
0979 }
0980 
0981 /* setup EQ store and assign default values */
0982 static struct snd_us16x08_eq_store *snd_us16x08_create_eq_store(void)
0983 {
0984     int i, b_idx;
0985     struct snd_us16x08_eq_store *tmp;
0986 
0987     tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
0988     if (!tmp)
0989         return NULL;
0990 
0991     for (i = 0; i < SND_US16X08_MAX_CHANNELS; i++) {
0992         for (b_idx = 0; b_idx < SND_US16X08_ID_EQ_BAND_COUNT; b_idx++) {
0993             tmp->val[b_idx][0][i] = 0x0c;
0994             tmp->val[b_idx][3][i] = 0x00;
0995             switch (b_idx) {
0996             case 0: /* EQ Low */
0997                 tmp->val[b_idx][1][i] = 0x05;
0998                 tmp->val[b_idx][2][i] = 0xff;
0999                 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