diff options
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/iriver/h10/lcd-as-h10.S | 528 | ||||
-rw-r--r-- | firmware/target/arm/iriver/h10/lcd-h10_20gb.c | 203 |
2 files changed, 586 insertions, 145 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..f4f7b9398e --- /dev/null +++ b/firmware/target/arm/iriver/h10/lcd-as-h10.S | |||
@@ -0,0 +1,528 @@ | |||
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 | * All files in this archive are subject to the GNU General Public License. | ||
15 | * See the file COPYING in the source tree root for full license agreement. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include "config.h" | ||
23 | #include "cpu.h" | ||
24 | |||
25 | /**************************************************************************** | ||
26 | * void lcd_write_yuv_420_lines(unsigned char const * const src[3], | ||
27 | * int width, | ||
28 | * int stride); | ||
29 | * | ||
30 | * |R| |1.000000 -0.000001 1.402000| |Y'| | ||
31 | * |G| = |1.000000 -0.334136 -0.714136| |Pb| | ||
32 | * |B| |1.000000 1.772000 0.000000| |Pr| | ||
33 | * Scaled, normalized, rounded and tweaked to yield RGB 565: | ||
34 | * |R| |74 0 101| |Y' - 16| >> 9 | ||
35 | * |G| = |74 -24 -51| |Cb - 128| >> 8 | ||
36 | * |B| |74 128 0| |Cr - 128| >> 9 | ||
37 | * | ||
38 | * Write four RGB565 pixels in the following order on each loop: | ||
39 | * 1 3 + > down | ||
40 | * 2 4 \/ left | ||
41 | */ | ||
42 | .section .icode, "ax", %progbits | ||
43 | .align 2 | ||
44 | .global lcd_write_yuv420_lines | ||
45 | .type lcd_write_yuv420_lines, %function | ||
46 | lcd_write_yuv420_lines: | ||
47 | @ r0 = yuv_src | ||
48 | @ r1 = width | ||
49 | @ r2 = stride | ||
50 | stmfd sp!, { r4-r12, lr } @ save non-scratch | ||
51 | ldmia r0, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p | ||
52 | @ r5 = yuv_src[1] = Cb_p | ||
53 | @ r6 = yuv_src[2] = Cr_p | ||
54 | @ | ||
55 | mov r0, #0x7000000c @ r0 = &LCD2_PORT = 0x70008a0c | ||
56 | add r0, r0, #0x8a00 @ | ||
57 | mov r14, #LCD2_DATA_MASK @ | ||
58 | @ | ||
59 | sub r2, r2, #1 @ Adjust stride because of increment | ||
60 | 10: @ loop line @ | ||
61 | ldrb r7, [r4], #1 @ r7 = *Y'_p++; | ||
62 | ldrb r8, [r5], #1 @ r8 = *Cb_p++; | ||
63 | ldrb r9, [r6], #1 @ r9 = *Cr_p++; | ||
64 | @ | ||
65 | sub r7, r7, #16 @ r7 = Y = (Y' - 16)*74 | ||
66 | add r12, r7, r7, asl #2 @ actually (Y' - 16)*37 and shift right | ||
67 | add r7, r12, r7, asl #5 @ by one less when adding - same for all | ||
68 | @ | ||
69 | sub r8, r8, #128 @ Cb -= 128 | ||
70 | sub r9, r9, #128 @ Cr -= 128 | ||
71 | @ | ||
72 | add r10, r9, r9, asl #1 @ r10 = Cr*51 + Cb*24 | ||
73 | add r10, r10, r10, asl #4 @ | ||
74 | add r10, r10, r8, asl #3 @ | ||
75 | add r10, r10, r8, asl #4 @ | ||
76 | @ | ||
77 | add r11, r9, r9, asl #2 @ r9 = Cr*101 | ||
78 | add r11, r11, r9, asl #5 @ | ||
79 | add r9, r11, r9, asl #6 @ | ||
80 | @ | ||
81 | add r8, r8, #2 @ r8 = bu = (Cb*128 + 128) >> 8 | ||
82 | mov r8, r8, asr #2 @ | ||
83 | add r9, r9, #256 @ r9 = rv = (r8 + 256) >> 9 | ||
84 | mov r9, r9, asr #9 @ | ||
85 | rsb r10, r10, #128 @ r10 = guv = (-r9 + 128) >> 8 | ||
86 | mov r10, r10, asr #8 @ | ||
87 | @ compute R, G, and B | ||
88 | add r3, r8, r7, asr #8 @ r3 = b = (Y >> 9) + bu | ||
89 | add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv | ||
90 | add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv | ||
91 | @ | ||
92 | orr r12, r3, r11 @ check if clamping is needed... | ||
93 | orr r12, r12, r7, asr #1 @ ...at all | ||
94 | cmp r12, #31 @ | ||
95 | bls 15f @ no clamp @ | ||
96 | cmp r3, #31 @ clamp b | ||
97 | mvnhi r3, r3, asr #31 @ | ||
98 | andhi r3, r3, #31 @ | ||
99 | cmp r11, #31 @ clamp r | ||
100 | mvnhi r11, r11, asr #31 @ | ||
101 | andhi r11, r11, #31 @ | ||
102 | cmp r7, #63 @ clamp g | ||
103 | mvnhi r7, r7, asr #31 @ | ||
104 | andhi r7, r7, #63 @ | ||
105 | 15: @ no clamp @ | ||
106 | @ | ||
107 | ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride) | ||
108 | @ | ||
109 | orr r3, r3, r11, lsl #11 @ r3 = b | (r << 11) | ||
110 | orr r3, r3, r7, lsl #5 @ r3 |= (g << 5) | ||
111 | @ | ||
112 | orr r7, r14, r3, lsr #8 @ store pixel | ||
113 | orr r11, r14, r3 @ | ||
114 | 20: @ | ||
115 | ldr r3, [r0] @ | ||
116 | tst r3, #LCD2_BUSY_MASK @ | ||
117 | bne 20b @ | ||
118 | stmia r0, { r7, r11 } @ | ||
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 r3, r8, r7, asr #8 @ r3 = 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, r3, 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 r3, #31 @ clamp b | ||
133 | mvnhi r3, r3, asr #31 @ | ||
134 | andhi r3, r3, #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 @ | ||
141 | 15: @ no clamp @ | ||
142 | @ | ||
143 | ldrb r12, [r4], #1 @ r12 = Y' = *(Y'_p++) | ||
144 | @ | ||
145 | orr r3, r3, r11, lsl #11 @ r3 = b | (r << 11) | ||
146 | orr r3, r3, r7, lsl #5 @ r3 |= (g << 5) | ||
147 | @ | ||
148 | orr r7, r14, r3, lsr #8 @ store pixel | ||
149 | orr r11, r14, r3 @ | ||
150 | 20: @ | ||
151 | ldr r3, [r0] @ | ||
152 | tst r3, #LCD2_BUSY_MASK @ | ||
153 | bne 20b @ | ||
154 | stmia r0, { r7, r11 } @ | ||
155 | @ | ||
156 | sub r7, r12, #16 @ r7 = Y = (Y' - 16)*74 | ||
157 | add r12, r7, r7, asl #2 @ | ||
158 | add r7, r12, r7, asl #5 @ | ||
159 | @ compute R, G, and B | ||
160 | add r3, r8, r7, asr #8 @ r3 = b = (Y >> 9) + bu | ||
161 | add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv | ||
162 | add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv | ||
163 | @ | ||
164 | orr r12, r3, r11 @ check if clamping is needed... | ||
165 | orr r12, r12, r7, asr #1 @ ...at all | ||
166 | cmp r12, #31 @ | ||
167 | bls 15f @ no clamp @ | ||
168 | cmp r3, #31 @ clamp b | ||
169 | mvnhi r3, r3, asr #31 @ | ||
170 | andhi r3, r3, #31 @ | ||
171 | cmp r11, #31 @ clamp r | ||
172 | mvnhi r11, r11, asr #31 @ | ||
173 | andhi r11, r11, #31 @ | ||
174 | cmp r7, #63 @ clamp g | ||
175 | mvnhi r7, r7, asr #31 @ | ||
176 | andhi r7, r7, #63 @ | ||
177 | 15: @ no clamp @ | ||
178 | @ | ||
179 | ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride) | ||
180 | @ | ||
181 | orr r3, r3, r7, lsl #5 @ r3 = b | (g << 5) | ||
182 | orr r3, r3, r11, lsl #11 @ r3 |= (r << 11) | ||
183 | @ | ||
184 | orr r7, r14, r3, lsr #8 @ store pixel | ||
185 | orr r11, r14, r3 @ | ||
186 | 20: @ | ||
187 | ldr r3, [r0] @ | ||
188 | tst r3, #LCD2_BUSY_MASK @ | ||
189 | bne 20b @ | ||
190 | stmia r0, { r7, r11 } @ | ||
191 | @ | ||
192 | sub r7, r12, #16 @ r7 = Y = (Y' - 16)*74 | ||
193 | add r12, r7, r7, asl #2 @ | ||
194 | add r7, r12, r7, asl #5 @ | ||
195 | @ compute R, G, and B | ||
196 | add r3, r8, r7, asr #8 @ r3 = b = (Y >> 9) + bu | ||
197 | add r11, r9, r7, asr #8 @ r11 = r = (Y >> 9) + rv | ||
198 | add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv | ||
199 | @ | ||
200 | orr r12, r3, r11 @ check if clamping is needed... | ||
201 | orr r12, r12, r7, asr #1 @ ...at all | ||
202 | cmp r12, #31 @ | ||
203 | bls 15f @ no clamp @ | ||
204 | cmp r3, #31 @ clamp b | ||
205 | mvnhi r3, r3, asr #31 @ | ||
206 | andhi r3, r3, #31 @ | ||
207 | cmp r11, #31 @ clamp r | ||
208 | mvnhi r11, r11, asr #31 @ | ||
209 | andhi r11, r11, #31 @ | ||
210 | cmp r7, #63 @ clamp g | ||
211 | mvnhi r7, r7, asr #31 @ | ||
212 | andhi r7, r7, #63 @ | ||
213 | 15: @ no clamp @ | ||
214 | @ | ||
215 | orr r3, r3, r11, lsl #11 @ r3 = b | (r << 11) | ||
216 | orr r3, r3, r7, lsl #5 @ r3 |= (g << 5) | ||
217 | @ | ||
218 | orr r7, r14, r3, lsr #8 @ store pixel | ||
219 | orr r11, r14, r3 @ | ||
220 | 20: @ | ||
221 | ldr r3, [r0] @ | ||
222 | tst r3, #LCD2_BUSY_MASK @ | ||
223 | bne 20b @ | ||
224 | stmia r0, { r7, r11 } @ | ||
225 | @ | ||
226 | subs r1, r1, #2 @ subtract block from width | ||
227 | bgt 10b @ loop line @ | ||
228 | @ | ||
229 | ldmfd sp!, { r4-r12, pc } @ restore registers and return | ||
230 | .ltorg @ dump constant pool | ||
231 | .size lcd_write_yuv420_lines, .-lcd_write_yuv420_lines | ||
232 | |||
233 | |||
234 | /**************************************************************************** | ||
235 | * void lcd_write_yuv_420_lines_odither(unsigned char const * const src[3], | ||
236 | * int width, | ||
237 | * int stride, | ||
238 | * int x_screen, | ||
239 | * int y_screen); | ||
240 | * | ||
241 | * |R| |1.000000 -0.000001 1.402000| |Y'| | ||
242 | * |G| = |1.000000 -0.334136 -0.714136| |Pb| | ||
243 | * |B| |1.000000 1.772000 0.000000| |Pr| | ||
244 | * Red scaled at twice g & b but at same precision to place it in correct | ||
245 | * bit position after multiply and leave instruction count lower. | ||
246 | * |R| |258 0 408| |Y' - 16| | ||
247 | * |G| = |149 -49 -104| |Cb - 128| | ||
248 | * |B| |149 258 0| |Cr - 128| | ||
249 | * | ||
250 | * Write four RGB565 pixels in the following order on each loop: | ||
251 | * 1 3 + > down | ||
252 | * 2 4 \/ left | ||
253 | * | ||
254 | * Kernel pattern (raw|use order): | ||
255 | * 5 3 4 2 row0 row2 > down | ||
256 | * 1 7 0 6 | 5 1 3 7 4 0 2 6 col0 left | ||
257 | * 4 2 5 3 | 4 0 2 6 5 1 3 7 col2 \/ | ||
258 | * 0 6 1 7 | ||
259 | */ | ||
260 | .section .icode, "ax", %progbits | ||
261 | .align 2 | ||
262 | .global lcd_write_yuv420_lines_odither | ||
263 | .type lcd_write_yuv420_lines_odither, %function | ||
264 | lcd_write_yuv420_lines_odither: | ||
265 | @ r0 = yuv_src | ||
266 | @ r1 = width | ||
267 | @ r2 = stride | ||
268 | @ r3 = x_screen | ||
269 | @ [sp] = y_screen | ||
270 | stmfd sp!, { r4-r12, lr } @ save non-scratch | ||
271 | ldmia r0, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p | ||
272 | @ r5 = yuv_src[1] = Cb_p | ||
273 | @ r6 = yuv_src[2] = Cr_p | ||
274 | @ | ||
275 | ldr r0, [sp, #40] @ Line up pattern and kernel quadrant | ||
276 | eor r14, r3, r0 @ | ||
277 | and r14, r14, #0x2 @ | ||
278 | mov r14, r14, lsl #6 @ 0x00 or 0x80 | ||
279 | @ | ||
280 | mov r0, #0x7000000c @ r0 = &LCD2_PORT = 0x70008a0c | ||
281 | add r0, r0, #0x8a00 @ | ||
282 | @ | ||
283 | sub r2, r2, #1 @ Adjust stride because of increment | ||
284 | 10: @ loop line @ | ||
285 | @ | ||
286 | ldrb r7, [r4], #1 @ r7 = *Y'_p++; | ||
287 | ldrb r8, [r5], #1 @ r8 = *Cb_p++; | ||
288 | ldrb r9, [r6], #1 @ r9 = *Cr_p++; | ||
289 | @ | ||
290 | eor r14, r14, #0x80 @ flip pattern quadrant | ||
291 | @ | ||
292 | sub r7, r7, #16 @ r7 = Y = (Y' - 16)*149 | ||
293 | add r12, r7, r7, asl #2 @ | ||
294 | add r12, r12, r12, asl #4 @ | ||
295 | add r7, r12, r7, asl #6 @ | ||
296 | @ | ||
297 | sub r8, r8, #128 @ Cb -= 128 | ||
298 | sub r9, r9, #128 @ Cr -= 128 | ||
299 | @ | ||
300 | add r10, r8, r8, asl #4 @ r10 = guv = Cr*104 + Cb*49 | ||
301 | add r10, r10, r8, asl #5 @ | ||
302 | add r10, r10, r9, asl #3 @ | ||
303 | add r10, r10, r9, asl #5 @ | ||
304 | add r10, r10, r9, asl #6 @ | ||
305 | @ | ||
306 | mov r8, r8, asl #1 @ r8 = bu = Cb*258 | ||
307 | add r8, r8, r8, asl #7 @ | ||
308 | @ | ||
309 | add r9, r9, r9, asl #1 @ r9 = rv = Cr*408 | ||
310 | add r9, r9, r9, asl #4 @ | ||
311 | mov r9, r9, asl #3 @ | ||
312 | @ | ||
313 | @ compute R, G, and B | ||
314 | add r3, r8, r7 @ r3 = b' = Y + bu | ||
315 | add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv | ||
316 | rsb r7, r10, r7 @ r7 = g' = Y + guv | ||
317 | @ | ||
318 | @ r8 = bu, r9 = rv, r10 = guv | ||
319 | @ | ||
320 | sub r12, r3, r3, lsr #5 @ r3 = 31/32*b + b/256 | ||
321 | add r3, r12, r3, lsr #8 @ | ||
322 | @ | ||
323 | sub r12, r11, r11, lsr #5 @ r11 = 31/32*r + r/256 | ||
324 | add r11, r12, r11, lsr #8 @ | ||
325 | @ | ||
326 | sub r12, r7, r7, lsr #6 @ r7 = 63/64*g + g/256 | ||
327 | add r7, r12, r7, lsr #8 @ | ||
328 | @ | ||
329 | add r12, r14, #0x200 @ | ||
330 | @ | ||
331 | add r3, r3, r12 @ b = r3 + delta | ||
332 | add r11, r11, r12, lsl #1 @ r = r11 + delta*2 | ||
333 | add r7, r7, r12, lsr #1 @ g = r7 + delta/2 | ||
334 | @ | ||
335 | orr r12, r3, r11, asr #1 @ check if clamping is needed... | ||
336 | orr r12, r12, r7 @ ...at all | ||
337 | movs r12, r12, asr #15 @ | ||
338 | beq 15f @ no clamp @ | ||
339 | movs r12, r3, asr #15 @ clamp b | ||
340 | mvnne r3, r12, lsr #15 @ | ||
341 | andne r3, r3, #0x7c00 @ mask b only if clamped | ||
342 | movs r12, r11, asr #16 @ clamp r | ||
343 | mvnne r11, r12, lsr #16 @ | ||
344 | movs r12, r7, asr #15 @ clamp g | ||
345 | mvnne r7, r12, lsr #15 @ | ||
346 | 15: @ no clamp @ | ||
347 | @ | ||
348 | ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride) | ||
349 | @ | ||
350 | and r11, r11, #0xf800 @ pack pixel | ||
351 | and r7, r7, #0x7e00 @ r3 = pixel = (r & 0xf800) | | ||
352 | orr r11, r11, r7, lsr #4 @ ((g & 0x7e00) >> 4) | | ||
353 | orr r3, r11, r3, lsr #10 @ (b >> 10) | ||
354 | @ | ||
355 | mov r11, #LCD2_DATA_MASK @ store pixel | ||
356 | orr r7, r11, r3, lsr #8 @ | ||
357 | orr r11, r11, r3 @ | ||
358 | 20: @ | ||
359 | ldr r3, [r0] @ | ||
360 | tst r3, #LCD2_BUSY_MASK @ | ||
361 | bne 20b @ | ||
362 | stmia r0, { r7, r11 } @ | ||
363 | @ | ||
364 | sub r7, r12, #16 @ r7 = Y = (Y' - 16)*149 | ||
365 | add r12, r7, r7, asl #2 @ | ||
366 | add r12, r12, r12, asl #4 @ | ||
367 | add r7, r12, r7, asl #6 @ | ||
368 | @ compute R, G, and B | ||
369 | add r3, r8, r7 @ r3 = b' = Y + bu | ||
370 | add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv | ||
371 | rsb r7, r10, r7 @ r7 = g' = Y + guv | ||
372 | @ | ||
373 | sub r12, r3, r3, lsr #5 @ r3 = 31/32*b' + b'/256 | ||
374 | add r3, r12, r3, lsr #8 @ | ||
375 | @ | ||
376 | sub r12, r11, r11, lsr #5 @ r11 = 31/32*r' + r'/256 | ||
377 | add r11, r12, r11, lsr #8 @ | ||
378 | @ | ||
379 | sub r12, r7, r7, lsr #6 @ r7 = 63/64*g' + g'/256 | ||
380 | add r7, r12, r7, lsr #8 @ | ||
381 | @ | ||
382 | @ This element is zero - use r14 @ | ||
383 | @ | ||
384 | add r3, r3, r14 @ b = r3 + delta | ||
385 | add r11, r11, r14, lsl #1 @ r = r11 + delta*2 | ||
386 | add r7, r7, r14, lsr #1 @ g = r7 + delta/2 | ||
387 | @ | ||
388 | orr r12, r3, r11, asr #1 @ check if clamping is needed... | ||
389 | orr r12, r12, r7 @ ...at all | ||
390 | movs r12, r12, asr #15 @ | ||
391 | beq 15f @ no clamp @ | ||
392 | movs r12, r3, asr #15 @ clamp b | ||
393 | mvnne r3, r12, lsr #15 @ | ||
394 | andne r3, r3, #0x7c00 @ mask b only if clamped | ||
395 | movs r12, r11, asr #16 @ clamp r | ||
396 | mvnne r11, r12, lsr #16 @ | ||
397 | movs r12, r7, asr #15 @ clamp g | ||
398 | mvnne r7, r12, lsr #15 @ | ||
399 | 15: @ no clamp @ | ||
400 | @ | ||
401 | ldrb r12, [r4], #1 @ r12 = Y' = *(Y'_p++) | ||
402 | @ | ||
403 | and r11, r11, #0xf800 @ pack pixel | ||
404 | and r7, r7, #0x7e00 @ r3 = pixel = (r & 0xf800) | | ||
405 | orr r11, r11, r7, lsr #4 @ ((g & 0x7e00) >> 4) | | ||
406 | orr r3, r11, r3, lsr #10 @ (b >> 10) | ||
407 | @ | ||
408 | mov r11, #LCD2_DATA_MASK @ store pixel | ||
409 | orr r7, r11, r3, lsr #8 @ | ||
410 | orr r11, r11, r3 @ | ||
411 | 20: @ | ||
412 | ldr r3, [r0] @ | ||
413 | tst r3, #LCD2_BUSY_MASK @ | ||
414 | bne 20b @ | ||
415 | stmia r0, { r7, r11 } @ | ||
416 | @ | ||
417 | sub r7, r12, #16 @ r7 = Y = (Y' - 16)*149 | ||
418 | add r12, r7, r7, asl #2 @ | ||
419 | add r12, r12, r12, asl #4 @ | ||
420 | add r7, r12, r7, asl #6 @ | ||
421 | @ compute R, G, and B | ||
422 | add r3, r8, r7 @ r3 = b' = Y + bu | ||
423 | add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv | ||
424 | rsb r7, r10, r7 @ r7 = g' = Y + guv | ||
425 | @ | ||
426 | @ r8 = bu, r9 = rv, r10 = guv | ||
427 | @ | ||
428 | sub r12, r3, r3, lsr #5 @ r3 = 31/32*b' + b'/256 | ||
429 | add r3, r12, r3, lsr #8 @ | ||
430 | @ | ||
431 | sub r12, r11, r11, lsr #5 @ r11 = 31/32*r' + r'/256 | ||
432 | add r11, r12, r11, lsr #8 @ | ||
433 | @ | ||
434 | sub r12, r7, r7, lsr #6 @ r7 = 63/64*g' + g'/256 | ||
435 | add r7, r12, r7, lsr #8 @ | ||
436 | @ | ||
437 | add r12, r14, #0x100 @ | ||
438 | @ | ||
439 | add r3, r3, r12 @ b = r3 + delta | ||
440 | add r11, r11, r12, lsl #1 @ r = r11 + delta*2 | ||
441 | add r7, r7, r12, lsr #1 @ g = r7 + delta/2 | ||
442 | @ | ||
443 | orr r12, r3, r11, asr #1 @ check if clamping is needed... | ||
444 | orr r12, r12, r7 @ ...at all | ||
445 | movs r12, r12, asr #15 @ | ||
446 | beq 15f @ no clamp @ | ||
447 | movs r12, r3, asr #15 @ clamp b | ||
448 | mvnne r3, r12, lsr #15 @ | ||
449 | andne r3, r3, #0x7c00 @ mask b only if clamped | ||
450 | movs r12, r11, asr #16 @ clamp r | ||
451 | mvnne r11, r12, lsr #16 @ | ||
452 | movs r12, r7, asr #15 @ clamp g | ||
453 | mvnne r7, r12, lsr #15 @ | ||
454 | 15: @ no clamp @ | ||
455 | @ | ||
456 | ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride) | ||
457 | @ | ||
458 | and r11, r11, #0xf800 @ pack pixel | ||
459 | and r7, r7, #0x7e00 @ r3 = pixel = (r & 0xf800) | | ||
460 | orr r11, r11, r7, lsr #4 @ ((g & 0x7e00) >> 4) | | ||
461 | orr r3, r11, r3, lsr #10 @ (b >> 10) | ||
462 | @ | ||
463 | mov r11, #LCD2_DATA_MASK @ store pixel | ||
464 | orr r7, r11, r3, lsr #8 @ | ||
465 | orr r11, r11, r3 @ | ||
466 | 20: @ | ||
467 | ldr r3, [r0] @ | ||
468 | tst r3, #LCD2_BUSY_MASK @ | ||
469 | bne 20b @ | ||
470 | stmia r0, { r7, r11 } @ | ||
471 | @ | ||
472 | sub r7, r12, #16 @ r7 = Y = (Y' - 16)*149 | ||
473 | add r12, r7, r7, asl #2 @ | ||
474 | add r12, r12, r12, asl #4 @ | ||
475 | add r7, r12, r7, asl #6 @ | ||
476 | @ compute R, G, and B | ||
477 | add r3, r8, r7 @ r3 = b' = Y + bu | ||
478 | add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv | ||
479 | rsb r7, r10, r7 @ r7 = g' = Y + guv | ||
480 | @ | ||
481 | sub r12, r3, r3, lsr #5 @ r3 = 31/32*b + b/256 | ||
482 | add r3, r12, r3, lsr #8 @ | ||
483 | @ | ||
484 | sub r12, r11, r11, lsr #5 @ r11 = 31/32*r + r/256 | ||
485 | add r11, r12, r11, lsr #8 @ | ||
486 | @ | ||
487 | sub r12, r7, r7, lsr #6 @ r7 = 63/64*g + g/256 | ||
488 | add r7, r12, r7, lsr #8 @ | ||
489 | @ | ||
490 | add r12, r14, #0x300 @ | ||
491 | @ | ||
492 | add r3, r3, r12 @ b = r3 + delta | ||
493 | add r11, r11, r12, lsl #1 @ r = r11 + delta*2 | ||
494 | add r7, r7, r12, lsr #1 @ g = r7 + delta/2 | ||
495 | @ | ||
496 | orr r12, r3, r11, asr #1 @ check if clamping is needed... | ||
497 | orr r12, r12, r7 @ ...at all | ||
498 | movs r12, r12, asr #15 @ | ||
499 | beq 15f @ no clamp @ | ||
500 | movs r12, r3, asr #15 @ clamp b | ||
501 | mvnne r3, r12, lsr #15 @ | ||
502 | andne r3, r3, #0x7c00 @ mask b only if clamped | ||
503 | movs r12, r11, asr #16 @ clamp r | ||
504 | mvnne r11, r12, lsr #16 @ | ||
505 | movs r12, r7, asr #15 @ clamp g | ||
506 | mvnne r7, r12, lsr #15 @ | ||
507 | 15: @ no clamp @ | ||
508 | @ | ||
509 | and r11, r11, #0xf800 @ pack pixel | ||
510 | and r7, r7, #0x7e00 @ r3 = pixel = (r & 0xf800) | | ||
511 | orr r11, r11, r7, lsr #4 @ ((g & 0x7e00) >> 4) | | ||
512 | orr r3, r11, r3, lsr #10 @ (b >> 10) | ||
513 | @ | ||
514 | mov r11, #LCD2_DATA_MASK @ store pixel | ||
515 | orr r7, r11, r3, lsr #8 @ | ||
516 | orr r11, r11, r3 @ | ||
517 | 20: @ | ||
518 | ldr r3, [r0] @ | ||
519 | tst r3, #LCD2_BUSY_MASK @ | ||
520 | bne 20b @ | ||
521 | stmia r0, { r7, r11 } @ | ||
522 | @ | ||
523 | subs r1, r1, #2 @ subtract block from width | ||
524 | bgt 10b @ loop line @ | ||
525 | @ | ||
526 | ldmfd sp!, { r4-r12, pc } @ restore registers and return | ||
527 | .ltorg @ dump constant pool | ||
528 | .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 2c527fa4d9..892adffea9 100644 --- a/firmware/target/arm/iriver/h10/lcd-h10_20gb.c +++ b/firmware/target/arm/iriver/h10/lcd-h10_20gb.c | |||
@@ -34,6 +34,8 @@ static unsigned short disp_control_rev; | |||
34 | /* Contrast setting << 8 */ | 34 | /* Contrast setting << 8 */ |
35 | static int lcd_contrast; | 35 | static int lcd_contrast; |
36 | 36 | ||
37 | static unsigned lcd_yuv_options NOCACHEBSS_ATTR = 0; | ||
38 | |||
37 | /* Forward declarations */ | 39 | /* Forward declarations */ |
38 | static void lcd_display_off(void); | 40 | static void lcd_display_off(void); |
39 | 41 | ||
@@ -166,8 +168,6 @@ void lcd_set_flip(bool yesno) | |||
166 | lcd_write_reg(R_GATE_SCAN_START_POS, yesno ? 0x0002 : 0x0000); | 168 | lcd_write_reg(R_GATE_SCAN_START_POS, yesno ? 0x0002 : 0x0000); |
167 | /* SM=0, GS=x, SS=x, NL4-0=10011 (G1-G160) */ | 169 | /* SM=0, GS=x, SS=x, NL4-0=10011 (G1-G160) */ |
168 | lcd_write_reg(R_DRV_OUTPUT_CONTROL, yesno ? 0x0213 : 0x0113); | 170 | lcd_write_reg(R_DRV_OUTPUT_CONTROL, yesno ? 0x0213 : 0x0113); |
169 | /* HEA7-0=0xxx, HSA7-0=0xxx */ | ||
170 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, y_offset ? 0x8304 : 0x7f00); | ||
171 | } | 171 | } |
172 | 172 | ||
173 | /* LCD init */ | 173 | /* LCD init */ |
@@ -239,8 +239,8 @@ static void lcd_power_on(void) | |||
239 | lcd_write_reg(R_1ST_SCR_DRV_POS, 0x9f00); | 239 | lcd_write_reg(R_1ST_SCR_DRV_POS, 0x9f00); |
240 | /* SE27-20(End)=0x5c (92), SS27-20(Start)=0x00 */ | 240 | /* SE27-20(End)=0x5c (92), SS27-20(Start)=0x00 */ |
241 | lcd_write_reg(R_2ND_SCR_DRV_POS, 0x5c00); | 241 | lcd_write_reg(R_2ND_SCR_DRV_POS, 0x5c00); |
242 | /* HEA7-0=0xxx, HSA7-0=0xxx */ | 242 | /* HEA7-0=7f, HSA7-0=00 */ |
243 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, y_offset ? 0x8304 : 0x7f00); | 243 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 0x7f00); |
244 | /* PKP12-10=0x0, PKP02-00=0x0 */ | 244 | /* PKP12-10=0x0, PKP02-00=0x0 */ |
245 | lcd_write_reg(R_GAMMA_FINE_ADJ_POS1, 0x0003); | 245 | lcd_write_reg(R_GAMMA_FINE_ADJ_POS1, 0x0003); |
246 | /* PKP32-30=0x4, PKP22-20=0x0 */ | 246 | /* PKP32-30=0x4, PKP22-20=0x0 */ |
@@ -395,177 +395,91 @@ void lcd_blit(const fb_data* data, int x, int by, int width, | |||
395 | (void)stride; | 395 | (void)stride; |
396 | } | 396 | } |
397 | 397 | ||
398 | #define CSUB_X 2 | 398 | void lcd_yuv_set_options(unsigned options) |
399 | #define CSUB_Y 2 | 399 | { |
400 | 400 | lcd_yuv_options = options; | |
401 | #define RYFAC (31*257) | 401 | } |
402 | #define GYFAC (31*257) | ||
403 | #define BYFAC (31*257) | ||
404 | #define RVFAC 11170 /* 31 * 257 * 1.402 */ | ||
405 | #define GVFAC (-5690) /* 31 * 257 * -0.714136 */ | ||
406 | #define GUFAC (-2742) /* 31 * 257 * -0.344136 */ | ||
407 | #define BUFAC 14118 /* 31 * 257 * 1.772 */ | ||
408 | 402 | ||
409 | #define ROUNDOFFS (127*257) | 403 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ |
410 | #define ROUNDOFFSG (63*257) | 404 | extern void lcd_write_yuv420_lines(unsigned char const * const src[3], |
405 | int width, | ||
406 | int stride); | ||
407 | extern void lcd_write_yuv420_lines_odither(unsigned char const * const src[3], | ||
408 | int width, | ||
409 | int stride, | ||
410 | int x_screen, /* To align dither pattern */ | ||
411 | int y_screen); | ||
411 | 412 | ||
412 | /* Performance function to blit a YUV bitmap directly to the LCD */ | 413 | /* Performance function to blit a YUV bitmap directly to the LCD */ |
413 | void lcd_yuv_blit(unsigned char * const src[3], | 414 | void lcd_yuv_blit(unsigned char * const src[3], |
414 | int src_x, int src_y, int stride, | 415 | int src_x, int src_y, int stride, |
415 | int x, int y, int width, int height) | 416 | int x, int y, int width, int height) |
416 | { | 417 | { |
417 | int y0, x0, y1, x1; | 418 | const unsigned char *yuv_src[3]; |
418 | int ymax; | 419 | const unsigned char *ysrc_max; |
420 | int y0; | ||
421 | int options; | ||
419 | 422 | ||
420 | if (!display_on) | 423 | if (!display_on) |
421 | return; | 424 | return; |
422 | 425 | ||
423 | width = (width + 1) & ~1; | 426 | width &= ~1; |
427 | height &= ~1; | ||
424 | 428 | ||
425 | /* calculate the drawing region */ | 429 | /* calculate the drawing region */ |
426 | x0 = x; | ||
427 | x1 = x + width - 1; | ||
428 | y0 = y; | ||
429 | y1 = y + height - 1; | ||
430 | 430 | ||
431 | /* The 20GB LCD is actually 128x160 but rotated 90 degrees so the origin | 431 | /* The 20GB LCD is actually 128x160 but rotated 90 degrees so the origin |
432 | * is actually the bottom left and horizontal and vertical are swapped. | 432 | * is actually the bottom left and horizontal and vertical are swapped. |
433 | * Rockbox expects the origin to be the top left so we need to use | 433 | * Rockbox expects the origin to be the top left so we need to use |
434 | * 127 - y instead of just y */ | 434 | * 127 - y instead of just y */ |
435 | |||
436 | /* max horiz << 8 | start horiz */ | ||
437 | lcd_send_cmd(R_HORIZ_RAM_ADDR_POS); | ||
438 | lcd_send_data( (((LCD_HEIGHT-1)-y0+y_offset) << 8) | ((LCD_HEIGHT-1)-y1+y_offset) ); | ||
439 | 435 | ||
440 | /* max vert << 8 | start vert */ | 436 | /* max vert << 8 | start vert */ |
441 | lcd_send_cmd(R_VERT_RAM_ADDR_POS); | 437 | lcd_write_reg(R_VERT_RAM_ADDR_POS, ((x + width - 1) << 8) | x); |
442 | lcd_send_data((x1 << 8) | x0); | ||
443 | |||
444 | /* position cursor (set AD0-AD15) */ | ||
445 | /* start vert << 8 | start horiz */ | ||
446 | lcd_send_cmd(R_RAM_ADDR_SET); | ||
447 | lcd_send_data( (x0 << 8) | ((LCD_HEIGHT-1)-y0+y_offset) ); | ||
448 | |||
449 | /* start drawing */ | ||
450 | lcd_send_cmd(R_WRITE_DATA_2_GRAM); | ||
451 | 438 | ||
452 | ymax = y + height - 1 ; | 439 | y0 = LCD_HEIGHT - 1 - y + y_offset; |
453 | 440 | ||
454 | const int stride_div_csub_x = stride/CSUB_X; | 441 | /* DIT=0, BGR=1, HWM=0, I/D1-0=10, AM=0, LG2-0=000 */ |
442 | lcd_write_reg(R_ENTRY_MODE, 0x1020); | ||
455 | 443 | ||
456 | for (; y <= ymax ; y++) | 444 | yuv_src[0] = src[0] + src_y * stride + src_x; |
457 | { | 445 | yuv_src[1] = src[1] + (src_y * stride >> 2) + (src_x >> 1); |
458 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ | 446 | yuv_src[2] = src[2] + (yuv_src[1] - src[1]); |
459 | const unsigned char *ysrc = src[0] + stride * src_y + src_x; | 447 | ysrc_max = yuv_src[0] + height * stride; |
460 | 448 | ||
461 | const int uvoffset = stride_div_csub_x * (src_y/CSUB_Y) + | 449 | options = lcd_yuv_options; |
462 | (src_x/CSUB_X); | ||
463 | 450 | ||
464 | const unsigned char *usrc = src[1] + uvoffset; | 451 | do |
465 | const unsigned char *vsrc = src[2] + uvoffset; | 452 | { |
466 | const unsigned char *row_end = ysrc + width; | 453 | /* max horiz << 8 | start horiz */ |
454 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (y0 << 8) | (y0 - 1)); | ||
467 | 455 | ||
468 | int y, u, v; | 456 | /* position cursor (set AD0-AD15) */ |
469 | int red1, green1, blue1; | 457 | /* start vert << 8 | start horiz */ |
470 | int red2, green2, blue2; | 458 | lcd_write_reg(R_RAM_ADDR_SET, (x << 8) | y0); |
471 | unsigned rbits, gbits, bbits; | ||
472 | 459 | ||
473 | int rc, gc, bc; | 460 | /* start drawing */ |
461 | lcd_send_cmd(R_WRITE_DATA_2_GRAM); | ||
474 | 462 | ||
475 | do | 463 | if (options & LCD_YUV_DITHER) |
464 | { | ||
465 | lcd_write_yuv420_lines_odither(yuv_src, width, stride, | ||
466 | x, y); | ||
467 | y -= 2; | ||
468 | } | ||
469 | else | ||
476 | { | 470 | { |
477 | u = *usrc++ - 128; | 471 | lcd_write_yuv420_lines(yuv_src, width, stride); |
478 | v = *vsrc++ - 128; | ||
479 | rc = RVFAC * v + ROUNDOFFS; | ||
480 | gc = GVFAC * v + GUFAC * u + ROUNDOFFSG; | ||
481 | bc = BUFAC * u + ROUNDOFFS; | ||
482 | |||
483 | /* Pixel 1 */ | ||
484 | y = *ysrc++; | ||
485 | |||
486 | red1 = RYFAC * y + rc; | ||
487 | green1 = GYFAC * y + gc; | ||
488 | blue1 = BYFAC * y + bc; | ||
489 | |||
490 | /* Pixel 2 */ | ||
491 | y = *ysrc++; | ||
492 | red2 = RYFAC * y + rc; | ||
493 | green2 = GYFAC * y + gc; | ||
494 | blue2 = BYFAC * y + bc; | ||
495 | |||
496 | /* Since out of bounds errors are relatively rare, we check two | ||
497 | pixels at once to see if any components are out of bounds, and | ||
498 | then fix whichever is broken. This works due to high values and | ||
499 | negative values both becoming larger than the cutoff when | ||
500 | casted to unsigned. And ORing them together checks all of them | ||
501 | simultaneously. */ | ||
502 | if (((unsigned)(red1 | green1 | blue1 | | ||
503 | red2 | green2 | blue2)) > (RYFAC*255+ROUNDOFFS)) { | ||
504 | if (((unsigned)(red1 | green1 | blue1)) > | ||
505 | (RYFAC*255+ROUNDOFFS)) { | ||
506 | if ((unsigned)red1 > (RYFAC*255+ROUNDOFFS)) | ||
507 | { | ||
508 | if (red1 < 0) | ||
509 | red1 = 0; | ||
510 | else | ||
511 | red1 = (RYFAC*255+ROUNDOFFS); | ||
512 | } | ||
513 | if ((unsigned)green1 > (GYFAC*255+ROUNDOFFSG)) | ||
514 | { | ||
515 | if (green1 < 0) | ||
516 | green1 = 0; | ||
517 | else | ||
518 | green1 = (GYFAC*255+ROUNDOFFSG); | ||
519 | } | ||
520 | if ((unsigned)blue1 > (BYFAC*255+ROUNDOFFS)) | ||
521 | { | ||
522 | if (blue1 < 0) | ||
523 | blue1 = 0; | ||
524 | else | ||
525 | blue1 = (BYFAC*255+ROUNDOFFS); | ||
526 | } | ||
527 | } | ||
528 | |||
529 | if (((unsigned)(red2 | green2 | blue2)) > | ||
530 | (RYFAC*255+ROUNDOFFS)) { | ||
531 | if ((unsigned)red2 > (RYFAC*255+ROUNDOFFS)) | ||
532 | { | ||
533 | if (red2 < 0) | ||
534 | red2 = 0; | ||
535 | else | ||
536 | red2 = (RYFAC*255+ROUNDOFFS); | ||
537 | } | ||
538 | if ((unsigned)green2 > (GYFAC*255+ROUNDOFFSG)) | ||
539 | { | ||
540 | if (green2 < 0) | ||
541 | green2 = 0; | ||
542 | else | ||
543 | green2 = (GYFAC*255+ROUNDOFFSG); | ||
544 | } | ||
545 | if ((unsigned)blue2 > (BYFAC*255+ROUNDOFFS)) | ||
546 | { | ||
547 | if (blue2 < 0) | ||
548 | blue2 = 0; | ||
549 | else | ||
550 | blue2 = (BYFAC*255+ROUNDOFFS); | ||
551 | } | ||
552 | } | ||
553 | } | ||
554 | |||
555 | rbits = red1 >> 16 ; | ||
556 | gbits = green1 >> 15 ; | ||
557 | bbits = blue1 >> 16 ; | ||
558 | lcd_send_data((rbits << 11) | (gbits << 5) | bbits); | ||
559 | |||
560 | rbits = red2 >> 16 ; | ||
561 | gbits = green2 >> 15 ; | ||
562 | bbits = blue2 >> 16 ; | ||
563 | lcd_send_data((rbits << 11) | (gbits << 5) | bbits); | ||
564 | } | 472 | } |
565 | while (ysrc < row_end); | ||
566 | 473 | ||
567 | src_y++; | 474 | y0 -= 2; |
475 | yuv_src[0] += stride << 1; | ||
476 | yuv_src[1] += stride >> 1; | ||
477 | yuv_src[2] += stride >> 1; | ||
568 | } | 478 | } |
479 | while (yuv_src[0] < ysrc_max); | ||
480 | |||
481 | /* DIT=0, BGR=1, HWM=0, I/D1-0=10, AM=1, LG2-0=000 */ | ||
482 | lcd_write_reg(R_ENTRY_MODE, 0x1028); | ||
569 | } | 483 | } |
570 | 484 | ||
571 | 485 | ||
@@ -573,8 +487,7 @@ void lcd_yuv_blit(unsigned char * const src[3], | |||
573 | void lcd_update_rect(int x0, int y0, int width, int height) | 487 | void lcd_update_rect(int x0, int y0, int width, int height) |
574 | { | 488 | { |
575 | int x1, y1; | 489 | int x1, y1; |
576 | 490 | unsigned short *addr; | |
577 | unsigned short *addr = (unsigned short *)lcd_framebuffer; | ||
578 | 491 | ||
579 | if (!display_on) | 492 | if (!display_on) |
580 | return; | 493 | return; |