1 | /* |
2 | * Intel XScale PXA255/270 LCDC emulation. |
3 | * |
4 | * Copyright (c) 2006 Openedhand Ltd. |
5 | * Written by Andrzej Zaborowski <balrog@zabor.org> |
6 | * |
7 | * This code is licensed under the GPLv2. |
8 | * |
9 | * Framebuffer format conversion routines. |
10 | */ |
11 | |
12 | # define SKIP_PIXEL(to) to += deststep |
13 | #if BITS == 8 |
14 | # define COPY_PIXEL(to, from) do { *to = from; SKIP_PIXEL(to); } while (0) |
15 | #elif BITS == 15 || BITS == 16 |
16 | # define COPY_PIXEL(to, from) \ |
17 | do { \ |
18 | *(uint16_t *) to = from; \ |
19 | SKIP_PIXEL(to); \ |
20 | } while (0) |
21 | #elif BITS == 24 |
22 | # define COPY_PIXEL(to, from) \ |
23 | do { \ |
24 | *(uint16_t *) to = from; \ |
25 | *(to + 2) = (from) >> 16; \ |
26 | SKIP_PIXEL(to); \ |
27 | } while (0) |
28 | #elif BITS == 32 |
29 | # define COPY_PIXEL(to, from) \ |
30 | do { \ |
31 | *(uint32_t *) to = from; \ |
32 | SKIP_PIXEL(to); \ |
33 | } while (0) |
34 | #else |
35 | # error unknown bit depth |
36 | #endif |
37 | |
38 | #ifdef HOST_WORDS_BIGENDIAN |
39 | # define SWAP_WORDS 1 |
40 | #endif |
41 | |
42 | #define FN_2(x) FN(x + 1) FN(x) |
43 | #define FN_4(x) FN_2(x + 2) FN_2(x) |
44 | |
45 | static void glue(pxa2xx_draw_line2_, BITS)(void *opaque, |
46 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
47 | { |
48 | uint32_t *palette = opaque; |
49 | uint32_t data; |
50 | while (width > 0) { |
51 | data = *(uint32_t *) src; |
52 | #define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]); |
53 | #ifdef SWAP_WORDS |
54 | FN_4(12) |
55 | FN_4(8) |
56 | FN_4(4) |
57 | FN_4(0) |
58 | #else |
59 | FN_4(0) |
60 | FN_4(4) |
61 | FN_4(8) |
62 | FN_4(12) |
63 | #endif |
64 | #undef FN |
65 | width -= 16; |
66 | src += 4; |
67 | } |
68 | } |
69 | |
70 | static void glue(pxa2xx_draw_line4_, BITS)(void *opaque, |
71 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
72 | { |
73 | uint32_t *palette = opaque; |
74 | uint32_t data; |
75 | while (width > 0) { |
76 | data = *(uint32_t *) src; |
77 | #define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]); |
78 | #ifdef SWAP_WORDS |
79 | FN_2(6) |
80 | FN_2(4) |
81 | FN_2(2) |
82 | FN_2(0) |
83 | #else |
84 | FN_2(0) |
85 | FN_2(2) |
86 | FN_2(4) |
87 | FN_2(6) |
88 | #endif |
89 | #undef FN |
90 | width -= 8; |
91 | src += 4; |
92 | } |
93 | } |
94 | |
95 | static void glue(pxa2xx_draw_line8_, BITS)(void *opaque, |
96 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
97 | { |
98 | uint32_t *palette = opaque; |
99 | uint32_t data; |
100 | while (width > 0) { |
101 | data = *(uint32_t *) src; |
102 | #define FN(x) COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]); |
103 | #ifdef SWAP_WORDS |
104 | FN(24) |
105 | FN(16) |
106 | FN(8) |
107 | FN(0) |
108 | #else |
109 | FN(0) |
110 | FN(8) |
111 | FN(16) |
112 | FN(24) |
113 | #endif |
114 | #undef FN |
115 | width -= 4; |
116 | src += 4; |
117 | } |
118 | } |
119 | |
120 | static void glue(pxa2xx_draw_line16_, BITS)(void *opaque, |
121 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
122 | { |
123 | uint32_t data; |
124 | unsigned int r, g, b; |
125 | while (width > 0) { |
126 | data = *(uint32_t *) src; |
127 | #ifdef SWAP_WORDS |
128 | data = bswap32(data); |
129 | #endif |
130 | b = (data & 0x1f) << 3; |
131 | data >>= 5; |
132 | g = (data & 0x3f) << 2; |
133 | data >>= 6; |
134 | r = (data & 0x1f) << 3; |
135 | data >>= 5; |
136 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
137 | b = (data & 0x1f) << 3; |
138 | data >>= 5; |
139 | g = (data & 0x3f) << 2; |
140 | data >>= 6; |
141 | r = (data & 0x1f) << 3; |
142 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
143 | width -= 2; |
144 | src += 4; |
145 | } |
146 | } |
147 | |
148 | static void glue(pxa2xx_draw_line16t_, BITS)(void *opaque, |
149 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
150 | { |
151 | uint32_t data; |
152 | unsigned int r, g, b; |
153 | while (width > 0) { |
154 | data = *(uint32_t *) src; |
155 | #ifdef SWAP_WORDS |
156 | data = bswap32(data); |
157 | #endif |
158 | b = (data & 0x1f) << 3; |
159 | data >>= 5; |
160 | g = (data & 0x1f) << 3; |
161 | data >>= 5; |
162 | r = (data & 0x1f) << 3; |
163 | data >>= 5; |
164 | if (data & 1) |
165 | SKIP_PIXEL(dest); |
166 | else |
167 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
168 | data >>= 1; |
169 | b = (data & 0x1f) << 3; |
170 | data >>= 5; |
171 | g = (data & 0x1f) << 3; |
172 | data >>= 5; |
173 | r = (data & 0x1f) << 3; |
174 | data >>= 5; |
175 | if (data & 1) |
176 | SKIP_PIXEL(dest); |
177 | else |
178 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
179 | width -= 2; |
180 | src += 4; |
181 | } |
182 | } |
183 | |
184 | static void glue(pxa2xx_draw_line18_, BITS)(void *opaque, |
185 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
186 | { |
187 | uint32_t data; |
188 | unsigned int r, g, b; |
189 | while (width > 0) { |
190 | data = *(uint32_t *) src; |
191 | #ifdef SWAP_WORDS |
192 | data = bswap32(data); |
193 | #endif |
194 | b = (data & 0x3f) << 2; |
195 | data >>= 6; |
196 | g = (data & 0x3f) << 2; |
197 | data >>= 6; |
198 | r = (data & 0x3f) << 2; |
199 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
200 | width -= 1; |
201 | src += 4; |
202 | } |
203 | } |
204 | |
205 | /* The wicked packed format */ |
206 | static void glue(pxa2xx_draw_line18p_, BITS)(void *opaque, |
207 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
208 | { |
209 | uint32_t data[3]; |
210 | unsigned int r, g, b; |
211 | while (width > 0) { |
212 | data[0] = *(uint32_t *) src; |
213 | src += 4; |
214 | data[1] = *(uint32_t *) src; |
215 | src += 4; |
216 | data[2] = *(uint32_t *) src; |
217 | src += 4; |
218 | #ifdef SWAP_WORDS |
219 | data[0] = bswap32(data[0]); |
220 | data[1] = bswap32(data[1]); |
221 | data[2] = bswap32(data[2]); |
222 | #endif |
223 | b = (data[0] & 0x3f) << 2; |
224 | data[0] >>= 6; |
225 | g = (data[0] & 0x3f) << 2; |
226 | data[0] >>= 6; |
227 | r = (data[0] & 0x3f) << 2; |
228 | data[0] >>= 12; |
229 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
230 | b = (data[0] & 0x3f) << 2; |
231 | data[0] >>= 6; |
232 | g = ((data[1] & 0xf) << 4) | (data[0] << 2); |
233 | data[1] >>= 4; |
234 | r = (data[1] & 0x3f) << 2; |
235 | data[1] >>= 12; |
236 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
237 | b = (data[1] & 0x3f) << 2; |
238 | data[1] >>= 6; |
239 | g = (data[1] & 0x3f) << 2; |
240 | data[1] >>= 6; |
241 | r = ((data[2] & 0x3) << 6) | (data[1] << 2); |
242 | data[2] >>= 8; |
243 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
244 | b = (data[2] & 0x3f) << 2; |
245 | data[2] >>= 6; |
246 | g = (data[2] & 0x3f) << 2; |
247 | data[2] >>= 6; |
248 | r = data[2] << 2; |
249 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
250 | width -= 4; |
251 | } |
252 | } |
253 | |
254 | static void glue(pxa2xx_draw_line19_, BITS)(void *opaque, |
255 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
256 | { |
257 | uint32_t data; |
258 | unsigned int r, g, b; |
259 | while (width > 0) { |
260 | data = *(uint32_t *) src; |
261 | #ifdef SWAP_WORDS |
262 | data = bswap32(data); |
263 | #endif |
264 | b = (data & 0x3f) << 2; |
265 | data >>= 6; |
266 | g = (data & 0x3f) << 2; |
267 | data >>= 6; |
268 | r = (data & 0x3f) << 2; |
269 | data >>= 6; |
270 | if (data & 1) |
271 | SKIP_PIXEL(dest); |
272 | else |
273 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
274 | width -= 1; |
275 | src += 4; |
276 | } |
277 | } |
278 | |
279 | /* The wicked packed format */ |
280 | static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque, |
281 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
282 | { |
283 | uint32_t data[3]; |
284 | unsigned int r, g, b; |
285 | while (width > 0) { |
286 | data[0] = *(uint32_t *) src; |
287 | src += 4; |
288 | data[1] = *(uint32_t *) src; |
289 | src += 4; |
290 | data[2] = *(uint32_t *) src; |
291 | src += 4; |
292 | # ifdef SWAP_WORDS |
293 | data[0] = bswap32(data[0]); |
294 | data[1] = bswap32(data[1]); |
295 | data[2] = bswap32(data[2]); |
296 | # endif |
297 | b = (data[0] & 0x3f) << 2; |
298 | data[0] >>= 6; |
299 | g = (data[0] & 0x3f) << 2; |
300 | data[0] >>= 6; |
301 | r = (data[0] & 0x3f) << 2; |
302 | data[0] >>= 6; |
303 | if (data[0] & 1) |
304 | SKIP_PIXEL(dest); |
305 | else |
306 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
307 | data[0] >>= 6; |
308 | b = (data[0] & 0x3f) << 2; |
309 | data[0] >>= 6; |
310 | g = ((data[1] & 0xf) << 4) | (data[0] << 2); |
311 | data[1] >>= 4; |
312 | r = (data[1] & 0x3f) << 2; |
313 | data[1] >>= 6; |
314 | if (data[1] & 1) |
315 | SKIP_PIXEL(dest); |
316 | else |
317 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
318 | data[1] >>= 6; |
319 | b = (data[1] & 0x3f) << 2; |
320 | data[1] >>= 6; |
321 | g = (data[1] & 0x3f) << 2; |
322 | data[1] >>= 6; |
323 | r = ((data[2] & 0x3) << 6) | (data[1] << 2); |
324 | data[2] >>= 2; |
325 | if (data[2] & 1) |
326 | SKIP_PIXEL(dest); |
327 | else |
328 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
329 | data[2] >>= 6; |
330 | b = (data[2] & 0x3f) << 2; |
331 | data[2] >>= 6; |
332 | g = (data[2] & 0x3f) << 2; |
333 | data[2] >>= 6; |
334 | r = data[2] << 2; |
335 | data[2] >>= 6; |
336 | if (data[2] & 1) |
337 | SKIP_PIXEL(dest); |
338 | else |
339 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
340 | width -= 4; |
341 | } |
342 | } |
343 | |
344 | static void glue(pxa2xx_draw_line24_, BITS)(void *opaque, |
345 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
346 | { |
347 | uint32_t data; |
348 | unsigned int r, g, b; |
349 | while (width > 0) { |
350 | data = *(uint32_t *) src; |
351 | #ifdef SWAP_WORDS |
352 | data = bswap32(data); |
353 | #endif |
354 | b = data & 0xff; |
355 | data >>= 8; |
356 | g = data & 0xff; |
357 | data >>= 8; |
358 | r = data & 0xff; |
359 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
360 | width -= 1; |
361 | src += 4; |
362 | } |
363 | } |
364 | |
365 | static void glue(pxa2xx_draw_line24t_, BITS)(void *opaque, |
366 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
367 | { |
368 | uint32_t data; |
369 | unsigned int r, g, b; |
370 | while (width > 0) { |
371 | data = *(uint32_t *) src; |
372 | #ifdef SWAP_WORDS |
373 | data = bswap32(data); |
374 | #endif |
375 | b = (data & 0x7f) << 1; |
376 | data >>= 7; |
377 | g = data & 0xff; |
378 | data >>= 8; |
379 | r = data & 0xff; |
380 | data >>= 8; |
381 | if (data & 1) |
382 | SKIP_PIXEL(dest); |
383 | else |
384 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
385 | width -= 1; |
386 | src += 4; |
387 | } |
388 | } |
389 | |
390 | static void glue(pxa2xx_draw_line25_, BITS)(void *opaque, |
391 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
392 | { |
393 | uint32_t data; |
394 | unsigned int r, g, b; |
395 | while (width > 0) { |
396 | data = *(uint32_t *) src; |
397 | #ifdef SWAP_WORDS |
398 | data = bswap32(data); |
399 | #endif |
400 | b = data & 0xff; |
401 | data >>= 8; |
402 | g = data & 0xff; |
403 | data >>= 8; |
404 | r = data & 0xff; |
405 | data >>= 8; |
406 | if (data & 1) |
407 | SKIP_PIXEL(dest); |
408 | else |
409 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
410 | width -= 1; |
411 | src += 4; |
412 | } |
413 | } |
414 | |
415 | /* Overlay planes disabled, no transparency */ |
416 | static drawfn glue(pxa2xx_draw_fn_, BITS)[16] = |
417 | { |
418 | [0 ... 0xf] = NULL, |
419 | [pxa_lcdc_2bpp] = glue(pxa2xx_draw_line2_, BITS), |
420 | [pxa_lcdc_4bpp] = glue(pxa2xx_draw_line4_, BITS), |
421 | [pxa_lcdc_8bpp] = glue(pxa2xx_draw_line8_, BITS), |
422 | [pxa_lcdc_16bpp] = glue(pxa2xx_draw_line16_, BITS), |
423 | [pxa_lcdc_18bpp] = glue(pxa2xx_draw_line18_, BITS), |
424 | [pxa_lcdc_18pbpp] = glue(pxa2xx_draw_line18p_, BITS), |
425 | [pxa_lcdc_24bpp] = glue(pxa2xx_draw_line24_, BITS), |
426 | }; |
427 | |
428 | /* Overlay planes enabled, transparency used */ |
429 | static drawfn glue(glue(pxa2xx_draw_fn_, BITS), t)[16] = |
430 | { |
431 | [0 ... 0xf] = NULL, |
432 | [pxa_lcdc_4bpp] = glue(pxa2xx_draw_line4_, BITS), |
433 | [pxa_lcdc_8bpp] = glue(pxa2xx_draw_line8_, BITS), |
434 | [pxa_lcdc_16bpp] = glue(pxa2xx_draw_line16t_, BITS), |
435 | [pxa_lcdc_19bpp] = glue(pxa2xx_draw_line19_, BITS), |
436 | [pxa_lcdc_19pbpp] = glue(pxa2xx_draw_line19p_, BITS), |
437 | [pxa_lcdc_24bpp] = glue(pxa2xx_draw_line24t_, BITS), |
438 | [pxa_lcdc_25bpp] = glue(pxa2xx_draw_line25_, BITS), |
439 | }; |
440 | |
441 | #undef BITS |
442 | #undef COPY_PIXEL |
443 | #undef SKIP_PIXEL |
444 | |
445 | #ifdef SWAP_WORDS |
446 | # undef SWAP_WORDS |
447 | #endif |
448 | |