diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/target/coldfire/iaudio/x5/lcd-as-x5.S | 334 | ||||
-rwxr-xr-x | firmware/target/coldfire/iaudio/x5/lcd-x5.c | 135 |
2 files changed, 364 insertions, 105 deletions
diff --git a/firmware/target/coldfire/iaudio/x5/lcd-as-x5.S b/firmware/target/coldfire/iaudio/x5/lcd-as-x5.S index 323710cc57..1a527bb8f3 100644 --- a/firmware/target/coldfire/iaudio/x5/lcd-as-x5.S +++ b/firmware/target/coldfire/iaudio/x5/lcd-as-x5.S | |||
@@ -23,10 +23,342 @@ | |||
23 | 23 | ||
24 | .section .icode,"ax",@progbits | 24 | .section .icode,"ax",@progbits |
25 | 25 | ||
26 | /* begin lcd_write_yuv420_lines | ||
27 | * | ||
28 | * See http://en.wikipedia.org/wiki/YCbCr | ||
29 | * ITU-R BT.601 (formerly CCIR 601): | ||
30 | * |Y'| | 0.299000 0.587000 0.114000| |R| | ||
31 | * |Pb| = |-0.168736 -0.331264 0.500000| |G| or 0.564334*(B - Y') | ||
32 | * |Pr| | 0.500000 -0.418688 0.081312| |B| or 0.713267*(R - Y') | ||
33 | * Scaled, normalized and rounded: | ||
34 | * |Y'| | 65 129 25| |R| + 16 : 16->235 | ||
35 | * |Cb| = |-38 -74 112| |G| + 128 : 16->240 | ||
36 | * |Cr| |112 -94 -18| |B| + 128 : 16->240 | ||
37 | * | ||
38 | * The inverse: | ||
39 | * |R| |1.000000 -0.000001 1.402000| |Y'| | ||
40 | * |G| = |1.000000 -0.334136 -0.714136| |Pb| | ||
41 | * |B| |1.000000 1.772000 0.000000| |Pr| | ||
42 | * Scaled, normalized, rounded and tweaked to yield RGB 666: | ||
43 | * |R| |74 0 102| |Y' - 16| / 256 | ||
44 | * |G| = |74 -25 -52| |Cb - 128| / 256 | ||
45 | * |B| |74 129 0| |Cr - 128| / 256 | ||
46 | */ | ||
47 | .align 2 | ||
48 | .global lcd_write_yuv420_lines | ||
49 | .type lcd_write_yuv420_lines,@function | ||
50 | lcd_write_yuv420_lines: | ||
51 | lea.l (-40,%sp),%sp /* free up some registers */ | ||
52 | movem.l %d2-%d7/%a2-%a5,(%sp) | ||
53 | |||
54 | lea.l 0xf0008002,%a0 /* LCD data port */ | ||
55 | move.l (40+4,%sp),%a1 /* Y data */ | ||
56 | move.l (40+8,%sp),%a2 /* Cb data */ | ||
57 | move.l (40+12,%sp),%a3 /* guv storage */ | ||
58 | move.l (40+16,%sp),%a4 /* Cr data */ | ||
59 | move.l (40+20,%sp),%d0 /* width */ | ||
60 | lea.l (%a1,%d0.l),%a5 /* end address */ | ||
61 | |||
62 | .yuv_line_loop1: | ||
63 | /** Write first pixel **/ | ||
64 | clr.l %d1 /* get y component */ | ||
65 | move.b (%a1)+,%d1 | ||
66 | subq.l #8,%d1 | ||
67 | subq.l #8,%d1 | ||
68 | moveq.l #74,%d6 | ||
69 | muls.w %d6,%d1 | ||
70 | asr.l #8,%d1 | ||
71 | |||
72 | clr %d2 /* get bu component */ | ||
73 | move.b (%a2),%d2 | ||
74 | moveq.l #-128,%d6 | ||
75 | add.l %d6,%d2 | ||
76 | move.l %d2,%d3 /* %d3 = cb component for guv */ | ||
77 | move.w #129,%d6 | ||
78 | muls.w %d6,%d2 | ||
79 | asr.l #8,%d2 | ||
80 | move.b %d2,(%a2)+ /* save bu for next line */ | ||
81 | |||
82 | moveq.l #-25,%d6 /* multiply first term of guv */ | ||
83 | muls.w %d6,%d3 | ||
84 | |||
85 | clr %d4 /* get rv component */ | ||
86 | move.b (%a4),%d4 | ||
87 | moveq.l #-128,%d6 | ||
88 | add.l %d6,%d4 | ||
89 | move.l %d4,%d7 /* %d7 = cr component for guv */ | ||
90 | moveq.l #102,%d6 | ||
91 | muls.w %d6,%d4 | ||
92 | asr.l #8,%d4 | ||
93 | move.b %d4,(%a4)+ /* save rv for next line */ | ||
94 | |||
95 | moveq.l #-52,%d6 /* multiply second term of guv */ | ||
96 | muls.w %d6,%d7 | ||
97 | add.l %d7,%d3 | ||
98 | asr.l #8,%d3 | ||
99 | move.b %d3,(%a3)+ /* save guv for next line */ | ||
100 | /* : %d1 = Y, %d2 = bu, %d3 = guv, %d4 = rv */ | ||
101 | |||
102 | move.l %d1,%d5 /* get r */ | ||
103 | add.l %d4,%d5 | ||
104 | move.l %d1,%d6 /* get g */ | ||
105 | add.l %d3,%d6 | ||
106 | move.l %d1,%d7 /* get b */ | ||
107 | add.l %d2,%d7 | ||
108 | |||
109 | move.l %d7,%d1 /* is clamping needed? */ | ||
110 | or.l %d6,%d1 | ||
111 | or.l %d5,%d1 | ||
112 | asr.l #6,%d1 | ||
113 | beq.b .yuv_no_clamp1 /* values in range: skip clamping */ | ||
114 | bpl.b .yuv_r63_test1 /* no negative values: skip to high bounds checks */ | ||
115 | .yuv_r0_test1: | ||
116 | clr.l %d1 /* check for any values < 0 */ | ||
117 | cmp.l %d1,%d5 | ||
118 | bgt.b .yuv_g0_test1 | ||
119 | clr.l %d5 | ||
120 | .yuv_g0_test1: | ||
121 | cmp.l %d1,%d6 | ||
122 | bgt.b .yuv_b0_test1 | ||
123 | clr.l %d6 | ||
124 | .yuv_b0_test1: | ||
125 | cmp.l %d1,%d7 | ||
126 | bgt.b .yuv_r63_test1 | ||
127 | clr.l %d7 | ||
128 | .yuv_r63_test1: /* check for any values > 63 */ | ||
129 | moveq.l #63,%d1 | ||
130 | cmp.l %d1,%d5 | ||
131 | blt.b .yuv_g63_test1 | ||
132 | move.l %d1,%d5 | ||
133 | .yuv_g63_test1: | ||
134 | cmp.l %d1,%d6 | ||
135 | blt.b .yuv_b63_test1 | ||
136 | move.l %d1,%d6 | ||
137 | .yuv_b63_test1: | ||
138 | cmp.l %d1,%d7 | ||
139 | blt.b .yuv_no_clamp1 | ||
140 | move.l %d1,%d7 | ||
141 | .yuv_no_clamp1: | ||
142 | /* : %d5 = R, %d6 = G, %d7 = B */ | ||
143 | |||
144 | move.l %d6,%d1 /* save g for lower 9 bits */ | ||
145 | lsl.l #3,%d5 /* R << 3 */ | ||
146 | lsr.l #3,%d1 /* G >> 3 */ | ||
147 | or.l %d5,%d1 | ||
148 | move.w %d1,(%a0) /* |00000000|000000000|0000000r|rrrrrggg| */ | ||
149 | lsl.l #6,%d6 /* B << 6 */ | ||
150 | or.l %d6,%d7 /* |00000000|000000000|0000gggg|ggbbbbbb| */ | ||
151 | move.w %d7,(%a0) | ||
152 | |||
153 | /** Write second pixel **/ | ||
154 | clr %d1 | ||
155 | move.b (%a1)+,%d1 /* get y component */ | ||
156 | subq.l #8,%d1 | ||
157 | subq.l #8,%d1 | ||
158 | moveq.l #74,%d6 | ||
159 | muls.w %d6,%d1 | ||
160 | asr.l #8,%d1 | ||
161 | /* : %d1 = Y, %d2 = bu, %d3 = guv, %d4 = rv */ | ||
162 | |||
163 | /* Add Y + each chroma component (can clobber %d2-%d4 values now) */ | ||
164 | add.l %d1,%d4 /* get r */ | ||
165 | add.l %d1,%d3 /* get g */ | ||
166 | add.l %d1,%d2 /* get b */ | ||
167 | |||
168 | move.l %d2,%d1 /* is clamping needed? */ | ||
169 | or.l %d3,%d1 | ||
170 | or.l %d4,%d1 | ||
171 | asr.l #6,%d1 | ||
172 | beq.b .yuv_no_clamp2 /* values in range: skip clamping */ | ||
173 | bpl.b .yuv_r63_test2 /* no negative values: skip to high bounds checks */ | ||
174 | .yuv_r0_test2: | ||
175 | clr.l %d1 /* check for any values < 0 */ | ||
176 | cmp.l %d1,%d4 | ||
177 | bgt.b .yuv_g0_test2 | ||
178 | clr.l %d4 | ||
179 | .yuv_g0_test2: | ||
180 | cmp.l %d1,%d3 | ||
181 | bgt.b .yuv_b0_test2 | ||
182 | clr.l %d3 | ||
183 | .yuv_b0_test2: | ||
184 | cmp.l %d1,%d2 | ||
185 | bgt.b .yuv_r63_test2 | ||
186 | clr.l %d2 | ||
187 | .yuv_r63_test2: /* check for any values > 63 */ | ||
188 | moveq.l #63,%d1 | ||
189 | cmp.l %d1,%d4 | ||
190 | blt.b .yuv_g63_test2 | ||
191 | move.l %d1,%d4 | ||
192 | .yuv_g63_test2: | ||
193 | cmp.l %d1,%d3 | ||
194 | blt.b .yuv_b63_test2 | ||
195 | move.l %d1,%d3 | ||
196 | .yuv_b63_test2: | ||
197 | cmp.l %d1,%d2 | ||
198 | blt.b .yuv_no_clamp2 | ||
199 | move.l %d1,%d2 | ||
200 | .yuv_no_clamp2: | ||
201 | /* : %d4 = R, %d3 = G, %d2 = B */ | ||
202 | |||
203 | move.l %d3,%d1 /* save g for lower 9 bits */ | ||
204 | lsl.l #3,%d4 /* R << 3 */ | ||
205 | lsr.l #3,%d1 /* G >> 3 */ | ||
206 | or.l %d4,%d1 /* |00000000|000000000|0000000r|rrrrrggg| */ | ||
207 | move.w %d1,(%a0) | ||
208 | lsl.l #6,%d3 /* G << 6 */ | ||
209 | or.l %d3,%d2 /* |00000000|000000000|0000gggg|ggbbbbbb| */ | ||
210 | move.w %d2,(%a0) | ||
211 | |||
212 | cmp.l %a1,%a5 /* run %a1 up to end of line */ | ||
213 | bhi.w .yuv_line_loop1 | ||
214 | |||
215 | /* Rewind chroma pointers */ | ||
216 | move.l (40+8,%sp),%a2 /* bu data */ | ||
217 | move.l (40+12,%sp),%a3 /* guv data */ | ||
218 | move.l (40+16,%sp),%a4 /* rv data */ | ||
219 | lea.l (%a5,%d0),%a5 /* next end address */ | ||
220 | |||
221 | .yuv_line_loop2: | ||
222 | clr %d1 | ||
223 | move.b (%a1)+,%d1 /* get y component */ | ||
224 | subq.l #8,%d1 | ||
225 | subq.l #8,%d1 | ||
226 | moveq.l #74,%d6 | ||
227 | muls.w %d6,%d1 | ||
228 | asr.l #8,%d1 | ||
229 | |||
230 | move.b (%a2)+,%d2 /* read save chromas and sign extend */ | ||
231 | extb.l %d2 | ||
232 | move.b (%a3)+,%d3 | ||
233 | extb.l %d3 | ||
234 | move.b (%a4)+,%d4 | ||
235 | extb.l %d4 | ||
236 | /* : %d1 = Y, %d2 = bu, %d3 = guv, %d4 = rv */ | ||
237 | |||
238 | move.l %d1,%d5 /* get r */ | ||
239 | add.l %d4,%d5 | ||
240 | move.l %d1,%d6 /* get g */ | ||
241 | add.l %d3,%d6 | ||
242 | move.l %d1,%d7 /* get b */ | ||
243 | add.l %d2,%d7 | ||
244 | |||
245 | move.l %d7,%d1 /* is clamping needed? */ | ||
246 | or.l %d6,%d1 | ||
247 | or.l %d5,%d1 | ||
248 | asr.l #6,%d1 | ||
249 | beq.b .yuv_no_clamp3 /* values in range: skip clamping */ | ||
250 | bpl.b .yuv_r63_test3 /* no negative values: skip to high bounds checks */ | ||
251 | .yuv_r0_test3: | ||
252 | clr.l %d1 /* check for any values < 0 */ | ||
253 | cmp.l %d1,%d5 | ||
254 | bgt.b .yuv_g0_test3 | ||
255 | clr.l %d5 | ||
256 | .yuv_g0_test3: | ||
257 | cmp.l %d1,%d6 | ||
258 | bgt.b .yuv_b0_test3 | ||
259 | clr.l %d6 | ||
260 | .yuv_b0_test3: | ||
261 | cmp.l %d1,%d7 | ||
262 | bgt.b .yuv_r63_test3 | ||
263 | clr.l %d7 | ||
264 | .yuv_r63_test3: /* check for any values > 63 */ | ||
265 | moveq.l #63,%d1 | ||
266 | cmp.l %d1,%d5 | ||
267 | blt.b .yuv_g63_test3 | ||
268 | move.l %d1,%d5 | ||
269 | .yuv_g63_test3: | ||
270 | cmp.l %d1,%d6 | ||
271 | blt.b .yuv_b63_test3 | ||
272 | move.l %d1,%d6 | ||
273 | .yuv_b63_test3: | ||
274 | cmp.l %d1,%d7 | ||
275 | blt.b .yuv_no_clamp3 | ||
276 | move.l %d1,%d7 | ||
277 | .yuv_no_clamp3: | ||
278 | /* : %d5 = R, %d6 = G, %d7 = B */ | ||
279 | |||
280 | move.l %d6,%d1 /* save g for lower 9 bits */ | ||
281 | lsl.l #3,%d5 /* R << 3 */ | ||
282 | lsr.l #3,%d1 /* G >> 3 */ | ||
283 | or.l %d5,%d1 | ||
284 | move.w %d1,(%a0) /* |00000000|000000000|0000000r|rrrrrggg| */ | ||
285 | lsl.l #6,%d6 /* B << 6 */ | ||
286 | or.l %d6,%d7 /* |00000000|000000000|0000gggg|ggbbbbbb| */ | ||
287 | move.w %d7,(%a0) | ||
288 | |||
289 | /** Write second pixel **/ | ||
290 | clr %d1 | ||
291 | move.b (%a1)+,%d1 /* get y component */ | ||
292 | subq.l #8,%d1 | ||
293 | subq.l #8,%d1 | ||
294 | moveq.l #74,%d6 | ||
295 | muls.w %d6,%d1 | ||
296 | asr.l #8,%d1 | ||
297 | /* : %d1 = Y, %d2 = bu, %d3 = guv, %d4 = rv */ | ||
298 | |||
299 | /* Add Y + each chroma component (can clobber %d2-%d4 values now) */ | ||
300 | add.l %d1,%d4 /* get r */ | ||
301 | add.l %d1,%d3 /* get g */ | ||
302 | add.l %d1,%d2 /* get b */ | ||
303 | |||
304 | move.l %d2,%d1 /* is clamping needed? */ | ||
305 | or.l %d3,%d1 | ||
306 | or.l %d4,%d1 | ||
307 | asr.l #6,%d1 | ||
308 | beq.b .yuv_no_clamp4 /* values in range: skip clamping */ | ||
309 | bpl.b .yuv_r63_test4 /* no negative values: skip to high bounds checks */ | ||
310 | .yuv_r0_test4: | ||
311 | clr.l %d1 /* check for any values < 0 */ | ||
312 | cmp.l %d1,%d4 | ||
313 | bgt.b .yuv_g0_test4 | ||
314 | clr.l %d4 | ||
315 | .yuv_g0_test4: | ||
316 | cmp.l %d1,%d3 | ||
317 | bgt.b .yuv_b0_test4 | ||
318 | clr.l %d3 | ||
319 | .yuv_b0_test4: | ||
320 | cmp.l %d1,%d2 | ||
321 | bgt.b .yuv_r63_test4 | ||
322 | clr.l %d2 | ||
323 | .yuv_r63_test4: /* check for any values > 63 */ | ||
324 | moveq.l #63,%d1 | ||
325 | cmp.l %d1,%d4 | ||
326 | blt.b .yuv_g63_test4 | ||
327 | move.l %d1,%d4 | ||
328 | .yuv_g63_test4: | ||
329 | cmp.l %d1,%d3 | ||
330 | blt.b .yuv_b63_test4 | ||
331 | move.l %d1,%d3 | ||
332 | .yuv_b63_test4: | ||
333 | cmp.l %d1,%d2 | ||
334 | blt.b .yuv_no_clamp4 | ||
335 | move.l %d1,%d2 | ||
336 | .yuv_no_clamp4: | ||
337 | /* : %d4 = R, %d3 = G, %d2 = B */ | ||
338 | |||
339 | move.l %d3,%d1 /* save g for lower 9 bits */ | ||
340 | lsl.l #3,%d4 /* R << 3 */ | ||
341 | lsr.l #3,%d1 /* G >> 3 */ | ||
342 | or.l %d4,%d1 /* |00000000|000000000|0000000r|rrrrrggg| */ | ||
343 | move.w %d1,(%a0) | ||
344 | lsl.l #6,%d3 /* G << 6 */ | ||
345 | or.l %d3,%d2 /* |00000000|000000000|0000gggg|ggbbbbbb| */ | ||
346 | move.w %d2,(%a0) | ||
347 | |||
348 | cmp.l %a1,%a5 /* run %a0 up to end of line */ | ||
349 | bhi.w .yuv_line_loop2 | ||
350 | |||
351 | movem.l (%sp),%d2-%d7/%a2-%a5 | ||
352 | lea.l (40,%sp),%sp /* restore registers */ | ||
353 | |||
354 | rts | ||
355 | /* end lcd_write_yuv420_lines */ | ||
356 | |||
357 | |||
358 | /* begin lcd_write_data */ | ||
26 | .align 2 | 359 | .align 2 |
27 | .global lcd_write_data | 360 | .global lcd_write_data |
28 | .type lcd_write_data,@function | 361 | .type lcd_write_data,@function |
29 | |||
30 | lcd_write_data: | 362 | lcd_write_data: |
31 | move.l (4,%sp),%a0 /* data pointer */ | 363 | move.l (4,%sp),%a0 /* data pointer */ |
32 | move.l (8,%sp),%d0 /* length in words */ | 364 | move.l (8,%sp),%d0 /* length in words */ |
diff --git a/firmware/target/coldfire/iaudio/x5/lcd-x5.c b/firmware/target/coldfire/iaudio/x5/lcd-x5.c index 240b1db586..e1fe23a442 100755 --- a/firmware/target/coldfire/iaudio/x5/lcd-x5.c +++ b/firmware/target/coldfire/iaudio/x5/lcd-x5.c | |||
@@ -100,25 +100,6 @@ static inline void lcd_begin_write_gram(void) | |||
100 | LCD_CMD = R_WRITE_DATA_2_GRAM << 1; | 100 | LCD_CMD = R_WRITE_DATA_2_GRAM << 1; |
101 | } | 101 | } |
102 | 102 | ||
103 | static inline void lcd_write_one(unsigned short px) | ||
104 | { | ||
105 | unsigned short pxsr = px >> 8; | ||
106 | LCD_DATA = pxsr + (pxsr & 0x1F8); | ||
107 | LCD_DATA = px << 1; | ||
108 | } | ||
109 | |||
110 | /* Write two pixels to gram from a long */ | ||
111 | /* called very frequently - inline! */ | ||
112 | static inline void lcd_write_two(unsigned long px2) | ||
113 | { | ||
114 | unsigned short px2sr = px2 >> 24; | ||
115 | LCD_DATA = px2sr + (px2sr & 0x1F8); | ||
116 | LCD_DATA = px2 >> 15; | ||
117 | px2sr = px2 >> 8; | ||
118 | LCD_DATA = px2sr + (px2sr & 0x1F8); | ||
119 | LCD_DATA = px2 << 1; | ||
120 | } | ||
121 | |||
122 | /*** hardware configuration ***/ | 103 | /*** hardware configuration ***/ |
123 | 104 | ||
124 | int lcd_default_contrast(void) | 105 | int lcd_default_contrast(void) |
@@ -423,45 +404,38 @@ void lcd_blit(const fb_data* data, int x, int by, int width, | |||
423 | /*if(display_on)*/ | 404 | /*if(display_on)*/ |
424 | } | 405 | } |
425 | 406 | ||
426 | /* Performance function to blit a YUV bitmap directly to the LCD */ | 407 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. |
427 | /* Assumes YCrCb 4:2:0. */ | 408 | * y should have two lines of Y back to back. |
428 | /* | 409 | * bu and rv should contain the Cb and Cr data for the two lines of Y. |
429 | See http://en.wikipedia.org/wiki/YCbCr | 410 | * Stores bu, guv and rv in repective buffers for use in second line. |
430 | ITU-R BT.601 (formerly CCIR 601): | 411 | */ |
431 | |Y'| | 0.299000 0.587000 0.114000| |R| | 412 | extern void lcd_write_yuv420_lines(const unsigned char *y, |
432 | |Pb| = |-0.168736 -0.331264 0.500000| |G| or 0.564334 * (B - Y') | 413 | unsigned char *bu, unsigned char *guv, unsigned char *rv, |
433 | |Pr| | 0.500000 -0.418688 0.081312| |B| or 0.713267 * (R - Y') | 414 | int width); |
434 | Scaled, normalized and rounded: | 415 | |
435 | |Y'| | 65 129 25| |R| + 16 : 16->235 | 416 | /* Performance function to blit a YUV bitmap directly to the LCD |
436 | |Cb| = |-38 -74 112| |G| + 128 : 16->240 | 417 | * src_x, src_y, width and height should be even and within the LCD's |
437 | |Cr| |112 -94 -18| |B| + 128 : 16->240 | 418 | * boundaries. |
438 | 419 | */ | |
439 | The inverse: | ||
440 | |R| |1.000000 -0.000001 1.402000| |Y'| | ||
441 | |G| = |1.000000 -0.334136 -0.714136| |Pb| | ||
442 | |B| |1.000000 1.772000 0.000000| |Pr| | ||
443 | Scaled, normalized, rounded and tweaked to yield RGB 666: | ||
444 | |R| |298 0 409| |Y' - 16| / 1024 | ||
445 | |G| = |298 -100 -208| |Cb - 128| / 1024 | ||
446 | |B| |298 516 0| |Cr - 128| / 1024 | ||
447 | */ | ||
448 | void lcd_yuv_blit(unsigned char * const [3], int, int, int, | ||
449 | int, int, int, int) ICODE_ATTR; | ||
450 | void lcd_yuv_blit(unsigned char * const src[3], | 420 | void lcd_yuv_blit(unsigned char * const src[3], |
451 | int src_x, int src_y, int stride, | 421 | int src_x, int src_y, int stride, |
452 | int x, int y, int width, int height) | 422 | int x, int y, int width, int height) |
453 | { | 423 | { |
424 | /* IRAM Y, Cb/bu, guv and Cb/rv buffers. */ | ||
425 | unsigned char y_ibuf[LCD_WIDTH*2]; | ||
426 | unsigned char bu_ibuf[LCD_WIDTH/2]; | ||
427 | unsigned char guv_ibuf[LCD_WIDTH/2]; | ||
428 | unsigned char rv_ibuf[LCD_WIDTH/2]; | ||
454 | const unsigned char *ysrc, *usrc, *vsrc; | 429 | const unsigned char *ysrc, *usrc, *vsrc; |
455 | int uv_stepper, uv_step, y_end; | 430 | const unsigned char *ysrc_max; |
456 | 431 | ||
457 | if (!display_on) | 432 | if (!display_on) |
458 | return; | 433 | return; |
459 | 434 | ||
460 | width = (width + 1) & ~1; | 435 | width = (width + 1) & ~1; |
461 | height = (height + 1) & ~1; | 436 | height = (height + 1) & ~1; |
462 | y_end = y + height; | ||
463 | 437 | ||
464 | /* Set start position and window */ | 438 | /* Set start position and window */ |
465 | lcd_write_reg(R_RAM_ADDR_SET, (x << 8) | | 439 | lcd_write_reg(R_RAM_ADDR_SET, (x << 8) | |
466 | (((y + roll_offset) & 127) + y_offset)); | 440 | (((y + roll_offset) & 127) + y_offset)); |
467 | lcd_write_reg(R_VERT_RAM_ADDR_POS, ((x + width - 1) << 8) | x); | 441 | lcd_write_reg(R_VERT_RAM_ADDR_POS, ((x + width - 1) << 8) | x); |
@@ -471,72 +445,26 @@ void lcd_yuv_blit(unsigned char * const src[3], | |||
471 | ysrc = src[0] + src_y*stride + src_x; | 445 | ysrc = src[0] + src_y*stride + src_x; |
472 | usrc = src[1] + (src_y*stride >> 2) + (src_x >> 1); | 446 | usrc = src[1] + (src_y*stride >> 2) + (src_x >> 1); |
473 | vsrc = src[2] + (usrc - src[1]); | 447 | vsrc = src[2] + (usrc - src[1]); |
474 | 448 | ysrc_max = ysrc + height*stride; | |
475 | stride = stride - width; /* Use end of current line->start of next */ | ||
476 | uv_stepper = (stride >> 1) - (width >> 1); | ||
477 | uv_step = uv_stepper - (stride >> 1); | ||
478 | 449 | ||
479 | do | 450 | do |
480 | { | 451 | { |
481 | const unsigned char *ysrc_end = ysrc + width; | 452 | memcpy(y_ibuf, ysrc, width); |
482 | 453 | memcpy(&y_ibuf[width], &ysrc[stride], width); | |
483 | do | 454 | memcpy(bu_ibuf, usrc, width >> 1); |
484 | { | 455 | memcpy(rv_ibuf, vsrc, width >> 1); |
485 | int lum, cb, cr; | 456 | lcd_write_yuv420_lines(y_ibuf, bu_ibuf, guv_ibuf, rv_ibuf, width); |
486 | int rv, guv, bu; | 457 | ysrc += stride << 1; |
487 | int r, g, b; | 458 | usrc += stride >> 1; |
488 | 459 | vsrc += stride >> 1; | |
489 | lum = 298* *ysrc++ - 4768; /* 298*16 */ | ||
490 | cb = *usrc++ - 128; | ||
491 | cr = *vsrc++ - 128; | ||
492 | bu = 516*cb; | ||
493 | guv = -100*cb - 208*cr; | ||
494 | rv = 409*cr; | ||
495 | |||
496 | r = (lum + rv) >> 10; | ||
497 | g = (lum + guv) >> 10; | ||
498 | b = (lum + bu) >> 10; | ||
499 | |||
500 | if ((unsigned)r > 63) | ||
501 | r = (r < 0) ? 0 : 63; | ||
502 | if ((unsigned)g > 63) | ||
503 | g = (g < 0) ? 0 : 63; | ||
504 | if ((unsigned)b > 63) | ||
505 | b = (b < 0) ? 0 : 63; | ||
506 | |||
507 | LCD_DATA = (r << 3) | (g >> 3); | ||
508 | LCD_DATA = (g << 6) | b; | ||
509 | |||
510 | lum = 298* *ysrc++ - 4768; /* 298*16 */ | ||
511 | r = (lum + rv) >> 10; | ||
512 | g = (lum + guv) >> 10; | ||
513 | b = (lum + bu) >> 10; | ||
514 | |||
515 | if ((unsigned)r > 63) | ||
516 | r = (r < 0) ? 0 : 63; | ||
517 | if ((unsigned)g > 63) | ||
518 | g = (g < 0) ? 0 : 63; | ||
519 | if ((unsigned)b > 63) | ||
520 | b = (b < 0) ? 0 : 63; | ||
521 | |||
522 | LCD_DATA = (r << 3) | (g >> 3); | ||
523 | LCD_DATA = (g << 6) | b; | ||
524 | } | ||
525 | while (ysrc < ysrc_end); | ||
526 | |||
527 | usrc += uv_step; | ||
528 | vsrc += uv_step; | ||
529 | uv_step = uv_stepper - uv_step; | ||
530 | |||
531 | ysrc += stride; | ||
532 | } | 460 | } |
533 | while (++y < y_end); | 461 | while (ysrc < ysrc_max); |
534 | } /* lcd_yuv_blit */ | 462 | } /* lcd_yuv_blit */ |
535 | 463 | ||
464 | |||
536 | /* Update the display. | 465 | /* Update the display. |
537 | This must be called after all other LCD functions that change the | 466 | This must be called after all other LCD functions that change the |
538 | lcd frame buffer. */ | 467 | lcd frame buffer. */ |
539 | void lcd_update(void) ICODE_ATTR; | ||
540 | void lcd_update(void) | 468 | void lcd_update(void) |
541 | { | 469 | { |
542 | if (!display_on) | 470 | if (!display_on) |
@@ -554,7 +482,6 @@ void lcd_update(void) | |||
554 | } /* lcd_update */ | 482 | } /* lcd_update */ |
555 | 483 | ||
556 | /* Update a fraction of the display. */ | 484 | /* Update a fraction of the display. */ |
557 | void lcd_update_rect(int, int, int, int) ICODE_ATTR; | ||
558 | void lcd_update_rect(int x, int y, int width, int height) | 485 | void lcd_update_rect(int x, int y, int width, int height) |
559 | { | 486 | { |
560 | int ymax; | 487 | int ymax; |