From c983e3b1d25503e71d0d7cba7c921b16c216770b Mon Sep 17 00:00:00 2001 From: Maurus Cuelenaere Date: Sat, 20 Dec 2008 01:48:46 +0000 Subject: [PATCH] Ingenic targets: * LCD rework * Dynamic DMA enabling * PCM cleanup * USB: replace printf() with logf() * System: get rid of in_interrupt_mode() * Backlight: add support for software PWM git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19495 a1c6a512-1295-4272-9138-f99709370657 --- firmware/export/jz4740.h | 3 +- .../mips/ingenic_jz47xx/ata-nand-jz4740.c | 8 ++ .../mips/ingenic_jz47xx/kernel-jz4740.c | 18 +-- .../target/mips/ingenic_jz47xx/lcd-jz4740.c | 91 ++++++++------- .../onda_vx747/backlight-onda_vx747.c | 100 +++++++++++++---- .../onda_vx747/backlight-target.h | 1 + .../onda_vx747/lcd-onda_vx747.c | 6 +- .../onda_vx747/sadc-onda_vx747.c | 2 +- .../target/mips/ingenic_jz47xx/pcm-jz4740.c | 41 ++++--- .../mips/ingenic_jz47xx/system-jz4740.c | 104 +++++++++--------- .../mips/ingenic_jz47xx/system-target.h | 5 +- .../target/mips/ingenic_jz47xx/usb-jz4740.c | 40 +++---- 12 files changed, 253 insertions(+), 166 deletions(-) diff --git a/firmware/export/jz4740.h b/firmware/export/jz4740.h index 505248a67a..afd10cef57 100644 --- a/firmware/export/jz4740.h +++ b/firmware/export/jz4740.h @@ -3025,7 +3025,8 @@ do { \ /* * n = 0 ~ 7 */ -#define __gpio_as_pwm(n) __gpio_as_pwm##n() +#define ___gpio_as_pwm(n) __gpio_as_pwm ## n() +#define __gpio_as_pwm(n) ___gpio_as_pwm(n) //------------------------------------------- // GPIO or Interrupt Mode diff --git a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c index 979a9067d3..a4b4a86a55 100644 --- a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c @@ -138,6 +138,8 @@ static void jz_nand_write_dma(void *source, unsigned int len, int bw) if(((unsigned int)source < 0xa0000000) && len) dma_cache_wback_inv((unsigned long)source, len); + + dma_enable(); REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = 0; REG_DMAC_DSAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)source); @@ -151,6 +153,8 @@ static void jz_nand_write_dma(void *source, unsigned int len, int bw) while( REG_DMAC_DTCR(DMA_NAND_CHANNEL) ) yield(); + dma_disable(); + mutex_unlock(&nand_mtx); } @@ -161,6 +165,8 @@ static void jz_nand_read_dma(void *target, unsigned int len, int bw) if(((unsigned int)target < 0xa0000000) && len) dma_cache_wback_inv((unsigned long)target, len); + dma_enable(); + REG_DMAC_DCCSR(DMA_NAND_CHANNEL) = 0; REG_DMAC_DSAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)NAND_DATAPORT); REG_DMAC_DTAR(DMA_NAND_CHANNEL) = PHYSADDR((unsigned long)target); @@ -172,6 +178,8 @@ static void jz_nand_read_dma(void *target, unsigned int len, int bw) while( REG_DMAC_DTCR(DMA_NAND_CHANNEL) ) yield(); + dma_disable(); + mutex_unlock(&nand_mtx); } diff --git a/firmware/target/mips/ingenic_jz47xx/kernel-jz4740.c b/firmware/target/mips/ingenic_jz47xx/kernel-jz4740.c index dcfdfd6a38..431af490da 100644 --- a/firmware/target/mips/ingenic_jz47xx/kernel-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/kernel-jz4740.c @@ -24,38 +24,26 @@ #include "kernel.h" #include "jz4740.h" -#define USE_RTC_CLOCK 0 void tick_start(unsigned int interval_in_ms) { - unsigned int tps = interval_in_ms; unsigned int latch; + __cpm_start_tcu(); __tcu_stop_counter(0); __tcu_disable_pwm_output(0); - __tcu_stop_counter(1); - __tcu_disable_pwm_output(1); - __tcu_stop_counter(2); - __tcu_disable_pwm_output(2); - __tcu_clear_full_match_flag(2); __tcu_mask_half_match_irq(0); __tcu_unmask_full_match_irq(0); -#if USE_RTC_CLOCK - __tcu_select_rtcclk(0); - __tcu_select_clk_div1(0); - latch = (__cpm_get_rtcclk() + (tps>>1)) / tps; -#else __tcu_select_extalclk(0); __tcu_select_clk_div4(0); - latch = (JZ_EXTAL / 4 + (tps>>1)) / tps; -#endif + latch = (JZ_EXTAL / 4 + (interval_in_ms>>1)) / interval_in_ms; + REG_TCU_TCNT(0) = 0; REG_TCU_TDFR(0) = latch; REG_TCU_TDHR(0) = latch; - //REG_TCU_TDHR(0) = 0; __tcu_clear_full_match_flag(0); __tcu_start_counter(0); diff --git a/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c b/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c index 1401bf8a3f..996731c0cd 100644 --- a/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c @@ -25,9 +25,16 @@ #include "lcd-target.h" #include "system.h" #include "kernel.h" +#include "backlight-target.h" + +/* + Warning: code behaviour is unpredictable when threads get switched in IRQ mode! + So don't update the LCD in an interrupt handler! + */ static volatile bool lcd_is_on = false; static struct mutex lcd_mtx; +static struct wakeup lcd_wkup; /* LCD init */ void lcd_init_device(void) @@ -35,6 +42,8 @@ void lcd_init_device(void) lcd_init_controller(); lcd_is_on = true; mutex_init(&lcd_mtx); + wakeup_init(&lcd_wkup); + system_enable_irq(DMA_IRQ(DMA_LCD_CHANNEL)); } void lcd_enable(bool state) @@ -55,73 +64,75 @@ bool lcd_enabled(void) return lcd_is_on; } -/* Don't switch threads when in interrupt mode! */ -static inline void lcd_lock(void) -{ - if(LIKELY(!in_interrupt_mode())) - mutex_lock(&lcd_mtx); - else - while( !(REG_DMAC_DCCSR(DMA_LCD_CHANNEL) & DMAC_DCCSR_TT)); -} - -static inline void lcd_unlock(void) -{ - if(LIKELY(!in_interrupt_mode())) - mutex_unlock(&lcd_mtx); -} - -static inline void lcd_wait(void) -{ - if(LIKELY(!in_interrupt_mode())) - { - while( !(REG_DMAC_DCCSR(DMA_LCD_CHANNEL) & DMAC_DCCSR_TT) ) - yield(); - } - else - while( !(REG_DMAC_DCCSR(DMA_LCD_CHANNEL) & DMAC_DCCSR_TT)); -} - /* Update a fraction of the display. */ void lcd_update_rect(int x, int y, int width, int height) { - lcd_lock(); +#if 1 + /* This is an ugly HACK until partial LCD drawing works.. */ + width = LCD_WIDTH; + height = LCD_HEIGHT; + x = 0; + y = 0; +#endif + + mutex_lock(&lcd_mtx); lcd_set_target(x, y, width, height); - REG_DMAC_DCCSR(DMA_LCD_CHANNEL) = 0; + dma_enable(); + + REG_DMAC_DCCSR(DMA_LCD_CHANNEL) = DMAC_DCCSR_NDES; REG_DMAC_DRSR(DMA_LCD_CHANNEL) = DMAC_DRSR_RS_SLCD; /* source = SLCD */ - REG_DMAC_DSAR(DMA_LCD_CHANNEL) = ((unsigned int)&lcd_framebuffer[y][x]) & 0x1FFFFFFF; - REG_DMAC_DTAR(DMA_LCD_CHANNEL) = 0x130500B0; /* SLCD_FIFO */ + REG_DMAC_DSAR(DMA_LCD_CHANNEL) = PHYSADDR((unsigned long)&lcd_framebuffer[y][x]); + REG_DMAC_DTAR(DMA_LCD_CHANNEL) = PHYSADDR(SLCD_FIFO); REG_DMAC_DTCR(DMA_LCD_CHANNEL) = width*height; REG_DMAC_DCMD(DMA_LCD_CHANNEL) = ( DMAC_DCMD_SAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 | DMAC_DCMD_DWDH_16 | DMAC_DCMD_DS_16BIT ); - REG_DMAC_DCCSR(DMA_LCD_CHANNEL) = DMAC_DCCSR_NDES; - __dcache_writeback_all(); /* Size of framebuffer is way bigger than cache size; - we need to find a way to make the framebuffer uncached, so this statement can get removed. */ + __dcache_writeback_all(); /* Size of framebuffer is way bigger than cache size. + We need to find a way to make the framebuffer uncached, so this statement can get removed. */ while(REG_SLCD_STATE & SLCD_STATE_BUSY); + REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN; /* Enable SLCD DMA support */ - REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN; - REG_DMAC_DCCSR(DMA_LCD_CHANNEL) |= DMAC_DCCSR_EN; + REG_DMAC_DCCSR(DMA_LCD_CHANNEL) |= DMAC_DCCSR_EN; /* Enable DMA channel */ + REG_DMAC_DCMD(DMA_LCD_CHANNEL) |= DMAC_DCMD_TIE; /* Enable DMA interrupt */ - lcd_wait(); + wakeup_wait(&lcd_wkup, TIMEOUT_BLOCK); - REG_DMAC_DCCSR(DMA_LCD_CHANNEL) &= ~DMAC_DCCSR_EN; + REG_DMAC_DCCSR(DMA_LCD_CHANNEL) &= ~DMAC_DCCSR_EN; /* Disable DMA channel */ + + dma_disable(); while(REG_SLCD_STATE & SLCD_STATE_BUSY); + REG_SLCD_CTRL &= ~SLCD_CTRL_DMA_EN; /* Disable SLCD DMA support */ - REG_SLCD_CTRL &= ~SLCD_CTRL_DMA_EN; + mutex_unlock(&lcd_mtx); +} + +void DMA_CALLBACK(DMA_LCD_CHANNEL)(void) +{ + if (REG_DMAC_DCCSR(DMA_LCD_CHANNEL) & DMAC_DCCSR_HLT) + REG_DMAC_DCCSR(DMA_LCD_CHANNEL) &= ~DMAC_DCCSR_HLT; + + if (REG_DMAC_DCCSR(DMA_LCD_CHANNEL) & DMAC_DCCSR_AR) + REG_DMAC_DCCSR(DMA_LCD_CHANNEL) &= ~DMAC_DCCSR_AR; + + if (REG_DMAC_DCCSR(DMA_LCD_CHANNEL) & DMAC_DCCSR_CT) + REG_DMAC_DCCSR(DMA_LCD_CHANNEL) &= ~DMAC_DCCSR_CT; + + if (REG_DMAC_DCCSR(DMA_LCD_CHANNEL) & DMAC_DCCSR_TT) + REG_DMAC_DCCSR(DMA_LCD_CHANNEL) &= ~DMAC_DCCSR_TT; - lcd_unlock(); + wakeup_signal(&lcd_wkup); } /* Update the display. This must be called after all other LCD functions that change the display. */ void lcd_update(void) { - if (!lcd_is_on) + if (!lcd_is_on || !backlight_enabled()) return; lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); diff --git a/firmware/target/mips/ingenic_jz47xx/onda_vx747/backlight-onda_vx747.c b/firmware/target/mips/ingenic_jz47xx/onda_vx747/backlight-onda_vx747.c index 501a90551e..208236ef95 100644 --- a/firmware/target/mips/ingenic_jz47xx/onda_vx747/backlight-onda_vx747.c +++ b/firmware/target/mips/ingenic_jz47xx/onda_vx747/backlight-onda_vx747.c @@ -23,60 +23,119 @@ #include "jz4740.h" #include "backlight-target.h" -#define PWM_CHN 7 /* PWM_CHN7 == GPIO(32*3 + 31) */ -#define __gpio_as_PWM_CHN __gpio_as_pwm7 +/* PWM_CHN7 == GPIO(32*3 + 31) */ +#define BACKLIGHT_GPIO (32*3+31) +#define BACKLIGHT_PWM 7 + +#define SW_PWM 1 + +#if SW_PWM + +static bool backlight_on; static void set_backlight(int val) { +(void)val; +} + +bool _backlight_init(void) +{ + __gpio_as_output(BACKLIGHT_GPIO); + __gpio_set_pin(BACKLIGHT_GPIO); + + backlight_on = true; + + return true; +} + +bool backlight_enabled(void) +{ + return backlight_on; +} + +void _backlight_on(void) +{ + __gpio_set_pin(BACKLIGHT_GPIO); + backlight_on = true; +} + +void _backlight_off(void) +{ + __gpio_clear_pin(BACKLIGHT_GPIO); + backlight_on = false; +} + +#else + +static int old_val; +static void set_backlight(int val) +{ + if(val == old_val) + return; + /* Taken from the OF */ int tmp; tmp = (val/2 + __cpm_get_rtcclk()) / val; if(tmp > 0xFFFF) tmp = 0xFFFF; - __tcu_set_half_data(PWM_CHN, (tmp * val * 1374389535) >> 5); - __tcu_set_full_data(PWM_CHN, tmp); + __tcu_set_half_data(BACKLIGHT_PWM, (tmp * val * 1374389535) >> 5); + __tcu_set_full_data(BACKLIGHT_PWM, tmp); + + old_val = val; } static void set_backlight_on(void) { - __tcu_start_timer_clock(PWM_CHN); + if(old_val == MAX_BRIGHTNESS_SETTING) + return; + + __tcu_start_timer_clock(BACKLIGHT_PWM); set_backlight(MAX_BRIGHTNESS_SETTING); - __tcu_set_count(PWM_CHN, 0); - __tcu_start_counter(PWM_CHN); + __tcu_set_count(BACKLIGHT_PWM, 0); + __tcu_start_counter(BACKLIGHT_PWM); - __tcu_enable_pwm_output(PWM_CHN); + __tcu_enable_pwm_output(BACKLIGHT_PWM); } static void set_backlight_off(void) { - __tcu_stop_counter(PWM_CHN); - __tcu_disable_pwm_output(PWM_CHN); - __tcu_stop_timer_clock(PWM_CHN); + __tcu_stop_counter(BACKLIGHT_PWM); + __tcu_disable_pwm_output(BACKLIGHT_PWM); + __tcu_stop_timer_clock(BACKLIGHT_PWM); + + old_val = -1; } bool _backlight_init(void) { - __gpio_as_PWM_CHN(); - __tcu_start_timer_clock(PWM_CHN); + __gpio_as_pwm(BACKLIGHT_PWM); + __tcu_start_timer_clock(BACKLIGHT_PWM); - __tcu_stop_counter(PWM_CHN); - __tcu_disable_pwm_output(PWM_CHN); + __tcu_stop_counter(BACKLIGHT_PWM); + __tcu_disable_pwm_output(BACKLIGHT_PWM); - __tcu_init_pwm_output_low(PWM_CHN); - __tcu_select_rtcclk(PWM_CHN); - __tcu_select_clk_div1(PWM_CHN); + __tcu_init_pwm_output_low(BACKLIGHT_PWM); + __tcu_select_rtcclk(BACKLIGHT_PWM); + __tcu_select_clk_div1(BACKLIGHT_PWM); - __tcu_mask_half_match_irq(PWM_CHN); - __tcu_mask_full_match_irq(PWM_CHN); + __tcu_mask_half_match_irq(BACKLIGHT_PWM); + __tcu_mask_full_match_irq(BACKLIGHT_PWM); + + old_val = -1; set_backlight_on(); return true; } +bool backlight_enabled(void) +{ + return old_val > -1 ? true : false; +} + void _backlight_on(void) { set_backlight_on(); @@ -86,6 +145,7 @@ void _backlight_off(void) { set_backlight_off(); } +#endif /* !SW_PWM */ #ifdef HAVE_BACKLIGHT_BRIGHTNESS void _backlight_set_brightness(int brightness) diff --git a/firmware/target/mips/ingenic_jz47xx/onda_vx747/backlight-target.h b/firmware/target/mips/ingenic_jz47xx/onda_vx747/backlight-target.h index 4170f96cc0..f3f17f024e 100644 --- a/firmware/target/mips/ingenic_jz47xx/onda_vx747/backlight-target.h +++ b/firmware/target/mips/ingenic_jz47xx/onda_vx747/backlight-target.h @@ -33,5 +33,6 @@ bool _backlight_init(void); void _backlight_on(void); void _backlight_off(void); void _backlight_set_brightness(int brightness); +bool backlight_enabled(void); #endif /* BACKLIGHT_TARGET_H */ diff --git a/firmware/target/mips/ingenic_jz47xx/onda_vx747/lcd-onda_vx747.c b/firmware/target/mips/ingenic_jz47xx/onda_vx747/lcd-onda_vx747.c index f7c6a137fc..40d9bb6106 100644 --- a/firmware/target/mips/ingenic_jz47xx/onda_vx747/lcd-onda_vx747.c +++ b/firmware/target/mips/ingenic_jz47xx/onda_vx747/lcd-onda_vx747.c @@ -204,7 +204,7 @@ static void _set_lcd_clock(void) __cpm_stop_lcd(); pll_div = ( REG_CPM_CPCCR & CPM_CPCCR_PCS ); /* clock source, 0:pllout/2 1: pllout */ pll_div = pll_div ? 1 : 2 ; - val = ( __cpm_get_pllout()/pll_div ) / 336000000; + val = ( __cpm_get_pllout()/pll_div ) / __cpm_get_pclk(); val--; if ( val > 0x1ff ) val = 0x1ff; /* CPM_LPCDR is too large, set it to 0x1ff */ @@ -235,8 +235,8 @@ void lcd_set_target(short x, short y, short width, short height) SLCD_SEND_COMMAND(REG_RAM_VADDR_START, x); /* x_start */ SLCD_SEND_COMMAND(REG_RAM_VADDR_END, x+width-1); /* x_end */ #endif - SLCD_SEND_COMMAND(REG_RAM_HADDR_SET, x); /* set cursor at x_start */ - SLCD_SEND_COMMAND(REG_RAM_VADDR_SET, y); /* set cursor at y_start */ + SLCD_SEND_COMMAND(REG_RAM_HADDR_SET, y); /* set cursor at x_start */ + SLCD_SEND_COMMAND(REG_RAM_VADDR_SET, x); /* set cursor at y_start */ SLCD_SET_COMMAND(REG_RW_GRAM); /* write data to GRAM */ } diff --git a/firmware/target/mips/ingenic_jz47xx/onda_vx747/sadc-onda_vx747.c b/firmware/target/mips/ingenic_jz47xx/onda_vx747/sadc-onda_vx747.c index 0271fd1b96..95c2f84a7e 100644 --- a/firmware/target/mips/ingenic_jz47xx/onda_vx747/sadc-onda_vx747.c +++ b/firmware/target/mips/ingenic_jz47xx/onda_vx747/sadc-onda_vx747.c @@ -47,7 +47,7 @@ BTN_MENU | BTN_VOL_UP) -#define TS_AD_COUNT 5 +#define TS_AD_COUNT 3 #define SADC_CFG_SNUM ((TS_AD_COUNT - 1) << SADC_CFG_SNUM_BIT) #define SADC_CFG_INIT ( \ diff --git a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c index dce989d81f..c97ef13533 100644 --- a/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/pcm-jz4740.c @@ -41,17 +41,12 @@ void pcm_postinit(void) __i2s_set_oss_sample_size(16); } -const void * pcm_play_dma_get_peak_buffer(int *count) -{ - /* TODO */ - *count = 0; - return NULL; -} - void pcm_play_dma_init(void) { /* TODO */ + system_enable_irq(DMA_IRQ(DMA_AIC_TX_CHANNEL)); + /* Initialize default register values. */ audiohw_init(); } @@ -59,11 +54,6 @@ void pcm_play_dma_init(void) void pcm_dma_apply_settings(void) { /* TODO */ - - /* - __i2s_set_oss_sample_size(pcm_sampr); - i2s_codec_set_samplerate(pcm_sampr); - */ } static void play_start_pcm(void) @@ -72,33 +62,47 @@ static void play_start_pcm(void) __i2s_enable_replay(); REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) |= DMAC_DCCSR_EN; + REG_DMAC_DCMD(DMA_AIC_TX_CHANNEL) |= DMAC_DCMD_TIE; } 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(); } void pcm_play_dma_start(const void *addr, size_t size) { + dma_enable(); + 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_32 - | DMAC_DCMD_TIE); + REG_DMAC_DCMD(DMA_AIC_TX_CHANNEL) = (DMAC_DCMD_SAI| DMAC_DCMD_SWDH_32 | DMAC_DCMD_DS_32BIT | DMAC_DCMD_DWDH_32); play_start_pcm(); } void DMA_CALLBACK(DMA_AIC_TX_CHANNEL)(void) { - if( REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) & DMAC_DCCSR_TT ) + if (REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) & DMAC_DCCSR_AR) + 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_TT | DMAC_DCCSR_HLT)) + { + REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) &= ~(DMAC_DCCSR_TT | DMAC_DCCSR_HLT); + REG_DMAC_DCCSR(DMA_AIC_TX_CHANNEL) &= ~DMAC_DCCSR_EN; __aic_disable_transmit_dma(); + } } size_t pcm_get_bytes_waiting(void) @@ -106,6 +110,13 @@ size_t pcm_get_bytes_waiting(void) return REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL); } +const void * pcm_play_dma_get_peak_buffer(int *count) +{ + /* TODO */ + *count = REG_DMAC_DTCR(DMA_AIC_TX_CHANNEL)>>2; + return NULL; +} + void pcm_play_dma_stop(void) { play_stop_pcm(); diff --git a/firmware/target/mips/ingenic_jz47xx/system-jz4740.c b/firmware/target/mips/ingenic_jz47xx/system-jz4740.c index f733582d70..22d35d93de 100644 --- a/firmware/target/mips/ingenic_jz47xx/system-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/system-jz4740.c @@ -24,8 +24,8 @@ #include "mips.h" #include "mipsregs.h" #include "panic.h" -#include "system-target.h" -#include +#include "system.h" +#include "string.h" #include "kernel.h" #define NUM_DMA 6 @@ -322,53 +322,45 @@ static int get_irq_number(void) return irq; } -static bool intr_mode = false; - -bool in_interrupt_mode(void) -{ - return intr_mode; -} - void intr_handler(void) { int irq = get_irq_number(); - if(irq < 0) + if(UNLIKELY(irq < 0)) return; ack_irq(irq); - if(irq > 0) - { - intr_mode = true; + if(LIKELY(irq > 0)) irqvector[irq-1](); - intr_mode = false; - } } -#define EXC(x,y) if(_cause == (x)) return (y); +#define EXC(x,y) case (x): return (y); static char* parse_exception(unsigned int cause) { - unsigned int _cause = cause & M_CauseExcCode; - EXC(EXC_INT, "Interrupt"); - EXC(EXC_MOD, "TLB Modified"); - EXC(EXC_TLBL, "TLB Exception (Load or Ifetch)"); - EXC(EXC_ADEL, "Address Error (Load or Ifetch)"); - EXC(EXC_ADES, "Address Error (Store)"); - EXC(EXC_TLBS, "TLB Exception (Store)"); - EXC(EXC_IBE, "Instruction Bus Error"); - EXC(EXC_DBE, "Data Bus Error"); - EXC(EXC_SYS, "Syscall"); - EXC(EXC_BP, "Breakpoint"); - EXC(EXC_RI, "Reserved Instruction"); - EXC(EXC_CPU, "Coprocessor Unusable"); - EXC(EXC_OV, "Overflow"); - EXC(EXC_TR, "Trap Instruction"); - EXC(EXC_FPE, "Floating Point Exception"); - EXC(EXC_C2E, "COP2 Exception"); - EXC(EXC_MDMX, "MDMX Exception"); - EXC(EXC_WATCH, "Watch Exception"); - EXC(EXC_MCHECK, "Machine Check Exception"); - EXC(EXC_CacheErr, "Cache error caused re-entry to Debug Mode"); - return NULL; + switch(cause & M_CauseExcCode) + { + EXC(EXC_INT, "Interrupt"); + EXC(EXC_MOD, "TLB Modified"); + EXC(EXC_TLBL, "TLB Exception (Load or Ifetch)"); + EXC(EXC_ADEL, "Address Error (Load or Ifetch)"); + EXC(EXC_ADES, "Address Error (Store)"); + EXC(EXC_TLBS, "TLB Exception (Store)"); + EXC(EXC_IBE, "Instruction Bus Error"); + EXC(EXC_DBE, "Data Bus Error"); + EXC(EXC_SYS, "Syscall"); + EXC(EXC_BP, "Breakpoint"); + EXC(EXC_RI, "Reserved Instruction"); + EXC(EXC_CPU, "Coprocessor Unusable"); + EXC(EXC_OV, "Overflow"); + EXC(EXC_TR, "Trap Instruction"); + EXC(EXC_FPE, "Floating Point Exception"); + EXC(EXC_C2E, "COP2 Exception"); + EXC(EXC_MDMX, "MDMX Exception"); + EXC(EXC_WATCH, "Watch Exception"); + EXC(EXC_MCHECK, "Machine Check Exception"); + EXC(EXC_CacheErr, "Cache error caused re-entry to Debug Mode"); + default: + return NULL; + } } void exception_handler(void* stack_ptr, unsigned int cause, unsigned int epc) @@ -644,18 +636,31 @@ static void tlb_call_refill(void) ); } -static void dma_init(void) +static int dma_count = 0; +void dma_enable(void) { - __cpm_start_dmac(); - - REG_DMAC_DCCSR(0) = 0; - REG_DMAC_DCCSR(1) = 0; - REG_DMAC_DCCSR(2) = 0; - REG_DMAC_DCCSR(3) = 0; - REG_DMAC_DCCSR(4) = 0; - REG_DMAC_DCCSR(5) = 0; - - REG_DMAC_DMACR = (DMAC_DMACR_PR_012345 | DMAC_DMACR_DMAE); + if(++dma_count == 1) + { + __cpm_start_dmac(); + + REG_DMAC_DCCSR(0) = 0; + REG_DMAC_DCCSR(1) = 0; + REG_DMAC_DCCSR(2) = 0; + REG_DMAC_DCCSR(3) = 0; + REG_DMAC_DCCSR(4) = 0; + REG_DMAC_DCCSR(5) = 0; + + REG_DMAC_DMACR = (DMAC_DMACR_PR_012345 | DMAC_DMACR_DMAE); + } +} + +void dma_disable(void) +{ + if(--dma_count == 0) + { + REG_DMAC_DMACR &= ~DMAC_DMACR_DMAE; + __cpm_stop_dmac(); + } } extern int main(void); @@ -686,7 +691,6 @@ void system_main(void) dis_irq(i); tlb_init(); - dma_init(); detect_clock(); diff --git a/firmware/target/mips/ingenic_jz47xx/system-target.h b/firmware/target/mips/ingenic_jz47xx/system-target.h index a8133140fa..39782a3222 100644 --- a/firmware/target/mips/ingenic_jz47xx/system-target.h +++ b/firmware/target/mips/ingenic_jz47xx/system-target.h @@ -101,7 +101,8 @@ void udelay(unsigned int usec); void mdelay(unsigned int msec); void power_off(void); void system_reboot(void); -bool in_interrupt_mode(void); +void dma_enable(void); +void dma_disable(void); #define DMA_LCD_CHANNEL 0 #define DMA_NAND_CHANNEL 1 @@ -111,4 +112,6 @@ bool in_interrupt_mode(void); #define XDMA_CALLBACK(n) DMA ## n #define DMA_CALLBACK(n) XDMA_CALLBACK(n) +#define DMA_IRQ(n) (IRQ_DMA_0 + n) + #endif /* __SYSTEM_TARGET_H_ */ diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c index 16965159f6..f06e796e05 100644 --- a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c @@ -20,6 +20,8 @@ ****************************************************************************/ #include "config.h" +#define LOGF_ENABLE +#include "logf.h" #include "system.h" #include "usb_ch9.h" #include "usb_drv.h" @@ -28,12 +30,6 @@ #include "jz4740.h" #include "thread.h" -#if 1 -#define DEBUGF printf -#else -#define DEBUGF(...) -#endif - #define USB_EP0_IDLE 0 #define USB_EP0_RX 1 #define USB_EP0_TX 2 @@ -85,7 +81,7 @@ static inline void select_endpoint(int ep) static void readFIFO(struct usb_endpoint *ep, unsigned int size) { - DEBUGF("readFIFO(EP%d, %d)", EP_NUMBER(ep), size); + logf("readFIFO(EP%d, %d)", EP_NUMBER(ep), size); register unsigned char *ptr = (unsigned char*)EP_PTR(ep); register unsigned int *ptr32 = (unsigned int*)ptr; @@ -121,7 +117,7 @@ static void readFIFO(struct usb_endpoint *ep, unsigned int size) static void writeFIFO(struct usb_endpoint *ep, unsigned int size) { - DEBUGF("writeFIFO(EP%d, %d)", EP_NUMBER(ep), size); + logf("writeFIFO(EP%d, %d)", EP_NUMBER(ep), size); register unsigned int *d = (unsigned int *)EP_PTR(ep); register unsigned char *c; @@ -140,6 +136,8 @@ static void writeFIFO(struct usb_endpoint *ep, unsigned int size) REG8(ep->fifo_addr) = *c++; } } + else + REG32(ep->fifo_addr) = 0; } static void EP0_send(void) @@ -152,6 +150,8 @@ static void EP0_send(void) else length = (EP_BUF_LEFT(ep) <= ep->fifo_size ? EP_BUF_LEFT(ep) : ep->fifo_size); + select_endpoint(0); + writeFIFO(ep, length); ep->sent += length; @@ -243,7 +243,7 @@ static void setup_endpoint(struct usb_endpoint *ep) static void udc_reset(void) { - DEBUGF("udc_reset"); + logf("udc_reset"); register unsigned int i; @@ -303,19 +303,19 @@ void UDC(void) if(intrUSB & USB_INTR_RESUME); if(intrDMA & USB_INTR_DMA_BULKIN) { - DEBUGF("DMA_BULKIN %d", ((REG_USB_REG_CNTL1 >> 4) & 0xF)); + logf("DMA_BULKIN %d", ((REG_USB_REG_CNTL1 >> 4) & 0xF)); usb_core_transfer_complete(((REG_USB_REG_CNTL1 >> 4) & 0xF) | USB_DIR_IN, USB_DIR_IN, 0, 0); } if(intrDMA & USB_INTR_DMA_BULKOUT) { - DEBUGF("DMA_BULKOUT %d", ((REG_USB_REG_CNTL2 >> 4) & 0xF)); + logf("DMA_BULKOUT %d", ((REG_USB_REG_CNTL2 >> 4) & 0xF)); usb_core_transfer_complete(((REG_USB_REG_CNTL2 >> 4) & 0xF) | USB_DIR_OUT, USB_DIR_OUT, 0, 0); } } bool usb_drv_stalled(int endpoint, bool in) { - DEBUGF("usb_drv_stalled(%d, %s)", endpoint, in?"IN":"OUT"); + logf("usb_drv_stalled(%d, %s)", endpoint, in?"IN":"OUT"); select_endpoint(endpoint); @@ -332,7 +332,7 @@ bool usb_drv_stalled(int endpoint, bool in) void usb_drv_stall(int endpoint, bool stall, bool in) { - DEBUGF("usb_drv_stall(%d,%s,%s)", endpoint, stall?"y":"n", in?"IN":"OUT"); + logf("usb_drv_stall(%d,%s,%s)", endpoint, stall?"y":"n", in?"IN":"OUT"); select_endpoint(endpoint); @@ -424,14 +424,14 @@ void usb_drv_exit(void) void usb_drv_set_address(int address) { - DEBUGF("set adr: 0x%x", address); + logf("set adr: %d", address); REG_USB_REG_FADDR = address; } int usb_drv_send(int endpoint, void* ptr, int length) { - DEBUGF("usb_drv_send(%d, 0x%x, %d)", endpoint, (int)ptr, length); + logf("usb_drv_send(%d, 0x%x, %d)", endpoint, (int)ptr, length); if(endpoint == EP_CONTROL && ptr == NULL && length == 0) /* ACK request */ return 0; @@ -451,7 +451,7 @@ int usb_drv_send(int endpoint, void* ptr, int length) int usb_drv_recv(int endpoint, void* ptr, int length) { - DEBUGF("usb_drv_recv(%d, 0x%x, %d)", endpoint, (int)ptr, length); + logf("usb_drv_recv(%d, 0x%x, %d)", endpoint, (int)ptr, length); if(endpoint == EP_CONTROL && ptr == NULL && length == 0) /* ACK request */ return 0; @@ -461,7 +461,7 @@ int usb_drv_recv(int endpoint, void* ptr, int length) void usb_drv_set_test_mode(int mode) { - DEBUGF("usb_drv_set_test_mode(%d)", mode); + logf("usb_drv_set_test_mode(%d)", mode); switch(mode) { @@ -490,7 +490,7 @@ int usb_drv_port_speed(void) void usb_drv_cancel_all_transfers(void) { - DEBUGF("usb_drv_cancel_all_transfers()"); + logf("usb_drv_cancel_all_transfers()"); unsigned int i; for(i=0; i