summaryrefslogtreecommitdiff
path: root/firmware/target/coldfire/iaudio/x5/lcd-as-x5.S
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/coldfire/iaudio/x5/lcd-as-x5.S')
-rw-r--r--firmware/target/coldfire/iaudio/x5/lcd-as-x5.S334
1 files changed, 333 insertions, 1 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
50lcd_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
30lcd_write_data: 362lcd_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 */