diff options
author | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2008-12-03 00:20:24 +0000 |
---|---|---|
committer | Maurus Cuelenaere <mcuelenaere@gmail.com> | 2008-12-03 00:20:24 +0000 |
commit | 815998c6693998b7d7a3a523058ff0988e735d27 (patch) | |
tree | 1ad06d79a90b946362f79d5c73dbe77d8f101ba4 | |
parent | 0e97b1a1ebf205f33e80266f06d75bf71aa73de7 (diff) | |
download | rockbox-815998c6693998b7d7a3a523058ff0988e735d27.tar.gz rockbox-815998c6693998b7d7a3a523058ff0988e735d27.zip |
Jz4740 targets: make sure you don't yield when in interrupt mode
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19309 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c | 54 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/system-jz4740.c | 11 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/system-target.h | 3 |
3 files changed, 52 insertions, 16 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c b/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c index 72c0268af0..f45ffc0349 100644 --- a/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c @@ -23,7 +23,7 @@ #include "jz4740.h" #include "lcd.h" #include "lcd-target.h" -#include "system-target.h" +#include "system.h" #include "kernel.h" static volatile bool _lcd_on = false; @@ -56,39 +56,63 @@ bool lcd_enabled(void) return _lcd_on; } +/* Don't switch threads when in interrupt mode! */ +static 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 void lcd_unlock(void) +{ + if(LIKELY(!in_interrupt_mode())) + mutex_unlock(&lcd_mtx); + 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) { - mutex_lock(&lcd_mtx); + lcd_lock(); lcd_set_target(x, y, width, height); REG_DMAC_DCCSR(DMA_LCD_CHANNEL) = 0; - 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_DTCR(DMA_LCD_CHANNEL) = width*height; + 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_DTCR(DMA_LCD_CHANNEL) = width*height; - REG_DMAC_DCMD(DMA_LCD_CHANNEL) = (DMAC_DCMD_SAI | DMAC_DCMD_RDIL_IGN | DMAC_DCMD_SWDH_32 /* (1 << 23) | (0 << 16) | (0 << 14) */ - | DMAC_DCMD_DWDH_16 | DMAC_DCMD_DS_16BIT); /* | (2 << 12) | (3 << 8) */ - REG_DMAC_DCCSR(DMA_LCD_CHANNEL) = DMAC_DCCSR_NDES; /* (1 << 31) */ + 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 */ + __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; + REG_SLCD_CTRL |= SLCD_CTRL_DMA_EN; REG_DMAC_DCCSR(DMA_LCD_CHANNEL) |= DMAC_DCCSR_EN; - while( !(REG_DMAC_DCCSR(DMA_LCD_CHANNEL) & DMAC_DCCSR_TT) ) - yield(); + 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)); REG_DMAC_DCCSR(DMA_LCD_CHANNEL) &= ~DMAC_DCCSR_EN; while(REG_SLCD_STATE & SLCD_STATE_BUSY); - REG_SLCD_CTRL = 0; - mutex_unlock(&lcd_mtx); + REG_SLCD_CTRL &= ~SLCD_CTRL_DMA_EN; + + lcd_unlock(); } /* Update the display. diff --git a/firmware/target/mips/ingenic_jz47xx/system-jz4740.c b/firmware/target/mips/ingenic_jz47xx/system-jz4740.c index 89011e1baf..10741024a9 100644 --- a/firmware/target/mips/ingenic_jz47xx/system-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/system-jz4740.c @@ -322,6 +322,13 @@ 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(); @@ -330,7 +337,11 @@ void intr_handler(void) ack_irq(irq); if(irq > 0) + { + intr_mode = true; irqvector[irq-1](); + intr_mode = false; + } } #define EXC(x,y) if(_cause == (x)) return (y); diff --git a/firmware/target/mips/ingenic_jz47xx/system-target.h b/firmware/target/mips/ingenic_jz47xx/system-target.h index 39bf35bba6..6ab5d02135 100644 --- a/firmware/target/mips/ingenic_jz47xx/system-target.h +++ b/firmware/target/mips/ingenic_jz47xx/system-target.h @@ -67,7 +67,7 @@ static inline int disable_interrupt_save(int mask) unsigned int oldstatus; oldstatus = read_c0_status(); - write_c0_status(oldstatus | mask); + write_c0_status(oldstatus & ~mask); return oldstatus; } @@ -101,6 +101,7 @@ void udelay(unsigned int usec); void mdelay(unsigned int msec); void power_off(void); void system_reboot(void); +bool in_interrupt_mode(void); #define DMA_LCD_CHANNEL 0 #define DMA_NAND_CHANNEL 1 |