#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
 #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 */
 
 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 */
 
 
                                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;
                        }
        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 },
        { 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
  */
 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,