summaryrefslogtreecommitdiffstats
path: root/firmware/target/arm/philips
diff options
context:
space:
mode:
authorSzymon Dziok <b0hoon@o2.pl>2010-12-05 19:45:50 +0000
committerSzymon Dziok <b0hoon@o2.pl>2010-12-05 19:45:50 +0000
commit32a0ce375f018e0948d22d863199e85ece4bfff8 (patch)
tree5d582e03e49e400d445c9c0f23e182e790524b6d /firmware/target/arm/philips
parent516693fcc9a35eeae86422a17ac9d2be4bbe899c (diff)
downloadrockbox-32a0ce375f018e0948d22d863199e85ece4bfff8.tar.gz
rockbox-32a0ce375f018e0948d22d863199e85ece4bfff8.zip
HDD6330: implement lcd_yuv_blit() function. The inner loop is written in assembler and the entire function is about 20% faster than the original from the ipod color.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28737 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/philips')
-rw-r--r--firmware/target/arm/philips/hdd6330/lcd-as-hdd6330.S149
-rw-r--r--firmware/target/arm/philips/hdd6330/lcd-hdd6330.c101
2 files changed, 240 insertions, 10 deletions
diff --git a/firmware/target/arm/philips/hdd6330/lcd-as-hdd6330.S b/firmware/target/arm/philips/hdd6330/lcd-as-hdd6330.S
new file mode 100644
index 0000000000..364eb5b08f
--- /dev/null
+++ b/firmware/target/arm/philips/hdd6330/lcd-as-hdd6330.S
@@ -0,0 +1,149 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id:$
+ *
+ * Copyright (C) 2010 by Szymon Dziok
+ *
+ * Philips Gogear HDD6330 LCD assembly routine
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+#include "cpu.h"
+
+/****************************************************************************
+ void lcd_yuv_write_inner_loop(unsigned char const * const ysrc,
+ unsigned char const * const usrc,
+ unsigned char const * const vsrc,
+ int width);
+*/
+ .section .icode, "ax", %progbits
+ .align 2
+ .global lcd_yuv_write_inner_loop
+ .type lcd_yuv_write_inner_loop, %function
+lcd_yuv_write_inner_loop:
+ @ r0 = ysrc
+ @ r1 = usrc
+ @ r2 = vsrc
+ @ r3 = width
+ stmfd sp!, { r4-r11, lr } @ save regs
+ mov r4, #0x70000000 @ r4 = LCD2_BLOCK_CTRL - 0x20
+ add r4, r4, #0x8a00 @
+ add r5, r4, #0x100 @ r5 = LCD2_BLOCK_DATA
+10: @ loop
+
+ ldrb r7, [r1], #1 @ *usrc++
+ ldrb r8, [r2], #1 @ *vsrc++
+
+ add r10, r8, r8, asl #2 @ 101* vsrc
+ add r10, r10, r8, asl #5
+ add r10, r10, r8, asl #6
+ sub r10, r10, #0x3600
+ sub r10, r10, #0x0020 @ -13856 (ROUNDOFFSR)
+
+ add r11, r8, r8, asl #1 @ 51*vsrc + 24*usrc
+ add r11, r11, r11, asl #4
+ add r11, r11, r7, asl #3
+ add r11, r11, r7, asl #4
+ mov r12, #0x2100
+ add r12, r12, #0x60 @ +8544 (ROUNDOFFSG) - r11
+ rsb r11, r11, r12
+
+ mov r12, r7, asl #7 @ 128 * usrc
+ sub r12, r12, #0x4300
+ sub r12, r12, #0x00a0 @ -17312 (ROUNDOFFSB)
+
+@ pixel_1
+ ldrb r8, [r0], #1 @ *ysrc++
+ mov r7, r8, asl #1
+ add r7, r7, r8, asl #3
+ add r7, r7, r8, asl #6 @ ysrc * 74
+
+ add r9, r10, r7
+ mov r9, r9, asr #9 @ R
+
+ add r8, r11, r7
+ mov r8, r8, asr #8 @ G
+
+ add r7, r12, r7
+ mov r7, r7, asr #9 @ B
+
+ cmp r9, #31 @ clamp R
+ mvnhi r9, r9, asr #31
+ andhi r9, r9, #31
+
+ cmp r8, #63 @ clamp G
+ mvnhi r8, r8, asr #31
+ andhi r8, r8, #63
+
+ cmp r7, #31 @ clamp B
+ mvnhi r7, r7, asr #31
+ andhi r7, r7, #31
+
+ orr r6, r7, r8, lsl #5 @ pack pixel
+ orr r6, r6, r9, lsl #11
+
+ mov r7, r6, lsl #8 @ swap bytes
+ and r7, r7, #0xff00
+ add r6, r7, r6, lsr #8
+
+@ pixel_2
+ ldrb r8, [r0], #1 @ *ysrc++
+ mov r7, r8, asl #1
+ add r7, r7, r8, asl #3
+ add r7, r7, r8, asl #6 @ ysrc * 74
+
+ add r9, r10, r7
+ mov r9, r9, asr #9 @ R
+
+ add r8, r11, r7
+ mov r8, r8, asr #8 @ G
+
+ add r7, r12, r7
+ mov r7, r7, asr #9 @ B
+
+ cmp r9, #31 @ clamp R
+ mvnhi r9, r9, asr #31
+ andhi r9, r9, #31
+
+ cmp r8, #63 @ clamp G
+ mvnhi r8, r8, asr #31
+ andhi r8, r8, #63
+
+ cmp r7, #31 @ clamp B
+ mvnhi r7, r7, asr #31
+ andhi r7, r7, #31
+
+ orr r7, r7, r8, lsl #5 @ pack pixel
+ orr r7, r7, r9, lsl #11
+
+ orr r6, r6, r7, lsl #24 @ swap bytes and add pixels simultaneously
+ mov r7, r7, lsr #8
+ orr r6, r6, r7, lsl #16
+
+11: @ while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_TXOK));
+ ldr r11, [r4, #0x20] @
+ tst r11, #0x1000000 @
+ beq 11b @
+
+ str r6, [r5] @ send two pixels
+
+ subs r3, r3, #2 @ decrease width
+ bgt 10b @ loop
+
+ ldmpc regs=r4-r11 @ restore regs
+ .ltorg @ dump constant pool
+ .size lcd_yuv_write_inner_loop, .-lcd_yuv_write_inner_loop
diff --git a/firmware/target/arm/philips/hdd6330/lcd-hdd6330.c b/firmware/target/arm/philips/hdd6330/lcd-hdd6330.c
index c8127c4450..53c0be1d6e 100644
--- a/firmware/target/arm/philips/hdd6330/lcd-hdd6330.c
+++ b/firmware/target/arm/philips/hdd6330/lcd-hdd6330.c
@@ -80,21 +80,102 @@ void lcd_yuv_set_options(unsigned options)
lcd_yuv_options = options;
}
+#define CSUB_X 2
+#define CSUB_Y 2
+
+/* YUV- > RGB565 conversion
+ * |R| |1.000000 -0.000001 1.402000| |Y'|
+ * |G| = |1.000000 -0.334136 -0.714136| |Pb|
+ * |B| |1.000000 1.772000 0.000000| |Pr|
+ * Scaled, normalized, rounded and tweaked to yield RGB 565:
+ * |R| |74 0 101| |Y' - 16| >> 9
+ * |G| = |74 -24 -51| |Cb - 128| >> 8
+ * |B| |74 128 0| |Cr - 128| >> 9
+*/
+
+extern void lcd_yuv_write_inner_loop(unsigned char const * const ysrc,
+ unsigned char const * const usrc,
+ unsigned char const * const vsrc,
+ int width);
+
/* Performance function to blit a YUV bitmap directly to the LCD */
void lcd_blit_yuv(unsigned char * const src[3],
int src_x, int src_y, int stride,
int x, int y, int width, int height)
{
- (void)src;
- (void)src_x;
- (void)src_y;
- (void)stride;
- (void)x;
- (void)y;
- (void)width;
- (void)height;
+ int h;
+
+ width = (width + 1) & ~1;
+
+ lcd_send_reg(0x01);
+ lcd_send_data(0x48);
+
+ lcd_send_reg(0x05);
+ lcd_send_data(0x0f);
+
+ lcd_send_reg(0x08);
+ lcd_send_data(y);
+
+ lcd_send_reg(0x09);
+ lcd_send_data(y + height - 1);
+
+ lcd_send_reg(0x0a);
+ lcd_send_data(x + 16);
+
+ lcd_send_reg(0x0b);
+ lcd_send_data(x + width - 1 + 16);
+
+ lcd_send_reg(0x06);
+
+ const int stride_div_csub_x = stride/CSUB_X;
+
+ h=0;
+ while (1)
+ {
+ /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
+ const unsigned char *ysrc = src[0] + stride * src_y + src_x;
+
+ const int uvoffset = stride_div_csub_x * (src_y/CSUB_Y) +
+ (src_x/CSUB_X);
+
+ const unsigned char *usrc = src[1] + uvoffset;
+ const unsigned char *vsrc = src[2] + uvoffset;
+
+ int pixels_to_write;
+
+ if (h==0)
+ {
+ while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_READY));
+ LCD2_BLOCK_CONFIG = 0;
+
+ if (height == 0) break;
+
+ pixels_to_write = (width * height) * 2;
+ h = height;
+
+ /* calculate how much we can do in one go */
+ if (pixels_to_write > 0x10000)
+ {
+ h = (0x10000/2) / width;
+ pixels_to_write = (width * h) * 2;
+ }
+
+ height -= h;
+ LCD2_BLOCK_CTRL = 0x10000080;
+ LCD2_BLOCK_CONFIG = 0xc0010000 | (pixels_to_write - 1);
+ LCD2_BLOCK_CTRL = 0x34000000;
+ }
+
+ lcd_yuv_write_inner_loop(ysrc,usrc,vsrc,width);
+
+ src_y++;
+ h--;
+ }
+
+ while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_READY));
+ LCD2_BLOCK_CONFIG = 0;
}
-
+
/* Update the display.
This must be called after all other LCD functions that change the display. */
void lcd_update(void)
@@ -146,7 +227,7 @@ void lcd_update_rect(int x, int y, int width, int height)
addr = (unsigned long*)&lcd_framebuffer[y][x];
- while (height > 0)
+ while (height > 0)
{
int c, r;
int h, pixels_to_write;