summaryrefslogtreecommitdiff
path: root/firmware/target/arm/samsung
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/samsung')
-rw-r--r--firmware/target/arm/samsung/yh820/lcd-as-yh820.S550
-rw-r--r--firmware/target/arm/samsung/yh820/lcd-yh820.c74
-rw-r--r--firmware/target/arm/samsung/yh925/lcd-as-yh925.S538
-rw-r--r--firmware/target/arm/samsung/yh925/lcd-yh925.c94
4 files changed, 1256 insertions, 0 deletions
diff --git a/firmware/target/arm/samsung/yh820/lcd-as-yh820.S b/firmware/target/arm/samsung/yh820/lcd-as-yh820.S
new file mode 100644
index 0000000000..542ceeeb36
--- /dev/null
+++ b/firmware/target/arm/samsung/yh820/lcd-as-yh820.S
@@ -0,0 +1,550 @@
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 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
23#include "config.h"
24#include "cpu.h"
25
26/****************************************************************************
27 * void lcd_write_yuv420_lines(unsigned char const * const src[3],
28 * int width,
29 * int stride);
30 *
31 * |R| |1.000000 -0.000001 1.402000| |Y'|
32 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
33 * |B| |1.000000 1.772000 0.000000| |Pr|
34 * Scaled, normalized, rounded and tweaked to yield RGB 565:
35 * |R| |74 0 101| |Y' - 16| >> 9
36 * |G| = |74 -24 -51| |Cb - 128| >> 8
37 * |B| |74 128 0| |Cr - 128| >> 9
38 *
39 * Write four RGB565 pixels in the following order on each loop:
40 * 1 3 + > down
41 * 2 4 \/ left
42 */
43 .section .icode, "ax", %progbits
44 .align 2
45 .global lcd_write_yuv420_lines
46 .type lcd_write_yuv420_lines, %function
47lcd_write_yuv420_lines:
48 @ r0 = yuv_src
49 @ r1 = width
50 @ r2 = stride
51 stmfd sp!, { r4-r10, lr } @ save non-scratch
52 ldmia r0, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p
53 @ r5 = yuv_src[1] = Cb_p
54 @ r6 = yuv_src[2] = Cr_p
55 @ r0 = scratch
56 sub r2, r2, #1 @
57 mov r3, #0x70000000 @
58 orr r3, r3, #0x3000 @ r3 = LCD1_BASE
5910: @ loop line @
60 ldrb r7, [r4], #1 @ r7 = *Y'_p++;
61 ldrb r8, [r5], #1 @ r8 = *Cb_p++;
62 ldrb r9, [r6], #1 @ r9 = *Cr_p++;
63 @
64 sub r7, r7, #16 @ r7 = Y = (Y' - 16)*74
65 add r12, r7, r7, asl #2 @ actually (Y' - 16)*37 and shift right
66 add r7, r12, r7, asl #5 @ by one less when adding - same for all
67 @
68 sub r8, r8, #128 @ Cb -= 128
69 sub r9, r9, #128 @ Cr -= 128
70 @
71 add r10, r9, r9, asl #1 @ r10 = Cr*51 + Cb*24
72 add r10, r10, r10, asl #4 @
73 add r10, r10, r8, asl #3 @
74 add r10, r10, r8, asl #4 @
75 @
76 add lr, r9, r9, asl #2 @ r9 = Cr*101
77 add lr, lr, r9, asl #5 @
78 add r9, lr, r9, asl #6 @
79 @
80 add r8, r8, #2 @ r8 = bu = (Cb*128 + 128) >> 8
81 mov r8, r8, asr #2 @
82 add r9, r9, #256 @ r9 = rv = (r9 + 256) >> 9
83 mov r9, r9, asr #9 @
84 rsb r10, r10, #128 @ r10 = guv = (-r10 + 128) >> 8
85 mov r10, r10, asr #8 @
86 @ compute R, G, and B
87 add r0, r8, r7, asr #8 @ r0 = b = (Y >> 9) + bu
88 add lr, r9, r7, asr #8 @ lr = r = (Y >> 9) + rv
89 add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv
90 @
91 orr r12, r0, lr @ check if clamping is needed...
92 orr r12, r12, r7, asr #1 @ ...at all
93 cmp r12, #31 @
94 bls 15f @ no clamp @
95 cmp r0, #31 @ clamp b
96 mvnhi r0, r0, asr #31 @
97 andhi r0, r0, #31 @
98 cmp lr, #31 @ clamp r
99 mvnhi lr, lr, asr #31 @
100 andhi lr, lr, #31 @
101 cmp r7, #63 @ clamp g
102 mvnhi r7, r7, asr #31 @
103 andhi r7, r7, #63 @
10415: @ no clamp @
105 @
106 ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride)
107 @
108 mov lr, lr, lsl #3 @
109 orr lr, lr, r7, lsr #3 @ lr = (r << 3) | (g >> 3)
110 orr r0, r0, r7, lsl #5 @ r0 = (g << 5) | b
1111: @ busy @
112 ldr r7, [r3] @ r7 = LCD1_BASE
113 tst r7, #LCD1_BUSY_MASK @ bridge busy?
114 bne 1b @
115 str lr, [r3, #0x10] @ send MSB
1161: @busy @
117 ldr r7, [r3] @ r7 = LCD1_BASE
118 tst r7, #LCD1_BUSY_MASK @ bridge busy?
119 bne 1b @
120 str r0, [r3, #0x10] @ send LSB
121 @
122 sub r7, r12, #16 @ r7 = Y = (Y' - 16)*74
123 add r12, r7, r7, asl #2 @
124 add r7, r12, r7, asl #5 @
125 @ compute R, G, and B
126 add r0, r8, r7, asr #8 @ r0 = b = (Y >> 9) + bu
127 add lr, r9, r7, asr #8 @ lr = r = (Y >> 9) + rv
128 add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv
129 @
130 orr r12, r0, lr @ check if clamping is needed...
131 orr r12, r12, r7, asr #1 @ ...at all
132 cmp r12, #31 @
133 bls 15f @ no clamp @
134 cmp r0, #31 @ clamp b
135 mvnhi r0, r0, asr #31 @
136 andhi r0, r0, #31 @
137 cmp lr, #31 @ clamp r
138 mvnhi lr, lr, asr #31 @
139 andhi lr, lr, #31 @
140 cmp r7, #63 @ clamp g
141 mvnhi r7, r7, asr #31 @
142 andhi r7, r7, #63 @
14315: @ no clamp @
144 @
145 ldrb r12, [r4], #1 @ r12 = Y' = *(Y'_p++)
146 @
147 mov lr, lr, lsl #3 @
148 orr lr, lr, r7, lsr #3 @ lr = (r << 3) | (g >> 3)
149 orr r0, r0, r7, lsl #5 @ r0 = (g << 5) | b
1501: @ busy @
151 ldr r7, [r3] @ r7 = LCD1_BASE
152 tst r7, #LCD1_BUSY_MASK @ bridge busy?
153 bne 1b @
154 str lr, [r3, #0x10] @ send MSB
1551: @ busy @
156 ldr r7, [r3] @ r7 = LCD1_BASE
157 tst r7, #LCD1_BUSY_MASK @ bridge busy?
158 bne 1b @
159 str r0, [r3, #0x10] @ send LSB
160 @
161 sub r7, r12, #16 @ r7 = Y = (Y' - 16)*74
162 add r12, r7, r7, asl #2 @
163 add r7, r12, r7, asl #5 @
164 @ compute R, G, and B
165 add r0, r8, r7, asr #8 @ r0 = b = (Y >> 9) + bu
166 add lr, r9, r7, asr #8 @ lr = r = (Y >> 9) + rv
167 add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv
168 @
169 orr r12, r0, lr @ check if clamping is needed...
170 orr r12, r12, r7, asr #1 @ ...at all
171 cmp r12, #31 @
172 bls 15f @ no clamp @
173 cmp r0, #31 @ clamp b
174 mvnhi r0, r0, asr #31 @
175 andhi r0, r0, #31 @
176 cmp lr, #31 @ clamp r
177 mvnhi lr, lr, asr #31 @
178 andhi lr, lr, #31 @
179 cmp r7, #63 @ clamp g
180 mvnhi r7, r7, asr #31 @
181 andhi r7, r7, #63 @
18215: @ no clamp @
183 @
184 ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride)
185 @
186 @
187 mov lr, lr, lsl #3 @
188 orr lr, lr, r7, lsr #3 @ lr = (r << 3) | (g >> 3)
189 orr r0, r0, r7, lsl #5 @ r0 = (g << 5) | b
1901: @ busy @
191 ldr r7, [r3] @ r7 = LCD1_BASE
192 tst r7, #LCD1_BUSY_MASK @ bridge busy?
193 bne 1b @
194 str lr, [r3, #0x10] @ send MSB
1951: @ busy @
196 ldr r7, [r3] @ r7 = LCD1_BASE
197 tst r7, #LCD1_BUSY_MASK @ bridge busy?
198 bne 1b @
199 str r0, [r3, #0x10] @ send LSB
200 @
201 sub r7, r12, #16 @ r7 = Y = (Y' - 16)*74
202 add r12, r7, r7, asl #2 @
203 add r7, r12, r7, asl #5 @
204 @ compute R, G, and B
205 add r0, r8, r7, asr #8 @ r0 = b = (Y >> 9) + bu
206 add lr, r9, r7, asr #8 @ lr = r = (Y >> 9) + rv
207 add r7, r10, r7, asr #7 @ r7 = g = (Y >> 8) + guv
208 @
209 orr r12, r0, lr @ check if clamping is needed...
210 orr r12, r12, r7, asr #1 @ ...at all
211 cmp r12, #31 @
212 bls 15f @ no clamp @
213 cmp r0, #31 @ clamp b
214 mvnhi r0, r0, asr #31 @
215 andhi r0, r0, #31 @
216 cmp lr, #31 @ clamp r
217 mvnhi lr, lr, asr #31 @
218 andhi lr, lr, #31 @
219 cmp r7, #63 @ clamp g
220 mvnhi r7, r7, asr #31 @
221 andhi r7, r7, #63 @
22215: @ no clamp @
223 @
224 mov lr, lr, lsl #3 @
225 orr lr, lr, r7, lsr #3 @ lr = (r << 3) | (g >> 3)
226 orr r0, r0, r7, lsl #5 @ r0 = (g << 5) | b
2271: @ busy @
228 ldr r7, [r3] @ r7 = LCD1_BASE
229 tst r7, #LCD1_BUSY_MASK @ bridge busy?
230 bne 1b @
231 str lr, [r3, #0x10] @ send MSB
2321: @ busy @
233 ldr r7, [r3] @ r7 = LCD1_BASE
234 tst r7, #LCD1_BUSY_MASK @ bridge busy?
235 bne 1b @
236 str r0, [r3, #0x10] @ send LSB
237 @
238 subs r1, r1, #2 @ subtract block from width
239 bgt 10b @ loop line @
240 @
241 ldmpc regs=r4-r10 @ restore registers and return
242 .ltorg @ dump constant pool
243 .size lcd_write_yuv420_lines, .-lcd_write_yuv420_lines
244
245/****************************************************************************
246 * void lcd_write_yuv420_lines_odither(unsigned char const * const src[3],
247 * int width,
248 * int stride,
249 * int x_screen,
250 * int y_screen);
251 *
252 * |R| |1.000000 -0.000001 1.402000| |Y'|
253 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
254 * |B| |1.000000 1.772000 0.000000| |Pr|
255 * Red scaled at twice g & b but at same precision to place it in correct
256 * bit position after multiply and leave instruction count lower.
257 * |R| |258 0 408| |Y' - 16|
258 * |G| = |149 -49 -104| |Cb - 128|
259 * |B| |149 258 0| |Cr - 128|
260 *
261 * Write four RGB565 pixels in the following order on each loop:
262 * 1 3 + > down
263 * 2 4 \/ left
264 *
265 * Kernel pattern (raw|rotated|use order):
266 * 5 3 4 2 2 6 3 7 row0 row2 > down
267 * 1 7 0 6 | 4 0 5 1 | 2 4 6 0 3 5 7 1 col0 left
268 * 4 2 5 3 | 3 7 2 6 | 3 5 7 1 2 4 6 0 col2 \/
269 * 0 6 1 7 5 1 4 0
270 */
271 .section .icode, "ax", %progbits
272 .align 2
273 .global lcd_write_yuv420_lines_odither
274 .type lcd_write_yuv420_lines_odither, %function
275lcd_write_yuv420_lines_odither:
276 @ r0 = yuv_src
277 @ r1 = width
278 @ r2 = stride
279 @ r3 = x_screen
280 @ [sp] = y_screen
281 stmfd sp!, { r4-r11, lr } @ save non-scratch
282 ldmia r0, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p
283 @ r5 = yuv_src[1] = Cb_p
284 @ r6 = yuv_src[2] = Cr_p
285 @
286 sub r2, r2, #1 @
287 ldr r14, [sp, #36] @ Line up pattern and kernel quadrant
288 eor r14, r14, r3 @
289 and r14, r14, #0x2 @
290 mov r14, r14, lsl #6 @ 0x00 or 0x80
291 mov r3, #0x70000000 @
292 orr r3, r3, #0x3000 @ r3 = LCD1_BASE
29310: @ loop line @
294 @
295 ldrb r7, [r4], #1 @ r7 = *Y'_p++;
296 ldrb r8, [r5], #1 @ r8 = *Cb_p++;
297 ldrb r9, [r6], #1 @ r9 = *Cr_p++;
298 @
299 eor r14, r14, #0x80 @ flip pattern quadrant
300 @
301 sub r7, r7, #16 @ r7 = Y = (Y' - 16)*149
302 add r12, r7, r7, asl #2 @
303 add r12, r12, r12, asl #4 @
304 add r7, r12, r7, asl #6 @
305 @
306 sub r8, r8, #128 @ Cb -= 128
307 sub r9, r9, #128 @ Cr -= 128
308 @
309 add r10, r8, r8, asl #4 @ r10 = guv = Cr*104 + Cb*49
310 add r10, r10, r8, asl #5 @
311 add r10, r10, r9, asl #3 @
312 add r10, r10, r9, asl #5 @
313 add r10, r10, r9, asl #6 @
314 @
315 mov r8, r8, asl #1 @ r8 = bu = Cb*258
316 add r8, r8, r8, asl #7 @
317 @
318 add r9, r9, r9, asl #1 @ r9 = rv = Cr*408
319 add r9, r9, r9, asl #4 @
320 mov r9, r9, asl #3 @
321 @
322 @ compute R, G, and B
323 add r0, r8, r7 @ r0 = b' = Y + bu
324 add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv
325 rsb r7, r10, r7 @ r7 = g' = Y + guv
326 @
327 @ r8 = bu, r9 = rv, r10 = guv
328 @
329 sub r12, r0, r0, lsr #5 @ r0 = 31/32*b + b/256
330 add r0, r12, r0, lsr #8 @
331 @
332 sub r12, r11, r11, lsr #5 @ r11 = 31/32*r + r/256
333 add r11, r12, r11, lsr #8 @
334 @
335 sub r12, r7, r7, lsr #6 @ r7 = 63/64*g + g/256
336 add r7, r12, r7, lsr #8 @
337 @
338 add r12, r14, #0x100 @
339 @
340 add r0, r0, r12 @ b = r0 + delta
341 add r11, r11, r12, lsl #1 @ r = r11 + delta*2
342 add r7, r7, r12, lsr #1 @ g = r7 + delta/2
343 @
344 orr r12, r0, r11, asr #1 @ check if clamping is needed...
345 orr r12, r12, r7 @ ...at all
346 movs r12, r12, asr #15 @
347 beq 15f @ no clamp @
348 movs r12, r0, asr #15 @ clamp b
349 mvnne r0, r12, lsr #15 @
350 andne r0, r0, #0x7c00 @ mask b only if clamped
351 movs r12, r11, asr #16 @ clamp r
352 mvnne r11, r12, lsr #16 @
353 movs r12, r7, asr #15 @ clamp g
354 mvnne r7, r12, lsr #15 @
35515: @ no clamp @
356 @
357 ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride)
358 @
359
360 and r11, r11, #0xf800 @ pack pixel
361 mov r11, r11, lsr #8
362 and r7, r7, #0x7e00
363 orr r11, r11, r7, lsr #12
364 mov r7, r7, lsr#4
365 orr r0, r7, r0, lsr #10
3661: @ busy @
367 ldr r7, [r3] @ r7 = LCD1_BASE
368 tst r7, #LCD1_BUSY_MASK @ bridge busy?
369 bne 1b @
370 str r11, [r3, #0x10] @ send MSB
3711: @ busy @
372 ldr r7, [r3] @ r7 = LCD1_BASE
373 tst r7, #LCD1_BUSY_MASK @ bridge busy?
374 bne 1b @
375 str r0, [r3, #0x10] @ send LSB
376 @
377 sub r7, r12, #16 @ r7 = Y = (Y' - 16)*149
378 add r12, r7, r7, asl #2 @
379 add r12, r12, r12, asl #4 @
380 add r7, r12, r7, asl #6 @
381 @ compute R, G, and B
382 add r0, r8, r7 @ r0 = b' = Y + bu
383 add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv
384 rsb r7, r10, r7 @ r7 = g' = Y + guv
385 @
386 sub r12, r0, r0, lsr #5 @ r0 = 31/32*b' + b'/256
387 add r0, r12, r0, lsr #8 @
388 @
389 sub r12, r11, r11, lsr #5 @ r11 = 31/32*r' + r'/256
390 add r11, r12, r11, lsr #8 @
391 @
392 sub r12, r7, r7, lsr #6 @ r7 = 63/64*g' + g'/256
393 add r7, r12, r7, lsr #8 @
394 @
395 add r12, r14, #0x200 @
396 @
397 add r0, r0, r12 @ b = r0 + delta
398 add r11, r11, r12, lsl #1 @ r = r11 + delta*2
399 add r7, r7, r12, lsr #1 @ g = r7 + delta/2
400 @
401 orr r12, r0, r11, asr #1 @ check if clamping is needed...
402 orr r12, r12, r7 @ ...at all
403 movs r12, r12, asr #15 @
404 beq 15f @ no clamp @
405 movs r12, r0, asr #15 @ clamp b
406 mvnne r0, r12, lsr #15 @
407 andne r0, r0, #0x7c00 @ mask b only if clamped
408 movs r12, r11, asr #16 @ clamp r
409 mvnne r11, r12, lsr #16 @
410 movs r12, r7, asr #15 @ clamp g
411 mvnne r7, r12, lsr #15 @
41215: @ no clamp @
413 @
414 ldrb r12, [r4], #1 @ r12 = Y' = *(Y'_p++)
415
416 and r11, r11, #0xf800 @ pack pixel
417 mov r11, r11, lsr #8
418 and r7, r7, #0x7e00
419 orr r11, r11, r7, lsr #12
420 mov r7, r7, lsr#4
421 orr r0, r7, r0, lsr #10
4221: @ busy @
423 ldr r7, [r3] @ r7 = LCD1_BASE
424 tst r7, #LCD1_BUSY_MASK @ bridge busy?
425 bne 1b @
426 str r11, [r3, #0x10] @ send MSB
4271: @ busy @
428 ldr r7, [r3] @ r7 = LCD1_BASE
429 tst r7, #LCD1_BUSY_MASK @ bridge busy?
430 bne 1b @
431 str r0, [r3, #0x10] @ send LSB
432
433 sub r7, r12, #16 @ r7 = Y = (Y' - 16)*149
434 add r12, r7, r7, asl #2 @
435 add r12, r12, r12, asl #4 @
436 add r7, r12, r7, asl #6 @
437 @ compute R, G, and B
438 add r0, r8, r7 @ r0 = b' = Y + bu
439 add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv
440 rsb r7, r10, r7 @ r7 = g' = Y + guv
441 @
442 @ r8 = bu, r9 = rv, r10 = guv
443 @
444 sub r12, r0, r0, lsr #5 @ r0 = 31/32*b' + b'/256
445 add r0, r12, r0, lsr #8 @
446 @
447 sub r12, r11, r11, lsr #5 @ r11 = 31/32*r' + r'/256
448 add r11, r12, r11, lsr #8 @
449 @
450 sub r12, r7, r7, lsr #6 @ r7 = 63/64*g' + g'/256
451 add r7, r12, r7, lsr #8 @
452 @
453 add r12, r14, #0x300 @
454 @
455 add r0, r0, r12 @ b = r0 + delta
456 add r11, r11, r12, lsl #1 @ r = r11 + delta*2
457 add r7, r7, r12, lsr #1 @ g = r7 + delta/2
458 @
459 orr r12, r0, r11, asr #1 @ check if clamping is needed...
460 orr r12, r12, r7 @ ...at all
461 movs r12, r12, asr #15 @
462 beq 15f @ no clamp @
463 movs r12, r0, asr #15 @ clamp b
464 mvnne r0, r12, lsr #15 @
465 andne r0, r0, #0x7c00 @ mask b only if clamped
466 movs r12, r11, asr #16 @ clamp r
467 mvnne r11, r12, lsr #16 @
468 movs r12, r7, asr #15 @ clamp g
469 mvnne r7, r12, lsr #15 @
47015: @ no clamp @
471 @
472 ldrb r12, [r4, r2] @ r12 = Y' = *(Y'_p + stride)
473
474 and r11, r11, #0xf800 @ pack pixel
475 mov r11, r11, lsr #8
476 and r7, r7, #0x7e00
477 orr r11, r11, r7, lsr #12
478 mov r7, r7, lsr#4
479 orr r0, r7, r0, lsr #10
4801: @ busy @
481 ldr r7, [r3] @ r7 = LCD1_BASE
482 tst r7, #LCD1_BUSY_MASK @ bridge busy?
483 bne 1b @
484 str r11, [r3, #0x10] @ send MSB
4851: @ busy @
486 ldr r7, [r3] @ r7 = LCD1_BASE
487 tst r7, #LCD1_BUSY_MASK @ bridge busy?
488 bne 1b @
489 str r0, [r3, #0x10] @ send LSB
490
491 sub r7, r12, #16 @ r7 = Y = (Y' - 16)*149
492 add r12, r7, r7, asl #2 @
493 add r12, r12, r12, asl #4 @
494 add r7, r12, r7, asl #6 @
495 @ compute R, G, and B
496 add r0, r8, r7 @ r0 = b' = Y + bu
497 add r11, r9, r7, asl #1 @ r11 = r' = Y*2 + rv
498 rsb r7, r10, r7 @ r7 = g' = Y + guv
499 @
500 sub r12, r0, r0, lsr #5 @ r0 = 31/32*b + b/256
501 add r0, r12, r0, lsr #8 @
502 @
503 sub r12, r11, r11, lsr #5 @ r11 = 31/32*r + r/256
504 add r11, r12, r11, lsr #8 @
505 @
506 sub r12, r7, r7, lsr #6 @ r7 = 63/64*g + g/256
507 add r7, r12, r7, lsr #8 @
508 @
509 @ This element is zero - use r14 @
510 @
511 add r0, r0, r14 @ b = r0 + delta
512 add r11, r11, r14, lsl #1 @ r = r11 + delta*2
513 add r7, r7, r14, lsr #1 @ g = r7 + delta/2
514 @
515 orr r12, r0, r11, asr #1 @ check if clamping is needed...
516 orr r12, r12, r7 @ ...at all
517 movs r12, r12, asr #15 @
518 beq 15f @ no clamp @
519 movs r12, r0, asr #15 @ clamp b
520 mvnne r0, r12, lsr #15 @
521 andne r0, r0, #0x7c00 @ mask b only if clamped
522 movs r12, r11, asr #16 @ clamp r
523 mvnne r11, r12, lsr #16 @
524 movs r12, r7, asr #15 @ clamp g
525 mvnne r7, r12, lsr #15 @
52615: @ no clamp @
527
528 and r11, r11, #0xf800 @ pack pixel
529 mov r11, r11, lsr #8
530 and r7, r7, #0x7e00
531 orr r11, r11, r7, lsr #12
532 mov r7, r7, lsr#4
533 orr r0, r7, r0, lsr #10
5341: @ busy @
535 ldr r7, [r3] @ r7 = LCD1_BASE
536 tst r7, #LCD1_BUSY_MASK @ bridge busy?
537 bne 1b @
538 str r11, [r3, #0x10] @ send MSB
5391: @ busy @
540 ldr r7, [r3] @ r7 = LCD1_BASE
541 tst r7, #LCD1_BUSY_MASK @ bridge busy?
542 bne 1b @
543 str r0, [r3, #0x10] @ send LSB
544
545 subs r1, r1, #2 @ subtract block from width
546 bgt 10b @ loop line @
547 @
548 ldmpc regs=r4-r11 @ restore registers and return
549 .ltorg @ dump constant pool
550 .size lcd_write_yuv420_lines_odither, .-lcd_write_yuv420_lines_odither
diff --git a/firmware/target/arm/samsung/yh820/lcd-yh820.c b/firmware/target/arm/samsung/yh820/lcd-yh820.c
index 25692eb8ac..f4b55ab917 100644
--- a/firmware/target/arm/samsung/yh820/lcd-yh820.c
+++ b/firmware/target/arm/samsung/yh820/lcd-yh820.c
@@ -30,6 +30,8 @@
30#endif 30#endif
31 31
32/* Display status */ 32/* Display status */
33static unsigned lcd_yuv_options SHAREDBSS_ATTR = 0;
34
33#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) 35#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
34static bool is_lcd_enabled = true; 36static bool is_lcd_enabled = true;
35#endif 37#endif
@@ -289,6 +291,78 @@ void lcd_set_flip(bool yesno)
289 291
290/*** update functions ***/ 292/*** update functions ***/
291 293
294void lcd_yuv_set_options(unsigned options)
295{
296 lcd_yuv_options = options;
297}
298
299/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
300extern void lcd_write_yuv420_lines(unsigned char const * const src[3],
301 int width,
302 int stride);
303extern void lcd_write_yuv420_lines_odither(unsigned char const * const src[3],
304 int width,
305 int stride,
306 int x_screen, /* To align dither pattern */
307 int y_screen);
308/* Performance function to blit a YUV bitmap directly to the LCD */
309void lcd_blit_yuv(unsigned char * const src[3],
310 int src_x, int src_y, int stride,
311 int x, int y, int width, int height)
312{
313 unsigned char const * yuv_src[3];
314 off_t z;
315
316 /* Sorry, but width and height must be >= 2 or else */
317 width &= ~1;
318 height >>= 1;
319
320 z = stride*src_y;
321 yuv_src[0] = src[0] + z + src_x;
322 yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
323 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
324
325 lcd_send_command(R_ENTRY_MODE);
326 lcd_send_command(0x03);
327
328 lcd_send_command(R_Y_ADDR_AREA);
329 lcd_send_command(x + 4);
330 lcd_send_command(x + width - 1 + 4);
331
332 if (lcd_yuv_options & LCD_YUV_DITHER)
333 {
334 do
335 {
336 lcd_send_command(R_X_ADDR_AREA);
337 lcd_send_command(y);
338 lcd_send_command(y + 1);
339
340 lcd_write_yuv420_lines_odither(yuv_src, width, stride, x, y);
341 yuv_src[0] += stride << 1; /* Skip down two luma lines */
342 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
343 yuv_src[2] += stride >> 1;
344 y += 2;
345 }
346 while (--height > 0);
347 }
348 else
349 {
350 do
351 {
352 lcd_send_command(R_X_ADDR_AREA);
353 lcd_send_command(y);
354 lcd_send_command(y + 1);
355
356 lcd_write_yuv420_lines(yuv_src, width, stride);
357 yuv_src[0] += stride << 1; /* Skip down two luma lines */
358 yuv_src[1] += stride >> 1; /* Skip down one chroma line */
359 yuv_src[2] += stride >> 1;
360 y += 2;
361 }
362 while (--height > 0);
363 }
364}
365
292/* Update the display. 366/* Update the display.
293 This must be called after all other LCD functions that change the display. */ 367 This must be called after all other LCD functions that change the display. */
294void lcd_update(void) 368void lcd_update(void)
diff --git a/firmware/target/arm/samsung/yh925/lcd-as-yh925.S b/firmware/target/arm/samsung/yh925/lcd-as-yh925.S
new file mode 100644
index 0000000000..8ac8b4289f
--- /dev/null
+++ b/firmware/target/arm/samsung/yh925/lcd-as-yh925.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
48lcd_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
6210: @ 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 @
10715: @ 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 @
11620: @
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 @
14415: @ 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 @
15320: @
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 @
18115: @ 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 @
19020: @
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 @
21815: @ 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 @
22520: @
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
270lcd_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
29010: @ 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 @
35215: @ 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 @
36420: @
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 @
40615: @ 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 @
41820: @
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 @
46215: @ 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 @
47420: @
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 @
51615: @ 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 @
52620: @
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/samsung/yh925/lcd-yh925.c b/firmware/target/arm/samsung/yh925/lcd-yh925.c
index e2b3ae3694..93bfb3a5f2 100644
--- a/firmware/target/arm/samsung/yh925/lcd-yh925.c
+++ b/firmware/target/arm/samsung/yh925/lcd-yh925.c
@@ -37,6 +37,8 @@ static unsigned short disp_control_rev;
37/* Contrast setting << 8 */ 37/* Contrast setting << 8 */
38static int lcd_contrast; 38static int lcd_contrast;
39 39
40static unsigned lcd_yuv_options SHAREDBSS_ATTR = 0;
41
40/* Forward declarations */ 42/* Forward declarations */
41#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) 43#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
42static void lcd_display_off(void); 44static void lcd_display_off(void);
@@ -508,6 +510,98 @@ bool lcd_active(void)
508 510
509/*** update functions ***/ 511/*** update functions ***/
510 512
513void lcd_yuv_set_options(unsigned options)
514{
515 lcd_yuv_options = options;
516}
517
518/* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */
519extern void lcd_write_yuv420_lines(unsigned char const * const src[3],
520 int width,
521 int stride);
522extern void lcd_write_yuv420_lines_odither(unsigned char const * const src[3],
523 int width,
524 int stride,
525 int x_screen, /* To align dither pattern */
526 int y_screen);
527
528/* Performance function to blit a YUV bitmap directly to the LCD */
529void lcd_blit_yuv(unsigned char * const src[3],
530 int src_x, int src_y, int stride,
531 int x, int y, int width, int height)
532{
533 const unsigned char *yuv_src[3];
534 const unsigned char *ysrc_max;
535 int y0;
536 int options;
537
538 /* NOT MODIFIED FOR THE YH-925 */
539
540 if (!display_on)
541 return;
542
543 width &= ~1;
544 height &= ~1;
545
546 x += x_offset;
547
548 /* calculate the drawing region */
549
550 /* The 20GB LCD is actually 128x160 but rotated 90 degrees so the origin
551 * is actually the bottom left and horizontal and vertical are swapped.
552 * Rockbox expects the origin to be the top left so we need to use
553 * 127 - y instead of just y */
554
555 /* max vert << 8 | start vert */
556 lcd_write_reg(R_VERT_RAM_ADDR_POS, ((x + width - 1) << 8) | x);
557
558 y0 = LCD_HEIGHT - 1 - y + y_offset;
559
560 /* DIT=0, BGR=1, HWM=0, I/D1-0=10, AM=0, LG2-0=000 */
561 lcd_write_reg(R_ENTRY_MODE, 0x1020);
562
563 yuv_src[0] = src[0] + src_y * stride + src_x;
564 yuv_src[1] = src[1] + (src_y * stride >> 2) + (src_x >> 1);
565 yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
566 ysrc_max = yuv_src[0] + height * stride;
567
568 options = lcd_yuv_options;
569
570 do
571 {
572 /* max horiz << 8 | start horiz */
573 lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (y0 << 8) | (y0 - 1));
574
575 /* position cursor (set AD0-AD15) */
576 /* start vert << 8 | start horiz */
577 lcd_write_reg(R_RAM_ADDR_SET, (x << 8) | y0);
578
579 /* start drawing */
580 lcd_send_cmd(R_WRITE_DATA_2_GRAM);
581
582 if (options & LCD_YUV_DITHER)
583 {
584 lcd_write_yuv420_lines_odither(yuv_src, width, stride,
585 x, y);
586 y -= 2;
587 }
588 else
589 {
590 lcd_write_yuv420_lines(yuv_src, width, stride);
591 }
592
593 y0 -= 2;
594 yuv_src[0] += stride << 1;
595 yuv_src[1] += stride >> 1;
596 yuv_src[2] += stride >> 1;
597 }
598 while (yuv_src[0] < ysrc_max);
599
600 /* DIT=0, BGR=1, HWM=0, I/D1-0=10, AM=1, LG2-0=000 */
601 lcd_write_reg(R_ENTRY_MODE, 0x1028);
602}
603
604
511/* Update a fraction of the display. */ 605/* Update a fraction of the display. */
512void lcd_update_rect(int x0, int y0, int width, int height) 606void lcd_update_rect(int x0, int y0, int width, int height)
513{ 607{