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.S242
1 files changed, 242 insertions, 0 deletions
diff --git a/firmware/target/coldfire/iaudio/x5/lcd-as-x5.S b/firmware/target/coldfire/iaudio/x5/lcd-as-x5.S
index b319d745ca..e6621e1dea 100644
--- a/firmware/target/coldfire/iaudio/x5/lcd-as-x5.S
+++ b/firmware/target/coldfire/iaudio/x5/lcd-as-x5.S
@@ -25,6 +25,248 @@
25 25
26 .section .icode,"ax",@progbits 26 .section .icode,"ax",@progbits
27 27
28/* begin lcd_write_yuv420_lines
29 *
30 * See http://en.wikipedia.org/wiki/YCbCr
31 * ITU-R BT.601 (formerly CCIR 601):
32 * |Y'| | 0.299000 0.587000 0.114000| |R|
33 * |Pb| = |-0.168736 -0.331264 0.500000| |G| or 0.564334*(B - Y')
34 * |Pr| | 0.500000 -0.418688 0.081312| |B| or 0.713267*(R - Y')
35 * Scaled, normalized and rounded:
36 * |Y'| | 65 129 25| |R| + 16 : 16->235
37 * |Cb| = |-38 -74 112| |G| + 128 : 16->240
38 * |Cr| |112 -94 -18| |B| + 128 : 16->240
39 *
40 * The inverse:
41 * |R| |1.000000 -0.000001 1.402000| |Y'|
42 * |G| = |1.000000 -0.334136 -0.714136| |Pb|
43 * |B| |1.000000 1.772000 0.000000| |Pr|
44 * Scaled, normalized, rounded and tweaked to yield RGB 666:
45 * |R| |19611723 0 26881894| |Y' - 16| >> 26
46 * |G| = |19611723 -6406711 -13692816| |Cb - 128| >> 26
47 * |B| |19611723 33976259 0| |Cr - 128| >> 26
48 *
49 * Needs EMAC set to saturated, signed integer mode.
50 *
51 * register usage:
52 * %a0 - LCD data port
53 * %a1 - Y pointer
54 * %a2 - C pointer
55 * %a3 - C width
56 * %a4 - Y end address
57 * %a5 - Y factor
58 * %a6 - BU factor
59 * %d0 - scratch
60 * %d1 - B, previous Y \ alternating
61 * %d2 - U / B, previous Y /
62 * %d3 - V / G
63 * %d4 - R / output pixel
64 * %d5 - GU factor
65 * %d6 - GV factor
66 * %d7 - RGB signed -> unsigned conversion mask
67 */
68 .align 2
69 .global lcd_write_yuv420_lines
70 .type lcd_write_yuv420_lines, @function
71
72lcd_write_yuv420_lines:
73 lea.l (-44, %sp), %sp /* free up some registers */
74 movem.l %d2-%d7/%a2-%a6, (%sp)
75
76 lea.l 0xf0008002, %a0 /* LCD data port */
77 movem.l (44+4, %sp), %a1-%a3 /* Y data, C data, C width */
78 lea.l (%a1, %a3*2), %a4 /* Y end address */
79
80 move.l #19611723, %a5 /* y factor */
81 move.l #33976259, %a6 /* bu factor */
82 move.l #-6406711, %d5 /* gu factor */
83 move.l #-13692816, %d6 /* gv factor */
84 move.l #0x01040820, %d7 /* bitmask for signed->unsigned conversion
85 * of R, G and B within RGGB6666 at once */
86
87 /* chroma for first 2x2 block */
88 clr.l %d3 /* load v component */
89 move.b (%a2, %a3), %d3
90 clr.l %d2 /* load u component */
91 move.b (%a2)+, %d2
92 moveq.l #-128, %d0
93 add.l %d0, %d2
94 add.l %d0, %d3
95
96 mac.l %a6, %d2, %acc0 /* bu */
97 mac.l %d5, %d2, %acc1 /* gu */
98 mac.l %d6, %d3, %acc1 /* gv */
99 move.l #26881894, %d0 /* rv factor */
100 mac.l %d0, %d3, %acc2 /* rv */
101
102 /* luma for very first pixel (top left) */
103 clr.l %d1
104 move.b (%a1, %a3*2), %d1
105 moveq.l #-126, %d0
106 add.l %d1, %d0 /* y' (-0.5 ... +0.5) */
107 mac.l %a5, %d0, %acc0
108 mac.l %a5, %d0, %acc1
109 mac.l %a5, %d0, %acc2
110
111 bra.b .yuv_line_entry
112
113.yuv_line_loop:
114 /* chroma for 2x2 pixel block */
115 clr.l %d3 /* load v component */
116 move.b (%a2, %a3), %d3
117 clr.l %d2 /* load u component */
118 move.b (%a2)+, %d2
119 moveq.l #-128, %d0
120 add.l %d0, %d2
121 add.l %d0, %d3
122
123 mac.l %a6, %d2, %acc0 /* bu */
124 mac.l %d5, %d2, %acc1 /* gu */
125 mac.l %d6, %d3, %acc1 /* gv */
126 move.l #26881894, %d0 /* rv factor */
127 mac.l %d0, %d3, %acc2 /* rv */
128
129 /* luma for first pixel (top left) */
130 clr.l %d1
131 move.b (%a1, %a3*2), %d1
132 moveq.l #-126, %d0
133 add.l %d1, %d0 /* y' (-0.5 ... +0.5) */
134 mac.l %a5, %d0, %acc0
135 mac.l %a5, %d0, %acc1
136 mac.l %a5, %d0, %acc2
137
138 move.w %d4, (%a0)
139 /* 2nd LCD write is delayed one pixel to use it for filling the EMAC latency */
140
141 /* convert to RGB666, pack and output */
142.yuv_line_entry:
143 moveq.l #26, %d0
144 move.l %acc0, %d4
145 move.l %acc1, %d3
146 move.l %acc2, %d2
147 lsr.l %d0, %d4
148 lsr.l %d0, %d3
149 lsr.l %d0, %d2
150
151 lsl.l #6, %d2
152 or.l %d3, %d2 /* |00000000|00000000|0000Rrrr|rrGggggg| */
153 lsl.l #7, %d2
154 or.l %d2, %d3 /* |00000000|00000Rrr|rrrGgggg|g0Gggggg| */
155 lsl.l #6, %d3
156 or.l %d3, %d4 /* |0000000R|rrrrrGgg|ggg0Gggg|ggBbbbbb| */
157 eor.l %d7, %d4 /* |0000000r|rrrrrggg|ggg0gggg|ggbbbbbb| */
158 swap %d4
159 move.w %d4, (%a0)
160 swap %d4
161
162 /* luma for second pixel (bottom left) as delta from the first */
163 clr.l %d2
164 move.b (%a1)+, %d2
165 move.l %d2, %d0
166 sub.l %d1, %d0
167 mac.l %a5, %d0, %acc0
168 mac.l %a5, %d0, %acc1
169 mac.l %a5, %d0, %acc2
170
171 move.w %d4, (%a0)
172 /* 2nd LCD write is delayed one pixel to use it for filling the EMAC latency */
173
174 /* convert to RGB666, pack and output */
175 moveq.l #26, %d0
176 move.l %acc0, %d4
177 move.l %acc1, %d3
178 move.l %acc2, %d1
179 lsr.l %d0, %d4
180 lsr.l %d0, %d3
181 lsr.l %d0, %d1
182
183 lsl.l #6, %d1
184 or.l %d3, %d1 /* |00000000|00000000|0000Rrrr|rrGggggg| */
185 lsl.l #7, %d1
186 or.l %d1, %d3 /* |00000000|00000Rrr|rrrGgggg|g0Gggggg| */
187 lsl.l #6, %d3
188 or.l %d3, %d4 /* |0000000R|rrrrrGgg|ggg0Gggg|ggBbbbbb| */
189 eor.l %d7, %d4 /* |0000000r|rrrrrggg|ggg0gggg|ggbbbbbb| */
190 swap %d4
191 move.w %d4, (%a0)
192 swap %d4
193
194 /* luma for third pixel (top right) as delta from the second */
195 clr.l %d1
196 move.b (%a1, %a3*2), %d1
197 move.l %d1, %d0
198 sub.l %d2, %d0
199 mac.l %a5, %d0, %acc0
200 mac.l %a5, %d0, %acc1
201 mac.l %a5, %d0, %acc2
202
203 move.w %d4, (%a0)
204 /* 2nd LCD write is delayed one pixel to use it for filling the EMAC latency */
205
206 /* convert to RGB666, pack and output */
207 moveq.l #26, %d0
208 move.l %acc0, %d4
209 move.l %acc1, %d3
210 move.l %acc2, %d2
211 lsr.l %d0, %d4
212 lsr.l %d0, %d3
213 lsr.l %d0, %d2
214
215 lsl.l #6, %d2
216 or.l %d3, %d2 /* |00000000|00000000|0000Rrrr|rrGggggg| */
217 lsl.l #7, %d2
218 or.l %d2, %d3 /* |00000000|00000Rrr|rrrGgggg|g0Gggggg| */
219 lsl.l #6, %d3
220 or.l %d3, %d4 /* |0000000R|rrrrrGgg|ggg0Gggg|ggBbbbbb| */
221 eor.l %d7, %d4 /* |0000000r|rrrrrggg|ggg0gggg|ggbbbbbb| */
222 swap %d4
223 move.w %d4, (%a0)
224 swap %d4
225
226 /* luma for fourth pixel (bottom right) as delta from the thrid */
227 clr.l %d2
228 move.b (%a1)+, %d2
229 move.l %d2, %d0
230 sub.l %d1, %d0
231 mac.l %a5, %d0, %acc0
232 mac.l %a5, %d0, %acc1
233 mac.l %a5, %d0, %acc2
234
235 move.w %d4, (%a0)
236 /* 2nd LCD write is delayed one pixel to use it for filling the EMAC latency */
237
238 /* convert to RGB666, pack and output */
239 moveq.l #26, %d0
240 movclr.l %acc0, %d4
241 movclr.l %acc1, %d3
242 movclr.l %acc2, %d1
243 lsr.l %d0, %d4
244 lsr.l %d0, %d3
245 lsr.l %d0, %d1
246
247 lsl.l #6, %d1
248 or.l %d3, %d1 /* |00000000|00000000|0000Rrrr|rrGggggg| */
249 lsl.l #7, %d1
250 or.l %d1, %d3 /* |00000000|00000Rrr|rrrGgggg|g0Gggggg| */
251 lsl.l #6, %d3
252 or.l %d3, %d4 /* |0000000R|rrrrrGgg|ggg0Gggg|ggBbbbbb| */
253 eor.l %d7, %d4 /* |0000000r|rrrrrggg|ggg0gggg|ggbbbbbb| */
254 swap %d4
255 move.w %d4, (%a0)
256 swap %d4
257
258 cmp.l %a1, %a4 /* run %a1 up to end of line */
259 bhi.w .yuv_line_loop
260
261 move.w %d4, (%a0) /* write (very) last 2nd word */
262
263 movem.l (%sp), %d2-%d7/%a2-%a6
264 lea.l (44, %sp), %sp /* restore registers */
265 rts
266.yuv_end:
267 .size lcd_write_yuv420_lines, .yuv_end - lcd_write_yuv420_lines
268
269
28/* begin lcd_write_data */ 270/* begin lcd_write_data */
29 .align 2 271 .align 2
30 .global lcd_write_data 272 .global lcd_write_data