Import 2.3.18pre1
[davej-history.git] / drivers / video / fbcon-cfb16.c
blob9fef8171ee4aff0074b1fb568975443d4a9df6f5
1 /*
2 * linux/drivers/video/cfb16.c -- Low level frame buffer operations for 16 bpp
3 * truecolor packed pixels
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
9 * more details.
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>
18 #include <video/fbcon.h>
19 #include <video/fbcon-cfb16.h>
23 * 16 bpp packed pixels
26 static u32 tab_cfb16[] = {
27 #if defined(__BIG_ENDIAN)
28 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
29 #elif defined(__LITTLE_ENDIAN)
30 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
31 #else
32 #error FIXME: No endianness??
33 #endif
36 void fbcon_cfb16_setup(struct display *p)
38 p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<1;
39 p->next_plane = 0;
42 void fbcon_cfb16_bmove(struct display *p, int sy, int sx, int dy, int dx,
43 int height, int width)
45 int bytes = p->next_line, linesize = bytes * fontheight(p), rows;
46 u8 *src, *dst;
48 if (sx == 0 && dx == 0 && width * fontwidth(p) * 2 == bytes) {
49 mymemmove(p->screen_base + dy * linesize,
50 p->screen_base + sy * linesize,
51 height * linesize);
52 return;
54 if (fontwidthlog(p)) {
55 sx <<= fontwidthlog(p)+1;
56 dx <<= fontwidthlog(p)+1;
57 width <<= fontwidthlog(p)+1;
58 } else {
59 sx *= fontwidth(p)*2;
60 dx *= fontwidth(p)*2;
61 width *= fontwidth(p)*2;
63 if (dy < sy || (dy == sy && dx < sx)) {
64 src = p->screen_base + sy * linesize + sx;
65 dst = p->screen_base + dy * linesize + dx;
66 for (rows = height * fontheight(p); rows--;) {
67 mymemmove(dst, src, width);
68 src += bytes;
69 dst += bytes;
71 } else {
72 src = p->screen_base + (sy+height) * linesize + sx - bytes;
73 dst = p->screen_base + (dy+height) * linesize + dx - bytes;
74 for (rows = height * fontheight(p); rows--;) {
75 mymemmove(dst, src, width);
76 src -= bytes;
77 dst -= bytes;
82 static inline void rectfill(u8 *dest, int width, int height, u32 data,
83 int linesize)
85 int i;
87 data |= data<<16;
89 while (height-- > 0) {
90 u32 *p = (u32 *)dest;
91 for (i = 0; i < width/4; i++) {
92 *p++ = data;
93 *p++ = data;
95 if (width & 2)
96 *p++ = data;
97 if (width & 1)
98 *(u16 *)p = data;
99 dest += linesize;
103 void fbcon_cfb16_clear(struct vc_data *conp, struct display *p, int sy, int sx,
104 int height, int width)
106 u8 *dest;
107 int bytes = p->next_line, lines = height * fontheight(p);
108 u32 bgx;
110 dest = p->screen_base + sy * fontheight(p) * bytes + sx * fontwidth(p) * 2;
112 bgx = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
114 width *= fontwidth(p)/4;
115 if (width * 8 == bytes)
116 rectfill(dest, lines * width * 4, 1, bgx, bytes);
117 else
118 rectfill(dest, width * 4, lines, bgx, bytes);
121 void fbcon_cfb16_putc(struct vc_data *conp, struct display *p, int c, int yy,
122 int xx)
124 u8 *dest, *cdat, bits;
125 int bytes = p->next_line, rows;
126 u32 eorx, fgx, bgx;
128 dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2;
130 fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, c)];
131 bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, c)];
132 fgx |= (fgx << 16);
133 bgx |= (bgx << 16);
134 eorx = fgx ^ bgx;
136 switch (fontwidth(p)) {
137 case 4:
138 case 8:
139 cdat = p->fontdata + (c & p->charmask) * fontheight(p);
140 for (rows = fontheight(p); rows--; dest += bytes) {
141 bits = *cdat++;
142 ((u32 *)dest)[0] = (tab_cfb16[bits >> 6] & eorx) ^ bgx;
143 ((u32 *)dest)[1] = (tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx;
144 if (fontwidth(p) == 8) {
145 ((u32 *)dest)[2] = (tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx;
146 ((u32 *)dest)[3] = (tab_cfb16[bits & 3] & eorx) ^ bgx;
149 break;
150 case 12:
151 case 16:
152 cdat = p->fontdata + ((c & p->charmask) * fontheight(p) << 1);
153 for (rows = fontheight(p); rows--; dest += bytes) {
154 bits = *cdat++;
155 ((u32 *)dest)[0] = (tab_cfb16[bits >> 6] & eorx) ^ bgx;
156 ((u32 *)dest)[1] = (tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx;
157 ((u32 *)dest)[2] = (tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx;
158 ((u32 *)dest)[3] = (tab_cfb16[bits & 3] & eorx) ^ bgx;
159 bits = *cdat++;
160 ((u32 *)dest)[4] = (tab_cfb16[bits >> 6] & eorx) ^ bgx;
161 ((u32 *)dest)[5] = (tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx;
162 if (fontwidth(p) == 16) {
163 ((u32 *)dest)[6] = (tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx;
164 ((u32 *)dest)[7] = (tab_cfb16[bits & 3] & eorx) ^ bgx;
167 break;
171 void fbcon_cfb16_putcs(struct vc_data *conp, struct display *p,
172 const unsigned short *s, int count, int yy, int xx)
174 u8 *cdat, *dest, *dest0;
175 u16 c;
176 int rows, bytes = p->next_line;
177 u32 eorx, fgx, bgx;
179 dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 2;
180 fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, scr_readw(s))];
181 bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, scr_readw(s))];
182 fgx |= (fgx << 16);
183 bgx |= (bgx << 16);
184 eorx = fgx ^ bgx;
186 switch (fontwidth(p)) {
187 case 4:
188 case 8:
189 while (count--) {
190 c = scr_readw(s++) & p->charmask;
191 cdat = p->fontdata + c * fontheight(p);
192 for (rows = fontheight(p), dest = dest0; rows--; dest += bytes) {
193 u8 bits = *cdat++;
194 ((u32 *)dest)[0] = (tab_cfb16[bits >> 6] & eorx) ^ bgx;
195 ((u32 *)dest)[1] = (tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx;
196 if (fontwidth(p) == 8) {
197 ((u32 *)dest)[2] = (tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx;
198 ((u32 *)dest)[3] = (tab_cfb16[bits & 3] & eorx) ^ bgx;
201 dest0 += fontwidth(p)*2;;
203 break;
204 case 12:
205 case 16:
206 while (count--) {
207 c = scr_readw(s++) & p->charmask;
208 cdat = p->fontdata + (c * fontheight(p) << 1);
209 for (rows = fontheight(p), dest = dest0; rows--; dest += bytes) {
210 u8 bits = *cdat++;
211 ((u32 *)dest)[0] = (tab_cfb16[bits >> 6] & eorx) ^ bgx;
212 ((u32 *)dest)[1] = (tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx;
213 ((u32 *)dest)[2] = (tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx;
214 ((u32 *)dest)[3] = (tab_cfb16[bits & 3] & eorx) ^ bgx;
215 bits = *cdat++;
216 ((u32 *)dest)[4] = (tab_cfb16[bits >> 6] & eorx) ^ bgx;
217 ((u32 *)dest)[5] = (tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx;
218 if (fontwidth(p) == 16) {
219 ((u32 *)dest)[6] = (tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx;
220 ((u32 *)dest)[7] = (tab_cfb16[bits & 3] & eorx) ^ bgx;
223 dest0 += fontwidth(p)*2;
225 break;
229 void fbcon_cfb16_revc(struct display *p, int xx, int yy)
231 u8 *dest;
232 int bytes = p->next_line, rows;
234 dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p)*2;
235 for (rows = fontheight(p); rows--; dest += bytes) {
236 switch (fontwidth(p)) {
237 case 16:
238 ((u32 *)dest)[6] ^= 0xffffffff; ((u32 *)dest)[7] ^= 0xffffffff;
239 /* FALL THROUGH */
240 case 12:
241 ((u32 *)dest)[4] ^= 0xffffffff; ((u32 *)dest)[5] ^= 0xffffffff;
242 /* FALL THROUGH */
243 case 8:
244 ((u32 *)dest)[2] ^= 0xffffffff; ((u32 *)dest)[3] ^= 0xffffffff;
245 /* FALL THROUGH */
246 case 4:
247 ((u32 *)dest)[0] ^= 0xffffffff; ((u32 *)dest)[1] ^= 0xffffffff;
252 void fbcon_cfb16_clear_margins(struct vc_data *conp, struct display *p,
253 int bottom_only)
255 int bytes = p->next_line;
256 u32 bgx;
258 unsigned int right_start = conp->vc_cols*fontwidth(p);
259 unsigned int bottom_start = conp->vc_rows*fontheight(p);
260 unsigned int right_width, bottom_width;
262 bgx = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
264 if (!bottom_only && (right_width = p->var.xres-right_start))
265 rectfill(p->screen_base+right_start*2, right_width,
266 p->var.yres_virtual, bgx, bytes);
267 if ((bottom_width = p->var.yres-bottom_start))
268 rectfill(p->screen_base+(p->var.yoffset+bottom_start)*bytes,
269 right_start, bottom_width, bgx, bytes);
274 * `switch' for the low level operations
277 struct display_switch fbcon_cfb16 = {
278 fbcon_cfb16_setup, fbcon_cfb16_bmove, fbcon_cfb16_clear, fbcon_cfb16_putc,
279 fbcon_cfb16_putcs, fbcon_cfb16_revc, NULL, NULL, fbcon_cfb16_clear_margins,
280 FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
284 #ifdef MODULE
285 int init_module(void)
287 return 0;
290 void cleanup_module(void)
292 #endif /* MODULE */
296 * Visible symbols for modules
299 EXPORT_SYMBOL(fbcon_cfb16);
300 EXPORT_SYMBOL(fbcon_cfb16_setup);
301 EXPORT_SYMBOL(fbcon_cfb16_bmove);
302 EXPORT_SYMBOL(fbcon_cfb16_clear);
303 EXPORT_SYMBOL(fbcon_cfb16_putc);
304 EXPORT_SYMBOL(fbcon_cfb16_putcs);
305 EXPORT_SYMBOL(fbcon_cfb16_revc);
306 EXPORT_SYMBOL(fbcon_cfb16_clear_margins);