From 298bbe8d3c1ab612d43a56b659a117d0ef12cd4c Mon Sep 17 00:00:00 2001 From: Andree Buschmann Date: Mon, 13 Dec 2010 19:58:04 +0000 Subject: 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 --- .../target/arm/s5l8700/ipodnano2g/lcd-asm-nano2g.S | 36 +++++++++++++++++- .../target/arm/s5l8700/ipodnano2g/lcd-nano2g.c | 44 +++++++++++----------- 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 25cf662c3f..3902d34133 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 d1c41d652f..7b177f4fc4 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); -- cgit v1.2.3