File Index
Files and directories
Sign in
FILE

mixer_us16x08.c

File preview with syntax highlighting.

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