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>
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,
32 static int get_pixel_mac(struct display *p, int pixel_x, int pixel_y);
34 void fbcon_mac_setup(struct display *p)
37 p->next_line = p->line_length;
39 p->next_line = p->var.xres_virtual>>3;
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)
57 int dl,dr,dt,db,dw,dlo;
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 fb_memmove(dest, src, s);
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 */
89 dlo = ((dl+7)&~7) - dl;
90 w = (r&~7) - ((l+7)&~7);
91 dw = (dr&~7) - ((dl+7)&~7);
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 printk( "ERROR: shift algorithm...\n" );
110 switch (p->var.bits_per_pixel) {
146 src += height * fontheight(p);
147 dest += height * fontheight(p);
154 for (i = t; i < b; i++) {
157 for (; j & 31 && j < r; j++)
158 plot_pixel_mac(p, get_pixel_mac(p, j+(dx-sx), i+(dy-sy)), j, i);
161 fb_memmove(dest, src, s);
163 dest += p->next_line;
166 dest -= p->next_line;
173 plot_pixel_mac(p, get_pixel_mac(p, j+(dx-sx), i+(dy-sy)), j, i);
189 void fbcon_mac_clear(struct vc_data *conp, struct display *p, int sy, int sx,
190 int height, int width)
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;
205 fb_memclear(dest, s);
207 fb_memset255(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;
219 switch (p->var.bits_per_pixel) {
246 for (i = t; i < b; i++) {
249 for (; j & 31 && j < r; j++)
250 plot_pixel_mac(p, pixel, j, i);
253 if (PIXEL_WHITE_MAC == pixel)
254 fb_memclear(dest, s);
256 fb_memset255(dest, s);
257 dest += p->next_line;
262 plot_pixel_mac(p, pixel, j, i);
267 void fbcon_mac_putc(struct vc_data *conp, struct display *p, int c, int yy,
271 u_int rows, bold, ch_reverse, ch_underline;
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++) {
282 if (!conp->vc_can_do_color) {
283 if (ch_underline && rows == (fontheight(p)-2))
290 for (j = 0; j < fontwidth(p); j++) {
291 plot_pixel_mac(p, (d & 0x80) >> 7, (xx*fontwidth(p)) + j, (yy*fontheight(p)) + rows);
298 void fbcon_mac_putcs(struct vc_data *conp, struct display *p,
299 const unsigned short *s, int count, int yy, int xx)
305 fbcon_mac_putc(conp, p, c, yy, xx++);
310 void fbcon_mac_revc(struct display *p, int xx, int yy)
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);
321 static inline void plot_helper(u8 *dest, u8 bit, int bw)
324 case PIXEL_BLACK_MAC:
325 fb_writeb( fb_readb(dest) | bit, dest );
327 case PIXEL_WHITE_MAC:
328 fb_writeb( fb_readb(dest) & (~bit), dest );
330 case PIXEL_INVERT_MAC:
331 fb_writeb( fb_readb(dest) ^ bit, dest );
334 printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
341 static void plot_pixel_mac(struct display *p, int bw, int pixel_x, int pixel_y)
347 /* There *are* 68k Macs that support more than 832x624, you know :-) */
348 if (pixel_x < 0 || pixel_y < 0 || pixel_x >= p->var.xres || pixel_y >= p->var.yres) {
349 printk ("ERROR: pixel_x == %d, pixel_y == %d", pixel_x, pixel_y);
354 switch (p->var.bits_per_pixel) {
356 dest = (u8 *) ((pixel_x >> 3) + p->screen_base + pixel_y * p->next_line);
357 bit = 0x80 >> (pixel_x & 7);
358 plot_helper(dest, bit, bw);
362 dest = (u8 *) ((pixel_x >> 2) + p->screen_base + pixel_y * p->next_line);
363 bit = 0xC0 >> ((pixel_x & 3) << 1);
364 plot_helper(dest, bit, bw);
368 dest = (u8 *) ((pixel_x >> 1) + p->screen_base + pixel_y * p->next_line);
369 bit = 0xF0 >> ((pixel_x & 1) << 2);
370 plot_helper(dest, bit, bw);
374 dest = (u8 *) (pixel_x + p->screen_base + pixel_y * p->next_line);
376 plot_helper(dest, bit, bw);
379 /* FIXME: You can't access framebuffer directly like this! */
381 dest16 = (u16 *) ((pixel_x *2) + p->screen_base + pixel_y * p->next_line);
384 case PIXEL_BLACK_MAC: *dest16 = ~pix16; break;
385 case PIXEL_WHITE_MAC: *dest16 = pix16; break;
386 case PIXEL_INVERT_MAC: *dest16 ^= pix16; break;
387 default: printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
392 dest32 = (u32 *) ((pixel_x *4) + p->screen_base + pixel_y * p->next_line);
395 case PIXEL_BLACK_MAC: *dest32 = ~pix32; break;
396 case PIXEL_WHITE_MAC: *dest32 = pix32; break;
397 case PIXEL_INVERT_MAC: *dest32 ^= pix32; break;
398 default: printk( "ERROR: Unknown pixel value in plot_pixel_mac\n");
404 static int get_pixel_mac(struct display *p, int pixel_x, int pixel_y)
411 switch (p->var.bits_per_pixel) {
413 dest = (u8 *) ((pixel_x / 8) + p->screen_base + pixel_y * p->next_line);
414 bit = 0x80 >> (pixel_x & 7);
418 dest = (u8 *) ((pixel_x / 4) + p->screen_base + pixel_y * p->next_line);
419 bit = 0xC0 >> (pixel_x & 3);
423 dest = (u8 *) ((pixel_x / 2) + p->screen_base + pixel_y * p->next_line);
424 bit = 0xF0 >> (pixel_x & 1);
428 dest = (u8 *) (pixel_x + p->screen_base + pixel_y * p->next_line);
432 dest16 = (u16 *) ((pixel_x *2) + p->screen_base + pixel_y * p->next_line);
433 pixel = *dest16 ? 1 : 0;
436 dest32 = (u32 *) ((pixel_x *4) + p->screen_base + pixel_y * p->next_line);
437 pixel = *dest32 ? 1 : 0;
441 return pixel ? PIXEL_BLACK_MAC : PIXEL_WHITE_MAC;
446 * `switch' for the low level operations
449 struct display_switch fbcon_mac = {
450 setup: fbcon_mac_setup,
451 bmove: fbcon_redraw_bmove,
452 clear: fbcon_redraw_clear,
453 putc: fbcon_mac_putc,
454 putcs: fbcon_mac_putcs,
455 revc: fbcon_mac_revc,
456 fontwidthmask: FONTWIDTHRANGE(1,8)
461 MODULE_LICENSE("GPL");
463 int init_module(void)
468 void cleanup_module(void)
474 * Visible symbols for modules
477 EXPORT_SYMBOL(fbcon_mac);
478 EXPORT_SYMBOL(fbcon_mac_setup);
479 EXPORT_SYMBOL(fbcon_mac_bmove);
480 EXPORT_SYMBOL(fbcon_mac_clear);
481 EXPORT_SYMBOL(fbcon_mac_putc);
482 EXPORT_SYMBOL(fbcon_mac_putcs);
483 EXPORT_SYMBOL(fbcon_mac_revc);