blob: 1dce32a0c3494a69d19aeecb2fd619242b118a1b [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
17#define COPY_PIXEL(to, from) *(uint16_t *)to = from; to += 2;
ths5fafdf22007-09-16 21:08:06 +000018#elif BITS == 24
pbrookbdd50032006-02-06 04:11:15 +000019#define COPY_PIXEL(to, from) \
20 *(to++) = from; *(to++) = (from) >> 8; *(to++) = (from) >> 16
21#elif BITS == 32
22#define COPY_PIXEL(to, from) *(uint32_t *)to = from; to += 4;
23#else
24#error unknown bit depth
25#endif
26
balroge9c05b42007-10-04 23:45:31 +000027#undef RGB
28#define BORDER bgr
pbrookbdd50032006-02-06 04:11:15 +000029#define ORDER 0
30#include "pl110_template.h"
31#define ORDER 1
32#include "pl110_template.h"
33#define ORDER 2
34#include "pl110_template.h"
balroge9c05b42007-10-04 23:45:31 +000035#undef BORDER
36#define RGB
37#define BORDER rgb
38#define ORDER 0
39#include "pl110_template.h"
40#define ORDER 1
41#include "pl110_template.h"
42#define ORDER 2
43#include "pl110_template.h"
44#undef BORDER
pbrookbdd50032006-02-06 04:11:15 +000045
Peter Maydell4fbf5552011-07-22 13:19:33 +000046static drawfn glue(pl110_draw_fn_,BITS)[48] =
pbrookbdd50032006-02-06 04:11:15 +000047{
balroge9c05b42007-10-04 23:45:31 +000048 glue(pl110_draw_line1_lblp_bgr,BITS),
49 glue(pl110_draw_line2_lblp_bgr,BITS),
50 glue(pl110_draw_line4_lblp_bgr,BITS),
51 glue(pl110_draw_line8_lblp_bgr,BITS),
Peter Maydell4fbf5552011-07-22 13:19:33 +000052 glue(pl110_draw_line16_555_lblp_bgr,BITS),
balroge9c05b42007-10-04 23:45:31 +000053 glue(pl110_draw_line32_lblp_bgr,BITS),
Peter Maydell4fbf5552011-07-22 13:19:33 +000054 glue(pl110_draw_line16_lblp_bgr,BITS),
55 glue(pl110_draw_line12_lblp_bgr,BITS),
pbrookbdd50032006-02-06 04:11:15 +000056
balroge9c05b42007-10-04 23:45:31 +000057 glue(pl110_draw_line1_bbbp_bgr,BITS),
58 glue(pl110_draw_line2_bbbp_bgr,BITS),
59 glue(pl110_draw_line4_bbbp_bgr,BITS),
60 glue(pl110_draw_line8_bbbp_bgr,BITS),
Peter Maydell4fbf5552011-07-22 13:19:33 +000061 glue(pl110_draw_line16_555_bbbp_bgr,BITS),
balroge9c05b42007-10-04 23:45:31 +000062 glue(pl110_draw_line32_bbbp_bgr,BITS),
Peter Maydell4fbf5552011-07-22 13:19:33 +000063 glue(pl110_draw_line16_bbbp_bgr,BITS),
64 glue(pl110_draw_line12_bbbp_bgr,BITS),
pbrookbdd50032006-02-06 04:11:15 +000065
balroge9c05b42007-10-04 23:45:31 +000066 glue(pl110_draw_line1_lbbp_bgr,BITS),
67 glue(pl110_draw_line2_lbbp_bgr,BITS),
68 glue(pl110_draw_line4_lbbp_bgr,BITS),
69 glue(pl110_draw_line8_lbbp_bgr,BITS),
Peter Maydell4fbf5552011-07-22 13:19:33 +000070 glue(pl110_draw_line16_555_lbbp_bgr,BITS),
balroge9c05b42007-10-04 23:45:31 +000071 glue(pl110_draw_line32_lbbp_bgr,BITS),
Peter Maydell4fbf5552011-07-22 13:19:33 +000072 glue(pl110_draw_line16_lbbp_bgr,BITS),
73 glue(pl110_draw_line12_lbbp_bgr,BITS),
balroge9c05b42007-10-04 23:45:31 +000074
75 glue(pl110_draw_line1_lblp_rgb,BITS),
76 glue(pl110_draw_line2_lblp_rgb,BITS),
77 glue(pl110_draw_line4_lblp_rgb,BITS),
78 glue(pl110_draw_line8_lblp_rgb,BITS),
Peter Maydell4fbf5552011-07-22 13:19:33 +000079 glue(pl110_draw_line16_555_lblp_rgb,BITS),
balroge9c05b42007-10-04 23:45:31 +000080 glue(pl110_draw_line32_lblp_rgb,BITS),
Peter Maydell4fbf5552011-07-22 13:19:33 +000081 glue(pl110_draw_line16_lblp_rgb,BITS),
82 glue(pl110_draw_line12_lblp_rgb,BITS),
balroge9c05b42007-10-04 23:45:31 +000083
84 glue(pl110_draw_line1_bbbp_rgb,BITS),
85 glue(pl110_draw_line2_bbbp_rgb,BITS),
86 glue(pl110_draw_line4_bbbp_rgb,BITS),
87 glue(pl110_draw_line8_bbbp_rgb,BITS),
Peter Maydell4fbf5552011-07-22 13:19:33 +000088 glue(pl110_draw_line16_555_bbbp_rgb,BITS),
balroge9c05b42007-10-04 23:45:31 +000089 glue(pl110_draw_line32_bbbp_rgb,BITS),
Peter Maydell4fbf5552011-07-22 13:19:33 +000090 glue(pl110_draw_line16_bbbp_rgb,BITS),
91 glue(pl110_draw_line12_bbbp_rgb,BITS),
balroge9c05b42007-10-04 23:45:31 +000092
93 glue(pl110_draw_line1_lbbp_rgb,BITS),
94 glue(pl110_draw_line2_lbbp_rgb,BITS),
95 glue(pl110_draw_line4_lbbp_rgb,BITS),
96 glue(pl110_draw_line8_lbbp_rgb,BITS),
Peter Maydell4fbf5552011-07-22 13:19:33 +000097 glue(pl110_draw_line16_555_lbbp_rgb,BITS),
balroge9c05b42007-10-04 23:45:31 +000098 glue(pl110_draw_line32_lbbp_rgb,BITS),
Peter Maydell4fbf5552011-07-22 13:19:33 +000099 glue(pl110_draw_line16_lbbp_rgb,BITS),
100 glue(pl110_draw_line12_lbbp_rgb,BITS),
pbrookbdd50032006-02-06 04:11:15 +0000101};
102
103#undef BITS
104#undef COPY_PIXEL
105
106#else
107
108#if ORDER == 0
balroge9c05b42007-10-04 23:45:31 +0000109#define NAME glue(glue(lblp_, BORDER), BITS)
Juan Quintelae2542fe2009-07-27 16:13:06 +0200110#ifdef HOST_WORDS_BIGENDIAN
pbrookbdd50032006-02-06 04:11:15 +0000111#define SWAP_WORDS 1
112#endif
113#elif ORDER == 1
balroge9c05b42007-10-04 23:45:31 +0000114#define NAME glue(glue(bbbp_, BORDER), BITS)
Juan Quintelae2542fe2009-07-27 16:13:06 +0200115#ifndef HOST_WORDS_BIGENDIAN
pbrookbdd50032006-02-06 04:11:15 +0000116#define SWAP_WORDS 1
117#endif
118#else
119#define SWAP_PIXELS 1
balroge9c05b42007-10-04 23:45:31 +0000120#define NAME glue(glue(lbbp_, BORDER), BITS)
Juan Quintelae2542fe2009-07-27 16:13:06 +0200121#ifdef HOST_WORDS_BIGENDIAN
pbrookbdd50032006-02-06 04:11:15 +0000122#define SWAP_WORDS 1
123#endif
124#endif
125
126#define FN_2(x, y) FN(x, y) FN(x+1, y)
pbrook1f9519c2006-10-18 21:16:44 +0000127#define FN_4(x, y) FN_2(x, y) FN_2(x+2, y)
pbrookbdd50032006-02-06 04:11:15 +0000128#define FN_8(y) FN_4(0, y) FN_4(4, y)
129
pbrook714fa302009-04-01 12:27:59 +0000130static 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 +0000131{
pbrook714fa302009-04-01 12:27:59 +0000132 uint32_t *pallette = opaque;
pbrookbdd50032006-02-06 04:11:15 +0000133 uint32_t data;
134 while (width > 0) {
135 data = *(uint32_t *)src;
136#ifdef SWAP_PIXELS
137#define FN(x, y) COPY_PIXEL(d, pallette[(data >> (y + 7 - (x))) & 1]);
138#else
139#define FN(x, y) COPY_PIXEL(d, pallette[(data >> ((x) + y)) & 1]);
140#endif
pbrookbe9d3652006-02-19 12:31:32 +0000141#ifdef SWAP_WORDS
pbrookbdd50032006-02-06 04:11:15 +0000142 FN_8(24)
143 FN_8(16)
144 FN_8(8)
145 FN_8(0)
146#else
147 FN_8(0)
148 FN_8(8)
149 FN_8(16)
150 FN_8(24)
151#endif
152#undef FN
153 width -= 32;
154 src += 4;
155 }
156}
157
pbrook714fa302009-04-01 12:27:59 +0000158static 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 +0000159{
pbrook714fa302009-04-01 12:27:59 +0000160 uint32_t *pallette = opaque;
pbrookbdd50032006-02-06 04:11:15 +0000161 uint32_t data;
162 while (width > 0) {
163 data = *(uint32_t *)src;
164#ifdef SWAP_PIXELS
165#define FN(x, y) COPY_PIXEL(d, pallette[(data >> (y + 6 - (x)*2)) & 3]);
166#else
167#define FN(x, y) COPY_PIXEL(d, pallette[(data >> ((x)*2 + y)) & 3]);
168#endif
pbrookbe9d3652006-02-19 12:31:32 +0000169#ifdef SWAP_WORDS
pbrookbdd50032006-02-06 04:11:15 +0000170 FN_4(0, 24)
171 FN_4(0, 16)
172 FN_4(0, 8)
173 FN_4(0, 0)
174#else
175 FN_4(0, 0)
176 FN_4(0, 8)
177 FN_4(0, 16)
178 FN_4(0, 24)
179#endif
180#undef FN
181 width -= 16;
182 src += 4;
183 }
184}
185
pbrook714fa302009-04-01 12:27:59 +0000186static 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 +0000187{
pbrook714fa302009-04-01 12:27:59 +0000188 uint32_t *pallette = opaque;
pbrookbdd50032006-02-06 04:11:15 +0000189 uint32_t data;
190 while (width > 0) {
191 data = *(uint32_t *)src;
192#ifdef SWAP_PIXELS
193#define FN(x, y) COPY_PIXEL(d, pallette[(data >> (y + 4 - (x)*4)) & 0xf]);
194#else
195#define FN(x, y) COPY_PIXEL(d, pallette[(data >> ((x)*4 + y)) & 0xf]);
196#endif
pbrookbe9d3652006-02-19 12:31:32 +0000197#ifdef SWAP_WORDS
pbrookbdd50032006-02-06 04:11:15 +0000198 FN_2(0, 24)
199 FN_2(0, 16)
200 FN_2(0, 8)
201 FN_2(0, 0)
202#else
203 FN_2(0, 0)
204 FN_2(0, 8)
205 FN_2(0, 16)
206 FN_2(0, 24)
207#endif
208#undef FN
209 width -= 8;
210 src += 4;
211 }
212}
213
pbrook714fa302009-04-01 12:27:59 +0000214static 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 +0000215{
pbrook714fa302009-04-01 12:27:59 +0000216 uint32_t *pallette = opaque;
pbrookbdd50032006-02-06 04:11:15 +0000217 uint32_t data;
218 while (width > 0) {
219 data = *(uint32_t *)src;
220#define FN(x) COPY_PIXEL(d, pallette[(data >> (x)) & 0xff]);
pbrookbe9d3652006-02-19 12:31:32 +0000221#ifdef SWAP_WORDS
pbrookbdd50032006-02-06 04:11:15 +0000222 FN(24)
223 FN(16)
224 FN(8)
225 FN(0)
226#else
227 FN(0)
228 FN(8)
229 FN(16)
230 FN(24)
231#endif
232#undef FN
233 width -= 4;
234 src += 4;
235 }
236}
237
pbrook714fa302009-04-01 12:27:59 +0000238static 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 +0000239{
240 uint32_t data;
241 unsigned int r, g, b;
242 while (width > 0) {
243 data = *(uint32_t *)src;
pbrookbe9d3652006-02-19 12:31:32 +0000244#ifdef SWAP_WORDS
pbrookbdd50032006-02-06 04:11:15 +0000245 data = bswap32(data);
246#endif
balroge9c05b42007-10-04 23:45:31 +0000247#ifdef RGB
248#define LSB r
249#define MSB b
250#else
251#define LSB b
252#define MSB r
253#endif
pbrookbdd50032006-02-06 04:11:15 +0000254#if 0
balroge9c05b42007-10-04 23:45:31 +0000255 LSB = data & 0x1f;
pbrookbdd50032006-02-06 04:11:15 +0000256 data >>= 5;
257 g = data & 0x3f;
258 data >>= 6;
balroge9c05b42007-10-04 23:45:31 +0000259 MSB = data & 0x1f;
pbrookbdd50032006-02-06 04:11:15 +0000260 data >>= 5;
261#else
balroge9c05b42007-10-04 23:45:31 +0000262 LSB = (data & 0x1f) << 3;
pbrookbdd50032006-02-06 04:11:15 +0000263 data >>= 5;
264 g = (data & 0x3f) << 2;
265 data >>= 6;
balroge9c05b42007-10-04 23:45:31 +0000266 MSB = (data & 0x1f) << 3;
pbrookbdd50032006-02-06 04:11:15 +0000267 data >>= 5;
268#endif
269 COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
balroge9c05b42007-10-04 23:45:31 +0000270 LSB = (data & 0x1f) << 3;
pbrookbdd50032006-02-06 04:11:15 +0000271 data >>= 5;
272 g = (data & 0x3f) << 2;
273 data >>= 6;
balroge9c05b42007-10-04 23:45:31 +0000274 MSB = (data & 0x1f) << 3;
pbrookbdd50032006-02-06 04:11:15 +0000275 data >>= 5;
276 COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
balroge9c05b42007-10-04 23:45:31 +0000277#undef MSB
278#undef LSB
pbrookbdd50032006-02-06 04:11:15 +0000279 width -= 2;
280 src += 4;
281 }
282}
283
pbrook714fa302009-04-01 12:27:59 +0000284static 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 +0000285{
286 uint32_t data;
287 unsigned int r, g, b;
288 while (width > 0) {
289 data = *(uint32_t *)src;
balroge9c05b42007-10-04 23:45:31 +0000290#ifdef RGB
291#define LSB r
292#define MSB b
pbrookbdd50032006-02-06 04:11:15 +0000293#else
balroge9c05b42007-10-04 23:45:31 +0000294#define LSB b
295#define MSB r
296#endif
Paul Brook399a4e22009-05-06 16:18:34 +0100297#ifndef SWAP_WORDS
balroge9c05b42007-10-04 23:45:31 +0000298 LSB = data & 0xff;
299 g = (data >> 8) & 0xff;
300 MSB = (data >> 16) & 0xff;
301#else
302 LSB = (data >> 24) & 0xff;
pbrookbdd50032006-02-06 04:11:15 +0000303 g = (data >> 16) & 0xff;
balroge9c05b42007-10-04 23:45:31 +0000304 MSB = (data >> 8) & 0xff;
pbrookbdd50032006-02-06 04:11:15 +0000305#endif
306 COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
balroge9c05b42007-10-04 23:45:31 +0000307#undef MSB
308#undef LSB
pbrookbdd50032006-02-06 04:11:15 +0000309 width--;
310 src += 4;
311 }
312}
313
Peter Maydell4fbf5552011-07-22 13:19:33 +0000314static void glue(pl110_draw_line16_555_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
315{
316 /* RGB 555 plus an intensity bit (which we ignore) */
317 uint32_t data;
318 unsigned int r, g, b;
319 while (width > 0) {
320 data = *(uint32_t *)src;
321#ifdef SWAP_WORDS
322 data = bswap32(data);
323#endif
324#ifdef RGB
325#define LSB r
326#define MSB b
327#else
328#define LSB b
329#define MSB r
330#endif
331 LSB = (data & 0x1f) << 3;
332 data >>= 5;
333 g = (data & 0x1f) << 3;
334 data >>= 5;
335 MSB = (data & 0x1f) << 3;
336 data >>= 5;
337 COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
338 LSB = (data & 0x1f) << 3;
339 data >>= 5;
340 g = (data & 0x1f) << 3;
341 data >>= 5;
342 MSB = (data & 0x1f) << 3;
343 data >>= 6;
344 COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
345#undef MSB
346#undef LSB
347 width -= 2;
348 src += 4;
349 }
350}
351
352static void glue(pl110_draw_line12_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep)
353{
354 /* RGB 444 with 4 bits of zeroes at the top of each halfword */
355 uint32_t data;
356 unsigned int r, g, b;
357 while (width > 0) {
358 data = *(uint32_t *)src;
359#ifdef SWAP_WORDS
360 data = bswap32(data);
361#endif
362#ifdef RGB
363#define LSB r
364#define MSB b
365#else
366#define LSB b
367#define MSB r
368#endif
369 LSB = (data & 0xf) << 4;
370 data >>= 4;
371 g = (data & 0xf) << 4;
372 data >>= 4;
373 MSB = (data & 0xf) << 4;
374 data >>= 8;
375 COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
376 LSB = (data & 0xf) << 4;
377 data >>= 4;
378 g = (data & 0xf) << 4;
379 data >>= 4;
380 MSB = (data & 0xf) << 4;
381 data >>= 8;
382 COPY_PIXEL(d, glue(rgb_to_pixel,BITS)(r, g, b));
383#undef MSB
384#undef LSB
385 width -= 2;
386 src += 4;
387 }
388}
389
pbrookbdd50032006-02-06 04:11:15 +0000390#undef SWAP_PIXELS
391#undef NAME
392#undef SWAP_WORDS
393#undef ORDER
394
395#endif