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

@ -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 */