From a0458dac2b14d4ec50dc2d65d26005a58b6a5581 Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Tue, 26 May 2009 22:57:49 +0000 Subject: Fix audio on Onda VX747 git-svn-id: svn://svn.rockbox.org/rockbox/trunk@21097 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c | 115 ++++++++++++----------- 1 file changed, 59 insertions(+), 56 deletions(-) (limited to 'firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c') diff --git a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c index 11a5e6d8c0..05c89be158 100644 --- a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c @@ -37,12 +37,15 @@ static void* playback_address; void pcm_postinit(void) { audiohw_postinit(); - + /* playback sample: 16 bits burst: 16 bytes */ __i2s_set_iss_sample_size(16); __i2s_set_oss_sample_size(16); - __i2s_set_transmit_trigger(16 - 4); - __i2s_set_receive_trigger(4); + __i2s_set_transmit_trigger(10); + __i2s_set_receive_trigger(1); + + /* Flush FIFO */ + __aic_flush_fifo(); } void pcm_play_dma_init(void) @@ -50,7 +53,7 @@ void pcm_play_dma_init(void) /* TODO */ system_enable_irq(DMA_IRQ(DMA_AIC_TX_CHANNEL)); - + /* Initialize default register values. */ audiohw_init(); } @@ -63,30 +66,39 @@ void pcm_dma_apply_settings(void) static void play_start_pcm(void) { - /* Prefill FIFO */ - REG_AIC_DR = 0; - REG_AIC_DR = 0; - REG_AIC_DR = 0; - REG_AIC_DR = 0; - - __i2s_enable_transmit_dma(); - __i2s_enable_replay(); - + __aic_enable_transmit_dma(); + __aic_enable_replay(); + REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) |= DMAC_DCCSR_EN; - REG_DMAC_DCMD(DMA_AIC_TX_CHANNEL) |= DMAC_DCMD_TIE; - + playback_started = true; } +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); + + //__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_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); + + playback_address = (void*)addr; +} + static void play_stop_pcm(void) { REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) = (REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) | DMAC_DCCSR_HLT) & ~DMAC_DCCSR_EN; - + dma_disable(); - - __i2s_disable_transmit_dma(); - __i2s_disable_replay(); - + + __aic_disable_transmit_dma(); + __aic_disable_replay(); + playback_started = false; } @@ -94,56 +106,47 @@ void pcm_play_dma_start(const void *addr, size_t size) { dma_enable(); - __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; - 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_32BIT | DMAC_DCMD_DWDH_16); - - playback_address = (void*)addr; + set_dma(addr, size); play_start_pcm(); } -static void play_dma_callback(void) +static inline void play_dma_callback(void) { unsigned char *start; size_t size = 0; - pcm_callback_for_more(&start, &size); - if(size != 0) + + if(LIKELY(size > 0)) { - __dcache_writeback_all(); - REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) = DMAC_DCCSR_NDES; - REG_DMAC_DSAR(DMA_AIC_TX_CHANNEL) = PHYSADDR((unsigned long)start); - REG_DMAC_DTAR(DMA_AIC_TX_CHANNEL) = PHYSADDR((unsigned long)AIC_DR); - 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_32BIT | DMAC_DCMD_DWDH_16); + set_dma(start, size); REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) |= DMAC_DCCSR_EN; - REG_DMAC_DCMD(DMA_AIC_TX_CHANNEL) |= DMAC_DCMD_TIE; - return; } - - /* Error, callback missing or no more DMA to do */ - pcm_play_dma_stop(); - pcm_play_dma_stopped_callback(); + 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) { if (REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) & DMAC_DCCSR_AR) + { + logf("PCM DMA address error"); REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) &= ~DMAC_DCCSR_AR; + } - if (REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) & DMAC_DCCSR_CT) - REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) &= ~DMAC_DCCSR_CT; + if (REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) & DMAC_DCCSR_HLT) + { + logf("PCM DMA halt"); + REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) &= ~DMAC_DCCSR_HLT; + } - if (REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) & (DMAC_DCCSR_TT | DMAC_DCCSR_HLT)) + if (REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) & DMAC_DCCSR_TT) { - REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) &= ~(DMAC_DCCSR_TT | DMAC_DCCSR_HLT); - REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) &= ~DMAC_DCCSR_EN; + REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) &= ~DMAC_DCCSR_TT; play_dma_callback(); } } @@ -151,7 +154,7 @@ void DMA_CALLBACK(DMA_AIC_TX_CHANNEL)(void) size_t pcm_get_bytes_waiting(void) { if(playback_started) - return REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL) & ~3; + return (REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL) * 16) & ~3; else return 0; } @@ -161,8 +164,8 @@ const void * pcm_play_dma_get_peak_buffer(int *count) /* TODO */ if(playback_started) { - *count = REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL); - return (void*)(playback_address + ((REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL) + 2) & ~3)); + *count = REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL) >> 2; + return (void*)(playback_address + ((REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL)*16 + 2) & ~3)); } else { @@ -174,7 +177,7 @@ const void * pcm_play_dma_get_peak_buffer(int *count) void pcm_play_dma_stop(void) { play_stop_pcm(); - + /* TODO */ } @@ -191,9 +194,9 @@ void pcm_play_unlock(void) void pcm_play_dma_pause(bool pause) { if(pause) - play_stop_pcm(); + REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) &= ~DMAC_DCCSR_EN; else - play_start_pcm(); + REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) |= DMAC_DCCSR_EN; } void audiohw_close(void) -- cgit v1.2.3