1
0
Fork 0
forked from len0rd/rockbox

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, &button_queue,
#endif #endif
bidi_l2v, bidi_l2v,
#ifdef HAVE_LCD_BITMAP
is_diacritic,
#endif
font_get_bits, font_get_bits,
font_load, font_load,
font_get, font_get,
@ -461,6 +464,9 @@ static const struct plugin_api rockbox_api = {
sound_max, sound_max,
sound_unit, sound_unit,
sound_val2phys, sound_val2phys,
#ifdef AUDIOHW_HAVE_EQ
sound_enum_hw_eq_band_setting,
#endif
#ifndef SIMULATOR #ifndef SIMULATOR
mp3_play_data, mp3_play_data,
mp3_play_pause, mp3_play_pause,
@ -491,7 +497,6 @@ static const struct plugin_api rockbox_api = {
pcm_init_recording, pcm_init_recording,
pcm_close_recording, pcm_close_recording,
pcm_record_data, pcm_record_data,
pcm_record_more,
pcm_stop_recording, pcm_stop_recording,
pcm_calculate_rec_peaks, pcm_calculate_rec_peaks,
audio_set_recording_gain, audio_set_recording_gain,
@ -630,7 +635,12 @@ static const struct plugin_api rockbox_api = {
codec_thread_do_callback, codec_thread_do_callback,
codec_load_file, codec_load_file,
get_codec_filename, 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
#endif /* CONFIG_CODEC == SWCODEC */
get_metadata, get_metadata,
mp3info, mp3info,
count_mp3_frames, count_mp3_frames,
@ -711,24 +721,6 @@ static const struct plugin_api rockbox_api = {
appsversion, appsversion,
/* new stuff at the end, sort into place next time /* new stuff at the end, sort into place next time
the API gets incompatible */ 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) 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 */ #define PLUGIN_MAGIC 0x526F634B /* RocK */
/* increase this every time the api struct changes */ /* 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 /* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any backwards compatibility (and please take the opportunity to sort in any
new function which are "waiting" at the end of the function table) */ 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 */ /* plugin return codes */
enum plugin_status { enum plugin_status {
@ -259,6 +259,9 @@ struct plugin_api {
struct event_queue *button_queue; struct event_queue *button_queue;
#endif #endif
unsigned short *(*bidi_l2v)( const unsigned char *str, int orientation ); 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 ); const unsigned char *(*font_get_bits)( struct font *pf, unsigned short char_code );
int (*font_load)(struct font*, const char *path); int (*font_load)(struct font*, const char *path);
struct font* (*font_get)(int font); struct font* (*font_get)(int font);
@ -577,6 +580,10 @@ struct plugin_api {
int (*sound_max)(int setting); int (*sound_max)(int setting);
const char * (*sound_unit)(int setting); const char * (*sound_unit)(int setting);
int (*sound_val2phys)(int setting, int value); 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 #ifndef SIMULATOR
void (*mp3_play_data)(const unsigned char* start, int size, void (*mp3_play_data)(const unsigned char* start, int size,
void (*get_more)(unsigned char** start, size_t* 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 *audio_master_sampr_list;
const unsigned long *hw_freq_sampr; const unsigned long *hw_freq_sampr;
void (*pcm_apply_settings)(void); 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); unsigned char* start, size_t size);
void (*pcm_play_stop)(void); void (*pcm_play_stop)(void);
void (*pcm_set_frequency)(unsigned int frequency); void (*pcm_set_frequency)(unsigned int frequency);
@ -610,9 +617,8 @@ struct plugin_api {
const unsigned long *rec_freq_sampr; const unsigned long *rec_freq_sampr;
void (*pcm_init_recording)(void); void (*pcm_init_recording)(void);
void (*pcm_close_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 *start, size_t size);
void (*pcm_record_more)(void *start, size_t size);
void (*pcm_stop_recording)(void); void (*pcm_stop_recording)(void);
void (*pcm_calculate_rec_peaks)(int *left, int *right); void (*pcm_calculate_rec_peaks)(int *left, int *right);
void (*audio_set_recording_gain)(int left, int right, int type); void (*audio_set_recording_gain)(int left, int right, int type);
@ -774,7 +780,15 @@ struct plugin_api {
unsigned int *audio_thread_id); unsigned int *audio_thread_id);
int (*codec_load_file)(const char* codec, struct codec_api *api); int (*codec_load_file)(const char* codec, struct codec_api *api);
const char *(*get_codec_filename)(int cod_spec); 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
#endif /* CONFIG_CODEC == SWCODEC */
bool (*get_metadata)(struct mp3entry* id3, int fd, const char* trackname); bool (*get_metadata)(struct mp3entry* id3, int fd, const char* trackname);
bool (*mp3info)(struct mp3entry *entry, const char *filename); bool (*mp3info)(struct mp3entry *entry, const char *filename);
int (*count_mp3_frames)(int fd, int startpos, int filesize, int (*count_mp3_frames)(int fd, int startpos, int filesize,
@ -874,28 +888,6 @@ struct plugin_api {
const char *appsversion; const char *appsversion;
/* new stuff at the end, sort into place next time /* new stuff at the end, sort into place next time
the API gets incompatible */ 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 */ /* 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 */ /* Stop the recording when the buffer is full */
#ifndef SIMULATOR #ifndef SIMULATOR
int recording_callback(int status) void recording_callback(int status, void **start, size_t *size)
{ {
int tail = audio_tail ^ 1; int tail = audio_tail ^ 1;
@ -991,10 +991,9 @@ int recording_callback(int status)
audio_tail = tail; audio_tail = tail;
/* Always record full buffer, even if not required */ /* Always record full buffer, even if not required */
rb->pcm_record_more(audio_data[tail], *start = audio_data[tail];
BUFFER_SIZE * sizeof (int16_t)); *size = BUFFER_SIZE * sizeof (int16_t);
return 0;
(void)status; (void)status;
} }
#endif #endif

View file

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

View file

@ -89,7 +89,7 @@ enum voice_thread_messages
/* Structure to store clip data callback info */ /* Structure to store clip data callback info */
struct voice_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 */ unsigned char *start; /* Start of clip */
size_t size; /* Size 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 */ /* Stop any current clip and start playing a new one */
void mp3_play_data(const unsigned char* start, int size, 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 /* Shared struct to get data to the thread - once it replies, it has
* safely cached it in its own private data */ * safely cached it in its own private data */

View file

@ -50,9 +50,9 @@
/** RAW PCM routines used with playback and recording **/ /** RAW PCM routines used with playback and recording **/
/* Typedef for registered callback */ /* 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); 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 /* set the pcm frequency - use values in hw_sampr_list
* use -1 for the default frequency * use -1 for the default frequency
@ -71,7 +71,7 @@ void pcm_init(void);
void pcm_postinit(void); void pcm_postinit(void);
/* This is for playing "raw" PCM data */ /* 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); unsigned char* start, size_t size);
void pcm_calculate_peaks(int *left, int *right); 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- /** The following are for internal use between pcm.c and target-
specific portion **/ 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_curr_sampr;
extern unsigned long pcm_sampr; extern unsigned long pcm_sampr;
extern int pcm_fsel; extern int pcm_fsel;
@ -94,8 +99,6 @@ extern int pcm_fsel;
void * pcm_dma_addr(void *addr); void * pcm_dma_addr(void *addr);
#endif #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_playing;
extern volatile bool pcm_paused; extern volatile bool pcm_paused;
@ -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_start(const void *addr, size_t size);
void pcm_play_dma_stop(void); void pcm_play_dma_stop(void);
void pcm_play_dma_pause(bool pause); void pcm_play_dma_pause(bool pause);
void pcm_play_dma_stopped_callback(void);
const void * pcm_play_dma_get_peak_buffer(int *count); const void * pcm_play_dma_get_peak_buffer(int *count);
void pcm_dma_apply_settings(void); void pcm_dma_apply_settings(void);
@ -124,7 +126,7 @@ void pcm_init_recording(void);
void pcm_close_recording(void); void pcm_close_recording(void);
/* Start recording "raw" PCM data */ /* 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); void *start, size_t size);
/* Stop tranferring data into supplied buffer */ /* Stop tranferring data into supplied buffer */
@ -133,15 +135,14 @@ void pcm_stop_recording(void);
/* Is pcm currently recording? */ /* Is pcm currently recording? */
bool pcm_is_recording(void); bool pcm_is_recording(void);
/* Continue transferring data in - call during interrupt handler */ /* Called by bottom layer ISR when transfer is complete. Returns non-zero
void pcm_record_more(void *start, size_t size); * 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); void pcm_calculate_rec_peaks(int *left, int *right);
/** The following are for internal use between pcm.c and target- /** The following are for internal use between pcm.c and target-
specific portion **/ 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 */ /* DMA transfer in is currently active */
extern volatile bool pcm_recording; extern volatile bool pcm_recording;
@ -151,7 +152,6 @@ void pcm_rec_dma_close(void);
void pcm_rec_dma_start(void *addr, size_t size); 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_record_more(void *start, size_t size);
void pcm_rec_dma_stop(void); void pcm_rec_dma_stop(void);
void pcm_rec_dma_stopped_callback(void);
const void * pcm_rec_dma_get_peak_buffer(void); const void * pcm_rec_dma_get_peak_buffer(void);
#endif /* HAVE_RECORDING */ #endif /* HAVE_RECORDING */

View file

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

View file

@ -74,17 +74,12 @@ static void dma_callback(void)
{ {
if(!dma_size) if(!dma_size)
{ {
register pcm_more_callback_type get_more = pcm_callback_for_more; pcm_play_get_more_callback(&dma_start_addr, &dma_size);
if(get_more)
get_more(&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();
} }
@ -275,31 +270,19 @@ static void rec_dma_callback(void)
if(!rec_dma_size) if(!rec_dma_size)
{ {
register pcm_more_callback_type2 more_ready = pcm_callback_more_ready; pcm_rec_more_ready_callback(0, &rec_dma_start_addr, &rec_dma_size);
if (!more_ready || more_ready(0) < 0)
if(rec_dma_size != 0)
{ {
/* Finished recording */ dump_dcache_range(rec_dma_start_addr, rec_dma_size);
pcm_rec_dma_stop();
pcm_rec_dma_stopped_callback();
return;
}
}
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 #if CONFIG_CPU == AS3525
mono_samples = AS3525_UNCACHED_ADDR(start); mono_samples = AS3525_UNCACHED_ADDR(rec_dma_start_addr);
#endif #endif
rec_dma_size = size; rec_dma_start();
}
}
} }
void pcm_rec_dma_stop(void) void pcm_rec_dma_stop(void)
{ {
dma_disable_channel(1); dma_disable_channel(1);

View file

@ -52,9 +52,9 @@ static struct dma_data dma_play_data =
static void play_dma_callback(void) static void play_dma_callback(void)
{ {
unsigned char *start; void *start;
size_t size = 0; size_t size;
pcm_more_callback_type get_more = pcm_callback_for_more; bool rror;
if (dma_play_data.locked != 0) if (dma_play_data.locked != 0)
{ {
@ -63,14 +63,12 @@ static void play_dma_callback(void)
return; return;
} }
if (dma_play_bd.mode.status & BD_RROR) rror = dma_play_bd.mode.status & BD_RROR;
{
/* Stop on error */ pcm_play_get_more_callback(rror ? NULL : &start, &size);
}
else if (get_more != NULL && (get_more(&start, &size), size != 0)) if (size == 0)
{ return;
start = (void*)(((unsigned long)start + 3) & ~3);
size &= ~3;
/* Flush any pending cache writes */ /* Flush any pending cache writes */
clean_dcache_range(start, size); clean_dcache_range(start, size);
@ -79,12 +77,6 @@ static void play_dma_callback(void)
dma_play_bd.mode.command = TRANSFER_16BIT; dma_play_bd.mode.command = TRANSFER_16BIT;
dma_play_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR; dma_play_bd.mode.status = BD_DONE | BD_WRAP | BD_INTR;
sdma_channel_run(DMA_PLAY_CH_NUM); sdma_channel_run(DMA_PLAY_CH_NUM);
return;
}
/* Error, callback missing or no more DMA to do */
pcm_play_dma_stop();
pcm_play_dma_stopped_callback();
} }
void pcm_play_lock(void) 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_STCR2 &= ~SSI_STCR_TFEN0;
SSI_SCR2 &= ~(SSI_SCR_TE | SSI_SCR_SSIEN); 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)) if (!sdma_channel_reset(DMA_PLAY_CH_NUM))
return; return;
@ -383,8 +369,9 @@ static struct dma_data dma_rec_data =
static void rec_dma_callback(void) static void rec_dma_callback(void)
{ {
pcm_more_callback_type2 more_ready;
int status = 0; int status = 0;
void *start;
size_t size;
if (dma_rec_data.locked != 0) if (dma_rec_data.locked != 0)
{ {
@ -395,17 +382,22 @@ static void rec_dma_callback(void)
if (dma_rec_bd.mode.status & BD_RROR) if (dma_rec_bd.mode.status & BD_RROR)
status = DMA_REC_ERROR_DMA; 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) if (size == 0)
{
sdma_channel_run(DMA_REC_CH_NUM);
return; return;
}
/* Finished recording */ /* Invalidate - buffer must be coherent */
pcm_rec_dma_stop(); dump_dcache_range(start, size);
pcm_rec_dma_stopped_callback();
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) 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) void pcm_rec_dma_stop(void)
{ {
/* Stop receiving data */ /* 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 */ /* NOTE: direct stack use forbidden by GCC stack handling bug for FIQ */
void ICODE_ATTR __attribute__((interrupt("FIQ"))) fiq_playback(void) void ICODE_ATTR __attribute__((interrupt("FIQ"))) fiq_playback(void)
{ {
register pcm_more_callback_type get_more;
register size_t size; register size_t size;
DMA0_STATUS; /* Clear any pending interrupt */ 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. */ /* Buffer empty. Try to get more. */
get_more = pcm_callback_for_more; pcm_play_get_more_callback((void **)&dma_play_data.addr,
if (get_more) { &dma_play_data.size);
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;
}
if (dma_play_data.size == 0) { if (dma_play_data.size == 0) {
break; /* No more data */
return;
} }
if (dma_play_data.addr < UNCACHED_BASE_ADDR) { if (dma_play_data.addr < UNCACHED_BASE_ADDR) {
@ -158,10 +154,6 @@ void ICODE_ATTR __attribute__((interrupt("FIQ"))) fiq_playback(void)
cpucache_flush(); cpucache_flush();
} }
} }
/* Callback missing or no more DMA to do */
pcm_play_dma_stop();
pcm_play_dma_stopped_callback();
} }
#else #else
/* ASM optimised FIQ handler. Checks for the minimum allowed loop cycles by /* ASM optimised FIQ handler. Checks for the minimum allowed loop cycles by
@ -247,28 +239,16 @@ void fiq_playback(void)
#endif #endif
".more_data: \n" ".more_data: \n"
"ldr r2, =pcm_callback_for_more \n" "ldr r2, =pcm_play_get_more_callback \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 */
"mov r0, r11 \n" /* r0 = &p */ "mov r0, r11 \n" /* r0 = &p */
"add r1, r11, #4 \n" /* r1 = &size */ "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" "bx r2 \n"
"ldmia r11, { r8-r9 } \n" /* reload p and size */ "ldmia r11, { r8-r9 } \n" /* load new p and size */
"cmp r9, #0 \n" /* did we actually get more data? */ "cmp r9, #0 \n"
"bne .check_fifo \n" "bne .check_fifo \n" /* size != 0? refill */
".stop: \n" /* call termination routines */ ".exit: \n" /* (r9=0 if stopping, look above) */
"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) */
"stmia r11, { r8-r9 } \n" /* save p and size */ "stmia r11, { r8-r9 } \n" /* save p and size */
"ldmfd sp!, { r0-r3, lr } \n" "ldmfd sp!, { r0-r3, lr } \n"
"subs pc, lr, #4 \n" /* FIQ specific return sequence */ "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 */ /* NOTE: direct stack use forbidden by GCC stack handling bug for FIQ */
void fiq_playback(void) void fiq_playback(void)
{ {
register pcm_more_callback_type get_more;
#if CONFIG_CPU == PP5002 #if CONFIG_CPU == PP5002
inl(0xcf001040); inl(0xcf001040);
#endif #endif
@ -305,16 +283,11 @@ void fiq_playback(void)
} }
/* p is empty, get some more data */ /* p is empty, get some more data */
get_more = pcm_callback_for_more; pcm_play_get_more_callback((void **)&dma_play_data.addr,
if (get_more) {
get_more((unsigned char**)&dma_play_data.addr,
&dma_play_data.size); &dma_play_data.size);
}
} while (dma_play_data.size); } while (dma_play_data.size);
/* No more data, so disable the FIFO/interrupt */ /* No more data */
pcm_play_dma_stop();
pcm_play_dma_stopped_callback();
} }
#endif /* ASM / C selection */ #endif /* ASM / C selection */
#endif /* CPU_PP502x */ #endif /* CPU_PP502x */
@ -589,7 +562,6 @@ void fiq_record(void) ICODE_ATTR __attribute__((interrupt ("FIQ")));
#if defined(SANSA_C200) || defined(SANSA_E200) #if defined(SANSA_C200) || defined(SANSA_E200)
void fiq_record(void) void fiq_record(void)
{ {
register pcm_more_callback_type2 more_ready;
register int32_t value; register int32_t value;
if (audio_channels == 2) { if (audio_channels == 2) {
@ -648,20 +620,13 @@ void fiq_record(void)
} }
} }
more_ready = pcm_callback_more_ready; pcm_rec_more_ready_callback(0, (void *)&dma_rec_data.addr,
&dma_rec_data.size);
if (more_ready == NULL || more_ready(0) < 0) {
/* Finished recording */
pcm_rec_dma_stop();
pcm_rec_dma_stopped_callback();
}
} }
#else #else
void fiq_record(void) void fiq_record(void)
{ {
register pcm_more_callback_type2 more_ready;
while (dma_rec_data.size > 0) { while (dma_rec_data.size > 0) {
if (IIS_RX_FULL_COUNT < 2) { if (IIS_RX_FULL_COUNT < 2) {
return; return;
@ -676,24 +641,12 @@ void fiq_record(void)
dma_rec_data.size -= 4; dma_rec_data.size -= 4;
} }
more_ready = pcm_callback_more_ready; pcm_rec_more_ready_callback(0, (void *)&dma_rec_data.addr,
&dma_rec_data.size);
if (more_ready == NULL || more_ready(0) < 0) {
/* Finished recording */
pcm_rec_dma_stop();
pcm_rec_dma_stopped_callback();
}
} }
#endif /* SANSA_E200 */ #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) void pcm_rec_dma_stop(void)
{ {
/* disable interrupt */ /* disable interrupt */

View file

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

View file

@ -214,25 +214,18 @@ void pcm_play_dma_pause(bool pause)
void fiq_handler(void) void fiq_handler(void)
{ {
static unsigned char *start; static void *start;
static size_t size; static size_t size;
register pcm_more_callback_type get_more; /* No stack for this */
/* clear any pending interrupt */ /* clear any pending interrupt */
SRCPND = DMA2_MASK; SRCPND = DMA2_MASK;
/* Buffer empty. Try to get more. */ /* Buffer empty. Try to get more. */
get_more = pcm_callback_for_more; pcm_play_get_more_callback(&start, &size);
size = 0;
if (size == 0)
return;
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 */ /* Flush any pending cache writes */
clean_dcache_range(start, size); clean_dcache_range(start, size);
@ -242,7 +235,6 @@ void fiq_handler(void)
/* Re-Activate the channel */ /* Re-Activate the channel */
DMASKTRIG2 = 0x2; DMASKTRIG2 = 0x2;
}
} }
size_t pcm_get_bytes_waiting(void) size_t pcm_get_bytes_waiting(void)

View file

@ -254,25 +254,18 @@ void pcm_play_dma_pause(bool pause)
void fiq_handler(void) void fiq_handler(void)
{ {
static unsigned char *start; static void *start;
static size_t size; static size_t size;
register pcm_more_callback_type get_more; /* No stack for this */
/* clear any pending interrupt */ /* clear any pending interrupt */
SRCPND = DMA2_MASK; SRCPND = DMA2_MASK;
/* Buffer empty. Try to get more. */ /* Buffer empty. Try to get more. */
get_more = pcm_callback_for_more; pcm_play_get_more_callback(&start, &size);
size = 0;
if (size == 0)
return;
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 */ /* Flush any pending cache writes */
clean_dcache_range(start, size); clean_dcache_range(start, size);
@ -282,7 +275,6 @@ void fiq_handler(void)
/* Re-Activate the channel */ /* Re-Activate the channel */
DMASKTRIG2 = 0x2; DMASKTRIG2 = 0x2;
}
} }
size_t pcm_get_bytes_waiting(void) size_t pcm_get_bytes_waiting(void)

View file

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

View file

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

View file

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

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. */ /* Audio card wants more? Get some more then. */
while (len > 0) { while (len > 0) {
if ((ssize_t)pcm_data_size <= 0) { pcm_play_get_more_callback(&pcm_data, &pcm_data_size);
pcm_data_size = 0;
if (pcm_callback_for_more)
pcm_callback_for_more(&pcm_data, &pcm_data_size);
}
if (pcm_data_size > 0) {
start: start:
if (pcm_data_size != 0) {
udata->num_in = pcm_data_size / pcm_sample_bytes; udata->num_in = pcm_data_size / pcm_sample_bytes;
udata->num_out = len / 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; len -= udata->num_out;
} else { } else {
DEBUGF("sdl_audio_callback: No Data.\n"); DEBUGF("sdl_audio_callback: No Data.\n");
pcm_play_dma_stop();
pcm_play_dma_stopped_callback();
break; 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) unsigned long pcm_rec_status(void)
{ {
return 0; 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) static inline void play_dma_callback(void)
{ {
unsigned char *start = NULL; unsigned char *start;
size_t size = 0; size_t size;
if(pcm_callback_for_more) pcm_play_get_more_callback(&start, &size);
pcm_callback_for_more(&start, &size);
if(LIKELY(size > 0 && start)) if (size != 0)
{ {
set_dma(start, size); set_dma(start, size);
REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) |= DMAC_DCCSR_EN; 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"))); 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; return NULL;
} }
void pcm_rec_dma_record_more(void *start, size_t size)
{
(void) start;
(void) size;
}
#endif #endif