diff --git a/firmware/export/config/gigabeats.h b/firmware/export/config/gigabeats.h index 2e489239b9..19a8fa4bf8 100644 --- a/firmware/export/config/gigabeats.h +++ b/firmware/export/config/gigabeats.h @@ -220,6 +220,7 @@ /* #define HAVE_ADJUSTABLE_CPU_FREQ */ #define HAVE_PCM_DMA_ADDRESS +#define HAVE_PCM_REC_DMA_ADDRESS #define BOOTFILE_EXT "gigabeat" #define BOOTFILE "rockbox." BOOTFILE_EXT diff --git a/firmware/export/pcm.h b/firmware/export/pcm.h index 0f8222f90d..0e71814b34 100644 --- a/firmware/export/pcm.h +++ b/firmware/export/pcm.h @@ -140,7 +140,6 @@ void pcm_calculate_rec_peaks(int *left, int *right); /** The following are for internal use between pcm.c and target- specific portion **/ -extern volatile const void *pcm_rec_peak_addr; /* 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 */ @@ -150,9 +149,10 @@ extern volatile bool pcm_recording; void pcm_rec_dma_init(void); 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(int *count); +const void * pcm_rec_dma_get_peak_buffer(void); #endif /* HAVE_RECORDING */ diff --git a/firmware/pcm.c b/firmware/pcm.c index edd4113677..8d2ec2bf60 100644 --- a/firmware/pcm.c +++ b/firmware/pcm.c @@ -40,7 +40,6 @@ * pcm_play_unlock * Semi-private - * pcm_play_dma_init - * pcm_play_dma_init * pcm_play_dma_start * pcm_play_dma_stop * pcm_play_dma_pause @@ -66,10 +65,10 @@ * 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_rec_peak_addr (R/W) * pcm_callback_more_ready (R) * pcm_recording (R) * @@ -210,6 +209,9 @@ void pcm_init(void) /* Common code to pcm_play_data and pcm_play_pause */ static void pcm_play_data_start(unsigned char *start, size_t size) { + start = (unsigned char *)(((uintptr_t)start + 3) & ~3); + size &= ~3; + if (!(start && size)) { pcm_more_callback_type get_more = pcm_callback_for_more; @@ -218,6 +220,9 @@ static void pcm_play_data_start(unsigned char *start, size_t size) { logf(" get_more"); get_more(&start, &size); + + start = (unsigned char *)(((uintptr_t)start + 3) & ~3); + size &= ~3; } } @@ -359,7 +364,7 @@ bool pcm_is_paused(void) /** Low level pcm recording apis **/ /* Next start for recording peaks */ -const volatile void *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 */ volatile pcm_more_callback_type2 pcm_callback_more_ready SHAREDBSS_ATTR = NULL; @@ -373,17 +378,23 @@ volatile bool pcm_recording SHAREDBSS_ATTR = false; void pcm_calculate_rec_peaks(int *left, int *right) { static int peaks[2]; - int count; - const void *addr = pcm_rec_dma_get_peak_buffer(&count); if (pcm_recording) { - if (count > 0) - { - pcm_peak_peeker(addr, count, peaks); + const void *peak_addr = pcm_rec_peak_addr; + const void *addr = pcm_rec_dma_get_peak_buffer(); - if (addr == pcm_rec_peak_addr) - pcm_rec_peak_addr = (int32_t *)addr + count; + if (addr != NULL) + { + int count = (int)(((intptr_t)addr - (intptr_t)peak_addr) >> 2); + + if (count > 0) + { + pcm_peak_peeker(peak_addr, count, peaks); + + if (peak_addr == pcm_rec_peak_addr) + pcm_rec_peak_addr = addr; + } } /* else keep previous peak values */ } @@ -443,6 +454,10 @@ void pcm_record_data(pcm_more_callback_type2 more_ready, { logf("pcm_record_data"); + /* 32-bit aligned and sized data only */ + start = (void *)(((uintptr_t)start + 3) & ~3); + size &= ~3; + if (!(start && size)) { logf(" no buffer"); @@ -453,6 +468,13 @@ void pcm_record_data(pcm_more_callback_type2 more_ready, pcm_callback_more_ready = 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 + logf(" pcm_rec_dma_start"); pcm_apply_settings(); pcm_rec_dma_start(start, size); @@ -477,6 +499,28 @@ void pcm_stop_recording(void) pcm_rec_unlock(); } /* pcm_stop_recording */ +void pcm_record_more(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; + } + +#ifdef HAVE_PCM_REC_DMA_ADDRESS + /* Need a physical DMA address translation, if not already physical. */ + pcm_rec_peak_addr = pcm_dma_addr(start); +#else + pcm_rec_peak_addr = start; +#endif + + pcm_rec_dma_record_more(start, size); +} + bool pcm_is_recording(void) { return pcm_recording; diff --git a/firmware/target/arm/as3525/pcm-as3525.c b/firmware/target/arm/as3525/pcm-as3525.c index 53a3f0c9a3..4d78899398 100644 --- a/firmware/target/arm/as3525/pcm-as3525.c +++ b/firmware/target/arm/as3525/pcm-as3525.c @@ -202,7 +202,7 @@ void pcm_rec_unlock(void) } -void pcm_record_more(void *start, size_t size) +void pcm_rec_dma_record_more(void *start, size_t size) { rec_start_addr = start; rec_size = size; @@ -331,16 +331,9 @@ void pcm_rec_dma_init(void) } -const void * pcm_rec_dma_get_peak_buffer(int *count) +const void * pcm_rec_dma_get_peak_buffer(void) { - const void *peak_buffer; - - pcm_rec_lock(); - *count = rec_size >> 2; - peak_buffer = (const void*)rec_start_addr; - pcm_rec_unlock(); - - return peak_buffer; + return (const void*)rec_start_addr; } #endif /* HAVE_RECORDING */ 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 c0651caf51..02051fad90 100644 --- a/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c +++ b/firmware/target/arm/imx31/gigabeat-s/pcm-gigabeat-s.c @@ -432,17 +432,13 @@ void pcm_rec_unlock(void) } } -void pcm_record_more(void *start, size_t size) +void pcm_rec_dma_record_more(void *start, size_t size) { - start = (void *)(((unsigned long)start + 3) & ~3); - size &= ~3; - /* Invalidate - buffer must be coherent */ dump_dcache_range(start, size); start = (void *)addr_virt_to_phys((unsigned long)start); - pcm_rec_peak_addr = start; dma_rec_bd.buf_addr = start; dma_rec_bd.mode.count = size; dma_rec_bd.mode.command = TRANSFER_16BIT; @@ -469,12 +465,6 @@ void pcm_rec_dma_start(void *addr, size_t size) { pcm_rec_dma_stop(); - addr = (void *)(((unsigned long)addr + 3) & ~3); - size &= ~3; - - if (size <= 0) - return; - if (!sdma_channel_reset(DMA_REC_CH_NUM)) return; @@ -482,7 +472,6 @@ void pcm_rec_dma_start(void *addr, size_t size) dump_dcache_range(addr, size); addr = (void *)addr_virt_to_phys((unsigned long)addr); - pcm_rec_peak_addr = addr; dma_rec_bd.buf_addr = addr; dma_rec_bd.mode.count = size; dma_rec_bd.mode.command = TRANSFER_16BIT; @@ -524,10 +513,10 @@ void pcm_rec_dma_init(void) sdma_channel_set_priority(DMA_REC_CH_NUM, DMA_REC_CH_PRIORITY); } -const void * pcm_rec_dma_get_peak_buffer(int *count) +const void * pcm_rec_dma_get_peak_buffer(void) { static unsigned long pda NOCACHEBSS_ATTR; - unsigned long buf, addr, end, bufend; + unsigned long buf, end, bufend; int oldstatus; /* read burst dma destination address register in channel context */ @@ -536,19 +525,13 @@ const void * pcm_rec_dma_get_peak_buffer(int *count) oldstatus = disable_irq_save(); end = pda; buf = (unsigned long)dma_rec_bd.buf_addr; - addr = (unsigned long)pcm_rec_peak_addr; bufend = buf + dma_rec_bd.mode.count; restore_irq(oldstatus); /* Be addresses are coherent (no buffer change during read) */ - if (addr >= buf && addr < bufend && - end >= buf && end < bufend) - { - *count = (end >> 2) - (addr >> 2); - return (void *)(addr & ~3); - } + if (end >= buf && end < bufend) + return (void *)(end & ~3); - *count = 0; return NULL; } diff --git a/firmware/target/arm/pcm-pp.c b/firmware/target/arm/pcm-pp.c index bd12b13032..bad3f593fe 100644 --- a/firmware/target/arm/pcm-pp.c +++ b/firmware/target/arm/pcm-pp.c @@ -431,9 +431,6 @@ static void play_stop_pcm(void) void pcm_play_dma_start(const void *addr, size_t size) { - addr = (void *)(((long)addr + 2) & ~3); - size &= ~3; - #if NUM_CORES > 1 /* This will become more important later - and different ! */ dma_play_data.core = processor_id(); /* save initiating core */ @@ -441,9 +438,6 @@ void pcm_play_dma_start(const void *addr, size_t size) pcm_play_dma_stop(); - if (size == 0) - return; - #ifdef CPU_PP502x if ((unsigned long)addr < UNCACHED_BASE_ADDR) { /* Flush any pending cache writes */ @@ -691,9 +685,8 @@ void fiq_record(void) #endif /* SANSA_E200 */ /* Continue transferring data in */ -void pcm_record_more(void *start, size_t size) +void pcm_rec_dma_record_more(void *start, size_t size) { - pcm_rec_peak_addr = start; /* Start peaking at dest */ dma_rec_data.addr = (unsigned long)start; /* Start of RX buffer */ dma_rec_data.size = size; /* Bytes to transfer */ } @@ -718,7 +711,6 @@ void pcm_rec_dma_start(void *addr, size_t size) { pcm_rec_dma_stop(); - pcm_rec_peak_addr = addr; dma_rec_data.addr = (unsigned long)addr; dma_rec_data.size = size; #if NUM_CORES > 1 @@ -749,17 +741,9 @@ void pcm_rec_dma_init(void) pcm_rec_dma_stop(); } /* pcm_init */ -const void * pcm_rec_dma_get_peak_buffer(int *count) +const void * pcm_rec_dma_get_peak_buffer(void) { - unsigned long addr, end; - - int status = disable_fiq_save(); - addr = (unsigned long)pcm_rec_peak_addr; - end = dma_rec_data.addr; - restore_fiq(status); - - *count = (end >> 2) - (addr >> 2); - return (void *)(addr & ~3); + return (void *)((unsigned long)dma_rec_data.addr & ~3); } /* pcm_rec_dma_get_peak_buffer */ #endif /* HAVE_RECORDING */ diff --git a/firmware/target/arm/pcm-telechips.c b/firmware/target/arm/pcm-telechips.c index f0ef667d4f..9d14fa5ed5 100644 --- a/firmware/target/arm/pcm-telechips.c +++ b/firmware/target/arm/pcm-telechips.c @@ -141,8 +141,8 @@ static void play_stop_pcm(void) void pcm_play_dma_start(const void *addr, size_t size) { - dma_play_data.p = (void *)(((uintptr_t)addr + 2) & ~3); - dma_play_data.size = (size & ~3); + dma_play_data.p = addr; + dma_play_data.size = size; #if NUM_CORES > 1 /* This will become more important later - and different ! */ @@ -229,9 +229,8 @@ void pcm_rec_unlock(void) { } -const void * pcm_rec_dma_get_peak_buffer(int *count) +const void * pcm_rec_dma_get_peak_buffer(void) { - *count = 0; return NULL; } diff --git a/firmware/target/arm/s5l8700/pcm-s5l8700.c b/firmware/target/arm/s5l8700/pcm-s5l8700.c index 1edb05fd15..7798f41d11 100644 --- a/firmware/target/arm/s5l8700/pcm-s5l8700.c +++ b/firmware/target/arm/s5l8700/pcm-s5l8700.c @@ -367,7 +367,7 @@ void pcm_rec_unlock(void) { } -void pcm_record_more(void *start, size_t size) +void pcm_rec_dma_record_more(void *start, size_t size) { (void)start; (void)size; @@ -393,9 +393,9 @@ void pcm_rec_dma_init(void) } -const void * pcm_rec_dma_get_peak_buffer(int *count) +const void * pcm_rec_dma_get_peak_buffer(void) { - (void)count; + return NULL; } #endif /* HAVE_RECORDING */ diff --git a/firmware/target/coldfire/pcm-coldfire.c b/firmware/target/coldfire/pcm-coldfire.c index 209d227187..f9c0764d64 100644 --- a/firmware/target/coldfire/pcm-coldfire.c +++ b/firmware/target/coldfire/pcm-coldfire.c @@ -235,12 +235,6 @@ void pcm_play_dma_start(const void *addr, size_t size) /* Stop any DMA in progress */ pcm_play_dma_stop(); - addr = (void *)(((long)addr + 3) & ~3); - size &= ~3; - - if (size <= 0) - return; - /* Set up DMA transfer */ SAR0 = (unsigned long)addr; /* Source address */ DAR0 = (unsigned long)&PDOR3; /* Destination address */ @@ -382,12 +376,6 @@ void pcm_rec_dma_start(void *addr, size_t size) /* stop any DMA in progress */ pcm_rec_dma_stop(); - addr = (void *)(((long)addr + 3) & ~3); - size &= ~3; - - if (size <= 0) - return; - and_l(~PDIR2_FIFO_RESET, &DATAINCONTROL); /* Start the DMA transfer.. */ @@ -396,7 +384,6 @@ void pcm_rec_dma_start(void *addr, size_t size) INTERRUPTCLEAR = (1 << 25) | (1 << 24) | (1 << 23) | (1 << 22); #endif - pcm_rec_peak_addr = (unsigned long *)addr; /* Start peaking at dest */ SAR1 = (unsigned long)&PDIR2; /* Source address */ DAR1 = (unsigned long)addr; /* Destination address */ BCR1 = (unsigned long)size; /* Bytes to transfer */ @@ -490,30 +477,15 @@ void DMA1(void) } /* DMA1 */ /* Continue transferring data in - call from interrupt callback */ -void pcm_record_more(void *start, size_t size) +void pcm_rec_dma_record_more(void *start, size_t size) { - start = (void *)(((long)start + 3) & ~3); - size &= ~3; - - pcm_rec_peak_addr = (unsigned long *)start; /* Start peaking at dest */ 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(int *count) +const void * pcm_rec_dma_get_peak_buffer(void) { - unsigned long addr, end; - - /* Make sure interrupt doesn't change the second value after we read the - * first value. */ - int level = set_irq_level(DMA_IRQ_LEVEL); - addr = (unsigned long)pcm_rec_peak_addr; - end = DAR1; - restore_irq(level); - - addr >>= 2; - *count = (end >> 2) - addr; - return (void *)(addr << 2); + return (void *)(DAR1 & ~3); } /* pcm_rec_dma_get_peak_buffer */ #endif diff --git a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c index a4ecd0b786..993f70bad8 100644 --- a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c @@ -288,13 +288,12 @@ void pcm_rec_unlock(void) { } -const void * pcm_rec_dma_get_peak_buffer(int *count) +const void * pcm_rec_dma_get_peak_buffer(void) { - *count = 0; return NULL; } -void pcm_record_more(void *start, size_t size) +void pcm_rec_dma_record_more(void *start, size_t size) { (void) start; (void) size;