summaryrefslogtreecommitdiff
path: root/firmware/target/arm/sandisk/sansa-c200
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/sandisk/sansa-c200')
-rw-r--r--firmware/target/arm/sandisk/sansa-c200/lcd-as-c200.S243
-rw-r--r--firmware/target/arm/sandisk/sansa-c200/lcd-c200.c49
2 files changed, 284 insertions, 8 deletions
diff --git a/firmware/target/arm/sandisk/sansa-c200/lcd-as-c200.S b/firmware/target/arm/sandisk/sansa-c200/lcd-as-c200.S
new file mode 100644
index 0000000000..9b0cd75bae
--- /dev/null
+++ b/firmware/target/arm/sandisk/sansa-c200/lcd-as-c200.S
@@ -0,0 +1,243 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 by Jens Arnold
11 * Heavily based on lcd-as-memframe.c by Michael Sevakis
12 *
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
20
21#include "config.h"
22#include "cpu.h"
23
24/****************************************************************************
25 * void lcd_write_yuv_420_lines(unsigned char const * const src[3],
26 * int width,
27 * int stride);
28 *
29 * |R| |1.000000 -0.000001 1.402000| |Y'|
30 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
31 * |B| |1.000000 1.772000 0.000000| |Pr|
32 * Scaled, normalized, rounded and tweaked to yield RGB 565:
33 * |R| |74 0 101| |Y' - 16| >> 9
34 * |G| = |74 -24 -51| |Cb - 128| >> 8
35 * |B| |74 128 0| |Cr - 128| >> 9
36 *
37 * Write four RGB565 pixels in the following order on each loop:
38 * 1 3 + > down
39 * 2 4 \/ left
40 */
41 .section .icode, "ax", %progbits
42 .align 2
43 .global lcd_write_yuv420_lines
44 .type lcd_write_yuv420_lines, %function
45lcd_write_yuv420_lines:
46 @ r0 = yuv_src
47 @ r1 = width
48 @ r2 = stride
49 stmfd sp!, { r4-r12 } @ save non-scratch
50 ldmia r0, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p
51 @ r5 = yuv_src[1] = Cb_p
52 @ r6 = yuv_src[2] = Cr_p
53 @ r0 = scratch
54 sub r2, r2, #1 @
55 mov r3, #0x70000000 @
56 orr r3, r3, #0x3000 @ r3 = LCD1_BASE
5710: @ loop line @
58 ldrb r7, [r4], #1 @ r7 = *Y'_p++;
59 ldrb r8, [r5], #1 @ r8 = *Cb_p++;
60 ldrb r9, [r6], #1 @ r9 = *Cr_p++;
61 @
62 sub r7, r7, #16 @ r7 = Y = (Y' - 16)*74
63 add r12, r7, r7, asl #2 @ actually (Y' - 16)*37 and shift right
64 add r7, r12, r7, asl #5 @ by one less when adding - same for all
65 @
66 sub r8, r8, #128 @ Cb -= 128
67 sub r9, r9, #128 @ Cr -= 128
68 @
69 add r10, r9, r9, asl #1 @ r10 = Cr*51 + Cb*24
70 add r10, r10, r10, asl #4 @
71 add r10, r10, r8, asl #3 @
72 add r10, r10, r8, asl #4 @
73 @
74 add r11, r9, r9, asl #2 @ r9 = Cr*101
75 add r11, r11, r9, asl #5 @
76 add r9, r11, r9, asl #6 @
77 @
78 add r8, r8, #2 @ r8 = bu = (Cb*128 + 128) >> 8
79 mov r8, r8, asr #2 @
80 add r9, r9, #256 @ r9 = rv = (r9 + 256) >> 9
81 mov r9, r9, asr #9 @
82 rsb r10, r10, #128 @ r10 = guv = (-r10 + 128) >> 8
83 mov r10, r10, asr #8 @
84 @ compute R, G, and B
85 add r0, r8, r7, asr #8 @ r0 = b = (Y >> 9) + bu
86 add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv
87 add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv
88 @
89 orr r12, r0, r11 @ check if clamping is needed...
90 orr r12, r12, r7, asr #1 @ ...at all
91 cmp r12, #31 @
92 bls 15f @ no clamp @
93 cmp r0, #31 @ clamp b
94 mvnhi r0, r0, asr #31 @
95 andhi r0, r0, #31 @
96 cmp r11, #31 @ clamp r
97 mvnhi r11, r11, asr #31 @
98 andhi r11, r11, #31 @
99 cmp r7, #63 @ clamp g
100 mvnhi r7, r7, asr #31 @
101 andhi r7, r7, #63 @
10215: @ no clamp @
103 @
104 ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride)
105 @
106 mov r11, r11, lsl #3 @
107 orr r11, r11, r7, lsr #3 @ r11 = (r << 3) | (g >> 3)
108 orr r0, r0, r7, lsl #5 @ r0 = (g << 5) | b
1091: @ busy @
110 ldr r7, [r3] @ r7 = LCD1_BASE
111 tst r7, #LCD1_BUSY_MASK @ bridge busy?
112 bne 1b @
113 str r11, [r3, #0x10] @ send MSB
1141: @busy @
115 ldr r7, [r3] @ r7 = LCD1_BASE
116 tst r7, #LCD1_BUSY_MASK @ bridge busy?
117 bne 1b @
118 str r0, [r3, #0x10] @ send LSB
119 @
120 sub r7, r12, #16 @ r7 = Y = (Y' - 16)*74
121 add r12, r7, r7, asl #2 @
122 add r7, r12, r7, asl #5 @
123 @ compute R, G, and B
124 add r0, r8, r7, asr #8 @ r0 = b = (Y >> 9) + bu
125 add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv
126 add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv
127 @
128 orr r12, r0, r11 @ check if clamping is needed...
129 orr r12, r12, r7, asr #1 @ ...at all
130 cmp r12, #31 @
131 bls 15f @ no clamp @
132 cmp r0, #31 @ clamp b
133 mvnhi r0, r0, asr #31 @
134 andhi r0, r0, #31 @
135 cmp r11, #31 @ clamp r
136 mvnhi r11, r11, asr #31 @
137 andhi r11, r11, #31 @
138 cmp r7, #63 @ clamp g
139 mvnhi r7, r7, asr #31 @
140 andhi r7, r7, #63 @
14115: @ no clamp @
142 @
143 ldrb r12, [r4], #1 @ r12 = Y' = *(Y'_p++)
144 @
145 mov r11, r11, lsl #3 @
146 orr r11, r11, r7, lsr #3 @ r11 = (r << 3) | (g >> 3)
147 orr r0, r0, r7, lsl #5 @ r0 = (g << 5) | b
1481: @ busy @
149 ldr r7, [r3] @ r7 = LCD1_BASE
150 tst r7, #LCD1_BUSY_MASK @ bridge busy?
151 bne 1b @
152 str r11, [r3, #0x10] @ send MSB
1531: @ busy @
154 ldr r7, [r3] @ r7 = LCD1_BASE
155 tst r7, #LCD1_BUSY_MASK @ bridge busy?
156 bne 1b @
157 str r0, [r3, #0x10] @ send LSB
158 @
159 sub r7, r12, #16 @ r7 = Y = (Y' - 16)*74
160 add r12, r7, r7, asl #2 @
161 add r7, r12, r7, asl #5 @
162 @ compute R, G, and B
163 add r0, r8, r7, asr #8 @ r0 = b = (Y >> 9) + bu
164 add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv
165 add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv
166 @
167 orr r12, r0, r11 @ check if clamping is needed...
168 orr r12, r12, r7, asr #1 @ ...at all
169 cmp r12, #31 @
170 bls 15f @ no clamp @
171 cmp r0, #31 @ clamp b
172 mvnhi r0, r0, asr #31 @
173 andhi r0, r0, #31 @
174 cmp r11, #31 @ clamp r
175 mvnhi r11, r11, asr #31 @
176 andhi r11, r11, #31 @
177 cmp r7, #63 @ clamp g
178 mvnhi r7, r7, asr #31 @
179 andhi r7, r7, #63 @
18015: @ no clamp @
181 @
182 ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride)
183 @
184 @
185 mov r11, r11, lsl #3 @
186 orr r11, r11, r7, lsr #3 @ r11 = (r << 3) | (g >> 3)
187 orr r0, r0, r7, lsl #5 @ r0 = (g << 5) | b
1881: @ busy @
189 ldr r7, [r3] @ r7 = LCD1_BASE
190 tst r7, #LCD1_BUSY_MASK @ bridge busy?
191 bne 1b @
192 str r11, [r3, #0x10] @ send MSB
1931: @ busy @
194 ldr r7, [r3] @ r7 = LCD1_BASE
195 tst r7, #LCD1_BUSY_MASK @ bridge busy?
196 bne 1b @
197 str r0, [r3, #0x10] @ send LSB
198 @
199 sub r7, r12, #16 @ r7 = Y = (Y' - 16)*74
200 add r12, r7, r7, asl #2 @
201 add r7, r12, r7, asl #5 @
202 @ compute R, G, and B
203 add r0, r8, r7, asr #8 @ r0 = b = (Y >> 9) + bu
204 add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv
205 add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv
206 @
207 orr r12, r0, r11 @ check if clamping is needed...
208 orr r12, r12, r7, asr #1 @ ...at all
209 cmp r12, #31 @
210 bls 15f @ no clamp @
211 cmp r0, #31 @ clamp b
212 mvnhi r0, r0, asr #31 @
213 andhi r0, r0, #31 @
214 cmp r11, #31 @ clamp r
215 mvnhi r11, r11, asr #31 @
216 andhi r11, r11, #31 @
217 cmp r7, #63 @ clamp g
218 mvnhi r7, r7, asr #31 @
219 andhi r7, r7, #63 @
22015: @ no clamp @
221 @
222 mov r11, r11, lsl #3 @
223 orr r11, r11, r7, lsr #3 @ r11 = (r << 3) | (g >> 3)
224 orr r0, r0, r7, lsl #5 @ r0 = (g << 5) | b
2251: @ busy @
226 ldr r7, [r3] @ r7 = LCD1_BASE
227 tst r7, #LCD1_BUSY_MASK @ bridge busy?
228 bne 1b @
229 str r11, [r3, #0x10] @ send MSB
2301: @ busy @
231 ldr r7, [r3] @ r7 = LCD1_BASE
232 tst r7, #LCD1_BUSY_MASK @ bridge busy?
233 bne 1b @
234 str r0, [r3, #0x10] @ send LSB
235 @
236 subs r1, r1, #2 @ subtract block from width
237 bgt 10b @ loop line @
238 @
239 ldmfd sp!, { r4-r12 } @ restore registers and return
240 bx lr @
241 .ltorg @ dump constant pool
242 .size lcd_write_yuv420_lines, .-lcd_write_yuv420_lines
243
diff --git a/firmware/target/arm/sandisk/sansa-c200/lcd-c200.c b/firmware/target/arm/sandisk/sansa-c200/lcd-c200.c
index ef336b46c0..d503fd2c9b 100644
--- a/firmware/target/arm/sandisk/sansa-c200/lcd-c200.c
+++ b/firmware/target/arm/sandisk/sansa-c200/lcd-c200.c
@@ -206,19 +206,49 @@ void lcd_blit(const fb_data* data, int x, int by, int width,
206 (void)stride; 206 (void)stride;
207} 207}
208 208
209/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
210extern void lcd_write_yuv420_lines(unsigned char const * const src[3],
211 int width,
212 int stride);
209/* Performance function to blit a YUV bitmap directly to the LCD */ 213/* Performance function to blit a YUV bitmap directly to the LCD */
210void lcd_yuv_blit(unsigned char * const src[3], 214void lcd_yuv_blit(unsigned char * const src[3],
211 int src_x, int src_y, int stride, 215 int src_x, int src_y, int stride,
212 int x, int y, int width, int height) 216 int x, int y, int width, int height)
213{ 217{
214 (void)src; 218 unsigned char const * yuv_src[3];
215 (void)src_x; 219 off_t z;
216 (void)src_y; 220
217 (void)stride; 221 /* Sorry, but width and height must be >= 2 or else */
218 (void)x; 222 width &= ~1;
219 (void)y; 223 height >>= 1;
220 (void)width; 224
221 (void)height; 225 y += 0x1a;
226
227 z = stride*src_y;
228 yuv_src[0] = src[0] + z + src_x;
229 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
230 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
231
232 lcd_send_command(R_ENTRY_MODE);
233 lcd_send_command(0x80);
234
235 lcd_send_command(R_X_ADDR_AREA);
236 lcd_send_command(x);
237 lcd_send_command(x + width - 1);
238
239 do
240 {
241 lcd_send_command(R_Y_ADDR_AREA);
242 lcd_send_command(y);
243 lcd_send_command(y + 1);
244
245 lcd_write_yuv420_lines(yuv_src, width, stride);
246 yuv_src[0] += stride << 1; /* Skip down two luma lines */
247 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
248 yuv_src[2] += stride >> 1;
249 y += 2;
250 }
251 while (--height > 0);
222} 252}
223 253
224/* Update the display. 254/* Update the display.
@@ -239,6 +269,9 @@ void lcd_update_rect(int x0, int y0, int width, int height)
239 if ((x1 <= 0) || (y1 <= 0)) 269 if ((x1 <= 0) || (y1 <= 0))
240 return; 270 return;
241 271
272 lcd_send_command(R_ENTRY_MODE);
273 lcd_send_command(0x82);
274
242 if(y1 >= LCD_HEIGHT) 275 if(y1 >= LCD_HEIGHT)
243 y1 = LCD_HEIGHT - 1; 276 y1 = LCD_HEIGHT - 1;
244 277