mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-11-09 21:22:39 -05:00
HD200 - Use DMA transfers in lcd_update() and lcd_update_rect(). Gives 12-26% speedup.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27757 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
33a5f1a2bb
commit
a86b08e4fa
1 changed files with 87 additions and 17 deletions
|
|
@ -55,6 +55,13 @@ static bool cached_invert = false;
|
||||||
static bool cached_flip = false;
|
static bool cached_flip = false;
|
||||||
static int cached_contrast = DEFAULT_CONTRAST_SETTING;
|
static int cached_contrast = DEFAULT_CONTRAST_SETTING;
|
||||||
|
|
||||||
|
static struct mutex lcd_mtx; /* The update functions use DMA and yield */
|
||||||
|
|
||||||
|
volatile unsigned char page IBSS_ATTR;
|
||||||
|
unsigned char column IBSS_ATTR;
|
||||||
|
unsigned int dma_len IBSS_ATTR;
|
||||||
|
volatile unsigned long dma_count IBSS_ATTR;
|
||||||
|
|
||||||
/*** hardware configuration ***/
|
/*** hardware configuration ***/
|
||||||
int lcd_default_contrast(void)
|
int lcd_default_contrast(void)
|
||||||
{
|
{
|
||||||
|
|
@ -155,24 +162,72 @@ void lcd_init_device(void)
|
||||||
lcd_set_contrast(cached_contrast);
|
lcd_set_contrast(cached_contrast);
|
||||||
lcd_set_invert_display(cached_invert);
|
lcd_set_invert_display(cached_invert);
|
||||||
|
|
||||||
|
/* Configure DMA3 */
|
||||||
|
DAR3 = 0xf0000002;
|
||||||
|
DSR3 = 1;
|
||||||
|
DIVR3 = 57; /* DMA3 is mapped into vector 57 in system.c */
|
||||||
|
ICR9 = (6 << 2); /* Enable DMA3 interrupt at level 6, priority 0 */
|
||||||
|
and_l(~(1<<17), &IMR);
|
||||||
|
|
||||||
|
mutex_init(&lcd_mtx);
|
||||||
|
|
||||||
lcd_update();
|
lcd_update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* LCD DMA ISR */
|
||||||
|
void DMA3(void) __attribute__ ((interrupt_handler, section(".icode")));
|
||||||
|
void DMA3(void)
|
||||||
|
{
|
||||||
|
DSR3 = 1;
|
||||||
|
|
||||||
|
if (--dma_count > 0)
|
||||||
|
{
|
||||||
|
/* Setup write address in lcd controller ram*/
|
||||||
|
lcd_write_command(LCD_SET_PAGE | ++page);
|
||||||
|
lcd_write_command_e(LCD_SET_COLUMN | ((column >> 4) & 0xf),
|
||||||
|
column & 0x0f);
|
||||||
|
|
||||||
|
SAR3 = (unsigned long)&lcd_framebuffer[page][column];
|
||||||
|
BCR3 = dma_len;
|
||||||
|
DCR3 = DMA_INT | DMA_AA | DMA_BWC(1)
|
||||||
|
| DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE)
|
||||||
|
| DMA_DSIZE(DMA_SIZE_BYTE) | DMA_START;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Update the display.
|
/* Update the display.
|
||||||
This must be called after all other LCD functions that change the display. */
|
This must be called after all other LCD functions that change the display. */
|
||||||
void lcd_update(void) ICODE_ATTR;
|
void lcd_update(void) ICODE_ATTR;
|
||||||
void lcd_update(void)
|
void lcd_update(void)
|
||||||
{
|
{
|
||||||
int y;
|
mutex_lock(&lcd_mtx);
|
||||||
|
|
||||||
for(y = 0;y < LCD_FBHEIGHT;y++)
|
/* Setup initial address in lcd controller */
|
||||||
{
|
lcd_write_command(LCD_SET_PAGE | 0);
|
||||||
lcd_write_command(LCD_SET_PAGE | y);
|
|
||||||
lcd_write_command_e(LCD_SET_COLUMN, 0);
|
lcd_write_command_e(LCD_SET_COLUMN, 0);
|
||||||
lcd_write_data(lcd_framebuffer[y], LCD_WIDTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Initial lcd ram address */
|
||||||
|
page = 0;
|
||||||
|
column = 0;
|
||||||
|
|
||||||
|
/* Number of pages to address */
|
||||||
|
dma_count = LCD_FBHEIGHT;
|
||||||
|
|
||||||
|
/* Transfer size in bytes to the given page */
|
||||||
|
dma_len = LCD_WIDTH*2;
|
||||||
|
|
||||||
|
/* Initialize DMA transfer */
|
||||||
|
SAR3 = (unsigned long)lcd_framebuffer;
|
||||||
|
BCR3 = LCD_WIDTH*2;
|
||||||
|
DCR3 = DMA_INT | DMA_AA | DMA_BWC(1)
|
||||||
|
| DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE)
|
||||||
|
| DMA_DSIZE(DMA_SIZE_BYTE) | DMA_START;
|
||||||
|
|
||||||
|
while (dma_count > 0)
|
||||||
|
yield();
|
||||||
|
|
||||||
|
mutex_unlock(&lcd_mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update a fraction of the display. */
|
/* Update a fraction of the display. */
|
||||||
|
|
@ -191,16 +246,31 @@ void lcd_update_rect(int x, int y, int width, int height)
|
||||||
if (width <= 0)
|
if (width <= 0)
|
||||||
return; /* nothing left to do, 0 is harmful to lcd_write_data() */
|
return; /* nothing left to do, 0 is harmful to lcd_write_data() */
|
||||||
|
|
||||||
|
mutex_lock(&lcd_mtx);
|
||||||
|
|
||||||
if (ymax >= LCD_FBHEIGHT)
|
if (ymax >= LCD_FBHEIGHT)
|
||||||
ymax = LCD_FBHEIGHT-1;
|
ymax = LCD_FBHEIGHT-1;
|
||||||
|
|
||||||
/* Copy specified rectange bitmap to hardware */
|
/* Initial lcd ram address*/
|
||||||
for (; y <= ymax; y++)
|
|
||||||
{
|
|
||||||
lcd_write_command(LCD_SET_PAGE | y );
|
lcd_write_command(LCD_SET_PAGE | y );
|
||||||
lcd_write_command_e(LCD_SET_COLUMN | ((x >> 4) & 0xf), x & 0x0f);
|
lcd_write_command_e(LCD_SET_COLUMN | ((x >> 4) & 0xf), x & 0x0f);
|
||||||
lcd_write_data (&lcd_framebuffer[y][x], width);
|
|
||||||
}
|
page = y;
|
||||||
|
column = x;
|
||||||
|
dma_len = width*2;
|
||||||
|
dma_count = ymax - y + 1;
|
||||||
|
|
||||||
|
/* Initialize DMA transfer */
|
||||||
|
SAR3 = (unsigned long)&lcd_framebuffer[page][column];
|
||||||
|
BCR3 = dma_len;
|
||||||
|
DCR3 = DMA_INT | DMA_AA | DMA_BWC(1)
|
||||||
|
| DMA_SINC | DMA_SSIZE(DMA_SIZE_LINE)
|
||||||
|
| DMA_DSIZE(DMA_SIZE_BYTE) | DMA_START;
|
||||||
|
|
||||||
|
while (dma_count > 0)
|
||||||
|
yield();
|
||||||
|
|
||||||
|
mutex_unlock(&lcd_mtx);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue