summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2010-05-24 16:42:32 +0000
committerMichael Sevakis <jethead71@rockbox.org>2010-05-24 16:42:32 +0000
commitd56999890f2aacf197d9ae4383313271499509a9 (patch)
tree76a0177e2cf19bb15a065199b812ef20158422e1 /firmware
parent6688988ec42aa2254c8e370ec1932033a258b6fa (diff)
downloadrockbox-d56999890f2aacf197d9ae4383313271499509a9.tar.gz
rockbox-d56999890f2aacf197d9ae4383313271499509a9.tar.bz2
rockbox-d56999890f2aacf197d9ae4383313271499509a9.zip
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
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/pcm.h30
-rw-r--r--firmware/pcm.c150
-rw-r--r--firmware/target/arm/as3525/pcm-as3525.c43
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c81
-rw-r--r--firmware/target/arm/pcm-pp.c83
-rw-r--r--firmware/target/arm/pcm-telechips.c43
-rw-r--r--firmware/target/arm/pnx0101/pcm-pnx0101.c7
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c34
-rw-r--r--firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c34
-rw-r--r--firmware/target/arm/s5l8700/pcm-s5l8700.c22
-rw-r--r--firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c15
-rw-r--r--firmware/target/coldfire/pcm-coldfire.c63
-rw-r--r--firmware/target/hosted/sdl/pcm-sdl.c18
-rw-r--r--firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c21
14 files changed, 239 insertions, 405 deletions
diff --git a/firmware/export/pcm.h b/firmware/export/pcm.h
index 0d2d39b03d..40bfe6fa46 100644
--- a/firmware/export/pcm.h
+++ b/firmware/export/pcm.h
@@ -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 */
diff --git a/firmware/pcm.c b/firmware/pcm.c
index a69f0a8232..8080823077 100644
--- a/firmware/pcm.c
+++ b/firmware/pcm.c
@@ -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;
-
- if (!size)
- {
- pcm_rec_dma_stop();
- pcm_rec_dma_stopped_callback();
- return;
- }
+ pcm_rec_callback_type have_more = pcm_callback_more_ready;
-#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
+ *size = 0;
- pcm_rec_dma_record_more(start, size);
-}
+ if (have_more && start)
+ {
+ have_more(status, start, size);
+ *start = (void *)(((uintptr_t)*start + 3) & ~3);
+ *size &= ~3;
-bool pcm_is_recording(void)
-{
- return pcm_recording;
-}
+ 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;
+ }
+ }
-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 */
diff --git a/firmware/target/arm/as3525/pcm-as3525.c b/firmware/target/arm/as3525/pcm-as3525.c
index cefca0fbe5..a2e3cfbf9f 100644
--- a/firmware/target/arm/as3525/pcm-as3525.c
+++ b/firmware/target/arm/as3525/pcm-as3525.c
@@ -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)
- {
- pcm_play_dma_stop();
- pcm_play_dma_stopped_callback();
+ if (!dma_size)
+ return;
}
- 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)
- {
- /* Finished recording */
- pcm_rec_dma_stop();
- pcm_rec_dma_stopped_callback();
- return;
- }
- }
-
- rec_dma_start();
-}
-
+ pcm_rec_more_ready_callback(0, &rec_dma_start_addr, &rec_dma_size);
-void pcm_rec_dma_record_more(void *start, size_t size)
-{
- dump_dcache_range(start, size);
- rec_dma_start_addr = start;
+ if(rec_dma_size != 0)
+ {
+ dump_dcache_range(rec_dma_start_addr, rec_dma_size);
#if CONFIG_CPU == AS3525
- mono_samples = AS3525_UNCACHED_ADDR(start);
+ mono_samples = AS3525_UNCACHED_ADDR(rec_dma_start_addr);
#endif
- rec_dma_size = size;
+ rec_dma_start();
+ }
+ }
}
-
void pcm_rec_dma_stop(void)
{
dma_disable_channel(1);
diff --git a/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c
index 02051fad90..2c65c70360 100644
--- a/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c
+++ b/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c
@@ -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;
-
- /* 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);
+ rror = dma_play_bd.mode.status & BD_RROR;
+
+ 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 */
diff --git a/firmware/target/arm/pcm-pp.c b/firmware/target/arm/pcm-pp.c
index e0b603c81f..6289b4c730 100644
--- a/firmware/target/arm/pcm-pp.c
+++ b/firmware/target/arm/pcm-pp.c
@@ -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"
-
- ".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) */
+ "ldmia r11, { r8-r9 } \n" /* load new p and size */
+ "cmp r9, #0 \n"
+ "bne .check_fifo \n" /* size != 0? refill */
+
+ ".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 */
diff --git a/firmware/target/arm/pcm-telechips.c b/firmware/target/arm/pcm-telechips.c
index 3ce038ffcd..d718ca38ac 100644
--- a/firmware/target/arm/pcm-telechips.c
+++ b/firmware/target/arm/pcm-telechips.c
@@ -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;
diff --git a/firmware/target/arm/pnx0101/pcm-pnx0101.c b/firmware/target/arm/pnx0101/pcm-pnx0101.c
index fe1e05b79a..9d4ffbd773 100644
--- a/firmware/target/arm/pnx0101/pcm-pnx0101.c
+++ b/firmware/target/arm/pnx0101/pcm-pnx0101.c
@@ -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)
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
index bb1b2d9eaa..e9f55479c7 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
@@ -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)
diff --git a/firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c b/firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c
index 486a235614..30db29c42c 100644
--- a/firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c
+++ b/firmware/target/arm/s3c2440/mini2440/pcm-mini2440.c
@@ -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)
diff --git a/firmware/target/arm/s5l8700/pcm-s5l8700.c b/firmware/target/arm/s5l8700/pcm-s5l8700.c
index 7798f41d11..4d24b327af 100644
--- a/firmware/target/arm/s5l8700/pcm-s5l8700.c
+++ b/firmware/target/arm/s5l8700/pcm-s5l8700.c
@@ -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)
{
}
diff --git a/firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c b/firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c
index ab3ceba0f3..d7d8f92a0c 100644
--- a/firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c
+++ b/firmware/target/arm/tms320dm320/mrobe-500/pcm-mr500.c
@@ -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 */
diff --git a/firmware/target/coldfire/pcm-coldfire.c b/firmware/target/coldfire/pcm-coldfire.c
index f9c0764d64..06f17d1170 100644
--- a/firmware/target/coldfire/pcm-coldfire.c
+++ b/firmware/target/coldfire/pcm-coldfire.c
@@ -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;
-
- if (more_ready != NULL && more_ready(status) >= 0)
- return;
+ /* Inform PCM we have more data (or error) */
+ pcm_rec_more_ready_callback(status, &start, &size);
- /* 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);
diff --git a/firmware/target/hosted/sdl/pcm-sdl.c b/firmware/target/hosted/sdl/pcm-sdl.c
index ee92fa208d..03e6e1336c 100644
--- a/firmware/target/hosted/sdl/pcm-sdl.c
+++ b/firmware/target/hosted/sdl/pcm-sdl.c
@@ -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;
diff --git a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c
index 993f70bad8..4cf43471eb 100644
--- a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c
@@ -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