Import 2.3.15pre2
[davej-history.git] / drivers / video / fbcon-mac.c
blob2c6486c41d38092cf6280c26d980d87d54b0763c
1 /*
2 * linux/drivers/video/fbcon-mac.c -- Low level frame buffer operations for
3 * x bpp packed pixels, font width != 8
5 * Created 26 Dec 1997 by Michael Schmitz
6 * Based on the old macfb.c 6x11 code by Randy Thelen
8 * This driver is significantly slower than the 8bit font drivers
9 * and would probably benefit from splitting into drivers for each depth.
11 * This file is subject to the terms and conditions of the GNU General Public
12 * License. See the file COPYING in the main directory of this archive for
15 #include <linux/module.h>
16 #include <linux/tty.h>
17 #include <linux/console.h>
18 #include <linux/string.h>
19 #include <linux/fb.h>
20 #include <linux/delay.h>
22 #include <video/fbcon.h>
23 #include <video/fbcon-mac.h>
27 * variable bpp packed pixels
30 static void plot_pixel_mac(struct display *p, int bw, int pixel_x,
31 int pixel_y);
32 static int get_pixel_mac(struct display *p, int pixel_x, int pixel_y);
34 void fbcon_mac_setup(struct display *p)
36 if (p->line_length)
37 p->next_line = p->line_length;
38 else
39 p->next_line = p->var.xres_virtual>>3;
40 p->next_plane = 0;
45 * Macintosh
47 #define PIXEL_BLACK_MAC 0
48 #define PIXEL_WHITE_MAC 1
49 #define PIXEL_INVERT_MAC 2
51 void fbcon_mac_bmove(struct display *p, int sy, int sx, int dy, int dx,
52 int height, int width)
54 int i, j;
55 u8 *dest, *src;
56 int l,r,t,b,w,lo,s;
57 int dl,dr,dt,db,dw,dlo;
58 int move_up;
60 src = (u8 *) (p->screen_base + sy * fontheight(p) * p->next_line);
61 dest = (u8 *) (p->screen_base + dy * fontheight(p) * p->next_line);
63 if( sx == 0 && width == p->conp->vc_cols) {
64 s = height * fontheight(p) * p->next_line;
65 mymemmove(dest, src, s);
66 return;
69 l = sx * fontwidth(p);
70 r = l + width * fontwidth(p);
71 t = sy * fontheight(p);
72 b = t + height * fontheight(p);
74 dl = dx * fontwidth(p);
75 dr = dl + width * fontwidth(p);
76 dt = dy * fontheight(p);
77 db = dt + height * fontheight(p);
79 /* w is the # pixels between two long-aligned points, left and right */
80 w = (r&~31) - ((l+31)&~31);
81 dw = (dr&~31) - ((dl+31)&~31);
82 /* lo is the # pixels between the left edge and a long-aligned left pixel */
83 lo = ((l+31)&~31) - l;
84 dlo = ((dl+31)&~31) - dl;
86 /* if dx != sx then, logic has to align the left and right edges for fast moves */
87 if (lo != dlo) {
88 lo = ((l+7)&~7) - l;
89 dlo = ((dl+7)&~7) - dl;
90 w = (r&~7) - ((l+7)&~7);
91 dw = (dr&~7) - ((dl+7)&~7);
92 if (lo != dlo) {
93 unsigned char err_str[128];
94 unsigned short err_buf[256];
95 unsigned long cnt, len;
96 sprintf( err_str, "ERROR: Shift algorithm: sx=%d,sy=%d,dx=%d,dy=%d,w=%d,h=%d,bpp=%d",
97 sx,sy,dx,dy,width,height,p->var.bits_per_pixel);
98 len = strlen(err_str);
99 for (cnt = 0; cnt < len; cnt++)
100 err_buf[cnt] = 0x700 | err_str[cnt];
101 fbcon_mac_putcs(p->conp, p, err_buf, len, 0, 0);
102 /* pause for the user */
103 for(cnt = 0; cnt < 50000; cnt++)
104 udelay(100);
105 return;
109 s = 0;
110 switch (p->var.bits_per_pixel) {
111 case 1:
112 s = w >> 3;
113 src += lo >> 3;
114 dest += lo >> 3;
115 break;
116 case 2:
117 s = w >> 2;
118 src += lo >> 2;
119 dest += lo >> 2;
120 break;
121 case 4:
122 s = w >> 1;
123 src += lo >> 1;
124 dest += lo >> 1;
125 break;
126 case 8:
127 s = w;
128 src += lo;
129 dest += lo;
130 break;
131 case 16:
132 s = w << 1;
133 src += lo << 1;
134 dest += lo << 1;
135 break;
136 case 32:
137 s = w << 2;
138 src += lo << 2;
139 dest += lo << 2;
140 break;
143 if (sy <= sx) {
144 i = b;
145 move_up = 0;
146 src += height * fontheight(p);
147 dest += height * fontheight(p);
148 } else {
149 i = t;
150 move_up = 1;
153 while (1) {
154 for (i = t; i < b; i++) {
155 j = l;
157 for (; j & 31 && j < r; j++)
158 plot_pixel_mac(p, get_pixel_mac(p, j+(dx-sx), i+(dy-sy)), j, i);
160 if (j < r) {
161 mymemmove(dest, src, s);
162 if (move_up) {
163 dest += p->next_line;
164 src += p->next_line;
165 } else {
166 dest -= p->next_line;
167 src -= p->next_line;
169 j += w;
172 for (; j < r; j++)
173 plot_pixel_mac(p, get_pixel_mac(p, j+(dx-sx), i+(dy-sy)), j, i);
176 if (move_up) {
177 i++;
178 if (i >= b)
179 break;
180 } else {
181 i--;
182 if (i < t)
183 break;
189 void fbcon_mac_clear(struct vc_data *conp, struct display *p, int sy, int sx,
190 int height, int width)
192 int pixel;
193 int i, j;
194 int inverse;
195 u8 *dest;
196 int l,r,t,b,w,lo,s;
198 inverse = conp ? attr_reverse(p,conp->vc_attr) : 0;
199 pixel = inverse ? PIXEL_WHITE_MAC : PIXEL_BLACK_MAC;
200 dest = (u8 *) (p->screen_base + sy * fontheight(p) * p->next_line);
202 if( sx == 0 && width == p->conp->vc_cols) {
203 s = height * fontheight(p) * p->next_line;
204 if (inverse)
205 mymemclear(dest, s);
206 else
207 mymemset(dest, s);
210 l = sx * fontwidth(p);
211 r = l + width * fontwidth(p);
212 t = sy * fontheight(p);
213 b = t + height * fontheight(p);
214 /* w is the # pixels between two long-aligned points, left and right */
215 w = (r&~31) - ((l+31)&~31);
216 /* lo is the # pixels between the left edge and a long-aligned left pixel */
217 lo = ((l+31)&~31) - l;
218 s = 0;
219 switch (p->var.bits_per_pixel) {
220 case 1:
221 s = w >> 3;
222 dest += lo >> 3;
223 break;
224 case 2:
225 s = w >> 2;
226 dest += lo >> 2;
227 break;
228 case 4:
229 s = w >> 1;
230 dest += lo >> 1;
231 break;
232 case 8:
233 s = w;
234 dest += lo;
235 break;
236 case 16:
237 s = w << 1;
238 dest += lo << 1;
239 break;
240 case 32:
241 s = w << 2;
242 dest += lo << 2;
243 break;
246 for (i = t; i < b; i++) {
247 j = l;
249 for (; j & 31 && j < r; j++)
250 plot_pixel_mac(p, pixel, j, i);
252 if (j < r) {
253 if (PIXEL_WHITE_MAC == pixel)
254 mymemclear(dest, s);
255 else
256 mymemset(dest, s);
257 dest += p->next_line;
258 j += w;
261 for (; j < r; j++)
262 plot_pixel_mac(p, pixel, j, i);
267 void fbcon_mac_putc(struct vc_data *conp, struct display *p, int c, int yy,
268 int xx)
270 u8 *cdat;
271 u_int rows, bold, ch_reverse, ch_underline;
272 u8 d;
273 int j;
275 cdat = p->fontdata+(c&p->charmask)*fontheight(p);
276 bold = attr_bold(p,c);
277 ch_reverse = attr_reverse(p,c);
278 ch_underline = attr_underline(p,c);
280 for (rows = 0; rows < fontheight(p); rows++) {
281 d = *cdat++;
282 if (!conp->vc_can_do_color) {
283 if (ch_underline && rows == (fontheight(p)-2))
284 d = 0xff;
285 else if (bold)
286 d |= d>>1;
287 if (ch_reverse)
288 d = ~d;
290 for (j = 0; j < fontwidth(p); j++) {
291 plot_pixel_mac(p, (d & 0x80) >> 7, (xx*fontwidth(p)) + j, (yy*fontheight(p)) + rows);
292 d <<= 1;
298 void fbcon_mac_putcs(struct vc_data *conp, struct display *p,
299 const unsigned short *s, int count, int yy, int xx)
301 u16 c;
303 while (count--) {
304 c = scr_readw(s++);
305 fbcon_mac_putc(conp, p, c, yy, xx++);
310 void fbcon_mac_revc(struct display *p, int xx, int yy)
312 u_int rows, j;
314 for (rows = 0; rows < fontheight(p); rows++) {
315 for (j = 0; j < fontwidth(p); j++) {
316 plot_pixel_mac (p, PIXEL_INVERT_MAC, (xx*fontwidth(p))+j, (yy*fontheight(p))+rows);
322 * plot_pixel_mac
324 * bw == 0 = black
325 * 1 = white
326 * 2 = invert
328 static void plot_pixel_mac(struct display *p, int bw, int pixel_x, int pixel_y)
330 u8 *dest, bit;
331 u16 *dest16, pix16;
332 u32 *dest32, pix32;
334 if (pixel_x < 0 || pixel_y < 0 || pixel_x >= 832 || pixel_y >= 624) {
335 int cnt;
336 printk ("ERROR: pixel_x == %d, pixel_y == %d", pixel_x, pixel_y);
337 for(cnt = 0; cnt < 100000; cnt++)
338 udelay(100);
339 return;
342 switch (p->var.bits_per_pixel) {
343 case 1:
344 dest = (u8 *) ((pixel_x >> 3) + p->screen_base + pixel_y * p->next_line);
345 bit = 0x80 >> (pixel_x & 7);
346 switch (bw) {
347 case PIXEL_BLACK_MAC:
348 *dest |= bit;
349 break;
350 case PIXEL_WHITE_MAC:
351 *dest &= ~bit;
352 break;
353 case PIXEL_INVERT_MAC:
354 *dest ^= bit;
355 break;
356 default:
357 printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
359 break;
361 case 2:
362 dest = (u8 *) ((pixel_x >> 2) + p->screen_base + pixel_y * p->next_line);
363 bit = 0xC0 >> ((pixel_x & 3) << 1);
364 switch (bw) {
365 case PIXEL_BLACK_MAC:
366 *dest |= bit;
367 break;
368 case PIXEL_WHITE_MAC:
369 *dest &= ~bit;
370 break;
371 case PIXEL_INVERT_MAC:
372 *dest ^= bit;
373 break;
374 default:
375 printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
377 break;
379 case 4:
380 dest = (u8 *) ((pixel_x / 2) + p->screen_base + pixel_y * p->next_line);
381 bit = 0xF0 >> ((pixel_x & 1) << 2);
382 switch (bw) {
383 case PIXEL_BLACK_MAC:
384 *dest |= bit;
385 break;
386 case PIXEL_WHITE_MAC:
387 *dest &= ~bit;
388 break;
389 case PIXEL_INVERT_MAC:
390 *dest ^= bit;
391 break;
392 default:
393 printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
395 break;
397 case 8:
398 dest = (u8 *) (pixel_x + p->screen_base + pixel_y * p->next_line);
399 bit = 0xFF;
400 switch (bw) {
401 case PIXEL_BLACK_MAC:
402 *dest |= bit;
403 break;
404 case PIXEL_WHITE_MAC:
405 *dest &= ~bit;
406 break;
407 case PIXEL_INVERT_MAC:
408 *dest ^= bit;
409 break;
410 default:
411 printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
413 break;
415 case 16:
416 dest16 = (u16 *) ((pixel_x *2) + p->screen_base + pixel_y * p->next_line);
417 pix16 = 0xFFFF;
418 switch (bw) {
419 case PIXEL_BLACK_MAC:
420 *dest16 = ~pix16;
421 break;
422 case PIXEL_WHITE_MAC:
423 *dest16 = pix16;
424 break;
425 case PIXEL_INVERT_MAC:
426 *dest16 ^= pix16;
427 break;
428 default:
429 printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
431 break;
433 case 32:
434 dest32 = (u32 *) ((pixel_x *4) + p->screen_base + pixel_y * p->next_line);
435 pix32 = 0xFFFFFFFF;
436 switch (bw) {
437 case PIXEL_BLACK_MAC:
438 *dest32 = ~pix32;
439 break;
440 case PIXEL_WHITE_MAC:
441 *dest32 = pix32;
442 break;
443 case PIXEL_INVERT_MAC:
444 *dest32 ^= pix32;
445 break;
446 default:
447 printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
449 break;
453 static int get_pixel_mac(struct display *p, int pixel_x, int pixel_y)
455 u8 *dest, bit;
456 u16 *dest16;
457 u32 *dest32;
458 u8 pixel;
460 switch (p->var.bits_per_pixel) {
461 case 1:
462 dest = (u8 *) ((pixel_x / 8) + p->screen_base + pixel_y * p->next_line);
463 bit = 0x80 >> (pixel_x & 7);
464 pixel = *dest & bit;
465 break;
466 case 2:
467 dest = (u8 *) ((pixel_x / 4) + p->screen_base + pixel_y * p->next_line);
468 bit = 0xC0 >> (pixel_x & 3);
469 pixel = *dest & bit;
470 break;
471 case 4:
472 dest = (u8 *) ((pixel_x / 2) + p->screen_base + pixel_y * p->next_line);
473 bit = 0xF0 >> (pixel_x & 1);
474 pixel = *dest & bit;
475 break;
476 case 8:
477 dest = (u8 *) (pixel_x + p->screen_base + pixel_y * p->next_line);
478 pixel = *dest;
479 break;
480 case 16:
481 dest16 = (u16 *) ((pixel_x *2) + p->screen_base + pixel_y * p->next_line);
482 pixel = *dest16 ? 1 : 0;
483 break;
484 case 32:
485 dest32 = (u32 *) ((pixel_x *4) + p->screen_base + pixel_y * p->next_line);
486 pixel = *dest32 ? 1 : 0;
487 break;
490 return pixel ? PIXEL_BLACK_MAC : PIXEL_WHITE_MAC;
495 * `switch' for the low level operations
498 struct display_switch fbcon_mac = {
499 fbcon_mac_setup, fbcon_mac_bmove, fbcon_mac_clear, fbcon_mac_putc,
500 fbcon_mac_putcs, fbcon_mac_revc, NULL, NULL, NULL, FONTWIDTHRANGE(1,8)
504 #ifdef MODULE
505 int init_module(void)
507 return 0;
510 void cleanup_module(void)
512 #endif /* MODULE */
516 * Visible symbols for modules
519 EXPORT_SYMBOL(fbcon_mac);
520 EXPORT_SYMBOL(fbcon_mac_setup);
521 EXPORT_SYMBOL(fbcon_mac_bmove);
522 EXPORT_SYMBOL(fbcon_mac_clear);
523 EXPORT_SYMBOL(fbcon_mac_putc);
524 EXPORT_SYMBOL(fbcon_mac_putcs);
525 EXPORT_SYMBOL(fbcon_mac_revc);