summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndree Buschmann <AndreeBuschmann@t-online.de>2010-12-13 19:58:04 +0000
committerAndree Buschmann <AndreeBuschmann@t-online.de>2010-12-13 19:58:04 +0000
commit298bbe8d3c1ab612d43a56b659a117d0ef12cd4c (patch)
tree2e328c12e90a1bb6624a3edb4c256f0b68459e53
parent693bf86a25ecf61e6bfa345529ab1bec2d8790f9 (diff)
downloadrockbox-298bbe8d3c1ab612d43a56b659a117d0ef12cd4c.zip
rockbox-298bbe8d3c1ab612d43a56b659a117d0ef12cd4c.tar.gz
rockbox-298bbe8d3c1ab612d43a56b659a117d0ef12cd4c.tar.bz2
rockbox-298bbe8d3c1ab612d43a56b659a117d0ef12cd4c.tar.xz
FS#11807 - Major speedup of iPod nano 2G. Part 5: Introduce asm for RGB screen updates, set LCD_PHTIME to Apple's default for LDS176 type LCD's.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28824 a1c6a512-1295-4272-9138-f99709370657
-rwxr-xr-xfirmware/target/arm/s5l8700/ipodnano2g/lcd-asm-nano2g.S36
-rw-r--r--firmware/target/arm/s5l8700/ipodnano2g/lcd-nano2g.c44
2 files changed, 56 insertions, 24 deletions
diff --git a/firmware/target/arm/s5l8700/ipodnano2g/lcd-asm-nano2g.S b/firmware/target/arm/s5l8700/ipodnano2g/lcd-asm-nano2g.S
index 25cf662..3902d34 100755
--- a/firmware/target/arm/s5l8700/ipodnano2g/lcd-asm-nano2g.S
+++ b/firmware/target/arm/s5l8700/ipodnano2g/lcd-asm-nano2g.S
@@ -22,10 +22,44 @@
#include "config.h"
.section .icode, "ax", %progbits
+
+/****************************************************************************
+ * void lcd_write_line(const fb_data *addr,
+ * int pixelcount,
+ * const unsigned int lcd_base_addr);
+ *
+ * Writes pixelcount pixels from src-pointer (lcd_framebuffer) to LCD dataport.
+ */
+ .align 2
+ .global lcd_write_line
+ .type lcd_write_line, %function
+ /* r0 = addr, must be aligned */
+ /* r1 = pixel count, must be even */
+lcd_write_line: /* r2 = LCD_BASE */
+ stmfd sp!, {r4-r6, lr} /* save non-scratch registers */
+ add r12, r2, #0x40 /* LCD_WDATA = LCD data port */
+
+.loop:
+ ldmia r0!, {r3, r5} /* read 2 pixel (=8 byte) */
+
+ /* wait for FIFO half full */
+.fifo_wait:
+ ldr lr, [r2, #0x1C] /* while (LCD_STATUS & 0x08); */
+ tst lr, #0x8
+ bgt .fifo_wait
+
+ mov r4, r3, asr #16 /* r3 = 1st pixel, r4 = 2nd pixel */
+ mov r6, r5, asr #16 /* r5 = 3rd pixel, r6 = 4th pixel */
+ stmia r12, {r3-r6} /* write pixels (lowest 16 bit used) */
+
+ subs r1, r1, #4
+ bgt .loop
+
+ ldmpc regs=r4-r6
/****************************************************************************
* extern void lcd_write_yuv420_lines(unsigned char const * const src[3],
- * unsigned LCD_BASE,
+ * const unsigned LCD_BASE,
* int width,
* int stride);
*
diff --git a/firmware/target/arm/s5l8700/ipodnano2g/lcd-nano2g.c b/firmware/target/arm/s5l8700/ipodnano2g/lcd-nano2g.c
index d1c41d6..7b177f4 100644
--- a/firmware/target/arm/s5l8700/ipodnano2g/lcd-nano2g.c
+++ b/firmware/target/arm/s5l8700/ipodnano2g/lcd-nano2g.c
@@ -312,10 +312,12 @@ void lcd_init_device(void)
PCON13 &= ~0xf; /* Set pin 0 to input */
PCON14 &= ~0xf0; /* Set pin 1 to input */
- if (((PDAT13 & 1) == 0) && ((PDAT14 & 2) == 2))
- lcd_type = 0; /* Similar to ILI9320 - aka "type 2" */
- else
- lcd_type = 1; /* Similar to LDS176 - aka "type 7" */
+ if (((PDAT13 & 1) == 0) && ((PDAT14 & 2) == 2)) {
+ lcd_type = 0; /* Similar to ILI9320 - aka "type 2" */
+ } else {
+ lcd_type = 1; /* Similar to LDS176 - aka "type 7" */
+ LCD_PHTIME = 0x22; /* Set Phase Time reg (relevant for LCD IF speed) */
+ }
LCD_CON |= 0x100; /* use 16 bit bus width, little endian */
@@ -337,6 +339,11 @@ void lcd_update(void)
lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
}
+/* Line write helper function. */
+extern void lcd_write_line(const fb_data *addr,
+ int pixelcount,
+ const unsigned int lcd_base_addr);
+
/* Update a fraction of the display. */
void lcd_update_rect(int, int, int, int) ICODE_ATTR;
void lcd_update_rect(int x, int y, int width, int height)
@@ -344,7 +351,9 @@ void lcd_update_rect(int x, int y, int width, int height)
int y0, x0, y1, x1;
fb_data* p;
- width = (width + 1) & ~1; /* ensure width is even */
+ /* Both x and width need to be preprocessed due to asm optimizations */
+ x = x & ~1; /* ensure x is even */
+ width = (width + 3) & ~3; /* ensure width is a multiple of 4 */
x0 = x; /* start horiz */
y0 = y; /* start vert */
@@ -376,33 +385,22 @@ void lcd_update_rect(int x, int y, int width, int height)
/* Copy display bitmap to hardware */
p = &lcd_framebuffer[y0][x0];
- if (LCD_WIDTH == width)
- {
- x1 = height*LCD_WIDTH/4;
- do {
- while (LCD_STATUS & 0x08); /* wait while FIFO is half full */
- lcd_write_pixel(*(p++));
- lcd_write_pixel(*(p++));
- lcd_write_pixel(*(p++));
- lcd_write_pixel(*(p++));
- } while (--x1 > 0);
+ if (LCD_WIDTH == width) {
+ /* Write all lines at once */
+ lcd_write_line(p, height*LCD_WIDTH, LCD_BASE);
} else {
y1 = height;
do {
- x1 = width/2; /* width is forced to even to allow speed up */
- do {
- while (LCD_STATUS & 0x08); /* wait while FIFO is half full */
- lcd_write_pixel(*(p++));
- lcd_write_pixel(*(p++));
- } while (--x1 > 0 );
- p += LCD_WIDTH - width;
+ /* Write a single line */
+ lcd_write_line(p, width, LCD_BASE);
+ p += LCD_WIDTH;
} while (--y1 > 0 );
}
}
/* Line write helper function for lcd_yuv_blit. Writes two lines of yuv420. */
extern void lcd_write_yuv420_lines(unsigned char const * const src[3],
- unsigned lcd_baseadress,
+ const unsigned int lcd_baseadress,
int width,
int stride);