diff options
author | Solomon Peachy <pizza@shaftnet.org> | 2022-10-13 11:03:53 -0400 |
---|---|---|
committer | Solomon Peachy <pizza@shaftnet.org> | 2022-10-13 11:08:06 -0400 |
commit | 418169aff8faf2cf90124cd95dba0af821cea73d (patch) | |
tree | 4fc206af57c9a07fba6cbcb3517fa946a7b84668 /firmware/target/arm/iriver/h10 | |
parent | f9ea1fc79d6aaff9949a5b11ae011b4e04e0e9d9 (diff) | |
download | rockbox-418169aff8faf2cf90124cd95dba0af821cea73d.tar.gz rockbox-418169aff8faf2cf90124cd95dba0af821cea73d.zip |
Revert "Remove YUV blitting functions and LCD modes"
This reverts commit fe6aa21e9eb88f49005863efd2003d0982920048.
Change-Id: I8bb1e5d6c52ed1478002d2140ef494ec5d62b8e3
Diffstat (limited to 'firmware/target/arm/iriver/h10')
-rw-r--r-- | firmware/target/arm/iriver/h10/lcd-as-h10.S | 538 | ||||
-rw-r--r-- | firmware/target/arm/iriver/h10/lcd-h10_20gb.c | 90 | ||||
-rw-r--r-- | firmware/target/arm/iriver/h10/lcd-h10_5gb.c | 162 |
3 files changed, 790 insertions, 0 deletions
diff --git a/firmware/target/arm/iriver/h10/lcd-as-h10.S b/firmware/target/arm/iriver/h10/lcd-as-h10.S new file mode 100644 index 0000000000..8ac8b4289f --- /dev/null +++ b/firmware/target/arm/iriver/h10/lcd-as-h10.S | |||
@@ -0,0 +1,538 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2007-2008 by Michael Sevakis | ||
11 | * | ||
12 | * H10 20GB LCD assembly routines | ||
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_write_yuv420_lines(unsigned char const * const src[3], | ||
29 | * int width, | ||
30 | * int stride); | ||
31 | * | ||
32 | * |R| |1.000000 -0.000001 1.402000| |Y'| | ||
33 | * |G| = |1.000000 -0.334136 -0.714136| |Pb| | ||
34 | * |B| |1.000000 1.772000 0.000000| |Pr| | ||
35 | * Scaled, normalized, rounded and tweaked to yield RGB 565: | ||
36 | * |R| |74 0 101| |Y' - 16| >> 9 | ||
37 | * |G| = |74 -24 -51| |Cb - 128| >> 8 | ||
38 | * |B| |74 128 0| |Cr - 128| >> 9 | ||
39 | * | ||
40 | * Write four RGB565 pixels in the following order on each loop: | ||
41 | * 1 3 + > down | ||
42 | * 2 4 \/ left | ||
43 | */ | ||
44 | .section .icode, "ax", %progbits | ||
45 | .align 2 | ||
46 | .global lcd_write_yuv420_lines | ||
47 | .type lcd_write_yuv420_lines, %function | ||
48 | lcd_write_yuv420_lines: | ||
49 | @ r0 = yuv_src | ||
50 | @ r1 = width | ||
51 | @ r2 = stride | ||
52 | stmfd sp!, { r4-r11, lr } @ save non-scratch | ||
53 | ldmia r0, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p | ||
54 | @ r5 = yuv_src[1] = Cb_p | ||
55 | @ r6 = yuv_src[2] = Cr_p | ||
56 | @ | ||
57 | mov r0, #0x7000000c @ r0 = &LCD2_PORT = 0x70008a0c | ||
58 | add r0, r0, #0x8a00 @ | ||
59 | mov r14, #LCD2_DATA_MASK @ | ||
60 | @ | ||
61 | sub r2, r2, #1 @ Adjust stride because of increment | ||
62 | 10: @ loop line @ | ||
63 | ldrb r7, [r4], #1 @ r7 = *Y'_p++; | ||
64 | ldrb r8, [r5], #1 @ r8 = *Cb_p++; | ||
65 | ldrb r9, [r6], #1 @ r9 = *Cr_p++; | ||
66 | @ | ||
67 | sub r7, r7, #16 @ r7 = Y = (Y' - 16)*74 | ||
68 | add r12, r7, r7, asl #2 @ actually (Y' - 16)*37 and shift right | ||
69 | add r7, r12, r7, asl #5 @ by one less when adding - same for all | ||
70 | @ | ||
71 | sub r8, r8, #128 @ Cb -= 128 | ||
72 | sub r9, r9, #128 @ Cr -= 128 | ||
73 | @ | ||
74 | add r10, r9, r9, asl #1 @ r10 = Cr*51 + Cb*24 | ||
75 | add r10, r10, r10, asl #4 @ | ||
76 | add r10, r10, r8, asl #3 @ | ||
77 | add r10, r10, r8, asl #4 @ | ||
78 | @ | ||
79 | add r11, r9, r9, asl #2 @ r9 = Cr*101 | ||
80 | add r11, r11, r9, asl #5 @ | ||
81 | add r9, r11, r9, asl #6 @ | ||
82 | @ | ||
83 | add r8, r8, #2 @ r8 = bu = (Cb*128 + 128) >> 8 | ||
84 | mov r8, r8, asr #2 @ | ||
85 | add r9, r9, #256 @ r9 = rv = (r8 + 256) >> 9 | ||
86 | mov r9, r9, asr #9 @ | ||
87 | rsb r10, r10, #128 @ r10 = guv = (-r9 + 128) >> 8 | ||
88 | mov r10, r10, asr #8 @ | ||
89 | @ compute R, G, and B | ||
90 | add r3, r8, r7, asr #8 @ r3 = b = (Y >> 9) + bu | ||
91 | add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv | ||
92 | add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv | ||
93 | @ | ||
94 | orr r12, r3, r11 @ check if clamping is needed... | ||
95 | orr r12, r12, r7, asr #1 @ ...at all | ||
96 | cmp r12, #31 @ | ||
97 | bls 15f @ no clamp @ | ||
98 | cmp r3, #31 @ clamp b | ||
99 | mvnhi r3, r3, asr #31 @ | ||
100 | andhi r3, r3, #31 @ | ||
101 | cmp r11, #31 @ clamp r | ||
102 | mvnhi r11, r11, asr #31 @ | ||
103 | andhi r11, r11, #31 @ | ||
104 | cmp r7, #63 @ clamp g | ||
105 | mvnhi r7, r7, asr #31 @ | ||
106 | andhi r7, r7, #63 @ | ||
107 | 15: @ no clamp @ | ||
108 | @ | ||
109 | ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride) | ||
110 | @ | ||
111 | orr r3, r3, r11, lsl #11 @ r3 = b | (r << 11) | ||
112 | orr r3, r3, r7, lsl #5 @ r3 |= (g << 5) | ||
113 | @ | ||
114 | orr r7, r14, r3, lsr #8 @ store pixel | ||
115 | orr r11, r14, r3 @ | ||
116 | 20: @ | ||
117 | ldr r3, [r0] @ | ||
118 | tst r3, #LCD2_BUSY_MASK @ | ||
119 | bne 20b @ | ||
120 | str r7, [r0] @ | ||
121 | str r11, [r0] @ | ||
122 | @ | ||
123 | sub r7, r12, #16 @ r7 = Y = (Y' - 16)*74 | ||
124 | add r12, r7, r7, asl #2 @ | ||
125 | add r7, r12, r7, asl #5 @ | ||
126 | @ compute R, G, and B | ||
127 | add r3, r8, r7, asr #8 @ r3 = b = (Y >> 9) + bu | ||
128 | add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv | ||
129 | add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv | ||
130 | @ | ||
131 | orr r12, r3, r11 @ check if clamping is needed... | ||
132 | orr r12, r12, r7, asr #1 @ ...at all | ||
133 | cmp r12, #31 @ | ||
134 | bls 15f @ no clamp @ | ||
135 | cmp r3, #31 @ clamp b | ||
136 | mvnhi r3, r3, asr #31 @ | ||
137 | andhi r3, r3, #31 @ | ||
138 | cmp r11, #31 @ clamp r | ||
139 | mvnhi r11, r11, asr #31 @ | ||
140 | andhi r11, r11, #31 @ | ||
141 | cmp r7, #63 @ clamp g | ||
142 | mvnhi r7, r7, asr #31 @ | ||
143 | andhi r7, r7, #63 @ | ||
144 | 15: @ no clamp @ | ||
145 | @ | ||
146 | ldrb r12, [r4], #1 @ r12 = Y' = *(Y'_p++) | ||
147 | @ | ||
148 | orr r3, r3, r11, lsl #11 @ r3 = b | (r << 11) | ||
149 | orr r3, r3, r7, lsl #5 @ r3 |= (g << 5) | ||
150 | @ | ||
151 | orr r7, r14, r3, lsr #8 @ store pixel | ||
152 | orr r11, r14, r3 @ | ||
153 | 20: @ | ||
154 | ldr r3, [r0] @ | ||
155 | tst r3, #LCD2_BUSY_MASK @ | ||
156 | bne 20b @ | ||
157 | str r7, [r0] @ | ||
158 | str r11, [r0] @ | ||
159 | @ | ||
160 | sub r7, r12, #16 @ r7 = Y = (Y' - 16)*74 | ||
161 | add r12, r7, r7, asl #2 @ | ||
162 | add r7, r12, r7, asl #5 @ | ||
163 | @ compute R, G, and B | ||
164 | add r3, r8, r7, asr #8 @ r3 = b = (Y >> 9) + bu | ||
165 | add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv | ||
166 | add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv | ||
167 | @ | ||
168 | orr r12, r3, r11 @ check if clamping is needed... | ||
169 | orr r12, r12, r7, asr #1 @ ...at all | ||
170 | cmp r12, #31 @ | ||
171 | bls 15f @ no clamp @ | ||
172 | cmp r3, #31 @ clamp b | ||
173 | mvnhi r3, r3, asr #31 @ | ||
174 | andhi r3, r3, #31 @ | ||
175 | cmp r11, #31 @ clamp r | ||
176 | mvnhi r11, r11, asr #31 @ | ||
177 | andhi r11, r11, #31 @ | ||
178 | cmp r7, #63 @ clamp g | ||
179 | mvnhi r7, r7, asr #31 @ | ||
180 | andhi r7, r7, #63 @ | ||
181 | 15: @ no clamp @ | ||
182 | @ | ||
183 | ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride) | ||
184 | @ | ||
185 | orr r3, r3, r7, lsl #5 @ r3 = b | (g << 5) | ||
186 | orr r3, r3, r11, lsl #11 @ r3 |= (r << 11) | ||
187 | @ | ||
188 | orr r7, r14, r3, lsr #8 @ store pixel | ||
189 | orr r11, r14, r3 @ | ||
190 | 20: @ | ||
191 | ldr r3, [r0] @ | ||
192 | tst r3, #LCD2_BUSY_MASK @ | ||
193 | bne 20b @ | ||
194 | str r7, [r0] @ | ||
195 | str r11, [r0] @ | ||
196 | @ | ||
197 | sub r7, r12, #16 @ r7 = Y = (Y' - 16)*74 | ||
198 | add r12, r7, r7, asl #2 @ | ||
199 | add r7, r12, r7, asl #5 @ | ||
200 | @ compute R, G, and B | ||
201 | add r3, r8, r7, asr #8 @ r3 = b = (Y >> 9) + bu | ||
202 | add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv | ||
203 | add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv | ||
204 | @ | ||
205 | orr r12, r3, r11 @ check if clamping is needed... | ||
206 | orr r12, r12, r7, asr #1 @ ...at all | ||
207 | cmp r12, #31 @ | ||
208 | bls 15f @ no clamp @ | ||
209 | cmp r3, #31 @ clamp b | ||
210 | mvnhi r3, r3, asr #31 @ | ||
211 | andhi r3, r3, #31 @ | ||
212 | cmp r11, #31 @ clamp r | ||
213 | mvnhi r11, r11, asr #31 @ | ||
214 | andhi r11, r11, #31 @ | ||
215 | cmp r7, #63 @ clamp g | ||
216 | mvnhi r7, r7, asr #31 @ | ||
217 | andhi r7, r7, #63 @ | ||
218 | 15: @ no clamp @ | ||
219 | @ | ||
220 | orr r3, r3, r11, lsl #11 @ r3 = b | (r << 11) | ||
221 | orr r3, r3, r7, lsl #5 @ r3 |= (g << 5) | ||
222 | @ | ||
223 | orr r7, r14, r3, lsr #8 @ store pixel | ||
224 | orr r11, r14, r3 @ | ||
225 | 20: @ | ||
226 | ldr r3, [r0] @ | ||
227 | tst r3, #LCD2_BUSY_MASK @ | ||
228 | bne 20b @ | ||
229 | str r7, [r0] @ | ||
230 | str r11, [r0] @ | ||
231 | @ | ||
232 | subs r1, r1, #2 @ subtract block from width | ||
233 | bgt 10b @ loop line @ | ||
234 | @ | ||
235 | ldmpc regs=r4-r11 @ restore registers and return | ||
236 | .ltorg @ dump constant pool | ||
237 | .size lcd_write_yuv420_lines, .-lcd_write_yuv420_lines | ||
238 | |||
239 | |||
240 | /**************************************************************************** | ||
241 | * void lcd_write_yuv420_lines_odither(unsigned char const * const src[3], | ||
242 | * int width, | ||
243 | * int stride, | ||
244 | * int x_screen, | ||
245 | * int y_screen); | ||
246 | * | ||
247 | * |R| |1.000000 -0.000001 1.402000| |Y'| | ||
248 | * |G| = |1.000000 -0.334136 -0.714136| |Pb| | ||
249 | * |B| |1.000000 1.772000 0.000000| |Pr| | ||
250 | * Red scaled at twice g & b but at same precision to place it in correct | ||
251 | * bit position after multiply and leave instruction count lower. | ||
252 | * |R| |258 0 408| |Y' - 16| | ||
253 | * |G| = |149 -49 -104| |Cb - 128| | ||
254 | * |B| |149 258 0| |Cr - 128| | ||
255 | * | ||
256 | * Write four RGB565 pixels in the following order on each loop: | ||
257 | * 1 3 + > down | ||
258 | * 2 4 \/ left | ||
259 | * | ||
260 | * Kernel pattern (raw|use order): | ||
261 | * 5 3 4 2 row0 row2 > down | ||
262 | * 1 7 0 6 | 5 1 3 7 4 0 2 6 col0 left | ||
263 | * 4 2 5 3 | 4 0 2 6 5 1 3 7 col2 \/ | ||
264 | * 0 6 1 7 | ||
265 | */ | ||
266 | .section .icode, "ax", %progbits | ||
267 | .align 2 | ||
268 | .global lcd_write_yuv420_lines_odither | ||
269 | .type lcd_write_yuv420_lines_odither, %function | ||
270 | lcd_write_yuv420_lines_odither: | ||
271 | @ r0 = yuv_src | ||
272 | @ r1 = width | ||
273 | @ r2 = stride | ||
274 | @ r3 = x_screen | ||
275 | @ [sp] = y_screen | ||
276 | stmfd sp!, { r4-r11, lr } @ save non-scratch | ||
277 | ldmia r0, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p | ||
278 | @ r5 = yuv_src[1] = Cb_p | ||
279 | @ r6 = yuv_src[2] = Cr_p | ||
280 | @ | ||
281 | ldr r0, [sp, #36] @ Line up pattern and kernel quadrant | ||
282 | eor r14, r3, r0 @ | ||
283 | and r14, r14, #0x2 @ | ||
284 | mov r14, r14, lsl #6 @ 0x00 or 0x80 | ||
285 | @ | ||
286 | mov r0, #0x7000000c @ r0 = &LCD2_PORT = 0x70008a0c | ||
287 | add r0, r0, #0x8a00 @ | ||
288 | @ | ||
289 | sub r2, r2, #1 @ Adjust stride because of increment | ||
290 | 10: @ loop line @ | ||
291 | @ | ||
292 | ldrb r7, [r4], #1 @ r7 = *Y'_p++; | ||
293 | ldrb r8, [r5], #1 @ r8 = *Cb_p++; | ||
294 | ldrb r9, [r6], #1 @ r9 = *Cr_p++; | ||
295 | @ | ||
296 | eor r14, r14, #0x80 @ flip pattern quadrant | ||
297 | @ | ||
298 | sub r7, r7, #16 @ r7 = Y = (Y' - 16)*149 | ||
299 | add r12, r7, r7, asl #2 @ | ||
300 | add r12, r12, r12, asl #4 @ | ||
301 | add r7, r12, r7, asl #6 @ | ||
302 | @ | ||
303 | sub r8, r8, #128 @ Cb -= 128 | ||
304 | sub r9, r9, #128 @ Cr -= 128 | ||
305 | @ | ||
306 | add r10, r8, r8, asl #4 @ r10 = guv = Cr*104 + Cb*49 | ||
307 | add r10, r10, r8, asl #5 @ | ||
308 | add r10, r10, r9, asl #3 @ | ||
309 | add r10, r10, r9, asl #5 @ | ||
310 | add r10, r10, r9, asl #6 @ | ||
311 | @ | ||
312 | mov r8, r8, asl #1 @ r8 = bu = Cb*258 | ||
313 | add r8, r8, r8, asl #7 @ | ||
314 | @ | ||
315 | add r9, r9, r9, asl #1 @ r9 = rv = Cr*408 | ||
316 | add r9, r9, r9, asl #4 @ | ||
317 | mov r9, r9, asl #3 @ | ||
318 | @ | ||
319 | @ compute R, G, and B | ||
320 | add r3, r8, r7 @ r3 = b' = Y + bu | ||
321 | add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv | ||
322 | rsb r7, r10, r7 @ r7 = g' = Y + guv | ||
323 | @ | ||
324 | @ r8 = bu, r9 = rv, r10 = guv | ||
325 | @ | ||
326 | sub r12, r3, r3, lsr #5 @ r3 = 31/32*b + b/256 | ||
327 | add r3, r12, r3, lsr #8 @ | ||
328 | @ | ||
329 | sub r12, r11, r11, lsr #5 @ r11 = 31/32*r + r/256 | ||
330 | add r11, r12, r11, lsr #8 @ | ||
331 | @ | ||
332 | sub r12, r7, r7, lsr #6 @ r7 = 63/64*g + g/256 | ||
333 | add r7, r12, r7, lsr #8 @ | ||
334 | @ | ||
335 | add r12, r14, #0x200 @ | ||
336 | @ | ||
337 | add r3, r3, r12 @ b = r3 + delta | ||
338 | add r11, r11, r12, lsl #1 @ r = r11 + delta*2 | ||
339 | add r7, r7, r12, lsr #1 @ g = r7 + delta/2 | ||
340 | @ | ||
341 | orr r12, r3, r11, asr #1 @ check if clamping is needed... | ||
342 | orr r12, r12, r7 @ ...at all | ||
343 | movs r12, r12, asr #15 @ | ||
344 | beq 15f @ no clamp @ | ||
345 | movs r12, r3, asr #15 @ clamp b | ||
346 | mvnne r3, r12, lsr #15 @ | ||
347 | andne r3, r3, #0x7c00 @ mask b only if clamped | ||
348 | movs r12, r11, asr #16 @ clamp r | ||
349 | mvnne r11, r12, lsr #16 @ | ||
350 | movs r12, r7, asr #15 @ clamp g | ||
351 | mvnne r7, r12, lsr #15 @ | ||
352 | 15: @ no clamp @ | ||
353 | @ | ||
354 | ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride) | ||
355 | @ | ||
356 | and r11, r11, #0xf800 @ pack pixel | ||
357 | and r7, r7, #0x7e00 @ r3 = pixel = (r & 0xf800) | | ||
358 | orr r11, r11, r7, lsr #4 @ ((g & 0x7e00) >> 4) | | ||
359 | orr r3, r11, r3, lsr #10 @ (b >> 10) | ||
360 | @ | ||
361 | mov r11, #LCD2_DATA_MASK @ store pixel | ||
362 | orr r7, r11, r3, lsr #8 @ | ||
363 | orr r11, r11, r3 @ | ||
364 | 20: @ | ||
365 | ldr r3, [r0] @ | ||
366 | tst r3, #LCD2_BUSY_MASK @ | ||
367 | bne 20b @ | ||
368 | str r7, [r0] @ | ||
369 | str r11, [r0] @ | ||
370 | @ | ||
371 | sub r7, r12, #16 @ r7 = Y = (Y' - 16)*149 | ||
372 | add r12, r7, r7, asl #2 @ | ||
373 | add r12, r12, r12, asl #4 @ | ||
374 | add r7, r12, r7, asl #6 @ | ||
375 | @ compute R, G, and B | ||
376 | add r3, r8, r7 @ r3 = b' = Y + bu | ||
377 | add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv | ||
378 | rsb r7, r10, r7 @ r7 = g' = Y + guv | ||
379 | @ | ||
380 | sub r12, r3, r3, lsr #5 @ r3 = 31/32*b' + b'/256 | ||
381 | add r3, r12, r3, lsr #8 @ | ||
382 | @ | ||
383 | sub r12, r11, r11, lsr #5 @ r11 = 31/32*r' + r'/256 | ||
384 | add r11, r12, r11, lsr #8 @ | ||
385 | @ | ||
386 | sub r12, r7, r7, lsr #6 @ r7 = 63/64*g' + g'/256 | ||
387 | add r7, r12, r7, lsr #8 @ | ||
388 | @ | ||
389 | @ This element is zero - use r14 @ | ||
390 | @ | ||
391 | add r3, r3, r14 @ b = r3 + delta | ||
392 | add r11, r11, r14, lsl #1 @ r = r11 + delta*2 | ||
393 | add r7, r7, r14, lsr #1 @ g = r7 + delta/2 | ||
394 | @ | ||
395 | orr r12, r3, r11, asr #1 @ check if clamping is needed... | ||
396 | orr r12, r12, r7 @ ...at all | ||
397 | movs r12, r12, asr #15 @ | ||
398 | beq 15f @ no clamp @ | ||
399 | movs r12, r3, asr #15 @ clamp b | ||
400 | mvnne r3, r12, lsr #15 @ | ||
401 | andne r3, r3, #0x7c00 @ mask b only if clamped | ||
402 | movs r12, r11, asr #16 @ clamp r | ||
403 | mvnne r11, r12, lsr #16 @ | ||
404 | movs r12, r7, asr #15 @ clamp g | ||
405 | mvnne r7, r12, lsr #15 @ | ||
406 | 15: @ no clamp @ | ||
407 | @ | ||
408 | ldrb r12, [r4], #1 @ r12 = Y' = *(Y'_p++) | ||
409 | @ | ||
410 | and r11, r11, #0xf800 @ pack pixel | ||
411 | and r7, r7, #0x7e00 @ r3 = pixel = (r & 0xf800) | | ||
412 | orr r11, r11, r7, lsr #4 @ ((g & 0x7e00) >> 4) | | ||
413 | orr r3, r11, r3, lsr #10 @ (b >> 10) | ||
414 | @ | ||
415 | mov r11, #LCD2_DATA_MASK @ store pixel | ||
416 | orr r7, r11, r3, lsr #8 @ | ||
417 | orr r11, r11, r3 @ | ||
418 | 20: @ | ||
419 | ldr r3, [r0] @ | ||
420 | tst r3, #LCD2_BUSY_MASK @ | ||
421 | bne 20b @ | ||
422 | str r7, [r0] @ | ||
423 | str r11, [r0] @ | ||
424 | @ | ||
425 | sub r7, r12, #16 @ r7 = Y = (Y' - 16)*149 | ||
426 | add r12, r7, r7, asl #2 @ | ||
427 | add r12, r12, r12, asl #4 @ | ||
428 | add r7, r12, r7, asl #6 @ | ||
429 | @ compute R, G, and B | ||
430 | add r3, r8, r7 @ r3 = b' = Y + bu | ||
431 | add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv | ||
432 | rsb r7, r10, r7 @ r7 = g' = Y + guv | ||
433 | @ | ||
434 | @ r8 = bu, r9 = rv, r10 = guv | ||
435 | @ | ||
436 | sub r12, r3, r3, lsr #5 @ r3 = 31/32*b' + b'/256 | ||
437 | add r3, r12, r3, lsr #8 @ | ||
438 | @ | ||
439 | sub r12, r11, r11, lsr #5 @ r11 = 31/32*r' + r'/256 | ||
440 | add r11, r12, r11, lsr #8 @ | ||
441 | @ | ||
442 | sub r12, r7, r7, lsr #6 @ r7 = 63/64*g' + g'/256 | ||
443 | add r7, r12, r7, lsr #8 @ | ||
444 | @ | ||
445 | add r12, r14, #0x100 @ | ||
446 | @ | ||
447 | add r3, r3, r12 @ b = r3 + delta | ||
448 | add r11, r11, r12, lsl #1 @ r = r11 + delta*2 | ||
449 | add r7, r7, r12, lsr #1 @ g = r7 + delta/2 | ||
450 | @ | ||
451 | orr r12, r3, r11, asr #1 @ check if clamping is needed... | ||
452 | orr r12, r12, r7 @ ...at all | ||
453 | movs r12, r12, asr #15 @ | ||
454 | beq 15f @ no clamp @ | ||
455 | movs r12, r3, asr #15 @ clamp b | ||
456 | mvnne r3, r12, lsr #15 @ | ||
457 | andne r3, r3, #0x7c00 @ mask b only if clamped | ||
458 | movs r12, r11, asr #16 @ clamp r | ||
459 | mvnne r11, r12, lsr #16 @ | ||
460 | movs r12, r7, asr #15 @ clamp g | ||
461 | mvnne r7, r12, lsr #15 @ | ||
462 | 15: @ no clamp @ | ||
463 | @ | ||
464 | ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride) | ||
465 | @ | ||
466 | and r11, r11, #0xf800 @ pack pixel | ||
467 | and r7, r7, #0x7e00 @ r3 = pixel = (r & 0xf800) | | ||
468 | orr r11, r11, r7, lsr #4 @ ((g & 0x7e00) >> 4) | | ||
469 | orr r3, r11, r3, lsr #10 @ (b >> 10) | ||
470 | @ | ||
471 | mov r11, #LCD2_DATA_MASK @ store pixel | ||
472 | orr r7, r11, r3, lsr #8 @ | ||
473 | orr r11, r11, r3 @ | ||
474 | 20: @ | ||
475 | ldr r3, [r0] @ | ||
476 | tst r3, #LCD2_BUSY_MASK @ | ||
477 | bne 20b @ | ||
478 | str r7, [r0] @ | ||
479 | str r11, [r0] @ | ||
480 | @ | ||
481 | sub r7, r12, #16 @ r7 = Y = (Y' - 16)*149 | ||
482 | add r12, r7, r7, asl #2 @ | ||
483 | add r12, r12, r12, asl #4 @ | ||
484 | add r7, r12, r7, asl #6 @ | ||
485 | @ compute R, G, and B | ||
486 | add r3, r8, r7 @ r3 = b' = Y + bu | ||
487 | add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv | ||
488 | rsb r7, r10, r7 @ r7 = g' = Y + guv | ||
489 | @ | ||
490 | sub r12, r3, r3, lsr #5 @ r3 = 31/32*b + b/256 | ||
491 | add r3, r12, r3, lsr #8 @ | ||
492 | @ | ||
493 | sub r12, r11, r11, lsr #5 @ r11 = 31/32*r + r/256 | ||
494 | add r11, r12, r11, lsr #8 @ | ||
495 | @ | ||
496 | sub r12, r7, r7, lsr #6 @ r7 = 63/64*g + g/256 | ||
497 | add r7, r12, r7, lsr #8 @ | ||
498 | @ | ||
499 | add r12, r14, #0x300 @ | ||
500 | @ | ||
501 | add r3, r3, r12 @ b = r3 + delta | ||
502 | add r11, r11, r12, lsl #1 @ r = r11 + delta*2 | ||
503 | add r7, r7, r12, lsr #1 @ g = r7 + delta/2 | ||
504 | @ | ||
505 | orr r12, r3, r11, asr #1 @ check if clamping is needed... | ||
506 | orr r12, r12, r7 @ ...at all | ||
507 | movs r12, r12, asr #15 @ | ||
508 | beq 15f @ no clamp @ | ||
509 | movs r12, r3, asr #15 @ clamp b | ||
510 | mvnne r3, r12, lsr #15 @ | ||
511 | andne r3, r3, #0x7c00 @ mask b only if clamped | ||
512 | movs r12, r11, asr #16 @ clamp r | ||
513 | mvnne r11, r12, lsr #16 @ | ||
514 | movs r12, r7, asr #15 @ clamp g | ||
515 | mvnne r7, r12, lsr #15 @ | ||
516 | 15: @ no clamp @ | ||
517 | @ | ||
518 | and r11, r11, #0xf800 @ pack pixel | ||
519 | and r7, r7, #0x7e00 @ r3 = pixel = (r & 0xf800) | | ||
520 | orr r11, r11, r7, lsr #4 @ ((g & 0x7e00) >> 4) | | ||
521 | orr r3, r11, r3, lsr #10 @ (b >> 10) | ||
522 | @ | ||
523 | mov r11, #LCD2_DATA_MASK @ store pixel | ||
524 | orr r7, r11, r3, lsr #8 @ | ||
525 | orr r11, r11, r3 @ | ||
526 | 20: @ | ||
527 | ldr r3, [r0] @ | ||
528 | tst r3, #LCD2_BUSY_MASK @ | ||
529 | bne 20b @ | ||
530 | str r7, [r0] @ | ||
531 | str r11, [r0] @ | ||
532 | @ | ||
533 | subs r1, r1, #2 @ subtract block from width | ||
534 | bgt 10b @ loop line @ | ||
535 | @ | ||
536 | ldmpc regs=r4-r11 @ restore registers and return | ||
537 | .ltorg @ dump constant pool | ||
538 | .size lcd_write_yuv420_lines_odither, .-lcd_write_yuv420_lines_odither | ||
diff --git a/firmware/target/arm/iriver/h10/lcd-h10_20gb.c b/firmware/target/arm/iriver/h10/lcd-h10_20gb.c index 403c1c19e0..c7e339295d 100644 --- a/firmware/target/arm/iriver/h10/lcd-h10_20gb.c +++ b/firmware/target/arm/iriver/h10/lcd-h10_20gb.c | |||
@@ -36,6 +36,8 @@ static unsigned short disp_control_rev; | |||
36 | /* Contrast setting << 8 */ | 36 | /* Contrast setting << 8 */ |
37 | static int lcd_contrast; | 37 | static int lcd_contrast; |
38 | 38 | ||
39 | static unsigned lcd_yuv_options SHAREDBSS_ATTR = 0; | ||
40 | |||
39 | /* Forward declarations */ | 41 | /* Forward declarations */ |
40 | #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) | 42 | #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) |
41 | static void lcd_display_off(void); | 43 | static void lcd_display_off(void); |
@@ -396,6 +398,94 @@ bool lcd_active(void) | |||
396 | 398 | ||
397 | /*** update functions ***/ | 399 | /*** update functions ***/ |
398 | 400 | ||
401 | void lcd_yuv_set_options(unsigned options) | ||
402 | { | ||
403 | lcd_yuv_options = options; | ||
404 | } | ||
405 | |||
406 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ | ||
407 | extern void lcd_write_yuv420_lines(unsigned char const * const src[3], | ||
408 | int width, | ||
409 | int stride); | ||
410 | extern void lcd_write_yuv420_lines_odither(unsigned char const * const src[3], | ||
411 | int width, | ||
412 | int stride, | ||
413 | int x_screen, /* To align dither pattern */ | ||
414 | int y_screen); | ||
415 | |||
416 | /* Performance function to blit a YUV bitmap directly to the LCD */ | ||
417 | void lcd_blit_yuv(unsigned char * const src[3], | ||
418 | int src_x, int src_y, int stride, | ||
419 | int x, int y, int width, int height) | ||
420 | { | ||
421 | const unsigned char *yuv_src[3]; | ||
422 | const unsigned char *ysrc_max; | ||
423 | int y0; | ||
424 | int options; | ||
425 | |||
426 | if (!display_on) | ||
427 | return; | ||
428 | |||
429 | width &= ~1; | ||
430 | height &= ~1; | ||
431 | |||
432 | /* calculate the drawing region */ | ||
433 | |||
434 | /* The 20GB LCD is actually 128x160 but rotated 90 degrees so the origin | ||
435 | * is actually the bottom left and horizontal and vertical are swapped. | ||
436 | * Rockbox expects the origin to be the top left so we need to use | ||
437 | * 127 - y instead of just y */ | ||
438 | |||
439 | /* max vert << 8 | start vert */ | ||
440 | lcd_write_reg(R_VERT_RAM_ADDR_POS, ((x + width - 1) << 8) | x); | ||
441 | |||
442 | y0 = LCD_HEIGHT - 1 - y + y_offset; | ||
443 | |||
444 | /* DIT=0, BGR=1, HWM=0, I/D1-0=10, AM=0, LG2-0=000 */ | ||
445 | lcd_write_reg(R_ENTRY_MODE, 0x1020); | ||
446 | |||
447 | yuv_src[0] = src[0] + src_y * stride + src_x; | ||
448 | yuv_src[1] = src[1] + (src_y * stride >> 2) + (src_x >> 1); | ||
449 | yuv_src[2] = src[2] + (yuv_src[1] - src[1]); | ||
450 | ysrc_max = yuv_src[0] + height * stride; | ||
451 | |||
452 | options = lcd_yuv_options; | ||
453 | |||
454 | do | ||
455 | { | ||
456 | /* max horiz << 8 | start horiz */ | ||
457 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (y0 << 8) | (y0 - 1)); | ||
458 | |||
459 | /* position cursor (set AD0-AD15) */ | ||
460 | /* start vert << 8 | start horiz */ | ||
461 | lcd_write_reg(R_RAM_ADDR_SET, (x << 8) | y0); | ||
462 | |||
463 | /* start drawing */ | ||
464 | lcd_send_cmd(R_WRITE_DATA_2_GRAM); | ||
465 | |||
466 | if (options & LCD_YUV_DITHER) | ||
467 | { | ||
468 | lcd_write_yuv420_lines_odither(yuv_src, width, stride, | ||
469 | x, y); | ||
470 | y -= 2; | ||
471 | } | ||
472 | else | ||
473 | { | ||
474 | lcd_write_yuv420_lines(yuv_src, width, stride); | ||
475 | } | ||
476 | |||
477 | y0 -= 2; | ||
478 | yuv_src[0] += stride << 1; | ||
479 | yuv_src[1] += stride >> 1; | ||
480 | yuv_src[2] += stride >> 1; | ||
481 | } | ||
482 | while (yuv_src[0] < ysrc_max); | ||
483 | |||
484 | /* DIT=0, BGR=1, HWM=0, I/D1-0=10, AM=1, LG2-0=000 */ | ||
485 | lcd_write_reg(R_ENTRY_MODE, 0x1028); | ||
486 | } | ||
487 | |||
488 | |||
399 | /* Update a fraction of the display. */ | 489 | /* Update a fraction of the display. */ |
400 | void lcd_update_rect(int x0, int y0, int width, int height) | 490 | void lcd_update_rect(int x0, int y0, int width, int height) |
401 | { | 491 | { |
diff --git a/firmware/target/arm/iriver/h10/lcd-h10_5gb.c b/firmware/target/arm/iriver/h10/lcd-h10_5gb.c index 4386e1670c..5e1ad9ce23 100644 --- a/firmware/target/arm/iriver/h10/lcd-h10_5gb.c +++ b/firmware/target/arm/iriver/h10/lcd-h10_5gb.c | |||
@@ -118,6 +118,168 @@ void lcd_init_device(void) | |||
118 | 118 | ||
119 | /*** update functions ***/ | 119 | /*** update functions ***/ |
120 | 120 | ||
121 | #define CSUB_X 2 | ||
122 | #define CSUB_Y 2 | ||
123 | |||
124 | #define RYFAC (31*257) | ||
125 | #define GYFAC (31*257) | ||
126 | #define BYFAC (31*257) | ||
127 | #define RVFAC 11170 /* 31 * 257 * 1.402 */ | ||
128 | #define GVFAC (-5690) /* 31 * 257 * -0.714136 */ | ||
129 | #define GUFAC (-2742) /* 31 * 257 * -0.344136 */ | ||
130 | #define BUFAC 14118 /* 31 * 257 * 1.772 */ | ||
131 | |||
132 | #define ROUNDOFFS (127*257) | ||
133 | #define ROUNDOFFSG (63*257) | ||
134 | |||
135 | /* Performance function to blit a YUV bitmap directly to the LCD */ | ||
136 | void lcd_blit_yuv(unsigned char * const src[3], | ||
137 | int src_x, int src_y, int stride, | ||
138 | int x, int y, int width, int height) | ||
139 | { | ||
140 | int y0, x0, y1, x1; | ||
141 | int ymax; | ||
142 | |||
143 | width = (width + 1) & ~1; | ||
144 | |||
145 | /* calculate the drawing region */ | ||
146 | x0 = x; | ||
147 | x1 = x + width - 1; | ||
148 | y0 = y; | ||
149 | y1 = y + height - 1; | ||
150 | |||
151 | /* max horiz << 8 | start horiz */ | ||
152 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (x1 << 8) | x0); | ||
153 | |||
154 | /* max vert << 8 | start vert */ | ||
155 | lcd_write_reg(R_VERT_RAM_ADDR_POS, (y1 << 8) | y0); | ||
156 | |||
157 | /* start vert << 8 | start horiz */ | ||
158 | lcd_write_reg(R_RAM_ADDR_SET, (y0 << 8) | x0); | ||
159 | |||
160 | /* start drawing */ | ||
161 | lcd_send_cmd(R_WRITE_DATA_2_GRAM); | ||
162 | |||
163 | ymax = y + height - 1 ; | ||
164 | |||
165 | const int stride_div_csub_x = stride/CSUB_X; | ||
166 | |||
167 | for (; y <= ymax ; y++) | ||
168 | { | ||
169 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ | ||
170 | const unsigned char *ysrc = src[0] + stride * src_y + src_x; | ||
171 | |||
172 | const int uvoffset = stride_div_csub_x * (src_y/CSUB_Y) + | ||
173 | (src_x/CSUB_X); | ||
174 | |||
175 | const unsigned char *usrc = src[1] + uvoffset; | ||
176 | const unsigned char *vsrc = src[2] + uvoffset; | ||
177 | const unsigned char *row_end = ysrc + width; | ||
178 | |||
179 | int y, u, v; | ||
180 | int red1, green1, blue1; | ||
181 | int red2, green2, blue2; | ||
182 | unsigned rbits, gbits, bbits; | ||
183 | |||
184 | int rc, gc, bc; | ||
185 | |||
186 | do | ||
187 | { | ||
188 | u = *usrc++ - 128; | ||
189 | v = *vsrc++ - 128; | ||
190 | rc = RVFAC * v + ROUNDOFFS; | ||
191 | gc = GVFAC * v + GUFAC * u + ROUNDOFFSG; | ||
192 | bc = BUFAC * u + ROUNDOFFS; | ||
193 | |||
194 | /* Pixel 1 */ | ||
195 | y = *ysrc++; | ||
196 | |||
197 | red1 = RYFAC * y + rc; | ||
198 | green1 = GYFAC * y + gc; | ||
199 | blue1 = BYFAC * y + bc; | ||
200 | |||
201 | /* Pixel 2 */ | ||
202 | y = *ysrc++; | ||
203 | red2 = RYFAC * y + rc; | ||
204 | green2 = GYFAC * y + gc; | ||
205 | blue2 = BYFAC * y + bc; | ||
206 | |||
207 | /* Since out of bounds errors are relatively rare, we check two | ||
208 | pixels at once to see if any components are out of bounds, and | ||
209 | then fix whichever is broken. This works due to high values and | ||
210 | negative values both becoming larger than the cutoff when | ||
211 | casted to unsigned. And ORing them together checks all of them | ||
212 | simultaneously. */ | ||
213 | if (((unsigned)(red1 | green1 | blue1 | | ||
214 | red2 | green2 | blue2)) > (RYFAC*255+ROUNDOFFS)) { | ||
215 | if (((unsigned)(red1 | green1 | blue1)) > | ||
216 | (RYFAC*255+ROUNDOFFS)) { | ||
217 | if ((unsigned)red1 > (RYFAC*255+ROUNDOFFS)) | ||
218 | { | ||
219 | if (red1 < 0) | ||
220 | red1 = 0; | ||
221 | else | ||
222 | red1 = (RYFAC*255+ROUNDOFFS); | ||
223 | } | ||
224 | if ((unsigned)green1 > (GYFAC*255+ROUNDOFFSG)) | ||
225 | { | ||
226 | if (green1 < 0) | ||
227 | green1 = 0; | ||
228 | else | ||
229 | green1 = (GYFAC*255+ROUNDOFFSG); | ||
230 | } | ||
231 | if ((unsigned)blue1 > (BYFAC*255+ROUNDOFFS)) | ||
232 | { | ||
233 | if (blue1 < 0) | ||
234 | blue1 = 0; | ||
235 | else | ||
236 | blue1 = (BYFAC*255+ROUNDOFFS); | ||
237 | } | ||
238 | } | ||
239 | |||
240 | if (((unsigned)(red2 | green2 | blue2)) > | ||
241 | (RYFAC*255+ROUNDOFFS)) { | ||
242 | if ((unsigned)red2 > (RYFAC*255+ROUNDOFFS)) | ||
243 | { | ||
244 | if (red2 < 0) | ||
245 | red2 = 0; | ||
246 | else | ||
247 | red2 = (RYFAC*255+ROUNDOFFS); | ||
248 | } | ||
249 | if ((unsigned)green2 > (GYFAC*255+ROUNDOFFSG)) | ||
250 | { | ||
251 | if (green2 < 0) | ||
252 | green2 = 0; | ||
253 | else | ||
254 | green2 = (GYFAC*255+ROUNDOFFSG); | ||
255 | } | ||
256 | if ((unsigned)blue2 > (BYFAC*255+ROUNDOFFS)) | ||
257 | { | ||
258 | if (blue2 < 0) | ||
259 | blue2 = 0; | ||
260 | else | ||
261 | blue2 = (BYFAC*255+ROUNDOFFS); | ||
262 | } | ||
263 | } | ||
264 | } | ||
265 | |||
266 | rbits = red1 >> 16 ; | ||
267 | gbits = green1 >> 15 ; | ||
268 | bbits = blue1 >> 16 ; | ||
269 | lcd_send_data((rbits << 11) | (gbits << 5) | bbits); | ||
270 | |||
271 | rbits = red2 >> 16 ; | ||
272 | gbits = green2 >> 15 ; | ||
273 | bbits = blue2 >> 16 ; | ||
274 | lcd_send_data((rbits << 11) | (gbits << 5) | bbits); | ||
275 | } | ||
276 | while (ysrc < row_end); | ||
277 | |||
278 | src_y++; | ||
279 | } | ||
280 | } | ||
281 | |||
282 | |||
121 | /* Update a fraction of the display. */ | 283 | /* Update a fraction of the display. */ |
122 | void lcd_update_rect(int x0, int y0, int width, int height) | 284 | void lcd_update_rect(int x0, int y0, int width, int height) |
123 | { | 285 | { |