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/codec-jz4740.c | 93 +++++++++-------- firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c | 115 +++++++++++---------- .../target/mips/ingenic_jz47xx/system-target.h | 4 +- 3 files changed, 109 insertions(+), 103 deletions(-) (limited to 'firmware/target/mips/ingenic_jz47xx') diff --git a/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c b/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c index 44d291f312..6a0b6ae340 100644 --- a/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/codec-jz4740.c @@ -26,7 +26,7 @@ /* TODO */ const struct sound_settings_info audiohw_settings[] = { - [SOUND_VOLUME] = {"dB", 0, 1, -73, 6, -20}, + [SOUND_VOLUME] = {"dB", 0, 2, 0, 6, 0}, /* HAVE_SW_TONE_CONTROLS */ [SOUND_BASS] = {"dB", 0, 1, -24, 24, 0}, [SOUND_TREBLE] = {"dB", 0, 1, -24, 24, 0}, @@ -62,40 +62,39 @@ static void i2s_codec_init(void) { __cpm_start_aic1(); __cpm_start_aic2(); - + __aic_enable(); - + __i2s_internal_codec(); __i2s_as_slave(); __i2s_select_i2s(); __aic_select_i2s(); - + __aic_disable_byteswap(); __aic_disable_unsignadj(); __aic_disable_mono2stereo(); - + i2s_codec_reset(); - - //REG_ICDC_CDCCR2 = (ICDC_CDCCR2_AINVOL(ICDC_CDCCR2_AINVOL_DB(0)) | ICDC_CDCCR2_SMPR(ICDC_CDCCR2_SMPR_48) + + REG_ICDC_CDCCR1 &= ~(ICDC_CDCCR1_SUSPD | ICDC_CDCCR1_RST); + REG_ICDC_CDCCR2 = ( ICDC_CDCCR2_AINVOL(14) | ICDC_CDCCR2_SMPR(ICDC_CDCCR2_SMPR_44) | ICDC_CDCCR2_HPVOL(ICDC_CDCCR2_HPVOL_0)); - - REG_ICDC_CDCCR1 &= ~(ICDC_CDCCR1_SUSPD | ICDC_CDCCR1_RST); mdelay(15); REG_ICDC_CDCCR1 &= ~(ICDC_CDCCR1_PDVR | ICDC_CDCCR1_VRCGL | ICDC_CDCCR1_VRCGH); REG_ICDC_CDCCR1 |= (ICDC_CDCCR1_EDAC | ICDC_CDCCR1_HPCG); - + mdelay(600); REG_ICDC_CDCCR1 &= ~(ICDC_CDCCR1_PDVRA | ICDC_CDCCR1_HPCG | ICDC_CDCCR1_PDHPM | ICDC_CDCCR1_PDHP); - + mdelay(2); - + /* CDCCR1.ELININ=0, CDCCR1.EMIC=0, CDCCR1.EADC=0, CDCCR1.SW1ON=0, CDCCR1.EDAC=1, CDCCR1.SW2ON=1, CDCCR1.HPMUTE=0 */ REG_ICDC_CDCCR1 = (REG_ICDC_CDCCR1 & ~(ICDC_CDCCR1_ELININ | ICDC_CDCCR1_EMIC | ICDC_CDCCR1_EADC | ICDC_CDCCR1_SW1ON | ICDC_CDCCR1_HPMUTE)) | (ICDC_CDCCR1_EDAC | ICDC_CDCCR1_SW2ON); - + HP_on_off_flag = 1; /* HP is on */ } @@ -111,7 +110,7 @@ static void i2s_codec_set_mic(unsigned short v) /* 0 <= v <= 100 */ REG_ICDC_CDCCR2 = ((REG_ICDC_CDCCR2 & ~(0x1f << 16)) | (codec_mic_gain << 16)); } -static void i2s_codec_set_bass(unsigned short v) /* 0 <= v <= 100 */ +static void i2s_codec_set_base(unsigned short v) /* 0 <= v <= 100 */ { v &= 0xff; @@ -200,6 +199,7 @@ static unsigned short i2s_codec_get_volume(void) return val; } +static unsigned long HP_register_value; static void HP_turn_on(void) { //see 1.3.4.1 @@ -261,11 +261,41 @@ static void HP_turn_off(void) } #endif -static void i2s_codec_set_samplerate(unsigned int rate) +void audiohw_mute(bool mute) +{ + if(mute) + REG_ICDC_CDCCR1 |= ICDC_CDCCR1_HPMUTE; + else + REG_ICDC_CDCCR1 &= ~ICDC_CDCCR1_HPMUTE; +} + +void audiohw_preinit(void) +{ +} + +void audiohw_postinit(void) +{ + audiohw_mute(false); + //HP_turn_on(); +} + +void audiohw_init(void) +{ + i2s_codec_init(); +} + +void audiohw_set_volume(int v) +{ + /* 0 <= v <= 60 */ + unsigned int codec_volume = v / 20; + REG_ICDC_CDCCR2 = (REG_ICDC_CDCCR2 & ~ICDC_CDCCR2_HPVOL(0x3)) | ICDC_CDCCR2_HPVOL(codec_volume); +} + +void audiohw_set_frequency(int freq) { unsigned int speed; - - switch (rate) + + switch(freq) { case 8000: speed = ICDC_CDCCR2_SMPR(ICDC_CDCCR2_SMPR_8); @@ -297,33 +327,6 @@ static void i2s_codec_set_samplerate(unsigned int rate) default: return; } - REG_ICDC_CDCCR2 &= ~ICDC_CDCCR2_SMPR(0xF); - REG_ICDC_CDCCR2 |= speed; -} -void audiohw_mute(bool mute) -{ - if(mute) - REG_ICDC_CDCCR1 |= ICDC_CDCCR1_HPMUTE; - else - REG_ICDC_CDCCR1 &= ~ICDC_CDCCR1_HPMUTE; -} - -void audiohw_preinit(void) -{ -} - -void audiohw_postinit(void) -{ - audiohw_mute(false); -} - -void audiohw_init(void) -{ - i2s_codec_init(); -} - -void audiohw_set_frequency(int freq) -{ - i2s_codec_set_samplerate(freq); + REG_ICDC_CDCCR2 = (REG_ICDC_CDCCR2 & ~ICDC_CDCCR2_SMPR(0xF)) | speed; } 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) diff --git a/firmware/target/mips/ingenic_jz47xx/system-target.h b/firmware/target/mips/ingenic_jz47xx/system-target.h index 08c3aeddb6..b2d960ef54 100644 --- a/firmware/target/mips/ingenic_jz47xx/system-target.h +++ b/firmware/target/mips/ingenic_jz47xx/system-target.h @@ -86,10 +86,10 @@ void mdelay(unsigned int msec); void dma_enable(void); void dma_disable(void); -#define DMA_LCD_CHANNEL 0 +#define DMA_AIC_TX_CHANNEL 0 #define DMA_NAND_CHANNEL 1 #define DMA_USB_CHANNEL 2 -#define DMA_AIC_TX_CHANNEL 3 +#define DMA_LCD_CHANNEL 3 #define XDMA_CALLBACK(n) DMA ## n #define DMA_CALLBACK(n) XDMA_CALLBACK(n) -- cgit v1.2.3