summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorMaurus Cuelenaere <mcuelenaere@gmail.com>2009-07-27 18:58:22 +0000
committerMaurus Cuelenaere <mcuelenaere@gmail.com>2009-07-27 18:58:22 +0000
commite38f3abac90b1fd10c22a0769e66d724f53502ad (patch)
tree8a1d16008fe17d9799cdd5c4d2d9623e1dcf7aed /firmware
parent0e83c80bfc6027de854a89f13b83cc5a55a05308 (diff)
downloadrockbox-e38f3abac90b1fd10c22a0769e66d724f53502ad.tar.gz
rockbox-e38f3abac90b1fd10c22a0769e66d724f53502ad.tar.bz2
rockbox-e38f3abac90b1fd10c22a0769e66d724f53502ad.zip
Jz4740 PCM driver: do 32-bit or 16-bit burst sizes if 16-byte ones won't fit (improves PDBox)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22074 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c64
1 files changed, 56 insertions, 8 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c
index 32a14744df..a4ecd0b786 100644
--- a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c
@@ -65,16 +65,35 @@ void pcm_dma_apply_settings(void)
static void* playback_address;
static inline void set_dma(const void *addr, size_t size)
{
- logf("%x %x %d %d %x", (unsigned int)addr, size, (REG_AIC_SR>>24) & 0x20, (REG_AIC_SR>>8) & 0x20, REG_AIC_SR & 0xF);
+ int burst_size;
+ logf("%x %d %x", (unsigned int)addr, size, REG_AIC_SR);
+
+ if(size % 16)
+ {
+ if(size % 4)
+ {
+ size /= 2;
+ burst_size = DMAC_DCMD_DS_16BIT;
+ }
+ else
+ {
+ size /= 4;
+ burst_size = DMAC_DCMD_DS_32BIT;
+ }
+ }
+ else
+ {
+ size /= 16;
+ burst_size = DMAC_DCMD_DS_16BYTE;
+ }
__dcache_writeback_all();
REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) = DMAC_DCCSR_NDES;
REG_DMAC_DSAR(DMA_AIC_TX_CHANNEL) = PHYSADDR((unsigned long)addr);
REG_DMAC_DTAR(DMA_AIC_TX_CHANNEL) = PHYSADDR((unsigned long)AIC_DR);
- REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL) = size / 16;
+ REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL) = size;
REG_DMAC_DRSR(DMA_AIC_TX_CHANNEL) = DMAC_DRSR_RS_AICOUT;
- REG_DMAC_DCMD(DMA_AIC_TX_CHANNEL) = (DMAC_DCMD_SAI | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DS_16BYTE | DMAC_DCMD_DWDH_16 | DMAC_DCMD_TIE |
- DMAC_DCMD_RDIL_IGN);
+ REG_DMAC_DCMD(DMA_AIC_TX_CHANNEL) = (DMAC_DCMD_SAI | DMAC_DCMD_SWDH_32 | burst_size | DMAC_DCMD_DWDH_16 | DMAC_DCMD_TIE);
playback_address = (void*)addr;
}
@@ -181,10 +200,37 @@ void pcm_play_dma_pause(bool pause)
restore_irq(flags);
}
+static int get_dma_count(void)
+{
+ int count = REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL);
+ switch(REG_DMAC_DCMD(DMA_AIC_TX_CHANNEL) & DMAC_DCMD_DS_MASK)
+ {
+ case DMAC_DCMD_DS_16BIT:
+ count *= 2;
+ break;
+ case DMAC_DCMD_DS_32BIT:
+ count *= 4;
+ break;
+ case DMAC_DCMD_DS_16BYTE:
+ count *= 16;
+ break;
+ }
+
+ return count;
+}
+
size_t pcm_get_bytes_waiting(void)
{
- return REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) & DMAC_DCCSR_EN ?
- (REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL) * 16) & ~3 : 0;
+ int bytes, flags = disable_irq_save();
+
+ if(REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) & DMAC_DCCSR_EN)
+ bytes = get_dma_count() & ~3;
+ else
+ bytes = 0;
+
+ restore_irq(flags);
+
+ return bytes;
}
const void * pcm_play_dma_get_peak_buffer(int *count)
@@ -194,8 +240,9 @@ const void * pcm_play_dma_get_peak_buffer(int *count)
const void* addr;
if(REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) & DMAC_DCCSR_EN)
{
- *count = REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL)*16 >> 2;
- addr = (const void*)(playback_address + ((REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL)*16 + 2) & ~3));
+ int bytes = get_dma_count();
+ *count = bytes >> 2;
+ addr = (const void*)((int)(playback_address + bytes + 2) & ~3);
}
else
{
@@ -210,6 +257,7 @@ const void * pcm_play_dma_get_peak_buffer(int *count)
void audiohw_close(void)
{
+ /* TODO: prevent pop */
}
#ifdef HAVE_RECORDING