brintos

brintos / linux-shallow public Read only

0
0
Text · 28.1 KiB · ff54804 Raw
1012 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *   Scarlett Driver for ALSA4 *5 *   Copyright (c) 2013 by Tobias Hoffmann6 *   Copyright (c) 2013 by Robin Gareus <robin at gareus.org>7 *   Copyright (c) 2002 by Takashi Iwai <tiwai at suse.de>8 *   Copyright (c) 2014 by Chris J Arges <chris.j.arges at canonical.com>9 *10 *   Many codes borrowed from audio.c by11 *	    Alan Cox (alan at lxorguk.ukuu.org.uk)12 *	    Thomas Sailer (sailer at ife.ee.ethz.ch)13 *14 *   Code cleanup:15 *   David Henningsson <david.henningsson at canonical.com>16 */17 18/*19 * Rewritten and extended to support more models, e.g. Scarlett 18i8.20 *21 * Auto-detection via UAC2 is not feasible to properly discover the vast22 * majority of features. It's related to both Linux/ALSA's UAC2 as well as23 * Focusrite's implementation of it. Eventually quirks may be sufficient but24 * right now it's a major headache to work around these things.25 *26 * NB. Neither the OSX nor the win driver provided by Focusrite performs27 * discovery, they seem to operate the same as this driver.28 */29 30/* Mixer Interface for the Focusrite Scarlett 18i6 audio interface.31 *32 * The protocol was reverse engineered by looking at communication between33 * Scarlett MixControl (v 1.2.128.0) and the Focusrite(R) Scarlett 18i634 * (firmware v305) using wireshark and usbmon in January 2013.35 * Extended in July 2013.36 *37 * this mixer gives complete access to all features of the device:38 *  - change Impedance of inputs (Line-in, Mic / Instrument, Hi-Z)39 *  - select clock source40 *  - dynamic input to mixer-matrix assignment41 *  - 18 x 6 mixer-matrix gain stages42 *  - bus routing & volume control43 *  - automatic re-initialization on connect if device was power-cycled44 *45 * USB URB commands overview (bRequest = 0x01 = UAC2_CS_CUR)46 * wIndex47 * 0x01 Analog Input line/instrument impedance switch, wValue=0x0901 +48 *      channel, data=Line/Inst (2bytes)49 *      pad (-10dB) switch, wValue=0x0b01 + channel, data=Off/On (2bytes)50 *      ?? wValue=0x0803/04, ?? (2bytes)51 * 0x0a Master Volume, wValue=0x0200+bus[0:all + only 1..4?] data(2bytes)52 *      Bus Mute/Unmute wValue=0x0100+bus[0:all + only 1..4?], data(2bytes)53 * 0x28 Clock source, wValue=0x0100, data={1:int,2:spdif,3:adat} (1byte)54 * 0x29 Set Sample-rate, wValue=0x0100, data=sample-rate(4bytes)55 * 0x32 Mixer mux, wValue=0x0600 + mixer-channel, data=input-to-connect(2bytes)56 * 0x33 Output mux, wValue=bus, data=input-to-connect(2bytes)57 * 0x34 Capture mux, wValue=0...18, data=input-to-connect(2bytes)58 * 0x3c Matrix Mixer gains, wValue=mixer-node  data=gain(2bytes)59 *      ?? [sometimes](4bytes, e.g 0x000003be 0x000003bf ...03ff)60 *61 * USB reads: (i.e. actually issued by original software)62 * 0x01 wValue=0x0901+channel (1byte!!), wValue=0x0b01+channed (1byte!!)63 * 0x29 wValue=0x0100 sample-rate(4bytes)64 *      wValue=0x0200 ?? 1byte (only once)65 * 0x2a wValue=0x0100 ?? 4bytes, sample-rate2 ??66 *67 * USB reads with bRequest = 0x03 = UAC2_CS_MEM68 * 0x3c wValue=0x0002 1byte: sync status (locked=1)69 *      wValue=0x0000 18*2byte: peak meter (inputs)70 *      wValue=0x0001 8(?)*2byte: peak meter (mix)71 *      wValue=0x0003 6*2byte: peak meter (pcm/daw)72 *73 * USB write with bRequest = 0x0374 * 0x3c Save settings to hardware: wValue=0x005a, data=0xa575 *76 *77 * <ditaa>78 *  /--------------\    18chn            6chn    /--------------\79 *  | Hardware  in +--+-------\        /------+--+ ALSA PCM out |80 *  \--------------/  |       |        |      |  \--------------/81 *                    |       |        |      |82 *                    |       v        v      |83 *                    |   +---------------+   |84 *                    |    \ Matrix  Mux /    |85 *                    |     +-----+-----+     |86 *                    |           |           |87 *                    |           | 18chn     |88 *                    |           v           |89 *                    |     +-----------+     |90 *                    |     | Mixer     |     |91 *                    |     |    Matrix |     |92 *                    |     |           |     |93 *                    |     | 18x6 Gain |     |94 *                    |     |   stages  |     |95 *                    |     +-----+-----+     |96 *                    |           |           |97 *                    |           |           |98 *                    | 18chn     | 6chn      | 6chn99 *                    v           v           v100 *                    =========================101 *             +---------------+     +--—------------+102 *              \ Output  Mux /       \ Capture Mux /103 *               +-----+-----+         +-----+-----+104 *                     |                     |105 *                     | 6chn                |106 *                     v                     |107 *              +-------------+              |108 *              | Master Gain |              |109 *              +------+------+              |110 *                     |                     |111 *                     | 6chn                | 18chn112 *                     | (3 stereo pairs)    |113 *  /--------------\   |                     |   /--------------\114 *  | Hardware out |<--/                     \-->| ALSA PCM  in |115 *  \--------------/                             \--------------/116 * </ditaa>117 *118 */119 120#include <linux/slab.h>121#include <linux/usb.h>122#include <linux/usb/audio-v2.h>123 124#include <sound/core.h>125#include <sound/control.h>126#include <sound/tlv.h>127 128#include "usbaudio.h"129#include "mixer.h"130#include "helper.h"131#include "power.h"132 133#include "mixer_scarlett.h"134 135/* some gui mixers can't handle negative ctl values */136#define SND_SCARLETT_LEVEL_BIAS 128137#define SND_SCARLETT_MATRIX_IN_MAX 18138#define SND_SCARLETT_CONTROLS_MAX 10139#define SND_SCARLETT_OFFSETS_MAX 5140 141enum {142	SCARLETT_OUTPUTS,143	SCARLETT_SWITCH_IMPEDANCE,144	SCARLETT_SWITCH_PAD,145	SCARLETT_SWITCH_GAIN,146};147 148enum {149	SCARLETT_OFFSET_PCM = 0,150	SCARLETT_OFFSET_ANALOG = 1,151	SCARLETT_OFFSET_SPDIF = 2,152	SCARLETT_OFFSET_ADAT = 3,153	SCARLETT_OFFSET_MIX = 4,154};155 156struct scarlett_mixer_elem_enum_info {157	int start;158	int len;159	int offsets[SND_SCARLETT_OFFSETS_MAX];160	char const * const *names;161};162 163struct scarlett_mixer_control {164	unsigned char num;165	unsigned char type;166	const char *name;167};168 169struct scarlett_device_info {170	int matrix_in;171	int matrix_out;172	int input_len;173	int output_len;174 175	struct scarlett_mixer_elem_enum_info opt_master;176	struct scarlett_mixer_elem_enum_info opt_matrix;177 178	/* initial values for matrix mux */179	int matrix_mux_init[SND_SCARLETT_MATRIX_IN_MAX];180 181	int num_controls;	/* number of items in controls */182	const struct scarlett_mixer_control controls[SND_SCARLETT_CONTROLS_MAX];183};184 185/********************** Enum Strings *************************/186 187static const struct scarlett_mixer_elem_enum_info opt_pad = {188	.start = 0,189	.len = 2,190	.offsets = {},191	.names = (char const * const []){192		"0dB", "-10dB"193	}194};195 196static const struct scarlett_mixer_elem_enum_info opt_gain = {197	.start = 0,198	.len = 2,199	.offsets = {},200	.names = (char const * const []){201		"Lo", "Hi"202	}203};204 205static const struct scarlett_mixer_elem_enum_info opt_impedance = {206	.start = 0,207	.len = 2,208	.offsets = {},209	.names = (char const * const []){210		"Line", "Hi-Z"211	}212};213 214static const struct scarlett_mixer_elem_enum_info opt_clock = {215	.start = 1,216	.len = 3,217	.offsets = {},218	.names = (char const * const []){219		"Internal", "SPDIF", "ADAT"220	}221};222 223static const struct scarlett_mixer_elem_enum_info opt_sync = {224	.start = 0,225	.len = 2,226	.offsets = {},227	.names = (char const * const []){228		"No Lock", "Locked"229	}230};231 232static int scarlett_ctl_switch_info(struct snd_kcontrol *kctl,233		struct snd_ctl_elem_info *uinfo)234{235	struct usb_mixer_elem_info *elem = kctl->private_data;236 237	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;238	uinfo->count = elem->channels;239	uinfo->value.integer.min = 0;240	uinfo->value.integer.max = 1;241	return 0;242}243 244static int scarlett_ctl_switch_get(struct snd_kcontrol *kctl,245		struct snd_ctl_elem_value *ucontrol)246{247	struct usb_mixer_elem_info *elem = kctl->private_data;248	int i, err, val;249 250	for (i = 0; i < elem->channels; i++) {251		err = snd_usb_get_cur_mix_value(elem, i, i, &val);252		if (err < 0)253			return err;254 255		val = !val; /* invert mute logic for mixer */256		ucontrol->value.integer.value[i] = val;257	}258 259	return 0;260}261 262static int scarlett_ctl_switch_put(struct snd_kcontrol *kctl,263		struct snd_ctl_elem_value *ucontrol)264{265	struct usb_mixer_elem_info *elem = kctl->private_data;266	int i, changed = 0;267	int err, oval, val;268 269	for (i = 0; i < elem->channels; i++) {270		err = snd_usb_get_cur_mix_value(elem, i, i, &oval);271		if (err < 0)272			return err;273 274		val = ucontrol->value.integer.value[i];275		val = !val;276		if (oval != val) {277			err = snd_usb_set_cur_mix_value(elem, i, i, val);278			if (err < 0)279				return err;280 281			changed = 1;282		}283	}284 285	return changed;286}287 288static int scarlett_ctl_resume(struct usb_mixer_elem_list *list)289{290	struct usb_mixer_elem_info *elem = mixer_elem_list_to_info(list);291	int i;292 293	for (i = 0; i < elem->channels; i++)294		if (elem->cached & (1 << i))295			snd_usb_set_cur_mix_value(elem, i, i,296						  elem->cache_val[i]);297	return 0;298}299 300static int scarlett_ctl_info(struct snd_kcontrol *kctl,301			     struct snd_ctl_elem_info *uinfo)302{303	struct usb_mixer_elem_info *elem = kctl->private_data;304 305	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;306	uinfo->count = elem->channels;307	uinfo->value.integer.min = 0;308	uinfo->value.integer.max = (int)kctl->private_value +309		SND_SCARLETT_LEVEL_BIAS;310	uinfo->value.integer.step = 1;311	return 0;312}313 314static int scarlett_ctl_get(struct snd_kcontrol *kctl,315			    struct snd_ctl_elem_value *ucontrol)316{317	struct usb_mixer_elem_info *elem = kctl->private_data;318	int i, err, val;319 320	for (i = 0; i < elem->channels; i++) {321		err = snd_usb_get_cur_mix_value(elem, i, i, &val);322		if (err < 0)323			return err;324 325		val = clamp(val / 256, -128, (int)kctl->private_value) +326				    SND_SCARLETT_LEVEL_BIAS;327		ucontrol->value.integer.value[i] = val;328	}329 330	return 0;331}332 333static int scarlett_ctl_put(struct snd_kcontrol *kctl,334			    struct snd_ctl_elem_value *ucontrol)335{336	struct usb_mixer_elem_info *elem = kctl->private_data;337	int i, changed = 0;338	int err, oval, val;339 340	for (i = 0; i < elem->channels; i++) {341		err = snd_usb_get_cur_mix_value(elem, i, i, &oval);342		if (err < 0)343			return err;344 345		val = ucontrol->value.integer.value[i] -346			SND_SCARLETT_LEVEL_BIAS;347		val = val * 256;348		if (oval != val) {349			err = snd_usb_set_cur_mix_value(elem, i, i, val);350			if (err < 0)351				return err;352 353			changed = 1;354		}355	}356 357	return changed;358}359 360static void scarlett_generate_name(int i, char *dst, int offsets[])361{362	if (i > offsets[SCARLETT_OFFSET_MIX])363		sprintf(dst, "Mix %c",364			'A'+(i - offsets[SCARLETT_OFFSET_MIX] - 1));365	else if (i > offsets[SCARLETT_OFFSET_ADAT])366		sprintf(dst, "ADAT %d", i - offsets[SCARLETT_OFFSET_ADAT]);367	else if (i > offsets[SCARLETT_OFFSET_SPDIF])368		sprintf(dst, "SPDIF %d", i - offsets[SCARLETT_OFFSET_SPDIF]);369	else if (i > offsets[SCARLETT_OFFSET_ANALOG])370		sprintf(dst, "Analog %d", i - offsets[SCARLETT_OFFSET_ANALOG]);371	else if (i > offsets[SCARLETT_OFFSET_PCM])372		sprintf(dst, "PCM %d", i - offsets[SCARLETT_OFFSET_PCM]);373	else374		sprintf(dst, "Off");375}376 377static int scarlett_ctl_enum_dynamic_info(struct snd_kcontrol *kctl,378					  struct snd_ctl_elem_info *uinfo)379{380	struct usb_mixer_elem_info *elem = kctl->private_data;381	struct scarlett_mixer_elem_enum_info *opt = elem->private_data;382	unsigned int items = opt->len;383 384	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;385	uinfo->count = elem->channels;386	uinfo->value.enumerated.items = items;387 388	if (uinfo->value.enumerated.item >= items)389		uinfo->value.enumerated.item = items - 1;390 391	/* generate name dynamically based on item number and offset info */392	scarlett_generate_name(uinfo->value.enumerated.item,393			       uinfo->value.enumerated.name,394			       opt->offsets);395 396	return 0;397}398 399static int scarlett_ctl_enum_info(struct snd_kcontrol *kctl,400				  struct snd_ctl_elem_info *uinfo)401{402	struct usb_mixer_elem_info *elem = kctl->private_data;403	struct scarlett_mixer_elem_enum_info *opt = elem->private_data;404 405	return snd_ctl_enum_info(uinfo, elem->channels, opt->len,406				 (const char * const *)opt->names);407}408 409static int scarlett_ctl_enum_get(struct snd_kcontrol *kctl,410				 struct snd_ctl_elem_value *ucontrol)411{412	struct usb_mixer_elem_info *elem = kctl->private_data;413	struct scarlett_mixer_elem_enum_info *opt = elem->private_data;414	int err, val;415 416	err = snd_usb_get_cur_mix_value(elem, 0, 0, &val);417	if (err < 0)418		return err;419 420	val = clamp(val - opt->start, 0, opt->len-1);421 422	ucontrol->value.enumerated.item[0] = val;423 424	return 0;425}426 427static int scarlett_ctl_enum_put(struct snd_kcontrol *kctl,428				 struct snd_ctl_elem_value *ucontrol)429{430	struct usb_mixer_elem_info *elem = kctl->private_data;431	struct scarlett_mixer_elem_enum_info *opt = elem->private_data;432	int err, oval, val;433 434	err = snd_usb_get_cur_mix_value(elem, 0, 0, &oval);435	if (err < 0)436		return err;437 438	val = ucontrol->value.integer.value[0];439	val = val + opt->start;440	if (val != oval) {441		snd_usb_set_cur_mix_value(elem, 0, 0, val);442		return 1;443	}444	return 0;445}446 447static int scarlett_ctl_enum_resume(struct usb_mixer_elem_list *list)448{449	struct usb_mixer_elem_info *elem = mixer_elem_list_to_info(list);450 451	if (elem->cached)452		snd_usb_set_cur_mix_value(elem, 0, 0, *elem->cache_val);453	return 0;454}455 456static int scarlett_ctl_meter_get(struct snd_kcontrol *kctl,457				  struct snd_ctl_elem_value *ucontrol)458{459	struct usb_mixer_elem_info *elem = kctl->private_data;460	struct snd_usb_audio *chip = elem->head.mixer->chip;461	unsigned char buf[2 * MAX_CHANNELS] = {0, };462	int wValue = (elem->control << 8) | elem->idx_off;463	int idx = snd_usb_ctrl_intf(elem->head.mixer->hostif) | (elem->head.id << 8);464	int err;465 466	err = snd_usb_ctl_msg(chip->dev,467				usb_rcvctrlpipe(chip->dev, 0),468				UAC2_CS_MEM,469				USB_RECIP_INTERFACE | USB_TYPE_CLASS |470				USB_DIR_IN, wValue, idx, buf, elem->channels);471	if (err < 0)472		return err;473 474	ucontrol->value.enumerated.item[0] = clamp((int)buf[0], 0, 1);475	return 0;476}477 478static const struct snd_kcontrol_new usb_scarlett_ctl_switch = {479	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,480	.name = "",481	.info = scarlett_ctl_switch_info,482	.get =  scarlett_ctl_switch_get,483	.put =  scarlett_ctl_switch_put,484};485 486static const DECLARE_TLV_DB_SCALE(db_scale_scarlett_gain, -12800, 100, 0);487 488static const struct snd_kcontrol_new usb_scarlett_ctl = {489	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,490	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |491		  SNDRV_CTL_ELEM_ACCESS_TLV_READ,492	.name = "",493	.info = scarlett_ctl_info,494	.get =  scarlett_ctl_get,495	.put =  scarlett_ctl_put,496	.private_value = 6,  /* max value */497	.tlv = { .p = db_scale_scarlett_gain }498};499 500static const struct snd_kcontrol_new usb_scarlett_ctl_master = {501	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,502	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |503		  SNDRV_CTL_ELEM_ACCESS_TLV_READ,504	.name = "",505	.info = scarlett_ctl_info,506	.get =  scarlett_ctl_get,507	.put =  scarlett_ctl_put,508	.private_value = 6,  /* max value */509	.tlv = { .p = db_scale_scarlett_gain }510};511 512static const struct snd_kcontrol_new usb_scarlett_ctl_enum = {513	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,514	.name = "",515	.info = scarlett_ctl_enum_info,516	.get =  scarlett_ctl_enum_get,517	.put =  scarlett_ctl_enum_put,518};519 520static const struct snd_kcontrol_new usb_scarlett_ctl_dynamic_enum = {521	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,522	.name = "",523	.info = scarlett_ctl_enum_dynamic_info,524	.get =  scarlett_ctl_enum_get,525	.put =  scarlett_ctl_enum_put,526};527 528static const struct snd_kcontrol_new usb_scarlett_ctl_sync = {529	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,530	.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,531	.name = "",532	.info = scarlett_ctl_enum_info,533	.get =  scarlett_ctl_meter_get,534};535 536static int add_new_ctl(struct usb_mixer_interface *mixer,537		       const struct snd_kcontrol_new *ncontrol,538		       usb_mixer_elem_resume_func_t resume,539		       int index, int offset, int num,540		       int val_type, int channels, const char *name,541		       const struct scarlett_mixer_elem_enum_info *opt,542		       struct usb_mixer_elem_info **elem_ret543)544{545	struct snd_kcontrol *kctl;546	struct usb_mixer_elem_info *elem;547	int err;548 549	elem = kzalloc(sizeof(*elem), GFP_KERNEL);550	if (!elem)551		return -ENOMEM;552 553	elem->head.mixer = mixer;554	elem->head.resume = resume;555	elem->control = offset;556	elem->idx_off = num;557	elem->head.id = index;558	elem->val_type = val_type;559 560	elem->channels = channels;561 562	/* add scarlett_mixer_elem_enum_info struct */563	elem->private_data = (void *)opt;564 565	kctl = snd_ctl_new1(ncontrol, elem);566	if (!kctl) {567		kfree(elem);568		return -ENOMEM;569	}570	kctl->private_free = snd_usb_mixer_elem_free;571 572	strscpy(kctl->id.name, name, sizeof(kctl->id.name));573 574	err = snd_usb_mixer_add_control(&elem->head, kctl);575	if (err < 0)576		return err;577 578	if (elem_ret)579		*elem_ret = elem;580 581	return 0;582}583 584static int add_output_ctls(struct usb_mixer_interface *mixer,585			   int index, const char *name,586			   const struct scarlett_device_info *info)587{588	int err;589	char mx[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];590	struct usb_mixer_elem_info *elem;591 592	/* Add mute switch */593	snprintf(mx, sizeof(mx), "Master %d (%s) Playback Switch",594		index + 1, name);595	err = add_new_ctl(mixer, &usb_scarlett_ctl_switch,596			  scarlett_ctl_resume, 0x0a, 0x01,597			  2*index+1, USB_MIXER_S16, 2, mx, NULL, &elem);598	if (err < 0)599		return err;600 601	/* Add volume control and initialize to 0 */602	snprintf(mx, sizeof(mx), "Master %d (%s) Playback Volume",603		index + 1, name);604	err = add_new_ctl(mixer, &usb_scarlett_ctl_master,605			  scarlett_ctl_resume, 0x0a, 0x02,606			  2*index+1, USB_MIXER_S16, 2, mx, NULL, &elem);607	if (err < 0)608		return err;609 610	/* Add L channel source playback enumeration */611	snprintf(mx, sizeof(mx), "Master %dL (%s) Source Playback Enum",612		index + 1, name);613	err = add_new_ctl(mixer, &usb_scarlett_ctl_dynamic_enum,614			  scarlett_ctl_enum_resume, 0x33, 0x00,615			  2*index, USB_MIXER_S16, 1, mx, &info->opt_master,616			  &elem);617	if (err < 0)618		return err;619 620	/* Add R channel source playback enumeration */621	snprintf(mx, sizeof(mx), "Master %dR (%s) Source Playback Enum",622		index + 1, name);623	err = add_new_ctl(mixer, &usb_scarlett_ctl_dynamic_enum,624			  scarlett_ctl_enum_resume, 0x33, 0x00,625			  2*index+1, USB_MIXER_S16, 1, mx, &info->opt_master,626			  &elem);627	if (err < 0)628		return err;629 630	return 0;631}632 633/********************** device-specific config *************************/634 635/*  untested...  */636static const struct scarlett_device_info s6i6_info = {637	.matrix_in = 18,638	.matrix_out = 8,639	.input_len = 6,640	.output_len = 6,641 642	.opt_master = {643		.start = -1,644		.len = 27,645		.offsets = {0, 12, 16, 18, 18},646		.names = NULL647	},648 649	.opt_matrix = {650		.start = -1,651		.len = 19,652		.offsets = {0, 12, 16, 18, 18},653		.names = NULL654	},655 656	.num_controls = 9,657	.controls = {658		{ .num = 0, .type = SCARLETT_OUTPUTS, .name = "Monitor" },659		{ .num = 1, .type = SCARLETT_OUTPUTS, .name = "Headphone" },660		{ .num = 2, .type = SCARLETT_OUTPUTS, .name = "SPDIF" },661		{ .num = 1, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL},662		{ .num = 1, .type = SCARLETT_SWITCH_PAD, .name = NULL},663		{ .num = 2, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL},664		{ .num = 2, .type = SCARLETT_SWITCH_PAD, .name = NULL},665		{ .num = 3, .type = SCARLETT_SWITCH_GAIN, .name = NULL},666		{ .num = 4, .type = SCARLETT_SWITCH_GAIN, .name = NULL},667	},668 669	.matrix_mux_init = {670		12, 13, 14, 15,                 /* Analog -> 1..4 */671		16, 17,                          /* SPDIF -> 5,6 */672		0, 1, 2, 3, 4, 5, 6, 7,     /* PCM[1..12] -> 7..18 */673		8, 9, 10, 11674	}675};676 677/*  untested...  */678static const struct scarlett_device_info s8i6_info = {679	.matrix_in = 18,680	.matrix_out = 6,681	.input_len = 8,682	.output_len = 6,683 684	.opt_master = {685		.start = -1,686		.len = 25,687		.offsets = {0, 12, 16, 18, 18},688		.names = NULL689	},690 691	.opt_matrix = {692		.start = -1,693		.len = 19,694		.offsets = {0, 12, 16, 18, 18},695		.names = NULL696	},697 698	.num_controls = 7,699	.controls = {700		{ .num = 0, .type = SCARLETT_OUTPUTS, .name = "Monitor" },701		{ .num = 1, .type = SCARLETT_OUTPUTS, .name = "Headphone" },702		{ .num = 2, .type = SCARLETT_OUTPUTS, .name = "SPDIF" },703		{ .num = 1, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL},704		{ .num = 2, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL},705		{ .num = 3, .type = SCARLETT_SWITCH_PAD, .name = NULL},706		{ .num = 4, .type = SCARLETT_SWITCH_PAD, .name = NULL},707	},708 709	.matrix_mux_init = {710		12, 13, 14, 15,                 /* Analog -> 1..4 */711		16, 17,                          /* SPDIF -> 5,6 */712		0, 1, 2, 3, 4, 5, 6, 7,     /* PCM[1..12] -> 7..18 */713		8, 9, 10, 11714	}715};716 717static const struct scarlett_device_info s18i6_info = {718	.matrix_in = 18,719	.matrix_out = 6,720	.input_len = 18,721	.output_len = 6,722 723	.opt_master = {724		.start = -1,725		.len = 31,726		.offsets = {0, 6, 14, 16, 24},727		.names = NULL,728	},729 730	.opt_matrix = {731		.start = -1,732		.len = 25,733		.offsets = {0, 6, 14, 16, 24},734		.names = NULL,735	},736 737	.num_controls = 5,738	.controls = {739		{ .num = 0, .type = SCARLETT_OUTPUTS, .name = "Monitor" },740		{ .num = 1, .type = SCARLETT_OUTPUTS, .name = "Headphone" },741		{ .num = 2, .type = SCARLETT_OUTPUTS, .name = "SPDIF" },742		{ .num = 1, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL},743		{ .num = 2, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL},744	},745 746	.matrix_mux_init = {747		 6,  7,  8,  9, 10, 11, 12, 13, /* Analog -> 1..8 */748		16, 17, 18, 19, 20, 21,     /* ADAT[1..6] -> 9..14 */749		14, 15,                          /* SPDIF -> 15,16 */750		0, 1                          /* PCM[1,2] -> 17,18 */751	}752};753 754static const struct scarlett_device_info s18i8_info = {755	.matrix_in = 18,756	.matrix_out = 8,757	.input_len = 18,758	.output_len = 8,759 760	.opt_master = {761		.start = -1,762		.len = 35,763		.offsets = {0, 8, 16, 18, 26},764		.names = NULL765	},766 767	.opt_matrix = {768		.start = -1,769		.len = 27,770		.offsets = {0, 8, 16, 18, 26},771		.names = NULL772	},773 774	.num_controls = 10,775	.controls = {776		{ .num = 0, .type = SCARLETT_OUTPUTS, .name = "Monitor" },777		{ .num = 1, .type = SCARLETT_OUTPUTS, .name = "Headphone 1" },778		{ .num = 2, .type = SCARLETT_OUTPUTS, .name = "Headphone 2" },779		{ .num = 3, .type = SCARLETT_OUTPUTS, .name = "SPDIF" },780		{ .num = 1, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL},781		{ .num = 1, .type = SCARLETT_SWITCH_PAD, .name = NULL},782		{ .num = 2, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL},783		{ .num = 2, .type = SCARLETT_SWITCH_PAD, .name = NULL},784		{ .num = 3, .type = SCARLETT_SWITCH_PAD, .name = NULL},785		{ .num = 4, .type = SCARLETT_SWITCH_PAD, .name = NULL},786	},787 788	.matrix_mux_init = {789		 8,  9, 10, 11, 12, 13, 14, 15, /* Analog -> 1..8 */790		18, 19, 20, 21, 22, 23,     /* ADAT[1..6] -> 9..14 */791		16, 17,                          /* SPDIF -> 15,16 */792		0, 1                          /* PCM[1,2] -> 17,18 */793	}794};795 796static const struct scarlett_device_info s18i20_info = {797	.matrix_in = 18,798	.matrix_out = 8,799	.input_len = 18,800	.output_len = 20,801 802	.opt_master = {803		.start = -1,804		.len = 47,805		.offsets = {0, 20, 28, 30, 38},806		.names = NULL807	},808 809	.opt_matrix = {810		.start = -1,811		.len = 39,812		.offsets = {0, 20, 28, 30, 38},813		.names = NULL814	},815 816	.num_controls = 10,817	.controls = {818		{ .num = 0, .type = SCARLETT_OUTPUTS, .name = "Monitor" },819		{ .num = 1, .type = SCARLETT_OUTPUTS, .name = "Line 3/4" },820		{ .num = 2, .type = SCARLETT_OUTPUTS, .name = "Line 5/6" },821		{ .num = 3, .type = SCARLETT_OUTPUTS, .name = "Line 7/8" },822		{ .num = 4, .type = SCARLETT_OUTPUTS, .name = "Line 9/10" },823		{ .num = 5, .type = SCARLETT_OUTPUTS, .name = "SPDIF" },824		{ .num = 6, .type = SCARLETT_OUTPUTS, .name = "ADAT 1/2" },825		{ .num = 7, .type = SCARLETT_OUTPUTS, .name = "ADAT 3/4" },826		{ .num = 8, .type = SCARLETT_OUTPUTS, .name = "ADAT 5/6" },827		{ .num = 9, .type = SCARLETT_OUTPUTS, .name = "ADAT 7/8" },828		/*{ .num = 1, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL},829		{ .num = 1, .type = SCARLETT_SWITCH_PAD, .name = NULL},830		{ .num = 2, .type = SCARLETT_SWITCH_IMPEDANCE, .name = NULL},831		{ .num = 2, .type = SCARLETT_SWITCH_PAD, .name = NULL},832		{ .num = 3, .type = SCARLETT_SWITCH_PAD, .name = NULL},833		{ .num = 4, .type = SCARLETT_SWITCH_PAD, .name = NULL},*/834	},835 836	.matrix_mux_init = {837		20, 21, 22, 23, 24, 25, 26, 27, /* Analog -> 1..8 */838		30, 31, 32, 33, 34, 35,     /* ADAT[1..6] -> 9..14 */839		28, 29,                          /* SPDIF -> 15,16 */840		0, 1                          /* PCM[1,2] -> 17,18 */841	}842};843 844 845static int scarlett_controls_create_generic(struct usb_mixer_interface *mixer,846	const struct scarlett_device_info *info)847{848	int i, err;849	char mx[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];850	const struct scarlett_mixer_control *ctl;851	struct usb_mixer_elem_info *elem;852 853	/* create master switch and playback volume */854	err = add_new_ctl(mixer, &usb_scarlett_ctl_switch,855			  scarlett_ctl_resume, 0x0a, 0x01, 0,856			  USB_MIXER_S16, 1, "Master Playback Switch", NULL,857			  &elem);858	if (err < 0)859		return err;860 861	err = add_new_ctl(mixer, &usb_scarlett_ctl_master,862			  scarlett_ctl_resume, 0x0a, 0x02, 0,863			  USB_MIXER_S16, 1, "Master Playback Volume", NULL,864			  &elem);865	if (err < 0)866		return err;867 868	/* iterate through controls in info struct and create each one */869	for (i = 0; i < info->num_controls; i++) {870		ctl = &info->controls[i];871 872		switch (ctl->type) {873		case SCARLETT_OUTPUTS:874			err = add_output_ctls(mixer, ctl->num, ctl->name, info);875			if (err < 0)876				return err;877			break;878		case SCARLETT_SWITCH_IMPEDANCE:879			sprintf(mx, "Input %d Impedance Switch", ctl->num);880			err = add_new_ctl(mixer, &usb_scarlett_ctl_enum,881					  scarlett_ctl_enum_resume, 0x01,882					  0x09, ctl->num, USB_MIXER_S16, 1, mx,883					  &opt_impedance, &elem);884			if (err < 0)885				return err;886			break;887		case SCARLETT_SWITCH_PAD:888			sprintf(mx, "Input %d Pad Switch", ctl->num);889			err = add_new_ctl(mixer, &usb_scarlett_ctl_enum,890					  scarlett_ctl_enum_resume, 0x01,891					  0x0b, ctl->num, USB_MIXER_S16, 1, mx,892					  &opt_pad, &elem);893			if (err < 0)894				return err;895			break;896		case SCARLETT_SWITCH_GAIN:897			sprintf(mx, "Input %d Gain Switch", ctl->num);898			err = add_new_ctl(mixer, &usb_scarlett_ctl_enum,899					  scarlett_ctl_enum_resume, 0x01,900					  0x08, ctl->num, USB_MIXER_S16, 1, mx,901					  &opt_gain, &elem);902			if (err < 0)903				return err;904			break;905		}906	}907 908	return 0;909}910 911/*912 * Create and initialize a mixer for the Focusrite(R) Scarlett913 */914int snd_scarlett_controls_create(struct usb_mixer_interface *mixer)915{916	int err, i, o;917	char mx[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];918	const struct scarlett_device_info *info;919	struct usb_mixer_elem_info *elem;920	static char sample_rate_buffer[4] = { '\x80', '\xbb', '\x00', '\x00' };921 922	/* only use UAC_VERSION_2 */923	if (!mixer->protocol)924		return 0;925 926	switch (mixer->chip->usb_id) {927	case USB_ID(0x1235, 0x8012):928		info = &s6i6_info;929		break;930	case USB_ID(0x1235, 0x8002):931		info = &s8i6_info;932		break;933	case USB_ID(0x1235, 0x8004):934		info = &s18i6_info;935		break;936	case USB_ID(0x1235, 0x8014):937		info = &s18i8_info;938		break;939	case USB_ID(0x1235, 0x800c):940		info = &s18i20_info;941		break;942	default: /* device not (yet) supported */943		return -EINVAL;944	}945 946	/* generic function to create controls */947	err = scarlett_controls_create_generic(mixer, info);948	if (err < 0)949		return err;950 951	/* setup matrix controls */952	for (i = 0; i < info->matrix_in; i++) {953		snprintf(mx, sizeof(mx), "Matrix %02d Input Playback Route",954			 i+1);955		err = add_new_ctl(mixer, &usb_scarlett_ctl_dynamic_enum,956				  scarlett_ctl_enum_resume, 0x32,957				  0x06, i, USB_MIXER_S16, 1, mx,958				  &info->opt_matrix, &elem);959		if (err < 0)960			return err;961 962		for (o = 0; o < info->matrix_out; o++) {963			sprintf(mx, "Matrix %02d Mix %c Playback Volume", i+1,964				o+'A');965			err = add_new_ctl(mixer, &usb_scarlett_ctl,966					  scarlett_ctl_resume, 0x3c, 0x00,967					  (i << 3) + (o & 0x07), USB_MIXER_S16,968					  1, mx, NULL, &elem);969			if (err < 0)970				return err;971 972		}973	}974 975	for (i = 0; i < info->input_len; i++) {976		snprintf(mx, sizeof(mx), "Input Source %02d Capture Route",977			 i+1);978		err = add_new_ctl(mixer, &usb_scarlett_ctl_dynamic_enum,979				  scarlett_ctl_enum_resume, 0x34,980				  0x00, i, USB_MIXER_S16, 1, mx,981				  &info->opt_master, &elem);982		if (err < 0)983			return err;984	}985 986	/* val_len == 1 needed here */987	err = add_new_ctl(mixer, &usb_scarlett_ctl_enum,988			  scarlett_ctl_enum_resume, 0x28, 0x01, 0,989			  USB_MIXER_U8, 1, "Sample Clock Source",990			  &opt_clock, &elem);991	if (err < 0)992		return err;993 994	/* val_len == 1 and UAC2_CS_MEM */995	err = add_new_ctl(mixer, &usb_scarlett_ctl_sync, NULL, 0x3c, 0x00, 2,996			  USB_MIXER_U8, 1, "Sample Clock Sync Status",997			  &opt_sync, &elem);998	if (err < 0)999		return err;1000 1001	/* initialize sampling rate to 48000 */1002	err = snd_usb_ctl_msg(mixer->chip->dev,1003		usb_sndctrlpipe(mixer->chip->dev, 0), UAC2_CS_CUR,1004		USB_RECIP_INTERFACE | USB_TYPE_CLASS |1005		USB_DIR_OUT, 0x0100, snd_usb_ctrl_intf(mixer->hostif) |1006		(0x29 << 8), sample_rate_buffer, 4);1007	if (err < 0)1008		return err;1009 1010	return err;1011}1012