1 /*
2  *  linux/drivers/video/cfb4.c -- Low level frame buffer operations for 4 bpp
3  *				  packed pixels
4  *
5  *	Created 26 Dec 1997 by Michael Schmitz
6  *	Based on the old macfb.c 4bpp code by Alan Cox
7  *
8  *  This file is subject to the terms and conditions of the GNU General Public
9  *  License.  See the file COPYING in the main directory of this archive for
10  *  more details.
11  */
12 
13 #include <linux/module.h>
14 #include <linux/tty.h>
15 #include <linux/console.h>
16 #include <linux/string.h>
17 #include <linux/fb.h>
18 
19 #include <video/fbcon.h>
20 #include <video/fbcon-cfb4.h>
21 
22 
23     /*
24      *  4 bpp packed pixels
25      */
26 
27     /*
28      *  IFF the font is even pixel aligned (that is to say each
29      *  character start is a byte start in the pixel pairs). That
30      *  avoids us having to mask bytes and means we won't be here
31      *  all week. On a MacII that matters _lots_
32      */
33 
34 static u16 nibbletab_cfb4[] = {
35 #if defined(__BIG_ENDIAN)
36     0x0000,0x000f,0x00f0,0x00ff,
37     0x0f00,0x0f0f,0x0ff0,0x0fff,
38     0xf000,0xf00f,0xf0f0,0xf0ff,
39     0xff00,0xff0f,0xfff0,0xffff
40 #elif defined(__LITTLE_ENDIAN)
41     0x0000,0xf000,0x0f00,0xff00,
42     0x00f0,0xf0f0,0x0ff0,0xfff0,
43     0x000f,0xf00f,0x0f0f,0xff0f,
44     0x00ff,0xf0ff,0x0fff,0xffff
45 #else
46 #error FIXME: No endianness??
47 #endif
48 
49 };
50 
fbcon_cfb4_setup(struct display * p)51 void fbcon_cfb4_setup(struct display *p)
52 {
53     p->next_line = p->line_length ? p->line_length : p->var.xres_virtual>>1;
54     p->next_plane = 0;
55 }
56 
fbcon_cfb4_bmove(struct display * p,int sy,int sx,int dy,int dx,int height,int width)57 void fbcon_cfb4_bmove(struct display *p, int sy, int sx, int dy, int dx,
58 		      int height, int width)
59 {
60 	int bytes = p->next_line, linesize = bytes * fontheight(p), rows;
61 	u8 *src,*dst;
62 
63 	if (sx == 0 && dx == 0 && width * 4 == bytes) {
64 		fb_memmove(p->screen_base + dy * linesize,
65 			  p->screen_base + sy * linesize,
66 			  height * linesize);
67 	}
68 	else {
69 		if (dy < sy || (dy == sy && dx < sx)) {
70 			src = p->screen_base + sy * linesize + sx * 4;
71 			dst = p->screen_base + dy * linesize + dx * 4;
72 			for (rows = height * fontheight(p) ; rows-- ;) {
73 				fb_memmove(dst, src, width * 4);
74 				src += bytes;
75 				dst += bytes;
76 			}
77 		}
78 		else {
79 			src = p->screen_base + (sy+height) * linesize + sx * 4
80 				- bytes;
81 			dst = p->screen_base + (dy+height) * linesize + dx * 4
82 				- bytes;
83 			for (rows = height * fontheight(p) ; rows-- ;) {
84 				fb_memmove(dst, src, width * 4);
85 				src -= bytes;
86 				dst -= bytes;
87 			}
88 		}
89 	}
90 }
91 
fbcon_cfb4_clear(struct vc_data * conp,struct display * p,int sy,int sx,int height,int width)92 void fbcon_cfb4_clear(struct vc_data *conp, struct display *p, int sy, int sx,
93 		      int height, int width)
94 {
95 	u8 *dest0,*dest;
96 	int bytes=p->next_line,lines=height * fontheight(p), rows, i;
97 	u32 bgx;
98 
99 /*	if(p->screen_base!=0xFDD00020)
100 		mac_boom(1);*/
101 	dest = p->screen_base + sy * fontheight(p) * bytes + sx * 4;
102 
103 	bgx=attr_bgcol_ec(p,conp);
104 	bgx |= (bgx << 4);	/* expand the colour to 32bits */
105 	bgx |= (bgx << 8);
106 	bgx |= (bgx << 16);
107 
108 	if (sx == 0 && width * 4 == bytes) {
109 		for (i = 0 ; i < lines * width ; i++) {
110 			fb_writel (bgx, dest);
111 			dest+=4;
112 		}
113 	} else {
114 		dest0=dest;
115 		for (rows = lines; rows-- ; dest0 += bytes) {
116 			dest=dest0;
117 			for (i = 0 ; i < width ; i++) {
118 				/* memset ?? */
119 				fb_writel (bgx, dest);
120 				dest+=4;
121 			}
122 		}
123 	}
124 }
125 
fbcon_cfb4_putc(struct vc_data * conp,struct display * p,int c,int yy,int xx)126 void fbcon_cfb4_putc(struct vc_data *conp, struct display *p, int c, int yy,
127 		     int xx)
128 {
129 	u8 *dest,*cdat;
130 	int bytes=p->next_line,rows;
131 	u32 eorx,fgx,bgx;
132 
133 	dest = p->screen_base + yy * fontheight(p) * bytes + xx * 4;
134 	cdat = p->fontdata + (c & p->charmask) * fontheight(p);
135 
136 	fgx=attr_fgcol(p,c);
137 	bgx=attr_bgcol(p,c);
138 	fgx |= (fgx << 4);
139 	fgx |= (fgx << 8);
140 	bgx |= (bgx << 4);
141 	bgx |= (bgx << 8);
142 	eorx = fgx ^ bgx;
143 
144 	for (rows = fontheight(p) ; rows-- ; dest += bytes) {
145 		fb_writew((nibbletab_cfb4[*cdat >> 4] & eorx) ^ bgx, dest+0);
146 		fb_writew((nibbletab_cfb4[*cdat++ & 0xf] & eorx) ^ bgx, dest+2);
147 	}
148 }
149 
fbcon_cfb4_putcs(struct vc_data * conp,struct display * p,const unsigned short * s,int count,int yy,int xx)150 void fbcon_cfb4_putcs(struct vc_data *conp, struct display *p,
151 		      const unsigned short *s, int count, int yy, int xx)
152 {
153 	u8 *cdat, *dest, *dest0;
154 	u16 c;
155 	int rows,bytes=p->next_line;
156 	u32 eorx, fgx, bgx;
157 
158 	dest0 = p->screen_base + yy * fontheight(p) * bytes + xx * 4;
159 	c = scr_readw(s);
160 	fgx = attr_fgcol(p, c);
161 	bgx = attr_bgcol(p, c);
162 	fgx |= (fgx << 4);
163 	fgx |= (fgx << 8);
164 	fgx |= (fgx << 16);
165 	bgx |= (bgx << 4);
166 	bgx |= (bgx << 8);
167 	bgx |= (bgx << 16);
168 	eorx = fgx ^ bgx;
169 	while (count--) {
170 		c = scr_readw(s++) & p->charmask;
171 		cdat = p->fontdata + c * fontheight(p);
172 
173 		for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
174 			fb_writew((nibbletab_cfb4[*cdat >> 4] & eorx) ^ bgx, dest+0);
175 			fb_writew((nibbletab_cfb4[*cdat++ & 0xf] & eorx) ^ bgx, dest+2);
176 		}
177 		dest0+=4;
178 	}
179 }
180 
fbcon_cfb4_revc(struct display * p,int xx,int yy)181 void fbcon_cfb4_revc(struct display *p, int xx, int yy)
182 {
183 	u8 *dest;
184 	int bytes=p->next_line, rows;
185 
186 	dest = p->screen_base + yy * fontheight(p) * bytes + xx * 4;
187 	for (rows = fontheight(p) ; rows-- ; dest += bytes) {
188 		fb_writel(fb_readl(dest+0) ^ 0xffffffff, dest+0);
189 	}
190 }
191 
192 
193     /*
194      *  `switch' for the low level operations
195      */
196 
197 struct display_switch fbcon_cfb4 = {
198     setup:		fbcon_cfb4_setup,
199     bmove:		fbcon_cfb4_bmove,
200     clear:		fbcon_cfb4_clear,
201     putc:		fbcon_cfb4_putc,
202     putcs:		fbcon_cfb4_putcs,
203     revc:		fbcon_cfb4_revc,
204     fontwidthmask:	FONTWIDTH(8)
205 };
206 
207 
208 #ifdef MODULE
209 MODULE_LICENSE("GPL");
210 
init_module(void)211 int init_module(void)
212 {
213     return 0;
214 }
215 
cleanup_module(void)216 void cleanup_module(void)
217 {}
218 #endif /* MODULE */
219 
220 
221     /*
222      *  Visible symbols for modules
223      */
224 
225 EXPORT_SYMBOL(fbcon_cfb4);
226 EXPORT_SYMBOL(fbcon_cfb4_setup);
227 EXPORT_SYMBOL(fbcon_cfb4_bmove);
228 EXPORT_SYMBOL(fbcon_cfb4_clear);
229 EXPORT_SYMBOL(fbcon_cfb4_putc);
230 EXPORT_SYMBOL(fbcon_cfb4_putcs);
231 EXPORT_SYMBOL(fbcon_cfb4_revc);
232