diff options
author | Andree Buschmann <AndreeBuschmann@t-online.de> | 2010-12-13 19:58:04 +0000 |
---|---|---|
committer | Andree Buschmann <AndreeBuschmann@t-online.de> | 2010-12-13 19:58:04 +0000 |
commit | 298bbe8d3c1ab612d43a56b659a117d0ef12cd4c (patch) | |
tree | 2e328c12e90a1bb6624a3edb4c256f0b68459e53 | |
parent | 693bf86a25ecf61e6bfa345529ab1bec2d8790f9 (diff) | |
download | rockbox-298bbe8d3c1ab612d43a56b659a117d0ef12cd4c.tar.gz rockbox-298bbe8d3c1ab612d43a56b659a117d0ef12cd4c.zip |
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-x | firmware/target/arm/s5l8700/ipodnano2g/lcd-asm-nano2g.S | 36 | ||||
-rw-r--r-- | firmware/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 @@ | |||
22 | #include "config.h" | 22 | #include "config.h" |
23 | 23 | ||
24 | .section .icode, "ax", %progbits | 24 | .section .icode, "ax", %progbits |
25 | |||
26 | /**************************************************************************** | ||
27 | * void lcd_write_line(const fb_data *addr, | ||
28 | * int pixelcount, | ||
29 | * const unsigned int lcd_base_addr); | ||
30 | * | ||
31 | * Writes pixelcount pixels from src-pointer (lcd_framebuffer) to LCD dataport. | ||
32 | */ | ||
33 | .align 2 | ||
34 | .global lcd_write_line | ||
35 | .type lcd_write_line, %function | ||
36 | /* r0 = addr, must be aligned */ | ||
37 | /* r1 = pixel count, must be even */ | ||
38 | lcd_write_line: /* r2 = LCD_BASE */ | ||
39 | stmfd sp!, {r4-r6, lr} /* save non-scratch registers */ | ||
40 | add r12, r2, #0x40 /* LCD_WDATA = LCD data port */ | ||
41 | |||
42 | .loop: | ||
43 | ldmia r0!, {r3, r5} /* read 2 pixel (=8 byte) */ | ||
44 | |||
45 | /* wait for FIFO half full */ | ||
46 | .fifo_wait: | ||
47 | ldr lr, [r2, #0x1C] /* while (LCD_STATUS & 0x08); */ | ||
48 | tst lr, #0x8 | ||
49 | bgt .fifo_wait | ||
50 | |||
51 | mov r4, r3, asr #16 /* r3 = 1st pixel, r4 = 2nd pixel */ | ||
52 | mov r6, r5, asr #16 /* r5 = 3rd pixel, r6 = 4th pixel */ | ||
53 | stmia r12, {r3-r6} /* write pixels (lowest 16 bit used) */ | ||
54 | |||
55 | subs r1, r1, #4 | ||
56 | bgt .loop | ||
57 | |||
58 | ldmpc regs=r4-r6 | ||
25 | 59 | ||
26 | /**************************************************************************** | 60 | /**************************************************************************** |
27 | * extern void lcd_write_yuv420_lines(unsigned char const * const src[3], | 61 | * extern void lcd_write_yuv420_lines(unsigned char const * const src[3], |
28 | * unsigned LCD_BASE, | 62 | * const unsigned LCD_BASE, |
29 | * int width, | 63 | * int width, |
30 | * int stride); | 64 | * int stride); |
31 | * | 65 | * |
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) | |||
312 | PCON13 &= ~0xf; /* Set pin 0 to input */ | 312 | PCON13 &= ~0xf; /* Set pin 0 to input */ |
313 | PCON14 &= ~0xf0; /* Set pin 1 to input */ | 313 | PCON14 &= ~0xf0; /* Set pin 1 to input */ |
314 | 314 | ||
315 | if (((PDAT13 & 1) == 0) && ((PDAT14 & 2) == 2)) | 315 | if (((PDAT13 & 1) == 0) && ((PDAT14 & 2) == 2)) { |
316 | lcd_type = 0; /* Similar to ILI9320 - aka "type 2" */ | 316 | lcd_type = 0; /* Similar to ILI9320 - aka "type 2" */ |
317 | else | 317 | } else { |
318 | lcd_type = 1; /* Similar to LDS176 - aka "type 7" */ | 318 | lcd_type = 1; /* Similar to LDS176 - aka "type 7" */ |
319 | LCD_PHTIME = 0x22; /* Set Phase Time reg (relevant for LCD IF speed) */ | ||
320 | } | ||
319 | 321 | ||
320 | LCD_CON |= 0x100; /* use 16 bit bus width, little endian */ | 322 | LCD_CON |= 0x100; /* use 16 bit bus width, little endian */ |
321 | 323 | ||
@@ -337,6 +339,11 @@ void lcd_update(void) | |||
337 | lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); | 339 | lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); |
338 | } | 340 | } |
339 | 341 | ||
342 | /* Line write helper function. */ | ||
343 | extern void lcd_write_line(const fb_data *addr, | ||
344 | int pixelcount, | ||
345 | const unsigned int lcd_base_addr); | ||
346 | |||
340 | /* Update a fraction of the display. */ | 347 | /* Update a fraction of the display. */ |
341 | void lcd_update_rect(int, int, int, int) ICODE_ATTR; | 348 | void lcd_update_rect(int, int, int, int) ICODE_ATTR; |
342 | void lcd_update_rect(int x, int y, int width, int height) | 349 | 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) | |||
344 | int y0, x0, y1, x1; | 351 | int y0, x0, y1, x1; |
345 | fb_data* p; | 352 | fb_data* p; |
346 | 353 | ||
347 | width = (width + 1) & ~1; /* ensure width is even */ | 354 | /* Both x and width need to be preprocessed due to asm optimizations */ |
355 | x = x & ~1; /* ensure x is even */ | ||
356 | width = (width + 3) & ~3; /* ensure width is a multiple of 4 */ | ||
348 | 357 | ||
349 | x0 = x; /* start horiz */ | 358 | x0 = x; /* start horiz */ |
350 | y0 = y; /* start vert */ | 359 | y0 = y; /* start vert */ |
@@ -376,33 +385,22 @@ void lcd_update_rect(int x, int y, int width, int height) | |||
376 | 385 | ||
377 | /* Copy display bitmap to hardware */ | 386 | /* Copy display bitmap to hardware */ |
378 | p = &lcd_framebuffer[y0][x0]; | 387 | p = &lcd_framebuffer[y0][x0]; |
379 | if (LCD_WIDTH == width) | 388 | if (LCD_WIDTH == width) { |
380 | { | 389 | /* Write all lines at once */ |
381 | x1 = height*LCD_WIDTH/4; | 390 | lcd_write_line(p, height*LCD_WIDTH, LCD_BASE); |
382 | do { | ||
383 | while (LCD_STATUS & 0x08); /* wait while FIFO is half full */ | ||
384 | lcd_write_pixel(*(p++)); | ||
385 | lcd_write_pixel(*(p++)); | ||
386 | lcd_write_pixel(*(p++)); | ||
387 | lcd_write_pixel(*(p++)); | ||
388 | } while (--x1 > 0); | ||
389 | } else { | 391 | } else { |
390 | y1 = height; | 392 | y1 = height; |
391 | do { | 393 | do { |
392 | x1 = width/2; /* width is forced to even to allow speed up */ | 394 | /* Write a single line */ |
393 | do { | 395 | lcd_write_line(p, width, LCD_BASE); |
394 | while (LCD_STATUS & 0x08); /* wait while FIFO is half full */ | 396 | p += LCD_WIDTH; |
395 | lcd_write_pixel(*(p++)); | ||
396 | lcd_write_pixel(*(p++)); | ||
397 | } while (--x1 > 0 ); | ||
398 | p += LCD_WIDTH - width; | ||
399 | } while (--y1 > 0 ); | 397 | } while (--y1 > 0 ); |
400 | } | 398 | } |
401 | } | 399 | } |
402 | 400 | ||
403 | /* Line write helper function for lcd_yuv_blit. Writes two lines of yuv420. */ | 401 | /* Line write helper function for lcd_yuv_blit. Writes two lines of yuv420. */ |
404 | extern void lcd_write_yuv420_lines(unsigned char const * const src[3], | 402 | extern void lcd_write_yuv420_lines(unsigned char const * const src[3], |
405 | unsigned lcd_baseadress, | 403 | const unsigned int lcd_baseadress, |
406 | int width, | 404 | int width, |
407 | int stride); | 405 | int stride); |
408 | 406 | ||