1/*
2 * Arm PrimeCell PL110 Color LCD Controller
3 *
4 * Copyright (c) 2005 CodeSourcery, LLC.
5 * Written by Paul Brook
6 *
7 * This code is licensed under the GNU LGPL
8 *
9 * Framebuffer format conversion routines.
10 */
11
12#ifndef ORDER
13
14#if BITS == 8
15#define COPY_PIXEL(to, from) *(to++) = from
16#elif BITS == 15 || BITS == 16
17#define COPY_PIXEL(to, from) do { *(uint16_t *)to = from; to += 2; } while (0)
18#elif BITS == 24
19#define COPY_PIXEL(to, from) \
20 do { \
21 *(to++) = from; \
22 *(to++) = (from) >> 8; \
23 *(to++) = (from) >> 16; \
24 } while (0)
25#elif BITS == 32
26#define COPY_PIXEL(to, from) do { *(uint32_t *)to = from; to += 4; } while (0)
27#else
28#error unknown bit depth
29#endif
30
31#undef RGB
32#define BORDER bgr
33#define ORDER 0
34#include "pl110_template.h"
35#define ORDER 1
36#include "pl110_template.h"
37#define ORDER 2
38#include "pl110_template.h"
39#undef BORDER
40#define RGB
41#define BORDER rgb
42#define ORDER 0
43#include "pl110_template.h"
44#define ORDER 1
45#include "pl110_template.h"
46#define ORDER 2
47#include "pl110_template.h"
48#undef BORDER
49
50static drawfn glue(pl110_draw_fn_,BITS)[48] =
51{
52 glue(pl110_draw_line1_lblp_bgr,BITS),
53 glue(pl110_draw_line2_lblp_bgr,BITS),
54 glue(pl110_draw_line4_lblp_bgr,BITS),
55 glue(pl110_draw_line8_lblp_bgr,BITS),
56 glue(pl110_draw_line16_555_lblp_bgr,BITS),
57 glue(pl110_draw_line32_lblp_bgr,BITS),
58 glue(pl110_draw_line16_lblp_bgr,BITS),
59 glue(pl110_draw_line12_lblp_bgr,BITS),
60
61 glue(pl110_draw_line1_bbbp_bgr,BITS),
62 glue(pl110_draw_line2_bbbp_bgr,BITS),
63 glue(pl110_draw_line4_bbbp_bgr,BITS),
64 glue(pl110_draw_line8_bbbp_bgr,BITS),
65 glue(pl110_draw_line16_555_bbbp_bgr,BITS),
66 glue(pl110_draw_line32_bbbp_bgr,BITS),
67 glue(pl110_draw_line16_bbbp_bgr,BITS),
68 glue(pl110_draw_line12_bbbp_bgr,BITS),
69
70 glue(pl110_draw_line1_lbbp_bgr,BITS),
71 glue(pl110_draw_line2_lbbp_bgr,BITS),
72 glue(pl110_draw_line4_lbbp_bgr,BITS),
73 glue(pl110_draw_line8_lbbp_bgr,BITS),
74 glue(pl110_draw_line16_555_lbbp_bgr,BITS),
75 glue(pl110_draw_line32_lbbp_bgr,BITS),
76 glue(pl110_draw_line16_lbbp_bgr,BITS),
77 glue(pl110_draw_line12_lbbp_bgr,BITS),
78
79 glue(pl110_draw_line1_lblp_rgb,BITS),
80 glue(pl110_draw_line2_lblp_rgb,BITS),
81 glue(pl110_draw_line4_lblp_rgb,BITS),
82 glue(pl110_draw_line8_lblp_rgb,BITS),
83 glue(pl110_draw_line16_555_lblp_rgb,BITS),
84 glue(pl110_draw_line32_lblp_rgb,BITS),
85 glue(pl110_draw_line16_lblp_rgb,BITS),
86 glue(pl110_draw_line12_lblp_rgb,BITS),
87
88 glue(pl110_draw_line1_bbbp_rgb,BITS),
89 glue(pl110_draw_line2_bbbp_rgb,BITS),
90 glue(pl110_draw_line4_bbbp_rgb,BITS),
91 glue(pl110_draw_line8_bbbp_rgb,BITS),
92 glue(pl110_draw_line16_555_bbbp_rgb,BITS),
93 glue(pl110_draw_line32_bbbp_rgb,BITS),
94 glue(pl110_draw_line16_bbbp_rgb,BITS),
95 glue(pl110_draw_line12_bbbp_rgb,BITS),
96
97 glue(pl110_draw_line1_lbbp_rgb,BITS),
98 glue(pl110_draw_line2_lbbp_rgb,BITS),
99 glue(pl110_draw_line4_lbbp_rgb,BITS),
100 glue(pl110_draw_line8_lbbp_rgb,BITS),
101 glue(pl110_draw_line16_555_lbbp_rgb,BITS),
102 glue(pl110_draw_line32_lbbp_rgb,BITS),
103 glue(pl110_draw_line16_lbbp_rgb,BITS),
104 glue(pl110_draw_line12_lbbp_rgb,BITS),
105};
106
107#undef BITS
108#undef COPY_PIXEL
109
110#else
111
112#if ORDER == 0
113#define NAME glue(glue(lblp_, BORDER), BITS)
114#ifdef HOST_WORDS_BIGENDIAN
115#define SWAP_WORDS 1
116#endif
117#elif ORDER == 1
118#define NAME glue(glue(bbbp_, BORDER), BITS)
119#ifndef HOST_WORDS_BIGENDIAN
120#define SWAP_WORDS 1
121#endif
122#else
123#define SWAP_PIXELS 1
124#define NAME glue(glue(lbbp_, BORDER), BITS)
125#ifdef HOST_WORDS_BIGENDIAN
126#define SWAP_WORDS 1
127#endif
128#endif
129
130#define FN_2(x, y) FN(x, y) FN(x+1, y)
131#define FN_4(x, y) FN_2(x, y) FN_2(x+2, y)
132#define FN_8(y) FN_4(0, y) FN_4(4, y)
133
134static void glue(pl110_draw_line1_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
135{
136 uint32_t *palette = opaque;
137 uint32_t data;
138 while (width > 0) {
139 data = *(uint32_t *)src;
140#ifdef SWAP_PIXELS
141#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 7 - (x))) & 1]);
142#else
143#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x) + y)) & 1]);
144#endif
145#ifdef SWAP_WORDS
146 FN_8(24)
147 FN_8(16)
148 FN_8(8)
149 FN_8(0)
150#else
151 FN_8(0)
152 FN_8(8)
153 FN_8(16)
154 FN_8(24)
155#endif
156#undef FN
157 width -= 32;
158 src += 4;
159 }
160}
161
162static void glue(pl110_draw_line2_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
163{
164 uint32_t *palette = opaque;
165 uint32_t data;
166 while (width > 0) {
167 data = *(uint32_t *)src;
168#ifdef SWAP_PIXELS
169#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 6 - (x)*2)) & 3]);
170#else
171#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x)*2 + y)) & 3]);
172#endif
173#ifdef SWAP_WORDS
174 FN_4(0, 24)
175 FN_4(0, 16)
176 FN_4(0, 8)
177 FN_4(0, 0)
178#else
179 FN_4(0, 0)
180 FN_4(0, 8)
181 FN_4(0, 16)
182 FN_4(0, 24)
183#endif
184#undef FN
185 width -= 16;
186 src += 4;
187 }
188}
189
190static void glue(pl110_draw_line4_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
191{
192 uint32_t *palette = opaque;
193 uint32_t data;
194 while (width > 0) {
195 data = *(uint32_t *)src;
196#ifdef SWAP_PIXELS
197#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 4 - (x)*4)) & 0xf]);
198#else
199#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x)*4 + y)) & 0xf]);
200#endif
201#ifdef SWAP_WORDS
202 FN_2(0, 24)
203 FN_2(0, 16)
204 FN_2(0, 8)
205 FN_2(0, 0)
206#else
207 FN_2(0, 0)
208 FN_2(0, 8)
209 FN_2(0, 16)
210 FN_2(0, 24)
211#endif
212#undef FN
213 width -= 8;
214 src += 4;
215 }
216}
217
218static void glue(pl110_draw_line8_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
219{
220 uint32_t *palette = opaque;
221 uint32_t data;
222 while (width > 0) {
223 data = *(uint32_t *)src;
224#define FN(x) COPY_PIXEL(d, palette[(data >> (x)) & 0xff]);
225#ifdef SWAP_WORDS
226 FN(24)
227 FN(16)
228 FN(8)
229 FN(0)
230#else
231 FN(0)
232 FN(8)
233 FN(16)
234 FN(24)
235#endif
236#undef FN
237 width -= 4;
238 src += 4;
239 }
240}
241
242static void glue(pl110_draw_line16_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
243{
244 uint32_t data;
245 unsigned int r, g, b;
246 while (width > 0) {
247 data = *(uint32_t *)src;
248#ifdef SWAP_WORDS
249 data = bswap32(data);
250#endif
251#ifdef RGB
252#define LSB r
253#define MSB b
254#else
255#define LSB b
256#define MSB r
257#endif
258#if 0
259 LSB = data & 0x1f;
260 data >>= 5;
261 g = data & 0x3f;
262 data >>= 6;
263 MSB = data & 0x1f;
264 data >>= 5;
265#else
266 LSB = (data & 0x1f) << 3;
267 data >>= 5;
268 g = (data & 0x3f) << 2;
269 data >>= 6;
270 MSB = (data & 0x1f) << 3;
271 data >>= 5;
272#endif
273 COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
274 LSB = (data & 0x1f) << 3;
275 data >>= 5;
276 g = (data & 0x3f) << 2;
277 data >>= 6;
278 MSB = (data & 0x1f) << 3;
279 data >>= 5;
280 COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
281#undef MSB
282#undef LSB
283 width -= 2;
284 src += 4;
285 }
286}
287
288static void glue(pl110_draw_line32_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
289{
290 uint32_t data;
291 unsigned int r, g, b;
292 while (width > 0) {
293 data = *(uint32_t *)src;
294#ifdef RGB
295#define LSB r
296#define MSB b
297#else
298#define LSB b
299#define MSB r
300#endif
301#ifndef SWAP_WORDS
302 LSB = data & 0xff;
303 g = (data >> 8) & 0xff;
304 MSB = (data >> 16) & 0xff;
305#else
306 LSB = (data >> 24) & 0xff;
307 g = (data >> 16) & 0xff;
308 MSB = (data >> 8) & 0xff;
309#endif
310 COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
311#undef MSB
312#undef LSB
313 width--;
314 src += 4;
315 }
316}
317
318static void glue(pl110_draw_line16_555_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
319{
320 /* RGB 555 plus an intensity bit (which we ignore) */
321 uint32_t data;
322 unsigned int r, g, b;
323 while (width > 0) {
324 data = *(uint32_t *)src;
325#ifdef SWAP_WORDS
326 data = bswap32(data);
327#endif
328#ifdef RGB
329#define LSB r
330#define MSB b
331#else
332#define LSB b
333#define MSB r
334#endif
335 LSB = (data & 0x1f) << 3;
336 data >>= 5;
337 g = (data & 0x1f) << 3;
338 data >>= 5;
339 MSB = (data & 0x1f) << 3;
340 data >>= 5;
341 COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
342 LSB = (data & 0x1f) << 3;
343 data >>= 5;
344 g = (data & 0x1f) << 3;
345 data >>= 5;
346 MSB = (data & 0x1f) << 3;
347 data >>= 6;
348 COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
349#undef MSB
350#undef LSB
351 width -= 2;
352 src += 4;
353 }
354}
355
356static void glue(pl110_draw_line12_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
357{
358 /* RGB 444 with 4 bits of zeroes at the top of each halfword */
359 uint32_t data;
360 unsigned int r, g, b;
361 while (width > 0) {
362 data = *(uint32_t *)src;
363#ifdef SWAP_WORDS
364 data = bswap32(data);
365#endif
366#ifdef RGB
367#define LSB r
368#define MSB b
369#else
370#define LSB b
371#define MSB r
372#endif
373 LSB = (data & 0xf) << 4;
374 data >>= 4;
375 g = (data & 0xf) << 4;
376 data >>= 4;
377 MSB = (data & 0xf) << 4;
378 data >>= 8;
379 COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
380 LSB = (data & 0xf) << 4;
381 data >>= 4;
382 g = (data & 0xf) << 4;
383 data >>= 4;
384 MSB = (data & 0xf) << 4;
385 data >>= 8;
386 COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
387#undef MSB
388#undef LSB
389 width -= 2;
390 src += 4;
391 }
392}
393
394#undef SWAP_PIXELS
395#undef NAME
396#undef SWAP_WORDS
397#undef ORDER
398
399#endif
400