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
This commit is contained in:
Maurus Cuelenaere 2008-12-03 00:20:24 +00:00
parent 0e97b1a1eb
commit 815998c669
3 changed files with 52 additions and 16 deletions

View file

@ -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.

View file

@ -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);

View file

@ -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