diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1998-04-05 11:23:36 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1998-04-05 11:23:36 +0000 |
commit | 4318fbda2a7ee51caafdc4eb1f8028a3f0605142 (patch) | |
tree | cddb50a81d7d1a628cc400519162080c6d87868e /drivers/video/fbcon.c | |
parent | 36ea5120664550fae6d31f1c6f695e4f8975cb06 (diff) |
o Merge with Linux 2.1.91.
o First round of bugfixes for the SC/MC CPUs.
o FPU context switch fixes.
o Lazy context switches.
o Faster syscalls.
o Removed dead code.
o Shitloads of other things I forgot ...
Diffstat (limited to 'drivers/video/fbcon.c')
-rw-r--r-- | drivers/video/fbcon.c | 571 |
1 files changed, 241 insertions, 330 deletions
diff --git a/drivers/video/fbcon.c b/drivers/video/fbcon.c index 872d77928..a41bf081d 100644 --- a/drivers/video/fbcon.c +++ b/drivers/video/fbcon.c @@ -28,26 +28,17 @@ * The low level operations for the various display memory organizations are * now in separate source files. * - * Currently only the following organizations are supported: + * Currently the following organizations are supported: * - * - non-accelerated: - * - * o mfb Monochrome - * o ilbm Interleaved bitplanes à la Amiga - * o afb Bitplanes à la Amiga - * o iplan2p[248] Interleaved bitplanes à la Atari (2, 4 and 8 planes) - * o cfb{8,16} Packed pixels (8 and 16 bpp) - * - * - accelerated: - * - * o cyber CyberVision64 packed pixels (accelerated) - * o retz3 Retina Z3 packed pixels (accelerated) - * o mach64 ATI Mach 64 packed pixels (accelerated) + * o afb Amiga bitplanes + * o cfb{2,4,8,16,24,32} Packed pixels + * o ilbm Amiga interleaved bitplanes + * o iplan2p[248] Atari interleaved bitplanes + * o mfb Monochrome * * To do: * * - Implement 16 plane mode (iplan2p16) - * - Add support for 24/32 bit packed pixels (cfb{24,32}) * - Hardware cursor * * @@ -56,6 +47,8 @@ * more details. */ +#undef FBCONDEBUG + #define SUPPORT_SCROLLBACK 0 #define FLASHING_CURSOR 1 @@ -65,6 +58,7 @@ #include <linux/sched.h> #include <linux/fs.h> #include <linux/kernel.h> +#include <linux/delay.h> /* MSch: for IRQ probe */ #include <linux/tty.h> #include <linux/console.h> #include <linux/string.h> @@ -74,9 +68,6 @@ #include <linux/vt_kern.h> #include <linux/selection.h> #include <linux/init.h> -#ifdef CONFIG_KMOD -#include <linux/kmod.h> -#endif #include <asm/irq.h> #include <asm/system.h> @@ -88,6 +79,9 @@ #ifdef CONFIG_ATARI #include <asm/atariints.h> #endif +#ifdef CONFIG_MAC +#include <asm/macints.h> +#endif #ifdef __mc68000__ #include <asm/machdep.h> #include <asm/setup.h> @@ -95,8 +89,14 @@ #include <asm/linux_logo.h> #include "fbcon.h" +#include "fbcon-mac.h" /* for 6x11 font on mac */ #include "font.h" +#ifdef FBCONDEBUG +# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) +#else +# define DPRINTK(fmt, args...) +#endif struct display fb_display[MAX_NR_CONSOLES]; @@ -112,6 +112,7 @@ static int cursor_drawn = 0; /* # VBL ints between cursor state changes */ #define AMIGA_CURSOR_BLINK_RATE (20) #define ATARI_CURSOR_BLINK_RATE (42) +#define MAC_CURSOR_BLINK_RATE (32) #define DEFAULT_CURSOR_BLINK_RATE (20) static int vbl_cursor_cnt = 0; @@ -146,26 +147,25 @@ static __inline__ int CURSOR_UNDRAWN(void) static unsigned long fbcon_startup(unsigned long kmem_start, const char **display_desc); static void fbcon_init(struct vc_data *conp); -static int fbcon_deinit(struct vc_data *conp); +static void fbcon_deinit(struct vc_data *conp); static int fbcon_changevar(int con); -static int fbcon_clear(struct vc_data *conp, int sy, int sx, int height, +static void fbcon_clear(struct vc_data *conp, int sy, int sx, int height, int width); -static int fbcon_putc(struct vc_data *conp, int c, int ypos, int xpos); -static int fbcon_putcs(struct vc_data *conp, const char *s, int count, - int ypos, int xpos); -static int fbcon_cursor(struct vc_data *conp, int mode); -static int fbcon_scroll(struct vc_data *conp, int t, int b, - int dir, int count); -static int fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, - int height, int width); +static void fbcon_putc(struct vc_data *conp, int c, int ypos, int xpos); +static void fbcon_putcs(struct vc_data *conp, const char *s, int count, + int ypos, int xpos); +static void fbcon_cursor(struct vc_data *conp, int mode); +static void fbcon_scroll(struct vc_data *conp, int t, int b, int dir, + int count); +static void fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, + int height, int width); static int fbcon_switch(struct vc_data *conp); static int fbcon_blank(int blank); static int fbcon_get_font(struct vc_data *conp, int *w, int *h, char *data); static int fbcon_set_font(struct vc_data *conp, int w, int h, char *data); static int fbcon_set_palette(struct vc_data *conp, unsigned char *table); static int fbcon_scrolldelta(int lines); -int fbcon_register_driver(struct display_switch *dispsw, int is_accel); -int fbcon_unregister_driver(struct display_switch *dispsw); +static int fbcon_set_mode(struct vc_data *conp, int mode); /* @@ -193,16 +193,23 @@ static __inline__ void ypan_down(int unit, struct vc_data *conp, struct display *p, int count); static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy, int dx, int height, int width, u_int y_break); -static struct display_switch *probe_list(struct display_switch *dispsw, - struct display *disp); -#ifdef CONFIG_KMOD -static void request_driver(struct display *disp, int is_accel); -#endif -static struct display_switch *fbcon_get_driver(struct display *disp); static int fbcon_show_logo(void); #if FLASHING_CURSOR + +#ifdef CONFIG_MAC +/* + * On the Macintoy, there may or may not be a working VBL int. We need to prob + */ +static int vbl_detected = 0; + +static void fbcon_vbl_detect(int irq, void *dummy, struct pt_regs *fp) +{ + vbl_detected++; +} +#endif + static void cursor_timer_handler(unsigned long dev_addr); static struct timer_list cursor_timer = { @@ -212,7 +219,7 @@ static struct timer_list cursor_timer = { static void cursor_timer_handler(unsigned long dev_addr) { fbcon_vbl_handler(0, NULL, NULL); - cursor_timer.expires = jiffies+2; + cursor_timer.expires = jiffies+HZ/50; cursor_timer.data = 0; cursor_timer.next = cursor_timer.next = NULL; add_timer(&cursor_timer); @@ -223,49 +230,8 @@ static void cursor_timer_handler(unsigned long dev_addr) * Low Level Operations */ -static struct display_switch dispsw_dummy; +static struct display_switch fbcon_dummy; -#ifdef CONFIG_FBCON_MFB -extern int fbcon_init_mfb(void); -#endif -#ifdef CONFIG_FBCON_ILBM -extern int fbcon_init_ilbm(void); -#endif -#ifdef CONFIG_FBCON_AFB -extern int fbcon_init_afb(void); -#endif -#ifdef CONFIG_FBCON_IPLAN2P2 -extern int fbcon_init_iplan2p2(void); -#endif -#ifdef CONFIG_FBCON_IPLAN2P4 -extern int fbcon_init_iplan2p4(void); -#endif -#ifdef CONFIG_FBCON_IPLAN2P8 -extern int fbcon_init_iplan2p8(void); -#endif -#ifdef CONFIG_FBCON_CFB8 -extern int fbcon_init_cfb8(void); -#endif -#ifdef CONFIG_FBCON_CFB16 -extern int fbcon_init_cfb16(void); -#endif -#ifdef CONFIG_FBCON_CFB24 -extern int fbcon_init_cfb24(void); -#endif -#ifdef CONFIG_FBCON_CFB32 -extern int fbcon_init_cfb32(void); -#endif -#ifdef CONFIG_FBCON_CYBER -extern int fbcon_init_cyber(void); -#endif -#ifdef CONFIG_FBCON_RETINAZ3 -extern int fbcon_init_retz3(void); -#endif -#ifdef CONFIG_FBCON_MACH64 -extern int fbcon_init_mach64(void); -#endif - -extern int num_registered_fb; __initfunc(static unsigned long fbcon_startup(unsigned long kmem_start, const char **display_desc)) @@ -275,49 +241,10 @@ __initfunc(static unsigned long fbcon_startup(unsigned long kmem_start, /* Probe all frame buffer devices */ kmem_start = probe_framebuffers(kmem_start); - if (!num_registered_fb) + if (!num_registered_fb) { + DPRINTK("no framebuffer registered\n"); return kmem_start; - - /* Initialize all built-in low level drivers */ -#ifdef CONFIG_FBCON_RETINAZ3 - fbcon_init_retz3(); -#endif -#ifdef CONFIG_FBCON_MFB - fbcon_init_mfb(); -#endif -#ifdef CONFIG_FBCON_IPLAN2P2 - fbcon_init_iplan2p2(); -#endif -#ifdef CONFIG_FBCON_IPLAN2P4 - fbcon_init_iplan2p4(); -#endif -#ifdef CONFIG_FBCON_IPLAN2P8 - fbcon_init_iplan2p8(); -#endif -#ifdef CONFIG_FBCON_ILBM - fbcon_init_ilbm(); -#endif -#ifdef CONFIG_FBCON_AFB - fbcon_init_afb(); -#endif -#ifdef CONFIG_FBCON_CFB8 - fbcon_init_cfb8(); -#endif -#ifdef CONFIG_FBCON_CFB16 - fbcon_init_cfb16(); -#endif -#ifdef CONFIG_FBCON_CFB24 - fbcon_init_cfb24(); -#endif -#ifdef CONFIG_FBCON_CFB32 - fbcon_init_cfb32(); -#endif -#ifdef CONFIG_FBCON_CYBER - fbcon_init_cyber(); -#endif -#ifdef CONFIG_FBCON_MACH64 - fbcon_init_mach64(); -#endif + } *display_desc = "frame buffer device"; @@ -335,9 +262,49 @@ __initfunc(static unsigned long fbcon_startup(unsigned long kmem_start, "console/cursor", fbcon_vbl_handler); } #endif /* CONFIG_ATARI */ + +#ifdef CONFIG_MAC + /* + * On a Macintoy, the VBL interrupt may or may not be active. + * As interrupt based cursor is more reliable and race free, we + * probe for VBL interrupts. + */ + if (MACH_IS_MAC) { + int ct = 0; + /* + * Probe for VBL: set temp. handler ... + */ + irqres = request_irq(IRQ_MAC_VBL, fbcon_vbl_detect, 0, + "console/cursor", fbcon_vbl_detect); + /* + * ... and spin for 20 ms ... + */ + while (!vbl_detected && ++ct<1000) + udelay(20); + + if(ct==1000) + printk("fbcon_startup: No VBL detected, using timer based cursor.\n"); + + if (vbl_detected) { + /* + * interrupt based cursor ok + */ + cursor_blink_rate = MAC_CURSOR_BLINK_RATE; + irqres = request_irq(IRQ_MAC_VBL, fbcon_vbl_handler, 0, + "console/cursor", fbcon_vbl_handler); + } else { + /* + * VBL not detected: fall through, use timer based cursor + */ + irqres = 1; + /* free interrupt here ?? */ + } + } +#endif /* CONFIG_MAC */ + if (irqres) { cursor_blink_rate = DEFAULT_CURSOR_BLINK_RATE; - cursor_timer.expires = jiffies+2; + cursor_timer.expires = jiffies+HZ/50; cursor_timer.data = 0; cursor_timer.next = cursor_timer.prev = NULL; add_timer(&cursor_timer); @@ -360,22 +327,24 @@ static void fbcon_init(struct vc_data *conp) info->changevar = &fbcon_changevar; fb_display[unit] = *(info->disp); /* copy from default */ + DPRINTK("mode: %s\n",info->modename); + DPRINTK("visual: %d\n",fb_display[unit].visual); + DPRINTK("res: %dx%d-%d\n",fb_display[unit].var.xres, + fb_display[unit].var.yres, + fb_display[unit].var.bits_per_pixel); fb_display[unit].conp = conp; fb_display[unit].fb_info = info; fbcon_setup(unit, 1, 1); } -static int fbcon_deinit(struct vc_data *conp) +static void fbcon_deinit(struct vc_data *conp) { int unit = conp->vc_num; struct display *p = &fb_display[unit]; - if (p->dispsw) - p->dispsw->release(); - p->dispsw = 0; + p->dispsw = NULL; p->conp = 0; - return(0); } @@ -405,7 +374,6 @@ static void fbcon_setup(int con, int setcol, int init) struct display *p = &fb_display[con]; struct vc_data *conp = p->conp; int nr_rows, nr_cols; - struct display_switch *old_dispsw, *new_dispsw; p->var.xoffset = p->var.yoffset = p->yscroll = 0; /* reset wrap/pan */ @@ -415,9 +383,17 @@ static void fbcon_setup(int con, int setcol, int init) getdefaultfont(p->var.xres, p->var.yres, NULL, &p->fontwidth, &p->fontheight, &p->fontdata); if (p->fontwidth != 8) { - /* ++Geert: changed from panic() to `correct and continue' */ - printk(KERN_ERR "fbcon_setup: No support for fontwidth != 8"); - p->fontwidth = 8; +#ifdef CONFIG_MAC + if (MACH_IS_MAC) + /* ++Geert: hack to make 6x11 fonts work on mac */ + p->dispsw = &fbcon_mac; + else +#endif + { + /* ++Geert: changed from panic() to `correct and continue' */ + printk(KERN_ERR "fbcon_setup: No support for fontwidth != 8"); + p->dispsw = &fbcon_dummy; + } } updatescrollmode(p); @@ -435,18 +411,12 @@ static void fbcon_setup(int con, int setcol, int init) p->vrows = p->var.yres_virtual/p->fontheight; conp->vc_can_do_color = p->var.bits_per_pixel != 1; - new_dispsw = fbcon_get_driver(p); - if (!new_dispsw) { + if (!p->dispsw) { printk(KERN_WARNING "fbcon_setup: type %d (aux %d, depth %d) not " "supported\n", p->type, p->type_aux, p->var.bits_per_pixel); - dispsw_dummy.open(p); - new_dispsw = &dispsw_dummy; + p->dispsw = &fbcon_dummy; } - /* Be careful when changing dispsw, it might be the current console. */ - old_dispsw = p->dispsw; - p->dispsw = new_dispsw; - if (old_dispsw) - old_dispsw->release(); + p->dispsw->setup(p); if (setcol) { p->fgcol = p->var.bits_per_pixel > 2 ? 7 : (1<<p->var.bits_per_pixel)-1; @@ -492,15 +462,18 @@ static __inline__ int real_y(struct display *p, int ypos) } -static int fbcon_clear(struct vc_data *conp, int sy, int sx, int height, - int width) +static void fbcon_clear(struct vc_data *conp, int sy, int sx, int height, + int width) { int unit = conp->vc_num; struct display *p = &fb_display[unit]; u_int y_break; if (!p->can_soft_blank && console_blanked) - return(0); + return; + + if (!height || !width) + return; if ((sy <= p->cursor_y) && (p->cursor_y < sy+height) && (sx <= p->cursor_x) && (p->cursor_x < sx+width)) @@ -515,47 +488,41 @@ static int fbcon_clear(struct vc_data *conp, int sy, int sx, int height, p->dispsw->clear(conp, p, real_y(p, sy+b), sx, height-b, width); } else p->dispsw->clear(conp, p, real_y(p, sy), sx, height, width); - - return(0); } -static int fbcon_putc(struct vc_data *conp, int c, int ypos, int xpos) +static void fbcon_putc(struct vc_data *conp, int c, int ypos, int xpos) { int unit = conp->vc_num; struct display *p = &fb_display[unit]; if (!p->can_soft_blank && console_blanked) - return 0; + return; if ((p->cursor_x == xpos) && (p->cursor_y == ypos)) CURSOR_UNDRAWN(); p->dispsw->putc(conp, p, c, real_y(p, ypos), xpos); - - return 0; } -static int fbcon_putcs(struct vc_data *conp, const char *s, int count, +static void fbcon_putcs(struct vc_data *conp, const char *s, int count, int ypos, int xpos) { int unit = conp->vc_num; struct display *p = &fb_display[unit]; if (!p->can_soft_blank && console_blanked) - return 0; + return; if ((p->cursor_y == ypos) && (xpos <= p->cursor_x) && (p->cursor_x < (xpos + count))) CURSOR_UNDRAWN(); p->dispsw->putcs(conp, p, s, count, real_y(p, ypos), xpos); - - return(0); } -static int fbcon_cursor(struct vc_data *conp, int mode) +static void fbcon_cursor(struct vc_data *conp, int mode) { int unit = conp->vc_num; struct display *p = &fb_display[unit]; @@ -563,9 +530,9 @@ static int fbcon_cursor(struct vc_data *conp, int mode) /* Avoid flickering if there's no real change. */ if (p->cursor_x == conp->vc_x && p->cursor_y == conp->vc_y && (mode == CM_ERASE) == !cursor_on) - return 0; + return; if (CURSOR_UNDRAWN ()) - p->dispsw->rev_char(p, p->cursor_x, real_y(p, p->cursor_y)); + p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y)); p->cursor_x = conp->vc_x; p->cursor_y = conp->vc_y; @@ -580,8 +547,6 @@ static int fbcon_cursor(struct vc_data *conp, int mode) cursor_on = 1; break; } - - return(0); } @@ -598,7 +563,7 @@ static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp) * switching code should set vbl_cursor_cnt to an appropriate value. */ p = &fb_display[fg_console]; - p->dispsw->rev_char(p, p->cursor_x, real_y(p, p->cursor_y)); + p->dispsw->revc(p, p->cursor_x, real_y(p, p->cursor_y)); cursor_drawn ^= 1; vbl_cursor_cnt = cursor_blink_rate; } @@ -623,7 +588,7 @@ static __inline__ void ywrap_up(int unit, struct display *p, int count) p->var.xoffset = 0; p->var.yoffset = p->yscroll*p->fontheight; p->var.vmode |= FB_VMODE_YWRAP; - p->fb_info->updatevar(unit); + p->fb_info->updatevar(unit, p->fb_info); #if SUPPORT_SCROLLBACK scrollback_max += count; if (scrollback_max > p->vrows-conp->vc_rows) @@ -646,7 +611,7 @@ static __inline__ void ywrap_down(int unit, struct display *p, int count) p->var.xoffset = 0; p->var.yoffset = p->yscroll*p->fontheight; p->var.vmode |= FB_VMODE_YWRAP; - p->fb_info->updatevar(unit); + p->fb_info->updatevar(unit, p->fb_info); #if SUPPORT_SCROLLBACK scrollback_max -= count; if (scrollback_max < 0) @@ -668,7 +633,7 @@ static __inline__ void ypan_up(int unit, struct vc_data *conp, p->var.xoffset = 0; p->var.yoffset = p->yscroll*p->fontheight; p->var.vmode &= ~FB_VMODE_YWRAP; - p->fb_info->updatevar(unit); + p->fb_info->updatevar(unit, p->fb_info); } @@ -684,17 +649,21 @@ static __inline__ void ypan_down(int unit, struct vc_data *conp, p->var.xoffset = 0; p->var.yoffset = p->yscroll*p->fontheight; p->var.vmode &= ~FB_VMODE_YWRAP; - p->fb_info->updatevar(unit); + p->fb_info->updatevar(unit, p->fb_info); } -static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, int count) +static void fbcon_scroll(struct vc_data *conp, int t, int b, int dir, + int count) { int unit = conp->vc_num; struct display *p = &fb_display[unit]; if (!p->can_soft_blank && console_blanked) - return(0); + return; + + if (!count) + return; fbcon_cursor(conp, CM_ERASE); @@ -822,19 +791,20 @@ static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir, int count) fbcon_clear(conp, 0, t, conp->vc_rows, count); break; } - - return(0); } -static int fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, - int height, int width) +static void fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, + int height, int width) { int unit = conp->vc_num; struct display *p = &fb_display[unit]; if (!p->can_soft_blank && console_blanked) - return(0); + return; + + if (!width || !height) + return; if (((sy <= p->cursor_y) && (p->cursor_y < sy+height) && (sx <= p->cursor_x) && (p->cursor_x < sx+width)) || @@ -850,8 +820,6 @@ static int fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, * over again, so we use fbcon_bmove_rec() */ fbcon_bmove_rec(p, sy, sx, dy, dx, height, width, p->vrows-p->yscroll); - - return(0); } @@ -894,7 +862,7 @@ static int fbcon_switch(struct vc_data *conp) struct fb_info *info = p->fb_info; if (info && info->switch_con) - (*info->switch_con)(conp->vc_num); + (*info->switch_con)(conp->vc_num, info); #if SUPPORT_SCROLLBACK scrollback_max = 0; scrollback_current = 0; @@ -906,11 +874,19 @@ static int fbcon_switch(struct vc_data *conp) static int fbcon_blank(int blank) { struct display *p = &fb_display[fg_console]; + struct fb_info *info = p->fb_info; fbcon_cursor(p->conp, blank ? CM_ERASE : CM_DRAW); if (!p->can_soft_blank) { if (blank) { +#ifdef CONFIG_MAC + if (MACH_IS_MAC) + mymemset(p->screen_base, + p->var.xres_virtual*p->var.yres_virtual* + p->var.bits_per_pixel>>3); + else +#endif if (p->visual == FB_VISUAL_MONO01) mymemset(p->screen_base, p->var.xres_virtual*p->var.yres_virtual* @@ -925,7 +901,7 @@ static int fbcon_blank(int blank) return(1); } } - (*p->fb_info->blank)(blank); + (*info->blank)(blank, info); return(0); } @@ -975,7 +951,7 @@ static int fbcon_set_font(struct vc_data *conp, int w, int h, char *data) copy_from_user( name, data, MAX_FONT_NAME ); name[sizeof(name)-1] = 0; - if (!findsoftfont( name, &w, &h, (u_char **)&data )) + if (!findsoftfont( name, &w, &h, (u8 **)&data )) return( -ENOENT ); userspace = 0; } else if (w == 1) { @@ -1049,9 +1025,9 @@ activate: return( 0 ); } -static unsigned short palette_red[16]; -static unsigned short palette_green[16]; -static unsigned short palette_blue[16]; +static u16 palette_red[16]; +static u16 palette_green[16]; +static u16 palette_blue[16]; static struct fb_cmap palette_cmap = { 0, 16, palette_red, palette_green, palette_blue, NULL @@ -1062,7 +1038,7 @@ static int fbcon_set_palette(struct vc_data *conp, unsigned char *table) int unit = conp->vc_num; struct display *p = &fb_display[unit]; int i, j, k; - u_char val; + u8 val; if (!conp->vc_can_do_color || (!p->can_soft_blank && console_blanked)) return(-EINVAL); @@ -1078,7 +1054,7 @@ static int fbcon_set_palette(struct vc_data *conp, unsigned char *table) palette_cmap.len = 1<<p->var.bits_per_pixel; if (palette_cmap.len > 16) palette_cmap.len = 16; - return(p->fb_info->setcmap(&palette_cmap, unit)); + return p->fb_info->fbops->fb_set_cmap(&palette_cmap, 1, unit, p->fb_info); } static int fbcon_scrolldelta(int lines) @@ -1109,13 +1085,27 @@ static int fbcon_scrolldelta(int lines) p->var.vmode |= FB_VMODE_YWRAP; p->var.xoffset = 0; p->var.yoffset = offset*p->fontheight; - p->fb_info->updatevar(unit); + p->fb_info->updatevar(unit, p->fb_info); #else return -ENOSYS; #endif } + /* + * Switch between `text' (emulated and accelerated) and `graphics' + * (unaccelerated text) mode + */ + +static int fbcon_set_mode(struct vc_data *conp, int mode) +{ + struct display *p = &fb_display[conp->vc_num]; + struct fb_ops *ops = p->fb_info->fbops; + + return ops->fb_set_mode ? ops->fb_set_mode(mode, p->fb_info) : 0; +} + + #define LOGO_H 80 #define LOGO_W 80 #define LOGO_LINE (LOGO_W/8) @@ -1166,7 +1156,8 @@ __initfunc(static int fbcon_show_logo( void )) palette_cmap.green[j] = (green[i+j] << 8) | green[i+j]; palette_cmap.blue[j] = (blue[i+j] << 8) | blue[i+j]; } - p->fb_info->setcmap( &palette_cmap, fg_console ); + p->fb_info->fbops->fb_set_cmap(&palette_cmap, 1, fg_console, + p->fb_info); } fb_display[fg_console].cmap.len = old_cmap_len; } @@ -1184,12 +1175,65 @@ __initfunc(static int fbcon_show_logo( void )) logo_depth = 1; } -#if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CYBER) || \ - defined(CONFIG_FBCON_RETINAZ3) - if ((depth % 8 == 0) && (p->visual == FB_VISUAL_TRUECOLOR || - p->visual == FB_VISUAL_DIRECTCOLOR)) { +#if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB24) || \ + defined(CONFIG_FBCON_CFB32) + if (p->visual == FB_VISUAL_TRUECOLOR) { + unsigned int val; /* max. depth 32! */ + int bdepth; + int redshift, greenshift, blueshift; + + /* Bug: Doesn't obey msb_right ... (who needs that?) */ + redshift = p->var.red.offset; + greenshift = p->var.green.offset; + blueshift = p->var.blue.offset; + + if (depth >= 24 && (depth % 8) == 0) { + /* have at least 8 bits per color */ + src = logo; + bdepth = depth/8; + for( y1 = 0; y1 < LOGO_H; y1++ ) { + dst = fb + y1*line; + for( x1 = 0; x1 < LOGO_W; x1++, src++ ) { + val = ((linux_logo_red[*src] & redmask) << redshift) | + ((linux_logo_green[*src] & greenmask) << greenshift) | + ((linux_logo_blue[*src] & bluemask) << blueshift); + for( i = bdepth-1; i >= 0; --i ) + *dst++ = val >> (i*8); + } + } + } + else if (depth >= 15 && depth <= 23) { + /* have 5..7 bits per color, using 16 color image */ + unsigned int pix; + src = linux_logo16; + bdepth = (depth+7)/8; + for( y1 = 0; y1 < LOGO_H; y1++ ) { + dst = fb + y1*line; + for( x1 = 0; x1 < LOGO_W/2; x1++, src++ ) { + pix = (*src >> 4) | 0x10; /* upper nibble */ + val = (pix << redshift) | + (pix << greenshift) | + (pix << blueshift); + for( i = 0; i < bdepth; ++i ) + *dst++ = val >> (i*8); + pix = (*src & 0x0f) | 0x10; /* lower nibble */ + val = (pix << redshift) | + (pix << greenshift) | + (pix << blueshift); + for( i = bdepth-1; i >= 0; --i ) + *dst++ = val >> (i*8); + } + } + } + + done = 1; + } +#endif +#if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB24) || \ + defined(CONFIG_FBCON_CFB32) + if ((depth % 8 == 0) && (p->visual == FB_VISUAL_DIRECTCOLOR)) { /* Modes without color mapping, needs special data transformation... */ - unsigned long val; /* max. depth 32! */ + unsigned int val; /* max. depth 32! */ int bdepth = depth/8; unsigned char mask[9] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff }; unsigned char redmask, greenmask, bluemask; @@ -1218,8 +1262,7 @@ __initfunc(static int fbcon_show_logo( void )) done = 1; } #endif -#if defined(CONFIG_FBCON_CFB8) || defined(CONFIG_FBCON_CYBER) || \ - defined(CONFIG_FBCON_RETINAZ3) +#if defined(CONFIG_FBCON_CFB8) if (depth == 8 && p->type == FB_TYPE_PACKED_PIXELS) { /* depth 8 or more, packed, with color registers */ @@ -1316,153 +1359,23 @@ struct consw fb_con = { fbcon_startup, fbcon_init, fbcon_deinit, fbcon_clear, fbcon_putc, fbcon_putcs, fbcon_cursor, fbcon_scroll, fbcon_bmove, fbcon_switch, fbcon_blank, fbcon_get_font, fbcon_set_font, fbcon_set_palette, - fbcon_scrolldelta + fbcon_scrolldelta, fbcon_set_mode }; /* - * Driver registration - */ - -static struct display_switch *drivers = NULL, *accel_drivers = NULL; - -int fbcon_register_driver(struct display_switch *dispsw, int is_accel) -{ - struct display_switch **list; - - list = is_accel ? &accel_drivers : &drivers; - dispsw->next = *list; - *list = dispsw; - return 0; -} - -int fbcon_unregister_driver(struct display_switch *dispsw) -{ - struct display_switch **list; - - for (list = &accel_drivers; *list; list = &(*list)->next) - if (*list == dispsw) { - *list = dispsw->next; - dispsw->next = NULL; - return 0; - } - for (list = &drivers; *list; list = &(*list)->next) - if (*list == dispsw) { - *list = dispsw->next; - dispsw->next = NULL; - return 0; - } - return -EINVAL; -} - - -static struct display_switch *probe_list(struct display_switch *dispsw, - struct display *disp) -{ - while (dispsw) { - if (!dispsw->open(disp)) - return(dispsw); - dispsw = dispsw->next; - } - return(NULL); -} - - -#ifdef CONFIG_KMOD -static void request_driver(struct display *disp, int is_accel) -{ - char modname[30]; - int len; - const char *type; - - if (disp->var.bits_per_pixel == 1) - type = "mfb"; - else - switch (disp->type) { - case FB_TYPE_INTERLEAVED_PLANES: - if (disp->type_aux == 2) - type = "iplan2p%d"; - else - type = "ilbm"; - break; - case FB_TYPE_PLANES: - type = "afb"; - break; - case FB_TYPE_PACKED_PIXELS: - type = "cfb%d"; - break; - default: - return; - } - len = sprintf(modname, "fbcon-"); - len += sprintf(modname+len, type, disp->var.bits_per_pixel); - if (is_accel) - len += sprintf(modname+len, "-%d", disp->var.accel); - request_module(modname); -} -#endif /* CONFIG_KMOD */ - - -static struct display_switch *fbcon_get_driver(struct display *disp) -{ - struct display_switch *dispsw; - - if (disp->var.accel != FB_ACCEL_NONE) { - /* First try an accelerated driver */ - dispsw = probe_list(accel_drivers, disp); -#ifdef CONFIG_KMOD - if (!dispsw) { - request_driver(disp, 1); - dispsw = probe_list(accel_drivers, disp); - } -#endif - if (dispsw) - return(dispsw); - } - - /* Then try an unaccelerated driver */ - dispsw = probe_list(drivers, disp); -#ifdef CONFIG_KMOD - if (!dispsw) { - request_driver(disp, 0); - dispsw = probe_list(drivers, disp); - } -#endif - return(dispsw); -} - - -/* * Dummy Low Level Operations */ -static int open_dummy(struct display *p) -{ - if (p->line_length) - p->next_line = p->line_length; - else - p->next_line = p->var.xres_virtual>>3; - p->next_plane = 0; - p->var.bits_per_pixel = 1; - return 0; -} +static void fbcon_dummy_op(void) {} -static void misc_dummy(void) {} - -static struct display_switch dispsw_dummy = { - open_dummy, - /* release_dummy */ - misc_dummy, - /* bmove_dummy */ - (void (*)(struct display *, int, int, int, int, int, int))misc_dummy, - /* clear_dummy */ - (void (*)(struct vc_data *, struct display *, int, int, int, int))misc_dummy, - /* putc_dummy */ - (void (*)(struct vc_data *, struct display *, int, int, int))misc_dummy, - /* putcs_dummy */ - (void (*)(struct vc_data *, struct display *, const char *, int, int, int))misc_dummy, - /* rev_char_dummy */ - (void (*)(struct display *, int, int))misc_dummy, +static struct display_switch fbcon_dummy = { + (void *)fbcon_dummy_op, /* fbcon_dummy_setup */ + (void *)fbcon_dummy_op, /* fbcon_dummy_bmove */ + (void *)fbcon_dummy_op, /* fbcon_dummy_clear */ + (void *)fbcon_dummy_op, /* fbcon_dummy_putc */ + (void *)fbcon_dummy_op, /* fbcon_dummy_putcs */ + (void *)fbcon_dummy_op, /* fbcon_dummy_revc */ }; @@ -1471,5 +1384,3 @@ static struct display_switch dispsw_dummy = { */ EXPORT_SYMBOL(fb_display); -EXPORT_SYMBOL(fbcon_register_driver); -EXPORT_SYMBOL(fbcon_unregister_driver); |