1 /*
2 * linux/drivers/video/afb.c -- Low level frame buffer operations for
3 * bitplanes à la Amiga
4 *
5 * Created 5 Apr 1997 by Geert Uytterhoeven
6 *
7 * This file is subject to the terms and conditions of the GNU General Public
8 * License. See the file COPYING in the main directory of this archive for
9 * more details.
10 */
11
12 #include <linux/module.h>
13 #include <linux/tty.h>
14 #include <linux/console.h>
15 #include <linux/string.h>
16 #include <linux/fb.h>
17
18 #include <video/fbcon.h>
19 #include <video/fbcon-afb.h>
20
21
22 /*
23 * Bitplanes à la Amiga
24 */
25
26 static u8 expand_table[1024] = {
27 /* bg = fg = 0 */
28 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
29 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
30 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
32 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
35 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
43 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
55 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 /* bg = 0, fg = 1 */
61 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
62 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
63 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
64 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
65 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
66 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
67 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
68 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
69 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
70 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
71 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
72 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
73 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
74 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
75 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
76 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
77 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
78 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
79 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
80 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
81 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
82 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
83 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
84 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
85 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
86 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
87 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
88 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
89 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
90 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
91 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
92 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
93 /* bg = 1, fg = 0 */
94 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
95 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
96 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8,
97 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0,
98 0xdf, 0xde, 0xdd, 0xdc, 0xdb, 0xda, 0xd9, 0xd8,
99 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0,
100 0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8,
101 0xc7, 0xc6, 0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0,
102 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8,
103 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0,
104 0xaf, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa8,
105 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0,
106 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98,
107 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90,
108 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88,
109 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
110 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78,
111 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70,
112 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68,
113 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x60,
114 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58,
115 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50,
116 0x4f, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48,
117 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40,
118 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38,
119 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30,
120 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28,
121 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20,
122 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18,
123 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
124 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
125 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
126 /* bg = fg = 1 */
127 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
128 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
129 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
130 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
131 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
132 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
133 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
134 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
135 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
136 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
137 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
138 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
139 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
140 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
141 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
142 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
143 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
144 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
145 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
146 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
147 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
148 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
149 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
150 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
151 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
152 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
153 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
154 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
155 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
156 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
157 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
158 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
159 };
160
161 void fbcon_afb_setup(struct display *p)
162 {
163 if (p->line_length)
164 p->next_line = p->line_length;
165 else
166 p->next_line = p->var.xres_virtual>>3;
167 p->next_plane = p->var.yres_virtual*p->next_line;
168 }
169
170 void fbcon_afb_bmove(struct display *p, int sy, int sx, int dy, int dx,
171 int height, int width)
172 {
173 u8 *src, *dest, *src0, *dest0;
174 u_short i, j;
175
176 if (sx == 0 && dx == 0 && width == p->next_line) {
177 src = p->screen_base+sy*fontheight(p)*width;
178 dest = p->screen_base+dy*fontheight(p)*width;
179 i = p->var.bits_per_pixel;
180 do {
181 fb_memmove(dest, src, height*fontheight(p)*width);
182 src += p->next_plane;
183 dest += p->next_plane;
184 } while (--i);
185 } else if (dy <= sy) {
186 src0 = p->screen_base+sy*fontheight(p)*p->next_line+sx;
187 dest0 = p->screen_base+dy*fontheight(p)*p->next_line+dx;
188 i = p->var.bits_per_pixel;
189 do {
190 src = src0;
191 dest = dest0;
192 j = height*fontheight(p);
193 do {
194 fb_memmove(dest, src, width);
195 src += p->next_line;
196 dest += p->next_line;
197 } while (--j);
198 src0 += p->next_plane;
199 dest0 += p->next_plane;
200 } while (--i);
201 } else {
202 src0 = p->screen_base+(sy+height)*fontheight(p)*p->next_line+sx;
203 dest0 = p->screen_base+(dy+height)*fontheight(p)*p->next_line+dx;
204 i = p->var.bits_per_pixel;
205 do {
206 src = src0;
207 dest = dest0;
208 j = height*fontheight(p);
209 do {
210 src -= p->next_line;
211 dest -= p->next_line;
212 fb_memmove(dest, src, width);
213 } while (--j);
214 src0 += p->next_plane;
215 dest0 += p->next_plane;
216 } while (--i);
217 }
218 }
219
220 void fbcon_afb_clear(struct vc_data *conp, struct display *p, int sy, int sx,
221 int height, int width)
222 {
223 u8 *dest, *dest0;
224 u_short i, j;
225 int bg;
226
227 dest0 = p->screen_base+sy*fontheight(p)*p->next_line+sx;
228
229 bg = attr_bgcol_ec(p,conp);
230 i = p->var.bits_per_pixel;
231 do {
232 dest = dest0;
233 j = height*fontheight(p);
234 do {
235 if (bg & 1)
236 fb_memset255(dest, width);
237 else
238 fb_memclear(dest, width);
239 dest += p->next_line;
240 } while (--j);
241 bg >>= 1;
242 dest0 += p->next_plane;
243 } while (--i);
244 }
245
246 void fbcon_afb_putc(struct vc_data *conp, struct display *p, int c, int yy,
247 int xx)
248 {
249 u8 *dest, *dest0, *cdat, *cdat0, *expand;
250 u_short i, j;
251 int fg, bg;
252
253 dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
254 cdat0 = p->fontdata+(c&p->charmask)*fontheight(p);
255 fg = attr_fgcol(p,c);
256 bg = attr_bgcol(p,c);
257
258 i = p->var.bits_per_pixel;
259 do {
260 dest = dest0;
261 cdat = cdat0;
262 expand = expand_table;
263 if (bg & 1)
264 expand += 512;
265 if (fg & 1)
266 expand += 256;
267 j = fontheight(p);
268 do {
269 *dest = expand[*cdat++];
270 dest += p->next_line;
271 } while (--j);
272 bg >>= 1;
273 fg >>= 1;
274 dest0 += p->next_plane;
275 } while (--i);
276 }
277
278 /*
279 * I've split the console character loop in two parts
280 * (cfr. fbcon_putcs_ilbm())
281 */
282
283 void fbcon_afb_putcs(struct vc_data *conp, struct display *p,
284 const unsigned short *s, int count, int yy, int xx)
285 {
286 u8 *dest, *dest0, *dest1, *expand;
287 u8 *cdat1, *cdat2, *cdat3, *cdat4, *cdat10, *cdat20, *cdat30, *cdat40;
288 u_short i, j;
289 u16 c1, c2, c3, c4;
290 int fg0, bg0, fg, bg;
291
292 dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
293 fg0 = attr_fgcol(p, scr_readw(s));
294 bg0 = attr_bgcol(p, scr_readw(s));
295
296 while (count--)
297 if (xx&3 || count < 3) { /* Slow version */
298 c1 = scr_readw(s++) & p->charmask;
299 dest1 = dest0++;
300 xx++;
301
302 cdat10 = p->fontdata+c1*fontheight(p);
303 fg = fg0;
304 bg = bg0;
305
306 i = p->var.bits_per_pixel;
307 do {
308 dest = dest1;
309 cdat1 = cdat10;
310 expand = expand_table;
311 if (bg & 1)
312 expand += 512;
313 if (fg & 1)
314 expand += 256;
315 j = fontheight(p);
316 do {
317 *dest = expand[*cdat1++];
318 dest += p->next_line;
319 } while (--j);
320 bg >>= 1;
321 fg >>= 1;
322 dest1 += p->next_plane;
323 } while (--i);
324 } else { /* Fast version */
325 c1 = scr_readw(&s[0]) & p->charmask;
326 c2 = scr_readw(&s[1]) & p->charmask;
327 c3 = scr_readw(&s[2]) & p->charmask;
328 c4 = scr_readw(&s[3]) & p->charmask;
329
330 dest1 = dest0;
331 cdat10 = p->fontdata+c1*fontheight(p);
332 cdat20 = p->fontdata+c2*fontheight(p);
333 cdat30 = p->fontdata+c3*fontheight(p);
334 cdat40 = p->fontdata+c4*fontheight(p);
335 fg = fg0;
336 bg = bg0;
337
338 i = p->var.bits_per_pixel;
339 do {
340 dest = dest1;
341 cdat1 = cdat10;
342 cdat2 = cdat20;
343 cdat3 = cdat30;
344 cdat4 = cdat40;
345 expand = expand_table;
346 if (bg & 1)
347 expand += 512;
348 if (fg & 1)
349 expand += 256;
350 j = fontheight(p);
351 do {
352 #if defined(__BIG_ENDIAN)
353 *(u32 *)dest = expand[*cdat1++]<<24 |
354 expand[*cdat2++]<<16 |
355 expand[*cdat3++]<<8 |
356 expand[*cdat4++];
357 #elif defined(__LITTLE_ENDIAN)
358 *(u32 *)dest = expand[*cdat1++] |
359 expand[*cdat2++]<<8 |
360 expand[*cdat3++]<<16 |
361 expand[*cdat4++]<<24;
362 #else
363 #error FIXME: No endianness??
364 #endif
365 dest += p->next_line;
366 } while (--j);
367 bg >>= 1;
368 fg >>= 1;
369 dest1 += p->next_plane;
370 } while (--i);
371 s += 4;
372 dest0 += 4;
373 xx += 4;
374 count -= 3;
375 }
376 }
377
378 void fbcon_afb_revc(struct display *p, int xx, int yy)
379 {
380 u8 *dest, *dest0;
381 u_short i, j;
382 int mask;
383
384 dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
385 mask = p->fgcol ^ p->bgcol;
386
387 /*
388 * This should really obey the individual character's
389 * background and foreground colors instead of simply
390 * inverting.
391 */
392
393 i = p->var.bits_per_pixel;
394 do {
395 if (mask & 1) {
396 dest = dest0;
397 j = fontheight(p);
398 do {
399 *dest = ~*dest;
400 dest += p->next_line;
401 } while (--j);
402 }
403 mask >>= 1;
404 dest0 += p->next_plane;
405 } while (--i);
406 }
407
408
409 /*
410 * `switch' for the low level operations
411 */
412
413 struct display_switch fbcon_afb = {
414 setup: fbcon_afb_setup,
415 bmove: fbcon_afb_bmove,
416 clear: fbcon_afb_clear,
417 putc: fbcon_afb_putc,
418 putcs: fbcon_afb_putcs,
419 revc: fbcon_afb_revc,
420 fontwidthmask: FONTWIDTH(8)
421 };
422
423
424 #ifdef MODULE
425 int init_module(void)
426 {
427 return 0;
428 }
429
430 void cleanup_module(void)
431 {}
432 #endif /* MODULE */
433
434
435 /*
436 * Visible symbols for modules
437 */
438
439 EXPORT_SYMBOL(fbcon_afb);
440 EXPORT_SYMBOL(fbcon_afb_setup);
441 EXPORT_SYMBOL(fbcon_afb_bmove);
442 EXPORT_SYMBOL(fbcon_afb_clear);
443 EXPORT_SYMBOL(fbcon_afb_putc);
444 EXPORT_SYMBOL(fbcon_afb_putcs);
445 EXPORT_SYMBOL(fbcon_afb_revc);
446
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.