summaryrefslogtreecommitdiff
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
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
-rw-r--r--firmware/SOURCES1
-rw-r--r--firmware/target/arm/philips/hdd6330/lcd-as-hdd6330.S149
-rw-r--r--firmware/target/arm/philips/hdd6330/lcd-hdd6330.c101
3 files changed, 241 insertions, 10 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 349155f8ce..7f21a89771 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -735,6 +735,7 @@ target/arm/philips/fmradio_i2c-hdd.c
735target/arm/philips/hdd6330/backlight-hdd6330.c 735target/arm/philips/hdd6330/backlight-hdd6330.c
736target/arm/philips/hdd6330/button-hdd6330.c 736target/arm/philips/hdd6330/button-hdd6330.c
737target/arm/philips/hdd6330/lcd-hdd6330.c 737target/arm/philips/hdd6330/lcd-hdd6330.c
738target/arm/philips/hdd6330/lcd-as-hdd6330.S
738target/arm/philips/hdd6330/powermgmt-hdd6330.c 739target/arm/philips/hdd6330/powermgmt-hdd6330.c
739target/arm/usb-fw-pp502x.c 740target/arm/usb-fw-pp502x.c
740#endif /* SIMULATOR */ 741#endif /* SIMULATOR */
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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id:$
9 *
10 * Copyright (C) 2010 by Szymon Dziok
11 *
12 * Philips Gogear HDD6330 LCD assembly routine
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23
24#include "config.h"
25#include "cpu.h"
26
27/****************************************************************************
28 void lcd_yuv_write_inner_loop(unsigned char const * const ysrc,
29 unsigned char const * const usrc,
30 unsigned char const * const vsrc,
31 int width);
32*/
33 .section .icode, "ax", %progbits
34 .align 2
35 .global lcd_yuv_write_inner_loop
36 .type lcd_yuv_write_inner_loop, %function
37lcd_yuv_write_inner_loop:
38 @ r0 = ysrc
39 @ r1 = usrc
40 @ r2 = vsrc
41 @ r3 = width
42 stmfd sp!, { r4-r11, lr } @ save regs
43 mov r4, #0x70000000 @ r4 = LCD2_BLOCK_CTRL - 0x20
44 add r4, r4, #0x8a00 @
45 add r5, r4, #0x100 @ r5 = LCD2_BLOCK_DATA
4610: @ loop
47
48 ldrb r7, [r1], #1 @ *usrc++
49 ldrb r8, [r2], #1 @ *vsrc++
50
51 add r10, r8, r8, asl #2 @ 101* vsrc
52 add r10, r10, r8, asl #5
53 add r10, r10, r8, asl #6
54 sub r10, r10, #0x3600
55 sub r10, r10, #0x0020 @ -13856 (ROUNDOFFSR)
56
57 add r11, r8, r8, asl #1 @ 51*vsrc + 24*usrc
58 add r11, r11, r11, asl #4
59 add r11, r11, r7, asl #3
60 add r11, r11, r7, asl #4
61 mov r12, #0x2100
62 add r12, r12, #0x60 @ +8544 (ROUNDOFFSG) - r11
63 rsb r11, r11, r12
64
65 mov r12, r7, asl #7 @ 128 * usrc
66 sub r12, r12, #0x4300
67 sub r12, r12, #0x00a0 @ -17312 (ROUNDOFFSB)
68
69@ pixel_1
70 ldrb r8, [r0], #1 @ *ysrc++
71 mov r7, r8, asl #1
72 add r7, r7, r8, asl #3
73 add r7, r7, r8, asl #6 @ ysrc * 74
74
75 add r9, r10, r7
76 mov r9, r9, asr #9 @ R
77
78 add r8, r11, r7
79 mov r8, r8, asr #8 @ G
80
81 add r7, r12, r7
82 mov r7, r7, asr #9 @ B
83
84 cmp r9, #31 @ clamp R
85 mvnhi r9, r9, asr #31
86 andhi r9, r9, #31
87
88 cmp r8, #63 @ clamp G
89 mvnhi r8, r8, asr #31
90 andhi r8, r8, #63
91
92 cmp r7, #31 @ clamp B
93 mvnhi r7, r7, asr #31
94 andhi r7, r7, #31
95
96 orr r6, r7, r8, lsl #5 @ pack pixel
97 orr r6, r6, r9, lsl #11
98
99 mov r7, r6, lsl #8 @ swap bytes
100 and r7, r7, #0xff00
101 add r6, r7, r6, lsr #8
102
103@ pixel_2
104 ldrb r8, [r0], #1 @ *ysrc++
105 mov r7, r8, asl #1
106 add r7, r7, r8, asl #3
107 add r7, r7, r8, asl #6 @ ysrc * 74
108
109 add r9, r10, r7
110 mov r9, r9, asr #9 @ R
111
112 add r8, r11, r7
113 mov r8, r8, asr #8 @ G
114
115 add r7, r12, r7
116 mov r7, r7, asr #9 @ B
117
118 cmp r9, #31 @ clamp R
119 mvnhi r9, r9, asr #31
120 andhi r9, r9, #31
121
122 cmp r8, #63 @ clamp G
123 mvnhi r8, r8, asr #31
124 andhi r8, r8, #63
125
126 cmp r7, #31 @ clamp B
127 mvnhi r7, r7, asr #31
128 andhi r7, r7, #31
129
130 orr r7, r7, r8, lsl #5 @ pack pixel
131 orr r7, r7, r9, lsl #11
132
133 orr r6, r6, r7, lsl #24 @ swap bytes and add pixels simultaneously
134 mov r7, r7, lsr #8
135 orr r6, r6, r7, lsl #16
136
13711: @ while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_TXOK));
138 ldr r11, [r4, #0x20] @
139 tst r11, #0x1000000 @
140 beq 11b @
141
142 str r6, [r5] @ send two pixels
143
144 subs r3, r3, #2 @ decrease width
145 bgt 10b @ loop
146
147 ldmpc regs=r4-r11 @ restore regs
148 .ltorg @ dump constant pool
149 .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)
80 lcd_yuv_options = options; 80 lcd_yuv_options = options;
81} 81}
82 82
83#define CSUB_X 2
84#define CSUB_Y 2
85
86/* YUV- > RGB565 conversion
87 * |R| |1.000000 -0.000001 1.402000| |Y'|
88 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
89 * |B| |1.000000 1.772000 0.000000| |Pr|
90 * Scaled, normalized, rounded and tweaked to yield RGB 565:
91 * |R| |74 0 101| |Y' - 16| >> 9
92 * |G| = |74 -24 -51| |Cb - 128| >> 8
93 * |B| |74 128 0| |Cr - 128| >> 9
94*/
95
96extern void lcd_yuv_write_inner_loop(unsigned char const * const ysrc,
97 unsigned char const * const usrc,
98 unsigned char const * const vsrc,
99 int width);
100
83/* Performance function to blit a YUV bitmap directly to the LCD */ 101/* Performance function to blit a YUV bitmap directly to the LCD */
84void lcd_blit_yuv(unsigned char * const src[3], 102void lcd_blit_yuv(unsigned char * const src[3],
85 int src_x, int src_y, int stride, 103 int src_x, int src_y, int stride,
86 int x, int y, int width, int height) 104 int x, int y, int width, int height)
87{ 105{
88 (void)src; 106 int h;
89 (void)src_x; 107
90 (void)src_y; 108 width = (width + 1) & ~1;
91 (void)stride; 109
92 (void)x; 110 lcd_send_reg(0x01);
93 (void)y; 111 lcd_send_data(0x48);
94 (void)width; 112
95 (void)height; 113 lcd_send_reg(0x05);
114 lcd_send_data(0x0f);
115
116 lcd_send_reg(0x08);
117 lcd_send_data(y);
118
119 lcd_send_reg(0x09);
120 lcd_send_data(y + height - 1);
121
122 lcd_send_reg(0x0a);
123 lcd_send_data(x + 16);
124
125 lcd_send_reg(0x0b);
126 lcd_send_data(x + width - 1 + 16);
127
128 lcd_send_reg(0x06);
129
130 const int stride_div_csub_x = stride/CSUB_X;
131
132 h=0;
133 while (1)
134 {
135 /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
136 const unsigned char *ysrc = src[0] + stride * src_y + src_x;
137
138 const int uvoffset = stride_div_csub_x * (src_y/CSUB_Y) +
139 (src_x/CSUB_X);
140
141 const unsigned char *usrc = src[1] + uvoffset;
142 const unsigned char *vsrc = src[2] + uvoffset;
143
144 int pixels_to_write;
145
146 if (h==0)
147 {
148 while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_READY));
149 LCD2_BLOCK_CONFIG = 0;
150
151 if (height == 0) break;
152
153 pixels_to_write = (width * height) * 2;
154 h = height;
155
156 /* calculate how much we can do in one go */
157 if (pixels_to_write > 0x10000)
158 {
159 h = (0x10000/2) / width;
160 pixels_to_write = (width * h) * 2;
161 }
162
163 height -= h;
164 LCD2_BLOCK_CTRL = 0x10000080;
165 LCD2_BLOCK_CONFIG = 0xc0010000 | (pixels_to_write - 1);
166 LCD2_BLOCK_CTRL = 0x34000000;
167 }
168
169 lcd_yuv_write_inner_loop(ysrc,usrc,vsrc,width);
170
171 src_y++;
172 h--;
173 }
174
175 while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_READY));
176 LCD2_BLOCK_CONFIG = 0;
96} 177}
97 178
98/* Update the display. 179/* Update the display.
99 This must be called after all other LCD functions that change the display. */ 180 This must be called after all other LCD functions that change the display. */
100void lcd_update(void) 181void lcd_update(void)
@@ -146,7 +227,7 @@ void lcd_update_rect(int x, int y, int width, int height)
146 227
147 addr = (unsigned long*)&lcd_framebuffer[y][x]; 228 addr = (unsigned long*)&lcd_framebuffer[y][x];
148 229
149 while (height > 0) 230 while (height > 0)
150 { 231 {
151 int c, r; 232 int c, r;
152 int h, pixels_to_write; 233 int h, pixels_to_write;