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

@ -1347,6 +1347,7 @@ Lyre prototype 1 */
#elif (CONFIG_USBOTG == USBOTG_DESIGNWARE)
#define USB_HAS_BULK
#define USB_HAS_INTERRUPT
#define USB_HAS_ISOCHRONOUS
#elif (CONFIG_USBOTG == USBOTG_ARC) || \
(CONFIG_USBOTG == USBOTG_JZ4740) || \
(CONFIG_USBOTG == USBOTG_JZ4760) || \
@ -1356,6 +1357,9 @@ Lyre prototype 1 */
(CONFIG_USBOTG == USBOTG_TNETV105)
#define USB_HAS_BULK
#define USB_HAS_INTERRUPT
#if (CONFIG_USBOTG == USBOTG_ARC)
#define USB_HAS_ISOCHRONOUS
#endif
#define USB_LEGACY_CONTROL_API
#elif defined(CPU_TCC780X)
#define USB_HAS_BULK
@ -1366,11 +1370,6 @@ Lyre prototype 1 */
//#define USB_HAS_INTERRUPT -- seems to be broken
#endif /* CONFIG_USBOTG */
#if (CONFIG_USBOTG == USBOTG_ARC) || \
(CONFIG_USBOTG == USBOTG_AS3525)
#define USB_HAS_ISOCHRONOUS
#endif
/* define the class drivers to enable */
#ifdef BOOTLOADER
@ -1398,6 +1397,10 @@ Lyre prototype 1 */
#endif
#endif
#ifdef USB_HAS_ISOCHRONOUS
#define USB_ENABLE_AUDIO
#endif
#endif /* BOOTLOADER */
#endif /* HAVE_USBSTACK */

View file

@ -72,6 +72,9 @@
enum pcm_mixer_channel
{
PCM_MIXER_CHAN_PLAYBACK = 0,
#ifdef USB_ENABLE_AUDIO
PCM_MIXER_CHAN_USBAUDIO,
#endif
PCM_MIXER_CHAN_VOICE,
#ifndef HAVE_HARDWARE_BEEP
PCM_MIXER_CHAN_BEEP,

View file

@ -200,7 +200,8 @@
#define DWC_DOEPCTL(x) (*((REG32_PTR_T)(OTGBASE + 0xb00 + 0x20*(x))))
#define EPENA (1<<31)
#define EPDIS (1<<30)
#define SD0PID (1<<28)
#define SETD1PIDOF (1<<29)
#define SETD0PIDEF (1<<28)
#define SNAK (1<<27)
#define CNAK (1<<26)
#define DTXFNUM(x) ((x)<<22)

View file

@ -167,6 +167,9 @@ enum {
#endif
#ifdef USB_ENABLE_HID
USB_DRIVER_HID,
#endif
#ifdef USB_ENABLE_AUDIO
USB_DRIVER_AUDIO,
#endif
USB_NUM_DRIVERS
};
@ -256,6 +259,10 @@ void usb_firewire_connect_event(void);
void usb_set_hid(bool enable);
#endif
#ifdef USB_ENABLE_AUDIO
void usb_set_audio(int value);
#endif
#if defined(USB_ENABLE_STORAGE) && defined(HAVE_MULTIDRIVE)
/* when the target has several drives, decide whether mass storage should
* skip the first drive. This is useful when the second drive is a SD card

View file

@ -339,6 +339,12 @@ struct usb_endpoint_descriptor {
#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */
#define USB_ENDPOINT_DIR_MASK 0x80
#define USB_ENDPOINT_SYNCTYPE_MASK 0x0c /* in bmAttributes */
#define USB_ENDPOINT_SYNC_NONE (0 << 2)
#define USB_ENDPOINT_SYNC_ASYNC (1 << 2)
#define USB_ENDPOINT_SYNC_ADAPTIVE (2 << 2)
#define USB_ENDPOINT_SYNC_SYNC (3 << 2)
#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */
#define USB_ENDPOINT_XFER_CONTROL 0
#define USB_ENDPOINT_XFER_ISOC 1

View file

@ -74,6 +74,7 @@ void usb_drv_stall(int endpoint, bool stall,bool in);
bool usb_drv_stalled(int endpoint,bool in);
int usb_drv_send(int endpoint, void* ptr, int length);
int usb_drv_send_nonblocking(int endpoint, void* ptr, int length);
int usb_drv_recv_blocking(int endpoint, void* ptr, int length);
int usb_drv_recv_nonblocking(int endpoint, void* ptr, int length);
void usb_drv_control_response(enum usb_control_response resp,
void* data, int length);
@ -86,6 +87,14 @@ void usb_drv_set_test_mode(int mode);
bool usb_drv_connected(void);
int usb_drv_request_endpoint(int type, int dir);
void usb_drv_release_endpoint(int ep);
#ifdef USB_HAS_ISOCHRONOUS
/* returns the last received frame number (the 11-bit number contained in the last SOF):
* - full-speed: the host sends one SOF every 1ms (so 1000 SOF/s)
* - high-speed: the hosts sends one SOF every 125us but each consecutive 8 SOF have the same frame
* number
* thus in all mode, the frame number can be interpreted as the current millisecond *in USB time*. */
int usb_drv_get_frame_number(void);
#endif
/* USB_STRING_INITIALIZER(u"Example String") */
#define USB_STRING_INITIALIZER(S) { \