xref: /openbmc/linux/sound/usb/mixer_s1810c.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
18dc5efe3SNick Kossifidis // SPDX-License-Identifier: GPL-2.0
28dc5efe3SNick Kossifidis /*
38dc5efe3SNick Kossifidis  * Presonus Studio 1810c driver for ALSA
48dc5efe3SNick Kossifidis  * Copyright (C) 2019 Nick Kossifidis <mickflemm@gmail.com>
58dc5efe3SNick Kossifidis  *
68dc5efe3SNick Kossifidis  * Based on reverse engineering of the communication protocol
78dc5efe3SNick Kossifidis  * between the windows driver / Univeral Control (UC) program
88dc5efe3SNick Kossifidis  * and the device, through usbmon.
98dc5efe3SNick Kossifidis  *
108dc5efe3SNick Kossifidis  * For now this bypasses the mixer, with all channels split,
118dc5efe3SNick Kossifidis  * so that the software can mix with greater flexibility.
128dc5efe3SNick Kossifidis  * It also adds controls for the 4 buttons on the front of
138dc5efe3SNick Kossifidis  * the device.
148dc5efe3SNick Kossifidis  */
158dc5efe3SNick Kossifidis 
168dc5efe3SNick Kossifidis #include <linux/usb.h>
178dc5efe3SNick Kossifidis #include <linux/usb/audio-v2.h>
188dc5efe3SNick Kossifidis #include <linux/slab.h>
198dc5efe3SNick Kossifidis #include <sound/core.h>
208dc5efe3SNick Kossifidis #include <sound/control.h>
218dc5efe3SNick Kossifidis 
228dc5efe3SNick Kossifidis #include "usbaudio.h"
238dc5efe3SNick Kossifidis #include "mixer.h"
248dc5efe3SNick Kossifidis #include "mixer_quirks.h"
258dc5efe3SNick Kossifidis #include "helper.h"
268dc5efe3SNick Kossifidis #include "mixer_s1810c.h"
278dc5efe3SNick Kossifidis 
288dc5efe3SNick Kossifidis #define SC1810C_CMD_REQ	160
298dc5efe3SNick Kossifidis #define SC1810C_CMD_REQTYPE \
308dc5efe3SNick Kossifidis 	(USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT)
318dc5efe3SNick Kossifidis #define SC1810C_CMD_F1		0x50617269
328dc5efe3SNick Kossifidis #define SC1810C_CMD_F2		0x14
338dc5efe3SNick Kossifidis 
348dc5efe3SNick Kossifidis /*
358dc5efe3SNick Kossifidis  * DISCLAIMER: These are just guesses based on the
368dc5efe3SNick Kossifidis  * dumps I got.
378dc5efe3SNick Kossifidis  *
388dc5efe3SNick Kossifidis  * It seems like a selects between
398dc5efe3SNick Kossifidis  * device (0), mixer (0x64) and output (0x65)
408dc5efe3SNick Kossifidis  *
418dc5efe3SNick Kossifidis  * For mixer (0x64):
428dc5efe3SNick Kossifidis  *  * b selects an input channel (see below).
438dc5efe3SNick Kossifidis  *  * c selects an output channel pair (see below).
448dc5efe3SNick Kossifidis  *  * d selects left (0) or right (1) of that pair.
458dc5efe3SNick Kossifidis  *  * e 0-> disconnect, 0x01000000-> connect,
468dc5efe3SNick Kossifidis  *	0x0109-> used for stereo-linking channels,
478dc5efe3SNick Kossifidis  *	e is also used for setting volume levels
488dc5efe3SNick Kossifidis  *	in which case b is also set so I guess
498dc5efe3SNick Kossifidis  *	this way it is possible to set the volume
508dc5efe3SNick Kossifidis  *	level from the specified input to the
518dc5efe3SNick Kossifidis  *	specified output.
528dc5efe3SNick Kossifidis  *
538dc5efe3SNick Kossifidis  * IN Channels:
548dc5efe3SNick Kossifidis  * 0  - 7  Mic/Inst/Line (Analog inputs)
558dc5efe3SNick Kossifidis  * 8  - 9  S/PDIF
568dc5efe3SNick Kossifidis  * 10 - 17 ADAT
578dc5efe3SNick Kossifidis  * 18 - 35 DAW (Inputs from the host)
588dc5efe3SNick Kossifidis  *
598dc5efe3SNick Kossifidis  * OUT Channels (pairs):
608dc5efe3SNick Kossifidis  * 0 -> Main out
618dc5efe3SNick Kossifidis  * 1 -> Line1/2
628dc5efe3SNick Kossifidis  * 2 -> Line3/4
638dc5efe3SNick Kossifidis  * 3 -> S/PDIF
648dc5efe3SNick Kossifidis  * 4 -> ADAT?
658dc5efe3SNick Kossifidis  *
668dc5efe3SNick Kossifidis  * For device (0):
678dc5efe3SNick Kossifidis  *  * b and c are not used, at least not on the
688dc5efe3SNick Kossifidis  *    dumps I got.
698dc5efe3SNick Kossifidis  *  * d sets the control id to be modified
708dc5efe3SNick Kossifidis  *    (see below).
718dc5efe3SNick Kossifidis  *  * e sets the setting for that control.
728dc5efe3SNick Kossifidis  *    (so for the switches I was interested
738dc5efe3SNick Kossifidis  *    in it's 0/1)
748dc5efe3SNick Kossifidis  *
758dc5efe3SNick Kossifidis  * For output (0x65):
768dc5efe3SNick Kossifidis  *   * b is the output channel (see above).
778dc5efe3SNick Kossifidis  *   * c is zero.
788dc5efe3SNick Kossifidis  *   * e I guess the same as with mixer except 0x0109
798dc5efe3SNick Kossifidis  *	 which I didn't see in my dumps.
808dc5efe3SNick Kossifidis  *
818dc5efe3SNick Kossifidis  * The two fixed fields have the same values for
828dc5efe3SNick Kossifidis  * mixer and output but a different set for device.
838dc5efe3SNick Kossifidis  */
848dc5efe3SNick Kossifidis struct s1810c_ctl_packet {
858dc5efe3SNick Kossifidis 	u32 a;
868dc5efe3SNick Kossifidis 	u32 b;
878dc5efe3SNick Kossifidis 	u32 fixed1;
888dc5efe3SNick Kossifidis 	u32 fixed2;
898dc5efe3SNick Kossifidis 	u32 c;
908dc5efe3SNick Kossifidis 	u32 d;
918dc5efe3SNick Kossifidis 	u32 e;
928dc5efe3SNick Kossifidis };
938dc5efe3SNick Kossifidis 
948dc5efe3SNick Kossifidis #define SC1810C_CTL_LINE_SW	0
958dc5efe3SNick Kossifidis #define SC1810C_CTL_MUTE_SW	1
968dc5efe3SNick Kossifidis #define SC1810C_CTL_AB_SW	3
978dc5efe3SNick Kossifidis #define SC1810C_CTL_48V_SW	4
988dc5efe3SNick Kossifidis 
998dc5efe3SNick Kossifidis #define SC1810C_SET_STATE_REQ	161
1008dc5efe3SNick Kossifidis #define SC1810C_SET_STATE_REQTYPE SC1810C_CMD_REQTYPE
1018dc5efe3SNick Kossifidis #define SC1810C_SET_STATE_F1	0x64656D73
1028dc5efe3SNick Kossifidis #define SC1810C_SET_STATE_F2	0xF4
1038dc5efe3SNick Kossifidis 
1048dc5efe3SNick Kossifidis #define SC1810C_GET_STATE_REQ	162
1058dc5efe3SNick Kossifidis #define SC1810C_GET_STATE_REQTYPE \
1068dc5efe3SNick Kossifidis 	(USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN)
1078dc5efe3SNick Kossifidis #define SC1810C_GET_STATE_F1	SC1810C_SET_STATE_F1
1088dc5efe3SNick Kossifidis #define SC1810C_GET_STATE_F2	SC1810C_SET_STATE_F2
1098dc5efe3SNick Kossifidis 
1108dc5efe3SNick Kossifidis #define SC1810C_STATE_F1_IDX	2
1118dc5efe3SNick Kossifidis #define SC1810C_STATE_F2_IDX	3
1128dc5efe3SNick Kossifidis 
1138dc5efe3SNick Kossifidis /*
1148dc5efe3SNick Kossifidis  * This packet includes mixer volumes and
1158dc5efe3SNick Kossifidis  * various other fields, it's an extended
1168dc5efe3SNick Kossifidis  * version of ctl_packet, with a and b
1178dc5efe3SNick Kossifidis  * being zero and different f1/f2.
1188dc5efe3SNick Kossifidis  */
1198dc5efe3SNick Kossifidis struct s1810c_state_packet {
1208dc5efe3SNick Kossifidis 	u32 fields[63];
1218dc5efe3SNick Kossifidis };
1228dc5efe3SNick Kossifidis 
1238dc5efe3SNick Kossifidis #define SC1810C_STATE_48V_SW	58
1248dc5efe3SNick Kossifidis #define SC1810C_STATE_LINE_SW	59
1258dc5efe3SNick Kossifidis #define SC1810C_STATE_MUTE_SW	60
1268dc5efe3SNick Kossifidis #define SC1810C_STATE_AB_SW	62
1278dc5efe3SNick Kossifidis 
1288dc5efe3SNick Kossifidis struct s1810_mixer_state {
1298dc5efe3SNick Kossifidis 	uint16_t seqnum;
1308dc5efe3SNick Kossifidis 	struct mutex usb_mutex;
1318dc5efe3SNick Kossifidis 	struct mutex data_mutex;
1328dc5efe3SNick Kossifidis };
1338dc5efe3SNick Kossifidis 
1348dc5efe3SNick Kossifidis static int
snd_s1810c_send_ctl_packet(struct usb_device * dev,u32 a,u32 b,u32 c,u32 d,u32 e)1358dc5efe3SNick Kossifidis snd_s1810c_send_ctl_packet(struct usb_device *dev, u32 a,
1368dc5efe3SNick Kossifidis 			   u32 b, u32 c, u32 d, u32 e)
1378dc5efe3SNick Kossifidis {
1388dc5efe3SNick Kossifidis 	struct s1810c_ctl_packet pkt = { 0 };
1398dc5efe3SNick Kossifidis 	int ret = 0;
1408dc5efe3SNick Kossifidis 
1418dc5efe3SNick Kossifidis 	pkt.fixed1 = SC1810C_CMD_F1;
1428dc5efe3SNick Kossifidis 	pkt.fixed2 = SC1810C_CMD_F2;
1438dc5efe3SNick Kossifidis 
1448dc5efe3SNick Kossifidis 	pkt.a = a;
1458dc5efe3SNick Kossifidis 	pkt.b = b;
1468dc5efe3SNick Kossifidis 	pkt.c = c;
1478dc5efe3SNick Kossifidis 	pkt.d = d;
1488dc5efe3SNick Kossifidis 	/*
1498dc5efe3SNick Kossifidis 	 * Value for settings 0/1 for this
1508dc5efe3SNick Kossifidis 	 * output channel is always 0 (probably because
1518dc5efe3SNick Kossifidis 	 * there is no ADAT output on 1810c)
1528dc5efe3SNick Kossifidis 	 */
1538dc5efe3SNick Kossifidis 	pkt.e = (c == 4) ? 0 : e;
1548dc5efe3SNick Kossifidis 
1558dc5efe3SNick Kossifidis 	ret = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0),
1568dc5efe3SNick Kossifidis 			      SC1810C_CMD_REQ,
1578dc5efe3SNick Kossifidis 			      SC1810C_CMD_REQTYPE, 0, 0, &pkt, sizeof(pkt));
1588dc5efe3SNick Kossifidis 	if (ret < 0) {
1598dc5efe3SNick Kossifidis 		dev_warn(&dev->dev, "could not send ctl packet\n");
1608dc5efe3SNick Kossifidis 		return ret;
1618dc5efe3SNick Kossifidis 	}
1628dc5efe3SNick Kossifidis 	return 0;
1638dc5efe3SNick Kossifidis }
1648dc5efe3SNick Kossifidis 
1658dc5efe3SNick Kossifidis /*
166ff630b6aSgushengxian  * When opening Universal Control the program periodically
1678dc5efe3SNick Kossifidis  * sends and receives state packets for syncinc state between
1688dc5efe3SNick Kossifidis  * the device and the host.
1698dc5efe3SNick Kossifidis  *
1708dc5efe3SNick Kossifidis  * Note that if we send only the request to get data back we'll
1718dc5efe3SNick Kossifidis  * get an error, we need to first send an empty state packet and
1728dc5efe3SNick Kossifidis  * then ask to receive a filled. Their seqnumbers must also match.
1738dc5efe3SNick Kossifidis  */
1748dc5efe3SNick Kossifidis static int
snd_sc1810c_get_status_field(struct usb_device * dev,u32 * field,int field_idx,uint16_t * seqnum)1758dc5efe3SNick Kossifidis snd_sc1810c_get_status_field(struct usb_device *dev,
1768dc5efe3SNick Kossifidis 			     u32 *field, int field_idx, uint16_t *seqnum)
1778dc5efe3SNick Kossifidis {
178d0ee674bSTakashi Iwai 	struct s1810c_state_packet pkt_out = { { 0 } };
179d0ee674bSTakashi Iwai 	struct s1810c_state_packet pkt_in = { { 0 } };
1808dc5efe3SNick Kossifidis 	int ret = 0;
1818dc5efe3SNick Kossifidis 
1828dc5efe3SNick Kossifidis 	pkt_out.fields[SC1810C_STATE_F1_IDX] = SC1810C_SET_STATE_F1;
1838dc5efe3SNick Kossifidis 	pkt_out.fields[SC1810C_STATE_F2_IDX] = SC1810C_SET_STATE_F2;
1848dc5efe3SNick Kossifidis 	ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
1858dc5efe3SNick Kossifidis 			      SC1810C_SET_STATE_REQ,
1868dc5efe3SNick Kossifidis 			      SC1810C_SET_STATE_REQTYPE,
1878dc5efe3SNick Kossifidis 			      (*seqnum), 0, &pkt_out, sizeof(pkt_out));
1888dc5efe3SNick Kossifidis 	if (ret < 0) {
1898dc5efe3SNick Kossifidis 		dev_warn(&dev->dev, "could not send state packet (%d)\n", ret);
1908dc5efe3SNick Kossifidis 		return ret;
1918dc5efe3SNick Kossifidis 	}
1928dc5efe3SNick Kossifidis 
1938dc5efe3SNick Kossifidis 	ret = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0),
1948dc5efe3SNick Kossifidis 			      SC1810C_GET_STATE_REQ,
1958dc5efe3SNick Kossifidis 			      SC1810C_GET_STATE_REQTYPE,
1968dc5efe3SNick Kossifidis 			      (*seqnum), 0, &pkt_in, sizeof(pkt_in));
1978dc5efe3SNick Kossifidis 	if (ret < 0) {
1988dc5efe3SNick Kossifidis 		dev_warn(&dev->dev, "could not get state field %u (%d)\n",
1998dc5efe3SNick Kossifidis 			 field_idx, ret);
2008dc5efe3SNick Kossifidis 		return ret;
2018dc5efe3SNick Kossifidis 	}
2028dc5efe3SNick Kossifidis 
2038dc5efe3SNick Kossifidis 	(*field) = pkt_in.fields[field_idx];
2048dc5efe3SNick Kossifidis 	(*seqnum)++;
2058dc5efe3SNick Kossifidis 	return 0;
2068dc5efe3SNick Kossifidis }
2078dc5efe3SNick Kossifidis 
2088dc5efe3SNick Kossifidis /*
2098dc5efe3SNick Kossifidis  * This is what I got when bypassing the mixer with
2108dc5efe3SNick Kossifidis  * all channels split. I'm not 100% sure of what's going
2118dc5efe3SNick Kossifidis  * on, I could probably clean this up based on my observations
2128dc5efe3SNick Kossifidis  * but I prefer to keep the same behavior as the windows driver.
2138dc5efe3SNick Kossifidis  */
snd_s1810c_init_mixer_maps(struct snd_usb_audio * chip)2148dc5efe3SNick Kossifidis static int snd_s1810c_init_mixer_maps(struct snd_usb_audio *chip)
2158dc5efe3SNick Kossifidis {
2168dc5efe3SNick Kossifidis 	u32 a, b, c, e, n, off;
2178dc5efe3SNick Kossifidis 	struct usb_device *dev = chip->dev;
2188dc5efe3SNick Kossifidis 
2198dc5efe3SNick Kossifidis 	/* Set initial volume levels ? */
2208dc5efe3SNick Kossifidis 	a = 0x64;
2218dc5efe3SNick Kossifidis 	e = 0xbc;
2228dc5efe3SNick Kossifidis 	for (n = 0; n < 2; n++) {
2238dc5efe3SNick Kossifidis 		off = n * 18;
224*3db3d859SColin Ian King 		for (b = off; b < 18 + off; b++) {
2258dc5efe3SNick Kossifidis 			/* This channel to all outputs ? */
2268dc5efe3SNick Kossifidis 			for (c = 0; c <= 8; c++) {
2278dc5efe3SNick Kossifidis 				snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e);
2288dc5efe3SNick Kossifidis 				snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e);
2298dc5efe3SNick Kossifidis 			}
2308dc5efe3SNick Kossifidis 			/* This channel to main output (again) */
2318dc5efe3SNick Kossifidis 			snd_s1810c_send_ctl_packet(dev, a, b, 0, 0, e);
2328dc5efe3SNick Kossifidis 			snd_s1810c_send_ctl_packet(dev, a, b, 0, 1, e);
2338dc5efe3SNick Kossifidis 		}
2348dc5efe3SNick Kossifidis 		/*
2358dc5efe3SNick Kossifidis 		 * I noticed on UC that DAW channels have different
2368dc5efe3SNick Kossifidis 		 * initial volumes, so this makes sense.
2378dc5efe3SNick Kossifidis 		 */
2388dc5efe3SNick Kossifidis 		e = 0xb53bf0;
2398dc5efe3SNick Kossifidis 	}
2408dc5efe3SNick Kossifidis 
2418dc5efe3SNick Kossifidis 	/* Connect analog outputs ? */
2428dc5efe3SNick Kossifidis 	a = 0x65;
2438dc5efe3SNick Kossifidis 	e = 0x01000000;
2448dc5efe3SNick Kossifidis 	for (b = 1; b < 3; b++) {
2458dc5efe3SNick Kossifidis 		snd_s1810c_send_ctl_packet(dev, a, b, 0, 0, e);
2468dc5efe3SNick Kossifidis 		snd_s1810c_send_ctl_packet(dev, a, b, 0, 1, e);
2478dc5efe3SNick Kossifidis 	}
2488dc5efe3SNick Kossifidis 	snd_s1810c_send_ctl_packet(dev, a, 0, 0, 0, e);
2498dc5efe3SNick Kossifidis 	snd_s1810c_send_ctl_packet(dev, a, 0, 0, 1, e);
2508dc5efe3SNick Kossifidis 
2518dc5efe3SNick Kossifidis 	/* Set initial volume levels for S/PDIF mappings ? */
2528dc5efe3SNick Kossifidis 	a = 0x64;
2538dc5efe3SNick Kossifidis 	e = 0xbc;
2548dc5efe3SNick Kossifidis 	c = 3;
2558dc5efe3SNick Kossifidis 	for (n = 0; n < 2; n++) {
2568dc5efe3SNick Kossifidis 		off = n * 18;
2578dc5efe3SNick Kossifidis 		for (b = off; b < 18 + off; b++) {
2588dc5efe3SNick Kossifidis 			snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e);
2598dc5efe3SNick Kossifidis 			snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e);
2608dc5efe3SNick Kossifidis 		}
2618dc5efe3SNick Kossifidis 		e = 0xb53bf0;
2628dc5efe3SNick Kossifidis 	}
2638dc5efe3SNick Kossifidis 
2648dc5efe3SNick Kossifidis 	/* Connect S/PDIF output ? */
2658dc5efe3SNick Kossifidis 	a = 0x65;
2668dc5efe3SNick Kossifidis 	e = 0x01000000;
2678dc5efe3SNick Kossifidis 	snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e);
2688dc5efe3SNick Kossifidis 	snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e);
2698dc5efe3SNick Kossifidis 
2708dc5efe3SNick Kossifidis 	/* Connect all outputs (again) ? */
2718dc5efe3SNick Kossifidis 	a = 0x65;
2728dc5efe3SNick Kossifidis 	e = 0x01000000;
2738dc5efe3SNick Kossifidis 	for (b = 0; b < 4; b++) {
2748dc5efe3SNick Kossifidis 		snd_s1810c_send_ctl_packet(dev, a, b, 0, 0, e);
2758dc5efe3SNick Kossifidis 		snd_s1810c_send_ctl_packet(dev, a, b, 0, 1, e);
2768dc5efe3SNick Kossifidis 	}
2778dc5efe3SNick Kossifidis 
2788dc5efe3SNick Kossifidis 	/* Basic routing to get sound out of the device */
2798dc5efe3SNick Kossifidis 	a = 0x64;
2808dc5efe3SNick Kossifidis 	e = 0x01000000;
2818dc5efe3SNick Kossifidis 	for (c = 0; c < 4; c++) {
2828dc5efe3SNick Kossifidis 		for (b = 0; b < 36; b++) {
2838dc5efe3SNick Kossifidis 			if ((c == 0 && b == 18) ||	/* DAW1/2 -> Main */
2848dc5efe3SNick Kossifidis 			    (c == 1 && b == 20) ||	/* DAW3/4 -> Line3/4 */
2858dc5efe3SNick Kossifidis 			    (c == 2 && b == 22) ||	/* DAW4/5 -> Line5/6 */
2868dc5efe3SNick Kossifidis 			    (c == 3 && b == 24)) {	/* DAW5/6 -> S/PDIF */
2878dc5efe3SNick Kossifidis 				/* Left */
2888dc5efe3SNick Kossifidis 				snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e);
2898dc5efe3SNick Kossifidis 				snd_s1810c_send_ctl_packet(dev, a, b, c, 1, 0);
2908dc5efe3SNick Kossifidis 				b++;
2918dc5efe3SNick Kossifidis 				/* Right */
2928dc5efe3SNick Kossifidis 				snd_s1810c_send_ctl_packet(dev, a, b, c, 0, 0);
2938dc5efe3SNick Kossifidis 				snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e);
2948dc5efe3SNick Kossifidis 			} else {
2958dc5efe3SNick Kossifidis 				/* Leave the rest disconnected */
2968dc5efe3SNick Kossifidis 				snd_s1810c_send_ctl_packet(dev, a, b, c, 0, 0);
2978dc5efe3SNick Kossifidis 				snd_s1810c_send_ctl_packet(dev, a, b, c, 1, 0);
2988dc5efe3SNick Kossifidis 			}
2998dc5efe3SNick Kossifidis 		}
3008dc5efe3SNick Kossifidis 	}
3018dc5efe3SNick Kossifidis 
3028dc5efe3SNick Kossifidis 	/* Set initial volume levels for S/PDIF (again) ? */
3038dc5efe3SNick Kossifidis 	a = 0x64;
3048dc5efe3SNick Kossifidis 	e = 0xbc;
3058dc5efe3SNick Kossifidis 	c = 3;
3068dc5efe3SNick Kossifidis 	for (n = 0; n < 2; n++) {
3078dc5efe3SNick Kossifidis 		off = n * 18;
3088dc5efe3SNick Kossifidis 		for (b = off; b < 18 + off; b++) {
3098dc5efe3SNick Kossifidis 			snd_s1810c_send_ctl_packet(dev, a, b, c, 0, e);
3108dc5efe3SNick Kossifidis 			snd_s1810c_send_ctl_packet(dev, a, b, c, 1, e);
3118dc5efe3SNick Kossifidis 		}
3128dc5efe3SNick Kossifidis 		e = 0xb53bf0;
3138dc5efe3SNick Kossifidis 	}
3148dc5efe3SNick Kossifidis 
3158dc5efe3SNick Kossifidis 	/* Connect S/PDIF outputs (again) ? */
3168dc5efe3SNick Kossifidis 	a = 0x65;
3178dc5efe3SNick Kossifidis 	e = 0x01000000;
3188dc5efe3SNick Kossifidis 	snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e);
3198dc5efe3SNick Kossifidis 	snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e);
3208dc5efe3SNick Kossifidis 
3218dc5efe3SNick Kossifidis 	/* Again ? */
3228dc5efe3SNick Kossifidis 	snd_s1810c_send_ctl_packet(dev, a, 3, 0, 0, e);
3238dc5efe3SNick Kossifidis 	snd_s1810c_send_ctl_packet(dev, a, 3, 0, 1, e);
3248dc5efe3SNick Kossifidis 
3258dc5efe3SNick Kossifidis 	return 0;
3268dc5efe3SNick Kossifidis }
3278dc5efe3SNick Kossifidis 
3288dc5efe3SNick Kossifidis /*
3298dc5efe3SNick Kossifidis  * Sync state with the device and retrieve the requested field,
3308dc5efe3SNick Kossifidis  * whose index is specified in (kctl->private_value & 0xFF),
3318dc5efe3SNick Kossifidis  * from the received fields array.
3328dc5efe3SNick Kossifidis  */
3338dc5efe3SNick Kossifidis static int
snd_s1810c_get_switch_state(struct usb_mixer_interface * mixer,struct snd_kcontrol * kctl,u32 * state)3348dc5efe3SNick Kossifidis snd_s1810c_get_switch_state(struct usb_mixer_interface *mixer,
3358dc5efe3SNick Kossifidis 			    struct snd_kcontrol *kctl, u32 *state)
3368dc5efe3SNick Kossifidis {
3378dc5efe3SNick Kossifidis 	struct snd_usb_audio *chip = mixer->chip;
3388dc5efe3SNick Kossifidis 	struct s1810_mixer_state *private = mixer->private_data;
3398dc5efe3SNick Kossifidis 	u32 field = 0;
3408dc5efe3SNick Kossifidis 	u32 ctl_idx = (u32) (kctl->private_value & 0xFF);
3418dc5efe3SNick Kossifidis 	int ret = 0;
3428dc5efe3SNick Kossifidis 
3438dc5efe3SNick Kossifidis 	mutex_lock(&private->usb_mutex);
3448dc5efe3SNick Kossifidis 	ret = snd_sc1810c_get_status_field(chip->dev, &field,
3458dc5efe3SNick Kossifidis 					   ctl_idx, &private->seqnum);
3468dc5efe3SNick Kossifidis 	if (ret < 0)
3478dc5efe3SNick Kossifidis 		goto unlock;
3488dc5efe3SNick Kossifidis 
3498dc5efe3SNick Kossifidis 	*state = field;
3508dc5efe3SNick Kossifidis  unlock:
3518dc5efe3SNick Kossifidis 	mutex_unlock(&private->usb_mutex);
3528dc5efe3SNick Kossifidis 	return ret ? ret : 0;
3538dc5efe3SNick Kossifidis }
3548dc5efe3SNick Kossifidis 
3558dc5efe3SNick Kossifidis /*
3568dc5efe3SNick Kossifidis  * Send a control packet to the device for the control id
3578dc5efe3SNick Kossifidis  * specified in (kctl->private_value >> 8) with value
3588dc5efe3SNick Kossifidis  * specified in (kctl->private_value >> 16).
3598dc5efe3SNick Kossifidis  */
3608dc5efe3SNick Kossifidis static int
snd_s1810c_set_switch_state(struct usb_mixer_interface * mixer,struct snd_kcontrol * kctl)3618dc5efe3SNick Kossifidis snd_s1810c_set_switch_state(struct usb_mixer_interface *mixer,
3628dc5efe3SNick Kossifidis 			    struct snd_kcontrol *kctl)
3638dc5efe3SNick Kossifidis {
3648dc5efe3SNick Kossifidis 	struct snd_usb_audio *chip = mixer->chip;
3658dc5efe3SNick Kossifidis 	struct s1810_mixer_state *private = mixer->private_data;
3668dc5efe3SNick Kossifidis 	u32 pval = (u32) kctl->private_value;
3678dc5efe3SNick Kossifidis 	u32 ctl_id = (pval >> 8) & 0xFF;
3688dc5efe3SNick Kossifidis 	u32 ctl_val = (pval >> 16) & 0x1;
3698dc5efe3SNick Kossifidis 	int ret = 0;
3708dc5efe3SNick Kossifidis 
3718dc5efe3SNick Kossifidis 	mutex_lock(&private->usb_mutex);
3728dc5efe3SNick Kossifidis 	ret = snd_s1810c_send_ctl_packet(chip->dev, 0, 0, 0, ctl_id, ctl_val);
3738dc5efe3SNick Kossifidis 	mutex_unlock(&private->usb_mutex);
3748dc5efe3SNick Kossifidis 	return ret;
3758dc5efe3SNick Kossifidis }
3768dc5efe3SNick Kossifidis 
3778dc5efe3SNick Kossifidis /* Generic get/set/init functions for switch controls */
3788dc5efe3SNick Kossifidis 
3798dc5efe3SNick Kossifidis static int
snd_s1810c_switch_get(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ctl_elem)3808dc5efe3SNick Kossifidis snd_s1810c_switch_get(struct snd_kcontrol *kctl,
3818dc5efe3SNick Kossifidis 		      struct snd_ctl_elem_value *ctl_elem)
3828dc5efe3SNick Kossifidis {
3838dc5efe3SNick Kossifidis 	struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
3848dc5efe3SNick Kossifidis 	struct usb_mixer_interface *mixer = list->mixer;
3858dc5efe3SNick Kossifidis 	struct s1810_mixer_state *private = mixer->private_data;
3868dc5efe3SNick Kossifidis 	u32 pval = (u32) kctl->private_value;
3878dc5efe3SNick Kossifidis 	u32 ctl_idx = pval & 0xFF;
3888dc5efe3SNick Kossifidis 	u32 state = 0;
3898dc5efe3SNick Kossifidis 	int ret = 0;
3908dc5efe3SNick Kossifidis 
3918dc5efe3SNick Kossifidis 	mutex_lock(&private->data_mutex);
3928dc5efe3SNick Kossifidis 	ret = snd_s1810c_get_switch_state(mixer, kctl, &state);
3938dc5efe3SNick Kossifidis 	if (ret < 0)
3948dc5efe3SNick Kossifidis 		goto unlock;
3958dc5efe3SNick Kossifidis 
3968dc5efe3SNick Kossifidis 	switch (ctl_idx) {
3978dc5efe3SNick Kossifidis 	case SC1810C_STATE_LINE_SW:
3988dc5efe3SNick Kossifidis 	case SC1810C_STATE_AB_SW:
3998dc5efe3SNick Kossifidis 		ctl_elem->value.enumerated.item[0] = (int)state;
4008dc5efe3SNick Kossifidis 		break;
4018dc5efe3SNick Kossifidis 	default:
4028dc5efe3SNick Kossifidis 		ctl_elem->value.integer.value[0] = (long)state;
4038dc5efe3SNick Kossifidis 	}
4048dc5efe3SNick Kossifidis 
4058dc5efe3SNick Kossifidis  unlock:
4068dc5efe3SNick Kossifidis 	mutex_unlock(&private->data_mutex);
4078dc5efe3SNick Kossifidis 	return (ret < 0) ? ret : 0;
4088dc5efe3SNick Kossifidis }
4098dc5efe3SNick Kossifidis 
4108dc5efe3SNick Kossifidis static int
snd_s1810c_switch_set(struct snd_kcontrol * kctl,struct snd_ctl_elem_value * ctl_elem)4118dc5efe3SNick Kossifidis snd_s1810c_switch_set(struct snd_kcontrol *kctl,
4128dc5efe3SNick Kossifidis 		      struct snd_ctl_elem_value *ctl_elem)
4138dc5efe3SNick Kossifidis {
4148dc5efe3SNick Kossifidis 	struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
4158dc5efe3SNick Kossifidis 	struct usb_mixer_interface *mixer = list->mixer;
4168dc5efe3SNick Kossifidis 	struct s1810_mixer_state *private = mixer->private_data;
4178dc5efe3SNick Kossifidis 	u32 pval = (u32) kctl->private_value;
4188dc5efe3SNick Kossifidis 	u32 ctl_idx = pval & 0xFF;
4198dc5efe3SNick Kossifidis 	u32 curval = 0;
4208dc5efe3SNick Kossifidis 	u32 newval = 0;
4218dc5efe3SNick Kossifidis 	int ret = 0;
4228dc5efe3SNick Kossifidis 
4238dc5efe3SNick Kossifidis 	mutex_lock(&private->data_mutex);
4248dc5efe3SNick Kossifidis 	ret = snd_s1810c_get_switch_state(mixer, kctl, &curval);
4258dc5efe3SNick Kossifidis 	if (ret < 0)
4268dc5efe3SNick Kossifidis 		goto unlock;
4278dc5efe3SNick Kossifidis 
4288dc5efe3SNick Kossifidis 	switch (ctl_idx) {
4298dc5efe3SNick Kossifidis 	case SC1810C_STATE_LINE_SW:
4308dc5efe3SNick Kossifidis 	case SC1810C_STATE_AB_SW:
4318dc5efe3SNick Kossifidis 		newval = (u32) ctl_elem->value.enumerated.item[0];
4328dc5efe3SNick Kossifidis 		break;
4338dc5efe3SNick Kossifidis 	default:
4348dc5efe3SNick Kossifidis 		newval = (u32) ctl_elem->value.integer.value[0];
4358dc5efe3SNick Kossifidis 	}
4368dc5efe3SNick Kossifidis 
4378dc5efe3SNick Kossifidis 	if (curval == newval)
4388dc5efe3SNick Kossifidis 		goto unlock;
4398dc5efe3SNick Kossifidis 
4408dc5efe3SNick Kossifidis 	kctl->private_value &= ~(0x1 << 16);
4418dc5efe3SNick Kossifidis 	kctl->private_value |= (unsigned int)(newval & 0x1) << 16;
4428dc5efe3SNick Kossifidis 	ret = snd_s1810c_set_switch_state(mixer, kctl);
4438dc5efe3SNick Kossifidis 
4448dc5efe3SNick Kossifidis  unlock:
4458dc5efe3SNick Kossifidis 	mutex_unlock(&private->data_mutex);
4468dc5efe3SNick Kossifidis 	return (ret < 0) ? 0 : 1;
4478dc5efe3SNick Kossifidis }
4488dc5efe3SNick Kossifidis 
4498dc5efe3SNick Kossifidis static int
snd_s1810c_switch_init(struct usb_mixer_interface * mixer,const struct snd_kcontrol_new * new_kctl)4508dc5efe3SNick Kossifidis snd_s1810c_switch_init(struct usb_mixer_interface *mixer,
4518dc5efe3SNick Kossifidis 		       const struct snd_kcontrol_new *new_kctl)
4528dc5efe3SNick Kossifidis {
4538dc5efe3SNick Kossifidis 	struct snd_kcontrol *kctl;
4548dc5efe3SNick Kossifidis 	struct usb_mixer_elem_info *elem;
4558dc5efe3SNick Kossifidis 
4568dc5efe3SNick Kossifidis 	elem = kzalloc(sizeof(struct usb_mixer_elem_info), GFP_KERNEL);
4578dc5efe3SNick Kossifidis 	if (!elem)
4588dc5efe3SNick Kossifidis 		return -ENOMEM;
4598dc5efe3SNick Kossifidis 
4608dc5efe3SNick Kossifidis 	elem->head.mixer = mixer;
4618dc5efe3SNick Kossifidis 	elem->control = 0;
4628dc5efe3SNick Kossifidis 	elem->head.id = 0;
4638dc5efe3SNick Kossifidis 	elem->channels = 1;
4648dc5efe3SNick Kossifidis 
4658dc5efe3SNick Kossifidis 	kctl = snd_ctl_new1(new_kctl, elem);
4668dc5efe3SNick Kossifidis 	if (!kctl) {
4678dc5efe3SNick Kossifidis 		kfree(elem);
4688dc5efe3SNick Kossifidis 		return -ENOMEM;
4698dc5efe3SNick Kossifidis 	}
4708dc5efe3SNick Kossifidis 	kctl->private_free = snd_usb_mixer_elem_free;
4718dc5efe3SNick Kossifidis 
4728dc5efe3SNick Kossifidis 	return snd_usb_mixer_add_control(&elem->head, kctl);
4738dc5efe3SNick Kossifidis }
4748dc5efe3SNick Kossifidis 
4758dc5efe3SNick Kossifidis static int
snd_s1810c_line_sw_info(struct snd_kcontrol * kctl,struct snd_ctl_elem_info * uinfo)4768dc5efe3SNick Kossifidis snd_s1810c_line_sw_info(struct snd_kcontrol *kctl,
4778dc5efe3SNick Kossifidis 			struct snd_ctl_elem_info *uinfo)
4788dc5efe3SNick Kossifidis {
4798dc5efe3SNick Kossifidis 	static const char *const texts[2] = {
4808dc5efe3SNick Kossifidis 		"Preamp On (Mic/Inst)",
4818dc5efe3SNick Kossifidis 		"Preamp Off (Line in)"
4828dc5efe3SNick Kossifidis 	};
4838dc5efe3SNick Kossifidis 
4848dc5efe3SNick Kossifidis 	return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
4858dc5efe3SNick Kossifidis }
4868dc5efe3SNick Kossifidis 
4878dc5efe3SNick Kossifidis static const struct snd_kcontrol_new snd_s1810c_line_sw = {
4888dc5efe3SNick Kossifidis 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4898dc5efe3SNick Kossifidis 	.name = "Line 1/2 Source Type",
4908dc5efe3SNick Kossifidis 	.info = snd_s1810c_line_sw_info,
4918dc5efe3SNick Kossifidis 	.get = snd_s1810c_switch_get,
4928dc5efe3SNick Kossifidis 	.put = snd_s1810c_switch_set,
4938dc5efe3SNick Kossifidis 	.private_value = (SC1810C_STATE_LINE_SW | SC1810C_CTL_LINE_SW << 8)
4948dc5efe3SNick Kossifidis };
4958dc5efe3SNick Kossifidis 
4968dc5efe3SNick Kossifidis static const struct snd_kcontrol_new snd_s1810c_mute_sw = {
4978dc5efe3SNick Kossifidis 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
4988dc5efe3SNick Kossifidis 	.name = "Mute Main Out Switch",
4998dc5efe3SNick Kossifidis 	.info = snd_ctl_boolean_mono_info,
5008dc5efe3SNick Kossifidis 	.get = snd_s1810c_switch_get,
5018dc5efe3SNick Kossifidis 	.put = snd_s1810c_switch_set,
5028dc5efe3SNick Kossifidis 	.private_value = (SC1810C_STATE_MUTE_SW | SC1810C_CTL_MUTE_SW << 8)
5038dc5efe3SNick Kossifidis };
5048dc5efe3SNick Kossifidis 
5058dc5efe3SNick Kossifidis static const struct snd_kcontrol_new snd_s1810c_48v_sw = {
5068dc5efe3SNick Kossifidis 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5078dc5efe3SNick Kossifidis 	.name = "48V Phantom Power On Mic Inputs Switch",
5088dc5efe3SNick Kossifidis 	.info = snd_ctl_boolean_mono_info,
5098dc5efe3SNick Kossifidis 	.get = snd_s1810c_switch_get,
5108dc5efe3SNick Kossifidis 	.put = snd_s1810c_switch_set,
5118dc5efe3SNick Kossifidis 	.private_value = (SC1810C_STATE_48V_SW | SC1810C_CTL_48V_SW << 8)
5128dc5efe3SNick Kossifidis };
5138dc5efe3SNick Kossifidis 
5148dc5efe3SNick Kossifidis static int
snd_s1810c_ab_sw_info(struct snd_kcontrol * kctl,struct snd_ctl_elem_info * uinfo)5158dc5efe3SNick Kossifidis snd_s1810c_ab_sw_info(struct snd_kcontrol *kctl,
5168dc5efe3SNick Kossifidis 		      struct snd_ctl_elem_info *uinfo)
5178dc5efe3SNick Kossifidis {
5188dc5efe3SNick Kossifidis 	static const char *const texts[2] = {
5198dc5efe3SNick Kossifidis 		"1/2",
5208dc5efe3SNick Kossifidis 		"3/4"
5218dc5efe3SNick Kossifidis 	};
5228dc5efe3SNick Kossifidis 
5238dc5efe3SNick Kossifidis 	return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
5248dc5efe3SNick Kossifidis }
5258dc5efe3SNick Kossifidis 
5268dc5efe3SNick Kossifidis static const struct snd_kcontrol_new snd_s1810c_ab_sw = {
5278dc5efe3SNick Kossifidis 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5288dc5efe3SNick Kossifidis 	.name = "Headphone 1 Source Route",
5298dc5efe3SNick Kossifidis 	.info = snd_s1810c_ab_sw_info,
5308dc5efe3SNick Kossifidis 	.get = snd_s1810c_switch_get,
5318dc5efe3SNick Kossifidis 	.put = snd_s1810c_switch_set,
5328dc5efe3SNick Kossifidis 	.private_value = (SC1810C_STATE_AB_SW | SC1810C_CTL_AB_SW << 8)
5338dc5efe3SNick Kossifidis };
5348dc5efe3SNick Kossifidis 
snd_sc1810_mixer_state_free(struct usb_mixer_interface * mixer)5358dc5efe3SNick Kossifidis static void snd_sc1810_mixer_state_free(struct usb_mixer_interface *mixer)
5368dc5efe3SNick Kossifidis {
5378dc5efe3SNick Kossifidis 	struct s1810_mixer_state *private = mixer->private_data;
5388dc5efe3SNick Kossifidis 	kfree(private);
5398dc5efe3SNick Kossifidis 	mixer->private_data = NULL;
5408dc5efe3SNick Kossifidis }
5418dc5efe3SNick Kossifidis 
5428dc5efe3SNick Kossifidis /* Entry point, called from mixer_quirks.c */
snd_sc1810_init_mixer(struct usb_mixer_interface * mixer)5438dc5efe3SNick Kossifidis int snd_sc1810_init_mixer(struct usb_mixer_interface *mixer)
5448dc5efe3SNick Kossifidis {
5458dc5efe3SNick Kossifidis 	struct s1810_mixer_state *private = NULL;
5468dc5efe3SNick Kossifidis 	struct snd_usb_audio *chip = mixer->chip;
5478dc5efe3SNick Kossifidis 	struct usb_device *dev = chip->dev;
5488dc5efe3SNick Kossifidis 	int ret = 0;
5498dc5efe3SNick Kossifidis 
5508dc5efe3SNick Kossifidis 	/* Run this only once */
5518dc5efe3SNick Kossifidis 	if (!list_empty(&chip->mixer_list))
5528dc5efe3SNick Kossifidis 		return 0;
5538dc5efe3SNick Kossifidis 
5548dc5efe3SNick Kossifidis 	dev_info(&dev->dev,
5558dc5efe3SNick Kossifidis 		 "Presonus Studio 1810c, device_setup: %u\n", chip->setup);
5568dc5efe3SNick Kossifidis 	if (chip->setup == 1)
5575ff40e6dSAlexander Tsoy 		dev_info(&dev->dev, "(8out/18in @ 48kHz)\n");
5588dc5efe3SNick Kossifidis 	else if (chip->setup == 2)
5595ff40e6dSAlexander Tsoy 		dev_info(&dev->dev, "(6out/8in @ 192kHz)\n");
5608dc5efe3SNick Kossifidis 	else
5615ff40e6dSAlexander Tsoy 		dev_info(&dev->dev, "(8out/14in @ 96kHz)\n");
5628dc5efe3SNick Kossifidis 
5638dc5efe3SNick Kossifidis 	ret = snd_s1810c_init_mixer_maps(chip);
5648dc5efe3SNick Kossifidis 	if (ret < 0)
5658dc5efe3SNick Kossifidis 		return ret;
5668dc5efe3SNick Kossifidis 
5678dc5efe3SNick Kossifidis 	private = kzalloc(sizeof(struct s1810_mixer_state), GFP_KERNEL);
5688dc5efe3SNick Kossifidis 	if (!private)
5698dc5efe3SNick Kossifidis 		return -ENOMEM;
5708dc5efe3SNick Kossifidis 
5718dc5efe3SNick Kossifidis 	mutex_init(&private->usb_mutex);
5728dc5efe3SNick Kossifidis 	mutex_init(&private->data_mutex);
5738dc5efe3SNick Kossifidis 
5748dc5efe3SNick Kossifidis 	mixer->private_data = private;
5758dc5efe3SNick Kossifidis 	mixer->private_free = snd_sc1810_mixer_state_free;
5768dc5efe3SNick Kossifidis 
5778dc5efe3SNick Kossifidis 	private->seqnum = 1;
5788dc5efe3SNick Kossifidis 
5798dc5efe3SNick Kossifidis 	ret = snd_s1810c_switch_init(mixer, &snd_s1810c_line_sw);
5808dc5efe3SNick Kossifidis 	if (ret < 0)
5818dc5efe3SNick Kossifidis 		return ret;
5828dc5efe3SNick Kossifidis 
5838dc5efe3SNick Kossifidis 	ret = snd_s1810c_switch_init(mixer, &snd_s1810c_mute_sw);
5848dc5efe3SNick Kossifidis 	if (ret < 0)
5858dc5efe3SNick Kossifidis 		return ret;
5868dc5efe3SNick Kossifidis 
5878dc5efe3SNick Kossifidis 	ret = snd_s1810c_switch_init(mixer, &snd_s1810c_48v_sw);
5888dc5efe3SNick Kossifidis 	if (ret < 0)
5898dc5efe3SNick Kossifidis 		return ret;
5908dc5efe3SNick Kossifidis 
5918dc5efe3SNick Kossifidis 	ret = snd_s1810c_switch_init(mixer, &snd_s1810c_ab_sw);
5928dc5efe3SNick Kossifidis 	if (ret < 0)
5938dc5efe3SNick Kossifidis 		return ret;
5948dc5efe3SNick Kossifidis 	return ret;
5958dc5efe3SNick Kossifidis }
596