2 * linux/drivers/video/ilbm.c -- Low level frame buffer operations for
3 * interleaved bitplanes à la Amiga
5 * Created 5 Apr 1997 by Geert Uytterhoeven
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
12 #include <linux/module.h>
13 #include <linux/tty.h>
14 #include <linux/console.h>
15 #include <linux/string.h>
18 #include <video/fbcon.h>
19 #include <video/fbcon-ilbm.h>
23 * Interleaved bitplanes à la Amiga
25 * This code heavily relies on the fact that
27 * next_line == interleave == next_plane*bits_per_pixel
29 * But maybe it can be merged with the code for normal bitplanes without
30 * much performance loss?
33 void fbcon_ilbm_setup(struct display *p)
36 p->next_line = p->line_length*p->var.bits_per_pixel;
37 p->next_plane = p->line_length;
39 p->next_line = p->type_aux;
40 p->next_plane = p->type_aux/p->var.bits_per_pixel;
44 void fbcon_ilbm_bmove(struct display *p, int sy, int sx, int dy, int dx,
45 int height, int width)
47 if (sx == 0 && dx == 0 && width == p->next_plane)
48 fb_memmove(p->screen_base+dy*fontheight(p)*p->next_line,
49 p->screen_base+sy*fontheight(p)*p->next_line,
50 height*fontheight(p)*p->next_line);
56 src = p->screen_base+sy*fontheight(p)*p->next_line+sx;
57 dest = p->screen_base+dy*fontheight(p)*p->next_line+dx;
58 for (i = p->var.bits_per_pixel*height*fontheight(p); i--;) {
59 fb_memmove(dest, src, width);
61 dest += p->next_plane;
64 src = p->screen_base+(sy+height)*fontheight(p)*p->next_line+sx;
65 dest = p->screen_base+(dy+height)*fontheight(p)*p->next_line+dx;
66 for (i = p->var.bits_per_pixel*height*fontheight(p); i--;) {
68 dest -= p->next_plane;
69 fb_memmove(dest, src, width);
75 void fbcon_ilbm_clear(struct vc_data *conp, struct display *p, int sy, int sx,
76 int height, int width)
82 dest = p->screen_base+sy*fontheight(p)*p->next_line+sx;
84 bg0 = attr_bgcol_ec(p,conp);
85 for (rows = height*fontheight(p); rows--;) {
87 for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
89 fb_memset255(dest, width);
91 fb_memclear(dest, width);
97 void fbcon_ilbm_putc(struct vc_data *conp, struct display *p, int c, int yy,
103 int fg0, bg0, fg, bg;
105 dest = p->screen_base+yy*fontheight(p)*p->next_line+xx;
106 cdat = p->fontdata+(c&p->charmask)*fontheight(p);
107 fg0 = attr_fgcol(p,c);
108 bg0 = attr_bgcol(p,c);
110 for (rows = fontheight(p); rows--;) {
114 for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
133 * I've split the console character loop in two parts:
135 * - slow version: this blits one character at a time
137 * - fast version: this blits 4 characters at a time at a longword
138 * aligned address, to reduce the number of expensive
141 * Experiments on my A4000/040 revealed that this makes a console switch
142 * on a 640x400 screen with 256 colors about 3 times faster.
147 void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p,
148 const unsigned short *s, int count, int yy, int xx)
150 u8 *dest0, *dest, *cdat1, *cdat2, *cdat3, *cdat4;
154 int fg0, bg0, fg, bg;
156 dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
158 fg0 = attr_fgcol(p, c1);
159 bg0 = attr_bgcol(p, c1);
162 if (xx&3 || count < 3) { /* Slow version */
163 c1 = scr_readw(s++) & p->charmask;
167 cdat1 = p->fontdata+c1*fontheight(p);
168 for (rows = fontheight(p); rows--;) {
172 for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
188 } else { /* Fast version */
189 c1 = scr_readw(&s[0]) & p->charmask;
190 c2 = scr_readw(&s[1]) & p->charmask;
191 c3 = scr_readw(&s[2]) & p->charmask;
192 c4 = scr_readw(&s[3]) & p->charmask;
195 cdat1 = p->fontdata+c1*fontheight(p);
196 cdat2 = p->fontdata+c2*fontheight(p);
197 cdat3 = p->fontdata+c3*fontheight(p);
198 cdat4 = p->fontdata+c4*fontheight(p);
199 for (rows = fontheight(p); rows--;) {
200 #if defined(__BIG_ENDIAN)
201 d = *cdat1++<<24 | *cdat2++<<16 | *cdat3++<<8 | *cdat4++;
202 #elif defined(__LITTLE_ENDIAN)
203 d = *cdat1++ | *cdat2++<<8 | *cdat3++<<16 | *cdat4++<<24;
205 #error FIXME: No endianness??
209 for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
212 *(u32 *)dest = 0xffffffff;
219 *(u32 *)dest = 0x00000000;
232 void fbcon_ilbm_revc(struct display *p, int xx, int yy)
238 dest0 = p->screen_base+yy*fontheight(p)*p->next_line+xx;
239 mask = p->fgcol ^ p->bgcol;
242 * This should really obey the individual character's
243 * background and foreground colors instead of simply
247 for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) {
250 for (rows = fontheight(p); rows--; dest += p->next_line)
259 * `switch' for the low level operations
262 struct display_switch fbcon_ilbm = {
263 setup: fbcon_ilbm_setup,
264 bmove: fbcon_ilbm_bmove,
265 clear: fbcon_ilbm_clear,
266 putc: fbcon_ilbm_putc,
267 putcs: fbcon_ilbm_putcs,
268 revc: fbcon_ilbm_revc,
269 fontwidthmask: FONTWIDTH(8)
274 MODULE_LICENSE("GPL");
276 int init_module(void)
281 void cleanup_module(void)
287 * Visible symbols for modules
290 EXPORT_SYMBOL(fbcon_ilbm);
291 EXPORT_SYMBOL(fbcon_ilbm_setup);
292 EXPORT_SYMBOL(fbcon_ilbm_bmove);
293 EXPORT_SYMBOL(fbcon_ilbm_clear);
294 EXPORT_SYMBOL(fbcon_ilbm_putc);
295 EXPORT_SYMBOL(fbcon_ilbm_putcs);
296 EXPORT_SYMBOL(fbcon_ilbm_revc);