blob: 36ba791c6fdf65520e8407ab01395adaf2015700 [file] [log] [blame]
ths5fafdf22007-09-16 21:08:06 +00001/*
pbrookbdd50032006-02-06 04:11:15 +00002 * Arm PrimeCell PL110 Color LCD Controller
3 *
4 * Copyright (c) 2005 CodeSourcery, LLC.
5 * Written by Paul Brook
6 *
Matthew Fernandez8e31bf32011-06-26 12:21:35 +10007 * This code is licensed under the GNU LGPL
pbrookbdd50032006-02-06 04:11:15 +00008 *
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
Paolo Bonzini2cdaca92014-01-31 14:47:33 +000017#define COPY_PIXEL(to, from) do { *(uint16_t *)to = from; to += 2; } while (0)
ths5fafdf22007-09-16 21:08:06 +000018#elif BITS == 24
Paolo Bonzini2cdaca92014-01-31 14:47:33 +000019#define COPY_PIXEL(to, from) \
20 do { \
21 *(to++) = from; \
22 *(to++) = (from) >> 8; \
23 *(to++) = (from) >> 16; \
24 } while (0)
pbrookbdd50032006-02-06 04:11:15 +000025#elif BITS == 32
Paolo Bonzini2cdaca92014-01-31 14:47:33 +000026#define COPY_PIXEL(to, from) do { *(uint32_t *)to = from; to += 4; } while (0)
pbrookbdd50032006-02-06 04:11:15 +000027#else
28#error unknown bit depth
29#endif
30
balroge9c05b42007-10-04 23:45:31 +000031#undef RGB
32#define BORDER bgr
pbrookbdd50032006-02-06 04:11:15 +000033#define ORDER 0
Paolo Bonzini47b43a12013-03-18 17:36:02 +010034#include "pl110_template.h"
pbrookbdd50032006-02-06 04:11:15 +000035#define ORDER 1
Paolo Bonzini47b43a12013-03-18 17:36:02 +010036#include "pl110_template.h"
pbrookbdd50032006-02-06 04:11:15 +000037#define ORDER 2
Paolo Bonzini47b43a12013-03-18 17:36:02 +010038#include "pl110_template.h"
balroge9c05b42007-10-04 23:45:31 +000039#undef BORDER
40#define RGB
41#define BORDER rgb
42#define ORDER 0
Paolo Bonzini47b43a12013-03-18 17:36:02 +010043#include "pl110_template.h"
balroge9c05b42007-10-04 23:45:31 +000044#define ORDER 1
Paolo Bonzini47b43a12013-03-18 17:36:02 +010045#include "pl110_template.h"
balroge9c05b42007-10-04 23:45:31 +000046#define ORDER 2
Paolo Bonzini47b43a12013-03-18 17:36:02 +010047#include "pl110_template.h"
balroge9c05b42007-10-04 23:45:31 +000048#undef BORDER
pbrookbdd50032006-02-06 04:11:15 +000049
Peter Maydell4fbf5552011-07-22 13:19:33 +000050static drawfn glue(pl110_draw_fn_,BITS)[48] =
pbrookbdd50032006-02-06 04:11:15 +000051{
balroge9c05b42007-10-04 23:45:31 +000052 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),
Peter Maydell4fbf5552011-07-22 13:19:33 +000056 glue(pl110_draw_line16_555_lblp_bgr,BITS),
balroge9c05b42007-10-04 23:45:31 +000057 glue(pl110_draw_line32_lblp_bgr,BITS),
Peter Maydell4fbf5552011-07-22 13:19:33 +000058 glue(pl110_draw_line16_lblp_bgr,BITS),
59 glue(pl110_draw_line12_lblp_bgr,BITS),
pbrookbdd50032006-02-06 04:11:15 +000060
balroge9c05b42007-10-04 23:45:31 +000061 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),
Peter Maydell4fbf5552011-07-22 13:19:33 +000065 glue(pl110_draw_line16_555_bbbp_bgr,BITS),
balroge9c05b42007-10-04 23:45:31 +000066 glue(pl110_draw_line32_bbbp_bgr,BITS),
Peter Maydell4fbf5552011-07-22 13:19:33 +000067 glue(pl110_draw_line16_bbbp_bgr,BITS),
68 glue(pl110_draw_line12_bbbp_bgr,BITS),
pbrookbdd50032006-02-06 04:11:15 +000069
balroge9c05b42007-10-04 23:45:31 +000070 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),
Peter Maydell4fbf5552011-07-22 13:19:33 +000074 glue(pl110_draw_line16_555_lbbp_bgr,BITS),
balroge9c05b42007-10-04 23:45:31 +000075 glue(pl110_draw_line32_lbbp_bgr,BITS),
Peter Maydell4fbf5552011-07-22 13:19:33 +000076 glue(pl110_draw_line16_lbbp_bgr,BITS),
77 glue(pl110_draw_line12_lbbp_bgr,BITS),
balroge9c05b42007-10-04 23:45:31 +000078
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),
Peter Maydell4fbf5552011-07-22 13:19:33 +000083 glue(pl110_draw_line16_555_lblp_rgb,BITS),
balroge9c05b42007-10-04 23:45:31 +000084 glue(pl110_draw_line32_lblp_rgb,BITS),
Peter Maydell4fbf5552011-07-22 13:19:33 +000085 glue(pl110_draw_line16_lblp_rgb,BITS),
86 glue(pl110_draw_line12_lblp_rgb,BITS),
balroge9c05b42007-10-04 23:45:31 +000087
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),
Peter Maydell4fbf5552011-07-22 13:19:33 +000092 glue(pl110_draw_line16_555_bbbp_rgb,BITS),
balroge9c05b42007-10-04 23:45:31 +000093 glue(pl110_draw_line32_bbbp_rgb,BITS),
Peter Maydell4fbf5552011-07-22 13:19:33 +000094 glue(pl110_draw_line16_bbbp_rgb,BITS),
95 glue(pl110_draw_line12_bbbp_rgb,BITS),
balroge9c05b42007-10-04 23:45:31 +000096
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),
Peter Maydell4fbf5552011-07-22 13:19:33 +0000101 glue(pl110_draw_line16_555_lbbp_rgb,BITS),
balroge9c05b42007-10-04 23:45:31 +0000102 glue(pl110_draw_line32_lbbp_rgb,BITS),
Peter Maydell4fbf5552011-07-22 13:19:33 +0000103 glue(pl110_draw_line16_lbbp_rgb,BITS),
104 glue(pl110_draw_line12_lbbp_rgb,BITS),
pbrookbdd50032006-02-06 04:11:15 +0000105};
106
107#undef BITS
108#undef COPY_PIXEL
109
110#else
111
112#if ORDER == 0
balroge9c05b42007-10-04 23:45:31 +0000113#define NAME glue(glue(lblp_, BORDER), BITS)
Juan Quintelae2542fe2009-07-27 16:13:06 +0200114#ifdef HOST_WORDS_BIGENDIAN
pbrookbdd50032006-02-06 04:11:15 +0000115#define SWAP_WORDS 1
116#endif
117#elif ORDER == 1
balroge9c05b42007-10-04 23:45:31 +0000118#define NAME glue(glue(bbbp_, BORDER), BITS)
Juan Quintelae2542fe2009-07-27 16:13:06 +0200119#ifndef HOST_WORDS_BIGENDIAN
pbrookbdd50032006-02-06 04:11:15 +0000120#define SWAP_WORDS 1
121#endif
122#else
123#define SWAP_PIXELS 1
balroge9c05b42007-10-04 23:45:31 +0000124#define NAME glue(glue(lbbp_, BORDER), BITS)
Juan Quintelae2542fe2009-07-27 16:13:06 +0200125#ifdef HOST_WORDS_BIGENDIAN
pbrookbdd50032006-02-06 04:11:15 +0000126#define SWAP_WORDS 1
127#endif
128#endif
129
130#define FN_2(x, y) FN(x, y) FN(x+1, y)
pbrook1f9519c2006-10-18 21:16:44 +0000131#define FN_4(x, y) FN_2(x, y) FN_2(x+2, y)
pbrookbdd50032006-02-06 04:11:15 +0000132#define FN_8(y) FN_4(0, y) FN_4(4, y)
133
pbrook714fa302009-04-01 12:27:59 +0000134static void glue(pl110_draw_line1_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
pbrookbdd50032006-02-06 04:11:15 +0000135{
Peter Maydell6e4c0d12012-08-27 12:32:36 +0100136 uint32_t *palette = opaque;
pbrookbdd50032006-02-06 04:11:15 +0000137 uint32_t data;
138 while (width > 0) {
139 data = *(uint32_t *)src;
140#ifdef SWAP_PIXELS
Peter Maydell6e4c0d12012-08-27 12:32:36 +0100141#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 7 - (x))) & 1]);
pbrookbdd50032006-02-06 04:11:15 +0000142#else
Peter Maydell6e4c0d12012-08-27 12:32:36 +0100143#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x) + y)) & 1]);
pbrookbdd50032006-02-06 04:11:15 +0000144#endif
pbrookbe9d3652006-02-19 12:31:32 +0000145#ifdef SWAP_WORDS
pbrookbdd50032006-02-06 04:11:15 +0000146 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
pbrook714fa302009-04-01 12:27:59 +0000162static void glue(pl110_draw_line2_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
pbrookbdd50032006-02-06 04:11:15 +0000163{
Peter Maydell6e4c0d12012-08-27 12:32:36 +0100164 uint32_t *palette = opaque;
pbrookbdd50032006-02-06 04:11:15 +0000165 uint32_t data;
166 while (width > 0) {
167 data = *(uint32_t *)src;
168#ifdef SWAP_PIXELS
Peter Maydell6e4c0d12012-08-27 12:32:36 +0100169#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 6 - (x)*2)) & 3]);
pbrookbdd50032006-02-06 04:11:15 +0000170#else
Peter Maydell6e4c0d12012-08-27 12:32:36 +0100171#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x)*2 + y)) & 3]);
pbrookbdd50032006-02-06 04:11:15 +0000172#endif
pbrookbe9d3652006-02-19 12:31:32 +0000173#ifdef SWAP_WORDS
pbrookbdd50032006-02-06 04:11:15 +0000174 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
pbrook714fa302009-04-01 12:27:59 +0000190static void glue(pl110_draw_line4_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
pbrookbdd50032006-02-06 04:11:15 +0000191{
Peter Maydell6e4c0d12012-08-27 12:32:36 +0100192 uint32_t *palette = opaque;
pbrookbdd50032006-02-06 04:11:15 +0000193 uint32_t data;
194 while (width > 0) {
195 data = *(uint32_t *)src;
196#ifdef SWAP_PIXELS
Peter Maydell6e4c0d12012-08-27 12:32:36 +0100197#define FN(x, y) COPY_PIXEL(d, palette[(data >> (y + 4 - (x)*4)) & 0xf]);
pbrookbdd50032006-02-06 04:11:15 +0000198#else
Peter Maydell6e4c0d12012-08-27 12:32:36 +0100199#define FN(x, y) COPY_PIXEL(d, palette[(data >> ((x)*4 + y)) & 0xf]);
pbrookbdd50032006-02-06 04:11:15 +0000200#endif
pbrookbe9d3652006-02-19 12:31:32 +0000201#ifdef SWAP_WORDS
pbrookbdd50032006-02-06 04:11:15 +0000202 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
pbrook714fa302009-04-01 12:27:59 +0000218static void glue(pl110_draw_line8_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
pbrookbdd50032006-02-06 04:11:15 +0000219{
Peter Maydell6e4c0d12012-08-27 12:32:36 +0100220 uint32_t *palette = opaque;
pbrookbdd50032006-02-06 04:11:15 +0000221 uint32_t data;
222 while (width > 0) {
223 data = *(uint32_t *)src;
Peter Maydell6e4c0d12012-08-27 12:32:36 +0100224#define FN(x) COPY_PIXEL(d, palette[(data >> (x)) & 0xff]);
pbrookbe9d3652006-02-19 12:31:32 +0000225#ifdef SWAP_WORDS
pbrookbdd50032006-02-06 04:11:15 +0000226 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
pbrook714fa302009-04-01 12:27:59 +0000242static void glue(pl110_draw_line16_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
pbrookbdd50032006-02-06 04:11:15 +0000243{
244 uint32_t data;
245 unsigned int r, g, b;
246 while (width > 0) {
247 data = *(uint32_t *)src;
pbrookbe9d3652006-02-19 12:31:32 +0000248#ifdef SWAP_WORDS
pbrookbdd50032006-02-06 04:11:15 +0000249 data = bswap32(data);
250#endif
balroge9c05b42007-10-04 23:45:31 +0000251#ifdef RGB
252#define LSB r
253#define MSB b
254#else
255#define LSB b
256#define MSB r
257#endif
pbrookbdd50032006-02-06 04:11:15 +0000258#if 0
balroge9c05b42007-10-04 23:45:31 +0000259 LSB = data & 0x1f;
pbrookbdd50032006-02-06 04:11:15 +0000260 data >>= 5;
261 g = data & 0x3f;
262 data >>= 6;
balroge9c05b42007-10-04 23:45:31 +0000263 MSB = data & 0x1f;
pbrookbdd50032006-02-06 04:11:15 +0000264 data >>= 5;
265#else
balroge9c05b42007-10-04 23:45:31 +0000266 LSB = (data & 0x1f) << 3;
pbrookbdd50032006-02-06 04:11:15 +0000267 data >>= 5;
268 g = (data & 0x3f) << 2;
269 data >>= 6;
balroge9c05b42007-10-04 23:45:31 +0000270 MSB = (data & 0x1f) << 3;
pbrookbdd50032006-02-06 04:11:15 +0000271 data >>= 5;
272#endif
273 COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
balroge9c05b42007-10-04 23:45:31 +0000274 LSB = (data & 0x1f) << 3;
pbrookbdd50032006-02-06 04:11:15 +0000275 data >>= 5;
276 g = (data & 0x3f) << 2;
277 data >>= 6;
balroge9c05b42007-10-04 23:45:31 +0000278 MSB = (data & 0x1f) << 3;
pbrookbdd50032006-02-06 04:11:15 +0000279 data >>= 5;
280 COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
balroge9c05b42007-10-04 23:45:31 +0000281#undef MSB
282#undef LSB
pbrookbdd50032006-02-06 04:11:15 +0000283 width -= 2;
284 src += 4;
285 }
286}
287
pbrook714fa302009-04-01 12:27:59 +0000288static void glue(pl110_draw_line32_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
pbrookbdd50032006-02-06 04:11:15 +0000289{
290 uint32_t data;
291 unsigned int r, g, b;
292 while (width > 0) {
293 data = *(uint32_t *)src;
balroge9c05b42007-10-04 23:45:31 +0000294#ifdef RGB
295#define LSB r
296#define MSB b
pbrookbdd50032006-02-06 04:11:15 +0000297#else
balroge9c05b42007-10-04 23:45:31 +0000298#define LSB b
299#define MSB r
300#endif
Paul Brook399a4e22009-05-06 16:18:34 +0100301#ifndef SWAP_WORDS
balroge9c05b42007-10-04 23:45:31 +0000302 LSB = data & 0xff;
303 g = (data >> 8) & 0xff;
304 MSB = (data >> 16) & 0xff;
305#else
306 LSB = (data >> 24) & 0xff;
pbrookbdd50032006-02-06 04:11:15 +0000307 g = (data >> 16) & 0xff;
balroge9c05b42007-10-04 23:45:31 +0000308 MSB = (data >> 8) & 0xff;
pbrookbdd50032006-02-06 04:11:15 +0000309#endif
310 COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
balroge9c05b42007-10-04 23:45:31 +0000311#undef MSB
312#undef LSB
pbrookbdd50032006-02-06 04:11:15 +0000313 width--;
314 src += 4;
315 }
316}
317
Peter Maydell4fbf5552011-07-22 13:19:33 +0000318static 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
pbrookbdd50032006-02-06 04:11:15 +0000394#undef SWAP_PIXELS
395#undef NAME
396#undef SWAP_WORDS
397#undef ORDER
398
399#endif