xref: /openbmc/qemu/hw/display/pl110_template.h (revision 4a09d0bb)
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 
50 static 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 
134 static 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 
162 static 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 
190 static 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 
218 static 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 
242 static 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 
288 static 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 
318 static 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 
356 static 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