linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] UAC3: Add Selectors and Processing Units.
@ 2018-07-11 12:37 Jorge Sanjuan
  2018-07-11 12:37 ` [PATCH 1/5] ALSA: usb-audio: Add support for Selector Units in UAC3 Jorge Sanjuan
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: Jorge Sanjuan @ 2018-07-11 12:37 UTC (permalink / raw)
  To: tiwai; +Cc: alsa-devel, linux-kernel

This patchset is motivated by the addition of Multi Function
Processing Units (MFPU) to an UAC3 topology where there could be
signal processing algorithims applied to the audio signal.

The MFPUs themself don't provide any useful control, they offer a 
description of what algorithims it supports and it is for Selector Units
to take the bypass control of the dry (unprocessed) signal and the modified
one. Moreover, Up/Down mixers may be needed in this topologies to control
which outputs of the logical output cluster from the MFPU are to be passed 
as the final modified audio signal.

These patches add support for Selector Units and Processing units for UAC3
and adds a couple fixes that I found while implemeting them:

 1) Defualt naming of the virtual terminals was not accurate due to codes
    overlap between the three UAC standards.
 2) UAC2 parsing of processing units was using UAC1 controls bitmap.

Based on: next-20180711

Jorge Sanjuan (5):
  ALSA: usb-audio: Add support for Selector Units in UAC3
  ALSA: usb-audio: Processing Unit controls parsing in UAC2
  ALSA: usb-audio: Add support for Processing Units in UAC3
  ALSA: usb-audio: Unify virtual type units type to UAC3 values
  ALSA: usb-audio: Tidy up logic for Processing Unit min/max values

 include/linux/usb/audio-v3.h   |  15 +++
 include/uapi/linux/usb/audio.h |  49 ++++++++--
 sound/usb/mixer.c              | 212 +++++++++++++++++++++++++++++++++--------
 3 files changed, 225 insertions(+), 51 deletions(-)

-- 
2.11.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/5] ALSA: usb-audio: Add support for Selector Units in UAC3
  2018-07-11 12:37 [PATCH 0/5] UAC3: Add Selectors and Processing Units Jorge Sanjuan
@ 2018-07-11 12:37 ` Jorge Sanjuan
  2018-07-11 12:37 ` [PATCH 2/5] ALSA: usb-audio: Processing Unit controls parsing in UAC2 Jorge Sanjuan
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Jorge Sanjuan @ 2018-07-11 12:37 UTC (permalink / raw)
  To: tiwai; +Cc: alsa-devel, linux-kernel

This patch add support for Selector Units and Clock Selector Units
defined in the new UAC3 spec.

Selector Units play a really important role in the new UAC3 spec as
Processing Units do not define an on/off switch control anymore.
This forces topology designers to add bypass paths in the topology
to enable/dissable the Processing Units.

Signed-off-by: Jorge Sanjuan <jorge.sanjuan@codethink.co.uk>
---
 sound/usb/mixer.c | 54 ++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 44 insertions(+), 10 deletions(-)

diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index ca963e94ec03..a51f2320a3dd 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -940,6 +940,19 @@ static int check_input_term(struct mixer_build *state, int id,
 
 				return 0;
 			}
+			case UAC3_SELECTOR_UNIT:
+			case UAC3_CLOCK_SELECTOR: {
+				struct uac_selector_unit_descriptor *d = p1;
+				/* call recursively to retrieve the channel info */
+				err = check_input_term(state, d->baSourceID[0], term);
+				if (err < 0)
+					return err;
+				term->type = d->bDescriptorSubtype << 16; /* virtual type */
+				term->id = id;
+				term->name = 0; /* TODO: UAC3 Class-specific strings */
+
+				return 0;
+			}
 			default:
 				return -ENODEV;
 			}
@@ -2509,11 +2522,20 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
 	cval->res = 1;
 	cval->initialized = 1;
 
-	if (state->mixer->protocol == UAC_VERSION_1)
+	switch (state->mixer->protocol) {
+	case UAC_VERSION_1:
+	default:
 		cval->control = 0;
-	else /* UAC_VERSION_2 */
-		cval->control = (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) ?
-			UAC2_CX_CLOCK_SELECTOR : UAC2_SU_SELECTOR;
+		break;
+	case UAC_VERSION_2:
+	case UAC_VERSION_3:
+		if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR ||
+		    desc->bDescriptorSubtype == UAC3_CLOCK_SELECTOR)
+			cval->control = UAC2_CX_CLOCK_SELECTOR;
+		else /* UAC2/3_SELECTOR_UNIT */
+			cval->control = UAC2_SU_SELECTOR;
+		break;
+	}
 
 	namelist = kmalloc_array(desc->bNrInPins, sizeof(char *), GFP_KERNEL);
 	if (!namelist) {
@@ -2555,12 +2577,22 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
 	len = check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name));
 	if (!len) {
 		/* no mapping ? */
+		switch (state->mixer->protocol) {
+		case UAC_VERSION_1:
+		case UAC_VERSION_2:
+		default:
 		/* if iSelector is given, use it */
-		nameid = uac_selector_unit_iSelector(desc);
-		if (nameid)
-			len = snd_usb_copy_string_desc(state->chip, nameid,
-						       kctl->id.name,
-						       sizeof(kctl->id.name));
+			nameid = uac_selector_unit_iSelector(desc);
+			if (nameid)
+				len = snd_usb_copy_string_desc(state->chip,
+							nameid, kctl->id.name,
+							sizeof(kctl->id.name));
+			break;
+		case UAC_VERSION_3:
+			/* TODO: Class-Specific strings not yet supported */
+			break;
+		}
+
 		/* ... or pick up the terminal name at next */
 		if (!len)
 			len = get_term_name(state->chip, &state->oterm,
@@ -2570,7 +2602,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
 			strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name));
 
 		/* and add the proper suffix */
-		if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR)
+		if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR ||
+		    desc->bDescriptorSubtype == UAC3_CLOCK_SELECTOR)
 			append_ctl_name(kctl, " Clock Source");
 		else if ((state->oterm.type & 0xff00) == 0x0100)
 			append_ctl_name(kctl, " Capture Source");
@@ -2641,6 +2674,7 @@ static int parse_audio_unit(struct mixer_build *state, int unitid)
 			return parse_audio_mixer_unit(state, unitid, p1);
 		case UAC3_CLOCK_SOURCE:
 			return parse_clock_source_unit(state, unitid, p1);
+		case UAC3_SELECTOR_UNIT:
 		case UAC3_CLOCK_SELECTOR:
 			return parse_audio_selector_unit(state, unitid, p1);
 		case UAC3_FEATURE_UNIT:
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/5] ALSA: usb-audio: Processing Unit controls parsing in UAC2
  2018-07-11 12:37 [PATCH 0/5] UAC3: Add Selectors and Processing Units Jorge Sanjuan
  2018-07-11 12:37 ` [PATCH 1/5] ALSA: usb-audio: Add support for Selector Units in UAC3 Jorge Sanjuan
@ 2018-07-11 12:37 ` Jorge Sanjuan
  2018-07-11 12:37 ` [PATCH 3/5] ALSA: usb-audio: Add support for Processing Units in UAC3 Jorge Sanjuan
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Jorge Sanjuan @ 2018-07-11 12:37 UTC (permalink / raw)
  To: tiwai; +Cc: alsa-devel, linux-kernel

Current support for UAC2 Processing Units does the parsing
as one control per bit in the bitmap. However, the UAC2 spec
defines the controls as bit pairs where b01 means read-only
and b11 means read/write control.

This patch fixes that and uses the helper functions for checking
controls readability/writability when the control is defined as
bit pairs (UAC2 and UAC3).

Signed-off-by: Jorge Sanjuan <jorge.sanjuan@codethink.co.uk>
---
 sound/usb/mixer.c | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index a51f2320a3dd..bfb3484096a6 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -2300,8 +2300,16 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
 	for (valinfo = info->values; valinfo->control; valinfo++) {
 		__u8 *controls = uac_processing_unit_bmControls(desc, state->mixer->protocol);
 
-		if (!(controls[valinfo->control / 8] & (1 << ((valinfo->control % 8) - 1))))
-			continue;
+		if (state->mixer->protocol == UAC_VERSION_1) {
+			if (!(controls[valinfo->control / 8] &
+					(1 << ((valinfo->control % 8) - 1))))
+				continue;
+		} else { /* UAC_VERSION_2/3 */
+			if (!uac_v2v3_control_is_readable(controls[valinfo->control / 8],
+							  valinfo->control))
+				continue;
+		}
+
 		map = find_map(state->map, unitid, valinfo->control);
 		if (check_ignored_ctl(map))
 			continue;
@@ -2313,6 +2321,11 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
 		cval->val_type = valinfo->val_type;
 		cval->channels = 1;
 
+		if (state->mixer->protocol > UAC_VERSION_1 &&
+		    !uac_v2v3_control_is_writeable(controls[valinfo->control / 8],
+						   valinfo->control))
+			cval->master_readonly = 1;
+
 		/* get min/max values */
 		if (type == UAC_PROCESS_UP_DOWNMIX && cval->control == UAC_UD_MODE_SELECT) {
 			__u8 *control_spec = uac_processing_unit_specific(desc, state->mixer->protocol);
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/5] ALSA: usb-audio: Add support for Processing Units in UAC3
  2018-07-11 12:37 [PATCH 0/5] UAC3: Add Selectors and Processing Units Jorge Sanjuan
  2018-07-11 12:37 ` [PATCH 1/5] ALSA: usb-audio: Add support for Selector Units in UAC3 Jorge Sanjuan
  2018-07-11 12:37 ` [PATCH 2/5] ALSA: usb-audio: Processing Unit controls parsing in UAC2 Jorge Sanjuan
@ 2018-07-11 12:37 ` Jorge Sanjuan
  2018-07-11 12:37 ` [PATCH 4/5] ALSA: usb-audio: Unify virtual type units type to UAC3 values Jorge Sanjuan
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: Jorge Sanjuan @ 2018-07-11 12:37 UTC (permalink / raw)
  To: tiwai; +Cc: alsa-devel, linux-kernel

This patch adds support for the Processig Units defined in
the UAC3 spec. The main difference with the previous specs
is the lack of on/off switches in the controls for these
units and the addiction of the new Multi Function Processing
Unit.

The current version of the UAC3 spec doesn't define any
useful controls for the new Multi Function Processing Unit
so no control will get created once this unit is parsed.

Signed-off-by: Jorge Sanjuan <jorge.sanjuan@codethink.co.uk>
---
 include/linux/usb/audio-v3.h   | 15 +++++++++++++
 include/uapi/linux/usb/audio.h | 49 ++++++++++++++++++++++++++++++++--------
 sound/usb/mixer.c              | 51 ++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 104 insertions(+), 11 deletions(-)

diff --git a/include/linux/usb/audio-v3.h b/include/linux/usb/audio-v3.h
index a710e28b5215..334bfa6dfb47 100644
--- a/include/linux/usb/audio-v3.h
+++ b/include/linux/usb/audio-v3.h
@@ -387,6 +387,12 @@ struct uac3_interrupt_data_msg {
 #define UAC3_CONNECTORS			0x0f
 #define UAC3_POWER_DOMAIN		0x10
 
+/* A.20 PROCESSING UNIT PROCESS TYPES */
+#define UAC3_PROCESS_UNDEFINED		0x00
+#define UAC3_PROCESS_UP_DOWNMIX		0x01
+#define UAC3_PROCESS_STEREO_EXTENDER	0x02
+#define UAC3_PROCESS_MULTI_FUNCTION	0x03
+
 /* A.22 AUDIO CLASS-SPECIFIC REQUEST CODES */
 /* see audio-v2.h for the rest, which is identical to v2 */
 #define UAC3_CS_REQ_INTEN			0x04
@@ -406,6 +412,15 @@ struct uac3_interrupt_data_msg {
 #define UAC3_TE_OVERFLOW			0x04
 #define UAC3_TE_LATENCY 			0x05
 
+/* A.23.10 PROCESSING UNITS CONTROL SELECTROS */
+
+/* Up/Down Mixer */
+#define UAC3_UD_MODE_SELECT			0x01
+
+/* Stereo Extender */
+#define UAC3_EXT_WIDTH_CONTROL			0x01
+
+
 /* BADD predefined Unit/Terminal values */
 #define UAC3_BADD_IT_ID1	1  /* Input Terminal ID1: bTerminalID = 1 */
 #define UAC3_BADD_FU_ID2	2  /* Feature Unit ID2: bUnitID = 2 */
diff --git a/include/uapi/linux/usb/audio.h b/include/uapi/linux/usb/audio.h
index 74e520fb944f..ddc5396800aa 100644
--- a/include/uapi/linux/usb/audio.h
+++ b/include/uapi/linux/usb/audio.h
@@ -390,33 +390,64 @@ static inline __u8 uac_processing_unit_iChannelNames(struct uac_processing_unit_
 static inline __u8 uac_processing_unit_bControlSize(struct uac_processing_unit_descriptor *desc,
 						    int protocol)
 {
-	return (protocol == UAC_VERSION_1) ?
-		desc->baSourceID[desc->bNrInPins + 4] :
-		2; /* in UAC2, this value is constant */
+	switch (protocol) {
+	case UAC_VERSION_1:
+		return desc->baSourceID[desc->bNrInPins + 4];
+	case UAC_VERSION_2:
+		return 2; /* in UAC2, this value is constant */
+	case UAC_VERSION_3:
+		return 4; /* in UAC3, this value is constant */
+	default:
+		return 1;
+	}
 }
 
 static inline __u8 *uac_processing_unit_bmControls(struct uac_processing_unit_descriptor *desc,
 						   int protocol)
 {
-	return (protocol == UAC_VERSION_1) ?
-		&desc->baSourceID[desc->bNrInPins + 5] :
-		&desc->baSourceID[desc->bNrInPins + 6];
+	switch (protocol) {
+	case UAC_VERSION_1:
+		return &desc->baSourceID[desc->bNrInPins + 5];
+	case UAC_VERSION_2:
+		return &desc->baSourceID[desc->bNrInPins + 6];
+	case UAC_VERSION_3:
+		return &desc->baSourceID[desc->bNrInPins + 2];
+	default:
+		return NULL;
+	}
 }
 
 static inline __u8 uac_processing_unit_iProcessing(struct uac_processing_unit_descriptor *desc,
 						   int protocol)
 {
 	__u8 control_size = uac_processing_unit_bControlSize(desc, protocol);
-	return *(uac_processing_unit_bmControls(desc, protocol)
-			+ control_size);
+
+	switch (protocol) {
+	case UAC_VERSION_1:
+	case UAC_VERSION_2:
+	default:
+		return *(uac_processing_unit_bmControls(desc, protocol)
+			 + control_size);
+	case UAC_VERSION_3:
+		return 0; /* UAC3 does not have this field */
+	}
 }
 
 static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_descriptor *desc,
 						 int protocol)
 {
 	__u8 control_size = uac_processing_unit_bControlSize(desc, protocol);
-	return uac_processing_unit_bmControls(desc, protocol)
+
+	switch (protocol) {
+	case UAC_VERSION_1:
+	case UAC_VERSION_2:
+	default:
+		return uac_processing_unit_bmControls(desc, protocol)
 			+ control_size + 1;
+	case UAC_VERSION_3:
+		return uac_processing_unit_bmControls(desc, protocol)
+			+ control_size;
+	}
 }
 
 /* 4.5.2 Class-Specific AS Interface Descriptor */
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index bfb3484096a6..39fde49e8749 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -953,6 +953,23 @@ static int check_input_term(struct mixer_build *state, int id,
 
 				return 0;
 			}
+			case UAC3_PROCESSING_UNIT: {
+				struct uac_processing_unit_descriptor *d = p1;
+
+				if (!d->bNrInPins)
+					return -EINVAL;
+
+				/* call recursively to retrieve the channel info */
+				err = check_input_term(state, d->baSourceID[0], term);
+				if (err < 0)
+					return err;
+
+				term->type = d->bDescriptorSubtype << 16; /* virtual type */
+				term->id = id;
+				term->name = 0; /* TODO: UAC3 Class-specific strings */
+
+				return 0;
+			}
 			default:
 				return -ENODEV;
 			}
@@ -2180,6 +2197,11 @@ struct procunit_info {
 	struct procunit_value_info *values;
 };
 
+static struct procunit_value_info undefined_proc_info[] = {
+	{ 0x00, "Control Undefined", 0 },
+	{ 0 }
+};
+
 static struct procunit_value_info updown_proc_info[] = {
 	{ UAC_UD_ENABLE, "Switch", USB_MIXER_BOOLEAN },
 	{ UAC_UD_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 },
@@ -2228,6 +2250,23 @@ static struct procunit_info procunits[] = {
 	{ UAC_PROCESS_DYN_RANGE_COMP, "DCR", dcr_proc_info },
 	{ 0 },
 };
+
+static struct procunit_value_info uac3_updown_proc_info[] = {
+	{ UAC3_UD_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 },
+	{ 0 }
+};
+static struct procunit_value_info uac3_stereo_ext_proc_info[] = {
+	{ UAC3_EXT_WIDTH_CONTROL, "Width Control", USB_MIXER_U8 },
+	{ 0 }
+};
+
+static struct procunit_info uac3_procunits[] = {
+	{ UAC3_PROCESS_UP_DOWNMIX, "Up Down", uac3_updown_proc_info },
+	{ UAC3_PROCESS_STEREO_EXTENDER, "3D Stereo Extender", uac3_stereo_ext_proc_info },
+	{ UAC3_PROCESS_MULTI_FUNCTION, "Multi-Function", undefined_proc_info },
+	{ 0 },
+};
+
 /*
  * predefined data for extension units
  */
@@ -2388,8 +2427,16 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
 static int parse_audio_processing_unit(struct mixer_build *state, int unitid,
 				       void *raw_desc)
 {
-	return build_audio_procunit(state, unitid, raw_desc,
-				    procunits, "Processing Unit");
+	switch (state->mixer->protocol) {
+	case UAC_VERSION_1:
+	case UAC_VERSION_2:
+	default:
+		return build_audio_procunit(state, unitid, raw_desc,
+				procunits, "Processing Unit");
+	case UAC_VERSION_3:
+		return build_audio_procunit(state, unitid, raw_desc,
+				uac3_procunits, "Processing Unit");
+	}
 }
 
 static int parse_audio_extension_unit(struct mixer_build *state, int unitid,
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/5] ALSA: usb-audio: Unify virtual type units type to UAC3 values
  2018-07-11 12:37 [PATCH 0/5] UAC3: Add Selectors and Processing Units Jorge Sanjuan
                   ` (2 preceding siblings ...)
  2018-07-11 12:37 ` [PATCH 3/5] ALSA: usb-audio: Add support for Processing Units in UAC3 Jorge Sanjuan
@ 2018-07-11 12:37 ` Jorge Sanjuan
  2018-07-11 12:37 ` [PATCH 5/5] ALSA: usb-audio: Tidy up logic for Processing Unit min/max values Jorge Sanjuan
  2018-07-16 14:38 ` [PATCH 0/5] UAC3: Add Selectors and Processing Units Takashi Iwai
  5 siblings, 0 replies; 7+ messages in thread
From: Jorge Sanjuan @ 2018-07-11 12:37 UTC (permalink / raw)
  To: tiwai; +Cc: alsa-devel, linux-kernel

The Audio Control interface descriptor subtypes do not match
across all the UAC versions. That makes reusability of the
"virtual type" (Mixer, Processors, Selectors, etc) terminals
difficult. It also makes the mixer get the default names for
the virtual terminals wrong due to the overlap.

This patch proposes an unified approach by always using the most
comprehensive spec version to define them all (in this case UAC3).

Signed-off-by: Jorge Sanjuan <jorge.sanjuan@codethink.co.uk>
---
 sound/usb/mixer.c | 36 +++++++++++++++++++++++-------------
 1 file changed, 23 insertions(+), 13 deletions(-)

diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 39fde49e8749..87f18cb74ca3 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -675,16 +675,16 @@ static int get_term_name(struct snd_usb_audio *chip, struct usb_audio_term *iter
 		if (term_only)
 			return 0;
 		switch (iterm->type >> 16) {
-		case UAC_SELECTOR_UNIT:
+		case UAC3_SELECTOR_UNIT:
 			strcpy(name, "Selector");
 			return 8;
-		case UAC1_PROCESSING_UNIT:
+		case UAC3_PROCESSING_UNIT:
 			strcpy(name, "Process Unit");
 			return 12;
-		case UAC1_EXTENSION_UNIT:
+		case UAC3_EXTENSION_UNIT:
 			strcpy(name, "Ext Unit");
 			return 8;
-		case UAC_MIXER_UNIT:
+		case UAC3_MIXER_UNIT:
 			strcpy(name, "Mixer");
 			return 5;
 		default:
@@ -832,7 +832,7 @@ static int check_input_term(struct mixer_build *state, int id,
 			case UAC_MIXER_UNIT: {
 				struct uac_mixer_unit_descriptor *d = p1;
 
-				term->type = d->bDescriptorSubtype << 16; /* virtual type */
+				term->type = UAC3_MIXER_UNIT << 16; /* virtual type */
 				term->channels = uac_mixer_unit_bNrChannels(d);
 				term->chconfig = uac_mixer_unit_wChannelConfig(d, protocol);
 				term->name = uac_mixer_unit_iMixer(d);
@@ -845,15 +845,23 @@ static int check_input_term(struct mixer_build *state, int id,
 				err = check_input_term(state, d->baSourceID[0], term);
 				if (err < 0)
 					return err;
-				term->type = d->bDescriptorSubtype << 16; /* virtual type */
+				term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */
 				term->id = id;
 				term->name = uac_selector_unit_iSelector(d);
 				return 0;
 			}
 			case UAC1_PROCESSING_UNIT:
+			/* UAC2_EFFECT_UNIT */
+				if (protocol == UAC_VERSION_1)
+					term->type = UAC3_PROCESSING_UNIT << 16; /* virtual type */
+				else /* UAC_VERSION_2 */
+					term->type = UAC3_EFFECT_UNIT << 16; /* virtual type */
 			case UAC1_EXTENSION_UNIT:
 			/* UAC2_PROCESSING_UNIT_V2 */
-			/* UAC2_EFFECT_UNIT */
+				if (protocol == UAC_VERSION_1 && !term->type)
+					term->type = UAC3_EXTENSION_UNIT << 16; /* virtual type */
+				else if (protocol == UAC_VERSION_2 && !term->type)
+					term->type = UAC3_PROCESSING_UNIT << 16; /* virtual type */
 			case UAC2_EXTENSION_UNIT_V2: {
 				struct uac_processing_unit_descriptor *d = p1;
 
@@ -869,7 +877,9 @@ static int check_input_term(struct mixer_build *state, int id,
 					id = d->baSourceID[0];
 					break; /* continue to parse */
 				}
-				term->type = d->bDescriptorSubtype << 16; /* virtual type */
+				if (!term->type)
+					term->type = UAC3_EXTENSION_UNIT << 16; /* virtual type */
+
 				term->channels = uac_processing_unit_bNrChannels(d);
 				term->chconfig = uac_processing_unit_wChannelConfig(d, protocol);
 				term->name = uac_processing_unit_iProcessing(d, protocol);
@@ -878,7 +888,7 @@ static int check_input_term(struct mixer_build *state, int id,
 			case UAC2_CLOCK_SOURCE: {
 				struct uac_clock_source_descriptor *d = p1;
 
-				term->type = d->bDescriptorSubtype << 16; /* virtual type */
+				term->type = UAC3_CLOCK_SOURCE << 16; /* virtual type */
 				term->id = id;
 				term->name = d->iClockSource;
 				return 0;
@@ -923,7 +933,7 @@ static int check_input_term(struct mixer_build *state, int id,
 			case UAC3_CLOCK_SOURCE: {
 				struct uac3_clock_source_descriptor *d = p1;
 
-				term->type = d->bDescriptorSubtype << 16; /* virtual type */
+				term->type = UAC3_CLOCK_SOURCE << 16; /* virtual type */
 				term->id = id;
 				term->name = le16_to_cpu(d->wClockSourceStr);
 				return 0;
@@ -936,7 +946,7 @@ static int check_input_term(struct mixer_build *state, int id,
 					return err;
 
 				term->channels = err;
-				term->type = d->bDescriptorSubtype << 16; /* virtual type */
+				term->type = UAC3_MIXER_UNIT << 16; /* virtual type */
 
 				return 0;
 			}
@@ -947,7 +957,7 @@ static int check_input_term(struct mixer_build *state, int id,
 				err = check_input_term(state, d->baSourceID[0], term);
 				if (err < 0)
 					return err;
-				term->type = d->bDescriptorSubtype << 16; /* virtual type */
+				term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */
 				term->id = id;
 				term->name = 0; /* TODO: UAC3 Class-specific strings */
 
@@ -964,7 +974,7 @@ static int check_input_term(struct mixer_build *state, int id,
 				if (err < 0)
 					return err;
 
-				term->type = d->bDescriptorSubtype << 16; /* virtual type */
+				term->type = UAC3_PROCESSING_UNIT << 16; /* virtual type */
 				term->id = id;
 				term->name = 0; /* TODO: UAC3 Class-specific strings */
 
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 5/5] ALSA: usb-audio: Tidy up logic for Processing Unit min/max values
  2018-07-11 12:37 [PATCH 0/5] UAC3: Add Selectors and Processing Units Jorge Sanjuan
                   ` (3 preceding siblings ...)
  2018-07-11 12:37 ` [PATCH 4/5] ALSA: usb-audio: Unify virtual type units type to UAC3 values Jorge Sanjuan
@ 2018-07-11 12:37 ` Jorge Sanjuan
  2018-07-16 14:38 ` [PATCH 0/5] UAC3: Add Selectors and Processing Units Takashi Iwai
  5 siblings, 0 replies; 7+ messages in thread
From: Jorge Sanjuan @ 2018-07-11 12:37 UTC (permalink / raw)
  To: tiwai; +Cc: alsa-devel, linux-kernel

This patch refactors the processing units min/max calculation logic
for the mixer controls and fixes an issue where the Mode Select
checking of the Up/Down mixers doesn't differentiate between the
UAC1 and UAC2 Control Selector (0x02) and the UAC3 one which is
different (0x01).

Signed-off-by: Jorge Sanjuan <jorge.sanjuan@codethink.co.uk>
---
 sound/usb/mixer.c | 58 +++++++++++++++++++++++++++++++++++++++----------------
 1 file changed, 41 insertions(+), 17 deletions(-)

diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 87f18cb74ca3..73e811f86a95 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -2376,25 +2376,49 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
 			cval->master_readonly = 1;
 
 		/* get min/max values */
-		if (type == UAC_PROCESS_UP_DOWNMIX && cval->control == UAC_UD_MODE_SELECT) {
-			__u8 *control_spec = uac_processing_unit_specific(desc, state->mixer->protocol);
-			/* FIXME: hard-coded */
-			cval->min = 1;
-			cval->max = control_spec[0];
-			cval->res = 1;
-			cval->initialized = 1;
-		} else {
-			if (type == USB_XU_CLOCK_RATE) {
-				/*
-				 * E-Mu USB 0404/0202/TrackerPre/0204
-				 * samplerate control quirk
-				 */
-				cval->min = 0;
-				cval->max = 5;
+		switch (type) {
+		case UAC_PROCESS_UP_DOWNMIX: {
+			bool mode_sel = false;
+
+			switch (state->mixer->protocol) {
+			case UAC_VERSION_1:
+			case UAC_VERSION_2:
+			default:
+				if (cval->control == UAC_UD_MODE_SELECT)
+					mode_sel = true;
+				break;
+			case UAC_VERSION_3:
+				if (cval->control == UAC3_UD_MODE_SELECT)
+					mode_sel = true;
+				break;
+			}
+
+			if (mode_sel) {
+				__u8 *control_spec = uac_processing_unit_specific(desc,
+								state->mixer->protocol);
+				cval->min = 1;
+				cval->max = control_spec[0];
 				cval->res = 1;
 				cval->initialized = 1;
-			} else
-				get_min_max(cval, valinfo->min_value);
+				break;
+			}
+
+			get_min_max(cval, valinfo->min_value);
+			break;
+		}
+		case USB_XU_CLOCK_RATE:
+			/*
+			 * E-Mu USB 0404/0202/TrackerPre/0204
+			 * samplerate control quirk
+			 */
+			cval->min = 0;
+			cval->max = 5;
+			cval->res = 1;
+			cval->initialized = 1;
+			break;
+		default:
+			get_min_max(cval, valinfo->min_value);
+			break;
 		}
 
 		kctl = snd_ctl_new1(&mixer_procunit_ctl, cval);
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/5] UAC3: Add Selectors and Processing Units.
  2018-07-11 12:37 [PATCH 0/5] UAC3: Add Selectors and Processing Units Jorge Sanjuan
                   ` (4 preceding siblings ...)
  2018-07-11 12:37 ` [PATCH 5/5] ALSA: usb-audio: Tidy up logic for Processing Unit min/max values Jorge Sanjuan
@ 2018-07-16 14:38 ` Takashi Iwai
  5 siblings, 0 replies; 7+ messages in thread
From: Takashi Iwai @ 2018-07-16 14:38 UTC (permalink / raw)
  To: Jorge Sanjuan; +Cc: alsa-devel, linux-kernel

On Wed, 11 Jul 2018 14:37:50 +0200,
Jorge Sanjuan wrote:
> 
> This patchset is motivated by the addition of Multi Function
> Processing Units (MFPU) to an UAC3 topology where there could be
> signal processing algorithims applied to the audio signal.
> 
> The MFPUs themself don't provide any useful control, they offer a 
> description of what algorithims it supports and it is for Selector Units
> to take the bypass control of the dry (unprocessed) signal and the modified
> one. Moreover, Up/Down mixers may be needed in this topologies to control
> which outputs of the logical output cluster from the MFPU are to be passed 
> as the final modified audio signal.
> 
> These patches add support for Selector Units and Processing units for UAC3
> and adds a couple fixes that I found while implemeting them:
> 
>  1) Defualt naming of the virtual terminals was not accurate due to codes
>     overlap between the three UAC standards.
>  2) UAC2 parsing of processing units was using UAC1 controls bitmap.
> 
> Based on: next-20180711
> 
> Jorge Sanjuan (5):
>   ALSA: usb-audio: Add support for Selector Units in UAC3
>   ALSA: usb-audio: Processing Unit controls parsing in UAC2
>   ALSA: usb-audio: Add support for Processing Units in UAC3
>   ALSA: usb-audio: Unify virtual type units type to UAC3 values
>   ALSA: usb-audio: Tidy up logic for Processing Unit min/max values

Applied all five patches now.  Thanks.


Takashi

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2018-07-16 14:38 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-11 12:37 [PATCH 0/5] UAC3: Add Selectors and Processing Units Jorge Sanjuan
2018-07-11 12:37 ` [PATCH 1/5] ALSA: usb-audio: Add support for Selector Units in UAC3 Jorge Sanjuan
2018-07-11 12:37 ` [PATCH 2/5] ALSA: usb-audio: Processing Unit controls parsing in UAC2 Jorge Sanjuan
2018-07-11 12:37 ` [PATCH 3/5] ALSA: usb-audio: Add support for Processing Units in UAC3 Jorge Sanjuan
2018-07-11 12:37 ` [PATCH 4/5] ALSA: usb-audio: Unify virtual type units type to UAC3 values Jorge Sanjuan
2018-07-11 12:37 ` [PATCH 5/5] ALSA: usb-audio: Tidy up logic for Processing Unit min/max values Jorge Sanjuan
2018-07-16 14:38 ` [PATCH 0/5] UAC3: Add Selectors and Processing Units Takashi Iwai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).