diff --git a/drivers/usb/gadget/function/f_midi2.c b/drivers/usb/gadget/function/f_midi2.c
index c68a6fa0d237..b15d832ff441 100644
--- a/drivers/usb/gadget/function/f_midi2.c
+++ b/drivers/usb/gadget/function/f_midi2.c
@@ -151,7 +151,7 @@ static struct usb_ms20_gr_trm_block_descriptor gtb_desc = {
 };
 
 DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1);
-DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(1);
+DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(16);
 DECLARE_UAC_AC_HEADER_DESCRIPTOR(1);
 DECLARE_USB_MS20_ENDPOINT_DESCRIPTOR(32);
 
@@ -185,7 +185,7 @@ static struct usb_interface_descriptor midi2_midi1_if_desc = {
 	.bDescriptorType =	USB_DT_INTERFACE,
 	.bInterfaceNumber =	0, // to be filled
 	.bAlternateSetting =	0,
-	.bNumEndpoints =	2,
+	.bNumEndpoints =	2, // to be filled
 	.bInterfaceClass =	USB_CLASS_AUDIO,
 	.bInterfaceSubClass =	USB_SUBCLASS_MIDISTREAMING,
 	.bInterfaceProtocol =	0,
@@ -200,50 +200,6 @@ static struct usb_ms_header_descriptor midi2_midi1_class_desc = {
 	.wTotalLength =		__cpu_to_le16(0x41), // to be calculated
 };
 
-/* MIDI 1.0 IN (Embedded) Jack */
-static struct usb_midi_in_jack_descriptor midi2_midi1_in_jack1_desc = {
-	.bLength =		0x06,
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubtype =	USB_MS_MIDI_IN_JACK,
-	.bJackType =		USB_MS_EMBEDDED,
-	.bJackID =		0x01,
-	.iJack =		0,
-};
-
-/* MIDI 1.0 IN (External) Jack */
-static struct usb_midi_in_jack_descriptor midi2_midi1_in_jack2_desc = {
-	.bLength =		0x06,
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubtype =	USB_MS_MIDI_IN_JACK,
-	.bJackType =		USB_MS_EXTERNAL,
-	.bJackID =		0x02,
-	.iJack =		0,
-};
-
-/* MIDI 1.0 OUT (Embedded) Jack */
-static struct usb_midi_out_jack_descriptor_1 midi2_midi1_out_jack1_desc = {
-	.bLength =		0x09,
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubtype =	USB_MS_MIDI_OUT_JACK,
-	.bJackType =		USB_MS_EMBEDDED,
-	.bJackID =		0x03,
-	.bNrInputPins =		1,
-	.pins =			{ { 0x02, 0x01 } },
-	.iJack =		0,
-};
-
-/* MIDI 1.0 OUT (External) Jack */
-static struct usb_midi_out_jack_descriptor_1 midi2_midi1_out_jack2_desc = {
-	.bLength =		0x09,
-	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubtype =	USB_MS_MIDI_OUT_JACK,
-	.bJackType =		USB_MS_EXTERNAL,
-	.bJackID =		0x04,
-	.bNrInputPins =		1,
-	.pins =			{ { 0x01, 0x01 } },
-	.iJack =		0,
-};
-
 /* MIDI 1.0 EP OUT */
 static struct usb_endpoint_descriptor midi2_midi1_ep_out_desc = {
 	.bLength =		USB_DT_ENDPOINT_AUDIO_SIZE,
@@ -257,8 +213,8 @@ static struct usb_ss_ep_comp_descriptor midi2_midi1_ep_out_ss_comp_desc = {
 	.bDescriptorType        = USB_DT_SS_ENDPOINT_COMP,
 };
 
-static struct usb_ms_endpoint_descriptor_1 midi2_midi1_ep_out_class_desc = {
-	.bLength =		0x05,
+static struct usb_ms_endpoint_descriptor_16 midi2_midi1_ep_out_class_desc = {
+	.bLength =		0x05, // to be filled
 	.bDescriptorType =	USB_DT_CS_ENDPOINT,
 	.bDescriptorSubtype =	USB_MS_GENERAL,
 	.bNumEmbMIDIJack =	1,
@@ -278,8 +234,8 @@ static struct usb_ss_ep_comp_descriptor midi2_midi1_ep_in_ss_comp_desc = {
 	.bDescriptorType        = USB_DT_SS_ENDPOINT_COMP,
 };
 
-static struct usb_ms_endpoint_descriptor_1 midi2_midi1_ep_in_class_desc = {
-	.bLength =		0x05,
+static struct usb_ms_endpoint_descriptor_16 midi2_midi1_ep_in_class_desc = {
+	.bLength =		0x05, // to be filled
 	.bDescriptorType =	USB_DT_CS_ENDPOINT,
 	.bDescriptorSubtype =	USB_MS_GENERAL,
 	.bNumEmbMIDIJack =	1,
@@ -337,25 +293,29 @@ static void *midi2_audio_descs[] = {
 static void *midi2_midi1_descs[] = {
 	&midi2_midi1_if_desc,
 	&midi2_midi1_class_desc,
-	&midi2_midi1_in_jack1_desc,
-	&midi2_midi1_in_jack2_desc,
-	&midi2_midi1_out_jack1_desc,
-	&midi2_midi1_out_jack2_desc,
 	NULL
 };
 
-static void *midi2_midi1_ep_descs[] = {
+static void *midi2_midi1_ep_out_descs[] = {
 	&midi2_midi1_ep_out_desc,
 	&midi2_midi1_ep_out_class_desc,
+	NULL
+};
+
+static void *midi2_midi1_ep_in_descs[] = {
 	&midi2_midi1_ep_in_desc,
 	&midi2_midi1_ep_in_class_desc,
 	NULL
 };
 
-static void *midi2_midi1_ep_ss_descs[] = {
+static void *midi2_midi1_ep_out_ss_descs[] = {
 	&midi2_midi1_ep_out_desc,
 	&midi2_midi1_ep_out_ss_comp_desc,
 	&midi2_midi1_ep_out_class_desc,
+	NULL
+};
+
+static void *midi2_midi1_ep_in_ss_descs[] = {
 	&midi2_midi1_ep_in_desc,
 	&midi2_midi1_ep_in_ss_comp_desc,
 	&midi2_midi1_ep_in_class_desc,
@@ -1197,6 +1157,11 @@ struct f_midi2_usb_config {
 	struct usb_descriptor_header **list;
 	unsigned int size;
 	unsigned int alloc;
+
+	/* MIDI 1.0 jacks */
+	unsigned char jack_in, jack_out, jack_id;
+	struct usb_midi_in_jack_descriptor jack_ins[16];
+	struct usb_midi_out_jack_descriptor_1 jack_outs[16];
 };
 
 static int append_config(struct f_midi2_usb_config *config, void *d)
@@ -1231,12 +1196,61 @@ static int append_configs(struct f_midi2_usb_config *config, void **d)
 	return 0;
 }
 
+static int append_midi1_in_jack(struct f_midi2 *midi2,
+				struct f_midi2_usb_config *config,
+				unsigned int type)
+{
+	struct usb_midi_in_jack_descriptor *jack =
+		&config->jack_ins[config->jack_in++];
+	int id = ++config->jack_id;
+	int err;
+
+	jack->bLength = 0x06;
+	jack->bDescriptorType = USB_DT_CS_INTERFACE;
+	jack->bDescriptorSubtype = USB_MS_MIDI_IN_JACK;
+	jack->bJackType = type;
+	jack->bJackID = id;
+	jack->iJack = midi2->strings[STR_GTB1].id; // TODO: better names?
+
+	err = append_config(config, jack);
+	if (err < 0)
+		return err;
+	return id;
+}
+
+static int append_midi1_out_jack(struct f_midi2 *midi2,
+				 struct f_midi2_usb_config *config,
+				 unsigned int type, unsigned int source)
+{
+	struct usb_midi_out_jack_descriptor_1 *jack =
+		&config->jack_outs[config->jack_out++];
+	int id = ++config->jack_id;
+	int err;
+
+	jack->bLength = 0x09;
+	jack->bDescriptorType = USB_DT_CS_INTERFACE;
+	jack->bDescriptorSubtype = USB_MS_MIDI_OUT_JACK;
+	jack->bJackType = type;
+	jack->bJackID = id;
+	jack->bNrInputPins = 1;
+	jack->pins[0].baSourceID = source;
+	jack->pins[0].baSourcePin = 0x01;
+	jack->iJack = midi2->strings[STR_GTB1].id; // TODO: better names?
+
+	err = append_config(config, jack);
+	if (err < 0)
+		return err;
+	return id;
+}
+
 static int f_midi2_create_usb_configs(struct f_midi2 *midi2,
 				      struct f_midi2_usb_config *config,
 				      int speed)
 {
-	void **midi1_eps;
-	int i, err;
+	struct f_midi2_block *blk = &midi2->midi2_eps[0].blks[0];
+	void **midi1_in_eps, **midi1_out_eps;
+	int i, jack, total;
+	int err;
 
 	switch (speed) {
 	default:
@@ -1248,7 +1262,8 @@ static int f_midi2_create_usb_configs(struct f_midi2 *midi2,
 				cpu_to_le16(512);
 		fallthrough;
 	case USB_SPEED_FULL:
-		midi1_eps = midi2_midi1_ep_descs;
+		midi1_in_eps = midi2_midi1_ep_in_descs;
+		midi1_out_eps = midi2_midi1_ep_out_descs;
 		break;
 	case USB_SPEED_SUPER:
 	case USB_SPEED_SUPER_PLUS:
@@ -1257,19 +1272,85 @@ static int f_midi2_create_usb_configs(struct f_midi2 *midi2,
 		for (i = 0; i < midi2->num_eps; i++)
 			midi2_midi2_ep_out_desc[i].wMaxPacketSize =
 				cpu_to_le16(1024);
-		midi1_eps = midi2_midi1_ep_ss_descs;
+		midi1_in_eps = midi2_midi1_ep_in_ss_descs;
+		midi1_out_eps = midi2_midi1_ep_out_ss_descs;
 		break;
 	}
 
 	err = append_configs(config, midi2_audio_descs);
 	if (err < 0)
 		return err;
+
+	switch (blk->info.direction) {
+	case SNDRV_UMP_DIR_INPUT:
+	case SNDRV_UMP_DIR_OUTPUT:
+		midi2_midi1_if_desc.bNumEndpoints = 1;
+		break;
+	default:
+		midi2_midi1_if_desc.bNumEndpoints = 2;
+		break;
+	}
+
 	err = append_configs(config, midi2_midi1_descs);
 	if (err < 0)
 		return err;
-	err = append_configs(config, midi1_eps);
-	if (err < 0)
-		return err;
+
+	total = USB_DT_MS_HEADER_SIZE;
+	if (blk->info.direction != SNDRV_UMP_DIR_INPUT) {
+		midi2_midi1_ep_out_class_desc.bLength =
+			USB_DT_MS_ENDPOINT_SIZE(blk->info.num_groups);
+		total += midi2_midi1_ep_out_class_desc.bLength;
+		midi2_midi1_ep_out_class_desc.bNumEmbMIDIJack =
+			blk->info.num_groups;
+		total += blk->info.num_groups *
+			(USB_DT_MIDI_IN_SIZE + USB_DT_MIDI_OUT_SIZE(1));
+		for (i = 0; i < blk->info.num_groups; i++) {
+			jack = append_midi1_in_jack(midi2, config,
+						    USB_MS_EMBEDDED);
+			if (jack < 0)
+				return jack;
+			midi2_midi1_ep_out_class_desc.baAssocJackID[i] = jack;
+			jack = append_midi1_out_jack(midi2, config,
+						     USB_MS_EXTERNAL, jack);
+			if (jack < 0)
+				return jack;
+		}
+	}
+
+	if (blk->info.direction != SNDRV_UMP_DIR_OUTPUT) {
+		midi2_midi1_ep_in_class_desc.bLength =
+			USB_DT_MS_ENDPOINT_SIZE(blk->info.num_groups);
+		total += midi2_midi1_ep_in_class_desc.bLength;
+		midi2_midi1_ep_in_class_desc.bNumEmbMIDIJack =
+			blk->info.num_groups;
+		total += blk->info.num_groups *
+			(USB_DT_MIDI_IN_SIZE + USB_DT_MIDI_OUT_SIZE(1));
+		for (i = 0; i < blk->info.num_groups; i++) {
+			jack = append_midi1_in_jack(midi2, config,
+						    USB_MS_EXTERNAL);
+			if (jack < 0)
+				return jack;
+			jack = append_midi1_out_jack(midi2, config,
+						     USB_MS_EMBEDDED, jack);
+			if (jack < 0)
+				return jack;
+			midi2_midi1_ep_in_class_desc.baAssocJackID[i] = jack;
+		}
+	}
+
+	midi2_midi1_class_desc.wTotalLength = cpu_to_le16(total);
+
+	if (blk->info.direction != SNDRV_UMP_DIR_INPUT) {
+		err = append_configs(config, midi1_out_eps);
+		if (err < 0)
+			return err;
+	}
+	if (blk->info.direction != SNDRV_UMP_DIR_OUTPUT) {
+		err = append_configs(config, midi1_in_eps);
+		if (err < 0)
+			return err;
+	}
+
 	err = append_configs(config, midi2_midi2_descs);
 	if (err < 0)
 		return err;
@@ -1421,14 +1502,19 @@ static int f_midi2_bind(struct usb_configuration *c, struct usb_function *f)
 	midi2_audio_class_desc.baInterfaceNr[0] = status;
 
 	/* allocate instance-specific endpoints */
-	status = f_midi2_init_ep(midi2, NULL, &midi2->midi1_ep_in,
-				 &midi2_midi1_ep_in_desc, 0, NULL);
-	if (status)
-		goto fail;
-	status = f_midi2_init_ep(midi2, NULL, &midi2->midi1_ep_out,
-				 &midi2_midi1_ep_out_desc, 0, NULL);
-	if (status)
-		goto fail;
+	if (midi2->midi2_eps[0].blks[0].info.direction != SNDRV_UMP_DIR_OUTPUT) {
+		status = f_midi2_init_ep(midi2, NULL, &midi2->midi1_ep_in,
+					 &midi2_midi1_ep_in_desc, 0, NULL);
+		if (status)
+			goto fail;
+	}
+
+	if (midi2->midi2_eps[0].blks[0].info.direction != SNDRV_UMP_DIR_INPUT) {
+		status = f_midi2_init_ep(midi2, NULL, &midi2->midi1_ep_out,
+					 &midi2_midi1_ep_out_desc, 0, NULL);
+		if (status)
+			goto fail;
+	}
 
 	for (i = 0; i < midi2->num_eps; i++) {
 		status = f_midi2_init_midi2_ep_in(midi2, i);
