diff options
Diffstat (limited to 'drivers/video')
55 files changed, 14726 insertions, 3792 deletions
diff --git a/drivers/video/Config.in b/drivers/video/Config.in index e39e33bfc..b4766876b 100644 --- a/drivers/video/Config.in +++ b/drivers/video/Config.in @@ -7,43 +7,70 @@ if [ "$CONFIG_FB" = "y" ]; then mainmenu_option next_comment comment 'Frame buffer devices' - if [ "$CONFIG_AMIGA" = "y" ]; then + if [ "$CONFIG_APOLLO" = "y" ]; then + define_bool CONFIG_FB_APOLLO y + fi + if [ "$CONFIG_AMIGA" = "y" ]; then bool 'Amiga native chipset support' CONFIG_FB_AMIGA if [ "$CONFIG_FB_AMIGA" != "n" ]; then bool 'Amiga OCS chipset support' CONFIG_FB_AMIGA_OCS bool 'Amiga ECS chipset support' CONFIG_FB_AMIGA_ECS bool 'Amiga AGA chipset support' CONFIG_FB_AMIGA_AGA fi - tristate 'Amiga Cybervision support' CONFIG_FB_CYBER + tristate 'Amiga CyberVision support' CONFIG_FB_CYBER if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool 'Amiga CyberVision3D support (experimental)' CONFIG_FB_VIRGE tristate 'Amiga RetinaZ3 support' CONFIG_FB_RETINAZ3 fi fi if [ "$CONFIG_ATARI" = "y" ]; then bool 'Atari native chipset support' CONFIG_FB_ATARI -# tristate 'Mach64 Frame Buffer support' CONFIG_FB_MACH64 + bool 'ATI Mach64 display support' CONFIG_FB_ATY + fi + if [ "$CONFIG_PPC" = "y" ]; then + bool 'Open Firmware frame buffer device support' CONFIG_FB_OF + bool 'S3 Trio frame buffer device support' CONFIG_FB_S3TRIO + if [ "$CONFIG_FB_OF" = "y" ]; then +# bool 'Apple "control" display support' CONFIG_FB_CONTROL +# bool 'Apple "platinum" display support' CONFIG_FB_PLATINUM +# bool 'Apple "valkyrie" display support' CONFIG_FB_VALKYRIE + bool 'ATI Mach64 display support' CONFIG_FB_ATY +# bool 'IMS Twin Turbo display support' CONFIG_FB_IMSTT +# bool 'Chips 65550 display support' CONFIG_FB_CT65550 +# bool 'S3 Trio display support' CONFIG_FB_S3TRIO + fi + fi + if [ "$CONFIG_MAC" = "y" ]; then + define_bool CONFIG_FB_MAC y + fi + if [ "$CONFIG_TGA_CONSOLE" = "y" ]; then + define_bool CONFIG_FB_TGA y fi - if [ "$CONFIG_CHRP" = "y" -o "$CONFIG_PMAC" = "y" ]; then - bool 'Open Firmware frame buffer device support' CONFIG_FB_OPEN_FIRMWARE - fi - tristate 'Virtual Frame Buffer support' CONFIG_FB_VIRTUAL + tristate 'Virtual Frame Buffer support (ONLY FOR TESTING!)' CONFIG_FB_VIRTUAL bool 'Advanced low level driver options' CONFIG_FBCON_ADVANCED if [ "$CONFIG_FBCON_ADVANCED" = "y" ]; then - tristate 'Monochrome support' CONFIG_FBCON_MFB - tristate 'Interleaved bitplanes support' CONFIG_FBCON_ILBM - tristate 'Normal bitplanes support' CONFIG_FBCON_AFB - tristate 'Atari interleaved bitplanes (2 planes) support' CONFIG_FBCON_IPLAN2P2 - tristate 'Atari interleaved bitplanes (4 planes) support' CONFIG_FBCON_IPLAN2P4 - tristate 'Atari interleaved bitplanes (8 planes) support' CONFIG_FBCON_IPLAN2P8 - tristate '8 bpp packed pixel support' CONFIG_FBCON_CFB8 - tristate '16 bpp packed pixel support' CONFIG_FBCON_CFB16 - tristate 'Cybervision support (accelerated)' CONFIG_FBCON_CYBER - tristate 'RetinaZ3 support (accelerated)' CONFIG_FBCON_RETINAZ3 + bool 'Monochrome support' CONFIG_FBCON_MFB + bool '2 bpp packed pixels support' CONFIG_FBCON_CFB2 + bool '4 bpp packed pixels support' CONFIG_FBCON_CFB4 + bool '8 bpp packed pixels support' CONFIG_FBCON_CFB8 + bool '16 bpp packed pixels support' CONFIG_FBCON_CFB16 + bool '24 bpp packed pixels support' CONFIG_FBCON_CFB24 + bool '32 bpp packed pixels support' CONFIG_FBCON_CFB32 + bool 'Amiga bitplanes support' CONFIG_FBCON_AFB + bool 'Amiga interleaved bitplanes support' CONFIG_FBCON_ILBM + bool 'Atari interleaved bitplanes (2 planes) support' CONFIG_FBCON_IPLAN2P2 + bool 'Atari interleaved bitplanes (4 planes) support' CONFIG_FBCON_IPLAN2P4 + bool 'Atari interleaved bitplanes (8 planes) support' CONFIG_FBCON_IPLAN2P8 + bool 'Mac variable bpp packed pixels support' CONFIG_FBCON_MAC else - if [ "$CONFIG_FB_AMIGA" != "n" -o "$CONFIG_FB_ATARI" != "n" -o \ - "$CONFIG_FB_CYBER" != "n" -o "$CONFIG_FB_RETINAZ3" != "n" -o \ - "$CONFIG_FB_VIRTUAL" != "n" ]; then + if [ "$CONFIG_FB_AMIGA" = "y" -o "$CONFIG_FB_AMIGA" = "m" -o \ + "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATARI" = "m" -o \ + "$CONFIG_FB_CYBER" = "y" -o "$CONFIG_FB_CYBER" = "m" -o \ + "$CONFIG_FB_RETINAZ3" = "y" -o "$CONFIG_FB_RETINAZ3" = "m" -o \ + "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_VIRGE" = "m" -o \ + "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_MAC" = "m" -o \ + "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_VIRTUAL" = "m" ]; then define_bool CONFIG_FBCON_MFB y fi if [ "$CONFIG_FB_AMIGA" = "y" -o "$CONFIG_FB_AMIGA" = "m" ]; then @@ -55,20 +82,32 @@ if [ "$CONFIG_FB" = "y" ]; then define_bool CONFIG_FBCON_IPLAN2P4 y define_bool CONFIG_FBCON_IPLAN2P8 y fi + if [ "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_MAC" = "m" -o \ + "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_VIRTUAL" = "m" ]; then + define_bool CONFIG_FBCON_MAC y + define_bool CONFIG_FBCON_CFB2 y + define_bool CONFIG_FBCON_CFB4 y + fi if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATARI" = "m" -o \ - "$CONFIG_FB_OPEN_FIRMWARE" = "y" -o \ + "$CONFIG_FB_OF" = "y" -o "$CONFIG_FB_OF" = "m" -o \ + "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_MAC" = "m" -o \ + "$CONFIG_FB_TGA" = "y" -o "$CONFIG_FB_TGA" = "m" -o \ "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_VIRTUAL" = "m" ]; then define_bool CONFIG_FBCON_CFB8 y fi if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATARI" = "m" -o \ + "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_ATY" = "m" -o \ + "$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_MAC" = "m" -o \ "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_VIRTUAL" = "m" ]; then define_bool CONFIG_FBCON_CFB16 y fi - if [ "$CONFIG_FB_CYBER" = "y" -o "$CONFIG_FB_CYBER" = "m" ]; then - define_bool CONFIG_FBCON_CYBER y + if [ "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_VIRTUAL" = "m" ]; then + define_bool CONFIG_FBCON_CFB24 y fi - if [ "$CONFIG_FB_RETINAZ3" = "y" -o "$CONFIG_FB_RETINAZ3" = "m" ]; then - define_bool CONFIG_FBCON_RETINAZ3 y + if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATARI" = "m" -o \ + "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_ATY" = "m" -o \ + "$CONFIG_FB_VIRTUAL" = "y" -o "$CONFIG_FB_VIRTUAL" = "m" ]; then + define_bool CONFIG_FBCON_CFB32 y fi fi diff --git a/drivers/video/Makefile b/drivers/video/Makefile index ebed69d68..2349e4720 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -22,15 +22,11 @@ MOD_LIST_NAME := VIDEO_MODULES # Frame Buffer Console ifeq ($(CONFIG_FB),y) - L_OBJS += fonts.o font_8x8.o font_8x16.o pearl_8x8.o - LX_OBJS += fbcon.o fbcmap.o + L_OBJS += fonts.o font_8x8.o font_8x16.o pearl_8x8.o font_6x11.o + LX_OBJS += fbcon.o fbcmap.o fbgen.o endif -# Frame buffer devices - -ifeq ($(CONFIG_APOLLO),y) -L_OBJS += dn_fb.o -endif +# Frame Buffer Devices ifeq ($(CONFIG_FB_AMIGA),y) L_OBJS += amifb.o @@ -40,6 +36,10 @@ else endif endif +ifeq ($(CONFIG_FB_APOLLO),y) +L_OBJS += dnfb.o +endif + ifeq ($(CONFIG_FB_ATARI),y) L_OBJS += atafb.o else @@ -48,134 +48,114 @@ else endif endif +ifeq ($(CONFIG_FB_ATY),y) +L_OBJS += atyfb.o +endif + ifeq ($(CONFIG_FB_CYBER),y) -LX_OBJS += cyberfb.o +L_OBJS += cyberfb.o else ifeq ($(CONFIG_FB_CYBER),m) - MX_OBJS += cyberfb.o + M_OBJS += cyberfb.o endif endif +ifeq ($(CONFIG_FB_MAC),y) +L_OBJS += macfb.o +endif + +ifeq ($(CONFIG_FB_OF),y) +L_OBJS += offb.o +endif + ifeq ($(CONFIG_FB_RETINAZ3),y) -LX_OBJS += retz3fb.o +L_OBJS += retz3fb.o else ifeq ($(CONFIG_FB_RETINAZ3),m) - MX_OBJS += retz3fb.o + M_OBJS += retz3fb.o endif endif -ifeq ($(CONFIG_FB_VIRTUAL),y) -L_OBJS += vfb.o +ifeq ($(CONFIG_FB_S3TRIO),y) +L_OBJS += S3triofb.o else - ifeq ($(CONFIG_FB_VIRTUAL),m) - M_OBJS += vfb.o + ifeq ($(CONFIG_FB_S3TRIO),m) + M_OBJS += S3triofb.o endif endif -ifeq ($(CONFIG_FB_OPEN_FIRMWARE),y) -L_OBJS += offb.o +ifeq ($(CONFIG_FB_TGA),y) +L_OBJS += tgafb.o endif -ifeq ($(CONFIG_FB_MACH64),y) -L_OBJS += mach64fb.o +ifeq ($(CONFIG_FB_VIRGE),y) +L_OBJS += virgefb.o else - ifeq ($(CONFIG_FB_MACH64),m) - M_OBJS += mach64fb.o + ifeq ($(CONFIG_FB_VIRGE),m) + M_OBJS += virgefb.o endif endif -ifeq ($(CONFIG_FB_TGA),y) -L_OBJS += tgafb.o +ifeq ($(CONFIG_FB_VIRTUAL),y) +L_OBJS += vfb.o +else + ifeq ($(CONFIG_FB_VIRTUAL),m) + M_OBJS += vfb.o + endif endif -# Low level drivers +# Generic Low Level Drivers -ifeq ($(CONFIG_FBCON_AFB),y) -L_OBJS += fbcon-afb.o -else - ifeq ($(CONFIG_FBCON_AFB),m) - M_OBJS += fbcon-afb.o - endif +ifdef CONFIG_FBCON_AFB +LX_OBJS += fbcon-afb.o endif -ifeq ($(CONFIG_FBCON_CFB8),y) -L_OBJS += fbcon-cfb8.o -else - ifeq ($(CONFIG_FBCON_CFB8),m) - M_OBJS += fbcon-cfb8.o - endif +ifdef CONFIG_FBCON_CFB2 +LX_OBJS += fbcon-cfb2.o endif -ifeq ($(CONFIG_FBCON_CFB16),y) +ifdef CONFIG_FBCON_CFB4 +LX_OBJS += fbcon-cfb4.o +endif + +ifdef CONFIG_FBCON_CFB8 +LX_OBJS += fbcon-cfb8.o +endif + +ifdef CONFIG_FBCON_CFB16 LX_OBJS += fbcon-cfb16.o -else - ifeq ($(CONFIG_FBCON_CFB16),m) - MX_OBJS += fbcon-cfb16.o - endif endif -ifeq ($(CONFIG_FBCON_ILBM),y) -L_OBJS += fbcon-ilbm.o -else - ifeq ($(CONFIG_FBCON_ILBM),m) - M_OBJS += fbcon-ilbm.o - endif +ifdef CONFIG_FBCON_CFB24 +LX_OBJS += fbcon-cfb24.o endif -ifeq ($(CONFIG_FBCON_IPLAN2P2),y) -L_OBJS += fbcon-iplan2p2.o -else - ifeq ($(CONFIG_FBCON_IPLAN2P2),m) - M_OBJS += fbcon-iplan2p2.o - endif +ifdef CONFIG_FBCON_CFB32 +LX_OBJS += fbcon-cfb32.o endif -ifeq ($(CONFIG_FBCON_IPLAN2P4),y) -L_OBJS += fbcon-iplan2p4.o -else - ifeq ($(CONFIG_FBCON_IPLAN2P4),m) - M_OBJS += fbcon-iplan2p4.o - endif +ifdef CONFIG_FBCON_ILBM +LX_OBJS += fbcon-ilbm.o endif -ifeq ($(CONFIG_FBCON_IPLAN2P8),y) -L_OBJS += fbcon-iplan2p8.o -else - ifeq ($(CONFIG_FBCON_IPLAN2P8),m) - M_OBJS += fbcon-iplan2p8.o - endif +ifdef CONFIG_FBCON_IPLAN2P2 +LX_OBJS += fbcon-iplan2p2.o endif -ifeq ($(CONFIG_FBCON_MFB),y) -L_OBJS += fbcon-mfb.o -else - ifeq ($(CONFIG_FBCON_MFB),m) - M_OBJS += fbcon-mfb.o - endif +ifdef CONFIG_FBCON_IPLAN2P4 +LX_OBJS += fbcon-iplan2p4.o endif -ifeq ($(CONFIG_FBCON_CYBER),y) -L_OBJS += fbcon-cyber.o -else - ifeq ($(CONFIG_FBCON_CYBER),m) - M_OBJS += fbcon-cyber.o - endif +ifdef CONFIG_FBCON_IPLAN2P8 +LX_OBJS += fbcon-iplan2p8.o endif -ifeq ($(CONFIG_FBCON_RETINAZ3),y) -L_OBJS += fbcon-retz3.o -else - ifeq ($(CONFIG_FBCON_RETINAZ3),m) - M_OBJS += fbcon-retz3.o - endif +ifdef CONFIG_FBCON_MAC +LX_OBJS += fbcon-mac.o endif -ifeq ($(CONFIG_FBCON_MACH64),y) -L_OBJS += fbcon-mach64.o -else - ifeq ($(CONFIG_FBCON_MACH64),m) - M_OBJS += fbcon-mach64.o - endif +ifdef CONFIG_FBCON_MFB +LX_OBJS += fbcon-mfb.o endif # GSP Console @@ -184,7 +164,7 @@ ifdef CONFIG_AMIGA_GSP L_OBJS := $(L_OBJS) gspcon.o gspcore.o endif -# VGA Console +# VGA Text Console ifdef CONFIG_ABSTRACT_CONSOLE ifdef CONFIG_VGA_CONSOLE diff --git a/drivers/video/S3triofb.c b/drivers/video/S3triofb.c new file mode 100644 index 000000000..16c0b888a --- /dev/null +++ b/drivers/video/S3triofb.c @@ -0,0 +1,885 @@ +/* + * linux/drivers/video/S3Triofb.c -- Open Firmware based frame buffer device + * + * Copyright (C) 1997 Peter De Schrijver + * + * This driver is partly based on the PowerMac console driver: + * + * Copyright (C) 1996 Paul Mackerras + * + * and on the Open Firmware based frame buffer device: + * + * Copyright (C) 1997 Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +/* + Bugs : + OF dependencies should be removed. + + This driver should be merged with the CyberVision driver. The + CyberVision is a Zorro III implementation of the S3Trio64 chip. + +*/ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/tty.h> +#include <linux/malloc.h> +#include <linux/vmalloc.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <asm/io.h> +#include <asm/prom.h> +#include <linux/pci.h> + +#include "fbcon-cfb8.h" + + +#define mem_in8(addr) in_8((void *)(addr)) +#define mem_in16(addr) in_le16((void *)(addr)) +#define mem_in32(addr) in_le32((void *)(addr)) + +#define mem_out8(val, addr) out_8((void *)(addr), val) +#define mem_out16(val, addr) out_le16((void *)(addr), val) +#define mem_out32(val, addr) out_le32((void *)(addr), val) + +#define IO_OUT16VAL(v, r) (((v) << 8) | (r)) + +#define arraysize(x) (sizeof(x)/sizeof(*(x))) + +static int currcon = 0; +static struct display disp; +static struct fb_info fb_info; +static struct { u_char red, green, blue, pad; } palette[256]; +static char s3trio_name[16] = "S3Trio "; + + +static struct fb_fix_screeninfo fb_fix; +static struct fb_var_screeninfo fb_var = { 0, }; + + + /* + * Interface used by the world + */ + +void of_video_setup(char *options, int *ints); + +static int s3trio_open(struct fb_info *info); +static int s3trio_release(struct fb_info *info); +static int s3trio_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info); +static int s3trio_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int s3trio_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int s3trio_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int s3trio_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int s3trio_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int s3trio_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info); + +#ifdef CONFIG_FB_COMPAT_XPMAC +extern struct vc_mode display_info; +extern struct fb_info *console_fb_info; +extern int (*console_setmode_ptr)(struct vc_mode *, int); +extern int (*console_set_cmap_ptr)(struct fb_cmap *, int, int, + struct fb_info *); +static int s3trio_console_setmode(struct vc_mode *mode, int doit); +#endif /* CONFIG_FB_COMPAT_XPMAC */ + + /* + * Interface to the low level console driver + */ + +unsigned long s3trio_fb_init(unsigned long mem_start); +static int s3triofbcon_switch(int con, struct fb_info *info); +static int s3triofbcon_updatevar(int con, struct fb_info *info); +static void s3triofbcon_blank(int blank, struct fb_info *info); +static int s3triofbcon_setcmap(struct fb_cmap *cmap, int con); + + /* + * Text console acceleration + */ + +#ifdef CONFIG_FBCON_CFB8 +static struct display_switch fbcon_trio8; +#endif + + /* + * Accelerated Functions used by the low level console driver + */ + +static void Trio_WaitQueue(u_short fifo); +static void Trio_WaitBlit(void); +static void Trio_BitBLT(u_short curx, u_short cury, u_short destx, + u_short desty, u_short width, u_short height, + u_short mode); +static void Trio_RectFill(u_short x, u_short y, u_short width, u_short height, + u_short mode, u_short color); +static void Trio_MoveCursor(u_short x, u_short y); + + + /* + * Internal routines + */ + +static int s3trio_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, + u_int *transp, struct fb_info *info); +static int s3trio_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info); +static void do_install_cmap(int con); + + +static struct fb_ops s3trio_ops = { + s3trio_open, s3trio_release, s3trio_get_fix, s3trio_get_var, s3trio_set_var, + s3trio_get_cmap, s3trio_set_cmap, s3trio_pan_display, NULL, s3trio_ioctl +}; + + + /* + * Open/Release the frame buffer device + */ + +static int s3trio_open(struct fb_info *info) +{ + /* + * Nothing, only a usage count for the moment + */ + + MOD_INC_USE_COUNT; + return(0); +} + +static int s3trio_release(struct fb_info *info) +{ + MOD_DEC_USE_COUNT; + return(0); +} + + + /* + * Get the Fixed Part of the Display + */ + +static int s3trio_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) +{ + memcpy(fix, &fb_fix, sizeof(fb_fix)); + return 0; +} + + + /* + * Get the User Defined Part of the Display + */ + +static int s3trio_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + memcpy(var, &fb_var, sizeof(fb_var)); + return 0; +} + + + /* + * Set the User Defined Part of the Display + */ + +static int s3trio_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + if (var->xres > fb_var.xres || var->yres > fb_var.yres || + var->xres_virtual > fb_var.xres_virtual || + var->yres_virtual > fb_var.yres_virtual || + var->bits_per_pixel > fb_var.bits_per_pixel || + var->nonstd || var->vmode != FB_VMODE_NONINTERLACED) + return -EINVAL; + memcpy(var, &fb_var, sizeof(fb_var)); + return 0; +} + + + /* + * Pan or Wrap the Display + * + * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag + */ + +static int s3trio_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + if (var->xoffset || var->yoffset) + return -EINVAL; + else + return 0; +} + + /* + * Get the Colormap + */ + +static int s3trio_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + if (con == currcon) /* current console? */ + return fb_get_cmap(cmap, &fb_display[con].var, kspc, s3trio_getcolreg, + info); + else if (fb_display[con].cmap.len) /* non default colormap? */ + fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); + else + fb_copy_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), + cmap, kspc ? 0 : 2); + return 0; +} + + /* + * Set the Colormap + */ + +static int s3trio_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + int err; + + + if (!fb_display[con].cmap.len) { /* no colormap allocated? */ + if ((err = fb_alloc_cmap(&fb_display[con].cmap, + 1<<fb_display[con].var.bits_per_pixel, 0))) + return err; + } + if (con == currcon) /* current console? */ + return fb_set_cmap(cmap, &fb_display[con].var, kspc, s3trio_setcolreg, + info); + else + fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); + return 0; +} + + +static int s3trio_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info) +{ + return -EINVAL; +} + +__initfunc(int s3trio_resetaccel(void)) { + + +#define EC01_ENH_ENB 0x0005 +#define EC01_LAW_ENB 0x0010 +#define EC01_MMIO_ENB 0x0020 + +#define EC00_RESET 0x8000 +#define EC00_ENABLE 0x4000 +#define MF_MULT_MISC 0xE000 +#define SRC_FOREGROUND 0x0020 +#define SRC_BACKGROUND 0x0000 +#define MIX_SRC 0x0007 +#define MF_T_CLIP 0x1000 +#define MF_L_CLIP 0x2000 +#define MF_B_CLIP 0x3000 +#define MF_R_CLIP 0x4000 +#define MF_PIX_CONTROL 0xA000 +#define MFA_SRC_FOREGR_MIX 0x0000 +#define MF_PIX_CONTROL 0xA000 + + outw(EC00_RESET, 0x42e8); + inw( 0x42e8); + outw(EC00_ENABLE, 0x42e8); + inw( 0x42e8); + outw(EC01_ENH_ENB | EC01_LAW_ENB, + 0x4ae8); + outw(MF_MULT_MISC, 0xbee8); /* 16 bit I/O registers */ + + /* Now set some basic accelerator registers */ + Trio_WaitQueue(0x0400); + outw(SRC_FOREGROUND | MIX_SRC, 0xbae8); + outw(SRC_BACKGROUND | MIX_SRC, 0xb6e8);/* direct color*/ + outw(MF_T_CLIP | 0, 0xbee8 ); /* clip virtual area */ + outw(MF_L_CLIP | 0, 0xbee8 ); + outw(MF_R_CLIP | (640 - 1), 0xbee8); + outw(MF_B_CLIP | (480 - 1), 0xbee8); + Trio_WaitQueue(0x0400); + outw(0xffff, 0xaae8); /* Enable all planes */ + outw(0xffff, 0xaae8); /* Enable all planes */ + outw( MF_PIX_CONTROL | MFA_SRC_FOREGR_MIX, 0xbee8); + +} + +__initfunc(int s3trio_init(void)) { + + u_char bus, dev; + unsigned int t32; + unsigned short cmd; + int i; + + bus=0; + dev=(3<<3); + pcibios_read_config_dword(bus, dev, PCI_VENDOR_ID, &t32); + if(t32 == (PCI_DEVICE_ID_S3_TRIO << 16) + PCI_VENDOR_ID_S3) { + pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_0, &t32); + pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_1, &t32); + pcibios_read_config_word(bus, dev, PCI_COMMAND,&cmd); + + pcibios_write_config_word(bus, dev, PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY); + + pcibios_write_config_dword(bus, dev, PCI_BASE_ADDRESS_0,0xffffffff); + pcibios_read_config_dword(bus, dev, PCI_BASE_ADDRESS_0, &t32); + +/* This is a gross hack as OF only maps enough memory for the framebuffer and + we want to use MMIO too. We should find out which chunk of address space + we can use here */ + pcibios_write_config_dword(bus,dev,PCI_BASE_ADDRESS_0,0xc6000000); + + /* unlock s3 */ + + outb(0x01, 0x3C3); + + outb(inb(0x03CC) | 1, 0x3c2); + + outw(IO_OUT16VAL(0x48, 0x38),0x03D4); + outw(IO_OUT16VAL(0xA0, 0x39),0x03D4); + outb(0x33,0x3d4); + outw(IO_OUT16VAL( inb(0x3d5) & ~(0x2 | + 0x10 | 0x40) , 0x33),0x3d4); + + outw(IO_OUT16VAL(0x6,0x8), 0x3c4); + + /* switch to MMIO only mode */ + + outb(0x58,0x3d4); + outw(IO_OUT16VAL(inb(0x3d5) | 3 | 0x10,0x58),0x3d4); + outw(IO_OUT16VAL(8,0x53),0x3d4); + + /* switch off I/O accesses */ + +#if 0 + pcibios_write_config_word(bus, dev, PCI_COMMAND, + PCI_COMMAND_IO | PCI_COMMAND_MEMORY); +#endif + } + + return 0; +} + + + /* + * Initialisation + * We heavily rely on OF for the moment. This needs fixing. + */ + +__initfunc(unsigned long s3trio_fb_init(unsigned long mem_start)) +{ + struct device_node *dp; + int i, err, *pp, len; + unsigned *up, address; + u_long *CursorBase; + + if (!prom_display_paths[0]) + return mem_start; + if (!(dp = find_path_device(prom_display_paths[0]))) + return mem_start; + + strncat(s3trio_name, dp->name, sizeof(s3trio_name)); + s3trio_name[sizeof(s3trio_name)-1] = '\0'; + strcpy(fb_fix.id, s3trio_name); + + if((pp = (int *)get_property(dp, "vendor-id", &len)) != NULL + && *pp!=PCI_VENDOR_ID_S3) { + printk("%s: can't find S3 Trio board\n", dp->full_name); + return mem_start; + } + + if((pp = (int *)get_property(dp, "device-id", &len)) != NULL + && *pp!=PCI_DEVICE_ID_S3_TRIO) { + printk("%s: can't find S3 Trio board\n", dp->full_name); + return mem_start; + } + + if ((pp = (int *)get_property(dp, "depth", &len)) != NULL + && len == sizeof(int) && *pp != 8) { + printk("%s: can't use depth = %d\n", dp->full_name, *pp); + return mem_start; + } + if ((pp = (int *)get_property(dp, "width", &len)) != NULL + && len == sizeof(int)) + fb_var.xres = fb_var.xres_virtual = *pp; + if ((pp = (int *)get_property(dp, "height", &len)) != NULL + && len == sizeof(int)) + fb_var.yres = fb_var.yres_virtual = *pp; + if ((pp = (int *)get_property(dp, "linebytes", &len)) != NULL + && len == sizeof(int)) + fb_fix.line_length = *pp; + else + fb_fix.line_length = fb_var.xres_virtual; + fb_fix.smem_len = fb_fix.line_length*fb_var.yres; + + s3trio_init(); + address=0xc6000000; + fb_fix.smem_start = ioremap(address,64*1024*1024); + fb_fix.type = FB_TYPE_PACKED_PIXELS; + fb_fix.type_aux = 0; + + + s3trio_resetaccel(); + + mem_out8(0x30,fb_fix.smem_start+0x1008000 + 0x03D4); + mem_out8(0x2d,fb_fix.smem_start+0x1008000 + 0x03D4); + mem_out8(0x2e,fb_fix.smem_start+0x1008000 + 0x03D4); + + mem_out8(0x50,fb_fix.smem_start+0x1008000 + 0x03D4); + + /* disable HW cursor */ + + mem_out8(0x39,fb_fix.smem_start+0x1008000 + 0x03D4); + mem_out8(0xa0,fb_fix.smem_start+0x1008000 + 0x03D5); + + mem_out8(0x45,fb_fix.smem_start+0x1008000 + 0x03D4); + mem_out8(0,fb_fix.smem_start+0x1008000 + 0x03D5); + + mem_out8(0x4e,fb_fix.smem_start+0x1008000 + 0x03D4); + mem_out8(0,fb_fix.smem_start+0x1008000 + 0x03D5); + + mem_out8(0x4f,fb_fix.smem_start+0x1008000 + 0x03D4); + mem_out8(0,fb_fix.smem_start+0x1008000 + 0x03D5); + + /* init HW cursor */ + + CursorBase=(u_long *)(fb_fix.smem_start + 2*1024*1024 - 0x400); + for (i=0; i < 8; i++) { + *(CursorBase +(i*4)) = 0xffffff00; + *(CursorBase+1+(i*4)) = 0xffff0000; + *(CursorBase+2+(i*4)) = 0xffff0000; + *(CursorBase+3+(i*4)) = 0xffff0000; + } + for (i=8; i < 64; i++) { + *(CursorBase +(i*4)) = 0xffff0000; + *(CursorBase+1+(i*4)) = 0xffff0000; + *(CursorBase+2+(i*4)) = 0xffff0000; + *(CursorBase+3+(i*4)) = 0xffff0000; + } + + + mem_out8(0x4c,fb_fix.smem_start+0x1008000 + 0x03D4); + mem_out8(((2*1024 - 1)&0xf00)>>8,fb_fix.smem_start+0x1008000 + 0x03D5); + + mem_out8(0x4d,fb_fix.smem_start+0x1008000 + 0x03D4); + mem_out8((2*1024 - 1) & 0xff,fb_fix.smem_start+0x1008000 + 0x03D5); + + mem_out8(0x45,fb_fix.smem_start+0x1008000 + 0x03D4); + mem_in8(fb_fix.smem_start+0x1008000 + 0x03D4); + + mem_out8(0x4a,fb_fix.smem_start+0x1008000 + 0x03D4); + mem_out8(0x80,fb_fix.smem_start+0x1008000 + 0x03D5); + mem_out8(0x80,fb_fix.smem_start+0x1008000 + 0x03D5); + mem_out8(0x80,fb_fix.smem_start+0x1008000 + 0x03D5); + + mem_out8(0x4b,fb_fix.smem_start+0x1008000 + 0x03D4); + mem_out8(0x00,fb_fix.smem_start+0x1008000 + 0x03D5); + mem_out8(0x00,fb_fix.smem_start+0x1008000 + 0x03D5); + mem_out8(0x00,fb_fix.smem_start+0x1008000 + 0x03D5); + + mem_out8(0x45,fb_fix.smem_start+0x1008000 + 0x03D4); + mem_out8(0,fb_fix.smem_start+0x1008000 + 0x03D5); + + s3trio_setcolreg(255, 56, 100, 160, 0, NULL /* not used */); + s3trio_setcolreg(254, 0, 0, 0, 0, NULL /* not used */); + memset((char *)fb_fix.smem_start,0,640*480); + +#if 0 + Trio_RectFill(0,0,90,90,7,1); +#endif + + fb_fix.visual = FB_VISUAL_PSEUDOCOLOR ; + fb_var.xoffset = fb_var.yoffset = 0; + fb_var.bits_per_pixel = 8; + fb_var.grayscale = 0; + fb_var.red.offset = fb_var.green.offset = fb_var.blue.offset = 0; + fb_var.red.length = fb_var.green.length = fb_var.blue.length = 8; + fb_var.red.msb_right = fb_var.green.msb_right = fb_var.blue.msb_right = 0; + fb_var.transp.offset = fb_var.transp.length = fb_var.transp.msb_right = 0; + fb_var.nonstd = 0; + fb_var.activate = 0; + fb_var.height = fb_var.width = -1; + fb_var.accel = 5; + fb_var.pixclock = 1; + fb_var.left_margin = fb_var.right_margin = 0; + fb_var.upper_margin = fb_var.lower_margin = 0; + fb_var.hsync_len = fb_var.vsync_len = 0; + fb_var.sync = 0; + fb_var.vmode = FB_VMODE_NONINTERLACED; + + disp.var = fb_var; + disp.cmap.start = 0; + disp.cmap.len = 0; + disp.cmap.red = disp.cmap.green = disp.cmap.blue = disp.cmap.transp = NULL; + disp.screen_base = fb_fix.smem_start; + disp.visual = fb_fix.visual; + disp.type = fb_fix.type; + disp.type_aux = fb_fix.type_aux; + disp.ypanstep = 0; + disp.ywrapstep = 0; + disp.line_length = fb_fix.line_length; + disp.can_soft_blank = 1; + disp.inverse = 0; +#ifdef CONFIG_FBCON_CFB8 + disp.dispsw = &fbcon_trio8; +#else + disp.dispsw = NULL; +#endif + + strcpy(fb_info.modename, "Trio64 "); + strncat(fb_info.modename, dp->full_name, sizeof(fb_info.modename)); + fb_info.node = -1; + fb_info.fbops = &s3trio_ops; +#if 0 + fb_info.fbvar_num = 1; + fb_info.fbvar = &fb_var; +#endif + fb_info.disp = &disp; + fb_info.fontname[0] = '\0'; + fb_info.changevar = NULL; + fb_info.switch_con = &s3triofbcon_switch; + fb_info.updatevar = &s3triofbcon_updatevar; + fb_info.blank = &s3triofbcon_blank; +#if 0 + fb_info.setcmap = &s3triofbcon_setcmap; +#endif + +#ifdef CONFIG_FB_COMPAT_XPMAC + if (!console_fb_info) { + display_info.height = fb_var.yres; + display_info.width = fb_var.xres; + display_info.depth = 8; + display_info.pitch = fb_fix.line_length; + display_info.mode = 0; + strncpy(display_info.name, dp->name, sizeof(display_info.name)); + display_info.fb_address = (unsigned long)fb_fix.smem_start; + display_info.disp_reg_address = address + 0x1008000; + display_info.cmap_adr_address = address + 0x1008000 + 0x3c8; + display_info.cmap_data_address = address + 0x1008000 + 0x3c9; + console_fb_info = &fb_info; + console_setmode_ptr = s3trio_console_setmode; + console_set_cmap_ptr = s3trio_set_cmap; + } +#endif /* CONFIG_FB_COMPAT_XPMAC) */ + + err = register_framebuffer(&fb_info); + if (err < 0) + return mem_start; + + printk("fb%d: S3 Trio frame buffer device on %s\n", + GET_FB_IDX(fb_info.node), dp->full_name); + + return mem_start; +} + + +static int s3triofbcon_switch(int con, struct fb_info *info) +{ + /* Do we have to save the colormap? */ + if (fb_display[currcon].cmap.len) + fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1, + s3trio_getcolreg, info); + + currcon = con; + /* Install new colormap */ + do_install_cmap(con); + return 0; +} + + /* + * Update the `var' structure (called by fbcon.c) + */ + +static int s3triofbcon_updatevar(int con, struct fb_info *info) +{ + /* Nothing */ + return 0; +} + + /* + * Blank the display. + */ + +static void s3triofbcon_blank(int blank, struct fb_info *info) +{ + /* Nothing */ +} + + /* + * Set the colormap + */ + +static int s3triofbcon_setcmap(struct fb_cmap *cmap, int con) +{ + return(s3trio_set_cmap(cmap, 1, con, &fb_info)); +} + + + /* + * Read a single color register and split it into + * colors/transparent. Return != 0 for invalid regno. + */ + +static int s3trio_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, + u_int *transp, struct fb_info *info) +{ + if (regno > 255) + return 1; + *red = palette[regno].red; + *green = palette[regno].green; + *blue = palette[regno].blue; + return 0; +} + + + /* + * Set a single color register. The values supplied are already + * rounded down to the hardware's capabilities (according to the + * entries in the var structure). Return != 0 for invalid regno. + */ + +static int s3trio_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) +{ + if (regno > 255) + return 1; + palette[regno].red = red; + palette[regno].green = green; + palette[regno].blue = blue; + + mem_out8(regno,fb_fix.smem_start+0x1008000 + 0x3c8); + mem_out8((red & 0xff) >> 2,fb_fix.smem_start+0x1008000 + 0x3c9); + mem_out8((green & 0xff) >> 2,fb_fix.smem_start+0x1008000 + 0x3c9); + mem_out8((blue & 0xff) >> 2,fb_fix.smem_start+0x1008000 + 0x3c9); + + return 0; +} + + +static void do_install_cmap(int con) +{ + if (con != currcon) + return; + if (fb_display[con].cmap.len) + fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1, + s3trio_setcolreg, &fb_info); + else + fb_set_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), + &fb_display[con].var, 1, s3trio_setcolreg, &fb_info); +} + +#ifdef CONFIG_FB_COMPAT_XPMAC + + /* + * Backward compatibility mode for Xpmac + */ + +static int s3trio_console_setmode(struct vc_mode *mode, int doit) +{ + int err; + struct fb_var_screeninfo var; + struct s3trio_par par; + + if (mode->mode <= 0 || mode->mode > VMODE_MAX ) + return -EINVAL; + par.video_mode = mode->mode; + + switch (mode->depth) { + case 24: + case 32: + par.color_mode = CMODE_32; + break; + case 16: + par.color_mode = CMODE_16; + break; + case 8: + case 0: /* (default) */ + par.color_mode = CMODE_8; + break; + default: + return -EINVAL; + } + encode_var(&var, &par); + if ((err = decode_var(&var, &par))) + return err; + if (doit) + s3trio_set_var(&var, currcon, 0); + return 0; +} + +#endif /* CONFIG_FB_COMPAT_XPMAC */ + +void s3trio_video_setup(char *options, int *ints) { + + return; + +} + +static void Trio_WaitQueue(u_short fifo) { + + u_short status; + + do + { + status = mem_in16(fb_fix.smem_start + 0x1000000 + 0x9AE8); + } while (!(status & fifo)); + +} + +static void Trio_WaitBlit(void) { + + u_short status; + + do + { + status = mem_in16(fb_fix.smem_start + 0x1000000 + 0x9AE8); + } while (status & 0x200); + +} + +static void Trio_BitBLT(u_short curx, u_short cury, u_short destx, + u_short desty, u_short width, u_short height, + u_short mode) { + + u_short blitcmd = 0xc011; + + /* Set drawing direction */ + /* -Y, X maj, -X (default) */ + + if (curx > destx) + blitcmd |= 0x0020; /* Drawing direction +X */ + else { + curx += (width - 1); + destx += (width - 1); + } + + if (cury > desty) + blitcmd |= 0x0080; /* Drawing direction +Y */ + else { + cury += (height - 1); + desty += (height - 1); + } + + Trio_WaitQueue(0x0400); + + outw(0xa000, 0xBEE8); + outw(0x60 | mode, 0xBAE8); + + outw(curx, 0x86E8); + outw(cury, 0x82E8); + + outw(destx, 0x8EE8); + outw(desty, 0x8AE8); + + outw(height - 1, 0xBEE8); + outw(width - 1, 0x96E8); + + outw(blitcmd, 0x9AE8); + +} + +static void Trio_RectFill(u_short x, u_short y, u_short width, u_short height, + u_short mode, u_short color) { + + u_short blitcmd = 0x40b1; + + Trio_WaitQueue(0x0400); + + outw(0xa000, 0xBEE8); + outw((0x20 | mode), 0xBAE8); + outw(0xe000, 0xBEE8); + outw(color, 0xA6E8); + outw(x, 0x86E8); + outw(y, 0x82E8); + outw((height - 1), 0xBEE8); + outw((width - 1), 0x96E8); + outw(blitcmd, 0x9AE8); + +} + + +static void Trio_MoveCursor(u_short x, u_short y) { + + mem_out8(0x39, fb_fix.smem_start + 0x1008000 + 0x3d4); + mem_out8(0xa0, fb_fix.smem_start + 0x1008000 + 0x3d5); + + mem_out8(0x46, fb_fix.smem_start + 0x1008000 + 0x3d4); + mem_out8((x & 0x0700) >> 8, fb_fix.smem_start + 0x1008000 + 0x3d5); + mem_out8(0x47, fb_fix.smem_start + 0x1008000 + 0x3d4); + mem_out8(x & 0x00ff, fb_fix.smem_start + 0x1008000 + 0x3d5); + + mem_out8(0x48, fb_fix.smem_start + 0x1008000 + 0x3d4); + mem_out8((y & 0x0700) >> 8, fb_fix.smem_start + 0x1008000 + 0x3d5); + mem_out8(0x49, fb_fix.smem_start + 0x1008000 + 0x3d4); + mem_out8(y & 0x00ff, fb_fix.smem_start + 0x1008000 + 0x3d5); + +} + + + /* + * Text console acceleration + */ + +#ifdef CONFIG_FBCON_CFB8 +static void fbcon_trio8_bmove(struct display *p, int sy, int sx, int dy, + int dx, int height, int width) +{ + sx *= 8; dx *= 8; width *= 8; + Trio_BitBLT((u_short)sx, (u_short)(sy*p->fontheight), (u_short)dx, + (u_short)(dy*p->fontheight), (u_short)width, + (u_short)(height*p->fontheight), (u_short)S3_NEW); +} + +static void fbcon_trio8_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width) +{ + unsigned char bg; + + sx *= 8; width *= 8; + bg = attr_bgcol_ec(p,conp); + Trio_RectFill((u_short)sx, + (u_short)(sy*p->fontheight), + (u_short)width, + (u_short)(height*p->fontheight), + (u_short)S3_NEW, + (u_short)bg); +} + +static void fbcon_trio8_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx) +{ + Trio_WaitBlit(); + fbcon_cfb8_putc(conp, p, c, yy, xx); +} + +static void fbcon_trio8_putcs(struct vc_data *conp, struct display *p, + const char *s, int count, int yy, int xx) +{ + Trio_WaitBlit(); + fbcon_cfb8_putcs(conp, p, s, count, yy, xx); +} + +static void fbcon_trio8_revc(struct display *p, int xx, int yy) +{ + Trio_WaitBlit(); + fbcon_cfb8_revc(p, xx, yy); +} + +static struct display_switch fbcon_trio8 = { + fbcon_cfb8_setup, fbcon_trio8_bmove, fbcon_trio8_clear, fbcon_trio8_putc, + fbcon_trio8_putcs, fbcon_trio8_revc +}; +#endif diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index 7aa9df61a..09ff067df 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -60,6 +60,11 @@ #include <asm/amigaints.h> #include <asm/setup.h> +#include "fbcon-afb.h" +#include "fbcon-ilbm.h" +#include "fbcon-mfb.h" + + #define DEBUG #if !defined(CONFIG_FB_AMIGA_OCS) && !defined(CONFIG_FB_AMIGA_ECS) && !defined(CONFIG_FB_AMIGA_AGA) @@ -535,15 +540,6 @@ static u_short maxfmode, chipset; /* - * Monitor Specifications - * - * These are typical for a `generic' Amiga monitor (e.g. A1960) - */ - -static long vfmin = 50, vfmax = 90, hfmin = 15000, hfmax = 38000; - - - /* * Various macros */ @@ -672,7 +668,7 @@ static u_short *lofsprite, *shfsprite, *dummysprite; * Current Video Mode */ -static struct amiga_fb_par { +static struct amifb_par { /* General Values */ @@ -740,6 +736,7 @@ static struct amiga_fb_par { static int currcon = 0; static struct display disp; + static struct fb_info fb_info; @@ -789,229 +786,199 @@ static u_short is_lace = 0; /* Screen is laced */ * The rest of the name is filled in during initialization */ -static char amiga_fb_name[16] = "Amiga "; +static char amifb_name[16] = "Amiga "; - /* - * Predefined Video Mode Names - * - * The a2024-?? modes don't work yet because there's no A2024 driver. - */ - -static char *amiga_fb_modenames[] = { - - /* - * Autodetect (Default) Video Mode - */ - - "default", /* - * AmigaOS Video Modes - */ - - "ntsc", /* 640x200, 15 kHz, 60 Hz (NTSC) */ - "ntsc-lace", /* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */ - "pal", /* 640x256, 15 kHz, 50 Hz (PAL) */ - "pal-lace", /* 640x512, 15 kHz, 50 Hz interlaced (PAL) */ - "multiscan", /* 640x480, 29 kHz, 57 Hz */ - "multiscan-lace", /* 640x960, 29 kHz, 57 Hz interlaced */ - "a2024-10", /* 1024x800, 10 Hz (Not yet supported) */ - "a2024-15", /* 1024x800, 15 Hz (Not yet supported) */ - "euro36", /* 640x200, 15 kHz, 72 Hz */ - "euro36-lace", /* 640x400, 15 kHz, 72 Hz interlaced */ - "euro72", /* 640x400, 29 kHz, 68 Hz */ - "euro72-lace", /* 640x800, 29 kHz, 68 Hz interlaced */ - "super72", /* 800x300, 23 kHz, 70 Hz */ - "super72-lace", /* 800x600, 23 kHz, 70 Hz interlaced */ - "dblntsc", /* 640x200, 27 kHz, 57 Hz doublescan */ - "dblntsc-ff", /* 640x400, 27 kHz, 57 Hz */ - "dblntsc-lace", /* 640x800, 27 kHz, 57 Hz interlaced */ - "dblpal", /* 640x256, 27 kHz, 47 Hz doublescan */ - "dblpal-ff", /* 640x512, 27 kHz, 47 Hz */ - "dblpal-lace", /* 640x1024, 27 kHz, 47 Hz interlaced */ - - /* - * VGA Video Modes - */ - - "vga", /* 640x480, 31 kHz, 60 Hz (VGA) */ - "vga70", /* 640x400, 31 kHz, 70 Hz (VGA) */ - - /* - * User Defined Video Modes: to be set after boot up using e.g. fbset - */ - - "user0", "user1", "user2", "user3", "user4", "user5", "user6", "user7" -}; - -static struct fb_var_screeninfo amiga_fb_predefined[] = { - - /* - * Autodetect (Default) Video Mode + * Predefined Video Modes + * */ - { 0, }, - - /* - * AmigaOS Video Modes - */ +static struct fb_videomode amifb_predefined[] __initdata = { - { - /* ntsc */ - 640, 200, 640, 200, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 106, 86, 44, 16, 76, 2, - FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - }, { - /* ntsc-lace */ - 640, 400, 640, 400, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 106, 86, 88, 33, 76, 4, - FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP - }, { - /* pal */ - 640, 256, 640, 256, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 106, 86, 40, 14, 76, 2, - FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - }, { - /* pal-lace */ - 640, 512, 640, 512, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 106, 86, 80, 29, 76, 4, - FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP - }, { - /* multiscan */ - 640, 480, 640, 480, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 96, 112, 29, 8, 72, 8, - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - - }, { - /* multiscan-lace */ - 640, 960, 640, 960, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 96, 112, 58, 16, 72, 16, - 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP - }, { - /* a2024-10 (Not yet supported) */ - 1024, 800, 1024, 800, 0, 0, 2, 0, - {0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 0, 0, 0, 0, 0, 0, - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - }, { - /* a2024-15 (Not yet supported) */ - 1024, 800, 1024, 800, 0, 0, 2, 0, - {0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 0, 0, 0, 0, 0, 0, - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - }, { - /* euro36 */ - 640, 200, 640, 200, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 92, 124, 6, 6, 52, 5, - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - }, { - /* euro36-lace */ - 640, 400, 640, 400, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 92, 124, 12, 12, 52, 10, - 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP - }, { - /* euro72 */ - 640, 400, 640, 400, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 164, 92, 9, 9, 80, 8, - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - }, { - /* euro72-lace */ - 640, 800, 640, 800, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 164, 92, 18, 18, 80, 16, - 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP - }, { - /* super72 */ - 800, 300, 800, 300, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 212, 140, 10, 11, 80, 7, - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - }, { - /* super72-lace */ - 800, 600, 800, 600, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 212, 140, 20, 22, 80, 14, - 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP - }, { - /* dblntsc */ - 640, 200, 640, 200, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 196, 124, 18, 17, 80, 4, - 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP - }, { - /* dblntsc-ff */ - 640, 400, 640, 400, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 196, 124, 36, 35, 80, 7, - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - }, { - /* dblntsc-lace */ - 640, 800, 640, 800, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 196, 124, 72, 70, 80, 14, - 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP - }, { - /* dblpal */ - 640, 256, 640, 256, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 196, 124, 14, 13, 80, 4, - 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP - }, { - /* dblpal-ff */ - 640, 512, 640, 512, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 196, 124, 28, 27, 80, 7, - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - }, { - /* dblpal-lace */ - 640, 1024, 640, 1024, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 196, 124, 56, 54, 80, 14, - 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP - }, - - /* - * VGA Video Modes - */ + /* + * AmigaOS Video Modes + */ - { - /* vga */ - 640, 480, 640, 480, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 64, 96, 30, 9, 112, 2, - 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - }, { - /* vga70 */ - 640, 400, 640, 400, 0, 0, 4, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 64, 96, 35, 12, 112, 2, - FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP - }, + { + "ntsc", { /* 640x200, 15 kHz, 60 Hz (NTSC) */ + 640, 200, 640, 200, 0, 0, 4, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_HIRES, 106, 86, 44, 16, 76, 2, + FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + } + }, { + "ntsc-lace", { /* 640x400, 15 kHz, 60 Hz interlaced (NTSC) */ + 640, 400, 640, 400, 0, 0, 4, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_HIRES, 106, 86, 88, 33, 76, 4, + FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP + } + }, { + "pal", { /* 640x256, 15 kHz, 50 Hz (PAL) */ + 640, 256, 640, 256, 0, 0, 4, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_HIRES, 106, 86, 40, 14, 76, 2, + FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + } + }, { + "pal-lace", { /* 640x512, 15 kHz, 50 Hz interlaced (PAL) */ + 640, 512, 640, 512, 0, 0, 4, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_HIRES, 106, 86, 80, 29, 76, 4, + FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP + } + }, { + "multiscan", { /* 640x480, 29 kHz, 57 Hz */ + 640, 480, 640, 480, 0, 0, 4, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_SHRES, 96, 112, 29, 8, 72, 8, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + } + }, { + "multiscan-lace", { /* 640x960, 29 kHz, 57 Hz interlaced */ + 640, 960, 640, 960, 0, 0, 4, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_SHRES, 96, 112, 58, 16, 72, 16, + 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP + } + }, { + "euro36", { /* 640x200, 15 kHz, 72 Hz */ + 640, 200, 640, 200, 0, 0, 4, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_HIRES, 92, 124, 6, 6, 52, 5, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + } + }, { + "euro36-lace", { /* 640x400, 15 kHz, 72 Hz interlaced */ + 640, 400, 640, 400, 0, 0, 4, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_HIRES, 92, 124, 12, 12, 52, 10, + 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP + } + }, { + "euro72", { /* 640x400, 29 kHz, 68 Hz */ + 640, 400, 640, 400, 0, 0, 4, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_SHRES, 164, 92, 9, 9, 80, 8, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + } + }, { + "euro72-lace", { /* 640x800, 29 kHz, 68 Hz interlaced */ + 640, 800, 640, 800, 0, 0, 4, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_SHRES, 164, 92, 18, 18, 80, 16, + 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP + } + }, { + "super72", { /* 800x300, 23 kHz, 70 Hz */ + 800, 300, 800, 300, 0, 0, 4, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_SHRES, 212, 140, 10, 11, 80, 7, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + } + }, { + "super72-lace", { /* 800x600, 23 kHz, 70 Hz interlaced */ + 800, 600, 800, 600, 0, 0, 4, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_SHRES, 212, 140, 20, 22, 80, 14, + 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP + } + }, { + "dblntsc", { /* 640x200, 27 kHz, 57 Hz doublescan */ + 640, 200, 640, 200, 0, 0, 4, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_SHRES, 196, 124, 18, 17, 80, 4, + 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP + } + }, { + "dblntsc-ff", { /* 640x400, 27 kHz, 57 Hz */ + 640, 400, 640, 400, 0, 0, 4, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_SHRES, 196, 124, 36, 35, 80, 7, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + } + }, { + "dblntsc-lace", { /* 640x800, 27 kHz, 57 Hz interlaced */ + 640, 800, 640, 800, 0, 0, 4, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_SHRES, 196, 124, 72, 70, 80, 14, + 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP + } + }, { + "dblpal", { /* 640x256, 27 kHz, 47 Hz doublescan */ + 640, 256, 640, 256, 0, 0, 4, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_SHRES, 196, 124, 14, 13, 80, 4, + 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP + } + }, { + "dblpal-ff", { /* 640x512, 27 kHz, 47 Hz */ + 640, 512, 640, 512, 0, 0, 4, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_SHRES, 196, 124, 28, 27, 80, 7, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + } + }, { + "dblpal-lace", { /* 640x1024, 27 kHz, 47 Hz interlaced */ + 640, 1024, 640, 1024, 0, 0, 4, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_SHRES, 196, 124, 56, 54, 80, 14, + 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP + } + }, + + /* + * VGA Video Modes + */ + + { + "vga", { /* 640x480, 31 kHz, 60 Hz (VGA) */ + 640, 480, 640, 480, 0, 0, 4, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_SHRES, 64, 96, 30, 9, 112, 2, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + } + }, { + "vga70", { /* 640x400, 31 kHz, 70 Hz (VGA) */ + 640, 400, 640, 400, 0, 0, 4, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_SHRES, 64, 96, 35, 12, 112, 2, + FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + } + }, - /* - * User Defined Video Modes - */ +#if 0 - { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, } + /* + * A2024 video modes + * These modes don't work yet because there's no A2024 driver. + */ + + { + "a2024-10", { /* 1024x800, 10 Hz */ + 1024, 800, 1024, 800, 0, 0, 2, 0, + {0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_HIRES, 0, 0, 0, 0, 0, 0, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + } + }, { + "a2024-15", { /* 1024x800, 15 Hz */ + 1024, 800, 1024, 800, 0, 0, 2, 0, + {0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0}, + 0, 0, -1, -1, 0, TAG_HIRES, 0, 0, 0, 0, 0, 0, + 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP + } + } +#endif }; -#define NUM_USER_MODES (8) -#define NUM_TOTAL_MODES arraysize(amiga_fb_predefined) -#define NUM_PREDEF_MODES (NUM_TOTAL_MODES-NUM_USER_MODES) +#define NUM_TOTAL_MODES arraysize(amifb_predefined) static int amifb_ilbm = 0; /* interleaved or normal bitplanes */ - static int amifb_inverse = 0; -static int amifb_usermode = 0; +static int amifb_usermode __initdata = 0; +static int amifb_userdepth __initdata = -1; /* * Some default modes @@ -1023,6 +990,9 @@ static int amifb_usermode = 0; #define DEFMODE_AMBER_NTSC "ntsc-lace" /* for flicker fixed NTSC (A3000) */ #define DEFMODE_AGA "vga70" /* for AGA */ +static struct fb_var_screeninfo amifb_default; + + /* * Macros for the conversion from real world values to hardware register * values @@ -1181,40 +1151,47 @@ static u_short sprfetchmode[3] = { * Interface used by the world */ -void amiga_video_setup(char *options, int *ints); - -static int amiga_fb_open(int fbidx); -static int amiga_fb_release(int fbidx); -static int amiga_fb_get_fix(struct fb_fix_screeninfo *fix, int con); -static int amiga_fb_get_var(struct fb_var_screeninfo *var, int con); -static int amiga_fb_set_var(struct fb_var_screeninfo *var, int con); -static int amiga_fb_pan_display(struct fb_var_screeninfo *var, int con); -static int amiga_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con); -static int amiga_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con); -static int amiga_fb_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg, int con); - -static int amiga_fb_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix, int con); -static int amiga_fb_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data, int con); -static int amiga_fb_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data, int con); -static int amiga_fb_get_cursorstate(struct fb_cursorstate *state, int con); -static int amiga_fb_set_cursorstate(struct fb_cursorstate *state, int con); +void amifb_setup(char *options, int *ints); + +static int amifb_open(struct fb_info *info); +static int amifb_release(struct fb_info *info); +static int amifb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info); +static int amifb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int amifb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int amifb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int amifb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int amifb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int amifb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info); + +static int amifb_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix, int con); +static int amifb_get_var_cursorinfo(struct fb_var_cursorinfo *var, + u_char *data, int con); +static int amifb_set_var_cursorinfo(struct fb_var_cursorinfo *var, + u_char *data, int con); +static int amifb_get_cursorstate(struct fb_cursorstate *state, int con); +static int amifb_set_cursorstate(struct fb_cursorstate *state, int con); /* * Interface to the low level console driver */ -unsigned long amiga_fb_init(unsigned long mem_start); -static int amifbcon_switch(int con); -static int amifbcon_updatevar(int con); -static void amifbcon_blank(int blank); -static int amifbcon_setcmap(struct fb_cmap *cmap, int con); +unsigned long amifb_init(unsigned long mem_start); +static int amifbcon_switch(int con, struct fb_info *info); +static int amifbcon_updatevar(int con, struct fb_info *info); +static void amifbcon_blank(int blank, struct fb_info *info); /* * Internal routines */ -static void do_install_cmap(int con); +static void do_install_cmap(int con, struct fb_info *info); static int flash_cursor(void); static void amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp); static void get_video_mode(const char *name); @@ -1227,22 +1204,22 @@ static char *strtoke(char *s,const char *ct); */ static int ami_encode_fix(struct fb_fix_screeninfo *fix, - struct amiga_fb_par *par); + struct amifb_par *par); static int ami_decode_var(struct fb_var_screeninfo *var, - struct amiga_fb_par *par); + struct amifb_par *par); static int ami_encode_var(struct fb_var_screeninfo *var, - struct amiga_fb_par *par); -static void ami_get_par(struct amiga_fb_par *par); + struct amifb_par *par); +static void ami_get_par(struct amifb_par *par); static void ami_set_var(struct fb_var_screeninfo *var); #ifdef DEBUG -static void ami_set_par(struct amiga_fb_par *par); +static void ami_set_par(struct amifb_par *par); #endif static void ami_pan_var(struct fb_var_screeninfo *var); static int ami_update_par(void); static int ami_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, - u_int *transp); + u_int *transp, struct fb_info *info); static int ami_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp); + u_int transp, struct fb_info *info); static void ami_update_display(void); static void ami_init_display(void); static void ami_do_blank(void); @@ -1265,29 +1242,14 @@ static void ami_rebuild_copper(void); extern unsigned short ami_intena_vals[]; -static struct fb_ops amiga_fb_ops = { - amiga_fb_open, amiga_fb_release, amiga_fb_get_fix, amiga_fb_get_var, - amiga_fb_set_var, amiga_fb_get_cmap, amiga_fb_set_cmap, - amiga_fb_pan_display, amiga_fb_ioctl +static struct fb_ops amifb_ops = { + amifb_open, amifb_release, amifb_get_fix, amifb_get_var, + amifb_set_var, amifb_get_cmap, amifb_set_cmap, + amifb_pan_display, NULL, amifb_ioctl }; -struct useropts { - long xres; - long yres; - long xres_virtual; - long yres_virtual; - long bits_per_pixel; - long left_margin; - long right_margin; - long upper_margin; - long lower_margin; - long hsync_len; - long vsync_len; -} useropts __initdata = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 -}; -__initfunc(void amiga_video_setup(char *options, int *ints)) +__initfunc(void amifb_setup(char *options, int *ints)) { char *this_opt; char mcap_spec[80]; @@ -1313,51 +1275,51 @@ __initfunc(void amiga_video_setup(char *options, int *ints)) else if (!strncmp(this_opt, "fstart:", 7)) min_fstrt = simple_strtoul(this_opt+7, NULL, 0); else if (!strncmp(this_opt, "depth:", 6)) - useropts.bits_per_pixel = simple_strtoul(this_opt+6, NULL, 0); + amifb_userdepth = simple_strtoul(this_opt+6, NULL, 0); else if (!strncmp(this_opt, "size:", 5)) { p = this_opt + 5; if (*p != ';') - useropts.xres = simple_strtoul(p, NULL, 0); + amifb_default.xres = simple_strtoul(p, NULL, 0); if (!(p = strchr(p, ';'))) continue; if (*++p != ';') - useropts.yres = simple_strtoul(p, NULL, 0); + amifb_default.yres = simple_strtoul(p, NULL, 0); if (!(p = strchr(p, ';'))) continue; if (*++p != ';') - useropts.xres_virtual = simple_strtoul(p, NULL, 0); + amifb_default.xres_virtual = simple_strtoul(p, NULL, 0); if (!(p = strchr(p, ';'))) continue; if (*++p != ';') - useropts.yres_virtual = simple_strtoul(p, NULL, 0); + amifb_default.yres_virtual = simple_strtoul(p, NULL, 0); if (!(p = strchr(p, ';'))) continue; if (*++p) - useropts.bits_per_pixel = simple_strtoul(p, NULL, 0); + amifb_default.bits_per_pixel = simple_strtoul(p, NULL, 0); } else if (!strncmp(this_opt, "timing:", 7)) { p = this_opt + 7; if (*p != ';') - useropts.left_margin = simple_strtoul(p, NULL, 0); + amifb_default.left_margin = simple_strtoul(p, NULL, 0); if (!(p = strchr(p, ';'))) continue; if (*++p != ';') - useropts.right_margin = simple_strtoul(p, NULL, 0); + amifb_default.right_margin = simple_strtoul(p, NULL, 0); if (!(p = strchr(p, ';'))) continue; if (*++p != ';') - useropts.upper_margin = simple_strtoul(p, NULL, 0); + amifb_default.upper_margin = simple_strtoul(p, NULL, 0); if (!(p = strchr(p, ';'))) continue; if (*++p) - useropts.lower_margin = simple_strtoul(p, NULL, 0); + amifb_default.lower_margin = simple_strtoul(p, NULL, 0); } else if (!strncmp(this_opt, "sync:", 5)) { p = this_opt + 5; if (*p != ';') - useropts.hsync_len = simple_strtoul(p, NULL, 0); + amifb_default.hsync_len = simple_strtoul(p, NULL, 0); if (!(p = strchr(p, ';'))) continue; if (*++p) - useropts.vsync_len = simple_strtoul(p, NULL, 0); + amifb_default.vsync_len = simple_strtoul(p, NULL, 0); } else get_video_mode(this_opt); } @@ -1395,10 +1357,10 @@ __initfunc(void amiga_video_setup(char *options, int *ints)) if (hmax <= 0 || hmax <= hmin) goto cap_invalid; - vfmin = vmin; - vfmax = vmax; - hfmin = hmin; - hfmax = hmax; + fb_info.monspecs.vfmin = vmin; + fb_info.monspecs.vfmax = vmax; + fb_info.monspecs.hfmin = hmin; + fb_info.monspecs.hfmax = hmax; cap_invalid: ; } @@ -1408,7 +1370,7 @@ cap_invalid: * Open/Release the frame buffer device */ -static int amiga_fb_open(int fbidx) +static int amifb_open(struct fb_info *info) { /* * Nothing, only a usage count for the moment @@ -1418,7 +1380,7 @@ static int amiga_fb_open(int fbidx) return(0); } -static int amiga_fb_release(int fbidx) +static int amifb_release(struct fb_info *info) { MOD_DEC_USE_COUNT; return(0); @@ -1429,9 +1391,10 @@ static int amiga_fb_release(int fbidx) * Get the Fixed Part of the Display */ -static int amiga_fb_get_fix(struct fb_fix_screeninfo *fix, int con) +static int amifb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) { - struct amiga_fb_par par; + struct amifb_par par; if (con == -1) ami_get_par(&par); @@ -1448,12 +1411,13 @@ static int amiga_fb_get_fix(struct fb_fix_screeninfo *fix, int con) * Get the User Defined Part of the Display */ -static int amiga_fb_get_var(struct fb_var_screeninfo *var, int con) +static int amifb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) { int err = 0; if (con == -1) { - struct amiga_fb_par par; + struct amifb_par par; ami_get_par(&par); err = ami_encode_var(var, &par); @@ -1466,11 +1430,12 @@ static int amiga_fb_get_var(struct fb_var_screeninfo *var, int con) * Set the User Defined Part of the Display */ -static int amiga_fb_set_var(struct fb_var_screeninfo *var, int con) +static int amifb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) { int err, activate = var->activate; int oldxres, oldyres, oldvxres, oldvyres, oldbpp; - struct amiga_fb_par par; + struct amifb_par par; struct display *display; if (con >= 0) @@ -1513,13 +1478,32 @@ static int amiga_fb_set_var(struct fb_var_screeninfo *var, int con) display->line_length = fix.line_length; display->can_soft_blank = 1; display->inverse = amifb_inverse; + switch (fix.type) { +#ifdef CONFIG_FBCON_ILBM + case FB_TYPE_INTERLEAVED_PLANES: + display->dispsw = &fbcon_ilbm; + break; +#endif +#ifdef CONFIG_FBCON_AFB + case FB_TYPE_PLANES: + display->dispsw = &fbcon_afb; + break; +#endif +#ifdef CONFIG_FBCON_MFB + case FB_TYPE_PACKED_PIXELS: /* depth == 1 */ + display->dispsw = &fbcon_mfb; + break; +#endif + default: + display->dispsw = NULL; + } if (fb_info.changevar) (*fb_info.changevar)(con); } if (oldbpp != var->bits_per_pixel) { if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) return err; - do_install_cmap(con); + do_install_cmap(con, info); } if (con == currcon) ami_set_var(&display->var); @@ -1533,7 +1517,8 @@ static int amiga_fb_set_var(struct fb_var_screeninfo *var, int con) * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag */ -static int amiga_fb_pan_display(struct fb_var_screeninfo *var, int con) +static int amifb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) { if (var->vmode & FB_VMODE_YWRAP) { if (var->yoffset<0 || var->yoffset >= fb_display[con].var.yres_virtual || var->xoffset) @@ -1562,15 +1547,16 @@ static int amiga_fb_pan_display(struct fb_var_screeninfo *var, int con) * Get the Colormap */ -static int amiga_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con) +static int amifb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) { if (con == currcon) /* current console? */ return fb_get_cmap(cmap, &fb_display[con].var, kspc, - ami_getcolreg); + ami_getcolreg, info); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else - fb_copy_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), + fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), cmap, kspc ? 0 : 2); return 0; } @@ -1579,7 +1565,8 @@ static int amiga_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con) * Set the Colormap */ -static int amiga_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con) +static int amifb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) { int err; @@ -1591,7 +1578,7 @@ static int amiga_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con) } if (con == currcon) /* current console? */ return fb_set_cmap(cmap, &fb_display[con].var, kspc, - ami_setcolreg); + ami_setcolreg, info); else fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); return 0; @@ -1601,8 +1588,8 @@ static int amiga_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con) * Amiga Frame Buffer Specific ioctls */ -static int amiga_fb_ioctl(struct inode *inode, struct file *file, - u_int cmd, u_long arg, int con) +static int amifb_ioctl(struct inode *inode, struct file *file, + u_int cmd, u_long arg, int con, struct fb_info *info) { int i; @@ -1612,7 +1599,7 @@ static int amiga_fb_ioctl(struct inode *inode, struct file *file, i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(crsrfix)); if (!i) { - i = amiga_fb_get_fix_cursorinfo(&crsrfix, con); + i = amifb_get_fix_cursorinfo(&crsrfix, con); copy_to_user((void *)arg, &crsrfix, sizeof(crsrfix)); } return i; @@ -1622,7 +1609,7 @@ static int amiga_fb_ioctl(struct inode *inode, struct file *file, i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(crsrvar)); if (!i) { - i = amiga_fb_get_var_cursorinfo(&crsrvar, + i = amifb_get_var_cursorinfo(&crsrvar, ((struct fb_var_cursorinfo *)arg)->data, con); copy_to_user((void *)arg, &crsrvar, sizeof(crsrvar)); } @@ -1634,7 +1621,7 @@ static int amiga_fb_ioctl(struct inode *inode, struct file *file, i = verify_area(VERIFY_READ, (void *)arg, sizeof(crsrvar)); if (!i) { copy_from_user(&crsrvar, (void *)arg, sizeof(crsrvar)); - i = amiga_fb_set_var_cursorinfo(&crsrvar, + i = amifb_set_var_cursorinfo(&crsrvar, ((struct fb_var_cursorinfo *)arg)->data, con); } return i; @@ -1644,7 +1631,7 @@ static int amiga_fb_ioctl(struct inode *inode, struct file *file, i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(crsrstate)); if (!i) { - i = amiga_fb_get_cursorstate(&crsrstate, con); + i = amifb_get_cursorstate(&crsrstate, con); copy_to_user((void *)arg, &crsrstate, sizeof(crsrstate)); } return i; @@ -1655,27 +1642,27 @@ static int amiga_fb_ioctl(struct inode *inode, struct file *file, i = verify_area(VERIFY_READ, (void *)arg, sizeof(crsrstate)); if (!i) { copy_from_user(&crsrstate, (void *)arg, sizeof(crsrstate)); - i = amiga_fb_set_cursorstate(&crsrstate, con); + i = amifb_set_cursorstate(&crsrstate, con); } return i; } #ifdef DEBUG case FBCMD_GET_CURRENTPAR : { - struct amiga_fb_par par; + struct amifb_par par; - i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct amiga_fb_par)); + i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct amifb_par)); if (!i) { ami_get_par(&par); - copy_to_user((void *)arg, &par, sizeof(struct amiga_fb_par)); + copy_to_user((void *)arg, &par, sizeof(struct amifb_par)); } return i; } case FBCMD_SET_CURRENTPAR : { - struct amiga_fb_par par; + struct amifb_par par; - i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct amiga_fb_par)); + i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct amifb_par)); if (!i) { - copy_from_user(&par, (void *)arg, sizeof(struct amiga_fb_par)); + copy_from_user(&par, (void *)arg, sizeof(struct amifb_par)); ami_set_par(&par); } return i; @@ -1689,27 +1676,27 @@ static int amiga_fb_ioctl(struct inode *inode, struct file *file, * Hardware Cursor */ -static int amiga_fb_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix, int con) +static int amifb_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix, int con) { return ami_get_fix_cursorinfo(fix, con); } -static int amiga_fb_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data, int con) +static int amifb_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data, int con) { return ami_get_var_cursorinfo(var, data, con); } -static int amiga_fb_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data, int con) +static int amifb_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data, int con) { return ami_set_var_cursorinfo(var, data, con); } -static int amiga_fb_get_cursorstate(struct fb_cursorstate *state, int con) +static int amifb_get_cursorstate(struct fb_cursorstate *state, int con) { return ami_get_cursorstate(state, con); } -static int amiga_fb_set_cursorstate(struct fb_cursorstate *state, int con) +static int amifb_set_cursorstate(struct fb_cursorstate *state, int con) { return ami_set_cursorstate(state, con); } @@ -1719,7 +1706,7 @@ static int amiga_fb_set_cursorstate(struct fb_cursorstate *state, int con) * Initialisation */ -__initfunc(unsigned long amiga_fb_init(unsigned long mem_start)) +__initfunc(unsigned long amifb_init(unsigned long mem_start)) { int err, tag, i; u_long chipptr; @@ -1745,7 +1732,7 @@ __initfunc(unsigned long amiga_fb_init(unsigned long mem_start)) switch (amiga_chipset) { #ifdef CONFIG_FB_AMIGA_OCS case CS_OCS: - strcat(amiga_fb_name, "OCS"); + strcat(amifb_name, "OCS"); default_chipset: chipset = TAG_OCS; maxdepth[TAG_SHRES] = 0; /* OCS means no SHRES */ @@ -1761,7 +1748,7 @@ default_chipset: #ifdef CONFIG_FB_AMIGA_ECS case CS_ECS: - strcat(amiga_fb_name, "ECS"); + strcat(amifb_name, "ECS"); chipset = TAG_ECS; maxdepth[TAG_SHRES] = 2; maxdepth[TAG_HIRES] = 4; @@ -1785,7 +1772,7 @@ default_chipset: #ifdef CONFIG_FB_AMIGA_AGA case CS_AGA: - strcat(amiga_fb_name, "AGA"); + strcat(amifb_name, "AGA"); chipset = TAG_AGA; maxdepth[TAG_SHRES] = 8; maxdepth[TAG_HIRES] = 8; @@ -1804,7 +1791,7 @@ default_chipset: default: #ifdef CONFIG_FB_AMIGA_OCS printk("Unknown graphics chipset, defaulting to OCS\n"); - strcat(amiga_fb_name, "Unknown"); + strcat(amifb_name, "Unknown"); goto default_chipset; #else /* CONFIG_FB_AMIGA_OCS */ return mem_start; @@ -1824,26 +1811,42 @@ default_chipset: * Replace the Tag Values with the Real Pixel Clock Values */ - for (i = 0; i < NUM_PREDEF_MODES; i++) { - tag = amiga_fb_predefined[i].pixclock; + if (amifb_userdepth != -1) + amifb_default.bits_per_pixel = amifb_userdepth; + for (i = 0; i < NUM_TOTAL_MODES; i++) { + struct fb_var_screeninfo *var = &amifb_predefined[i].var; + tag = var->pixclock; if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) { - amiga_fb_predefined[i].pixclock = pixclock[tag]; - if (amiga_fb_predefined[i].bits_per_pixel > maxdepth[tag]) - amiga_fb_predefined[i].bits_per_pixel = maxdepth[tag]; + var->pixclock = pixclock[tag]; + if (var->bits_per_pixel > maxdepth[tag]) + var->bits_per_pixel = maxdepth[tag]; } } + tag = amifb_default.pixclock; + if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) { + amifb_default.pixclock = pixclock[tag]; + if (amifb_default.bits_per_pixel > maxdepth[tag]) + amifb_default.bits_per_pixel = maxdepth[tag]; + } + + /* + * These monitor specs are for a typical Amiga monitor (e.g. A1960) + */ + if (fb_info.monspecs.hfmin == 0) { + fb_info.monspecs.hfmin = 15000; + fb_info.monspecs.hfmax = 38000; + fb_info.monspecs.vfmin = 49; + fb_info.monspecs.vfmax = 90; + } - strcpy(fb_info.modename, amiga_fb_name); + strcpy(fb_info.modename, amifb_name); fb_info.changevar = NULL; fb_info.node = -1; - fb_info.fbops = &amiga_fb_ops; - fb_info.fbvar_num = NUM_TOTAL_MODES; - fb_info.fbvar = amiga_fb_predefined; + fb_info.fbops = &amifb_ops; fb_info.disp = &disp; fb_info.switch_con = &amifbcon_switch; fb_info.updatevar = &amifbcon_updatevar; fb_info.blank = &amifbcon_blank; - fb_info.setcmap = &amifbcon_setcmap; err = register_framebuffer(&fb_info); if (err < 0) @@ -1889,10 +1892,11 @@ default_chipset: custom.intena = IF_VERTB; custom.intena = IF_SETCLR | IF_COPER; - amiga_fb_set_var(&amiga_fb_predefined[0], -1); + amifb_set_var(&amifb_default, -1, &fb_info); - printk("%s frame buffer device, using %ldK of video memory\n", - fb_info.modename, videomemorysize>>10); + printk("fb%d: %s frame buffer device, using %ldK of video memory\n", + GET_FB_IDX(fb_info.node), fb_info.modename, + videomemorysize>>10); /* TODO: This driver cannot be unloaded yet */ MOD_INC_USE_COUNT; @@ -1900,17 +1904,17 @@ default_chipset: return mem_start; } -static int amifbcon_switch(int con) +static int amifbcon_switch(int con, struct fb_info *info) { /* Do we have to save the colormap? */ if (fb_display[currcon].cmap.len) fb_get_cmap(&fb_display[currcon].cmap, - &fb_display[currcon].var, 1, ami_getcolreg); + &fb_display[currcon].var, 1, ami_getcolreg, info); currcon = con; ami_set_var(&fb_display[con].var); /* Install new colormap */ - do_install_cmap(con); + do_install_cmap(con, info); return 0; } @@ -1918,7 +1922,7 @@ static int amifbcon_switch(int con) * Update the `var' structure (called by fbcon.c) */ -static int amifbcon_updatevar(int con) +static int amifbcon_updatevar(int con, struct fb_info *info) { ami_pan_var(&fb_display[con].var); return 0; @@ -1928,7 +1932,7 @@ static int amifbcon_updatevar(int con) * Blank the display. */ -static void amifbcon_blank(int blank) +static void amifbcon_blank(int blank, struct fb_info *info) { do_blank = blank ? blank : -1; } @@ -1937,23 +1941,17 @@ static void amifbcon_blank(int blank) * Set the colormap */ -static int amifbcon_setcmap(struct fb_cmap *cmap, int con) -{ - return(amiga_fb_set_cmap(cmap, 1, con)); -} - - -static void do_install_cmap(int con) +static void do_install_cmap(int con, struct fb_info *info) { if (con != currcon) return; if (fb_display[con].cmap.len) fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1, - ami_setcolreg); + ami_setcolreg, info); else - fb_set_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), + fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), &fb_display[con].var, 1, - ami_setcolreg); + ami_setcolreg, info); } static int flash_cursor(void) @@ -2039,33 +2037,9 @@ __initfunc(static void get_video_mode(const char *name)) { int i; - for (i = 1; i < NUM_PREDEF_MODES; i++) { - if (!strcmp(name, amiga_fb_modenames[i])) { - amiga_fb_predefined[0] = amiga_fb_predefined[i]; - - if (useropts.xres != -1) - amiga_fb_predefined[0].xres = useropts.xres; - if (useropts.yres != -1) - amiga_fb_predefined[0].yres = useropts.yres; - if (useropts.xres_virtual != -1) - amiga_fb_predefined[0].xres_virtual = useropts.xres_virtual; - if (useropts.yres_virtual != -1) - amiga_fb_predefined[0].yres_virtual = useropts.yres_virtual; - if (useropts.bits_per_pixel != -1) - amiga_fb_predefined[0].bits_per_pixel = useropts.bits_per_pixel; - if (useropts.left_margin != -1) - amiga_fb_predefined[0].left_margin = useropts.left_margin; - if (useropts.right_margin != -1) - amiga_fb_predefined[0].right_margin = useropts.right_margin; - if (useropts.upper_margin != -1) - amiga_fb_predefined[0].upper_margin = useropts.upper_margin; - if (useropts.lower_margin != -1) - amiga_fb_predefined[0].lower_margin = useropts.lower_margin; - if (useropts.hsync_len != -1) - amiga_fb_predefined[0].hsync_len = useropts.hsync_len; - if (useropts.vsync_len != -1) - amiga_fb_predefined[0].vsync_len = useropts.vsync_len; - + for (i = 0; i < NUM_TOTAL_MODES; i++) { + if (!strcmp(name, amifb_predefined[i].name)) { + amifb_default = amifb_predefined[i].var; amifb_usermode = i; return; } @@ -2073,23 +2047,22 @@ __initfunc(static void get_video_mode(const char *name)) } /* - * Probe the Video Modes + * Probe the Video Modes */ __initfunc(static void check_default_mode(void)) { - struct amiga_fb_par par; + struct amifb_par par; int mode; - for (mode = 0; mode < NUM_PREDEF_MODES; mode++) { - if (!ami_decode_var(&amiga_fb_predefined[mode], &par)) { - if (mode) - amiga_fb_predefined[0] = amiga_fb_predefined[mode]; + if (!ami_decode_var(&amifb_default, &par)) + return; + printk("Can't use default video mode. Probing video modes...\n"); + for (mode = 0; mode < NUM_TOTAL_MODES; mode++) + if (!ami_decode_var(&amifb_predefined[mode].var, &par)) { + amifb_default = amifb_predefined[mode].var; return; } - if (!mode) - printk("Can't use default video mode. Probing video modes...\n"); - } panic("Can't find any usable video mode"); } @@ -2141,13 +2114,19 @@ __initfunc(static char *strtoke(char *s,const char *ct)) */ static int ami_encode_fix(struct fb_fix_screeninfo *fix, - struct amiga_fb_par *par) + struct amifb_par *par) { memset(fix, 0, sizeof(struct fb_fix_screeninfo)); - strcpy(fix->id, amiga_fb_name); + strcpy(fix->id, amifb_name); fix->smem_start = (char *)videomemory; fix->smem_len = videomemorysize; +#ifdef CONFIG_FBCON_MFB + if (par->bpp == 1) { + fix->type = FB_TYPE_PACKED_PIXELS; + fix->type_aux = 0; + } else +#endif if (amifb_ilbm) { fix->type = FB_TYPE_INTERLEAVED_PLANES; fix->type_aux = par->next_line; @@ -2169,6 +2148,7 @@ static int ami_encode_fix(struct fb_fix_screeninfo *fix, fix->xpanstep = 16<<maxfmode; fix->ypanstep = 1; } + fix->accel = FB_ACCEL_AMIGABLITT; return 0; } @@ -2178,11 +2158,11 @@ static int ami_encode_fix(struct fb_fix_screeninfo *fix, */ static int ami_decode_var(struct fb_var_screeninfo *var, - struct amiga_fb_par *par) + struct amifb_par *par) { u_short clk_shift, line_shift; u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n; - u_long hrate = 0, vrate = 0; + u_int htotal, vtotal; /* * Find a matching Pixel Clock @@ -2319,8 +2299,8 @@ static int ami_decode_var(struct fb_var_screeninfo *var, DPRINTK("diwstrt_v too low for pal\n"); return -EINVAL; } - hrate = 15625; - vrate = 50; + htotal = PAL_HTOTAL>>clk_shift; + vtotal = PAL_VTOTAL>>1; if (!IS_OCS) { par->beamcon0 = BMC0_PAL; par->bplcon3 |= BPC3_BRDRBLNK; @@ -2349,8 +2329,8 @@ static int ami_decode_var(struct fb_var_screeninfo *var, DPRINTK("diwstrt_v too low for ntsc\n"); return -EINVAL; } - hrate = 15750; - vrate = 60; + htotal = NTSC_HTOTAL>>clk_shift; + vtotal = NTSC_VTOTAL>>1; if (!IS_OCS) { par->beamcon0 = 0; par->bplcon3 |= BPC3_BRDRBLNK; @@ -2409,9 +2389,8 @@ static int ami_decode_var(struct fb_var_screeninfo *var, par->beamcon0 |= BMC0_VSYTRUE; if (var->sync & FB_SYNC_COMP_HIGH_ACT) par->beamcon0 |= BMC0_CSYTRUE; - hrate = (amiga_masterclock+par->htotal/2)/par->htotal; - vrate = div2(par->vtotal) * par->htotal; - vrate = (amiga_masterclock+vrate/2)/vrate; + htotal = par->htotal>>clk_shift; + vtotal = par->vtotal>>1; } else { DPRINTK("only broadcast modes possible for ocs\n"); return -EINVAL; @@ -2546,7 +2525,8 @@ static int ami_decode_var(struct fb_var_screeninfo *var, par->crsr.spot_x = par->crsr.spot_y = 0; par->crsr.height = par->crsr.width = 0; - if (hrate < hfmin || hrate > hfmax || vrate < vfmin || vrate > vfmax) { + if (!fbmon_valid_timings(pixclock[clk_shift], htotal, vtotal, + &fb_info)) { DPRINTK("mode doesn't fit for monitor\n"); return -EINVAL; } @@ -2560,7 +2540,7 @@ static int ami_decode_var(struct fb_var_screeninfo *var, */ static int ami_encode_var(struct fb_var_screeninfo *var, - struct amiga_fb_par *par) + struct amifb_par *par) { u_short clk_shift, line_shift; int i; @@ -2606,7 +2586,6 @@ static int ami_encode_var(struct fb_var_screeninfo *var, var->height = -1; var->width = -1; - var->accel = 0; var->pixclock = pixclock[clk_shift]; @@ -2657,7 +2636,7 @@ static int ami_encode_var(struct fb_var_screeninfo *var, * Get current hardware setting */ -static void ami_get_par(struct amiga_fb_par *par) +static void ami_get_par(struct amifb_par *par) { *par = currentpar; } @@ -2676,7 +2655,7 @@ static void ami_set_var(struct fb_var_screeninfo *var) } #ifdef DEBUG -static void ami_set_par(struct amiga_fb_par *par) +static void ami_set_par(struct amifb_par *par) { do_vmode_pan = 0; do_vmode_full = 0; @@ -2695,7 +2674,7 @@ static void ami_set_par(struct amiga_fb_par *par) static void ami_pan_var(struct fb_var_screeninfo *var) { - struct amiga_fb_par *par = ¤tpar; + struct amifb_par *par = ¤tpar; par->xoffset = var->xoffset; par->yoffset = var->yoffset; @@ -2715,7 +2694,7 @@ static void ami_pan_var(struct fb_var_screeninfo *var) static int ami_update_par(void) { - struct amiga_fb_par *par = ¤tpar; + struct amifb_par *par = ¤tpar; short clk_shift, vshift, fstrt, fsize, fstop, fconst, shift, move, mod; clk_shift = par->clk_shift; @@ -2780,7 +2759,7 @@ static int ami_update_par(void) */ static int ami_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, - u_int *transp) + u_int *transp, struct fb_info *info) { if (IS_AGA) { if (regno > 255) @@ -2804,7 +2783,7 @@ static int ami_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, */ static int ami_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp) + u_int transp, struct fb_info *info) { #if defined(CONFIG_FB_AMIGA_AGA) u_short bplcon3 = currentpar.bplcon3; @@ -2867,7 +2846,7 @@ static int ami_setcolreg(u_int regno, u_int red, u_int green, u_int blue, static void ami_update_display(void) { - struct amiga_fb_par *par = ¤tpar; + struct amifb_par *par = ¤tpar; custom.bplcon1 = par->bplcon1; custom.bpl1mod = par->bpl1mod; @@ -2882,7 +2861,7 @@ static void ami_update_display(void) static void ami_init_display(void) { - struct amiga_fb_par *par = ¤tpar; + struct amifb_par *par = ¤tpar; custom.bplcon0 = par->bplcon0 & ~BPC0_LACE; custom.bplcon2 = (IS_OCS ? 0 : BPC2_KILLEHB) | BPC2_PF2P2 | BPC2_PF1P2; @@ -2938,7 +2917,7 @@ static void ami_init_display(void) static void ami_do_blank(void) { - struct amiga_fb_par *par = ¤tpar; + struct amifb_par *par = ¤tpar; #if defined(CONFIG_FB_AMIGA_AGA) u_short bplcon3 = par->bplcon3; #endif @@ -3023,7 +3002,7 @@ static void ami_do_blank(void) static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix, int con) { - struct amiga_fb_par *par = ¤tpar; + struct amifb_par *par = ¤tpar; fix->crsr_width = fix->crsr_xsize = par->crsr.width; fix->crsr_height = fix->crsr_ysize = par->crsr.height; @@ -3034,7 +3013,7 @@ static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix, int con) static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data, int con) { - struct amiga_fb_par *par = ¤tpar; + struct amifb_par *par = ¤tpar; register u_short *lspr, *sspr; #ifdef __mc68000__ register u_long datawords asm ("d2"); @@ -3109,7 +3088,7 @@ static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data, i static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data, int con) { - struct amiga_fb_par *par = ¤tpar; + struct amifb_par *par = ¤tpar; register u_short *lspr, *sspr; #ifdef __mc68000__ register u_long datawords asm ("d2"); @@ -3228,7 +3207,7 @@ static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data, i static int ami_get_cursorstate(struct fb_cursorstate *state, int con) { - struct amiga_fb_par *par = ¤tpar; + struct amifb_par *par = ¤tpar; state->xoffset = par->crsr.crsr_x; state->yoffset = par->crsr.crsr_y; @@ -3238,7 +3217,7 @@ static int ami_get_cursorstate(struct fb_cursorstate *state, int con) static int ami_set_cursorstate(struct fb_cursorstate *state, int con) { - struct amiga_fb_par *par = ¤tpar; + struct amifb_par *par = ¤tpar; par->crsr.crsr_x = state->xoffset; par->crsr.crsr_y = state->yoffset; @@ -3250,7 +3229,7 @@ static int ami_set_cursorstate(struct fb_cursorstate *state, int con) static void ami_set_sprite(void) { - struct amiga_fb_par *par = ¤tpar; + struct amifb_par *par = ¤tpar; copins *copl, *cops; u_short hs, vs, ve; u_long pl, ps, pt; @@ -3333,7 +3312,7 @@ __initfunc(static void ami_init_copper(void)) static void ami_reinit_copper(void) { - struct amiga_fb_par *par = ¤tpar; + struct amifb_par *par = ¤tpar; copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0; copdisplay.wait->l = CWAIT(32, par->diwstrt_v-4); @@ -3345,7 +3324,7 @@ static void ami_reinit_copper(void) static void ami_build_copper(void) { - struct amiga_fb_par *par = ¤tpar; + struct amifb_par *par = ¤tpar; copins *copl, *cops; u_long p; @@ -3422,7 +3401,7 @@ static void ami_build_copper(void) static void ami_rebuild_copper(void) { - struct amiga_fb_par *par = ¤tpar; + struct amifb_par *par = ¤tpar; copins *copl, *cops; u_short line, h_end1, h_end2; short i; @@ -3507,7 +3486,7 @@ static void ami_rebuild_copper(void) #ifdef MODULE int init_module(void) { - return(amiga_fb_init(NULL)); + return(amifb_init(NULL)); } void cleanup_module(void) diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c index ada071f2b..ff7aedfe7 100644 --- a/drivers/video/atafb.c +++ b/drivers/video/atafb.c @@ -66,10 +66,31 @@ #include <asm/atarihw.h> #include <asm/atariints.h> +#include <asm/atari_stram.h> #include <linux/fb.h> #include <asm/atarikb.h> +#ifdef CONFIG_FBCON_CFB8 +#include "fbcon-cfb8.h" +#endif +#ifdef CONFIG_FBCON_CFB16 +#include "fbcon-cfb16.h" +#endif +#ifdef CONFIG_FBCON_IPLAN2P2 +#include "fbcon-iplan2p2.h" +#endif +#ifdef CONFIG_FBCON_IPLAN2P4 +#include "fbcon-iplan2p4.h" +#endif +#ifdef CONFIG_FBCON_IPLAN2P8 +#include "fbcon-iplan2p8.h" +#endif +#ifdef CONFIG_FBCON_MFB +#include "fbcon-mfb.h" +#endif + + #define SWITCH_ACIA 0x01 /* modes for switch on OverScan */ #define SWITCH_SND6 0x40 #define SWITCH_SND7 0x80 @@ -92,16 +113,18 @@ static int use_hwscroll = 1; static int sttt_xres=640,st_yres=400,tt_yres=480; static int sttt_xres_virtual=640,sttt_yres_virtual=400; static int ovsc_offset=0, ovsc_addlen=0; -int ovsc_switchmode=0; -static struct atari_fb_par { +static struct atafb_par { unsigned long screen_base; int yres_virtual; +#if defined ATAFB_TT || defined ATAFB_STE union { struct { int mode; int sync; } tt, st; +#endif +#ifdef ATAFB_FALCON struct falcon_hw { /* Here are fields for storing a video mode, as direct * parameters for the hardware. @@ -121,6 +144,7 @@ static struct atari_fb_par { short ste_mode; short bpp; } falcon; +#endif /* Nothing needed for external mode */ } hw; } current_par; @@ -130,6 +154,7 @@ static struct atari_fb_par { * hardware extensions (e.g. ScreenBlaster) */ static int DontCalcRes = 0; +#ifdef ATAFB_FALCON #define HHT hw.falcon.hht #define HBB hw.falcon.hbb #define HBE hw.falcon.hbe @@ -150,6 +175,7 @@ static int DontCalcRes = 0; #define VMO_DOUBLE 0x01 #define VMO_INTER 0x02 #define VMO_PREMASK 0x0c +#endif static struct fb_info fb_info; @@ -239,26 +265,22 @@ extern int fontheight_8x16; extern int fontwidth_8x16; extern unsigned char fontdata_8x16[]; -/* import first 16 colors from fbcon.c */ -extern unsigned short packed16_cmap[16]; - - /* ++roman: This structure abstracts from the underlying hardware (ST(e), * TT, or Falcon. * * int (*detect)( void ) * This function should detect the current video mode settings and - * store them in atari_fb_predefined[0] for later reference by the + * store them in atafb_predefined[0] for later reference by the * user. Return the index+1 of an equivalent predefined mode or 0 * if there is no such. * * int (*encode_fix)( struct fb_fix_screeninfo *fix, - * struct atari_fb_par *par ) + * struct atafb_par *par ) * This function should fill in the 'fix' structure based on the * values in the 'par' structure. * * int (*decode_var)( struct fb_var_screeninfo *var, - * struct atari_fb_par *par ) + * struct atafb_par *par ) * Get the video params out of 'var'. If a value doesn't fit, round * it up, if it's too big, return EINVAL. * Round up in the following order: bits_per_pixel, xres, yres, @@ -266,26 +288,26 @@ extern unsigned short packed16_cmap[16]; * horizontal timing, vertical timing. * * int (*encode_var)( struct fb_var_screeninfo *var, - * struct atari_fb_par *par ); + * struct atafb_par *par ); * Fill the 'var' structure based on the values in 'par' and maybe * other values read out of the hardware. * - * void (*get_par)( struct atari_fb_par *par ) + * void (*get_par)( struct atafb_par *par ) * Fill the hardware's 'par' structure. * - * void (*set_par)( struct atari_fb_par *par ) + * void (*set_par)( struct atafb_par *par ) * Set the hardware according to 'par'. * * int (*setcolreg)( unsigned regno, unsigned red, * unsigned green, unsigned blue, - * unsigned transp ) + * unsigned transp, struct fb_info *info ) * Set a single color register. The values supplied are already * rounded down to the hardware's capabilities (according to the * entries in the var structure). Return != 0 for invalid regno. * * int (*getcolreg)( unsigned regno, unsigned *red, * unsigned *green, unsigned *blue, - * unsigned *transp ) + * unsigned *transp, struct fb_info *info ) * Read a single color register and split it into * colors/transparent. Return != 0 for invalid regno. * @@ -305,23 +327,23 @@ extern unsigned short packed16_cmap[16]; static struct fb_hwswitch { int (*detect)( void ); int (*encode_fix)( struct fb_fix_screeninfo *fix, - struct atari_fb_par *par ); + struct atafb_par *par ); int (*decode_var)( struct fb_var_screeninfo *var, - struct atari_fb_par *par ); + struct atafb_par *par ); int (*encode_var)( struct fb_var_screeninfo *var, - struct atari_fb_par *par ); - void (*get_par)( struct atari_fb_par *par ); - void (*set_par)( struct atari_fb_par *par ); + struct atafb_par *par ); + void (*get_par)( struct atafb_par *par ); + void (*set_par)( struct atafb_par *par ); int (*getcolreg)( unsigned regno, unsigned *red, unsigned *green, unsigned *blue, - unsigned *transp ); + unsigned *transp, struct fb_info *info ); int (*setcolreg)( unsigned regno, unsigned red, unsigned green, unsigned blue, - unsigned transp ); + unsigned transp, struct fb_info *info ); void (*set_screen_base)( unsigned long s_base ); int (*blank)( int blank_mode ); int (*pan_display)( struct fb_var_screeninfo *var, - struct atari_fb_par *par); + struct atafb_par *par); } *fbhw; static char *autodetect_names[] = {"autodetect", NULL}; @@ -337,15 +359,6 @@ static char *vga16_names[] = {"vga16", "default3", NULL}; static char *vga256_names[] = {"vga256", NULL}; static char *falh2_names[] = {"falh2", NULL}; static char *falh16_names[] = {"falh16", NULL}; -static char *user0_names[] = {"user0", NULL}; -static char *user1_names[] = {"user1", NULL}; -static char *user2_names[] = {"user2", NULL}; -static char *user3_names[] = {"user3", NULL}; -static char *user4_names[] = {"user4", NULL}; -static char *user5_names[] = {"user5", NULL}; -static char *user6_names[] = {"user6", NULL}; -static char *user7_names[] = {"user7", NULL}; -static char *dummy_names[] = {"dummy", NULL}; static char **fb_var_names[] = { /* Writing the name arrays directly in this array (via "(char *[]){...}") @@ -365,22 +378,11 @@ static char **fb_var_names[] = { vga256_names, falh2_names, falh16_names, - dummy_names, dummy_names, dummy_names, dummy_names, - dummy_names, dummy_names, dummy_names, dummy_names, - dummy_names, dummy_names, - user0_names, - user1_names, - user2_names, - user3_names, - user4_names, - user5_names, - user6_names, - user7_names, NULL /* ,NULL */ /* this causes a sigsegv on my gcc-2.5.8 */ }; -static struct fb_var_screeninfo atari_fb_predefined[] = { +static struct fb_var_screeninfo atafb_predefined[] = { /* * yres_virtual==0 means use hw-scrolling if possible, else yres */ @@ -436,53 +438,9 @@ static struct fb_var_screeninfo atari_fb_predefined[] = { 896, 608, 896, 0, 0, 0, 4, 0, {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, - /* Minor 14..23 free for more standard video modes */ - { 0, }, - { 0, }, - { 0, }, - { 0, }, - { 0, }, - { 0, }, - { 0, }, - { 0, }, - { 0, }, - { 0, }, - /* Minor 24..31 reserved for user defined video modes */ - { /* user0, initialized to Rx;y;d from commandline, if supplied */ - 0, 0, 0, 0, 0, 0, 0, 0, - {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, - { /* user1 */ - 0, 0, 0, 0, 0, 0, 0, 0, - {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, - { /* user2 */ - 0, 0, 0, 0, 0, 0, 0, 0, - {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, - { /* user3 */ - 0, 0, 0, 0, 0, 0, 0, 0, - {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, - { /* user4 */ - 0, 0, 0, 0, 0, 0, 0, 0, - {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, - { /* user5 */ - 0, 0, 0, 0, 0, 0, 0, 0, - {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, - { /* user6 */ - 0, 0, 0, 0, 0, 0, 0, 0, - {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, - { /* user7 */ - 0, 0, 0, 0, 0, 0, 0, 0, - {0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0}, - 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 } }; -static int num_atari_fb_predefined=arraysize(atari_fb_predefined); +static int num_atafb_predefined=arraysize(atafb_predefined); static int @@ -492,7 +450,7 @@ get_video_mode(char *vname) char **name; int i; name_list=fb_var_names; - for (i = 0 ; i < num_atari_fb_predefined ; i++) { + for (i = 0 ; i < num_atafb_predefined ; i++) { name=*(name_list++); if (! name || ! *name) break; @@ -512,7 +470,7 @@ get_video_mode(char *vname) #ifdef ATAFB_TT static int tt_encode_fix( struct fb_fix_screeninfo *fix, - struct atari_fb_par *par ) + struct atafb_par *par ) { int mode; @@ -539,7 +497,7 @@ static int tt_encode_fix( struct fb_fix_screeninfo *fix, static int tt_decode_var( struct fb_var_screeninfo *var, - struct atari_fb_par *par ) + struct atafb_par *par ) { int xres=var->xres; int yres=var->yres; @@ -620,7 +578,7 @@ static int tt_decode_var( struct fb_var_screeninfo *var, } static int tt_encode_var( struct fb_var_screeninfo *var, - struct atari_fb_par *par ) + struct atafb_par *par ) { int linelen, i; var->red.offset=0; @@ -716,7 +674,7 @@ static int tt_encode_var( struct fb_var_screeninfo *var, } -static void tt_get_par( struct atari_fb_par *par ) +static void tt_get_par( struct atafb_par *par ) { unsigned long addr; par->hw.tt.mode=shifter_tt.tt_shiftmode; @@ -727,7 +685,7 @@ static void tt_get_par( struct atari_fb_par *par ) par->screen_base = PTOV(addr); } -static void tt_set_par( struct atari_fb_par *par ) +static void tt_set_par( struct atafb_par *par ) { shifter_tt.tt_shiftmode=par->hw.tt.mode; shifter.syncmode=par->hw.tt.sync; @@ -739,7 +697,7 @@ static void tt_set_par( struct atari_fb_par *par ) static int tt_getcolreg( unsigned regno, unsigned *red, unsigned *green, unsigned *blue, - unsigned *transp ) + unsigned *transp, struct fb_info *info ) { if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH) regno += 254; @@ -756,7 +714,7 @@ static int tt_getcolreg( unsigned regno, unsigned *red, static int tt_setcolreg( unsigned regno, unsigned red, unsigned green, unsigned blue, - unsigned transp ) + unsigned transp, struct fb_info *info ) { if ((shifter_tt.tt_shiftmode & TT_SHIFTER_MODEMASK) == TT_SHIFTER_STHIGH) regno += 254; @@ -772,7 +730,7 @@ static int tt_setcolreg( unsigned regno, unsigned red, static int tt_detect( void ) -{ struct atari_fb_par par; +{ struct atafb_par par; /* Determine the connected monitor: The DMA sound must be * disabled before reading the MFP GPIP, because the Sound @@ -789,7 +747,7 @@ static int tt_detect( void ) mono_moni = (mfp.par_dt_reg & 0x80) == 0; tt_get_par(&par); - tt_encode_var(&atari_fb_predefined[0], &par); + tt_encode_var(&atafb_predefined[0], &par); return 1; } @@ -807,10 +765,6 @@ static int f030_bus_width; /* Falcon ram bus width (for vid_control) */ #define F_MON_VGA 2 #define F_MON_TV 3 -/* Multisync monitor capabilities */ -/* Atari-TOS defaults if no boot option present */ -static long vfmin=58, vfmax=62, hfmin=31000, hfmax=32000; - static struct pixel_clock { unsigned long f; /* f/[Hz] */ unsigned long t; /* t/[ps] (=1/f) */ @@ -837,7 +791,7 @@ static inline int hxx_prescale(struct falcon_hw *hw) } static int falcon_encode_fix( struct fb_fix_screeninfo *fix, - struct atari_fb_par *par ) + struct atafb_par *par ) { strcpy(fix->id, "Atari Builtin"); fix->smem_start = (char *)real_screen_base; @@ -867,7 +821,7 @@ static int falcon_encode_fix( struct fb_fix_screeninfo *fix, static int falcon_decode_var( struct fb_var_screeninfo *var, - struct atari_fb_par *par ) + struct atafb_par *par ) { int bpp = var->bits_per_pixel; int xres = var->xres; @@ -943,7 +897,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, if (mon_type == F_MON_SM || DontCalcRes) { /* Skip all calculations. VGA/TV/SC1224 only supported. */ - struct fb_var_screeninfo *myvar = &atari_fb_predefined[0]; + struct fb_var_screeninfo *myvar = &atafb_predefined[0]; if (bpp > myvar->bits_per_pixel || var->xres > myvar->xres || @@ -1069,11 +1023,14 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, /* Choose master pixelclock depending on hor. timing */ plen = 1 * xstretch; - if ((plen * xres + f25.right+f25.hsync+f25.left) * hfmin < f25.f) + if ((plen * xres + f25.right+f25.hsync+f25.left) * + fb_info.monspecs.hfmin < f25.f) pclock = &f25; - else if ((plen * xres + f32.right+f32.hsync+f32.left) * hfmin < f32.f) + else if ((plen * xres + f32.right+f32.hsync+f32.left) * + fb_info.monspecs.hfmin < f32.f) pclock = &f32; - else if ((plen * xres + fext.right+fext.hsync+fext.left) * hfmin < fext.f + else if ((plen * xres + fext.right+fext.hsync+fext.left) * + fb_info.monspecs.hfmin < fext.f && fext.f) pclock = &fext; else @@ -1246,14 +1203,14 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, /* check hor. frequency */ hfreq = pclock->f / ((par->HHT+2)*prescale*2); - if (hfreq > hfmax && mon_type!=F_MON_VGA) { + if (hfreq > fb_info.monspecs.hfmax && mon_type!=F_MON_VGA) { /* ++guenther: ^^^^^^^^^^^^^^^^^^^ can't remember why I did this */ /* Too high -> enlarge margin */ left_margin += 1; right_margin += 1; goto again; } - if (hfreq > hfmax || hfreq < hfmin) + if (hfreq > fb_info.monspecs.hfmax || hfreq < fb_info.monspecs.hfmin) return -EINVAL; /* Vxx-registers */ @@ -1282,45 +1239,52 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, /* V-frequency check, hope I didn't create any loop here. */ /* Interlace and doubleline are mutually exclusive. */ vfreq = (hfreq * 2) / (par->VFT + 1); - if (vfreq > vfmax && !doubleline && !interlace) { + if (vfreq > fb_info.monspecs.vfmax && !doubleline && !interlace) { /* Too high -> try again with doubleline */ doubleline = 1; goto again; } - else if (vfreq < vfmin && !interlace && !doubleline) { + else if (vfreq < fb_info.monspecs.vfmin && !interlace && !doubleline) { /* Too low -> try again with interlace */ interlace = 1; goto again; } - else if (vfreq < vfmin && doubleline) { + else if (vfreq < fb_info.monspecs.vfmin && doubleline) { /* Doubleline too low -> clear doubleline and enlarge margins */ int lines; doubleline = 0; - for (lines=0; (hfreq*2)/(par->VFT+1+4*lines-2*yres)>vfmax; lines++) + for (lines=0; + (hfreq*2)/(par->VFT+1+4*lines-2*yres)>fb_info.monspecs.vfmax; + lines++) ; upper_margin += lines; lower_margin += lines; goto again; } - else if (vfreq > vfmax && doubleline) { + else if (vfreq > fb_info.monspecs.vfmax && doubleline) { /* Doubleline too high -> enlarge margins */ int lines; - for (lines=0; (hfreq*2)/(par->VFT+1+4*lines)>vfmax; lines+=2) + for (lines=0; + (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax; + lines+=2) ; upper_margin += lines; lower_margin += lines; goto again; } - else if (vfreq > vfmax && interlace) { + else if (vfreq > fb_info.monspecs.vfmax && interlace) { /* Interlace, too high -> enlarge margins */ int lines; - for (lines=0; (hfreq*2)/(par->VFT+1+4*lines)>vfmax; lines++) + for (lines=0; + (hfreq*2)/(par->VFT+1+4*lines)>fb_info.monspecs.vfmax; + lines++) ; upper_margin += lines; lower_margin += lines; goto again; } - else if (vfreq < vfmin || vfreq > vfmax) + else if (vfreq < fb_info.monspecs.vfmin || + vfreq > fb_info.monspecs.vfmax) return -EINVAL; set_screen_base: @@ -1339,7 +1303,7 @@ static int falcon_decode_var( struct fb_var_screeninfo *var, } static int falcon_encode_var( struct fb_var_screeninfo *var, - struct atari_fb_par *par ) + struct atafb_par *par ) { /* !!! only for VGA !!! */ int linelen, i; @@ -1425,12 +1389,13 @@ static int falcon_encode_var( struct fb_var_screeninfo *var, var->transp.msb_right=0; linelen = var->xres_virtual * var->bits_per_pixel / 8; - if (screen_len) + if (screen_len) { if (par->yres_virtual) var->yres_virtual = par->yres_virtual; else /* yres_virtual==0 means use maximum */ var->yres_virtual = screen_len / linelen; + } else { if (hwscroll < 0) var->yres_virtual = 2 * var->yres; @@ -1506,7 +1471,7 @@ static int f_change_mode = 0; static struct falcon_hw f_new_mode; static int f_pan_display = 0; -static void falcon_get_par( struct atari_fb_par *par ) +static void falcon_get_par( struct atafb_par *par ) { unsigned long addr; struct falcon_hw *hw = &par->hw.falcon; @@ -1543,7 +1508,7 @@ static void falcon_get_par( struct atari_fb_par *par ) ((hw->f_shift & 0x510)==0 && hw->st_shift==0x200); } -static void falcon_set_par( struct atari_fb_par *par ) +static void falcon_set_par( struct atafb_par *par ) { f_change_mode = 0; @@ -1627,7 +1592,7 @@ static void falcon_vbl_switcher( int irq, void *dummy, struct pt_regs *fp ) static int falcon_pan_display( struct fb_var_screeninfo *var, - struct atari_fb_par *par ) + struct atafb_par *par ) { int xoffset; int bpp = fb_display[currcon].var.bits_per_pixel; @@ -1659,7 +1624,7 @@ static int falcon_pan_display( struct fb_var_screeninfo *var, static int falcon_getcolreg( unsigned regno, unsigned *red, unsigned *green, unsigned *blue, - unsigned *transp ) + unsigned *transp, struct fb_info *info ) { unsigned long col; if (regno > 255) @@ -1679,7 +1644,7 @@ static int falcon_getcolreg( unsigned regno, unsigned *red, static int falcon_setcolreg( unsigned regno, unsigned red, unsigned green, unsigned blue, - unsigned transp ) + unsigned transp, struct fb_info *info ) { if (regno > 255) return 1; @@ -1690,7 +1655,7 @@ static int falcon_setcolreg( unsigned regno, unsigned red, (((green & 0xe) >> 1) | ((green & 1) << 3) << 4) | ((blue & 0xe) >> 1) | ((blue & 1) << 3); #ifdef CONFIG_FBCON_CFB16 - packed16_cmap[regno] = (red << 11) | (green << 5) | blue; + fbcon_cfb16_cmap[regno] = (red << 11) | (green << 5) | blue; #endif } return 0; @@ -1738,7 +1703,7 @@ static int falcon_blank( int blank_mode ) static int falcon_detect( void ) { - struct atari_fb_par par; + struct atafb_par par; unsigned char fhw; /* Determine connected monitor and set monitor parameters */ @@ -1748,18 +1713,18 @@ static int falcon_detect( void ) f030_bus_width = fhw << 6 & 0x80; switch (mon_type) { case F_MON_SM: - vfmin = 70; - vfmax = 72; - hfmin = 35713; - hfmax = 35715; + fb_info.monspecs.vfmin = 70; + fb_info.monspecs.vfmax = 72; + fb_info.monspecs.hfmin = 35713; + fb_info.monspecs.hfmax = 35715; break; case F_MON_SC: case F_MON_TV: /* PAL...NTSC */ - vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */ - vfmax = 60; - hfmin = 15620; - hfmax = 15755; + fb_info.monspecs.vfmin = 49; /* not 50, since TOS defaults to 49.9x Hz */ + fb_info.monspecs.vfmax = 60; + fb_info.monspecs.hfmin = 15620; + fb_info.monspecs.hfmax = 15755; break; } /* initialize hsync-len */ @@ -1769,7 +1734,7 @@ static int falcon_detect( void ) fext.hsync = h_syncs[mon_type] / fext.t; falcon_get_par(&par); - falcon_encode_var(&atari_fb_predefined[0], &par); + falcon_encode_var(&atafb_predefined[0], &par); /* Detected mode is always the "autodetect" slot */ return 1; @@ -1782,7 +1747,7 @@ static int falcon_detect( void ) #ifdef ATAFB_STE static int stste_encode_fix( struct fb_fix_screeninfo *fix, - struct atari_fb_par *par ) + struct atafb_par *par ) { int mode; @@ -1813,7 +1778,7 @@ static int stste_encode_fix( struct fb_fix_screeninfo *fix, static int stste_decode_var( struct fb_var_screeninfo *var, - struct atari_fb_par *par ) + struct atafb_par *par ) { int xres=var->xres; int yres=var->yres; @@ -1871,7 +1836,7 @@ static int stste_decode_var( struct fb_var_screeninfo *var, } static int stste_encode_var( struct fb_var_screeninfo *var, - struct atari_fb_par *par ) + struct atafb_par *par ) { int linelen, i; var->red.offset=0; @@ -1922,12 +1887,13 @@ static int stste_encode_var( struct fb_var_screeninfo *var, if (! use_hwscroll) var->yres_virtual=var->yres; - else if (screen_len) + else if (screen_len) { if (par->yres_virtual) var->yres_virtual = par->yres_virtual; else /* yres_virtual==0 means use maximum */ var->yres_virtual = screen_len / linelen; + } else { if (hwscroll < 0) var->yres_virtual = 2 * var->yres; @@ -1948,7 +1914,7 @@ static int stste_encode_var( struct fb_var_screeninfo *var, } -static void stste_get_par( struct atari_fb_par *par ) +static void stste_get_par( struct atafb_par *par ) { unsigned long addr; par->hw.st.mode=shifter_tt.st_shiftmode; @@ -1960,7 +1926,7 @@ static void stste_get_par( struct atari_fb_par *par ) par->screen_base = PTOV(addr); } -static void stste_set_par( struct atari_fb_par *par ) +static void stste_set_par( struct atafb_par *par ) { shifter_tt.st_shiftmode=par->hw.st.mode; shifter.syncmode=par->hw.st.sync; @@ -1972,7 +1938,7 @@ static void stste_set_par( struct atari_fb_par *par ) static int stste_getcolreg( unsigned regno, unsigned *red, unsigned *green, unsigned *blue, - unsigned *transp ) + unsigned *transp, struct fb_info *info ) { unsigned col; if (regno > 15) @@ -1995,7 +1961,7 @@ static int stste_getcolreg( unsigned regno, unsigned *red, static int stste_setcolreg( unsigned regno, unsigned red, unsigned green, unsigned blue, - unsigned transp ) + unsigned transp, struct fb_info *info ) { if (regno > 15) return 1; @@ -2015,7 +1981,7 @@ static int stste_setcolreg( unsigned regno, unsigned red, static int stste_detect( void ) -{ struct atari_fb_par par; +{ struct atafb_par par; /* Determine the connected monitor: The DMA sound must be * disabled before reading the MFP GPIP, because the Sound @@ -2028,7 +1994,7 @@ static int stste_detect( void ) mono_moni = (mfp.par_dt_reg & 0x80) == 0; stste_get_par(&par); - stste_encode_var(&atari_fb_predefined[0], &par); + stste_encode_var(&atafb_predefined[0], &par); if (!ATARIHW_PRESENT(EXTD_SHIFTER)) use_hwscroll = 0; @@ -2067,12 +2033,12 @@ static void stste_set_screen_base(unsigned long s_base) #define SYNC_DELAY (mono_moni ? 1500 : 2000) /* SWITCH_ACIA may be used for Falcon (ScreenBlaster III internal!) */ -static void st_ovsc_switch(int switchmode) +static void st_ovsc_switch(void) { unsigned long flags; register unsigned char old, new; - if ((switchmode & (SWITCH_ACIA | SWITCH_SND6 | SWITCH_SND7)) == 0) + if (!(atari_switches & ATARI_SWITCH_OVSC_MASK)) return; save_flags(flags); cli(); @@ -2093,11 +2059,15 @@ static void st_ovsc_switch(int switchmode) mfp.tim_ct_b = 0x10; udelay(SYNC_DELAY); - if (switchmode == SWITCH_ACIA) - acia.key_ctrl = (ACIA_DIV64|ACIA_D8N1S|ACIA_RHTID|ACIA_RIE); - else { + if (atari_switches & ATARI_SWITCH_OVSC_IKBD) + acia.key_ctrl = ACIA_DIV64 | ACIA_D8N1S | ACIA_RHTID | ACIA_RIE; + if (atari_switches & ATARI_SWITCH_OVSC_MIDI) + acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | ACIA_RHTID; + if (atari_switches & (ATARI_SWITCH_OVSC_SND6|ATARI_SWITCH_OVSC_SND7)) { sound_ym.rd_data_reg_sel = 14; - sound_ym.wd_data = sound_ym.rd_data_reg_sel | switchmode; + sound_ym.wd_data = sound_ym.rd_data_reg_sel | + ((atari_switches&ATARI_SWITCH_OVSC_SND6) ? 0x40:0) | + ((atari_switches&ATARI_SWITCH_OVSC_SND7) ? 0x80:0); } restore_flags(flags); } @@ -2107,7 +2077,7 @@ static void st_ovsc_switch(int switchmode) #ifdef ATAFB_EXT static int ext_encode_fix( struct fb_fix_screeninfo *fix, - struct atari_fb_par *par ) + struct atafb_par *par ) { strcpy(fix->id,"Unknown Extern"); @@ -2157,9 +2127,9 @@ static int ext_encode_fix( struct fb_fix_screeninfo *fix, static int ext_decode_var( struct fb_var_screeninfo *var, - struct atari_fb_par *par ) + struct atafb_par *par ) { - struct fb_var_screeninfo *myvar = &atari_fb_predefined[0]; + struct fb_var_screeninfo *myvar = &atafb_predefined[0]; if (var->bits_per_pixel > myvar->bits_per_pixel || var->xres > myvar->xres || @@ -2173,7 +2143,7 @@ static int ext_decode_var( struct fb_var_screeninfo *var, static int ext_encode_var( struct fb_var_screeninfo *var, - struct atari_fb_par *par ) + struct atafb_par *par ) { int i; @@ -2217,12 +2187,12 @@ static int ext_encode_var( struct fb_var_screeninfo *var, } -static void ext_get_par( struct atari_fb_par *par ) +static void ext_get_par( struct atafb_par *par ) { par->screen_base = external_addr; } -static void ext_set_par( struct atari_fb_par *par ) +static void ext_set_par( struct atafb_par *par ) { } @@ -2238,10 +2208,8 @@ static void ext_set_par( struct atari_fb_par *par ) static int ext_getcolreg( unsigned regno, unsigned *red, unsigned *green, unsigned *blue, - unsigned *transp ) - -{ unsigned char colmask = (1 << external_bitspercol) - 1; - + unsigned *transp, struct fb_info *info ) +{ if (! external_vgaiobase) return 1; @@ -2254,7 +2222,7 @@ static int ext_getcolreg( unsigned regno, unsigned *red, static int ext_setcolreg( unsigned regno, unsigned red, unsigned green, unsigned blue, - unsigned transp ) + unsigned transp, struct fb_info *info ) { unsigned char colmask = (1 << external_bitspercol) - 1; @@ -2292,8 +2260,8 @@ static int ext_setcolreg( unsigned regno, unsigned red, static int ext_detect( void ) { - struct fb_var_screeninfo *myvar = &atari_fb_predefined[0]; - struct atari_fb_par dummy_par; + struct fb_var_screeninfo *myvar = &atafb_predefined[0]; + struct atafb_par dummy_par; myvar->xres = external_xres; myvar->xres_virtual = external_xres_virtual; @@ -2319,7 +2287,7 @@ static void set_screen_base(unsigned long s_base) static int pan_display( struct fb_var_screeninfo *var, - struct atari_fb_par *par ) + struct atafb_par *par ) { if (!fbhw->set_screen_base || (!ATARIHW_PRESENT(EXTD_SHIFTER) && var->xoffset)) @@ -2369,7 +2337,7 @@ static struct fb_hwswitch ext_switch = { -static void atari_fb_get_par( struct atari_fb_par *par ) +static void atafb_get_par( struct atafb_par *par ) { if (current_par_valid) { *par=current_par; @@ -2379,7 +2347,7 @@ static void atari_fb_get_par( struct atari_fb_par *par ) } -static void atari_fb_set_par( struct atari_fb_par *par ) +static void atafb_set_par( struct atafb_par *par ) { fbhw->set_par(par); current_par=*par; @@ -2396,7 +2364,7 @@ static void atari_fb_set_par( struct atari_fb_par *par ) /* used for hardware scrolling */ static int -fb_update_var(int con) +fb_update_var(int con, struct fb_info *info) { int off=fb_display[con].var.yoffset*fb_display[con].var.xres_virtual* fb_display[con].var.bits_per_pixel>>3; @@ -2412,12 +2380,12 @@ static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive) { int err,activate; - struct atari_fb_par par; + struct atafb_par par; if ((err=fbhw->decode_var(var, &par))) return err; activate=var->activate; if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) - atari_fb_set_par(&par); + atafb_set_par(&par); fbhw->encode_var(var, &par); var->activate=activate; return 0; @@ -2426,17 +2394,17 @@ do_fb_set_var(struct fb_var_screeninfo *var, int isactive) /* Functions for handling colormap */ static void -do_install_cmap(int con) +do_install_cmap(int con, struct fb_info *info) { if (con != currcon) return; if (fb_display[con].cmap.len) fb_set_cmap(&fb_display[con].cmap, &(fb_display[con].var), 1, - fbhw->setcolreg); + fbhw->setcolreg, info); else - fb_set_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), + fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), &(fb_display[con].var), 1, - fbhw->setcolreg); + fbhw->setcolreg, info); } @@ -2444,7 +2412,7 @@ do_install_cmap(int con) * Open/Release the frame buffer device */ -static int atari_fb_open(int fbidx) +static int atafb_open(struct fb_info *info) { /* * Nothing, only a usage count for the moment @@ -2454,7 +2422,7 @@ static int atari_fb_open(int fbidx) return(0); } -static int atari_fb_release(int fbidx) +static int atafb_release(struct fb_info *info) { MOD_DEC_USE_COUNT; return(0); @@ -2462,11 +2430,11 @@ static int atari_fb_release(int fbidx) static int -atari_fb_get_fix(struct fb_fix_screeninfo *fix, int con) +atafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) { - struct atari_fb_par par; + struct atafb_par par; if (con == -1) - atari_fb_get_par(&par); + atafb_get_par(&par); else fbhw->decode_var(&fb_display[con].var,&par); memset(fix, 0, sizeof(struct fb_fix_screeninfo)); @@ -2474,11 +2442,11 @@ atari_fb_get_fix(struct fb_fix_screeninfo *fix, int con) } static int -atari_fb_get_var(struct fb_var_screeninfo *var, int con) +atafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) { - struct atari_fb_par par; + struct atafb_par par; if (con == -1) { - atari_fb_get_par(&par); + atafb_get_par(&par); fbhw->encode_var(var, &par); } else @@ -2487,9 +2455,10 @@ atari_fb_get_var(struct fb_var_screeninfo *var, int con) } static void -atari_fb_set_disp(int con) +atafb_set_disp(int con, struct fb_info *info) { struct fb_fix_screeninfo fix; + struct fb_var_screeninfo var; struct display *display; if (con >= 0) @@ -2497,7 +2466,8 @@ atari_fb_set_disp(int con) else display = &disp; /* used during initialization */ - atari_fb_get_fix(&fix, con); + atafb_get_fix(&fix, con, info); + atafb_get_var(&var, con, info); if (con == -1) con=0; display->screen_base = (u_char *)fix.smem_start; @@ -2514,10 +2484,50 @@ atari_fb_set_disp(int con) display->can_soft_blank = 1; display->inverse = (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse); + switch (fix.type) { + case FB_TYPE_INTERLEAVED_PLANES: + switch (var.bits_per_pixel) { +#ifdef CONFIG_FBCON_IPLAN2P2 + case 2: + display->dispsw = &fbcon_iplan2p2; + break; +#endif +#ifdef CONFIG_FBCON_IPLAN2P4 + case 4: + display->dispsw = &fbcon_iplan2p4; + break; +#endif +#ifdef CONFIG_FBCON_IPLAN2P8 + case 8: + display->dispsw = &fbcon_iplan2p8; + break; +#endif + } + break; + case FB_TYPE_PACKED_PIXELS: + switch (var.bits_per_pixel) { +#ifdef CONFIG_FBCON_MFB + case 1: + display->dispsw = &fbcon_mfb; + break; +#endif +#ifdef CONFIG_FBCON_CFB8 + case 8: + display->dispsw = &fbcon_cfb8; + break; +#endif +#ifdef CONFIG_FBCON_CFB16 + case 16: + display->dispsw = &fbcon_cfb16; + break; +#endif + } + break; + } } static int -atari_fb_set_var(struct fb_var_screeninfo *var, int con) +atafb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) { int err,oldxres,oldyres,oldbpp,oldxres_virtual, oldyres_virtual,oldyoffset; @@ -2536,10 +2546,10 @@ atari_fb_set_var(struct fb_var_screeninfo *var, int con) || oldyres_virtual != var->yres_virtual || oldbpp != var->bits_per_pixel || oldyoffset != var->yoffset) { - atari_fb_set_disp(con); + atafb_set_disp(con, info); (*fb_info.changevar)(con); fb_alloc_cmap(&fb_display[con].cmap, 0, 0); - do_install_cmap(con); + do_install_cmap(con, info); } } var->activate=0; @@ -2549,22 +2559,22 @@ atari_fb_set_var(struct fb_var_screeninfo *var, int con) static int -atari_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con) +atafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) { if (con == currcon) /* current console ? */ return fb_get_cmap(cmap, &(fb_display[con].var), kspc, - fbhw->getcolreg); + fbhw->getcolreg, info); else if (fb_display[con].cmap.len) /* non default colormap ? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else - fb_copy_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), + fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), cmap, kspc ? 0 : 2); return 0; } static int -atari_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con) +atafb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) { int err; if (! fb_display[con].cmap.len) { /* no colormap allocated ? */ @@ -2575,14 +2585,14 @@ atari_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con) } if (con == currcon) /* current console ? */ return fb_set_cmap(cmap, &(fb_display[con].var), kspc, - fbhw->setcolreg); + fbhw->setcolreg, info); else fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); return 0; } static int -atari_fb_pan_display(struct fb_var_screeninfo *var, int con) +atafb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info) { int xoffset = var->xoffset; int yoffset = var->yoffset; @@ -2606,33 +2616,33 @@ atari_fb_pan_display(struct fb_var_screeninfo *var, int con) } static int -atari_fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg, int con) +atafb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, int con, struct fb_info *info) { switch (cmd) { #ifdef FBCMD_GET_CURRENTPAR case FBCMD_GET_CURRENTPAR: if (copy_to_user((void *)arg, (void *)¤t_par, - sizeof(struct atari_fb_par))) + sizeof(struct atafb_par))) return -EFAULT; return 0; #endif #ifdef FBCMD_SET_CURRENTPAR case FBCMD_SET_CURRENTPAR: if (copy_from_user((void *)¤t_par, (void *)arg, - sizeof(struct atari_fb_par))) + sizeof(struct atafb_par))) return -EFAULT; - atari_fb_set_par(¤t_par); + atafb_set_par(¤t_par); return 0; #endif } return -EINVAL; } -static struct fb_ops atari_fb_ops = { - atari_fb_open, atari_fb_release, atari_fb_get_fix, atari_fb_get_var, - atari_fb_set_var, atari_fb_get_cmap, atari_fb_set_cmap, - atari_fb_pan_display, atari_fb_ioctl +static struct fb_ops atafb_ops = { + atafb_open, atafb_release, atafb_get_fix, atafb_get_var, + atafb_set_var, atafb_get_cmap, atafb_set_cmap, + atafb_pan_display, NULL, atafb_ioctl }; static void @@ -2645,14 +2655,14 @@ check_default_par( int detected_mode ) /* First try the user supplied mode */ if (default_par) { - var=atari_fb_predefined[default_par-1]; + var=atafb_predefined[default_par-1]; var.activate = FB_ACTIVATE_TEST; if (do_fb_set_var(&var,1)) default_par=0; /* failed */ } /* Next is the autodetected one */ if (! default_par) { - var=atari_fb_predefined[detected_mode-1]; /* autodetect */ + var=atafb_predefined[detected_mode-1]; /* autodetect */ var.activate = FB_ACTIVATE_TEST; if (!do_fb_set_var(&var,1)) default_par=detected_mode; @@ -2665,7 +2675,7 @@ check_default_par( int detected_mode ) default_par=get_video_mode(default_name); if (! default_par) panic("can't set default video mode\n"); - var=atari_fb_predefined[default_par-1]; + var=atafb_predefined[default_par-1]; var.activate = FB_ACTIVATE_TEST; if (! do_fb_set_var(&var,1)) break; /* ok */ @@ -2677,16 +2687,17 @@ check_default_par( int detected_mode ) } static int -atafb_switch(int con) +atafb_switch(int con, struct fb_info *info) { /* Do we have to save the colormap ? */ if (fb_display[currcon].cmap.len) fb_get_cmap(&fb_display[currcon].cmap, - &(fb_display[currcon].var), 1, fbhw->getcolreg); + &(fb_display[currcon].var), 1, fbhw->getcolreg, + info); do_fb_set_var(&fb_display[con].var,1); currcon=con; /* Install new colormap */ - do_install_cmap(con); + do_install_cmap(con, info); return 0; } @@ -2698,7 +2709,7 @@ atafb_switch(int con) * 4 = off */ static void -atafb_blank(int blank) +atafb_blank(int blank, struct fb_info *info) { unsigned short black[16]; struct fb_cmap cmap; @@ -2713,19 +2724,13 @@ atafb_blank(int blank) cmap.start=0; cmap.len=16; fb_set_cmap(&cmap, &(fb_display[currcon].var), 1, - fbhw->setcolreg); + fbhw->setcolreg, info); } else - do_install_cmap(currcon); -} - -static int -atafb_setcmap(struct fb_cmap *cmap, int con) -{ - return(atari_fb_set_cmap(cmap, 1, con)); + do_install_cmap(currcon, info); } -__initfunc(unsigned long atari_fb_init(unsigned long mem_start)) +__initfunc(unsigned long atafb_init(unsigned long mem_start)) { int err; int pad; @@ -2770,6 +2775,16 @@ __initfunc(unsigned long atari_fb_init(unsigned long mem_start)) panic("Cannot initialize video hardware\n"); #endif } while (0); + + /* Multisync monitor capabilities */ + /* Atari-TOS defaults if no boot option present */ + if (fb_info.monspecs.hfmin == 0) { + fb_info.monspecs.hfmin = 31000; + fb_info.monspecs.hfmax = 32000; + fb_info.monspecs.vfmin = 58; + fb_info.monspecs.vfmax = 62; + } + detected_mode = fbhw->detect(); check_default_par(detected_mode); #ifdef ATAFB_EXT @@ -2778,13 +2793,14 @@ __initfunc(unsigned long atari_fb_init(unsigned long mem_start)) mem_req = default_mem_req + ovsc_offset + ovsc_addlen; mem_req = ((mem_req + PAGE_SIZE - 1) & PAGE_MASK) + PAGE_SIZE; - screen_base = (unsigned long) atari_stram_alloc(mem_req, &mem_start); + screen_base = (unsigned long)atari_stram_alloc(mem_req, &mem_start, + "atafb"); memset((char *) screen_base, 0, mem_req); pad = ((screen_base + PAGE_SIZE-1) & PAGE_MASK) - screen_base; screen_base+=pad; real_screen_base=screen_base+ovsc_offset; screen_len = (mem_req - pad - ovsc_offset) & PAGE_MASK; - st_ovsc_switch(ovsc_switchmode); + st_ovsc_switch(); if (CPU_IS_040_OR_060) { /* On a '040+, the cache mode of video RAM must be set to * write-through also for internal video hardware! */ @@ -2815,32 +2831,29 @@ __initfunc(unsigned long atari_fb_init(unsigned long mem_start)) strcpy(fb_info.modename, "Atari Builtin "); fb_info.changevar = NULL; fb_info.node = -1; - fb_info.fbops = &atari_fb_ops; - fb_info.fbvar_num = num_atari_fb_predefined; - fb_info.fbvar = atari_fb_predefined; + fb_info.fbops = &atafb_ops; fb_info.disp = &disp; fb_info.switch_con = &atafb_switch; fb_info.updatevar = &fb_update_var; fb_info.blank = &atafb_blank; - fb_info.setcmap = &atafb_setcmap; - do_fb_set_var(&atari_fb_predefined[default_par-1], 1); + do_fb_set_var(&atafb_predefined[default_par-1], 1); strcat(fb_info.modename, fb_var_names[default_par-1][0]); err=register_framebuffer(&fb_info); if (err < 0) return(err); - atari_fb_get_var(&disp.var, -1); - atari_fb_set_disp(-1); + atafb_get_var(&disp.var, -1, &fb_info); + atafb_set_disp(-1, &fb_info); printk("Determined %dx%d, depth %d\n", disp.var.xres, disp.var.yres, disp.var.bits_per_pixel); if ((disp.var.xres != disp.var.xres_virtual) || (disp.var.yres != disp.var.yres_virtual)) printk(" virtual %dx%d\n", disp.var.xres_virtual, disp.var.yres_virtual); - do_install_cmap(0); - printk("%s frame buffer device, using %dK of video memory\n", - fb_info.modename, screen_len>>10); + do_install_cmap(0, &fb_info); + printk("fb%d: %s frame buffer device, using %dK of video memory\n", + GET_FB_IDX(fb_info.node), fb_info.modename, screen_len>>10); /* TODO: This driver cannot be unloaded yet */ MOD_INC_USE_COUNT; @@ -2870,7 +2883,7 @@ static char * strtoke(char * s,const char * ct) return sbegin; } -__initfunc(void atari_video_setup( char *options, int *ints )) +__initfunc(void atafb_setup( char *options, int *ints )) { char *this_opt; int temp; @@ -2902,15 +2915,6 @@ __initfunc(void atari_video_setup( char *options, int *ints )) if (hwscroll > 200) hwscroll = 200; } - else if (! strncmp(this_opt, "sw_",3)) { - if (! strcmp(this_opt+3, "acia")) - ovsc_switchmode = SWITCH_ACIA; - else if (! strcmp(this_opt+3, "snd6")) - ovsc_switchmode = SWITCH_SND6; - else if (! strcmp(this_opt+3, "snd7")) - ovsc_switchmode = SWITCH_SND7; - else ovsc_switchmode = SWITCH_NONE; - } #ifdef ATAFB_EXT else if (!strcmp(this_opt,"mv300")) { external_bitspercol = 8; @@ -2939,12 +2943,8 @@ __initfunc(void atari_video_setup( char *options, int *ints )) if (*int_str) { /* Format to config extended internal video hardware like OverScan: - "<switch-type>,internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>" + "internal:<xres>;<yres>;<xres_max>;<yres_max>;<offset>" Explanation: - <switch-type> type to switch on higher resolution - sw_acia : via keyboard ACIA - sw_snd6 : via bit 6 of the soundchip port - sw_snd7 : via bit 7 of the soundchip port <xres>: x-resolution <yres>: y-resolution The following are only needed if you have an overscan which @@ -2974,9 +2974,9 @@ __initfunc(void atari_video_setup( char *options, int *ints )) if (ovsc_offset || (sttt_yres_virtual != st_yres)) use_hwscroll=0; + int_invalid: + ; } - else - int_invalid: ovsc_switchmode = SWITCH_NONE; #ifdef ATAFB_EXT if (*ext_str) { @@ -3103,10 +3103,10 @@ __initfunc(void atari_video_setup( char *options, int *ints )) hmax = 1000 * simple_strtoul(p, NULL, 10); if (hmax <= 0 || hmax <= hmin) goto cap_invalid; - vfmin = vmin; - vfmax = vmax; - hfmin = hmin; - hfmax = hmax; + fb_info.monspecs.vfmin = vmin; + fb_info.monspecs.vfmax = vmax; + fb_info.monspecs.hfmin = hmin; + fb_info.monspecs.hfmax = hmax; cap_invalid: ; } @@ -3126,9 +3126,9 @@ __initfunc(void atari_video_setup( char *options, int *ints )) depth = simple_strtoul(p, NULL, 10); if ((temp=get_video_mode("user0"))) { default_par=temp; - atari_fb_predefined[default_par-1].xres = xres; - atari_fb_predefined[default_par-1].yres = yres; - atari_fb_predefined[default_par-1].bits_per_pixel = depth; + atafb_predefined[default_par-1].xres = xres; + atafb_predefined[default_par-1].yres = yres; + atafb_predefined[default_par-1].bits_per_pixel = depth; } user_invalid: @@ -3139,7 +3139,7 @@ __initfunc(void atari_video_setup( char *options, int *ints )) #ifdef MODULE int init_module(void) { - return(atari_fb_init(NULL)); + return(atafb_init(NULL)); } void cleanup_module(void) @@ -3147,6 +3147,7 @@ void cleanup_module(void) /* Not reached because the usecount will never be decremented to zero */ unregister_framebuffer(&fb_info); - /* TODO: clean up ... */ + /* atari_stram_free( screen_base ); */ + /* TODO: further clean up ... */ } #endif /* MODULE */ diff --git a/drivers/video/ati-gt.h b/drivers/video/ati-gt.h new file mode 100644 index 000000000..32dc792b5 --- /dev/null +++ b/drivers/video/ati-gt.h @@ -0,0 +1,203 @@ +/* the usage for the following structs vary from the gx and vt: +and sdram and sgram gt's + pll registers (sdram) 6,7,11; + crtc_h_sync_strt_wid[3]; + dsp1[3] (sdram,sgram,unused) + dsp2[3] (offset regbase+24, depends on colour mode); + crtc_h_tot_disp,crtc_v_tot_disp,crtc_v_sync_strt_wid,unused; + pll registers (sgram) 7,11; +*/ + +/* Register values for 1280x1024, 75Hz mode (20). no 16/32 */ +static struct aty_regvals aty_gt_reg_init_20 = { + { 0x41, 0xf9, 0x04 }, + { 0xe02a7, 0x1401a6, 0 }, + { 0x260957, 0x2806d6, 0 }, + { 0x10006b6, 0x20006b6, 0x30006b6 }, + + 0x9f00d2, 0x03ff0429, 0x30400, 0, + { 0xb5, 0x04 } +}; + +#if 0 +/* Register values for 1280x960, 75Hz mode (19) */ +static struct aty_regvals aty_gt_reg_init_19 = { +}; +#endif + +/* Register values for 1152x870, 75Hz mode (18) */ +static struct aty_regvals aty_gt_reg_init_18 = { + { 0x41, 0xe6, 0x04 }, + { 0x300295, 0x300194, 0x300593 }, + { 0x260a1c, 0x380561, 0}, + { 0x1000744, 0x2000744, 0x3000744 }, + + 0x8f00b5, 0x3650392, 0x230368, 0, + { 0xe6, 0x04 } +}; + +/* Register values for 1024x768, 75Hz mode (17), 32 bpp untested */ +static struct aty_regvals aty_gt_reg_init_17 = { + { 0x41, 0xb5, 0x04 }, + { 0xc0283, 0xc0182, 0xc0581 }, + { 0x36066d, 0x3806d6, 0}, + { 0xa0049e, 0x100049e, 0x200049e }, + + 0x7f00a3, 0x2ff031f, 0x30300, 0, + { 0xb8, 0x04 } +}; + +#if 0 +/* Register values for x, Hz mode (16) */ +static struct aty_regvals aty_gt_reg_init_16 = { +}; +#endif + +/* Register values for 1024x768, 70Hz mode (15) */ +static struct aty_regvals aty_gt_reg_init_15 = { + { 0x41, 0xad, 0x04 }, + { 0x310284, 0x310183, 0x310582 }, + { 0x0, 0x380727 }, + { 0x0 }, + 0x7f00a5, 0x2ff0325, 0x260302, +}; + +/* Register values for 1024x768, 60Hz mode (14) */ +static struct aty_regvals aty_gt_reg_init_14 = { + { 0x40, 0xe1, 0x14 }, + { 0x310284, 0x310183, 0x310582 }, + { 0x3607c0, 0x380840, 0x0 }, + { 0xa80592, 0x1000592, 0x0 }, + + 0x7f00a7, 0x2ff0325, 0x260302, 0, + { 0xe1, 0x14 } +}; + +/* Register values for 832x624, 75Hz mode (13) */ +static struct aty_regvals aty_gt_reg_init_13 = { + { 0x40, 0xc6, 0x14 }, + { 0x28026d, 0x28016c, 0x28056b }, + { 0x3608cf, 0x380960, 0 }, + { 0xb00655, 0x1000655, 0x2000655 }, + + 0x67008f, 0x26f029a, 0x230270, 0, + { 0xc6, 0x14 } +}; + +/* Register values for 800x600, 75Hz mode (12) */ +static struct aty_regvals aty_gt_reg_init_12 = { + { 0x42, 0xe4, 0x04 }, + { 0xa0267, 0xa0166, 0x0a0565}, + { 0x360a33, 0x48056d, 0}, + { 0xc00755, 0x1000755, 0x02000755}, + + 0x630083, 0x2570270, 0x30258, 0, + { 0xe4, 0x4 } +}; + +/* Register values for 800x600, 72Hz mode (11) */ +static struct aty_regvals aty_gt_reg_init_11 = { + { 0x42, 0xe6, 0x04 }, + { 0xf026c, 0xf016b, 0xf056a }, + { 0x360a1d, 0x480561, 0}, + { 0xc00745, 0x1000745, 0x2000745 }, + + 0x630081, 0x02570299, 0x6027c +}; + +/* Register values for 800x600, 60Hz mode (10) */ +static struct aty_regvals aty_gt_reg_init_10 = { + { 0x42, 0xb8, 0x04 }, + { 0x10026a, 0x100169, 0x100568 }, + { 0x460652, 0x4806ba, 0}, + { 0x68048b, 0xa0048b, 0x100048b }, + + 0x630083, 0x02570273, 0x40258, 0, + { 0xb8, 0x4 } +}; + +/* Register values for 800x600, 56Hz mode (9) */ +static struct aty_regvals aty_gt_reg_init_9 = { + { 0x42, 0xf9, 0x14 }, + { 0x90268, 0x90167, 0x090566 }, + { 0x460701, 0x480774, 0}, + { 0x700509, 0xa80509, 0x1000509 }, + + 0x63007f, 0x2570270, 0x20258 +}; + +#if 0 +/* Register values for 768x576, 50Hz mode (8) */ +static struct aty_regvals aty_gt_reg_init_8 = { +}; + +/* Register values for 640x870, 75Hz Full Page Display (7) */ +static struct aty_regvals aty_gt_reg_init_7 = { +}; +#endif + +/* Register values for 640x480, 67Hz mode (6) */ +static struct aty_regvals aty_gt_reg_init_6 = { + { 0x42, 0xd1, 0x14 }, + { 0x280259, 0x280158, 0x280557 }, + { 0x460858, 0x4808e2, 0}, + { 0x780600, 0xb00600, 0x1000600 }, + + 0x4f006b, 0x1df020c, 0x2301e2, 0, + { 0x8b, 0x4 } +}; + +/* Register values for 640x480, 60Hz mode (5) */ +static struct aty_regvals aty_gt_reg_init_5 = { + { 0x43, 0xe8, 0x04 }, + { 0x2c0253, 0x2c0152, 0x2c0551 }, + { 0x460a06, 0x580555, 0}, + { 0x880734, 0xc00734, 0x1000734 }, + + 0x4f0063, 0x1df020c, 0x2201e9, 0, + { 0xe8, 0x04 } +}; + +#if 0 +/* Register values for x, Hz mode (4) */ +static struct aty_regvals aty_gt_reg_init_4 = { +}; + +/* Register values for x, Hz mode (3) */ +static struct aty_regvals aty_gt_reg_init_3 = { +}; + +/* Register values for x, Hz mode (2) */ +static struct aty_regvals aty_gt_reg_init_2 = { +}; + +/* Register values for x, Hz mode (1) */ +static struct aty_regvals aty_gt_reg_init_1 = { +}; +#endif + +/* yikes, more data structures (dsp2) + * XXX kludge for sgram + */ +static int sgram_dsp[20][3] = { + {0,0,0}, + {0,0,0}, + {0,0,0}, + {0,0,0}, + {0x5203d7,0x7803d9,0xb803dd}, //5 + {0x940666,0xe0066a,0x1700672}, //6 + {0,0,0}, + {0,0,0}, + {0x88055f,0xd80563,0x170056b}, //9 + {0x8404d9,0xb804dd,0x17004e5}, //10 + {0x7803e2,0xb803e6,0x17003ee}, //11 + {0x7803eb,0xb803ef,0x17003f7}, //12 + {0xe806c5,0x17006cd,0x2e006dd}, //13 + {0xe005f6,0x17005fe,0x2e0060e}, //14 + {0xd8052c,0x1700534,0x2e00544}, //15 + {0,0,0}, + {0xb804f2,0x17004e5,0x2e0050a}, //17 + {0xb803e6,0x17003ee,0x2e003fe}, //18 + {0,0,0}, + {0,0,0}, +}; diff --git a/drivers/video/ati-gx.h b/drivers/video/ati-gx.h new file mode 100644 index 000000000..df48c1865 --- /dev/null +++ b/drivers/video/ati-gx.h @@ -0,0 +1,122 @@ +/* Register values for 1280x1024, 75Hz (WAS 60) mode (20) */ +static struct aty_regvals aty_gx_reg_init_20 = { + { 0x200, 0x200, 0x200 }, + + { 0x1200a5, 0x1200a3, 0x1200a3 }, + { 0x30c0200, 0x30e0300, 0x30e0300 }, + { 0x2, 0x3, 0x3 }, + + 0x9f00d2, 0x3ff0429, 0x30400, 0x28100040, + { 0xd4, 0x9 } +}; + +/* Register values for 1152x870, 75Hz mode (18) */ +static struct aty_regvals aty_gx_reg_init_18 = { + { 0x200, 0x200, 0x200 }, + + { 0x300097, 0x300095, 0x300094 }, + { 0x3090200, 0x30e0300, 0x30e0600 }, + { 0x2, 0x3, 0x6 }, + + 0x8f00b5, 0x3650392, 0x230368, 0x24100040, + { 0x53, 0x3 } +}; + +/* Register values for 1024x768, 75Hz mode (17) */ +static struct aty_regvals aty_gx_reg_init_17 = { + { 0x200, 0x200, 0x200 }, + + { 0x2c0087, 0x2c0085, 0x2c0084 }, + { 0x3070200, 0x30e0300, 0x30e0600 }, + { 0x2, 0x3, 0x6 }, + + 0x7f00a5, 0x2ff0323, 0x230302, 0x20100000, + { 0x42, 0x3 } +}; + +/* Register values for 1024x768, 72Hz mode (15) */ +static struct aty_regvals aty_gx_reg_init_15 = { + { 0, 0, 0 }, + + { 0x310086, 0x310084, 0x310084 }, + { 0x3070200, 0x30e0300, 0x30e0300 }, + { 0x2002312, 0x3002312, 0x3002312 }, + + 0x7f00a5, 0x2ff0325, 0x260302, 0x20100000, + { 0x88, 0x7 } +}; + +/* Register values for 1024x768, 60Hz mode (14) */ +static struct aty_regvals aty_gx_reg_init_14 = { + { 0, 0, 0 }, + + { 0x310086, 0x310084, 0x310084 }, + { 0x3060200, 0x30d0300, 0x30d0300 }, + { 0x2002312, 0x3002312, 0x3002312 }, + + 0x7f00a7, 0x2ff0325, 0x260302, 0x20100000, + { 0x6c, 0x6 } +}; + +/* Register values for 832x624, 75Hz mode (13) */ +static struct aty_regvals aty_gx_reg_init_13 = { + { 0x200, 0x200, 0x200 }, + + { 0x28006f, 0x28006d, 0x28006c }, + { 0x3050200, 0x30b0300, 0x30e0600 }, + { 0x2, 0x3, 0x6 }, + + 0x67008f, 0x26f029a, 0x230270, 0x1a100040, + { 0x4f, 0x5 } +}; + +#if 0 /* not filled in yet */ +/* Register values for 800x600, 75Hz mode (12) */ +static struct aty_regvals aty_gx_reg_init_12 = { + { 0x10, 0x28, 0x50 }, + { }, + { } /* pixel clock = 49.11MHz for V=74.40Hz */ +}; + +/* Register values for 800x600, 72Hz mode (11) */ +static struct aty_regvals aty_gx_reg_init_11 = { + { 0x10, 0x28, 0x50 }, + { }, + { } /* pixel clock = 49.63MHz for V=71.66Hz */ +}; + +/* Register values for 800x600, 60Hz mode (10) */ +static struct aty_regvals aty_gx_reg_init_10 = { + { 0x10, 0x28, 0x50 }, + { }, + { } /* pixel clock = 41.41MHz for V=59.78Hz */ +}; + +/* Register values for 640x870, 75Hz Full Page Display (7) */ +static struct aty_regvals aty_gx_reg_init_7 = { + { 0x10, 0x30, 0x68 }, + { }, + { } /* pixel clock = 57.29MHz for V=75.01Hz */ +}; +#endif + +/* Register values for 640x480, 67Hz mode (6) */ +static struct aty_regvals aty_gx_reg_init_6 = { + { 0x200, 0x200, 0x200 }, + + { 0x28005b, 0x280059, 0x280058 }, + { 0x3040200, 0x3060300, 0x30c0600 }, + { 0x2002312, 0x3002312, 0x6002312 }, + + 0x4f006b, 0x1df020c, 0x2301e2, 0x14100040, + { 0x35, 0x07 } +}; + +#if 0 /* not filled in yet */ +/* Register values for 640x480, 60Hz mode (5) */ +static struct aty_regvals aty_gx_reg_init_5 = { + { 0x200, 0x200, 0x200 }, + { }, + { 0x35, 0x07 } +}; +#endif diff --git a/drivers/video/ati-vt.h b/drivers/video/ati-vt.h new file mode 100644 index 000000000..3b25d6d5d --- /dev/null +++ b/drivers/video/ati-vt.h @@ -0,0 +1,147 @@ +/* Register values for 1280x1024, 60Hz mode (20) */ +static struct aty_regvals aty_vt_reg_init_20 = { + { 0, 0, 0 }, + + { 0x002e02a7, 0x002e02a7, 0 }, + { 0x03070200, 0x03070200, 0 }, + { 0x0a00cb22, 0x0b00cb23, 0 }, + + 0x009f00d2, 0x03ff0429, 0x00030400, 0x28000000, + { 0x00, 0xaa } +}; + +/* Register values for 1280x960, 75Hz mode (19) */ +static struct aty_regvals aty_vt_reg_init_19 = { + { 0, 0, 0 }, + { 0x003202a3, 0x003201a2, 0 }, + { 0x030b0200, 0x030b0300, 0 }, + { 0x0a00cb22, 0x0b00cb23, 0 }, + + 0x009f00d1, 0x03bf03e7, 0x000303c0, 0x28000000, + { 0x00, 0xc6 } +}; + +/* Register values for 1152x870, 75Hz mode (18) */ +static struct aty_regvals aty_vt_reg_init_18 = { + { 0, 0, 0 }, + + { 0x00300295, 0x00300194, 0 }, + { 0x03080200, 0x03080300, 0 }, + { 0x0a00cb21, 0x0b00cb22, 0 }, + + 0x008f00b5, 0x03650392, 0x00230368, 0x24000000, + { 0x00, 0x9d } +}; + +/* Register values for 1024x768, 75Hz mode (17) */ +static struct aty_regvals aty_vt_reg_init_17 = { + { 0, 0, 0 }, + + { 0x002c0283, 0x002c0182, 0 }, + { 0x03080200, 0x03080300, 0 }, + { 0x0a00cb21, 0x0b00cb22, 0 }, + + 0x007f00a3, 0x02ff031f, 0x00030300, 0x20000000, + { 0x01, 0xf7 } +}; + +/* Register values for 1024x768, 70Hz mode (15) */ +static struct aty_regvals aty_vt_reg_init_15 = { + { 0, 0, 0 }, + { 0x00310284, 0x00310183, 0 }, + { 0x03080200, 0x03080300, 0 }, + { 0x0a00cb21, 0x0b00cb22, 0 }, + + 0x007f00a5, 0x02ff0325, 0x00260302, 0x20000000, + { 0x01, 0xeb } +}; + +/* Register values for 1024x768, 60Hz mode (14) */ +static struct aty_regvals aty_vt_reg_init_14 = { + { 0, 0, 0 }, + + { 0x00310284, 0x00310183, 0x00310582 }, /* 32 bit 0x00310582 */ + { 0x03080200, 0x03080300, 0x03070600 }, /* 32 bit 0x03070600 */ + { 0x0a00cb21, 0x0b00cb22, 0x0e00cb23 }, + + 0x007f00a7, 0x02ff0325, 0x00260302, 0x20000000, + { 0x01, 0xcc } +}; + +/* Register values for 832x624, 75Hz mode (13) */ +static struct aty_regvals aty_vt_reg_init_13 = { + { 0, 0, 0 }, + + { 0x0028026d, 0x0028016c, 0x0028056b }, + { 0x03080200, 0x03070300, 0x03090600 }, + { 0x0a00cb21, 0x0b00cb21, 0x0e00cb22 }, + + 0x0067008f, 0x026f029a, 0x00230270, 0x1a000000, + { 0x01, 0xb4 } +}; + +/* Register values for 800x600, 75Hz mode (12) */ +static struct aty_regvals aty_vt_reg_init_12 = { + { 0, 0, 0 }, + + { 0x002a0267, 0x002a0166, 0x002a0565 }, + { 0x03040200, 0x03060300, 0x03070600 }, + { 0x0a00cb21, 0x0b00cb21, 0x0e00cb22 }, + + 0x00630083, 0x02570270, 0x00030258, 0x19000000, + { 0x01, 0x9c } +}; + +/* Register values for 800x600, 72Hz mode (11) */ +static struct aty_regvals aty_vt_reg_init_11 = { + { 0, 0, 0 }, + + { 0x002f026c, 0x002f016b, 0x002f056a }, + { 0x03050200, 0x03070300, 0x03090600 }, + { 0x0a00cb21, 0x0b00cb21, 0x0e00cb22 }, + + 0x00630081, 0x02570299, 0x0006027c, 0x19000000, + { 0x01, 0x9d } +}; + +/* Register values for 800x600, 60Hz mode (10) */ +static struct aty_regvals aty_vt_reg_init_10 = { + { 0, 0, 0 }, + + { 0x0030026a, 0x00300169, 0x00300568 }, + { 0x03050200, 0x03070300, 0x03090600 }, + { 0x0a00cb21, 0x0b00cb21, 0x0e00cb22 }, + + 0x00630083, 0x02570273, 0x00040258, 0x19000000, + { 0x02, 0xfb } +}; + +/* Register values for 640x480, 67Hz mode (6) */ +static struct aty_regvals aty_vt_reg_init_6 = { + { 0, 0, 0 }, + + { 0x00280259, 0x00280158, 0x00280557 }, + { 0x03050200, 0x03070300, 0x030a0600 }, + { 0x0a00cb21, 0x0b00cb21, 0x0e00cb22 }, + + 0x004f006b, 0x01df020c, 0x002301e2, 0x14000000, + { 0x02, 0xbe } +}; + +/* Register values for 640x480, 60Hz mode (5) */ +static struct aty_regvals aty_vt_reg_init_5 = { + { 0, 0, 0 }, + + { 0x002c0253, 0x002c0152, 0x002c0551 }, + { 0x03050200, 0x03070300, 0x03090600 }, + { 0x0a00cb21, 0x0b00cb21, 0x0e00cb22 }, + + 0x004f0063, 0x01df020c, 0x002201e9, 0x14000000, + { 0x02, 0x9e } +}; + /* 8 bit 15 bit 32 bit */ +static int vt_mem_cntl[3][3] = { { 0x0A00CB21, 0x0B00CB21, 0x0E00CB21 }, /* 1 MB VRAM */ + { 0x0A00CB22, 0x0B00CB22, 0x0E00CB22 }, /* 2 MB VRAM */ + { 0x0200053B, 0x0300053B, 0x0600053B } /* 4 M B VRAM */ + }; + diff --git a/drivers/video/aty.h b/drivers/video/aty.h new file mode 100644 index 000000000..7c9b00ad7 --- /dev/null +++ b/drivers/video/aty.h @@ -0,0 +1,923 @@ +/* + * Exported procedures for the ATI/mach64 display driver on PowerMacs. + * + * Copyright (C) 1997 Michael AK Tesch + * written with much help from Jon Howell + * + * Updated for 3D RAGE PRO by Geert Uytterhoeven + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +/* + * most of the rest of this file comes from ATI sample code + */ +#ifndef REGMACH64_H +#define REGMACH64_H + +/* NON-GUI MEMORY MAPPED Registers - expressed in BYTE offsets */ + +#define CRTC_H_TOTAL_DISP 0x0000 /* Dword offset 0_00 */ +#define CRTC_H_SYNC_STRT_WID 0x0004 /* Dword offset 0_01 */ +#define CRTC_H_SYNC_STRT 0x0004 +#define CRTC_H_SYNC_DLY 0x0005 +#define CRTC_H_SYNC_WID 0x0006 + +#define CRTC_V_TOTAL_DISP 0x0008 /* Dword offset 0_02 */ +#define CRTC_V_TOTAL 0x0008 +#define CRTC_V_DISP 0x000A +#define CRTC_V_SYNC_STRT_WID 0x000C /* Dword offset 0_03 */ +#define CRTC_V_SYNC_STRT 0x000C +#define CRTC_V_SYNC_WID 0x000E + +#define CRTC_VLINE_CRNT_VLINE 0x0010 /* Dword offset 0_04 */ +#define CRTC_OFF_PITCH 0x0014 /* Dword offset 0_05 */ +#define CRTC_OFFSET 0x0014 +#define CRTC_PITCH 0x0016 + +#define CRTC_INT_CNTL 0x0018 /* Dword offset 0_06 */ +#define CRTC_GEN_CNTL 0x001C /* Dword offset 0_07 */ +#define CRTC_PIX_WIDTH 0x001D +#define CRTC_FIFO 0x001E +#define CRTC_EXT_DISP 0x001F + +#define DSP_CONFIG 0x0020 /* Dword offset 0_08 */ +#define DSP_ON_OFF 0x0024 /* Dword offset 0_09 */ +#define TIMER_CONFIG 0x0028 /* Dword offset 0_0A */ +#define MEM_BUF_CNTL 0x002C /* Dword offset 0_0B */ +#define MEM_ADDR_CONFIG 0x0034 /* Dword offset 0_0D */ + +#define CRT_TRAP 0x0038 /* Dword offset 0_0E */ + +#define I2C_CNTL_0 0x003C /* Dword offset 0_0F */ + +#define OVR_CLR 0x0040 /* Dword offset 0_10 */ +#define OVR_WID_LEFT_RIGHT 0x0044 /* Dword offset 0_11 */ +#define OVR_WID_TOP_BOTTOM 0x0048 /* Dword offset 0_12 */ + +#define VGA_DSP_CONFIG 0x004C /* Dword offset 0_13 */ +#define VGA_DSP_ON_OFF 0x0050 /* Dword offset 0_14 */ + +#define CUR_CLR0 0x0060 /* Dword offset 0_18 */ +#define CUR_CLR1 0x0064 /* Dword offset 0_19 */ +#define CUR_OFFSET 0x0068 /* Dword offset 0_1A */ +#define CUR_HORZ_VERT_POSN 0x006C /* Dword offset 0_1B */ +#define CUR_HORZ_VERT_OFF 0x0070 /* Dword offset 0_1C */ + +#define GP_IO 0x0078 /* Dword offset 0_1E */ + +#define HW_DEBUG 0x007C /* Dword offset 0_1F */ + +#define SCRATCH_REG0 0x0080 /* Dword offset 0_20 */ +#define SCRATCH_REG1 0x0084 /* Dword offset 0_21 */ + +#define CLOCK_CNTL 0x0090 /* Dword offset 0_24 */ +#define CLOCK_SEL_CNTL 0x0090 /* Dword offset 0_24 */ + +#define CONFIG_STAT1 0x0094 /* Dword offset 0_25 */ +#define CONFIG_STAT2 0x0098 /* Dword offset 0_26 */ + +#define BUS_CNTL 0x00A0 /* Dword offset 0_28 */ + +#define EXT_MEM_CNTL 0x00AC /* Dword offset 0_2B */ +#define MEM_CNTL 0x00B0 /* Dword offset 0_2C */ + +#define MEM_VGA_WP_SEL 0x00B4 /* Dword offset 0_2D */ +#define MEM_VGA_RP_SEL 0x00B8 /* Dword offset 0_2E */ + +#define DAC_REGS 0x00C0 /* Dword offset 0_30 */ +#define DAC_W_INDEX 0x00C0 /* Dword offset 0_30 */ +#define DAC_DATA 0x00C1 /* Dword offset 0_30 */ +#define DAC_MASK 0x00C2 /* Dword offset 0_30 */ +#define DAC_R_INDEX 0x00C3 /* Dword offset 0_30 */ +#define DAC_CNTL 0x00C4 /* Dword offset 0_31 */ + +#define EXT_DAC_REGS 0x00C8 /* Dword offset 0_32 */ + +#define GEN_TEST_CNTL 0x00D0 /* Dword offset 0_34 */ + +#define CUSTOM_MACRO_CNTL 0x00D4 /* Dword offset 0_35 */ + +#define CONFIG_CNTL 0x00DC /* Dword offset 0_37 (CT, ET, VT) */ +#define CONFIG_CHIP_ID 0x00E0 /* Dword offset 0_38 */ +#define CONFIG_STAT0 0x00E4 /* Dword offset 0_39 */ +#define CRC_SIG 0x00E8 /* Dword offset 0_3A */ + + +/* GUI MEMORY MAPPED Registers */ + +#define DST_OFF_PITCH 0x0100 /* Dword offset 0_40 */ +#define DST_X 0x0104 /* Dword offset 0_41 */ +#define DST_Y 0x0108 /* Dword offset 0_42 */ +#define DST_Y_X 0x010C /* Dword offset 0_43 */ +#define DST_WIDTH 0x0110 /* Dword offset 0_44 */ +#define DST_HEIGHT 0x0114 /* Dword offset 0_45 */ +#define DST_HEIGHT_WIDTH 0x0118 /* Dword offset 0_46 */ +#define DST_X_WIDTH 0x011C /* Dword offset 0_47 */ +#define DST_BRES_LNTH 0x0120 /* Dword offset 0_48 */ +#define DST_BRES_ERR 0x0124 /* Dword offset 0_49 */ +#define DST_BRES_INC 0x0128 /* Dword offset 0_4A */ +#define DST_BRES_DEC 0x012C /* Dword offset 0_4B */ +#define DST_CNTL 0x0130 /* Dword offset 0_4C */ +#define DST_Y_X__ALIAS__ 0x0134 /* Dword offset 0_4D */ +#define TRAIL_BRES_ERR 0x0138 /* Dword offset 0_4E */ +#define TRAIL_BRES_INC 0x013C /* Dword offset 0_4F */ +#define TRAIL_BRES_DEC 0x0140 /* Dword offset 0_50 */ +#define LEAD_BRES_LNTH 0x0144 /* Dword offset 0_51 */ +#define Z_OFF_PITCH 0x0148 /* Dword offset 0_52 */ +#define Z_CNTL 0x014C /* Dword offset 0_53 */ +#define ALPHA_TST_CNTL 0x0150 /* Dword offset 0_54 */ +#define SECONDARY_STW_EXP 0x0158 /* Dword offset 0_56 */ +#define SECONDARY_S_X_INC 0x015C /* Dword offset 0_57 */ +#define SECONDARY_S_Y_INC 0x0160 /* Dword offset 0_58 */ +#define SECONDARY_S_START 0x0164 /* Dword offset 0_59 */ +#define SECONDARY_W_X_INC 0x0168 /* Dword offset 0_5A */ +#define SECONDARY_W_Y_INC 0x016C /* Dword offset 0_5B */ +#define SECONDARY_W_START 0x0170 /* Dword offset 0_5C */ +#define SECONDARY_T_X_INC 0x0174 /* Dword offset 0_5D */ +#define SECONDARY_T_Y_INC 0x0178 /* Dword offset 0_5E */ +#define SECONDARY_T_START 0x017C /* Dword offset 0_5F */ + +#define SRC_OFF_PITCH 0x0180 /* Dword offset 0_60 */ +#define SRC_X 0x0184 /* Dword offset 0_61 */ +#define SRC_Y 0x0188 /* Dword offset 0_62 */ +#define SRC_Y_X 0x018C /* Dword offset 0_63 */ +#define SRC_WIDTH1 0x0190 /* Dword offset 0_64 */ +#define SRC_HEIGHT1 0x0194 /* Dword offset 0_65 */ +#define SRC_HEIGHT1_WIDTH1 0x0198 /* Dword offset 0_66 */ +#define SRC_X_START 0x019C /* Dword offset 0_67 */ +#define SRC_Y_START 0x01A0 /* Dword offset 0_68 */ +#define SRC_Y_X_START 0x01A4 /* Dword offset 0_69 */ +#define SRC_WIDTH2 0x01A8 /* Dword offset 0_6A */ +#define SRC_HEIGHT2 0x01AC /* Dword offset 0_6B */ +#define SRC_HEIGHT2_WIDTH2 0x01B0 /* Dword offset 0_6C */ +#define SRC_CNTL 0x01B4 /* Dword offset 0_6D */ + +#define SCALE_OFF 0x01C0 /* Dword offset 0_70 */ +#define SECONDARY_SCALE_OFF 0x01C4 /* Dword offset 0_71 */ + +#define TEX_0_OFF 0x01C0 /* Dword offset 0_70 */ +#define TEX_1_OFF 0x01C4 /* Dword offset 0_71 */ +#define TEX_2_OFF 0x01C8 /* Dword offset 0_72 */ +#define TEX_3_OFF 0x01CC /* Dword offset 0_73 */ +#define TEX_4_OFF 0x01D0 /* Dword offset 0_74 */ +#define TEX_5_OFF 0x01D4 /* Dword offset 0_75 */ +#define TEX_6_OFF 0x01D8 /* Dword offset 0_76 */ +#define TEX_7_OFF 0x01DC /* Dword offset 0_77 */ + +#define SCALE_WIDTH 0x01DC /* Dword offset 0_77 */ +#define SCALE_HEIGHT 0x01E0 /* Dword offset 0_78 */ + +#define TEX_8_OFF 0x01E0 /* Dword offset 0_78 */ +#define TEX_9_OFF 0x01E4 /* Dword offset 0_79 */ +#define TEX_10_OFF 0x01E8 /* Dword offset 0_7A */ +#define S_Y_INC 0x01EC /* Dword offset 0_7B */ + +#define SCALE_PITCH 0x01EC /* Dword offset 0_7B */ +#define SCALE_X_INC 0x01F0 /* Dword offset 0_7C */ + +#define RED_X_INC 0x01F0 /* Dword offset 0_7C */ +#define GREEN_X_INC 0x01F4 /* Dword offset 0_7D */ + +#define SCALE_Y_INC 0x01F4 /* Dword offset 0_7D */ +#define SCALE_VACC 0x01F8 /* Dword offset 0_7E */ +#define SCALE_3D_CNTL 0x01FC /* Dword offset 0_7F */ + +#define HOST_DATA0 0x0200 /* Dword offset 0_80 */ +#define HOST_DATA1 0x0204 /* Dword offset 0_81 */ +#define HOST_DATA2 0x0208 /* Dword offset 0_82 */ +#define HOST_DATA3 0x020C /* Dword offset 0_83 */ +#define HOST_DATA4 0x0210 /* Dword offset 0_84 */ +#define HOST_DATA5 0x0214 /* Dword offset 0_85 */ +#define HOST_DATA6 0x0218 /* Dword offset 0_86 */ +#define HOST_DATA7 0x021C /* Dword offset 0_87 */ +#define HOST_DATA8 0x0220 /* Dword offset 0_88 */ +#define HOST_DATA9 0x0224 /* Dword offset 0_89 */ +#define HOST_DATAA 0x0228 /* Dword offset 0_8A */ +#define HOST_DATAB 0x022C /* Dword offset 0_8B */ +#define HOST_DATAC 0x0230 /* Dword offset 0_8C */ +#define HOST_DATAD 0x0234 /* Dword offset 0_8D */ +#define HOST_DATAE 0x0238 /* Dword offset 0_8E */ +#define HOST_DATAF 0x023C /* Dword offset 0_8F */ +#define HOST_CNTL 0x0240 /* Dword offset 0_90 */ + +#define BM_HOSTDATA 0x0244 /* Dword offset 0_91 */ +#define BM_ADDR 0x0248 /* Dword offset 0_92 */ +#define BM_DATA 0x0248 /* Dword offset 0_92 */ +#define BM_GUI_TABLE_CMD 0x024C /* Dword offset 0_93 */ + +#define PAT_REG0 0x0280 /* Dword offset 0_A0 */ +#define PAT_REG1 0x0284 /* Dword offset 0_A1 */ +#define PAT_CNTL 0x0288 /* Dword offset 0_A2 */ + +#define SC_LEFT 0x02A0 /* Dword offset 0_A8 */ +#define SC_RIGHT 0x02A4 /* Dword offset 0_A9 */ +#define SC_LEFT_RIGHT 0x02A8 /* Dword offset 0_AA */ +#define SC_TOP 0x02AC /* Dword offset 0_AB */ +#define SC_BOTTOM 0x02B0 /* Dword offset 0_AC */ +#define SC_TOP_BOTTOM 0x02B4 /* Dword offset 0_AD */ + +#define DP_BKGD_CLR 0x02C0 /* Dword offset 0_B0 */ +#define DP_FOG_CLR 0x02C4 /* Dword offset 0_B1 */ +#define DP_FRGD_CLR 0x02C4 /* Dword offset 0_B1 */ +#define DP_WRITE_MSK 0x02C8 /* Dword offset 0_B2 */ +#define DP_CHAIN_MSK 0x02CC /* Dword offset 0_B3 */ +#define DP_PIX_WIDTH 0x02D0 /* Dword offset 0_B4 */ +#define DP_MIX 0x02D4 /* Dword offset 0_B5 */ +#define DP_SRC 0x02D8 /* Dword offset 0_B6 */ +#define DP_FRGD_CLR_MIX 0x02DC /* Dword offset 0_B7 */ +#define DP_FRGD_BLGD_CLR 0x02E0 /* Dword offset 0_B8 */ + +#define DST_X_Y 0x02E8 /* Dword offset 0_BA */ +#define DST_WIDTH_HEIGHT 0x02EC /* Dword offset 0_BB */ +#define USR_DST_PICTH 0x02F0 /* Dword offset 0_BC */ +#define DP_SET_GUI_ENGINE2 0x02F8 /* Dword offset 0_BE */ +#define DP_SET_GUI_ENGINE 0x02FC /* Dword offset 0_BF */ + +#define CLR_CMP_CLR 0x0300 /* Dword offset 0_C0 */ +#define CLR_CMP_MSK 0x0304 /* Dword offset 0_C1 */ +#define CLR_CMP_CNTL 0x0308 /* Dword offset 0_C2 */ + +#define FIFO_STAT 0x0310 /* Dword offset 0_C4 */ + +#define CONTEXT_MASK 0x0320 /* Dword offset 0_C8 */ +#define CONTEXT_LOAD_CNTL 0x032C /* Dword offset 0_CB */ + +#define GUI_TRAJ_CNTL 0x0330 /* Dword offset 0_CC */ +#define GUI_STAT 0x0338 /* Dword offset 0_CE */ + +#define TEX_PALETTE_INDEX 0x0340 /* Dword offset 0_D0 */ +#define STW_EXP 0x0344 /* Dword offset 0_D1 */ +#define LOG_MAX_INC 0x0348 /* Dword offset 0_D2 */ +#define S_X_INC 0x034C /* Dword offset 0_D3 */ +#define S_Y_INC__ALIAS__ 0x0350 /* Dword offset 0_D4 */ + +#define SCALE_PITCH__ALIAS__ 0x0350 /* Dword offset 0_D4 */ + +#define S_START 0x0354 /* Dword offset 0_D5 */ +#define W_X_INC 0x0358 /* Dword offset 0_D6 */ +#define W_Y_INC 0x035C /* Dword offset 0_D7 */ +#define W_START 0x0360 /* Dword offset 0_D8 */ +#define T_X_INC 0x0364 /* Dword offset 0_D9 */ +#define T_Y_INC 0x0368 /* Dword offset 0_DA */ + +#define SECONDARY_SCALE_PITCH 0x0368 /* Dword offset 0_DA */ + +#define T_START 0x036C /* Dword offset 0_DB */ +#define TEX_SIZE_PITCH 0x0370 /* Dword offset 0_DC */ +#define TEX_CNTL 0x0374 /* Dword offset 0_DD */ +#define SECONDARY_TEX_OFFSET 0x0378 /* Dword offset 0_DE */ +#define TEX_PALETTE 0x037C /* Dword offset 0_DF */ + +#define SCALE_PITCH_BOTH 0x0380 /* Dword offset 0_E0 */ +#define SECONDARY_SCALE_OFF_ACC 0x0384 /* Dword offset 0_E1 */ +#define SCALE_OFF_ACC 0x0388 /* Dword offset 0_E2 */ +#define SCALE_DST_Y_X 0x038C /* Dword offset 0_E3 */ + +#define COMPOSITE_SHADOW_ID 0x0398 /* Dword offset 0_E6 */ + +#define SECONDARY_SCALE_X_INC 0x039C /* Dword offset 0_E7 */ + +#define SPECULAR_RED_X_INC 0x039C /* Dword offset 0_E7 */ +#define SPECULAR_RED_Y_INC 0x03A0 /* Dword offset 0_E8 */ +#define SPECULAR_RED_START 0x03A4 /* Dword offset 0_E9 */ + +#define SECONDARY_SCALE_HACC 0x03A4 /* Dword offset 0_E9 */ + +#define SPECULAR_GREEN_X_INC 0x03A8 /* Dword offset 0_EA */ +#define SPECULAR_GREEN_Y_INC 0x03AC /* Dword offset 0_EB */ +#define SPECULAR_GREEN_START 0x03B0 /* Dword offset 0_EC */ +#define SPECULAR_BLUE_X_INC 0x03B4 /* Dword offset 0_ED */ +#define SPECULAR_BLUE_Y_INC 0x03B8 /* Dword offset 0_EE */ +#define SPECULAR_BLUE_START 0x03BC /* Dword offset 0_EF */ + +#define SCALE_X_INC__ALIAS__ 0x03C0 /* Dword offset 0_F0 */ + +#define RED_X_INC__ALIAS__ 0x03C0 /* Dword offset 0_F0 */ +#define RED_Y_INC 0x03C4 /* Dword offset 0_F1 */ +#define RED_START 0x03C8 /* Dword offset 0_F2 */ + +#define SCALE_HACC 0x03C8 /* Dword offset 0_F2 */ +#define SCALE_Y_INC__ALIAS__ 0x03CC /* Dword offset 0_F3 */ + +#define GREEN_X_INC__ALIAS__ 0x03CC /* Dword offset 0_F3 */ +#define GREEN_Y_INC 0x03D0 /* Dword offset 0_F4 */ + +#define SECONDARY_SCALE_Y_INC 0x03D0 /* Dword offset 0_F4 */ +#define SECONDARY_SCALE_VACC 0x03D4 /* Dword offset 0_F5 */ + +#define GREEN_START 0x03D4 /* Dword offset 0_F5 */ +#define BLUE_X_INC 0x03D8 /* Dword offset 0_F6 */ +#define BLUE_Y_INC 0x03DC /* Dword offset 0_F7 */ +#define BLUE_START 0x03E0 /* Dword offset 0_F8 */ +#define Z_X_INC 0x03E4 /* Dword offset 0_F9 */ +#define Z_Y_INC 0x03E8 /* Dword offset 0_FA */ +#define Z_START 0x03EC /* Dword offset 0_FB */ +#define ALPHA_X_INC 0x03F0 /* Dword offset 0_FC */ +#define FOG_X_INC 0x03F0 /* Dword offset 0_FC */ +#define ALPHA_Y_INC 0x03F4 /* Dword offset 0_FD */ +#define FOG_Y_INC 0x03F4 /* Dword offset 0_FD */ +#define ALPHA_START 0x03F8 /* Dword offset 0_FE */ +#define FOG_START 0x03F8 /* Dword offset 0_FE */ + +#define OVERLAY_Y_X_START 0x0400 /* Dword offset 1_00 */ +#define OVERLAY_Y_X_END 0x0404 /* Dword offset 1_01 */ +#define OVERLAY_VIDEO_KEY_CLR 0x0408 /* Dword offset 1_02 */ +#define OVERLAY_VIDEO_KEY_MSK 0x040C /* Dword offset 1_03 */ +#define OVERLAY_GRAPHICS_KEY_CLR 0x0410 /* Dword offset 1_04 */ +#define OVERLAY_GRAPHICS_KEY_MSK 0x0414 /* Dword offset 1_05 */ +#define OVERLAY_KEY_CNTL 0x0418 /* Dword offset 1_06 */ + +#define OVERLAY_SCALE_INC 0x0420 /* Dword offset 1_08 */ +#define OVERLAY_SCALE_CNTL 0x0424 /* Dword offset 1_09 */ +#define SCALER_HEIGHT_WIDTH 0x0428 /* Dword offset 1_0A */ +#define SCALER_TEST 0x042C /* Dword offset 1_0B */ +#define SCALER_BUF0_OFFSET 0x0434 /* Dword offset 1_0D */ +#define SCALER_BUF1_OFFSET 0x0438 /* Dword offset 1_0E */ +#define SCALE_BUF_PITCH 0x043C /* Dword offset 1_0F */ + +#define CAPTURE_START_END 0x0440 /* Dword offset 1_10 */ +#define CAPTURE_X_WIDTH 0x0444 /* Dword offset 1_11 */ +#define VIDEO_FORMAT 0x0448 /* Dword offset 1_12 */ +#define VBI_START_END 0x044C /* Dword offset 1_13 */ +#define CAPTURE_CONFIG 0x0450 /* Dword offset 1_14 */ +#define TRIG_CNTL 0x0454 /* Dword offset 1_15 */ + +#define OVERLAY_EXCLUSIVE_HORZ 0x0458 /* Dword offset 1_16 */ +#define OVERLAY_EXCLUSIVE_VERT 0x045C /* Dword offset 1_17 */ + +#define VAL_WIDTH 0x0460 /* Dword offset 1_18 */ +#define CAPTURE_DEBUG 0x0464 /* Dword offset 1_19 */ +#define VIDEO_SYNC_TEST 0x0468 /* Dword offset 1_1A */ + +#define SNAPSHOT_VH_COUNTS 0x0470 /* Dword offset 1_1C */ +#define SNAPSHOT_F_COUNT 0x0474 /* Dword offset 1_1D */ +#define N_VIF_COUNT 0x0478 /* Dword offset 1_1E */ +#define SNAPSHOT_VIF_COUNT 0x047C /* Dword offset 1_1F */ + +#define CAPTURE_BUF0_OFFSET 0x0480 /* Dword offset 1_20 */ +#define CAPTURE_BUF1_OFFSET 0x0484 /* Dword offset 1_21 */ +#define CAPTURE_BUF_PITCH 0x0488 /* Dword offset 1_22 */ + +#define MPP_CONFIG 0x04C0 /* Dword offset 1_30 */ +#define MPP_STROBE_SEQ 0x04C4 /* Dword offset 1_31 */ +#define MPP_ADDR 0x04C8 /* Dword offset 1_32 */ +#define MPP_DATA 0x04CC /* Dword offset 1_33 */ +#define TVO_CNTL 0x0500 /* Dword offset 1_40 */ + +#define CRT_HORZ_VERT_LOAD 0x0544 /* Dword offset 1_51 */ + +#define AGP_BASE 0x0548 /* Dword offset 1_52 */ +#define AGP_CNTL 0x054C /* Dword offset 1_53 */ + +#define SCALER_COLOUR_CNTL 0x0550 /* Dword offset 1_54 */ +#define SCALER_H_COEFF0 0x0554 /* Dword offset 1_55 */ +#define SCALER_H_COEFF1 0x0558 /* Dword offset 1_56 */ +#define SCALER_H_COEFF2 0x055C /* Dword offset 1_57 */ +#define SCALER_H_COEFF3 0x0560 /* Dword offset 1_58 */ +#define SCALER_H_COEFF4 0x0564 /* Dword offset 1_59 */ + +#define GUI_CNTL 0x0578 /* Dword offset 1_5E */ + +#define BM_FRAME_BUF_OFFSET 0x0580 /* Dword offset 1_60 */ +#define BM_SYSTEM_MEM_ADDR 0x0584 /* Dword offset 1_61 */ +#define BM_COMMAND 0x0588 /* Dword offset 1_62 */ +#define BM_STATUS 0x058C /* Dword offset 1_63 */ +#define BM_GUI_TABLE 0x05B8 /* Dword offset 1_6E */ +#define BM_SYSTEM_TABLE 0x05BC /* Dword offset 1_6F */ + +#define SCALER_BUF0_OFFSET_U 0x05D4 /* Dword offset 1_75 */ +#define SCALER_BUF0_OFFSET_V 0x05D8 /* Dword offset 1_76 */ +#define SCALER_BUF1_OFFSET_U 0x05DC /* Dword offset 1_77 */ +#define SCALER_BUF1_OFFSET_V 0x05E0 /* Dword offset 1_78 */ + +#define VERTEX_1_S 0x0640 /* Dword offset 1_90 */ +#define VERTEX_1_T 0x0644 /* Dword offset 1_91 */ +#define VERTEX_1_W 0x0648 /* Dword offset 1_92 */ +#define VERTEX_1_SPEC_ARGB 0x064C /* Dword offset 1_93 */ +#define VERTEX_1_Z 0x0650 /* Dword offset 1_94 */ +#define VERTEX_1_ARGB 0x0654 /* Dword offset 1_95 */ +#define VERTEX_1_X_Y 0x0658 /* Dword offset 1_96 */ +#define ONE_OVER_AREA 0x065C /* Dword offset 1_97 */ +#define VERTEX_2_S 0x0660 /* Dword offset 1_98 */ +#define VERTEX_2_T 0x0664 /* Dword offset 1_99 */ +#define VERTEX_2_W 0x0668 /* Dword offset 1_9A */ +#define VERTEX_2_SPEC_ARGB 0x066C /* Dword offset 1_9B */ +#define VERTEX_2_Z 0x0670 /* Dword offset 1_9C */ +#define VERTEX_2_ARGB 0x0674 /* Dword offset 1_9D */ +#define VERTEX_2_X_Y 0x0678 /* Dword offset 1_9E */ +#define ONE_OVER_AREA 0x065C /* Dword offset 1_9F */ +#define VERTEX_3_S 0x0680 /* Dword offset 1_A0 */ +#define VERTEX_3_T 0x0684 /* Dword offset 1_A1 */ +#define VERTEX_3_W 0x0688 /* Dword offset 1_A2 */ +#define VERTEX_3_SPEC_ARGB 0x068C /* Dword offset 1_A3 */ +#define VERTEX_3_Z 0x0690 /* Dword offset 1_A4 */ +#define VERTEX_3_ARGB 0x0694 /* Dword offset 1_A5 */ +#define VERTEX_3_X_Y 0x0698 /* Dword offset 1_A6 */ +#define ONE_OVER_AREA 0x065C /* Dword offset 1_A7 */ +#define VERTEX_1_S 0x0640 /* Dword offset 1_AB */ +#define VERTEX_1_T 0x0644 /* Dword offset 1_AC */ +#define VERTEX_1_W 0x0648 /* Dword offset 1_AD */ +#define VERTEX_2_S 0x0660 /* Dword offset 1_AE */ +#define VERTEX_2_T 0x0664 /* Dword offset 1_AF */ +#define VERTEX_2_W 0x0668 /* Dword offset 1_B0 */ +#define VERTEX_3_SECONDARY_S 0x06C0 /* Dword offset 1_B0 */ +#define VERTEX_3_S 0x0680 /* Dword offset 1_B1 */ +#define VERTEX_3_SECONDARY_T 0x06C4 /* Dword offset 1_B1 */ +#define VERTEX_3_T 0x0684 /* Dword offset 1_B2 */ +#define VERTEX_3_SECONDARY_W 0x06C8 /* Dword offset 1_B2 */ +#define VERTEX_3_W 0x0688 /* Dword offset 1_B3 */ +#define VERTEX_1_SPEC_ARGB 0x064C /* Dword offset 1_B4 */ +#define VERTEX_2_SPEC_ARGB 0x066C /* Dword offset 1_B5 */ +#define VERTEX_3_SPEC_ARGB 0x068C /* Dword offset 1_B6 */ +#define VERTEX_1_Z 0x0650 /* Dword offset 1_B7 */ +#define VERTEX_2_Z 0x0670 /* Dword offset 1_B8 */ +#define VERTEX_3_Z 0x0690 /* Dword offset 1_B9 */ +#define VERTEX_1_ARGB 0x0654 /* Dword offset 1_BA */ +#define VERTEX_2_ARGB 0x0674 /* Dword offset 1_BB */ +#define VERTEX_3_ARGB 0x0694 /* Dword offset 1_BC */ +#define VERTEX_1_X_Y 0x0658 /* Dword offset 1_BD */ +#define VERTEX_2_X_Y 0x0678 /* Dword offset 1_BE */ +#define VERTEX_3_X_Y 0x0698 /* Dword offset 1_BF */ +#define ONE_OVER_AREA_UC 0x0700 /* Dword offset 1_C0 */ +#define SETUP_CNTL 0x0704 /* Dword offset 1_C1 */ +#define VERTEX_1_SECONDARY_S 0x0728 /* Dword offset 1_CA */ +#define VERTEX_1_SECONDARY_T 0x072C /* Dword offset 1_CB */ +#define VERTEX_1_SECONDARY_W 0x0730 /* Dword offset 1_CC */ +#define VERTEX_2_SECONDARY_S 0x0734 /* Dword offset 1_CD */ +#define VERTEX_2_SECONDARY_T 0x0738 /* Dword offset 1_CE */ +#define VERTEX_2_SECONDARY_W 0x073C /* Dword offset 1_CF */ + + +/* CRTC control values (mostly CRTC_GEN_CNTL) */ + +#define CRTC_H_SYNC_NEG 0x00200000 +#define CRTC_V_SYNC_NEG 0x00200000 + +#define CRTC_DBL_SCAN_EN 0x00000001 +#define CRTC_INTERLACE_EN 0x00000002 +#define CRTC_HSYNC_DIS 0x00000004 +#define CRTC_VSYNC_DIS 0x00000008 +#define CRTC_CSYNC_EN 0x00000010 +#define CRTC_PIX_BY_2_EN 0x00000020 /* unused on RAGE */ +#define CRTC_DISPLAY_DIS 0x00000040 +#define CRTC_VGA_XOVERSCAN 0x00000040 + +#define CRTC_PIX_WIDTH_MASK 0x00000700 +#define CRTC_PIX_WIDTH_4BPP 0x00000100 +#define CRTC_PIX_WIDTH_8BPP 0x00000200 +#define CRTC_PIX_WIDTH_15BPP 0x00000300 +#define CRTC_PIX_WIDTH_16BPP 0x00000400 +#define CRTC_PIX_WIDTH_24BPP 0x00000500 +#define CRTC_PIX_WIDTH_32BPP 0x00000600 + +#define CRTC_BYTE_PIX_ORDER 0x00000800 +#define CRTC_PIX_ORDER_MSN_LSN 0x00000000 +#define CRTC_PIX_ORDER_LSN_MSN 0x00000800 + +#define CRTC_FIFO_LWM 0x000f0000 + +#define VGA_128KAP_PAGING 0x00100000 +#define VFC_SYNC_TRISTATE 0x00200000 +#define CRTC_LOCK_REGS 0x00400000 +#define CRTC_SYNC_TRISTATE 0x00800000 + +#define CRTC_EXT_DISP_EN 0x01000000 +#define CRTC_ENABLE 0x02000000 +#define CRTC_DISP_REQ_ENB 0x04000000 +#define VGA_ATI_LINEAR 0x08000000 +#define CRTC_VSYNC_FALL_EDGE 0x10000000 +#define VGA_TEXT_132 0x20000000 +#define VGA_XCRT_CNT_EN 0x40000000 +#define VGA_CUR_B_TEST 0x80000000 + +#define CRTC_CRNT_VLINE 0x07f00000 +#define CRTC_VBLANK 0x00000001 + + +/* DAC control values */ + +#define DAC_EXT_SEL_RS2 0x01 +#define DAC_EXT_SEL_RS3 0x02 +#define DAC_8BIT_EN 0x00000100 +#define DAC_PIX_DLY_MASK 0x00000600 +#define DAC_PIX_DLY_0NS 0x00000000 +#define DAC_PIX_DLY_2NS 0x00000200 +#define DAC_PIX_DLY_4NS 0x00000400 +#define DAC_BLANK_ADJ_MASK 0x00001800 +#define DAC_BLANK_ADJ_0 0x00000000 +#define DAC_BLANK_ADJ_1 0x00000800 +#define DAC_BLANK_ADJ_2 0x00001000 + + +/* Mix control values */ + +#define MIX_NOT_DST 0x0000 +#define MIX_0 0x0001 +#define MIX_1 0x0002 +#define MIX_DST 0x0003 +#define MIX_NOT_SRC 0x0004 +#define MIX_XOR 0x0005 +#define MIX_XNOR 0x0006 +#define MIX_SRC 0x0007 +#define MIX_NAND 0x0008 +#define MIX_NOT_SRC_OR_DST 0x0009 +#define MIX_SRC_OR_NOT_DST 0x000a +#define MIX_OR 0x000b +#define MIX_AND 0x000c +#define MIX_SRC_AND_NOT_DST 0x000d +#define MIX_NOT_SRC_AND_DST 0x000e +#define MIX_NOR 0x000f + +/* Maximum engine dimensions */ +#define ENGINE_MIN_X 0 +#define ENGINE_MIN_Y 0 +#define ENGINE_MAX_X 4095 +#define ENGINE_MAX_Y 16383 + +/* Mach64 engine bit constants - these are typically ORed together */ + +/* BUS_CNTL register constants */ +#define BUS_FIFO_ERR_ACK 0x00200000 +#define BUS_HOST_ERR_ACK 0x00800000 + +/* GEN_TEST_CNTL register constants */ +#define GEN_OVR_OUTPUT_EN 0x20 +#define HWCURSOR_ENABLE 0x80 +#define GUI_ENGINE_ENABLE 0x100 +#define BLOCK_WRITE_ENABLE 0x200 + +/* DSP_CONFIG register constants */ +#define DSP_XCLKS_PER_QW 0x00003fff +#define DSP_LOOP_LATENCY 0x000f0000 +#define DSP_PRECISION 0x00700000 + +/* DSP_ON_OFF register constants */ +#define DSP_OFF 0x000007ff +#define DSP_ON 0x07ff0000 + +/* CLOCK_CNTL register constants */ +#define CLOCK_SEL 0x0f +#define CLOCK_DIV 0x30 +#define CLOCK_DIV1 0x00 +#define CLOCK_DIV2 0x10 +#define CLOCK_DIV4 0x20 +#define CLOCK_STROBE 0x40 +#define PLL_WR_EN 0x02 + +/* PLL registers */ +#define PLL_MACRO_CNTL 0x01 +#define PLL_REF_DIV 0x02 +#define PLL_GEN_CNTL 0x03 +#define MCLK_FB_DIV 0x04 +#define PLL_VCLK_CNTL 0x05 +#define VCLK_POST_DIV 0x06 +#define VCLK0_FB_DIV 0x07 +#define VCLK1_FB_DIV 0x08 +#define VCLK2_FB_DIV 0x09 +#define VCLK3_FB_DIV 0x0A +#define PLL_XCLK_CNTL 0x0B +#define PLL_TEST_CTRL 0x0E +#define PLL_TEST_COUNT 0x0F + +/* Fields in PLL registers */ +#define PLL_PC_GAIN 0x07 +#define PLL_VC_GAIN 0x18 +#define PLL_DUTY_CYC 0xE0 +#define PLL_OVERRIDE 0x01 +#define PLL_MCLK_RST 0x02 +#define OSC_EN 0x04 +#define EXT_CLK_EN 0x08 +#define MCLK_SRC_SEL 0x70 +#define EXT_CLK_CNTL 0x80 +#define VCLK_SRC_SEL 0x03 +#define PLL_VCLK_RST 0x04 +#define VCLK_INVERT 0x08 +#define VCLK0_POST 0x03 +#define VCLK1_POST 0x0C +#define VCLK2_POST 0x30 +#define VCLK3_POST 0xC0 + +/* CONFIG_CNTL register constants */ +#define APERTURE_4M_ENABLE 1 +#define APERTURE_8M_ENABLE 2 +#define VGA_APERTURE_ENABLE 4 + +/* CONFIG_STAT0 register constants (GX, CX) */ +#define CFG_BUS_TYPE 0x00000007 +#define CFG_MEM_TYPE 0x00000038 +#define CFG_INIT_DAC_TYPE 0x00000e00 + +/* CONFIG_STAT0 register constants (CT, ET, VT) */ +#define CFG_MEM_TYPE_xT 0x00000007 + +#define ISA 0 +#define EISA 1 +#define LOCAL_BUS 6 +#define PCI 7 + +/* Memory types for GX, CX */ +#define DRAMx4 0 +#define VRAMx16 1 +#define VRAMx16ssr 2 +#define DRAMx16 3 +#define GraphicsDRAMx16 4 +#define EnhancedVRAMx16 5 +#define EnhancedVRAMx16ssr 6 + +/* Memory types for CT, ET, VT, GT */ +#define DRAM 1 +#define EDO 2 +#define PSEUDO_EDO 3 +#define SDRAM 4 +#define SGRAM 5 +#define WRAM 6 + +#define DAC_INTERNAL 0x00 +#define DAC_IBMRGB514 0x01 +#define DAC_ATI68875 0x02 +#define DAC_TVP3026_A 0x72 +#define DAC_BT476 0x03 +#define DAC_BT481 0x04 +#define DAC_ATT20C491 0x14 +#define DAC_SC15026 0x24 +#define DAC_MU9C1880 0x34 +#define DAC_IMSG174 0x44 +#define DAC_ATI68860_B 0x05 +#define DAC_ATI68860_C 0x15 +#define DAC_TVP3026_B 0x75 +#define DAC_STG1700 0x06 +#define DAC_ATT498 0x16 +#define DAC_STG1702 0x07 +#define DAC_SC15021 0x17 +#define DAC_ATT21C498 0x27 +#define DAC_STG1703 0x37 +#define DAC_CH8398 0x47 +#define DAC_ATT20C408 0x57 + +#define CLK_ATI18818_0 0 +#define CLK_ATI18818_1 1 +#define CLK_STG1703 2 +#define CLK_CH8398 3 +#define CLK_INTERNAL 4 +#define CLK_ATT20C408 5 +#define CLK_IBMRGB514 6 + +/* MEM_CNTL register constants */ +#define MEM_SIZE_ALIAS 0x00000007 +#define MEM_SIZE_512K 0x00000000 +#define MEM_SIZE_1M 0x00000001 +#define MEM_SIZE_2M 0x00000002 +#define MEM_SIZE_4M 0x00000003 +#define MEM_SIZE_6M 0x00000004 +#define MEM_SIZE_8M 0x00000005 +#define MEM_SIZE_ALIAS_GTB 0x0000000F +#define MEM_SIZE_2M_GTB 0x00000003 +#define MEM_SIZE_4M_GTB 0x00000007 +#define MEM_SIZE_6M_GTB 0x00000009 +#define MEM_SIZE_8M_GTB 0x0000000B +#define MEM_BNDRY 0x00030000 +#define MEM_BNDRY_0K 0x00000000 +#define MEM_BNDRY_256K 0x00010000 +#define MEM_BNDRY_512K 0x00020000 +#define MEM_BNDRY_1M 0x00030000 +#define MEM_BNDRY_EN 0x00040000 + +/* ATI PCI constants */ +#define PCI_ATI_VENDOR_ID 0x1002 +#define PCI_MACH64_GX 0x4758 +#define PCI_MACH64_CX 0x4358 +#define PCI_MACH64_CT 0x4354 +#define PCI_MACH64_ET 0x4554 +#define PCI_MACH64_VT 0x5654 +#define PCI_MACH64_GT 0x4754 + +/* CONFIG_CHIP_ID register constants */ +#define CFG_CHIP_TYPE 0x0000FFFF +#define CFG_CHIP_CLASS 0x00FF0000 +#define CFG_CHIP_REV 0xFF000000 +#define CFG_CHIP_VERSION 0x07000000 +#define CFG_CHIP_FOUNDRY 0x38000000 +#define CFG_CHIP_REVISION 0xC0000000 + +/* Chip IDs read from CONFIG_CHIP_ID */ +#define MACH64_GX_ID 0xD7 +#define MACH64_CX_ID 0x57 +#define MACH64_CT_ID 0x4354 +#define MACH64_ET_ID 0x4554 +#define MACH64_VT_ID 0x5654 +#define MACH64_GT_ID 0x4754 + +/* Mach64 chip types */ +#define MACH64_UNKNOWN 0 +#define MACH64_GX 1 +#define MACH64_CX 2 +#define MACH64_CT 3 +#define MACH64_ET 4 +#define MACH64_VT 5 +#define MACH64_GT 6 + +/* DST_CNTL register constants */ +#define DST_X_RIGHT_TO_LEFT 0 +#define DST_X_LEFT_TO_RIGHT 1 +#define DST_Y_BOTTOM_TO_TOP 0 +#define DST_Y_TOP_TO_BOTTOM 2 +#define DST_X_MAJOR 0 +#define DST_Y_MAJOR 4 +#define DST_X_TILE 8 +#define DST_Y_TILE 0x10 +#define DST_LAST_PEL 0x20 +#define DST_POLYGON_ENABLE 0x40 +#define DST_24_ROTATION_ENABLE 0x80 + +/* SRC_CNTL register constants */ +#define SRC_PATTERN_ENABLE 1 +#define SRC_ROTATION_ENABLE 2 +#define SRC_LINEAR_ENABLE 4 +#define SRC_BYTE_ALIGN 8 +#define SRC_LINE_X_RIGHT_TO_LEFT 0 +#define SRC_LINE_X_LEFT_TO_RIGHT 0x10 + +/* HOST_CNTL register constants */ +#define HOST_BYTE_ALIGN 1 + +/* GUI_TRAJ_CNTL register constants */ +#define PAT_MONO_8x8_ENABLE 0x01000000 +#define PAT_CLR_4x2_ENABLE 0x02000000 +#define PAT_CLR_8x1_ENABLE 0x04000000 + +/* DP_CHAIN_MASK register constants */ +#define DP_CHAIN_4BPP 0x8888 +#define DP_CHAIN_7BPP 0xD2D2 +#define DP_CHAIN_8BPP 0x8080 +#define DP_CHAIN_8BPP_RGB 0x9292 +#define DP_CHAIN_15BPP 0x4210 +#define DP_CHAIN_16BPP 0x8410 +#define DP_CHAIN_24BPP 0x8080 +#define DP_CHAIN_32BPP 0x8080 + +/* DP_PIX_WIDTH register constants */ +#define DST_1BPP 0 +#define DST_4BPP 1 +#define DST_8BPP 2 +#define DST_15BPP 3 +#define DST_16BPP 4 +#define DST_32BPP 6 +#define SRC_1BPP 0 +#define SRC_4BPP 0x100 +#define SRC_8BPP 0x200 +#define SRC_15BPP 0x300 +#define SRC_16BPP 0x400 +#define SRC_32BPP 0x600 +#define HOST_1BPP 0 +#define HOST_4BPP 0x10000 +#define HOST_8BPP 0x20000 +#define HOST_15BPP 0x30000 +#define HOST_16BPP 0x40000 +#define HOST_32BPP 0x60000 +#define BYTE_ORDER_MSB_TO_LSB 0 +#define BYTE_ORDER_LSB_TO_MSB 0x1000000 + +/* DP_MIX register constants */ +#define BKGD_MIX_NOT_D 0 +#define BKGD_MIX_ZERO 1 +#define BKGD_MIX_ONE 2 +#define BKGD_MIX_D 3 +#define BKGD_MIX_NOT_S 4 +#define BKGD_MIX_D_XOR_S 5 +#define BKGD_MIX_NOT_D_XOR_S 6 +#define BKGD_MIX_S 7 +#define BKGD_MIX_NOT_D_OR_NOT_S 8 +#define BKGD_MIX_D_OR_NOT_S 9 +#define BKGD_MIX_NOT_D_OR_S 10 +#define BKGD_MIX_D_OR_S 11 +#define BKGD_MIX_D_AND_S 12 +#define BKGD_MIX_NOT_D_AND_S 13 +#define BKGD_MIX_D_AND_NOT_S 14 +#define BKGD_MIX_NOT_D_AND_NOT_S 15 +#define BKGD_MIX_D_PLUS_S_DIV2 0x17 +#define FRGD_MIX_NOT_D 0 +#define FRGD_MIX_ZERO 0x10000 +#define FRGD_MIX_ONE 0x20000 +#define FRGD_MIX_D 0x30000 +#define FRGD_MIX_NOT_S 0x40000 +#define FRGD_MIX_D_XOR_S 0x50000 +#define FRGD_MIX_NOT_D_XOR_S 0x60000 +#define FRGD_MIX_S 0x70000 +#define FRGD_MIX_NOT_D_OR_NOT_S 0x80000 +#define FRGD_MIX_D_OR_NOT_S 0x90000 +#define FRGD_MIX_NOT_D_OR_S 0xa0000 +#define FRGD_MIX_D_OR_S 0xb0000 +#define FRGD_MIX_D_AND_S 0xc0000 +#define FRGD_MIX_NOT_D_AND_S 0xd0000 +#define FRGD_MIX_D_AND_NOT_S 0xe0000 +#define FRGD_MIX_NOT_D_AND_NOT_S 0xf0000 +#define FRGD_MIX_D_PLUS_S_DIV2 0x170000 + +/* DP_SRC register constants */ +#define BKGD_SRC_BKGD_CLR 0 +#define BKGD_SRC_FRGD_CLR 1 +#define BKGD_SRC_HOST 2 +#define BKGD_SRC_BLIT 3 +#define BKGD_SRC_PATTERN 4 +#define FRGD_SRC_BKGD_CLR 0 +#define FRGD_SRC_FRGD_CLR 0x100 +#define FRGD_SRC_HOST 0x200 +#define FRGD_SRC_BLIT 0x300 +#define FRGD_SRC_PATTERN 0x400 +#define MONO_SRC_ONE 0 +#define MONO_SRC_PATTERN 0x10000 +#define MONO_SRC_HOST 0x20000 +#define MONO_SRC_BLIT 0x30000 + +/* CLR_CMP_CNTL register constants */ +#define COMPARE_FALSE 0 +#define COMPARE_TRUE 1 +#define COMPARE_NOT_EQUAL 4 +#define COMPARE_EQUAL 5 +#define COMPARE_DESTINATION 0 +#define COMPARE_SOURCE 0x1000000 + +/* FIFO_STAT register constants */ +#define FIFO_ERR 0x80000000 + +/* CONTEXT_LOAD_CNTL constants */ +#define CONTEXT_NO_LOAD 0 +#define CONTEXT_LOAD 0x10000 +#define CONTEXT_LOAD_AND_DO_FILL 0x20000 +#define CONTEXT_LOAD_AND_DO_LINE 0x30000 +#define CONTEXT_EXECUTE 0 +#define CONTEXT_CMD_DISABLE 0x80000000 + +/* GUI_STAT register constants */ +#define ENGINE_IDLE 0 +#define ENGINE_BUSY 1 +#define SCISSOR_LEFT_FLAG 0x10 +#define SCISSOR_RIGHT_FLAG 0x20 +#define SCISSOR_TOP_FLAG 0x40 +#define SCISSOR_BOTTOM_FLAG 0x80 + +/* ATI VGA Extended Regsiters */ +#define sioATIEXT 0x1ce +#define bioATIEXT 0x3ce + +#define ATI2E 0xae +#define ATI32 0xb2 +#define ATI36 0xb6 + +/* VGA Graphics Controller Registers */ +#define VGAGRA 0x3ce +#define GRA06 0x06 + +/* VGA Seququencer Registers */ +#define VGASEQ 0x3c4 +#define SEQ02 0x02 +#define SEQ04 0x04 + +#define MACH64_MAX_X ENGINE_MAX_X +#define MACH64_MAX_Y ENGINE_MAX_Y + +#define INC_X 0x0020 +#define INC_Y 0x0080 + +#define RGB16_555 0x0000 +#define RGB16_565 0x0040 +#define RGB16_655 0x0080 +#define RGB16_664 0x00c0 + +#define POLY_TEXT_TYPE 0x0001 +#define IMAGE_TEXT_TYPE 0x0002 +#define TEXT_TYPE_8_BIT 0x0004 +#define TEXT_TYPE_16_BIT 0x0008 +#define POLY_TEXT_TYPE_8 (POLY_TEXT_TYPE | TEXT_TYPE_8_BIT) +#define IMAGE_TEXT_TYPE_8 (IMAGE_TEXT_TYPE | TEXT_TYPE_8_BIT) +#define POLY_TEXT_TYPE_16 (POLY_TEXT_TYPE | TEXT_TYPE_16_BIT) +#define IMAGE_TEXT_TYPE_16 (IMAGE_TEXT_TYPE | TEXT_TYPE_16_BIT) + +#define MACH64_NUM_CLOCKS 16 +#define MACH64_NUM_FREQS 50 + +/* Wait until "v" queue entries are free */ +#define aty_WaitQueue(v) { while ((aty_ld_le32(FIFO_STAT) & 0xffff) > \ + ((unsigned short)(0x8000 >> (v)))); } + +/* Wait until GP is idle and queue is empty */ +#define aty_WaitIdleEmpty() { aty_WaitQueue(16); \ + while ((aty_ld_le32(GUI_STAT) & 1) != 0); } + +#define SKIP_2(_v) ((((_v)<<1)&0xfff8)|((_v)&0x3)|(((_v)&0x80)>>5)) + +#define MACH64_BIT_BLT(_srcx, _srcy, _dstx, _dsty, _w, _h, _dir) \ +{ \ + aty_WaitQueue(5); \ + aty_st_le32(SRC_Y_X, (((_srcx) << 16) | ((_srcy) & 0x0000ffff))); \ + aty_st_le32(SRC_WIDTH1, (_w)); \ + aty_st_le32(DST_CNTL, (_dir)); \ + aty_st_le32(DST_Y_X, (((_dstx) << 16) | ((_dsty) & 0x0000ffff))); \ + aty_st_le32(DST_HEIGHT_WIDTH, (((_w) << 16) | ((_h) & 0x0000ffff))); \ +} +#endif /* REGMACH64_H */ + diff --git a/drivers/video/atyfb.c b/drivers/video/atyfb.c new file mode 100644 index 000000000..e1f8b3ef4 --- /dev/null +++ b/drivers/video/atyfb.c @@ -0,0 +1,1685 @@ +/* + * linux/drivers/video/atyfb.c -- Frame buffer device for ATI/Open Firmware + * + * Copyright (C) 1997 Geert Uytterhoeven + * + * This driver is partly based on the PowerMac console driver: + * + * Copyright (C) 1996 Paul Mackerras + * + * and on the PowerMac ATI/mach64 display driver: + * + * Copyright (C) 1997 Michael AK Tesch + * + * with work by Jon Howell + * Harry AC Eaton + * Anthony Tong <atong@uiuc.edu> + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/tty.h> +#include <linux/malloc.h> +#include <linux/vmalloc.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/fb.h> +#include <linux/selection.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/nvram.h> +#include <linux/vc_ioctl.h> +#include <asm/io.h> +#include <asm/prom.h> +#include <asm/pci-bridge.h> + +#include "aty.h" +#include "fbcon.h" +#include "fbcon-cfb8.h" +#include "fbcon-cfb16.h" +#include "fbcon-cfb32.h" + + +static int currcon = 0; +static struct display fb_disp; +static struct fb_info fb_info; +static struct { u_char red, green, blue, pad; } palette[256]; + +static char atyfb_name[16] = "ATY Mach64"; + +struct atyfb_par { + int vmode; + int cmode; + u_int vxres; /* virtual screen size */ + u_int vyres; + int xoffset; /* virtual screen position */ + int yoffset; +}; + + +/* + * Video mode values. + * These are supposed to be the same as the values that + * Apple uses in MacOS. + */ +#define VMODE_NVRAM 0 /* use value stored in nvram */ +#define VMODE_512_384_60I 1 /* 512x384, 60Hz interlaced (NTSC) */ +#define VMODE_512_384_60 2 /* 512x384, 60Hz */ +#define VMODE_640_480_50I 3 /* 640x480, 50Hz interlaced (PAL) */ +#define VMODE_640_480_60I 4 /* 640x480, 60Hz interlaced (NTSC) */ +#define VMODE_640_480_60 5 /* 640x480, 60Hz (VGA) */ +#define VMODE_640_480_67 6 /* 640x480, 67Hz */ +#define VMODE_640_870_75P 7 /* 640x870, 75Hz (portrait) */ +#define VMODE_768_576_50I 8 /* 768x576, 50Hz (PAL full frame) */ +#define VMODE_800_600_56 9 /* 800x600, 56Hz */ +#define VMODE_800_600_60 10 /* 800x600, 60Hz */ +#define VMODE_800_600_72 11 /* 800x600, 72Hz */ +#define VMODE_800_600_75 12 /* 800x600, 75Hz */ +#define VMODE_832_624_75 13 /* 832x624, 75Hz */ +#define VMODE_1024_768_60 14 /* 1024x768, 60Hz */ +#define VMODE_1024_768_70 15 /* 1024x768, 70Hz (or 72Hz?) */ +#define VMODE_1024_768_75V 16 /* 1024x768, 75Hz (VESA) */ +#define VMODE_1024_768_75 17 /* 1024x768, 75Hz */ +#define VMODE_1152_870_75 18 /* 1152x870, 75Hz */ +#define VMODE_1280_960_75 19 /* 1280x960, 75Hz */ +#define VMODE_1280_1024_75 20 /* 1280x1024, 75Hz */ +#define VMODE_MAX 20 +#define VMODE_CHOOSE 99 /* choose based on monitor sense */ + +/* + * Color mode values, used to select number of bits/pixel. + */ +#define CMODE_NVRAM -1 /* use value stored in nvram */ +#define CMODE_8 0 /* 8 bits/pixel */ +#define CMODE_16 1 /* 16 (actually 15) bits/pixel */ +#define CMODE_32 2 /* 32 (actually 24) bits/pixel */ + + +static int default_video_mode = VMODE_NVRAM; +static int default_color_mode = CMODE_NVRAM; + +static struct atyfb_par default_par; +static struct atyfb_par current_par; + + +/* + * Addresses in NVRAM where video mode and pixel size are stored. + */ +#define NV_VMODE 0x140f +#define NV_CMODE 0x1410 + +/* + * Horizontal and vertical resolution information. + */ +extern struct vmode_attr { + int hres; + int vres; + int vfreq; + int interlaced; +} vmode_attrs[VMODE_MAX]; + + +/* + * Horizontal and vertical resolution for each mode. + */ +static struct vmode_attr vmode_attrs[VMODE_MAX] = { + {512, 384, 60, 1}, + {512, 384, 60}, + {640, 480, 50, 1}, + {640, 480, 60, 1}, + {640, 480, 60}, + {640, 480, 67}, + {640, 870, 75}, + {768, 576, 50, 1}, + {800, 600, 56}, + {800, 600, 60}, + {800, 600, 72}, + {800, 600, 75}, + {832, 624, 75}, + {1024, 768, 60}, + {1024, 768, 72}, + {1024, 768, 75}, + {1024, 768, 75}, + {1152, 870, 75}, + {1280, 960, 75}, + {1280, 1024, 75} +}; + + +/* + * We get a sense value from the monitor and use it to choose + * what resolution to use. This structure maps sense values + * to display mode values (which determine the resolution and + * frequencies). + */ +static struct mon_map { + int sense; + int vmode; +} monitor_map [] = { + {0x000, VMODE_1280_1024_75}, /* 21" RGB */ + {0x114, VMODE_640_870_75P}, /* Portrait Monochrome */ + {0x221, VMODE_512_384_60}, /* 12" RGB*/ + {0x331, VMODE_1280_1024_75}, /* 21" RGB (Radius) */ + {0x334, VMODE_1280_1024_75}, /* 21" mono (Radius) */ + {0x335, VMODE_1280_1024_75}, /* 21" mono */ + {0x40A, VMODE_640_480_60I}, /* NTSC */ + {0x51E, VMODE_640_870_75P}, /* Portrait RGB */ + {0x603, VMODE_832_624_75}, /* 12"-16" multiscan */ + {0x60b, VMODE_1024_768_70}, /* 13"-19" multiscan */ + {0x623, VMODE_1152_870_75}, /* 13"-21" multiscan */ + {0x62b, VMODE_640_480_67}, /* 13"/14" RGB */ + {0x700, VMODE_640_480_50I}, /* PAL */ + {0x714, VMODE_640_480_60I}, /* NTSC */ + {0x717, VMODE_800_600_75}, /* VGA */ + {0x72d, VMODE_832_624_75}, /* 16" RGB (Goldfish) */ + {0x730, VMODE_768_576_50I}, /* PAL (Alternate) */ + {0x73a, VMODE_1152_870_75}, /* 3rd party 19" */ + {-1, VMODE_640_480_60}, /* catch-all, must be last */ +}; + +static int map_monitor_sense(int sense) +{ + struct mon_map *map; + + for (map = monitor_map; map->sense >= 0; ++map) + if (map->sense == sense) + break; + return map->vmode; +} + +struct aty_cmap_regs { + unsigned char windex; + unsigned char lut; + unsigned char mask; + unsigned char rindex; + unsigned char cntl; +}; + +typedef struct aty_regvals { + int offset[3]; /* first pixel address */ + + int crtc_h_sync_strt_wid[3]; /* depth dependant */ + int crtc_gen_cntl[3]; + int mem_cntl[3]; + + int crtc_h_tot_disp; /* mode dependant */ + int crtc_v_tot_disp; + int crtc_v_sync_strt_wid; + int crtc_off_pitch; + + unsigned char clock_val[2]; /* vals for 20 and 21 */ +} aty_regvals; + +struct rage_regvals { + int h_total, h_sync_start, h_sync_width; + int v_total, v_sync_start, v_sync_width; + int h_sync_neg, v_sync_neg; +}; + +static int aty_vram_reqd(const struct atyfb_par *par); +static struct aty_regvals *get_aty_struct(int vmode); + +static unsigned long frame_buffer; + +static int total_vram; /* total amount of video memory, bytes */ +static int chip_type; /* what chip type was detected */ + +static unsigned long ati_regbase; +static struct aty_cmap_regs *aty_cmap_regs; + +#include "ati-gx.h" +#include "ati-gt.h" +#include "ati-vt.h" + +static struct aty_regvals *aty_gt_reg_init[20] = { + NULL, NULL, NULL, NULL, + &aty_gt_reg_init_5, + &aty_gt_reg_init_6, + NULL, NULL, + &aty_gt_reg_init_9, + &aty_gt_reg_init_10, + &aty_gt_reg_init_11, + &aty_gt_reg_init_12, + &aty_gt_reg_init_13, + &aty_gt_reg_init_14, + &aty_gt_reg_init_15, + NULL, + &aty_gt_reg_init_17, + &aty_gt_reg_init_18, + NULL, + &aty_gt_reg_init_20 +}; + +static struct aty_regvals *aty_gx_reg_init[20] = { + NULL, NULL, NULL, NULL, + &aty_gx_reg_init_6, + &aty_gx_reg_init_6, + NULL, NULL, NULL, NULL, NULL, NULL, + &aty_gx_reg_init_13, + &aty_gx_reg_init_14, + &aty_gx_reg_init_15, + NULL, + &aty_gx_reg_init_17, + &aty_gx_reg_init_18, + NULL, + &aty_gx_reg_init_20 +}; + +static struct aty_regvals *aty_vt_reg_init[21] = { + NULL, NULL, NULL, NULL, + &aty_vt_reg_init_5, + &aty_vt_reg_init_6, + NULL, NULL, NULL, + &aty_vt_reg_init_10, + &aty_vt_reg_init_11, + &aty_vt_reg_init_12, + &aty_vt_reg_init_13, + &aty_vt_reg_init_14, + &aty_vt_reg_init_15, + NULL, + &aty_vt_reg_init_17, + &aty_vt_reg_init_18, + &aty_vt_reg_init_19, + &aty_vt_reg_init_20 +}; + + /* + * Interface used by the world + */ + +unsigned long atyfb_init(unsigned long mem_start); +void atyfb_setup(char *options, int *ints); + +static int atyfb_open(struct fb_info *info); +static int atyfb_release(struct fb_info *info); +static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info); +static int atyfb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int atyfb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int atyfb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info); + + + /* + * Interface to the low level console driver + */ + +static int atyfbcon_switch(int con, struct fb_info *info); +static int atyfbcon_updatevar(int con, struct fb_info *info); +static void atyfbcon_blank(int blank, struct fb_info *info); + + + /* + * Text console acceleration + */ + +#ifdef CONFIG_FBCON_CFB8 +static struct display_switch fbcon_aty8; +#endif + + +#ifdef CONFIG_FB_COMPAT_XPMAC +extern struct vc_mode display_info; +extern struct fb_info *console_fb_info; +extern int (*console_setmode_ptr)(struct vc_mode *, int); +extern int (*console_set_cmap_ptr)(struct fb_cmap *, int, int, + struct fb_info *); +static int atyfb_console_setmode(struct vc_mode *, int); +#endif + + + /* + * Internal routines + */ + +static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, + u_int *transp, struct fb_info *info); +static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info); +static void do_install_cmap(int con, struct fb_info *info); + + +static struct fb_ops atyfb_ops = { + atyfb_open, atyfb_release, atyfb_get_fix, atyfb_get_var, atyfb_set_var, + atyfb_get_cmap, atyfb_set_cmap, atyfb_pan_display, NULL, atyfb_ioctl +}; + + +static inline int aty_vram_reqd(const struct atyfb_par *par) +{ + return (par->vxres*par->vyres) << par->cmode; +} + +extern inline unsigned aty_ld_le32(volatile unsigned long addr) +{ + register unsigned long temp = ati_regbase,val; + + asm("lwbrx %0,%1,%2": "=r"(val):"r"(addr), "r"(temp)); + return val; +} + +extern inline void aty_st_le32(volatile unsigned long addr, unsigned val) +{ + register unsigned long temp = ati_regbase; + + asm("stwbrx %0,%1,%2": : "r"(val), "r"(addr), "r"(temp):"memory"); +} + +extern inline unsigned char aty_ld_8(volatile unsigned long addr) +{ + return *(char *) ((long) addr + (long) ati_regbase); +} + +extern inline void aty_st_8(volatile unsigned long addr, unsigned char val) +{ + *(unsigned char *) (addr + (unsigned long) ati_regbase) = val; +} + +static void aty_st_514(int offset, char val) +{ + aty_WaitQueue(5); + aty_st_8(DAC_CNTL, 1); + aty_st_8(DAC_W_INDEX, offset & 0xff); /* right addr byte */ + aty_st_8(DAC_DATA, (offset >> 8) & 0xff); /* left addr byte */ + eieio(); + aty_st_8(DAC_MASK, val); + eieio(); + aty_st_8(DAC_CNTL, 0); +} + +static void aty_st_pll(int offset, char val) +{ + aty_WaitQueue(3); + aty_st_8(CLOCK_CNTL + 1, (offset << 2) | PLL_WR_EN); /* write addr byte */ + eieio(); + aty_st_8(CLOCK_CNTL + 2, val); /* write the register value */ + eieio(); + aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN); +} + +static struct aty_regvals *get_aty_struct(int vmode) +{ + int v = vmode - 1; + + switch (chip_type) { + case MACH64_GT_ID: + return aty_gt_reg_init[v]; + break; + case MACH64_VT_ID: + return aty_vt_reg_init[v]; + break; + default: /* default to MACH64_GX_ID */ + return aty_gx_reg_init[v]; + break; + } +} + +static int read_aty_sense(void) +{ + int sense, i; + + aty_st_le32(GP_IO, 0x31003100); /* drive outputs high */ + __delay(200); + aty_st_le32(GP_IO, 0); /* turn off outputs */ + __delay(2000); + i = aty_ld_le32(GP_IO); /* get primary sense value */ + sense = ((i & 0x3000) >> 3) | (i & 0x100); + + /* drive each sense line low in turn and collect the other 2 */ + aty_st_le32(GP_IO, 0x20000000); /* drive A low */ + __delay(2000); + i = aty_ld_le32(GP_IO); + sense |= ((i & 0x1000) >> 7) | ((i & 0x100) >> 4); + aty_st_le32(GP_IO, 0x20002000); /* drive A high again */ + __delay(200); + + aty_st_le32(GP_IO, 0x10000000); /* drive B low */ + __delay(2000); + i = aty_ld_le32(GP_IO); + sense |= ((i & 0x2000) >> 10) | ((i & 0x100) >> 6); + aty_st_le32(GP_IO, 0x10001000); /* drive B high again */ + __delay(200); + + aty_st_le32(GP_IO, 0x01000000); /* drive C low */ + __delay(2000); + sense |= (aty_ld_le32(GP_IO) & 0x3000) >> 12; + aty_st_le32(GP_IO, 0); /* turn off outputs */ + + return sense; +} + +static void RGB514_Program(int cmode) +{ + typedef struct { + char pixel_dly; + char misc2_cntl; + char pixel_rep; + char pixel_cntl_index; + char pixel_cntl_v1; + } RGB514_DAC_Table; + + static RGB514_DAC_Table RGB514DAC_Tab[8] = { + {0, 0x41, 0x03, 0x71, 0x45}, // 8bpp + {0, 0x45, 0x04, 0x0c, 0x01}, // 555 + {0, 0x45, 0x06, 0x0e, 0x00}, // XRGB + }; + RGB514_DAC_Table *pDacProgTab; + + pDacProgTab = &RGB514DAC_Tab[cmode]; + + aty_st_514(0x90, 0x00); + aty_st_514(0x04, pDacProgTab->pixel_dly); + aty_st_514(0x05, 0x00); + + aty_st_514(0x2, 0x1); + aty_st_514(0x71, pDacProgTab->misc2_cntl); + aty_st_514(0x0a, pDacProgTab->pixel_rep); + + aty_st_514(pDacProgTab->pixel_cntl_index, pDacProgTab->pixel_cntl_v1); +} + +static void set_off_pitch(const struct atyfb_par *par) +{ + u32 pitch, offset; + + pitch = par->vxres>>3; + offset = ((par->yoffset*par->vxres+par->xoffset)>>3)<<par->cmode; + aty_st_le32(CRTC_OFF_PITCH, pitch<<22 | offset); + if (chip_type == MACH64_GT_ID) { + /* Is this OK for other chips? */ + aty_st_le32(DST_OFF_PITCH, pitch<<22 | offset); + aty_st_le32(SRC_OFF_PITCH, pitch<<22 | offset); + } +} + +static void atyfb_set_par(struct atyfb_par *par) +{ + int i, hres; + struct aty_regvals *init = get_aty_struct(par->vmode); + int vram_type = aty_ld_le32(CONFIG_STAT0) & 7; + + if (init == 0) /* paranoia, shouldn't get here */ + panic("aty: display mode %d not supported", par->vmode); + + current_par = *par; + hres = vmode_attrs[par->vmode-1].hres; + + /* clear FIFO errors */ + aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL) | BUS_HOST_ERR_ACK + | BUS_FIFO_ERR_ACK); + + /* Reset engine */ + i = aty_ld_le32(GEN_TEST_CNTL); + aty_st_le32(GEN_TEST_CNTL, i & ~GUI_ENGINE_ENABLE); + eieio(); + aty_WaitIdleEmpty(); + aty_st_le32(GEN_TEST_CNTL, i | GUI_ENGINE_ENABLE); + aty_WaitIdleEmpty(); + + if ( chip_type != MACH64_GT_ID ) { + i = aty_ld_le32(CRTC_GEN_CNTL); + aty_st_le32(CRTC_GEN_CNTL, i | CRTC_EXT_DISP_EN); + } + + if ( chip_type == MACH64_GX_ID ) { + i = aty_ld_le32(GEN_TEST_CNTL); + aty_st_le32(GEN_TEST_CNTL, i | GEN_OVR_OUTPUT_EN ); + } + + switch (chip_type) { + case MACH64_VT_ID: + aty_st_pll(PLL_MACRO_CNTL, 0xb5); + aty_st_pll(PLL_REF_DIV, 0x2d); + aty_st_pll(PLL_GEN_CNTL, 0x14); + aty_st_pll(MCLK_FB_DIV, 0xbd); + aty_st_pll(PLL_VCLK_CNTL, 0x0b); + aty_st_pll(VCLK_POST_DIV, init->clock_val[0]); + aty_st_pll(VCLK0_FB_DIV, init->clock_val[1]); + aty_st_pll(VCLK1_FB_DIV, 0xd6); + aty_st_pll(VCLK2_FB_DIV, 0xee); + aty_st_pll(VCLK3_FB_DIV, 0xf8); + aty_st_pll(PLL_XCLK_CNTL, 0x0); + aty_st_pll(PLL_TEST_CTRL, 0x0); + aty_st_pll(PLL_TEST_COUNT, 0x0); + break; + case MACH64_GT_ID: + if (vram_type == 5) { + aty_st_pll(0, 0xcd); + aty_st_pll(PLL_MACRO_CNTL, + par->vmode >= VMODE_1024_768_60 ? 0xd3: 0xd5); + aty_st_pll(PLL_REF_DIV, 0x21); + aty_st_pll(PLL_GEN_CNTL, 0x44); + aty_st_pll(MCLK_FB_DIV, 0xe8); + aty_st_pll(PLL_VCLK_CNTL, 0x03); + aty_st_pll(VCLK_POST_DIV, init->offset[0]); + aty_st_pll(VCLK0_FB_DIV, init->offset[1]); + aty_st_pll(VCLK1_FB_DIV, 0x8e); + aty_st_pll(VCLK2_FB_DIV, 0x9e); + aty_st_pll(VCLK3_FB_DIV, 0xc6); + aty_st_pll(PLL_XCLK_CNTL, init->offset[2]); + aty_st_pll(12, 0xa6); + aty_st_pll(13, 0x1b); + } else { + aty_st_pll(PLL_MACRO_CNTL, 0xd5); + aty_st_pll(PLL_REF_DIV, 0x21); + aty_st_pll(PLL_GEN_CNTL, 0xc4); + aty_st_pll(MCLK_FB_DIV, 0xda); + aty_st_pll(PLL_VCLK_CNTL, 0x03); + /* offset actually holds clock values */ + aty_st_pll(VCLK_POST_DIV, init->offset[0]); + aty_st_pll(VCLK0_FB_DIV, init->offset[1]); + aty_st_pll(VCLK1_FB_DIV, 0x8e); + aty_st_pll(VCLK2_FB_DIV, 0x9e); + aty_st_pll(VCLK3_FB_DIV, 0xc6); + aty_st_pll(PLL_TEST_CTRL, 0x0); + aty_st_pll(PLL_XCLK_CNTL, init->offset[2]); + aty_st_pll(12, 0xa0); + aty_st_pll(13, 0x1b); + } + break; + default: + RGB514_Program(par->cmode); + aty_WaitIdleEmpty(); + aty_st_514(0x06, 0x02); + aty_st_514(0x10, 0x01); + aty_st_514(0x70, 0x01); + aty_st_514(0x8f, 0x1f); + aty_st_514(0x03, 0x00); + aty_st_514(0x05, 0x00); + aty_st_514(0x20, init->clock_val[0]); + aty_st_514(0x21, init->clock_val[1]); + break; + } + + aty_ld_8(DAC_REGS); /* clear counter */ + aty_WaitIdleEmpty(); + + aty_st_le32(CRTC_H_TOTAL_DISP, init->crtc_h_tot_disp); + aty_st_le32(CRTC_H_SYNC_STRT_WID, init->crtc_h_sync_strt_wid[par->cmode]); + aty_st_le32(CRTC_V_TOTAL_DISP, init->crtc_v_tot_disp); + aty_st_le32(CRTC_V_SYNC_STRT_WID, init->crtc_v_sync_strt_wid); + + aty_st_8(CLOCK_CNTL, 0); + aty_st_8(CLOCK_CNTL, CLOCK_STROBE); + + aty_st_le32(CRTC_VLINE_CRNT_VLINE, 0); + + set_off_pitch(par); + + if (chip_type == MACH64_GT_ID) { + aty_st_le32(BUS_CNTL, 0x7b23a040); + + /* need to set DSP values !! assume sdram */ + i = init->crtc_gen_cntl[0] - (0x100000 * par->cmode); + if ( vram_type == 5 ) + i = init->crtc_gen_cntl[1] - (0x100000 * par->cmode); + aty_st_le32(DSP_CONFIG, i); + + i = aty_ld_le32(MEM_CNTL) & MEM_SIZE_ALIAS; + if ( vram_type == 5 ) { + i |= ((1 * par->cmode) << 26) | 0x4215b0; + aty_st_le32(DSP_ON_OFF,sgram_dsp[par->vmode-1][par->cmode]); + + //aty_st_le32(CLOCK_CNTL,8192); + } else { + i |= ((1 * par->cmode) << 26) | 0x300090; + aty_st_le32(DSP_ON_OFF, init->mem_cntl[par->cmode]); + } + + aty_st_le32(MEM_CNTL, i); + aty_st_le32(EXT_MEM_CNTL, 0x5000001); + + /* if (total_vram > 0x400000) + i |= 0x538; this not been verified on > 4Megs!! */ + } else { + +/* The magic constant below translates into: +* 5 = No RDY delay, 1 wait st for mem write, increment during burst transfer +* 9 = DAC access delayed, 1 wait state for DAC +* 0 = Disables interupts for FIFO errors +* e = Allows FIFO to generate 14 wait states before generating error +* 1 = DAC snooping disabled, ROM disabled +* 0 = ROM page at 0 (disabled so doesn't matter) +* f = 15 ROM wait states (disabled so doesn't matter) +* f = 15 BUS wait states (I'm not sure this applies to PCI bus types) +* at some point it would be good to experiment with bench marks to see if +* we can gain some speed by fooling with the wait states etc. +*/ + if (chip_type == MACH64_VT_ID) + aty_st_le32(BUS_CNTL, 0x680000f9); + else + aty_st_le32(BUS_CNTL, 0x590e10ff); + + switch (total_vram) { + case 0x00100000: + aty_st_le32(MEM_CNTL, vt_mem_cntl[0][par->cmode]); + break; + case 0x00200000: + aty_st_le32(MEM_CNTL, vt_mem_cntl[1][par->cmode]); + break; + case 0x00400000: + aty_st_le32(MEM_CNTL, vt_mem_cntl[2][par->cmode]); + break; + default: + i = aty_ld_le32(MEM_CNTL) & 0x000F; + aty_st_le32(MEM_CNTL, + (init->mem_cntl[par->cmode] & 0xFFFFFFF0) | i); + } + } +/* These magic constants are harder to figure out +* on the vt chipset bit 2 set makes the screen brighter +* and bit 15 makes the screen black! But nothing else +* seems to matter for the vt DAC_CNTL +*/ + switch (chip_type) { + case MACH64_GT_ID: + i = 0x86010102; + break; + case MACH64_VT_ID: + i = 0x87010184; + break; + default: + i = 0x47012100; + break; + } + + aty_st_le32(DAC_CNTL, i); + aty_st_8(DAC_MASK, 0xff); + + switch (par->cmode) { + case CMODE_16: + i = CRTC_PIX_WIDTH_15BPP; break; + /*case CMODE_24: */ + case CMODE_32: + i = CRTC_PIX_WIDTH_32BPP; break; + case CMODE_8: + default: + i = CRTC_PIX_WIDTH_8BPP; break; + } + + if (chip_type != MACH64_GT_ID) { + aty_st_le32(CRTC_INT_CNTL, 0x00000002); + aty_st_le32(GEN_TEST_CNTL, GUI_ENGINE_ENABLE | BLOCK_WRITE_ENABLE); /* gui_en block_en */ + i |= init->crtc_gen_cntl[par->cmode]; + } + /* Gentlemen, start your crtc engine */ + aty_st_le32(CRTC_GEN_CNTL, CRTC_EXT_DISP_EN | CRTC_ENABLE | i); + +#ifdef CONFIG_FB_COMPAT_XPMAC + display_info.height = vmode_attrs[par->vmode-1].vres; + display_info.width = vmode_attrs[par->vmode-1].hres; + display_info.depth = 8<<par->cmode; + display_info.pitch = par->vxres<<par->cmode; + display_info.mode = par->vmode; + strcpy(display_info.name, atyfb_name); + display_info.fb_address = + iopa(((chip_type != MACH64_GT_ID) ? + frame_buffer + init->offset[par->cmode] : frame_buffer)); + display_info.cmap_adr_address = iopa((unsigned long)&aty_cmap_regs->windex); + display_info.cmap_data_address = iopa((unsigned long)&aty_cmap_regs->lut); + display_info.disp_reg_address = iopa(ati_regbase); +#endif /* CONFIG_FB_COMPAT_XPMAC) */ +} + + + /* + * Open/Release the frame buffer device + */ + +static int atyfb_open(struct fb_info *info) + +{ + /* + * Nothing, only a usage count for the moment + */ + + MOD_INC_USE_COUNT; + return(0); +} + +static int atyfb_release(struct fb_info *info) +{ + MOD_DEC_USE_COUNT; + return(0); +} + + +static int encode_fix(struct fb_fix_screeninfo *fix, + const struct atyfb_par *par) +{ + struct aty_regvals *init; + + memset(fix, 0, sizeof(struct fb_fix_screeninfo)); + + strcpy(fix->id, atyfb_name); + init = get_aty_struct(par->vmode); + /* + * FIXME: This will cause problems on non-GT chips, because the frame + * buffer must be aligned to a page + */ + fix->smem_start = (char *)((chip_type != MACH64_GT_ID) + ? frame_buffer + init->offset[par->cmode] : frame_buffer); + fix->smem_len = (u32)total_vram; + if (fix->smem_len > 0x7ff000) + fix->smem_len = 0x7ff000; /* last page is MMIO */ + fix->mmio_start = (char *)(ati_regbase & ~0xfff); + fix->mmio_len = 4096; + fix->type = FB_TYPE_PACKED_PIXELS; + fix->type_aux = 0; + fix->line_length = par->vxres<<par->cmode; + fix->visual = par->cmode == CMODE_8 ? FB_VISUAL_PSEUDOCOLOR + : FB_VISUAL_TRUECOLOR; + fix->ywrapstep = 0; + fix->xpanstep = 8; + fix->ypanstep = 1; + + return 0; +} + + +static int decode_var(struct fb_var_screeninfo *var, + struct atyfb_par *par) +{ + int xres = var->xres; + int yres = var->yres; + int bpp = var->bits_per_pixel; + struct aty_regvals *init; + + /* This should support more video modes */ + + if (xres <= 512 && yres <= 384) + par->vmode = VMODE_512_384_60; /* 512x384, 60Hz */ + else if (xres <= 640 && yres <= 480) + par->vmode = VMODE_640_480_67; /* 640x480, 67Hz */ + else if (xres <= 640 && yres <= 870) + par->vmode = VMODE_640_870_75P; /* 640x870, 75Hz (portrait) */ + else if (xres <= 768 && yres <= 576) + par->vmode = VMODE_768_576_50I; /* 768x576, 50Hz (PAL full frame) */ + else if (xres <= 800 && yres <= 600) + par->vmode = VMODE_800_600_75; /* 800x600, 75Hz */ + else if (xres <= 832 && yres <= 624) + par->vmode = VMODE_832_624_75; /* 832x624, 75Hz */ + else if (xres <= 1024 && yres <= 768) + par->vmode = VMODE_1024_768_75; /* 1024x768, 75Hz */ + else if (xres <= 1152 && yres <= 870) + par->vmode = VMODE_1152_870_75; /* 1152x870, 75Hz */ + else if (xres <= 1280 && yres <= 960) + par->vmode = VMODE_1280_960_75; /* 1280x960, 75Hz */ + else if (xres <= 1280 && yres <= 1024) + par->vmode = VMODE_1280_1024_75; /* 1280x1024, 75Hz */ + else + return -EINVAL; + + xres = vmode_attrs[par->vmode-1].hres; + yres = vmode_attrs[par->vmode-1].vres; + + if (var->xres_virtual <= xres) + par->vxres = xres; + else + par->vxres = (var->xres_virtual+7) & ~7; + if (var->yres_virtual <= yres) + par->vyres = yres; + else + par->vyres = var->yres_virtual; + + par->xoffset = (var->xoffset+7) & ~7; + par->yoffset = var->yoffset; + if (par->xoffset+xres > par->vxres || par->yoffset+yres > par->vyres) + return -EINVAL; + + if (bpp <= 8) + par->cmode = CMODE_8; + else if (bpp <= 16) + par->cmode = CMODE_16; + else if (bpp <= 32) + par->cmode = CMODE_32; + else + return -EINVAL; + + if (aty_vram_reqd(par) > total_vram) + return -EINVAL; + + /* Check if we know about the wanted video mode */ + init = get_aty_struct(par->vmode); + if (init == NULL || init->crtc_h_sync_strt_wid[par->cmode] == 0 || + (chip_type != MACH64_GT_ID && + init->crtc_gen_cntl[par->cmode] == 0) || + (chip_type == MACH64_GT_ID && (aty_ld_le32(CONFIG_STAT0) & 7) == 5 && + init->crtc_gen_cntl[1] == 0)) + return -EINVAL; + +#if 0 + if (!fbmon_valid_timings(pixclock, htotal, vtotal, info)) + return -EINVAL; +#endif + + return 0; +} + +static int encode_var(struct fb_var_screeninfo *var, + const struct atyfb_par *par) +{ + memset(var, 0, sizeof(struct fb_var_screeninfo)); + + var->xres = vmode_attrs[par->vmode-1].hres; + var->yres = vmode_attrs[par->vmode-1].vres; + var->xres_virtual = par->vxres; + var->yres_virtual = par->vyres; + var->xoffset = par->xoffset; + var->yoffset = par->yoffset; + var->grayscale = 0; + switch (par->cmode) { + case CMODE_8: + var->bits_per_pixel = 8; + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 0; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + var->transp.offset = 0; + var->transp.length = 0; + break; + case CMODE_16: /* RGB 555 */ + var->bits_per_pixel = 16; + var->red.offset = 10; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 5; + var->blue.offset = 0; + var->blue.length = 5; + var->transp.offset = 0; + var->transp.length = 0; + break; + case CMODE_32: /* RGB 888 */ + var->bits_per_pixel = 32; + var->red.offset = 16; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + var->transp.offset = 24; + var->transp.length = 8; + break; + } + var->red.msb_right = 0; + var->green.msb_right = 0; + var->blue.msb_right = 0; + var->transp.msb_right = 0; + var->nonstd = 0; + var->activate = 0; + var->height = -1; + var->width = -1; + var->accel = /* FB_ACCEL_ATY */ 0; + var->vmode = FB_VMODE_NONINTERLACED; + var->left_margin = var->right_margin = 64; /* guesses */ + var->upper_margin = var->lower_margin = 32; + var->hsync_len = 64; + var->vsync_len = 2; + + /* no long long support in the kernel :-( */ + /* this splittig trick will work if xres > 232 */ + var->pixclock = 1000000000/ + (var->left_margin+var->xres+var->right_margin+var->hsync_len); + var->pixclock *= 1000; + var->pixclock /= vmode_attrs[par->vmode-1].vfreq* + (var->upper_margin+var->yres+var->lower_margin+var->vsync_len); + var->sync = 0; + + return 0; +} + + +static void init_par(struct atyfb_par *par, int vmode, int cmode) +{ + par->vmode = vmode; + par->cmode = cmode; + par->vxres = vmode_attrs[vmode-1].hres; + par->vyres = vmode_attrs[vmode-1].vres; + par->xoffset = 0; + par->yoffset = 0; +} + + + /* + * Get the Fixed Part of the Display + */ + +static int atyfb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) +{ + struct atyfb_par par; + + if (con == -1) + par = default_par; + else + decode_var(&fb_display[con].var, &par); + encode_fix(fix, &par); + return 0; +} + + + /* + * Get the User Defined Part of the Display + */ + +static int atyfb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + if (con == -1) + encode_var(var, &default_par); + else + *var=fb_display[con].var; + return 0; +} + + + /* + * Set the User Defined Part of the Display + */ + +static int atyfb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct atyfb_par par; + struct display *display; + int oldxres, oldyres, oldvxres, oldvyres, oldbpp; + int err; + int activate = var->activate; + + if (con >= 0) + display = &fb_display[con]; + else + display = &fb_disp; /* used during initialization */ + + if ((err = decode_var(var, &par))) + return err; + + encode_var(var, &par); + + if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { + oldxres = display->var.xres; + oldyres = display->var.yres; + oldvxres = display->var.xres_virtual; + oldvyres = display->var.yres_virtual; + oldbpp = display->var.bits_per_pixel; + display->var = *var; + if (oldxres != var->xres || oldyres != var->yres || + oldvxres != var->xres_virtual || oldvyres != var->yres_virtual || + oldbpp != var->bits_per_pixel) { + struct fb_fix_screeninfo fix; + + encode_fix(&fix, &par); + display->screen_base = (u_char *)fix.smem_start; + display->visual = fix.visual; + display->type = fix.type; + display->type_aux = fix.type_aux; + display->ypanstep = fix.ypanstep; + display->ywrapstep = fix.ywrapstep; + display->line_length = fix.line_length; + display->can_soft_blank = 1; + display->inverse = 0; + switch (par.cmode) { + case CMODE_8: +#if 1 + display->dispsw = &fbcon_cfb8; +#else + display->dispsw = &fbcon_aty8; +#endif + break; + case CMODE_16: + display->dispsw = &fbcon_cfb16; + break; + case CMODE_32: + display->dispsw = &fbcon_cfb32; + break; + default: + display->dispsw = NULL; + break; + } + if (fb_info.changevar) + (*fb_info.changevar)(con); + } + if (con == currcon) + atyfb_set_par(&par); + if (oldbpp != var->bits_per_pixel) { + if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) + return err; + do_install_cmap(con, info); + } + } + + return 0; +} + + + /* + * Pan or Wrap the Display + * + * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag + */ + +static int atyfb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + u32 xres, yres, xoffset, yoffset; + struct atyfb_par *par = ¤t_par; + + xres = vmode_attrs[par->vmode-1].hres; + yres = vmode_attrs[par->vmode-1].vres; + xoffset = (var->xoffset+7) & ~7; + yoffset = var->yoffset; + if (xoffset+xres > par->vxres || yoffset+yres > par->vyres) + return -EINVAL; + par->xoffset = xoffset; + par->yoffset = yoffset; + set_off_pitch(par); + return 0; +} + + /* + * Get the Colormap + */ + +static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + if (con == currcon) /* current console? */ + return fb_get_cmap(cmap, &fb_display[con].var, kspc, atyfb_getcolreg, + info); + else if (fb_display[con].cmap.len) /* non default colormap? */ + fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); + else + fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), + cmap, kspc ? 0 : 2); + return 0; +} + + /* + * Set the Colormap + */ + +static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + int err; + + if (!fb_display[con].cmap.len) { /* no colormap allocated? */ + if ((err = fb_alloc_cmap(&fb_display[con].cmap, + 1<<fb_display[con].var.bits_per_pixel, 0))) + return err; + } + if (con == currcon) /* current console? */ + return fb_set_cmap(cmap, &fb_display[con].var, kspc, atyfb_setcolreg, + info); + else + fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); + return 0; +} + + +static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info) +{ + return -EINVAL; +} + + + /* + * Initialisation + */ + +__initfunc(unsigned long atyfb_init(unsigned long mem_start)) +{ +#ifdef __powerpc__ + /* We don't want to be called like this. */ + /* We rely on Open Firmware (offb) instead. */ + return mem_start; +#else /* !__powerpc__ */ + /* To be merged with Bernd's mach64fb */ + return mem_start; +#endif /* !__powerpc__ */ +} + + +unsigned long atyfb_of_init(unsigned long mem_start, struct device_node *dp) +{ + int i, err, sense; + struct fb_var_screeninfo var; + struct aty_regvals *init; + unsigned long addr; + unsigned char bus, devfn; + unsigned short cmd; + + if (dp->next) + printk("Warning: only using first ATI card detected\n"); + if (dp->n_addrs != 1 && dp->n_addrs != 3) + printk("Warning: expecting 1 or 3 addresses for ATY (got %d)", + dp->n_addrs); + + ati_regbase = (int)ioremap((0x7ffc00 + dp->addrs[0].address), 0x1000); + aty_cmap_regs = (struct aty_cmap_regs *)(ati_regbase + 0xC0); + + /* enable memory-space accesses using config-space command register */ + if (pci_device_loc(dp, &bus, &devfn) == 0) { + pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd); + if (cmd != 0xffff) { + cmd |= PCI_COMMAND_MEMORY; + pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd); + } + } + chip_type = (aty_ld_le32(CONFIG_CHIP_ID) & CFG_CHIP_TYPE); + + i = aty_ld_le32(MEM_CNTL); + if (chip_type != MACH64_GT_ID) + switch (i & MEM_SIZE_ALIAS) { + case MEM_SIZE_512K: + total_vram = 0x80000; + break; + case MEM_SIZE_1M: + total_vram = 0x100000; + break; + case MEM_SIZE_2M: + total_vram = 0x200000; + break; + case MEM_SIZE_4M: + total_vram = 0x400000; + break; + case MEM_SIZE_6M: + total_vram = 0x600000; + break; + case MEM_SIZE_8M: + total_vram = 0x800000; + break; + default: + total_vram = 0x80000; + } + else + switch (i & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */ + case MEM_SIZE_512K: + total_vram = 0x80000; + break; + case MEM_SIZE_1M: + total_vram = 0x100000; + break; + case MEM_SIZE_2M_GTB: + total_vram = 0x200000; + break; + case MEM_SIZE_4M_GTB: + total_vram = 0x400000; + break; + case MEM_SIZE_6M_GTB: + total_vram = 0x600000; + break; + case MEM_SIZE_8M_GTB: + total_vram = 0x800000; + break; + default: + total_vram = 0x80000; + } + +#if 1 + printk("aty_display_init: node = %p, addrs = ", dp->node); + printk(" %x(%x)", dp->addrs[0].address, dp->addrs[0].size); + printk(", intrs ="); + for (i = 0; i < dp->n_intrs; ++i) + printk(" %x", dp->intrs[i].line); + printk("\nregbase: %x pci loc: %x:%x total_vram: %x cregs: %p\n", + (int)ati_regbase, bus, devfn, total_vram, aty_cmap_regs); +#endif + + /* Map in frame buffer */ + addr = dp->addrs[0].address; + + /* use the big-endian aperture (??) */ + addr += 0x800000; + frame_buffer = (unsigned long)__ioremap(addr, 0x800000, _PAGE_WRITETHRU); + + if (default_video_mode != -1) { + sense = read_aty_sense(); + printk("monitor sense = %x\n", sense); + if (default_video_mode == VMODE_NVRAM) { + default_video_mode = nvram_read_byte(NV_VMODE); + init = get_aty_struct(default_video_mode); + if (default_video_mode <= 0 || + default_video_mode > VMODE_MAX || init == 0) + default_video_mode = VMODE_CHOOSE; + } + if (default_video_mode == VMODE_CHOOSE) + default_video_mode = map_monitor_sense(sense); + + init = get_aty_struct(default_video_mode); + if (!init) + default_video_mode = VMODE_640_480_60; + } + + /* + * Reduce the pixel size if we don't have enough VRAM. + */ + + if (default_color_mode == CMODE_NVRAM) + default_color_mode = nvram_read_byte(NV_CMODE); + if (default_color_mode < CMODE_8 || + default_color_mode > CMODE_32) + default_color_mode = CMODE_8; + + init_par(&default_par, default_video_mode, default_color_mode); + while (aty_vram_reqd(&default_par) > total_vram) { + while (default_color_mode > CMODE_8 && + aty_vram_reqd(&default_par) > total_vram) { + --default_color_mode; + init_par(&default_par, default_video_mode, default_color_mode); + } + /* + * adjust the video mode smaller if there still is not enough VRAM + */ + if (aty_vram_reqd(&default_par) > total_vram) + do { + default_video_mode--; + init_par(&default_par, default_video_mode, default_color_mode); + init = get_aty_struct(default_video_mode); + } while ((init == 0) && + (default_video_mode > VMODE_640_480_60)); + } + + if (chip_type == MACH64_GT_ID && (aty_ld_le32(CONFIG_STAT0) & 7) == 5 + && init->crtc_gen_cntl[1] == 0) { + default_video_mode = VMODE_640_480_67; + default_color_mode = CMODE_8; + init_par(&default_par, default_video_mode, default_color_mode); + } + + switch (chip_type) { + case MACH64_GX_ID: + strcat(atyfb_name, "GX"); + break; + case MACH64_VT_ID: + strcat(atyfb_name, "VT"); + break; + case MACH64_GT_ID: + strcat(atyfb_name, "GT"); + break; + default: + break; + } + strcpy(fb_info.modename, atyfb_name); + fb_info.node = -1; + fb_info.fbops = &atyfb_ops; + fb_info.disp = &fb_disp; + fb_info.fontname[0] = '\0'; + fb_info.changevar = NULL; + fb_info.switch_con = &atyfbcon_switch; + fb_info.updatevar = &atyfbcon_updatevar; + fb_info.blank = &atyfbcon_blank; + + err = register_framebuffer(&fb_info); + if (err < 0) + return mem_start; + + for (i = 0; i < 16; i++) { + int j = color_table[i]; + palette[i].red = default_red[j]; + palette[i].green = default_grn[j]; + palette[i].blue = default_blu[j]; + } + atyfb_set_par(&default_par); + encode_var(&var, &default_par); + atyfb_set_var(&var, -1, &fb_info); + + printk("fb%d: %s frame buffer device on %s\n", GET_FB_IDX(fb_info.node), + atyfb_name, dp->full_name); + +#ifdef CONFIG_FB_COMPAT_XPMAC + if (!console_fb_info) { + console_fb_info = &fb_info; + console_setmode_ptr = atyfb_console_setmode; + console_set_cmap_ptr = atyfb_set_cmap; + } +#endif /* CONFIG_FB_COMPAT_XPMAC) */ + + return mem_start; +} + + +/* XXX: doesn't work yet */ +void atyfb_setup(char *options, int *ints) +{ + char *this_opt; + int vmode; + int depth; + + if (!options || !*options) + return; + + for (this_opt = strtok(options, ","); this_opt; + this_opt = strtok(NULL, ",")) { + if (!strncmp(this_opt, "vmode:", 6)) { + vmode = simple_strtoul(this_opt+6, NULL, 0); + if (vmode > 0 && vmode <= VMODE_MAX) + default_video_mode = vmode; + } else if (!strncmp(this_opt, "cmode:", 6)) { + depth = simple_strtoul(this_opt+6, NULL, 0); + switch (depth) { + case 8: + default_color_mode = CMODE_8; + break; + case 15: + case 16: + default_color_mode = CMODE_16; + break; + case 24: + case 32: + default_color_mode = CMODE_32; + break; + }; + } + } +} + + +static int atyfbcon_switch(int con, struct fb_info *info) +{ + struct atyfb_par par; + + /* Do we have to save the colormap? */ + if (fb_display[currcon].cmap.len) + fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1, + atyfb_getcolreg, info); + currcon = con; + decode_var(&fb_display[con].var, &par); + atyfb_set_par(&par); + /* Install new colormap */ + do_install_cmap(con, info); + return 0; +} + + /* + * Update the `var' structure (called by fbcon.c) + */ + +static int atyfbcon_updatevar(int con, struct fb_info *info) +{ + current_par.yoffset = fb_display[con].var.yoffset; + set_off_pitch(¤t_par); + return 0; +} + + /* + * Blank the display. + */ + +static void atyfbcon_blank(int blank, struct fb_info *info) +{ + char gen_cntl; + + gen_cntl = aty_ld_8(CRTC_GEN_CNTL); + if (blank & VESA_VSYNC_SUSPEND) + gen_cntl |= 0x8; + if (blank & VESA_HSYNC_SUSPEND) + gen_cntl |= 0x4; + if ((blank & VESA_POWERDOWN) == VESA_POWERDOWN) + gen_cntl |= 0x40; + if (blank == VESA_NO_BLANKING) + gen_cntl &= ~(0x4c); + aty_st_8(CRTC_GEN_CNTL, gen_cntl); +} + + + /* + * Read a single color register and split it into + * colors/transparent. Return != 0 for invalid regno. + */ + +static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, + u_int *transp, struct fb_info *info) +{ + if (regno > 255) + return 1; + *red = palette[regno].red; + *green = palette[regno].green; + *blue = palette[regno].blue; + return 0; +} + + + /* + * Set a single color register. The values supplied are already + * rounded down to the hardware's capabilities (according to the + * entries in the var structure). Return != 0 for invalid regno. + */ + +static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) +{ + int i, scale; + + if (regno > 255) + return 1; + palette[regno].red = red; + palette[regno].green = green; + palette[regno].blue = blue; + aty_WaitQueue(2); + i = aty_ld_8(DAC_CNTL) & 0xfc; + if (chip_type == MACH64_GT_ID) + i |= 0x2; /*DAC_CNTL|0x2 turns off the extra brightness for gt*/ + aty_st_8(DAC_CNTL, i); + aty_st_8(DAC_REGS + DAC_MASK, 0xff); + eieio(); + scale = ((chip_type != MACH64_GX_ID) && + (current_par.cmode == CMODE_16)) ? 3 : 0; + aty_WaitQueue(4); + aty_cmap_regs->windex = regno << scale; + eieio(); + aty_cmap_regs->lut = red << scale; + eieio(); + aty_cmap_regs->lut = green << scale; + eieio(); + aty_cmap_regs->lut = blue << scale; + eieio(); + if (regno < 16) { +#ifdef CONFIG_FBCON_CFB16 + fbcon_cfb16_cmap[regno] = (regno << 10) | (regno << 5) | regno; +#endif +#ifdef CONFIG_FBCON_CFB32 + fbcon_cfb32_cmap[regno] = (regno << 24) | (regno << 16) | + (regno << 8) | regno; +#endif + } + return 0; +} + + +static void do_install_cmap(int con, struct fb_info *info) +{ + if (con != currcon) + return; + if (fb_display[con].cmap.len) + fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1, + atyfb_setcolreg, info); + else + fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), + &fb_display[con].var, 1, atyfb_setcolreg, + info); +} + + + /* + * Accelerated functions + */ + +void aty_waitblit(void) +{ + aty_WaitIdleEmpty(); /* Make sure that all commands have finished */ +} + +void aty_rectcopy(int srcx, int srcy, int dstx, int dsty, u_int width, + u_int height) +{ + u_int direction = 0; + + if (srcy < dsty) { + dsty += height - 1; + srcy += height - 1; + } else + direction |= DST_Y_TOP_TO_BOTTOM; + + if (srcx < dstx) { + dstx += width - 1; + srcx += width - 1; + } else + direction |= DST_X_LEFT_TO_RIGHT; + + aty_WaitQueue(4); + aty_st_le32(DP_WRITE_MSK, 0x000000FF /* pGC->planemask */ ); + aty_st_le32(DP_MIX, (MIX_SRC << 16) | MIX_DST); + aty_st_le32(DP_SRC, FRGD_SRC_BLIT); + + aty_WaitQueue(5); + aty_st_le32(SRC_Y_X, (srcx << 16) | (srcy & 0x0000ffff)); + aty_st_le32(SRC_WIDTH1, width); + aty_st_le32(DST_CNTL, direction); + aty_st_le32(DST_Y_X, (dstx << 16) | (dsty & 0x0000ffff)); + aty_st_le32(DST_HEIGHT_WIDTH, (width << 16) | (height & 0x0000ffff)); + + aty_WaitIdleEmpty(); /* Make sure that all commands have finished */ + + /* + * Make sure that the destination trajectory is correctly set + * for subsequent calls. MACH64_BIT_BLT is the only function that + * currently changes the destination trajectory from L->R and T->B. + */ + aty_st_le32(DST_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM)); +} + +void aty_rectfill(int dstx, int dsty, u_int width, u_int height, u_int color) +{ + if (!width || !height) + return; + + aty_WaitQueue(5); + aty_st_le32(DP_FRGD_CLR, color /* pGC->fgPixel */ ); + aty_st_le32(DP_WRITE_MSK, 0x000000FF /* pGC->planemask */ ); + aty_st_le32(DP_MIX, (MIX_SRC << 16) | MIX_DST); + aty_st_le32(DP_SRC, FRGD_SRC_FRGD_CLR); + + aty_st_le32(DST_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM); + + aty_WaitQueue(2); + aty_st_le32(DST_Y_X, (((u_int)dstx << 16) | ((u_int)dsty & 0x0000ffff))); + aty_st_le32(DST_HEIGHT_WIDTH, (((u_int)width << 16) | height)); + + aty_WaitIdleEmpty(); /* Make sure that all commands have finished */ +} + + + /* + * Text console acceleration + */ + +static void fbcon_aty8_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) +{ + sx *= p->fontwidth; + sy *= p->fontheight; + dx *= p->fontwidth; + dy *= p->fontheight; + width *= p->fontwidth; + height *= p->fontheight; + + aty_rectcopy(sx, sy, dx, dy, width, height); +} + +static void fbcon_aty8_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width) +{ + u32 bgx = attr_bgcol_ec(p, conp); + bgx |= (bgx << 8); + bgx |= (bgx << 16); + + sx *= p->fontwidth; + sy *= p->fontheight; + width *= p->fontwidth; + height *= p->fontheight; + + aty_rectfill(sx, sy, width, height, bgx); +} + +static void fbcon_aty8_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx) +{ + aty_waitblit(); + fbcon_cfb8_putc(conp, p, c, yy, xx); +} + +static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p, + const char *s, int count, int yy, int xx) +{ + aty_waitblit(); + fbcon_cfb8_putcs(conp, p, s, count, yy, xx); +} + +static struct display_switch fbcon_aty8 = { + fbcon_cfb8_setup, fbcon_aty8_bmove, fbcon_aty8_clear, fbcon_aty8_putc, + fbcon_aty8_putcs, fbcon_cfb8_revc +}; + + +#ifdef CONFIG_FB_COMPAT_XPMAC + + /* + * Backward compatibility mode for Xpmac + */ + +static int atyfb_console_setmode(struct vc_mode *mode, int doit) +{ + int err; + struct fb_var_screeninfo var; + struct atyfb_par par; + int vmode, cmode; + + if (mode->mode <= 0 || mode->mode > VMODE_MAX ) + return -EINVAL; + vmode = mode->mode; + + switch (mode->depth) { + case 24: + case 32: + cmode = CMODE_32; + break; + case 16: + cmode = CMODE_16; + break; + case 8: + case 0: /* (default) */ + cmode = CMODE_8; + break; + default: + return -EINVAL; + } + init_par(&par, vmode, cmode); + encode_var(&var, &par); + if ((err = decode_var(&var, &par))) + return err; + if (doit) + atyfb_set_var(&var, currcon, 0); + return 0; +} + +#endif /* CONFIG_FB_COMPAT_XPMAC */ diff --git a/drivers/video/cyberfb.c b/drivers/video/cyberfb.c index ccd83bb01..2eaacb57d 100644 --- a/drivers/video/cyberfb.c +++ b/drivers/video/cyberfb.c @@ -36,18 +36,34 @@ #include <asm/system.h> #include <asm/irq.h> #include <asm/pgtable.h> +#include <asm/amigahw.h> + #include "s3blit.h" +#include "fbcon.h" +#include "fbcon-cfb8.h" +#include "fbcon-cfb16.h" + +#ifdef CYBERFBDEBUG +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) +#else +#define DPRINTK(fmt, args...) +#endif #define arraysize(x) (sizeof(x)/sizeof(*(x))) -struct Cyber_fb_par { + +#define wb_64(reg,dat) (*((unsigned char volatile *)CyberRegs + reg) = dat) + + + +struct cyberfb_par { int xres; int yres; int bpp; }; -static struct Cyber_fb_par current_par; +static struct cyberfb_par current_par; static int current_par_valid = 0; static int currcon = 0; @@ -68,13 +84,13 @@ static struct fb_hwswitch { /* Display Control */ - int (*encode_fix)(struct fb_fix_screeninfo *fix, struct Cyber_fb_par *par); - int (*decode_var)(struct fb_var_screeninfo *var, struct Cyber_fb_par *par); - int (*encode_var)(struct fb_var_screeninfo *var, struct Cyber_fb_par *par); + int (*encode_fix)(struct fb_fix_screeninfo *fix, struct cyberfb_par *par); + int (*decode_var)(struct fb_var_screeninfo *var, struct cyberfb_par *par); + int (*encode_var)(struct fb_var_screeninfo *var, struct cyberfb_par *par); int (*getcolreg)(u_int regno, u_int *red, u_int *green, u_int *blue, - u_int *transp); + u_int *transp, struct fb_info *info); int (*setcolreg)(u_int regno, u_int red, u_int green, u_int blue, - u_int transp); + u_int transp, struct fb_info *info); void (*blank)(int blank); } *fbhw; @@ -83,7 +99,7 @@ static struct fb_hwswitch { * Frame Buffer Name */ -static char Cyber_fb_name[16] = "Cybervision"; +static char cyberfb_name[16] = "Cybervision"; /* @@ -106,105 +122,67 @@ static unsigned char Cyber_colour_table [256][4]; static unsigned long CyberMem; static unsigned long CyberSize; static volatile char *CyberRegs; - - -/* - * Predefined Video Mode Names - */ - -static char *Cyber_fb_modenames[] = { - - /* - * Autodetect (Default) Video Mode - */ - - "default", - - /* - * Predefined Video Modes - */ - - "cyber8", /* Cybervision 8 bpp */ - "cyber16", /* Cybervision 16 bpp */ - "800x600x8", - "640x480x8", - - /* - * Dummy Video Modes - */ - - "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", - "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", - "dummy", "dummy", - - /* - * User Defined Video Modes - * - * This doesn't work yet!! - */ - - "user0", "user1", "user2", "user3", "user4", "user5", "user6", "user7" -}; - + /* - * Predefined Video Mode Definitions + * Predefined Video Modes */ -static struct fb_var_screeninfo cyber_fb_predefined[] = { - - /* - * Autodetect (Default) Video Mode - */ - - { 0, }, - - /* - * Predefined Video Modes - */ - - { - /* Cybervision 8 bpp */ - CYBER8_WIDTH, CYBER8_HEIGHT, CYBER8_WIDTH, CYBER8_HEIGHT, 0, 0, 8, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, CYBER8_PIXCLOCK, 64, 96, 35, 12, 112, 2, - FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED - }, { - /* Cybervision 16 bpp */ - 800, 600, 800, 600, 0, 0, 16, 0, - {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, CYBER16_PIXCLOCK, 64, 96, 35, 12, 112, 2, - FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED - }, { - /* Cybervision 8 bpp */ - 800, 600, 800, 600, 0, 0, 8, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, CYBER8_PIXCLOCK, 64, 96, 35, 12, 112, 2, - FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED - }, { - /* Cybervision 8 bpp */ - 640, 480, 640, 480, 0, 0, 8, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, CYBER8_PIXCLOCK, 64, 96, 35, 12, 112, 2, - FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED - }, - /* - * Dummy Video Modes - */ - - { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, - { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, - - /* - * User Defined Video Modes - */ - - { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, } +static struct fb_videomode cyberfb_predefined[] __initdata = { + { + "640x480-8", { /* Cybervision 8 bpp */ + 640, 480, 640, 480, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NONE, CYBER8_PIXCLOCK, 64, 96, 35, 12, 112, 2, + FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } + }, { + "800x600-8", { /* Cybervision 8 bpp */ + 800, 600, 800, 600, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NONE, CYBER8_PIXCLOCK, 64, 96, 35, 12, 112, 2, + FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } + }, { + "1024x768-8", { /* Cybervision 8 bpp */ + 1024, 768, 1024, 768, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NONE, CYBER8_PIXCLOCK, 64, 96, 35, 12, 112, 2, + FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } + }, { + "1152x886-8", { /* Cybervision 8 bpp */ + 1152, 886, 1152, 886, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NONE, CYBER8_PIXCLOCK, 64, 96, 35, 12, 112, 2, + FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } + }, { + "1280x1024-8", { /* Cybervision 8 bpp */ + 1280, 1024, 1280, 1024, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NONE, CYBER8_PIXCLOCK, 64, 96, 35, 12, 112, 2, + FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } + }, { + "1600x1200-8", { /* Cybervision 8 bpp */ + 1600, 1200, 1600, 1200, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NONE, CYBER8_PIXCLOCK, 64, 96, 35, 12, 112, 2, + FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } + }, { + "800x600-16", { /* Cybervision 16 bpp */ + 800, 600, 800, 600, 0, 0, 16, 0, + {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NONE, CYBER16_PIXCLOCK, 64, 96, 35, 12, 112, 2, + FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } + } }; -#define NUM_TOTAL_MODES arraysize(cyber_fb_predefined) -#define NUM_PREDEF_MODES (5) +#define NUM_TOTAL_MODES arraysize(cyberfb_predefined) static int Cyberfb_inverse = 0; @@ -212,57 +190,72 @@ static int Cyberfb_inverse = 0; static int Cyberfb_Cyber8 = 0; /* Use Cybervision board */ static int Cyberfb_Cyber16 = 0; /* Use Cybervision board */ #endif -static int Cyberfb_mode = 0; - /* * Some default modes */ -#define CYBER8_DEFMODE (1) -#define CYBER16_DEFMODE (2) +#define CYBER8_DEFMODE (0) +#define CYBER16_DEFMODE (6) + +static struct fb_var_screeninfo cyberfb_default; /* * Interface used by the world */ -void Cyber_video_setup(char *options, int *ints); - -static int Cyber_fb_open(int fbidx); -static int Cyber_fb_release(int fbidx); -static int Cyber_fb_get_fix(struct fb_fix_screeninfo *fix, int con); -static int Cyber_fb_get_var(struct fb_var_screeninfo *var, int con); -static int Cyber_fb_set_var(struct fb_var_screeninfo *var, int con); -static int Cyber_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con); -static int Cyber_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con); -static int Cyber_fb_pan_display(struct fb_var_screeninfo *var, int con); -static int Cyber_fb_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg, int con); +void cyberfb_setup(char *options, int *ints); + +static int cyberfb_open(struct fb_info *info); +static int cyberfb_release(struct fb_info *info); +static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct +fb_info *info); +static int cyberfb_get_var(struct fb_var_screeninfo *var, int con, struct +fb_info *info); +static int cyberfb_set_var(struct fb_var_screeninfo *var, int con, struct +fb_info *info); +static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int cyberfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int cyberfb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int cyberfb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info); /* * Interface to the low level console driver */ -unsigned long Cyber_fb_init(unsigned long mem_start); -static int Cyberfb_switch(int con); -static int Cyberfb_updatevar(int con); -static void Cyberfb_blank(int blank); -static int Cyberfb_setcmap(struct fb_cmap *cmap, int con); +unsigned long cyberfb_init(unsigned long mem_start); +static int Cyberfb_switch(int con, struct fb_info *info); +static int Cyberfb_updatevar(int con, struct fb_info *info); +static void Cyberfb_blank(int blank, struct fb_info *info); + + +/* + * Text console acceleration + */ + +#ifdef CONFIG_FBCON_CFB8 +static struct display_switch fbcon_cyber8; +#endif /* * Accelerated Functions used by the low level console driver */ -void Cyber_WaitQueue(u_short fifo); -void Cyber_WaitBlit(void); -void Cyber_BitBLT(u_short curx, u_short cury, u_short destx, u_short desty, - u_short width, u_short height, u_short mode); -void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height, - u_short mode, u_short color); -void Cyber_MoveCursor(u_short x, u_short y); +static void Cyber_WaitQueue(u_short fifo); +static void Cyber_WaitBlit(void); +static void Cyber_BitBLT(u_short curx, u_short cury, u_short destx, + u_short desty, u_short width, u_short height, + u_short mode); +static void Cyber_RectFill(u_short x, u_short y, u_short width, u_short height, + u_short mode, u_short color); +static void Cyber_MoveCursor(u_short x, u_short y); /* @@ -271,15 +264,15 @@ void Cyber_MoveCursor(u_short x, u_short y); static int Cyber_init(void); static int Cyber_encode_fix(struct fb_fix_screeninfo *fix, - struct Cyber_fb_par *par); + struct cyberfb_par *par); static int Cyber_decode_var(struct fb_var_screeninfo *var, - struct Cyber_fb_par *par); + struct cyberfb_par *par); static int Cyber_encode_var(struct fb_var_screeninfo *var, - struct Cyber_fb_par *par); + struct cyberfb_par *par); static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, - u_int *transp); + u_int *transp, struct fb_info *info); static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp); + u_int transp, struct fb_info *info); static void Cyber_blank(int blank); @@ -287,11 +280,11 @@ static void Cyber_blank(int blank); * Internal routines */ -static void Cyber_fb_get_par(struct Cyber_fb_par *par); -static void Cyber_fb_set_par(struct Cyber_fb_par *par); +static void cyberfb_get_par(struct cyberfb_par *par); +static void cyberfb_set_par(struct cyberfb_par *par); static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive); -static void do_install_cmap(int con); -static void Cyber_fb_set_disp(int con); +static void do_install_cmap(int con, struct fb_info *info); +static void cyberfb_set_disp(int con, struct fb_info *info); static int get_video_mode(const char *name); @@ -311,41 +304,32 @@ static int Cyber_init(void) char size; volatile u_long *CursorBase; -#if 0 - if (Cyberfb_mode == -1) + for (i = 0; i < 256; i++) { - if (Cyberfb_Cyber8) - Cyberfb_mode = CYBER8_DEFMODE; - else - Cyberfb_mode = CYBER16_DEFMODE; + Cyber_colour_table [i][0] = i; + Cyber_colour_table [i][1] = i; + Cyber_colour_table [i][2] = i; + Cyber_colour_table [i][3] = 0; } -#endif - - for (i = 0; i < 256; i++) - - for (i = 0; i < 256; i++) - { - Cyber_colour_table [i][0] = i; - Cyber_colour_table [i][1] = i; - Cyber_colour_table [i][2] = i; - Cyber_colour_table [i][3] = 0; - } /* * Just clear the thing for the biggest mode. + * + * ++Andre, TODO: determine size first, then clear all memory + * (the 3D penguin might need texture memory :-) ) */ - memset ((char*)CyberMem, 0, CYBER8_WIDTH * CYBER8_HEIGHT); + memset ((char*)CyberMem, 0, 1600 * 1200); /* Disable hardware cursor */ - *(CyberRegs + S3_CRTC_ADR) = S3_REG_LOCK2; - *(CyberRegs + S3_CRTC_DATA) = 0xa0; - *(CyberRegs + S3_CRTC_ADR) = S3_HGC_MODE; - *(CyberRegs + S3_CRTC_DATA) = 0x00; - *(CyberRegs + S3_CRTC_ADR) = S3_HWGC_DX; - *(CyberRegs + S3_CRTC_DATA) = 0x00; - *(CyberRegs + S3_CRTC_ADR) = S3_HWGC_DY; - *(CyberRegs + S3_CRTC_DATA) = 0x00; + wb_64(S3_CRTC_ADR, S3_REG_LOCK2); + wb_64(S3_CRTC_DATA, 0xa0); + wb_64(S3_CRTC_ADR, S3_HGC_MODE); + wb_64(S3_CRTC_DATA, 0x00); + wb_64(S3_CRTC_ADR, S3_HWGC_DX); + wb_64(S3_CRTC_DATA, 0x00); + wb_64(S3_CRTC_ADR, S3_HWGC_DY); + wb_64(S3_CRTC_DATA, 0x00); /* Get memory size (if not 2MB it is 4MB) */ *(CyberRegs + S3_CRTC_ADR) = S3_LAW_CTL; @@ -372,8 +356,8 @@ static int Cyber_init(void) *(CursorBase+3+(i*4)) = 0xffff0000; } - Cyber_setcolreg (255, 56, 100, 160, 0); - Cyber_setcolreg (254, 0, 0, 0, 0); + Cyber_setcolreg (255, 56, 100, 160, 0, NULL /* unused */); + Cyber_setcolreg (254, 0, 0, 0, 0, NULL /* unused */); return 0; } @@ -385,11 +369,11 @@ static int Cyber_init(void) */ static int Cyber_encode_fix(struct fb_fix_screeninfo *fix, - struct Cyber_fb_par *par) + struct cyberfb_par *par) { int i; - strcpy(fix->id, Cyber_fb_name); + strcpy(fix->id, cyberfb_name); fix->smem_start = (caddr_t)CyberMem; fix->smem_len = CyberSize; fix->mmio_start = (unsigned char *)CyberRegs; @@ -420,7 +404,7 @@ static int Cyber_encode_fix(struct fb_fix_screeninfo *fix, */ static int Cyber_decode_var(struct fb_var_screeninfo *var, - struct Cyber_fb_par *par) + struct cyberfb_par *par) { #if 1 par->xres = var->xres; @@ -447,7 +431,7 @@ static int Cyber_decode_var(struct fb_var_screeninfo *var, */ static int Cyber_encode_var(struct fb_var_screeninfo *var, - struct Cyber_fb_par *par) + struct cyberfb_par *par) { int i; @@ -486,7 +470,10 @@ static int Cyber_encode_var(struct fb_var_screeninfo *var, var->height = -1; var->width = -1; + var->accel = FB_ACCEL_CYBERVISION; + DPRINTK("accel CV64\n"); + var->vmode = FB_VMODE_NONINTERLACED; /* Dummy values */ @@ -517,20 +504,22 @@ static int Cyber_encode_var(struct fb_var_screeninfo *var, */ static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp) + u_int transp, struct fb_info *info) { if (regno > 255) + { return (1); + } - *(CyberRegs + 0x3c8) = (char)regno; + wb_64(0x3c8, (unsigned char) regno); Cyber_colour_table [regno][0] = red & 0xff; Cyber_colour_table [regno][1] = green & 0xff; Cyber_colour_table [regno][2] = blue & 0xff; Cyber_colour_table [regno][3] = transp; - *(CyberRegs + 0x3c9) = (red & 0xff) >> 2; - *(CyberRegs + 0x3c9) = (green & 0xff) >> 2; - *(CyberRegs + 0x3c9) = (blue & 0xff) >> 2; + wb_64(0x3c9, (red & 0xff) >> 2); + wb_64(0x3c9, (green & 0xff) >> 2); + wb_64(0x3c9, (blue & 0xff) >> 2); return (0); } @@ -542,13 +531,13 @@ static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue, */ static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, - u_int *transp) + u_int *transp, struct fb_info *info) { if (regno >= 256) return (1); - *red = Cyber_colour_table [regno][0]; - *green = Cyber_colour_table [regno][1]; - *blue = Cyber_colour_table [regno][2]; + *red = Cyber_colour_table [regno][0]; + *green = Cyber_colour_table [regno][1]; + *blue = Cyber_colour_table [regno][2]; *transp = Cyber_colour_table [regno][3]; return (0); } @@ -563,28 +552,32 @@ void Cyber_blank(int blank) int i; if (blank) + { for (i = 0; i < 256; i++) { - *(CyberRegs + 0x3c8) = i; - *(CyberRegs + 0x3c9) = 0; - *(CyberRegs + 0x3c9) = 0; - *(CyberRegs + 0x3c9) = 0; + wb_64(0x3c8, (unsigned char) i); + wb_64(0x3c9, 0); + wb_64(0x3c9, 0); + wb_64(0x3c9, 0); } + } else + { for (i = 0; i < 256; i++) { - *(CyberRegs + 0x3c8) = i; - *(CyberRegs + 0x3c9) = Cyber_colour_table [i][0] >> 2; - *(CyberRegs + 0x3c9) = Cyber_colour_table [i][1] >> 2; - *(CyberRegs + 0x3c9) = Cyber_colour_table [i][2] >> 2; + wb_64(0x3c8, (unsigned char) i); + wb_64(0x3c9, Cyber_colour_table[i][0] >> 2); + wb_64(0x3c9, Cyber_colour_table[i][1] >> 2); + wb_64(0x3c9, Cyber_colour_table[i][2] >> 2); } + } } /************************************************************** * We are waiting for "fifo" FIFO-slots empty */ -void Cyber_WaitQueue (u_short fifo) +static void Cyber_WaitQueue (u_short fifo) { u_short status; @@ -598,7 +591,7 @@ void Cyber_WaitQueue (u_short fifo) /************************************************************** * We are waiting for Hardware (Graphics Engine) not busy */ -void Cyber_WaitBlit (void) +static void Cyber_WaitBlit (void) { u_short status; @@ -612,8 +605,9 @@ void Cyber_WaitBlit (void) /************************************************************** * BitBLT - Through the Plane */ -void Cyber_BitBLT (u_short curx, u_short cury, u_short destx, u_short desty, - u_short width, u_short height, u_short mode) +static void Cyber_BitBLT (u_short curx, u_short cury, u_short destx, + u_short desty, u_short width, u_short height, + u_short mode) { u_short blitcmd = S3_BITBLT; @@ -655,8 +649,8 @@ void Cyber_BitBLT (u_short curx, u_short cury, u_short destx, u_short desty, /************************************************************** * Rectangle Fill Solid */ -void Cyber_RectFill (u_short x, u_short y, u_short width, u_short height, - u_short mode, u_short color) +static void Cyber_RectFill (u_short x, u_short y, u_short width, + u_short height, u_short mode, u_short color) { u_short blitcmd = S3_FILLEDRECT; @@ -677,11 +671,10 @@ void Cyber_RectFill (u_short x, u_short y, u_short width, u_short height, *((u_short volatile *)(CyberRegs + S3_CMD)) = blitcmd; } - /************************************************************** * Move cursor to x, y */ -void Cyber_MoveCursor (u_short x, u_short y) +static void Cyber_MoveCursor (u_short x, u_short y) { *(CyberRegs + S3_CRTC_ADR) = 0x39; *(CyberRegs + S3_CRTC_DATA) = 0xa0; @@ -714,16 +707,20 @@ static struct fb_hwswitch Cyber_switch = { * Fill the hardware's `par' structure. */ -static void Cyber_fb_get_par(struct Cyber_fb_par *par) +static void cyberfb_get_par(struct cyberfb_par *par) { if (current_par_valid) + { *par = current_par; + } else - fbhw->decode_var(&cyber_fb_predefined[Cyberfb_mode], par); + { + fbhw->decode_var(&cyberfb_default, par); + } } -static void Cyber_fb_set_par(struct Cyber_fb_par *par) +static void cyberfb_set_par(struct cyberfb_par *par) { current_par = *par; current_par_valid = 1; @@ -733,6 +730,7 @@ static void Cyber_fb_set_par(struct Cyber_fb_par *par) static void cyber_set_video(struct fb_var_screeninfo *var) { /* Set clipping rectangle to current screen size */ + *((u_short volatile *)(CyberRegs + 0xbee8)) = 0x1000; *((u_short volatile *)(CyberRegs + 0xbee8)) = 0x2000; @@ -744,13 +742,13 @@ static void cyber_set_video(struct fb_var_screeninfo *var) static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive) { int err, activate; - struct Cyber_fb_par par; + struct cyberfb_par par; if ((err = fbhw->decode_var(var, &par))) return(err); activate = var->activate; if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive) - Cyber_fb_set_par(&par); + cyberfb_set_par(&par); fbhw->encode_var(var, &par); var->activate = activate; @@ -759,16 +757,16 @@ static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive) } -static void do_install_cmap(int con) +static void do_install_cmap(int con, struct fb_info *info) { if (con != currcon) return; if (fb_display[con].cmap.len) fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1, - fbhw->setcolreg); + fbhw->setcolreg, info); else - fb_set_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), - &fb_display[con].var, 1, fbhw->setcolreg); + fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), + &fb_display[con].var, 1, fbhw->setcolreg, info); } @@ -776,7 +774,7 @@ static void do_install_cmap(int con) * Open/Release the frame buffer device */ -static int Cyber_fb_open(int fbidx) +static int cyberfb_open(struct fb_info *info) { /* * Nothing, only a usage count for the moment @@ -786,7 +784,7 @@ static int Cyber_fb_open(int fbidx) return(0); } -static int Cyber_fb_release(int fbidx) +static int cyberfb_release(struct fb_info *info) { MOD_DEC_USE_COUNT; return(0); @@ -797,13 +795,14 @@ static int Cyber_fb_release(int fbidx) * Get the Fixed Part of the Display */ -static int Cyber_fb_get_fix(struct fb_fix_screeninfo *fix, int con) +static int cyberfb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) { - struct Cyber_fb_par par; + struct cyberfb_par par; int error = 0; if (con == -1) - Cyber_fb_get_par(&par); + cyberfb_get_par(&par); else error = fbhw->decode_var(&fb_display[con].var, &par); return(error ? error : fbhw->encode_fix(fix, &par)); @@ -814,21 +813,28 @@ static int Cyber_fb_get_fix(struct fb_fix_screeninfo *fix, int con) * Get the User Defined Part of the Display */ -static int Cyber_fb_get_var(struct fb_var_screeninfo *var, int con) +static int cyberfb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) { - struct Cyber_fb_par par; + struct cyberfb_par par; int error = 0; - if (con == -1) { - Cyber_fb_get_par(&par); + if (con == -1) + { + cyberfb_get_par(&par); error = fbhw->encode_var(var, &par); - } else + disp.var = *var; /* ++Andre: don't know if this is the right place */ + } + else + { *var = fb_display[con].var; + } + return(error); } -static void Cyber_fb_set_disp(int con) +static void cyberfb_set_disp(int con, struct fb_info *info) { struct fb_fix_screeninfo fix; struct display *display; @@ -838,7 +844,7 @@ static void Cyber_fb_set_disp(int con) else display = &disp; /* used during initialization */ - Cyber_fb_get_fix(&fix, con); + cyberfb_get_fix(&fix, con, info); if (con == -1) con = 0; display->screen_base = (u_char *)fix.smem_start; @@ -849,6 +855,21 @@ static void Cyber_fb_set_disp(int con) display->ywrapstep = fix.ywrapstep; display->can_soft_blank = 1; display->inverse = Cyberfb_inverse; + switch (display->var.bits_per_pixel) { +#ifdef CONFIG_FBCON_CFB8 + case 8: + display->dispsw = &fbcon_cyber8; + break; +#endif +#ifdef CONFIG_FBCON_CFB16 + case 16: + display->dispsw = &fbcon_cfb16; + break; +#endif + default: + display->dispsw = NULL; + break; + } } @@ -856,7 +877,8 @@ static void Cyber_fb_set_disp(int con) * Set the User Defined Part of the Display */ -static int Cyber_fb_set_var(struct fb_var_screeninfo *var, int con) +static int cyberfb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) { int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp; @@ -873,10 +895,10 @@ static int Cyber_fb_set_var(struct fb_var_screeninfo *var, int con) oldvxres != var->xres_virtual || oldvyres != var->yres_virtual || oldbpp != var->bits_per_pixel) { - Cyber_fb_set_disp(con); + cyberfb_set_disp(con, info); (*fb_info.changevar)(con); fb_alloc_cmap(&fb_display[con].cmap, 0, 0); - do_install_cmap(con); + do_install_cmap(con, info); } } var->activate = 0; @@ -888,15 +910,16 @@ static int Cyber_fb_set_var(struct fb_var_screeninfo *var, int con) * Get the Colormap */ -static int Cyber_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con) +static int cyberfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) { if (con == currcon) /* current console? */ return(fb_get_cmap(cmap, &fb_display[con].var, - kspc, fbhw->getcolreg)); + kspc, fbhw->getcolreg, info)); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else - fb_copy_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), + fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), cmap, kspc ? 0 : 2); return(0); } @@ -906,7 +929,8 @@ static int Cyber_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con) * Set the Colormap */ -static int Cyber_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con) +static int cyberfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) { int err; @@ -915,9 +939,9 @@ static int Cyber_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con) 1<<fb_display[con].var.bits_per_pixel, 0))) return(err); } - if (con == currcon) /* current console? */ + if (con == currcon) /* current console? */ return(fb_set_cmap(cmap, &fb_display[con].var, - kspc, fbhw->setcolreg)); + kspc, fbhw->setcolreg, info)); else fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); return(0); @@ -930,31 +954,32 @@ static int Cyber_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con) * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag */ -static int Cyber_fb_pan_display(struct fb_var_screeninfo *var, int con) +static int cyberfb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) { return(-EINVAL); } /* - * Cybervision Frame Buffer Specific ioctls + * Cybervision Frame Buffer Specific ioctls */ -static int Cyber_fb_ioctl(struct inode *inode, struct file *file, - u_int cmd, u_long arg, int con) +static int cyberfb_ioctl(struct inode *inode, struct file *file, + u_int cmd, u_long arg, int con, struct fb_info *info) { return(-EINVAL); } -static struct fb_ops Cyber_fb_ops = { - Cyber_fb_open, Cyber_fb_release, Cyber_fb_get_fix, Cyber_fb_get_var, - Cyber_fb_set_var, Cyber_fb_get_cmap, Cyber_fb_set_cmap, - Cyber_fb_pan_display, Cyber_fb_ioctl +static struct fb_ops cyberfb_ops = { + cyberfb_open, cyberfb_release, cyberfb_get_fix, cyberfb_get_var, + cyberfb_set_var, cyberfb_get_cmap, cyberfb_set_cmap, + cyberfb_pan_display, NULL, cyberfb_ioctl }; -__initfunc(void Cyber_video_setup(char *options, int *ints)) +__initfunc(void cyberfb_setup(char *options, int *ints)) { char *this_opt; @@ -969,14 +994,18 @@ __initfunc(void Cyber_video_setup(char *options, int *ints)) fb_invert_cmaps(); } else if (!strncmp(this_opt, "font:", 5)) strcpy(fb_info.fontname, this_opt+5); -#if 0 - else if (!strcmp (this_opt, "cyber8")) - Cyberfb_Cyber8 = 1; - else if (!strcmp (this_opt, "cyber16")) - Cyberfb_Cyber16 = 1; -#endif + else if (!strcmp (this_opt, "cyber8")){ + cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var; + } + else if (!strcmp (this_opt, "cyber16")){ + cyberfb_default = cyberfb_predefined[CYBER16_DEFMODE].var; + } else - Cyberfb_mode = get_video_mode(this_opt); + get_video_mode(this_opt); + + DPRINTK("default mode: xres=%d, yres=%d, bpp=%d\n",cyberfb_default.xres, + cyberfb_default.yres, + cyberfb_default.bits_per_pixel); } @@ -984,10 +1013,10 @@ __initfunc(void Cyber_video_setup(char *options, int *ints)) * Initialization */ -__initfunc(unsigned long Cyber_fb_init(unsigned long mem_start)) +__initfunc(unsigned long cyberfb_init(unsigned long mem_start)) { int err; - struct Cyber_fb_par par; + struct cyberfb_par par; unsigned long board_addr; const struct ConfigDev *cd; @@ -1005,33 +1034,30 @@ __initfunc(unsigned long Cyber_fb_init(unsigned long mem_start)) fbhw = &Cyber_switch; - strcpy(fb_info.modename, Cyber_fb_name); + strcpy(fb_info.modename, cyberfb_name); fb_info.changevar = NULL; fb_info.node = -1; - fb_info.fbops = &Cyber_fb_ops; - fb_info.fbvar_num = NUM_TOTAL_MODES; - fb_info.fbvar = cyber_fb_predefined; + fb_info.fbops = &cyberfb_ops; fb_info.disp = &disp; fb_info.switch_con = &Cyberfb_switch; fb_info.updatevar = &Cyberfb_updatevar; fb_info.blank = &Cyberfb_blank; - fb_info.setcmap = &Cyberfb_setcmap; err = register_framebuffer(&fb_info); if (err < 0) return mem_start; fbhw->init(); - fbhw->decode_var(&cyber_fb_predefined[Cyberfb_mode], &par); - fbhw->encode_var(&cyber_fb_predefined[0], &par); + fbhw->decode_var(&cyberfb_default, &par); + fbhw->encode_var(&cyberfb_default, &par); - do_fb_set_var(&cyber_fb_predefined[0], 1); - Cyber_fb_get_var(&fb_display[0].var, -1); - Cyber_fb_set_disp(-1); - do_install_cmap(0); + do_fb_set_var(&cyberfb_default, 1); + cyberfb_get_var(&fb_display[0].var, -1, &fb_info); + cyberfb_set_disp(-1, &fb_info); + do_install_cmap(0, &fb_info); - printk("%s frame buffer device, using %ldK of video memory\n", - fb_info.modename, CyberSize>>10); + printk("fb%d: %s frame buffer device, using %ldK of video memory\n", + GET_FB_IDX(fb_info.node), fb_info.modename, CyberSize>>10); /* TODO: This driver cannot be unloaded yet */ MOD_INC_USE_COUNT; @@ -1040,17 +1066,17 @@ __initfunc(unsigned long Cyber_fb_init(unsigned long mem_start)) } -static int Cyberfb_switch(int con) +static int Cyberfb_switch(int con, struct fb_info *info) { /* Do we have to save the colormap? */ if (fb_display[currcon].cmap.len) fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1, - fbhw->getcolreg); + fbhw->getcolreg, info); do_fb_set_var(&fb_display[con].var, 1); currcon = con; /* Install new colormap */ - do_install_cmap(con); + do_install_cmap(con, info); return(0); } @@ -1062,7 +1088,7 @@ static int Cyberfb_switch(int con) * Since it's called by a kernel driver, no range checking is done. */ -static int Cyberfb_updatevar(int con) +static int Cyberfb_updatevar(int con, struct fb_info *info) { return(0); } @@ -1072,42 +1098,92 @@ static int Cyberfb_updatevar(int con) * Blank the display. */ -static void Cyberfb_blank(int blank) +static void Cyberfb_blank(int blank, struct fb_info *info) { fbhw->blank(blank); } /* - * Set the colormap + * Get a Video Mode */ -static int Cyberfb_setcmap(struct fb_cmap *cmap, int con) +__initfunc(static int get_video_mode(const char *name)) { - return(Cyber_fb_set_cmap(cmap, 1, con)); + int i; + + for (i = 0; i < NUM_TOTAL_MODES; i++) { + if (!strcmp(name, cyberfb_predefined[i].name)) { + cyberfb_default = cyberfb_predefined[i].var; + return(i); + } + } + /* ++Andre: set cyberfb default mode */ + cyberfb_default = cyberfb_predefined[CYBER8_DEFMODE].var; + return(0); } /* - * Get a Video Mode + * Text console acceleration */ -static int get_video_mode(const char *name) +#ifdef CONFIG_FBCON_CFB8 +static void fbcon_cyber8_bmove(struct display *p, int sy, int sx, int dy, + int dx, int height, int width) { - int i; + sx *= 8; dx *= 8; width *= 8; + Cyber_BitBLT((u_short)sx, (u_short)(sy*p->fontheight), (u_short)dx, + (u_short)(dy*p->fontheight), (u_short)width, + (u_short)(height*p->fontheight), (u_short)S3_NEW); +} - for (i = 1; i < NUM_PREDEF_MODES; i++) - if (!strcmp(name, Cyber_fb_modenames[i])) - cyber_fb_predefined[0] = cyber_fb_predefined[i]; - return(i); - return(0); +static void fbcon_cyber8_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width) +{ + unsigned char bg; + + sx *= 8; width *= 8; + bg = attr_bgcol_ec(p,conp); + Cyber_RectFill((u_short)sx, + (u_short)(sy*p->fontheight), + (u_short)width, + (u_short)(height*p->fontheight), + (u_short)S3_NEW, + (u_short)bg); +} + +static void fbcon_cyber8_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx) +{ + Cyber_WaitBlit(); + fbcon_cfb8_putc(conp, p, c, yy, xx); +} + +static void fbcon_cyber8_putcs(struct vc_data *conp, struct display *p, + const char *s, int count, int yy, int xx) +{ + Cyber_WaitBlit(); + fbcon_cfb8_putcs(conp, p, s, count, yy, xx); } +static void fbcon_cyber8_revc(struct display *p, int xx, int yy) +{ + Cyber_WaitBlit(); + fbcon_cfb8_revc(p, xx, yy); +} + +static struct display_switch fbcon_cyber8 = { + fbcon_cfb8_setup, fbcon_cyber8_bmove, fbcon_cyber8_clear, fbcon_cyber8_putc, + fbcon_cyber8_putcs, fbcon_cyber8_revc +}; +#endif + #ifdef MODULE int init_module(void) { - return(Cyber_fb_init(NULL)); + return(cyberfb_init(NULL)); } void cleanup_module(void) @@ -1118,12 +1194,3 @@ void cleanup_module(void) /* TODO: clean up ... */ } #endif /* MODULE */ - - -/* - * Visible symbols for modules - */ - -EXPORT_SYMBOL(Cyber_BitBLT); -EXPORT_SYMBOL(Cyber_RectFill); -EXPORT_SYMBOL(Cyber_WaitBlit); diff --git a/drivers/video/dn_fb.c b/drivers/video/dnfb.c index 8c5aeb099..db0a6172f 100644 --- a/drivers/video/dn_fb.c +++ b/drivers/video/dnfb.c @@ -5,6 +5,7 @@ #include <linux/tty.h> #include <linux/malloc.h> #include <linux/delay.h> +#include <linux/config.h> #include <linux/interrupt.h> #include <asm/setup.h> #include <asm/segment.h> @@ -14,6 +15,9 @@ #include <linux/fb.h> #include <linux/module.h> +#include "fbcon-mfb.h" + + /* apollo video HW definitions */ /* @@ -108,46 +112,44 @@ #endif -void dn_video_setup(char *options, int *ints); - /* frame buffer operations */ -static int dn_fb_open(int fbidx); -static int dn_fb_release(int fbidx); -static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con); -static int dn_fb_get_var(struct fb_var_screeninfo *var, int con); -static int dn_fb_set_var(struct fb_var_screeninfo *var, int isactive); -static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con); -static int dn_fb_set_cmap(struct fb_cmap *cmap,int kspc,int con); -static int dn_fb_pan_display(struct fb_var_screeninfo *var, int con); -static int dn_fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg, int con); - -static int dnfbcon_switch(int con); -static int dnfbcon_updatevar(int con); -static void dnfbcon_blank(int blank); - -static void dn_fb_set_disp(int con); +static int dnfb_open(struct fb_info *info); +static int dnfb_release(struct fb_info *info); +static int dnfb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info); +static int dnfb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int dnfb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int dnfb_get_cmap(struct fb_cmap *cmap,int kspc,int con, + struct fb_info *info); +static int dnfb_set_cmap(struct fb_cmap *cmap,int kspc,int con, + struct fb_info *info); +static int dnfb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int dnfb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, int con, + struct fb_info *info); + +static int dnfbcon_switch(int con, struct fb_info *info); +static int dnfbcon_updatevar(int con, struct fb_info *info); +static void dnfbcon_blank(int blank, struct fb_info *info); + +static void dnfb_set_disp(int con, struct fb_info *info); static struct display disp[MAX_NR_CONSOLES]; static struct fb_info fb_info; -static struct fb_ops dn_fb_ops = { - dn_fb_open,dn_fb_release, dn_fb_get_fix, dn_fb_get_var, dn_fb_set_var, - dn_fb_get_cmap, dn_fb_set_cmap, dn_fb_pan_display, dn_fb_ioctl +static struct fb_ops dnfb_ops = { + dnfb_open,dnfb_release, dnfb_get_fix, dnfb_get_var, dnfb_set_var, + dnfb_get_cmap, dnfb_set_cmap, dnfb_pan_display, NULL, dnfb_ioctl }; static int currcon=0; -#define NUM_TOTAL_MODES 1 -struct fb_var_screeninfo dn_fb_predefined[] = { - - { 0, }, +static char dnfb_name[]="Apollo"; -}; - -static char dn_fb_name[]="Apollo "; - -static int dn_fb_open(int fbidx) +static int dnfb_open(struct fb_info *info) { /* * Nothing, only a usage count for the moment @@ -157,14 +159,15 @@ static int dn_fb_open(int fbidx) return(0); } -static int dn_fb_release(int fbidx) +static int dnfb_release(struct fb_info *info) { MOD_DEC_USE_COUNT; return(0); } -static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con) { - +static int dnfb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) +{ memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id,"Apollo Mono"); fix->smem_start=(char*)(FRAME_BUFFER_START+IO_BASE); @@ -181,8 +184,9 @@ static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con) { } -static int dn_fb_get_var(struct fb_var_screeninfo *var, int con) { - +static int dnfb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ var->xres=1280; var->yres=1024; var->xres_virtual=2048; @@ -208,9 +212,9 @@ static int dn_fb_get_var(struct fb_var_screeninfo *var, int con) { } -static int dn_fb_set_var(struct fb_var_screeninfo *var, int isactive) { - - printk("fb_set_var\n"); +static int dnfb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ if(var->xres!=1280) return -EINVAL; if(var->yres!=1024) @@ -252,48 +256,48 @@ static int dn_fb_set_var(struct fb_var_screeninfo *var, int isactive) { } -static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con) { - +static int dnfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ printk("get cmap not supported\n"); return -EINVAL; } -static int dn_fb_set_cmap(struct fb_cmap *cmap,int kspc,int con) { - +static int dnfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ printk("set cmap not supported\n"); return -EINVAL; } -static int dn_fb_pan_display(struct fb_var_screeninfo *var, int con) { - +static int dnfb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ printk("panning not supported\n"); return -EINVAL; } -static int dn_fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg, int con) { - - printk("no IOCTLs as of yet.\n"); - +static int dnfb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, int con, + struct fb_info *info) +{ return -EINVAL; - } -static void dn_fb_set_disp(int con) { - +static void dnfb_set_disp(int con, struct fb_info *info) +{ struct fb_fix_screeninfo fix; - dn_fb_get_fix(&fix,con); + dnfb_get_fix(&fix, con, info); if(con==-1) con=0; disp[con].screen_base = (u_char *)fix.smem_start; -printk("screenbase: %p\n",fix.smem_start); disp[con].visual = fix.visual; disp[con].type = fix.type; disp[con].type_aux = fix.type_aux; @@ -302,27 +306,27 @@ printk("screenbase: %p\n",fix.smem_start); disp[con].can_soft_blank = 1; disp[con].inverse = 0; disp[con].line_length = fix.line_length; +#ifdef CONFIG_FBCON_MFB + disp[con].dispsw = &fbcon_mfb; +#else + disp[con].dispsw = NULL; +#endif } -unsigned long dn_fb_init(unsigned long mem_start) { - +unsigned long dnfb_init(unsigned long mem_start) +{ int err; -printk("dn_fb_init\n"); - fb_info.changevar=NULL; - strcpy(&fb_info.modename[0],dn_fb_name); + strcpy(&fb_info.modename[0],dnfb_name); fb_info.fontname[0]=0; fb_info.disp=disp; fb_info.switch_con=&dnfbcon_switch; fb_info.updatevar=&dnfbcon_updatevar; fb_info.blank=&dnfbcon_blank; fb_info.node = -1; - fb_info.fbops = &dn_fb_ops; - fb_info.fbvar = dn_fb_predefined; - fb_info.fbvar_num = NUM_TOTAL_MODES; + fb_info.fbops = &dnfb_ops; -printk("dn_fb_init: register\n"); err=register_framebuffer(&fb_info); if(err < 0) { panic("unable to register apollo frame buffer\n"); @@ -337,35 +341,34 @@ printk("dn_fb_init: register\n"); outb(S_DATA_PLN, AP_CONTROL_2); outw(SWAP(0x3),AP_ROP_1); - printk("apollo frame buffer alive and kicking !\n"); + printk("fb%d: apollo frame buffer alive and kicking !\n", + GET_FB_IDX(fb_info.node)); - dn_fb_get_var(&disp[0].var,0); + dnfb_get_var(&disp[0].var, 0, &fb_info); - dn_fb_set_disp(-1); + dnfb_set_disp(-1, &fb_info); return mem_start; } -static int dnfbcon_switch(int con) { - +static int dnfbcon_switch(int con, struct fb_info *info) +{ currcon=con; return 0; } -static int dnfbcon_updatevar(int con) { - +static int dnfbcon_updatevar(int con, struct fb_info *info) +{ return 0; - } -static void dnfbcon_blank(int blank) { - - printk("dnfbcon_blank: %d\n",blank); +static void dnfbcon_blank(int blank, struct fb_info *info) +{ if(blank) { outb(0, AP_CONTROL_3A); outb((AD_BLT | DST_EQ_SRC | NORM_CREG1) & ~ENAB_DISP, @@ -375,14 +378,4 @@ static void dnfbcon_blank(int blank) { outb(1, AP_CONTROL_3A); outb((AD_BLT | DST_EQ_SRC | NORM_CREG1), AP_CONTROL_1); } - - return ; - } - -void dn_video_setup(char *options, int *ints) { - - return; - -} - diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c index 9f3c586c7..bbf06d89b 100644 --- a/drivers/video/fbcmap.c +++ b/drivers/video/fbcmap.c @@ -35,45 +35,45 @@ static void memcpy_fs(int fsfromto, void *to, void *from, int len) #define CNVT_FROMHW(val,width) (((width) ? ((((val)<<16)-(val)) / \ ((1<<(width))-1)) : 0)) -static u_short red2[] = { +static u16 red2[] = { 0x0000, 0xaaaa }; -static u_short green2[] = { +static u16 green2[] = { 0x0000, 0xaaaa }; -static u_short blue2[] = { +static u16 blue2[] = { 0x0000, 0xaaaa -}; - -static u_short red4[] = { +}; + +static u16 red4[] = { 0x0000, 0xaaaa, 0x5555, 0xffff }; -static u_short green4[] = { +static u16 green4[] = { 0x0000, 0xaaaa, 0x5555, 0xffff }; -static u_short blue4[] = { +static u16 blue4[] = { 0x0000, 0xaaaa, 0x5555, 0xffff }; - -static u_short red8[] = { + +static u16 red8[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa }; -static u_short green8[] = { +static u16 green8[] = { 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0xaaaa, 0xaaaa }; -static u_short blue8[] = { +static u16 blue8[] = { 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa }; - -static u_short red16[] = { + +static u16 red16[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa, 0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff }; -static u_short green16[] = { +static u16 green16[] = { 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x5555, 0x5555, 0xffff, 0xffff, 0x5555, 0x5555, 0xffff, 0xffff }; -static u_short blue16[] = { +static u16 blue16[] = { 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff }; @@ -83,10 +83,10 @@ static struct fb_cmap default_2_colors = { }; static struct fb_cmap default_8_colors = { 0, 8, red8, green8, blue8, NULL -}; +}; static struct fb_cmap default_4_colors = { 0, 4, red4, green4, blue4, NULL -}; +}; static struct fb_cmap default_16_colors = { 0, 16, red16, green16, blue16, NULL }; @@ -98,32 +98,32 @@ static struct fb_cmap default_16_colors = { int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp) { - int size = len*sizeof(u_short); - + int size = len*sizeof(u16); + if (cmap->len != len) { - if (cmap->red) + if (cmap->red) kfree(cmap->red); if (cmap->green) kfree(cmap->green); if (cmap->blue) kfree(cmap->blue); if (cmap->transp) - kfree(cmap->transp); - cmap->red = cmap->green = cmap->blue = cmap->transp = NULL; - cmap->len = 0; - if (!len) - return 0; + kfree(cmap->transp); + cmap->red = cmap->green = cmap->blue = cmap->transp = NULL; + cmap->len = 0; + if (!len) + return 0; if (!(cmap->red = kmalloc(size, GFP_ATOMIC))) return -1; - if (!(cmap->green = kmalloc(size, GFP_ATOMIC))) + if (!(cmap->green = kmalloc(size, GFP_ATOMIC))) return -1; if (!(cmap->blue = kmalloc(size, GFP_ATOMIC))) - return -1; - if (transp) { + return -1; + if (transp) { if (!(cmap->transp = kmalloc(size, GFP_ATOMIC))) - return -1; - } else - cmap->transp = NULL; + return -1; + } else + cmap->transp = NULL; } cmap->start = 0; cmap->len = len; @@ -150,12 +150,12 @@ void fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto) size = from->len-fromoff; if (size < 0) return; - size *= sizeof(u_short); + size *= sizeof(u16); memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size); memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size); memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size); if (from->transp && to->transp) - memcpy_fs(fsfromto, to->transp+tooff, from->transp+fromoff, size); + memcpy_fs(fsfromto, to->transp+tooff, from->transp+fromoff, size); } @@ -164,10 +164,11 @@ void fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto) */ int fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, int kspc, - int (*getcolreg)(u_int, u_int *, u_int *, u_int *, u_int *)) + int (*getcolreg)(u_int, u_int *, u_int *, u_int *, u_int *, + struct fb_info *), struct fb_info *info) { int i, start; - u_short *red, *green, *blue, *transp; + u16 *red, *green, *blue, *transp; u_int hred, hgreen, hblue, htransp; red = cmap->red; @@ -178,7 +179,7 @@ int fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, int kspc, if (start < 0) return -EINVAL; for (i = 0; i < cmap->len; i++) { - if (getcolreg(start++, &hred, &hgreen, &hblue, &htransp)) + if (getcolreg(start++, &hred, &hgreen, &hblue, &htransp, info)) return 0; hred = CNVT_FROMHW(hred, var->red.length); hgreen = CNVT_FROMHW(hgreen, var->green.length); @@ -212,10 +213,11 @@ int fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, int kspc, */ int fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, int kspc, - int (*setcolreg)(u_int, u_int, u_int, u_int, u_int)) + int (*setcolreg)(u_int, u_int, u_int, u_int, u_int, + struct fb_info *), struct fb_info *info) { int i, start; - u_short *red, *green, *blue, *transp; + u16 *red, *green, *blue, *transp; u_int hred, hgreen, hblue, htransp; red = cmap->red; @@ -250,7 +252,7 @@ int fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, int kspc, blue++; if (transp) transp++; - if (setcolreg(start++, hred, hgreen, hblue, htransp)) + if (setcolreg(start++, hred, hgreen, hblue, htransp, info)) return 0; } return 0; @@ -261,22 +263,15 @@ int fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var, int kspc, * Get the default colormap for a specific screen depth */ -struct fb_cmap *fb_default_cmap(int bpp) +struct fb_cmap *fb_default_cmap(int len) { - switch (bpp) { - case 1: - return &default_2_colors; - break; - case 2: - return &default_4_colors; - break; - case 3: - return &default_8_colors; - break; - default: - return &default_16_colors; - break; - } + if (len <= 2) + return &default_2_colors; + if (len <= 4) + return &default_4_colors; + if (len <= 8) + return &default_8_colors; + return &default_16_colors; } diff --git a/drivers/video/fbcon-afb.c b/drivers/video/fbcon-afb.c index a56323041..66132809a 100644 --- a/drivers/video/fbcon-afb.c +++ b/drivers/video/fbcon-afb.c @@ -13,132 +13,242 @@ #include <linux/tty.h> #include <linux/console.h> #include <linux/string.h> +#include <linux/config.h> #include <linux/fb.h> #include "fbcon.h" +#include "fbcon-afb.h" /* - * Prototypes - */ - -static int open_afb(struct display *p); -static void release_afb(void); -static void bmove_afb(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -static void clear_afb(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width); -static void putc_afb(struct vc_data *conp, struct display *p, int c, int yy, - int xx); -static void putcs_afb(struct vc_data *conp, struct display *p, const char *s, - int count, int yy, int xx); -static void rev_char_afb(struct display *p, int xx, int yy); - - - /* - * `switch' for the low level operations + * Bitplanes ŕ la Amiga */ -static struct display_switch dispsw_afb = { - open_afb, release_afb, bmove_afb, clear_afb, putc_afb, putcs_afb, - rev_char_afb +static u8 expand_table[1024] = { + /* bg = fg = 0 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* bg = 0, fg = 1 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, + 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, + /* bg = 1, fg = 0 */ + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + 0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8, + 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, + 0xdf, 0xde, 0xdd, 0xdc, 0xdb, 0xda, 0xd9, 0xd8, + 0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0, + 0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8, + 0xc7, 0xc6, 0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0, + 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, + 0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0, + 0xaf, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa8, + 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0, + 0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, + 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, + 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, + 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, + 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, + 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, + 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, + 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x60, + 0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, + 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, + 0x4f, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, + 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, + 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, + 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, + 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, + 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, + 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, + 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, + 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + /* bg = fg = 1 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - /* - * Bitplanes ŕ la Amiga - */ - -static int open_afb(struct display *p) +void fbcon_afb_setup(struct display *p) { - if (p->type != FB_TYPE_PLANES) - return -EINVAL; - if (p->line_length) p->next_line = p->line_length; else p->next_line = p->var.xres_virtual>>3; p->next_plane = p->var.yres_virtual*p->next_line; - MOD_INC_USE_COUNT; - return 0; } -static void release_afb(void) +void fbcon_afb_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) { - MOD_DEC_USE_COUNT; -} - -static void bmove_afb(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - u_char *src, *dest, *src0, *dest0; - u_int i, rows; + u8 *src, *dest, *src0, *dest0; + u_short i, j; if (sx == 0 && dx == 0 && width == p->next_line) { src = p->screen_base+sy*p->fontheight*width; dest = p->screen_base+dy*p->fontheight*width; - for (i = p->var.bits_per_pixel; i--;) { + i = p->var.bits_per_pixel; + do { mymemmove(dest, src, height*p->fontheight*width); src += p->next_plane; dest += p->next_plane; - } + } while (--i); } else if (dy <= sy) { src0 = p->screen_base+sy*p->fontheight*p->next_line+sx; dest0 = p->screen_base+dy*p->fontheight*p->next_line+dx; - for (i = p->var.bits_per_pixel; i--;) { + i = p->var.bits_per_pixel; + do { src = src0; dest = dest0; - for (rows = height*p->fontheight; rows--;) { + j = height*p->fontheight; + do { mymemmove(dest, src, width); src += p->next_line; dest += p->next_line; - } + } while (--j); src0 += p->next_plane; dest0 += p->next_plane; - } + } while (--i); } else { src0 = p->screen_base+(sy+height)*p->fontheight*p->next_line+sx; dest0 = p->screen_base+(dy+height)*p->fontheight*p->next_line+dx; - for (i = p->var.bits_per_pixel; i--;) { + i = p->var.bits_per_pixel; + do { src = src0; dest = dest0; - for (rows = height*p->fontheight; rows--;) { + j = height*p->fontheight; + do { src -= p->next_line; dest -= p->next_line; mymemmove(dest, src, width); - } + } while (--j); src0 += p->next_plane; dest0 += p->next_plane; - } + } while (--i); } } -static void clear_afb(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width) +void fbcon_afb_clear(struct vc_data *conp, struct display *p, int sy, int sx, + int height, int width) { - u_char *dest, *dest0; - u_int i, rows; + u8 *dest, *dest0; + u_short i, j; int bg; dest0 = p->screen_base+sy*p->fontheight*p->next_line+sx; bg = attr_bgcol_ec(p,conp); - for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) { + i = p->var.bits_per_pixel; + do { dest = dest0; - for (rows = height*p->fontheight; rows--; dest += p->next_line) + j = height*p->fontheight; + do { if (bg & 1) mymemset(dest, width); else mymemclear(dest, width); + dest += p->next_line; + } while (--j); bg >>= 1; - } + dest0 += p->next_plane; + } while (--i); } -static void putc_afb(struct vc_data *conp, struct display *p, int c, int yy, - int xx) +void fbcon_afb_putc(struct vc_data *conp, struct display *p, int c, int yy, + int xx) { - u_char *dest, *dest0, *cdat, *cdat0; - u_int rows, i; - u_char d; + u8 *dest, *dest0, *cdat, *cdat0, *expand; + u_short i, j; int fg, bg; c &= 0xff; @@ -148,25 +258,24 @@ static void putc_afb(struct vc_data *conp, struct display *p, int c, int yy, fg = attr_fgcol(p,conp); bg = attr_bgcol(p,conp); - for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) { + i = p->var.bits_per_pixel; + do { dest = dest0; cdat = cdat0; - for (rows = p->fontheight; rows--; dest += p->next_line) { - d = *cdat++; - if (bg & 1) - if (fg & 1) - *dest = 0xff; - else - *dest = ~d; - else - if (fg & 1) - *dest = d; - else - *dest = 0x00; - } + expand = expand_table; + if (bg & 1) + expand += 512; + if (fg & 1) + expand += 256; + j = p->fontheight; + do { + *dest = expand[*cdat++]; + dest += p->next_line; + } while (--j); bg >>= 1; fg >>= 1; - } + dest0 += p->next_plane; + } while (--i); } /* @@ -174,14 +283,13 @@ static void putc_afb(struct vc_data *conp, struct display *p, int c, int yy, * (cfr. fbcon_putcs_ilbm()) */ -static void putcs_afb(struct vc_data *conp, struct display *p, const char *s, - int count, int yy, int xx) +void fbcon_afb_putcs(struct vc_data *conp, struct display *p, const char *s, + int count, int yy, int xx) { - u_char *dest, *dest0, *dest1; - u_char *cdat1, *cdat2, *cdat3, *cdat4, *cdat10, *cdat20, *cdat30, *cdat40; - u_int rows, i; - u_char c1, c2, c3, c4; - u_long d; + u8 *dest, *dest0, *dest1, *expand; + u8 *cdat1, *cdat2, *cdat3, *cdat4, *cdat10, *cdat20, *cdat30, *cdat40; + u_short i, j; + u8 c1, c2, c3, c4; int fg0, bg0, fg, bg; dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx; @@ -198,26 +306,25 @@ static void putcs_afb(struct vc_data *conp, struct display *p, const char *s, fg = fg0; bg = bg0; - for (i = p->var.bits_per_pixel; i--; dest1 += p->next_plane) { + i = p->var.bits_per_pixel; + do { dest = dest1; cdat1 = cdat10; - for (rows = p->fontheight; rows--; dest += p->next_line) { - d = *cdat1++; - if (bg & 1) - if (fg & 1) - *dest = 0xff; - else - *dest = ~d; - else - if (fg & 1) - *dest = d; - else - *dest = 0x00; - } + expand = expand_table; + if (bg & 1) + expand += 512; + if (fg & 1) + expand += 256; + j = p->fontheight; + do { + *dest = expand[*cdat1++]; + dest += p->next_line; + } while (--j); bg >>= 1; fg >>= 1; - } - } else { /* Fast version */ + dest1 += p->next_plane; + } while (--i); + } else { /* Fast version */ c1 = s[0]; c2 = s[1]; c3 = s[2]; @@ -231,28 +338,39 @@ static void putcs_afb(struct vc_data *conp, struct display *p, const char *s, fg = fg0; bg = bg0; - for (i = p->var.bits_per_pixel; i--; dest1 += p->next_plane) { + i = p->var.bits_per_pixel; + do { dest = dest1; cdat1 = cdat10; cdat2 = cdat20; cdat3 = cdat30; cdat4 = cdat40; - for (rows = p->fontheight; rows--; dest += p->next_line) { - d = *cdat1++<<24 | *cdat2++<<16 | *cdat3++<<8 | *cdat4++; - if (bg & 1) - if (fg & 1) - *(u_long *)dest = 0xffffffff; - else - *(u_long *)dest = ~d; - else - if (fg & 1) - *(u_long *)dest = d; - else - *(u_long *)dest = 0x00000000; - } + expand = expand_table; + if (bg & 1) + expand += 512; + if (fg & 1) + expand += 256; + j = p->fontheight; + do { +#if defined(__BIG_ENDIAN) + *(u32 *)dest = expand[*cdat1++]<<24 | + expand[*cdat2++]<<16 | + expand[*cdat3++]<<8 | + expand[*cdat4++]; +#elif defined(__LITTLE_ENDIAN) + *(u32 *)dest = expand[*cdat1++] | + expand[*cdat2++]<<8 | + expand[*cdat3++]<<16 | + expand[*cdat4++]<<24; +#else +#error FIXME: No endianness?? +#endif + dest += p->next_line; + } while (--j); bg >>= 1; fg >>= 1; - } + dest1 += p->next_plane; + } while (--i); s += 4; dest0 += 4; xx += 4; @@ -260,10 +378,10 @@ static void putcs_afb(struct vc_data *conp, struct display *p, const char *s, } } -static void rev_char_afb(struct display *p, int xx, int yy) +void fbcon_afb_revc(struct display *p, int xx, int yy) { - u_char *dest, *dest0; - u_int rows, i; + u8 *dest, *dest0; + u_short i, j; int mask; dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx; @@ -275,29 +393,40 @@ static void rev_char_afb(struct display *p, int xx, int yy) * inverting. */ - for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) { + i = p->var.bits_per_pixel; + do { if (mask & 1) { dest = dest0; - for (rows = p->fontheight; rows--; dest += p->next_line) + j = p->fontheight; + do { *dest = ~*dest; + dest += p->next_line; + } while (--j); } mask >>= 1; - } + dest0 += p->next_plane; + } while (--i); } -#ifdef MODULE -int init_module(void) -#else -int fbcon_init_afb(void) -#endif -{ - return(fbcon_register_driver(&dispsw_afb, 0)); -} + /* + * `switch' for the low level operations + */ -#ifdef MODULE -void cleanup_module(void) -{ - fbcon_unregister_driver(&dispsw_afb); -} -#endif /* MODULE */ +struct display_switch fbcon_afb = { + fbcon_afb_setup, fbcon_afb_bmove, fbcon_afb_clear, fbcon_afb_putc, + fbcon_afb_putcs, fbcon_afb_revc +}; + + + /* + * Visible symbols for modules + */ + +EXPORT_SYMBOL(fbcon_afb); +EXPORT_SYMBOL(fbcon_afb_setup); +EXPORT_SYMBOL(fbcon_afb_bmove); +EXPORT_SYMBOL(fbcon_afb_clear); +EXPORT_SYMBOL(fbcon_afb_putc); +EXPORT_SYMBOL(fbcon_afb_putcs); +EXPORT_SYMBOL(fbcon_afb_revc); diff --git a/drivers/video/fbcon-afb.h b/drivers/video/fbcon-afb.h new file mode 100644 index 000000000..537b3bdd7 --- /dev/null +++ b/drivers/video/fbcon-afb.h @@ -0,0 +1,15 @@ + /* + * Amiga bitplanes (afb) + */ + +extern struct display_switch fbcon_afb; +extern void fbcon_afb_setup(struct display *p); +extern void fbcon_afb_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width); +extern void fbcon_afb_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width); +extern void fbcon_afb_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx); +extern void fbcon_afb_putcs(struct vc_data *conp, struct display *p, + const char *s, int count, int yy, int xx); +extern void fbcon_afb_revc(struct display *p, int xx, int yy); diff --git a/drivers/video/fbcon-cfb16.c b/drivers/video/fbcon-cfb16.c index 8bd58ce8a..b27683c95 100644 --- a/drivers/video/fbcon-cfb16.c +++ b/drivers/video/fbcon-cfb16.c @@ -1,6 +1,6 @@ /* * linux/drivers/video/cfb16.c -- Low level frame buffer operations for 16 bpp - * packed pixels + * truecolor packed pixels * * Created 5 Apr 1997 by Geert Uytterhoeven * @@ -13,69 +13,40 @@ #include <linux/tty.h> #include <linux/console.h> #include <linux/string.h> +#include <linux/config.h> #include <linux/fb.h> #include "fbcon.h" - - - /* - * Prototypes - */ - -static int open_cfb16(struct display *p); -static void release_cfb16(void); -static void bmove_cfb16(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -static void clear_cfb16(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width); -static void putc_cfb16(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -static void putcs_cfb16(struct vc_data *conp, struct display *p, - const char *s, int count, int yy, int xx); -static void rev_char_cfb16(struct display *p, int xx, int yy); - - - /* - * `switch' for the low level operations - */ - -static struct display_switch dispsw_cfb16 = { - open_cfb16, release_cfb16, bmove_cfb16, clear_cfb16, putc_cfb16, - putcs_cfb16, rev_char_cfb16 -}; +#include "fbcon-cfb16.h" /* * 16 bpp packed pixels */ -u_short packed16_cmap[16]; +u16 fbcon_cfb16_cmap[16]; -static u_long tab_cfb16[] = { - 0x00000000,0x0000ffff,0xffff0000,0xffffffff +static u32 tab_cfb16[] = { +#if defined(__BIG_ENDIAN) + 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff +#elif defined(__LITTLE_ENDIAN) + 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff +#else +#error FIXME: No endianness?? +#endif }; -static int open_cfb16(struct display *p) +void fbcon_cfb16_setup(struct display *p) { - if (p->type != FB_TYPE_PACKED_PIXELS || p->var.bits_per_pixel != 16) - return -EINVAL; - p->next_line = p->var.xres_virtual<<1; p->next_plane = 0; - MOD_INC_USE_COUNT; - return 0; -} - -static void release_cfb16(void) -{ - MOD_DEC_USE_COUNT; } -static void bmove_cfb16(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) +void fbcon_cfb16_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) { int bytes = p->next_line, linesize = bytes * p->fontheight, rows; - u_char *src,*dst; + u8 *src, *dst; if (sx == 0 && dx == 0 && width * 16 == bytes) mymemmove(p->screen_base + dy * linesize, @@ -100,82 +71,78 @@ static void bmove_cfb16(struct display *p, int sy, int sx, int dy, int dx, } } -static void clear_cfb16(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width) +void fbcon_cfb16_clear(struct vc_data *conp, struct display *p, int sy, int sx, + int height, int width) { - u_char *dest0,*dest; - int bytes=p->next_line,lines=height * p->fontheight, rows, i; - u_long bgx; + u8 *dest0, *dest; + int bytes = p->next_line, lines = height * p->fontheight, rows, i; + u32 bgx; dest = p->screen_base + sy * p->fontheight * bytes + sx * 16; - bgx = attr_bgcol_ec(p,conp); - bgx = packed16_cmap[bgx]; + bgx = fbcon_cfb16_cmap[attr_bgcol_ec(p, conp)]; bgx |= (bgx << 16); if (sx == 0 && width * 16 == bytes) for (i = 0 ; i < lines * width ; i++) { - ((u_long *)dest)[0]=bgx; - ((u_long *)dest)[1]=bgx; - ((u_long *)dest)[2]=bgx; - ((u_long *)dest)[3]=bgx; - dest+=16; + ((u32 *)dest)[0] = bgx; + ((u32 *)dest)[1] = bgx; + ((u32 *)dest)[2] = bgx; + ((u32 *)dest)[3] = bgx; + dest += 16; } else { - dest0=dest; + dest0 = dest; for (rows = lines; rows-- ; dest0 += bytes) { - dest=dest0; + dest = dest0; for (i = 0 ; i < width ; i++) { - ((u_long *)dest)[0]=bgx; - ((u_long *)dest)[1]=bgx; - ((u_long *)dest)[2]=bgx; - ((u_long *)dest)[3]=bgx; - dest+=16; + ((u32 *)dest)[0] = bgx; + ((u32 *)dest)[1] = bgx; + ((u32 *)dest)[2] = bgx; + ((u32 *)dest)[3] = bgx; + dest += 16; } } } } -static void putc_cfb16(struct vc_data *conp, struct display *p, int c, int yy, - int xx) +void fbcon_cfb16_putc(struct vc_data *conp, struct display *p, int c, int yy, + int xx) { - u_char *dest,*cdat; - int bytes=p->next_line,rows; - ulong eorx,fgx,bgx; + u8 *dest, *cdat; + int bytes = p->next_line, rows; + u32 eorx, fgx, bgx; c &= 0xff; dest = p->screen_base + yy * p->fontheight * bytes + xx * 16; cdat = p->fontdata + c * p->fontheight; - fgx = attr_fgcol(p,conp); - fgx = packed16_cmap[fgx]; - bgx = attr_bgcol(p,conp); - bgx = packed16_cmap[bgx]; + fgx = fbcon_cfb16_cmap[attr_fgcol(p, conp)]; + bgx = fbcon_cfb16_cmap[attr_bgcol(p, conp)]; fgx |= (fgx << 16); bgx |= (bgx << 16); eorx = fgx ^ bgx; for (rows = p->fontheight ; rows-- ; dest += bytes) { - ((u_long *)dest)[0]= (tab_cfb16[*cdat >> 6] & eorx) ^ bgx; - ((u_long *)dest)[1]= (tab_cfb16[*cdat >> 4 & 0x3] & eorx) ^ bgx; - ((u_long *)dest)[2]= (tab_cfb16[*cdat >> 2 & 0x3] & eorx) ^ bgx; - ((u_long *)dest)[3]= (tab_cfb16[*cdat++ & 0x3] & eorx) ^ bgx; + u8 bits = *cdat++; + ((u32 *)dest)[0] = (tab_cfb16[bits >> 6] & eorx) ^ bgx; + ((u32 *)dest)[1] = (tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx; + ((u32 *)dest)[2] = (tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx; + ((u32 *)dest)[3] = (tab_cfb16[bits & 3] & eorx) ^ bgx; } } -static void putcs_cfb16(struct vc_data *conp, struct display *p, const char *s, - int count, int yy, int xx) +void fbcon_cfb16_putcs(struct vc_data *conp, struct display *p, const char *s, + int count, int yy, int xx) { - u_char *cdat, c, *dest, *dest0; - int rows,bytes=p->next_line; - u_long eorx, fgx, bgx; + u8 *cdat, c, *dest, *dest0; + int rows, bytes = p->next_line; + u32 eorx, fgx, bgx; dest0 = p->screen_base + yy * p->fontheight * bytes + xx * 16; - fgx = attr_fgcol(p,conp); - fgx = packed16_cmap[fgx]; - bgx = attr_bgcol(p,conp); - bgx = packed16_cmap[bgx]; + fgx = fbcon_cfb16_cmap[attr_fgcol(p, conp)]; + bgx = fbcon_cfb16_cmap[attr_bgcol(p, conp)]; fgx |= (fgx << 16); bgx |= (bgx << 16); eorx = fgx ^ bgx; @@ -184,49 +151,50 @@ static void putcs_cfb16(struct vc_data *conp, struct display *p, const char *s, cdat = p->fontdata + c * p->fontheight; for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) { - ((u_long *)dest)[0]= (tab_cfb16[*cdat >> 6] & eorx) ^ bgx; - ((u_long *)dest)[1]= (tab_cfb16[*cdat >> 4 & 0x3] & eorx) ^ bgx; - ((u_long *)dest)[2]= (tab_cfb16[*cdat >> 2 & 0x3] & eorx) ^ bgx; - ((u_long *)dest)[3]= (tab_cfb16[*cdat++ & 0x3] & eorx) ^ bgx; + u8 bits = *cdat++; + ((u32 *)dest)[0] = (tab_cfb16[bits >> 6] & eorx) ^ bgx; + ((u32 *)dest)[1] = (tab_cfb16[bits >> 4 & 3] & eorx) ^ bgx; + ((u32 *)dest)[2] = (tab_cfb16[bits >> 2 & 3] & eorx) ^ bgx; + ((u32 *)dest)[3] = (tab_cfb16[bits & 3] & eorx) ^ bgx; } - dest0+=16; + dest0 += 16; } } -static void rev_char_cfb16(struct display *p, int xx, int yy) +void fbcon_cfb16_revc(struct display *p, int xx, int yy) { - u_char *dest; - int bytes=p->next_line, rows; + u8 *dest; + int bytes = p->next_line, rows; dest = p->screen_base + yy * p->fontheight * bytes + xx * 16; for (rows = p->fontheight ; rows-- ; dest += bytes) { - ((u_long *)dest)[0] ^= 0xffffffff; - ((u_long *)dest)[1] ^= 0xffffffff; - ((u_long *)dest)[2] ^= 0xffffffff; - ((u_long *)dest)[3] ^= 0xffffffff; + ((u32 *)dest)[0] ^= 0xffffffff; + ((u32 *)dest)[1] ^= 0xffffffff; + ((u32 *)dest)[2] ^= 0xffffffff; + ((u32 *)dest)[3] ^= 0xffffffff; } } -#ifdef MODULE -int init_module(void) -#else -int fbcon_init_cfb16(void) -#endif -{ - return(fbcon_register_driver(&dispsw_cfb16, 0)); -} + /* + * `switch' for the low level operations + */ -#ifdef MODULE -void cleanup_module(void) -{ - fbcon_unregister_driver(&dispsw_cfb16); -} -#endif /* MODULE */ +struct display_switch fbcon_cfb16 = { + fbcon_cfb16_setup, fbcon_cfb16_bmove, fbcon_cfb16_clear, fbcon_cfb16_putc, + fbcon_cfb16_putcs, fbcon_cfb16_revc +}; /* * Visible symbols for modules */ -EXPORT_SYMBOL(packed16_cmap); +EXPORT_SYMBOL(fbcon_cfb16); +EXPORT_SYMBOL(fbcon_cfb16_setup); +EXPORT_SYMBOL(fbcon_cfb16_bmove); +EXPORT_SYMBOL(fbcon_cfb16_clear); +EXPORT_SYMBOL(fbcon_cfb16_putc); +EXPORT_SYMBOL(fbcon_cfb16_putcs); +EXPORT_SYMBOL(fbcon_cfb16_revc); +EXPORT_SYMBOL(fbcon_cfb16_cmap); diff --git a/drivers/video/fbcon-cfb16.h b/drivers/video/fbcon-cfb16.h new file mode 100644 index 000000000..905d6329a --- /dev/null +++ b/drivers/video/fbcon-cfb16.h @@ -0,0 +1,16 @@ + /* + * 16 bpp packed pixel (cfb16) + */ + +extern struct display_switch fbcon_cfb16; +extern u16 fbcon_cfb16_cmap[16]; +extern void fbcon_cfb16_setup(struct display *p); +extern void fbcon_cfb16_bmove(struct display *p, int sy, int sx, int dy, + int dx, int height, int width); +extern void fbcon_cfb16_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width); +extern void fbcon_cfb16_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx); +extern void fbcon_cfb16_putcs(struct vc_data *conp, struct display *p, + const char *s, int count, int yy, int xx); +extern void fbcon_cfb16_revc(struct display *p, int xx, int yy); diff --git a/drivers/video/fbcon-cfb2.c b/drivers/video/fbcon-cfb2.c new file mode 100644 index 000000000..617c85235 --- /dev/null +++ b/drivers/video/fbcon-cfb2.c @@ -0,0 +1,205 @@ +/* + * linux/drivers/video/cfb2.c -- Low level frame buffer operations for 2 bpp + * packed pixels + * + * Created 26 Dec 1997 by Michael Schmitz + * Based on cfb4.c + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/module.h> +#include <linux/tty.h> +#include <linux/console.h> +#include <linux/string.h> +#include <linux/config.h> +#include <linux/fb.h> + +#include "fbcon.h" +#include "fbcon-cfb2.h" + + + /* + * 2 bpp packed pixels + */ + + /* + * IFF the font is even pixel aligned (that is to say each + * character start is a byte start in the pixel pairs). That + * avoids us having to mask bytes and means we won't be here + * all week. On a MacII that matters _lots_ + */ + +static u_char nibbletab_cfb2[]={ + 0x00,0x03,0x0c,0x0f, + 0x30,0x33,0x3c,0x3f, + 0xc0,0xc3,0xcc,0xcf, + 0xf0,0xf3,0xfc,0xff +}; + + +void fbcon_cfb2_setup(struct display *p) +{ + p->next_line = p->var.xres_virtual>>2; + p->next_plane = 0; +} + +void fbcon_cfb2_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) +{ + int bytes = p->next_line, linesize = bytes * p->fontheight, rows; + u8 *src,*dst; + + if (sx == 0 && dx == 0 && width * 2 == bytes) { + mymemmove(p->screen_base + dy * linesize, + p->screen_base + sy * linesize, + height * linesize); + } + else { + if (dy < sy || (dy == sy && dx < sx)) { + src = p->screen_base + sy * linesize + sx * 2; + dst = p->screen_base + dy * linesize + dx * 2; + for (rows = height * p->fontheight ; rows-- ;) { + mymemmove(dst, src, width * 2); + src += bytes; + dst += bytes; + } + } + else { + src = p->screen_base + (sy+height) * linesize + sx * 2 + - bytes; + dst = p->screen_base + (dy+height) * linesize + dx * 2 + - bytes; + for (rows = height * p->fontheight ; rows-- ;) { + mymemmove(dst, src, width * 2); + src -= bytes; + dst -= bytes; + } + } + } +} + +void fbcon_cfb2_clear(struct vc_data *conp, struct display *p, int sy, int sx, + int height, int width) +{ + u8 *dest0,*dest; + int bytes=p->next_line,lines=height * p->fontheight, rows, i; + u32 bgx; + + dest = p->screen_base + sy * p->fontheight * bytes + sx * 2; + + bgx=attr_bgcol_ec(p,conp); + bgx |= (bgx << 2); /* expand the colour to 16 bits */ + bgx |= (bgx << 4); + bgx |= (bgx << 8); + + if (sx == 0 && width * 2 == bytes) { + for (i = 0 ; i < lines * width ; i++) { + ((u16 *)dest)[0]=bgx; + dest+=2; + } + } else { + dest0=dest; + for (rows = lines; rows-- ; dest0 += bytes) { + dest=dest0; + for (i = 0 ; i < width ; i++) { + /* memset ?? */ + ((u16 *)dest)[0]=bgx; + dest+=2; + } + } + } +} + +void fbcon_cfb2_putc(struct vc_data *conp, struct display *p, int c, int yy, + int xx) +{ + u8 *dest,*cdat; + int bytes=p->next_line,rows; + u32 eorx,fgx,bgx; + + c &= 0xff; + + dest = p->screen_base + yy * p->fontheight * bytes + xx * 2; + cdat = p->fontdata + c * p->fontheight; + + fgx=3;/*attr_fgcol(p,conp)&0x0F;*/ + bgx=attr_bgcol(p,conp)&0x0F; + fgx |= (fgx << 2); /* expand color to 8 bits */ + fgx |= (fgx << 4); + bgx |= (bgx << 2); + bgx |= (bgx << 4); + eorx = fgx ^ bgx; + + for (rows = p->fontheight ; rows-- ; dest += bytes) { + ((u8 *)dest)[0]= + (nibbletab_cfb2[*cdat >> 4] & eorx) ^ bgx; + ((u8 *)dest)[1]= + (nibbletab_cfb2[*cdat++ & 0xf] & eorx) ^ bgx; + } +} + +void fbcon_cfb2_putcs(struct vc_data *conp, struct display *p, const char *s, + int count, int yy, int xx) +{ + u8 *cdat, c, *dest, *dest0; + int rows,bytes=p->next_line; + u32 eorx, fgx, bgx; + + dest0 = p->screen_base + yy * p->fontheight * bytes + xx * 2; + fgx=3/*attr_fgcol(p,conp)*/; + bgx=attr_bgcol(p,conp); + fgx |= (fgx << 2); + fgx |= (fgx << 4); + bgx |= (bgx << 2); + bgx |= (bgx << 4); + eorx = fgx ^ bgx; + while (count--) { + c = *s++; + cdat = p->fontdata + c * p->fontheight; + + for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) { + ((u8 *)dest)[0]= + (nibbletab_cfb2[*cdat >> 4] & eorx) ^ bgx; + ((u8 *)dest)[1]= + (nibbletab_cfb2[*cdat++ & 0xf] & eorx) ^ bgx; + } + dest0+=2; + } +} + +void fbcon_cfb2_revc(struct display *p, int xx, int yy) +{ + u8 *dest; + int bytes=p->next_line, rows; + + dest = p->screen_base + yy * p->fontheight * bytes + xx * 2; + for (rows = p->fontheight ; rows-- ; dest += bytes) { + ((u16 *)dest)[0] ^= 0xffff; + } +} + + + /* + * `switch' for the low level operations + */ + +struct display_switch fbcon_cfb2 = { + fbcon_cfb2_setup, fbcon_cfb2_bmove, fbcon_cfb2_clear, fbcon_cfb2_putc, + fbcon_cfb2_putcs, fbcon_cfb2_revc +}; + + + /* + * Visible symbols for modules + */ + +EXPORT_SYMBOL(fbcon_cfb2); +EXPORT_SYMBOL(fbcon_cfb2_setup); +EXPORT_SYMBOL(fbcon_cfb2_bmove); +EXPORT_SYMBOL(fbcon_cfb2_clear); +EXPORT_SYMBOL(fbcon_cfb2_putc); +EXPORT_SYMBOL(fbcon_cfb2_putcs); +EXPORT_SYMBOL(fbcon_cfb2_revc); diff --git a/drivers/video/fbcon-cfb2.h b/drivers/video/fbcon-cfb2.h new file mode 100644 index 000000000..4fb3bb13a --- /dev/null +++ b/drivers/video/fbcon-cfb2.h @@ -0,0 +1,15 @@ + /* + * 2 bpp packed pixel (cfb2) + */ + +extern struct display_switch fbcon_cfb2; +extern void fbcon_cfb2_setup(struct display *p); +extern void fbcon_cfb2_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width); +extern void fbcon_cfb2_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width); +extern void fbcon_cfb2_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx); +extern void fbcon_cfb2_putcs(struct vc_data *conp, struct display *p, + const char *s, int count, int yy, int xx); +extern void fbcon_cfb2_revc(struct display *p, int xx, int yy); diff --git a/drivers/video/fbcon-cfb24.c b/drivers/video/fbcon-cfb24.c new file mode 100644 index 000000000..65a4ad556 --- /dev/null +++ b/drivers/video/fbcon-cfb24.c @@ -0,0 +1,221 @@ +/* + * linux/drivers/video/cfb24.c -- Low level frame buffer operations for 24 bpp + * truecolor packed pixels + * + * Created 7 Mar 1998 by Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/module.h> +#include <linux/tty.h> +#include <linux/console.h> +#include <linux/string.h> +#include <linux/config.h> +#include <linux/fb.h> + +#include "fbcon.h" +#include "fbcon-cfb24.h" + + +#warning Remove this warning after the test cycle was finalized + + + /* + * 24 bpp packed pixels + */ + +u32 fbcon_cfb24_cmap[16]; + +void fbcon_cfb24_setup(struct display *p) +{ + p->next_line = p->line_length ? p->line_length : p->var.xres_virtual*3; + p->next_plane = 0; +} + +void fbcon_cfb24_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) +{ + int bytes = p->next_line, linesize = bytes * p->fontheight, rows; + u8 *src, *dst; + + if (sx == 0 && dx == 0 && width * 24 == bytes) + mymemmove(p->screen_base + dy * linesize, + p->screen_base + sy * linesize, + height * linesize); + else if (dy < sy || (dy == sy && dx < sx)) { + src = p->screen_base + sy * linesize + sx * 24; + dst = p->screen_base + dy * linesize + dx * 24; + for (rows = height * p->fontheight ; rows-- ;) { + mymemmove(dst, src, width * 24); + src += bytes; + dst += bytes; + } + } else { + src = p->screen_base + (sy+height) * linesize + sx * 24 - bytes; + dst = p->screen_base + (dy+height) * linesize + dx * 24 - bytes; + for (rows = height * p->fontheight ; rows-- ;) { + mymemmove(dst, src, width * 24); + src -= bytes; + dst -= bytes; + } + } +} + +void fbcon_cfb24_clear(struct vc_data *conp, struct display *p, int sy, int sx, + int height, int width) +{ + u8 *dest0, *dest; + int bytes = p->next_line, lines = height * p->fontheight, rows, i; + u32 bgx; + + dest = p->screen_base + sy * p->fontheight * bytes + sx * 24; + + bgx = fbcon_cfb24_cmap[attr_bgcol_ec(p, conp)]; + + if (sx == 0 && width * 24 == bytes) + for (i = 0 ; i < lines * width ; i++) { + ((u32 *)dest)[0] = bgx; + ((u32 *)dest)[1] = bgx; + ((u32 *)dest)[2] = bgx; + ((u32 *)dest)[3] = bgx; + ((u32 *)dest)[4] = bgx; + ((u32 *)dest)[5] = bgx; + dest += 24; + } + else { + dest0 = dest; + for (rows = lines; rows-- ; dest0 += bytes) { + dest = dest0; + for (i = 0 ; i < width ; i++) { + ((u32 *)dest)[0] = bgx; + ((u32 *)dest)[1] = bgx; + ((u32 *)dest)[2] = bgx; + ((u32 *)dest)[3] = bgx; + ((u32 *)dest)[4] = bgx; + ((u32 *)dest)[5] = bgx; + dest += 24; + } + } + } +} + +static inline void store4pixels(u32 d1, u32 d2, u32 d3, u32 d4, u32 *dest) +{ +#if defined(__BIG_ENDIAN) + *dest++ = (d1<<8) | (d2>>16); + *dest++ = (d2<<16) | (d3>>8); + *dest++ = (d3<<24) | d4; +#elif defined(__LITTLE_ENDIAN) +#error Please add support for little endian byteorder +#else +#error FIXME: No endianness?? +#endif +} + +void fbcon_cfb24_putc(struct vc_data *conp, struct display *p, int c, int yy, + int xx) +{ + u8 *dest, *cdat; + int bytes = p->next_line, rows; + u32 eorx, fgx, bgx; + + c &= 0xff; + + dest = p->screen_base + yy * p->fontheight * bytes + xx * 24; + cdat = p->fontdata + c * p->fontheight; + + fgx = fbcon_cfb24_cmap[attr_fgcol(p, conp)]; + bgx = fbcon_cfb24_cmap[attr_bgcol(p, conp)]; + eorx = fgx ^ bgx; + + for (rows = p->fontheight ; rows-- ; dest += bytes) { + u8 bits = *cdat++; + u32 d1, d2, d3, d4; + d1 = (-(bits >> 7) & eorx) ^ bgx; + d2 = (-(bits >> 6 & 1) & eorx) ^ bgx; + d3 = (-(bits >> 5 & 1) & eorx) ^ bgx; + d4 = (-(bits >> 4 & 1) & eorx) ^ bgx; + store4pixels(d1, d2, d3, d4, (u32 *)dest); + d1 = (-(bits >> 3 & 1) & eorx) ^ bgx; + d2 = (-(bits >> 2 & 1) & eorx) ^ bgx; + d3 = (-(bits >> 1 & 1) & eorx) ^ bgx; + d4 = (-(bits & 1) & eorx) ^ bgx; + store4pixels(d1, d2, d3, d4, (u32 *)(dest+12)); + } +} + +void fbcon_cfb24_putcs(struct vc_data *conp, struct display *p, const char *s, + int count, int yy, int xx) +{ + u8 *cdat, c, *dest, *dest0; + int rows, bytes = p->next_line; + u32 eorx, fgx, bgx; + + dest0 = p->screen_base + yy * p->fontheight * bytes + xx * 24; + fgx = fbcon_cfb24_cmap[attr_fgcol(p, conp)]; + bgx = fbcon_cfb24_cmap[attr_bgcol(p, conp)]; + eorx = fgx ^ bgx; + while (count--) { + c = *s++; + cdat = p->fontdata + c * p->fontheight; + + for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) { + u8 bits = *cdat++; + u32 d1, d2, d3, d4; + d1 = (-(bits >> 7) & eorx) ^ bgx; + d2 = (-(bits >> 6 & 1) & eorx) ^ bgx; + d3 = (-(bits >> 5 & 1) & eorx) ^ bgx; + d4 = (-(bits >> 4 & 1) & eorx) ^ bgx; + store4pixels(d1, d2, d3, d4, (u32 *)dest); + d1 = (-(bits >> 3 & 1) & eorx) ^ bgx; + d2 = (-(bits >> 2 & 1) & eorx) ^ bgx; + d3 = (-(bits >> 1 & 1) & eorx) ^ bgx; + d4 = (-(bits & 1) & eorx) ^ bgx; + store4pixels(d1, d2, d3, d4, (u32 *)(dest+12)); + } + dest0 += 24; + } +} + +void fbcon_cfb24_revc(struct display *p, int xx, int yy) +{ + u8 *dest; + int bytes = p->next_line, rows; + + dest = p->screen_base + yy * p->fontheight * bytes + xx * 24; + for (rows = p->fontheight ; rows-- ; dest += bytes) { + ((u32 *)dest)[0] ^= 0xffffffff; + ((u32 *)dest)[1] ^= 0xffffffff; + ((u32 *)dest)[2] ^= 0xffffffff; + ((u32 *)dest)[3] ^= 0xffffffff; + ((u32 *)dest)[4] ^= 0xffffffff; + ((u32 *)dest)[5] ^= 0xffffffff; + } +} + + + /* + * `switch' for the low level operations + */ + +struct display_switch fbcon_cfb24 = { + fbcon_cfb24_setup, fbcon_cfb24_bmove, fbcon_cfb24_clear, fbcon_cfb24_putc, + fbcon_cfb24_putcs, fbcon_cfb24_revc +}; + + + /* + * Visible symbols for modules + */ + +EXPORT_SYMBOL(fbcon_cfb24); +EXPORT_SYMBOL(fbcon_cfb24_setup); +EXPORT_SYMBOL(fbcon_cfb24_bmove); +EXPORT_SYMBOL(fbcon_cfb24_clear); +EXPORT_SYMBOL(fbcon_cfb24_putc); +EXPORT_SYMBOL(fbcon_cfb24_putcs); +EXPORT_SYMBOL(fbcon_cfb24_revc); +EXPORT_SYMBOL(fbcon_cfb24_cmap); diff --git a/drivers/video/fbcon-cfb24.h b/drivers/video/fbcon-cfb24.h new file mode 100644 index 000000000..bd672ab20 --- /dev/null +++ b/drivers/video/fbcon-cfb24.h @@ -0,0 +1,16 @@ + /* + * 24 bpp packed pixel (cfb24) + */ + +extern struct display_switch fbcon_cfb24; +extern u32 fbcon_cfb24_cmap[16]; +extern void fbcon_cfb24_setup(struct display *p); +extern void fbcon_cfb24_bmove(struct display *p, int sy, int sx, int dy, + int dx, int height, int width); +extern void fbcon_cfb24_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width); +extern void fbcon_cfb24_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx); +extern void fbcon_cfb24_putcs(struct vc_data *conp, struct display *p, + const char *s, int count, int yy, int xx); +extern void fbcon_cfb24_revc(struct display *p, int xx, int yy); diff --git a/drivers/video/fbcon-cfb32.c b/drivers/video/fbcon-cfb32.c new file mode 100644 index 000000000..8c3306458 --- /dev/null +++ b/drivers/video/fbcon-cfb32.c @@ -0,0 +1,205 @@ +/* + * linux/drivers/video/cfb32.c -- Low level frame buffer operations for 32 bpp + * truecolor packed pixels + * + * Created 28 Dec 1997 by Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/module.h> +#include <linux/tty.h> +#include <linux/console.h> +#include <linux/string.h> +#include <linux/config.h> +#include <linux/fb.h> + +#include "fbcon.h" +#include "fbcon-cfb32.h" + + + /* + * 32 bpp packed pixels + */ + +u32 fbcon_cfb32_cmap[16]; + +void fbcon_cfb32_setup(struct display *p) +{ + p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<2; + p->next_plane = 0; +} + +void fbcon_cfb32_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) +{ + int bytes = p->next_line, linesize = bytes * p->fontheight, rows; + u8 *src, *dst; + + if (sx == 0 && dx == 0 && width * 32 == bytes) + mymemmove(p->screen_base + dy * linesize, + p->screen_base + sy * linesize, + height * linesize); + else if (dy < sy || (dy == sy && dx < sx)) { + src = p->screen_base + sy * linesize + sx * 32; + dst = p->screen_base + dy * linesize + dx * 32; + for (rows = height * p->fontheight ; rows-- ;) { + mymemmove(dst, src, width * 32); + src += bytes; + dst += bytes; + } + } else { + src = p->screen_base + (sy+height) * linesize + sx * 32 - bytes; + dst = p->screen_base + (dy+height) * linesize + dx * 32 - bytes; + for (rows = height * p->fontheight ; rows-- ;) { + mymemmove(dst, src, width * 32); + src -= bytes; + dst -= bytes; + } + } +} + +void fbcon_cfb32_clear(struct vc_data *conp, struct display *p, int sy, int sx, + int height, int width) +{ + u8 *dest0, *dest; + int bytes = p->next_line, lines = height * p->fontheight, rows, i; + u32 bgx; + + dest = p->screen_base + sy * p->fontheight * bytes + sx * 32; + + bgx = fbcon_cfb32_cmap[attr_bgcol_ec(p, conp)]; + + if (sx == 0 && width * 32 == bytes) + for (i = 0 ; i < lines * width ; i++) { + ((u32 *)dest)[0] = bgx; + ((u32 *)dest)[1] = bgx; + ((u32 *)dest)[2] = bgx; + ((u32 *)dest)[3] = bgx; + ((u32 *)dest)[4] = bgx; + ((u32 *)dest)[5] = bgx; + ((u32 *)dest)[6] = bgx; + ((u32 *)dest)[7] = bgx; + dest += 32; + } + else { + dest0 = dest; + for (rows = lines; rows-- ; dest0 += bytes) { + dest = dest0; + for (i = 0 ; i < width ; i++) { + ((u32 *)dest)[0] = bgx; + ((u32 *)dest)[1] = bgx; + ((u32 *)dest)[2] = bgx; + ((u32 *)dest)[3] = bgx; + ((u32 *)dest)[4] = bgx; + ((u32 *)dest)[5] = bgx; + ((u32 *)dest)[6] = bgx; + ((u32 *)dest)[7] = bgx; + dest += 32; + } + } + } +} + +void fbcon_cfb32_putc(struct vc_data *conp, struct display *p, int c, int yy, + int xx) +{ + u8 *dest, *cdat; + int bytes = p->next_line, rows; + u32 eorx, fgx, bgx; + + c &= 0xff; + + dest = p->screen_base + yy * p->fontheight * bytes + xx * 32; + cdat = p->fontdata + c * p->fontheight; + + fgx = fbcon_cfb32_cmap[attr_fgcol(p, conp)]; + bgx = fbcon_cfb32_cmap[attr_bgcol(p, conp)]; + eorx = fgx ^ bgx; + + for (rows = p->fontheight ; rows-- ; dest += bytes) { + u8 bits = *cdat++; + ((u32 *)dest)[0] = (-(bits >> 7) & eorx) ^ bgx; + ((u32 *)dest)[1] = (-(bits >> 6 & 1) & eorx) ^ bgx; + ((u32 *)dest)[2] = (-(bits >> 5 & 1) & eorx) ^ bgx; + ((u32 *)dest)[3] = (-(bits >> 4 & 1) & eorx) ^ bgx; + ((u32 *)dest)[4] = (-(bits >> 3 & 1) & eorx) ^ bgx; + ((u32 *)dest)[5] = (-(bits >> 2 & 1) & eorx) ^ bgx; + ((u32 *)dest)[6] = (-(bits >> 1 & 1) & eorx) ^ bgx; + ((u32 *)dest)[7] = (-(bits & 1) & eorx) ^ bgx; + } +} + +void fbcon_cfb32_putcs(struct vc_data *conp, struct display *p, const char *s, + int count, int yy, int xx) +{ + u8 *cdat, c, *dest, *dest0; + int rows, bytes = p->next_line; + u32 eorx, fgx, bgx; + + dest0 = p->screen_base + yy * p->fontheight * bytes + xx * 32; + fgx = fbcon_cfb32_cmap[attr_fgcol(p, conp)]; + bgx = fbcon_cfb32_cmap[attr_bgcol(p, conp)]; + eorx = fgx ^ bgx; + while (count--) { + c = *s++; + cdat = p->fontdata + c * p->fontheight; + + for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) { + u8 bits = *cdat++; + ((u32 *)dest)[0] = (-(bits >> 7) & eorx) ^ bgx; + ((u32 *)dest)[1] = (-(bits >> 6 & 1) & eorx) ^ bgx; + ((u32 *)dest)[2] = (-(bits >> 5 & 1) & eorx) ^ bgx; + ((u32 *)dest)[3] = (-(bits >> 4 & 1) & eorx) ^ bgx; + ((u32 *)dest)[4] = (-(bits >> 3 & 1) & eorx) ^ bgx; + ((u32 *)dest)[5] = (-(bits >> 2 & 1) & eorx) ^ bgx; + ((u32 *)dest)[6] = (-(bits >> 1 & 1) & eorx) ^ bgx; + ((u32 *)dest)[7] = (-(bits & 1) & eorx) ^ bgx; + } + dest0 += 32; + } +} + +void fbcon_cfb32_revc(struct display *p, int xx, int yy) +{ + u8 *dest; + int bytes = p->next_line, rows; + + dest = p->screen_base + yy * p->fontheight * bytes + xx * 32; + for (rows = p->fontheight ; rows-- ; dest += bytes) { + ((u32 *)dest)[0] ^= 0xffffffff; + ((u32 *)dest)[1] ^= 0xffffffff; + ((u32 *)dest)[2] ^= 0xffffffff; + ((u32 *)dest)[3] ^= 0xffffffff; + ((u32 *)dest)[4] ^= 0xffffffff; + ((u32 *)dest)[5] ^= 0xffffffff; + ((u32 *)dest)[6] ^= 0xffffffff; + ((u32 *)dest)[7] ^= 0xffffffff; + } +} + + + /* + * `switch' for the low level operations + */ + +struct display_switch fbcon_cfb32 = { + fbcon_cfb32_setup, fbcon_cfb32_bmove, fbcon_cfb32_clear, fbcon_cfb32_putc, + fbcon_cfb32_putcs, fbcon_cfb32_revc +}; + + + /* + * Visible symbols for modules + */ + +EXPORT_SYMBOL(fbcon_cfb32); +EXPORT_SYMBOL(fbcon_cfb32_setup); +EXPORT_SYMBOL(fbcon_cfb32_bmove); +EXPORT_SYMBOL(fbcon_cfb32_clear); +EXPORT_SYMBOL(fbcon_cfb32_putc); +EXPORT_SYMBOL(fbcon_cfb32_putcs); +EXPORT_SYMBOL(fbcon_cfb32_revc); +EXPORT_SYMBOL(fbcon_cfb32_cmap); diff --git a/drivers/video/fbcon-cfb32.h b/drivers/video/fbcon-cfb32.h new file mode 100644 index 000000000..1f74141c2 --- /dev/null +++ b/drivers/video/fbcon-cfb32.h @@ -0,0 +1,16 @@ + /* + * 32 bpp packed pixel (cfb32) + */ + +extern struct display_switch fbcon_cfb32; +extern u32 fbcon_cfb32_cmap[16]; +extern void fbcon_cfb32_setup(struct display *p); +extern void fbcon_cfb32_bmove(struct display *p, int sy, int sx, int dy, + int dx, int height, int width); +extern void fbcon_cfb32_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width); +extern void fbcon_cfb32_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx); +extern void fbcon_cfb32_putcs(struct vc_data *conp, struct display *p, + const char *s, int count, int yy, int xx); +extern void fbcon_cfb32_revc(struct display *p, int xx, int yy); diff --git a/drivers/video/fbcon-cfb4.c b/drivers/video/fbcon-cfb4.c new file mode 100644 index 000000000..bcdfcc436 --- /dev/null +++ b/drivers/video/fbcon-cfb4.c @@ -0,0 +1,208 @@ +/* + * linux/drivers/video/cfb4.c -- Low level frame buffer operations for 4 bpp + * packed pixels + * + * Created 26 Dec 1997 by Michael Schmitz + * Based on the old macfb.c 4bpp code by Alan Cox + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#include <linux/module.h> +#include <linux/tty.h> +#include <linux/console.h> +#include <linux/string.h> +#include <linux/config.h> +#include <linux/fb.h> + +#include "fbcon.h" +#include "fbcon-cfb4.h" + + + /* + * 4 bpp packed pixels + */ + + /* + * IFF the font is even pixel aligned (that is to say each + * character start is a byte start in the pixel pairs). That + * avoids us having to mask bytes and means we won't be here + * all week. On a MacII that matters _lots_ + */ + +static u16 nibbletab_cfb4[] = { + 0x0000,0x000f,0x00f0,0x00ff, + 0x0f00,0x0f0f,0x0ff0,0x0fff, + 0xf000,0xf00f,0xf0f0,0xf0ff, + 0xff00,0xff0f,0xfff0,0xffff +}; + +void fbcon_cfb4_setup(struct display *p) +{ + p->next_line = p->var.xres_virtual>>1; + p->next_plane = 0; +} + +void fbcon_cfb4_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) +{ + int bytes = p->next_line, linesize = bytes * p->fontheight, rows; + u8 *src,*dst; + + if (sx == 0 && dx == 0 && width * 4 == bytes) { + mymemmove(p->screen_base + dy * linesize, + p->screen_base + sy * linesize, + height * linesize); + } + else { + if (dy < sy || (dy == sy && dx < sx)) { + src = p->screen_base + sy * linesize + sx * 4; + dst = p->screen_base + dy * linesize + dx * 4; + for (rows = height * p->fontheight ; rows-- ;) { + mymemmove(dst, src, width * 4); + src += bytes; + dst += bytes; + } + } + else { + src = p->screen_base + (sy+height) * linesize + sx * 4 + - bytes; + dst = p->screen_base + (dy+height) * linesize + dx * 4 + - bytes; + for (rows = height * p->fontheight ; rows-- ;) { + mymemmove(dst, src, width * 4); + src -= bytes; + dst -= bytes; + } + } + } +} + +void fbcon_cfb4_clear(struct vc_data *conp, struct display *p, int sy, int sx, + int height, int width) +{ + u8 *dest0,*dest; + int bytes=p->next_line,lines=height * p->fontheight, rows, i; + u32 bgx; + +/* if(p->screen_base!=0xFDD00020) + mac_boom(1);*/ + dest = p->screen_base + sy * p->fontheight * bytes + sx * 4; + + bgx=attr_bgcol_ec(p,conp); + bgx |= (bgx << 4); /* expand the colour to 32bits */ + bgx |= (bgx << 8); + bgx |= (bgx << 16); + + if (sx == 0 && width * 4 == bytes) { + for (i = 0 ; i < lines * width ; i++) { + ((u32 *)dest)[0]=bgx; + dest+=4; + } + } else { + dest0=dest; + for (rows = lines; rows-- ; dest0 += bytes) { + dest=dest0; + for (i = 0 ; i < width ; i++) { + /* memset ?? */ + ((u32 *)dest)[0]=bgx; + dest+=4; + } + } + } +} + +void fbcon_cfb4_putc(struct vc_data *conp, struct display *p, int c, int yy, + int xx) +{ + u8 *dest,*cdat; + int bytes=p->next_line,rows; + u32 eorx,fgx,bgx; + + c &= 0xff; + + dest = p->screen_base + yy * p->fontheight * bytes + xx * 4; + cdat = p->fontdata + c * p->fontheight; + + fgx=15;/*attr_fgcol(p,conp)&0x0F;*/ + bgx=attr_bgcol(p,conp)&0x0F; + fgx |= (fgx << 4); + fgx |= (fgx << 8); + bgx |= (bgx << 4); + bgx |= (bgx << 8); + eorx = fgx ^ bgx; + + for (rows = p->fontheight ; rows-- ; dest += bytes) { + ((u16 *)dest)[0]= + (nibbletab_cfb4[*cdat >> 4] & eorx) ^ bgx; + ((u16 *)dest)[1]= + (nibbletab_cfb4[*cdat++ & 0xf] & eorx) ^ bgx; + } +} + +void fbcon_cfb4_putcs(struct vc_data *conp, struct display *p, const char *s, + int count, int yy, int xx) +{ + u8 *cdat, c, *dest, *dest0; + int rows,bytes=p->next_line; + u32 eorx, fgx, bgx; + + dest0 = p->screen_base + yy * p->fontheight * bytes + xx * 4; + fgx=15/*attr_fgcol(p,conp)*/; + bgx=attr_bgcol(p,conp); + fgx |= (fgx << 4); + fgx |= (fgx << 8); + fgx |= (fgx << 16); + bgx |= (bgx << 4); + bgx |= (bgx << 8); + bgx |= (bgx << 16); + eorx = fgx ^ bgx; + while (count--) { + c = *s++; + cdat = p->fontdata + c * p->fontheight; + + for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) { + ((u16 *)dest)[0]= + (nibbletab_cfb4[*cdat >> 4] & eorx) ^ bgx; + ((u16 *)dest)[1]= + (nibbletab_cfb4[*cdat++ & 0xf] & eorx) ^ bgx; + } + dest0+=4; + } +} + +void fbcon_cfb4_revc(struct display *p, int xx, int yy) +{ + u8 *dest; + int bytes=p->next_line, rows; + + dest = p->screen_base + yy * p->fontheight * bytes + xx * 4; + for (rows = p->fontheight ; rows-- ; dest += bytes) { + ((u32 *)dest)[0] ^= 0x0f0f0f0f; + } +} + + + /* + * `switch' for the low level operations + */ + +struct display_switch fbcon_cfb4 = { + fbcon_cfb4_setup, fbcon_cfb4_bmove, fbcon_cfb4_clear, fbcon_cfb4_putc, + fbcon_cfb4_putcs, fbcon_cfb4_revc +}; + + + /* + * Visible symbols for modules + */ + +EXPORT_SYMBOL(fbcon_cfb4); +EXPORT_SYMBOL(fbcon_cfb4_setup); +EXPORT_SYMBOL(fbcon_cfb4_bmove); +EXPORT_SYMBOL(fbcon_cfb4_clear); +EXPORT_SYMBOL(fbcon_cfb4_putc); +EXPORT_SYMBOL(fbcon_cfb4_putcs); +EXPORT_SYMBOL(fbcon_cfb4_revc); diff --git a/drivers/video/fbcon-cfb4.h b/drivers/video/fbcon-cfb4.h new file mode 100644 index 000000000..6fe3bc5a4 --- /dev/null +++ b/drivers/video/fbcon-cfb4.h @@ -0,0 +1,15 @@ + /* + * 4 bpp packed pixel (cfb4) + */ + +extern struct display_switch fbcon_cfb4; +extern void fbcon_cfb4_setup(struct display *p); +extern void fbcon_cfb4_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width); +extern void fbcon_cfb4_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width); +extern void fbcon_cfb4_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx); +extern void fbcon_cfb4_putcs(struct vc_data *conp, struct display *p, + const char *s, int count, int yy, int xx); +extern void fbcon_cfb4_revc(struct display *p, int xx, int yy); diff --git a/drivers/video/fbcon-cfb8.c b/drivers/video/fbcon-cfb8.c index 5fa339be1..c559f4025 100644 --- a/drivers/video/fbcon-cfb8.c +++ b/drivers/video/fbcon-cfb8.c @@ -13,70 +13,44 @@ #include <linux/tty.h> #include <linux/console.h> #include <linux/string.h> +#include <linux/config.h> #include <linux/fb.h> #include "fbcon.h" - - - /* - * Prototypes - */ - -static int open_cfb8(struct display *p); -static void release_cfb8(void); -static void bmove_cfb8(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -static void clear_cfb8(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width); -static void putc_cfb8(struct vc_data *conp, struct display *p, int c, int yy, - int xx); -static void putcs_cfb8(struct vc_data *conp, struct display *p, - const char *s, int count, int yy, int xx); -static void rev_char_cfb8(struct display *p, int xx, int yy); - - - /* - * `switch' for the low level operations - */ - -static struct display_switch dispsw_cfb8 = { - open_cfb8, release_cfb8, bmove_cfb8, clear_cfb8, putc_cfb8, putcs_cfb8, - rev_char_cfb8 -}; +#include "fbcon-cfb8.h" /* * 8 bpp packed pixels */ -static u_long nibbletab_cfb8[] = { +static u32 nibbletab_cfb8[] = { +#if defined(__BIG_ENDIAN) 0x00000000,0x000000ff,0x0000ff00,0x0000ffff, 0x00ff0000,0x00ff00ff,0x00ffff00,0x00ffffff, 0xff000000,0xff0000ff,0xff00ff00,0xff00ffff, 0xffff0000,0xffff00ff,0xffffff00,0xffffffff +#elif defined(__LITTLE_ENDIAN) + 0x00000000,0xff000000,0x00ff0000,0xffff0000, + 0x0000ff00,0xff00ff00,0x00ffff00,0xffffff00, + 0x000000ff,0xff0000ff,0x00ff00ff,0xffff00ff, + 0x0000ffff,0xff00ffff,0x00ffffff,0xffffffff +#else +#error FIXME: No endianness?? +#endif }; -static int open_cfb8(struct display *p) +void fbcon_cfb8_setup(struct display *p) { - if (p->type != FB_TYPE_PACKED_PIXELS || p->var.bits_per_pixel != 8) - return -EINVAL; - p->next_line = p->var.xres_virtual; p->next_plane = 0; - MOD_INC_USE_COUNT; - return 0; } -static void release_cfb8(void) -{ - MOD_DEC_USE_COUNT; -} - -static void bmove_cfb8(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) +void fbcon_cfb8_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) { int bytes = p->next_line, linesize = bytes * p->fontheight, rows; - u_char *src,*dst; + u8 *src,*dst; if (sx == 0 && dx == 0 && width * 8 == bytes) mymemmove(p->screen_base + dy * linesize, @@ -101,12 +75,12 @@ static void bmove_cfb8(struct display *p, int sy, int sx, int dy, int dx, } } -static void clear_cfb8(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width) +void fbcon_cfb8_clear(struct vc_data *conp, struct display *p, int sy, int sx, + int height, int width) { - u_char *dest0,*dest; + u8 *dest0,*dest; int bytes=p->next_line,lines=height * p->fontheight, rows, i; - u_long bgx; + u32 bgx; dest = p->screen_base + sy * p->fontheight * bytes + sx * 8; @@ -116,8 +90,8 @@ static void clear_cfb8(struct vc_data *conp, struct display *p, int sy, int sx, if (sx == 0 && width * 8 == bytes) for (i = 0 ; i < lines * width ; i++) { - ((u_long *)dest)[0]=bgx; - ((u_long *)dest)[1]=bgx; + ((u32 *)dest)[0]=bgx; + ((u32 *)dest)[1]=bgx; dest+=8; } else { @@ -125,20 +99,20 @@ static void clear_cfb8(struct vc_data *conp, struct display *p, int sy, int sx, for (rows = lines; rows-- ; dest0 += bytes) { dest=dest0; for (i = 0 ; i < width ; i++) { - ((u_long *)dest)[0]=bgx; - ((u_long *)dest)[1]=bgx; + ((u32 *)dest)[0]=bgx; + ((u32 *)dest)[1]=bgx; dest+=8; } } } } -static void putc_cfb8(struct vc_data *conp, struct display *p, int c, int yy, - int xx) +void fbcon_cfb8_putc(struct vc_data *conp, struct display *p, int c, int yy, + int xx) { - u_char *dest,*cdat; + u8 *dest,*cdat; int bytes=p->next_line,rows; - ulong eorx,fgx,bgx; + u32 eorx,fgx,bgx; c &= 0xff; @@ -154,17 +128,17 @@ static void putc_cfb8(struct vc_data *conp, struct display *p, int c, int yy, eorx = fgx ^ bgx; for (rows = p->fontheight ; rows-- ; dest += bytes) { - ((u_long *)dest)[0]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx; - ((u_long *)dest)[1]= (nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx; + ((u32 *)dest)[0]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx; + ((u32 *)dest)[1]= (nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx; } } -static void putcs_cfb8(struct vc_data *conp, struct display *p, const char *s, - int count, int yy, int xx) +void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p, const char *s, + int count, int yy, int xx) { - u_char *cdat, c, *dest, *dest0; + u8 *cdat, c, *dest, *dest0; int rows,bytes=p->next_line; - u_long eorx, fgx, bgx; + u32 eorx, fgx, bgx; dest0 = p->screen_base + yy * p->fontheight * bytes + xx * 8; fgx=attr_fgcol(p,conp); @@ -179,39 +153,44 @@ static void putcs_cfb8(struct vc_data *conp, struct display *p, const char *s, cdat = p->fontdata + c * p->fontheight; for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) { - ((u_long *)dest)[0]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx; - ((u_long *)dest)[1]= (nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ - bgx; + ((u32 *)dest)[0]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx; + ((u32 *)dest)[1]= (nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx; } dest0+=8; } } -static void rev_char_cfb8(struct display *p, int xx, int yy) +void fbcon_cfb8_revc(struct display *p, int xx, int yy) { - u_char *dest; + u8 *dest; int bytes=p->next_line, rows; dest = p->screen_base + yy * p->fontheight * bytes + xx * 8; for (rows = p->fontheight ; rows-- ; dest += bytes) { - ((u_long *)dest)[0] ^= 0x0f0f0f0f; - ((u_long *)dest)[1] ^= 0x0f0f0f0f; + ((u32 *)dest)[0] ^= 0x0f0f0f0f; + ((u32 *)dest)[1] ^= 0x0f0f0f0f; } } -#ifdef MODULE -int init_module(void) -#else -int fbcon_init_cfb8(void) -#endif -{ - return(fbcon_register_driver(&dispsw_cfb8, 0)); -} + /* + * `switch' for the low level operations + */ -#ifdef MODULE -void cleanup_module(void) -{ - fbcon_unregister_driver(&dispsw_cfb8); -} -#endif /* MODULE */ +struct display_switch fbcon_cfb8 = { + fbcon_cfb8_setup, fbcon_cfb8_bmove, fbcon_cfb8_clear, fbcon_cfb8_putc, + fbcon_cfb8_putcs, fbcon_cfb8_revc +}; + + + /* + * Visible symbols for modules + */ + +EXPORT_SYMBOL(fbcon_cfb8); +EXPORT_SYMBOL(fbcon_cfb8_setup); +EXPORT_SYMBOL(fbcon_cfb8_bmove); +EXPORT_SYMBOL(fbcon_cfb8_clear); +EXPORT_SYMBOL(fbcon_cfb8_putc); +EXPORT_SYMBOL(fbcon_cfb8_putcs); +EXPORT_SYMBOL(fbcon_cfb8_revc); diff --git a/drivers/video/fbcon-cfb8.h b/drivers/video/fbcon-cfb8.h new file mode 100644 index 000000000..4c0ffec99 --- /dev/null +++ b/drivers/video/fbcon-cfb8.h @@ -0,0 +1,15 @@ + /* + * 8 bpp packed pixel (cfb8) + */ + +extern struct display_switch fbcon_cfb8; +extern void fbcon_cfb8_setup(struct display *p); +extern void fbcon_cfb8_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width); +extern void fbcon_cfb8_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width); +extern void fbcon_cfb8_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx); +extern void fbcon_cfb8_putcs(struct vc_data *conp, struct display *p, + const char *s, int count, int yy, int xx); +extern void fbcon_cfb8_revc(struct display *p, int xx, int yy); diff --git a/drivers/video/fbcon-cyber.c b/drivers/video/fbcon-cyber.c deleted file mode 100644 index ee740516d..000000000 --- a/drivers/video/fbcon-cyber.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * linux/drivers/video/cyber.c -- Low level frame buffer operations for the - * CyberVision64 (accelerated) - * - * Created 5 Apr 1997 by Geert Uytterhoeven - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include <linux/module.h> -#include <linux/tty.h> -#include <linux/console.h> -#include <linux/string.h> -#include <linux/fb.h> - -#include "fbcon.h" -#include "s3blit.h" - - - /* - * Prototypes - */ - -static int open_cyber(struct display *p); -static void release_cyber(void); -static void bmove_cyber(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -static void clear_cyber(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width); -static void putc_cyber(struct vc_data *conp, struct display *p, int c, int yy, - int xx); -static void putcs_cyber(struct vc_data *conp, struct display *p, const char *s, - int count, int yy, int xx); -static void rev_char_cyber(struct display *p, int xx, int yy); - - - /* - * Acceleration functions in cyberfb.c - */ - -extern void Cyber_WaitQueue(unsigned short fifo); -extern void Cyber_WaitBlit(void); -extern void Cyber_BitBLT(unsigned short curx, unsigned short cury, - unsigned short destx, unsigned short desty, - unsigned short width, unsigned short height, - unsigned short mode); -extern void Cyber_RectFill(unsigned short xx, unsigned short yy, - unsigned short width, unsigned short height, - unsigned short mode, unsigned short fillcolor); -extern void Cyber_MoveCursor(unsigned short xx, unsigned short yy); - - - /* - * `switch' for the low level operations - */ - -static struct display_switch dispsw_cyber = { - open_cyber, release_cyber, bmove_cyber, clear_cyber, putc_cyber, - putcs_cyber, rev_char_cyber -}; - - - /* - * CyberVision64 (accelerated) - */ - -static int open_cyber(struct display *p) -{ - if (p->type != FB_TYPE_PACKED_PIXELS || - p->var.accel != FB_ACCEL_CYBERVISION) - return -EINVAL; - - p->next_line = p->var.xres_virtual*p->var.bits_per_pixel>>3; - p->next_plane = 0; - MOD_INC_USE_COUNT; - return 0; -} - -static void release_cyber(void) -{ - MOD_DEC_USE_COUNT; -} - -static void bmove_cyber(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - sx *= 8; dx *= 8; width *= 8; - Cyber_BitBLT((u_short)sx, (u_short)(sy*p->fontheight), (u_short)dx, - (u_short)(dy*p->fontheight), (u_short)width, - (u_short)(height*p->fontheight), (u_short)S3_NEW); -} - -static void clear_cyber(struct vc_data *conp, struct display *p, int - sy, int sx, int height, int width) -{ - unsigned char bg; - - sx *= 8; width *= 8; - bg = attr_bgcol_ec(p,conp); - Cyber_RectFill((u_short)sx, - (u_short)(sy*p->fontheight), - (u_short)width, - (u_short)(height*p->fontheight), - (u_short)S3_NEW, - (u_short)bg); -} - -static void putc_cyber(struct vc_data *conp, struct display *p, int c, int yy, - int xx) -{ - u_char *dest, *cdat; - u_long tmp; - u_int rows, revs, underl; - u_char d; - u_char fg, bg; - - c &= 0xff; - - dest = p->screen_base+yy*p->fontheight*p->next_line+8*xx; - cdat = p->fontdata+(c*p->fontheight); - fg = p->fgcol; - bg = p->bgcol; - revs = conp->vc_reverse; - underl = conp->vc_underline; - - Cyber_WaitBlit(); - for (rows = p->fontheight; rows--; dest += p->next_line) { - d = *cdat++; - - if (underl && !rows) - d = 0xff; - if (revs) - d = ~d; - - tmp = ((d & 0x80) ? fg : bg) << 24; - tmp |= ((d & 0x40) ? fg : bg) << 16; - tmp |= ((d & 0x20) ? fg : bg) << 8; - tmp |= ((d & 0x10) ? fg : bg); - *((u_long*) dest) = tmp; - tmp = ((d & 0x8) ? fg : bg) << 24; - tmp |= ((d & 0x4) ? fg : bg) << 16; - tmp |= ((d & 0x2) ? fg : bg) << 8; - tmp |= ((d & 0x1) ? fg : bg); - *((u_long*) dest + 1) = tmp; - } -} - -static void putcs_cyber(struct vc_data *conp, struct display *p, const char *s, - int count, int yy, int xx) -{ - u_char *dest, *dest0, *cdat; - u_long tmp; - u_int rows, underl; - u_char c, d; - u_char fg, bg; - - dest0 = p->screen_base+yy*p->fontheight*p->next_line+8*xx; - fg = p->fgcol; - bg = p->bgcol; - underl = conp->vc_underline; - - Cyber_WaitBlit(); - while (count--) { - c = *s++; - dest = dest0; - dest0 += 8; - cdat = p->fontdata+(c*p->fontheight); - for (rows = p->fontheight; rows--; dest += p->next_line) { - d = *cdat++; - - if (underl && !rows) - d = 0xff; - - tmp = ((d & 0x80) ? fg : bg) << 24; - tmp |= ((d & 0x40) ? fg : bg) << 16; - tmp |= ((d & 0x20) ? fg : bg) << 8; - tmp |= ((d & 0x10) ? fg : bg); - *((u_long*) dest) = tmp; - tmp = ((d & 0x8) ? fg : bg) << 24; - tmp |= ((d & 0x4) ? fg : bg) << 16; - tmp |= ((d & 0x2) ? fg : bg) << 8; - tmp |= ((d & 0x1) ? fg : bg); - *((u_long*) dest + 1) = tmp; - } - } -} - - -static void rev_char_cyber(struct display *p, int xx, int yy) -{ - unsigned char *dest; - unsigned int rows; - unsigned char fg, bg; - - fg = p->fgcol; - bg = p->bgcol; - - dest = p->screen_base+yy*p->fontheight*p->next_line+8*xx; - Cyber_WaitBlit(); - for (rows = p->fontheight; rows--; dest += p->next_line) { - *dest = (*dest == fg) ? bg : fg; - *(dest+1) = (*(dest + 1) == fg) ? bg : fg; - *(dest+2) = (*(dest + 2) == fg) ? bg : fg; - *(dest+3) = (*(dest + 3) == fg) ? bg : fg; - *(dest+4) = (*(dest + 4) == fg) ? bg : fg; - *(dest+5) = (*(dest + 5) == fg) ? bg : fg; - *(dest+6) = (*(dest + 6) == fg) ? bg : fg; - *(dest+7) = (*(dest + 7) == fg) ? bg : fg; - } -} - - -#ifdef MODULE -int init_module(void) -#else -int fbcon_init_cyber(void) -#endif -{ - return(fbcon_register_driver(&dispsw_cyber, 1)); -} - -#ifdef MODULE -void cleanup_module(void) -{ - fbcon_unregister_driver(&dispsw_cyber); -} -#endif /* MODULE */ diff --git a/drivers/video/fbcon-ilbm.c b/drivers/video/fbcon-ilbm.c index 33be946e2..82f9982f6 100644 --- a/drivers/video/fbcon-ilbm.c +++ b/drivers/video/fbcon-ilbm.c @@ -16,33 +16,7 @@ #include <linux/fb.h> #include "fbcon.h" - - - /* - * Prototypes - */ - -static int open_ilbm(struct display *p); -static void release_ilbm(void); -static void bmove_ilbm(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -static void clear_ilbm(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width); -static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int yy, - int xx); -static void putcs_ilbm(struct vc_data *conp, struct display *p, const char *s, - int count, int yy, int xx); -static void rev_char_ilbm(struct display *p, int xx, int yy); - - - /* - * `switch' for the low level operations - */ - -static struct display_switch dispsw_ilbm = { - open_ilbm, release_ilbm, bmove_ilbm, clear_ilbm, putc_ilbm, putcs_ilbm, - rev_char_ilbm -}; +#include "fbcon-ilbm.h" /* @@ -56,11 +30,8 @@ static struct display_switch dispsw_ilbm = { * much performance loss? */ -static int open_ilbm(struct display *p) +void fbcon_ilbm_setup(struct display *p) { - if (p->type != FB_TYPE_INTERLEAVED_PLANES || p->type_aux == 2) - return -EINVAL; - if (p->line_length) { p->next_line = p->line_length*p->var.bits_per_pixel; p->next_plane = p->line_length; @@ -68,24 +39,17 @@ static int open_ilbm(struct display *p) p->next_line = p->type_aux; p->next_plane = p->type_aux/p->var.bits_per_pixel; } - MOD_INC_USE_COUNT; - return 0; } -static void release_ilbm(void) -{ - MOD_DEC_USE_COUNT; -} - -static void bmove_ilbm(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) +void fbcon_ilbm_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) { if (sx == 0 && dx == 0 && width == p->next_plane) mymemmove(p->screen_base+dy*p->fontheight*p->next_line, p->screen_base+sy*p->fontheight*p->next_line, height*p->fontheight*p->next_line); else { - u_char *src, *dest; + u8 *src, *dest; u_int i; if (dy <= sy) { @@ -108,10 +72,10 @@ static void bmove_ilbm(struct display *p, int sy, int sx, int dy, int dx, } } -static void clear_ilbm(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width) +void fbcon_ilbm_clear(struct vc_data *conp, struct display *p, int sy, int sx, + int height, int width) { - u_char *dest; + u8 *dest; u_int i, rows; int bg, bg0; @@ -130,12 +94,12 @@ static void clear_ilbm(struct vc_data *conp, struct display *p, int sy, int sx, } } -static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int yy, - int xx) +void fbcon_ilbm_putc(struct vc_data *conp, struct display *p, int c, int yy, + int xx) { - u_char *dest, *cdat; + u8 *dest, *cdat; u_int rows, i; - u_char d; + u8 d; int fg0, bg0, fg, bg; c &= 0xff; @@ -150,16 +114,17 @@ static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int yy, fg = fg0; bg = bg0; for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) { - if (bg & 1) + if (bg & 1){ if (fg & 1) *dest = 0xff; else *dest = ~d; - else + }else{ if (fg & 1) *dest = d; else *dest = 0x00; + } bg >>= 1; fg >>= 1; } @@ -181,13 +146,13 @@ static void putc_ilbm(struct vc_data *conp, struct display *p, int c, int yy, * -- Geert */ -static void putcs_ilbm(struct vc_data *conp, struct display *p, const char *s, - int count, int yy, int xx) +void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p, const char *s, + int count, int yy, int xx) { - u_char *dest0, *dest, *cdat1, *cdat2, *cdat3, *cdat4; + u8 *dest0, *dest, *cdat1, *cdat2, *cdat3, *cdat4; u_int rows, i; - u_char c1, c2, c3, c4; - u_long d; + u8 c1, c2, c3, c4; + u32 d; int fg0, bg0, fg, bg; dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx; @@ -206,16 +171,17 @@ static void putcs_ilbm(struct vc_data *conp, struct display *p, const char *s, fg = fg0; bg = bg0; for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) { - if (bg & 1) + if (bg & 1){ if (fg & 1) *dest = 0xff; else *dest = ~d; - else + }else{ if (fg & 1) *dest = d; else *dest = 0x00; + } bg >>= 1; fg >>= 1; } @@ -232,20 +198,27 @@ static void putcs_ilbm(struct vc_data *conp, struct display *p, const char *s, cdat3 = p->fontdata+c3*p->fontheight; cdat4 = p->fontdata+c4*p->fontheight; for (rows = p->fontheight; rows--;) { +#if defined(__BIG_ENDIAN) d = *cdat1++<<24 | *cdat2++<<16 | *cdat3++<<8 | *cdat4++; +#elif defined(__LITTLE_ENDIAN) + d = *cdat1++ | *cdat2++<<8 | *cdat3++<<16 | *cdat4++<<32); +#else +#error FIXME: No endianness?? +#endif fg = fg0; bg = bg0; for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) { - if (bg & 1) + if (bg & 1){ if (fg & 1) - *(u_long *)dest = 0xffffffff; + *(u32 *)dest = 0xffffffff; else - *(u_long *)dest = ~d; - else + *(u32 *)dest = ~d; + }else{ if (fg & 1) - *(u_long *)dest = d; + *(u32 *)dest = d; else - *(u_long *)dest = 0x00000000; + *(u32 *)dest = 0x00000000; + } bg >>= 1; fg >>= 1; } @@ -257,9 +230,9 @@ static void putcs_ilbm(struct vc_data *conp, struct display *p, const char *s, } } -static void rev_char_ilbm(struct display *p, int xx, int yy) +void fbcon_ilbm_revc(struct display *p, int xx, int yy) { - u_char *dest, *dest0; + u8 *dest, *dest0; u_int rows, i; int mask; @@ -283,18 +256,24 @@ static void rev_char_ilbm(struct display *p, int xx, int yy) } -#ifdef MODULE -int init_module(void) -#else -int fbcon_init_ilbm(void) -#endif -{ - return(fbcon_register_driver(&dispsw_ilbm, 0)); -} + /* + * `switch' for the low level operations + */ -#ifdef MODULE -void cleanup_module(void) -{ - fbcon_unregister_driver(&dispsw_ilbm); -} -#endif /* MODULE */ +struct display_switch fbcon_ilbm = { + fbcon_ilbm_setup, fbcon_ilbm_bmove, fbcon_ilbm_clear, fbcon_ilbm_putc, + fbcon_ilbm_putcs, fbcon_ilbm_revc +}; + + + /* + * Visible symbols for modules + */ + +EXPORT_SYMBOL(fbcon_ilbm); +EXPORT_SYMBOL(fbcon_ilbm_setup); +EXPORT_SYMBOL(fbcon_ilbm_bmove); +EXPORT_SYMBOL(fbcon_ilbm_clear); +EXPORT_SYMBOL(fbcon_ilbm_putc); +EXPORT_SYMBOL(fbcon_ilbm_putcs); +EXPORT_SYMBOL(fbcon_ilbm_revc); diff --git a/drivers/video/fbcon-ilbm.h b/drivers/video/fbcon-ilbm.h new file mode 100644 index 000000000..e2434c7d1 --- /dev/null +++ b/drivers/video/fbcon-ilbm.h @@ -0,0 +1,15 @@ + /* + * Amiga interleaved bitplanes (ilbm) + */ + +extern struct display_switch fbcon_ilbm; +extern void fbcon_ilbm_setup(struct display *p); +extern void fbcon_ilbm_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width); +extern void fbcon_ilbm_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width); +extern void fbcon_ilbm_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx); +extern void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p, + const char *s, int count, int yy, int xx); +extern void fbcon_ilbm_revc(struct display *p, int xx, int yy); diff --git a/drivers/video/fbcon-iplan2p2.c b/drivers/video/fbcon-iplan2p2.c index 3973a0013..adef5819d 100644 --- a/drivers/video/fbcon-iplan2p2.c +++ b/drivers/video/fbcon-iplan2p2.c @@ -14,41 +14,13 @@ #include <linux/tty.h> #include <linux/console.h> #include <linux/string.h> +#include <linux/config.h> #include <linux/fb.h> -#include "fbcon.h" - - -#ifndef __mc68000__ -#error No support for non-m68k yet -#endif +#include <asm/byteorder.h> - - /* - * Prototypes - */ - -static int open_iplan2p2(struct display *p); -static void release_iplan2p2(void); -static void bmove_iplan2p2(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -static void clear_iplan2p2(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width); -static void putc_iplan2p2(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -static void putcs_iplan2p2(struct vc_data *conp, struct display *p, - const char *s, int count, int yy, int xx); -static void rev_char_iplan2p2(struct display *display, int xx, int yy); - - - /* - * `switch' for the low level operations - */ - -static struct display_switch dispsw_iplan2p2 = { - open_iplan2p2, release_iplan2p2, bmove_iplan2p2, clear_iplan2p2, - putc_iplan2p2, putcs_iplan2p2, rev_char_iplan2p2 -}; +#include "fbcon.h" +#include "fbcon-iplan2p2.h" /* @@ -65,8 +37,19 @@ static struct display_switch dispsw_iplan2p2 = { * The intensity bit (b3) is shifted into b1. */ -#define COLOR_2P(c) (((c & 7) >= 3 && (c & 7) != 4) | (c & 8) >> 2) +static const u8 color_2p[] = { 0, 0, 0, 1, 0, 1, 1, 1, 2, 2, 2, 3, 2, 3, 3, 3 }; +#define COLOR_2P(c) color_2p[c] +/* Perform the m68k movepw operation. */ +static inline void movepw(u8 *d, u16 val) +{ +#if defined __mc68000__ && !defined CONFIG_OPTIMIZE_060 + asm volatile ("movepw %1,%0@(0)" : : "a" (d), "d" (val)); +#else + d[0] = (val >> 16) & 0xff; + d[2] = val & 0xff; +#endif +} /* Sets the bytes in the visible column at d, height h, to the value * val for a 2 plane screen. The the bis of the color in 'color' are @@ -77,16 +60,13 @@ static struct display_switch dispsw_iplan2p2 = { * *(d+2) = (color & 2) ? 0xff : 0; */ -static __inline__ void memclear_2p_col(void *d, size_t h, u_short val, int bpr) +static __inline__ void memclear_2p_col(void *d, size_t h, u16 val, int bpr) { -#ifdef __mc68000__ - __asm__ __volatile__ ("1: movepw %4,%0@(0)\n\t" - "addal %5,%0\n\t" - "dbra %1,1b" - : "=a" (d), "=d" (h) - : "0" (d), "1" (h - 1), "d" (val), "r" (bpr)); -#else /* !m68k */ -#endif /* !m68k */ + u8 *dd = d; + do { + movepw(dd, val); + dd += bpr; + } while (--h); } /* Sets a 2 plane region from 'd', length 'count' bytes, to the color @@ -98,9 +78,9 @@ static __inline__ void memclear_2p_col(void *d, size_t h, u_short val, int bpr) * *(d+2) = *(d+3) = (color & 2) ? 0xff : 0; */ -static __inline__ void memset_even_2p(void *d, size_t count, u_long val) +static __inline__ void memset_even_2p(void *d, size_t count, u32 val) { - u_long *dd = d; + u32 *dd = d; count /= 4; while (count--) @@ -111,7 +91,7 @@ static __inline__ void memset_even_2p(void *d, size_t count, u_long val) static __inline__ void memmove_2p_col (void *d, void *s, int h, int bpr) { - u_char *dd = d, *ss = s; + u8 *dd = d, *ss = s; while (h--) { dd[0] = ss[0]; @@ -124,81 +104,54 @@ static __inline__ void memmove_2p_col (void *d, void *s, int h, int bpr) /* This expands a 2 bit color into a short for movepw (2 plane) operations. */ -static __inline__ u_short expand2w(u_char c) +static const u16 two2byte[] = { + 0x0000, 0xff00, 0x00ff, 0xffff +}; + +static __inline__ u16 expand2w(u8 c) { - u_short rv; - -#ifdef __mc68000__ - __asm__ __volatile__ ("lsrb #1,%2\n\t" - "scs %0\n\t" - "lsll #8,%0\n\t" - "lsrb #1,%2\n\t" - "scs %0\n\t" - : "=&d" (rv), "=d" (c) - : "1" (c)); -#endif /* !m68k */ - return(rv); + return two2byte[c]; } + /* This expands a 2 bit color into one long for a movel operation * (2 planes). */ -static __inline__ u_long expand2l(u_char c) +static const u32 two2word[] = { +#ifndef __LITTLE_ENDIAN + 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff +#else + 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff +#endif +}; + +static __inline__ u32 expand2l(u8 c) { - u_long rv; - -#ifdef __mc68000__ - __asm__ __volatile__ ("lsrb #1,%2\n\t" - "scs %0\n\t" - "extw %0\n\t" - "swap %0\n\t" - "lsrb #1,%2\n\t" - "scs %0\n\t" - "extw %0\n\t" - : "=&d" (rv), "=d" (c) - : "1" (c)); -#endif /* !m68k */ - return rv; + return two2word[c]; } /* This duplicates a byte 2 times into a short. */ -static __inline__ u_short dup2w(u_char c) +static __inline__ u16 dup2w(u8 c) { - ushort rv; - -#ifdef __mc68000__ - __asm__ __volatile__ ("moveb %1,%0\n\t" - "lslw #8,%0\n\t" - "moveb %1,%0\n\t" - : "=&d" (rv) - : "d" (c)); -#endif /* !m68k */ - return( rv ); + u16 rv; + + rv = c; + rv |= c << 8; + return rv; } -static int open_iplan2p2(struct display *p) +void fbcon_iplan2p2_setup(struct display *p) { - if (p->type != FB_TYPE_INTERLEAVED_PLANES || p->type_aux != 2 || - p->var.bits_per_pixel != 2) - return -EINVAL; - p->next_line = p->var.xres_virtual>>2; p->next_plane = 2; - MOD_INC_USE_COUNT; - return 0; } -static void release_iplan2p2(void) -{ - MOD_DEC_USE_COUNT; -} - -static void bmove_iplan2p2(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) +void fbcon_iplan2p2_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) { /* bmove() has to distinguish two major cases: If both, source and * destination, start at even addresses or both are at odd @@ -212,7 +165,7 @@ static void bmove_iplan2p2(struct display *p, int sy, int sx, int dy, int dx, * all movements by memmove_col(). */ - if (sx == 0 && dx == 0 && width == p->next_line/2) { + if (sx == 0 && dx == 0 && width * 2 == p->next_line) { /* Special (but often used) case: Moving whole lines can be * done with memmove() */ @@ -221,8 +174,8 @@ static void bmove_iplan2p2(struct display *p, int sy, int sx, int dy, int dx, p->next_line * height * p->fontheight); } else { int rows, cols; - u_char *src; - u_char *dst; + u8 *src; + u8 *dst; int bytes = p->next_line; int linesize = bytes * p->fontheight; u_int colsize = height * p->fontheight; @@ -298,21 +251,21 @@ static void bmove_iplan2p2(struct display *p, int sy, int sx, int dy, int dx, } } -static void clear_iplan2p2(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width) +void fbcon_iplan2p2_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width) { - ulong offset; - u_char *start; + u32 offset; + u8 *start; int rows; int bytes = p->next_line; int lines = height * p->fontheight; - ulong size; - u_long cval; - u_short pcval; + u32 size; + u32 cval; + u16 pcval; cval = expand2l (COLOR_2P (attr_bgcol_ec(p,conp))); - if (sx == 0 && width == bytes/2) { + if (sx == 0 && width * 2 == bytes) { offset = sy * bytes * p->fontheight; size = lines * bytes; memset_even_2p(p->screen_base+offset, size, cval); @@ -344,14 +297,14 @@ static void clear_iplan2p2(struct vc_data *conp, struct display *p, int sy, } } -static void putc_iplan2p2(struct vc_data *conp, struct display *p, int c, - int yy, int xx) +void fbcon_iplan2p2_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx) { - u_char *dest; - u_char *cdat; + u8 *dest; + u8 *cdat; int rows; int bytes = p->next_line; - ulong eorx, fgx, bgx, fdx; + u16 eorx, fgx, bgx, fdx; c &= 0xff; @@ -364,22 +317,18 @@ static void putc_iplan2p2(struct vc_data *conp, struct display *p, int c, for (rows = p->fontheight ; rows-- ; dest += bytes) { fdx = dup2w(*cdat++); -#ifdef __mc68000__ - __asm__ __volatile__ ("movepw %1,%0@(0)" - : /* no outputs */ - : "a" (dest), "d" ((fdx & eorx) ^ bgx)); -#endif /* !m68k */ + movepw(dest, (fdx & eorx) ^ bgx); } } -static void putcs_iplan2p2(struct vc_data *conp, struct display *p, - const char *s, int count, int yy, int xx) +void fbcon_iplan2p2_putcs(struct vc_data *conp, struct display *p, + const char *s, int count, int yy, int xx) { - u_char *dest, *dest0; - u_char *cdat, c; + u8 *dest, *dest0; + u8 *cdat, c; int rows; int bytes; - ulong eorx, fgx, bgx, fdx; + u16 eorx, fgx, bgx, fdx; bytes = p->next_line; dest0 = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*4 + (xx & 1); @@ -393,19 +342,15 @@ static void putcs_iplan2p2(struct vc_data *conp, struct display *p, for (rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) { fdx = dup2w(*cdat++); -#ifdef __mc68000__ - __asm__ __volatile__ ("movepw %1,%0@(0)" - : /* no outputs */ - : "a" (dest), "d" ((fdx & eorx) ^ bgx)); -#endif /* !m68k */ + movepw(dest, (fdx & eorx) ^ bgx); } INC_2P(dest0); } } -static void rev_char_iplan2p2(struct display *p, int xx, int yy) +void fbcon_iplan2p2_revc(struct display *p, int xx, int yy) { - u_char *dest; + u8 *dest; int j; int bytes; @@ -425,18 +370,24 @@ static void rev_char_iplan2p2(struct display *p, int xx, int yy) } -#ifdef MODULE -int init_module(void) -#else -int fbcon_init_iplan2p2(void) -#endif -{ - return(fbcon_register_driver(&dispsw_iplan2p2, 0)); -} + /* + * `switch' for the low level operations + */ -#ifdef MODULE -void cleanup_module(void) -{ - fbcon_unregister_driver(&dispsw_iplan2p2); -} -#endif /* MODULE */ +struct display_switch fbcon_iplan2p2 = { + fbcon_iplan2p2_setup, fbcon_iplan2p2_bmove, fbcon_iplan2p2_clear, + fbcon_iplan2p2_putc, fbcon_iplan2p2_putcs, fbcon_iplan2p2_revc +}; + + + /* + * Visible symbols for modules + */ + +EXPORT_SYMBOL(fbcon_iplan2p2); +EXPORT_SYMBOL(fbcon_iplan2p2_setup); +EXPORT_SYMBOL(fbcon_iplan2p2_bmove); +EXPORT_SYMBOL(fbcon_iplan2p2_clear); +EXPORT_SYMBOL(fbcon_iplan2p2_putc); +EXPORT_SYMBOL(fbcon_iplan2p2_putcs); +EXPORT_SYMBOL(fbcon_iplan2p2_revc); diff --git a/drivers/video/fbcon-iplan2p2.h b/drivers/video/fbcon-iplan2p2.h new file mode 100644 index 000000000..ae18a1b32 --- /dev/null +++ b/drivers/video/fbcon-iplan2p2.h @@ -0,0 +1,15 @@ + /* + * Atari interleaved bitplanes (2 planes) (iplan2p2) + */ + +extern struct display_switch fbcon_iplan2p2; +extern void fbcon_iplan2p2_setup(struct display *p); +extern void fbcon_iplan2p2_bmove(struct display *p, int sy, int sx, int dy, + int dx, int height, int width); +extern void fbcon_iplan2p2_clear(struct vc_data *conp, struct display *p, + int sy, int sx, int height, int width); +extern void fbcon_iplan2p2_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx); +extern void fbcon_iplan2p2_putcs(struct vc_data *conp, struct display *p, + const char *s, int count, int yy, int xx); +extern void fbcon_iplan2p2_revc(struct display *p, int xx, int yy); diff --git a/drivers/video/fbcon-iplan2p4.c b/drivers/video/fbcon-iplan2p4.c index e3a10f0ea..b299701c4 100644 --- a/drivers/video/fbcon-iplan2p4.c +++ b/drivers/video/fbcon-iplan2p4.c @@ -14,41 +14,13 @@ #include <linux/tty.h> #include <linux/console.h> #include <linux/string.h> +#include <linux/config.h> #include <linux/fb.h> -#include "fbcon.h" - - -#ifndef __mc68000__ -#error No support for non-m68k yet -#endif - - - /* - * Prototypes - */ - -static int open_iplan2p4(struct display *p); -static void release_iplan2p4(void); -static void bmove_iplan2p4(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -static void clear_iplan2p4(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width); -static void putc_iplan2p4(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -static void putcs_iplan2p4(struct vc_data *conp, struct display *p, - const char *s, int count, int yy, int xx); -static void rev_char_iplan2p4(struct display *p, int xx, int yy); - - - /* - * `switch' for the low level operations - */ +#include <asm/byteorder.h> -static struct display_switch dispsw_iplan2p4 = { - open_iplan2p4, release_iplan2p4, bmove_iplan2p4, clear_iplan2p4, - putc_iplan2p4, putcs_iplan2p4, rev_char_iplan2p4 -}; +#include "fbcon.h" +#include "fbcon-iplan2p4.h" /* @@ -60,6 +32,18 @@ static struct display_switch dispsw_iplan2p4 = { #define INC_4P(p) do { if (!((long)(++(p)) & 1)) (p) += 6; } while(0) #define DEC_4P(p) do { if ((long)(--(p)) & 1) (p) -= 6; } while(0) +/* Perform the m68k movepl operation. */ +static inline void movepl(u8 *d, u32 val) +{ +#if defined __mc68000__ && !defined CONFIG_OPTIMIZE_060 + asm volatile ("movepl %1,%0@(0)" : : "a" (d), "d" (val)); +#else + d[0] = (val >> 24) & 0xff; + d[2] = (val >> 16) & 0xff; + d[4] = (val >> 8) & 0xff; + d[6] = val & 0xff; +#endif +} /* Sets the bytes in the visible column at d, height h, to the value * val for a 4 plane screen. The the bis of the color in 'color' are @@ -72,15 +56,13 @@ static struct display_switch dispsw_iplan2p4 = { * *(d+6) = (color & 8) ? 0xff : 0; */ -static __inline__ void memclear_4p_col(void *d, size_t h, u_long val, int bpr) +static __inline__ void memclear_4p_col(void *d, size_t h, u32 val, int bpr) { -#ifdef __mc68000__ - __asm__ __volatile__ ("1: movepl %4,%0@(0)\n\t" - "addal %5,%0\n\t" - "dbra %1,1b" - : "=a" (d), "=d" (h) - : "0" (d), "1" (h - 1), "d" (val), "r" (bpr)); -#endif /* !m68k */ + u8 *dd = d; + do { + movepl(dd, val); + dd += bpr; + } while (--h); } /* Sets a 4 plane region from 'd', length 'count' bytes, to the color @@ -94,10 +76,10 @@ static __inline__ void memclear_4p_col(void *d, size_t h, u_long val, int bpr) * *(d+6) = *(d+7) = (color & 8) ? 0xff : 0; */ -static __inline__ void memset_even_4p(void *d, size_t count, u_long val1, - u_long val2) +static __inline__ void memset_even_4p(void *d, size_t count, u32 val1, + u32 val2) { - u_long *dd = d; + u32 *dd = d; count /= 8; while (count--) { @@ -110,7 +92,7 @@ static __inline__ void memset_even_4p(void *d, size_t count, u_long val1, static __inline__ void memmove_4p_col (void *d, void *s, int h, int bpr) { - u_char *dd = d, *ss = s; + u8 *dd = d, *ss = s; while (h--) { dd[0] = ss[0]; @@ -125,99 +107,59 @@ static __inline__ void memmove_4p_col (void *d, void *s, int h, int bpr) /* This expands a 4 bit color into a long for movepl (4 plane) operations. */ -static __inline__ u_long expand4l(u_char c) +static const u32 four2byte[] = { + 0x00000000, 0xff000000, 0x00ff0000, 0xffff0000, + 0x0000ff00, 0xff00ff00, 0x00ffff00, 0xffffff00, + 0x000000ff, 0xff0000ff, 0x00ff00ff, 0xffff00ff, + 0x0000ffff, 0xff00ffff, 0x00ffffff, 0xffffffff +}; + +static __inline__ u32 expand4l(u8 c) { - u_long rv; - -#ifdef __mc68000__ - __asm__ __volatile__ ("lsrb #1,%2\n\t" - "scs %0\n\t" - "lsll #8,%0\n\t" - "lsrb #1,%2\n\t" - "scs %0\n\t" - "lsll #8,%0\n\t" - "lsrb #1,%2\n\t" - "scs %0\n\t" - "lsll #8,%0\n\t" - "lsrb #1,%2\n\t" - "scs %0\n\t" - : "=&d" (rv), "=d" (c) - : "1" (c)); -#endif /* !m68k */ - return(rv); + return four2byte[c]; } + /* This expands a 4 bit color into two longs for two movel operations * (4 planes). */ -static __inline__ void expand4dl(u_char c, u_long *ret1, u_long *ret2) +static const u32 two2word[] = { +#ifndef __LITTLE_ENDIAN + 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff, +#else + 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff, +#endif +}; + +static __inline__ void expand4dl(u8 c, u32 *ret1, u32 *ret2) { - u_long rv1, rv2; - -#ifdef __mc68000__ - __asm__ __volatile__ ("lsrb #1,%3\n\t" - "scs %0\n\t" - "extw %0\n\t" - "swap %0\n\t" - "lsrb #1,%3\n\t" - "scs %0\n\t" - "extw %0\n\t" - "lsrb #1,%3\n\t" - "scs %1\n\t" - "extw %1\n\t" - "swap %1\n\t" - "lsrb #1,%3\n\t" - "scs %1\n\t" - "extw %1" - : "=&d" (rv1), "=&d" (rv2), "=d" (c) - : "2" (c)); -#endif /* !m68k */ - *ret1 = rv1; - *ret2 = rv2; + *ret1 = two2word[c & 3]; + *ret2 = two2word[c >> 2]; } /* This duplicates a byte 4 times into a long. */ -static __inline__ u_long dup4l(u_char c) +static __inline__ u32 dup4l(u8 c) { - ushort tmp; - ulong rv; - -#ifdef __mc68000__ - __asm__ __volatile__ ("moveb %2,%0\n\t" - "lslw #8,%0\n\t" - "moveb %2,%0\n\t" - "movew %0,%1\n\t" - "swap %0\n\t" - "movew %1,%0" - : "=&d" (rv), "=d" (tmp) - : "d" (c)); -#endif /* !m68k */ - return(rv); + u32 rv; + + rv = c; + rv |= rv << 8; + rv |= rv << 16; + return rv; } -static int open_iplan2p4(struct display *p) +void fbcon_iplan2p4_setup(struct display *p) { - if (p->type != FB_TYPE_INTERLEAVED_PLANES || p->type_aux != 2 || - p->var.bits_per_pixel != 4) - return -EINVAL; - p->next_line = p->var.xres_virtual>>1; p->next_plane = 2; - MOD_INC_USE_COUNT; - return 0; } -static void release_iplan2p4(void) -{ - MOD_DEC_USE_COUNT; -} - -static void bmove_iplan2p4(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) +void fbcon_iplan2p4_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) { /* bmove() has to distinguish two major cases: If both, source and * destination, start at even addresses or both are at odd @@ -231,7 +173,7 @@ static void bmove_iplan2p4(struct display *p, int sy, int sx, int dy, int dx, * all movements by memmove_col(). */ - if (sx == 0 && dx == 0 && width == p->next_line/4) { + if (sx == 0 && dx == 0 && width * 4 == p->next_line) { /* Special (but often used) case: Moving whole lines can be *done with memmove() */ @@ -240,8 +182,8 @@ static void bmove_iplan2p4(struct display *p, int sy, int sx, int dy, int dx, p->next_line * height * p->fontheight); } else { int rows, cols; - u_char *src; - u_char *dst; + u8 *src; + u8 *dst; int bytes = p->next_line; int linesize = bytes * p->fontheight; u_int colsize = height * p->fontheight; @@ -320,20 +262,20 @@ static void bmove_iplan2p4(struct display *p, int sy, int sx, int dy, int dx, } } -static void clear_iplan2p4(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width) +void fbcon_iplan2p4_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width) { - ulong offset; - u_char *start; + u32 offset; + u8 *start; int rows; int bytes = p->next_line; int lines = height * p->fontheight; - ulong size; - u_long cval1, cval2, pcval; + u32 size; + u32 cval1, cval2, pcval; expand4dl(attr_bgcol_ec(p,conp), &cval1, &cval2); - if (sx == 0 && width == bytes/4) { + if (sx == 0 && width * 4 == bytes) { offset = sy * bytes * p->fontheight; size = lines * bytes; memset_even_4p(p->screen_base+offset, size, cval1, cval2); @@ -365,14 +307,14 @@ static void clear_iplan2p4(struct vc_data *conp, struct display *p, int sy, } } -static void putc_iplan2p4(struct vc_data *conp, struct display *p, int c, - int yy, int xx) +void fbcon_iplan2p4_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx) { - u_char *dest; - u_char *cdat; + u8 *dest; + u8 *cdat; int rows; int bytes = p->next_line; - ulong eorx, fgx, bgx, fdx; + u32 eorx, fgx, bgx, fdx; c &= 0xff; @@ -385,22 +327,18 @@ static void putc_iplan2p4(struct vc_data *conp, struct display *p, int c, for(rows = p->fontheight ; rows-- ; dest += bytes) { fdx = dup4l(*cdat++); -#ifdef __mc68000__ - __asm__ __volatile__ ("movepl %1,%0@(0)" - : /* no outputs */ - : "a" (dest), "d" ((fdx & eorx) ^ bgx)); -#endif /* !m68k */ + movepl(dest, (fdx & eorx) ^ bgx); } } -static void putcs_iplan2p4(struct vc_data *conp, struct display *p, - const char *s, int count, int yy, int xx) +void fbcon_iplan2p4_putcs(struct vc_data *conp, struct display *p, + const char *s, int count, int yy, int xx) { - u_char *dest, *dest0; - u_char *cdat, c; + u8 *dest, *dest0; + u8 *cdat, c; int rows; int bytes; - ulong eorx, fgx, bgx, fdx; + u32 eorx, fgx, bgx, fdx; bytes = p->next_line; dest0 = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*8 + (xx & 1); @@ -421,19 +359,15 @@ static void putcs_iplan2p4(struct vc_data *conp, struct display *p, for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) { fdx = dup4l(*cdat++); -#ifdef __mc68000__ - __asm__ __volatile__ ("movepl %1,%0@(0)" - : /* no outputs */ - : "a" (dest), "d" ((fdx & eorx) ^ bgx)); -#endif /* !m68k */ + movepl(dest, (fdx & eorx) ^ bgx); } INC_4P(dest0); } } -static void rev_char_iplan2p4(struct display *p, int xx, int yy) +void fbcon_iplan2p4_revc(struct display *p, int xx, int yy) { - u_char *dest; + u8 *dest; int j; int bytes; @@ -456,18 +390,24 @@ static void rev_char_iplan2p4(struct display *p, int xx, int yy) } -#ifdef MODULE -int init_module(void) -#else -int fbcon_init_iplan2p4(void) -#endif -{ - return(fbcon_register_driver(&dispsw_iplan2p4, 0)); -} + /* + * `switch' for the low level operations + */ -#ifdef MODULE -void cleanup_module(void) -{ - fbcon_unregister_driver(&dispsw_iplan2p4); -} -#endif /* MODULE */ +struct display_switch fbcon_iplan2p4 = { + fbcon_iplan2p4_setup, fbcon_iplan2p4_bmove, fbcon_iplan2p4_clear, + fbcon_iplan2p4_putc, fbcon_iplan2p4_putcs, fbcon_iplan2p4_revc +}; + + + /* + * Visible symbols for modules + */ + +EXPORT_SYMBOL(fbcon_iplan2p4); +EXPORT_SYMBOL(fbcon_iplan2p4_setup); +EXPORT_SYMBOL(fbcon_iplan2p4_bmove); +EXPORT_SYMBOL(fbcon_iplan2p4_clear); +EXPORT_SYMBOL(fbcon_iplan2p4_putc); +EXPORT_SYMBOL(fbcon_iplan2p4_putcs); +EXPORT_SYMBOL(fbcon_iplan2p4_revc); diff --git a/drivers/video/fbcon-iplan2p4.h b/drivers/video/fbcon-iplan2p4.h new file mode 100644 index 000000000..ae3b38494 --- /dev/null +++ b/drivers/video/fbcon-iplan2p4.h @@ -0,0 +1,15 @@ + /* + * Atari interleaved bitplanes (4 planes) (iplan2p4) + */ + +extern struct display_switch fbcon_iplan2p4; +extern void fbcon_iplan2p4_setup(struct display *p); +extern void fbcon_iplan2p4_bmove(struct display *p, int sy, int sx, int dy, + int dx, int height, int width); +extern void fbcon_iplan2p4_clear(struct vc_data *conp, struct display *p, + int sy, int sx, int height, int width); +extern void fbcon_iplan2p4_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx); +extern void fbcon_iplan2p4_putcs(struct vc_data *conp, struct display *p, + const char *s, int count, int yy, int xx); +extern void fbcon_iplan2p4_revc(struct display *p, int xx, int yy); diff --git a/drivers/video/fbcon-iplan2p8.c b/drivers/video/fbcon-iplan2p8.c index 78f2f2e0e..5ea15c26b 100644 --- a/drivers/video/fbcon-iplan2p8.c +++ b/drivers/video/fbcon-iplan2p8.c @@ -14,41 +14,13 @@ #include <linux/tty.h> #include <linux/console.h> #include <linux/string.h> +#include <linux/config.h> #include <linux/fb.h> -#include "fbcon.h" - - -#ifndef __mc68000__ -#error No support for non-m68k yet -#endif - - - /* - * Prototypes - */ - -static int open_iplan2p8(struct display *p); -static void release_iplan2p8(void); -static void bmove_iplan2p8(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -static void clear_iplan2p8(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width); -static void putc_iplan2p8(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -static void putcs_iplan2p8(struct vc_data *conp, struct display *p, - const char *s, int count, int yy, int xx); -static void rev_char_iplan2p8(struct display *display, int xx, int yy); - - - /* - * `switch' for the low level operations - */ +#include <asm/byteorder.h> -static struct display_switch dispsw_iplan2p8 = { - open_iplan2p8, release_iplan2p8, bmove_iplan2p8, clear_iplan2p8, - putc_iplan2p8, putcs_iplan2p8, rev_char_iplan2p8 -}; +#include "fbcon.h" +#include "fbcon-iplan2p8.h" /* @@ -65,9 +37,26 @@ static struct display_switch dispsw_iplan2p8 = { #define INC_8P(p) do { if (!((long)(++(p)) & 1)) (p) += 14; } while(0) #define DEC_8P(p) do { if ((long)(--(p)) & 1) (p) -= 14; } while(0) +/* Perform the m68k movepl operation extended to 64 bits. */ +static inline void movepl2(u8 *d, u32 val1, u32 val2) +{ +#if defined __mc68000__ && !defined CONFIG_OPTIMIZE_060 + asm volatile ("movepl %1,%0@(0); movepl %2,%0@(8)" + : : "a" (d), "d" (val1), "d" (val2)); +#else + d[0] = (val1 >> 24) & 0xff; + d[2] = (val1 >> 16) & 0xff; + d[4] = (val1 >> 8) & 0xff; + d[6] = val1 & 0xff; + d[8] = (val2 >> 24) & 0xff; + d[10] = (val2 >> 16) & 0xff; + d[12] = (val2 >> 8) & 0xff; + d[14] = val2 & 0xff; +#endif +} /* Sets the bytes in the visible column at d, height h, to the value - * val1,val2 for a 8 plane screen. The the bis of the color in 'color' are + * val1,val2 for a 8 plane screen. The bits of the color in 'color' are * moved (8 times) to the respective bytes. This means: * * for(h times; d += bpr) @@ -81,18 +70,14 @@ static struct display_switch dispsw_iplan2p8 = { * *(d+14) = (color & 128) ? 0xff : 0; */ -static __inline__ void memclear_8p_col(void *d, size_t h, u_long val1, - u_long val2, int bpr) +static __inline__ void memclear_8p_col(void *d, size_t h, u32 val1, + u32 val2, int bpr) { -#ifdef __mc68000__ - __asm__ __volatile__ ("1: movepl %4,%0@(0)\n\t" - "movepl %5,%0@(8)\n\t" - "addal %6,%0\n\t" - "dbra %1,1b" - : "=a" (d), "=d" (h) - : "0" (d), "1" (h - 1), "d" (val1), "d" (val2), - "r" (bpr)); -#endif /* !m68k */ + u8 *dd = d; + do { + movepl2(dd, val1, val2); + dd += bpr; + } while (--h); } /* Sets a 8 plane region from 'd', length 'count' bytes, to the color @@ -110,10 +95,10 @@ static __inline__ void memclear_8p_col(void *d, size_t h, u_long val1, * *(d+14) = *(d+15) = (color & 128) ? 0xff : 0; */ -static __inline__ void memset_even_8p(void *d, size_t count, u_long val1, - u_long val2, u_long val3, u_long val4) +static __inline__ void memset_even_8p(void *d, size_t count, u32 val1, + u32 val2, u32 val3, u32 val4) { - u_long *dd = d; + u32 *dd = d; count /= 16; while (count--) { @@ -128,7 +113,7 @@ static __inline__ void memset_even_8p(void *d, size_t count, u_long val1, static __inline__ void memmove_8p_col (void *d, void *s, int h, int bpr) { - u_char *dd = d, *ss = s; + u8 *dd = d, *ss = s; while (h--) { dd[0] = ss[0]; @@ -149,124 +134,64 @@ static __inline__ void memmove_8p_col (void *d, void *s, int h, int bpr) * operations. */ -static __inline__ void expand8dl(u_char c, u_long *ret1, u_long *ret2) +static const u32 four2long[] = +{ + 0x00000000, 0xff000000, 0x00ff0000, 0xffff0000, + 0x0000ff00, 0xff00ff00, 0x00ffff00, 0xffffff00, + 0x000000ff, 0xff0000ff, 0x00ff00ff, 0xffff00ff, + 0x0000ffff, 0xff00ffff, 0x00ffffff, 0xffffffff, +}; + +static __inline__ void expand8dl(u8 c, u32 *ret1, u32 *ret2) { - u_long rv1, rv2; - -#ifdef __mc68000__ - __asm__ __volatile__ ("lsrb #1,%3\n\t" - "scs %0\n\t" - "lsll #8,%0\n\t" - "lsrb #1,%3\n\t" - "scs %0\n\t" - "lsll #8,%0\n\t" - "lsrb #1,%3\n\t" - "scs %0\n\t" - "lsll #8,%0\n\t" - "lsrb #1,%3\n\t" - "scs %0\n\t" - "lsrb #1,%3\n\t" - "scs %1\n\t" - "lsll #8,%1\n\t" - "lsrb #1,%3\n\t" - "scs %1\n\t" - "lsll #8,%1\n\t" - "lsrb #1,%3\n\t" - "scs %1\n\t" - "lsll #8,%1\n\t" - "lsrb #1,%3\n\t" - "scs %1" - : "=&d" (rv1), "=&d" (rv2),"=d" (c) - : "2" (c)); -#endif /* !m68k */ - *ret1 = rv1; - *ret2 = rv2; + *ret1 = four2long[c & 15]; + *ret2 = four2long[c >> 4]; } + /* This expands a 8 bit color into four longs for four movel operations * (8 planes). */ -#ifdef __mc68000__ -/* ++andreas: use macro to avoid taking address of return values */ -#define expand8ql(c, rv1, rv2, rv3, rv4) \ - do { \ - u_char tmp = c; \ - __asm__ __volatile__ ("lsrb #1,%5\n\t" \ - "scs %0\n\t" \ - "extw %0\n\t" \ - "swap %0\n\t" \ - "lsrb #1,%5\n\t" \ - "scs %0\n\t" \ - "extw %0\n\t" \ - "lsrb #1,%5\n\t" \ - "scs %1\n\t" \ - "extw %1\n\t" \ - "swap %1\n\t" \ - "lsrb #1,%5\n\t" \ - "scs %1\n\t" \ - "extw %1\n\t" \ - "lsrb #1,%5\n\t" \ - "scs %2\n\t" \ - "extw %2\n\t" \ - "swap %2\n\t" \ - "lsrb #1,%5\n\t" \ - "scs %2\n\t" \ - "extw %2\n\t" \ - "lsrb #1,%5\n\t" \ - "scs %3\n\t" \ - "extw %3\n\t" \ - "swap %3\n\t" \ - "lsrb #1,%5\n\t" \ - "scs %3\n\t" \ - "extw %3" \ - : "=&d" (rv1), "=&d" (rv2), "=&d" (rv3), \ - "=&d" (rv4), "=d" (tmp) \ - : "4" (tmp)); \ - } while (0) -#endif /* !m68k */ +static const u32 two2word[] = +{ +#ifndef __LITTLE_ENDIAN + 0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff +#else + 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff +#endif +}; + +static inline void expand8ql(u8 c, u32 *rv1, u32 *rv2, u32 *rv3, u32 *rv4) +{ + *rv1 = two2word[c & 4]; + *rv2 = two2word[(c >> 2) & 4]; + *rv3 = two2word[(c >> 4) & 4]; + *rv4 = two2word[c >> 6]; +} /* This duplicates a byte 4 times into a long. */ -static __inline__ u_long dup4l(u_char c) +static __inline__ u32 dup4l(u8 c) { - ushort tmp; - ulong rv; - -#ifdef __mc68000__ - __asm__ __volatile__ ("moveb %2,%0\n\t" - "lslw #8,%0\n\t" - "moveb %2,%0\n\t" - "movew %0,%1\n\t" - "swap %0\n\t" - "movew %1,%0" - : "=&d" (rv), "=d" (tmp) - : "d" (c)); -#endif /* !m68k */ - return(rv); + u32 rv; + + rv = c; + rv |= rv << 8; + rv |= rv << 16; + return rv; } -static int open_iplan2p8(struct display *p) +void fbcon_iplan2p8_setup(struct display *p) { - if (p->type != FB_TYPE_INTERLEAVED_PLANES || p->type_aux != 2 || - p->var.bits_per_pixel != 8) - return -EINVAL; - p->next_line = p->var.xres_virtual; p->next_plane = 2; - MOD_INC_USE_COUNT; - return 0; -} - -static void release_iplan2p8(void) -{ - MOD_DEC_USE_COUNT; } -static void bmove_iplan2p8(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) +void fbcon_iplan2p8_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) { /* bmove() has to distinguish two major cases: If both, source and * destination, start at even addresses or both are at odd @@ -280,7 +205,7 @@ static void bmove_iplan2p8(struct display *p, int sy, int sx, int dy, int dx, * all movements by memmove_col(). */ - if (sx == 0 && dx == 0 && width == p->next_line/8) { + if (sx == 0 && dx == 0 && width * 8 == p->next_line) { /* Special (but often used) case: Moving whole lines can be * done with memmove() */ @@ -289,8 +214,8 @@ static void bmove_iplan2p8(struct display *p, int sy, int sx, int dy, int dx, p->next_line * height * p->fontheight); } else { int rows, cols; - u_char *src; - u_char *dst; + u8 *src; + u8 *dst; int bytes = p->next_line; int linesize = bytes * p->fontheight; u_int colsize = height * p->fontheight; @@ -369,20 +294,20 @@ static void bmove_iplan2p8(struct display *p, int sy, int sx, int dy, int dx, } } -static void clear_iplan2p8(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width) +void fbcon_iplan2p8_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width) { - ulong offset; - u_char *start; + u32 offset; + u8 *start; int rows; int bytes = p->next_line; int lines = height * p->fontheight; - ulong size; - u_long cval1, cval2, cval3, cval4, pcval1, pcval2; + u32 size; + u32 cval1, cval2, cval3, cval4, pcval1, pcval2; - expand8ql(attr_bgcol_ec(p,conp), cval1, cval2, cval3, cval4); + expand8ql(attr_bgcol_ec(p,conp), &cval1, &cval2, &cval3, &cval4); - if (sx == 0 && width == bytes/8) { + if (sx == 0 && width * 8 == bytes) { offset = sy * bytes * p->fontheight; size = lines * bytes; memset_even_8p(p->screen_base+offset, size, cval1, cval2, cval3, cval4); @@ -414,14 +339,14 @@ static void clear_iplan2p8(struct vc_data *conp, struct display *p, int sy, } } -static void putc_iplan2p8(struct vc_data *conp, struct display *p, int c, - int yy, int xx) +void fbcon_iplan2p8_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx) { - u_char *dest; - u_char *cdat; + u8 *dest; + u8 *cdat; int rows; int bytes = p->next_line; - ulong eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx; + u32 eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx; c &= 0xff; @@ -434,24 +359,18 @@ static void putc_iplan2p8(struct vc_data *conp, struct display *p, int c, for(rows = p->fontheight ; rows-- ; dest += bytes) { fdx = dup4l(*cdat++); -#ifdef __mc68000__ - __asm__ __volatile__ ("movepl %1,%0@(0)\n\t" - "movepl %2,%0@(8)" - : /* no outputs */ - : "a" (dest), "d" ((fdx & eorx1) ^ bgx1), - "d" ((fdx & eorx2) ^ bgx2) ); -#endif /* !m68k */ + movepl2(dest, (fdx & eorx1) ^ bgx1, (fdx & eorx2) ^ bgx2); } } -static void putcs_iplan2p8(struct vc_data *conp, struct display *p, - const char *s, int count, int yy, int xx) +void fbcon_iplan2p8_putcs(struct vc_data *conp, struct display *p, + const char *s, int count, int yy, int xx) { - u_char *dest, *dest0; - u_char *cdat, c; + u8 *dest, *dest0; + u8 *cdat, c; int rows; int bytes; - ulong eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx; + u32 eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx; bytes = p->next_line; dest0 = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*16 + @@ -475,21 +394,15 @@ static void putcs_iplan2p8(struct vc_data *conp, struct display *p, for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) { fdx = dup4l(*cdat++); -#ifdef __mc68000__ - __asm__ __volatile__ ("movepl %1,%0@(0)\n\t" - "movepl %2,%0@(8)" - : /* no outputs */ - : "a" (dest), "d" ((fdx & eorx1) ^ bgx1), - "d" ((fdx & eorx2) ^ bgx2)); -#endif /* !m68k */ + movepl2(dest, (fdx & eorx1) ^ bgx1, (fdx & eorx2) ^ bgx2); } INC_8P(dest0); } } -static void rev_char_iplan2p8(struct display *p, int xx, int yy) +void fbcon_iplan2p8_revc(struct display *p, int xx, int yy) { - u_char *dest; + u8 *dest; int j; int bytes; @@ -502,7 +415,7 @@ static void rev_char_iplan2p8(struct display *p, int xx, int yy) /* This should really obey the individual character's * background and foreground colors instead of simply * inverting. For 8 plane mode, only the lower 4 bits of the - * color are inverted, because only that color registers have + * color are inverted, because only these color registers have * been set up. */ dest[0] = ~dest[0]; @@ -514,18 +427,24 @@ static void rev_char_iplan2p8(struct display *p, int xx, int yy) } -#ifdef MODULE -int init_module(void) -#else -int fbcon_init_iplan2p8(void) -#endif -{ - return(fbcon_register_driver(&dispsw_iplan2p8, 0)); -} + /* + * `switch' for the low level operations + */ -#ifdef MODULE -void cleanup_module(void) -{ - fbcon_unregister_driver(&dispsw_iplan2p8); -} -#endif /* MODULE */ +struct display_switch fbcon_iplan2p8 = { + fbcon_iplan2p8_setup, fbcon_iplan2p8_bmove, fbcon_iplan2p8_clear, + fbcon_iplan2p8_putc, fbcon_iplan2p8_putcs, fbcon_iplan2p8_revc +}; + + + /* + * Visible symbols for modules + */ + +EXPORT_SYMBOL(fbcon_iplan2p8); +EXPORT_SYMBOL(fbcon_iplan2p8_setup); +EXPORT_SYMBOL(fbcon_iplan2p8_bmove); +EXPORT_SYMBOL(fbcon_iplan2p8_clear); +EXPORT_SYMBOL(fbcon_iplan2p8_putc); +EXPORT_SYMBOL(fbcon_iplan2p8_putcs); +EXPORT_SYMBOL(fbcon_iplan2p8_revc); diff --git a/drivers/video/fbcon-iplan2p8.h b/drivers/video/fbcon-iplan2p8.h new file mode 100644 index 000000000..f2c46e229 --- /dev/null +++ b/drivers/video/fbcon-iplan2p8.h @@ -0,0 +1,15 @@ + /* + * Atari interleaved bitplanes (8 planes) (iplan2p8) + */ + +extern struct display_switch fbcon_iplan2p8; +extern void fbcon_iplan2p8_setup(struct display *p); +extern void fbcon_iplan2p8_bmove(struct display *p, int sy, int sx, int dy, + int dx, int height, int width); +extern void fbcon_iplan2p8_clear(struct vc_data *conp, struct display *p, + int sy, int sx, int height, int width); +extern void fbcon_iplan2p8_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx); +extern void fbcon_iplan2p8_putcs(struct vc_data *conp, struct display *p, + const char *s, int count, int yy, int xx); +extern void fbcon_iplan2p8_revc(struct display *p, int xx, int yy); diff --git a/drivers/video/fbcon-mac.c b/drivers/video/fbcon-mac.c new file mode 100644 index 000000000..1dd5f1988 --- /dev/null +++ b/drivers/video/fbcon-mac.c @@ -0,0 +1,513 @@ +/* + * linux/drivers/video/fbcon-mac.c -- Low level frame buffer operations for + * x bpp packed pixels, font width != 8 + * + * Created 26 Dec 1997 by Michael Schmitz + * Based on the old macfb.c 6x11 code by Randy Thelen + * + * This driver is significantly slower than the 8bit font drivers + * and would probably benefit from splitting into drivers for each depth. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + */ + +#include <linux/module.h> +#include <linux/tty.h> +#include <linux/console.h> +#include <linux/string.h> +#include <linux/config.h> +#include <linux/fb.h> +#include <linux/delay.h> + +#include "fbcon.h" +#include "fbcon-mac.h" + + + /* + * variable bpp packed pixels + */ + +static void plot_pixel_mac(struct display *p, int bw, int pixel_x, + int pixel_y); +static int get_pixel_mac(struct display *p, int pixel_x, int pixel_y); + +void fbcon_mac_setup(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; +} + + + /* + * Macintosh + */ +#define PIXEL_BLACK_MAC 0 +#define PIXEL_WHITE_MAC 1 +#define PIXEL_INVERT_MAC 2 + +void fbcon_mac_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) +{ + int i, j; + u8 *dest, *src; + int l,r,t,b,w,lo,s; + int dl,dr,dt,db,dw,dlo; + int move_up; + + src = (u8 *) (p->screen_base + sy * p->fontheight * p->next_line); + dest = (u8 *) (p->screen_base + dy * p->fontheight * p->next_line); + + if( sx == 0 && width == p->conp->vc_cols) { + s = height * p->fontheight * p->next_line; + mymemmove(dest, src, s); + return; + } + + l = sx * p->fontwidth; + r = l + width * p->fontwidth; + t = sy * p->fontheight; + b = t + height * p->fontheight; + + dl = dx * p->fontwidth; + dr = dl + width * p->fontwidth; + dt = dy * p->fontheight; + db = dt + height * p->fontheight; + + /* w is the # pixels between two long-aligned points, left and right */ + w = (r&~31) - ((l+31)&~31); + dw = (dr&~31) - ((dl+31)&~31); + /* lo is the # pixels between the left edge and a long-aligned left pixel */ + lo = ((l+31)&~31) - l; + dlo = ((dl+31)&~31) - dl; + + /* if dx != sx then, logic has to align the left and right edges for fast moves */ + if (lo != dlo) { + lo = ((l+7)&~7) - l; + dlo = ((dl+7)&~7) - dl; + w = (r&~7) - ((l+7)&~7); + dw = (dr&~7) - ((dl+7)&~7); + if (lo != dlo) { + char err_str[256]; + unsigned long cnt; + sprintf( err_str, "ERROR: Shift algorithm: sx=%d,sy=%d,dx=%d,dy=%d,w=%d,h=%d,bpp=%d", + sx,sy,dx,dy,width,height,p->var.bits_per_pixel); + fbcon_mac_putcs(p->conp, p, err_str, strlen(err_str), 0, 0); + /* pause for the user */ + for(cnt = 0; cnt < 50000; cnt++) + udelay(100); + return; + } + } + + s = 0; + switch (p->var.bits_per_pixel) { + case 1: + s = w >> 3; + src += lo >> 3; + dest += lo >> 3; + break; + case 2: + s = w >> 2; + src += lo >> 2; + dest += lo >> 2; + break; + case 4: + s = w >> 1; + src += lo >> 1; + dest += lo >> 1; + break; + case 8: + s = w; + src += lo; + dest += lo; + break; + case 16: + s = w << 1; + src += lo << 1; + dest += lo << 1; + break; + case 32: + s = w << 2; + src += lo << 2; + dest += lo << 2; + break; + } + + if (sy <= sx) { + i = b; + move_up = 0; + src += height * p->fontheight; + dest += height * p->fontheight; + } else { + i = t; + move_up = 1; + } + + while (1) { + for (i = t; i < b; i++) { + j = l; + + for (; j & 31 && j < r; j++) + plot_pixel_mac(p, get_pixel_mac(p, j+(dx-sx), i+(dy-sy)), j, i); + + if (j < r) { + mymemmove(dest, src, s); + if (move_up) { + dest += p->next_line; + src += p->next_line; + } else { + dest -= p->next_line; + src -= p->next_line; + } + j += w; + } + + for (; j < r; j++) + plot_pixel_mac(p, get_pixel_mac(p, j+(dx-sx), i+(dy-sy)), j, i); + } + + if (move_up) { + i++; + if (i >= b) + break; + } else { + i--; + if (i < t) + break; + } + } +} + + +void fbcon_mac_clear(struct vc_data *conp, struct display *p, int sy, int sx, + int height, int width) +{ + int pixel; + int i, j; + int inverse; + u8 *dest; + int l,r,t,b,w,lo,s; + + inverse = attr_reverse(p,conp); + pixel = inverse ? PIXEL_WHITE_MAC : PIXEL_BLACK_MAC; + dest = (u8 *) (p->screen_base + sy * p->fontheight * p->next_line); + + if( sx == 0 && width == p->conp->vc_cols) { + s = height * p->fontheight * p->next_line; + if (inverse) + mymemclear(dest, s); + else + mymemset(dest, s); + } + + l = sx * p->fontwidth; + r = l + width * p->fontwidth; + t = sy * p->fontheight; + b = t + height * p->fontheight; + /* w is the # pixels between two long-aligned points, left and right */ + w = (r&~31) - ((l+31)&~31); + /* lo is the # pixels between the left edge and a long-aligned left pixel */ + lo = ((l+31)&~31) - l; + s = 0; + switch (p->var.bits_per_pixel) { + case 1: + s = w >> 3; + dest += lo >> 3; + break; + case 2: + s = w >> 2; + dest += lo >> 2; + break; + case 4: + s = w >> 1; + dest += lo >> 1; + break; + case 8: + s = w; + dest += lo; + break; + case 16: + s = w << 1; + dest += lo << 1; + break; + case 32: + s = w << 2; + dest += lo << 2; + break; + } + + for (i = t; i < b; i++) { + j = l; + + for (; j & 31 && j < r; j++) + plot_pixel_mac(p, pixel, j, i); + + if (j < r) { + if (PIXEL_WHITE_MAC == pixel) + mymemclear(dest, s); + else + mymemset(dest, s); + dest += p->next_line; + j += w; + } + + for (; j < r; j++) + plot_pixel_mac(p, pixel, j, i); + } +} + + +void fbcon_mac_putc(struct vc_data *conp, struct display *p, int c, int yy, + int xx) +{ + u8 *cdat; + u_int rows, bold, ch_reverse, ch_underline; + u8 d; + int j; + + c &= 0xff; + + cdat = p->fontdata+c*p->fontheight; + bold = attr_bold(p,conp); + ch_reverse = attr_reverse(p,conp); + ch_underline = attr_underline(p,conp); + + for (rows = 0; rows < p->fontheight; rows++) { + d = *cdat++; + if (!conp->vc_can_do_color) { + if (ch_underline && rows == (p->fontheight-2)) + d = 0xff; + else if (bold) + d |= d>>1; + if (ch_reverse) + d = ~d; + } + for (j = 0; j < p->fontwidth; j++) { + plot_pixel_mac(p, (d & 0x80) >> 7, (xx*p->fontwidth) + j, (yy*p->fontheight) + rows); + d <<= 1; + } + } +} + + +void fbcon_mac_putcs(struct vc_data *conp, struct display *p, const char *s, + int count, int yy, int xx) +{ + u8 c; + + while (count--) { + c = *s++; + fbcon_mac_putc(conp, p, c, yy, xx++); + } +} + + +void fbcon_mac_revc(struct display *p, int xx, int yy) +{ + u_int rows, j; + + for (rows = 0; rows < p->fontheight; rows++) { + for (j = 0; j < p->fontwidth; j++) { + plot_pixel_mac (p, PIXEL_INVERT_MAC, (xx*p->fontwidth)+j, (yy*p->fontheight)+rows); + } + } +} + +/* + * plot_pixel_mac + * + * bw == 0 = black + * 1 = white + * 2 = invert + */ +static void plot_pixel_mac(struct display *p, int bw, int pixel_x, int pixel_y) +{ + u8 *dest, bit; + u16 *dest16, pix16; + u32 *dest32, pix32; + + if (pixel_x < 0 || pixel_y < 0 || pixel_x >= 832 || pixel_y >= 624) { + int cnt; + printk ("ERROR: pixel_x == %d, pixel_y == %d", pixel_x, pixel_y); + for(cnt = 0; cnt < 100000; cnt++) + udelay(100); + return; + } + + switch (p->var.bits_per_pixel) { + case 1: + dest = (u8 *) ((pixel_x >> 3) + p->screen_base + pixel_y * p->next_line); + bit = 0x80 >> (pixel_x & 7); + switch (bw) { + case PIXEL_BLACK_MAC: + *dest |= bit; + break; + case PIXEL_WHITE_MAC: + *dest &= ~bit; + break; + case PIXEL_INVERT_MAC: + *dest ^= bit; + break; + default: + printk( "ERROR: Unknown pixel value in plot_pixel_mac\n"); + } + break; + + case 2: + dest = (u8 *) ((pixel_x >> 2) + p->screen_base + pixel_y * p->next_line); + bit = 0xC0 >> ((pixel_x & 3) << 1); + switch (bw) { + case PIXEL_BLACK_MAC: + *dest |= bit; + break; + case PIXEL_WHITE_MAC: + *dest &= ~bit; + break; + case PIXEL_INVERT_MAC: + *dest ^= bit; + break; + default: + printk( "ERROR: Unknown pixel value in plot_pixel_mac\n"); + } + break; + + case 4: + dest = (u8 *) ((pixel_x / 2) + p->screen_base + pixel_y * p->next_line); + bit = 0xF0 >> ((pixel_x & 1) << 2); + switch (bw) { + case PIXEL_BLACK_MAC: + *dest |= bit; + break; + case PIXEL_WHITE_MAC: + *dest &= ~bit; + break; + case PIXEL_INVERT_MAC: + *dest ^= bit; + break; + default: + printk( "ERROR: Unknown pixel value in plot_pixel_mac\n"); + } + break; + + case 8: + dest = (u8 *) (pixel_x + p->screen_base + pixel_y * p->next_line); + bit = 0xFF; + switch (bw) { + case PIXEL_BLACK_MAC: + *dest |= bit; + break; + case PIXEL_WHITE_MAC: + *dest &= ~bit; + break; + case PIXEL_INVERT_MAC: + *dest ^= bit; + break; + default: + printk( "ERROR: Unknown pixel value in plot_pixel_mac\n"); + } + break; + + case 16: + dest16 = (u16 *) ((pixel_x *2) + p->screen_base + pixel_y * p->next_line); + pix16 = 0xFFFF; + switch (bw) { + case PIXEL_BLACK_MAC: + *dest16 = ~pix16; + break; + case PIXEL_WHITE_MAC: + *dest16 = pix16; + break; + case PIXEL_INVERT_MAC: + *dest16 ^= pix16; + break; + default: + printk( "ERROR: Unknown pixel value in plot_pixel_mac\n"); + } + break; + + case 32: + dest32 = (u32 *) ((pixel_x *4) + p->screen_base + pixel_y * p->next_line); + pix32 = 0xFFFFFFFF; + switch (bw) { + case PIXEL_BLACK_MAC: + *dest32 = ~pix32; + break; + case PIXEL_WHITE_MAC: + *dest32 = pix32; + break; + case PIXEL_INVERT_MAC: + *dest32 ^= pix32; + break; + default: + printk( "ERROR: Unknown pixel value in plot_pixel_mac\n"); + } + break; + } +} + +static int get_pixel_mac(struct display *p, int pixel_x, int pixel_y) +{ + u8 *dest, bit; + u16 *dest16; + u32 *dest32; + u8 pixel; + + switch (p->var.bits_per_pixel) { + case 1: + dest = (u8 *) ((pixel_x / 8) + p->screen_base + pixel_y * p->next_line); + bit = 0x80 >> (pixel_x & 7); + pixel = *dest & bit; + break; + case 2: + dest = (u8 *) ((pixel_x / 4) + p->screen_base + pixel_y * p->next_line); + bit = 0xC0 >> (pixel_x & 3); + pixel = *dest & bit; + break; + case 4: + dest = (u8 *) ((pixel_x / 2) + p->screen_base + pixel_y * p->next_line); + bit = 0xF0 >> (pixel_x & 1); + pixel = *dest & bit; + break; + case 8: + dest = (u8 *) (pixel_x + p->screen_base + pixel_y * p->next_line); + pixel = *dest; + break; + case 16: + dest16 = (u16 *) ((pixel_x *2) + p->screen_base + pixel_y * p->next_line); + pixel = *dest16 ? 1 : 0; + break; + case 32: + dest32 = (u32 *) ((pixel_x *4) + p->screen_base + pixel_y * p->next_line); + pixel = *dest32 ? 1 : 0; + break; + } + + return pixel ? PIXEL_BLACK_MAC : PIXEL_WHITE_MAC; +} + + + /* + * `switch' for the low level operations + */ + +struct display_switch fbcon_mac = { + fbcon_mac_setup, fbcon_mac_bmove, fbcon_mac_clear, fbcon_mac_putc, + fbcon_mac_putcs, fbcon_mac_revc +}; + + + /* + * Visible symbols for modules + */ + +EXPORT_SYMBOL(fbcon_mac); +EXPORT_SYMBOL(fbcon_mac_setup); +EXPORT_SYMBOL(fbcon_mac_bmove); +EXPORT_SYMBOL(fbcon_mac_clear); +EXPORT_SYMBOL(fbcon_mac_putc); +EXPORT_SYMBOL(fbcon_mac_putcs); +EXPORT_SYMBOL(fbcon_mac_revc); diff --git a/drivers/video/fbcon-mac.h b/drivers/video/fbcon-mac.h new file mode 100644 index 000000000..7e807cce9 --- /dev/null +++ b/drivers/video/fbcon-mac.h @@ -0,0 +1,15 @@ + /* + * Mac variable bpp packed pixels (mac) + */ + +extern struct display_switch fbcon_mac; +extern void fbcon_mac_setup(struct display *p); +extern void fbcon_mac_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width); +extern void fbcon_mac_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width); +extern void fbcon_mac_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx); +extern void fbcon_mac_putcs(struct vc_data *conp, struct display *p, + const char *s, int count, int yy, int xx); +extern void fbcon_mac_revc(struct display *p, int xx, int yy); diff --git a/drivers/video/fbcon-mfb.c b/drivers/video/fbcon-mfb.c index 7ac001ab4..3484cef2a 100644 --- a/drivers/video/fbcon-mfb.c +++ b/drivers/video/fbcon-mfb.c @@ -13,65 +13,30 @@ #include <linux/tty.h> #include <linux/console.h> #include <linux/string.h> +#include <linux/config.h> #include <linux/fb.h> #include "fbcon.h" - - - /* - * Prototypes - */ - -static int open_mfb(struct display *p); -static void release_mfb(void); -static void bmove_mfb(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -static void clear_mfb(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width); -static void putc_mfb(struct vc_data *conp, struct display *p, int c, int yy, - int xx); -static void putcs_mfb(struct vc_data *conp, struct display *p, const char *s, - int count, int yy, int xx); -static void rev_char_mfb(struct display *p, int xx, int yy); - - - /* - * `switch' for the low level operations - */ - -static struct display_switch dispsw_mfb = { - open_mfb, release_mfb, bmove_mfb, clear_mfb, putc_mfb, putcs_mfb, - rev_char_mfb -}; +#include "fbcon-mfb.h" /* * Monochrome */ -static int open_mfb(struct display *p) +void fbcon_mfb_setup(struct display *p) { - if (p->var.bits_per_pixel != 1) - return -EINVAL; - if (p->line_length) p->next_line = p->line_length; else p->next_line = p->var.xres_virtual>>3; p->next_plane = 0; - MOD_INC_USE_COUNT; - return 0; } -static void release_mfb(void) +void fbcon_mfb_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) { - MOD_DEC_USE_COUNT; -} - -static void bmove_mfb(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - u_char *src, *dest; + u8 *src, *dest; u_int rows; if (sx == 0 && dx == 0 && width == p->next_line) { @@ -97,10 +62,10 @@ static void bmove_mfb(struct display *p, int sy, int sx, int dy, int dx, } } -static void clear_mfb(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width) +void fbcon_mfb_clear(struct vc_data *conp, struct display *p, int sy, int sx, + int height, int width) { - u_char *dest; + u8 *dest; u_int rows; dest = p->screen_base+sy*p->fontheight*p->next_line+sx; @@ -118,12 +83,12 @@ static void clear_mfb(struct vc_data *conp, struct display *p, int sy, int sx, mymemclear_small(dest, width); } -static void putc_mfb(struct vc_data *conp, struct display *p, int c, int yy, - int xx) +void fbcon_mfb_putc(struct vc_data *conp, struct display *p, int c, int yy, + int xx) { - u_char *dest, *cdat; + u8 *dest, *cdat; u_int rows, bold, revs, underl; - u_char d; + u8 d; c &= 0xff; @@ -145,12 +110,12 @@ static void putc_mfb(struct vc_data *conp, struct display *p, int c, int yy, } } -static void putcs_mfb(struct vc_data *conp, struct display *p, const char *s, - int count, int yy, int xx) +void fbcon_mfb_putcs(struct vc_data *conp, struct display *p, const char *s, + int count, int yy, int xx) { - u_char *dest, *dest0, *cdat; + u8 *dest, *dest0, *cdat; u_int rows, bold, revs, underl; - u_char c, d; + u8 c, d; dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx; bold = attr_bold(p,conp); @@ -174,9 +139,9 @@ static void putcs_mfb(struct vc_data *conp, struct display *p, const char *s, } } -static void rev_char_mfb(struct display *p, int xx, int yy) +void fbcon_mfb_revc(struct display *p, int xx, int yy) { - u_char *dest; + u8 *dest; u_int rows; dest = p->screen_base+yy*p->fontheight*p->next_line+xx; @@ -185,18 +150,24 @@ static void rev_char_mfb(struct display *p, int xx, int yy) } -#ifdef MODULE -int init_module(void) -#else -int fbcon_init_mfb(void) -#endif -{ - return(fbcon_register_driver(&dispsw_mfb, 0)); -} + /* + * `switch' for the low level operations + */ -#ifdef MODULE -void cleanup_module(void) -{ - fbcon_unregister_driver(&dispsw_mfb); -} -#endif /* MODULE */ +struct display_switch fbcon_mfb = { + fbcon_mfb_setup, fbcon_mfb_bmove, fbcon_mfb_clear, fbcon_mfb_putc, + fbcon_mfb_putcs, fbcon_mfb_revc +}; + + + /* + * Visible symbols for modules + */ + +EXPORT_SYMBOL(fbcon_mfb); +EXPORT_SYMBOL(fbcon_mfb_setup); +EXPORT_SYMBOL(fbcon_mfb_bmove); +EXPORT_SYMBOL(fbcon_mfb_clear); +EXPORT_SYMBOL(fbcon_mfb_putc); +EXPORT_SYMBOL(fbcon_mfb_putcs); +EXPORT_SYMBOL(fbcon_mfb_revc); diff --git a/drivers/video/fbcon-mfb.h b/drivers/video/fbcon-mfb.h new file mode 100644 index 000000000..b67d9f70e --- /dev/null +++ b/drivers/video/fbcon-mfb.h @@ -0,0 +1,15 @@ + /* + * Monochrome (mfb) + */ + +extern struct display_switch fbcon_mfb; +extern void fbcon_mfb_setup(struct display *p); +extern void fbcon_mfb_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width); +extern void fbcon_mfb_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width); +extern void fbcon_mfb_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx); +extern void fbcon_mfb_putcs(struct vc_data *conp, struct display *p, + const char *s, int count, int yy, int xx); +extern void fbcon_mfb_revc(struct display *p, int xx, int yy); diff --git a/drivers/video/fbcon-retz3.c b/drivers/video/fbcon-retz3.c deleted file mode 100644 index 71095a084..000000000 --- a/drivers/video/fbcon-retz3.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * linux/drivers/video/retz3.c -- Low level frame buffer operations for the - * RetinaZ3 (accelerated) - * - * Created 5 Apr 1997 by Geert Uytterhoeven - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - */ - -#include <linux/module.h> -#include <linux/tty.h> -#include <linux/console.h> -#include <linux/string.h> -#include <linux/fb.h> - -#include "fbcon.h" - - -/* - * Prototypes - */ - -static int open_retz3(struct display *p); -static void release_retz3(void); -static void bmove_retz3(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -static void clear_retz3(struct vc_data *conp, struct display *p, int - sy, int sx, int height, int width); -static void putc_retz3(struct vc_data *conp, struct display *p, int c, - int ypos, int xpos); -static void putcs_retz3(struct vc_data *conp, struct display *p, const - char *s, int count, int ypos, int xpos); -static void rev_char_retz3(struct display *p, int xpos, int ypos); - - - /* - * Acceleration functions in retz3fb.c - */ - -extern void retz3_bitblt(struct fb_var_screeninfo *scr, - unsigned short srcx, unsigned short srcy, unsigned - short destx, unsigned short desty, unsigned short - width, unsigned short height, unsigned short cmd, - unsigned short mask); - -#define Z3BLTcopy 0xc0 -#define Z3BLTset 0xf0 - - -/* - * `switch' for the low level operations - */ - -static struct display_switch dispsw_retz3 = { - open_retz3, release_retz3, bmove_retz3, clear_retz3, putc_retz3, - putcs_retz3, rev_char_retz3 -}; - - -/* - * RetinaZ3 (accelerated) - */ - -static int open_retz3(struct display *p) -{ - if (p->type != FB_TYPE_PACKED_PIXELS || - p->var.accel != FB_ACCEL_RETINAZ3) - return -EINVAL; - - p->next_line = p->var.xres_virtual*p->var.bits_per_pixel>>3; - p->next_plane = 0; - MOD_INC_USE_COUNT; - return 0; -} - -static void release_retz3(void) -{ - MOD_DEC_USE_COUNT; -} - -static void bmove_retz3(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) -{ - int fontwidth = p->fontwidth; - - sx *= fontwidth; - dx *= fontwidth; - width *= fontwidth; - - retz3_bitblt(&p->var, - (unsigned short)sx, - (unsigned short)(sy*p->fontheight), - (unsigned short)dx, - (unsigned short)(dy*p->fontheight), - (unsigned short)width, - (unsigned short)(height*p->fontheight), - Z3BLTcopy, - 0xffff); -} - -static void clear_retz3(struct vc_data *conp, struct display *p, int - sy, int sx, int height, int width) -{ - unsigned short col; - int fontwidth = p->fontwidth; - - sx *= fontwidth; - width *= fontwidth; - - col = attr_bgcol_ec(p, conp); - col &= 0xff; - col |= (col << 8); - - retz3_bitblt(&p->var, - (unsigned short)sx, - (unsigned short)(sy*p->fontheight), - (unsigned short)sx, - (unsigned short)(sy*p->fontheight), - (unsigned short)width, - (unsigned short)(height*p->fontheight), - Z3BLTset, - col); -} - -static void putc_retz3(struct vc_data *conp, struct display *p, - int c, int ypos, int xpos) -{ - unsigned char *dest, *cdat; - unsigned long tmp; - unsigned int rows, revs, underl; - unsigned char d; - unsigned char fg, bg; - - c &= 0xff; - - dest = p->screen_base + ypos * p->fontheight * p->next_line + - xpos*p->fontwidth; - cdat = p->fontdata + c * p->fontheight; - - fg = p->fgcol; - bg = p->bgcol; - revs = conp->vc_reverse; - underl = conp->vc_underline; - - for (rows = p->fontheight; rows--; dest += p->next_line) { - d = *cdat++; - - if (underl && !rows) - d = 0xff; - if (revs) - d = ~d; - - tmp = ((d & 0x80) ? fg : bg) << 24; - tmp |= ((d & 0x40) ? fg : bg) << 16; - tmp |= ((d & 0x20) ? fg : bg) << 8; - tmp |= ((d & 0x10) ? fg : bg); - *((unsigned long*) dest) = tmp; - tmp = ((d & 0x8) ? fg : bg) << 24; - tmp |= ((d & 0x4) ? fg : bg) << 16; - tmp |= ((d & 0x2) ? fg : bg) << 8; - tmp |= ((d & 0x1) ? fg : bg); - *((unsigned long*) dest + 1) = tmp; - } -} - -static void putcs_retz3(struct vc_data *conp, struct display *p, - const char *s, int count, int ypos, int xpos) -{ - unsigned char *dest, *dest0, *cdat; - unsigned long tmp; - unsigned int rows, revs, underl; - unsigned char c, d; - unsigned char fg, bg; - - dest0 = p->screen_base + ypos * p->fontheight * p->next_line - + xpos * p->fontwidth; - - fg = p->fgcol; - bg = p->bgcol; - revs = conp->vc_reverse; - underl = conp->vc_underline; - - while (count--) { - c = *s++; - dest = dest0; - dest0 += 8; - - cdat = p->fontdata + c * p->fontheight; - for (rows = p->fontheight; rows--; dest += p->next_line) { - d = *cdat++; - - if (underl && !rows) - d = 0xff; - if (revs) - d = ~d; - - tmp = ((d & 0x80) ? fg : bg) << 24; - tmp |= ((d & 0x40) ? fg : bg) << 16; - tmp |= ((d & 0x20) ? fg : bg) << 8; - tmp |= ((d & 0x10) ? fg : bg); - *((unsigned long*) dest) = tmp; - tmp = ((d & 0x8) ? fg : bg) << 24; - tmp |= ((d & 0x4) ? fg : bg) << 16; - tmp |= ((d & 0x2) ? fg : bg) << 8; - tmp |= ((d & 0x1) ? fg : bg); - *((unsigned long*) dest + 1) = tmp; - } - } -} - -static void rev_char_retz3(struct display *p, int xpos, int ypos) -{ - unsigned char *dest; - int bytes=p->next_line, rows; - unsigned int bpp, mask; - - bpp = p->var.bits_per_pixel; - - switch (bpp){ - case 8: - mask = 0x0f0f0f0f; - break; - case 16: - mask = 0xffffffff; - break; - case 24: - mask = 0xffffffff; /* ??? */ - break; - default: - printk("illegal depth for rev_char_retz3(), bpp = %i\n", bpp); - return; - } - - dest = p->screen_base + ypos * p->fontheight * bytes + - xpos * p->fontwidth; - - for (rows = p->fontheight ; rows-- ; dest += bytes) { - ((unsigned long *)dest)[0] ^= mask; - ((unsigned long *)dest)[1] ^= mask; - } -} - - -#ifdef MODULE -int init_module(void) -#else -int fbcon_init_retz3(void) -#endif -{ - return(fbcon_register_driver(&dispsw_retz3, 1)); -} - -#ifdef MODULE -void cleanup_module(void) -{ - fbcon_unregister_driver(&dispsw_retz3); -} -#endif /* MODULE */ 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); diff --git a/drivers/video/fbcon.h b/drivers/video/fbcon.h index b83376d9e..4868b7730 100644 --- a/drivers/video/fbcon.h +++ b/drivers/video/fbcon.h @@ -8,6 +8,9 @@ * for more details. */ +#ifndef __VIDEO_FBCON_H +#define __VIDEO_FBCON_H + #include <linux/console_struct.h> @@ -16,8 +19,7 @@ */ struct display_switch { - int (*open)(struct display *p); - void (*release)(void); + void (*setup)(struct display *p); void (*bmove)(struct display *p, int sy, int sx, int dy, int dx, int height, int width); void (*clear)(struct vc_data *conp, struct display *p, int sy, int sx, @@ -26,20 +28,11 @@ struct display_switch { int xx); void (*putcs)(struct vc_data *conp, struct display *p, const char *s, int count, int yy, int xx); - void (*rev_char)(struct display *p, int xx, int yy); - struct display_switch *next; + void (*revc)(struct display *p, int xx, int yy); }; /* - * Driver registration - */ - -extern int fbcon_register_driver(struct display_switch *dispsw, int is_accel); -int fbcon_unregister_driver(struct display_switch *dispsw); - - - /* * Attribute Decoding */ @@ -335,3 +328,5 @@ static __inline__ void fast_memmove(char *dst, const char *src, size_t size) } #endif /* !m68k */ + +#endif /* __VIDEO_FBCON_H */ diff --git a/drivers/video/fbgen.c b/drivers/video/fbgen.c new file mode 100644 index 000000000..730438d16 --- /dev/null +++ b/drivers/video/fbgen.c @@ -0,0 +1,386 @@ +/* + * linux/drivers/video/fbgen.c -- Generic routines for frame buffer devices + * + * Created 3 Jan 1998 by Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file README.legal in the main directory of this archive + * for more details. + */ + +#include <linux/module.h> +#include <linux/string.h> +#include <linux/tty.h> +#include <linux/fb.h> +#include <linux/slab.h> + +#include <asm/uaccess.h> + + + +static int currcon = 0; + +static struct display disp; + + + /* + * `Generic' versions of the frame buffer device operations + */ + +extern int fbgen_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info); +extern int fbgen_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +extern int fbgen_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +extern int fbgen_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +extern int fbgen_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +extern int fbgen_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +extern int fbgen_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, int con, + struct fb_info *info); + + + /* + * Helper functions + */ + +int fbgen_do_set_var(struct fb_var_screeninfo *var, int isactive, + struct fb_info_gen *info); +void fbgen_set_disp(int con, struct fb_info_gen *info); +void fbgen_install_cmap(int con, struct fb_info_gen *info); +int fbgen_update_var(int con, struct fb_info *info); +int fbgen_switch(int con, struct fb_info *info); +void fbgen_blank(int blank, struct fb_info *info); + + +/* ---- `Generic' versions of the frame buffer device operations ----------- */ + + + /* + * Get the Fixed Part of the Display + */ + +int fbgen_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) +{ + struct fb_info_gen *info2 = (struct fb_info_gen *)info; + struct fbgen_hwswitch *fbhw = info2->fbhw; + char par[info2->parsize]; + + if (con == -1) + fbhw->get_par(&par, info2); + else { + int err; + + if ((err = fbhw->decode_var(&fb_display[con].var, &par, info2))) + return err; + } + memset(fix, 0, sizeof(struct fb_fix_screeninfo)); + return fbhw->encode_fix(fix, &par, info2); +} + + + /* + * Get the User Defined Part of the Display + */ + +int fbgen_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) +{ + struct fb_info_gen *info2 = (struct fb_info_gen *)info; + struct fbgen_hwswitch *fbhw = info2->fbhw; + char par[info2->parsize]; + + if (con == -1) { + fbhw->get_par(&par, info2); + fbhw->encode_var(var, &par, info2); + } else + *var = fb_display[con].var; + return 0; +} + + + /* + * Set the User Defined Part of the Display + */ + +int fbgen_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) +{ + struct fb_info_gen *info2 = (struct fb_info_gen *)info; + int err; + int oldxres, oldyres, oldbpp, oldxres_virtual, oldyres_virtual, oldyoffset; + + if ((err = fbgen_do_set_var(var, con == currcon, info2))) + return err; + if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { + oldxres = fb_display[con].var.xres; + oldyres = fb_display[con].var.yres; + oldxres_virtual = fb_display[con].var.xres_virtual; + oldyres_virtual = fb_display[con].var.yres_virtual; + oldbpp = fb_display[con].var.bits_per_pixel; + oldyoffset = fb_display[con].var.yoffset; + fb_display[con].var = *var; + if (oldxres != var->xres || oldyres != var->yres || + oldxres_virtual != var->xres_virtual || + oldyres_virtual != var->yres_virtual || + oldbpp != var->bits_per_pixel || + oldyoffset != var->yoffset) { + fbgen_set_disp(con, info2); + if (info->changevar) + (*info->changevar)(con); + if ((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0))) + return err; + fbgen_install_cmap(con, info2); + } + } + var->activate = 0; + return 0; +} + + + /* + * Get the Colormap + */ + +int fbgen_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + struct fb_info_gen *info2 = (struct fb_info_gen *)info; + struct fbgen_hwswitch *fbhw = info2->fbhw; + + if (con == currcon) /* current console ? */ + return fb_get_cmap(cmap, &fb_display[con].var, kspc, fbhw->getcolreg, + info); + else + if (fb_display[con].cmap.len) /* non default colormap ? */ + fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); + else + fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), + cmap, kspc ? 0 : 2); + return 0; +} + + + /* + * Set the Colormap + */ + +int fbgen_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + struct fb_info_gen *info2 = (struct fb_info_gen *)info; + struct fbgen_hwswitch *fbhw = info2->fbhw; + int err; + + if (!fb_display[con].cmap.len) { /* no colormap allocated ? */ + if ((err = fb_alloc_cmap(&fb_display[con].cmap, + 1 << fb_display[con].var.bits_per_pixel, 0))) + return err; + } + if (con == currcon) /* current console ? */ + return fb_set_cmap(cmap, &fb_display[con].var, kspc, fbhw->setcolreg, + info); + else + fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); + return 0; +} + + + /* + * Pan or Wrap the Display + * + * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag + */ + +int fbgen_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct fb_info_gen *info2 = (struct fb_info_gen *)info; + struct fbgen_hwswitch *fbhw = info2->fbhw; + int xoffset = var->xoffset; + int yoffset = var->yoffset; + int err; + + if (xoffset < 0 || + xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual || + yoffset < 0 || + yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual) + return -EINVAL; + if (con == currcon) { + if (fbhw->pan_display) { + if ((err = fbhw->pan_display(var, info2))) + return err; + } else + return -EINVAL; + } + fb_display[con].var.xoffset = var->xoffset; + fb_display[con].var.yoffset = var->yoffset; + if (var->vmode & FB_VMODE_YWRAP) + fb_display[con].var.vmode |= FB_VMODE_YWRAP; + else + fb_display[con].var.vmode &= ~FB_VMODE_YWRAP; + + return 0; +} + + + /* + * Frame Buffer Specific ioctls + */ + +int fbgen_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg, int con, struct fb_info *info) +{ + return -EINVAL; +} + + +/* ---- Helper functions --------------------------------------------------- */ + + + /* + * Change the video mode + */ + +int fbgen_do_set_var(struct fb_var_screeninfo *var, int isactive, + struct fb_info_gen *info) +{ + struct fbgen_hwswitch *fbhw = info->fbhw; + int err, activate; + char par[info->parsize]; + + if ((err = fbhw->decode_var(var, &par, info))) + return err; + activate = var->activate; + if (((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) && isactive) + fbhw->set_par(&par, info); + fbhw->encode_var(var, &par, info); + var->activate = activate; + return 0; +} + + +void fbgen_set_disp(int con, struct fb_info_gen *info) +{ + struct fbgen_hwswitch *fbhw = info->fbhw; + struct fb_fix_screeninfo fix; + char par[info->parsize]; + struct display *display; + + if (con >= 0) + display = &fb_display[con]; + else + display = &disp; /* used during initialization */ + + if (con == -1) + fbhw->get_par(&par, info); + else + fbhw->decode_var(&fb_display[con].var, &par, info); + memset(&fix, 0, sizeof(struct fb_fix_screeninfo)); + fbhw->encode_fix(&fix, &par, info); + + display->screen_base = fix.smem_start; + display->visual = fix.visual; + display->type = fix.type; + display->type_aux = fix.type_aux; + display->ypanstep = fix.ypanstep; + display->ywrapstep = fix.ywrapstep; + display->line_length = fix.line_length; + if (info->fbhw->blank || fix.visual == FB_VISUAL_PSEUDOCOLOR || + fix.visual == FB_VISUAL_DIRECTCOLOR) + display->can_soft_blank = 1; + else + display->can_soft_blank = 0; + display->dispsw = fbhw->get_dispsw(&par, info); +#if 0 /* FIXME: generic inverse is not supported yet */ + display->inverse = (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse); +#else + display->inverse = fix.visual == FB_VISUAL_MONO01; +#endif +} + + + /* + * Install the current colormap + */ + +void fbgen_install_cmap(int con, struct fb_info_gen *info) +{ + struct fbgen_hwswitch *fbhw = info->fbhw; + if (con != currcon) + return; + if (fb_display[con].cmap.len) + fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1, + fbhw->setcolreg, &info->info); + else + fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), + &fb_display[con].var, 1, fbhw->setcolreg, &info->info); +} + + + /* + * Update the `var' structure (called by fbcon.c) + */ + +int fbgen_update_var(int con, struct fb_info *info) +{ + struct fb_info_gen *info2 = (struct fb_info_gen *)info; + struct fbgen_hwswitch *fbhw = info2->fbhw; + int err; + + if (fbhw->pan_display) { + if ((err = fbhw->pan_display(&fb_display[con].var, info2))) + return err; + } + return 0; +} + + + /* + * Switch to a different virtual console + */ + +int fbgen_switch(int con, struct fb_info *info) +{ + struct fb_info_gen *info2 = (struct fb_info_gen *)info; + struct fbgen_hwswitch *fbhw = info2->fbhw; + + /* Do we have to save the colormap ? */ + if (fb_display[currcon].cmap.len) + fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1, + fbhw->getcolreg, &info2->info); + fbgen_do_set_var(&fb_display[con].var, 1, info2); + currcon = con; + /* Install new colormap */ + fbgen_install_cmap(con, info2); + return 0; +} + + + /* + * Blank the screen + */ + +void fbgen_blank(int blank, struct fb_info *info) +{ + struct fb_info_gen *info2 = (struct fb_info_gen *)info; + struct fbgen_hwswitch *fbhw = info2->fbhw; + u16 black[16]; + struct fb_cmap cmap; + + if (fbhw->blank && !fbhw->blank(blank, info2)) + return; + if (blank) { + memset(black, 0, 16*sizeof(u16)); + cmap.red = black; + cmap.green = black; + cmap.blue = black; + cmap.transp = NULL; + cmap.start = 0; + cmap.len = 16; + fb_set_cmap(&cmap, &fb_display[currcon].var, 1, fbhw->setcolreg, info); + } else + fbgen_install_cmap(currcon, info2); +} diff --git a/drivers/video/font_6x11.c b/drivers/video/font_6x11.c new file mode 100644 index 000000000..ebfe24258 --- /dev/null +++ b/drivers/video/font_6x11.c @@ -0,0 +1,3345 @@ +/**********************************************/ +/* */ +/* Font file generated by rthelen */ +/* */ +/**********************************************/ + +#define FONTDATAMAX (11*256) + +char fontname_6x11[] = "ProFont6x11"; + +int fontheight_6x11 = 11; +int fontwidth_6x11 = 6; + +unsigned char fontdata_6x11[FONTDATAMAX] = { + + /* 0 0x00 '^A' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 1 0x01 '^B' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 2 0x02 '^C' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 3 0x03 '^D' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 4 0x04 '^E' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 5 0x05 '^F' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 6 0x06 '^G' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 7 0x07 '^H' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 8 0x08 '^I' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 9 0x09 '^J' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 10 0x0a '^K' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 11 0x0b '^L' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 12 0x0c '^M' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 13 0x0d '^N' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 14 0x0e '^O' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 15 0x0f '^P' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 16 0x10 '^Q' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 17 0x11 '^R' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x54, /* 0 0 0 00 */ + 0x38, /* 00 000 */ + 0x54, /* 0 0 0 00 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 18 0x12 '^S' */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x50, /* 0 0 0000 */ + 0x50, /* 0 0 0000 */ + 0x20, /* 00 00000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 19 0x13 '^T' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x7c, /* 0 00 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 20 0x14 '^U' */ + 0x18, /* 000 000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x7c, /* 0 00 */ + 0x78, /* 0 000 */ + 0x78, /* 0 000 */ + 0x7c, /* 0 00 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 21 0x15 '^V' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 22 0x16 '^W' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 23 0x17 '^X' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 24 0x18 '^Y' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 25 0x19 '^Z' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 26 0x1a '^[' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 27 0x1b '^\' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 28 0x1c '^]' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 29 0x1d '^^' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 30 0x1e '^_' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 31 0x1f '^`' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 32 0x20 ' ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 33 0x21 '!' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 34 0x22 '"' */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 35 0x23 '#' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x7c, /* 0 00 */ + 0x28, /* 00 0 000 */ + 0x7c, /* 0 00 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 36 0x24 '$' */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x54, /* 0 0 0 00 */ + 0x50, /* 0 0 0000 */ + 0x38, /* 00 000 */ + 0x14, /* 000 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 37 0x25 '%' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x58, /* 0 0 000 */ + 0x28, /* 00 0 000 */ + 0x34, /* 00 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x48, /* 0 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 38 0x26 '&' */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x48, /* 0 00 000 */ + 0x50, /* 0 0 0000 */ + 0x20, /* 00 00000 */ + 0x54, /* 0 0 0 00 */ + 0x48, /* 0 00 000 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 39 0x27 ''' */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 40 0x28 '(' */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 41 0x29 ')' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 42 0x2a '*' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x54, /* 0 0 0 00 */ + 0x38, /* 00 000 */ + 0x54, /* 0 0 0 00 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 43 0x2b '+' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 44 0x2c ',' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + + /* 45 0x2d '-' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 46 0x2e '.' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 000 000 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 47 0x2f '/' */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x20, /* 00 00000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + + /* 48 0x30 '0' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x64, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 49 0x31 '1' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x18, /* 000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x1c, /* 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 50 0x32 '2' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 51 0x33 '3' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x04, /* 00000 00 */ + 0x18, /* 000 000 */ + 0x04, /* 00000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 52 0x34 '4' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x18, /* 000 000 */ + 0x28, /* 00 0 000 */ + 0x48, /* 0 00 000 */ + 0x7c, /* 0 00 */ + 0x08, /* 0000 000 */ + 0x1c, /* 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 53 0x35 '5' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 54 0x36 '6' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 55 0x37 '7' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 56 0x38 '8' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 57 0x39 '9' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x04, /* 00000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 58 0x3a ':' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 000 000 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x18, /* 000 000 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 59 0x3b ';' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x30, /* 00 0000 */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + + /* 60 0x3c '<' */ + 0x00, /* 00000000 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 61 0x3d '=' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 62 0x3e '>' */ + 0x00, /* 00000000 */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 63 0x3f '?' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 64 0x40 '@' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x74, /* 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 65 0x41 'A' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 66 0x42 'B' */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 67 0x43 'C' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 68 0x44 'D' */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 69 0x45 'E' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 70 0x46 'F' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 71 0x47 'G' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x4c, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 72 0x48 'H' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 73 0x49 'I' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 74 0x4a 'J' */ + 0x00, /* 00000000 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 75 0x4b 'K' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x48, /* 0 00 000 */ + 0x50, /* 0 0 0000 */ + 0x60, /* 0 00000 */ + 0x50, /* 0 0 0000 */ + 0x48, /* 0 00 000 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 76 0x4c 'L' */ + 0x00, /* 00000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 77 0x4d 'M' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x6c, /* 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 78 0x4e 'N' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x64, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x4c, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 79 0x4f 'O' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 80 0x50 'P' */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 81 0x51 'Q' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x54, /* 0 0 0 00 */ + 0x38, /* 00 000 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 82 0x52 'R' */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 83 0x53 'S' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x38, /* 00 000 */ + 0x04, /* 00000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 84 0x54 'T' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 85 0x55 'U' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 86 0x56 'V' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 87 0x57 'W' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x6c, /* 0 0 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 88 0x58 'X' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 89 0x59 'Y' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 90 0x5a 'Z' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x40, /* 0 000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 91 0x5b '[' */ + 0x0c, /* 0000 00 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x0c, /* 0000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 92 0x5c '\' */ + 0x20, /* 00 00000 */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x02, /* 000000 0 */ + 0x02, /* 000000 0 */ + 0x00, /* 00000000 */ + + /* 93 0x5d ']' */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x30, /* 00 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 94 0x5e '^' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 95 0x5f '_' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 0 0 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 96 0x60 '`' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 97 0x61 'a' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 98 0x62 'b' */ + 0x00, /* 00000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 99 0x63 'c' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 100 0x64 'd' */ + 0x00, /* 00000000 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 101 0x65 'e' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 102 0x66 'f' */ + 0x00, /* 00000000 */ + 0x0c, /* 0000 00 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 103 0x67 'g' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x04, /* 00000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + + /* 104 0x68 'h' */ + 0x00, /* 00000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 105 0x69 'i' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 106 0x6a 'j' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x60, /* 0 00000 */ + 0x00, /* 00000000 */ + + /* 107 0x6b 'k' */ + 0x00, /* 00000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x48, /* 0 00 000 */ + 0x50, /* 0 0 0000 */ + 0x70, /* 0 0000 */ + 0x48, /* 0 00 000 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 108 0x6c 'l' */ + 0x00, /* 00000000 */ + 0x30, /* 00 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 109 0x6d 'm' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 110 0x6e 'n' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x58, /* 0 0 000 */ + 0x64, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 111 0x6f 'o' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 112 0x70 'p' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 0 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + + /* 113 0x71 'q' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + + /* 114 0x72 'r' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x58, /* 0 0 000 */ + 0x64, /* 0 00 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 115 0x73 's' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x40, /* 0 000000 */ + 0x38, /* 00 000 */ + 0x04, /* 00000 00 */ + 0x78, /* 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 116 0x74 't' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x0c, /* 0000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 117 0x75 'u' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 118 0x76 'v' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 119 0x77 'w' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 120 0x78 'x' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 121 0x79 'y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x04, /* 00000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + + /* 122 0x7a 'z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 123 0x7b '{' */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + + /* 124 0x7c '|' */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 125 0x7d '}' */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + + /* 126 0x7e '~' */ + 0x00, /* 00000000 */ + 0x34, /* 00 0 00 */ + 0x58, /* 0 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 127 0x7f '^?' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 128 0x80 '\200' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 129 0x81 '\201' */ + 0x28, /* 00 0 000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 130 0x82 '\202' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 131 0x83 '\203' */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x78, /* 0 000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 132 0x84 '\204' */ + 0x58, /* 0 0 000 */ + 0x44, /* 0 000 00 */ + 0x64, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x4c, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 133 0x85 '\205' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 134 0x86 '\206' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 135 0x87 '\207' */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 136 0x88 '\210' */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 137 0x89 '\211' */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 138 0x8a '\212' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 139 0x8b '\213' */ + 0x34, /* 00 0 00 */ + 0x58, /* 0 0 000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 140 0x8c '\214' */ + 0x18, /* 000 000 */ + 0x24, /* 00 00 00 */ + 0x18, /* 000 000 */ + 0x3c, /* 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 141 0x8d '\215' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + + /* 142 0x8e '\216' */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 143 0x8f '\217' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 144 0x90 '\220' */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 145 0x91 '\221' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x40, /* 0 000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 146 0x92 '\222' */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 147 0x93 '\223' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 148 0x94 '\224' */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 149 0x95 '\225' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 150 0x96 '\226' */ + 0x34, /* 00 0 00 */ + 0x58, /* 0 0 000 */ + 0x00, /* 00000000 */ + 0x58, /* 0 0 000 */ + 0x64, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 151 0x97 '\227' */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 152 0x98 '\230' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 153 0x99 '\231' */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 154 0x9a '\232' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 155 0x9b '\233' */ + 0x34, /* 00 0 00 */ + 0x58, /* 0 0 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 156 0x9c '\234' */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 157 0x9d '\235' */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 158 0x9e '\236' */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 159 0x9f '\237' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x34, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 160 0xa0 '\240' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 161 0xa1 '\241' */ + 0x18, /* 000 000 */ + 0x24, /* 00 00 00 */ + 0x24, /* 00 00 00 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 162 0xa2 '\242' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x54, /* 0 0 0 00 */ + 0x50, /* 0 0 0000 */ + 0x54, /* 0 0 0 00 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 163 0xa3 '\243' */ + 0x30, /* 00 0000 */ + 0x48, /* 0 00 000 */ + 0x40, /* 0 000000 */ + 0x70, /* 0 0000 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x44, /* 0 000 00 */ + 0x78, /* 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 164 0xa4 '\244' */ + 0x44, /* 0 000 00 */ + 0x24, /* 00 00 00 */ + 0x50, /* 0 0 0000 */ + 0x48, /* 0 00 000 */ + 0x24, /* 00 00 00 */ + 0x14, /* 000 0 00 */ + 0x48, /* 0 00 000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 165 0xa5 '\245' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x7c, /* 0 00 */ + 0x7c, /* 0 00 */ + 0x7c, /* 0 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 166 0xa6 '\246' */ + 0x3c, /* 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x3c, /* 00 00 */ + 0x14, /* 000 0 00 */ + 0x14, /* 000 0 00 */ + 0x14, /* 000 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 167 0xa7 '\247' */ + 0x18, /* 000 000 */ + 0x24, /* 00 00 00 */ + 0x44, /* 0 000 00 */ + 0x48, /* 0 00 000 */ + 0x48, /* 0 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x58, /* 0 0 000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 168 0xa8 '\250' */ + 0x00, /* 00000000 */ + 0x70, /* 0 0000 */ + 0x08, /* 0000 000 */ + 0x64, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x64, /* 0 00 00 */ + 0x58, /* 0 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 169 0xa9 '\251' */ + 0x00, /* 00000000 */ + 0x70, /* 0 0000 */ + 0x08, /* 0000 000 */ + 0x34, /* 00 0 00 */ + 0x44, /* 0 000 00 */ + 0x34, /* 00 0 00 */ + 0x08, /* 0000 000 */ + 0x70, /* 0 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 170 0xaa '\252' */ + 0x00, /* 00000000 */ + 0x7a, /* 0 0 0 */ + 0x2e, /* 00 0 0 */ + 0x2e, /* 00 0 0 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 171 0xab '\253' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 172 0xac '\254' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 173 0xad '\255' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 174 0xae '\256' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x50, /* 0 0 0000 */ + 0x50, /* 0 0 0000 */ + 0x78, /* 0 000 */ + 0x50, /* 0 0 0000 */ + 0x50, /* 0 0 0000 */ + 0x5c, /* 0 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 175 0xaf '\257' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x4c, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x64, /* 0 00 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 176 0xb0 '\260' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x6c, /* 0 0 00 */ + 0x54, /* 0 0 0 00 */ + 0x6c, /* 0 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 177 0xb1 '\261' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 178 0xb2 '\262' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 179 0xb3 '\263' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x04, /* 00000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x1c, /* 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 180 0xb4 '\264' */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x7c, /* 0 00 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 181 0xb5 '\265' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x48, /* 0 00 000 */ + 0x48, /* 0 00 000 */ + 0x48, /* 0 00 000 */ + 0x48, /* 0 00 000 */ + 0x74, /* 0 0 00 */ + 0x40, /* 0 000000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + + /* 182 0xb6 '\266' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x0c, /* 0000 00 */ + 0x14, /* 000 0 00 */ + 0x24, /* 00 00 00 */ + 0x24, /* 00 00 00 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 183 0xb7 '\267' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x24, /* 00 00 00 */ + 0x10, /* 000 0000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x24, /* 00 00 00 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 184 0xb8 '\270' */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 185 0xb9 '\271' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 186 0xba '\272' */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x60, /* 0 00000 */ + 0x00, /* 00000000 */ + + /* 187 0xbb '\273' */ + 0x00, /* 00000000 */ + 0x1c, /* 000 00 */ + 0x24, /* 00 00 00 */ + 0x24, /* 00 00 00 */ + 0x1c, /* 000 00 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 188 0xbc '\274' */ + 0x00, /* 00000000 */ + 0x18, /* 000 000 */ + 0x24, /* 00 00 00 */ + 0x24, /* 00 00 00 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 189 0xbd '\275' */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x6c, /* 0 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 190 0xbe '\276' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x54, /* 0 0 0 00 */ + 0x5c, /* 0 0 00 */ + 0x50, /* 0 0 0000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 191 0xbf '\277' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x4c, /* 0 00 00 */ + 0x54, /* 0 0 0 00 */ + 0x64, /* 0 00 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 192 0xc0 '\300' */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x20, /* 00 00000 */ + 0x40, /* 0 000000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 193 0xc1 '\301' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x08, /* 0000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 194 0xc2 '\302' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x04, /* 00000 00 */ + 0x04, /* 00000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 195 0xc3 '\303' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0c, /* 0000 00 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x50, /* 0 0 0000 */ + 0x20, /* 00 00000 */ + 0x20, /* 00 00000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 196 0xc4 '\304' */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x60, /* 0 00000 */ + 0x00, /* 00000000 */ + + /* 197 0xc5 '\305' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x04, /* 00000 00 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x40, /* 0 000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 198 0xc6 '\306' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 199 0xc7 '\307' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x24, /* 00 00 00 */ + 0x48, /* 0 00 000 */ + 0x48, /* 0 00 000 */ + 0x24, /* 00 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 200 0xc8 '\310' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x48, /* 0 00 000 */ + 0x24, /* 00 00 00 */ + 0x24, /* 00 00 00 */ + 0x48, /* 0 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 201 0xc9 '\311' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x54, /* 0 0 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 202 0xca '\312' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 203 0xcb '\313' */ + 0x10, /* 000 0000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 204 0xcc '\314' */ + 0x58, /* 0 0 000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x7c, /* 0 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 205 0xcd '\315' */ + 0x58, /* 0 0 000 */ + 0x38, /* 00 000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 206 0xce '\316' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x50, /* 0 0 0000 */ + 0x50, /* 0 0 0000 */ + 0x58, /* 0 0 000 */ + 0x50, /* 0 0 0000 */ + 0x50, /* 0 0 0000 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 207 0xcf '\317' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x54, /* 0 0 0 00 */ + 0x5c, /* 0 0 00 */ + 0x50, /* 0 0 0000 */ + 0x2c, /* 00 0 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 208 0xd0 '\320' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 209 0xd1 '\321' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 0 0 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 210 0xd2 '\322' */ + 0x00, /* 00000000 */ + 0x14, /* 000 0 00 */ + 0x28, /* 00 0 000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 211 0xd3 '\323' */ + 0x00, /* 00000000 */ + 0x14, /* 000 0 00 */ + 0x14, /* 000 0 00 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 212 0xd4 '\324' */ + 0x00, /* 00000000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x18, /* 000 000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 213 0xd5 '\325' */ + 0x00, /* 00000000 */ + 0x18, /* 000 000 */ + 0x08, /* 0000 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 214 0xd6 '\326' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x7c, /* 0 00 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 215 0xd7 '\327' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 000 0000 */ + 0x28, /* 00 0 000 */ + 0x44, /* 0 000 00 */ + 0x28, /* 00 0 000 */ + 0x10, /* 000 0000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 216 0xd8 '\330' */ + 0x00, /* 00000000 */ + 0x28, /* 00 0 000 */ + 0x00, /* 00000000 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x44, /* 0 000 00 */ + 0x3c, /* 00 00 */ + 0x04, /* 00000 00 */ + 0x38, /* 00 000 */ + 0x00, /* 00000000 */ + + /* 217 0xd9 '\331' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 0 0 */ + 0x00, /* 00000000 */ + 0x7e, /* 0 0 */ + 0x00, /* 00000000 */ + 0x7e, /* 0 0 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 218 0xda '\332' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 219 0xdb '\333' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 220 0xdc '\334' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 221 0xdd '\335' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 222 0xde '\336' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 223 0xdf '\337' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 224 0xe0 '\340' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 225 0xe1 '\341' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 226 0xe2 '\342' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 227 0xe3 '\343' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 228 0xe4 '\344' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 229 0xe5 '\345' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 230 0xe6 '\346' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 231 0xe7 '\347' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 232 0xe8 '\350' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 233 0xe9 '\351' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 234 0xea '\352' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 235 0xeb '\353' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 236 0xec '\354' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 237 0xed '\355' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 238 0xee '\356' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 239 0xef '\357' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 240 0xf0 '\360' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 241 0xf1 '\361' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 242 0xf2 '\362' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 243 0xf3 '\363' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 244 0xf4 '\364' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 245 0xf5 '\365' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 246 0xf6 '\366' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 247 0xf7 '\367' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 248 0xf8 '\370' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 249 0xf9 '\371' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 250 0xfa '\372' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 251 0xfb '\373' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 252 0xfc '\374' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 253 0xfd '\375' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 254 0xfe '\376' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 255 0xff '\377' */ + 0x00, /* 00000000 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x3c, /* 00 00 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + +}; + diff --git a/drivers/video/fonts.c b/drivers/video/fonts.c index 8e89805bb..56a3a33b2 100644 --- a/drivers/video/fonts.c +++ b/drivers/video/fonts.c @@ -9,7 +9,7 @@ */ -#include <linux/config.h> /* for CONFIG_AMIGA */ +#include <linux/config.h> #include <linux/types.h> #include <linux/string.h> #ifdef __mc68000__ @@ -25,17 +25,22 @@ /* VGA8x8 */ extern char fontname_8x8[]; extern int fontwidth_8x8, fontheight_8x8; -extern u_char fontdata_8x8[]; +extern u8 fontdata_8x8[]; /* VGA8x16 */ extern char fontname_8x16[]; extern int fontwidth_8x16, fontheight_8x16; -extern u_char fontdata_8x16[]; +extern u8 fontdata_8x16[]; /* PEARL8x8 */ extern char fontname_pearl8x8[]; extern int fontwidth_pearl8x8, fontheight_pearl8x8; -extern u_char fontdata_pearl8x8[]; +extern u8 fontdata_pearl8x8[]; + +/* VGA6x11 */ +extern char fontname_6x11[]; +extern int fontwidth_6x11, fontheight_6x11; +extern u8 fontdata_6x11[]; /* @@ -46,18 +51,20 @@ struct softfontdesc { char *name; int *width; int *height; - u_char *data; + u8 *data; }; #define VGA8x8_IDX 0 #define VGA8x16_IDX 1 #define PEARL8x8_IDX 2 +#define VGA6x11_IDX 3 static struct softfontdesc softfonts[] = { { fontname_8x8, &fontwidth_8x8, &fontheight_8x8, fontdata_8x8 }, { fontname_8x16, &fontwidth_8x16, &fontheight_8x16, fontdata_8x16 }, { fontname_pearl8x8, &fontwidth_pearl8x8, &fontheight_pearl8x8, fontdata_pearl8x8 }, + { fontname_6x11, &fontwidth_6x11, &fontheight_6x11, fontdata_6x11 }, }; static unsigned int numsoftfonts = sizeof(softfonts)/sizeof(*softfonts); @@ -67,7 +74,7 @@ static unsigned int numsoftfonts = sizeof(softfonts)/sizeof(*softfonts); * Find a font with a specific name */ -int findsoftfont(char *name, int *width, int *height, u_char *data[]) +int findsoftfont(char *name, int *width, int *height, u8 *data[]) { unsigned int i; @@ -90,7 +97,7 @@ int findsoftfont(char *name, int *width, int *height, u_char *data[]) */ void getdefaultfont(int xres, int yres, char *name[], int *width, int *height, - u_char *data[]) + u8 *data[]) { int i; @@ -103,6 +110,16 @@ void getdefaultfont(int xres, int yres, char *name[], int *width, int *height, } else i = VGA8x16_IDX; +#if defined(CONFIG_MAC) + if (MACH_IS_MAC) { +#if 0 /* MSch: removed until 6x11 is debugged */ + i = VGA6x11_IDX; /* I added this for fun ... I like 6x11 */ +#endif + if (xres < 640) + i = VGA6x11_IDX; + } +#endif + if (name) *name = softfonts[i].name; if (width) diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c new file mode 100644 index 000000000..43932a080 --- /dev/null +++ b/drivers/video/macfb.c @@ -0,0 +1,459 @@ +/* + * We've been given MAC frame buffer info by the booter. Now go set it up + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/tty.h> +#include <linux/malloc.h> +#include <linux/delay.h> +#include <linux/nubus.h> +#include <linux/init.h> + +#include <asm/setup.h> +#include <asm/bootinfo.h> +#include <asm/uaccess.h> +#include <asm/pgtable.h> +#include <asm/irq.h> +#include <asm/macintosh.h> +#include <linux/fb.h> + + +/* conditionalize these ?? */ +#include "fbcon-mfb.h" +#include "fbcon-cfb2.h" +#include "fbcon-cfb4.h" +#include "fbcon-cfb8.h" + +#define arraysize(x) (sizeof(x)/sizeof(*(x))) + +static struct fb_var_screeninfo macfb_defined={ + 0,0,0,0, /* W,H, W, H (virtual) load xres,xres_virtual*/ + 0,0, /* virtual -> visible no offset */ + 8, /* depth -> load bits_per_pixel */ + 0, /* greyscale ? */ + {0,0,0}, /* R */ + {0,0,0}, /* G */ + {0,0,0}, /* B */ + {0,0,0}, /* transparency */ + 0, /* standard pixel format */ + FB_ACTIVATE_NOW, + 274,195, /* 14" monitor *Mikael Nykvist's anyway* */ + FB_ACCEL_NONE, /* The only way to accelerate a mac is .. */ + 0L,0L,0L,0L,0L, + 0L,0L,0, /* No sync info */ + FB_VMODE_NONINTERLACED, + {0,0,0,0,0,0} +}; + +#define NUM_TOTAL_MODES 1 +#define NUM_PREDEF_MODES 1 + +static struct display disp; +static struct fb_info fb_info; + +static int inverse = 0; + +struct macfb_par +{ + void *unused; +}; + +static int currcon = 0; +static int current_par_valid = 0; +struct macfb_par current_par; + +static int mac_xres,mac_yres,mac_depth, mac_xbytes, mac_vxres; +static unsigned long mac_videobase; +static unsigned long mac_videosize; + + /* + * Open/Release the frame buffer device + */ + +static int macfb_open(struct fb_info *info) +{ + /* + * Nothing, only a usage count for the moment + */ + MOD_INC_USE_COUNT; + return(0); +} + +static int macfb_release(struct fb_info *info) +{ + MOD_DEC_USE_COUNT; + return(0); +} + +static void macfb_encode_var(struct fb_var_screeninfo *var, + struct macfb_par *par) +{ + int i=0; + var->xres=mac_xres; + var->yres=mac_yres; + var->xres_virtual=mac_vxres; + var->yres_virtual=var->yres; + var->xoffset=0; + var->yoffset=0; + var->bits_per_pixel = mac_depth; + var->grayscale=0; + var->transp.offset=0; + var->transp.length=0; + var->transp.msb_right=0; + var->nonstd=0; + var->activate=0; + var->height= -1; + var->width= -1; + var->accel=0; + var->vmode=FB_VMODE_NONINTERLACED; + var->pixclock=0; + var->sync=0; + var->left_margin=0; + var->right_margin=0; + var->upper_margin=0; + var->lower_margin=0; + var->hsync_len=0; + var->vsync_len=0; + for(i=0;i<arraysize(var->reserved);i++) + var->reserved[i]=0; + return; +} + + +static void macfb_get_par(struct macfb_par *par) +{ + *par=current_par; +} + +static void macfb_set_par(struct macfb_par *par) +{ + current_par_valid=1; +} + +static int fb_update_var(int con, struct fb_info *info) +{ + return 0; +} + +static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive) +{ + struct macfb_par par; + + macfb_get_par(&par); + macfb_encode_var(var, &par); + return 0; +} + +extern int console_loglevel; + +static void macfb_encode_fix(struct fb_fix_screeninfo *fix, + struct macfb_par *par) +{ + int i; + + memset(fix, 0, sizeof(struct fb_fix_screeninfo)); + strcpy(fix->id,"Macintosh"); + + /* + * X works, but screen wraps ... + */ + fix->smem_start=(char *)(mac_videobase&PAGE_MASK); + fix->smem_offset=(mac_videobase&~PAGE_MASK); + fix->smem_len=PAGE_ALIGN(mac_videosize); + fix->type = FB_TYPE_PACKED_PIXELS; + fix->visual = FB_VISUAL_PSEUDOCOLOR; + fix->xpanstep=0; + fix->ypanstep=0; + fix->ywrapstep=0; + fix->line_length=mac_xbytes; + return; +} + +static int macfb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) +{ + struct macfb_par par; + macfb_get_par(&par); + macfb_encode_fix(fix, &par); + return 0; +} + +static int macfb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct macfb_par par; + if(con==-1) + { + macfb_get_par(&par); + macfb_encode_var(var, &par); + } + else + *var=fb_display[con].var; + return 0; +} + +static void macfb_set_disp(int con) +{ + struct fb_fix_screeninfo fix; + struct display *display; + + if (con >= 0) + display = &fb_display[con]; + else + display = &disp; /* used during initialization */ + + macfb_get_fix(&fix, con, 0); + + display->screen_base = (u_char *)(fix.smem_start+fix.smem_offset); + display->visual = fix.visual; + display->type = fix.type; + display->type_aux = fix.type_aux; + display->ypanstep = fix.ypanstep; + display->ywrapstep = fix.ywrapstep; + display->line_length = fix.line_length; + display->next_line = fix.line_length; + display->can_soft_blank = 0; + display->inverse = inverse; + + switch (mac_depth) { +#ifdef CONFIG_FBCON_MFB + case 1: + display->dispsw = &fbcon_mfb; + break; +#endif +#ifdef CONFIG_FBCON_CFB2 + case 2: + display->dispsw = &fbcon_cfb2; + break; +#endif +#ifdef CONFIG_FBCON_CFB4 + case 4: + display->dispsw = &fbcon_cfb4; + break; +#endif +#ifdef CONFIG_FBCON_CFB8 + case 8: + display->dispsw = &fbcon_cfb8; + break; +#endif + default: + display->dispsw = NULL; + break; + } +} + +static int macfb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + int err; + + if ((err=do_fb_set_var(var, 1))) + return err; + return 0; +} + +static int macfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ +#if 0 + printk("macfb_get_cmap: not supported!\n"); + /* interferes with X11 */ + if (console_loglevel < 7) + return -EINVAL; + if (con == currcon) /* current console? */ + return fb_get_cmap(cmap, &fb_display[con].var, kspc, 0 /*offb_getcolreg*/, info); + else if (fb_display[con].cmap.len) /* non default colormap? */ + fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); + else + fb_copy_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), + cmap, kspc ? 0 : 2); +#endif + return 0; + +} + +static int macfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ +#if 0 + printk("macfb_set_cmap: not supported!\n"); + if (console_loglevel < 7) + return -EINVAL; + if (!fb_display[con].cmap.len) { /* no colormap allocated? */ + if ((err = fb_alloc_cmap(&fb_display[con].cmap, + 1<<fb_display[con].var.bits_per_pixel, 0))) + return err; + } + if (con == currcon) /* current console? */ + return fb_set_cmap(cmap, &fb_display[con].var, kspc, 1 /*offb_setcolreg*/, info); + else + fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); +#endif + return 0; +} + +static int macfb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + /* no panning */ + printk("macfb_pan: not supported!\n"); + return -EINVAL; +} + +static int macfb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, int con, + struct fb_info *info) +{ + printk("macfb_ioctl: not supported!\n"); + return -EINVAL; +} + +static struct fb_ops macfb_ops = { + macfb_open, + macfb_release, + macfb_get_fix, + macfb_get_var, + macfb_set_var, + macfb_get_cmap, + macfb_set_cmap, + macfb_pan_display, + NULL, + macfb_ioctl +}; + +void macfb_setup(char *options, int *ints) +{ + char *this_opt; + int temp; + + fb_info.fontname[0] = '\0'; + + if (!options || !*options) + return; + + for(this_opt=strtok(options,","); this_opt; this_opt=strtok(NULL,",")) { + if (!*this_opt) continue; + + if (! strcmp(this_opt, "inverse")) + inverse=1; + else if (!strncmp(this_opt, "font:", 5)) { + strcpy(fb_info.fontname, this_opt+5); + printk("macfb_setup: option %s\n", this_opt); + } + } +} + +static int macfb_switch(int con, struct fb_info *info) +{ + do_fb_set_var(&fb_display[con].var,1); + currcon=con; + return 0; +} + +/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */ + +static void macfb_blank(int blank, struct fb_info *info) +{ + /* Not supported */ +} + +/* + * Nubus call back. This will give us our board identity and also + * other useful info we need later + */ + +static int nubus_video_card(struct nubus_device_specifier *ns, int slot, struct nubus_type *nt) +{ + if(nt->category==NUBUS_CAT_DISPLAY) + return 0; + /* Claim all video cards. We dont yet do driver specifics tho. */ + return -ENODEV; +} + +static struct nubus_device_specifier nb_video={ + nubus_video_card, + NULL +}; + +__initfunc(unsigned long macfb_init(unsigned long mem_start)) +{ + /* nubus_remap the video .. */ + int err; + + if (!MACH_IS_MAC) + return mem_start; + + mac_xres=mac_bi_data.dimensions&0xFFFF; + mac_yres=(mac_bi_data.dimensions&0xFFFF0000)>>16; + mac_depth=mac_bi_data.videodepth; + mac_xbytes=mac_bi_data.videorow; + mac_vxres = (mac_xbytes/mac_depth)*8; + mac_videosize=mac_xbytes*mac_yres; + mac_videobase=mac_bi_data.videoaddr; + + printk("macfb_init: xres %d yres %d bpp %d addr %x size %d \n", + mac_xres, mac_yres, mac_depth, mac_videobase, mac_videosize); + + mac_debugging_penguin(4); + + /* + * Fill in the available video resolution + */ + + macfb_defined.xres=mac_xres; + macfb_defined.yres=mac_yres; + macfb_defined.xres_virtual=mac_vxres; + macfb_defined.yres_virtual=mac_yres; + macfb_defined.bits_per_pixel=mac_depth; + + + /* + * Let there be consoles.. + */ + strcpy(fb_info.modename, "Macintosh Builtin "); + fb_info.changevar = NULL; + fb_info.node = -1; + fb_info.fbops = &macfb_ops; + fb_info.disp=&disp; + fb_info.switch_con=&macfb_switch; + fb_info.updatevar=&fb_update_var; + fb_info.blank=&macfb_blank; + do_fb_set_var(&macfb_defined,1); + + err=register_framebuffer(&fb_info); + if(err<0) + { + mac_boom(6); + return NULL; + } + + macfb_get_var(&disp.var, -1, &fb_info); + macfb_set_disp(-1); + + /* + * Register the nubus hook + */ + + register_nubus_device(&nb_video); + + printk("fb%d: %s frame buffer device using %ldK of video memory\n", + GET_FB_IDX(fb_info.node), fb_info.modename, mac_videosize>>10); + + return mem_start; +} + +#if 0 +/* + * These two auxiliary debug functions should go away ASAP. Only usage: + * before the console output is up (after head.S come some other crucial + * setup routines :-) + * + * Now in debug.c ... + */ +#endif diff --git a/drivers/video/offb.c b/drivers/video/offb.c index cc521899a..26ab95dfb 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -12,6 +12,7 @@ * more details. */ +#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -23,53 +24,83 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/fb.h> +#include <linux/selection.h> #include <linux/init.h> +#ifdef CONFIG_FB_COMPAT_XPMAC +#include <linux/vc_ioctl.h> +#endif #include <asm/io.h> #include <asm/prom.h> +#include "fbcon-cfb8.h" -#define arraysize(x) (sizeof(x)/sizeof(*(x))) static int currcon = 0; -static struct display disp; -static struct fb_info fb_info; -static struct { u_char red, green, blue, pad; } palette[256]; -static char offb_name[16] = "OFfb "; -static volatile unsigned char *unknown_cmap_adr = NULL; -static volatile unsigned char *unknown_cmap_data = NULL; +struct fb_info_offb { + struct fb_info info; + struct fb_fix_screeninfo fix; + struct fb_var_screeninfo var; + struct display disp; + struct { u_char red, green, blue, pad; } palette[256]; + volatile unsigned char *cmap_adr; + volatile unsigned char *cmap_data; +}; + +static struct fb_info_offb fb_info[FB_MAX]; + +#ifdef __powerpc__ +#define mach_eieio() eieio() +#else +#define mach_eieio() do {} while (0) +#endif -static struct fb_fix_screeninfo fb_fix = { 0, }; -static struct fb_var_screeninfo fb_var = { 0, }; +static int ofonly = 0; /* * Interface used by the world */ -void offb_video_setup(char *options, int *ints); - -static int offb_open(int fbidx); -static int offb_release(int fbidx); -static int offb_get_fix(struct fb_fix_screeninfo *fix, int con); -static int offb_get_var(struct fb_var_screeninfo *var, int con); -static int offb_set_var(struct fb_var_screeninfo *var, int con); -static int offb_pan_display(struct fb_var_screeninfo *var, int con); -static int offb_get_cmap(struct fb_cmap *cmap, int kspc, int con); -static int offb_set_cmap(struct fb_cmap *cmap, int kspc, int con); +unsigned long offb_init(unsigned long mem_start); +void offb_setup(char *options, int *ints); + +static int offb_open(struct fb_info *info); +static int offb_release(struct fb_info *info); +static int offb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info); +static int offb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int offb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int offb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int offb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int offb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); static int offb_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg, int con); + u_long arg, int con, struct fb_info *info); + +#ifdef CONFIG_FB_COMPAT_XPMAC +int console_getmode(struct vc_mode *); +int console_setmode(struct vc_mode *, int); +int console_powermode(int); +struct fb_info *console_fb_info = NULL; +int (*console_setmode_ptr)(struct vc_mode *, int) = NULL; +int (*console_set_cmap_ptr)(struct fb_cmap *, int, int, struct fb_info *) + = NULL; +struct vc_mode display_info; +#endif /* CONFIG_FB_COMPAT_XPMAC */ /* * Interface to the low level console driver */ -unsigned long offb_init(unsigned long mem_start); -static int offbcon_switch(int con); -static int offbcon_updatevar(int con); -static void offbcon_blank(int blank); -static int offbcon_setcmap(struct fb_cmap *cmap, int con); +static int offbcon_switch(int con, struct fb_info *info); +static int offbcon_updatevar(int con, struct fb_info *info); +static void offbcon_blank(int blank, struct fb_info *info); /* @@ -77,15 +108,15 @@ static int offbcon_setcmap(struct fb_cmap *cmap, int con); */ static int offb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, - u_int *transp); + u_int *transp, struct fb_info *info); static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp); -static void do_install_cmap(int con); + u_int transp, struct fb_info *info); +static void do_install_cmap(int con, struct fb_info *info); static struct fb_ops offb_ops = { offb_open, offb_release, offb_get_fix, offb_get_var, offb_set_var, - offb_get_cmap, offb_set_cmap, offb_pan_display, offb_ioctl + offb_get_cmap, offb_set_cmap, offb_pan_display, NULL, offb_ioctl }; @@ -93,20 +124,20 @@ static struct fb_ops offb_ops = { * Open/Release the frame buffer device */ -static int offb_open(int fbidx) +static int offb_open(struct fb_info *info) { - /* - * Nothing, only a usage count for the moment - */ + /* + * Nothing, only a usage count for the moment + */ MOD_INC_USE_COUNT; - return(0); + return(0); } - -static int offb_release(int fbidx) + +static int offb_release(struct fb_info *info) { MOD_DEC_USE_COUNT; - return(0); + return(0); } @@ -114,9 +145,12 @@ static int offb_release(int fbidx) * Get the Fixed Part of the Display */ -static int offb_get_fix(struct fb_fix_screeninfo *fix, int con) +static int offb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) { - memcpy(fix, &fb_fix, sizeof(fb_fix)); + struct fb_info_offb *info2 = (struct fb_info_offb *)info; + + memcpy(fix, &info2->fix, sizeof(struct fb_fix_screeninfo)); return 0; } @@ -125,9 +159,12 @@ static int offb_get_fix(struct fb_fix_screeninfo *fix, int con) * Get the User Defined Part of the Display */ -static int offb_get_var(struct fb_var_screeninfo *var, int con) +static int offb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) { - memcpy(var, &fb_var, sizeof(fb_var)); + struct fb_info_offb *info2 = (struct fb_info_offb *)info; + + memcpy(var, &info2->var, sizeof(struct fb_var_screeninfo)); return 0; } @@ -136,33 +173,36 @@ static int offb_get_var(struct fb_var_screeninfo *var, int con) * Set the User Defined Part of the Display */ -static int offb_set_var(struct fb_var_screeninfo *var, int con) +static int offb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) { struct display *display; int oldbpp = -1, err; + int activate = var->activate; + struct fb_info_offb *info2 = (struct fb_info_offb *)info; if (con >= 0) display = &fb_display[con]; else - display = &disp; /* used during initialization */ + display = &info2->disp; /* used during initialization */ - if (var->xres > fb_var.xres || var->yres > fb_var.yres || - var->xres_virtual > fb_var.xres_virtual || - var->yres_virtual > fb_var.yres_virtual || - var->bits_per_pixel > fb_var.bits_per_pixel || + if (var->xres > info2->var.xres || var->yres > info2->var.yres || + var->xres_virtual > info2->var.xres_virtual || + var->yres_virtual > info2->var.yres_virtual || + var->bits_per_pixel > info2->var.bits_per_pixel || var->nonstd || (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) return -EINVAL; - memcpy(var, &fb_var, sizeof(fb_var)); + memcpy(var, &info2->var, sizeof(struct fb_var_screeninfo)); - if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { + if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { oldbpp = display->var.bits_per_pixel; display->var = *var; } if (oldbpp != var->bits_per_pixel) { if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) return err; - do_install_cmap(con); + do_install_cmap(con, info); } return 0; } @@ -174,7 +214,8 @@ static int offb_set_var(struct fb_var_screeninfo *var, int con) * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag */ -static int offb_pan_display(struct fb_var_screeninfo *var, int con) +static int offb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) { if (var->xoffset || var->yoffset) return -EINVAL; @@ -186,14 +227,16 @@ static int offb_pan_display(struct fb_var_screeninfo *var, int con) * Get the Colormap */ -static int offb_get_cmap(struct fb_cmap *cmap, int kspc, int con) +static int offb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) { if (con == currcon) /* current console? */ - return fb_get_cmap(cmap, &fb_display[con].var, kspc, offb_getcolreg); + return fb_get_cmap(cmap, &fb_display[con].var, kspc, offb_getcolreg, + info); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else - fb_copy_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), + fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), cmap, kspc ? 0 : 2); return 0; } @@ -202,11 +245,13 @@ static int offb_get_cmap(struct fb_cmap *cmap, int kspc, int con) * Set the Colormap */ -static int offb_set_cmap(struct fb_cmap *cmap, int kspc, int con) +static int offb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) { + struct fb_info_offb *info2 = (struct fb_info_offb *)info; int err; - if (!unknown_cmap_adr) + if (!info2->cmap_adr) return -ENOSYS; if (!fb_display[con].cmap.len) { /* no colormap allocated? */ @@ -215,7 +260,8 @@ static int offb_set_cmap(struct fb_cmap *cmap, int kspc, int con) return err; } if (con == currcon) /* current console? */ - return fb_set_cmap(cmap, &fb_display[con].var, kspc, offb_setcolreg); + return fb_set_cmap(cmap, &fb_display[con].var, kspc, offb_setcolreg, + info); else fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); return 0; @@ -223,12 +269,24 @@ static int offb_set_cmap(struct fb_cmap *cmap, int kspc, int con) static int offb_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg, int con) + u_long arg, int con, struct fb_info *info) { return -EINVAL; } +#ifdef CONFIG_FB_ATY +extern unsigned long atyfb_of_init(unsigned long mem_start, + struct device_node *dp); + +static const char *aty_names[] = { + "ATY,mach64", "ATY,XCLAIM", "ATY,264VT", "ATY,mach64ii", "ATY,264GT-B", + "ATY,mach64_3D_pcc", "ATY,XCLAIM3D", "ATY,XCLAIMVR", "ATY,RAGEII_M", + "ATY,XCLAIMVRPro", "ATY,mach64_3DU" +}; +#endif /* CONFIG_FB_ATY */ + + /* * Initialisation */ @@ -236,128 +294,196 @@ static int offb_ioctl(struct inode *inode, struct file *file, u_int cmd, __initfunc(unsigned long offb_init(unsigned long mem_start)) { struct device_node *dp; - int i, err, *pp, len; + int dpy, i, err, *pp, len; unsigned *up, address; + struct fb_fix_screeninfo *fix; + struct fb_var_screeninfo *var; + struct display *disp; + struct fb_info_offb *info; + + for (dpy = 0; dpy < prom_num_displays; dpy++) { + if (!(dp = find_path_device(prom_display_paths[dpy]))) + continue; + + info = &fb_info[dpy]; + fix = &info->fix; + var = &info->var; + disp = &info->disp; + + if (!ofonly) { +#ifdef CONFIG_FB_ATY + for (i = 0; i < sizeof(aty_names)/sizeof(*aty_names); i++) + if (!strcmp(dp->name, aty_names[i])) + break; + if (i < sizeof(aty_names)/sizeof(*aty_names)) { + mem_start = atyfb_of_init(mem_start, dp); + continue; + } +#endif /* CONFIG_FB_ATY */ + } - if (!prom_display_path[0]) - return mem_start; - if (!(dp = find_path_device(prom_display_path))) - return mem_start; - - strncat(offb_name, dp->name, sizeof(offb_name)); - offb_name[sizeof(offb_name)-1] = '\0'; - strcpy(fb_fix.id, offb_name); + strcpy(fix->id, "OFfb "); + strncat(fix->id, dp->name, sizeof(fix->id)); + fix->id[sizeof(fix->id)-1] = '\0'; - if ((pp = (int *)get_property(dp, "depth", &len)) != NULL - && len == sizeof(int) && *pp != 8) { - printk("%s: can't use depth = %d\n", dp->full_name, *pp); - return mem_start; - } - if ((pp = (int *)get_property(dp, "width", &len)) != NULL - && len == sizeof(int)) - fb_var.xres = fb_var.xres_virtual = *pp; - if ((pp = (int *)get_property(dp, "height", &len)) != NULL - && len == sizeof(int)) - fb_var.yres = fb_var.yres_virtual = *pp; - if ((pp = (int *)get_property(dp, "linebytes", &len)) != NULL - && len == sizeof(int)) - fb_fix.line_length = *pp; - else - fb_fix.line_length = fb_var.xres_virtual; - fb_fix.smem_len = fb_fix.line_length*fb_var.yres; - if ((up = (unsigned *)get_property(dp, "address", &len)) != NULL - && len == sizeof(unsigned)) - address = (u_long)*up; - else { - for (i = 0; i < dp->n_addrs; ++i) - if (dp->addrs[i].size >= len) - break; - if (i >= dp->n_addrs) { - printk("no framebuffer address found for %s\n", dp->full_name); - return mem_start; + if ((pp = (int *)get_property(dp, "depth", &len)) != NULL + && len == sizeof(int) && *pp != 8) { + printk("%s: can't use depth = %d\n", dp->full_name, *pp); + continue; + } + if ((pp = (int *)get_property(dp, "width", &len)) != NULL + && len == sizeof(int)) + var->xres = var->xres_virtual = *pp; + if ((pp = (int *)get_property(dp, "height", &len)) != NULL + && len == sizeof(int)) + var->yres = var->yres_virtual = *pp; + if ((pp = (int *)get_property(dp, "linebytes", &len)) != NULL + && len == sizeof(int)) + fix->line_length = *pp; + else + fix->line_length = var->xres_virtual; + fix->smem_len = fix->line_length*var->yres; + if ((up = (unsigned *)get_property(dp, "address", &len)) != NULL + && len == sizeof(unsigned)) + address = (u_long)*up; + else { + for (i = 0; i < dp->n_addrs; ++i) + if (dp->addrs[i].size >= len) + break; + if (i >= dp->n_addrs) { + printk("no framebuffer address found for %s\n", dp->full_name); + continue; + } + address = (u_long)dp->addrs[i].address; + } + fix->smem_start = ioremap(address, fix->smem_len); + fix->type = FB_TYPE_PACKED_PIXELS; + fix->type_aux = 0; + + /* XXX kludge for ati */ + if (strncmp(dp->name, "ATY,", 4) == 0) { + info->cmap_adr = ioremap(address + 0x7ff000, 0x1000) + 0xcc0; + info->cmap_data = info->cmap_adr + 1; } - address = (u_long)dp->addrs[i].address; - } - fb_fix.smem_start = ioremap(address, fb_fix.smem_len); - fb_fix.type = FB_TYPE_PACKED_PIXELS; - fb_fix.type_aux = 0; - - /* XXX kludge for ati */ - if (strncmp(dp->name, "ATY,", 4) == 0) { - unknown_cmap_adr = ioremap(address + 0x7ff000, 0x1000) + 0xcc0; - unknown_cmap_data = unknown_cmap_adr + 1; - } - fb_fix.visual = unknown_cmap_adr ? FB_VISUAL_PSEUDOCOLOR : + fix->visual = info->cmap_adr ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_STATIC_PSEUDOCOLOR; - fb_var.xoffset = fb_var.yoffset = 0; - fb_var.bits_per_pixel = 8; - fb_var.grayscale = 0; - fb_var.red.offset = fb_var.green.offset = fb_var.blue.offset = 0; - fb_var.red.length = fb_var.green.length = fb_var.blue.length = 8; - fb_var.red.msb_right = fb_var.green.msb_right = fb_var.blue.msb_right = 0; - fb_var.transp.offset = fb_var.transp.length = fb_var.transp.msb_right = 0; - fb_var.nonstd = 0; - fb_var.activate = 0; - fb_var.height = fb_var.width = -1; - fb_var.accel = FB_ACCEL_NONE; - fb_var.pixclock = 10000; - fb_var.left_margin = fb_var.right_margin = 16; - fb_var.upper_margin = fb_var.lower_margin = 16; - fb_var.hsync_len = fb_var.vsync_len = 8; - fb_var.sync = 0; - fb_var.vmode = FB_VMODE_NONINTERLACED; - - disp.var = fb_var; - disp.cmap.start = 0; - disp.cmap.len = 0; - disp.cmap.red = disp.cmap.green = disp.cmap.blue = disp.cmap.transp = NULL; - disp.screen_base = fb_fix.smem_start; - disp.visual = fb_fix.visual; - disp.type = fb_fix.type; - disp.type_aux = fb_fix.type_aux; - disp.ypanstep = 0; - disp.ywrapstep = 0; - disp.line_length = fb_fix.line_length; - disp.can_soft_blank = 1; - disp.inverse = 0; - - strcpy(fb_info.modename, "OFfb "); - strncat(fb_info.modename, dp->full_name, sizeof(fb_info.modename)); - fb_info.node = -1; - fb_info.fbops = &offb_ops; - fb_info.fbvar_num = 1; - fb_info.fbvar = &fb_var; - fb_info.disp = &disp; - fb_info.fontname[0] = '\0'; - fb_info.changevar = NULL; - fb_info.switch_con = &offbcon_switch; - fb_info.updatevar = &offbcon_updatevar; - fb_info.blank = &offbcon_blank; - fb_info.setcmap = &offbcon_setcmap; - - err = register_framebuffer(&fb_info); - if (err < 0) - return mem_start; - - offb_set_var(&fb_var, -1); - - printk("Open Firmware frame buffer device on %s\n", dp->full_name); + var->xoffset = var->yoffset = 0; + var->bits_per_pixel = 8; + var->grayscale = 0; + var->red.offset = var->green.offset = var->blue.offset = 0; + var->red.length = var->green.length = var->blue.length = 8; + var->red.msb_right = var->green.msb_right = var->blue.msb_right = 0; + var->transp.offset = var->transp.length = var->transp.msb_right = 0; + var->nonstd = 0; + var->activate = 0; + var->height = var->width = -1; + var->accel = FB_ACCEL_NONE; + var->pixclock = 10000; + var->left_margin = var->right_margin = 16; + var->upper_margin = var->lower_margin = 16; + var->hsync_len = var->vsync_len = 8; + var->sync = 0; + var->vmode = FB_VMODE_NONINTERLACED; + + disp->var = *var; + disp->cmap.start = 0; + disp->cmap.len = 0; + disp->cmap.red = disp->cmap.green = disp->cmap.blue = disp->cmap.transp = NULL; + disp->screen_base = fix->smem_start; + disp->visual = fix->visual; + disp->type = fix->type; + disp->type_aux = fix->type_aux; + disp->ypanstep = 0; + disp->ywrapstep = 0; + disp->line_length = fix->line_length; + disp->can_soft_blank = info->cmap_adr ? 1 : 0; + disp->inverse = 0; +#ifdef CONFIG_FBCON_CFB8 + disp->dispsw = &fbcon_cfb8; +#else + disp->dispsw = NULL; +#endif + + strcpy(info->info.modename, "OFfb "); + strncat(info->info.modename, dp->full_name, + sizeof(info->info.modename)); + info->info.node = -1; + info->info.fbops = &offb_ops; + info->info.disp = disp; + info->info.fontname[0] = '\0'; + info->info.changevar = NULL; + info->info.switch_con = &offbcon_switch; + info->info.updatevar = &offbcon_updatevar; + info->info.blank = &offbcon_blank; + + err = register_framebuffer(&info->info); + if (err < 0) + continue; + + for (i = 0; i < 16; i++) { + int j = color_table[i]; + info->palette[i].red = default_red[j]; + info->palette[i].green = default_grn[j]; + info->palette[i].blue = default_blu[j]; + } + offb_set_var(var, -1, &info->info); + + printk("fb%d: Open Firmware frame buffer device on %s\n", + GET_FB_IDX(info->info.node), dp->full_name); + +#ifdef CONFIG_FB_COMPAT_XPMAC + if (!console_fb_info) { + display_info.height = var->yres; + display_info.width = var->xres; + display_info.depth = 8; + display_info.pitch = fix->line_length; + display_info.mode = 0; + strncpy(display_info.name, dp->name, sizeof(display_info.name)); + display_info.fb_address = iopa((unsigned long)fix->smem_start); + display_info.cmap_adr_address = 0; + display_info.cmap_data_address = 0; + display_info.disp_reg_address = 0; + /* XXX kludge for ati */ + if (strncmp(dp->name, "ATY,", 4) == 0) { + display_info.disp_reg_address = iopa(address + 0x7ffc00); + display_info.cmap_adr_address = iopa(address + 0x7ffcc0); + display_info.cmap_data_address = iopa(address + 0x7ffcc1); + } + console_fb_info = &info->info; + console_set_cmap_ptr = offb_set_cmap; + } +#endif /* CONFIG_FB_COMPAT_XPMAC) */ + } return mem_start; } -static int offbcon_switch(int con) + /* + * Setup: parse used options + */ + +void offb_setup(char *options, int *ints) +{ + if (!options || !*options) + return; + + if (!strcmp(options, "ofonly")) + ofonly = 1; +} + + +static int offbcon_switch(int con, struct fb_info *info) { /* Do we have to save the colormap? */ if (fb_display[currcon].cmap.len) fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1, - offb_getcolreg); + offb_getcolreg, info); currcon = con; /* Install new colormap */ - do_install_cmap(con); + do_install_cmap(con, info); return 0; } @@ -365,7 +491,7 @@ static int offbcon_switch(int con) * Update the `var' structure (called by fbcon.c) */ -static int offbcon_updatevar(int con) +static int offbcon_updatevar(int con, struct fb_info *info) { /* Nothing */ return 0; @@ -375,34 +501,42 @@ static int offbcon_updatevar(int con) * Blank the display. */ -static void offbcon_blank(int blank) +static void offbcon_blank(int blank, struct fb_info *info) { - /* Nothing */ -} + struct fb_info_offb *info2 = (struct fb_info_offb *)info; + int i, j; - /* - * Set the colormap - */ + if (!info2->cmap_adr) + return; -static int offbcon_setcmap(struct fb_cmap *cmap, int con) -{ - return(offb_set_cmap(cmap, 1, con)); + if (blank) + for (i = 0; i < 256; i++) { + *info2->cmap_adr = i; + mach_eieio(); + for (j = 0; j < 3; j++) { + *info2->cmap_data = 0; + mach_eieio(); + } + } + else + do_install_cmap(currcon, info); } - /* * Read a single color register and split it into * colors/transparent. Return != 0 for invalid regno. */ static int offb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, - u_int *transp) + u_int *transp, struct fb_info *info) { - if (!unknown_cmap_adr || regno > 255) + struct fb_info_offb *info2 = (struct fb_info_offb *)info; + + if (!info2->cmap_adr || regno > 255) return 1; - *red = palette[regno].red; - *green = palette[regno].green; - *blue = palette[regno].blue; + *red = info2->palette[regno].red; + *green = info2->palette[regno].green; + *blue = info2->palette[regno].blue; return 0; } @@ -414,41 +548,113 @@ static int offb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, */ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp) + u_int transp, struct fb_info *info) { - if (!unknown_cmap_adr || regno > 255) + struct fb_info_offb *info2 = (struct fb_info_offb *)info; + + if (!info2->cmap_adr || regno > 255) return 1; - palette[regno].red = red; - palette[regno].green = green; - palette[regno].blue = blue; - *unknown_cmap_adr = regno; -#ifdef __powerpc__ - eieio(); -#endif - *unknown_cmap_data = red; -#ifdef __powerpc__ - eieio(); -#endif - *unknown_cmap_data = green; -#ifdef __powerpc__ - eieio(); -#endif - *unknown_cmap_data = blue; -#ifdef __powerpc__ - eieio(); -#endif + info2->palette[regno].red = red; + info2->palette[regno].green = green; + info2->palette[regno].blue = blue; + *info2->cmap_adr = regno; + mach_eieio(); + *info2->cmap_data = red; + mach_eieio(); + *info2->cmap_data = green; + mach_eieio(); + *info2->cmap_data = blue; + mach_eieio(); return 0; } -static void do_install_cmap(int con) +static void do_install_cmap(int con, struct fb_info *info) { if (con != currcon) return; if (fb_display[con].cmap.len) fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1, - offb_setcolreg); + offb_setcolreg, info); else - fb_set_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), - &fb_display[con].var, 1, offb_setcolreg); + fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), + &fb_display[con].var, 1, offb_setcolreg, + info); } + + +#ifdef CONFIG_FB_COMPAT_XPMAC + + /* + * Backward compatibility mode for Xpmac + * + * To do: + * + * - console_setmode() should fill in a struct fb_var_screeninfo (using + * the MacOS video mode database) and simply call a decode_var() + * function, so console_setmode_ptr is no longer needed. + * + * - instead of using the console_* stuff (filled in by the frame + * buffer), we should use the correct struct fb_info for the + * foreground virtual console. + */ + +int console_getmode(struct vc_mode *mode) +{ + *mode = display_info; + return 0; +} + +int console_setmode(struct vc_mode *mode, int doit) +{ + int err; + + if (console_setmode_ptr == NULL) + return -EINVAL; + + err = (*console_setmode_ptr)(mode, doit); + return err; +} + +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 +}; + +int console_setcmap(int n_entries, unsigned char *red, unsigned char *green, + unsigned char *blue) +{ + int i, j, n; + + if (console_set_cmap_ptr == NULL) + return -EOPNOTSUPP; + for (i = 0; i < n_entries; i += n) { + n = n_entries-i; + if (n > 16) + n = 16; + palette_cmap.start = i; + palette_cmap.len = n; + for (j = 0; j < n; j++) { + palette_cmap.red[j] = (red[i+j] << 8) | red[i+j]; + palette_cmap.green[j] = (green[i+j] << 8) | green[i+j]; + palette_cmap.blue[j] = (blue[i+j] << 8) | blue[i+j]; + } + (*console_set_cmap_ptr)(&palette_cmap, 1, fg_console, console_fb_info); + } + return 0; +} + +int console_powermode(int mode) +{ + if (mode == VC_POWERMODE_INQUIRY) + return 0; + if (mode < VESA_NO_BLANKING || mode > VESA_POWERDOWN) + return -EINVAL; + /* Not supported */ + return -ENXIO; +} + +#endif /* CONFIG_FB_COMPAT_XPMAC */ diff --git a/drivers/video/retz3fb.c b/drivers/video/retz3fb.c index 18a410614..82dcc2877 100644 --- a/drivers/video/retz3fb.c +++ b/drivers/video/retz3fb.c @@ -21,6 +21,7 @@ */ +#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -39,6 +40,10 @@ #include <asm/pgtable.h> #include "retz3fb.h" +#include "fbcon.h" +#include "fbcon-cfb8.h" +#include "fbcon-cfb16.h" + /* #define DEBUG if(1) */ #define DEBUG if(0) @@ -54,7 +59,7 @@ #define arraysize(x) (sizeof(x)/sizeof(*(x))) -struct retz3_fb_par { +struct retz3fb_par { int xres; int yres; int xres_vir; @@ -93,7 +98,7 @@ struct display_data { long v_dispend; /* Horizontal Display End */ }; -static struct retz3_fb_par current_par; +static struct retz3fb_par current_par; static int current_par_valid = 0; static int currcon = 0; @@ -114,13 +119,15 @@ static struct fb_hwswitch { /* Display Control */ - int (*encode_fix)(struct fb_fix_screeninfo *fix, struct retz3_fb_par *par); - int (*decode_var)(struct fb_var_screeninfo *var, struct retz3_fb_par *par); - int (*encode_var)(struct fb_var_screeninfo *var, struct retz3_fb_par *par); + int (*encode_fix)(struct fb_fix_screeninfo *fix, struct retz3fb_par *par); + int (*decode_var)(struct fb_var_screeninfo *var, struct retz3fb_par *par); + int (*encode_var)(struct fb_var_screeninfo *var, struct retz3fb_par *par); int (*getcolreg)(unsigned int regno, unsigned int *red, unsigned - int *green, unsigned int *blue, unsigned int *transp); + int *green, unsigned int *blue, unsigned int *transp, + struct fb_info *info); int (*setcolreg)(unsigned int regno, unsigned int red, unsigned int - green, unsigned int blue, unsigned int transp); + green, unsigned int blue, unsigned int transp, + struct fb_info *info); void (*blank)(int blank); } *fbhw; @@ -129,7 +136,7 @@ static struct fb_hwswitch { * Frame Buffer Name */ -static char retz3_fb_name[16] = "RetinaZ3"; +static char retz3fb_name[16] = "RetinaZ3"; static unsigned char retz3_color_table [256][4]; @@ -140,46 +147,6 @@ static volatile unsigned char *z3_regs; /* - * Predefined Video Mode Names - */ - -static char *retz3_fb_modenames[] = { - - /* - * Autodetect (Default) Video Mode - */ - - "default", - - /* - * Predefined Video Modes - */ - - "640x480", /* RetinaZ3 8 bpp */ - "800x600", /* RetinaZ3 8 bpp */ - "1024x768i", - "640x480-16", /* RetinaZ3 16 bpp */ - "640x480-24", /* RetinaZ3 24 bpp */ - - /* - * Dummy Video Modes - */ - - "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", - "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", - "dummy", "dummy", "dummy", "dummy", "dummy", "dummy", - - /* - * User Defined Video Modes - * - * This doesn't work yet!! - */ - - "user0", "user1", "user2", "user3", - "user4", "user5", "user6", "user7" -}; - -/* * A small info on how to convert XFree86 timing values into fb * timings - by Frank Neumann: * @@ -217,131 +184,124 @@ under "programs/Xserver/hw/xfree86/doc/modeDB.txt". */ /* - * Predefined Video Mode Definitions + * Predefined Video Modes */ -static struct fb_var_screeninfo retz3_fb_predefined[] = { - - /* - * Autodetect (Default) Video Mode - */ - - { 0, }, - - /* - * Predefined Video Modes - */ - - /* - * NB: it is very important to adjust the pixel-clock to the color-depth. - */ - - { - 640, 480, 640, 480, 0, 0, 8, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_RETINAZ3, 38461, 28, 32, 12, 10, 96, 2, - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED - }, - /* - ModeLine "800x600" 36 800 824 896 1024 600 601 603 625 - < name > DCF HR SH1 SH2 HFL VR SV1 SV2 VFL - */ - { - /* 800 x 600, 8 bpp */ - 800, 600, 800, 600, 0, 0, 8, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_RETINAZ3, 27778, 64, 24, 22, 1, 120, 2, - FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED - }, - /* - ModeLine "1024x768i" 45 1024 1064 1224 1264 768 777 785 817 interlace - < name > DCF HR SH1 SH2 HFL VR SV1 SV2 VFL - */ - { - /* 1024 x 768, 8 bpp, interlaced */ - 1024, 768, 1024, 768, 0, 0, 8, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_RETINAZ3, 22222, 40, 40, 32, 9, 160, 8, - FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED - }, - { - 640, 480, 640, 480, 0, 0, 16, 0, - {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_RETINAZ3, 38461/2, 28, 32, 12, 10, 96, 2, - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED - }, - { - 640, 480, 640, 480, 0, 0, 24, 0, - {8, 8, 8}, {8, 8, 8}, {8, 8, 8}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_RETINAZ3, 38461/3, 28, 32, 12, 10, 96, 2, - FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED - }, - - /* - * Dummy Video Modes - */ - - { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, - { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, - { 0, }, { 0, }, - - /* - * User Defined Video Modes - */ - - { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, } +static struct fb_videomode retz3fb_predefined[] __initdata = { + /* + * NB: it is very important to adjust the pixel-clock to the color-depth. + */ + + { + "640x480", { /* 640x480, 8 bpp */ + 640, 480, 640, 480, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NCR77C32BLT, 38461, 28, 32, 12, 10, 96, 2, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } + }, + /* + ModeLine "800x600" 36 800 824 896 1024 600 601 603 625 + < name > DCF HR SH1 SH2 HFL VR SV1 SV2 VFL + */ + { + "800x600", { /* 800x600, 8 bpp */ + 800, 600, 800, 600, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NCR77C32BLT, 27778, 64, 24, 22, 1, 120, 2, + FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } + }, + /* + ModeLine "1024x768i" 45 1024 1064 1224 1264 768 777 785 817 interlace + < name > DCF HR SH1 SH2 HFL VR SV1 SV2 VFL + */ + { + "1024x768i", { /* 1024x768, 8 bpp, interlaced */ + 1024, 768, 1024, 768, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NCR77C32BLT, 22222, 40, 40, 32, 9, 160, 8, + FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED + } + }, { + "640x480-16", { /* 640x480, 16 bpp */ + 640, 480, 640, 480, 0, 0, 16, 0, + {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NCR77C32BLT, 38461/2, 28, 32, 12, 10, 96, 2, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } + }, { + "640x480-24", { /* 640x480, 24 bpp */ + 640, 480, 640, 480, 0, 0, 24, 0, + {8, 8, 8}, {8, 8, 8}, {8, 8, 8}, {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NCR77C32BLT, 38461/3, 28, 32, 12, 10, 96, 2, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } + }, }; -#define NUM_TOTAL_MODES arraysize(retz3_fb_predefined) -#define NUM_PREDEF_MODES 5 +#define NUM_TOTAL_MODES arraysize(retz3fb_predefined) +static struct fb_var_screeninfo retz3fb_default; static int z3fb_inverse = 0; -static int z3fb_mode = 0; +static int z3fb_mode __initdata = 0; /* * Interface used by the world */ -void retz3_video_setup(char *options, int *ints); - -static int retz3_fb_open(int fbidx); -static int retz3_fb_release(int fbidx); -static int retz3_fb_get_fix(struct fb_fix_screeninfo *fix, int con); -static int retz3_fb_get_var(struct fb_var_screeninfo *var, int con); -static int retz3_fb_set_var(struct fb_var_screeninfo *var, int con); -static int retz3_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con); -static int retz3_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con); -static int retz3_fb_pan_display(struct fb_var_screeninfo *var, int con); -static int retz3_fb_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, int con); +void retz3fb_setup(char *options, int *ints); + +static int retz3fb_open(struct fb_info *info); +static int retz3fb_release(struct fb_info *info); +static int retz3fb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info); +static int retz3fb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int retz3fb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int retz3fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int retz3fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int retz3fb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int retz3fb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, int con, + struct fb_info *info); /* * Interface to the low level console driver */ -unsigned long retz3_fb_init(unsigned long mem_start); -static int z3fb_switch(int con); -static int z3fb_updatevar(int con); -static void z3fb_blank(int blank); -static int z3fb_setcmap(struct fb_cmap *cmap, int con); +unsigned long retz3fb_init(unsigned long mem_start); +static int z3fb_switch(int con, struct fb_info *info); +static int z3fb_updatevar(int con, struct fb_info *info); +static void z3fb_blank(int blank, struct fb_info *info); + + +/* + * Text console acceleration + */ + +#ifdef CONFIG_FBCON_CFB8 +static struct display_switch fbcon_retz3_8; +#endif /* * Accelerated Functions used by the low level console driver */ -void retz3_bitblt(struct fb_var_screeninfo *scr, - unsigned short curx, unsigned short cury, unsigned - short destx, unsigned short desty, unsigned short - width, unsigned short height, unsigned short cmd, - unsigned short mask); -void retz3_fill(unsigned short x, unsigned short y, unsigned short - width, unsigned short height, unsigned short mode, - unsigned short color); +static void retz3_bitblt(struct fb_var_screeninfo *scr, + unsigned short curx, unsigned short cury, unsigned + short destx, unsigned short desty, unsigned short + width, unsigned short height, unsigned short cmd, + unsigned short mask); /* * Hardware Specific Routines @@ -349,17 +309,17 @@ void retz3_fill(unsigned short x, unsigned short y, unsigned short static int retz3_init(void); static int retz3_encode_fix(struct fb_fix_screeninfo *fix, - struct retz3_fb_par *par); + struct retz3fb_par *par); static int retz3_decode_var(struct fb_var_screeninfo *var, - struct retz3_fb_par *par); + struct retz3fb_par *par); static int retz3_encode_var(struct fb_var_screeninfo *var, - struct retz3_fb_par *par); + struct retz3fb_par *par); static int retz3_getcolreg(unsigned int regno, unsigned int *red, unsigned int *green, unsigned int *blue, - unsigned int *transp); + unsigned int *transp, struct fb_info *info); static int retz3_setcolreg(unsigned int regno, unsigned int red, unsigned int green, unsigned int blue, - unsigned int transp); + unsigned int transp, struct fb_info *info); static void retz3_blank(int blank); @@ -367,13 +327,11 @@ static void retz3_blank(int blank); * Internal routines */ -static void retz3_fb_get_par(struct retz3_fb_par *par); -static void retz3_fb_set_par(struct retz3_fb_par *par); +static void retz3fb_get_par(struct retz3fb_par *par); +static void retz3fb_set_par(struct retz3fb_par *par); static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive); -static void do_install_cmap(int con); -/* -static void retz3_fb_set_disp(int con); -*/ +static void do_install_cmap(int con, struct fb_info *info); +static void retz3fb_set_disp(int con, struct fb_info *info); static int get_video_mode(const char *name); @@ -397,7 +355,7 @@ static unsigned short find_fq(unsigned int freq) else if (freq <= 250000000) n2 = 0; else - return(0); + return 0; do { @@ -424,10 +382,12 @@ static unsigned short find_fq(unsigned int freq) static int retz3_set_video(struct fb_var_screeninfo *var, - struct retz3_fb_par *par) + struct retz3fb_par *par) { +#if 0 float freq_f; - long freq; +#endif + unsigned int freq; int xres, hfront, hsync, hback; int yres, vfront, vsync, vback; @@ -478,7 +438,7 @@ static int retz3_set_video(struct fb_var_screeninfo *var, vback = var->upper_margin; } - data.h_total = (hback / 8) + (xres / 8) + data.h_total = (hback / 8) + (xres / 8) + (hfront / 8) + (hsync / 8) - 1 /* + 1 */; data.h_dispend = ((xres + bpp - 1)/ 8) - 1; data.h_bstart = xres / 8 /* + 1 */; @@ -736,8 +696,13 @@ static int retz3_set_video(struct fb_var_screeninfo *var, /* * Convert from ps to Hz. */ +#if 0 freq_f = (1.0/(float)var->pixclock) * 1000000000; - freq = ((long)freq_f) * 1000; + freq = ((unsigned int)freq_f) * 1000; +#else + freq = 2000000000 / var->pixclock; + freq = freq * 500; +#endif best_freq = find_fq(freq); pll_w(0x02, best_freq); @@ -791,7 +756,7 @@ static int retz3_set_video(struct fb_var_screeninfo *var, */ switch (bpp){ case 8: - reg_w(0x83c6, 0x00); + reg_w(0x83c6, 0x00); break; case 16: reg_w(0x83c6, 0x60); @@ -805,7 +770,7 @@ static int retz3_set_video(struct fb_var_screeninfo *var, reg_w(VDAC_ADDRESS, 0x00); - seq_w(SEQ_MAP_MASK, 0x0f ); + seq_w(SEQ_MAP_MASK, 0x0f ); return 0; } @@ -854,8 +819,8 @@ static int retz3_init(void) } #endif - retz3_setcolreg (255, 56, 100, 160, 0); - retz3_setcolreg (254, 0, 0, 0, 0); + retz3_setcolreg (255, 56, 100, 160, 0, NULL /* unused */); + retz3_setcolreg (254, 0, 0, 0, 0, NULL /* unused */); return 0; } @@ -867,11 +832,11 @@ static int retz3_init(void) */ static int retz3_encode_fix(struct fb_fix_screeninfo *fix, - struct retz3_fb_par *par) + struct retz3fb_par *par) { short i; - strcpy(fix->id, retz3_fb_name); + strcpy(fix->id, retz3fb_name); fix->smem_start = (char *)z3_fbmem; fix->smem_len = z3_size; fix->mmio_start = (unsigned char *)z3_regs; @@ -889,6 +854,8 @@ static int retz3_encode_fix(struct fb_fix_screeninfo *fix, fix->ywrapstep = 0; fix->line_length = 0; + fix->accel = FB_ACCEL_NCR77C32BLT; + for (i = 0; i < arraysize(fix->reserved); i++) fix->reserved[i] = 0; @@ -902,7 +869,7 @@ static int retz3_encode_fix(struct fb_fix_screeninfo *fix, */ static int retz3_decode_var(struct fb_var_screeninfo *var, - struct retz3_fb_par *par) + struct retz3fb_par *par) { par->xres = var->xres; par->yres = var->yres; @@ -934,7 +901,7 @@ static int retz3_decode_var(struct fb_var_screeninfo *var, */ static int retz3_encode_var(struct fb_var_screeninfo *var, - struct retz3_fb_par *par) + struct retz3fb_par *par) { short i; @@ -959,7 +926,7 @@ static int retz3_encode_var(struct fb_var_screeninfo *var, var->height = -1; var->width = -1; - var->accel = FB_ACCEL_RETINAZ3; + var->accel = FB_ACCEL_NCR77C32BLT; var->pixclock = par->pixclock; @@ -987,7 +954,7 @@ static int retz3_encode_var(struct fb_var_screeninfo *var, static int retz3_setcolreg(unsigned int regno, unsigned int red, unsigned int green, unsigned int blue, - unsigned int transp) + unsigned int transp, struct fb_info *info) { /* We'll get to this */ @@ -1015,7 +982,7 @@ static int retz3_setcolreg(unsigned int regno, unsigned int red, static int retz3_getcolreg(unsigned int regno, unsigned int *red, unsigned int *green, unsigned int *blue, - unsigned int *transp) + unsigned int *transp, struct fb_info *info) { if (regno > 255) return 1; @@ -1052,11 +1019,11 @@ void retz3_blank(int blank) } -void retz3_bitblt (struct fb_var_screeninfo *var, - unsigned short srcx, unsigned short srcy, unsigned - short destx, unsigned short desty, unsigned short - width, unsigned short height, unsigned short cmd, - unsigned short mask) +static void retz3_bitblt (struct fb_var_screeninfo *var, + unsigned short srcx, unsigned short srcy, + unsigned short destx, unsigned short desty, + unsigned short width, unsigned short height, + unsigned short cmd, unsigned short mask) { volatile unsigned long *acm = (unsigned long *) (z3_mem + ACM_OFFSET); @@ -1129,7 +1096,7 @@ void retz3_bitblt (struct fb_var_screeninfo *var, *(acm + ACM_CONTROL/4) = tmp; tmp = width | (height << 16); - + *(acm + ACM_BITMAP_DIMENSION/4) = cpu_to_le32(tmp); *(((volatile unsigned char *)acm) + ACM_START_STATUS) = 0x00; @@ -1154,20 +1121,10 @@ void retz3_bitblt (struct fb_var_screeninfo *var, } #if 0 -void retz3_fill (unsigned short x, unsigned short y, unsigned - short width, unsigned short height, - unsigned short mode, unsigned short color) -{ - -} -#endif - - -#if 0 /* * Move cursor to x, y */ -void retz3_MoveCursor (unsigned short x, unsigned short y) +static void retz3_MoveCursor (unsigned short x, unsigned short y) { /* Guess we gotta deal with the cursor at some point */ } @@ -1189,16 +1146,16 @@ static struct fb_hwswitch retz3_switch = { * Fill the hardware's `par' structure. */ -static void retz3_fb_get_par(struct retz3_fb_par *par) +static void retz3fb_get_par(struct retz3fb_par *par) { if (current_par_valid) *par = current_par; else - fbhw->decode_var(&retz3_fb_predefined[z3fb_mode], par); + fbhw->decode_var(&retz3fb_default, par); } -static void retz3_fb_set_par(struct retz3_fb_par *par) +static void retz3fb_set_par(struct retz3fb_par *par) { current_par = *par; current_par_valid = 1; @@ -1208,7 +1165,7 @@ static void retz3_fb_set_par(struct retz3_fb_par *par) static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive) { int err, activate; - struct retz3_fb_par par; + struct retz3fb_par par; if ((err = fbhw->decode_var(var, &par))) return err; @@ -1217,7 +1174,7 @@ static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive) /* XXX ... what to do about isactive ? */ if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive) - retz3_fb_set_par(&par); + retz3fb_set_par(&par); fbhw->encode_var(var, &par); var->activate = activate; @@ -1227,17 +1184,17 @@ static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive) } -static void do_install_cmap(int con) +static void do_install_cmap(int con, struct fb_info *info) { if (con != currcon) return; if (fb_display[con].cmap.len) fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1, - fbhw->setcolreg); + fbhw->setcolreg, info); else - fb_set_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), + fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), &fb_display[con].var, 1, - fbhw->setcolreg); + fbhw->setcolreg, info); } @@ -1245,7 +1202,7 @@ static void do_install_cmap(int con) * Open/Release the frame buffer device */ -static int retz3_fb_open(int fbidx) +static int retz3fb_open(struct fb_info *info) { /* * Nothing, only a usage count for the moment @@ -1255,7 +1212,7 @@ static int retz3_fb_open(int fbidx) return 0; } -static int retz3_fb_release(int fbidx) +static int retz3fb_release(struct fb_info *info) { MOD_DEC_USE_COUNT; return 0; @@ -1266,13 +1223,14 @@ static int retz3_fb_release(int fbidx) * Get the Fixed Part of the Display */ -static int retz3_fb_get_fix(struct fb_fix_screeninfo *fix, int con) +static int retz3fb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) { - struct retz3_fb_par par; + struct retz3fb_par par; int error = 0; if (con == -1) - retz3_fb_get_par(&par); + retz3fb_get_par(&par); else error = fbhw->decode_var(&fb_display[con].var, &par); return(error ? error : fbhw->encode_fix(fix, &par)); @@ -1283,13 +1241,14 @@ static int retz3_fb_get_fix(struct fb_fix_screeninfo *fix, int con) * Get the User Defined Part of the Display */ -static int retz3_fb_get_var(struct fb_var_screeninfo *var, int con) +static int retz3fb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) { - struct retz3_fb_par par; + struct retz3fb_par par; int error = 0; if (con == -1) { - retz3_fb_get_par(&par); + retz3fb_get_par(&par); error = fbhw->encode_var(var, &par); } else *var = fb_display[con].var; @@ -1298,7 +1257,7 @@ static int retz3_fb_get_var(struct fb_var_screeninfo *var, int con) #if 1 -static void retz3_fb_set_disp(int con) +static void retz3fb_set_disp(int con, struct fb_info *info) { struct fb_fix_screeninfo fix; struct display *display; @@ -1308,7 +1267,7 @@ static void retz3_fb_set_disp(int con) else display = &disp; /* used during initialization */ - retz3_fb_get_fix(&fix, con); + retz3fb_get_fix(&fix, con, info); if (con == -1) con = 0; @@ -1321,6 +1280,21 @@ static void retz3_fb_set_disp(int con) display->ywrapstep = fix.ywrapstep; display->can_soft_blank = 1; display->inverse = z3fb_inverse; + switch (display->var.bits_per_pixel) { +#ifdef CONFIG_FBCON_CFB8 + case 8: + display->dispsw = &fbcon_retz3_8; + break; +#endif +#ifdef CONFIG_FBCON_CFB16 + case 16: + display->dispsw = &fbcon_cfb16; + break; +#endif + default: + display->dispsw = NULL; + break; + } } #endif @@ -1328,7 +1302,8 @@ static void retz3_fb_set_disp(int con) * Set the User Defined Part of the Display */ -static int retz3_fb_set_var(struct fb_var_screeninfo *var, int con) +static int retz3fb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) { int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp; struct display *display; @@ -1359,7 +1334,7 @@ static int retz3_fb_set_var(struct fb_var_screeninfo *var, int con) oldbpp != var->bits_per_pixel) { struct fb_fix_screeninfo fix; - retz3_fb_get_fix(&fix, con); + retz3fb_get_fix(&fix, con, info); display->screen_base = fix.smem_start; display->visual = fix.visual; @@ -1370,8 +1345,23 @@ static int retz3_fb_set_var(struct fb_var_screeninfo *var, int con) display->line_length = fix.line_length; display->can_soft_blank = 1; display->inverse = z3fb_inverse; + switch (display->var.bits_per_pixel) { +#ifdef CONFIG_FBCON_CFB8 + case 8: + display->dispsw = &fbcon_retz3_8; + break; +#endif +#ifdef CONFIG_FBCON_CFB16 + case 16: + display->dispsw = &fbcon_cfb16; + break; +#endif + default: + display->dispsw = NULL; + break; + } /* - retz3_fb_set_disp(con); + retz3fb_set_disp(con, info); */ if (fb_info.changevar) (*fb_info.changevar)(con); @@ -1380,7 +1370,7 @@ static int retz3_fb_set_var(struct fb_var_screeninfo *var, int con) if (oldbpp != var->bits_per_pixel) { if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) return err; - do_install_cmap(con); + do_install_cmap(con, info); } } return 0; @@ -1391,15 +1381,16 @@ static int retz3_fb_set_var(struct fb_var_screeninfo *var, int con) * Get the Colormap */ -static int retz3_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con) +static int retz3fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) { if (con == currcon) /* current console? */ return(fb_get_cmap(cmap, &fb_display[con].var, kspc, - fbhw->getcolreg)); + fbhw->getcolreg, info)); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else - fb_copy_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), + fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), cmap, kspc ? 0 : 2); return 0; } @@ -1409,7 +1400,8 @@ static int retz3_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con) * Set the Colormap */ -static int retz3_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con) +static int retz3fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) { int err; @@ -1421,7 +1413,7 @@ static int retz3_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con) } if (con == currcon) /* current console? */ return(fb_set_cmap(cmap, &fb_display[con].var, kspc, - fbhw->setcolreg)); + fbhw->setcolreg, info)); else fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); return 0; @@ -1434,7 +1426,8 @@ static int retz3_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con) * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag */ -static int retz3_fb_pan_display(struct fb_var_screeninfo *var, int con) +static int retz3fb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) { return -EINVAL; } @@ -1444,21 +1437,22 @@ static int retz3_fb_pan_display(struct fb_var_screeninfo *var, int con) * RetinaZ3 Frame Buffer Specific ioctls */ -static int retz3_fb_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, int con) +static int retz3fb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, int con, + struct fb_info *info) { return -EINVAL; } -static struct fb_ops retz3_fb_ops = { - retz3_fb_open, retz3_fb_release, retz3_fb_get_fix, retz3_fb_get_var, - retz3_fb_set_var, retz3_fb_get_cmap, retz3_fb_set_cmap, - retz3_fb_pan_display, retz3_fb_ioctl +static struct fb_ops retz3fb_ops = { + retz3fb_open, retz3fb_release, retz3fb_get_fix, retz3fb_get_var, + retz3fb_set_var, retz3fb_get_cmap, retz3fb_set_cmap, + retz3fb_pan_display, NULL, retz3fb_ioctl }; -__initfunc(void retz3_video_setup(char *options, int *ints)) +__initfunc(void retz3fb_setup(char *options, int *ints)) { char *this_opt; @@ -1467,7 +1461,7 @@ __initfunc(void retz3_video_setup(char *options, int *ints)) if (!options || !*options) return; - for (this_opt = strtok(options, ","); this_opt; + for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ",")){ if (!strcmp(this_opt, "inverse")) { z3fb_inverse = 1; @@ -1484,14 +1478,14 @@ __initfunc(void retz3_video_setup(char *options, int *ints)) * Initialization */ -__initfunc(unsigned long retz3_fb_init(unsigned long mem_start)) +__initfunc(unsigned long retz3fb_init(unsigned long mem_start)) { int err; unsigned long board_addr, board_size; unsigned int key; const struct ConfigDev *cd; - struct retz3_fb_par par; + struct retz3fb_par par; if (!(key = zorro_find(ZORRO_PROD_MACROSYSTEMS_RETINA_Z3, 0, 0))) return mem_start; @@ -1511,43 +1505,38 @@ __initfunc(unsigned long retz3_fb_init(unsigned long mem_start)) z3_size = 0x00400000; /* 4 MB */ - memset ((char*)z3_fbmem, 0, z3_size); - fbhw = &retz3_switch; fbhw->init(); - strcpy(fb_info.modename, retz3_fb_name); + strcpy(fb_info.modename, retz3fb_name); fb_info.changevar = NULL; fb_info.node = -1; - fb_info.fbops = &retz3_fb_ops; - fb_info.fbvar_num = NUM_TOTAL_MODES; - fb_info.fbvar = retz3_fb_predefined; + fb_info.fbops = &retz3fb_ops; fb_info.disp = &disp; fb_info.switch_con = &z3fb_switch; fb_info.updatevar = &z3fb_updatevar; fb_info.blank = &z3fb_blank; - fb_info.setcmap = &z3fb_setcmap; err = register_framebuffer(&fb_info); if (err < 0) return mem_start; if (z3fb_mode == -1) - z3fb_mode = 1; + retz3fb_default = retz3fb_predefined[0].var; - fbhw->decode_var(&retz3_fb_predefined[z3fb_mode], &par); - fbhw->encode_var(&retz3_fb_predefined[0], &par); + fbhw->decode_var(&retz3fb_default, &par); + fbhw->encode_var(&retz3fb_default, &par); - do_fb_set_var(&retz3_fb_predefined[0], 0); - retz3_fb_get_var(&disp.var, -1); + do_fb_set_var(&retz3fb_default, 0); + retz3fb_get_var(&disp.var, -1, &fb_info); - retz3_fb_set_disp(-1); + retz3fb_set_disp(-1, &fb_info); - do_install_cmap(0); + do_install_cmap(0, &fb_info); - printk("%s frame buffer device, using %ldK of video memory\n", - fb_info.modename, z3_size>>10); + printk("fb%d: %s frame buffer device, using %ldK of video memory\n", + GET_FB_IDX(fb_info.node), fb_info.modename, z3_size>>10); /* TODO: This driver cannot be unloaded yet */ MOD_INC_USE_COUNT; @@ -1556,17 +1545,18 @@ __initfunc(unsigned long retz3_fb_init(unsigned long mem_start)) } -static int z3fb_switch(int con) +static int z3fb_switch(int con, struct fb_info *info) { /* Do we have to save the colormap? */ if (fb_display[currcon].cmap.len) fb_get_cmap(&fb_display[currcon].cmap, - &fb_display[currcon].var, 1, fbhw->getcolreg); + &fb_display[currcon].var, 1, fbhw->getcolreg, + info); do_fb_set_var(&fb_display[con].var, 1); currcon = con; /* Install new colormap */ - do_install_cmap(con); + do_install_cmap(con, info); return 0; } @@ -1578,7 +1568,7 @@ static int z3fb_switch(int con) * Since it's called by a kernel driver, no range checking is done. */ -static int z3fb_updatevar(int con) +static int z3fb_updatevar(int con, struct fb_info *info) { return 0; } @@ -1588,33 +1578,23 @@ static int z3fb_updatevar(int con) * Blank the display. */ -static void z3fb_blank(int blank) +static void z3fb_blank(int blank, struct fb_info *info) { fbhw->blank(blank); } /* - * Set the colormap - */ - -static int z3fb_setcmap(struct fb_cmap *cmap, int con) -{ - return(retz3_fb_set_cmap(cmap, 1, con)); -} - - -/* * Get a Video Mode */ -static int get_video_mode(const char *name) +__initfunc(static int get_video_mode(const char *name)) { short i; - for (i = 1; i <= NUM_PREDEF_MODES; i++) - if (!strcmp(name, retz3_fb_modenames[i])){ - retz3_fb_predefined[0] = retz3_fb_predefined[i]; + for (i = 0; i <= NUM_TOTAL_MODES; i++) + if (!strcmp(name, retz3fb_predefined[i].name)){ + retz3fb_default = retz3fb_predefined[i].var; return i; } return -1; @@ -1624,7 +1604,7 @@ static int get_video_mode(const char *name) #ifdef MODULE int init_module(void) { - return(retz3_fb_init(NULL)); + return(retz3fb_init(NULL)); } void cleanup_module(void) @@ -1636,11 +1616,60 @@ void cleanup_module(void) unregister_framebuffer(&fb_info); /* TODO: clean up ... */ } -#endif /* MODULE */ +#endif /* - * Visible symbols for modules + * Text console acceleration */ -EXPORT_SYMBOL(retz3_bitblt); +#ifdef CONFIG_FBCON_CFB8 +static void fbcon_retz3_8_bmove(struct display *p, int sy, int sx, int dy, int dx, + int height, int width) +{ + int fontwidth = p->fontwidth; + + sx *= fontwidth; + dx *= fontwidth; + width *= fontwidth; + + retz3_bitblt(&p->var, + (unsigned short)sx, + (unsigned short)(sy*p->fontheight), + (unsigned short)dx, + (unsigned short)(dy*p->fontheight), + (unsigned short)width, + (unsigned short)(height*p->fontheight), + Z3BLTcopy, + 0xffff); +} + +static void fbcon_retz3_8_clear(struct vc_data *conp, struct display *p, int + sy, int sx, int height, int width) +{ + unsigned short col; + int fontwidth = p->fontwidth; + + sx *= fontwidth; + width *= fontwidth; + + col = attr_bgcol_ec(p, conp); + col &= 0xff; + col |= (col << 8); + + retz3_bitblt(&p->var, + (unsigned short)sx, + (unsigned short)(sy*p->fontheight), + (unsigned short)sx, + (unsigned short)(sy*p->fontheight), + (unsigned short)width, + (unsigned short)(height*p->fontheight), + Z3BLTset, + col); +} + +static struct display_switch fbcon_retz3_8 = { + fbcon_cfb8_setup, fbcon_retz3_8_bmove, fbcon_retz3_8_clear, + fbcon_cfb8_putc, fbcon_cfb8_putcs, fbcon_cfb8_revc +}; +#endif diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c new file mode 100644 index 000000000..3f795cd63 --- /dev/null +++ b/drivers/video/skeletonfb.c @@ -0,0 +1,388 @@ +/* + * linux/drivers/video/skeletonfb.c -- Skeleton for a frame buffer device + * + * Created 28 Dec 1997 by Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file README.legal in the main directory of this archive + * for more details. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/tty.h> +#include <linux/malloc.h> +#include <linux/delay.h> +#include <linux/fb.h> + +#include "fbcon.h" + + + /* + * This is just simple sample code. + * + * No warranty that it actually compiles. + * Even less warranty that it actually works :-) + */ + + +struct xxxfb_info { + /* + * Choose _one_ of the two alternatives: + * + * 1. Use the generic frame buffer operations (fbgen_*). + */ + struct fb_info_gen gen; + /* + * 2. Provide your own frame buffer operations. + */ + struct fb_info info; + + /* Here starts the frame buffer device dependent part */ + /* You can use this to store e.g. the board number if you support */ + /* multiple boards */ +}; + + +struct xxxfb_par { + /* + * The hardware specific data in this structure uniquely defines a video + * mode. + * + * If your hardware supports only one video mode, you can leave it empty. + */ +}; + + + /* + * If your driver supports multiple boards, you should make these arrays, + * or allocate them dynamically (using mem_start for builtin drivers, and + * kmalloc() for loaded modules). + */ + +static struct xxxfb_info fb_info; +static struct xxxfb_par current_par; +static int current_par_valid = 0; +static struct display disp; + +static struct fb_var_screeninfo default_var; + +static int currcon = 0; +static int inverse = 0; + + +/* ------------------- chipset specific functions -------------------------- */ + + +static void xxx_detect(void) +{ + /* + * This function should detect the current video mode settings and store + * it as the default video mode + */ + + /* ... */ + xxx_get_par(&par); + xxx_encode_var(&default_var, &par); +} + +static int xxx_encode_fix(struct fb_fix_screeninfo *fix, struct xxxfb_par *par, + const struct fb_info *fb_info) +{ + /* + * This function should fill in the 'fix' structure based on the values + * in the `par' structure. + */ + + /* ... */ + return 0; +} + +static int xxx_decode_var(struct fb_var_screeninfo *var, struct xxxfb_par *par, + const struct fb_info *fb_info) +{ + /* + * Get the video params out of 'var'. If a value doesn't fit, round it up, + * if it's too big, return -EINVAL. + * + * Suggestion: Round up in the following order: bits_per_pixel, xres, + * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale, + * bitfields, horizontal timing, vertical timing. + */ + + /* ... */ + + /* pixclock in picos, htotal in pixels, vtotal in scanlines */ + if (!fbmon_valid_timings(pixclock, htotal, vtotal, info)) + return -EINVAL; + + return 0; +} + +static int xxx_encode_var(struct fb_var_screeninfo *var, struct xxxfb_par *par, + const struct fb_info *fb_info) +{ + /* + * Fill the 'var' structure based on the values in 'par' and maybe other + * values read out of the hardware. + */ + + /* ... */ + return 0; +} + +static void xxx_get_par(struct xxxfb_par *par, const struct fb_info *fb_info) +{ + /* + * Fill the hardware's 'par' structure. + */ + + if (current_par_valid) + *par = current_par; + else { + /* ... */ + } +} + +static void xxx_set_par(struct xxxfb_par *par, const struct fb_info *fb_info) +{ + /* + * Set the hardware according to 'par'. + */ + + current_par = *par; + current_par_valid = 1; + /* ... */ +} + +static int xxx_getcolreg(unsigned regno, unsigned *red, unsigned *green, + unsigned *blue, unsigned *transp, + const struct fb_info *fb_info) +{ + /* + * Read a single color register and split it into colors/transparent. + * Return != 0 for invalid regno. + */ + + /* ... */ + return 0; +} + +static int xxx_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + const struct fb_info *fb_info) +{ + /* + * Set a single color register. The values supplied are already rounded + * down to the hardware's capabilities (according to the entries in the + * `var' structure). Return != 0 for invalid regno. + */ + + if (regno < 16) { + /* + * Make the first 16 colors of the palette available to fbcon + */ + if (is_cfb15) /* RGB 555 */ + fbcon_cfb15_cmap[regno] = be16_to_cpu((red << 10) | (green << 5) | + blue); + if (is_cfb16) /* RGB 565 */ + fbcon_cfb16_cmap[regno] = be16_to_cpu((red << 11) | (green << 5) | + blue); + if (is_cfb24) /* RGB 888 */ + fbcon_cfb24_cmap[regno] = be32_to_cpu((red << 16) | (green << 8) | + blue); + if (is_cfb32) /* RGBA 8888 */ + fbcon_cfb32_cmap[regno] = be32_to_cpu((red << 24) | (green << 16) | + (blue << 8) | transp); + } + /* ... */ + return 0; +} + +static int xxx_pan_display(struct fb_var_screeninfo *var, + struct xxxfb_par *par, + const struct fb_info *fb_info) +{ + /* + * Pan (or wrap, depending on the `vmode' field) the display using the + * `xoffset' and `yoffset' fields of the `var' structure. + * If the values don't fit, return -EINVAL. + */ + + /* ... */ + return 0; +} + +static int xxx_blank(int blank_mode, const struct fb_info *fb_info) +{ + /* + * Blank the screen if blank_mode != 0, else unblank. If blank == NULL + * then the caller blanks by setting the CLUT (Color Look Up Table) to all + * black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due + * to e.g. a video mode which doesn't support it. Implements VESA suspend + * and powerdown modes on hardware that supports disabling hsync/vsync: + * blank_mode == 2: suspend vsync + * blank_mode == 3: suspend hsync + * blank_mode == 4: powerdown + */ + + /* ... */ + return 0; +} + +static struct display_switch *xxx_get_dispsw(const void *par, + struct fb_info_gen *info) +{ + /* + * Return a pointer to appropriate low level text console operations for + * the video mode `par' of your video hardware. These can be generic + * software routines, or hardware accelerated routines specifically + * tailored for your hardware. + * If you don't have any appropriate operations, simple fill in the NULL + * pointer, and there will be no text output. + */ +#ifdef CONFIG_FBCON_CFB8 + if (is_cfb8) + return &fbcon_cfb8; +#endif +#ifdef CONFIG_FBCON_CFB16 + if (is_cfb16) + return &fbcon_cfb16; +#endif +#ifdef CONFIG_FBCON_CFB32 + if (is_cfb32) + return &fbcon_cfb32; +#endif + return NULL; +} + + +/* ------------ Interfaces to hardware functions ------------ */ + + +struct fbgen_hwswitch xxx_switch = { + xxx_detect, xxx_encode_fix, xxx_decode_var, xxx_encode_var, xxx_get_par, + xxx_set_par, xxx_getcolreg, xxx_setcolreg, xxx_blank, xxx_dispsw +}; + + + +/* ------------ Hardware Independant Functions ------------ */ + + + /* + * Initialization + */ + +__initfunc(unsigned long xxxfb_init(unsigned long mem_start)) +{ + int err; + struct fb_var_screeninfo var; + + fb_info.fbhw = &xxx_switch; + fbhw->detect(); + strcpy(fb_info.modename, "XXX"); + fb_info.changevar = NULL; + fb_info.node = -1; + fb_info.fbops = &xxxfb_ops; + fb_info.disp = disp; + fb_info.switch_con = &xxxfb_switch; + fb_info.updatevar = &xxxfb_update_var; + fb_info.blank = &xxxfb_blank; + /* This should give a reasonable default video mode */ + fbgen_get_var(&disp.var, -1, &fb_info.gen); + fbgen_do_set_var(var, 1, &fbinfo.gen); + err = register_framebuffer(&fb_info.gen.info); + if (err < 0) + return err; + fbgen_set_disp(-1, &fb_info.gen.info); + fbgen_install_cmap(0, &fb_info.gen); + printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node), + fb_info.modename); + + /* uncomment this if your driver cannot be unloaded */ + /* MOD_INC_USE_COUNT; */ + + return mem_start; +} + + + /* + * Cleanup + */ + +void xxxfb_cleanup(struct fb_info *info) +{ + /* + * If your driver supports multiple boards, you should unregister and + * clean up all instances. + */ + + unregister_framebuffer(&fb_info); + /* ... */ +} + + + /* + * Setup + */ + +__initfunc(void xxxfb_setup(char *options, int *ints)) +{ + /* Parse user speficied options (`video=xxxfb:') */ +} + + +/* ------------------------------------------------------------------------- */ + + + /* + * Frame buffer operations + */ + +static int xxxfb_open(const struct fb_info *info) +{ + /* Nothing, only a usage count for the moment */ + MOD_INC_USE_COUNT; + return 0; +} + +static int xxxfb_release(const struct fb_info *info) +{ + MOD_DEC_USE_COUNT; + return 0; +} + + + /* + * In most cases the `generic' routines (fbgen_*) should be satisfactory. + * However, you're free to fill in your own replacements. + */ + +static struct fb_ops xxxfb_ops = { + xxxfb_open, xxxfb_release, fbgen_get_fix, fbgen_get_var, fbgen_set_var, + fbgen_get_cmap, fbgen_set_cmap, fbgen_pan_display, NULL, fbgen_ioctl +}; + + +/* ------------------------------------------------------------------------- */ + + + /* + * Modularization + */ + +#ifdef MODULE +int init_module(void) +{ + return xxxfb_init(NULL); +} + +void cleanup_module(void) +{ + xxxfb_cleanup(void); +} +#endif /* MODULE */ diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c index ac3746109..7e74f7449 100644 --- a/drivers/video/tgafb.c +++ b/drivers/video/tgafb.c @@ -17,13 +17,12 @@ * * - How to set a single color register? * - * - We don't have support for CFB32 yet (fbcon-cfb32.c) - * * - Hardware cursor (useful for other graphics boards too) * * KNOWN PROBLEMS/TO DO ==================================================== */ +#include <linux/config.h> #include <linux/module.h> #include <linux/sched.h> #include <linux/kernel.h> @@ -37,11 +36,13 @@ #include <linux/interrupt.h> #include <linux/fb.h> #include <linux/init.h> -#include <linux/bios32.h> #include <linux/pci.h> #include <linux/selection.h> #include <asm/io.h> +#include "fbcon-cfb8.h" +#include "fbcon-cfb32.h" + /* TGA hardware description (minimal) */ /* @@ -188,10 +189,17 @@ static unsigned int base_addr_presets[4] __initdata = { unsigned char PLLbits[7] __initdata = { 0x80, 0x04, 0x00, 0x24, 0x44, 0x80, 0xb8 }; const unsigned long bt485_cursor_source[64] __initdata = { +#if 1 + 0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000, + 0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000, + 0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000, + 0x0000000000000000,0x0000000000000000,0x0000000000000000,0x0000000000000000, +#else 0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff, 0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff, 0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff, 0x00000000000000ff,0x00000000000000ff,0x00000000000000ff,0x00000000000000ff, +#endif 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 @@ -235,9 +243,8 @@ static int currcon = 0; static struct display disp; static struct fb_info fb_info; static struct { u_char red, green, blue, pad; } palette[256]; -static char tgafb_name[16] = "DEC TGA "; -static struct fb_fix_screeninfo fb_fix; +static struct fb_fix_screeninfo fb_fix = { { "DEC TGA ", } }; static struct fb_var_screeninfo fb_var = { 0, }; @@ -245,18 +252,22 @@ static struct fb_var_screeninfo fb_var = { 0, }; * Interface used by the world */ -void tgafb_video_setup(char *options, int *ints); - -static int tgafb_open(int fbidx); -static int tgafb_release(int fbidx); -static int tgafb_get_fix(struct fb_fix_screeninfo *fix, int con); -static int tgafb_get_var(struct fb_var_screeninfo *var, int con); -static int tgafb_set_var(struct fb_var_screeninfo *var, int con); -static int tgafb_pan_display(struct fb_var_screeninfo *var, int con); -static int tgafb_get_cmap(struct fb_cmap *cmap, int kspc, int con); -static int tgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con); +static int tgafb_open(struct fb_info *info); +static int tgafb_release(struct fb_info *info); +static int tgafb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info); +static int tgafb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int tgafb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int tgafb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int tgafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int tgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); static int tgafb_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg, int con); + u_long arg, int con, struct fb_info *info); /* @@ -264,10 +275,9 @@ static int tgafb_ioctl(struct inode *inode, struct file *file, u_int cmd, */ unsigned long tgafb_init(unsigned long mem_start); -static int tgafbcon_switch(int con); -static int tgafbcon_updatevar(int con); -static void tgafbcon_blank(int blank); -static int tgafbcon_setcmap(struct fb_cmap *cmap, int con); +static int tgafbcon_switch(int con, struct fb_info *info); +static int tgafbcon_updatevar(int con, struct fb_info *info); +static void tgafbcon_blank(int blank, struct fb_info *info); /* @@ -275,18 +285,18 @@ static int tgafbcon_setcmap(struct fb_cmap *cmap, int con); */ static int tgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, - u_int *transp); + u_int *transp, struct fb_info *info); static int tgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp); + u_int transp, struct fb_info *info); #if 1 static void tga_update_palette(void); #endif -static void do_install_cmap(int con); +static void do_install_cmap(int con, struct fb_info *info); static struct fb_ops tgafb_ops = { tgafb_open, tgafb_release, tgafb_get_fix, tgafb_get_var, tgafb_set_var, - tgafb_get_cmap, tgafb_set_cmap, tgafb_pan_display, tgafb_ioctl + tgafb_get_cmap, tgafb_set_cmap, tgafb_pan_display, NULL, tgafb_ioctl }; @@ -294,7 +304,7 @@ static struct fb_ops tgafb_ops = { * Open/Release the frame buffer device */ -static int tgafb_open(int fbidx) +static int tgafb_open(struct fb_info *info) { /* * Nothing, only a usage count for the moment @@ -304,7 +314,7 @@ static int tgafb_open(int fbidx) return(0); } -static int tgafb_release(int fbidx) +static int tgafb_release(struct fb_info *info) { MOD_DEC_USE_COUNT; return(0); @@ -315,7 +325,8 @@ static int tgafb_release(int fbidx) * Get the Fixed Part of the Display */ -static int tgafb_get_fix(struct fb_fix_screeninfo *fix, int con) +static int tgafb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) { memcpy(fix, &fb_fix, sizeof(fb_fix)); return 0; @@ -326,7 +337,8 @@ static int tgafb_get_fix(struct fb_fix_screeninfo *fix, int con) * Get the User Defined Part of the Display */ -static int tgafb_get_var(struct fb_var_screeninfo *var, int con) +static int tgafb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) { memcpy(var, &fb_var, sizeof(fb_var)); return 0; @@ -337,7 +349,8 @@ static int tgafb_get_var(struct fb_var_screeninfo *var, int con) * Set the User Defined Part of the Display */ -static int tgafb_set_var(struct fb_var_screeninfo *var, int con) +static int tgafb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) { struct display *display; int oldbpp = -1, err; @@ -363,7 +376,7 @@ static int tgafb_set_var(struct fb_var_screeninfo *var, int con) if (oldbpp != var->bits_per_pixel) { if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) return err; - do_install_cmap(con); + do_install_cmap(con, info); } return 0; } @@ -375,7 +388,8 @@ static int tgafb_set_var(struct fb_var_screeninfo *var, int con) * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag */ -static int tgafb_pan_display(struct fb_var_screeninfo *var, int con) +static int tgafb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) { if (var->xoffset || var->yoffset) return -EINVAL; @@ -387,14 +401,16 @@ static int tgafb_pan_display(struct fb_var_screeninfo *var, int con) * Get the Colormap */ -static int tgafb_get_cmap(struct fb_cmap *cmap, int kspc, int con) +static int tgafb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) { if (con == currcon) /* current console? */ - return fb_get_cmap(cmap, &fb_display[con].var, kspc, tgafb_getcolreg); + return fb_get_cmap(cmap, &fb_display[con].var, kspc, tgafb_getcolreg, + info); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else - fb_copy_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), + fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), cmap, kspc ? 0 : 2); return 0; } @@ -403,7 +419,8 @@ static int tgafb_get_cmap(struct fb_cmap *cmap, int kspc, int con) * Set the Colormap */ -static int tgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con) +static int tgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) { int err; @@ -413,7 +430,8 @@ static int tgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con) return err; } if (con == currcon) { /* current console? */ - err = fb_set_cmap(cmap, &fb_display[con].var, kspc, tgafb_setcolreg); + err = fb_set_cmap(cmap, &fb_display[con].var, kspc, tgafb_setcolreg, + info); #if 1 tga_update_palette(); #endif @@ -425,7 +443,7 @@ static int tgafb_set_cmap(struct fb_cmap *cmap, int kspc, int con) static int tgafb_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg, int con) + u_long arg, int con, struct fb_info *info) { return -EINVAL; } @@ -437,22 +455,14 @@ static int tgafb_ioctl(struct inode *inode, struct file *file, u_int cmd, __initfunc(unsigned long tgafb_init(unsigned long mem_start)) { - unsigned char pci_bus, pci_devfn; - int status; int i, j, temp, err; unsigned char *cbp; + struct pci_dev *pdev; - status = pcibios_find_device (PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, - 0, &pci_bus, &pci_devfn); - if (status == PCIBIOS_DEVICE_NOT_FOUND) + pdev = pci_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TGA, NULL); + if (!pdev) return mem_start; - - /* - * read BASE_REG_0 for memory address - */ - pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_0, - &tga_mem_base); - tga_mem_base &= ~15; + tga_mem_base = pdev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK; #ifdef DEBUG printk("tgafb_init: mem_base 0x%x\n", tga_mem_base); #endif /* DEBUG */ @@ -460,19 +470,18 @@ __initfunc(unsigned long tgafb_init(unsigned long mem_start)) tga_type = (readl((unsigned long)tga_mem_base) >> 12) & 0x0f; switch (tga_type) { case 0: - strcat(tgafb_name, "8plane"); + strcat(fb_fix.id, "8plane"); break; case 1: - strcat(tgafb_name, "24plane"); + strcat(fb_fix.id, "24plane"); break; case 3: - strcat(tgafb_name, "24plusZ"); + strcat(fb_fix.id, "24plusZ"); break; default: printk("TGA type (0x%x) unrecognized!\n", tga_type); return mem_start; } - strcpy(fb_fix.id, tgafb_name); tga_regs_base = ((unsigned long)tga_mem_base + TGA_REGS_OFFSET); tga_fb_base = ((unsigned long)tga_mem_base + fb_offset_presets[tga_type]); @@ -537,6 +546,9 @@ __initfunc(unsigned long tgafb_init(unsigned long mem_start)) TGA_WRITE_REG(default_red[j]|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG); TGA_WRITE_REG(default_grn[j]|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG); TGA_WRITE_REG(default_blu[j]|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG); + palette[i].red=default_red[j]; + palette[i].green=default_grn[j]; + palette[i].blue=default_blu[j]; } for (i = 0; i < 240*3; i += 4) { TGA_WRITE_REG(0x55|(BT485_DATA_PAL<<8), TGA_RAMDAC_REG); @@ -548,9 +560,9 @@ __initfunc(unsigned long tgafb_init(unsigned long mem_start)) /* initialize RAMDAC cursor colors */ BT485_WRITE(0, BT485_ADDR_CUR_WRITE); - BT485_WRITE(0xaa, BT485_DATA_CUR); /* overscan WHITE */ - BT485_WRITE(0xaa, BT485_DATA_CUR); /* overscan WHITE */ - BT485_WRITE(0xaa, BT485_DATA_CUR); /* overscan WHITE */ + BT485_WRITE(0x00, BT485_DATA_CUR); /* overscan WHITE */ + BT485_WRITE(0x00, BT485_DATA_CUR); /* overscan WHITE */ + BT485_WRITE(0x00, BT485_DATA_CUR); /* overscan WHITE */ BT485_WRITE(0x00, BT485_DATA_CUR); /* color 1 BLACK */ BT485_WRITE(0x00, BT485_DATA_CUR); /* color 1 BLACK */ @@ -677,7 +689,7 @@ __initfunc(unsigned long tgafb_init(unsigned long mem_start)) fb_var.xres = fb_var.xres_virtual = 640; fb_var.yres = fb_var.yres_virtual = 480; fb_fix.line_length = 80*fb_var.bits_per_pixel; - fb_fix.smem_start = (char *)tga_fb_base; + fb_fix.smem_start = (char *)(tga_fb_base + LCA_DENSE_MEM); fb_fix.smem_len = fb_fix.line_length*fb_var.yres; fb_fix.type = FB_TYPE_PACKED_PIXELS; fb_fix.type_aux = 0; @@ -686,7 +698,16 @@ __initfunc(unsigned long tgafb_init(unsigned long mem_start)) fb_var.xoffset = fb_var.yoffset = 0; fb_var.grayscale = 0; - fb_var.red.offset = fb_var.green.offset = fb_var.blue.offset = 0; + if (tga_type == 0) { /* 8-plane */ + fb_var.red.offset = 0; + fb_var.green.offset = 0; + fb_var.blue.offset = 0; + } else { /* 24-plane or 24plusZ */ + /* XXX: is this correct?? */ + fb_var.red.offset = 16; + fb_var.green.offset = 8; + fb_var.blue.offset = 0; + } fb_var.red.length = fb_var.green.length = fb_var.blue.length = 8; fb_var.red.msb_right = fb_var.green.msb_right = fb_var.blue.msb_right = 0; fb_var.transp.offset = fb_var.transp.length = fb_var.transp.msb_right = 0; @@ -717,41 +738,54 @@ __initfunc(unsigned long tgafb_init(unsigned long mem_start)) disp.line_length = fb_fix.line_length; disp.can_soft_blank = 1; disp.inverse = 0; + switch (tga_type) { +#ifdef CONFIG_FBCON_CFB8 + case 0: /* 8-plane */ + disp.dispsw = &fbcon_cfb8; + break; +#endif +#ifdef CONFIG_FBCON_CFB32 + case 1: /* 24-plane */ + case 3: /* 24plusZ */ + disp.dispsw = &fbcon_cfb32; + break; +#endif + default: + disp.dispsw = NULL; + } - strcpy(fb_info.modename, tgafb_name); + strcpy(fb_info.modename, fb_fix.id); fb_info.node = -1; fb_info.fbops = &tgafb_ops; - fb_info.fbvar_num = 1; - fb_info.fbvar = &fb_var; fb_info.disp = &disp; fb_info.fontname[0] = '\0'; fb_info.changevar = NULL; fb_info.switch_con = &tgafbcon_switch; fb_info.updatevar = &tgafbcon_updatevar; fb_info.blank = &tgafbcon_blank; - fb_info.setcmap = &tgafbcon_setcmap; err = register_framebuffer(&fb_info); if (err < 0) return mem_start; - tgafb_set_var(&fb_var, -1); + tgafb_set_var(&fb_var, -1, &fb_info); - printk("%s frame buffer device\n", tgafb_name); + printk("fb%d: %s frame buffer device\n", GET_FB_IDX(fb_info.node), + fb_fix.id); return mem_start; } -static int tgafbcon_switch(int con) +static int tgafbcon_switch(int con, struct fb_info *info) { /* Do we have to save the colormap? */ if (fb_display[currcon].cmap.len) fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1, - tgafb_getcolreg); + tgafb_getcolreg, info); currcon = con; /* Install new colormap */ - do_install_cmap(con); + do_install_cmap(con, info); return 0; } @@ -759,7 +793,7 @@ static int tgafbcon_switch(int con) * Update the `var' structure (called by fbcon.c) */ -static int tgafbcon_updatevar(int con) +static int tgafbcon_updatevar(int con, struct fb_info *info) { /* Nothing */ return 0; @@ -769,28 +803,18 @@ static int tgafbcon_updatevar(int con) * Blank the display. */ -static void tgafbcon_blank(int blank) +static void tgafbcon_blank(int blank, struct fb_info *info) { /* Nothing */ } /* - * Set the colormap - */ - -static int tgafbcon_setcmap(struct fb_cmap *cmap, int con) -{ - return(tgafb_set_cmap(cmap, 1, con)); -} - - - /* * Read a single color register and split it into * colors/transparent. Return != 0 for invalid regno. */ static int tgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, - u_int *transp) + u_int *transp, struct fb_info *info) { if (regno > 255) return 1; @@ -808,7 +832,7 @@ static int tgafb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, */ static int tgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp) + u_int transp, struct fb_info *info) { if (regno > 255) return 1; @@ -816,6 +840,11 @@ static int tgafb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, palette[regno].green = green; palette[regno].blue = blue; +#ifdef CONFIG_FBCON_CFB32 + if (regno < 16 && tga_type != 0) + fbcon_cfb32_cmap[regno] = (red << 16) | (green << 8) | blue; +#endif /* CONFIG_FBCON_CFB32 */ + /* How to set a single color register?? */ return 0; @@ -853,22 +882,22 @@ static void tga_update_palette(void) } #endif -static void do_install_cmap(int con) +static void do_install_cmap(int con, struct fb_info *info) { if (con != currcon) return; if (fb_display[con].cmap.len) fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1, - tgafb_setcolreg); + tgafb_setcolreg, info); else - fb_set_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), - &fb_display[con].var, 1, tgafb_setcolreg); + fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), + &fb_display[con].var, 1, tgafb_setcolreg, + info); #if 1 tga_update_palette(); #endif } - #if 0 /* No cursor stuff yet */ /* diff --git a/drivers/video/txtcon.c b/drivers/video/txtcon.c index cdecc08b0..83165b49b 100644 --- a/drivers/video/txtcon.c +++ b/drivers/video/txtcon.c @@ -14,48 +14,55 @@ */ +#include <linux/errno.h> #include <linux/types.h> +#include <linux/kdev_t.h> #include <linux/console.h> - /* - * Interface used by the world - */ + /* + * Interface used by the world + */ -static int txtcon_startup(u_long *kmem_start, const char **display_desc); +static unsigned long txtcon_startup(unsigned long kmem_start, + const char **display_desc); static void txtcon_init(struct vc_data *conp); -static int txtcon_deinit(struct vc_data *conp); -static int txtcon_clear(struct vc_data *conp, int sy, int sx, int height, - int width); -static int txtcon_putc(struct vc_data *conp, int c, int y, int x); -static int txtcon_putcs(struct vc_data *conp, const char *s, int count, int y, - int x); -static int txtcon_cursor(struct vc_data *conp, int mode); -static int txtcon_scroll(struct vc_data *conp, int t, int b, int dir, int count); -static int txtcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, - int height, int width); +static void txtcon_deinit(struct vc_data *conp); +static void txtcon_clear(struct vc_data *conp, int sy, int sx, int height, + int width); +static void txtcon_putc(struct vc_data *conp, int c, int y, int x); +static void txtcon_putcs(struct vc_data *conp, const char *s, int count, int y, + int x); +static void txtcon_cursor(struct vc_data *conp, int mode); +static void txtcon_scroll(struct vc_data *conp, int t, int b, int dir, + int count); +static void txtcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, + int height, int width); static int txtcon_switch(struct vc_data *conp); static int txtcon_blank(int blank); static int txtcon_get_font(struct vc_data *conp, int *w, int *h, char *data); static int txtcon_set_font(struct vc_data *conp, int w, int h, char *data); static int txtcon_set_palette(struct vc_data *conp, unsigned char *table); static int txtcon_scrolldelta(int lines); +static int txtcon_set_mode(struct vc_data *conp, int mode); -static int txtcon_startup(u_long *kmem_start, const char **display_desc) +static unsigned long txtcon_startup(unsigned long kmem_start, + const char **display_desc) { - return -ENODEV; + return kmem_start; } static void txtcon_init(struct vc_data *conp) { + /* ... */ } -static int txtcon_deinit(struct vc_data *conp) +static void txtcon_deinit(struct vc_data *conp) { - return 0; + /* ... */ } @@ -64,90 +71,108 @@ static int txtcon_deinit(struct vc_data *conp) /* txtcon_XXX routines - interface used by the world */ -static int txtcon_clear(struct vc_data *conp, int sy, int sx, int height, - int width) +static void txtcon_clear(struct vc_data *conp, int sy, int sx, int height, + int width) { - return -ENOSYS; + /* ... */ } -static int txtcon_putc(struct vc_data *conp, int c, int y, int x) +static void txtcon_putc(struct vc_data *conp, int c, int y, int x) { - return -ENOSYS; + /* ... */ } -static int txtcon_putcs(struct vc_data *conp, const char *s, int count, int y, - int x) +static void txtcon_putcs(struct vc_data *conp, const char *s, int count, int y, + int x) { - return -ENOSYS; + /* ... */ } -static int txtcon_cursor(struct vc_data *conp, int mode) +static void txtcon_cursor(struct vc_data *conp, int mode) { - return -ENOSYS; + /* ... */ } -static int txtcon_scroll(struct vc_data *conp, int t, int b, int dir, int count) +static void txtcon_scroll(struct vc_data *conp, int t, int b, int dir, + int count) { - return -ENOSYS; + /* ... */ } -static int txtcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, - int height, int width) +static void txtcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, + int height, int width) { - return -ENOSYS; + /* ... */ } static int txtcon_switch(struct vc_data *conp) { - return -ENOSYS; + return -ENOSYS; } static int txtcon_blank(int blank) { - return -ENOSYS; + return -ENOSYS; } static int txtcon_get_font(struct vc_data *conp, int *w, int *h, char *data) { - return -ENOSYS; + return -ENOSYS; } static int txtcon_set_font(struct vc_data *conp, int w, int h, char *data) { - return -ENOSYS; + return -ENOSYS; } static int txtcon_set_palette(struct vc_data *conp, unsigned char *table) { - return -ENOSYS; + return -ENOSYS; } static int txtcon_scrolldelta(int lines) { - return -ENOSYS; + return -ENOSYS; +} + +static int txtcon_set_mode(struct vc_data *conp, int mode) +{ + return -ENOSYS; } /* ====================================================================== */ - /* - * The console `switch' structure for the text mode based console - */ + /* + * The console `switch' structure for the text mode based console + */ struct consw txt_con = { - txtcon_startup, txtcon_init, txtcon_deinit, txtcon_clear, txtcon_putc, - txtcon_putcs, txtcon_cursor, txtcon_scroll, txtcon_bmove, txtcon_switch, - txtcon_blank, txtcon_get_font, txtcon_set_font, txtcon_set_palette, - txtcon_scrolldelta + txtcon_startup, + txtcon_init, + txtcon_deinit, + txtcon_clear, + txtcon_putc, + txtcon_putcs, + txtcon_cursor, + txtcon_scroll, + txtcon_bmove, + txtcon_switch, + txtcon_blank, + txtcon_get_font, + txtcon_set_font, + txtcon_set_palette, + txtcon_scrolldelta, + txtcon_set_mode }; diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index 63e7f7ca2..eea430ffa 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c @@ -8,6 +8,7 @@ * more details. */ +#include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> @@ -22,6 +23,14 @@ #include <linux/fb.h> #include <linux/init.h> +#include "fbcon-mfb.h" +#include "fbcon-cfb2.h" +#include "fbcon-cfb4.h" +#include "fbcon-cfb8.h" +#include "fbcon-cfb16.h" +#include "fbcon-cfb24.h" +#include "fbcon-cfb32.h" + #define arraysize(x) (sizeof(x)/sizeof(*(x))) @@ -41,61 +50,51 @@ static int currcon = 0; static struct display disp; static struct fb_info fb_info; static struct { u_char red, green, blue, pad; } palette[256]; -static char virtual_fb_name[16] = "Virtual FB"; - -static struct fb_var_screeninfo virtual_fb_predefined[] = { - - /* - * Autodetect (Default) Video Mode - */ - - { - /* 640x480, 8 bpp */ - 640, 480, 640, 480, 0, 0, 8, 0, - {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, - 0, 0, -1, -1, FB_ACCEL_NONE, 20000, 64, 64, 32, 32, 64, 2, - 0, FB_VMODE_NONINTERLACED - }, - - /* - * User Defined Video Modes (8) - */ - - { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, } +static char vfb_name[16] = "Virtual FB"; + +static struct fb_var_screeninfo vfb_default = { + /* 640x480, 8 bpp */ + 640, 480, 640, 480, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NONE, 20000, 64, 64, 32, 32, 64, 2, + 0, FB_VMODE_NONINTERLACED }; -#define NUM_USER_MODES (8) -#define NUM_TOTAL_MODES arraysize(virtual_fb_predefined) -#define NUM_PREDEF_MODES (1) +static int vfb_enable = 0; /* disabled by default */ /* * Interface used by the world */ -void vfb_video_setup(char *options, int *ints); - -static int virtual_fb_open(int fbidx); -static int virtual_fb_release(int fbidx); -static int virtual_fb_get_fix(struct fb_fix_screeninfo *fix, int con); -static int virtual_fb_get_var(struct fb_var_screeninfo *var, int con); -static int virtual_fb_set_var(struct fb_var_screeninfo *var, int con); -static int virtual_fb_pan_display(struct fb_var_screeninfo *var, int con); -static int virtual_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con); -static int virtual_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con); -static int virtual_fb_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg, int con); +void vfb_setup(char *options, int *ints); + +static int vfb_open(struct fb_info *info); +static int vfb_release(struct fb_info *info); +static int vfb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info); +static int vfb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int vfb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int vfb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int vfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int vfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int vfb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info); /* * Interface to the low level console driver */ -unsigned long virtual_fb_init(unsigned long mem_start); -static int vfbcon_switch(int con); -static int vfbcon_updatevar(int con); -static void vfbcon_blank(int blank); -static int vfbcon_setcmap(struct fb_cmap *cmap, int con); +unsigned long vfb_init(unsigned long mem_start); +static int vfbcon_switch(int con, struct fb_info *info); +static int vfbcon_updatevar(int con, struct fb_info *info); +static void vfbcon_blank(int blank, struct fb_info *info); /* @@ -107,16 +106,15 @@ static void vfb_encode_fix(struct fb_fix_screeninfo *fix, struct fb_var_screeninfo *var); static void set_color_bitfields(struct fb_var_screeninfo *var); static int vfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, - u_int *transp); + u_int *transp, struct fb_info *info); static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp); -static void do_install_cmap(int con); + u_int transp, struct fb_info *info); +static void do_install_cmap(int con, struct fb_info *info); -static struct fb_ops virtual_fb_ops = { - virtual_fb_open, virtual_fb_release, virtual_fb_get_fix, - virtual_fb_get_var, virtual_fb_set_var, virtual_fb_get_cmap, - virtual_fb_set_cmap, virtual_fb_pan_display, virtual_fb_ioctl +static struct fb_ops vfb_ops = { + vfb_open, vfb_release, vfb_get_fix, vfb_get_var, vfb_set_var, vfb_get_cmap, + vfb_set_cmap, vfb_pan_display, NULL, vfb_ioctl }; @@ -124,7 +122,7 @@ static struct fb_ops virtual_fb_ops = { * Open/Release the frame buffer device */ -static int virtual_fb_open(int fbidx) +static int vfb_open(struct fb_info *info) { /* * Nothing, only a usage count for the moment @@ -134,7 +132,7 @@ static int virtual_fb_open(int fbidx) return(0); } -static int virtual_fb_release(int fbidx) +static int vfb_release(struct fb_info *info) { MOD_DEC_USE_COUNT; return(0); @@ -145,12 +143,13 @@ static int virtual_fb_release(int fbidx) * Get the Fixed Part of the Display */ -static int virtual_fb_get_fix(struct fb_fix_screeninfo *fix, int con) +static int vfb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) { struct fb_var_screeninfo *var; if (con == -1) - var = &virtual_fb_predefined[0]; + var = &vfb_default; else var = &fb_display[con].var; vfb_encode_fix(fix, var); @@ -162,10 +161,11 @@ static int virtual_fb_get_fix(struct fb_fix_screeninfo *fix, int con) * Get the User Defined Part of the Display */ -static int virtual_fb_get_var(struct fb_var_screeninfo *var, int con) +static int vfb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) { if (con == -1) - *var = virtual_fb_predefined[0]; + *var = vfb_default; else *var = fb_display[con].var; set_color_bitfields(var); @@ -177,7 +177,8 @@ static int virtual_fb_get_var(struct fb_var_screeninfo *var, int con) * Set the User Defined Part of the Display */ -static int virtual_fb_set_var(struct fb_var_screeninfo *var, int con) +static int vfb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) { int err, activate = var->activate; int oldxres, oldyres, oldvxres, oldvyres, oldbpp; @@ -258,13 +259,53 @@ static int virtual_fb_set_var(struct fb_var_screeninfo *var, int con) display->line_length = fix.line_length; display->can_soft_blank = 1; display->inverse = 0; + switch (var->bits_per_pixel) { +#ifdef CONFIG_FBCON_MFB + case 1: + display->dispsw = &fbcon_mfb; + break; +#endif +#ifdef CONFIG_FBCON_CFB2 + case 2: + display->dispsw = &fbcon_cfb2; + break; +#endif +#ifdef CONFIG_FBCON_CFB4 + case 4: + display->dispsw = &fbcon_cfb4; + break; +#endif +#ifdef CONFIG_FBCON_CFB8 + case 8: + display->dispsw = &fbcon_cfb8; + break; +#endif +#ifdef CONFIG_FBCON_CFB16 + case 16: + display->dispsw = &fbcon_cfb16; + break; +#endif +#ifdef CONFIG_FBCON_CFB24 + case 24: + display->dispsw = &fbcon_cfb24; + break; +#endif +#ifdef CONFIG_FBCON_CFB32 + case 32: + display->dispsw = &fbcon_cfb32; + break; +#endif + default: + display->dispsw = NULL; + break; + } if (fb_info.changevar) (*fb_info.changevar)(con); } if (oldbpp != var->bits_per_pixel) { if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) return err; - do_install_cmap(con); + do_install_cmap(con, info); } } return 0; @@ -277,7 +318,8 @@ static int virtual_fb_set_var(struct fb_var_screeninfo *var, int con) * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag */ -static int virtual_fb_pan_display(struct fb_var_screeninfo *var, int con) +static int vfb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) { if (var->vmode & FB_VMODE_YWRAP) { if (var->yoffset < 0 || @@ -304,14 +346,16 @@ static int virtual_fb_pan_display(struct fb_var_screeninfo *var, int con) * Get the Colormap */ -static int virtual_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con) +static int vfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) { if (con == currcon) /* current console? */ - return fb_get_cmap(cmap, &fb_display[con].var, kspc, vfb_getcolreg); + return fb_get_cmap(cmap, &fb_display[con].var, kspc, vfb_getcolreg, + info); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else - fb_copy_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), + fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), cmap, kspc ? 0 : 2); return 0; } @@ -320,7 +364,8 @@ static int virtual_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con) * Set the Colormap */ -static int virtual_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con) +static int vfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) { int err; @@ -330,7 +375,8 @@ static int virtual_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con) return err; } if (con == currcon) /* current console? */ - return fb_set_cmap(cmap, &fb_display[con].var, kspc, vfb_setcolreg); + return fb_set_cmap(cmap, &fb_display[con].var, kspc, vfb_setcolreg, + info); else fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); return 0; @@ -341,19 +387,21 @@ static int virtual_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con) * Virtual Frame Buffer Specific ioctls */ -static int virtual_fb_ioctl(struct inode *inode, struct file *file, u_int cmd, - u_long arg, int con) +static int vfb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info) { return -EINVAL; } -__initfunc(void vfb_video_setup(char *options, int *ints)) +__initfunc(void vfb_setup(char *options, int *ints)) { char *this_opt; fb_info.fontname[0] = '\0'; + vfb_enable = 1; + if (!options || !*options) return; @@ -369,10 +417,13 @@ __initfunc(void vfb_video_setup(char *options, int *ints)) * Initialisation */ -__initfunc(unsigned long virtual_fb_init(unsigned long mem_start)) +__initfunc(unsigned long vfb_init(unsigned long mem_start)) { int err; + if (!vfb_enable) + return mem_start; + if (mem_start) { videomemory = mem_start; mem_start += videomemorysize; @@ -382,40 +433,37 @@ __initfunc(unsigned long virtual_fb_init(unsigned long mem_start)) if (!videomemory) return mem_start; - strcpy(fb_info.modename, virtual_fb_name); + strcpy(fb_info.modename, vfb_name); fb_info.changevar = NULL; fb_info.node = -1; - fb_info.fbops = &virtual_fb_ops; - fb_info.fbvar_num = NUM_TOTAL_MODES; - fb_info.fbvar = virtual_fb_predefined; + fb_info.fbops = &vfb_ops; fb_info.disp = &disp; fb_info.switch_con = &vfbcon_switch; fb_info.updatevar = &vfbcon_updatevar; fb_info.blank = &vfbcon_blank; - fb_info.setcmap = &vfbcon_setcmap; err = register_framebuffer(&fb_info); if (err < 0) return mem_start; - virtual_fb_set_var(&virtual_fb_predefined[0], -1); + vfb_set_var(&vfb_default, -1, &fb_info); - printk("Virtual frame buffer device, using %ldK of video memory\n", - videomemorysize>>10); + printk("fb%d: Virtual frame buffer device, using %ldK of video memory\n", + GET_FB_IDX(fb_info.node), videomemorysize>>10); return mem_start; } -static int vfbcon_switch(int con) +static int vfbcon_switch(int con, struct fb_info *info) { /* Do we have to save the colormap? */ if (fb_display[currcon].cmap.len) fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1, - vfb_getcolreg); + vfb_getcolreg, info); currcon = con; /* Install new colormap */ - do_install_cmap(con); + do_install_cmap(con, info); return 0; } @@ -423,7 +471,7 @@ static int vfbcon_switch(int con) * Update the `var' structure (called by fbcon.c) */ -static int vfbcon_updatevar(int con) +static int vfbcon_updatevar(int con, struct fb_info *info) { /* Nothing */ return 0; @@ -433,21 +481,11 @@ static int vfbcon_updatevar(int con) * Blank the display. */ -static void vfbcon_blank(int blank) +static void vfbcon_blank(int blank, struct fb_info *info) { /* Nothing */ } - /* - * Set the colormap - */ - -static int vfbcon_setcmap(struct fb_cmap *cmap, int con) -{ - return(virtual_fb_set_cmap(cmap, 1, con)); -} - - static u_long get_line_length(int xres_virtual, int bpp) { u_long length; @@ -462,7 +500,7 @@ static void vfb_encode_fix(struct fb_fix_screeninfo *fix, struct fb_var_screeninfo *var) { memset(fix, 0, sizeof(struct fb_fix_screeninfo)); - strcpy(fix->id, virtual_fb_name); + strcpy(fix->id, vfb_name); fix->smem_start = (caddr_t)videomemory; fix->smem_len = videomemorysize; fix->type = FB_TYPE_PACKED_PIXELS; @@ -471,6 +509,8 @@ static void vfb_encode_fix(struct fb_fix_screeninfo *fix, case 1: fix->visual = FB_VISUAL_MONO01; break; + case 2: + case 4: case 8: fix->visual = FB_VISUAL_PSEUDOCOLOR; break; @@ -544,7 +584,7 @@ static void set_color_bitfields(struct fb_var_screeninfo *var) */ static int vfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, - u_int *transp) + u_int *transp, struct fb_info *info) { if (regno > 255) return 1; @@ -562,7 +602,7 @@ static int vfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, */ static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp) + u_int transp, struct fb_info *info) { if (regno > 255) return 1; @@ -573,23 +613,23 @@ static int vfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, } -static void do_install_cmap(int con) +static void do_install_cmap(int con, struct fb_info *info) { if (con != currcon) return; if (fb_display[con].cmap.len) fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1, - vfb_setcolreg); + vfb_setcolreg, info); else - fb_set_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel), - &fb_display[con].var, 1, vfb_setcolreg); + fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), + &fb_display[con].var, 1, vfb_setcolreg, info); } #ifdef MODULE int init_module(void) { - return(virtual_fb_init(NULL)); + return(vfb_init(NULL)); } void cleanup_module(void) diff --git a/drivers/video/vgacon.c b/drivers/video/vgacon.c index 83a908a09..623ea799d 100644 --- a/drivers/video/vgacon.c +++ b/drivers/video/vgacon.c @@ -87,16 +87,16 @@ static unsigned long vgacon_startup(unsigned long kmem_start, const char **display_desc); static void vgacon_init(struct vc_data *conp); -static int vgacon_deinit(struct vc_data *conp); -static int vgacon_clear(struct vc_data *conp, int sy, int sx, int height, - int width); -static int vgacon_putc(struct vc_data *conp, int c, int ypos, int xpos); -static int vgacon_putcs(struct vc_data *conp, const char *s, int count, - int ypos, int xpos); -static int vgacon_cursor(struct vc_data *conp, int mode); -static int vgacon_scroll(struct vc_data *conp, int t, int b, - int dir, int count); -static int vgacon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, +static void vgacon_deinit(struct vc_data *conp); +static void vgacon_clear(struct vc_data *conp, int sy, int sx, int height, + int width); +static void vgacon_putc(struct vc_data *conp, int c, int ypos, int xpos); +static void vgacon_putcs(struct vc_data *conp, const char *s, int count, + int ypos, int xpos); +static void vgacon_cursor(struct vc_data *conp, int mode); +static void vgacon_scroll(struct vc_data *conp, int t, int b, int dir, + int count); +static void vgacon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, int height, int width); static int vgacon_switch(struct vc_data *conp); static int vgacon_blank(int blank); @@ -104,6 +104,7 @@ static int vgacon_get_font(struct vc_data *conp, int *w, int *h, char *data); static int vgacon_set_font(struct vc_data *conp, int w, int h, char *data); static int vgacon_set_palette(struct vc_data *conp, unsigned char *table); static int vgacon_scrolldelta(int lines); +static int vgacon_set_mode(struct vc_data *conp, int mode); /* @@ -215,25 +216,6 @@ __initfunc(static unsigned long vgacon_startup(unsigned long kmem_start, unsigned short saved; unsigned short *p; - /* - * Find out if there is a graphics card present. - * Are there smarter methods around? - */ - p = (unsigned short *)(((ORIG_VIDEO_MODE == 7) ? 0xb0000 : 0xb8000) + - + VGA_OFFSET); - saved = vga_readw(p); - vga_writew(0xAA55, p); - if (vga_readw(p) != 0xAA55) { - vga_writew(saved, p); - return kmem_start; - } - vga_writew(0x55AA, p); - if (vga_readw(p) != 0x55AA) { - vga_writew(saved, p); - return kmem_start; - } - vga_writew(saved, p); - vga_video_num_lines = ORIG_VIDEO_LINES; vga_video_num_columns = ORIG_VIDEO_COLS; vga_video_size_row = 2 * ORIG_VIDEO_COLS; @@ -327,6 +309,24 @@ __initfunc(static unsigned long vgacon_startup(unsigned long kmem_start, } } + /* + * Find out if there is a graphics card present. + * Are there smarter methods around? + */ + p = (unsigned short *)vga_video_mem_base; + saved = vga_readw(p); + vga_writew(0xAA55, p); + if (vga_readw(p) != 0xAA55) { + vga_writew(saved, p); + return kmem_start; + } + vga_writew(0x55AA, p); + if (vga_readw(p) != 0x55AA) { + vga_writew(saved, p); + return kmem_start; + } + vga_writew(saved, p); + vga_hardscroll_enabled = (vga_hardscroll_disabled_by_init ? 0 : (vga_video_type == VIDEO_TYPE_EGAC || vga_video_type == VIDEO_TYPE_VGAC @@ -358,22 +358,21 @@ static void vgacon_init(struct vc_data *conp) conp->vc_can_do_color = vga_can_do_color; } -static int vgacon_deinit(struct vc_data *conp) +static void vgacon_deinit(struct vc_data *conp) { - return 0; } /* ====================================================================== */ -static int vgacon_clear(struct vc_data *conp, int sy, int sx, int height, - int width) +static void vgacon_clear(struct vc_data *conp, int sy, int sx, int height, + int width) { int rows; unsigned long dest; if (console_blanked) - return 0; + return; dest = vga_video_mem_base + sy*vga_video_size_row + sx*2; if (sx == 0 && width == vga_video_num_columns) @@ -381,41 +380,38 @@ static int vgacon_clear(struct vc_data *conp, int sy, int sx, int height, else for (rows = height; rows-- ; dest += vga_video_size_row) vga_memsetw((void *)dest, conp->vc_video_erase_char, width); - return 0; } -static int vgacon_putc(struct vc_data *conp, int c, int ypos, int xpos) +static void vgacon_putc(struct vc_data *conp, int c, int ypos, int xpos) { - u_short *p; + u16 *p; if (console_blanked) - return 0; + return; - p = (u_short *)(vga_video_mem_base+ypos*vga_video_size_row+xpos*2); + p = (u16 *)(vga_video_mem_base+ypos*vga_video_size_row+xpos*2); vga_writew(conp->vc_attr << 8 | c, p); - return 0; } -static int vgacon_putcs(struct vc_data *conp, const char *s, int count, - int ypos, int xpos) +static void vgacon_putcs(struct vc_data *conp, const char *s, int count, + int ypos, int xpos) { - u_short *p; - u_short sattr; + u16 *p; + u16 sattr; if (console_blanked) - return 0; + return; - p = (u_short *)(vga_video_mem_base+ypos*vga_video_size_row+xpos*2); + p = (u16 *)(vga_video_mem_base+ypos*vga_video_size_row+xpos*2); sattr = conp->vc_attr << 8; while (count--) vga_writew(sattr | *s++, p++); - return 0; } -static int vgacon_cursor(struct vc_data *conp, int mode) +static void vgacon_cursor(struct vc_data *conp, int mode) { switch (mode) { case CM_ERASE: @@ -427,14 +423,14 @@ static int vgacon_cursor(struct vc_data *conp, int mode) write_vga(14, conp->vc_y*vga_video_num_columns+conp->vc_x); break; } - return 0; } -static int vgacon_scroll(struct vc_data *conp, int t, int b, int dir, int count) +static void vgacon_scroll(struct vc_data *conp, int t, int b, int dir, + int count) { if (console_blanked) - return 0; + return; vgacon_cursor(conp, CM_ERASE); @@ -469,19 +465,17 @@ static int vgacon_scroll(struct vc_data *conp, int t, int b, int dir, int count) vgacon_clear(conp, 0, t, conp->vc_rows, count); break; } - - return 0; } -static int vgacon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, - int height, int width) +static void vgacon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, + int height, int width) { unsigned long src, dst; int rows; if (console_blanked) - return 0; + return; if (sx == 0 && dx == 0 && width == vga_video_num_columns) { src = vga_video_mem_base + sy * vga_video_size_row; @@ -505,7 +499,6 @@ static int vgacon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, dst -= vga_video_size_row; } } - return 0; } @@ -522,7 +515,7 @@ static int vgacon_blank(int blank) return 0; } else { /* Tell console.c that it has to restore the screen itself */ - return(1); + return 1; } return 0; } @@ -564,6 +557,11 @@ static int vgacon_scrolldelta(int lines) return -ENOSYS; } +static int vgacon_set_mode(struct vc_data *conp, int mode) +{ + return -ENOSYS; +} + __initfunc(static int vgacon_show_logo( void )) { @@ -587,5 +585,5 @@ struct consw vga_con = { vgacon_startup, vgacon_init, vgacon_deinit, vgacon_clear, vgacon_putc, vgacon_putcs, vgacon_cursor, vgacon_scroll, vgacon_bmove, vgacon_switch, vgacon_blank, vgacon_get_font, vgacon_set_font, vgacon_set_palette, - vgacon_scrolldelta + vgacon_scrolldelta, vgacon_set_mode }; diff --git a/drivers/video/virgefb.c b/drivers/video/virgefb.c new file mode 100644 index 000000000..d08e4a722 --- /dev/null +++ b/drivers/video/virgefb.c @@ -0,0 +1,1190 @@ +/* + * linux/drivers/video/virgefb.c -- CyberVision64/3D frame buffer device + * + * Copyright (C) 1997 André Heynatz + * + * + * This file is based on the CyberVision frame buffer device (cyberfb.c): + * + * Copyright (C) 1996 Martin Apel + * Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#undef VIRGEFBDEBUG + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/mm.h> +#include <linux/tty.h> +#include <linux/malloc.h> +#include <linux/delay.h> +#include <linux/zorro.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <asm/uaccess.h> +#include <asm/system.h> +#include <asm/irq.h> +#include <asm/pgtable.h> +#include <asm/amigahw.h> + +#include "s3blit.h" +#include "fbcon.h" +#include "fbcon-cfb8.h" +#include "fbcon-cfb16.h" + + +#ifdef VIRGEFBDEBUG +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args) +#else +#define DPRINTK(fmt, args...) +#endif + +#define arraysize(x) (sizeof(x)/sizeof(*(x))) + +#if 1 +#define vgawb_3d(reg,dat) \ + (*((unsigned char *)(CyberVGARegs + (reg ^ 3))) = dat) +#define vgaww_3d(reg,dat) \ + (*((unsigned word *)(CyberVGARegs + (reg ^ 2))) = swab16(dat)) +#define vgawl_3d(reg,dat) \ + (*((unsigned long *)(CyberVGARegs + reg)) = swab32(dat)) +#else + /* + * Dunno why this doesn't work at the moment - we'll have to look at + * it later. + */ +#define vgawb_3d(reg,dat) \ + (*((unsigned char *)(CyberRegs + 0x8000 + reg)) = dat) +#define vgaww_3d(reg,dat) \ + (*((unsigned word *)(CyberRegs + 0x8000 + reg)) = dat) +#define vgawl_3d(reg,dat) \ + (*((unsigned long *)(CyberRegs + 0x8000 + reg)) = dat) +#endif + + /* + * We asume P5 mapped the big-endian version of these registers. + */ +#define wb_3d(reg,dat) \ + (*((unsigned char volatile *)(CyberRegs + reg)) = dat) +#define ww_3d(reg,dat) \ + (*((unsigned word volatile *)(CyberRegs + reg)) = dat) +#define wl_3d(reg,dat) \ + (*((unsigned long volatile *)(CyberRegs + reg)) = dat) + +#define rl_3d(reg) \ + (*((unsigned long volatile *)(CyberRegs + reg))) + + + + + + +struct virgefb_par { + int xres; + int yres; + int bpp; +}; + +static struct virgefb_par current_par; + +static int current_par_valid = 0; +static int currcon = 0; + +static struct display disp; +static struct fb_info fb_info; + + +/* + * Switch for Chipset Independency + */ + +static struct fb_hwswitch { + + /* Initialisation */ + + int (*init)(void); + + /* Display Control */ + + int (*encode_fix)(struct fb_fix_screeninfo *fix, struct virgefb_par *par); + int (*decode_var)(struct fb_var_screeninfo *var, struct virgefb_par *par); + int (*encode_var)(struct fb_var_screeninfo *var, struct virgefb_par *par); + int (*getcolreg)(u_int regno, u_int *red, u_int *green, u_int *blue, + u_int *transp, struct fb_info *info); + int (*setcolreg)(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info); + void (*blank)(int blank); +} *fbhw; + + +/* + * Frame Buffer Name + */ + +static char virgefb_name[16] = "Cybervision/3D"; + + +/* + * Cybervision Graphics Board + */ + +#define VIRGE8_WIDTH 1152 +#define VIRGE8_HEIGHT 886 +#define VIRGE8_PIXCLOCK 12500 /* ++Geert: Just a guess */ + +#if 0 +#define VIRGE16_WIDTH 800 +#define VIRGE16_HEIGHT 600 +#endif +#define VIRGE16_PIXCLOCK 25000 /* ++Geert: Just a guess */ + + +static unsigned int CyberKey = 0; +static unsigned char Cyber_colour_table [256][4]; +static unsigned long CyberMem; +static unsigned long CyberSize; +static volatile char *CyberRegs; +static volatile unsigned long CyberVGARegs; /* ++Andre: for CV64/3D, see macros at the beginning */ + + +/* + * Predefined Video Modes + */ + +static struct fb_videomode virgefb_predefined[] __initdata = { + { + "640x480-8", { /* Cybervision 8 bpp */ + 640, 480, 640, 480, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NONE, VIRGE8_PIXCLOCK, 64, 96, 35, 12, 112, 2, + FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } + }, { + "800x600-8", { /* Cybervision 8 bpp */ + 800, 600, 800, 600, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NONE, VIRGE8_PIXCLOCK, 64, 96, 35, 12, 112, 2, + FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } + }, { + "1024x768-8", { /* Cybervision 8 bpp */ + 1024, 768, 1024, 768, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NONE, VIRGE8_PIXCLOCK, 64, 96, 35, 12, 112, 2, + FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } + }, { + "1152x886-8", { /* Cybervision 8 bpp */ + 1152, 886, 1152, 886, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NONE, VIRGE8_PIXCLOCK, 64, 96, 35, 12, 112, 2, + FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } + }, { + "1280x1024-8", { /* Cybervision 8 bpp */ + 1280, 1024, 1280, 1024, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NONE, VIRGE8_PIXCLOCK, 64, 96, 35, 12, 112, 2, + FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } + }, { + "1600x1200-8", { /* Cybervision 8 bpp */ + 1600, 1200, 1600, 1200, 0, 0, 8, 0, + {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NONE, VIRGE8_PIXCLOCK, 64, 96, 35, 12, 112, 2, + FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } + }, { + "800x600-16", { /* Cybervision 16 bpp */ + 800, 600, 800, 600, 0, 0, 16, 0, + {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, + 0, 0, -1, -1, FB_ACCEL_NONE, VIRGE16_PIXCLOCK, 64, 96, 35, 12, 112, 2, + FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED + } + } +}; + + +#define NUM_TOTAL_MODES arraysize(virgefb_predefined) + + +static int Cyberfb_inverse = 0; +#if 0 +static int Cyberfb_Cyber8 = 0; /* Use Cybervision board */ +static int Cyberfb_Cyber16 = 0; /* Use Cybervision board */ +#endif + +/* + * Some default modes + */ + +#define VIRGE8_DEFMODE (0) +#define VIRGE16_DEFMODE (6) + +static struct fb_var_screeninfo virgefb_default; + + +/* + * Interface used by the world + */ + +void virgefb_setup(char *options, int *ints); + +static int virgefb_open(struct fb_info *info); +static int virgefb_release(struct fb_info *info); +static int virgefb_get_fix(struct fb_fix_screeninfo *fix, int con, struct +fb_info *info); +static int virgefb_get_var(struct fb_var_screeninfo *var, int con, struct +fb_info *info); +static int virgefb_set_var(struct fb_var_screeninfo *var, int con, struct +fb_info *info); +static int virgefb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int virgefb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info); +static int virgefb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info); +static int virgefb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info); + + +/* + * Interface to the low level console driver + */ + +unsigned long virgefb_init(unsigned long mem_start); +static int Cyberfb_switch(int con, struct fb_info *info); +static int Cyberfb_updatevar(int con, struct fb_info *info); +static void Cyberfb_blank(int blank, struct fb_info *info); + + +/* + * Text console acceleration + */ + +#ifdef CONFIG_FBCON_CFB8 +static struct display_switch fbcon_virge8; +#endif + + +/* + * Hardware Specific Routines + */ + +static int Cyber_init(void); +static int Cyber_encode_fix(struct fb_fix_screeninfo *fix, + struct virgefb_par *par); +static int Cyber_decode_var(struct fb_var_screeninfo *var, + struct virgefb_par *par); +static int Cyber_encode_var(struct fb_var_screeninfo *var, + struct virgefb_par *par); +static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, + u_int *transp, struct fb_info *info); +static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info); +static void Cyber_blank(int blank); + + +/* + * Internal routines + */ + +static void virgefb_get_par(struct virgefb_par *par); +static void virgefb_set_par(struct virgefb_par *par); +static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive); +static void do_install_cmap(int con, struct fb_info *info); +static void virgefb_set_disp(int con, struct fb_info *info); +static int get_video_mode(const char *name); + + +/* -------------------- Hardware specific routines ------------------------- */ + + +/* + * Initialization + * + * Set the default video mode for this chipset. If a video mode was + * specified on the command line, it will override the default mode. + */ + +static int Cyber_init(void) +{ + int i; + + for (i = 0; i < 256; i++) + { + Cyber_colour_table [i][0] = i; + Cyber_colour_table [i][1] = i; + Cyber_colour_table [i][2] = i; + Cyber_colour_table [i][3] = 0; + } + + /* + * Just clear the thing for the biggest mode. + * + * ++Andre, TODO: determine size first, then clear all memory + * (the 3D penguin might need texture memory :-) ) + */ + + memset ((char*)CyberMem, 0, 1600 * 1200); + + /* Disable hardware cursor */ + CyberSize = 0x00400000; /* 4 MB */ + + vgawb_3d(0x3c8, 255); + vgawb_3d(0x3c9, 56); + vgawb_3d(0x3c9, 100); + vgawb_3d(0x3c9, 160); + + vgawb_3d(0x3c8, 254); + vgawb_3d(0x3c9, 0); + vgawb_3d(0x3c9, 0); + vgawb_3d(0x3c9, 0); + + /* Disable hardware cursor */ + vgawb_3d(S3_CRTC_ADR, S3_REG_LOCK2); + vgawb_3d(S3_CRTC_DATA, 0xa0); + vgawb_3d(S3_CRTC_ADR, S3_HGC_MODE); + vgawb_3d(S3_CRTC_DATA, 0x00); + vgawb_3d(S3_CRTC_ADR, S3_HWGC_DX); + vgawb_3d(S3_CRTC_DATA, 0x00); + vgawb_3d(S3_CRTC_ADR, S3_HWGC_DY); + vgawb_3d(S3_CRTC_DATA, 0x00); + + return 0; /* TODO: hardware cursor for CV64/3D */ +} + + +/* + * This function should fill in the `fix' structure based on the + * values in the `par' structure. + */ + +static int Cyber_encode_fix(struct fb_fix_screeninfo *fix, + struct virgefb_par *par) +{ + int i; + + strcpy(fix->id, virgefb_name); + fix->smem_start = (caddr_t)CyberMem; + fix->smem_len = CyberSize; + fix->mmio_start = (unsigned char *)CyberRegs; + fix->mmio_len = 0x10000; /* TODO: verify this for the CV64/3D */ + + fix->type = FB_TYPE_PACKED_PIXELS; + fix->type_aux = 0; + if (par->bpp == 8) + fix->visual = FB_VISUAL_PSEUDOCOLOR; + else + fix->visual = FB_VISUAL_DIRECTCOLOR; + + fix->xpanstep = 0; + fix->ypanstep = 0; + fix->ywrapstep = 0; + fix->line_length = 0; + + for (i = 0; i < arraysize(fix->reserved); i++) + fix->reserved[i] = 0; + + return(0); +} + + +/* + * Get the video params out of `var'. If a value doesn't fit, round + * it up, if it's too big, return -EINVAL. + */ + +static int Cyber_decode_var(struct fb_var_screeninfo *var, + struct virgefb_par *par) +{ +#if 1 + par->xres = var->xres; + par->yres = var->yres; + par->bpp = var->bits_per_pixel; +#else + if (Cyberfb_Cyber8) { + par->xres = VIRGE8_WIDTH; + par->yres = VIRGE8_HEIGHT; + par->bpp = 8; + } else { + par->xres = VIRGE16_WIDTH; + par->yres = VIRGE16_HEIGHT; + par->bpp = 16; + } +#endif + return(0); +} + + +/* + * Fill the `var' structure based on the values in `par' and maybe + * other values read out of the hardware. + */ + +static int Cyber_encode_var(struct fb_var_screeninfo *var, + struct virgefb_par *par) +{ + int i; + + var->xres = par->xres; + var->yres = par->yres; + var->xres_virtual = par->xres; + var->yres_virtual = par->yres; + var->xoffset = 0; + var->yoffset = 0; + + var->bits_per_pixel = par->bpp; + var->grayscale = 0; + + if (par->bpp == 8) { + var->red.offset = 0; + var->red.length = 8; + var->red.msb_right = 0; + var->blue = var->green = var->red; + } else { + var->red.offset = 11; + var->red.length = 5; + var->red.msb_right = 0; + var->green.offset = 5; + var->green.length = 6; + var->green.msb_right = 0; + var->blue.offset = 0; + var->blue.length = 5; + var->blue.msb_right = 0; + } + var->transp.offset = 0; + var->transp.length = 0; + var->transp.msb_right = 0; + + var->nonstd = 0; + var->activate = 0; + + var->height = -1; + var->width = -1; + + var->accel = FB_ACCEL_S3VIRGE; + DPRINTK("accel CV64/3D\n"); + + var->vmode = FB_VMODE_NONINTERLACED; + + /* Dummy values */ + + if (par->bpp == 8) + var->pixclock = VIRGE8_PIXCLOCK; + else + var->pixclock = VIRGE16_PIXCLOCK; + var->sync = 0; + var->left_margin = 64; + var->right_margin = 96; + var->upper_margin = 35; + var->lower_margin = 12; + var->hsync_len = 112; + var->vsync_len = 2; + + for (i = 0; i < arraysize(var->reserved); i++) + var->reserved[i] = 0; + + return(0); +} + + +/* + * Set a single color register. The values supplied are already + * rounded down to the hardware's capabilities (according to the + * entries in the var structure). Return != 0 for invalid regno. + */ + +static int Cyber_setcolreg(u_int regno, u_int red, u_int green, u_int blue, + u_int transp, struct fb_info *info) +{ + if (regno > 255) + { + return (1); + } + + /* + * No colors on the CV3D yet. + */ + + vgawb_3d(0x3c8, (unsigned char) regno); + Cyber_colour_table [regno][0] = red & 0xff; + Cyber_colour_table [regno][1] = green & 0xff; + Cyber_colour_table [regno][2] = blue & 0xff; + Cyber_colour_table [regno][3] = transp; + + vgawb_3d(0x3c9, ((red & 0xff) >> 2)); + vgawb_3d(0x3c9, ((green & 0xff) >> 2)); + vgawb_3d(0x3c9, ((blue & 0xff) >> 2)); + + return (0); +} + + +/* + * Read a single color register and split it into + * colors/transparent. Return != 0 for invalid regno. + */ + +static int Cyber_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, + u_int *transp, struct fb_info *info) +{ + if (regno >= 256) + return (1); + *red = Cyber_colour_table [regno][0]; + *green = Cyber_colour_table [regno][1]; + *blue = Cyber_colour_table [regno][2]; + *transp = Cyber_colour_table [regno][3]; + return (0); +} + + +/* + * (Un)Blank the screen + */ + +void Cyber_blank(int blank) +{ + int i; + + if (blank) + { + for (i = 0; i < 256; i++) + { + vgawb_3d(0x3c8, (unsigned char) i); + vgawb_3d(0x3c9, 0); + vgawb_3d(0x3c9, 0); + vgawb_3d(0x3c9, 0); + } + } + else + { + for (i = 0; i < 256; i++) + { + vgawb_3d(0x3c8, (unsigned char) i); + vgawb_3d(0x3c9, Cyber_colour_table[i][0] >> 2); + vgawb_3d(0x3c9, Cyber_colour_table[i][1] >> 2); + vgawb_3d(0x3c9, Cyber_colour_table[i][2] >> 2); + } + } +} + +/* + * CV3D low-level support + */ + +#define Cyber3D_WaitQueue(v) { do { while ((rl_3d(0x8504) & 0x1f00) < (((v)+2) << 8)); } while (0); } + +static inline void Cyber3D_WaitBusy(void) +{ +unsigned long status; + + do { + status = rl_3d(0x8504); + } while (!(status & (1 << 13))); +} + +#define S3V_BITBLT (0x0 << 27) +#define S3V_RECTFILL (0x2 << 27) +#define S3V_AUTOEXE 0x01 +#define S3V_HWCLIP 0x02 +#define S3V_DRAW 0x20 +#define S3V_DST_8BPP 0x00 +#define S3V_DST_16BPP 0x04 +#define S3V_DST_24BPP 0x08 +#define S3V_MONO_PAT 0x100 + +#define S3V_BLT_COPY (0xcc<<17) +#define S3V_BLT_CLEAR (0x00<<17) +#define S3V_BLT_SET (0xff<<17) + + /* + * BitBLT - Through the Plane + */ + +static void Cyber3D_BitBLT(u_short curx, u_short cury, u_short destx, + u_short desty, u_short width, u_short height) +{ + unsigned int blitcmd = S3V_BITBLT | S3V_DRAW | S3V_DST_8BPP; + + blitcmd |= S3V_BLT_COPY; + + /* Set drawing direction */ + /* -Y, X maj, -X (default) */ + if (curx > destx) + { + blitcmd |= (1 << 25); /* Drawing direction +X */ + } + else + { + curx += (width - 1); + destx += (width - 1); + } + + if (cury > desty) + { + blitcmd |= (1 << 26); /* Drawing direction +Y */ + } + else + { + cury += (height - 1); + desty += (height - 1); + } + + wl_3d(0xa4f4, 1); /* pattern fb color */ + + wl_3d(0xa4e8, ~0); /* mono pat 0 */ + wl_3d(0xa4ec, ~0); /* mono pat 1 */ + + wl_3d(0xa504, ((width << 16) | height)); /* rwidth_height */ + wl_3d(0xa508, ((curx << 16) | cury)); /* rsrc_xy */ + wl_3d(0xa50c, ((destx << 16) | desty)); /* rdest_xy */ + + wl_3d(0xa500, blitcmd); /* GO! */ + + Cyber3D_WaitBusy(); +} + +/* + * Rectangle Fill Solid + */ + +static void Cyber3D_RectFill(u_short x, u_short y, u_short width, + u_short height, u_short color) +{ + unsigned int tmp; + unsigned int blitcmd = S3V_RECTFILL | S3V_DRAW | S3V_DST_8BPP | + S3V_BLT_CLEAR | S3V_MONO_PAT | (1 << 26) | (1 << 25); + + tmp = color & 0xff; + wl_3d(0xa4f4, tmp); + + wl_3d(0xa504, ((width << 16) | height)); /* rwidth_height */ + wl_3d(0xa50c, ((x << 16) | y)); /* rdest_xy */ + + wl_3d(0xa500, blitcmd); /* GO! */ + Cyber3D_WaitBusy(); +} + + +/************************************************************** + * Move cursor to x, y + */ +static void Cyber_MoveCursor (u_short x, u_short y) +{ + printk("Yuck .... MoveCursor on a 3D\n"); + return; +} + + +/* -------------------- Interfaces to hardware functions -------------------- */ + + +static struct fb_hwswitch Cyber_switch = { + Cyber_init, Cyber_encode_fix, Cyber_decode_var, Cyber_encode_var, + Cyber_getcolreg, Cyber_setcolreg, Cyber_blank +}; + + +/* -------------------- Generic routines ------------------------------------ */ + + +/* + * Fill the hardware's `par' structure. + */ + +static void virgefb_get_par(struct virgefb_par *par) +{ + if (current_par_valid) + { + *par = current_par; + } + else + { + fbhw->decode_var(&virgefb_default, par); + } +} + + +static void virgefb_set_par(struct virgefb_par *par) +{ + current_par = *par; + current_par_valid = 1; +} + + +static void virge_set_video(struct fb_var_screeninfo *var) +{ + /* Set clipping rectangle to current screen size */ + + unsigned int clip; + + clip = ((0 << 16) | (var->xres - 1)); + wl_3d(0xa4dc, clip); + clip = ((0 << 16) | (var->yres - 1)); + wl_3d(0xa4e0, clip); +} + + +static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive) +{ + int err, activate; + struct virgefb_par par; + + if ((err = fbhw->decode_var(var, &par))) + return(err); + activate = var->activate; + if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive) + virgefb_set_par(&par); + fbhw->encode_var(var, &par); + var->activate = activate; + + virge_set_video(var); + return 0; +} + + +static void do_install_cmap(int con, struct fb_info *info) +{ + if (con != currcon) + return; + if (fb_display[con].cmap.len) + fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1, + fbhw->setcolreg, info); + else + fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), + &fb_display[con].var, 1, fbhw->setcolreg, info); +} + + +/* + * Open/Release the frame buffer device + */ + +static int virgefb_open(struct fb_info *info) +{ + /* + * Nothing, only a usage count for the moment + */ + + MOD_INC_USE_COUNT; + return(0); +} + +static int virgefb_release(struct fb_info *info) +{ + MOD_DEC_USE_COUNT; + return(0); +} + + +/* + * Get the Fixed Part of the Display + */ + +static int virgefb_get_fix(struct fb_fix_screeninfo *fix, int con, + struct fb_info *info) +{ + struct virgefb_par par; + int error = 0; + + if (con == -1) + virgefb_get_par(&par); + else + error = fbhw->decode_var(&fb_display[con].var, &par); + return(error ? error : fbhw->encode_fix(fix, &par)); +} + + +/* + * Get the User Defined Part of the Display + */ + +static int virgefb_get_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + struct virgefb_par par; + int error = 0; + + if (con == -1) + { + virgefb_get_par(&par); + error = fbhw->encode_var(var, &par); + disp.var = *var; /* ++Andre: don't know if this is the right place */ + } + else + { + *var = fb_display[con].var; + } + + return(error); +} + + +static void virgefb_set_disp(int con, struct fb_info *info) +{ + struct fb_fix_screeninfo fix; + struct display *display; + + if (con >= 0) + display = &fb_display[con]; + else + display = &disp; /* used during initialization */ + + virgefb_get_fix(&fix, con, info); + if (con == -1) + con = 0; + display->screen_base = (u_char *)fix.smem_start; + display->visual = fix.visual; + display->type = fix.type; + display->type_aux = fix.type_aux; + display->ypanstep = fix.ypanstep; + display->ywrapstep = fix.ywrapstep; + display->can_soft_blank = 1; + display->inverse = Cyberfb_inverse; + switch (display->var.bits_per_pixel) { +#ifdef CONFIG_FBCON_CFB8 + case 8: + display->dispsw = &fbcon_virge8; + break; +#endif +#ifdef CONFIG_FBCON_CFB16 + case 16: + display->dispsw = &fbcon_cfb16; + break; +#endif + default: + display->dispsw = NULL; + break; + } +} + + +/* + * Set the User Defined Part of the Display + */ + +static int virgefb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp; + + if ((err = do_fb_set_var(var, con == currcon))) + return(err); + if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { + oldxres = fb_display[con].var.xres; + oldyres = fb_display[con].var.yres; + oldvxres = fb_display[con].var.xres_virtual; + oldvyres = fb_display[con].var.yres_virtual; + oldbpp = fb_display[con].var.bits_per_pixel; + fb_display[con].var = *var; + if (oldxres != var->xres || oldyres != var->yres || + oldvxres != var->xres_virtual || + oldvyres != var->yres_virtual || + oldbpp != var->bits_per_pixel) { + virgefb_set_disp(con, info); + (*fb_info.changevar)(con); + fb_alloc_cmap(&fb_display[con].cmap, 0, 0); + do_install_cmap(con, info); + } + } + var->activate = 0; + return(0); +} + + +/* + * Get the Colormap + */ + +static int virgefb_get_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + if (con == currcon) /* current console? */ + return(fb_get_cmap(cmap, &fb_display[con].var, + kspc, fbhw->getcolreg, info)); + else if (fb_display[con].cmap.len) /* non default colormap? */ + fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); + else + fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), + cmap, kspc ? 0 : 2); + return(0); +} + + +/* + * Set the Colormap + */ + +static int virgefb_set_cmap(struct fb_cmap *cmap, int kspc, int con, + struct fb_info *info) +{ + int err; + + if (!fb_display[con].cmap.len) { /* no colormap allocated? */ + if ((err = fb_alloc_cmap(&fb_display[con].cmap, + 1<<fb_display[con].var.bits_per_pixel, 0))) + return(err); + } + if (con == currcon) /* current console? */ + return(fb_set_cmap(cmap, &fb_display[con].var, + kspc, fbhw->setcolreg, info)); + else + fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); + return(0); +} + + +/* + * Pan or Wrap the Display + * + * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag + */ + +static int virgefb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) +{ + return(-EINVAL); +} + + +/* + * Cybervision Frame Buffer Specific ioctls + */ + +static int virgefb_ioctl(struct inode *inode, struct file *file, + u_int cmd, u_long arg, int con, struct fb_info *info) +{ + return(-EINVAL); +} + + +static struct fb_ops virgefb_ops = { + virgefb_open, virgefb_release, virgefb_get_fix, virgefb_get_var, + virgefb_set_var, virgefb_get_cmap, virgefb_set_cmap, + virgefb_pan_display, NULL, virgefb_ioctl +}; + + +__initfunc(void virgefb_setup(char *options, int *ints)) +{ + char *this_opt; + + fb_info.fontname[0] = '\0'; + + if (!options || !*options) + return; + + for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ",")) + if (!strcmp(this_opt, "inverse")) { + Cyberfb_inverse = 1; + fb_invert_cmaps(); + } else if (!strncmp(this_opt, "font:", 5)) + strcpy(fb_info.fontname, this_opt+5); + else if (!strcmp (this_opt, "virge8")){ + virgefb_default = virgefb_predefined[VIRGE8_DEFMODE].var; + } + else if (!strcmp (this_opt, "virge16")){ + virgefb_default = virgefb_predefined[VIRGE16_DEFMODE].var; + } + else + get_video_mode(this_opt); + + DPRINTK("default mode: xres=%d, yres=%d, bpp=%d\n",virgefb_default.xres, + virgefb_default.yres, + virgefb_default.bits_per_pixel); +} + + +/* + * Initialization + */ + +__initfunc(unsigned long virgefb_init(unsigned long mem_start)) +{ + int err; + struct virgefb_par par; + unsigned long board_addr; + const struct ConfigDev *cd; + + if (!(CyberKey = zorro_find(ZORRO_PROD_PHASE5_CYBERVISION64_3D, 0, 0))) + return mem_start; + + cd = zorro_get_board (CyberKey); + zorro_config_board (CyberKey, 0); + board_addr = (unsigned long)cd->cd_BoardAddr; + + /* This includes the video memory as well as the S3 register set */ + if ((unsigned long)cd->cd_BoardAddr < 0x01000000) + { + /* + * Ok we got the board running in Z2 space. + */ + + CyberMem = ZTWO_VADDR(board_addr); + printk("CV3D detected running in Z2 mode ... not yet supported!\n"); + return -ENODEV; + } + else + { + CyberVGARegs = kernel_map(board_addr +0x0c000000, + 0x00010000, + KERNELMAP_NOCACHE_SER, + &mem_start); + CyberRegs = (char *)kernel_map(board_addr +0x05000000, + 0x00010000, + KERNELMAP_NOCACHE_SER, + &mem_start); + CyberMem = kernel_map(board_addr + 0x04800000, + 0x00400000, + KERNELMAP_NOCACHE_SER, + &mem_start); + printk("CV3D detected running in Z3 mode\n"); + } + + fbhw = &Cyber_switch; + + strcpy(fb_info.modename, virgefb_name); + fb_info.changevar = NULL; + fb_info.node = -1; + fb_info.fbops = &virgefb_ops; + fb_info.disp = &disp; + fb_info.switch_con = &Cyberfb_switch; + fb_info.updatevar = &Cyberfb_updatevar; + fb_info.blank = &Cyberfb_blank; + + err = register_framebuffer(&fb_info); + if (err < 0) + return mem_start; + + fbhw->init(); + fbhw->decode_var(&virgefb_default, &par); + fbhw->encode_var(&virgefb_default, &par); + + do_fb_set_var(&virgefb_default, 1); + virgefb_get_var(&fb_display[0].var, -1, &fb_info); + virgefb_set_disp(-1, &fb_info); + do_install_cmap(0, &fb_info); + + printk("fb%d: %s frame buffer device, using %ldK of video memory\n", + GET_FB_IDX(fb_info.node), fb_info.modename, CyberSize>>10); + + /* TODO: This driver cannot be unloaded yet */ + MOD_INC_USE_COUNT; + + return mem_start; +} + + +static int Cyberfb_switch(int con, struct fb_info *info) +{ + /* Do we have to save the colormap? */ + if (fb_display[currcon].cmap.len) + fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1, + fbhw->getcolreg, info); + + do_fb_set_var(&fb_display[con].var, 1); + currcon = con; + /* Install new colormap */ + do_install_cmap(con, info); + return(0); +} + + +/* + * Update the `var' structure (called by fbcon.c) + * + * This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'. + * Since it's called by a kernel driver, no range checking is done. + */ + +static int Cyberfb_updatevar(int con, struct fb_info *info) +{ + return(0); +} + + +/* + * Blank the display. + */ + +static void Cyberfb_blank(int blank, struct fb_info *info) +{ + fbhw->blank(blank); +} + + +/* + * Get a Video Mode + */ + +__initfunc(static int get_video_mode(const char *name)) +{ + int i; + + for (i = 0; i < NUM_TOTAL_MODES; i++) { + if (!strcmp(name, virgefb_predefined[i].name)) { + virgefb_default = virgefb_predefined[i].var; + return(i); + } + } + /* ++Andre: set virgefb default mode */ + virgefb_default = virgefb_predefined[VIRGE8_DEFMODE].var; + return(0); +} + + +/* + * Text console acceleration + */ + +#ifdef CONFIG_FBCON_CFB8 +static void fbcon_virge8_bmove(struct display *p, int sy, int sx, int dy, + int dx, int height, int width) +{ + sx *= 8; dx *= 8; width *= 8; + Cyber3D_BitBLT((u_short)sx, (u_short)(sy*p->fontheight), (u_short)dx, + (u_short)(dy*p->fontheight), (u_short)width, + (u_short)(height*p->fontheight)); +} + +static void fbcon_virge8_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width) +{ + unsigned char bg; + + sx *= 8; width *= 8; + bg = attr_bgcol_ec(p,conp); + Cyber3D_RectFill((u_short)sx, (u_short)(sy*p->fontheight), + (u_short)width, (u_short)(height*p->fontheight), + (u_short)bg); +} + +static struct display_switch fbcon_virge8 = { + fbcon_cfb8_setup, fbcon_virge8_bmove, fbcon_virge8_clear, fbcon_cfb8_putc, + fbcon_cfb8_putcs, fbcon_cfb8_revc +}; +#endif + + +#ifdef MODULE +int init_module(void) +{ + return(virgefb_init(NULL)); +} + +void cleanup_module(void) +{ + /* Not reached because the usecount will never be + decremented to zero */ + unregister_framebuffer(&fb_info); + /* TODO: clean up ... */ +} +#endif /* MODULE */ |