summaryrefslogtreecommitdiffstats
path: root/firmware/target
diff options
context:
space:
mode:
authorMaurus Cuelenaere <mcuelenaere@gmail.com>2008-12-03 00:20:24 +0000
committerMaurus Cuelenaere <mcuelenaere@gmail.com>2008-12-03 00:20:24 +0000
commit815998c6693998b7d7a3a523058ff0988e735d27 (patch)
tree1ad06d79a90b946362f79d5c73dbe77d8f101ba4 /firmware/target
parent0e97b1a1ebf205f33e80266f06d75bf71aa73de7 (diff)
downloadrockbox-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
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/mips/ingenic_jz47xx/lcd-jz4740.c54
-rw-r--r--firmware/target/mips/ingenic_jz47xx/system-jz4740.c11
-rw-r--r--firmware/target/mips/ingenic_jz47xx/system-target.h3
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