Add USB Audio 1.0 support

Original commit credit to Amaury Pouly, Moshe Piekarski
Pushed across the finish line by Dana Conrad

To enable, see setting under General Settings --> System --> USB-DAC.
On devices with few endpoints, this may not work while HID and/or
mass storage is enabled.

Adds new dedicated mixer channel.

setting usb-dac can have values:
- never (0)
- always (1)
- while_charge_only (2)
- while_mass_storage (3)

Relevant devices are DWC2 and ARC usb controller devices. That being:
x1000 Native targets (m3k, erosqnative, q1, others...?),
sansac200, creativezenxfi2, vibe500, ipodmini2g,
ipod4g, creativezenxfi, creativezenxfi3, sansaview, ipodcolor,
creativezenxfistyle, samsungypz5, sansafuzeplus, iriverh10_5gb,
tatungtpj1022, gigabeats, faketarget, samsungyh820, gogearhdd1630, samsungyh925, ipodmini1g, ipodvideo, creativezenmozaic, sonynwze370, creativezen, gogearsa9200, gogearhdd6330, sonynwze360, sansae200, mrobe100, iriverh10, creativezenv, ipodnano1g, samsungyh920

USB Driver-wise, it should be noted that this patch requires some
slight changes:
- proper blocking on control OUT transfers, to make sure the data is
  received *before* using it, the usb_core should probably use that too
- drivers can now support interface alternate settings
- drivers can be notified of completion by a new fast handler, which
  is called directly from the driver; this is is necessary for
  isochronous transfers because going through the usb queue is way too
  slow

Designware changes:

- enable for USBOTG_DESIGNWARE
- set maxpacketsize to 1023 for ISO endpoints

Change-Id: I570871884a4e4820b4312b203b07701f06ecacc6
This commit is contained in:
Dana Conrad 2022-09-09 15:36:27 -05:00 committed by Solomon Peachy
parent af42428037
commit 9ce66e088e
20 changed files with 1867 additions and 35 deletions

View file

@ -0,0 +1,233 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: $
*
* Copyright (C) 2010 by Amaury Pouly
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
/* Parts of this file are based on Frank Gevaerts work and on audio.h from linux */
#ifndef USB_AUDIO_DEF_H
#define USB_AUDIO_DEF_H
#include "usb_ch9.h"
#define USB_SUBCLASS_AUDIO_CONTROL 1
#define USB_SUBCLASS_AUDIO_STREAMING 2
#define USB_AC_HEADER 1
#define USB_AC_INPUT_TERMINAL 2
#define USB_AC_OUTPUT_TERMINAL 3
#define USB_AC_MIXER_UNIT 4
#define USB_AC_SELECTOR_UNIT 5
#define USB_AC_FEATURE_UNIT 6
#define USB_AC_PROCESSING_UNIT 8
#define USB_AC_EXTENSION_UNIT 9
#define USB_AS_GENERAL 1
#define USB_AS_FORMAT_TYPE 2
#define USB_AC_CHANNEL_LEFT_FRONT 0x1
#define USB_AC_CHANNEL_RIGHT_FRONT 0x2
#define USB_AC_CHANNELS_LEFT_RIGHT_FRONT (USB_AC_CHANNEL_LEFT_FRONT | USB_AC_CHANNEL_RIGHT_FRONT)
/* usb audio data structures */
struct usb_ac_header {
uint8_t bLength;
uint8_t bDescriptorType; /* USB_DT_CS_INTERFACE */
uint8_t bDescriptorSubType; /* USB_AC_HEADER */
uint16_t bcdADC;
uint16_t wTotalLength;
uint8_t bInCollection;
uint8_t baInterfaceNr[];
} __attribute__ ((packed));
#define USB_AC_SIZEOF_HEADER(n) (8 + (n))
#define USB_AC_TERMINAL_UNDEFINED 0x100
#define USB_AC_TERMINAL_STREAMING 0x101
#define USB_AC_TERMINAL_VENDOR_SPEC 0x1ff
#define USB_AC_EXT_TERMINAL_UNDEFINED 0x600
#define USB_AC_EXT_TERMINAL_ANALOG 0x601
#define USB_AC_EXT_TERMINAL_DIGITAL 0x602
#define USB_AC_EXT_TERMINAL_LINE 0x603
#define USB_AC_EXT_TERMINAL_LEGACY 0x604
#define USB_AC_EXT_TERMINAL_SPDIF 0x605
#define USB_AC_EXT_TERMINAL_1394_DA 0x606
#define USB_AC_EXT_TERMINAL_1394_DV 0x607
#define USB_AC_EMB_MINIDISK 0x706
#define USB_AC_EMB_RADIO_RECV 0x710
#define USB_AC_INPUT_TERMINAL_UNDEFINED 0x200
#define USB_AC_INPUT_TERMINAL_MICROPHONE 0x201
#define USB_AC_INPUT_TERMINAL_DESKTOP_MICROPHONE 0x202
#define USB_AC_INPUT_TERMINAL_PERSONAL_MICROPHONE 0x203
#define USB_AC_INPUT_TERMINAL_OMNI_DIR_MICROPHONE 0x204
#define USB_AC_INPUT_TERMINAL_MICROPHONE_ARRAY 0x205
#define USB_AC_INPUT_TERMINAL_PROC_MICROPHONE_ARRAY 0x206
struct usb_ac_input_terminal {
uint8_t bLength;
uint8_t bDescriptorType; /* USB_DT_CS_INTERFACE */
uint8_t bDescriptorSubType; /* USB_AC_INPUT_TERMINAL */
uint8_t bTerminalId;
uint16_t wTerminalType; /* USB_AC_INPUT_TERMINAL_* */
uint8_t bAssocTerminal;
uint8_t bNrChannels;
uint16_t wChannelConfig;
uint8_t iChannelNames;
uint8_t iTerminal;
} __attribute__ ((packed));
#define USB_AC_OUTPUT_TERMINAL_UNDEFINED 0x300
#define USB_AC_OUTPUT_TERMINAL_SPEAKER 0x301
#define USB_AC_OUTPUT_TERMINAL_HEADPHONES 0x302
#define USB_AC_OUTPUT_TERMINAL_HEAD_MOUNTED_DISPLAY_AUDIO 0x303
#define USB_AC_OUTPUT_TERMINAL_DESKTOP_SPEAKER 0x304
#define USB_AC_OUTPUT_TERMINAL_ROOM_SPEAKER 0x305
#define USB_AC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER 0x306
#define USB_AC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER 0x307
struct usb_ac_output_terminal {
uint8_t bLength;
uint8_t bDescriptorType; /* USB_DT_CS_INTERFACE */
uint8_t bDescriptorSubType; /* USB_AC_OUTPUT_TERMINAL */
uint8_t bTerminalId;
uint16_t wTerminalType; /* USB_AC_OUTPUT_TERMINAL_* */
uint8_t bAssocTerminal;
uint8_t bSourceId;
uint8_t iTerminal;
} __attribute__ ((packed));
#define USB_AC_FU_CONTROL_UNDEFINED 0x00
#define USB_AC_MUTE_CONTROL 0x01
#define USB_AC_VOLUME_CONTROL 0x02
#define USB_AC_BASS_CONTROL 0x03
#define USB_AC_MID_CONTROL 0x04
#define USB_AC_TREBLE_CONTROL 0x05
#define USB_AC_EQUALIZER_CONTROL 0x06
#define USB_AC_AUTO_GAIN_CONTROL 0x07
#define USB_AC_DELAY_CONTROL 0x08
#define USB_AC_BASS_BOOST_CONTROL 0x09
#define USB_AC_LOUDNESS_CONTROL 0x0a
#define USB_AC_FU_MUTE (1 << (USB_AC_MUTE_CONTROL - 1))
#define USB_AC_FU_VOLUME (1 << (USB_AC_VOLUME_CONTROL - 1))
#define USB_AC_FU_BASS (1 << (USB_AC_BASS_CONTROL - 1))
#define USB_AC_FU_MID (1 << (USB_AC_MID_CONTROL - 1))
#define USB_AC_FU_TREBLE (1 << (USB_AC_TREBLE_CONTROL - 1))
#define USB_AC_FU_EQUILIZER (1 << (USB_AC_EQUALIZER_CONTROL - 1))
#define USB_AC_FU_AUTO_GAIN (1 << (USB_AC_AUTO_GAIN_CONTROL - 1))
#define USB_AC_FU_DELAY (1 << (USB_AC_DELAY_CONTROL - 1))
#define USB_AC_FU_BASS_BOOST (1 << (USB_AC_BASS_BOOST_CONTROL - 1))
#define USB_AC_FU_LOUDNESS (1 << (USB_AC_LOUDNESS_CONTROL - 1))
#define DEFINE_USB_AC_FEATURE_UNIT(n,ch) \
struct usb_ac_feature_unit_##n##_##ch { \
uint8_t bLength; \
uint8_t bDescriptorType; /* USB_DT_CS_INTERFACE */ \
uint8_t bDescriptorSubType; /* USB_AC_FEATURE_UNIT */ \
uint8_t bUnitId; \
uint8_t bSourceId; \
uint8_t bControlSize; \
uint##n##_t bmaControls[ch + 1]; /* FU_* ORed*/ \
uint8_t iFeature; \
} __attribute__ ((packed));
#define USB_AC_SET_REQ 0x00
#define USB_AC_GET_REQ 0x80
#define USB_AC_CUR_REQ 0x1
#define USB_AC_MIN_REQ 0x2
#define USB_AC_MAX_REQ 0x3
#define USB_AC_RES_REQ 0x4
#define USB_AC_MEM_REQ 0x5
#define USB_AC_SET_CUR (USB_AC_SET_REQ | USB_AC_CUR_REQ)
#define USB_AC_GET_CUR (USB_AC_GET_REQ | USB_AC_CUR_REQ)
#define USB_AC_SET_MIN (USB_AC_SET_REQ | USB_AC_MIN_REQ)
#define USB_AC_GET_MIN (USB_AC_GET_REQ | USB_AC_MIN_REQ)
#define USB_AC_SET_MAX (USB_AC_SET_REQ | USB_AC_MAX_REQ)
#define USB_AC_GET_MAX (USB_AC_GET_REQ | USB_AC_MAX_REQ)
#define USB_AC_SET_RES (USB_AC_SET_REQ | USB_AC_RES_REQ)
#define USB_AC_GET_RES (USB_AC_GET_REQ | USB_AC_RES_REQ)
#define USB_AC_SET_MEM (USB_AC_SET_REQ | USB_AC_MEM_REQ)
#define USB_AC_GET_MEM (USB_AC_GET_REQ | USB_AC_MEM_REQ)
#define USB_AC_GET_STAT 0xff
#define USB_AS_FORMAT_TYPE_UNDEFINED 0x0
#define USB_AS_FORMAT_TYPE_I 0x1
#define USB_AS_FORMAT_TYPE_II 0x2
#define USB_AS_FORMAT_TYPE_III 0x3
struct usb_as_interface {
uint8_t bLength;
uint8_t bDescriptorType; /* USB_DT_CS_INTERFACE */
uint8_t bDescriptorSubType; /* USB_AS_GENERAL */
uint8_t bTerminalLink;
uint8_t bDelay;
uint16_t wFormatTag;
} __attribute__ ((packed));
#define USB_AS_EP_GENERAL 0x01
#define USB_AS_EP_CS_SAMPLING_FREQ_CTL 0x01
#define USB_AS_EP_CS_PITCH_CTL 0x02
struct usb_iso_audio_endpoint_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint8_t bEndpointAddress;
uint8_t bmAttributes;
uint16_t wMaxPacketSize;
uint8_t bInterval;
uint8_t bRefresh;
uint8_t bSynchAddress;
} __attribute__ ((packed));
struct usb_as_iso_endpoint {
uint8_t bLength;
uint8_t bDescriptorType; /* USB_DT_CS_ENDPOINT */
uint8_t bDescriptorSubType; /* USB_AS_EP_GENERAL */
uint8_t bmAttributes;
uint8_t bLockDelayUnits;
uint16_t wLockDelay;
} __attribute__ ((packed));
#define USB_AS_FORMAT_TYPE_I_UNDEFINED 0x0
#define USB_AS_FORMAT_TYPE_I_PCM 0x1
#define USB_AS_FORMAT_TYPE_I_PCM8 0x2
#define USB_AS_FORMAT_TYPE_I_IEEE_FLOAT 0x3
#define USB_AS_FORMAT_TYPE_I_ALAW 0x4
#define USB_AS_FORMAT_TYPE_I_MULAW 0x5
struct usb_as_format_type_i_discrete {
uint8_t bLength;
uint8_t bDescriptorType; /* USB_DT_CS_INTERFACE */
uint8_t bDescriptorSubType; /* USB_AS_FORMAT_TYPE */
uint8_t bFormatType; /* USB_AS_FORMAT_TYPE_I */
uint8_t bNrChannels;
uint8_t bSubframeSize;
uint8_t bBitResolution;
uint8_t bSamFreqType; /* Number of discrete frequencies */
uint8_t tSamFreq[][3];
} __attribute__ ((packed));
#define USB_AS_SIZEOF_FORMAT_TYPE_I_DISCRETE(n) (8 + (n * 3))
#endif /* USB_AUDIO_DEF_H */