mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-07 13:45:03 -05:00
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
149 lines
5 KiB
C
149 lines
5 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2011 by Michael Sevakis
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#ifndef PCM_MIXER_H
|
|
#define PCM_MIXER_H
|
|
|
|
#include <sys/types.h>
|
|
|
|
/** Simple config **/
|
|
|
|
/* Length of PCM frames (always) */
|
|
#if CONFIG_CPU == PP5002
|
|
/* There's far less time to do mixing because HW FIFOs are short */
|
|
#define MIX_FRAME_SAMPLES 64
|
|
#elif (CONFIG_CPU == JZ4760B) || (CONFIG_CPU == JZ4732)
|
|
/* These MIPS32r1 targets have a very high interrupt latency, which
|
|
unfortunately causes a lot of audio underruns under even moderate load */
|
|
#define MIX_FRAME_SAMPLES 2048
|
|
#elif (CONFIG_PLATFORM & PLATFORM_MAEMO5) || defined(DX50) || defined(DX90)
|
|
/* Maemo 5 needs 2048 samples for decent performance.
|
|
Otherwise the locking overhead inside gstreamer costs too much */
|
|
/* iBasso Devices: Match Rockbox PCM buffer size to ALSA PCM buffer size
|
|
to minimize memory transfers. */
|
|
#define MIX_FRAME_SAMPLES 2048
|
|
#elif (CONFIG_PLATFORM & PLATFORM_HOSTED)
|
|
/* Hosted targets need larger buffers for decent performance due to
|
|
OS locking/scheduling overhead */
|
|
#define MIX_FRAME_SAMPLES 1024
|
|
#else
|
|
/* Assume HW DMA engine is available or sufficient latency exists in the
|
|
PCM pathway */
|
|
#define MIX_FRAME_SAMPLES 256
|
|
#endif
|
|
|
|
#if defined(CPU_COLDFIRE) || defined(CPU_PP)
|
|
/* For Coldfire, it's just faster
|
|
For PortalPlayer, this also avoids more expensive cache coherency */
|
|
#define DOWNMIX_BUF_IBSS IBSS_ATTR
|
|
#else
|
|
/* Otherwise can't DMA from IRAM, IRAM is pointless or worse */
|
|
#define DOWNMIX_BUF_IBSS
|
|
#endif
|
|
|
|
#if defined(CPU_COLDFIRE) || defined(CPU_PP)
|
|
#define MIXER_CALLBACK_ICODE ICODE_ATTR
|
|
#else
|
|
#define MIXER_CALLBACK_ICODE
|
|
#endif
|
|
|
|
|
|
/** Definitions **/
|
|
|
|
/* Channels are preassigned for simplicity */
|
|
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,
|
|
#endif
|
|
/* Add new channel indexes above this line */
|
|
PCM_MIXER_NUM_CHANNELS,
|
|
};
|
|
|
|
/* Channel playback states */
|
|
enum channel_status
|
|
{
|
|
CHANNEL_STOPPED = 0,
|
|
CHANNEL_PLAYING,
|
|
CHANNEL_PAUSED,
|
|
};
|
|
|
|
#define MIX_AMP_UNITY 0x00010000
|
|
#define MIX_AMP_MUTE 0x00000000
|
|
|
|
|
|
/** Public interfaces **/
|
|
|
|
/* Start playback on a channel */
|
|
void mixer_channel_play_data(enum pcm_mixer_channel channel,
|
|
pcm_play_callback_type get_more,
|
|
const void *start, size_t size);
|
|
|
|
/* Pause or resume a channel (when started) */
|
|
void mixer_channel_play_pause(enum pcm_mixer_channel channel, bool play);
|
|
|
|
/* Stop playback on a channel */
|
|
void mixer_channel_stop(enum pcm_mixer_channel channel);
|
|
|
|
/* Set channel's amplitude factor */
|
|
void mixer_channel_set_amplitude(enum pcm_mixer_channel channel,
|
|
unsigned int amplitude);
|
|
|
|
/* Return channel's playback status */
|
|
enum channel_status mixer_channel_status(enum pcm_mixer_channel channel);
|
|
|
|
/* Returns amount data remaining in channel before next callback */
|
|
size_t mixer_channel_get_bytes_waiting(enum pcm_mixer_channel channel);
|
|
|
|
/* Return pointer to channel's playing audio data and the size remaining */
|
|
const void * mixer_channel_get_buffer(enum pcm_mixer_channel channel,
|
|
int *count);
|
|
|
|
/* Calculate peak values for channel */
|
|
void mixer_channel_calculate_peaks(enum pcm_mixer_channel channel,
|
|
struct pcm_peaks *peaks);
|
|
|
|
/* Adjust channel pointer by a given offset to support movable buffers */
|
|
void mixer_adjust_channel_address(enum pcm_mixer_channel channel,
|
|
off_t offset);
|
|
|
|
/* Set a hook that is called upon getting a new source buffer for a channel
|
|
NOTE: Called for each buffer, not each mixer chunk */
|
|
typedef void (*chan_buffer_hook_fn_type)(const void *start, size_t size);
|
|
|
|
void mixer_channel_set_buffer_hook(enum pcm_mixer_channel channel,
|
|
chan_buffer_hook_fn_type fn);
|
|
|
|
/* Stop ALL channels and PCM and reset state */
|
|
void mixer_reset(void);
|
|
|
|
/* Set output samplerate */
|
|
void mixer_set_frequency(unsigned int samplerate);
|
|
|
|
/* Get output samplerate */
|
|
unsigned int mixer_get_frequency(void);
|
|
|
|
#endif /* PCM_MIXER_H */
|