brintos

brintos / linux-shallow public Read only

0
0
Text · 15.3 KiB · fac4bbc Raw
596 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Presonus Studio 1810c driver for ALSA4 * Copyright (C) 2019 Nick Kossifidis <mickflemm@gmail.com>5 *6 * Based on reverse engineering of the communication protocol7 * between the windows driver / Univeral Control (UC) program8 * and the device, through usbmon.9 *10 * For now this bypasses the mixer, with all channels split,11 * so that the software can mix with greater flexibility.12 * It also adds controls for the 4 buttons on the front of13 * the device.14 */15 16#include <linux/usb.h>17#include <linux/usb/audio-v2.h>18#include <linux/slab.h>19#include <sound/core.h>20#include <sound/control.h>21 22#include "usbaudio.h"23#include "mixer.h"24#include "mixer_quirks.h"25#include "helper.h"26#include "mixer_s1810c.h"27 28#define SC1810C_CMD_REQ	16029#define SC1810C_CMD_REQTYPE \30	(USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT)31#define SC1810C_CMD_F1		0x5061726932#define SC1810C_CMD_F2		0x1433 34/*35 * DISCLAIMER: These are just guesses based on the36 * dumps I got.37 *38 * It seems like a selects between39 * device (0), mixer (0x64) and output (0x65)40 *41 * For mixer (0x64):42 *  * b selects an input channel (see below).43 *  * c selects an output channel pair (see below).44 *  * d selects left (0) or right (1) of that pair.45 *  * e 0-> disconnect, 0x01000000-> connect,46 *	0x0109-> used for stereo-linking channels,47 *	e is also used for setting volume levels48 *	in which case b is also set so I guess49 *	this way it is possible to set the volume50 *	level from the specified input to the51 *	specified output.52 *53 * IN Channels:54 * 0  - 7  Mic/Inst/Line (Analog inputs)55 * 8  - 9  S/PDIF56 * 10 - 17 ADAT57 * 18 - 35 DAW (Inputs from the host)58 *59 * OUT Channels (pairs):60 * 0 -> Main out61 * 1 -> Line1/262 * 2 -> Line3/463 * 3 -> S/PDIF64 * 4 -> ADAT?65 *66 * For device (0):67 *  * b and c are not used, at least not on the68 *    dumps I got.69 *  * d sets the control id to be modified70 *    (see below).71 *  * e sets the setting for that control.72 *    (so for the switches I was interested73 *    in it's 0/1)74 *75 * For output (0x65):76 *   * b is the output channel (see above).77 *   * c is zero.78 *   * e I guess the same as with mixer except 0x010979 *	 which I didn't see in my dumps.80 *81 * The two fixed fields have the same values for82 * mixer and output but a different set for device.83 */84struct s1810c_ctl_packet {85	u32 a;86	u32 b;87	u32 fixed1;88	u32 fixed2;89	u32 c;90	u32 d;91	u32 e;92};93 94#define SC1810C_CTL_LINE_SW	095#define SC1810C_CTL_MUTE_SW	196#define SC1810C_CTL_AB_SW	397#define SC1810C_CTL_48V_SW	498 99#define SC1810C_SET_STATE_REQ	161100#define SC1810C_SET_STATE_REQTYPE SC1810C_CMD_REQTYPE101#define SC1810C_SET_STATE_F1	0x64656D73102#define SC1810C_SET_STATE_F2	0xF4103 104#define SC1810C_GET_STATE_REQ	162105#define SC1810C_GET_STATE_REQTYPE \106	(USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN)107#define SC1810C_GET_STATE_F1	SC1810C_SET_STATE_F1108#define SC1810C_GET_STATE_F2	SC1810C_SET_STATE_F2109 110#define SC1810C_STATE_F1_IDX	2111#define SC1810C_STATE_F2_IDX	3112 113/*114 * This packet includes mixer volumes and115 * various other fields, it's an extended116 * version of ctl_packet, with a and b117 * being zero and different f1/f2.118 */119struct s1810c_state_packet {120	u32 fields[63];121};122 123#define SC1810C_STATE_48V_SW	58124#define SC1810C_STATE_LINE_SW	59125#define SC1810C_STATE_MUTE_SW	60126#define SC1810C_STATE_AB_SW	62127 128struct s1810_mixer_state {129	uint16_t seqnum;130	struct mutex usb_mutex;131	struct mutex data_mutex;132};133 134static int135snd_s1810c_send_ctl_packet(struct usb_device *dev, u32 a,136			   u32 b, u32 c, u32 d, u32 e)137{138	struct s1810c_ctl_packet pkt = { 0 };139	int ret = 0;140 141	pkt.fixed1 = SC1810C_CMD_F1;142	pkt.fixed2 = SC1810C_CMD_F2;143 144	pkt.a = a;145	pkt.b = b;146	pkt.c = c;147	pkt.d = d;148	/*149	 * Value for settings 0/1 for this150	 * output channel is always 0 (probably because151	 * there is no ADAT output on 1810c)152	 */153	pkt.e = (c == 4) ? 0 : e;154 155	ret = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),156			      SC1810C_CMD_REQ,157			      SC1810C_CMD_REQTYPE, 0, 0, &pkt, sizeof(pkt));158	if (ret < 0) {159		dev_warn(&dev->dev, "could not send ctl packet\n");160		return ret;161	}162	return 0;163}164 165/*166 * When opening Universal Control the program periodically167 * sends and receives state packets for syncinc state between168 * the device and the host.169 *170 * Note that if we send only the request to get data back we'll171 * get an error, we need to first send an empty state packet and172 * then ask to receive a filled. Their seqnumbers must also match.173 */174static int175snd_sc1810c_get_status_field(struct usb_device *dev,176			     u32 *field, int field_idx, uint16_t *seqnum)177{178	struct s1810c_state_packet pkt_out = { { 0 } };179	struct s1810c_state_packet pkt_in = { { 0 } };180	int ret = 0;181 182	pkt_out.fields[SC1810C_STATE_F1_IDX] = SC1810C_SET_STATE_F1;183	pkt_out.fields[SC1810C_STATE_F2_IDX] = SC1810C_SET_STATE_F2;184	ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),185			      SC1810C_SET_STATE_REQ,186			      SC1810C_SET_STATE_REQTYPE,187			      (*seqnum), 0, &pkt_out, sizeof(pkt_out));188	if (ret < 0) {189		dev_warn(&dev->dev, "could not send state packet (%d)\n", ret);190		return ret;191	}192 193	ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),194			      SC1810C_GET_STATE_REQ,195			      SC1810C_GET_STATE_REQTYPE,196			      (*seqnum), 0, &pkt_in, sizeof(pkt_in));197	if (ret < 0) {198		dev_warn(&dev->dev, "could not get state field %u (%d)\n",199			 field_idx, ret);200		return ret;201	}202 203	(*field) = pkt_in.fields[field_idx];204	(*seqnum)++;205	return 0;206}207 208/*209 * This is what I got when bypassing the mixer with210 * all channels split. I'm not 100% sure of what's going211 * on, I could probably clean this up based on my observations212 * but I prefer to keep the same behavior as the windows driver.213 */214static int snd_s1810c_init_mixer_maps(struct snd_usb_audio *chip)215{216	u32 a, b, c, e, n, off;217	struct usb_device *dev = chip->dev;218 219	/* Set initial volume levels ? */220	a = 0x64;221	e = 0xbc;222	for (n = 0; n < 2; n++) {223		off = n * 18;224		for (b = off; b < 18 + off; b++) {225			/* This channel to all outputs ? */226			for (c = 0; c <= 8; c++) {227				snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e);228				snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e);229			}230			/* This channel to main output (again) */231			snd_s1810c_send_ctl_packet(dev, a, b, 0, 0, e);232			snd_s1810c_send_ctl_packet(dev, a, b, 0, 1, e);233		}234		/*235		 * I noticed on UC that DAW channels have different236		 * initial volumes, so this makes sense.237		 */238		e = 0xb53bf0;239	}240 241	/* Connect analog outputs ? */242	a = 0x65;243	e = 0x01000000;244	for (b = 1; b < 3; b++) {245		snd_s1810c_send_ctl_packet(dev, a, b, 0, 0, e);246		snd_s1810c_send_ctl_packet(dev, a, b, 0, 1, e);247	}248	snd_s1810c_send_ctl_packet(dev, a, 0, 0, 0, e);249	snd_s1810c_send_ctl_packet(dev, a, 0, 0, 1, e);250 251	/* Set initial volume levels for S/PDIF mappings ? */252	a = 0x64;253	e = 0xbc;254	c = 3;255	for (n = 0; n < 2; n++) {256		off = n * 18;257		for (b = off; b < 18 + off; b++) {258			snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e);259			snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e);260		}261		e = 0xb53bf0;262	}263 264	/* Connect S/PDIF output ? */265	a = 0x65;266	e = 0x01000000;267	snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e);268	snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e);269 270	/* Connect all outputs (again) ? */271	a = 0x65;272	e = 0x01000000;273	for (b = 0; b < 4; b++) {274		snd_s1810c_send_ctl_packet(dev, a, b, 0, 0, e);275		snd_s1810c_send_ctl_packet(dev, a, b, 0, 1, e);276	}277 278	/* Basic routing to get sound out of the device */279	a = 0x64;280	e = 0x01000000;281	for (c = 0; c < 4; c++) {282		for (b = 0; b < 36; b++) {283			if ((c == 0 && b == 18) ||	/* DAW1/2 -> Main */284			    (c == 1 && b == 20) ||	/* DAW3/4 -> Line3/4 */285			    (c == 2 && b == 22) ||	/* DAW4/5 -> Line5/6 */286			    (c == 3 && b == 24)) {	/* DAW5/6 -> S/PDIF */287				/* Left */288				snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e);289				snd_s1810c_send_ctl_packet(dev, a, b, c, 1, 0);290				b++;291				/* Right */292				snd_s1810c_send_ctl_packet(dev, a, b, c, 0, 0);293				snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e);294			} else {295				/* Leave the rest disconnected */296				snd_s1810c_send_ctl_packet(dev, a, b, c, 0, 0);297				snd_s1810c_send_ctl_packet(dev, a, b, c, 1, 0);298			}299		}300	}301 302	/* Set initial volume levels for S/PDIF (again) ? */303	a = 0x64;304	e = 0xbc;305	c = 3;306	for (n = 0; n < 2; n++) {307		off = n * 18;308		for (b = off; b < 18 + off; b++) {309			snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e);310			snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e);311		}312		e = 0xb53bf0;313	}314 315	/* Connect S/PDIF outputs (again) ? */316	a = 0x65;317	e = 0x01000000;318	snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e);319	snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e);320 321	/* Again ? */322	snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e);323	snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e);324 325	return 0;326}327 328/*329 * Sync state with the device and retrieve the requested field,330 * whose index is specified in (kctl->private_value & 0xFF),331 * from the received fields array.332 */333static int334snd_s1810c_get_switch_state(struct usb_mixer_interface *mixer,335			    struct snd_kcontrol *kctl, u32 *state)336{337	struct snd_usb_audio *chip = mixer->chip;338	struct s1810_mixer_state *private = mixer->private_data;339	u32 field = 0;340	u32 ctl_idx = (u32) (kctl->private_value & 0xFF);341	int ret = 0;342 343	mutex_lock(&private->usb_mutex);344	ret = snd_sc1810c_get_status_field(chip->dev, &field,345					   ctl_idx, &private->seqnum);346	if (ret < 0)347		goto unlock;348 349	*state = field;350 unlock:351	mutex_unlock(&private->usb_mutex);352	return ret ? ret : 0;353}354 355/*356 * Send a control packet to the device for the control id357 * specified in (kctl->private_value >> 8) with value358 * specified in (kctl->private_value >> 16).359 */360static int361snd_s1810c_set_switch_state(struct usb_mixer_interface *mixer,362			    struct snd_kcontrol *kctl)363{364	struct snd_usb_audio *chip = mixer->chip;365	struct s1810_mixer_state *private = mixer->private_data;366	u32 pval = (u32) kctl->private_value;367	u32 ctl_id = (pval >> 8) & 0xFF;368	u32 ctl_val = (pval >> 16) & 0x1;369	int ret = 0;370 371	mutex_lock(&private->usb_mutex);372	ret = snd_s1810c_send_ctl_packet(chip->dev, 0, 0, 0, ctl_id, ctl_val);373	mutex_unlock(&private->usb_mutex);374	return ret;375}376 377/* Generic get/set/init functions for switch controls */378 379static int380snd_s1810c_switch_get(struct snd_kcontrol *kctl,381		      struct snd_ctl_elem_value *ctl_elem)382{383	struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);384	struct usb_mixer_interface *mixer = list->mixer;385	struct s1810_mixer_state *private = mixer->private_data;386	u32 pval = (u32) kctl->private_value;387	u32 ctl_idx = pval & 0xFF;388	u32 state = 0;389	int ret = 0;390 391	mutex_lock(&private->data_mutex);392	ret = snd_s1810c_get_switch_state(mixer, kctl, &state);393	if (ret < 0)394		goto unlock;395 396	switch (ctl_idx) {397	case SC1810C_STATE_LINE_SW:398	case SC1810C_STATE_AB_SW:399		ctl_elem->value.enumerated.item[0] = (int)state;400		break;401	default:402		ctl_elem->value.integer.value[0] = (long)state;403	}404 405 unlock:406	mutex_unlock(&private->data_mutex);407	return (ret < 0) ? ret : 0;408}409 410static int411snd_s1810c_switch_set(struct snd_kcontrol *kctl,412		      struct snd_ctl_elem_value *ctl_elem)413{414	struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);415	struct usb_mixer_interface *mixer = list->mixer;416	struct s1810_mixer_state *private = mixer->private_data;417	u32 pval = (u32) kctl->private_value;418	u32 ctl_idx = pval & 0xFF;419	u32 curval = 0;420	u32 newval = 0;421	int ret = 0;422 423	mutex_lock(&private->data_mutex);424	ret = snd_s1810c_get_switch_state(mixer, kctl, &curval);425	if (ret < 0)426		goto unlock;427 428	switch (ctl_idx) {429	case SC1810C_STATE_LINE_SW:430	case SC1810C_STATE_AB_SW:431		newval = (u32) ctl_elem->value.enumerated.item[0];432		break;433	default:434		newval = (u32) ctl_elem->value.integer.value[0];435	}436 437	if (curval == newval)438		goto unlock;439 440	kctl->private_value &= ~(0x1 << 16);441	kctl->private_value |= (unsigned int)(newval & 0x1) << 16;442	ret = snd_s1810c_set_switch_state(mixer, kctl);443 444 unlock:445	mutex_unlock(&private->data_mutex);446	return (ret < 0) ? 0 : 1;447}448 449static int450snd_s1810c_switch_init(struct usb_mixer_interface *mixer,451		       const struct snd_kcontrol_new *new_kctl)452{453	struct snd_kcontrol *kctl;454	struct usb_mixer_elem_info *elem;455 456	elem = kzalloc(sizeof(struct usb_mixer_elem_info), GFP_KERNEL);457	if (!elem)458		return -ENOMEM;459 460	elem->head.mixer = mixer;461	elem->control = 0;462	elem->head.id = 0;463	elem->channels = 1;464 465	kctl = snd_ctl_new1(new_kctl, elem);466	if (!kctl) {467		kfree(elem);468		return -ENOMEM;469	}470	kctl->private_free = snd_usb_mixer_elem_free;471 472	return snd_usb_mixer_add_control(&elem->head, kctl);473}474 475static int476snd_s1810c_line_sw_info(struct snd_kcontrol *kctl,477			struct snd_ctl_elem_info *uinfo)478{479	static const char *const texts[2] = {480		"Preamp On (Mic/Inst)",481		"Preamp Off (Line in)"482	};483 484	return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);485}486 487static const struct snd_kcontrol_new snd_s1810c_line_sw = {488	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,489	.name = "Line 1/2 Source Type",490	.info = snd_s1810c_line_sw_info,491	.get = snd_s1810c_switch_get,492	.put = snd_s1810c_switch_set,493	.private_value = (SC1810C_STATE_LINE_SW | SC1810C_CTL_LINE_SW << 8)494};495 496static const struct snd_kcontrol_new snd_s1810c_mute_sw = {497	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,498	.name = "Mute Main Out Switch",499	.info = snd_ctl_boolean_mono_info,500	.get = snd_s1810c_switch_get,501	.put = snd_s1810c_switch_set,502	.private_value = (SC1810C_STATE_MUTE_SW | SC1810C_CTL_MUTE_SW << 8)503};504 505static const struct snd_kcontrol_new snd_s1810c_48v_sw = {506	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,507	.name = "48V Phantom Power On Mic Inputs Switch",508	.info = snd_ctl_boolean_mono_info,509	.get = snd_s1810c_switch_get,510	.put = snd_s1810c_switch_set,511	.private_value = (SC1810C_STATE_48V_SW | SC1810C_CTL_48V_SW << 8)512};513 514static int515snd_s1810c_ab_sw_info(struct snd_kcontrol *kctl,516		      struct snd_ctl_elem_info *uinfo)517{518	static const char *const texts[2] = {519		"1/2",520		"3/4"521	};522 523	return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);524}525 526static const struct snd_kcontrol_new snd_s1810c_ab_sw = {527	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,528	.name = "Headphone 1 Source Route",529	.info = snd_s1810c_ab_sw_info,530	.get = snd_s1810c_switch_get,531	.put = snd_s1810c_switch_set,532	.private_value = (SC1810C_STATE_AB_SW | SC1810C_CTL_AB_SW << 8)533};534 535static void snd_sc1810_mixer_state_free(struct usb_mixer_interface *mixer)536{537	struct s1810_mixer_state *private = mixer->private_data;538	kfree(private);539	mixer->private_data = NULL;540}541 542/* Entry point, called from mixer_quirks.c */543int snd_sc1810_init_mixer(struct usb_mixer_interface *mixer)544{545	struct s1810_mixer_state *private = NULL;546	struct snd_usb_audio *chip = mixer->chip;547	struct usb_device *dev = chip->dev;548	int ret = 0;549 550	/* Run this only once */551	if (!list_empty(&chip->mixer_list))552		return 0;553 554	dev_info(&dev->dev,555		 "Presonus Studio 1810c, device_setup: %u\n", chip->setup);556	if (chip->setup == 1)557		dev_info(&dev->dev, "(8out/18in @ 48kHz)\n");558	else if (chip->setup == 2)559		dev_info(&dev->dev, "(6out/8in @ 192kHz)\n");560	else561		dev_info(&dev->dev, "(8out/14in @ 96kHz)\n");562 563	ret = snd_s1810c_init_mixer_maps(chip);564	if (ret < 0)565		return ret;566 567	private = kzalloc(sizeof(struct s1810_mixer_state), GFP_KERNEL);568	if (!private)569		return -ENOMEM;570 571	mutex_init(&private->usb_mutex);572	mutex_init(&private->data_mutex);573 574	mixer->private_data = private;575	mixer->private_free = snd_sc1810_mixer_state_free;576 577	private->seqnum = 1;578 579	ret = snd_s1810c_switch_init(mixer, &snd_s1810c_line_sw);580	if (ret < 0)581		return ret;582 583	ret = snd_s1810c_switch_init(mixer, &snd_s1810c_mute_sw);584	if (ret < 0)585		return ret;586 587	ret = snd_s1810c_switch_init(mixer, &snd_s1810c_48v_sw);588	if (ret < 0)589		return ret;590 591	ret = snd_s1810c_switch_init(mixer, &snd_s1810c_ab_sw);592	if (ret < 0)593		return ret;594	return ret;595}596