Make PCM->driver interface about as simple as it will get. Registered callback, zero data, alignment and stops are handled entirely inside pcm.c; driver merely calls fixed pcm.c callback. Remove pcm_record_more and do it just like playback; the original reason behind it isn't very practical in general. Everything checks out on supported targets. There wer some compat changes I can't check out on many unsupoorted but if there's a problem it will be a minor oops. Plugins become incompatible due to recording tweak-- full update. Sorted API.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26253 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Michael Sevakis 2010-05-24 16:42:32 +00:00
parent 6688988ec4
commit d56999890f
19 changed files with 277 additions and 460 deletions

View file

@ -177,6 +177,9 @@ static const struct plugin_api rockbox_api = {
&button_queue,
#endif
bidi_l2v,
#ifdef HAVE_LCD_BITMAP
is_diacritic,
#endif
font_get_bits,
font_load,
font_get,
@ -461,6 +464,9 @@ static const struct plugin_api rockbox_api = {
sound_max,
sound_unit,
sound_val2phys,
#ifdef AUDIOHW_HAVE_EQ
sound_enum_hw_eq_band_setting,
#endif
#ifndef SIMULATOR
mp3_play_data,
mp3_play_pause,
@ -491,7 +497,6 @@ static const struct plugin_api rockbox_api = {
pcm_init_recording,
pcm_close_recording,
pcm_record_data,
pcm_record_more,
pcm_stop_recording,
pcm_calculate_rec_peaks,
audio_set_recording_gain,
@ -630,7 +635,12 @@ static const struct plugin_api rockbox_api = {
codec_thread_do_callback,
codec_load_file,
get_codec_filename,
find_array_ptr,
remove_array_ptr,
#if defined(HAVE_RECORDING) && (defined(HAVE_LINE_IN) || defined(HAVE_MIC_IN))
round_value_to_list32,
#endif
#endif /* CONFIG_CODEC == SWCODEC */
get_metadata,
mp3info,
count_mp3_frames,
@ -711,24 +721,6 @@ static const struct plugin_api rockbox_api = {
appsversion,
/* new stuff at the end, sort into place next time
the API gets incompatible */
#ifdef HAVE_LCD_BITMAP
is_diacritic,
#endif
#if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && \
(defined(HAVE_LINE_IN) || defined(HAVE_MIC_IN))
round_value_to_list32,
#endif
#ifdef AUDIOHW_HAVE_EQ
sound_enum_hw_eq_band_setting,
#endif
#if CONFIG_CODEC == SWCODEC
find_array_ptr,
remove_array_ptr,
#endif
};
int plugin_load(const char* plugin, const void* parameter)

View file

@ -144,12 +144,12 @@ void* plugin_get_buffer(size_t *buffer_size);
#define PLUGIN_MAGIC 0x526F634B /* RocK */
/* increase this every time the api struct changes */
#define PLUGIN_API_VERSION 186
#define PLUGIN_API_VERSION 187
/* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any
new function which are "waiting" at the end of the function table) */
#define PLUGIN_MIN_API_VERSION 182
#define PLUGIN_MIN_API_VERSION 187
/* plugin return codes */
enum plugin_status {
@ -259,6 +259,9 @@ struct plugin_api {
struct event_queue *button_queue;
#endif
unsigned short *(*bidi_l2v)( const unsigned char *str, int orientation );
#ifdef HAVE_LCD_BITMAP
bool (*is_diacritic)(const unsigned short char_code, bool *is_rtl);
#endif
const unsigned char *(*font_get_bits)( struct font *pf, unsigned short char_code );
int (*font_load)(struct font*, const char *path);
struct font* (*font_get)(int font);
@ -577,6 +580,10 @@ struct plugin_api {
int (*sound_max)(int setting);
const char * (*sound_unit)(int setting);
int (*sound_val2phys)(int setting, int value);
#ifdef AUDIOHW_HAVE_EQ
int (*sound_enum_hw_eq_band_setting)(unsigned int band,
unsigned int band_setting);
#endif /* AUDIOHW_HAVE_EQ */
#ifndef SIMULATOR
void (*mp3_play_data)(const unsigned char* start, int size,
void (*get_more)(unsigned char** start, size_t* size));
@ -591,7 +598,7 @@ struct plugin_api {
const unsigned long *audio_master_sampr_list;
const unsigned long *hw_freq_sampr;
void (*pcm_apply_settings)(void);
void (*pcm_play_data)(pcm_more_callback_type get_more,
void (*pcm_play_data)(pcm_play_callback_type get_more,
unsigned char* start, size_t size);
void (*pcm_play_stop)(void);
void (*pcm_set_frequency)(unsigned int frequency);
@ -610,9 +617,8 @@ struct plugin_api {
const unsigned long *rec_freq_sampr;
void (*pcm_init_recording)(void);
void (*pcm_close_recording)(void);
void (*pcm_record_data)(pcm_more_callback_type2 more_ready,
void (*pcm_record_data)(pcm_rec_callback_type more_ready,
void *start, size_t size);
void (*pcm_record_more)(void *start, size_t size);
void (*pcm_stop_recording)(void);
void (*pcm_calculate_rec_peaks)(int *left, int *right);
void (*audio_set_recording_gain)(int left, int right, int type);
@ -774,7 +780,15 @@ struct plugin_api {
unsigned int *audio_thread_id);
int (*codec_load_file)(const char* codec, struct codec_api *api);
const char *(*get_codec_filename)(int cod_spec);
void ** (*find_array_ptr)(void **arr, void *ptr);
int (*remove_array_ptr)(void **arr, void *ptr);
#if defined(HAVE_RECORDING) && (defined(HAVE_LINE_IN) || defined(HAVE_MIC_IN))
int (*round_value_to_list32)(unsigned long value,
const unsigned long list[],
int count,
bool signd);
#endif
#endif /* CONFIG_CODEC == SWCODEC */
bool (*get_metadata)(struct mp3entry* id3, int fd, const char* trackname);
bool (*mp3info)(struct mp3entry *entry, const char *filename);
int (*count_mp3_frames)(int fd, int startpos, int filesize,
@ -874,28 +888,6 @@ struct plugin_api {
const char *appsversion;
/* new stuff at the end, sort into place next time
the API gets incompatible */
#ifdef HAVE_LCD_BITMAP
bool (*is_diacritic)(const unsigned short char_code, bool *is_rtl);
#endif
#if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && \
(defined(HAVE_LINE_IN) || defined(HAVE_MIC_IN))
int (*round_value_to_list32)(unsigned long value,
const unsigned long list[],
int count,
bool signd);
#endif
#ifdef AUDIOHW_HAVE_EQ
int (*sound_enum_hw_eq_band_setting)(unsigned int band,
unsigned int band_setting);
#endif /* AUDIOHW_HAVE_EQ */
#if CONFIG_CODEC == SWCODEC
void ** (*find_array_ptr)(void **arr, void *ptr);
int (*remove_array_ptr)(void **arr, void *ptr);
#endif
};
/* plugin header */

View file

@ -982,7 +982,7 @@ uint32_t ICODE_ATTR buffer_magnitude(int16_t *input)
/* Stop the recording when the buffer is full */
#ifndef SIMULATOR
int recording_callback(int status)
void recording_callback(int status, void **start, size_t *size)
{
int tail = audio_tail ^ 1;
@ -991,10 +991,9 @@ int recording_callback(int status)
audio_tail = tail;
/* Always record full buffer, even if not required */
rb->pcm_record_more(audio_data[tail],
BUFFER_SIZE * sizeof (int16_t));
*start = audio_data[tail];
*size = BUFFER_SIZE * sizeof (int16_t);
return 0;
(void)status;
}
#endif

View file

@ -256,7 +256,7 @@ enum
/*******************************************************************/
/* Callback for when more data is ready - called in interrupt context */
static int pcm_rec_have_more(int status)
static void pcm_rec_have_more(int status, void **start, size_t *size)
{
if (status < 0)
{
@ -265,9 +265,9 @@ static int pcm_rec_have_more(int status)
{
/* Flush recorded data to disk and stop recording */
queue_post(&pcmrec_queue, PCMREC_STOP, 0);
return -1;
return;
}
/* else try again next transmission */
/* else try again next transmission - frame is invalid */
}
else if (!dma_lock)
{
@ -282,8 +282,8 @@ static int pcm_rec_have_more(int status)
dma_wr_pos = next_pos;
}
pcm_record_more(GET_PCM_CHUNK(dma_wr_pos), PCM_CHUNK_SIZE);
return 0;
*start = GET_PCM_CHUNK(dma_wr_pos);
*size = PCM_CHUNK_SIZE;
} /* pcm_rec_have_more */
static void reset_hardware(void)

View file

@ -89,7 +89,7 @@ enum voice_thread_messages
/* Structure to store clip data callback info */
struct voice_info
{
pcm_more_callback_type get_more; /* Callback to get more clips */
pcm_play_callback_type get_more; /* Callback to get more clips */
unsigned char *start; /* Start of clip */
size_t size; /* Size of clip */
};
@ -117,7 +117,7 @@ static inline bool playback_is_playing(void)
/* Stop any current clip and start playing a new one */
void mp3_play_data(const unsigned char* start, int size,
pcm_more_callback_type get_more)
pcm_play_callback_type get_more)
{
/* Shared struct to get data to the thread - once it replies, it has
* safely cached it in its own private data */

View file

@ -50,9 +50,9 @@
/** RAW PCM routines used with playback and recording **/
/* Typedef for registered callback */
typedef void (*pcm_more_callback_type)(unsigned char **start,
typedef void (*pcm_play_callback_type)(unsigned char **start,
size_t *size);
typedef int (*pcm_more_callback_type2)(int status);
typedef void (*pcm_rec_callback_type)(int status, void **start, size_t *size);
/* set the pcm frequency - use values in hw_sampr_list
* use -1 for the default frequency
@ -71,7 +71,7 @@ void pcm_init(void);
void pcm_postinit(void);
/* This is for playing "raw" PCM data */
void pcm_play_data(pcm_more_callback_type get_more,
void pcm_play_data(pcm_play_callback_type get_more,
unsigned char* start, size_t size);
void pcm_calculate_peaks(int *left, int *right);
@ -86,6 +86,11 @@ bool pcm_is_playing(void);
/** The following are for internal use between pcm.c and target-
specific portion **/
/* Called by the bottom layer ISR when more data is needed. Returns non-
* zero size if more data is to be played. Setting start to NULL
* forces stop. */
void pcm_play_get_more_callback(void **start, size_t *size);
extern unsigned long pcm_curr_sampr;
extern unsigned long pcm_sampr;
extern int pcm_fsel;
@ -94,10 +99,8 @@ extern int pcm_fsel;
void * pcm_dma_addr(void *addr);
#endif
/* the registered callback function to ask for more mp3 data */
extern volatile pcm_more_callback_type pcm_callback_for_more;
extern volatile bool pcm_playing;
extern volatile bool pcm_paused;
extern volatile bool pcm_playing;
extern volatile bool pcm_paused;
void pcm_play_dma_lock(void);
void pcm_play_dma_unlock(void);
@ -105,7 +108,6 @@ void pcm_play_dma_init(void);
void pcm_play_dma_start(const void *addr, size_t size);
void pcm_play_dma_stop(void);
void pcm_play_dma_pause(bool pause);
void pcm_play_dma_stopped_callback(void);
const void * pcm_play_dma_get_peak_buffer(int *count);
void pcm_dma_apply_settings(void);
@ -124,7 +126,7 @@ void pcm_init_recording(void);
void pcm_close_recording(void);
/* Start recording "raw" PCM data */
void pcm_record_data(pcm_more_callback_type2 more_ready,
void pcm_record_data(pcm_rec_callback_type more_ready,
void *start, size_t size);
/* Stop tranferring data into supplied buffer */
@ -133,17 +135,16 @@ void pcm_stop_recording(void);
/* Is pcm currently recording? */
bool pcm_is_recording(void);
/* Continue transferring data in - call during interrupt handler */
void pcm_record_more(void *start, size_t size);
/* Called by bottom layer ISR when transfer is complete. Returns non-zero
* size if successful. Setting start to NULL forces stop. */
void pcm_rec_more_ready_callback(int status, void **start, size_t *size);
void pcm_calculate_rec_peaks(int *left, int *right);
/** The following are for internal use between pcm.c and target-
specific portion **/
/* the registered callback function for when more data is available */
extern volatile pcm_more_callback_type2 pcm_callback_more_ready;
/* DMA transfer in is currently active */
extern volatile bool pcm_recording;
extern volatile bool pcm_recording;
/* APIs implemented in the target-specific portion */
void pcm_rec_dma_init(void);
@ -151,7 +152,6 @@ void pcm_rec_dma_close(void);
void pcm_rec_dma_start(void *addr, size_t size);
void pcm_rec_dma_record_more(void *start, size_t size);
void pcm_rec_dma_stop(void);
void pcm_rec_dma_stopped_callback(void);
const void * pcm_rec_dma_get_peak_buffer(void);
#endif /* HAVE_RECORDING */

View file

@ -39,6 +39,7 @@
* pcm_play_lock
* pcm_play_unlock
* Semi-private -
* pcm_play_get_more_callback
* pcm_play_dma_init
* pcm_play_dma_start
* pcm_play_dma_stop
@ -48,28 +49,27 @@
* pcm_sampr (R)
* pcm_fsel (R)
* pcm_curr_sampr (R)
* pcm_callback_for_more (R)
* pcm_playing (R)
* pcm_paused (R)
*
* ==Playback/Recording==
* Public -
* pcm_dma_addr
* Semi-private -
* pcm_dma_apply_settings
* pcm_dma_addr
*
* ==Recording==
* Public -
* pcm_rec_lock
* pcm_rec_unlock
* Semi-private -
* pcm_rec_more_ready_callback
* pcm_rec_dma_init
* pcm_rec_dma_close
* pcm_rec_dma_start
* pcm_rec_dma_record_more
* pcm_rec_dma_stop
* pcm_rec_dma_get_peak_buffer
* Data Read/Written within TSP -
* pcm_callback_more_ready (R)
* pcm_recording (R)
*
* States are set _after_ the target's pcm driver is called so that it may
@ -78,7 +78,7 @@
*/
/* the registered callback function to ask for more mp3 data */
volatile pcm_more_callback_type pcm_callback_for_more
static volatile pcm_play_callback_type pcm_callback_for_more
SHAREDBSS_ATTR = NULL;
/* PCM playback state */
volatile bool pcm_playing SHAREDBSS_ATTR = false;
@ -91,6 +91,14 @@ unsigned long pcm_sampr SHAREDBSS_ATTR = HW_SAMPR_DEFAULT;
/* samplerate frequency selection index */
int pcm_fsel SHAREDBSS_ATTR = HW_FREQ_DEFAULT;
/* Called internally by functions to reset the state */
static void pcm_play_stopped(void)
{
pcm_callback_for_more = NULL;
pcm_paused = false;
pcm_playing = false;
}
/**
* Perform peak calculation on a buffer of packed 16-bit samples.
*
@ -187,6 +195,16 @@ const void* pcm_get_peak_buffer(int * count)
return pcm_play_dma_get_peak_buffer(count);
}
bool pcm_is_playing(void)
{
return pcm_playing;
}
bool pcm_is_paused(void)
{
return pcm_paused;
}
/****************************************************************************
* Functions that do not require targeted implementation but only a targeted
* interface
@ -198,7 +216,7 @@ void pcm_init(void)
{
logf("pcm_init");
pcm_play_dma_stopped_callback();
pcm_play_stopped();
pcm_set_frequency(HW_SAMPR_DEFAULT);
@ -214,7 +232,7 @@ static void pcm_play_data_start(unsigned char *start, size_t size)
if (!(start && size))
{
pcm_more_callback_type get_more = pcm_callback_for_more;
pcm_play_callback_type get_more = pcm_callback_for_more;
size = 0;
if (get_more)
{
@ -239,10 +257,10 @@ static void pcm_play_data_start(unsigned char *start, size_t size)
/* Force a stop */
logf(" pcm_play_dma_stop");
pcm_play_dma_stop();
pcm_play_dma_stopped_callback();
pcm_play_stopped();
}
void pcm_play_data(pcm_more_callback_type get_more,
void pcm_play_data(pcm_play_callback_type get_more,
unsigned char *start, size_t size)
{
logf("pcm_play_data");
@ -257,6 +275,29 @@ void pcm_play_data(pcm_more_callback_type get_more,
pcm_play_unlock();
}
void pcm_play_get_more_callback(void **start, size_t *size)
{
pcm_play_callback_type get_more = pcm_callback_for_more;
*size = 0;
if (get_more && start)
{
/* Call registered callback */
get_more((unsigned char **)start, size);
*start = (void *)(((uintptr_t)*start + 3) & ~3);
*size &= ~3;
if (*start && *size)
return;
}
/* Error, callback missing or no more DMA to do */
pcm_play_dma_stop();
pcm_play_stopped();
}
void pcm_play_pause(bool play)
{
logf("pcm_play_pause: %s", play ? "play" : "pause");
@ -302,7 +343,7 @@ void pcm_play_stop(void)
{
logf(" pcm_play_dma_stop");
pcm_play_dma_stop();
pcm_play_dma_stopped_callback();
pcm_play_stopped();
}
else
{
@ -312,13 +353,6 @@ void pcm_play_stop(void)
pcm_play_unlock();
}
void pcm_play_dma_stopped_callback(void)
{
pcm_callback_for_more = NULL;
pcm_paused = false;
pcm_playing = false;
}
/**/
/* set frequency next frequency used by the audio hardware -
@ -350,27 +384,24 @@ void pcm_apply_settings(void)
}
}
bool pcm_is_playing(void)
{
return pcm_playing;
}
bool pcm_is_paused(void)
{
return pcm_paused;
}
#ifdef HAVE_RECORDING
/** Low level pcm recording apis **/
/* Next start for recording peaks */
static const void * volatile pcm_rec_peak_addr SHAREDBSS_ATTR = NULL;
/* the registered callback function for when more data is available */
volatile pcm_more_callback_type2
static volatile pcm_rec_callback_type
pcm_callback_more_ready SHAREDBSS_ATTR = NULL;
/* DMA transfer in is currently active */
volatile bool pcm_recording SHAREDBSS_ATTR = false;
/* Called internally by functions to reset the state */
static void pcm_recording_stopped(void)
{
pcm_recording = false;
pcm_callback_more_ready = NULL;
}
/**
* Return recording peaks - From the end of the last peak up to
* current write position.
@ -410,10 +441,16 @@ void pcm_calculate_rec_peaks(int *left, int *right)
*right = peaks[1];
} /* pcm_calculate_rec_peaks */
bool pcm_is_recording(void)
{
return pcm_recording;
}
/****************************************************************************
* Functions that do not require targeted implementation but only a targeted
* interface
*/
void pcm_init_recording(void)
{
logf("pcm_init_recording");
@ -424,7 +461,7 @@ void pcm_init_recording(void)
pcm_rec_lock();
logf(" pcm_rec_dma_init");
pcm_rec_dma_stopped_callback();
pcm_recording_stopped();
pcm_rec_dma_init();
pcm_rec_unlock();
@ -440,7 +477,7 @@ void pcm_close_recording(void)
{
logf(" pcm_rec_dma_stop");
pcm_rec_dma_stop();
pcm_rec_dma_stopped_callback();
pcm_recording_stopped();
}
logf(" pcm_rec_dma_close");
@ -449,7 +486,7 @@ void pcm_close_recording(void)
pcm_rec_unlock();
}
void pcm_record_data(pcm_more_callback_type2 more_ready,
void pcm_record_data(pcm_rec_callback_type more_ready,
void *start, size_t size)
{
logf("pcm_record_data");
@ -493,43 +530,40 @@ void pcm_stop_recording(void)
{
logf(" pcm_rec_dma_stop");
pcm_rec_dma_stop();
pcm_rec_dma_stopped_callback();
pcm_recording_stopped();
}
pcm_rec_unlock();
} /* pcm_stop_recording */
void pcm_record_more(void *start, size_t size)
void pcm_rec_more_ready_callback(int status, void **start, size_t *size)
{
start = (void *)(((uintptr_t)start + 3) & ~3);
size = size & ~3;
pcm_rec_callback_type have_more = pcm_callback_more_ready;
if (!size)
*size = 0;
if (have_more && start)
{
pcm_rec_dma_stop();
pcm_rec_dma_stopped_callback();
return;
have_more(status, start, size);
*start = (void *)(((uintptr_t)*start + 3) & ~3);
*size &= ~3;
if (*start && *size)
{
#ifdef HAVE_PCM_REC_DMA_ADDRESS
/* Need a physical DMA address translation, if not already
* physical. */
pcm_rec_peak_addr = pcm_dma_addr(*start);
#else
pcm_rec_peak_addr = *start;
#endif
return;
}
}
#ifdef HAVE_PCM_REC_DMA_ADDRESS
/* Need a physical DMA address translation, if not already physical. */
pcm_rec_peak_addr = pcm_dma_addr(start);
#else
pcm_rec_peak_addr = start;
#endif
pcm_rec_dma_record_more(start, size);
}
bool pcm_is_recording(void)
{
return pcm_recording;
}
void pcm_rec_dma_stopped_callback(void)
{
pcm_recording = false;
pcm_callback_more_ready = NULL;
/* Error, callback missing or no more DMA to do */
pcm_rec_dma_stop();
pcm_recording_stopped();
}
#endif /* HAVE_RECORDING */

View file

@ -74,18 +74,13 @@ static void dma_callback(void)
{
if(!dma_size)
{
register pcm_more_callback_type get_more = pcm_callback_for_more;
if(get_more)
get_more(&dma_start_addr, &dma_size);
pcm_play_get_more_callback(&dma_start_addr, &dma_size);
if (!dma_size)
return;
}
if(!dma_size)
{
pcm_play_dma_stop();
pcm_play_dma_stopped_callback();
}
else
play_start_pcm();
play_start_pcm();
}
void pcm_play_dma_start(const void *addr, size_t size)
@ -275,31 +270,19 @@ static void rec_dma_callback(void)
if(!rec_dma_size)
{
register pcm_more_callback_type2 more_ready = pcm_callback_more_ready;
if (!more_ready || more_ready(0) < 0)
pcm_rec_more_ready_callback(0, &rec_dma_start_addr, &rec_dma_size);
if(rec_dma_size != 0)
{
/* Finished recording */
pcm_rec_dma_stop();
pcm_rec_dma_stopped_callback();
return;
dump_dcache_range(rec_dma_start_addr, rec_dma_size);
#if CONFIG_CPU == AS3525
mono_samples = AS3525_UNCACHED_ADDR(rec_dma_start_addr);
#endif
rec_dma_start();
}
}
rec_dma_start();
}
void pcm_rec_dma_record_more(void *start, size_t size)
{
dump_dcache_range(start, size);
rec_dma_start_addr = start;
#if CONFIG_CPU == AS3525
mono_samples = AS3525_UNCACHED_ADDR(start);
#endif
rec_dma_size = size;
}
void pcm_rec_dma_stop(void)
{
dma_disable_channel(1);

View file

@ -52,9 +52,9 @@ static struct dma_data dma_play_data =
static void play_dma_callback(void)
{
unsigned char *start;
size_t size = 0;
pcm_more_callback_type get_more = pcm_callback_for_more;
void *start;
size_t size;
bool rror;
if (dma_play_data.locked != 0)
{
@ -63,28 +63,20 @@ static void play_dma_callback(void)
return;
}
if (dma_play_bd.mode.status & BD_RROR)
{
/* Stop on error */
}
else if (get_more != NULL && (get_more(&start, &size), size != 0))
{
start = (void*)(((unsigned long)start + 3) & ~3);
size &= ~3;
rror = dma_play_bd.mode.status & BD_RROR;
/* Flush any pending cache writes */
clean_dcache_range(start, size);
dma_play_bd.buf_addr = (void *)addr_virt_to_phys((unsigned long)start);
dma_play_bd.mode.count = size;
dma_play_bd.mode.command = TRANSFER_16BIT;
dma_play_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
sdma_channel_run(DMA_PLAY_CH_NUM);
pcm_play_get_more_callback(rror ? NULL : &start, &size);
if (size == 0)
return;
}
/* Error, callback missing or no more DMA to do */
pcm_play_dma_stop();
pcm_play_dma_stopped_callback();
/* Flush any pending cache writes */
clean_dcache_range(start, size);
dma_play_bd.buf_addr = (void *)addr_virt_to_phys((unsigned long)start);
dma_play_bd.mode.count = size;
dma_play_bd.mode.command = TRANSFER_16BIT;
dma_play_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
sdma_channel_run(DMA_PLAY_CH_NUM);
}
void pcm_play_lock(void)
@ -272,12 +264,6 @@ void pcm_play_dma_start(const void *addr, size_t size)
SSI_STCR2 &= ~SSI_STCR_TFEN0;
SSI_SCR2 &= ~(SSI_SCR_TE | SSI_SCR_SSIEN);
addr = (void *)(((unsigned long)addr + 3) & ~3);
size &= ~3;
if (size <= 0)
return;
if (!sdma_channel_reset(DMA_PLAY_CH_NUM))
return;
@ -383,8 +369,9 @@ static struct dma_data dma_rec_data =
static void rec_dma_callback(void)
{
pcm_more_callback_type2 more_ready;
int status = 0;
void *start;
size_t size;
if (dma_rec_data.locked != 0)
{
@ -395,17 +382,22 @@ static void rec_dma_callback(void)
if (dma_rec_bd.mode.status & BD_RROR)
status = DMA_REC_ERROR_DMA;
more_ready = pcm_callback_more_ready;
pcm_rec_more_ready_callback(status, &start, &size);
if (more_ready != NULL && more_ready(status) >= 0)
{
sdma_channel_run(DMA_REC_CH_NUM);
if (size == 0)
return;
}
/* Finished recording */
pcm_rec_dma_stop();
pcm_rec_dma_stopped_callback();
/* Invalidate - buffer must be coherent */
dump_dcache_range(start, size);
start = (void *)addr_virt_to_phys((unsigned long)start);
dma_rec_bd.buf_addr = start;
dma_rec_bd.mode.count = size;
dma_rec_bd.mode.command = TRANSFER_16BIT;
dma_rec_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
sdma_channel_run(DMA_REC_CH_NUM);
}
void pcm_rec_lock(void)
@ -432,19 +424,6 @@ void pcm_rec_unlock(void)
}
}
void pcm_rec_dma_record_more(void *start, size_t size)
{
/* Invalidate - buffer must be coherent */
dump_dcache_range(start, size);
start = (void *)addr_virt_to_phys((unsigned long)start);
dma_rec_bd.buf_addr = start;
dma_rec_bd.mode.count = size;
dma_rec_bd.mode.command = TRANSFER_16BIT;
dma_rec_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
}
void pcm_rec_dma_stop(void)
{
/* Stop receiving data */

View file

@ -115,7 +115,6 @@ void pcm_dma_apply_settings(void)
/* NOTE: direct stack use forbidden by GCC stack handling bug for FIQ */
void ICODE_ATTR __attribute__((interrupt("FIQ"))) fiq_playback(void)
{
register pcm_more_callback_type get_more;
register size_t size;
DMA0_STATUS; /* Clear any pending interrupt */
@ -141,15 +140,12 @@ void ICODE_ATTR __attribute__((interrupt("FIQ"))) fiq_playback(void)
}
/* Buffer empty. Try to get more. */
get_more = pcm_callback_for_more;
if (get_more) {
get_more((unsigned char **)&dma_play_data.addr, &dma_play_data.size);
dma_play_data.addr = (dma_play_data.addr + 2) & ~3;
dma_play_data.size &= ~3;
}
pcm_play_get_more_callback((void **)&dma_play_data.addr,
&dma_play_data.size);
if (dma_play_data.size == 0) {
break;
/* No more data */
return;
}
if (dma_play_data.addr < UNCACHED_BASE_ADDR) {
@ -158,10 +154,6 @@ void ICODE_ATTR __attribute__((interrupt("FIQ"))) fiq_playback(void)
cpucache_flush();
}
}
/* Callback missing or no more DMA to do */
pcm_play_dma_stop();
pcm_play_dma_stopped_callback();
}
#else
/* ASM optimised FIQ handler. Checks for the minimum allowed loop cycles by
@ -247,28 +239,16 @@ void fiq_playback(void)
#endif
".more_data: \n"
"ldr r2, =pcm_callback_for_more \n"
"ldr r2, [r2] \n" /* get callback address */
"cmp r2, #0 \n" /* check for null pointer */
"beq .stop \n" /* callback removed, stop */
"stmia r11, { r8-r9 } \n" /* save internal copies of variables back */
"ldr r2, =pcm_play_get_more_callback \n"
"mov r0, r11 \n" /* r0 = &p */
"add r1, r11, #4 \n" /* r1 = &size */
"mov lr, pc \n" /* call pcm_callback_for_more */
"mov lr, pc \n" /* call pcm_play_get_more_callback */
"bx r2 \n"
"ldmia r11, { r8-r9 } \n" /* reload p and size */
"cmp r9, #0 \n" /* did we actually get more data? */
"bne .check_fifo \n"
"ldmia r11, { r8-r9 } \n" /* load new p and size */
"cmp r9, #0 \n"
"bne .check_fifo \n" /* size != 0? refill */
".stop: \n" /* call termination routines */
"ldr r12, =pcm_play_dma_stop \n"
"mov lr, pc \n"
"bx r12 \n"
"ldr r12, =pcm_play_dma_stopped_callback \n"
"mov lr, pc \n"
"bx r12 \n"
".exit: \n" /* (r8=0 if stopping, look above) */
".exit: \n" /* (r9=0 if stopping, look above) */
"stmia r11, { r8-r9 } \n" /* save p and size */
"ldmfd sp!, { r0-r3, lr } \n"
"subs pc, lr, #4 \n" /* FIQ specific return sequence */
@ -284,8 +264,6 @@ void fiq_playback(void) __attribute__((interrupt ("FIQ"))) ICODE_ATTR;
/* NOTE: direct stack use forbidden by GCC stack handling bug for FIQ */
void fiq_playback(void)
{
register pcm_more_callback_type get_more;
#if CONFIG_CPU == PP5002
inl(0xcf001040);
#endif
@ -305,16 +283,11 @@ void fiq_playback(void)
}
/* p is empty, get some more data */
get_more = pcm_callback_for_more;
if (get_more) {
get_more((unsigned char**)&dma_play_data.addr,
&dma_play_data.size);
}
pcm_play_get_more_callback((void **)&dma_play_data.addr,
&dma_play_data.size);
} while (dma_play_data.size);
/* No more data, so disable the FIFO/interrupt */
pcm_play_dma_stop();
pcm_play_dma_stopped_callback();
/* No more data */
}
#endif /* ASM / C selection */
#endif /* CPU_PP502x */
@ -589,7 +562,6 @@ void fiq_record(void) ICODE_ATTR __attribute__((interrupt ("FIQ")));
#if defined(SANSA_C200) || defined(SANSA_E200)
void fiq_record(void)
{
register pcm_more_callback_type2 more_ready;
register int32_t value;
if (audio_channels == 2) {
@ -648,20 +620,13 @@ void fiq_record(void)
}
}
more_ready = pcm_callback_more_ready;
if (more_ready == NULL || more_ready(0) < 0) {
/* Finished recording */
pcm_rec_dma_stop();
pcm_rec_dma_stopped_callback();
}
pcm_rec_more_ready_callback(0, (void *)&dma_rec_data.addr,
&dma_rec_data.size);
}
#else
void fiq_record(void)
{
register pcm_more_callback_type2 more_ready;
while (dma_rec_data.size > 0) {
if (IIS_RX_FULL_COUNT < 2) {
return;
@ -676,24 +641,12 @@ void fiq_record(void)
dma_rec_data.size -= 4;
}
more_ready = pcm_callback_more_ready;
if (more_ready == NULL || more_ready(0) < 0) {
/* Finished recording */
pcm_rec_dma_stop();
pcm_rec_dma_stopped_callback();
}
pcm_rec_more_ready_callback(0, (void *)&dma_rec_data.addr,
&dma_rec_data.size);
}
#endif /* SANSA_E200 */
/* Continue transferring data in */
void pcm_rec_dma_record_more(void *start, size_t size)
{
dma_rec_data.addr = (unsigned long)start; /* Start of RX buffer */
dma_rec_data.size = size; /* Bytes to transfer */
}
void pcm_rec_dma_stop(void)
{
/* disable interrupt */

View file

@ -233,12 +233,6 @@ const void * pcm_rec_dma_get_peak_buffer(void)
{
return NULL;
}
void pcm_record_more(void *start, size_t size)
{
(void) start;
(void) size;
}
#endif
#if defined(CPU_TCC77X) || defined(CPU_TCC780X)
@ -289,21 +283,14 @@ void fiq_handler(void)
".more_data: \n"
"stmfd sp!, { r0-r3, lr } \n" /* stack scratch regs and lr */
"ldr r2, =pcm_callback_for_more \n"
"ldr r2, [r2] \n" /* get callback address */
"cmp r2, #0 \n" /* check for null pointer */
"movne r0, r11 \n" /* r0 = &p */
"addne r1, r11, #4 \n" /* r1 = &size */
"blxne r2 \n" /* call pcm_callback_for_more */
"ldmia r11, { r8-r9 } \n" /* reload p and size */
"cmp r9, #0x10 \n" /* did we actually get more data? */
"ldmgefd sp!, { r0-r3, lr } \n"
"bge .fill_fifo \n" /* yes: fill the fifo */
"ldr r12, =pcm_play_dma_stop \n"
"blx r12 \n" /* no: stop playback */
"ldr r12, =pcm_play_dma_stopped_callback \n"
"blx r12 \n"
"ldr r2, =pcm_play_get_more_callback \n"
"mov r0, r11 \n" /* r0 = &p */
"add r1, r11, #4 \n" /* r1 = &size */
"blx r2 \n" /* call pcm_play_get_more_callback */
"ldmia r11, { r8-r9 } \n" /* load new p and size */
"cmp r9, #0x10 \n" /* did we actually get enough data? */
"ldmfd sp!, { r0-r3, lr } \n"
"bpl .fill_fifo \n" /* not stop and enough? refill */
"b .exit \n"
".ltorg \n"
);
@ -315,17 +302,11 @@ void fiq_handler(void)
asm volatile( "stmfd sp!, {r0-r7, ip, lr} \n" /* Store context */
"sub sp, sp, #8 \n"); /* Reserve stack */
register pcm_more_callback_type get_more;
if (dma_play_data.size < 16)
{
/* p is empty, get some more data */
get_more = pcm_callback_for_more;
if (get_more)
{
get_more((unsigned char**)&dma_play_data.p,
&dma_play_data.size);
}
pcm_play_get_more_callback((void**)&dma_play_data.p,
&dma_play_data.size);
}
if (dma_play_data.size >= 16)
@ -341,12 +322,6 @@ void fiq_handler(void)
dma_play_data.size -= 16;
}
else
{
/* No more data, so disable the FIFO/interrupt */
pcm_play_dma_stop();
pcm_play_dma_stopped_callback();
}
/* Clear FIQ status */
CREQ = DAI_TX_IRQ_MASK | DAI_RX_IRQ_MASK;

View file

@ -104,13 +104,10 @@ static inline void fill_dma_buf(int offset)
p = tmp_p;
if (l >= lend)
return;
else if (pcm_callback_for_more)
pcm_callback_for_more((unsigned char**)&p,
&p_size);
pcm_play_get_more_callback((void**)&p, &p_size);
}
while (p_size);
pcm_play_dma_stopped_callback();
}
if (l < lend)

View file

@ -214,35 +214,27 @@ void pcm_play_dma_pause(bool pause)
void fiq_handler(void)
{
static unsigned char *start;
static size_t size;
register pcm_more_callback_type get_more; /* No stack for this */
static void *start;
static size_t size;
/* clear any pending interrupt */
SRCPND = DMA2_MASK;
/* Buffer empty. Try to get more. */
get_more = pcm_callback_for_more;
size = 0;
pcm_play_get_more_callback(&start, &size);
if (get_more == NULL || (get_more(&start, &size), size == 0))
{
/* Callback missing or no more DMA to do */
pcm_play_dma_stop();
pcm_play_dma_stopped_callback();
}
else
{
/* Flush any pending cache writes */
clean_dcache_range(start, size);
if (size == 0)
return;
/* set the new DMA values */
DCON2 = DMA_CONTROL_SETUP | (size >> 1);
DISRC2 = (unsigned int)start + 0x30000000;
/* Flush any pending cache writes */
clean_dcache_range(start, size);
/* Re-Activate the channel */
DMASKTRIG2 = 0x2;
}
/* set the new DMA values */
DCON2 = DMA_CONTROL_SETUP | (size >> 1);
DISRC2 = (unsigned int)start + 0x30000000;
/* Re-Activate the channel */
DMASKTRIG2 = 0x2;
}
size_t pcm_get_bytes_waiting(void)

View file

@ -254,35 +254,27 @@ void pcm_play_dma_pause(bool pause)
void fiq_handler(void)
{
static unsigned char *start;
static size_t size;
register pcm_more_callback_type get_more; /* No stack for this */
static void *start;
static size_t size;
/* clear any pending interrupt */
SRCPND = DMA2_MASK;
/* Buffer empty. Try to get more. */
get_more = pcm_callback_for_more;
size = 0;
pcm_play_get_more_callback(&start, &size);
if (get_more == NULL || (get_more(&start, &size), size == 0))
{
/* Callback missing or no more DMA to do */
pcm_play_dma_stop();
pcm_play_dma_stopped_callback();
}
else
{
/* Flush any pending cache writes */
clean_dcache_range(start, size);
if (size == 0)
return;
/* set the new DMA values */
DCON2 = DMA_CONTROL_SETUP | (size >> 1);
DISRC2 = (unsigned int)start + 0x30000000;
/* Flush any pending cache writes */
clean_dcache_range(start, size);
/* Re-Activate the channel */
DMASKTRIG2 = 0x2;
}
/* set the new DMA values */
DCON2 = DMA_CONTROL_SETUP | (size >> 1);
DISRC2 = (unsigned int)start + 0x30000000;
/* Re-Activate the channel */
DMASKTRIG2 = 0x2;
}
size_t pcm_get_bytes_waiting(void)

View file

@ -102,11 +102,11 @@ static const void* dma_callback(void)
{
if (dmamode)
{
unsigned char *dma_start_addr;
register pcm_more_callback_type get_more = pcm_callback_for_more;
if (get_more)
void *dma_start_addr;
pcm_play_get_more_callback(&dma_start_addr, &nextsize);
if (nextsize != 0)
{
get_more(&dma_start_addr, &nextsize);
if (nextsize >= 4096)
{
dblbufsize = (nextsize >> 4) & ~3;
@ -148,7 +148,6 @@ void fiq_handler(void)
"mov r10, #0x00000400 \n" /* INT_DMA */
"str r10, [r11] \n" /* ACK FIQ */
"stmfd sp!, {r0-r3,lr} \n"
"ldreq r0, =pcm_play_dma_stopped_callback \n"
"ldrne r0, =dma_callback \n"
"mov lr, pc \n"
"bx r0 \n"
@ -225,13 +224,6 @@ void pcm_play_dma_start(const void *addr_in, size_t size)
#endif
/* S3: DMA channel 0 on */
if (!size)
{
register pcm_more_callback_type get_more = pcm_callback_for_more;
if (get_more) get_more(&addr, &size);
else return; /* Nothing to play!? */
}
if (!size) return; /* Nothing to play!? */
clean_dcache();
if (size >= 4096)
{
@ -367,12 +359,6 @@ void pcm_rec_unlock(void)
{
}
void pcm_rec_dma_record_more(void *start, size_t size)
{
(void)start;
(void)size;
}
void pcm_rec_dma_stop(void)
{
}

View file

@ -132,8 +132,6 @@ char buffer[80];
void DSPHINT(void) __attribute__ ((section(".icode")));
void DSPHINT(void)
{
register pcm_more_callback_type get_more; /* No stack for this */
unsigned int i;
IO_INTC_FIQ0 = 1 << 11;
@ -152,16 +150,9 @@ void DSPHINT(void)
case MSG_REFILL:
/* Buffer empty. Try to get more. */
get_more = pcm_callback_for_more;
size = 0;
if (get_more == NULL || (get_more(&start, &size), size == 0))
{
/* Callback missing or no more DMA to do */
pcm_play_dma_stop();
pcm_play_dma_stopped_callback();
}
pcm_play_get_more_callback(&start, &size);
if (size != 0)
{
unsigned long sdem_addr=(unsigned long)start - CONFIG_SDRAM_START;
/* Flush any pending cache writes */

View file

@ -288,13 +288,14 @@ void DMA0(void) __attribute__ ((interrupt_handler, section(".icode")));
void DMA0(void)
{
unsigned long res = DSR0;
void *start;
size_t size;
and_l(~(DMA_EEXT | DMA_INT), &DCR0); /* per request and int OFF */
DSR0 = 1; /* Clear interrupt and errors */
if (res & 0x70)
{
/* Stop on error */
logf("DMA0 err: %02x", res);
#if 0
logf(" SAR0: %08x", SAR0);
@ -303,32 +304,17 @@ void DMA0(void)
logf(" DCR0: %08x", DCR0);
#endif
}
else
/* Force stop on error */
pcm_play_get_more_callback((res & 0x70) ? NULL : &start, &size);
if (size != 0)
{
pcm_more_callback_type get_more = pcm_callback_for_more;
unsigned char *start;
size_t size = 0;
if (get_more)
get_more(&start, &size);
start = (unsigned char *)(((long)start + 3) & ~3);
size &= ~3;
if (size > 0)
{
SAR0 = (unsigned long)start; /* Source address */
BCR0 = size; /* Bytes to transfer */
or_l(DMA_EEXT | DMA_INT, &DCR0); /* per request and int ON */
return;
}
/* Finished playing */
SAR0 = (unsigned long)start; /* Source address */
BCR0 = size; /* Bytes to transfer */
or_l(DMA_EEXT | DMA_INT, &DCR0); /* per request and int ON */
}
/* Stop interrupt and futher transfers */
pcm_play_dma_stop();
/* Inform PCM that we're done */
pcm_play_dma_stopped_callback();
/* else inished playing */
} /* DMA0 */
const void * pcm_play_dma_get_peak_buffer(int *count)
@ -436,7 +422,8 @@ void DMA1(void)
{
unsigned long res = DSR1;
int status = 0;
pcm_more_callback_type2 more_ready;
void *start;
size_t size;
and_l(~(DMA_EEXT | DMA_INT), &DCR1); /* per request and int OFF */
DSR1 = 1; /* Clear interrupt and errors */
@ -465,25 +452,17 @@ void DMA1(void)
}
#endif
more_ready = pcm_callback_more_ready;
/* Inform PCM we have more data (or error) */
pcm_rec_more_ready_callback(status, &start, &size);
if (more_ready != NULL && more_ready(status) >= 0)
return;
/* Finished recording */
pcm_rec_dma_stop();
/* Inform PCM that we're done */
pcm_rec_dma_stopped_callback();
if (size != 0)
{
DAR1 = (unsigned long)start; /* Destination address */
BCR1 = (unsigned long)size; /* Bytes to transfer */
or_l(DMA_EEXT | DMA_INT, &DCR1); /* per request and int ON */
}
} /* DMA1 */
/* Continue transferring data in - call from interrupt callback */
void pcm_rec_dma_record_more(void *start, size_t size)
{
DAR1 = (unsigned long)start; /* Destination address */
BCR1 = (unsigned long)size; /* Bytes to transfer */
or_l(DMA_EEXT | DMA_INT, &DCR1); /* per request and int ON */
} /* pcm_record_more */
const void * pcm_rec_dma_get_peak_buffer(void)
{
return (void *)(DAR1 & ~3);

View file

@ -228,15 +228,9 @@ static void sdl_audio_callback(struct pcm_udata *udata, Uint8 *stream, int len)
/* Audio card wants more? Get some more then. */
while (len > 0) {
if ((ssize_t)pcm_data_size <= 0) {
pcm_data_size = 0;
if (pcm_callback_for_more)
pcm_callback_for_more(&pcm_data, &pcm_data_size);
}
if (pcm_data_size > 0) {
pcm_play_get_more_callback(&pcm_data, &pcm_data_size);
start:
if (pcm_data_size != 0) {
udata->num_in = pcm_data_size / pcm_sample_bytes;
udata->num_out = len / pcm_sample_bytes;
@ -251,8 +245,6 @@ static void sdl_audio_callback(struct pcm_udata *udata, Uint8 *stream, int len)
len -= udata->num_out;
} else {
DEBUGF("sdl_audio_callback: No Data.\n");
pcm_play_dma_stop();
pcm_play_dma_stopped_callback();
break;
}
}
@ -292,12 +284,6 @@ void pcm_rec_dma_stop(void)
{
}
void pcm_rec_dma_record_more(void *start, size_t size)
{
(void)start;
(void)size;
}
unsigned long pcm_rec_status(void)
{
return 0;

View file

@ -100,23 +100,16 @@ static inline void set_dma(const void *addr, size_t size)
static inline void play_dma_callback(void)
{
unsigned char *start = NULL;
size_t size = 0;
unsigned char *start;
size_t size;
if(pcm_callback_for_more)
pcm_callback_for_more(&start, &size);
pcm_play_get_more_callback(&start, &size);
if(LIKELY(size > 0 && start))
if (size != 0)
{
set_dma(start, size);
REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) |= DMAC_DCCSR_EN;
}
else
{
/* Error, callback missing or no more DMA to do */
pcm_play_dma_stop();
pcm_play_dma_stopped_callback();
}
}
void DMA_CALLBACK(DMA_AIC_TX_CHANNEL)(void) __attribute__ ((section(".icode")));
@ -292,10 +285,4 @@ const void * pcm_rec_dma_get_peak_buffer(void)
{
return NULL;
}
void pcm_rec_dma_record_more(void *start, size_t size)
{
(void) start;
(void) size;
}
#endif