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
45static 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
70static 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
95static 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
120static 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
148static 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
184static 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 */
206static 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
254static 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 */
280static 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
344static 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
365static 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
390static 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 */
416static 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 */
429static 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