File: /usr/src/linux/drivers/video/fbcon-cfb8.c

1     /*
2      *  linux/drivers/video/cfb8.c -- Low level frame buffer operations for 8 bpp
3      *				  packed pixels
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-cfb8.h>
20     
21     
22         /*
23          *  8 bpp packed pixels
24          */
25     
26     static u32 nibbletab_cfb8[] = {
27     #if defined(__BIG_ENDIAN)
28         0x00000000,0x000000ff,0x0000ff00,0x0000ffff,
29         0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff,
30         0xff000000,0xff0000ff,0xff00ff00,0xff00ffff,
31         0xffff0000,0xffff00ff,0xffffff00,0xffffffff
32     #elif defined(__LITTLE_ENDIAN)
33         0x00000000,0xff000000,0x00ff0000,0xffff0000,
34         0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00,
35         0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff,
36         0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff
37     #else
38     #error FIXME: No endianness??
39     #endif
40     };
41     
42     void fbcon_cfb8_setup(struct display *p)
43     {
44         p->next_line = p->line_length ? p->line_length : p->var.xres_virtual;
45         p->next_plane = 0;
46     }
47     
48     void fbcon_cfb8_bmove(struct display *p, int sy, int sx, int dy, int dx,
49     		      int height, int width)
50     {
51         int bytes = p->next_line, linesize = bytes * fontheight(p), rows;
52         u8 *src,*dst;
53     
54         if (sx == 0 && dx == 0 && width * fontwidth(p) == bytes) {
55     	fb_memmove(p->screen_base + dy * linesize,
56     		  p->screen_base + sy * linesize,
57     		  height * linesize);
58     	return;
59         }
60         if (fontwidthlog(p)) {
61         	sx <<= fontwidthlog(p); dx <<= fontwidthlog(p); width <<= fontwidthlog(p);
62         } else {
63         	sx *= fontwidth(p); dx *= fontwidth(p); width *= fontwidth(p);
64         }
65         if (dy < sy || (dy == sy && dx < sx)) {
66     	src = p->screen_base + sy * linesize + sx;
67     	dst = p->screen_base + dy * linesize + dx;
68     	for (rows = height * fontheight(p) ; rows-- ;) {
69     	    fb_memmove(dst, src, width);
70     	    src += bytes;
71     	    dst += bytes;
72     	}
73         } else {
74     	src = p->screen_base + (sy+height) * linesize + sx - bytes;
75     	dst = p->screen_base + (dy+height) * linesize + dx - bytes;
76     	for (rows = height * fontheight(p) ; rows-- ;) {
77     	    fb_memmove(dst, src, width);
78     	    src -= bytes;
79     	    dst -= bytes;
80     	}
81         }
82     }
83     
84     static inline void rectfill(u8 *dest, int width, int height, u8 data,
85     			    int linesize)
86     {
87         while (height-- > 0) {
88     	fb_memset(dest, data, width);
89     	dest += linesize;
90         }
91     }
92     
93     void fbcon_cfb8_clear(struct vc_data *conp, struct display *p, int sy, int sx,
94     		      int height, int width)
95     {
96         u8 *dest;
97         int bytes=p->next_line,lines=height * fontheight(p);
98         u8 bgx;
99     
100         dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p);
101     
102         bgx=attr_bgcol_ec(p,conp);
103     
104         width *= fontwidth(p);
105         if (width == bytes)
106     	rectfill(dest, lines * width, 1, bgx, bytes);
107         else
108     	rectfill(dest, width, lines, bgx, bytes);
109     }
110     
111     void fbcon_cfb8_putc(struct vc_data *conp, struct display *p, int c, int yy,
112     		     int xx)
113     {
114         u8 *dest,*cdat;
115         int bytes=p->next_line,rows;
116         u32 eorx,fgx,bgx;
117     
118         dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p);
119         if (fontwidth(p) <= 8)
120     	cdat = p->fontdata + (c & p->charmask) * fontheight(p);
121         else
122     	cdat = p->fontdata + ((c & p->charmask) * fontheight(p) << 1);
123     
124         fgx=attr_fgcol(p,c);
125         bgx=attr_bgcol(p,c);
126         fgx |= (fgx << 8);
127         fgx |= (fgx << 16);
128         bgx |= (bgx << 8);
129         bgx |= (bgx << 16);
130         eorx = fgx ^ bgx;
131     
132         switch (fontwidth(p)) {
133         case 4:
134     	for (rows = fontheight(p) ; rows-- ; dest += bytes)
135     	    fb_writel((nibbletab_cfb8[*cdat++ >> 4] & eorx) ^ bgx, dest);
136             break;
137         case 8:
138     	for (rows = fontheight(p) ; rows-- ; dest += bytes) {
139     	    fb_writel((nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx, dest);
140     	    fb_writel((nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx, dest+4);
141             }
142             break;
143         case 12:
144         case 16:
145     	for (rows = fontheight(p) ; rows-- ; dest += bytes) {
146     	    fb_writel((nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx, dest);
147     	    fb_writel((nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx, dest+4);
148     	    fb_writel((nibbletab_cfb8[(*cdat >> 4) & 0xf] & eorx) ^ bgx, dest+8);
149     	    if (fontwidth(p) == 16)
150     		fb_writel((nibbletab_cfb8[*cdat & 0xf] & eorx) ^ bgx, dest+12);
151     	    cdat++;
152             }
153             break;
154         }
155     }
156     
157     void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p, 
158     		      const unsigned short *s, int count, int yy, int xx)
159     {
160         u8 *cdat, *dest, *dest0;
161         u16 c;
162         int rows,bytes=p->next_line;
163         u32 eorx, fgx, bgx;
164     
165         dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p);
166         fgx=attr_fgcol(p,scr_readw(s));
167         bgx=attr_bgcol(p,scr_readw(s));
168         fgx |= (fgx << 8);
169         fgx |= (fgx << 16);
170         bgx |= (bgx << 8);
171         bgx |= (bgx << 16);
172         eorx = fgx ^ bgx;
173         switch (fontwidth(p)) {
174         case 4:
175     	while (count--) {
176     	    c = scr_readw(s++) & p->charmask;
177     	    cdat = p->fontdata + c * fontheight(p);
178     
179     	    for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes)
180     		fb_writel((nibbletab_cfb8[*cdat++ >> 4] & eorx) ^ bgx, dest);
181     	    dest0+=4;
182             }
183             break;
184         case 8:
185     	while (count--) {
186     	    c = scr_readw(s++) & p->charmask;
187     	    cdat = p->fontdata + c * fontheight(p);
188     
189     	    for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
190     		fb_writel((nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx, dest);
191     		fb_writel((nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx, dest+4);
192     	    }
193     	    dest0+=8;
194             }
195             break;
196         case 12:
197         case 16:
198     	while (count--) {
199     	    c = scr_readw(s++) & p->charmask;
200     	    cdat = p->fontdata + (c * fontheight(p) << 1);
201     
202     	    for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
203     		fb_writel((nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx, dest);
204     		fb_writel((nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx, dest+4);
205     		fb_writel((nibbletab_cfb8[(*cdat >> 4) & 0xf] & eorx) ^ bgx, dest+8);
206     		if (fontwidth(p) == 16)
207     		   fb_writel((nibbletab_cfb8[*cdat & 0xf] & eorx) ^ bgx, dest+12);
208     		cdat++;
209     	    }
210     	    dest0+=fontwidth(p);
211             }
212             break;
213         }
214     }
215     
216     void fbcon_cfb8_revc(struct display *p, int xx, int yy)
217     {
218         u8 *dest;
219         int bytes=p->next_line, rows;
220     
221         dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p);
222         for (rows = fontheight(p) ; rows-- ; dest += bytes) {
223         	switch (fontwidth(p)) {
224         	case 16: fb_writel(fb_readl(dest+12) ^ 0x0f0f0f0f, dest+12); /* fall thru */
225         	case 12: fb_writel(fb_readl(dest+8) ^ 0x0f0f0f0f, dest+8); /* fall thru */
226         	case 8: fb_writel(fb_readl(dest+4) ^ 0x0f0f0f0f, dest+4); /* fall thru */
227         	case 4: fb_writel(fb_readl(dest) ^ 0x0f0f0f0f, dest); /* fall thru */
228         	default: break;
229         	}
230         }
231     }
232     
233     void fbcon_cfb8_clear_margins(struct vc_data *conp, struct display *p,
234     			      int bottom_only)
235     {
236         int bytes=p->next_line;
237         u8 bgx;
238     
239         unsigned int right_start = conp->vc_cols*fontwidth(p);
240         unsigned int bottom_start = conp->vc_rows*fontheight(p);
241         unsigned int right_width, bottom_width;
242     
243         bgx=attr_bgcol_ec(p,conp);
244     
245         if (!bottom_only && (right_width = p->var.xres-right_start))
246     	rectfill(p->screen_base+right_start, right_width, p->var.yres_virtual,
247     		 bgx, bytes);
248         if ((bottom_width = p->var.yres-bottom_start))
249     	rectfill(p->screen_base+(p->var.yoffset+bottom_start)*bytes,
250     		 right_start, bottom_width, bgx, bytes);
251     }
252     
253     
254         /*
255          *  `switch' for the low level operations
256          */
257     
258     struct display_switch fbcon_cfb8 = {
259         setup:		fbcon_cfb8_setup,
260         bmove:		fbcon_cfb8_bmove,
261         clear:		fbcon_cfb8_clear,
262         putc:		fbcon_cfb8_putc,
263         putcs:		fbcon_cfb8_putcs,
264         revc:		fbcon_cfb8_revc,
265         clear_margins:	fbcon_cfb8_clear_margins,
266         fontwidthmask:	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
267     };
268     
269     
270     #ifdef MODULE
271     MODULE_LICENSE("GPL");
272     
273     int init_module(void)
274     {
275         return 0;
276     }
277     
278     void cleanup_module(void)
279     {}
280     #endif /* MODULE */
281     
282     
283         /*
284          *  Visible symbols for modules
285          */
286     
287     EXPORT_SYMBOL(fbcon_cfb8);
288     EXPORT_SYMBOL(fbcon_cfb8_setup);
289     EXPORT_SYMBOL(fbcon_cfb8_bmove);
290     EXPORT_SYMBOL(fbcon_cfb8_clear);
291     EXPORT_SYMBOL(fbcon_cfb8_putc);
292     EXPORT_SYMBOL(fbcon_cfb8_putcs);
293     EXPORT_SYMBOL(fbcon_cfb8_revc);
294     EXPORT_SYMBOL(fbcon_cfb8_clear_margins);
295